Added support for big-endian disklabels, more positions, and

corrected calculations. Also, added more debug output.
This commit is contained in:
2017-07-26 23:46:42 +01:00
parent adf5c066c7
commit 8cd63de25e

View File

@@ -35,12 +35,21 @@ using System.Collections.Generic;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using DiscImageChef.CommonTypes; using DiscImageChef.CommonTypes;
using DiscImageChef.ImagePlugins; using DiscImageChef.ImagePlugins;
using DiscImageChef.Console;
using System.Linq;
namespace DiscImageChef.PartPlugins namespace DiscImageChef.PartPlugins
{ {
public class BSD : PartPlugin public class BSD : PartPlugin
{ {
public const uint DISKMAGIC = 0x82564557; public const uint DISKMAGIC = 0x82564557;
public const uint DISKCIGAM = 0x57455682;
/// <summary>Known sector locations for BSD disklabel</summary>
readonly ulong[] labelLocations = { 0, 1, 2, 9 };
/// <summary>Known byte offsets for BSD disklabel</summary>
readonly uint[] labelOffsets = { 0, 9, 64, 128, 516 };
/// <summary>Maximum size of a disklabel with 22 partitions</summary>
const uint maxLabelSize = 500;
public BSD() public BSD()
{ {
@@ -51,50 +60,106 @@ namespace DiscImageChef.PartPlugins
public override bool GetInformation(ImagePlugin imagePlugin, out List<Partition> partitions, ulong sectorOffset) public override bool GetInformation(ImagePlugin imagePlugin, out List<Partition> partitions, ulong sectorOffset)
{ {
partitions = new List<Partition>(); partitions = new List<Partition>();
uint run = (maxLabelSize + labelOffsets.Last()) / imagePlugin.GetSectorSize();
if((maxLabelSize + labelOffsets.Last()) % imagePlugin.GetSectorSize() > 0)
run++;
byte[] sector = imagePlugin.ReadSector(sectorOffset); byte[] sector;
if(sector.Length < 512) DiskLabel dl = new DiskLabel();
return false;
bool found = false; bool found = false;
DiskLabel dl = GetDiskLabel(sector); foreach(ulong location in labelLocations)
if(dl.d_magic == DISKMAGIC || dl.d_magic2 == DISKMAGIC)
found = true;
else
{ {
sector = imagePlugin.ReadSector(1 + sectorOffset); if(location + run + sectorOffset >= imagePlugin.GetSectors())
return false;
dl = GetDiskLabel(sector); byte[] tmp = imagePlugin.ReadSectors(location + sectorOffset, run);
foreach(uint offset in labelOffsets)
{
sector = new byte[maxLabelSize];
Array.Copy(tmp, offset, sector, 0, maxLabelSize);
dl = GetDiskLabel(sector);
DicConsole.DebugWriteLine("BSD plugin", "dl.magic on sector {0} at offset {1} = 0x{2:X8} (expected 0x{3:X8})", location + sectorOffset, offset, dl.d_magic, DISKMAGIC);
if((dl.d_magic == DISKMAGIC && dl.d_magic2 == DISKMAGIC) ||
(dl.d_magic == DISKCIGAM && dl.d_magic2 == DISKCIGAM))
{
found = true;
break;
}
}
found |= (dl.d_magic == DISKMAGIC || dl.d_magic2 == DISKMAGIC); if(found)
break;
} }
if(found) if(!found)
{ return false;
ulong counter = 0;
foreach(BSDPartition entry in dl.d_partitions) if(dl.d_magic == DISKCIGAM && dl.d_magic2 == DISKCIGAM)
DicConsole.DebugWriteLine("BSD plugin", "dl.d_type = {0}", dl.d_type);
DicConsole.DebugWriteLine("BSD plugin", "dl.d_subtype = {0}", dl.d_subtype);
DicConsole.DebugWriteLine("BSD plugin", "dl.d_typename = {0}", StringHandlers.CToString(dl.d_typename));
DicConsole.DebugWriteLine("BSD plugin", "dl.d_packname = {0}", StringHandlers.CToString(dl.d_packname));
DicConsole.DebugWriteLine("BSD plugin", "dl.d_secsize = {0}", dl.d_secsize);
DicConsole.DebugWriteLine("BSD plugin", "dl.d_nsectors = {0}", dl.d_nsectors);
DicConsole.DebugWriteLine("BSD plugin", "dl.d_ntracks = {0}", dl.d_ntracks);
DicConsole.DebugWriteLine("BSD plugin", "dl.d_ncylinders = {0}", dl.d_ncylinders);
DicConsole.DebugWriteLine("BSD plugin", "dl.d_secpercyl = {0}", dl.d_secpercyl);
DicConsole.DebugWriteLine("BSD plugin", "dl.d_secperunit = {0}", dl.d_secperunit);
DicConsole.DebugWriteLine("BSD plugin", "dl.d_sparespertrack = {0}", dl.d_sparespertrack);
DicConsole.DebugWriteLine("BSD plugin", "dl.d_sparespercyl = {0}", dl.d_sparespercyl);
DicConsole.DebugWriteLine("BSD plugin", "dl.d_acylinders = {0}", dl.d_acylinders);
DicConsole.DebugWriteLine("BSD plugin", "dl.d_rpm = {0}", dl.d_rpm);
DicConsole.DebugWriteLine("BSD plugin", "dl.d_interleave = {0}", dl.d_interleave);
DicConsole.DebugWriteLine("BSD plugin", "dl.d_trackskew = {0}", dl.d_trackskew);
DicConsole.DebugWriteLine("BSD plugin", "dl.d_cylskeew = {0}", dl.d_cylskeew);
DicConsole.DebugWriteLine("BSD plugin", "dl.d_headswitch = {0}", dl.d_headswitch);
DicConsole.DebugWriteLine("BSD plugin", "dl.d_trkseek = {0}", dl.d_trkseek);
DicConsole.DebugWriteLine("BSD plugin", "dl.d_flags = {0}", dl.d_flags);
DicConsole.DebugWriteLine("BSD plugin", "dl.d_drivedata[0] = {0}", dl.d_drivedata[0]);
DicConsole.DebugWriteLine("BSD plugin", "dl.d_drivedata[1] = {0}", dl.d_drivedata[1]);
DicConsole.DebugWriteLine("BSD plugin", "dl.d_drivedata[2] = {0}", dl.d_drivedata[2]);
DicConsole.DebugWriteLine("BSD plugin", "dl.d_drivedata[3] = {0}", dl.d_drivedata[3]);
DicConsole.DebugWriteLine("BSD plugin", "dl.d_drivedata[4] = {0}", dl.d_drivedata[4]);
DicConsole.DebugWriteLine("BSD plugin", "dl.d_spare[0] = {0}", dl.d_spare[0]);
DicConsole.DebugWriteLine("BSD plugin", "dl.d_spare[1] = {0}", dl.d_spare[1]);
DicConsole.DebugWriteLine("BSD plugin", "dl.d_spare[2] = {0}", dl.d_spare[2]);
DicConsole.DebugWriteLine("BSD plugin", "dl.d_spare[3] = {0}", dl.d_spare[3]);
DicConsole.DebugWriteLine("BSD plugin", "dl.d_spare[4] = {0}", dl.d_spare[4]);
DicConsole.DebugWriteLine("BSD plugin", "dl.d_magic2 = 0x{0:X8}", dl.d_magic2);
DicConsole.DebugWriteLine("BSD plugin", "dl.d_checksum = 0x{0:X8}", dl.d_checksum);
DicConsole.DebugWriteLine("BSD plugin", "dl.d_npartitions = {0}", dl.d_npartitions);
DicConsole.DebugWriteLine("BSD plugin", "dl.d_bbsize = {0}", dl.d_bbsize);
DicConsole.DebugWriteLine("BSD plugin", "dl.d_sbsize = {0}", dl.d_sbsize);
ulong counter = 0;
for(int i = 0; i < dl.d_npartitions && i < 22; i++)
{
DicConsole.DebugWriteLine("BSD plugin", "dl.d_partitions[i].p_offset = {0}", dl.d_partitions[i].p_offset);
DicConsole.DebugWriteLine("BSD plugin", "dl.d_partitions[i].p_size = {0}", dl.d_partitions[i].p_size);
DicConsole.DebugWriteLine("BSD plugin", "dl.d_partitions[i].p_fstype = {0} ({1})", dl.d_partitions[i].p_fstype, fsTypeToString(dl.d_partitions[i].p_fstype));
Partition part = new Partition
{ {
Partition part = new Partition Start = ((dl.d_partitions[i].p_offset * dl.d_secsize) / imagePlugin.GetSectorSize()),
{ Offset = (dl.d_partitions[i].p_offset * dl.d_secsize),
Start = entry.p_offset, Length = (dl.d_partitions[i].p_size * dl.d_secsize) / imagePlugin.GetSectorSize(),
Offset = (entry.p_offset * dl.d_secsize), Size = (dl.d_partitions[i].p_size * dl.d_secsize),
Size = entry.p_size, Type = fsTypeToString(dl.d_partitions[i].p_fstype),
Length = (entry.p_size * dl.d_secsize), Sequence = counter,
Type = fsTypeToString(entry.p_fstype), Scheme = Name
Sequence = counter, };
Scheme = Name if(dl.d_partitions[i].p_fstype != fsType.Unused)
}; {
if(entry.p_fstype != fsType.Unused) DicConsole.DebugWriteLine("BSD plugin", "part.start = {0}", part.Start);
{ DicConsole.DebugWriteLine("BSD plugin", "Adding it...");
partitions.Add(part); partitions.Add(part);
counter++; counter++;
}
} }
} }
return found; return partitions.Count > 0;
} }
/// <summary>Drive type</summary> /// <summary>Drive type</summary>
@@ -310,7 +375,7 @@ namespace DiscImageChef.PartPlugins
/// <summary>Maximum size of superblock in bytes</summary> /// <summary>Maximum size of superblock in bytes</summary>
public uint d_sbsize; public uint d_sbsize;
/// <summary>Partitions</summary> /// <summary>Partitions</summary>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 18)] [MarshalAs(UnmanagedType.ByValArray, SizeConst = 22)]
public BSDPartition[] d_partitions; public BSDPartition[] d_partitions;
} }
@@ -387,6 +452,8 @@ namespace DiscImageChef.PartPlugins
return "ZFS"; return "ZFS";
case fsType.NANDFS: case fsType.NANDFS:
return "FreeBSD nandfs"; return "FreeBSD nandfs";
case fsType.MSDOS:
return "FAT";
case fsType.Other: case fsType.Other:
return "Other or unknown"; return "Other or unknown";
default: default:
@@ -396,11 +463,22 @@ namespace DiscImageChef.PartPlugins
public static DiskLabel GetDiskLabel(byte[] disklabel) public static DiskLabel GetDiskLabel(byte[] disklabel)
{ {
DiskLabel dl = new DiskLabel(); GCHandle handle = GCHandle.Alloc(disklabel, GCHandleType.Pinned);
IntPtr dlPtr = Marshal.AllocHGlobal(512); DiskLabel dl = (DiskLabel)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(DiskLabel));
Marshal.Copy(disklabel, 0, dlPtr, 512); handle.Free();
dl = (DiskLabel)Marshal.PtrToStructure(dlPtr, typeof(DiskLabel)); return dl;
Marshal.FreeHGlobal(dlPtr); }
public static DiskLabel SwapDiskLabel(DiskLabel disklabel)
{
DiskLabel dl = BigEndianMarshal.SwapStructureMembersEndian(disklabel);
for(int i = 0; i < dl.d_drivedata.Length; i++)
dl.d_drivedata[i] = BigEndianMarshal.SwapStructureMembersEndian(dl.d_drivedata[i]);
for(int i = 0; i < dl.d_drivedata.Length; i++)
dl.d_spare[i] = BigEndianMarshal.SwapStructureMembersEndian(dl.d_spare[i]);
for(int i = 0; i < dl.d_drivedata.Length; i++)
dl.d_partitions[i] = BigEndianMarshal.SwapStructureMembersEndian(dl.d_partitions[i]);
return dl; return dl;
} }
} }