mirror of
https://github.com/aaru-dps/Aaru.git
synced 2025-12-16 19:24:25 +00:00
REFACTOR: Final cleanup of DiscImageChef.Partitions.
This commit is contained in:
@@ -108,7 +108,8 @@ namespace DiscImageChef.Partitions
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
switch(bootBlock.flags & TYPE_MASK) {
|
switch(bootBlock.flags & TYPE_MASK)
|
||||||
|
{
|
||||||
case TYPE_LINUX:
|
case TYPE_LINUX:
|
||||||
{
|
{
|
||||||
IntPtr tablePtr = Marshal.AllocHGlobal(512);
|
IntPtr tablePtr = Marshal.AllocHGlobal(512);
|
||||||
|
|||||||
@@ -59,8 +59,7 @@ namespace DiscImageChef.Partitions
|
|||||||
PluginUuid = new Guid("36405F8D-4F1A-07F5-209C-223D735D6D22");
|
PluginUuid = new Guid("36405F8D-4F1A-07F5-209C-223D735D6D22");
|
||||||
}
|
}
|
||||||
|
|
||||||
public override bool GetInformation(ImagePlugin imagePlugin,
|
public override bool GetInformation(ImagePlugin imagePlugin, out List<Partition> partitions, ulong sectorOffset)
|
||||||
out List<Partition> partitions, ulong sectorOffset)
|
|
||||||
{
|
{
|
||||||
uint sectorSize;
|
uint sectorSize;
|
||||||
|
|
||||||
@@ -84,7 +83,8 @@ namespace DiscImageChef.Partitions
|
|||||||
}
|
}
|
||||||
else if(sectorSize < 256) return false;
|
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.sbSig = 0x{0:X4}", ddm.sbSig);
|
||||||
DicConsole.DebugWriteLine("AppleMap Plugin", "ddm.sbBlockSize = {0}", ddm.sbBlockSize);
|
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}"
|
Type = oldEntry.pdFSID == HFS_MAGIC_OLD ? "Apple_HFS" : $"0x{oldEntry.pdFSID:X8}"
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
partitions.Add(part);
|
partitions.Add(part);
|
||||||
|
|
||||||
sequence++;
|
sequence++;
|
||||||
@@ -257,8 +256,7 @@ namespace DiscImageChef.Partitions
|
|||||||
DicConsole.DebugWriteLine("AppleMap Plugin", "dpme[{0}].first_data_block = {1}", i,
|
DicConsole.DebugWriteLine("AppleMap Plugin", "dpme[{0}].first_data_block = {1}", i,
|
||||||
entry.first_data_block);
|
entry.first_data_block);
|
||||||
DicConsole.DebugWriteLine("AppleMap Plugin", "dpme[{0}].data_sectors = {1}", i, entry.data_sectors);
|
DicConsole.DebugWriteLine("AppleMap Plugin", "dpme[{0}].data_sectors = {1}", i, entry.data_sectors);
|
||||||
DicConsole.DebugWriteLine("AppleMap Plugin", "dpme[{0}].flags = {1}", i,
|
DicConsole.DebugWriteLine("AppleMap Plugin", "dpme[{0}].flags = {1}", i, (AppleMapFlags)entry.flags);
|
||||||
(AppleMapFlags)entry.flags);
|
|
||||||
DicConsole.DebugWriteLine("AppleMap Plugin", "dpme[{0}].first_boot_block = {1}", i,
|
DicConsole.DebugWriteLine("AppleMap Plugin", "dpme[{0}].first_boot_block = {1}", i,
|
||||||
entry.first_boot_block);
|
entry.first_boot_block);
|
||||||
DicConsole.DebugWriteLine("AppleMap Plugin", "dpme[{0}].boot_size = {1}", i, entry.boot_size);
|
DicConsole.DebugWriteLine("AppleMap Plugin", "dpme[{0}].boot_size = {1}", i, entry.boot_size);
|
||||||
@@ -266,8 +264,7 @@ namespace DiscImageChef.Partitions
|
|||||||
entry.load_address);
|
entry.load_address);
|
||||||
DicConsole.DebugWriteLine("AppleMap Plugin", "dpme[{0}].load_address2 = 0x{1:X8}", i,
|
DicConsole.DebugWriteLine("AppleMap Plugin", "dpme[{0}].load_address2 = 0x{1:X8}", i,
|
||||||
entry.load_address2);
|
entry.load_address2);
|
||||||
DicConsole.DebugWriteLine("AppleMap Plugin", "dpme[{0}].entry_point = 0x{1:X8}", i,
|
DicConsole.DebugWriteLine("AppleMap Plugin", "dpme[{0}].entry_point = 0x{1:X8}", i, entry.entry_point);
|
||||||
entry.entry_point);
|
|
||||||
DicConsole.DebugWriteLine("AppleMap Plugin", "dpme[{0}].entry_point2 = 0x{1:X8}", i,
|
DicConsole.DebugWriteLine("AppleMap Plugin", "dpme[{0}].entry_point2 = 0x{1:X8}", i,
|
||||||
entry.entry_point2);
|
entry.entry_point2);
|
||||||
DicConsole.DebugWriteLine("AppleMap Plugin", "dpme[{0}].checksum = 0x{1:X8}", i, entry.checksum);
|
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))
|
if(flags.HasFlag(AppleMapFlags.Bootable))
|
||||||
{
|
{
|
||||||
sb.AppendFormat("First boot sector: {0}",
|
sb.AppendFormat("First boot sector: {0}", entry.first_boot_block * entrySize / sectorSize)
|
||||||
entry.first_boot_block * entrySize / sectorSize).AppendLine();
|
.AppendLine();
|
||||||
sb.AppendFormat("Boot is {0} bytes.", entry.boot_size).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 load address: 0x{0:X8}", entry.load_address).AppendLine();
|
||||||
sb.AppendFormat("Boot entry point: 0x{0:X8}", entry.entry_point).AppendLine();
|
sb.AppendFormat("Boot entry point: 0x{0:X8}", entry.entry_point).AppendLine();
|
||||||
@@ -316,8 +313,7 @@ namespace DiscImageChef.Partitions
|
|||||||
}
|
}
|
||||||
|
|
||||||
_partition.Description = sb.ToString();
|
_partition.Description = sb.ToString();
|
||||||
if(_partition.Start < imagePlugin.ImageInfo.Sectors &&
|
if(_partition.Start < imagePlugin.ImageInfo.Sectors && _partition.End < imagePlugin.ImageInfo.Sectors)
|
||||||
_partition.End < imagePlugin.ImageInfo.Sectors)
|
|
||||||
{
|
{
|
||||||
partitions.Add(_partition);
|
partitions.Add(_partition);
|
||||||
sequence++;
|
sequence++;
|
||||||
@@ -325,8 +321,7 @@ namespace DiscImageChef.Partitions
|
|||||||
// Some CD and DVDs end with an Apple_Free that expands beyond the disc size...
|
// Some CD and DVDs end with an Apple_Free that expands beyond the disc size...
|
||||||
else if(_partition.Start < imagePlugin.ImageInfo.Sectors)
|
else if(_partition.Start < imagePlugin.ImageInfo.Sectors)
|
||||||
{
|
{
|
||||||
DicConsole.DebugWriteLine("AppleMap Plugin",
|
DicConsole.DebugWriteLine("AppleMap Plugin", "Cutting last partition end ({0}) to media size ({1})",
|
||||||
"Cutting last partition end ({0}) to media size ({1})",
|
|
||||||
_partition.End, imagePlugin.ImageInfo.Sectors - 1);
|
_partition.End, imagePlugin.ImageInfo.Sectors - 1);
|
||||||
_partition.Length = imagePlugin.ImageInfo.Sectors - _partition.Start;
|
_partition.Length = imagePlugin.ImageInfo.Sectors - _partition.Start;
|
||||||
partitions.Add(_partition);
|
partitions.Add(_partition);
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ namespace DiscImageChef.Partitions
|
|||||||
{
|
{
|
||||||
public class Apricot : PartitionPlugin
|
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 =
|
readonly string[] bootTypeCodes =
|
||||||
{
|
{
|
||||||
"Non-bootable", "Apricot & XI RAM BIOS", "Generic ROM BIOS", "Apricot & XI ROM BIOS",
|
"Non-bootable", "Apricot & XI RAM BIOS", "Generic ROM BIOS", "Apricot & XI ROM BIOS",
|
||||||
@@ -49,12 +49,12 @@ namespace DiscImageChef.Partitions
|
|||||||
};
|
};
|
||||||
readonly string[] diskTypeCodes =
|
readonly string[] diskTypeCodes =
|
||||||
{"MF1DD 70-track", "MF1DD", "MF2DD", "Winchester 5M", "Winchester 10M", "Winchester 20M"};
|
{"MF1DD 70-track", "MF1DD", "MF2DD", "Winchester 5M", "Winchester 10M", "Winchester 20M"};
|
||||||
readonly string[] printDevices = {"Parallel", "Serial"};
|
|
||||||
readonly int[] lineModes = {256, 200};
|
readonly int[] lineModes = {256, 200};
|
||||||
readonly int[] lineWidths = {80, 40};
|
readonly int[] lineWidths = {80, 40};
|
||||||
readonly int[] baudRates = {50, 75, 110, 134, 150, 300, 600, 1200, 1800, 2400, 3600, 4800, 7200, 9600, 19200};
|
readonly string[] operatingSystemCodes = {"Invalid", "MS-DOS", "UCSD Pascal", "CP/M", "Concurrent CP/M"};
|
||||||
readonly double[] stopBits = {1, 1.5, 2};
|
|
||||||
readonly string[] parityTypes = {"None", "Odd", "Even", "Mark", "Space"};
|
readonly string[] parityTypes = {"None", "Odd", "Even", "Mark", "Space"};
|
||||||
|
readonly string[] printDevices = {"Parallel", "Serial"};
|
||||||
|
readonly double[] stopBits = {1, 1.5, 2};
|
||||||
|
|
||||||
public Apricot()
|
public Apricot()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -61,8 +61,7 @@ namespace DiscImageChef.Partitions
|
|||||||
PluginUuid = new Guid("d1dd0f24-ec39-4c4d-9072-be31919a3b5e");
|
PluginUuid = new Guid("d1dd0f24-ec39-4c4d-9072-be31919a3b5e");
|
||||||
}
|
}
|
||||||
|
|
||||||
public override bool GetInformation(ImagePlugin imagePlugin,
|
public override bool GetInformation(ImagePlugin imagePlugin, out List<Partition> partitions, ulong sectorOffset)
|
||||||
out List<Partition> partitions, ulong sectorOffset)
|
|
||||||
{
|
{
|
||||||
partitions = new List<Partition>();
|
partitions = new List<Partition>();
|
||||||
|
|
||||||
|
|||||||
@@ -44,12 +44,12 @@ namespace DiscImageChef.Partitions
|
|||||||
{
|
{
|
||||||
const uint DISKMAGIC = 0x82564557;
|
const uint DISKMAGIC = 0x82564557;
|
||||||
const uint DISKCIGAM = 0x57455682;
|
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>
|
/// <summary>Known sector locations for BSD disklabel</summary>
|
||||||
readonly ulong[] labelLocations = {0, 1, 2, 9};
|
readonly ulong[] labelLocations = {0, 1, 2, 9};
|
||||||
/// <summary>Known byte offsets for BSD disklabel</summary>
|
/// <summary>Known byte offsets for BSD disklabel</summary>
|
||||||
readonly uint[] labelOffsets = {0, 9, 64, 128, 516};
|
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()
|
public BSD()
|
||||||
{
|
{
|
||||||
@@ -167,6 +167,62 @@ namespace DiscImageChef.Partitions
|
|||||||
return partitions.Count > 0;
|
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>
|
/// <summary>Drive type</summary>
|
||||||
enum dType : ushort
|
enum dType : ushort
|
||||||
{
|
{
|
||||||
@@ -318,9 +374,13 @@ namespace DiscImageChef.Partitions
|
|||||||
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||||||
struct DiskLabel
|
struct DiskLabel
|
||||||
{
|
{
|
||||||
/// <summary><see cref="DISKMAGIC"/></summary>
|
/// <summary>
|
||||||
|
/// <see cref="DISKMAGIC" />
|
||||||
|
/// </summary>
|
||||||
public uint d_magic;
|
public uint d_magic;
|
||||||
/// <summary><see cref="dType"/></summary>
|
/// <summary>
|
||||||
|
/// <see cref="dType" />
|
||||||
|
/// </summary>
|
||||||
public dType d_type;
|
public dType d_type;
|
||||||
/// <summary>Disk subtype</summary>
|
/// <summary>Disk subtype</summary>
|
||||||
public ushort d_subtype;
|
public ushort d_subtype;
|
||||||
@@ -358,7 +418,9 @@ namespace DiscImageChef.Partitions
|
|||||||
public uint d_headswitch;
|
public uint d_headswitch;
|
||||||
/// <summary>Track to track seek in microseconds</summary>
|
/// <summary>Track to track seek in microseconds</summary>
|
||||||
public uint d_trkseek;
|
public uint d_trkseek;
|
||||||
/// <summary><see cref="dFlags"/></summary>
|
/// <summary>
|
||||||
|
/// <see cref="dFlags" />
|
||||||
|
/// </summary>
|
||||||
public dFlags d_flags;
|
public dFlags d_flags;
|
||||||
/// <summary>Drive-specific information</summary>
|
/// <summary>Drive-specific information</summary>
|
||||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 5)] public uint[] d_drivedata;
|
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 5)] public uint[] d_drivedata;
|
||||||
@@ -394,61 +456,5 @@ namespace DiscImageChef.Partitions
|
|||||||
/// <summary>Cylinder per group</summary>
|
/// <summary>Cylinder per group</summary>
|
||||||
public ushort p_cpg;
|
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -76,7 +76,8 @@ namespace DiscImageChef.Partitions
|
|||||||
Length = (ulong)(entry.pi_nblocks * sector.Length),
|
Length = (ulong)(entry.pi_nblocks * sector.Length),
|
||||||
Sequence = counter,
|
Sequence = counter,
|
||||||
Scheme = Name
|
Scheme = Name
|
||||||
}).Where(part => part.Size > 0)) {
|
}).Where(part => part.Size > 0))
|
||||||
|
{
|
||||||
partitions.Add(part);
|
partitions.Add(part);
|
||||||
counter++;
|
counter++;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -51,8 +51,7 @@ namespace DiscImageChef.Partitions
|
|||||||
PluginUuid = new Guid("CBC9D281-C1D0-44E8-9038-4D66FD2678AB");
|
PluginUuid = new Guid("CBC9D281-C1D0-44E8-9038-4D66FD2678AB");
|
||||||
}
|
}
|
||||||
|
|
||||||
public override bool GetInformation(ImagePlugin imagePlugin,
|
public override bool GetInformation(ImagePlugin imagePlugin, out List<Partition> partitions, ulong sectorOffset)
|
||||||
out List<Partition> partitions, ulong sectorOffset)
|
|
||||||
{
|
{
|
||||||
partitions = new List<Partition>();
|
partitions = new List<Partition>();
|
||||||
|
|
||||||
@@ -145,7 +144,9 @@ namespace DiscImageChef.Partitions
|
|||||||
entries.Add(entry);
|
entries.Add(entry);
|
||||||
}
|
}
|
||||||
#pragma warning disable RECS0022 // A catch clause that catches System.Exception and has an empty body
|
#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
|
#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;
|
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.partitionType = {0}", entry.partitionType);
|
||||||
DicConsole.DebugWriteLine("GPT Plugin", "entry.partitionId = {0}", entry.partitionId);
|
DicConsole.DebugWriteLine("GPT Plugin", "entry.partitionId = {0}", entry.partitionId);
|
||||||
DicConsole.DebugWriteLine("GPT Plugin", "entry.startLBA = {0}", entry.startLBA);
|
DicConsole.DebugWriteLine("GPT Plugin", "entry.startLBA = {0}", entry.startLBA);
|
||||||
|
|||||||
@@ -43,397 +43,13 @@ namespace DiscImageChef.Partitions
|
|||||||
// TODO: Support AAP extensions
|
// TODO: Support AAP extensions
|
||||||
public class MBR : PartitionPlugin
|
public class MBR : PartitionPlugin
|
||||||
{
|
{
|
||||||
const ulong GptMagic = 0x5452415020494645;
|
const ulong GPT_MAGIC = 0x5452415020494645;
|
||||||
|
|
||||||
public MBR()
|
const ushort MBR_MAGIC = 0xAA55;
|
||||||
{
|
const ushort NEC_MAGIC = 0xA55A;
|
||||||
Name = "Master Boot Record";
|
const ushort DM_MAGIC = 0x55AA;
|
||||||
PluginUuid = new Guid("5E8A34E8-4F1A-59E6-4BF7-7EA647063A76");
|
|
||||||
}
|
|
||||||
|
|
||||||
public override bool GetInformation(ImagePlugin imagePlugin,
|
static readonly string[] MbrTypes =
|
||||||
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 =
|
|
||||||
{
|
{
|
||||||
// 0x00
|
// 0x00
|
||||||
"Empty", "FAT12", "XENIX root", "XENIX /usr",
|
"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"
|
"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;
|
public override bool GetInformation(ImagePlugin imagePlugin, out List<Partition> partitions, ulong sectorOffset)
|
||||||
const ushort NEC_Magic = 0xA55A;
|
{
|
||||||
const ushort DM_Magic = 0x55AA;
|
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)]
|
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||||||
struct MasterBootRecord
|
struct MasterBootRecord
|
||||||
@@ -583,8 +579,10 @@ namespace DiscImageChef.Partitions
|
|||||||
/// <summary>Boot code</summary>
|
/// <summary>Boot code</summary>
|
||||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 446)] public byte[] boot_code;
|
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 446)] public byte[] boot_code;
|
||||||
/// <summary>Partitions</summary>
|
/// <summary>Partitions</summary>
|
||||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)] public MBRPartitionEntry[] entries;
|
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)] public MbrPartitionEntry[] entries;
|
||||||
/// <summary><see cref="MBR_Magic"/></summary>
|
/// <summary>
|
||||||
|
/// <see cref="MBR.MBR_MAGIC" />
|
||||||
|
/// </summary>
|
||||||
public ushort magic;
|
public ushort magic;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -595,8 +593,10 @@ namespace DiscImageChef.Partitions
|
|||||||
/// <summary>Boot code, almost always unused</summary>
|
/// <summary>Boot code, almost always unused</summary>
|
||||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 446)] public byte[] boot_code;
|
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 446)] public byte[] boot_code;
|
||||||
/// <summary>Partitions or pointers</summary>
|
/// <summary>Partitions or pointers</summary>
|
||||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)] public MBRPartitionEntry[] entries;
|
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)] public MbrPartitionEntry[] entries;
|
||||||
/// <summary><see cref="MBR_Magic"/></summary>
|
/// <summary>
|
||||||
|
/// <see cref="MBR.MBR_MAGIC" />
|
||||||
|
/// </summary>
|
||||||
public ushort magic;
|
public ushort magic;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -618,8 +618,10 @@ namespace DiscImageChef.Partitions
|
|||||||
/// <summary>Boot code, continuation</summary>
|
/// <summary>Boot code, continuation</summary>
|
||||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 222)] public byte[] boot_code2;
|
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 222)] public byte[] boot_code2;
|
||||||
/// <summary>Partitions</summary>
|
/// <summary>Partitions</summary>
|
||||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)] public MBRPartitionEntry[] entries;
|
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)] public MbrPartitionEntry[] entries;
|
||||||
/// <summary><see cref="MBR_Magic"/></summary>
|
/// <summary>
|
||||||
|
/// <see cref="MBR.MBR_MAGIC" />
|
||||||
|
/// </summary>
|
||||||
public ushort magic;
|
public ushort magic;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -633,8 +635,10 @@ namespace DiscImageChef.Partitions
|
|||||||
/// <summary>Set to 0</summary>
|
/// <summary>Set to 0</summary>
|
||||||
public ushort zero;
|
public ushort zero;
|
||||||
/// <summary>Partitions</summary>
|
/// <summary>Partitions</summary>
|
||||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)] public MBRPartitionEntry[] entries;
|
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)] public MbrPartitionEntry[] entries;
|
||||||
/// <summary><see cref="MBR_Magic"/></summary>
|
/// <summary>
|
||||||
|
/// <see cref="MBR.MBR_MAGIC" />
|
||||||
|
/// </summary>
|
||||||
public ushort magic;
|
public ushort magic;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -660,8 +664,10 @@ namespace DiscImageChef.Partitions
|
|||||||
/// <summary>Set to 0</summary>
|
/// <summary>Set to 0</summary>
|
||||||
public ushort zero2;
|
public ushort zero2;
|
||||||
/// <summary>Partitions</summary>
|
/// <summary>Partitions</summary>
|
||||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)] public MBRPartitionEntry[] entries;
|
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)] public MbrPartitionEntry[] entries;
|
||||||
/// <summary><see cref="MBR_Magic"/></summary>
|
/// <summary>
|
||||||
|
/// <see cref="MBR.MBR_MAGIC" />
|
||||||
|
/// </summary>
|
||||||
public ushort magic;
|
public ushort magic;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -670,11 +676,15 @@ namespace DiscImageChef.Partitions
|
|||||||
{
|
{
|
||||||
/// <summary>Boot code</summary>
|
/// <summary>Boot code</summary>
|
||||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 380)] public byte[] boot_code;
|
[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;
|
public ushort nec_magic;
|
||||||
/// <summary>Partitions</summary>
|
/// <summary>Partitions</summary>
|
||||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)] public MBRPartitionEntry[] entries;
|
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)] public MbrPartitionEntry[] entries;
|
||||||
/// <summary><see cref="MBR_Magic"/></summary>
|
/// <summary>
|
||||||
|
/// <see cref="MBR.MBR_MAGIC" />
|
||||||
|
/// </summary>
|
||||||
public ushort magic;
|
public ushort magic;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -683,16 +693,20 @@ namespace DiscImageChef.Partitions
|
|||||||
{
|
{
|
||||||
/// <summary>Boot code</summary>
|
/// <summary>Boot code</summary>
|
||||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 252)] public byte[] boot_code;
|
[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;
|
public ushort dm_magic;
|
||||||
/// <summary>Partitions</summary>
|
/// <summary>Partitions</summary>
|
||||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)] public MBRPartitionEntry[] entries;
|
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)] public MbrPartitionEntry[] entries;
|
||||||
/// <summary><see cref="MBR_Magic"/></summary>
|
/// <summary>
|
||||||
|
/// <see cref="MBR.MBR_MAGIC" />
|
||||||
|
/// </summary>
|
||||||
public ushort magic;
|
public ushort magic;
|
||||||
}
|
}
|
||||||
|
|
||||||
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||||||
struct MBRPartitionEntry
|
struct MbrPartitionEntry
|
||||||
{
|
{
|
||||||
/// <summary>Partition status, 0x80 or 0x00, else invalid</summary>
|
/// <summary>Partition status, 0x80 or 0x00, else invalid</summary>
|
||||||
public byte status;
|
public byte status;
|
||||||
|
|||||||
@@ -92,8 +92,9 @@ namespace DiscImageChef.Partitions
|
|||||||
|
|
||||||
Partition part = new Partition
|
Partition part = new Partition
|
||||||
{
|
{
|
||||||
Start = CHS.ToLBA(entry.dp_scyl, entry.dp_shd, (uint)(entry.dp_ssect + 1),
|
Start =
|
||||||
imagePlugin.ImageInfo.Heads, imagePlugin.ImageInfo.SectorsPerTrack),
|
CHS.ToLBA(entry.dp_scyl, entry.dp_shd, (uint)(entry.dp_ssect + 1), imagePlugin.ImageInfo.Heads,
|
||||||
|
imagePlugin.ImageInfo.SectorsPerTrack),
|
||||||
Type = DecodePC98Sid(entry.dp_sid),
|
Type = DecodePC98Sid(entry.dp_sid),
|
||||||
Name = StringHandlers.CToString(entry.dp_name, Encoding.GetEncoding(932)).Trim(),
|
Name = StringHandlers.CToString(entry.dp_name, Encoding.GetEncoding(932)).Trim(),
|
||||||
Sequence = counter,
|
Sequence = counter,
|
||||||
@@ -101,8 +102,8 @@ namespace DiscImageChef.Partitions
|
|||||||
};
|
};
|
||||||
part.Offset = part.Start * imagePlugin.GetSectorSize();
|
part.Offset = part.Start * imagePlugin.GetSectorSize();
|
||||||
part.Length = CHS.ToLBA(entry.dp_ecyl, entry.dp_ehd, (uint)(entry.dp_esect + 1),
|
part.Length = CHS.ToLBA(entry.dp_ecyl, entry.dp_ehd, (uint)(entry.dp_esect + 1),
|
||||||
imagePlugin.ImageInfo.Heads,
|
imagePlugin.ImageInfo.Heads, imagePlugin.ImageInfo.SectorsPerTrack) -
|
||||||
imagePlugin.ImageInfo.SectorsPerTrack) - part.Start;
|
part.Start;
|
||||||
part.Size = part.Length * imagePlugin.GetSectorSize();
|
part.Size = part.Length * imagePlugin.GetSectorSize();
|
||||||
|
|
||||||
DicConsole.DebugWriteLine("PC98 plugin", "part.Start = {0}", part.Start);
|
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.Length = {0}", part.Length);
|
||||||
DicConsole.DebugWriteLine("PC98 plugin", "part.Size = {0}", part.Size);
|
DicConsole.DebugWriteLine("PC98 plugin", "part.Size = {0}", part.Size);
|
||||||
|
|
||||||
if(((entry.dp_mid & 0x20) != 0x20 && (entry.dp_mid & 0x44) != 0x44) ||
|
if((entry.dp_mid & 0x20) != 0x20 && (entry.dp_mid & 0x44) != 0x44 ||
|
||||||
part.Start >= imagePlugin.ImageInfo.Sectors ||
|
part.Start >= imagePlugin.ImageInfo.Sectors || part.End > imagePlugin.ImageInfo.Sectors) continue;
|
||||||
part.End > imagePlugin.ImageInfo.Sectors) continue;
|
|
||||||
|
|
||||||
partitions.Add(part);
|
partitions.Add(part);
|
||||||
counter++;
|
counter++;
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ namespace DiscImageChef.Partitions
|
|||||||
/// <param name="imagePlugin">Disk image.</param>
|
/// <param name="imagePlugin">Disk image.</param>
|
||||||
/// <param name="partitions">Returns list of partitions.</param>
|
/// <param name="partitions">Returns list of partitions.</param>
|
||||||
/// <param name="sectorOffset">At which sector to start searching for the partition scheme.</param>
|
/// <param name="sectorOffset">At which sector to start searching for the partition scheme.</param>
|
||||||
public abstract bool GetInformation(ImagePlugin imagePlugin,
|
public abstract bool GetInformation(ImagePlugin imagePlugin, out List<Partition> partitions,
|
||||||
out List<Partition> partitions, ulong sectorOffset);
|
ulong sectorOffset);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -51,8 +51,7 @@ namespace DiscImageChef.Partitions
|
|||||||
PluginUuid = new Guid("F0BF4FFC-056E-4E7C-8B65-4EAEE250ADD9");
|
PluginUuid = new Guid("F0BF4FFC-056E-4E7C-8B65-4EAEE250ADD9");
|
||||||
}
|
}
|
||||||
|
|
||||||
public override bool GetInformation(ImagePlugin imagePlugin, out List<Partition> partitions,
|
public override bool GetInformation(ImagePlugin imagePlugin, out List<Partition> partitions, ulong sectorOffset)
|
||||||
ulong sectorOffset)
|
|
||||||
{
|
{
|
||||||
partitions = new List<Partition>();
|
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
|
// While all of Plan9 is supposedly UTF-8, it uses ASCII strcmp for reading its partition table
|
||||||
string[] really = StringHandlers.CToString(sector).Split('\n');
|
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;
|
if(!ulong.TryParse(tokens[2], out ulong start) || !ulong.TryParse(tokens[3], out ulong end)) break;
|
||||||
|
|
||||||
Partition part = new Partition
|
Partition part = new Partition
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -66,7 +66,8 @@ namespace DiscImageChef.Partitions
|
|||||||
|
|
||||||
ulong counter = 0;
|
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,
|
Start = entry.offset,
|
||||||
Offset = (ulong)(entry.offset * sector.Length),
|
Offset = (ulong)(entry.offset * sector.Length),
|
||||||
@@ -75,7 +76,10 @@ namespace DiscImageChef.Partitions
|
|||||||
Type = "Rio Karma",
|
Type = "Rio Karma",
|
||||||
Sequence = counter,
|
Sequence = counter,
|
||||||
Scheme = Name
|
Scheme = Name
|
||||||
} where entry.type == ENTRY_MAGIC select part) {
|
}
|
||||||
|
where entry.type == ENTRY_MAGIC
|
||||||
|
select part)
|
||||||
|
{
|
||||||
partitions.Add(part);
|
partitions.Add(part);
|
||||||
counter++;
|
counter++;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,6 +37,7 @@ using System.Runtime.InteropServices;
|
|||||||
using DiscImageChef.CommonTypes;
|
using DiscImageChef.CommonTypes;
|
||||||
using DiscImageChef.Console;
|
using DiscImageChef.Console;
|
||||||
using DiscImageChef.DiscImages;
|
using DiscImageChef.DiscImages;
|
||||||
|
|
||||||
#pragma warning disable 169
|
#pragma warning disable 169
|
||||||
#pragma warning disable 649
|
#pragma warning disable 649
|
||||||
|
|
||||||
@@ -120,11 +121,9 @@ namespace DiscImageChef.Partitions
|
|||||||
|
|
||||||
Partition part = new Partition
|
Partition part = new Partition
|
||||||
{
|
{
|
||||||
Start =
|
Start = dvh.partitions[i].first_block * dvh.device_params.dp_secbytes / imagePlugin.GetSectorSize(),
|
||||||
dvh.partitions[i].first_block * dvh.device_params.dp_secbytes / imagePlugin.GetSectorSize(),
|
|
||||||
Offset = dvh.partitions[i].first_block * dvh.device_params.dp_secbytes,
|
Offset = dvh.partitions[i].first_block * dvh.device_params.dp_secbytes,
|
||||||
Length =
|
Length = dvh.partitions[i].num_blocks * dvh.device_params.dp_secbytes / imagePlugin.GetSectorSize(),
|
||||||
dvh.partitions[i].num_blocks * dvh.device_params.dp_secbytes / imagePlugin.GetSectorSize(),
|
|
||||||
Size = dvh.partitions[i].num_blocks * dvh.device_params.dp_secbytes,
|
Size = dvh.partitions[i].num_blocks * dvh.device_params.dp_secbytes,
|
||||||
Type = TypeToString(dvh.partitions[i].type),
|
Type = TypeToString(dvh.partitions[i].type),
|
||||||
Sequence = counter,
|
Sequence = counter,
|
||||||
@@ -140,6 +139,31 @@ namespace DiscImageChef.Partitions
|
|||||||
return true;
|
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)]
|
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||||||
struct SGILabel
|
struct SGILabel
|
||||||
{
|
{
|
||||||
@@ -195,31 +219,6 @@ namespace DiscImageChef.Partitions
|
|||||||
LinuxRAID = 0xFD
|
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)]
|
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||||||
struct SGIPartition
|
struct SGIPartition
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -70,49 +70,13 @@ namespace DiscImageChef.Partitions
|
|||||||
const int LEN_DKL_PAD16 = DK_LABEL_SIZE - (456 + // sizeof(dk_vtoc16)
|
const int LEN_DKL_PAD16 = DK_LABEL_SIZE - (456 + // sizeof(dk_vtoc16)
|
||||||
4 * 4 + 12 * 2 + 2 * 2);
|
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()
|
public SunDisklabel()
|
||||||
{
|
{
|
||||||
Name = "Sun Disklabel";
|
Name = "Sun Disklabel";
|
||||||
PluginUuid = new Guid("50F35CC4-8375-4445-8DCB-1BA550C931A3");
|
PluginUuid = new Guid("50F35CC4-8375-4445-8DCB-1BA550C931A3");
|
||||||
}
|
}
|
||||||
|
|
||||||
public override bool GetInformation(ImagePlugin imagePlugin,
|
public override bool GetInformation(ImagePlugin imagePlugin, out List<Partition> partitions, ulong sectorOffset)
|
||||||
out List<Partition> partitions, ulong sectorOffset)
|
|
||||||
{
|
{
|
||||||
partitions = new List<Partition>();
|
partitions = new List<Partition>();
|
||||||
|
|
||||||
@@ -267,8 +231,7 @@ namespace DiscImageChef.Partitions
|
|||||||
Sequence = (ulong)i,
|
Sequence = (ulong)i,
|
||||||
Offset =
|
Offset =
|
||||||
((ulong)dkl8.dkl_map[i].dkl_cylno * sectorsPerCylinder + sectorOffset) * DK_LABEL_SIZE,
|
((ulong)dkl8.dkl_map[i].dkl_cylno * sectorsPerCylinder + sectorOffset) * DK_LABEL_SIZE,
|
||||||
Start =
|
Start = ((ulong)dkl8.dkl_map[i].dkl_cylno * sectorsPerCylinder + sectorOffset) *
|
||||||
((ulong)dkl8.dkl_map[i].dkl_cylno * sectorsPerCylinder + sectorOffset) *
|
|
||||||
DK_LABEL_SIZE / imagePlugin.GetSectorSize(),
|
DK_LABEL_SIZE / imagePlugin.GetSectorSize(),
|
||||||
Type = SunIdToString(dkl8.dkl_vtoc.v_part[i].p_tag),
|
Type = SunIdToString(dkl8.dkl_vtoc.v_part[i].p_tag),
|
||||||
Scheme = Name
|
Scheme = Name
|
||||||
@@ -336,9 +299,8 @@ namespace DiscImageChef.Partitions
|
|||||||
Sequence = (ulong)i,
|
Sequence = (ulong)i,
|
||||||
Offset =
|
Offset =
|
||||||
((ulong)dkl16.dkl_vtoc.v_part[i].p_start + sectorOffset) * dkl16.dkl_vtoc.v_sectorsz,
|
((ulong)dkl16.dkl_vtoc.v_part[i].p_start + sectorOffset) * dkl16.dkl_vtoc.v_sectorsz,
|
||||||
Start =
|
Start = ((ulong)dkl16.dkl_vtoc.v_part[i].p_start + sectorOffset) *
|
||||||
((ulong)dkl16.dkl_vtoc.v_part[i].p_start + sectorOffset) * dkl16.dkl_vtoc.v_sectorsz /
|
dkl16.dkl_vtoc.v_sectorsz / imagePlugin.GetSectorSize(),
|
||||||
imagePlugin.GetSectorSize(),
|
|
||||||
Type = SunIdToString(dkl16.dkl_vtoc.v_part[i].p_tag),
|
Type = SunIdToString(dkl16.dkl_vtoc.v_part[i].p_tag),
|
||||||
Scheme = Name
|
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>
|
/// <summary>SunOS logical partitions</summary>
|
||||||
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||||||
struct dk_map
|
struct dk_map
|
||||||
|
|||||||
@@ -43,87 +43,6 @@ namespace DiscImageChef.Partitions
|
|||||||
// Currently only DEC devices used in Ultrix are added, probably it's missing a lot of entries.
|
// Currently only DEC devices used in Ultrix are added, probably it's missing a lot of entries.
|
||||||
public class UNIX : PartitionPlugin
|
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 =
|
readonly Partition[] RA60 =
|
||||||
{
|
{
|
||||||
new Partition
|
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 =
|
readonly Partition[] RP02 =
|
||||||
{
|
{
|
||||||
new Partition
|
new Partition
|
||||||
@@ -1244,210 +1369,85 @@ namespace DiscImageChef.Partitions
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
readonly Partition[] RM02 =
|
public UNIX()
|
||||||
{
|
{
|
||||||
new Partition
|
Name = "UNIX hardwired";
|
||||||
{
|
PluginUuid = new Guid("9ED7E30B-53BF-4619-87A0-5D2002155617");
|
||||||
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 =
|
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,
|
case MediaType.RA60:
|
||||||
Name = "/",
|
parts = RA60;
|
||||||
Type = "data",
|
break;
|
||||||
Length = 10336,
|
case MediaType.RA80:
|
||||||
Start = 0,
|
parts = RA80;
|
||||||
Size = 5292032,
|
break;
|
||||||
Offset = 0,
|
case MediaType.RA81:
|
||||||
Sequence = 0
|
parts = RA81;
|
||||||
},
|
break;
|
||||||
new Partition
|
case MediaType.RC25:
|
||||||
{
|
parts = RC25;
|
||||||
Description = null,
|
break;
|
||||||
Name = "/usr",
|
case MediaType.RD31:
|
||||||
Type = "data",
|
parts = RD31;
|
||||||
Length = 21280,
|
break;
|
||||||
Start = 10336,
|
case MediaType.RD32:
|
||||||
Size = 10895360,
|
parts = RD32;
|
||||||
Offset = 5292032,
|
break;
|
||||||
Sequence = 1
|
case MediaType.RD51:
|
||||||
},
|
parts = RD51;
|
||||||
new Partition
|
break;
|
||||||
{
|
case MediaType.RD52:
|
||||||
Description = null,
|
parts = RD52;
|
||||||
Name = "error log",
|
break;
|
||||||
Type = "errorlog",
|
case MediaType.RD53:
|
||||||
Length = 200,
|
parts = RD53;
|
||||||
Start = 31616,
|
break;
|
||||||
Size = 102400,
|
case MediaType.RD54:
|
||||||
Offset = 16187392,
|
parts = RD54;
|
||||||
Sequence = 2
|
break;
|
||||||
},
|
case MediaType.RK06:
|
||||||
new Partition
|
parts = RK06;
|
||||||
{
|
break;
|
||||||
Description = null,
|
case MediaType.RK07:
|
||||||
Name = "swap",
|
parts = RK07;
|
||||||
Type = "swap",
|
break;
|
||||||
Length = 6388,
|
case MediaType.RM02:
|
||||||
Start = 31816,
|
case MediaType.RM03:
|
||||||
Size = 3270656,
|
parts = RM02;
|
||||||
Offset = 16289792,
|
break;
|
||||||
Sequence = 2
|
case MediaType.RM05:
|
||||||
},
|
parts = RM05;
|
||||||
new Partition
|
break;
|
||||||
{
|
case MediaType.RP02:
|
||||||
Description = null,
|
parts = RP02;
|
||||||
Name = "user",
|
break;
|
||||||
Type = "data",
|
case MediaType.RP03:
|
||||||
Length = 462016,
|
parts = RP03;
|
||||||
Start = 38304,
|
break;
|
||||||
Size = 236552192,
|
case MediaType.RP04:
|
||||||
Offset = 19611648,
|
case MediaType.RP05:
|
||||||
Sequence = 3
|
parts = RP04;
|
||||||
},
|
break;
|
||||||
new Partition
|
case MediaType.RP06:
|
||||||
{
|
parts = RP06;
|
||||||
Description = null,
|
break;
|
||||||
Name = "user",
|
default: return false;
|
||||||
Type = "data",
|
}
|
||||||
Length = 153824,
|
|
||||||
Start = 38304,
|
for(int i = 0; i < parts.Length; i++) parts[i].Scheme = "";
|
||||||
Size = 78757888,
|
|
||||||
Offset = 19611648,
|
partitions = parts.ToList();
|
||||||
Sequence = 4
|
|
||||||
},
|
return partitions.Count > 0;
|
||||||
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
|
|
||||||
}
|
}
|
||||||
};
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -65,7 +65,8 @@ namespace DiscImageChef.Partitions
|
|||||||
bool magicFound = false;
|
bool magicFound = false;
|
||||||
bool absolute = 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);
|
pdsector = imagePlugin.ReadSector(i + sectorOffset);
|
||||||
magic = BitConverter.ToUInt32(pdsector, 4);
|
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})",
|
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_OPEN)) info += " (open)";
|
||||||
if(parts[i].p_flag.HasFlag(pFlag.V_REMAP)) info += " (alternate sector mapping)";
|
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(parts[i].p_flag.HasFlag(pFlag.V_RONLY)) info += " (read-only)";
|
||||||
if(timestamps[i] != 0)
|
if(timestamps[i] != 0) info += $" created on {DateHandlers.UnixToDateTime(timestamps[i])}";
|
||||||
info += $" created on {DateHandlers.UnixToDateTime(timestamps[i])}";
|
|
||||||
|
|
||||||
part.Description = "UNIX slice" + info + ".";
|
part.Description = "UNIX slice" + info + ".";
|
||||||
|
|
||||||
@@ -362,6 +362,30 @@ namespace DiscImageChef.Partitions
|
|||||||
return partitions.Count > 0;
|
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)]
|
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||||||
struct PDInfo
|
struct PDInfo
|
||||||
{
|
{
|
||||||
@@ -523,29 +547,5 @@ namespace DiscImageChef.Partitions
|
|||||||
V_VALID = 0x200, /* Partition is valid to use */
|
V_VALID = 0x200, /* Partition is valid to use */
|
||||||
V_VOMASK = 0x300 /* mask for open and valid */
|
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}";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -58,17 +58,6 @@ namespace DiscImageChef.Partitions
|
|||||||
const long Xbox360SysExt2Len = 0x8000000;
|
const long Xbox360SysExt2Len = 0x8000000;
|
||||||
const long Xbox360CompatLen = 0x10000000;
|
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;
|
const uint XBOX360_DEVKIT_MAGIC = 0x00020000;
|
||||||
|
|
||||||
public Xbox()
|
public Xbox()
|
||||||
@@ -145,8 +134,7 @@ namespace DiscImageChef.Partitions
|
|||||||
Partition dataPart = new Partition
|
Partition dataPart = new Partition
|
||||||
{
|
{
|
||||||
Description = "Data volume",
|
Description = "Data volume",
|
||||||
Size =
|
Size = imagePlugin.ImageInfo.Sectors * imagePlugin.ImageInfo.SectorSize - MemoryUnitDataOff,
|
||||||
imagePlugin.ImageInfo.Sectors * imagePlugin.ImageInfo.SectorSize - MemoryUnitDataOff,
|
|
||||||
Length = imagePlugin.ImageInfo.Sectors - sysCachePart.Length,
|
Length = imagePlugin.ImageInfo.Sectors - sysCachePart.Length,
|
||||||
Sequence = 2,
|
Sequence = 2,
|
||||||
Offset = MemoryUnitDataOff,
|
Offset = MemoryUnitDataOff,
|
||||||
@@ -258,5 +246,16 @@ namespace DiscImageChef.Partitions
|
|||||||
return true;
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user