2016-07-28 18:13:49 +01:00
|
|
|
// /***************************************************************************
|
|
|
|
|
// The Disc Image Chef
|
|
|
|
|
// ----------------------------------------------------------------------------
|
|
|
|
|
//
|
|
|
|
|
// Filename : AppleMap.cs
|
|
|
|
|
// Author(s) : Natalia Portillo <claunia@claunia.com>
|
|
|
|
|
//
|
|
|
|
|
// Component : Partitioning scheme plugins.
|
|
|
|
|
//
|
|
|
|
|
// --[ Description ] ----------------------------------------------------------
|
|
|
|
|
//
|
|
|
|
|
// Manages Apple Partition Map.
|
|
|
|
|
//
|
|
|
|
|
// --[ License ] --------------------------------------------------------------
|
|
|
|
|
//
|
|
|
|
|
// This library is free software; you can redistribute it and/or modify
|
|
|
|
|
// it under the terms of the GNU Lesser General Public License as
|
|
|
|
|
// published by the Free Software Foundation; either version 2.1 of the
|
|
|
|
|
// License, or (at your option) any later version.
|
|
|
|
|
//
|
|
|
|
|
// This library is distributed in the hope that it will be useful, but
|
|
|
|
|
// WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
|
// Lesser General Public License for more details.
|
|
|
|
|
//
|
|
|
|
|
// You should have received a copy of the GNU Lesser General Public
|
|
|
|
|
// License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
|
|
|
|
//
|
|
|
|
|
// ----------------------------------------------------------------------------
|
2017-05-19 20:28:49 +01:00
|
|
|
// Copyright © 2011-2017 Natalia Portillo
|
2016-07-28 18:13:49 +01:00
|
|
|
// ****************************************************************************/
|
2014-04-17 19:58:14 +00:00
|
|
|
|
2011-03-03 18:34:33 +00:00
|
|
|
using System;
|
|
|
|
|
using System.Text;
|
|
|
|
|
using System.Collections.Generic;
|
2015-10-18 22:04:03 +01:00
|
|
|
using DiscImageChef.Console;
|
|
|
|
|
|
|
|
|
|
|
2014-06-15 23:39:34 +01:00
|
|
|
namespace DiscImageChef.PartPlugins
|
2011-03-03 18:34:33 +00:00
|
|
|
{
|
2016-07-28 22:25:26 +01:00
|
|
|
// Information about structures learnt from Inside Macintosh
|
|
|
|
|
// Constants from image testing
|
2014-04-14 02:29:13 +00:00
|
|
|
class AppleMap : PartPlugin
|
|
|
|
|
{
|
|
|
|
|
// "ER"
|
2016-07-28 22:25:26 +01:00
|
|
|
const ushort APM_MAGIC = 0x4552;
|
2014-04-14 02:29:13 +00:00
|
|
|
// "PM"
|
2016-07-28 22:25:26 +01:00
|
|
|
const ushort APM_ENTRY = 0x504D;
|
2014-04-14 02:29:13 +00:00
|
|
|
// "TS", old entry magic
|
2016-07-28 22:25:26 +01:00
|
|
|
const ushort APM_OLDENT = 0x5453;
|
2012-08-05 03:02:55 +00:00
|
|
|
|
2015-10-05 19:58:42 +01:00
|
|
|
public AppleMap()
|
2014-04-14 02:29:13 +00:00
|
|
|
{
|
2014-04-14 01:14:20 +00:00
|
|
|
Name = "Apple Partition Map";
|
2014-04-14 02:29:13 +00:00
|
|
|
PluginUUID = new Guid("36405F8D-4F1A-07F5-209C-223D735D6D22");
|
|
|
|
|
}
|
|
|
|
|
|
2015-10-05 19:45:07 +01:00
|
|
|
public override bool GetInformation(ImagePlugins.ImagePlugin imagePlugin, out List<CommonTypes.Partition> partitions)
|
2014-04-14 02:29:13 +00:00
|
|
|
{
|
|
|
|
|
ulong apm_entries;
|
2014-04-14 01:14:20 +00:00
|
|
|
uint sector_size;
|
|
|
|
|
|
2016-04-19 02:11:47 +01:00
|
|
|
if(imagePlugin.GetSectorSize() == 2352 || imagePlugin.GetSectorSize() == 2448)
|
2014-04-14 01:14:20 +00:00
|
|
|
sector_size = 2048;
|
|
|
|
|
else
|
|
|
|
|
sector_size = imagePlugin.GetSectorSize();
|
2016-04-19 02:11:47 +01:00
|
|
|
|
2015-10-05 19:45:07 +01:00
|
|
|
partitions = new List<CommonTypes.Partition>();
|
2016-04-19 02:11:47 +01:00
|
|
|
|
2014-04-14 02:29:13 +00:00
|
|
|
AppleMapBootEntry APMB = new AppleMapBootEntry();
|
2014-08-28 19:02:45 +01:00
|
|
|
AppleMapPartitionEntry APMEntry;
|
2012-08-05 03:02:55 +00:00
|
|
|
|
2014-04-14 01:14:20 +00:00
|
|
|
byte[] APMB_sector = imagePlugin.ReadSector(0);
|
2012-08-05 03:02:55 +00:00
|
|
|
|
* commandline:
* DiscImageChef.Settings/Settings.cs:
* DiscImageChef.Settings/docs/README.txt:
* DiscImageChef.Settings/packages.config:
* DiscImageChef.Settings/docs/LICENSE.txt:
* DiscImageChef.Settings/docs/ChangeLog.txt:
* DiscImageChef.Settings/docs/mono/index.xml:
* DiscImageChef.Settings/docs/html/index.html:
* DiscImageChef.Settings/Properties/AssemblyInfo.cs:
* DiscImageChef.Settings/DiscImageChef.Settings.csproj:
* DiscImageChef.Settings/docs/mono/ns-Claunia.PropertyList.xml:
* DiscImageChef.Settings/docs/mono/Claunia.PropertyList/UID.xml:
* DiscImageChef.Settings/docs/html/Claunia.PropertyList/UID.html:
* DiscImageChef.Settings/docs/mono/Claunia.PropertyList/NSSet.xml:
* DiscImageChef.Settings/docs/html/Claunia.PropertyList/index.html:
* DiscImageChef.Settings/docs/html/Claunia.PropertyList/NSSet.html:
* DiscImageChef.Settings/docs/mono/Claunia.PropertyList/NSDate.xml:
* DiscImageChef.Settings/docs/mono/Claunia.PropertyList/NSData.xml:
* DiscImageChef.Settings/docs/html/Claunia.PropertyList/NSDate.html:
* DiscImageChef.Settings/docs/html/Claunia.PropertyList/NSData.html:
* DiscImageChef.Settings/docs/mono/Claunia.PropertyList/NSArray.xml:
* DiscImageChef.Settings/docs/mono/Claunia.PropertyList/NSNumber.xml:
* DiscImageChef.Settings/docs/mono/Claunia.PropertyList/NSString.xml:
* DiscImageChef.Settings/docs/mono/Claunia.PropertyList/NSObject.xml:
* DiscImageChef.Settings/docs/html/Claunia.PropertyList/NSArray.html:
* DiscImageChef.Settings/docs/html/Claunia.PropertyList/NSNumber.html:
* DiscImageChef.Settings/docs/html/Claunia.PropertyList/NSString.html:
* DiscImageChef.Settings/docs/html/Claunia.PropertyList/NSObject.html:
* DiscImageChef.Settings/docs/mono/Claunia.PropertyList/NSDictionary.xml:
* DiscImageChef.Settings/docs/html/Claunia.PropertyList/NSDictionary.html:
* DiscImageChef.Settings/docs/mono/Claunia.PropertyList/PropertyListParser.xml:
* DiscImageChef.Settings/docs/html/Claunia.PropertyList/PropertyListParser.html:
* DiscImageChef.Settings/docs/mono/Claunia.PropertyList/XmlPropertyListParser.xml:
* DiscImageChef.Settings/docs/html/Claunia.PropertyList/XmlPropertyListParser.html:
* DiscImageChef.Settings/docs/mono/Claunia.PropertyList/ASCIIPropertyListParser.xml:
* DiscImageChef.Settings/docs/html/Claunia.PropertyList/ASCIIPropertyListParser.html:
* DiscImageChef.Settings/docs/mono/Claunia.PropertyList/BinaryPropertyListParser.xml:
* DiscImageChef.Settings/docs/mono/Claunia.PropertyList/BinaryPropertyListWriter.xml:
* DiscImageChef.Settings/docs/html/Claunia.PropertyList/BinaryPropertyListWriter.html:
* DiscImageChef.Settings/docs/html/Claunia.PropertyList/BinaryPropertyListParser.html:
* DiscImageChef.Settings/docs/mono/Claunia.PropertyList/PropertyListFormatException.xml:
* DiscImageChef.Settings/docs/html/Claunia.PropertyList/PropertyListFormatException.html:
Added supports for settings
* DiscImageChef/Commands/Configure.cs:
Added support for settings.
* DiscImageChef/Core/Statistics.cs:
* DiscImageChef/Commands/Verify.cs:
* DiscImageChef/Commands/Entropy.cs:
* DiscImageChef/Commands/Formats.cs:
* DiscImageChef/Commands/PrintHex.cs:
* DiscImageChef/Commands/MediaInfo.cs:
* DiscImageChef/Commands/Statistics.cs:
Added statistics.
* DiscImageChef.Decoders/SCSI/Inquiry.cs:
Corrected bug on inquiry decoding.
* DiscImageChef.Decoders/SCSI/Modes.cs:
Corrected bug on decoding mode page 2Ah without write
performance descriptors.
Corrected bug when there is a vendor page 0 in mode sense
decoding.
* DiscImageChef.Devices/Device/Constructor.cs:
Corrected detecting USB or FireWire attached CD/DVD/BD and
tape drives.
Try ATA identify on USB or FireWire that don't have SCSI
INQUIRY.
* DiscImageChef.DiscImages/CDRWin.cs:
Corrected CD-ROM XA vs CD-ROM detection.
* DiscImageChef.Partitions/AppleMap.cs:
Corrected big endian working.
Added debug output.
* DiscImageChef.sln:
Added supports for settings.
* DiscImageChef/Commands/Decode.cs:
* DiscImageChef/Commands/Analyze.cs:
* DiscImageChef/Commands/Compare.cs:
* DiscImageChef/Commands/Checksum.cs:
* DiscImageChef/Commands/Benchmark.cs:
* DiscImageChef/Commands/DeviceInfo.cs:
* DiscImageChef/Commands/CreateSidecar.cs:
Added statistics.
* DiscImageChef/Commands/DeviceReport.cs:
Added statistics.
Correct handling empty inquiry string fields.
Suppose it is not removable, til proved wrong.
Corrected MODE SENSE (6/10) detection and calling order.
If device is MMC type but reports neither mode page 2Ah
neither GET CONFIGURATION, try all CDs (old drives work like
that).
Try reading Lead-In and Lead-Out in Audio CD using Audio READ
CD commands.
Corrected READ LONG information handling, some drives return
2s-complement in 32 bit. Upper 16 bits are ignored.
Added support for DVD raw block (37856 bytes).
Check READ LONG up to 36 times the cooked block size. That
should be enough to detect huge blocked media (like DVD and
BD) without taking ages.
If READ LONG size had to be bruteforced, and debug is
activated, save the result.
* DiscImageChef/Commands/DumpMedia.cs:
Added statistics.
Corrected READ LONG information handling, some drives return
2s-complement in 32 bit. Upper 16 bits are ignored.
Start trying with 64 blocks at a time. Some drives report to
be able to read 255 at a time, but they really don't, they
take a lot longer to read.
* DiscImageChef/Commands/MediaScan.cs:
Added statistics.
Start trying with 64 blocks at a time. Some drives report to
be able to read 255 at a time, but they really don't, they
take a lot longer to read.
* DiscImageChef/DiscImageChef.csproj:
Added support for settings.
Added statistics.
* DiscImageChef/Main.cs:
* DiscImageChef/Options.cs:
Added support for settings.
Added statistics.
2016-02-03 18:58:11 +00:00
|
|
|
BigEndianBitConverter.IsLittleEndian = BitConverter.IsLittleEndian;
|
|
|
|
|
|
2014-04-14 01:14:20 +00:00
|
|
|
APMB.signature = BigEndianBitConverter.ToUInt16(APMB_sector, 0x00);
|
|
|
|
|
APMB.sector_size = BigEndianBitConverter.ToUInt16(APMB_sector, 0x02);
|
|
|
|
|
APMB.sectors = BigEndianBitConverter.ToUInt32(APMB_sector, 0x04);
|
|
|
|
|
APMB.reserved1 = BigEndianBitConverter.ToUInt16(APMB_sector, 0x08);
|
|
|
|
|
APMB.reserved2 = BigEndianBitConverter.ToUInt16(APMB_sector, 0x0A);
|
|
|
|
|
APMB.reserved3 = BigEndianBitConverter.ToUInt32(APMB_sector, 0x0C);
|
|
|
|
|
APMB.driver_entries = BigEndianBitConverter.ToUInt16(APMB_sector, 0x10);
|
|
|
|
|
APMB.first_driver_blk = BigEndianBitConverter.ToUInt32(APMB_sector, 0x12);
|
|
|
|
|
APMB.driver_size = BigEndianBitConverter.ToUInt16(APMB_sector, 0x16);
|
|
|
|
|
APMB.operating_system = BigEndianBitConverter.ToUInt16(APMB_sector, 0x18);
|
2012-08-05 03:02:55 +00:00
|
|
|
|
* commandline:
* DiscImageChef.Settings/Settings.cs:
* DiscImageChef.Settings/docs/README.txt:
* DiscImageChef.Settings/packages.config:
* DiscImageChef.Settings/docs/LICENSE.txt:
* DiscImageChef.Settings/docs/ChangeLog.txt:
* DiscImageChef.Settings/docs/mono/index.xml:
* DiscImageChef.Settings/docs/html/index.html:
* DiscImageChef.Settings/Properties/AssemblyInfo.cs:
* DiscImageChef.Settings/DiscImageChef.Settings.csproj:
* DiscImageChef.Settings/docs/mono/ns-Claunia.PropertyList.xml:
* DiscImageChef.Settings/docs/mono/Claunia.PropertyList/UID.xml:
* DiscImageChef.Settings/docs/html/Claunia.PropertyList/UID.html:
* DiscImageChef.Settings/docs/mono/Claunia.PropertyList/NSSet.xml:
* DiscImageChef.Settings/docs/html/Claunia.PropertyList/index.html:
* DiscImageChef.Settings/docs/html/Claunia.PropertyList/NSSet.html:
* DiscImageChef.Settings/docs/mono/Claunia.PropertyList/NSDate.xml:
* DiscImageChef.Settings/docs/mono/Claunia.PropertyList/NSData.xml:
* DiscImageChef.Settings/docs/html/Claunia.PropertyList/NSDate.html:
* DiscImageChef.Settings/docs/html/Claunia.PropertyList/NSData.html:
* DiscImageChef.Settings/docs/mono/Claunia.PropertyList/NSArray.xml:
* DiscImageChef.Settings/docs/mono/Claunia.PropertyList/NSNumber.xml:
* DiscImageChef.Settings/docs/mono/Claunia.PropertyList/NSString.xml:
* DiscImageChef.Settings/docs/mono/Claunia.PropertyList/NSObject.xml:
* DiscImageChef.Settings/docs/html/Claunia.PropertyList/NSArray.html:
* DiscImageChef.Settings/docs/html/Claunia.PropertyList/NSNumber.html:
* DiscImageChef.Settings/docs/html/Claunia.PropertyList/NSString.html:
* DiscImageChef.Settings/docs/html/Claunia.PropertyList/NSObject.html:
* DiscImageChef.Settings/docs/mono/Claunia.PropertyList/NSDictionary.xml:
* DiscImageChef.Settings/docs/html/Claunia.PropertyList/NSDictionary.html:
* DiscImageChef.Settings/docs/mono/Claunia.PropertyList/PropertyListParser.xml:
* DiscImageChef.Settings/docs/html/Claunia.PropertyList/PropertyListParser.html:
* DiscImageChef.Settings/docs/mono/Claunia.PropertyList/XmlPropertyListParser.xml:
* DiscImageChef.Settings/docs/html/Claunia.PropertyList/XmlPropertyListParser.html:
* DiscImageChef.Settings/docs/mono/Claunia.PropertyList/ASCIIPropertyListParser.xml:
* DiscImageChef.Settings/docs/html/Claunia.PropertyList/ASCIIPropertyListParser.html:
* DiscImageChef.Settings/docs/mono/Claunia.PropertyList/BinaryPropertyListParser.xml:
* DiscImageChef.Settings/docs/mono/Claunia.PropertyList/BinaryPropertyListWriter.xml:
* DiscImageChef.Settings/docs/html/Claunia.PropertyList/BinaryPropertyListWriter.html:
* DiscImageChef.Settings/docs/html/Claunia.PropertyList/BinaryPropertyListParser.html:
* DiscImageChef.Settings/docs/mono/Claunia.PropertyList/PropertyListFormatException.xml:
* DiscImageChef.Settings/docs/html/Claunia.PropertyList/PropertyListFormatException.html:
Added supports for settings
* DiscImageChef/Commands/Configure.cs:
Added support for settings.
* DiscImageChef/Core/Statistics.cs:
* DiscImageChef/Commands/Verify.cs:
* DiscImageChef/Commands/Entropy.cs:
* DiscImageChef/Commands/Formats.cs:
* DiscImageChef/Commands/PrintHex.cs:
* DiscImageChef/Commands/MediaInfo.cs:
* DiscImageChef/Commands/Statistics.cs:
Added statistics.
* DiscImageChef.Decoders/SCSI/Inquiry.cs:
Corrected bug on inquiry decoding.
* DiscImageChef.Decoders/SCSI/Modes.cs:
Corrected bug on decoding mode page 2Ah without write
performance descriptors.
Corrected bug when there is a vendor page 0 in mode sense
decoding.
* DiscImageChef.Devices/Device/Constructor.cs:
Corrected detecting USB or FireWire attached CD/DVD/BD and
tape drives.
Try ATA identify on USB or FireWire that don't have SCSI
INQUIRY.
* DiscImageChef.DiscImages/CDRWin.cs:
Corrected CD-ROM XA vs CD-ROM detection.
* DiscImageChef.Partitions/AppleMap.cs:
Corrected big endian working.
Added debug output.
* DiscImageChef.sln:
Added supports for settings.
* DiscImageChef/Commands/Decode.cs:
* DiscImageChef/Commands/Analyze.cs:
* DiscImageChef/Commands/Compare.cs:
* DiscImageChef/Commands/Checksum.cs:
* DiscImageChef/Commands/Benchmark.cs:
* DiscImageChef/Commands/DeviceInfo.cs:
* DiscImageChef/Commands/CreateSidecar.cs:
Added statistics.
* DiscImageChef/Commands/DeviceReport.cs:
Added statistics.
Correct handling empty inquiry string fields.
Suppose it is not removable, til proved wrong.
Corrected MODE SENSE (6/10) detection and calling order.
If device is MMC type but reports neither mode page 2Ah
neither GET CONFIGURATION, try all CDs (old drives work like
that).
Try reading Lead-In and Lead-Out in Audio CD using Audio READ
CD commands.
Corrected READ LONG information handling, some drives return
2s-complement in 32 bit. Upper 16 bits are ignored.
Added support for DVD raw block (37856 bytes).
Check READ LONG up to 36 times the cooked block size. That
should be enough to detect huge blocked media (like DVD and
BD) without taking ages.
If READ LONG size had to be bruteforced, and debug is
activated, save the result.
* DiscImageChef/Commands/DumpMedia.cs:
Added statistics.
Corrected READ LONG information handling, some drives return
2s-complement in 32 bit. Upper 16 bits are ignored.
Start trying with 64 blocks at a time. Some drives report to
be able to read 255 at a time, but they really don't, they
take a lot longer to read.
* DiscImageChef/Commands/MediaScan.cs:
Added statistics.
Start trying with 64 blocks at a time. Some drives report to
be able to read 255 at a time, but they really don't, they
take a lot longer to read.
* DiscImageChef/DiscImageChef.csproj:
Added support for settings.
Added statistics.
* DiscImageChef/Main.cs:
* DiscImageChef/Options.cs:
Added support for settings.
Added statistics.
2016-02-03 18:58:11 +00:00
|
|
|
DicConsole.DebugWriteLine("Apple Partition Map plugin", "APMB.signature = {0:X4}", APMB.signature);
|
|
|
|
|
DicConsole.DebugWriteLine("Apple Partition Map plugin", "APMB.sector_size = {0}", APMB.sector_size);
|
|
|
|
|
DicConsole.DebugWriteLine("Apple Partition Map plugin", "APMB.sectors = {0}", APMB.sectors);
|
|
|
|
|
DicConsole.DebugWriteLine("Apple Partition Map plugin", "APMB.reserved1 = {0:X4}", APMB.reserved1);
|
|
|
|
|
DicConsole.DebugWriteLine("Apple Partition Map plugin", "APMB.reserved2 = {0:X4}", APMB.reserved2);
|
|
|
|
|
DicConsole.DebugWriteLine("Apple Partition Map plugin", "APMB.reserved3 = {0:X8}", APMB.reserved3);
|
|
|
|
|
DicConsole.DebugWriteLine("Apple Partition Map plugin", "APMB.driver_entries = {0}", APMB.driver_entries);
|
|
|
|
|
DicConsole.DebugWriteLine("Apple Partition Map plugin", "APMB.first_driver_blk = {0}", APMB.first_driver_blk);
|
|
|
|
|
DicConsole.DebugWriteLine("Apple Partition Map plugin", "APMB.driver_size = {0}", APMB.driver_size);
|
|
|
|
|
DicConsole.DebugWriteLine("Apple Partition Map plugin", "APMB.operating_system = {0}", APMB.operating_system);
|
|
|
|
|
|
2014-04-14 01:14:20 +00:00
|
|
|
ulong first_sector = 0;
|
|
|
|
|
|
2016-04-19 02:11:47 +01:00
|
|
|
if(APMB.signature == APM_MAGIC) // APM boot block found, APM starts in next sector
|
2014-04-14 01:14:20 +00:00
|
|
|
first_sector = 1;
|
|
|
|
|
|
|
|
|
|
// Read first entry
|
2014-08-28 18:26:14 +01:00
|
|
|
byte[] APMEntry_sector;
|
|
|
|
|
bool APMFromHDDOnCD = false;
|
2014-04-14 01:14:20 +00:00
|
|
|
|
2016-04-19 02:11:47 +01:00
|
|
|
if(sector_size == 2048)
|
2014-08-28 18:26:14 +01:00
|
|
|
{
|
|
|
|
|
APMEntry_sector = Read2048SectorAs512(imagePlugin, first_sector);
|
|
|
|
|
APMEntry = DecodeAPMEntry(APMEntry_sector);
|
|
|
|
|
|
2016-04-19 02:11:47 +01:00
|
|
|
if(APMEntry.signature == APM_ENTRY || APMEntry.signature == APM_OLDENT)
|
2014-08-28 18:26:14 +01:00
|
|
|
{
|
|
|
|
|
sector_size = 512;
|
|
|
|
|
APMFromHDDOnCD = true;
|
2015-10-18 22:04:03 +01:00
|
|
|
DicConsole.DebugWriteLine("Apple Partition Map plugin", "PM sector size is 512 bytes, but device's 2048");
|
2014-08-28 18:26:14 +01:00
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
APMEntry_sector = imagePlugin.ReadSector(first_sector);
|
|
|
|
|
APMEntry = DecodeAPMEntry(APMEntry_sector);
|
|
|
|
|
|
2016-04-19 02:11:47 +01:00
|
|
|
if(APMEntry.signature != APM_ENTRY && APMEntry.signature != APM_OLDENT)
|
2014-08-28 18:26:14 +01:00
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
APMEntry_sector = imagePlugin.ReadSector(first_sector);
|
|
|
|
|
APMEntry = DecodeAPMEntry(APMEntry_sector);
|
|
|
|
|
|
2016-04-19 02:11:47 +01:00
|
|
|
if(APMEntry.signature != APM_ENTRY && APMEntry.signature != APM_OLDENT)
|
2014-08-28 18:26:14 +01:00
|
|
|
return false;
|
|
|
|
|
}
|
2014-04-14 01:14:20 +00:00
|
|
|
|
2016-04-19 02:11:47 +01:00
|
|
|
if(APMEntry.entries <= 1)
|
2014-04-14 01:14:20 +00:00
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
apm_entries = APMEntry.entries;
|
2016-04-19 02:11:47 +01:00
|
|
|
|
|
|
|
|
for(ulong i = 0; i < apm_entries; i++) // For each partition
|
2014-04-14 02:29:13 +00:00
|
|
|
{
|
2014-08-28 18:26:14 +01:00
|
|
|
if(APMFromHDDOnCD)
|
2016-08-09 15:31:44 +01:00
|
|
|
{
|
|
|
|
|
return false;
|
|
|
|
|
// TODO This needs several retesting
|
|
|
|
|
// APMEntry_sector = Read2048SectorAs512(imagePlugin, first_sector + i);
|
|
|
|
|
}
|
2014-08-28 18:26:14 +01:00
|
|
|
else
|
|
|
|
|
APMEntry_sector = imagePlugin.ReadSector(first_sector + i);
|
|
|
|
|
|
|
|
|
|
APMEntry = DecodeAPMEntry(APMEntry_sector);
|
2014-04-14 01:14:20 +00:00
|
|
|
|
2016-04-19 02:11:47 +01:00
|
|
|
if(APMEntry.signature == APM_ENTRY || APMEntry.signature == APM_OLDENT) // It should have partition entry signature
|
2014-04-14 02:29:13 +00:00
|
|
|
{
|
2015-10-05 19:45:07 +01:00
|
|
|
CommonTypes.Partition _partition = new CommonTypes.Partition();
|
2014-04-14 02:29:13 +00:00
|
|
|
StringBuilder sb = new StringBuilder();
|
2016-04-19 02:11:47 +01:00
|
|
|
|
2014-04-14 02:29:13 +00:00
|
|
|
_partition.PartitionSequence = i;
|
|
|
|
|
_partition.PartitionType = APMEntry.type;
|
|
|
|
|
_partition.PartitionName = APMEntry.name;
|
2014-04-14 01:14:20 +00:00
|
|
|
_partition.PartitionStart = APMEntry.start * sector_size;
|
|
|
|
|
_partition.PartitionLength = APMEntry.sectors * sector_size;
|
|
|
|
|
_partition.PartitionStartSector = APMEntry.start;
|
|
|
|
|
_partition.PartitionSectors = APMEntry.sectors;
|
2016-04-19 02:11:47 +01:00
|
|
|
|
2014-04-14 02:29:13 +00:00
|
|
|
sb.AppendLine("Partition flags:");
|
2016-04-19 02:11:47 +01:00
|
|
|
if((APMEntry.status & 0x01) == 0x01)
|
2014-04-14 02:29:13 +00:00
|
|
|
sb.AppendLine("Partition is valid.");
|
2016-04-19 02:11:47 +01:00
|
|
|
if((APMEntry.status & 0x02) == 0x02)
|
2014-04-14 02:29:13 +00:00
|
|
|
sb.AppendLine("Partition entry is not available.");
|
2016-04-19 02:11:47 +01:00
|
|
|
if((APMEntry.status & 0x04) == 0x04)
|
2014-04-14 02:29:13 +00:00
|
|
|
sb.AppendLine("Partition is mounted.");
|
2016-04-19 02:11:47 +01:00
|
|
|
if((APMEntry.status & 0x08) == 0x08)
|
2014-04-14 02:29:13 +00:00
|
|
|
sb.AppendLine("Partition is bootable.");
|
2016-04-19 02:11:47 +01:00
|
|
|
if((APMEntry.status & 0x10) == 0x10)
|
2014-04-14 02:29:13 +00:00
|
|
|
sb.AppendLine("Partition is readable.");
|
2016-04-19 02:11:47 +01:00
|
|
|
if((APMEntry.status & 0x20) == 0x20)
|
2014-04-14 02:29:13 +00:00
|
|
|
sb.AppendLine("Partition is writable.");
|
2016-04-19 02:11:47 +01:00
|
|
|
if((APMEntry.status & 0x40) == 0x40)
|
2014-04-14 02:29:13 +00:00
|
|
|
sb.AppendLine("Partition's boot code is position independent.");
|
2016-04-19 02:11:47 +01:00
|
|
|
|
|
|
|
|
if((APMEntry.status & 0x08) == 0x08)
|
2014-04-14 02:29:13 +00:00
|
|
|
{
|
|
|
|
|
sb.AppendFormat("First boot sector: {0}", APMEntry.first_boot_block).AppendLine();
|
|
|
|
|
sb.AppendFormat("Boot is {0} bytes.", APMEntry.boot_size).AppendLine();
|
|
|
|
|
sb.AppendFormat("Boot load address: 0x{0:X8}", APMEntry.load_address).AppendLine();
|
|
|
|
|
sb.AppendFormat("Boot entry point: 0x{0:X8}", APMEntry.entry_point).AppendLine();
|
|
|
|
|
sb.AppendFormat("Boot code checksum: 0x{0:X8}", APMEntry.checksum).AppendLine();
|
|
|
|
|
sb.AppendFormat("Processor: {0}", APMEntry.processor).AppendLine();
|
|
|
|
|
}
|
2016-04-19 02:11:47 +01:00
|
|
|
|
2014-04-14 02:29:13 +00:00
|
|
|
_partition.PartitionDescription = sb.ToString();
|
2016-04-19 02:11:47 +01:00
|
|
|
|
|
|
|
|
if((APMEntry.status & 0x01) == 0x01)
|
|
|
|
|
if(APMEntry.type != "Apple_partition_map")
|
|
|
|
|
partitions.Add(_partition);
|
2014-04-14 02:29:13 +00:00
|
|
|
}
|
|
|
|
|
}
|
2016-04-19 02:11:47 +01:00
|
|
|
|
2014-04-14 02:29:13 +00:00
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2016-07-28 22:25:26 +01:00
|
|
|
static byte[] Read2048SectorAs512(ImagePlugins.ImagePlugin imagePlugin, ulong LBA)
|
2014-08-28 18:26:14 +01:00
|
|
|
{
|
2016-07-28 22:25:26 +01:00
|
|
|
ulong LBA2k = LBA / 4;
|
2014-08-28 18:26:14 +01:00
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
2014-08-28 19:02:45 +01:00
|
|
|
static AppleMapPartitionEntry DecodeAPMEntry(byte[] APMEntry_sector)
|
2014-08-28 18:26:14 +01:00
|
|
|
{
|
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
2014-04-14 02:29:13 +00:00
|
|
|
public struct AppleMapBootEntry
|
|
|
|
|
{
|
|
|
|
|
// Signature ("ER")
|
2016-07-28 22:25:26 +01:00
|
|
|
public ushort signature;
|
2014-04-14 02:29:13 +00:00
|
|
|
// Byter per sector
|
2016-07-28 22:25:26 +01:00
|
|
|
public ushort sector_size;
|
2014-04-14 02:29:13 +00:00
|
|
|
// Sectors of the disk
|
2016-07-28 22:25:26 +01:00
|
|
|
public uint sectors;
|
2014-04-14 02:29:13 +00:00
|
|
|
// Reserved
|
2016-07-28 22:25:26 +01:00
|
|
|
public ushort reserved1;
|
2014-04-14 02:29:13 +00:00
|
|
|
// Reserved
|
2016-07-28 22:25:26 +01:00
|
|
|
public ushort reserved2;
|
2014-04-14 02:29:13 +00:00
|
|
|
// Reserved
|
2016-07-28 22:25:26 +01:00
|
|
|
public uint reserved3;
|
2014-04-14 02:29:13 +00:00
|
|
|
// Number of entries of the driver descriptor
|
2016-07-28 22:25:26 +01:00
|
|
|
public ushort driver_entries;
|
2014-04-14 02:29:13 +00:00
|
|
|
// First sector of the driver
|
2016-07-28 22:25:26 +01:00
|
|
|
public uint first_driver_blk;
|
2014-04-14 02:29:13 +00:00
|
|
|
// Size in 512bytes sectors of the driver
|
2016-07-28 22:25:26 +01:00
|
|
|
public ushort driver_size;
|
2014-04-14 02:29:13 +00:00
|
|
|
// Operating system (MacOS = 1)
|
2016-07-28 22:25:26 +01:00
|
|
|
public ushort operating_system;
|
2014-04-14 02:29:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public struct AppleMapPartitionEntry
|
|
|
|
|
{
|
|
|
|
|
// Signature ("PM" or "TS")
|
2016-07-28 22:25:26 +01:00
|
|
|
public ushort signature;
|
2014-04-14 02:29:13 +00:00
|
|
|
// Reserved
|
2016-07-28 22:25:26 +01:00
|
|
|
public ushort reserved1;
|
2014-04-14 02:29:13 +00:00
|
|
|
// Number of entries on the partition map, each one sector
|
2016-07-28 22:25:26 +01:00
|
|
|
public uint entries;
|
2014-04-14 02:29:13 +00:00
|
|
|
// First sector of the partition
|
2016-07-28 22:25:26 +01:00
|
|
|
public uint start;
|
2014-04-14 02:29:13 +00:00
|
|
|
// Number of sectos of the partition
|
2016-07-28 22:25:26 +01:00
|
|
|
public uint sectors;
|
2014-04-14 02:29:13 +00:00
|
|
|
// Partition name, 32 bytes, null-padded
|
|
|
|
|
public string name;
|
|
|
|
|
// Partition type. 32 bytes, null-padded
|
|
|
|
|
public string type;
|
|
|
|
|
// First sector of the data area
|
2016-07-28 22:25:26 +01:00
|
|
|
public uint first_data_block;
|
2014-04-14 02:29:13 +00:00
|
|
|
// Number of sectors of the data area
|
2016-07-28 22:25:26 +01:00
|
|
|
public uint data_sectors;
|
2014-04-14 02:29:13 +00:00
|
|
|
// Partition status
|
2016-07-28 22:25:26 +01:00
|
|
|
public uint status;
|
2014-04-14 02:29:13 +00:00
|
|
|
// First sector of the boot code
|
2016-07-28 22:25:26 +01:00
|
|
|
public uint first_boot_block;
|
2014-04-14 02:29:13 +00:00
|
|
|
// Size in bytes of the boot code
|
2016-07-28 22:25:26 +01:00
|
|
|
public uint boot_size;
|
2014-04-14 02:29:13 +00:00
|
|
|
// Load address of the boot code
|
2016-07-28 22:25:26 +01:00
|
|
|
public uint load_address;
|
2014-04-14 02:29:13 +00:00
|
|
|
// Reserved
|
2016-07-28 22:25:26 +01:00
|
|
|
public uint reserved2;
|
2014-04-14 02:29:13 +00:00
|
|
|
// Entry point of the boot code
|
2016-07-28 22:25:26 +01:00
|
|
|
public uint entry_point;
|
2014-04-14 02:29:13 +00:00
|
|
|
// Reserved
|
2016-07-28 22:25:26 +01:00
|
|
|
public uint reserved3;
|
2014-04-14 02:29:13 +00:00
|
|
|
// Boot code checksum
|
2016-07-28 22:25:26 +01:00
|
|
|
public uint checksum;
|
2014-04-14 02:29:13 +00:00
|
|
|
// Processor type, 16 bytes, null-padded
|
|
|
|
|
public string processor;
|
|
|
|
|
}
|
|
|
|
|
}
|
2011-03-03 18:34:33 +00:00
|
|
|
}
|