REFACTOR: Final cleanup of DiscImageChef.Partitions.

This commit is contained in:
2017-12-24 03:11:33 +00:00
parent 9dda52522c
commit 3f628cd3c9
19 changed files with 1638 additions and 1620 deletions

View File

@@ -108,7 +108,8 @@ namespace DiscImageChef.Partitions
}
}
switch(bootBlock.flags & TYPE_MASK) {
switch(bootBlock.flags & TYPE_MASK)
{
case TYPE_LINUX:
{
IntPtr tablePtr = Marshal.AllocHGlobal(512);

View File

@@ -59,8 +59,7 @@ namespace DiscImageChef.Partitions
PluginUuid = new Guid("36405F8D-4F1A-07F5-209C-223D735D6D22");
}
public override bool GetInformation(ImagePlugin imagePlugin,
out List<Partition> partitions, ulong sectorOffset)
public override bool GetInformation(ImagePlugin imagePlugin, out List<Partition> partitions, ulong sectorOffset)
{
uint sectorSize;
@@ -84,7 +83,8 @@ namespace DiscImageChef.Partitions
}
else if(sectorSize < 256) return false;
AppleDriverDescriptorMap ddm = BigEndianMarshal.ByteArrayToStructureBigEndian<AppleDriverDescriptorMap>(ddmSector);
AppleDriverDescriptorMap ddm =
BigEndianMarshal.ByteArrayToStructureBigEndian<AppleDriverDescriptorMap>(ddmSector);
DicConsole.DebugWriteLine("AppleMap Plugin", "ddm.sbSig = 0x{0:X4}", ddm.sbSig);
DicConsole.DebugWriteLine("AppleMap Plugin", "ddm.sbBlockSize = {0}", ddm.sbBlockSize);
@@ -170,7 +170,6 @@ namespace DiscImageChef.Partitions
Type = oldEntry.pdFSID == HFS_MAGIC_OLD ? "Apple_HFS" : $"0x{oldEntry.pdFSID:X8}"
};
partitions.Add(part);
sequence++;
@@ -257,8 +256,7 @@ namespace DiscImageChef.Partitions
DicConsole.DebugWriteLine("AppleMap Plugin", "dpme[{0}].first_data_block = {1}", i,
entry.first_data_block);
DicConsole.DebugWriteLine("AppleMap Plugin", "dpme[{0}].data_sectors = {1}", i, entry.data_sectors);
DicConsole.DebugWriteLine("AppleMap Plugin", "dpme[{0}].flags = {1}", i,
(AppleMapFlags)entry.flags);
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);
DicConsole.DebugWriteLine("AppleMap Plugin", "dpme[{0}].boot_size = {1}", i, entry.boot_size);
@@ -266,8 +264,7 @@ namespace DiscImageChef.Partitions
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_point = 0x{1:X8}", i, entry.entry_point);
DicConsole.DebugWriteLine("AppleMap Plugin", "dpme[{0}].entry_point2 = 0x{1:X8}", i,
entry.entry_point2);
DicConsole.DebugWriteLine("AppleMap Plugin", "dpme[{0}].checksum = 0x{1:X8}", i, entry.checksum);
@@ -303,8 +300,8 @@ namespace DiscImageChef.Partitions
if(flags.HasFlag(AppleMapFlags.Bootable))
{
sb.AppendFormat("First boot sector: {0}",
entry.first_boot_block * entrySize / sectorSize).AppendLine();
sb.AppendFormat("First boot sector: {0}", entry.first_boot_block * entrySize / sectorSize)
.AppendLine();
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();
@@ -316,8 +313,7 @@ namespace DiscImageChef.Partitions
}
_partition.Description = sb.ToString();
if(_partition.Start < imagePlugin.ImageInfo.Sectors &&
_partition.End < imagePlugin.ImageInfo.Sectors)
if(_partition.Start < imagePlugin.ImageInfo.Sectors && _partition.End < imagePlugin.ImageInfo.Sectors)
{
partitions.Add(_partition);
sequence++;
@@ -325,8 +321,7 @@ namespace DiscImageChef.Partitions
// Some CD and DVDs end with an Apple_Free that expands beyond the disc size...
else if(_partition.Start < imagePlugin.ImageInfo.Sectors)
{
DicConsole.DebugWriteLine("AppleMap Plugin",
"Cutting last partition end ({0}) to media size ({1})",
DicConsole.DebugWriteLine("AppleMap Plugin", "Cutting last partition end ({0}) to media size ({1})",
_partition.End, imagePlugin.ImageInfo.Sectors - 1);
_partition.Length = imagePlugin.ImageInfo.Sectors - _partition.Start;
partitions.Add(_partition);

View File

@@ -41,7 +41,7 @@ namespace DiscImageChef.Partitions
{
public class Apricot : PartitionPlugin
{
readonly string[] operatingSystemCodes = {"Invalid", "MS-DOS", "UCSD Pascal", "CP/M", "Concurrent CP/M"};
readonly int[] baudRates = {50, 75, 110, 134, 150, 300, 600, 1200, 1800, 2400, 3600, 4800, 7200, 9600, 19200};
readonly string[] bootTypeCodes =
{
"Non-bootable", "Apricot & XI RAM BIOS", "Generic ROM BIOS", "Apricot & XI ROM BIOS",
@@ -49,12 +49,12 @@ namespace DiscImageChef.Partitions
};
readonly string[] diskTypeCodes =
{"MF1DD 70-track", "MF1DD", "MF2DD", "Winchester 5M", "Winchester 10M", "Winchester 20M"};
readonly string[] printDevices = {"Parallel", "Serial"};
readonly int[] lineModes = {256, 200};
readonly int[] lineWidths = {80, 40};
readonly int[] baudRates = {50, 75, 110, 134, 150, 300, 600, 1200, 1800, 2400, 3600, 4800, 7200, 9600, 19200};
readonly double[] stopBits = {1, 1.5, 2};
readonly string[] operatingSystemCodes = {"Invalid", "MS-DOS", "UCSD Pascal", "CP/M", "Concurrent CP/M"};
readonly string[] parityTypes = {"None", "Odd", "Even", "Mark", "Space"};
readonly string[] printDevices = {"Parallel", "Serial"};
readonly double[] stopBits = {1, 1.5, 2};
public Apricot()
{

View File

@@ -61,8 +61,7 @@ namespace DiscImageChef.Partitions
PluginUuid = new Guid("d1dd0f24-ec39-4c4d-9072-be31919a3b5e");
}
public override bool GetInformation(ImagePlugin imagePlugin,
out List<Partition> partitions, ulong sectorOffset)
public override bool GetInformation(ImagePlugin imagePlugin, out List<Partition> partitions, ulong sectorOffset)
{
partitions = new List<Partition>();

View File

@@ -44,12 +44,12 @@ namespace DiscImageChef.Partitions
{
const uint DISKMAGIC = 0x82564557;
const uint DISKCIGAM = 0x57455682;
/// <summary>Maximum size of a disklabel with 22 partitions</summary>
const uint MAX_LABEL_SIZE = 500;
/// <summary>Known sector locations for BSD disklabel</summary>
readonly ulong[] labelLocations = {0, 1, 2, 9};
/// <summary>Known byte offsets for BSD disklabel</summary>
readonly uint[] labelOffsets = {0, 9, 64, 128, 516};
/// <summary>Maximum size of a disklabel with 22 partitions</summary>
const uint MAX_LABEL_SIZE = 500;
public BSD()
{
@@ -167,6 +167,62 @@ namespace DiscImageChef.Partitions
return partitions.Count > 0;
}
internal static string fsTypeToString(fsType typ)
{
switch(typ)
{
case fsType.Unused: return "Unused entry";
case fsType.Swap: return "Swap partition";
case fsType.V6: return "UNIX 6th Edition";
case fsType.V7: return "UNIX 7th Edition";
case fsType.SystemV: return "UNIX System V";
case fsType.V7_1K: return "UNIX 7th Edition with 1K blocks";
case fsType.V8: return "UNIX 8th Edition with 4K blocks";
case fsType.BSDFFS: return "4.2BSD Fast File System";
case fsType.BSDLFS: return "4.4LFS";
case fsType.HPFS: return "HPFS";
case fsType.ISO9660: return "ISO9660";
case fsType.Boot:
case fsType.SysVBoot: return "Boot";
case fsType.AFFS: return "Amiga FFS";
case fsType.HFS: return "Apple HFS";
case fsType.ADVfs: return "Digital Advanced File System";
case fsType.LSMpublic: return "Digital LSM Public Region";
case fsType.LSMprivate: return "Digital LSM Private Region";
case fsType.LSMsimple: return "Digital LSM Simple Disk";
case fsType.CCD: return "Concatenated disk";
case fsType.JFS2: return "IBM JFS2";
case fsType.HAMMER: return "Hammer";
case fsType.HAMMER2: return "Hammer2";
case fsType.UDF: return "UDF";
case fsType.EFS: return "EFS";
case fsType.ZFS: return "ZFS";
case fsType.NANDFS: return "FreeBSD nandfs";
case fsType.MSDOS: return "FAT";
case fsType.Other: return "Other or unknown";
default: return "Unknown";
}
}
static DiskLabel GetDiskLabel(byte[] disklabel)
{
GCHandle handle = GCHandle.Alloc(disklabel, GCHandleType.Pinned);
DiskLabel dl = (DiskLabel)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(DiskLabel));
handle.Free();
return dl;
}
static DiskLabel SwapDiskLabel(DiskLabel disklabel)
{
DiskLabel dl = BigEndianMarshal.SwapStructureMembersEndian(disklabel);
for(int i = 0; i < dl.d_drivedata.Length; i++) dl.d_drivedata[i] = Swapping.Swap(dl.d_drivedata[i]);
for(int i = 0; i < dl.d_spare.Length; i++) dl.d_spare[i] = Swapping.Swap(dl.d_spare[i]);
for(int i = 0; i < dl.d_partitions.Length; i++)
dl.d_partitions[i] = BigEndianMarshal.SwapStructureMembersEndian(dl.d_partitions[i]);
return dl;
}
/// <summary>Drive type</summary>
enum dType : ushort
{
@@ -318,9 +374,13 @@ namespace DiscImageChef.Partitions
[StructLayout(LayoutKind.Sequential, Pack = 1)]
struct DiskLabel
{
/// <summary><see cref="DISKMAGIC"/></summary>
/// <summary>
/// <see cref="DISKMAGIC" />
/// </summary>
public uint d_magic;
/// <summary><see cref="dType"/></summary>
/// <summary>
/// <see cref="dType" />
/// </summary>
public dType d_type;
/// <summary>Disk subtype</summary>
public ushort d_subtype;
@@ -358,7 +418,9 @@ namespace DiscImageChef.Partitions
public uint d_headswitch;
/// <summary>Track to track seek in microseconds</summary>
public uint d_trkseek;
/// <summary><see cref="dFlags"/></summary>
/// <summary>
/// <see cref="dFlags" />
/// </summary>
public dFlags d_flags;
/// <summary>Drive-specific information</summary>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 5)] public uint[] d_drivedata;
@@ -394,61 +456,5 @@ namespace DiscImageChef.Partitions
/// <summary>Cylinder per group</summary>
public ushort p_cpg;
}
internal static string fsTypeToString(fsType typ)
{
switch(typ)
{
case fsType.Unused: return "Unused entry";
case fsType.Swap: return "Swap partition";
case fsType.V6: return "UNIX 6th Edition";
case fsType.V7: return "UNIX 7th Edition";
case fsType.SystemV: return "UNIX System V";
case fsType.V7_1K: return "UNIX 7th Edition with 1K blocks";
case fsType.V8: return "UNIX 8th Edition with 4K blocks";
case fsType.BSDFFS: return "4.2BSD Fast File System";
case fsType.BSDLFS: return "4.4LFS";
case fsType.HPFS: return "HPFS";
case fsType.ISO9660: return "ISO9660";
case fsType.Boot:
case fsType.SysVBoot: return "Boot";
case fsType.AFFS: return "Amiga FFS";
case fsType.HFS: return "Apple HFS";
case fsType.ADVfs: return "Digital Advanced File System";
case fsType.LSMpublic: return "Digital LSM Public Region";
case fsType.LSMprivate: return "Digital LSM Private Region";
case fsType.LSMsimple: return "Digital LSM Simple Disk";
case fsType.CCD: return "Concatenated disk";
case fsType.JFS2: return "IBM JFS2";
case fsType.HAMMER: return "Hammer";
case fsType.HAMMER2: return "Hammer2";
case fsType.UDF: return "UDF";
case fsType.EFS: return "EFS";
case fsType.ZFS: return "ZFS";
case fsType.NANDFS: return "FreeBSD nandfs";
case fsType.MSDOS: return "FAT";
case fsType.Other: return "Other or unknown";
default: return "Unknown";
}
}
static DiskLabel GetDiskLabel(byte[] disklabel)
{
GCHandle handle = GCHandle.Alloc(disklabel, GCHandleType.Pinned);
DiskLabel dl = (DiskLabel)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(DiskLabel));
handle.Free();
return dl;
}
static DiskLabel SwapDiskLabel(DiskLabel disklabel)
{
DiskLabel dl = BigEndianMarshal.SwapStructureMembersEndian(disklabel);
for(int i = 0; i < dl.d_drivedata.Length; i++) dl.d_drivedata[i] = Swapping.Swap(dl.d_drivedata[i]);
for(int i = 0; i < dl.d_spare.Length; i++) dl.d_spare[i] = Swapping.Swap(dl.d_spare[i]);
for(int i = 0; i < dl.d_partitions.Length; i++)
dl.d_partitions[i] = BigEndianMarshal.SwapStructureMembersEndian(dl.d_partitions[i]);
return dl;
}
}
}

View File

@@ -76,7 +76,8 @@ namespace DiscImageChef.Partitions
Length = (ulong)(entry.pi_nblocks * sector.Length),
Sequence = counter,
Scheme = Name
}).Where(part => part.Size > 0)) {
}).Where(part => part.Size > 0))
{
partitions.Add(part);
counter++;
}

View File

@@ -51,8 +51,7 @@ namespace DiscImageChef.Partitions
PluginUuid = new Guid("CBC9D281-C1D0-44E8-9038-4D66FD2678AB");
}
public override bool GetInformation(ImagePlugin imagePlugin,
out List<Partition> partitions, ulong sectorOffset)
public override bool GetInformation(ImagePlugin imagePlugin, out List<Partition> partitions, ulong sectorOffset)
{
partitions = new List<Partition>();
@@ -145,7 +144,9 @@ namespace DiscImageChef.Partitions
entries.Add(entry);
}
#pragma warning disable RECS0022 // A catch clause that catches System.Exception and has an empty body
catch { // ignored
catch
{
// ignored
}
#pragma warning restore RECS0022 // A catch clause that catches System.Exception and has an empty body
}
@@ -154,7 +155,9 @@ namespace DiscImageChef.Partitions
ulong pseq = 0;
foreach(GptEntry entry in entries.Where(entry => entry.partitionType != Guid.Empty && entry.partitionId != Guid.Empty)) {
foreach(GptEntry entry in
entries.Where(entry => entry.partitionType != Guid.Empty && entry.partitionId != Guid.Empty))
{
DicConsole.DebugWriteLine("GPT Plugin", "entry.partitionType = {0}", entry.partitionType);
DicConsole.DebugWriteLine("GPT Plugin", "entry.partitionId = {0}", entry.partitionId);
DicConsole.DebugWriteLine("GPT Plugin", "entry.startLBA = {0}", entry.startLBA);

View File

@@ -43,397 +43,13 @@ namespace DiscImageChef.Partitions
// TODO: Support AAP extensions
public class MBR : PartitionPlugin
{
const ulong GptMagic = 0x5452415020494645;
const ulong GPT_MAGIC = 0x5452415020494645;
public MBR()
{
Name = "Master Boot Record";
PluginUuid = new Guid("5E8A34E8-4F1A-59E6-4BF7-7EA647063A76");
}
const ushort MBR_MAGIC = 0xAA55;
const ushort NEC_MAGIC = 0xA55A;
const ushort DM_MAGIC = 0x55AA;
public override bool GetInformation(ImagePlugin imagePlugin,
out List<Partition> partitions, ulong sectorOffset)
{
ulong counter = 0;
partitions = new List<Partition>();
if(imagePlugin.GetSectorSize() < 512) return false;
uint sectorSize = imagePlugin.GetSectorSize();
// Divider of sector size in MBR between real sector size
ulong divider = 1;
if(imagePlugin.ImageInfo.XmlMediaType == XmlMediaType.OpticalDisc)
{
sectorSize = 512;
divider = 4;
}
byte[] sector = imagePlugin.ReadSector(sectorOffset);
GCHandle handle = GCHandle.Alloc(sector, GCHandleType.Pinned);
MasterBootRecord mbr =
(MasterBootRecord)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(MasterBootRecord));
TimedMasterBootRecord mbr_time =
(TimedMasterBootRecord)Marshal.PtrToStructure(handle.AddrOfPinnedObject(),
typeof(TimedMasterBootRecord));
SerializedMasterBootRecord mbr_serial =
(SerializedMasterBootRecord)Marshal.PtrToStructure(handle.AddrOfPinnedObject(),
typeof(SerializedMasterBootRecord));
ModernMasterBootRecord mbr_modern =
(ModernMasterBootRecord)Marshal.PtrToStructure(handle.AddrOfPinnedObject(),
typeof(ModernMasterBootRecord));
NecMasterBootRecord mbr_nec =
(NecMasterBootRecord)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(NecMasterBootRecord));
DiskManagerMasterBootRecord mbr_ontrack =
(DiskManagerMasterBootRecord)Marshal.PtrToStructure(handle.AddrOfPinnedObject(),
typeof(DiskManagerMasterBootRecord));
handle.Free();
DicConsole.DebugWriteLine("MBR plugin", "xmlmedia = {0}", imagePlugin.ImageInfo.XmlMediaType);
DicConsole.DebugWriteLine("MBR plugin", "mbr.magic = {0:X4}", mbr.magic);
if(mbr.magic != MBR_Magic) return false; // Not MBR
byte[] hdrBytes = imagePlugin.ReadSector(1 + sectorOffset);
ulong signature = BitConverter.ToUInt64(hdrBytes, 0);
DicConsole.DebugWriteLine("MBR Plugin", "gpt.signature = 0x{0:X16}", signature);
if(signature == GptMagic) return false;
if(signature != GptMagic && imagePlugin.ImageInfo.XmlMediaType == XmlMediaType.OpticalDisc)
{
hdrBytes = imagePlugin.ReadSector(sectorOffset);
signature = BitConverter.ToUInt64(hdrBytes, 512);
DicConsole.DebugWriteLine("MBR Plugin", "gpt.signature @ 0x200 = 0x{0:X16}", signature);
if(signature == GptMagic) return false;
}
MBRPartitionEntry[] entries;
if(mbr_ontrack.dm_magic == DM_Magic) entries = mbr_ontrack.entries;
else if(mbr_nec.nec_magic == NEC_Magic) entries = mbr_nec.entries;
else entries = mbr.entries;
foreach(MBRPartitionEntry entry in entries)
{
byte start_sector = (byte)(entry.start_sector & 0x3F);
ushort start_cylinder = (ushort)(((entry.start_sector & 0xC0) << 2) | entry.start_cylinder);
byte end_sector = (byte)(entry.end_sector & 0x3F);
ushort end_cylinder = (ushort)(((entry.end_sector & 0xC0) << 2) | entry.end_cylinder);
ulong lba_start = entry.lba_start;
ulong lba_sectors = entry.lba_sectors;
// Let's start the fun...
bool valid = true;
bool extended = false;
bool minix = false;
if(entry.status != 0x00 && entry.status != 0x80) return false; // Maybe a FAT filesystem
valid &= entry.type != 0x00;
if(entry.type == 0x05 || entry.type == 0x0F || entry.type == 0x15 || entry.type == 0x1F ||
entry.type == 0x85 || entry.type == 0x91 || entry.type == 0x9B || entry.type == 0xC5 ||
entry.type == 0xCF || entry.type == 0xD5)
{
valid = false;
extended = true; // Extended partition
}
minix |= entry.type == 0x81 || entry.type == 0x80; // MINIX partition
valid &= entry.lba_start != 0 || entry.lba_sectors != 0 || entry.start_cylinder != 0 ||
entry.start_head != 0 || entry.start_sector != 0 || entry.end_cylinder != 0 ||
entry.end_head != 0 || entry.end_sector != 0;
if(entry.lba_start == 0 && entry.lba_sectors == 0 && valid)
{
lba_start = CHS.ToLBA(start_cylinder, entry.start_head, start_sector,
imagePlugin.ImageInfo.Heads, imagePlugin.ImageInfo.SectorsPerTrack);
lba_sectors = CHS.ToLBA(end_cylinder, entry.end_head, entry.end_sector,
imagePlugin.ImageInfo.Heads,
imagePlugin.ImageInfo.SectorsPerTrack) - lba_start;
}
// For optical media
lba_start /= divider;
lba_sectors /= divider;
if(minix && lba_start == sectorOffset) minix = false;
if(lba_start > imagePlugin.GetSectors())
{
valid = false;
extended = false;
}
// Some buggy implementations do some rounding errors getting a few sectors beyond device size
if(lba_start + lba_sectors > imagePlugin.GetSectors())
lba_sectors = imagePlugin.GetSectors() - lba_start;
DicConsole.DebugWriteLine("MBR plugin", "entry.status {0}", entry.status);
DicConsole.DebugWriteLine("MBR plugin", "entry.type {0}", entry.type);
DicConsole.DebugWriteLine("MBR plugin", "entry.lba_start {0}", entry.lba_start);
DicConsole.DebugWriteLine("MBR plugin", "entry.lba_sectors {0}", entry.lba_sectors);
DicConsole.DebugWriteLine("MBR plugin", "entry.start_cylinder {0}", start_cylinder);
DicConsole.DebugWriteLine("MBR plugin", "entry.start_head {0}", entry.start_head);
DicConsole.DebugWriteLine("MBR plugin", "entry.start_sector {0}", start_sector);
DicConsole.DebugWriteLine("MBR plugin", "entry.end_cylinder {0}", end_cylinder);
DicConsole.DebugWriteLine("MBR plugin", "entry.end_head {0}", entry.end_head);
DicConsole.DebugWriteLine("MBR plugin", "entry.end_sector {0}", end_sector);
DicConsole.DebugWriteLine("MBR plugin", "entry.minix = {0}", minix);
DicConsole.DebugWriteLine("MBR plugin", "lba_start {0}", lba_start);
DicConsole.DebugWriteLine("MBR plugin", "lba_sectors {0}", lba_sectors);
if(valid && minix) // Let's mix the fun
if(GetMinix(imagePlugin, lba_start, divider, sectorOffset, sectorSize,
out List<Partition> mnx_parts)) partitions.AddRange(mnx_parts);
else minix = false;
if(valid && !minix)
{
Partition part = new Partition();
if((lba_start > 0 || imagePlugin.ImageInfo.XmlMediaType == XmlMediaType.OpticalDisc) &&
lba_sectors > 0)
{
part.Start = lba_start + sectorOffset;
part.Length = lba_sectors;
part.Offset = part.Start * sectorSize;
part.Size = part.Length * sectorSize;
}
else valid = false;
if(valid)
{
part.Type = $"0x{entry.type:X2}";
part.Name = DecodeMBRType(entry.type);
part.Sequence = counter;
part.Description = entry.status == 0x80 ? "Partition is bootable." : "";
part.Scheme = Name;
counter++;
partitions.Add(part);
}
}
DicConsole.DebugWriteLine("MBR plugin", "entry.extended = {0}", extended);
if(!extended) continue;
bool processing_extended = true;
ulong chain_start = lba_start;
while(processing_extended)
{
sector = imagePlugin.ReadSector(lba_start);
handle = GCHandle.Alloc(sector, GCHandleType.Pinned);
ExtendedBootRecord ebr =
(ExtendedBootRecord)Marshal.PtrToStructure(handle.AddrOfPinnedObject(),
typeof(ExtendedBootRecord));
handle.Free();
DicConsole.DebugWriteLine("MBR plugin", "ebr.magic == MBR_Magic = {0}", ebr.magic == MBR_Magic);
if(ebr.magic != MBR_Magic) break;
ulong next_start = 0;
foreach(MBRPartitionEntry ebr_entry in ebr.entries)
{
bool ext_valid = true;
start_sector = (byte)(ebr_entry.start_sector & 0x3F);
start_cylinder = (ushort)(((ebr_entry.start_sector & 0xC0) << 2) | ebr_entry.start_cylinder);
end_sector = (byte)(ebr_entry.end_sector & 0x3F);
end_cylinder = (ushort)(((ebr_entry.end_sector & 0xC0) << 2) | ebr_entry.end_cylinder);
ulong ext_start = ebr_entry.lba_start;
ulong ext_sectors = ebr_entry.lba_sectors;
bool ext_minix = false;
DicConsole.DebugWriteLine("MBR plugin", "ebr_entry.status {0}", ebr_entry.status);
DicConsole.DebugWriteLine("MBR plugin", "ebr_entry.type {0}", ebr_entry.type);
DicConsole.DebugWriteLine("MBR plugin", "ebr_entry.lba_start {0}", ebr_entry.lba_start);
DicConsole.DebugWriteLine("MBR plugin", "ebr_entry.lba_sectors {0}", ebr_entry.lba_sectors);
DicConsole.DebugWriteLine("MBR plugin", "ebr_entry.start_cylinder {0}", start_cylinder);
DicConsole.DebugWriteLine("MBR plugin", "ebr_entry.start_head {0}", ebr_entry.start_head);
DicConsole.DebugWriteLine("MBR plugin", "ebr_entry.start_sector {0}", start_sector);
DicConsole.DebugWriteLine("MBR plugin", "ebr_entry.end_cylinder {0}", end_cylinder);
DicConsole.DebugWriteLine("MBR plugin", "ebr_entry.end_head {0}", ebr_entry.end_head);
DicConsole.DebugWriteLine("MBR plugin", "ebr_entry.end_sector {0}", end_sector);
// Let's start the fun...
ext_valid &= ebr_entry.status == 0x00 || ebr_entry.status == 0x80;
ext_valid &= ebr_entry.type != 0x00;
ext_valid &= ebr_entry.lba_start != 0 || ebr_entry.lba_sectors != 0 ||
ebr_entry.start_cylinder != 0 || ebr_entry.start_head != 0 ||
ebr_entry.start_sector != 0 || ebr_entry.end_cylinder != 0 ||
ebr_entry.end_head != 0 || ebr_entry.end_sector != 0;
if(ebr_entry.lba_start == 0 && ebr_entry.lba_sectors == 0 && ext_valid)
{
ext_start = CHS.ToLBA(start_cylinder, ebr_entry.start_head, start_sector,
imagePlugin.ImageInfo.Heads,
imagePlugin.ImageInfo.SectorsPerTrack);
ext_sectors = CHS.ToLBA(end_cylinder, ebr_entry.end_head, ebr_entry.end_sector,
imagePlugin.ImageInfo.Heads,
imagePlugin.ImageInfo.SectorsPerTrack) - ext_start;
}
ext_minix |= ebr_entry.type == 0x81 || ebr_entry.type == 0x80;
// For optical media
ext_start /= divider;
ext_sectors /= divider;
DicConsole.DebugWriteLine("MBR plugin", "ext_start {0}", ext_start);
DicConsole.DebugWriteLine("MBR plugin", "ext_sectors {0}", ext_sectors);
if(ebr_entry.type == 0x05 || ebr_entry.type == 0x0F || ebr_entry.type == 0x15 ||
ebr_entry.type == 0x1F || ebr_entry.type == 0x85 || ebr_entry.type == 0x91 ||
ebr_entry.type == 0x9B || ebr_entry.type == 0xC5 || ebr_entry.type == 0xCF ||
ebr_entry.type == 0xD5)
{
ext_valid = false;
next_start = chain_start + ext_start;
}
ext_start += lba_start;
ext_valid &= ext_start <= imagePlugin.GetSectors();
// Some buggy implementations do some rounding errors getting a few sectors beyond device size
if(ext_start + ext_sectors > imagePlugin.GetSectors())
ext_sectors = imagePlugin.GetSectors() - ext_start;
if(ext_valid && ext_minix) // Let's mix the fun
if(GetMinix(imagePlugin, lba_start, divider, sectorOffset, sectorSize,
out List<Partition> mnx_parts)) partitions.AddRange(mnx_parts);
else ext_minix = false;
if(!ext_valid || ext_minix) continue;
Partition part = new Partition();
if(ext_start > 0 && ext_sectors > 0)
{
part.Start = ext_start + sectorOffset;
part.Length = ext_sectors;
part.Offset = part.Start * sectorSize;
part.Size = part.Length * sectorSize;
}
else ext_valid = false;
if(!ext_valid) continue;
part.Type = $"0x{ebr_entry.type:X2}";
part.Name = DecodeMBRType(ebr_entry.type);
part.Sequence = counter;
part.Description = ebr_entry.status == 0x80 ? "Partition is bootable." : "";
part.Scheme = Name;
counter++;
partitions.Add(part);
}
DicConsole.DebugWriteLine("MBR plugin", "next_start {0}", next_start);
processing_extended &= next_start != 0;
processing_extended &= next_start <= imagePlugin.GetSectors();
lba_start = next_start;
}
}
// An empty MBR may exist, NeXT creates one and then hardcodes its disklabel
return partitions.Count != 0;
}
static bool GetMinix(ImagePlugin imagePlugin, ulong start, ulong divider, ulong sectorOffset, uint sectorSize,
out List<Partition> partitions)
{
partitions = new List<Partition>();
byte[] sector = imagePlugin.ReadSector(start);
GCHandle handle = GCHandle.Alloc(sector, GCHandleType.Pinned);
ExtendedBootRecord mnx =
(ExtendedBootRecord)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(ExtendedBootRecord));
handle.Free();
DicConsole.DebugWriteLine("MBR plugin", "mnx.magic == MBR_Magic = {0}", mnx.magic == MBR_Magic);
if(mnx.magic != MBR_Magic) return false;
bool any_mnx = false;
foreach(MBRPartitionEntry mnx_entry in mnx.entries)
{
bool mnx_valid = true;
byte start_sector = (byte)(mnx_entry.start_sector & 0x3F);
ushort start_cylinder = (ushort)(((mnx_entry.start_sector & 0xC0) << 2) | mnx_entry.start_cylinder);
byte end_sector = (byte)(mnx_entry.end_sector & 0x3F);
ushort end_cylinder = (ushort)(((mnx_entry.end_sector & 0xC0) << 2) | mnx_entry.end_cylinder);
ulong mnx_start = mnx_entry.lba_start;
ulong mnx_sectors = mnx_entry.lba_sectors;
DicConsole.DebugWriteLine("MBR plugin", "mnx_entry.status {0}", mnx_entry.status);
DicConsole.DebugWriteLine("MBR plugin", "mnx_entry.type {0}", mnx_entry.type);
DicConsole.DebugWriteLine("MBR plugin", "mnx_entry.lba_start {0}", mnx_entry.lba_start);
DicConsole.DebugWriteLine("MBR plugin", "mnx_entry.lba_sectors {0}", mnx_entry.lba_sectors);
DicConsole.DebugWriteLine("MBR plugin", "mnx_entry.start_cylinder {0}", start_cylinder);
DicConsole.DebugWriteLine("MBR plugin", "mnx_entry.start_head {0}", mnx_entry.start_head);
DicConsole.DebugWriteLine("MBR plugin", "mnx_entry.start_sector {0}", start_sector);
DicConsole.DebugWriteLine("MBR plugin", "mnx_entry.end_cylinder {0}", end_cylinder);
DicConsole.DebugWriteLine("MBR plugin", "mnx_entry.end_head {0}", mnx_entry.end_head);
DicConsole.DebugWriteLine("MBR plugin", "mnx_entry.end_sector {0}", end_sector);
mnx_valid &= mnx_entry.status == 0x00 || mnx_entry.status == 0x80;
mnx_valid &= mnx_entry.type == 0x81 || mnx_entry.type == 0x80;
mnx_valid &= mnx_entry.lba_start != 0 || mnx_entry.lba_sectors != 0 || mnx_entry.start_cylinder != 0 ||
mnx_entry.start_head != 0 || mnx_entry.start_sector != 0 || mnx_entry.end_cylinder != 0 ||
mnx_entry.end_head != 0 || mnx_entry.end_sector != 0;
if(mnx_entry.lba_start == 0 && mnx_entry.lba_sectors == 0 && mnx_valid)
{
mnx_start = CHS.ToLBA(start_cylinder, mnx_entry.start_head, start_sector,
imagePlugin.ImageInfo.Heads, imagePlugin.ImageInfo.SectorsPerTrack);
mnx_sectors = CHS.ToLBA(end_cylinder, mnx_entry.end_head, mnx_entry.end_sector,
imagePlugin.ImageInfo.Heads,
imagePlugin.ImageInfo.SectorsPerTrack) - mnx_start;
}
// For optical media
mnx_start /= divider;
mnx_sectors /= divider;
DicConsole.DebugWriteLine("MBR plugin", "mnx_start {0}", mnx_start);
DicConsole.DebugWriteLine("MBR plugin", "mnx_sectors {0}", mnx_sectors);
if(!mnx_valid) continue;
Partition part = new Partition();
if(mnx_start > 0 && mnx_sectors > 0)
{
part.Start = mnx_start + sectorOffset;
part.Length = mnx_sectors;
part.Offset = part.Start * sectorSize;
part.Size = part.Length * sectorSize;
}
else mnx_valid = false;
if(!mnx_valid) continue;
any_mnx = true;
part.Type = "MINIX";
part.Name = "MINIX";
part.Description = mnx_entry.status == 0x80 ? "Partition is bootable." : "";
part.Scheme = "MINIX";
partitions.Add(part);
}
return any_mnx;
}
static readonly string[] MBRTypes =
static readonly string[] MbrTypes =
{
// 0x00
"Empty", "FAT12", "XENIX root", "XENIX /usr",
@@ -568,14 +184,394 @@ namespace DiscImageChef.Partitions
"VMWare VMKCORE", "Linux RAID, FreeDOS", "SpeedStor, LANStep, PS/2 IML", "Xenix bad block"
};
static string DecodeMBRType(byte type)
public MBR()
{
return MBRTypes[type];
Name = "Master Boot Record";
PluginUuid = new Guid("5E8A34E8-4F1A-59E6-4BF7-7EA647063A76");
}
const ushort MBR_Magic = 0xAA55;
const ushort NEC_Magic = 0xA55A;
const ushort DM_Magic = 0x55AA;
public override bool GetInformation(ImagePlugin imagePlugin, out List<Partition> partitions, ulong sectorOffset)
{
ulong counter = 0;
partitions = new List<Partition>();
if(imagePlugin.GetSectorSize() < 512) return false;
uint sectorSize = imagePlugin.GetSectorSize();
// Divider of sector size in MBR between real sector size
ulong divider = 1;
if(imagePlugin.ImageInfo.XmlMediaType == XmlMediaType.OpticalDisc)
{
sectorSize = 512;
divider = 4;
}
byte[] sector = imagePlugin.ReadSector(sectorOffset);
GCHandle handle = GCHandle.Alloc(sector, GCHandleType.Pinned);
MasterBootRecord mbr =
(MasterBootRecord)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(MasterBootRecord));
TimedMasterBootRecord mbrTime =
(TimedMasterBootRecord)Marshal.PtrToStructure(handle.AddrOfPinnedObject(),
typeof(TimedMasterBootRecord));
SerializedMasterBootRecord mbrSerial =
(SerializedMasterBootRecord)Marshal.PtrToStructure(handle.AddrOfPinnedObject(),
typeof(SerializedMasterBootRecord));
ModernMasterBootRecord mbrModern =
(ModernMasterBootRecord)Marshal.PtrToStructure(handle.AddrOfPinnedObject(),
typeof(ModernMasterBootRecord));
NecMasterBootRecord mbrNec =
(NecMasterBootRecord)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(NecMasterBootRecord));
DiskManagerMasterBootRecord mbrOntrack =
(DiskManagerMasterBootRecord)Marshal.PtrToStructure(handle.AddrOfPinnedObject(),
typeof(DiskManagerMasterBootRecord));
handle.Free();
DicConsole.DebugWriteLine("MBR plugin", "xmlmedia = {0}", imagePlugin.ImageInfo.XmlMediaType);
DicConsole.DebugWriteLine("MBR plugin", "mbr.magic = {0:X4}", mbr.magic);
if(mbr.magic != MBR_MAGIC) return false; // Not MBR
byte[] hdrBytes = imagePlugin.ReadSector(1 + sectorOffset);
ulong signature = BitConverter.ToUInt64(hdrBytes, 0);
DicConsole.DebugWriteLine("MBR Plugin", "gpt.signature = 0x{0:X16}", signature);
if(signature == GPT_MAGIC) return false;
if(signature != GPT_MAGIC && imagePlugin.ImageInfo.XmlMediaType == XmlMediaType.OpticalDisc)
{
hdrBytes = imagePlugin.ReadSector(sectorOffset);
signature = BitConverter.ToUInt64(hdrBytes, 512);
DicConsole.DebugWriteLine("MBR Plugin", "gpt.signature @ 0x200 = 0x{0:X16}", signature);
if(signature == GPT_MAGIC) return false;
}
MbrPartitionEntry[] entries;
if(mbrOntrack.dm_magic == DM_MAGIC) entries = mbrOntrack.entries;
else if(mbrNec.nec_magic == NEC_MAGIC) entries = mbrNec.entries;
else entries = mbr.entries;
foreach(MbrPartitionEntry entry in entries)
{
byte startSector = (byte)(entry.start_sector & 0x3F);
ushort startCylinder = (ushort)(((entry.start_sector & 0xC0) << 2) | entry.start_cylinder);
byte endSector = (byte)(entry.end_sector & 0x3F);
ushort endCylinder = (ushort)(((entry.end_sector & 0xC0) << 2) | entry.end_cylinder);
ulong lbaStart = entry.lba_start;
ulong lbaSectors = entry.lba_sectors;
// Let's start the fun...
bool valid = true;
bool extended = false;
bool minix = false;
if(entry.status != 0x00 && entry.status != 0x80) return false; // Maybe a FAT filesystem
valid &= entry.type != 0x00;
if(entry.type == 0x05 || entry.type == 0x0F || entry.type == 0x15 || entry.type == 0x1F ||
entry.type == 0x85 || entry.type == 0x91 || entry.type == 0x9B || entry.type == 0xC5 ||
entry.type == 0xCF || entry.type == 0xD5)
{
valid = false;
extended = true; // Extended partition
}
minix |= entry.type == 0x81 || entry.type == 0x80; // MINIX partition
valid &= entry.lba_start != 0 || entry.lba_sectors != 0 || entry.start_cylinder != 0 ||
entry.start_head != 0 || entry.start_sector != 0 || entry.end_cylinder != 0 ||
entry.end_head != 0 || entry.end_sector != 0;
if(entry.lba_start == 0 && entry.lba_sectors == 0 && valid)
{
lbaStart = CHS.ToLBA(startCylinder, entry.start_head, startSector, imagePlugin.ImageInfo.Heads,
imagePlugin.ImageInfo.SectorsPerTrack);
lbaSectors = CHS.ToLBA(endCylinder, entry.end_head, entry.end_sector, imagePlugin.ImageInfo.Heads,
imagePlugin.ImageInfo.SectorsPerTrack) - lbaStart;
}
// For optical media
lbaStart /= divider;
lbaSectors /= divider;
if(minix && lbaStart == sectorOffset) minix = false;
if(lbaStart > imagePlugin.GetSectors())
{
valid = false;
extended = false;
}
// Some buggy implementations do some rounding errors getting a few sectors beyond device size
if(lbaStart + lbaSectors > imagePlugin.GetSectors()) lbaSectors = imagePlugin.GetSectors() - lbaStart;
DicConsole.DebugWriteLine("MBR plugin", "entry.status {0}", entry.status);
DicConsole.DebugWriteLine("MBR plugin", "entry.type {0}", entry.type);
DicConsole.DebugWriteLine("MBR plugin", "entry.lba_start {0}", entry.lba_start);
DicConsole.DebugWriteLine("MBR plugin", "entry.lba_sectors {0}", entry.lba_sectors);
DicConsole.DebugWriteLine("MBR plugin", "entry.start_cylinder {0}", startCylinder);
DicConsole.DebugWriteLine("MBR plugin", "entry.start_head {0}", entry.start_head);
DicConsole.DebugWriteLine("MBR plugin", "entry.start_sector {0}", startSector);
DicConsole.DebugWriteLine("MBR plugin", "entry.end_cylinder {0}", endCylinder);
DicConsole.DebugWriteLine("MBR plugin", "entry.end_head {0}", entry.end_head);
DicConsole.DebugWriteLine("MBR plugin", "entry.end_sector {0}", endSector);
DicConsole.DebugWriteLine("MBR plugin", "entry.minix = {0}", minix);
DicConsole.DebugWriteLine("MBR plugin", "lba_start {0}", lbaStart);
DicConsole.DebugWriteLine("MBR plugin", "lba_sectors {0}", lbaSectors);
if(valid && minix) // Let's mix the fun
if(GetMinix(imagePlugin, lbaStart, divider, sectorOffset, sectorSize, out List<Partition> mnxParts))
partitions.AddRange(mnxParts);
else minix = false;
if(valid && !minix)
{
Partition part = new Partition();
if((lbaStart > 0 || imagePlugin.ImageInfo.XmlMediaType == XmlMediaType.OpticalDisc) &&
lbaSectors > 0)
{
part.Start = lbaStart + sectorOffset;
part.Length = lbaSectors;
part.Offset = part.Start * sectorSize;
part.Size = part.Length * sectorSize;
}
else valid = false;
if(valid)
{
part.Type = $"0x{entry.type:X2}";
part.Name = DecodeMbrType(entry.type);
part.Sequence = counter;
part.Description = entry.status == 0x80 ? "Partition is bootable." : "";
part.Scheme = Name;
counter++;
partitions.Add(part);
}
}
DicConsole.DebugWriteLine("MBR plugin", "entry.extended = {0}", extended);
if(!extended) continue;
bool processingExtended = true;
ulong chainStart = lbaStart;
while(processingExtended)
{
sector = imagePlugin.ReadSector(lbaStart);
handle = GCHandle.Alloc(sector, GCHandleType.Pinned);
ExtendedBootRecord ebr =
(ExtendedBootRecord)Marshal.PtrToStructure(handle.AddrOfPinnedObject(),
typeof(ExtendedBootRecord));
handle.Free();
DicConsole.DebugWriteLine("MBR plugin", "ebr.magic == MBR_Magic = {0}", ebr.magic == MBR_MAGIC);
if(ebr.magic != MBR_MAGIC) break;
ulong nextStart = 0;
foreach(MbrPartitionEntry ebrEntry in ebr.entries)
{
bool extValid = true;
startSector = (byte)(ebrEntry.start_sector & 0x3F);
startCylinder = (ushort)(((ebrEntry.start_sector & 0xC0) << 2) | ebrEntry.start_cylinder);
endSector = (byte)(ebrEntry.end_sector & 0x3F);
endCylinder = (ushort)(((ebrEntry.end_sector & 0xC0) << 2) | ebrEntry.end_cylinder);
ulong extStart = ebrEntry.lba_start;
ulong extSectors = ebrEntry.lba_sectors;
bool extMinix = false;
DicConsole.DebugWriteLine("MBR plugin", "ebr_entry.status {0}", ebrEntry.status);
DicConsole.DebugWriteLine("MBR plugin", "ebr_entry.type {0}", ebrEntry.type);
DicConsole.DebugWriteLine("MBR plugin", "ebr_entry.lba_start {0}", ebrEntry.lba_start);
DicConsole.DebugWriteLine("MBR plugin", "ebr_entry.lba_sectors {0}", ebrEntry.lba_sectors);
DicConsole.DebugWriteLine("MBR plugin", "ebr_entry.start_cylinder {0}", startCylinder);
DicConsole.DebugWriteLine("MBR plugin", "ebr_entry.start_head {0}", ebrEntry.start_head);
DicConsole.DebugWriteLine("MBR plugin", "ebr_entry.start_sector {0}", startSector);
DicConsole.DebugWriteLine("MBR plugin", "ebr_entry.end_cylinder {0}", endCylinder);
DicConsole.DebugWriteLine("MBR plugin", "ebr_entry.end_head {0}", ebrEntry.end_head);
DicConsole.DebugWriteLine("MBR plugin", "ebr_entry.end_sector {0}", endSector);
// Let's start the fun...
extValid &= ebrEntry.status == 0x00 || ebrEntry.status == 0x80;
extValid &= ebrEntry.type != 0x00;
extValid &= ebrEntry.lba_start != 0 || ebrEntry.lba_sectors != 0 ||
ebrEntry.start_cylinder != 0 || ebrEntry.start_head != 0 ||
ebrEntry.start_sector != 0 || ebrEntry.end_cylinder != 0 ||
ebrEntry.end_head != 0 || ebrEntry.end_sector != 0;
if(ebrEntry.lba_start == 0 && ebrEntry.lba_sectors == 0 && extValid)
{
extStart = CHS.ToLBA(startCylinder, ebrEntry.start_head, startSector,
imagePlugin.ImageInfo.Heads, imagePlugin.ImageInfo.SectorsPerTrack);
extSectors = CHS.ToLBA(endCylinder, ebrEntry.end_head, ebrEntry.end_sector,
imagePlugin.ImageInfo.Heads, imagePlugin.ImageInfo.SectorsPerTrack) -
extStart;
}
extMinix |= ebrEntry.type == 0x81 || ebrEntry.type == 0x80;
// For optical media
extStart /= divider;
extSectors /= divider;
DicConsole.DebugWriteLine("MBR plugin", "ext_start {0}", extStart);
DicConsole.DebugWriteLine("MBR plugin", "ext_sectors {0}", extSectors);
if(ebrEntry.type == 0x05 || ebrEntry.type == 0x0F || ebrEntry.type == 0x15 ||
ebrEntry.type == 0x1F || ebrEntry.type == 0x85 || ebrEntry.type == 0x91 ||
ebrEntry.type == 0x9B || ebrEntry.type == 0xC5 || ebrEntry.type == 0xCF ||
ebrEntry.type == 0xD5)
{
extValid = false;
nextStart = chainStart + extStart;
}
extStart += lbaStart;
extValid &= extStart <= imagePlugin.GetSectors();
// Some buggy implementations do some rounding errors getting a few sectors beyond device size
if(extStart + extSectors > imagePlugin.GetSectors())
extSectors = imagePlugin.GetSectors() - extStart;
if(extValid && extMinix) // Let's mix the fun
if(GetMinix(imagePlugin, lbaStart, divider, sectorOffset, sectorSize,
out List<Partition> mnxParts)) partitions.AddRange(mnxParts);
else extMinix = false;
if(!extValid || extMinix) continue;
Partition part = new Partition();
if(extStart > 0 && extSectors > 0)
{
part.Start = extStart + sectorOffset;
part.Length = extSectors;
part.Offset = part.Start * sectorSize;
part.Size = part.Length * sectorSize;
}
else extValid = false;
if(!extValid) continue;
part.Type = $"0x{ebrEntry.type:X2}";
part.Name = DecodeMbrType(ebrEntry.type);
part.Sequence = counter;
part.Description = ebrEntry.status == 0x80 ? "Partition is bootable." : "";
part.Scheme = Name;
counter++;
partitions.Add(part);
}
DicConsole.DebugWriteLine("MBR plugin", "next_start {0}", nextStart);
processingExtended &= nextStart != 0;
processingExtended &= nextStart <= imagePlugin.GetSectors();
lbaStart = nextStart;
}
}
// An empty MBR may exist, NeXT creates one and then hardcodes its disklabel
return partitions.Count != 0;
}
static bool GetMinix(ImagePlugin imagePlugin, ulong start, ulong divider, ulong sectorOffset, uint sectorSize,
out List<Partition> partitions)
{
partitions = new List<Partition>();
byte[] sector = imagePlugin.ReadSector(start);
GCHandle handle = GCHandle.Alloc(sector, GCHandleType.Pinned);
ExtendedBootRecord mnx =
(ExtendedBootRecord)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(ExtendedBootRecord));
handle.Free();
DicConsole.DebugWriteLine("MBR plugin", "mnx.magic == MBR_Magic = {0}", mnx.magic == MBR_MAGIC);
if(mnx.magic != MBR_MAGIC) return false;
bool anyMnx = false;
foreach(MbrPartitionEntry mnxEntry in mnx.entries)
{
bool mnxValid = true;
byte startSector = (byte)(mnxEntry.start_sector & 0x3F);
ushort startCylinder = (ushort)(((mnxEntry.start_sector & 0xC0) << 2) | mnxEntry.start_cylinder);
byte endSector = (byte)(mnxEntry.end_sector & 0x3F);
ushort endCylinder = (ushort)(((mnxEntry.end_sector & 0xC0) << 2) | mnxEntry.end_cylinder);
ulong mnxStart = mnxEntry.lba_start;
ulong mnxSectors = mnxEntry.lba_sectors;
DicConsole.DebugWriteLine("MBR plugin", "mnx_entry.status {0}", mnxEntry.status);
DicConsole.DebugWriteLine("MBR plugin", "mnx_entry.type {0}", mnxEntry.type);
DicConsole.DebugWriteLine("MBR plugin", "mnx_entry.lba_start {0}", mnxEntry.lba_start);
DicConsole.DebugWriteLine("MBR plugin", "mnx_entry.lba_sectors {0}", mnxEntry.lba_sectors);
DicConsole.DebugWriteLine("MBR plugin", "mnx_entry.start_cylinder {0}", startCylinder);
DicConsole.DebugWriteLine("MBR plugin", "mnx_entry.start_head {0}", mnxEntry.start_head);
DicConsole.DebugWriteLine("MBR plugin", "mnx_entry.start_sector {0}", startSector);
DicConsole.DebugWriteLine("MBR plugin", "mnx_entry.end_cylinder {0}", endCylinder);
DicConsole.DebugWriteLine("MBR plugin", "mnx_entry.end_head {0}", mnxEntry.end_head);
DicConsole.DebugWriteLine("MBR plugin", "mnx_entry.end_sector {0}", endSector);
mnxValid &= mnxEntry.status == 0x00 || mnxEntry.status == 0x80;
mnxValid &= mnxEntry.type == 0x81 || mnxEntry.type == 0x80;
mnxValid &= mnxEntry.lba_start != 0 || mnxEntry.lba_sectors != 0 || mnxEntry.start_cylinder != 0 ||
mnxEntry.start_head != 0 || mnxEntry.start_sector != 0 || mnxEntry.end_cylinder != 0 ||
mnxEntry.end_head != 0 || mnxEntry.end_sector != 0;
if(mnxEntry.lba_start == 0 && mnxEntry.lba_sectors == 0 && mnxValid)
{
mnxStart = CHS.ToLBA(startCylinder, mnxEntry.start_head, startSector, imagePlugin.ImageInfo.Heads,
imagePlugin.ImageInfo.SectorsPerTrack);
mnxSectors = CHS.ToLBA(endCylinder, mnxEntry.end_head, mnxEntry.end_sector,
imagePlugin.ImageInfo.Heads, imagePlugin.ImageInfo.SectorsPerTrack) -
mnxStart;
}
// For optical media
mnxStart /= divider;
mnxSectors /= divider;
DicConsole.DebugWriteLine("MBR plugin", "mnx_start {0}", mnxStart);
DicConsole.DebugWriteLine("MBR plugin", "mnx_sectors {0}", mnxSectors);
if(!mnxValid) continue;
Partition part = new Partition();
if(mnxStart > 0 && mnxSectors > 0)
{
part.Start = mnxStart + sectorOffset;
part.Length = mnxSectors;
part.Offset = part.Start * sectorSize;
part.Size = part.Length * sectorSize;
}
else mnxValid = false;
if(!mnxValid) continue;
anyMnx = true;
part.Type = "MINIX";
part.Name = "MINIX";
part.Description = mnxEntry.status == 0x80 ? "Partition is bootable." : "";
part.Scheme = "MINIX";
partitions.Add(part);
}
return anyMnx;
}
static string DecodeMbrType(byte type)
{
return MbrTypes[type];
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
struct MasterBootRecord
@@ -583,8 +579,10 @@ namespace DiscImageChef.Partitions
/// <summary>Boot code</summary>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 446)] public byte[] boot_code;
/// <summary>Partitions</summary>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)] public MBRPartitionEntry[] entries;
/// <summary><see cref="MBR_Magic"/></summary>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)] public MbrPartitionEntry[] entries;
/// <summary>
/// <see cref="MBR.MBR_MAGIC" />
/// </summary>
public ushort magic;
}
@@ -595,8 +593,10 @@ namespace DiscImageChef.Partitions
/// <summary>Boot code, almost always unused</summary>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 446)] public byte[] boot_code;
/// <summary>Partitions or pointers</summary>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)] public MBRPartitionEntry[] entries;
/// <summary><see cref="MBR_Magic"/></summary>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)] public MbrPartitionEntry[] entries;
/// <summary>
/// <see cref="MBR.MBR_MAGIC" />
/// </summary>
public ushort magic;
}
@@ -618,8 +618,10 @@ namespace DiscImageChef.Partitions
/// <summary>Boot code, continuation</summary>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 222)] public byte[] boot_code2;
/// <summary>Partitions</summary>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)] public MBRPartitionEntry[] entries;
/// <summary><see cref="MBR_Magic"/></summary>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)] public MbrPartitionEntry[] entries;
/// <summary>
/// <see cref="MBR.MBR_MAGIC" />
/// </summary>
public ushort magic;
}
@@ -633,8 +635,10 @@ namespace DiscImageChef.Partitions
/// <summary>Set to 0</summary>
public ushort zero;
/// <summary>Partitions</summary>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)] public MBRPartitionEntry[] entries;
/// <summary><see cref="MBR_Magic"/></summary>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)] public MbrPartitionEntry[] entries;
/// <summary>
/// <see cref="MBR.MBR_MAGIC" />
/// </summary>
public ushort magic;
}
@@ -660,8 +664,10 @@ namespace DiscImageChef.Partitions
/// <summary>Set to 0</summary>
public ushort zero2;
/// <summary>Partitions</summary>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)] public MBRPartitionEntry[] entries;
/// <summary><see cref="MBR_Magic"/></summary>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)] public MbrPartitionEntry[] entries;
/// <summary>
/// <see cref="MBR.MBR_MAGIC" />
/// </summary>
public ushort magic;
}
@@ -670,11 +676,15 @@ namespace DiscImageChef.Partitions
{
/// <summary>Boot code</summary>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 380)] public byte[] boot_code;
/// <summary><see cref="NEC_Magic"/></summary>
/// <summary>
/// <see cref="MBR.NEC_MAGIC" />
/// </summary>
public ushort nec_magic;
/// <summary>Partitions</summary>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)] public MBRPartitionEntry[] entries;
/// <summary><see cref="MBR_Magic"/></summary>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)] public MbrPartitionEntry[] entries;
/// <summary>
/// <see cref="MBR.MBR_MAGIC" />
/// </summary>
public ushort magic;
}
@@ -683,16 +693,20 @@ namespace DiscImageChef.Partitions
{
/// <summary>Boot code</summary>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 252)] public byte[] boot_code;
/// <summary><see cref="DM_Magic"/></summary>
/// <summary>
/// <see cref="MBR.DM_MAGIC" />
/// </summary>
public ushort dm_magic;
/// <summary>Partitions</summary>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)] public MBRPartitionEntry[] entries;
/// <summary><see cref="MBR_Magic"/></summary>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)] public MbrPartitionEntry[] entries;
/// <summary>
/// <see cref="MBR.MBR_MAGIC" />
/// </summary>
public ushort magic;
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
struct MBRPartitionEntry
struct MbrPartitionEntry
{
/// <summary>Partition status, 0x80 or 0x00, else invalid</summary>
public byte status;

View File

@@ -92,8 +92,9 @@ namespace DiscImageChef.Partitions
Partition part = new Partition
{
Start = CHS.ToLBA(entry.dp_scyl, entry.dp_shd, (uint)(entry.dp_ssect + 1),
imagePlugin.ImageInfo.Heads, imagePlugin.ImageInfo.SectorsPerTrack),
Start =
CHS.ToLBA(entry.dp_scyl, entry.dp_shd, (uint)(entry.dp_ssect + 1), imagePlugin.ImageInfo.Heads,
imagePlugin.ImageInfo.SectorsPerTrack),
Type = DecodePC98Sid(entry.dp_sid),
Name = StringHandlers.CToString(entry.dp_name, Encoding.GetEncoding(932)).Trim(),
Sequence = counter,
@@ -101,8 +102,8 @@ namespace DiscImageChef.Partitions
};
part.Offset = part.Start * imagePlugin.GetSectorSize();
part.Length = CHS.ToLBA(entry.dp_ecyl, entry.dp_ehd, (uint)(entry.dp_esect + 1),
imagePlugin.ImageInfo.Heads,
imagePlugin.ImageInfo.SectorsPerTrack) - part.Start;
imagePlugin.ImageInfo.Heads, imagePlugin.ImageInfo.SectorsPerTrack) -
part.Start;
part.Size = part.Length * imagePlugin.GetSectorSize();
DicConsole.DebugWriteLine("PC98 plugin", "part.Start = {0}", part.Start);
@@ -113,9 +114,8 @@ namespace DiscImageChef.Partitions
DicConsole.DebugWriteLine("PC98 plugin", "part.Length = {0}", part.Length);
DicConsole.DebugWriteLine("PC98 plugin", "part.Size = {0}", part.Size);
if(((entry.dp_mid & 0x20) != 0x20 && (entry.dp_mid & 0x44) != 0x44) ||
part.Start >= imagePlugin.ImageInfo.Sectors ||
part.End > imagePlugin.ImageInfo.Sectors) continue;
if((entry.dp_mid & 0x20) != 0x20 && (entry.dp_mid & 0x44) != 0x44 ||
part.Start >= imagePlugin.ImageInfo.Sectors || part.End > imagePlugin.ImageInfo.Sectors) continue;
partitions.Add(part);
counter++;

View File

@@ -55,7 +55,7 @@ namespace DiscImageChef.Partitions
/// <param name="imagePlugin">Disk image.</param>
/// <param name="partitions">Returns list of partitions.</param>
/// <param name="sectorOffset">At which sector to start searching for the partition scheme.</param>
public abstract bool GetInformation(ImagePlugin imagePlugin,
out List<Partition> partitions, ulong sectorOffset);
public abstract bool GetInformation(ImagePlugin imagePlugin, out List<Partition> partitions,
ulong sectorOffset);
}
}

View File

@@ -51,8 +51,7 @@ namespace DiscImageChef.Partitions
PluginUuid = new Guid("F0BF4FFC-056E-4E7C-8B65-4EAEE250ADD9");
}
public override bool GetInformation(ImagePlugin imagePlugin, out List<Partition> partitions,
ulong sectorOffset)
public override bool GetInformation(ImagePlugin imagePlugin, out List<Partition> partitions, ulong sectorOffset)
{
partitions = new List<Partition>();
@@ -62,7 +61,9 @@ namespace DiscImageChef.Partitions
// While all of Plan9 is supposedly UTF-8, it uses ASCII strcmp for reading its partition table
string[] really = StringHandlers.CToString(sector).Split('\n');
foreach(string[] tokens in really.TakeWhile(part => part.Length >= 5 && part.Substring(0, 5) == "part ").Select(part => part.Split(' ')).TakeWhile(tokens => tokens.Length == 4)) {
foreach(string[] tokens in really.TakeWhile(part => part.Length >= 5 && part.Substring(0, 5) == "part ")
.Select(part => part.Split(' ')).TakeWhile(tokens => tokens.Length == 4))
{
if(!ulong.TryParse(tokens[2], out ulong start) || !ulong.TryParse(tokens[3], out ulong end)) break;
Partition part = new Partition

File diff suppressed because it is too large Load Diff

View File

@@ -66,7 +66,8 @@ namespace DiscImageChef.Partitions
ulong counter = 0;
foreach(Partition part in from entry in table.entries let part = new Partition
foreach(Partition part in from entry in table.entries
let part = new Partition
{
Start = entry.offset,
Offset = (ulong)(entry.offset * sector.Length),
@@ -75,7 +76,10 @@ namespace DiscImageChef.Partitions
Type = "Rio Karma",
Sequence = counter,
Scheme = Name
} where entry.type == ENTRY_MAGIC select part) {
}
where entry.type == ENTRY_MAGIC
select part)
{
partitions.Add(part);
counter++;
}

View File

@@ -37,6 +37,7 @@ using System.Runtime.InteropServices;
using DiscImageChef.CommonTypes;
using DiscImageChef.Console;
using DiscImageChef.DiscImages;
#pragma warning disable 169
#pragma warning disable 649
@@ -120,11 +121,9 @@ namespace DiscImageChef.Partitions
Partition part = new Partition
{
Start =
dvh.partitions[i].first_block * dvh.device_params.dp_secbytes / imagePlugin.GetSectorSize(),
Start = dvh.partitions[i].first_block * dvh.device_params.dp_secbytes / imagePlugin.GetSectorSize(),
Offset = dvh.partitions[i].first_block * dvh.device_params.dp_secbytes,
Length =
dvh.partitions[i].num_blocks * dvh.device_params.dp_secbytes / imagePlugin.GetSectorSize(),
Length = dvh.partitions[i].num_blocks * dvh.device_params.dp_secbytes / imagePlugin.GetSectorSize(),
Size = dvh.partitions[i].num_blocks * dvh.device_params.dp_secbytes,
Type = TypeToString(dvh.partitions[i].type),
Sequence = counter,
@@ -140,6 +139,31 @@ namespace DiscImageChef.Partitions
return true;
}
static string TypeToString(SGIType typ)
{
switch(typ)
{
case SGIType.Header: return "Volume header";
case SGIType.TrkRepl: return "Track replacements";
case SGIType.SecRepl: return "Sector replacements";
case SGIType.Swap: return "Raw data (swap)";
case SGIType.Bsd: return "4.2BSD Fast File System";
case SGIType.SystemV: return "UNIX System V";
case SGIType.Volume: return "Whole device";
case SGIType.EFS: return "EFS";
case SGIType.Lvol: return "Logical volume";
case SGIType.Rlvol: return "Raw logical volume";
case SGIType.XFS: return "XFS";
case SGIType.Xlvol: return "XFS log device";
case SGIType.Rxlvol: return "XLV volume";
case SGIType.Xvm: return "SGI XVM";
case SGIType.LinuxSwap: return "Linux swap";
case SGIType.Linux: return "Linux";
case SGIType.LinuxRAID: return "Linux RAID";
default: return "Unknown";
}
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
struct SGILabel
{
@@ -195,31 +219,6 @@ namespace DiscImageChef.Partitions
LinuxRAID = 0xFD
}
static string TypeToString(SGIType typ)
{
switch(typ)
{
case SGIType.Header: return "Volume header";
case SGIType.TrkRepl: return "Track replacements";
case SGIType.SecRepl: return "Sector replacements";
case SGIType.Swap: return "Raw data (swap)";
case SGIType.Bsd: return "4.2BSD Fast File System";
case SGIType.SystemV: return "UNIX System V";
case SGIType.Volume: return "Whole device";
case SGIType.EFS: return "EFS";
case SGIType.Lvol: return "Logical volume";
case SGIType.Rlvol: return "Raw logical volume";
case SGIType.XFS: return "XFS";
case SGIType.Xlvol: return "XFS log device";
case SGIType.Rxlvol: return "XLV volume";
case SGIType.Xvm: return "SGI XVM";
case SGIType.LinuxSwap: return "Linux swap";
case SGIType.Linux: return "Linux";
case SGIType.LinuxRAID: return "Linux RAID";
default: return "Unknown";
}
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
struct SGIPartition
{

View File

@@ -70,49 +70,13 @@ namespace DiscImageChef.Partitions
const int LEN_DKL_PAD16 = DK_LABEL_SIZE - (456 + // sizeof(dk_vtoc16)
4 * 4 + 12 * 2 + 2 * 2);
enum SunTag : ushort
{
SunEmpty = 0x0000,
SunBoot = 0x0001,
SunRoot = 0x0002,
SunSwap = 0x0003,
SunUsr = 0x0004,
SunWholeDisk = 0x0005,
SunStand = 0x0006,
SunVar = 0x0007,
SunHome = 0x0008,
SunAlt = 0x0009,
SunCache = 0x000A,
SunReserved = 0x000B,
VxVmPublic = 0x000E,
VxVmPrivate = 0x000F,
LinuxSwap = 0x0082,
Linux = 0x0083,
LVM = 0x008E,
LinuxRaid = 0x00FD,
NetBSD = 0x00FF,
FreeBSD_Swap = 0x0901,
FreeBSD_UFS = 0x0902,
FreeBSD_Vinum = 0x0903,
FreeBSD_ZFS = 0x0904,
FreeBSD_NANDFS = 0x0905
}
[Flags]
enum SunFlags : ushort
{
NoMount = 0x0001,
ReadOnly = 0x0010
}
public SunDisklabel()
{
Name = "Sun Disklabel";
PluginUuid = new Guid("50F35CC4-8375-4445-8DCB-1BA550C931A3");
}
public override bool GetInformation(ImagePlugin imagePlugin,
out List<Partition> partitions, ulong sectorOffset)
public override bool GetInformation(ImagePlugin imagePlugin, out List<Partition> partitions, ulong sectorOffset)
{
partitions = new List<Partition>();
@@ -267,8 +231,7 @@ namespace DiscImageChef.Partitions
Sequence = (ulong)i,
Offset =
((ulong)dkl8.dkl_map[i].dkl_cylno * sectorsPerCylinder + sectorOffset) * DK_LABEL_SIZE,
Start =
((ulong)dkl8.dkl_map[i].dkl_cylno * sectorsPerCylinder + sectorOffset) *
Start = ((ulong)dkl8.dkl_map[i].dkl_cylno * sectorsPerCylinder + sectorOffset) *
DK_LABEL_SIZE / imagePlugin.GetSectorSize(),
Type = SunIdToString(dkl8.dkl_vtoc.v_part[i].p_tag),
Scheme = Name
@@ -336,9 +299,8 @@ namespace DiscImageChef.Partitions
Sequence = (ulong)i,
Offset =
((ulong)dkl16.dkl_vtoc.v_part[i].p_start + sectorOffset) * dkl16.dkl_vtoc.v_sectorsz,
Start =
((ulong)dkl16.dkl_vtoc.v_part[i].p_start + sectorOffset) * dkl16.dkl_vtoc.v_sectorsz /
imagePlugin.GetSectorSize(),
Start = ((ulong)dkl16.dkl_vtoc.v_part[i].p_start + sectorOffset) *
dkl16.dkl_vtoc.v_sectorsz / imagePlugin.GetSectorSize(),
Type = SunIdToString(dkl16.dkl_vtoc.v_part[i].p_tag),
Scheme = Name
};
@@ -447,6 +409,41 @@ namespace DiscImageChef.Partitions
}
}
enum SunTag : ushort
{
SunEmpty = 0x0000,
SunBoot = 0x0001,
SunRoot = 0x0002,
SunSwap = 0x0003,
SunUsr = 0x0004,
SunWholeDisk = 0x0005,
SunStand = 0x0006,
SunVar = 0x0007,
SunHome = 0x0008,
SunAlt = 0x0009,
SunCache = 0x000A,
SunReserved = 0x000B,
VxVmPublic = 0x000E,
VxVmPrivate = 0x000F,
LinuxSwap = 0x0082,
Linux = 0x0083,
LVM = 0x008E,
LinuxRaid = 0x00FD,
NetBSD = 0x00FF,
FreeBSD_Swap = 0x0901,
FreeBSD_UFS = 0x0902,
FreeBSD_Vinum = 0x0903,
FreeBSD_ZFS = 0x0904,
FreeBSD_NANDFS = 0x0905
}
[Flags]
enum SunFlags : ushort
{
NoMount = 0x0001,
ReadOnly = 0x0010
}
/// <summary>SunOS logical partitions</summary>
[StructLayout(LayoutKind.Sequential, Pack = 1)]
struct dk_map

View File

@@ -43,87 +43,6 @@ namespace DiscImageChef.Partitions
// Currently only DEC devices used in Ultrix are added, probably it's missing a lot of entries.
public class UNIX : PartitionPlugin
{
public UNIX()
{
Name = "UNIX hardwired";
PluginUuid = new Guid("9ED7E30B-53BF-4619-87A0-5D2002155617");
}
public override bool GetInformation(ImagePlugin imagePlugin, out List<Partition> partitions, ulong sectorOffset)
{
partitions = new List<Partition>();
Partition[] parts;
if(sectorOffset != 0) return false;
switch(imagePlugin.ImageInfo.MediaType)
{
case MediaType.RA60:
parts = RA60;
break;
case MediaType.RA80:
parts = RA80;
break;
case MediaType.RA81:
parts = RA81;
break;
case MediaType.RC25:
parts = RC25;
break;
case MediaType.RD31:
parts = RD31;
break;
case MediaType.RD32:
parts = RD32;
break;
case MediaType.RD51:
parts = RD51;
break;
case MediaType.RD52:
parts = RD52;
break;
case MediaType.RD53:
parts = RD53;
break;
case MediaType.RD54:
parts = RD54;
break;
case MediaType.RK06:
parts = RK06;
break;
case MediaType.RK07:
parts = RK07;
break;
case MediaType.RM02:
case MediaType.RM03:
parts = RM02;
break;
case MediaType.RM05:
parts = RM05;
break;
case MediaType.RP02:
parts = RP02;
break;
case MediaType.RP03:
parts = RP03;
break;
case MediaType.RP04:
case MediaType.RP05:
parts = RP04;
break;
case MediaType.RP06:
parts = RP06;
break;
default: return false;
}
for(int i = 0; i < parts.Length; i++) parts[i].Scheme = "";
partitions = parts.ToList();
return partitions.Count > 0;
}
readonly Partition[] RA60 =
{
new Partition
@@ -986,6 +905,212 @@ namespace DiscImageChef.Partitions
}
};
readonly Partition[] RM02 =
{
new Partition
{
Description = null,
Name = "/",
Type = "data",
Length = 9120,
Start = 0,
Size = 4669440,
Offset = 0,
Sequence = 0
},
new Partition
{
Description = null,
Name = "error log",
Type = "errorlog",
Length = 200,
Start = 9120,
Size = 102400,
Offset = 4669440,
Sequence = 1
},
new Partition
{
Description = null,
Name = "swap",
Type = "swap",
Length = 5400,
Start = 9320,
Size = 2764800,
Offset = 2764800,
Sequence = 1
},
new Partition
{
Description = null,
Name = "/usr",
Type = "data",
Length = 5600,
Start = 29120,
Size = 2867200,
Offset = 14909440,
Sequence = 2
},
new Partition
{
Description = null,
Name = "user",
Type = "data",
Length = 96896,
Start = 34720,
Size = 49610752,
Offset = 17776640,
Sequence = 3
},
new Partition
{
Description = null,
Name = "user",
Type = "data",
Length = 32160,
Start = 34720,
Size = 16465920,
Offset = 17776640,
Sequence = 4
},
new Partition
{
Description = null,
Name = "user",
Type = "data",
Length = 32160,
Start = 66880,
Size = 16465920,
Offset = 34242560,
Sequence = 5
},
new Partition
{
Description = null,
Name = "user",
Type = "data",
Length = 32576,
Start = 99040,
Size = 16678912,
Offset = 50708480,
Sequence = 6
},
new Partition
{
Description = null,
Name = "bad sector file",
Type = "bad",
Length = 64,
Start = 131616,
Size = 32768,
Offset = 67387392,
Sequence = 8
}
};
readonly Partition[] RM05 =
{
new Partition
{
Description = null,
Name = "/",
Type = "data",
Length = 10336,
Start = 0,
Size = 5292032,
Offset = 0,
Sequence = 0
},
new Partition
{
Description = null,
Name = "/usr",
Type = "data",
Length = 21280,
Start = 10336,
Size = 10895360,
Offset = 5292032,
Sequence = 1
},
new Partition
{
Description = null,
Name = "error log",
Type = "errorlog",
Length = 200,
Start = 31616,
Size = 102400,
Offset = 16187392,
Sequence = 2
},
new Partition
{
Description = null,
Name = "swap",
Type = "swap",
Length = 6388,
Start = 31816,
Size = 3270656,
Offset = 16289792,
Sequence = 2
},
new Partition
{
Description = null,
Name = "user",
Type = "data",
Length = 462016,
Start = 38304,
Size = 236552192,
Offset = 19611648,
Sequence = 3
},
new Partition
{
Description = null,
Name = "user",
Type = "data",
Length = 153824,
Start = 38304,
Size = 78757888,
Offset = 19611648,
Sequence = 4
},
new Partition
{
Description = null,
Name = "user",
Type = "data",
Length = 153824,
Start = 192128,
Size = 78757888,
Offset = 98369536,
Sequence = 5
},
new Partition
{
Description = null,
Name = "user",
Type = "data",
Length = 154368,
Start = 192128,
Size = 79036416,
Offset = 98369536,
Sequence = 6
},
new Partition
{
Description = null,
Name = "bad sector file",
Type = "bad",
Length = 64,
Start = 421312,
Size = 32768,
Offset = 215711744,
Sequence = 8
}
};
readonly Partition[] RP02 =
{
new Partition
@@ -1244,210 +1369,85 @@ namespace DiscImageChef.Partitions
}
};
readonly Partition[] RM02 =
public UNIX()
{
new Partition
{
Description = null,
Name = "/",
Type = "data",
Length = 9120,
Start = 0,
Size = 4669440,
Offset = 0,
Sequence = 0
},
new Partition
{
Description = null,
Name = "error log",
Type = "errorlog",
Length = 200,
Start = 9120,
Size = 102400,
Offset = 4669440,
Sequence = 1
},
new Partition
{
Description = null,
Name = "swap",
Type = "swap",
Length = 5400,
Start = 9320,
Size = 2764800,
Offset = 2764800,
Sequence = 1
},
new Partition
{
Description = null,
Name = "/usr",
Type = "data",
Length = 5600,
Start = 29120,
Size = 2867200,
Offset = 14909440,
Sequence = 2
},
new Partition
{
Description = null,
Name = "user",
Type = "data",
Length = 96896,
Start = 34720,
Size = 49610752,
Offset = 17776640,
Sequence = 3
},
new Partition
{
Description = null,
Name = "user",
Type = "data",
Length = 32160,
Start = 34720,
Size = 16465920,
Offset = 17776640,
Sequence = 4
},
new Partition
{
Description = null,
Name = "user",
Type = "data",
Length = 32160,
Start = 66880,
Size = 16465920,
Offset = 34242560,
Sequence = 5
},
new Partition
{
Description = null,
Name = "user",
Type = "data",
Length = 32576,
Start = 99040,
Size = 16678912,
Offset = 50708480,
Sequence = 6
},
new Partition
{
Description = null,
Name = "bad sector file",
Type = "bad",
Length = 64,
Start = 131616,
Size = 32768,
Offset = 67387392,
Sequence = 8
Name = "UNIX hardwired";
PluginUuid = new Guid("9ED7E30B-53BF-4619-87A0-5D2002155617");
}
};
readonly Partition[] RM05 =
public override bool GetInformation(ImagePlugin imagePlugin, out List<Partition> partitions, ulong sectorOffset)
{
new Partition
partitions = new List<Partition>();
Partition[] parts;
if(sectorOffset != 0) return false;
switch(imagePlugin.ImageInfo.MediaType)
{
Description = null,
Name = "/",
Type = "data",
Length = 10336,
Start = 0,
Size = 5292032,
Offset = 0,
Sequence = 0
},
new Partition
{
Description = null,
Name = "/usr",
Type = "data",
Length = 21280,
Start = 10336,
Size = 10895360,
Offset = 5292032,
Sequence = 1
},
new Partition
{
Description = null,
Name = "error log",
Type = "errorlog",
Length = 200,
Start = 31616,
Size = 102400,
Offset = 16187392,
Sequence = 2
},
new Partition
{
Description = null,
Name = "swap",
Type = "swap",
Length = 6388,
Start = 31816,
Size = 3270656,
Offset = 16289792,
Sequence = 2
},
new Partition
{
Description = null,
Name = "user",
Type = "data",
Length = 462016,
Start = 38304,
Size = 236552192,
Offset = 19611648,
Sequence = 3
},
new Partition
{
Description = null,
Name = "user",
Type = "data",
Length = 153824,
Start = 38304,
Size = 78757888,
Offset = 19611648,
Sequence = 4
},
new Partition
{
Description = null,
Name = "user",
Type = "data",
Length = 153824,
Start = 192128,
Size = 78757888,
Offset = 98369536,
Sequence = 5
},
new Partition
{
Description = null,
Name = "user",
Type = "data",
Length = 154368,
Start = 192128,
Size = 79036416,
Offset = 98369536,
Sequence = 6
},
new Partition
{
Description = null,
Name = "bad sector file",
Type = "bad",
Length = 64,
Start = 421312,
Size = 32768,
Offset = 215711744,
Sequence = 8
case MediaType.RA60:
parts = RA60;
break;
case MediaType.RA80:
parts = RA80;
break;
case MediaType.RA81:
parts = RA81;
break;
case MediaType.RC25:
parts = RC25;
break;
case MediaType.RD31:
parts = RD31;
break;
case MediaType.RD32:
parts = RD32;
break;
case MediaType.RD51:
parts = RD51;
break;
case MediaType.RD52:
parts = RD52;
break;
case MediaType.RD53:
parts = RD53;
break;
case MediaType.RD54:
parts = RD54;
break;
case MediaType.RK06:
parts = RK06;
break;
case MediaType.RK07:
parts = RK07;
break;
case MediaType.RM02:
case MediaType.RM03:
parts = RM02;
break;
case MediaType.RM05:
parts = RM05;
break;
case MediaType.RP02:
parts = RP02;
break;
case MediaType.RP03:
parts = RP03;
break;
case MediaType.RP04:
case MediaType.RP05:
parts = RP04;
break;
case MediaType.RP06:
parts = RP06;
break;
default: return false;
}
for(int i = 0; i < parts.Length; i++) parts[i].Scheme = "";
partitions = parts.ToList();
return partitions.Count > 0;
}
};
}
}

View File

@@ -65,7 +65,8 @@ namespace DiscImageChef.Partitions
bool magicFound = false;
bool absolute = false;
foreach(ulong i in new ulong[] {0, 1, 8, 29}.TakeWhile(i => i + sectorOffset < imagePlugin.GetSectors())) {
foreach(ulong i in new ulong[] {0, 1, 8, 29}.TakeWhile(i => i + sectorOffset < imagePlugin.GetSectors()))
{
pdsector = imagePlugin.ReadSector(i + sectorOffset);
magic = BitConverter.ToUInt32(pdsector, 4);
DicConsole.DebugWriteLine("VTOC plugin", "sanity at {0} is 0x{1:X8} (should be 0x{2:X8} or 0x{3:X8})",
@@ -351,8 +352,7 @@ namespace DiscImageChef.Partitions
if(parts[i].p_flag.HasFlag(pFlag.V_OPEN)) info += " (open)";
if(parts[i].p_flag.HasFlag(pFlag.V_REMAP)) info += " (alternate sector mapping)";
if(parts[i].p_flag.HasFlag(pFlag.V_RONLY)) info += " (read-only)";
if(timestamps[i] != 0)
info += $" created on {DateHandlers.UnixToDateTime(timestamps[i])}";
if(timestamps[i] != 0) info += $" created on {DateHandlers.UnixToDateTime(timestamps[i])}";
part.Description = "UNIX slice" + info + ".";
@@ -362,6 +362,30 @@ namespace DiscImageChef.Partitions
return partitions.Count > 0;
}
static string decodeUNIXTAG(pTag type, bool isNew)
{
switch(type)
{
case pTag.V_UNUSED: return "Unused";
case pTag.V_BOOT: return "Boot";
case pTag.V_ROOT: return "/";
case pTag.V_SWAP: return "Swap";
case pTag.V_USER: return "/usr";
case pTag.V_BACKUP: return "Whole disk";
case pTag.V_STAND_OLD: return isNew ? "Stand" : "Alternate sector space";
case pTag.V_VAR_OLD: return isNew ? "/var" : "non UNIX";
case pTag.V_HOME_OLD: return isNew ? "/home" : "Alternate track space";
case pTag.V_ALTSCTR_OLD: return isNew ? "Alternate sector track" : "Stand";
case pTag.V_CACHE: return isNew ? "Cache" : "/var";
case pTag.V_RESERVED: return isNew ? "Reserved" : "/home";
case pTag.V_DUMP: return "dump";
case pTag.V_ALTSCTR: return "Alternate sector track";
case pTag.V_VMPUBLIC: return "volume mgt public partition";
case pTag.V_VMPRIVATE: return "volume mgt private partition";
default: return $"Unknown TAG: 0x{type:X4}";
}
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
struct PDInfo
{
@@ -523,29 +547,5 @@ namespace DiscImageChef.Partitions
V_VALID = 0x200, /* Partition is valid to use */
V_VOMASK = 0x300 /* mask for open and valid */
}
static string decodeUNIXTAG(pTag type, bool isNew)
{
switch(type)
{
case pTag.V_UNUSED: return "Unused";
case pTag.V_BOOT: return "Boot";
case pTag.V_ROOT: return "/";
case pTag.V_SWAP: return "Swap";
case pTag.V_USER: return "/usr";
case pTag.V_BACKUP: return "Whole disk";
case pTag.V_STAND_OLD: return isNew ? "Stand" : "Alternate sector space";
case pTag.V_VAR_OLD: return isNew ? "/var" : "non UNIX";
case pTag.V_HOME_OLD: return isNew ? "/home" : "Alternate track space";
case pTag.V_ALTSCTR_OLD: return isNew ? "Alternate sector track" : "Stand";
case pTag.V_CACHE: return isNew ? "Cache" : "/var";
case pTag.V_RESERVED: return isNew ? "Reserved" : "/home";
case pTag.V_DUMP: return "dump";
case pTag.V_ALTSCTR: return "Alternate sector track";
case pTag.V_VMPUBLIC: return "volume mgt public partition";
case pTag.V_VMPRIVATE: return "volume mgt private partition";
default: return $"Unknown TAG: 0x{type:X4}";
}
}
}
}

View File

@@ -58,17 +58,6 @@ namespace DiscImageChef.Partitions
const long Xbox360SysExt2Len = 0x8000000;
const long Xbox360CompatLen = 0x10000000;
[StructLayout(LayoutKind.Sequential, Pack = 1)]
struct Xbox360DevKitPartitionTable
{
public uint magic;
public uint unknown;
public uint contentOff;
public uint contentLen;
public uint dashboardOff;
public uint dashboardLen;
}
const uint XBOX360_DEVKIT_MAGIC = 0x00020000;
public Xbox()
@@ -145,8 +134,7 @@ namespace DiscImageChef.Partitions
Partition dataPart = new Partition
{
Description = "Data volume",
Size =
imagePlugin.ImageInfo.Sectors * imagePlugin.ImageInfo.SectorSize - MemoryUnitDataOff,
Size = imagePlugin.ImageInfo.Sectors * imagePlugin.ImageInfo.SectorSize - MemoryUnitDataOff,
Length = imagePlugin.ImageInfo.Sectors - sysCachePart.Length,
Sequence = 2,
Offset = MemoryUnitDataOff,
@@ -258,5 +246,16 @@ namespace DiscImageChef.Partitions
return true;
}
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
struct Xbox360DevKitPartitionTable
{
public uint magic;
public uint unknown;
public uint contentOff;
public uint contentLen;
public uint dashboardOff;
public uint dashboardLen;
}
}
}