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-12-19 03:50:57 +00:00
|
|
|
// Copyright © 2011-2018 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.Collections.Generic;
|
2017-07-13 00:19:21 +01:00
|
|
|
using System.Runtime.InteropServices;
|
2017-12-19 19:33:46 +00:00
|
|
|
using System.Text;
|
|
|
|
|
using DiscImageChef.Console;
|
2015-10-18 22:04:03 +01:00
|
|
|
|
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
|
2017-07-01 20:54:02 +01:00
|
|
|
public class AppleMap : PartPlugin
|
2014-04-14 02:29:13 +00:00
|
|
|
{
|
2017-07-13 00:19:21 +01:00
|
|
|
/// <summary>"ER", driver descriptor magic</summary>
|
|
|
|
|
const ushort DDM_MAGIC = 0x4552;
|
|
|
|
|
/// <summary>"PM", new entry magic</summary>
|
|
|
|
|
const ushort APM_MAGIC = 0x504D;
|
|
|
|
|
/// <summary>"TS", old map magic</summary>
|
|
|
|
|
const ushort APM_MAGIC_OLD = 0x5453;
|
|
|
|
|
/// <summary>Old indicator for HFS partition, "TFS1"</summary>
|
|
|
|
|
const uint HFS_MAGIC_OLD = 0x54465331;
|
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");
|
|
|
|
|
}
|
|
|
|
|
|
2017-12-19 20:33:03 +00:00
|
|
|
public override bool GetInformation(ImagePlugins.ImagePlugin imagePlugin,
|
|
|
|
|
out List<CommonTypes.Partition> partitions, ulong sectorOffset)
|
2014-04-14 02:29:13 +00:00
|
|
|
{
|
2014-04-14 01:14:20 +00:00
|
|
|
uint sector_size;
|
|
|
|
|
|
2017-12-19 20:33:03 +00:00
|
|
|
if(imagePlugin.GetSectorSize() == 2352 || imagePlugin.GetSectorSize() == 2448) 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
|
|
|
|
2017-12-19 20:33:03 +00:00
|
|
|
if(sectorOffset + 2 >= imagePlugin.GetSectors()) return false;
|
2017-11-08 17:05:00 +00:00
|
|
|
|
2017-07-24 23:35:33 +01:00
|
|
|
byte[] ddm_sector = imagePlugin.ReadSector(sectorOffset);
|
2017-07-13 00:19:21 +01:00
|
|
|
AppleDriverDescriptorMap ddm;
|
|
|
|
|
|
|
|
|
|
ushort max_drivers = 61;
|
|
|
|
|
|
|
|
|
|
if(sector_size == 256)
|
2014-08-28 18:26:14 +01:00
|
|
|
{
|
2017-07-13 00:19:21 +01:00
|
|
|
byte[] tmp = new byte[512];
|
|
|
|
|
Array.Copy(ddm_sector, 0, tmp, 0, 256);
|
|
|
|
|
ddm_sector = tmp;
|
|
|
|
|
max_drivers = 29;
|
|
|
|
|
}
|
2017-12-19 20:33:03 +00:00
|
|
|
else if(sector_size < 256) return false;
|
|
|
|
|
|
2017-07-13 00:19:21 +01:00
|
|
|
ddm = BigEndianMarshal.ByteArrayToStructureBigEndian<AppleDriverDescriptorMap>(ddm_sector);
|
|
|
|
|
|
|
|
|
|
DicConsole.DebugWriteLine("AppleMap Plugin", "ddm.sbSig = 0x{0:X4}", ddm.sbSig);
|
|
|
|
|
DicConsole.DebugWriteLine("AppleMap Plugin", "ddm.sbBlockSize = {0}", ddm.sbBlockSize);
|
|
|
|
|
DicConsole.DebugWriteLine("AppleMap Plugin", "ddm.sbBlocks = {0}", ddm.sbBlocks);
|
|
|
|
|
DicConsole.DebugWriteLine("AppleMap Plugin", "ddm.sbDevType = {0}", ddm.sbDevType);
|
|
|
|
|
DicConsole.DebugWriteLine("AppleMap Plugin", "ddm.sbDevId = {0}", ddm.sbDevId);
|
|
|
|
|
DicConsole.DebugWriteLine("AppleMap Plugin", "ddm.sbData = 0x{0:X8}", ddm.sbData);
|
|
|
|
|
DicConsole.DebugWriteLine("AppleMap Plugin", "ddm.sbDrvrCount = {0}", ddm.sbDrvrCount);
|
|
|
|
|
|
|
|
|
|
uint sequence = 0;
|
|
|
|
|
|
2017-07-15 01:36:13 +01:00
|
|
|
if(ddm.sbSig == DDM_MAGIC)
|
2017-07-13 00:19:21 +01:00
|
|
|
{
|
2017-07-15 01:36:13 +01:00
|
|
|
if(ddm.sbDrvrCount < max_drivers)
|
2014-08-28 18:26:14 +01:00
|
|
|
{
|
2017-07-15 01:36:13 +01:00
|
|
|
ddm.sbMap = new AppleDriverEntry[ddm.sbDrvrCount];
|
|
|
|
|
for(int i = 0; i < ddm.sbDrvrCount; i++)
|
2017-07-13 00:19:21 +01:00
|
|
|
{
|
2017-07-15 01:36:13 +01:00
|
|
|
byte[] tmp = new byte[8];
|
|
|
|
|
Array.Copy(ddm_sector, 18 + i * 8, tmp, 0, 8);
|
|
|
|
|
ddm.sbMap[i] = BigEndianMarshal.ByteArrayToStructureBigEndian<AppleDriverEntry>(tmp);
|
2017-12-19 20:33:03 +00:00
|
|
|
DicConsole.DebugWriteLine("AppleMap Plugin", "ddm.sbMap[{1}].ddBlock = {0}",
|
|
|
|
|
ddm.sbMap[i].ddBlock, i);
|
|
|
|
|
DicConsole.DebugWriteLine("AppleMap Plugin", "ddm.sbMap[{1}].ddSize = {0}", ddm.sbMap[i].ddSize,
|
|
|
|
|
i);
|
|
|
|
|
DicConsole.DebugWriteLine("AppleMap Plugin", "ddm.sbMap[{1}].ddType = {0}", ddm.sbMap[i].ddType,
|
|
|
|
|
i);
|
|
|
|
|
|
|
|
|
|
if(ddm.sbMap[i].ddSize == 0) continue;
|
2017-07-15 01:36:13 +01:00
|
|
|
|
|
|
|
|
CommonTypes.Partition part = new CommonTypes.Partition()
|
|
|
|
|
{
|
2017-07-19 16:37:11 +01:00
|
|
|
Size = (ulong)(ddm.sbMap[i].ddSize * 512),
|
|
|
|
|
Length = (ulong)((ddm.sbMap[i].ddSize * 512) / sector_size),
|
|
|
|
|
Sequence = sequence,
|
|
|
|
|
Offset = ddm.sbMap[i].ddBlock * sector_size,
|
2017-09-11 20:23:00 +01:00
|
|
|
Start = ddm.sbMap[i].ddBlock + sectorOffset,
|
2017-07-19 16:37:11 +01:00
|
|
|
Type = "Apple_Driver"
|
2017-07-15 01:36:13 +01:00
|
|
|
};
|
2017-07-13 00:19:21 +01:00
|
|
|
|
2017-12-19 20:33:03 +00:00
|
|
|
if((ddm.sbMap[i].ddSize * 512) % sector_size > 0) part.Length++;
|
2017-07-20 13:12:36 +01:00
|
|
|
|
2017-07-15 01:36:13 +01:00
|
|
|
partitions.Add(part);
|
2014-08-28 18:26:14 +01:00
|
|
|
|
2017-07-15 01:36:13 +01:00
|
|
|
sequence++;
|
|
|
|
|
}
|
2014-08-28 18:26:14 +01:00
|
|
|
}
|
|
|
|
|
}
|
2017-07-13 00:19:21 +01:00
|
|
|
|
2017-07-24 23:35:33 +01:00
|
|
|
byte[] part_sector = imagePlugin.ReadSector(1 + sectorOffset);
|
2017-12-19 20:33:03 +00:00
|
|
|
AppleOldDevicePartitionMap old_map =
|
|
|
|
|
BigEndianMarshal.ByteArrayToStructureBigEndian<AppleOldDevicePartitionMap>(part_sector);
|
2017-07-13 00:19:21 +01:00
|
|
|
|
|
|
|
|
// This is the easy one, no sector size mixing
|
|
|
|
|
if(old_map.pdSig == APM_MAGIC_OLD)
|
2014-08-28 18:26:14 +01:00
|
|
|
{
|
2017-12-19 20:33:03 +00:00
|
|
|
for(int i = 2; i < part_sector.Length; i += 12)
|
2017-07-13 00:19:21 +01:00
|
|
|
{
|
|
|
|
|
byte[] tmp = new byte[12];
|
|
|
|
|
Array.Copy(part_sector, i, tmp, 0, 12);
|
2017-12-19 20:33:03 +00:00
|
|
|
AppleMapOldPartitionEntry old_entry =
|
|
|
|
|
BigEndianMarshal.ByteArrayToStructureBigEndian<AppleMapOldPartitionEntry>(tmp);
|
|
|
|
|
DicConsole.DebugWriteLine("AppleMap Plugin", "old_map.sbMap[{1}].pdStart = {0}", old_entry.pdStart,
|
|
|
|
|
(i - 2) / 12);
|
|
|
|
|
DicConsole.DebugWriteLine("AppleMap Plugin", "old_map.sbMap[{1}].pdSize = {0}", old_entry.pdSize,
|
|
|
|
|
(i - 2) / 12);
|
|
|
|
|
DicConsole.DebugWriteLine("AppleMap Plugin", "old_map.sbMap[{1}].pdFSID = 0x{0:X8}",
|
|
|
|
|
old_entry.pdFSID, (i - 2) / 12);
|
2017-07-13 00:19:21 +01:00
|
|
|
|
|
|
|
|
if(old_entry.pdSize == 0 && old_entry.pdFSID == 0)
|
|
|
|
|
{
|
2017-12-19 20:33:03 +00:00
|
|
|
if(old_entry.pdStart == 0) break;
|
|
|
|
|
|
2017-07-13 00:19:21 +01:00
|
|
|
continue;
|
|
|
|
|
}
|
2014-08-28 18:26:14 +01:00
|
|
|
|
2017-07-13 00:19:21 +01:00
|
|
|
CommonTypes.Partition part = new CommonTypes.Partition
|
|
|
|
|
{
|
2017-07-19 16:37:11 +01:00
|
|
|
Size = old_entry.pdStart * ddm.sbBlockSize,
|
|
|
|
|
Length = (old_entry.pdStart * ddm.sbBlockSize) / sector_size,
|
|
|
|
|
Sequence = sequence,
|
|
|
|
|
Offset = old_entry.pdSize * ddm.sbBlockSize,
|
|
|
|
|
Start = (old_entry.pdSize * ddm.sbBlockSize) / sector_size,
|
2017-07-23 22:54:36 +01:00
|
|
|
Scheme = Name
|
2017-07-13 00:19:21 +01:00
|
|
|
};
|
2014-04-14 01:14:20 +00:00
|
|
|
|
2017-12-19 20:33:03 +00:00
|
|
|
if(old_entry.pdFSID == HFS_MAGIC_OLD) part.Type = "Apple_HFS";
|
|
|
|
|
else part.Type = string.Format("0x{0:X8}", old_entry.pdFSID);
|
2017-07-13 00:19:21 +01:00
|
|
|
|
|
|
|
|
partitions.Add(part);
|
2014-04-14 01:14:20 +00:00
|
|
|
|
2017-07-13 00:19:21 +01:00
|
|
|
sequence++;
|
|
|
|
|
}
|
|
|
|
|
|
2017-07-15 01:36:13 +01:00
|
|
|
return partitions.Count > 0;
|
2017-07-13 00:19:21 +01:00
|
|
|
}
|
2016-04-19 02:11:47 +01:00
|
|
|
|
2017-07-13 00:19:21 +01:00
|
|
|
AppleMapPartitionEntry entry;
|
|
|
|
|
uint entry_size;
|
|
|
|
|
uint entry_count;
|
|
|
|
|
uint sectors_to_read;
|
|
|
|
|
uint skip_ddm;
|
|
|
|
|
|
|
|
|
|
// If sector is bigger than 512
|
|
|
|
|
if(sector_size > 512)
|
2014-04-14 02:29:13 +00:00
|
|
|
{
|
2017-07-13 00:19:21 +01:00
|
|
|
byte[] tmp = new byte[512];
|
2017-12-19 20:33:03 +00:00
|
|
|
Array.Copy(ddm_sector, 512, tmp, 0, 512);
|
2017-07-13 00:19:21 +01:00
|
|
|
entry = BigEndianMarshal.ByteArrayToStructureBigEndian<AppleMapPartitionEntry>(tmp);
|
|
|
|
|
// Check for a partition entry that's 512-byte aligned
|
|
|
|
|
if(entry.signature == APM_MAGIC)
|
2016-08-09 15:31:44 +01:00
|
|
|
{
|
2017-07-13 00:19:21 +01:00
|
|
|
DicConsole.DebugWriteLine("AppleMap Plugin", "Found misaligned entry.");
|
|
|
|
|
entry_size = 512;
|
|
|
|
|
entry_count = entry.entries;
|
|
|
|
|
skip_ddm = 512;
|
|
|
|
|
sectors_to_read = (((entry_count + 1) * 512) / sector_size) + 1;
|
2016-08-09 15:31:44 +01:00
|
|
|
}
|
2014-08-28 18:26:14 +01:00
|
|
|
else
|
2014-04-14 02:29:13 +00:00
|
|
|
{
|
2017-07-13 00:19:21 +01:00
|
|
|
entry = BigEndianMarshal.ByteArrayToStructureBigEndian<AppleMapPartitionEntry>(part_sector);
|
|
|
|
|
if(entry.signature == APM_MAGIC)
|
2014-04-14 02:29:13 +00:00
|
|
|
{
|
2017-07-13 00:19:21 +01:00
|
|
|
DicConsole.DebugWriteLine("AppleMap Plugin", "Found aligned entry.");
|
|
|
|
|
entry_size = sector_size;
|
|
|
|
|
entry_count = entry.entries;
|
|
|
|
|
skip_ddm = sector_size;
|
|
|
|
|
sectors_to_read = entry_count + 2;
|
2014-04-14 02:29:13 +00:00
|
|
|
}
|
2017-12-19 20:33:03 +00:00
|
|
|
else return partitions.Count > 0;
|
2017-07-13 00:19:21 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
entry = BigEndianMarshal.ByteArrayToStructureBigEndian<AppleMapPartitionEntry>(part_sector);
|
|
|
|
|
if(entry.signature == APM_MAGIC)
|
|
|
|
|
{
|
|
|
|
|
DicConsole.DebugWriteLine("AppleMap Plugin", "Found aligned entry.");
|
|
|
|
|
entry_size = sector_size;
|
|
|
|
|
entry_count = entry.entries;
|
|
|
|
|
skip_ddm = sector_size;
|
|
|
|
|
sectors_to_read = entry_count + 2;
|
|
|
|
|
}
|
2017-12-19 20:33:03 +00:00
|
|
|
else return partitions.Count > 0;
|
2017-07-13 00:19:21 +01:00
|
|
|
}
|
|
|
|
|
|
2017-07-24 23:35:33 +01:00
|
|
|
byte[] entries = imagePlugin.ReadSectors(sectorOffset, sectors_to_read);
|
2017-07-13 00:19:21 +01:00
|
|
|
DicConsole.DebugWriteLine("AppleMap Plugin", "entry_size = {0}", entry_size);
|
|
|
|
|
DicConsole.DebugWriteLine("AppleMap Plugin", "entry_count = {0}", entry_count);
|
|
|
|
|
DicConsole.DebugWriteLine("AppleMap Plugin", "skip_ddm = {0}", skip_ddm);
|
|
|
|
|
DicConsole.DebugWriteLine("AppleMap Plugin", "sectors_to_read = {0}", sectors_to_read);
|
2016-04-19 02:11:47 +01:00
|
|
|
|
2017-07-13 00:19:21 +01:00
|
|
|
byte[] copy = new byte[entries.Length - skip_ddm];
|
|
|
|
|
Array.Copy(entries, skip_ddm, copy, 0, copy.Length);
|
|
|
|
|
entries = copy;
|
2016-04-19 02:11:47 +01:00
|
|
|
|
2017-07-13 00:19:21 +01:00
|
|
|
for(int i = 0; i < entry_count; i++)
|
|
|
|
|
{
|
|
|
|
|
byte[] tmp = new byte[entry_size];
|
|
|
|
|
Array.Copy(entries, i * entry_size, tmp, 0, entry_size);
|
|
|
|
|
entry = BigEndianMarshal.ByteArrayToStructureBigEndian<AppleMapPartitionEntry>(tmp);
|
|
|
|
|
if(entry.signature == APM_MAGIC)
|
|
|
|
|
{
|
|
|
|
|
DicConsole.DebugWriteLine("AppleMap Plugin", "dpme[{0}].signature = 0x{1:X4}", i, entry.signature);
|
|
|
|
|
DicConsole.DebugWriteLine("AppleMap Plugin", "dpme[{0}].reserved1 = 0x{1:X4}", i, entry.reserved1);
|
|
|
|
|
DicConsole.DebugWriteLine("AppleMap Plugin", "dpme[{0}].entries = {1}", i, entry.entries);
|
|
|
|
|
DicConsole.DebugWriteLine("AppleMap Plugin", "dpme[{0}].start = {1}", i, entry.start);
|
|
|
|
|
DicConsole.DebugWriteLine("AppleMap Plugin", "dpme[{0}].sectors = {1}", i, entry.sectors);
|
2017-12-19 20:33:03 +00:00
|
|
|
DicConsole.DebugWriteLine("AppleMap Plugin", "dpme[{0}].name = \"{1}\"", i,
|
|
|
|
|
StringHandlers.CToString(entry.name));
|
|
|
|
|
DicConsole.DebugWriteLine("AppleMap Plugin", "dpme[{0}].type = \"{1}\"", i,
|
|
|
|
|
StringHandlers.CToString(entry.type));
|
|
|
|
|
DicConsole.DebugWriteLine("AppleMap Plugin", "dpme[{0}].first_data_block = {1}", i,
|
|
|
|
|
entry.first_data_block);
|
2017-07-13 00:19:21 +01:00
|
|
|
DicConsole.DebugWriteLine("AppleMap Plugin", "dpme[{0}].data_sectors = {1}", i, entry.data_sectors);
|
2017-12-19 20:33:03 +00:00
|
|
|
DicConsole.DebugWriteLine("AppleMap Plugin", "dpme[{0}].flags = {1}", i,
|
|
|
|
|
(AppleMapFlags)entry.flags);
|
|
|
|
|
DicConsole.DebugWriteLine("AppleMap Plugin", "dpme[{0}].first_boot_block = {1}", i,
|
|
|
|
|
entry.first_boot_block);
|
2017-07-13 00:19:21 +01:00
|
|
|
DicConsole.DebugWriteLine("AppleMap Plugin", "dpme[{0}].boot_size = {1}", i, entry.boot_size);
|
2017-12-19 20:33:03 +00:00
|
|
|
DicConsole.DebugWriteLine("AppleMap Plugin", "dpme[{0}].load_address = 0x{1:X8}", i,
|
|
|
|
|
entry.load_address);
|
|
|
|
|
DicConsole.DebugWriteLine("AppleMap Plugin", "dpme[{0}].load_address2 = 0x{1:X8}", i,
|
|
|
|
|
entry.load_address2);
|
|
|
|
|
DicConsole.DebugWriteLine("AppleMap Plugin", "dpme[{0}].entry_point = 0x{1:X8}", i,
|
|
|
|
|
entry.entry_point);
|
|
|
|
|
DicConsole.DebugWriteLine("AppleMap Plugin", "dpme[{0}].entry_point2 = 0x{1:X8}", i,
|
|
|
|
|
entry.entry_point2);
|
2017-07-13 00:19:21 +01:00
|
|
|
DicConsole.DebugWriteLine("AppleMap Plugin", "dpme[{0}].checksum = 0x{1:X8}", i, entry.checksum);
|
2017-12-19 20:33:03 +00:00
|
|
|
DicConsole.DebugWriteLine("AppleMap Plugin", "dpme[{0}].processor = \"{1}\"", i,
|
|
|
|
|
StringHandlers.CToString(entry.processor));
|
2017-07-13 00:19:21 +01:00
|
|
|
|
|
|
|
|
AppleMapFlags flags = (AppleMapFlags)entry.flags;
|
|
|
|
|
|
|
|
|
|
// BeOS doesn't mark its partitions as valid
|
|
|
|
|
//if(flags.HasFlag(AppleMapFlags.Valid) &&
|
2017-07-23 19:57:10 +01:00
|
|
|
if(StringHandlers.CToString(entry.type) != "Apple_partition_map" && entry.sectors > 0)
|
2017-07-13 00:19:21 +01:00
|
|
|
{
|
|
|
|
|
StringBuilder sb = new StringBuilder();
|
|
|
|
|
|
|
|
|
|
CommonTypes.Partition _partition = new CommonTypes.Partition
|
|
|
|
|
{
|
2017-07-19 16:37:11 +01:00
|
|
|
Sequence = sequence,
|
|
|
|
|
Type = StringHandlers.CToString(entry.type),
|
|
|
|
|
Name = StringHandlers.CToString(entry.name),
|
|
|
|
|
Offset = entry.start * entry_size,
|
|
|
|
|
Size = entry.sectors * entry_size,
|
2017-09-11 20:23:00 +01:00
|
|
|
Start = ((entry.start * entry_size) / sector_size) + sectorOffset,
|
2017-07-23 22:54:36 +01:00
|
|
|
Length = (entry.sectors * entry_size) / sector_size,
|
|
|
|
|
Scheme = Name
|
2017-07-13 00:19:21 +01:00
|
|
|
};
|
|
|
|
|
sb.AppendLine("Partition flags:");
|
2017-12-19 20:33:03 +00:00
|
|
|
if(flags.HasFlag(AppleMapFlags.Valid)) sb.AppendLine("Partition is valid.");
|
|
|
|
|
if(flags.HasFlag(AppleMapFlags.Allocated)) sb.AppendLine("Partition entry is allocated.");
|
|
|
|
|
if(flags.HasFlag(AppleMapFlags.InUse)) sb.AppendLine("Partition is in use.");
|
|
|
|
|
if(flags.HasFlag(AppleMapFlags.Bootable)) sb.AppendLine("Partition is bootable.");
|
|
|
|
|
if(flags.HasFlag(AppleMapFlags.Readable)) sb.AppendLine("Partition is readable.");
|
|
|
|
|
if(flags.HasFlag(AppleMapFlags.Writable)) sb.AppendLine("Partition is writable.");
|
2017-07-13 00:19:21 +01:00
|
|
|
|
|
|
|
|
if(flags.HasFlag(AppleMapFlags.Bootable))
|
|
|
|
|
{
|
2017-12-19 20:33:03 +00:00
|
|
|
sb.AppendFormat("First boot sector: {0}",
|
|
|
|
|
(entry.first_boot_block * entry_size) / sector_size).AppendLine();
|
2017-07-13 00:19:21 +01:00
|
|
|
sb.AppendFormat("Boot is {0} bytes.", entry.boot_size).AppendLine();
|
|
|
|
|
sb.AppendFormat("Boot load address: 0x{0:X8}", entry.load_address).AppendLine();
|
|
|
|
|
sb.AppendFormat("Boot entry point: 0x{0:X8}", entry.entry_point).AppendLine();
|
|
|
|
|
sb.AppendFormat("Boot code checksum: 0x{0:X8}", entry.checksum).AppendLine();
|
|
|
|
|
sb.AppendFormat("Processor: {0}", StringHandlers.CToString(entry.processor)).AppendLine();
|
|
|
|
|
|
|
|
|
|
if(flags.HasFlag(AppleMapFlags.PicCode))
|
|
|
|
|
sb.AppendLine("Partition's boot code is position independent.");
|
|
|
|
|
}
|
|
|
|
|
|
2017-07-19 16:37:11 +01:00
|
|
|
_partition.Description = sb.ToString();
|
2017-12-19 20:33:03 +00:00
|
|
|
if(_partition.Start < imagePlugin.ImageInfo.sectors &&
|
|
|
|
|
_partition.End < imagePlugin.ImageInfo.sectors)
|
2017-08-07 16:09:46 +01:00
|
|
|
{
|
|
|
|
|
partitions.Add(_partition);
|
|
|
|
|
sequence++;
|
|
|
|
|
}
|
2017-07-23 19:57:10 +01:00
|
|
|
// Some CD and DVDs end with an Apple_Free that expands beyond the disc size...
|
2017-08-07 16:09:46 +01:00
|
|
|
else if(_partition.Start < imagePlugin.ImageInfo.sectors)
|
2017-07-23 19:57:10 +01:00
|
|
|
{
|
2017-12-19 20:33:03 +00:00
|
|
|
DicConsole.DebugWriteLine("AppleMap Plugin",
|
|
|
|
|
"Cutting last partition end ({0}) to media size ({1})",
|
|
|
|
|
_partition.End, imagePlugin.ImageInfo.sectors - 1);
|
2017-08-07 16:09:46 +01:00
|
|
|
_partition.Length = imagePlugin.ImageInfo.sectors - _partition.Start;
|
2017-07-23 19:57:10 +01:00
|
|
|
partitions.Add(_partition);
|
|
|
|
|
sequence++;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2017-12-19 20:33:03 +00:00
|
|
|
DicConsole.DebugWriteLine("AppleMap Plugin",
|
|
|
|
|
"Not adding partition becaus start ({0}) is outside media size ({1})",
|
|
|
|
|
_partition.Start, imagePlugin.ImageInfo.sectors - 1);
|
2017-07-23 19:57:10 +01:00
|
|
|
}
|
2017-07-13 00:19:21 +01:00
|
|
|
}
|
2014-04-14 02:29:13 +00:00
|
|
|
}
|
|
|
|
|
}
|
2016-04-19 02:11:47 +01:00
|
|
|
|
2017-07-15 01:36:13 +01:00
|
|
|
return partitions.Count > 0;
|
2014-04-14 02:29:13 +00:00
|
|
|
}
|
|
|
|
|
|
2017-07-13 00:19:21 +01:00
|
|
|
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
|
|
|
|
public struct AppleDriverDescriptorMap
|
2014-08-28 18:26:14 +01:00
|
|
|
{
|
2017-07-13 00:19:21 +01:00
|
|
|
/// <summary>Signature <see cref="DDM_MAGIC"/></summary>
|
|
|
|
|
public ushort sbSig;
|
|
|
|
|
/// <summary>Byter per sector</summary>
|
|
|
|
|
public ushort sbBlockSize;
|
|
|
|
|
/// <summary>Sectors of the disk</summary>
|
|
|
|
|
public uint sbBlocks;
|
|
|
|
|
/// <summary>Device type</summary>
|
|
|
|
|
public ushort sbDevType;
|
|
|
|
|
/// <summary>Device ID</summary>
|
|
|
|
|
public ushort sbDevId;
|
|
|
|
|
/// <summary>Reserved</summary>
|
|
|
|
|
public uint sbData;
|
|
|
|
|
/// <summary>Number of entries of the driver descriptor</summary>
|
|
|
|
|
public ushort sbDrvrCount;
|
|
|
|
|
/// <summary>Entries of the driver descriptor</summary>
|
2017-12-19 20:33:03 +00:00
|
|
|
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 61)] public AppleDriverEntry[] sbMap;
|
2017-07-13 00:19:21 +01:00
|
|
|
}
|
2014-08-28 18:26:14 +01:00
|
|
|
|
2017-07-13 00:19:21 +01:00
|
|
|
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
|
|
|
|
public struct AppleDriverEntry
|
|
|
|
|
{
|
|
|
|
|
/// <summary>First sector of the driver</summary>
|
|
|
|
|
public uint ddBlock;
|
|
|
|
|
/// <summary>Size in 512bytes sectors of the driver</summary>
|
|
|
|
|
public ushort ddSize;
|
|
|
|
|
/// <summary>Operating system (MacOS = 1)</summary>
|
|
|
|
|
public ushort ddType;
|
|
|
|
|
}
|
2014-08-28 18:26:14 +01:00
|
|
|
|
2017-07-13 00:19:21 +01:00
|
|
|
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
|
|
|
|
public struct AppleOldDevicePartitionMap
|
|
|
|
|
{
|
|
|
|
|
/// <summary>Signature <see cref="APM_MAGIC_OLD"/></summary>
|
|
|
|
|
public ushort pdSig;
|
|
|
|
|
/// <summary>Entries of the driver descriptor</summary>
|
2017-12-19 20:33:03 +00:00
|
|
|
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 42)] public AppleMapOldPartitionEntry[] pdMap;
|
2014-08-28 18:26:14 +01:00
|
|
|
}
|
|
|
|
|
|
2017-07-13 00:19:21 +01:00
|
|
|
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
|
|
|
|
public struct AppleMapOldPartitionEntry
|
2014-08-28 18:26:14 +01:00
|
|
|
{
|
2017-07-13 00:19:21 +01:00
|
|
|
/// <summary>First sector of the partition</summary>
|
|
|
|
|
public uint pdStart;
|
|
|
|
|
/// <summary>Number of sectors of the partition</summary>
|
|
|
|
|
public uint pdSize;
|
|
|
|
|
/// <summary>Partition type</summary>
|
|
|
|
|
public uint pdFSID;
|
2014-08-28 18:26:14 +01:00
|
|
|
}
|
|
|
|
|
|
2017-07-13 00:19:21 +01:00
|
|
|
[Flags]
|
|
|
|
|
public enum AppleMapFlags : uint
|
2014-04-14 02:29:13 +00:00
|
|
|
{
|
2017-07-13 00:19:21 +01:00
|
|
|
/// <summary>Partition is valid</summary>
|
|
|
|
|
Valid = 0x01,
|
|
|
|
|
/// <summary>Partition is allocated</summary>
|
|
|
|
|
Allocated = 0x02,
|
|
|
|
|
/// <summary>Partition is in use</summary>
|
|
|
|
|
InUse = 0x04,
|
|
|
|
|
/// <summary>Partition is bootable</summary>
|
|
|
|
|
Bootable = 0x08,
|
|
|
|
|
/// <summary>Partition is readable</summary>
|
|
|
|
|
Readable = 0x10,
|
|
|
|
|
/// <summary>Partition is writable</summary>
|
|
|
|
|
Writable = 0x20,
|
|
|
|
|
/// <summary>Partition boot code is position independent</summary>
|
|
|
|
|
PicCode = 0x40,
|
|
|
|
|
/// <summary>OS specific flag</summary>
|
|
|
|
|
Specific1 = 0x80,
|
|
|
|
|
/// <summary>OS specific flag</summary>
|
|
|
|
|
Specific2 = 0x100,
|
|
|
|
|
/// <summary>Unknown, seen in the wild</summary>
|
|
|
|
|
Unknown = 0x200,
|
|
|
|
|
/// <summary>Unknown, seen in the wild</summary>
|
|
|
|
|
Unknown2 = 0x40000000,
|
|
|
|
|
/// <summary>Reserved, not seen in the wild</summary>
|
|
|
|
|
Reserved = 0xBFFFFC00,
|
2014-04-14 02:29:13 +00:00
|
|
|
}
|
|
|
|
|
|
2017-07-13 00:19:21 +01:00
|
|
|
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
2014-04-14 02:29:13 +00:00
|
|
|
public struct AppleMapPartitionEntry
|
|
|
|
|
{
|
2017-07-13 00:19:21 +01:00
|
|
|
/// <summary>Signature <see cref="APM_MAGIC"/></summary>
|
2016-07-28 22:25:26 +01:00
|
|
|
public ushort signature;
|
2017-07-13 00:19:21 +01:00
|
|
|
/// <summary>Reserved</summary>
|
2016-07-28 22:25:26 +01:00
|
|
|
public ushort reserved1;
|
2017-07-13 00:19:21 +01:00
|
|
|
/// <summary>Number of entries on the partition map, each one sector</summary>
|
2016-07-28 22:25:26 +01:00
|
|
|
public uint entries;
|
2017-07-13 00:19:21 +01:00
|
|
|
/// <summary>First sector of the partition</summary>
|
2016-07-28 22:25:26 +01:00
|
|
|
public uint start;
|
2017-07-13 00:19:21 +01:00
|
|
|
/// <summary>Number of sectos of the partition</summary>
|
2016-07-28 22:25:26 +01:00
|
|
|
public uint sectors;
|
2017-07-13 00:19:21 +01:00
|
|
|
/// <summary>Partition name, 32 bytes, null-padded</summary>
|
2017-12-19 20:33:03 +00:00
|
|
|
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 32)] public byte[] name;
|
2017-07-13 00:19:21 +01:00
|
|
|
/// <summary>Partition type. 32 bytes, null-padded</summary>
|
2017-12-19 20:33:03 +00:00
|
|
|
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 32)] public byte[] type;
|
2017-07-13 00:19:21 +01:00
|
|
|
/// <summary>First sector of the data area</summary>
|
2016-07-28 22:25:26 +01:00
|
|
|
public uint first_data_block;
|
2017-07-13 00:19:21 +01:00
|
|
|
/// <summary>Number of sectors of the data area</summary>
|
2016-07-28 22:25:26 +01:00
|
|
|
public uint data_sectors;
|
2017-07-13 00:19:21 +01:00
|
|
|
/// <summary>Partition flags</summary>
|
|
|
|
|
public uint flags;
|
|
|
|
|
/// <summary>First sector of the boot code</summary>
|
2016-07-28 22:25:26 +01:00
|
|
|
public uint first_boot_block;
|
2017-07-13 00:19:21 +01:00
|
|
|
/// <summary>Size in bytes of the boot code</summary>
|
2016-07-28 22:25:26 +01:00
|
|
|
public uint boot_size;
|
2017-07-13 00:19:21 +01:00
|
|
|
/// <summary>Load address of the boot code</summary>
|
2016-07-28 22:25:26 +01:00
|
|
|
public uint load_address;
|
2017-07-13 00:19:21 +01:00
|
|
|
/// <summary>Load address of the boot code</summary>
|
|
|
|
|
public uint load_address2;
|
|
|
|
|
/// <summary>Entry point of the boot code</summary>
|
2016-07-28 22:25:26 +01:00
|
|
|
public uint entry_point;
|
2017-07-13 00:19:21 +01:00
|
|
|
/// <summary>Entry point of the boot code</summary>
|
|
|
|
|
public uint entry_point2;
|
|
|
|
|
/// <summary>Boot code checksum</summary>
|
2016-07-28 22:25:26 +01:00
|
|
|
public uint checksum;
|
2017-07-13 00:19:21 +01:00
|
|
|
/// <summary>Processor type, 16 bytes, null-padded</summary>
|
2017-12-19 20:33:03 +00:00
|
|
|
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)] public byte[] processor;
|
2017-07-13 00:19:21 +01:00
|
|
|
/// <summary>Boot arguments</summary>
|
2017-12-19 20:33:03 +00:00
|
|
|
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 32)] public uint[] boot_arguments;
|
2014-04-14 02:29:13 +00:00
|
|
|
}
|
|
|
|
|
}
|
2011-03-03 18:34:33 +00:00
|
|
|
}
|