mirror of
https://github.com/aaru-dps/Aaru.git
synced 2025-12-16 19:24:25 +00:00
Workaround when HFS and Apple Partition Map where created on a
512 byte/sector device (like a HDD) but are present on a 2048 byte/sector device (like a CD). Solves #1. HFS+ should not be affected (even if wrapped).
This commit is contained in:
@@ -96,34 +96,38 @@ namespace DiscImageChef.PartPlugins
|
||||
first_sector = 1;
|
||||
|
||||
// Read first entry
|
||||
byte[] APMEntry_sector = imagePlugin.ReadSector(first_sector);
|
||||
APMEntry.signature = BigEndianBitConverter.ToUInt16(APMEntry_sector, 0x00);
|
||||
APMEntry.reserved1 = BigEndianBitConverter.ToUInt16(APMEntry_sector, 0x02);
|
||||
APMEntry.entries = BigEndianBitConverter.ToUInt32(APMEntry_sector, 0x04);
|
||||
APMEntry.start = BigEndianBitConverter.ToUInt32(APMEntry_sector, 0x08);
|
||||
APMEntry.sectors = BigEndianBitConverter.ToUInt32(APMEntry_sector, 0x0C);
|
||||
cString = new byte[32];
|
||||
Array.Copy(APMEntry_sector, 0x10, cString, 0, 32);
|
||||
APMEntry.name = StringHandlers.CToString(cString);
|
||||
cString = new byte[32];
|
||||
Array.Copy(APMEntry_sector, 0x30, cString, 0, 32);
|
||||
APMEntry.type = StringHandlers.CToString(cString);
|
||||
APMEntry.first_data_block = BigEndianBitConverter.ToUInt32(APMEntry_sector, 0x50);
|
||||
APMEntry.data_sectors = BigEndianBitConverter.ToUInt32(APMEntry_sector, 0x54);
|
||||
APMEntry.status = BigEndianBitConverter.ToUInt32(APMEntry_sector, 0x58);
|
||||
APMEntry.first_boot_block = BigEndianBitConverter.ToUInt32(APMEntry_sector, 0x5C);
|
||||
APMEntry.boot_size = BigEndianBitConverter.ToUInt32(APMEntry_sector, 0x60);
|
||||
APMEntry.load_address = BigEndianBitConverter.ToUInt32(APMEntry_sector, 0x64);
|
||||
APMEntry.reserved2 = BigEndianBitConverter.ToUInt32(APMEntry_sector, 0x68);
|
||||
APMEntry.entry_point = BigEndianBitConverter.ToUInt32(APMEntry_sector, 0x6C);
|
||||
APMEntry.reserved3 = BigEndianBitConverter.ToUInt32(APMEntry_sector, 0x70);
|
||||
APMEntry.checksum = BigEndianBitConverter.ToUInt32(APMEntry_sector, 0x74);
|
||||
cString = new byte[16];
|
||||
Array.Copy(APMEntry_sector, 0x78, cString, 0, 16);
|
||||
APMEntry.processor = StringHandlers.CToString(cString);
|
||||
byte[] APMEntry_sector;
|
||||
bool APMFromHDDOnCD = false;
|
||||
|
||||
if (sector_size == 2048)
|
||||
{
|
||||
APMEntry_sector = Read2048SectorAs512(imagePlugin, first_sector);
|
||||
APMEntry = DecodeAPMEntry(APMEntry_sector);
|
||||
|
||||
if (APMEntry.signature == APM_ENTRY || APMEntry.signature == APM_OLDENT)
|
||||
{
|
||||
sector_size = 512;
|
||||
APMFromHDDOnCD = true;
|
||||
if (MainClass.isDebug)
|
||||
Console.WriteLine("DEBUG (Apple Partition Map Plugin): PM sector size is 512 bytes, but device's 2048");
|
||||
}
|
||||
else
|
||||
{
|
||||
APMEntry_sector = imagePlugin.ReadSector(first_sector);
|
||||
APMEntry = DecodeAPMEntry(APMEntry_sector);
|
||||
|
||||
if (APMEntry.signature != APM_ENTRY && APMEntry.signature != APM_OLDENT)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
APMEntry_sector = imagePlugin.ReadSector(first_sector);
|
||||
APMEntry = DecodeAPMEntry(APMEntry_sector);
|
||||
|
||||
if (APMEntry.signature != APM_ENTRY && APMEntry.signature != APM_OLDENT)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (APMEntry.entries <= 1)
|
||||
return false;
|
||||
@@ -133,31 +137,12 @@ namespace DiscImageChef.PartPlugins
|
||||
for (ulong i = 0; i < apm_entries; i++) // For each partition
|
||||
{
|
||||
APMEntry = new AppleMapPartitionEntry();
|
||||
if(APMFromHDDOnCD)
|
||||
APMEntry_sector = Read2048SectorAs512(imagePlugin, first_sector + i);
|
||||
else
|
||||
APMEntry_sector = imagePlugin.ReadSector(first_sector + i);
|
||||
APMEntry.signature = BigEndianBitConverter.ToUInt16(APMEntry_sector, 0x00);
|
||||
APMEntry.reserved1 = BigEndianBitConverter.ToUInt16(APMEntry_sector, 0x02);
|
||||
APMEntry.entries = BigEndianBitConverter.ToUInt32(APMEntry_sector, 0x04);
|
||||
APMEntry.start = BigEndianBitConverter.ToUInt32(APMEntry_sector, 0x08);
|
||||
APMEntry.sectors = BigEndianBitConverter.ToUInt32(APMEntry_sector, 0x0C);
|
||||
cString = new byte[32];
|
||||
Array.Copy(APMEntry_sector, 0x10, cString, 0, 32);
|
||||
APMEntry.name = StringHandlers.CToString(cString);
|
||||
cString = new byte[32];
|
||||
Array.Copy(APMEntry_sector, 0x30, cString, 0, 32);
|
||||
APMEntry.type = StringHandlers.CToString(cString);
|
||||
APMEntry.first_data_block = BigEndianBitConverter.ToUInt32(APMEntry_sector, 0x50);
|
||||
APMEntry.data_sectors = BigEndianBitConverter.ToUInt32(APMEntry_sector, 0x54);
|
||||
APMEntry.status = BigEndianBitConverter.ToUInt32(APMEntry_sector, 0x58);
|
||||
APMEntry.first_boot_block = BigEndianBitConverter.ToUInt32(APMEntry_sector, 0x5C);
|
||||
APMEntry.boot_size = BigEndianBitConverter.ToUInt32(APMEntry_sector, 0x60);
|
||||
APMEntry.load_address = BigEndianBitConverter.ToUInt32(APMEntry_sector, 0x64);
|
||||
APMEntry.reserved2 = BigEndianBitConverter.ToUInt32(APMEntry_sector, 0x68);
|
||||
APMEntry.entry_point = BigEndianBitConverter.ToUInt32(APMEntry_sector, 0x6C);
|
||||
APMEntry.reserved3 = BigEndianBitConverter.ToUInt32(APMEntry_sector, 0x70);
|
||||
APMEntry.checksum = BigEndianBitConverter.ToUInt32(APMEntry_sector, 0x74);
|
||||
cString = new byte[16];
|
||||
Array.Copy(APMEntry_sector, 0x78, cString, 0, 16);
|
||||
APMEntry.processor = StringHandlers.CToString(cString);
|
||||
|
||||
APMEntry = DecodeAPMEntry(APMEntry_sector);
|
||||
|
||||
if (APMEntry.signature == APM_ENTRY || APMEntry.signature == APM_OLDENT) // It should have partition entry signature
|
||||
{
|
||||
@@ -209,6 +194,52 @@ namespace DiscImageChef.PartPlugins
|
||||
return true;
|
||||
}
|
||||
|
||||
byte[] Read2048SectorAs512(ImagePlugins.ImagePlugin imagePlugin, UInt64 LBA)
|
||||
{
|
||||
UInt64 LBA2k = LBA / 4;
|
||||
int Remainder = (int)(LBA % 4);
|
||||
|
||||
byte[] buffer = imagePlugin.ReadSector(LBA2k);
|
||||
byte[] sector = new byte[512];
|
||||
|
||||
Array.Copy(buffer, Remainder * 512, sector, 0, 512);
|
||||
|
||||
return sector;
|
||||
}
|
||||
|
||||
AppleMapPartitionEntry DecodeAPMEntry(byte[] APMEntry_sector)
|
||||
{
|
||||
AppleMapPartitionEntry APMEntry = new AppleMapPartitionEntry();
|
||||
byte[] cString;
|
||||
|
||||
APMEntry.signature = BigEndianBitConverter.ToUInt16(APMEntry_sector, 0x00);
|
||||
APMEntry.reserved1 = BigEndianBitConverter.ToUInt16(APMEntry_sector, 0x02);
|
||||
APMEntry.entries = BigEndianBitConverter.ToUInt32(APMEntry_sector, 0x04);
|
||||
APMEntry.start = BigEndianBitConverter.ToUInt32(APMEntry_sector, 0x08);
|
||||
APMEntry.sectors = BigEndianBitConverter.ToUInt32(APMEntry_sector, 0x0C);
|
||||
cString = new byte[32];
|
||||
Array.Copy(APMEntry_sector, 0x10, cString, 0, 32);
|
||||
APMEntry.name = StringHandlers.CToString(cString);
|
||||
cString = new byte[32];
|
||||
Array.Copy(APMEntry_sector, 0x30, cString, 0, 32);
|
||||
APMEntry.type = StringHandlers.CToString(cString);
|
||||
APMEntry.first_data_block = BigEndianBitConverter.ToUInt32(APMEntry_sector, 0x50);
|
||||
APMEntry.data_sectors = BigEndianBitConverter.ToUInt32(APMEntry_sector, 0x54);
|
||||
APMEntry.status = BigEndianBitConverter.ToUInt32(APMEntry_sector, 0x58);
|
||||
APMEntry.first_boot_block = BigEndianBitConverter.ToUInt32(APMEntry_sector, 0x5C);
|
||||
APMEntry.boot_size = BigEndianBitConverter.ToUInt32(APMEntry_sector, 0x60);
|
||||
APMEntry.load_address = BigEndianBitConverter.ToUInt32(APMEntry_sector, 0x64);
|
||||
APMEntry.reserved2 = BigEndianBitConverter.ToUInt32(APMEntry_sector, 0x68);
|
||||
APMEntry.entry_point = BigEndianBitConverter.ToUInt32(APMEntry_sector, 0x6C);
|
||||
APMEntry.reserved3 = BigEndianBitConverter.ToUInt32(APMEntry_sector, 0x70);
|
||||
APMEntry.checksum = BigEndianBitConverter.ToUInt32(APMEntry_sector, 0x74);
|
||||
cString = new byte[16];
|
||||
Array.Copy(APMEntry_sector, 0x78, cString, 0, 16);
|
||||
APMEntry.processor = StringHandlers.CToString(cString);
|
||||
|
||||
return APMEntry;
|
||||
}
|
||||
|
||||
public struct AppleMapBootEntry
|
||||
{
|
||||
// Signature ("ER")
|
||||
|
||||
@@ -63,8 +63,13 @@ namespace DiscImageChef.Plugins
|
||||
if ((2 + partitionOffset) >= imagePlugin.GetSectors())
|
||||
return false;
|
||||
|
||||
byte[] mdb_sector = imagePlugin.ReadSector(2 + partitionOffset);
|
||||
UInt16 drSigWord = BigEndianBitConverter.ToUInt16(mdb_sector, 0);
|
||||
byte[] mdb_sector;
|
||||
UInt16 drSigWord;
|
||||
|
||||
if (imagePlugin.GetSectorSize() == 2352 || imagePlugin.GetSectorSize() == 2448 || imagePlugin.GetSectorSize() == 2048)
|
||||
{
|
||||
mdb_sector = imagePlugin.ReadSector(2 + partitionOffset);
|
||||
drSigWord = BigEndianBitConverter.ToUInt16(mdb_sector, 0);
|
||||
|
||||
if (drSigWord == HFS_MAGIC)
|
||||
{
|
||||
@@ -72,6 +77,34 @@ namespace DiscImageChef.Plugins
|
||||
|
||||
return drSigWord != HFSP_MAGIC;
|
||||
}
|
||||
else
|
||||
{
|
||||
mdb_sector = Read2048SectorAs512(imagePlugin, 2 + partitionOffset);
|
||||
drSigWord = BigEndianBitConverter.ToUInt16(mdb_sector, 0);
|
||||
|
||||
if (drSigWord == HFS_MAGIC)
|
||||
{
|
||||
if(MainClass.isDebug)
|
||||
Console.WriteLine("DEBUG (HFS Plugin): HFS sector size is 512 bytes, but device's 2048");
|
||||
|
||||
drSigWord = BigEndianBitConverter.ToUInt16(mdb_sector, 0x7C); // Seek to embedded HFS+ signature
|
||||
|
||||
return drSigWord != HFSP_MAGIC;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mdb_sector = imagePlugin.ReadSector(2 + partitionOffset);
|
||||
drSigWord = BigEndianBitConverter.ToUInt16(mdb_sector, 0);
|
||||
|
||||
if (drSigWord == HFS_MAGIC)
|
||||
{
|
||||
drSigWord = BigEndianBitConverter.ToUInt16(mdb_sector, 0x7C); // Seek to embedded HFS+ signature
|
||||
|
||||
return drSigWord != HFSP_MAGIC;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -86,8 +119,46 @@ namespace DiscImageChef.Plugins
|
||||
|
||||
byte[] pString;
|
||||
|
||||
byte[] bb_sector = imagePlugin.ReadSector(partitionOffset); // BB's first sector
|
||||
byte[] mdb_sector = imagePlugin.ReadSector(2 + partitionOffset); // MDB sector
|
||||
byte[] bb_sector;
|
||||
byte[] mdb_sector;
|
||||
UInt16 drSigWord;
|
||||
|
||||
bool APMFromHDDOnCD = false;
|
||||
|
||||
if (imagePlugin.GetSectorSize() == 2352 || imagePlugin.GetSectorSize() == 2448 || imagePlugin.GetSectorSize() == 2048)
|
||||
{
|
||||
mdb_sector = imagePlugin.ReadSector(2 + partitionOffset);
|
||||
drSigWord = BigEndianBitConverter.ToUInt16(mdb_sector, 0);
|
||||
|
||||
if (drSigWord == HFS_MAGIC)
|
||||
{
|
||||
bb_sector = imagePlugin.ReadSector(partitionOffset);
|
||||
}
|
||||
else
|
||||
{
|
||||
mdb_sector = Read2048SectorAs512(imagePlugin, 2 + partitionOffset);
|
||||
drSigWord = BigEndianBitConverter.ToUInt16(mdb_sector, 0);
|
||||
|
||||
if (drSigWord == HFS_MAGIC)
|
||||
{
|
||||
bb_sector = Read2048SectorAs512(imagePlugin, partitionOffset);
|
||||
APMFromHDDOnCD = true;
|
||||
}
|
||||
else
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mdb_sector = imagePlugin.ReadSector(2 + partitionOffset);
|
||||
drSigWord = BigEndianBitConverter.ToUInt16(mdb_sector, 0);
|
||||
|
||||
if (drSigWord == HFS_MAGIC)
|
||||
bb_sector = imagePlugin.ReadSector(partitionOffset);
|
||||
else
|
||||
return;
|
||||
}
|
||||
|
||||
MDB.drSigWord = BigEndianBitConverter.ToUInt16(mdb_sector, 0x000);
|
||||
if (MDB.drSigWord != HFS_MAGIC)
|
||||
return;
|
||||
@@ -181,6 +252,8 @@ namespace DiscImageChef.Plugins
|
||||
|
||||
sb.AppendLine("Apple Hierarchical File System");
|
||||
sb.AppendLine();
|
||||
if (APMFromHDDOnCD)
|
||||
sb.AppendLine("HFS uses 512 bytes/sector while devices uses 2048 bytes/sector.").AppendLine();
|
||||
sb.AppendLine("Master Directory Block:");
|
||||
sb.AppendFormat("Creation date: {0}", DateHandlers.MacToDateTime(MDB.drCrDate)).AppendLine();
|
||||
sb.AppendFormat("Last modification date: {0}", DateHandlers.MacToDateTime(MDB.drLsMod)).AppendLine();
|
||||
@@ -291,6 +364,19 @@ namespace DiscImageChef.Plugins
|
||||
return;
|
||||
}
|
||||
|
||||
byte[] Read2048SectorAs512(ImagePlugins.ImagePlugin imagePlugin, UInt64 LBA)
|
||||
{
|
||||
UInt64 LBA2k = LBA / 4;
|
||||
int Remainder = (int)(LBA % 4);
|
||||
|
||||
byte[] buffer = imagePlugin.ReadSector(LBA2k);
|
||||
byte[] sector = new byte[512];
|
||||
|
||||
Array.Copy(buffer, Remainder * 512, sector, 0, 512);
|
||||
|
||||
return sector;
|
||||
}
|
||||
|
||||
struct HFS_MasterDirectoryBlock // Should be sector 2 in volume
|
||||
{
|
||||
public UInt16 drSigWord;
|
||||
|
||||
Reference in New Issue
Block a user