Add more boot code hashes to FAT.

This commit is contained in:
2018-02-01 01:19:19 +00:00
parent be325bc888
commit d732d72342

View File

@@ -52,12 +52,6 @@ namespace DiscImageChef.Filesystems
const uint FSINFO_SIGNATURE2 = 0x61417272;
const uint FSINFO_SIGNATURE3 = 0xAA550000;
public FileSystemType XmlFsType { get; private set; }
public Encoding Encoding { get; private set; }
public string Name => "Microsoft File Allocation Table";
public Guid Id => new Guid("33513B2C-0D26-0D2D-32C3-79D8611158E0");
(string hash, string name)[] knownBootHashes =
{
("b639b4d5b25f63560e3b34a3a0feb732aa65486f", "Amstrad MS-DOS 3.20 (8-sector floppy)"),
@@ -139,9 +133,22 @@ namespace DiscImageChef.Filesystems
("3cea1921d29fcd3343d36c090cb3e3dba926781d", "Windows 98, Me"),
("037f9c8caed602d93c88f7e9d8f13a732b3ada76", "Windows NT"),
("a63806bfe11140c873082318dd4da834068be327", "Windows Vista"),
("8f024b3d501c39ee6e3f8ca28173ad6a780d3eb0", "Windows Vista, 8, 10")
("8f024b3d501c39ee6e3f8ca28173ad6a780d3eb0", "Windows Vista, 8, 10"),
("d3e93f8b82ef250db216037d827a4896dc97d2be", "TracerST"), // OEM ID: "TracerST"
//("b741f85ef40288ccc8887de1f6e849009097e1c9", "Norton Utilities"), // OEM ID: "IBM PNCI", need to confirm
("c49b275537ac7237cac64d83f34d2024ae0ca96a", "Windows NT (Spanish)"
), // Need to check Windows >= 2000 (Spanish)
//("a48b0e4b696317eed829e960d1aa576562a4f185", "TracerST"), // Unknown OEM ID, apparently Tracer, unconfirmed
("fe477972602ba76658ff7143859045b3c4036ca5", "iomega"
) // OEM ID: "SHIPDISK", contains timedate on boot code may not be unique
};
public FileSystemType XmlFsType { get; private set; }
public Encoding Encoding { get; private set; }
public string Name => "Microsoft File Allocation Table";
public Guid Id => new Guid("33513B2C-0D26-0D2D-32C3-79D8611158E0");
public bool Identify(IMediaImage imagePlugin, Partition partition)
{
if(2 + partition.Start >= partition.End) return false;
@@ -188,13 +195,16 @@ namespace DiscImageChef.Filesystems
int bitsInBps = CountBits.Count(bps);
if(imagePlugin.Info.SectorSize >= 512) bootable = BitConverter.ToUInt16(bpbSector, 0x1FE);
bool correctSpc = spc == 1 || spc == 2 || spc == 4 || spc == 8 || spc == 16 || spc == 32 || spc == 64;
bool correctSpc =
spc == 1 || spc == 2 || spc == 4 || spc == 8 || spc == 16 || spc == 32 || spc == 64;
string msxString = Encoding.ASCII.GetString(msxId);
string fat32String = Encoding.ASCII.GetString(fat32Id);
bool atariOemCorrect = atariOem[0] >= 0x20 && atariOem[1] >= 0x20 && atariOem[2] >= 0x20 &&
atariOem[3] >= 0x20 && atariOem[4] >= 0x20 && atariOem[5] >= 0x20;
bool dosOemCorrect = dosOem[0] >= 0x20 && dosOem[1] >= 0x20 && dosOem[2] >= 0x20 && dosOem[3] >= 0x20 &&
dosOem[4] >= 0x20 && dosOem[5] >= 0x20 && dosOem[6] >= 0x20 && dosOem[7] >= 0x20;
bool dosOemCorrect = dosOem[0] >= 0x20 && dosOem[1] >= 0x20 && dosOem[2] >= 0x20 &&
dosOem[3] >= 0x20 &&
dosOem[4] >= 0x20 && dosOem[5] >= 0x20 && dosOem[6] >= 0x20 &&
dosOem[7] >= 0x20;
string atariString = Encoding.ASCII.GetString(atariOem);
string oemString = Encoding.ASCII.GetString(dosOem);
@@ -226,7 +236,8 @@ namespace DiscImageChef.Filesystems
ushort apricotSectors = BitConverter.ToUInt16(bpbSector, 0x58);
byte apricotMediaDescriptor = bpbSector[0x5A];
ushort apricotFatSectors = BitConverter.ToUInt16(bpbSector, 0x5B);
bool apricotCorrectSpc = apricotSpc == 1 || apricotSpc == 2 || apricotSpc == 4 || apricotSpc == 8 ||
bool apricotCorrectSpc = apricotSpc == 1 || apricotSpc == 2 || apricotSpc == 4 ||
apricotSpc == 8 ||
apricotSpc == 16 || apricotSpc == 32 || apricotSpc == 64;
int bitsInApricotBps = CountBits.Count(apricotBps);
byte apricotPartitions = bpbSector[0x0C];
@@ -302,9 +313,12 @@ namespace DiscImageChef.Filesystems
}
// Apricot BPB
if(bitsInApricotBps == 1 && apricotCorrectSpc && apricotReservedSecs < partition.End - partition.Start &&
apricotFatsNo <= 2 && apricotRootEntries > 0 && apricotFatSectors > 0 &&
apricotSectors <= partition.End - partition.Start + 1 && apricotPartitions == 0) return true;
if(bitsInApricotBps == 1 && apricotCorrectSpc &&
apricotReservedSecs < partition.End - partition.Start &&
apricotFatsNo <= 2 &&
apricotRootEntries > 0 && apricotFatSectors > 0 &&
apricotSectors <= partition.End - partition.Start + 1 &&
apricotPartitions == 0) return true;
// All FAT12 without BPB can only be used on floppies, without partitions.
if(partition.Start != 0) return false;
@@ -332,7 +346,8 @@ namespace DiscImageChef.Filesystems
{
for(int c = 0; c < 11; c++)
if(rootDir[c + e] < 0x20 && rootDir[c + e] != 0x00 && rootDir[c + e] != 0x05 ||
rootDir[c + e] == 0xFF || rootDir[c + e] == 0x2E)
rootDir[c + e] == 0xFF ||
rootDir[c + e] == 0x2E)
{
validRootDir = false;
break;
@@ -361,15 +376,21 @@ namespace DiscImageChef.Filesystems
break;
case 0xFD:
if(imagePlugin.Info.Sectors == 4004 && imagePlugin.Info.SectorSize == 128) fat2SectorNo = 7;
else if(imagePlugin.Info.Sectors == 2002 && imagePlugin.Info.SectorSize == 128) fat2SectorNo = 7;
else if(imagePlugin.Info.Sectors == 2002 && imagePlugin.Info.SectorSize == 128)
fat2SectorNo = 7;
break;
case 0xFE:
if(imagePlugin.Info.Sectors == 320 && imagePlugin.Info.SectorSize == 512) fat2SectorNo = 2;
else if(imagePlugin.Info.Sectors == 2002 && imagePlugin.Info.SectorSize == 128) fat2SectorNo = 7;
else if(imagePlugin.Info.Sectors == 1232 && imagePlugin.Info.SectorSize == 1024) fat2SectorNo = 3;
else if(imagePlugin.Info.Sectors == 616 && imagePlugin.Info.SectorSize == 1024) fat2SectorNo = 2;
else if(imagePlugin.Info.Sectors == 720 && imagePlugin.Info.SectorSize == 128) fat2SectorNo = 5;
else if(imagePlugin.Info.Sectors == 640 && imagePlugin.Info.SectorSize == 512) fat2SectorNo = 2;
else if(imagePlugin.Info.Sectors == 2002 && imagePlugin.Info.SectorSize == 128)
fat2SectorNo = 7;
else if(imagePlugin.Info.Sectors == 1232 && imagePlugin.Info.SectorSize == 1024)
fat2SectorNo = 3;
else if(imagePlugin.Info.Sectors == 616 && imagePlugin.Info.SectorSize == 1024)
fat2SectorNo = 2;
else if(imagePlugin.Info.Sectors == 720 && imagePlugin.Info.SectorSize == 128)
fat2SectorNo = 5;
else if(imagePlugin.Info.Sectors == 640 && imagePlugin.Info.SectorSize == 512)
fat2SectorNo = 2;
break;
case 0xFF:
if(imagePlugin.Info.Sectors == 640 && imagePlugin.Info.SectorSize == 512) fat2SectorNo = 2;
@@ -446,7 +467,8 @@ namespace DiscImageChef.Filesystems
dos32Bpb = (BiosParameterBlock32)Marshal.PtrToStructure(bpbPtr, typeof(BiosParameterBlock32));
dos33Bpb = (BiosParameterBlock33)Marshal.PtrToStructure(bpbPtr, typeof(BiosParameterBlock33));
shortEbpb =
(BiosParameterBlockShortEbpb)Marshal.PtrToStructure(bpbPtr, typeof(BiosParameterBlockShortEbpb));
(BiosParameterBlockShortEbpb)
Marshal.PtrToStructure(bpbPtr, typeof(BiosParameterBlockShortEbpb));
ebpb = (BiosParameterBlockEbpb)Marshal.PtrToStructure(bpbPtr, typeof(BiosParameterBlockEbpb));
shortFat32Bpb =
(Fat32ParameterBlockShort)Marshal.PtrToStructure(bpbPtr, typeof(Fat32ParameterBlockShort));
@@ -470,9 +492,11 @@ namespace DiscImageChef.Filesystems
bool correctSpcAtari = atariBpb.spc == 1 || atariBpb.spc == 2 || atariBpb.spc == 4 ||
atariBpb.spc == 8 || atariBpb.spc == 16 || atariBpb.spc == 32 ||
atariBpb.spc == 64;
bool correctSpcMsx = msxBpb.spc == 1 || msxBpb.spc == 2 || msxBpb.spc == 4 || msxBpb.spc == 8 ||
bool correctSpcMsx = msxBpb.spc == 1 || msxBpb.spc == 2 || msxBpb.spc == 4 ||
msxBpb.spc == 8 ||
msxBpb.spc == 16 || msxBpb.spc == 32 || msxBpb.spc == 64;
bool correctSpcDos20 = dos2Bpb.spc == 1 || dos2Bpb.spc == 2 || dos2Bpb.spc == 4 || dos2Bpb.spc == 8 ||
bool correctSpcDos20 = dos2Bpb.spc == 1 || dos2Bpb.spc == 2 || dos2Bpb.spc == 4 ||
dos2Bpb.spc == 8 ||
dos2Bpb.spc == 16 || dos2Bpb.spc == 32 || dos2Bpb.spc == 64;
bool correctSpcDos30 = dos30Bpb.spc == 1 || dos30Bpb.spc == 2 || dos30Bpb.spc == 4 ||
dos30Bpb.spc == 8 || dos30Bpb.spc == 16 || dos30Bpb.spc == 32 ||
@@ -486,7 +510,8 @@ namespace DiscImageChef.Filesystems
bool correctSpcDos34 = shortEbpb.spc == 1 || shortEbpb.spc == 2 || shortEbpb.spc == 4 ||
shortEbpb.spc == 8 || shortEbpb.spc == 16 || shortEbpb.spc == 32 ||
shortEbpb.spc == 64;
bool correctSpcDos40 = ebpb.spc == 1 || ebpb.spc == 2 || ebpb.spc == 4 || ebpb.spc == 8 ||
bool correctSpcDos40 = ebpb.spc == 1 || ebpb.spc == 2 || ebpb.spc == 4 ||
ebpb.spc == 8 ||
ebpb.spc == 16 || ebpb.spc == 32 || ebpb.spc == 64;
bool correctSpcFat32Short = shortFat32Bpb.spc == 1 || shortFat32Bpb.spc == 2 ||
shortFat32Bpb.spc == 4 || shortFat32Bpb.spc == 8 ||
@@ -527,7 +552,8 @@ namespace DiscImageChef.Filesystems
dos33Bpb.oem_name[4] >= 0x20 && dos33Bpb.oem_name[5] >= 0x20 &&
dos33Bpb.oem_name[6] >= 0x20 && dos33Bpb.oem_name[7] >= 0x20;
if(bitsInBpsFat32 == 1 && correctSpcFat32 && fat32Bpb.fats_no <= 2 && fat32Bpb.sectors == 0 &&
if(bitsInBpsFat32 == 1 && correctSpcFat32 && fat32Bpb.fats_no <= 2 &&
fat32Bpb.sectors == 0 &&
fat32Bpb.spfat == 0 && fat32Bpb.signature == 0x29 &&
Encoding.ASCII.GetString(fat32Bpb.fs_type) == "FAT32 ")
{
@@ -536,7 +562,8 @@ namespace DiscImageChef.Filesystems
minBootNearJump = 0x58;
}
else if(bitsInBpsFat32Short == 1 && correctSpcFat32Short && shortFat32Bpb.fats_no <= 2 &&
shortFat32Bpb.sectors == 0 && shortFat32Bpb.spfat == 0 && shortFat32Bpb.signature == 0x28)
shortFat32Bpb.sectors == 0 && shortFat32Bpb.spfat == 0 &&
shortFat32Bpb.signature == 0x28)
{
DicConsole.DebugWriteLine("FAT plugin", "Using short FAT32 BPB");
useShortFat32 = shortFat32Bpb.big_sectors == 0
@@ -544,23 +571,28 @@ namespace DiscImageChef.Filesystems
: shortFat32Bpb.big_sectors <= partition.End - partition.Start + 1;
minBootNearJump = 0x57;
}
else if(bitsInBpsMsx == 1 && correctSpcMsx && msxBpb.fats_no <= 2 && msxBpb.root_ent > 0 &&
msxBpb.sectors <= partition.End - partition.Start + 1 && msxBpb.spfat > 0 &&
else if(bitsInBpsMsx == 1 &&
correctSpcMsx && msxBpb.fats_no <= 2 && msxBpb.root_ent > 0 &&
msxBpb.sectors <= partition.End - partition.Start + 1 &&
msxBpb.spfat > 0 &&
Encoding.ASCII.GetString(msxBpb.vol_id) == "VOL_ID")
{
DicConsole.DebugWriteLine("FAT plugin", "Using MSX BPB");
useMsxBpb = true;
}
else if(bitsInBpsApricot == 1 && correctSpcApricot && apricotBpb.mainBPB.fats_no <= 2 &&
else if(bitsInBpsApricot == 1 && correctSpcApricot &&
apricotBpb.mainBPB.fats_no <= 2 &&
apricotBpb.mainBPB.root_ent > 0 &&
apricotBpb.mainBPB.sectors <= partition.End - partition.Start + 1 &&
apricotBpb.mainBPB.spfat > 0 && apricotBpb.partitionCount == 0)
apricotBpb.mainBPB.spfat > 0 &&
apricotBpb.partitionCount == 0)
{
DicConsole.DebugWriteLine("FAT plugin", "Using Apricot BPB");
useApricotBpb = true;
}
else if(bitsInBpsDos40 == 1 && correctSpcDos40 && ebpb.fats_no <= 2 && ebpb.root_ent > 0 &&
ebpb.spfat > 0 && (ebpb.signature == 0x28 || ebpb.signature == 0x29 || andosOemCorrect))
ebpb.spfat > 0 && (ebpb.signature == 0x28 || ebpb.signature == 0x29 ||
andosOemCorrect))
{
if(ebpb.sectors == 0)
{
@@ -592,18 +624,25 @@ namespace DiscImageChef.Filesystems
minBootNearJump = 0x29;
}
}
else if(bitsInBpsDos33 == 1 && correctSpcDos33 && dos33Bpb.rsectors < partition.End - partition.Start &&
dos33Bpb.fats_no <= 2 && dos33Bpb.root_ent > 0 && dos33Bpb.spfat > 0)
if(dos33Bpb.sectors == 0 && dos33Bpb.hsectors <= partition.Start && dos33Bpb.big_sectors > 0 &&
else if(bitsInBpsDos33 == 1 && correctSpcDos33 &&
dos33Bpb.rsectors < partition.End - partition.Start &&
dos33Bpb.fats_no <= 2 &&
dos33Bpb.root_ent > 0 &&
dos33Bpb.spfat > 0)
if(dos33Bpb.sectors == 0 &&
dos33Bpb.hsectors <= partition.Start &&
dos33Bpb.big_sectors > 0 &&
dos33Bpb.big_sectors <= partition.End - partition.Start + 1)
{
DicConsole.DebugWriteLine("FAT plugin", "Using DOS 3.3 BPB");
useDos33Bpb = true;
minBootNearJump = 0x22;
}
else if(dos33Bpb.big_sectors == 0 && dos33Bpb.hsectors <= partition.Start && dos33Bpb.sectors > 0 &&
else if(dos33Bpb.big_sectors == 0 && dos33Bpb.hsectors <= partition.Start &&
dos33Bpb.sectors > 0 &&
dos33Bpb.sectors <= partition.End - partition.Start + 1)
if(atariBpb.jump[0] == 0x60 || atariBpb.jump[0] == 0xE9 && atariBpb.jump[1] == 0x00 &&
if(atariBpb.jump[0] == 0x60 || atariBpb.jump[0] == 0xE9 &&
atariBpb.jump[1] == 0x00 &&
Encoding.ASCII.GetString(dos33Bpb.oem_name) != "NEXT ")
{
DicConsole.DebugWriteLine("FAT plugin", "Using Atari BPB");
@@ -624,8 +663,10 @@ namespace DiscImageChef.Filesystems
useDos32Bpb = true;
minBootNearJump = 0x1E;
}
else if(dos30Bpb.sptrk > 0 && dos30Bpb.sptrk < 64 && dos30Bpb.heads > 0 && dos30Bpb.heads < 256)
if(atariBpb.jump[0] == 0x60 || atariBpb.jump[0] == 0xE9 && atariBpb.jump[1] == 0x00 &&
else if(dos30Bpb.sptrk > 0 && dos30Bpb.sptrk < 64 &&
dos30Bpb.heads > 0 && dos30Bpb.heads < 256)
if(atariBpb.jump[0] == 0x60 || atariBpb.jump[0] == 0xE9 &&
atariBpb.jump[1] == 0x00 &&
Encoding.ASCII.GetString(dos33Bpb.oem_name) != "NEXT ")
{
DicConsole.DebugWriteLine("FAT plugin", "Using Atari BPB");
@@ -639,7 +680,8 @@ namespace DiscImageChef.Filesystems
}
else
{
if(atariBpb.jump[0] == 0x60 || atariBpb.jump[0] == 0xE9 && atariBpb.jump[1] == 0x00 &&
if(atariBpb.jump[0] == 0x60 || atariBpb.jump[0] == 0xE9 &&
atariBpb.jump[1] == 0x00 &&
Encoding.ASCII.GetString(dos33Bpb.oem_name) != "NEXT ")
{
DicConsole.DebugWriteLine("FAT plugin", "Using Atari BPB");
@@ -672,7 +714,8 @@ namespace DiscImageChef.Filesystems
// DEC Rainbow, lacks a BPB but has a very concrete structure...
if(imagePlugin.Info.Sectors == 800 && imagePlugin.Info.SectorSize == 512 && !useAtariBpb && !useMsxBpb &&
!useDos2Bpb && !useDos3Bpb && !useDos32Bpb && !useDos33Bpb && !userShortExtendedBpb && !useExtendedBpb &&
!useDos2Bpb && !useDos3Bpb && !useDos32Bpb && !useDos33Bpb &&
!userShortExtendedBpb && !useExtendedBpb &&
!useShortFat32 && !useLongFat32 && !useApricotBpb)
{
// DEC Rainbow boots up with a Z80, first byte should be DI (disable interrupts)
@@ -695,7 +738,8 @@ namespace DiscImageChef.Filesystems
{
for(int c = 0; c < 11; c++)
if(rootDir[c + e] < 0x20 && rootDir[c + e] != 0x00 && rootDir[c + e] != 0x05 ||
rootDir[c + e] == 0xFF || rootDir[c + e] == 0x2E)
rootDir[c + e] == 0xFF ||
rootDir[c + e] == 0x2E)
{
validRootDir = false;
break;
@@ -726,7 +770,8 @@ namespace DiscImageChef.Filesystems
}
}
if(!useAtariBpb && !useMsxBpb && !useDos2Bpb && !useDos3Bpb && !useDos32Bpb && !useDos33Bpb &&
if(!useAtariBpb && !useMsxBpb && !useDos2Bpb && !useDos3Bpb && !useDos32Bpb &&
!useDos33Bpb &&
!userShortExtendedBpb && !useExtendedBpb && !useShortFat32 && !useLongFat32 && !useApricotBpb &&
!useDecRainbowBpb)
{
@@ -750,6 +795,7 @@ namespace DiscImageChef.Filesystems
fakeBpb.hsectors = 0;
fakeBpb.spfat = 1;
}
break;
case 0xFD:
if(imagePlugin.Info.Sectors == 4004 && imagePlugin.Info.SectorSize == 128)
@@ -782,6 +828,7 @@ namespace DiscImageChef.Filesystems
fakeBpb.hsectors = 0;
fakeBpb.spfat = 6;
}
break;
case 0xFE:
if(imagePlugin.Info.Sectors == 320 && imagePlugin.Info.SectorSize == 512)
@@ -873,6 +920,7 @@ namespace DiscImageChef.Filesystems
fakeBpb.hsectors = 0;
fakeBpb.spfat = 1;
}
break;
case 0xFF:
if(imagePlugin.Info.Sectors == 640 && imagePlugin.Info.SectorSize == 512)
@@ -890,12 +938,15 @@ namespace DiscImageChef.Filesystems
fakeBpb.hsectors = 0;
fakeBpb.spfat = 1;
}
break;
}
// This assumes a bootable sector will jump somewhere or disable interrupts in x86 code
XmlFsType.Bootable |= bpbSector[0] == 0xFA || (bpbSector[0] == 0xEB && bpbSector[1] <= 0x7F) ||
(bpbSector[0] == 0xE9 && BitConverter.ToUInt16(bpbSector, 1) <= 0x1FC);
XmlFsType.Bootable |= bpbSector[0] == 0xFA ||
bpbSector[0] == 0xEB && bpbSector[1] <= 0x7F ||
bpbSector[0] == 0xE9 &&
BitConverter.ToUInt16(bpbSector, 1) <= 0x1FC;
fakeBpb.boot_code = bpbSector;
}
else if(useShortFat32 || useLongFat32)
@@ -926,7 +977,8 @@ namespace DiscImageChef.Filesystems
if(fat32Bpb.oem_name != null)
if(fat32Bpb.oem_name[5] == 0x49 && fat32Bpb.oem_name[6] == 0x48 && fat32Bpb.oem_name[7] == 0x43)
sb.AppendLine("Volume has been modified by Windows 9x/Me Volume Tracker.");
else XmlFsType.SystemIdentifier = StringHandlers.CToString(fat32Bpb.oem_name);
else
XmlFsType.SystemIdentifier = StringHandlers.CToString(fat32Bpb.oem_name);
if(!string.IsNullOrEmpty(XmlFsType.SystemIdentifier))
sb.AppendFormat("OEM Name: {0}", XmlFsType.SystemIdentifier.Trim()).AppendLine();
@@ -946,6 +998,7 @@ namespace DiscImageChef.Filesystems
fat32Bpb.big_sectors * fat32Bpb.bps).AppendLine();
XmlFsType.Clusters = fat32Bpb.big_sectors / fat32Bpb.spc;
}
sb.AppendFormat("{0} clusters on volume.", XmlFsType.Clusters).AppendLine();
sb.AppendFormat("Media descriptor: 0x{0:X2}", fat32Bpb.media).AppendLine();
sb.AppendFormat("{0} sectors per FAT.", fat32Bpb.big_spfat).AppendLine();
@@ -966,6 +1019,7 @@ namespace DiscImageChef.Filesystems
sb.AppendLine("Volume should be checked on next mount.");
XmlFsType.Dirty = true;
}
if((fat32Bpb.flags & 0x02) == 0x02) sb.AppendLine("Disk surface should be on next mount.");
}
@@ -974,7 +1028,8 @@ namespace DiscImageChef.Filesystems
.AppendLine();
else sb.AppendLine("All copies of FAT are the same.");
if((fat32Bpb.mirror_flags & 0x6F20) == 0x6F20) sb.AppendLine("DR-DOS will boot this FAT32 using CHS.");
if((fat32Bpb.mirror_flags & 0x6F20) == 0x6F20)
sb.AppendLine("DR-DOS will boot this FAT32 using CHS.");
else if((fat32Bpb.mirror_flags & 0x4F20) == 0x4F20)
sb.AppendLine("DR-DOS will boot this FAT32 using LBA.");
@@ -988,8 +1043,13 @@ namespace DiscImageChef.Filesystems
// Check that jumps to a correct boot code position and has boot signature set.
// This will mean that the volume will boot, even if just to say "this is not bootable change disk"......
XmlFsType.Bootable |= ((fat32Bpb.jump[0] == 0xEB && fat32Bpb.jump[1] >= minBootNearJump && fat32Bpb.jump[1] < 0x80) ||
(fat32Bpb.jump[0] == 0xE9 && fat32Bpb.jump.Length >= 3 && BitConverter.ToUInt16(fat32Bpb.jump, 1) >= minBootNearJump && BitConverter.ToUInt16(fat32Bpb.jump, 1) <= 0x1FC));
XmlFsType.Bootable |=
fat32Bpb.jump[0] == 0xEB &&
fat32Bpb.jump[1] >= minBootNearJump && fat32Bpb.jump[1] < 0x80 ||
fat32Bpb.jump[0] == 0xE9 &&
fat32Bpb.jump.Length >= 3 &&
BitConverter.ToUInt16(fat32Bpb.jump, 1) >= minBootNearJump &&
BitConverter.ToUInt16(fat32Bpb.jump, 1) <= 0x1FC;
sectorsPerRealSector = fat32Bpb.bps / imagePlugin.Info.SectorSize;
// First root directory sector
@@ -1021,7 +1081,8 @@ namespace DiscImageChef.Filesystems
}
}
}
else if(useExtendedBpb) fakeBpb = ebpb;
else if(useExtendedBpb)
fakeBpb = ebpb;
else if(userShortExtendedBpb)
{
fakeBpb.jump = shortEbpb.jump;
@@ -1246,8 +1307,10 @@ namespace DiscImageChef.Filesystems
if(isFat12)
{
if(useAtariBpb) sb.AppendLine("Atari FAT12");
else if(useApricotBpb) sb.AppendLine("Apricot FAT12");
else sb.AppendLine("Microsoft FAT12");
else if(useApricotBpb)
sb.AppendLine("Apricot FAT12");
else
sb.AppendLine("Microsoft FAT12");
XmlFsType.Type = "FAT12";
}
else if(isFat16)
@@ -1264,7 +1327,8 @@ namespace DiscImageChef.Filesystems
XmlFsType.VolumeSerial =
$"{atariBpb.serial_no[0]:X2}{atariBpb.serial_no[1]:X2}{atariBpb.serial_no[2]:X2}";
XmlFsType.SystemIdentifier = StringHandlers.CToString(atariBpb.oem_name);
XmlFsType.SystemIdentifier =
StringHandlers.CToString(atariBpb.oem_name);
if(string.IsNullOrEmpty(XmlFsType.SystemIdentifier)) XmlFsType.SystemIdentifier = null;
}
else if(fakeBpb.oem_name != null)
@@ -1304,15 +1368,18 @@ namespace DiscImageChef.Filesystems
if(fakeBpb.sectors == 0)
{
sb.AppendFormat("{0} sectors on volume ({1} bytes).", fakeBpb.big_sectors,
fakeBpb.big_sectors * fakeBpb.bps).AppendLine();
fakeBpb.big_sectors * fakeBpb.bps)
.AppendLine();
XmlFsType.Clusters = fakeBpb.spc == 0 ? fakeBpb.big_sectors : fakeBpb.big_sectors / fakeBpb.spc;
}
else
{
sb.AppendFormat("{0} sectors on volume ({1} bytes).", fakeBpb.sectors,
fakeBpb.sectors * fakeBpb.bps).AppendLine();
fakeBpb.sectors * fakeBpb.bps)
.AppendLine();
XmlFsType.Clusters = fakeBpb.spc == 0 ? fakeBpb.sectors : fakeBpb.sectors / fakeBpb.spc;
}
sb.AppendFormat("{0} sectors per cluster.", fakeBpb.spc).AppendLine();
sb.AppendFormat("{0} clusters on volume.", XmlFsType.Clusters).AppendLine();
XmlFsType.ClusterSize = fakeBpb.bps * fakeBpb.spc;
@@ -1329,6 +1396,7 @@ namespace DiscImageChef.Filesystems
sb.AppendFormat("{0} sectors per track.", fakeBpb.sptrk).AppendLine();
sb.AppendFormat("{0} heads.", fakeBpb.heads).AppendLine();
}
if(fakeBpb.hsectors <= partition.Start)
sb.AppendFormat("{0} hidden sectors before BPB.", fakeBpb.hsectors).AppendLine();
@@ -1346,6 +1414,7 @@ namespace DiscImageChef.Filesystems
sb.AppendLine("Volume should be checked on next mount.");
XmlFsType.Dirty = true;
}
if((fakeBpb.flags & 0x02) == 0x02) sb.AppendLine("Disk surface should be on next mount.");
}
@@ -1366,14 +1435,21 @@ namespace DiscImageChef.Filesystems
// Check that jumps to a correct boot code position and has boot signature set.
// This will mean that the volume will boot, even if just to say "this is not bootable change disk"......
if(XmlFsType.Bootable == false && fakeBpb.jump != null)
XmlFsType.Bootable |= (fakeBpb.jump[0] == 0xEB && fakeBpb.jump[1] >= minBootNearJump && fakeBpb.jump[1] < 0x80) ||
(fakeBpb.jump[0] == 0xE9 && fakeBpb.jump.Length >= 3 && BitConverter.ToUInt16(fakeBpb.jump, 1) >= minBootNearJump && BitConverter.ToUInt16(fakeBpb.jump, 1) <= 0x1FC);
XmlFsType.Bootable |=
fakeBpb.jump[0] == 0xEB &&
fakeBpb.jump[1] >= minBootNearJump && fakeBpb.jump[1] < 0x80 ||
fakeBpb.jump[0] == 0xE9 &&
fakeBpb.jump.Length >= 3 &&
BitConverter.ToUInt16(fakeBpb.jump, 1) >= minBootNearJump &&
BitConverter.ToUInt16(fakeBpb.jump, 1) <= 0x1FC;
sectorsPerRealSector = fakeBpb.bps / imagePlugin.Info.SectorSize;
// First root directory sector
rootDirectorySector =
(ulong)(fakeBpb.spfat * fakeBpb.fats_no + fakeBpb.rsectors) * sectorsPerRealSector;
sectorsForRootDirectory = (uint)(fakeBpb.root_ent * 32 / imagePlugin.Info.SectorSize);
(ulong)(fakeBpb.spfat * fakeBpb.fats_no + fakeBpb.rsectors) *
sectorsPerRealSector;
sectorsForRootDirectory =
(uint)(fakeBpb.root_ent * 32 / imagePlugin.Info.SectorSize);
}
if(extraInfo != null) sb.Append(extraInfo);
@@ -1460,18 +1536,19 @@ namespace DiscImageChef.Filesystems
{
int sigSize = bpbSector[510] == 0x55 && bpbSector[511] == 0xAA ? 2 : 0;
byte[] bootCode = new byte[512 - sigSize - BitConverter.ToUInt16(bpbSector, 1) - 3];
Array.Copy(bpbSector, BitConverter.ToUInt16(bpbSector, 1) + 3, bootCode, 0, bootCode.Length);
Array.Copy(bpbSector, BitConverter.ToUInt16(bpbSector, 1) + 3, bootCode, 0,
bootCode.Length);
sha1Ctx = new Sha1Context();
sha1Ctx.Init();
sha1Ctx.Update(bootCode);
bootChk = sha1Ctx.End();
}
sb.AppendLine("Volume is bootable");
sb.AppendFormat("Boot code's SHA1: {0}", bootChk).AppendLine();
string bootName = knownBootHashes.FirstOrDefault(t => t.hash == bootChk).name;
if(string.IsNullOrWhiteSpace(bootName)) sb.AppendLine("Unknown boot code.");
else
sb.AppendFormat("Boot code corresponds to {0}", bootName).AppendLine();
else sb.AppendFormat("Boot code corresponds to {0}", bootName).AppendLine();
}
information = sb.ToString();
@@ -1484,11 +1561,14 @@ namespace DiscImageChef.Filesystems
struct AtariParameterBlock
{
/// <summary>68000 BRA.S jump or x86 loop</summary>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)] public byte[] jump;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)]
public byte[] jump;
/// <summary>OEM Name, 6 bytes, space-padded, "Loader" for Atari ST boot loader</summary>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 6)] public byte[] oem_name;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 6)]
public byte[] oem_name;
/// <summary>Volume serial number</summary>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] public byte[] serial_no;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
public byte[] serial_no;
/// <summary>Bytes per sector</summary>
public ushort bps;
/// <summary>Sectors per cluster</summary>
@@ -1531,11 +1611,13 @@ namespace DiscImageChef.Filesystems
/// <summary>Unknown.</summary>
public ushort unknown;
/// <summary>Filename to be loaded for booting.</summary>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 11)] public byte[] fname;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 11)]
public byte[] fname;
/// <summary>Reserved</summary>
public ushort reserved;
/// <summary>Boot code.</summary>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 455)] public byte[] boot_code;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 455)]
public byte[] boot_code;
/// <summary>Big endian word to make big endian sum of all sector words be equal to 0x1234 if disk is bootable.</summary>
public ushort checksum;
}
@@ -1547,9 +1629,11 @@ namespace DiscImageChef.Filesystems
struct MsxParameterBlock
{
/// <summary>x86 loop</summary>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] public byte[] jump;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
public byte[] jump;
/// <summary>OEM Name, 8 bytes, space-padded</summary>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)] public byte[] oem_name;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
public byte[] oem_name;
/// <summary>Bytes per sector</summary>
public ushort bps;
/// <summary>Sectors per cluster</summary>
@@ -1575,17 +1659,20 @@ namespace DiscImageChef.Filesystems
/// <summary>Jump for MSX-DOS 1 boot code</summary>
public ushort msxdos_jmp;
/// <summary>Set to "VOL_ID" by MSX-DOS 2</summary>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 11)] public byte[] vol_id;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 11)]
public byte[] vol_id;
/// <summary>Bigger than 0 if there are deleted files (MSX-DOS 2)</summary>
public byte undelete_flag;
/// <summary>Volume serial number (MSX-DOS 2)</summary>
public uint serial_no;
/// <summary>Reserved (MSX-DOS 2)</summary>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 5)] public byte[] reserved;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 5)]
public byte[] reserved;
/// <summary>Jump for MSX-DOS 2 boot code (MSX-DOS 2)</summary>
public ushort msxdos2_jmp;
/// <summary>Boot code.</summary>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 460)] public byte[] boot_code;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 460)]
public byte[] boot_code;
/// <summary>Always 0x55 0xAA.</summary>
public ushort boot_signature;
}
@@ -1595,9 +1682,11 @@ namespace DiscImageChef.Filesystems
struct BiosParameterBlock2
{
/// <summary>x86 jump</summary>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] public byte[] jump;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
public byte[] jump;
/// <summary>OEM Name, 8 bytes, space-padded</summary>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)] public byte[] oem_name;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
public byte[] oem_name;
/// <summary>Bytes per sector</summary>
public ushort bps;
/// <summary>Sectors per cluster</summary>
@@ -1615,7 +1704,8 @@ namespace DiscImageChef.Filesystems
/// <summary>Sectors per FAT</summary>
public ushort spfat;
/// <summary>Boot code.</summary>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 486)] public byte[] boot_code;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 486)]
public byte[] boot_code;
/// <summary>0x55 0xAA if bootable.</summary>
public ushort boot_signature;
}
@@ -1625,9 +1715,11 @@ namespace DiscImageChef.Filesystems
struct BiosParameterBlock30
{
/// <summary>x86 jump</summary>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] public byte[] jump;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
public byte[] jump;
/// <summary>OEM Name, 8 bytes, space-padded</summary>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)] public byte[] oem_name;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
public byte[] oem_name;
/// <summary>Bytes per sector</summary>
public ushort bps;
/// <summary>Sectors per cluster</summary>
@@ -1651,7 +1743,8 @@ namespace DiscImageChef.Filesystems
/// <summary>Hidden sectors before BPB</summary>
public ushort hsectors;
/// <summary>Boot code.</summary>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 480)] public byte[] boot_code;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 480)]
public byte[] boot_code;
/// <summary>Always 0x55 0xAA.</summary>
public ushort boot_signature;
}
@@ -1661,9 +1754,11 @@ namespace DiscImageChef.Filesystems
struct BiosParameterBlock32
{
/// <summary>x86 jump</summary>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] public byte[] jump;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
public byte[] jump;
/// <summary>OEM Name, 8 bytes, space-padded</summary>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)] public byte[] oem_name;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
public byte[] oem_name;
/// <summary>Bytes per sector</summary>
public ushort bps;
/// <summary>Sectors per cluster</summary>
@@ -1689,7 +1784,8 @@ namespace DiscImageChef.Filesystems
/// <summary>Total sectors including hidden ones</summary>
public ushort total_sectors;
/// <summary>Boot code.</summary>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 478)] public byte[] boot_code;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 478)]
public byte[] boot_code;
/// <summary>Always 0x55 0xAA.</summary>
public ushort boot_signature;
}
@@ -1699,9 +1795,11 @@ namespace DiscImageChef.Filesystems
struct BiosParameterBlock33
{
/// <summary>x86 jump</summary>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] public byte[] jump;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
public byte[] jump;
/// <summary>OEM Name, 8 bytes, space-padded</summary>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)] public byte[] oem_name;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
public byte[] oem_name;
/// <summary>Bytes per sector</summary>
public ushort bps;
/// <summary>Sectors per cluster</summary>
@@ -1727,7 +1825,8 @@ namespace DiscImageChef.Filesystems
/// <summary>Sectors in volume if > 65535</summary>
public uint big_sectors;
/// <summary>Boot code.</summary>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 474)] public byte[] boot_code;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 474)]
public byte[] boot_code;
/// <summary>Always 0x55 0xAA.</summary>
public ushort boot_signature;
}
@@ -1737,9 +1836,11 @@ namespace DiscImageChef.Filesystems
struct BiosParameterBlockShortEbpb
{
/// <summary>x86 jump</summary>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] public byte[] jump;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
public byte[] jump;
/// <summary>OEM Name, 8 bytes, space-padded</summary>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)] public byte[] oem_name;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
public byte[] oem_name;
/// <summary>Bytes per sector</summary>
public ushort bps;
/// <summary>Sectors per cluster</summary>
@@ -1773,7 +1874,8 @@ namespace DiscImageChef.Filesystems
/// <summary>Volume serial number</summary>
public uint serial_no;
/// <summary>Boot code.</summary>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 467)] public byte[] boot_code;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 467)]
public byte[] boot_code;
/// <summary>Always 0x55 0xAA.</summary>
public ushort boot_signature;
}
@@ -1783,9 +1885,11 @@ namespace DiscImageChef.Filesystems
struct BiosParameterBlockEbpb
{
/// <summary>x86 jump</summary>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] public byte[] jump;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
public byte[] jump;
/// <summary>OEM Name, 8 bytes, space-padded</summary>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)] public byte[] oem_name;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
public byte[] oem_name;
/// <summary>Bytes per sector</summary>
public ushort bps;
/// <summary>Sectors per cluster</summary>
@@ -1819,11 +1923,14 @@ namespace DiscImageChef.Filesystems
/// <summary>Volume serial number</summary>
public uint serial_no;
/// <summary>Volume label, 11 bytes, space-padded</summary>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 11)] public byte[] volume_label;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 11)]
public byte[] volume_label;
/// <summary>Filesystem type, 8 bytes, space-padded</summary>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)] public byte[] fs_type;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
public byte[] fs_type;
/// <summary>Boot code.</summary>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 448)] public byte[] boot_code;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 448)]
public byte[] boot_code;
/// <summary>Always 0x55 0xAA.</summary>
public ushort boot_signature;
}
@@ -1833,9 +1940,11 @@ namespace DiscImageChef.Filesystems
struct Fat32ParameterBlockShort
{
/// <summary>x86 jump</summary>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] public byte[] jump;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
public byte[] jump;
/// <summary>OEM Name, 8 bytes, space-padded</summary>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)] public byte[] oem_name;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
public byte[] oem_name;
/// <summary>Bytes per sector</summary>
public ushort bps;
/// <summary>Sectors per cluster</summary>
@@ -1873,7 +1982,8 @@ namespace DiscImageChef.Filesystems
/// <summary>Sector of FAT32PB backup</summary>
public ushort backup_sector;
/// <summary>Reserved</summary>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 12)] public byte[] reserved;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 12)]
public byte[] reserved;
/// <summary>Drive number</summary>
public byte drive_no;
/// <summary>Volume flags</summary>
@@ -1883,11 +1993,13 @@ namespace DiscImageChef.Filesystems
/// <summary>Volume serial number</summary>
public uint serial_no;
/// <summary>Volume label, 11 bytes, space-padded</summary>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 11)] public byte[] reserved2;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 11)]
public byte[] reserved2;
/// <summary>Sectors in volume if <see cref="big_sectors" /> equals 0</summary>
public ulong huge_sectors;
/// <summary>Boot code.</summary>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 420)] public byte[] boot_code;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 420)]
public byte[] boot_code;
/// <summary>Always 0x55 0xAA.</summary>
public ushort boot_signature;
}
@@ -1897,9 +2009,11 @@ namespace DiscImageChef.Filesystems
struct Fat32ParameterBlock
{
/// <summary>x86 jump</summary>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] public byte[] jump;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
public byte[] jump;
/// <summary>OEM Name, 8 bytes, space-padded</summary>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)] public byte[] oem_name;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
public byte[] oem_name;
/// <summary>Bytes per sector</summary>
public ushort bps;
/// <summary>Sectors per cluster</summary>
@@ -1937,7 +2051,8 @@ namespace DiscImageChef.Filesystems
/// <summary>Sector of FAT32PB backup</summary>
public ushort backup_sector;
/// <summary>Reserved</summary>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 12)] public byte[] reserved;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 12)]
public byte[] reserved;
/// <summary>Drive number</summary>
public byte drive_no;
/// <summary>Volume flags</summary>
@@ -1947,11 +2062,14 @@ namespace DiscImageChef.Filesystems
/// <summary>Volume serial number</summary>
public uint serial_no;
/// <summary>Volume label, 11 bytes, space-padded</summary>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 11)] public byte[] volume_label;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 11)]
public byte[] volume_label;
/// <summary>Filesystem type, 8 bytes, space-padded, must be "FAT32 "</summary>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)] public byte[] fs_type;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
public byte[] fs_type;
/// <summary>Boot code.</summary>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 419)] public byte[] boot_code;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 419)]
public byte[] boot_code;
/// <summary>Always 0x55 0xAA.</summary>
public ushort boot_signature;
}
@@ -1961,7 +2079,8 @@ namespace DiscImageChef.Filesystems
struct ApricotLabel
{
/// <summary>Version of format which created disk</summary>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)] public byte[] version;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
public byte[] version;
/// <summary>Operating system.</summary>
public byte operatingSystem;
/// <summary>Software write protection.</summary>
@@ -2005,17 +2124,22 @@ namespace DiscImageChef.Filesystems
/// <summary>Maximum number of copies.</summary>
public ushort maxCopies;
/// <summary>Serial number.</summary>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)] public byte[] serialNumber;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
public byte[] serialNumber;
/// <summary>Part number.</summary>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)] public byte[] partNumber;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
public byte[] partNumber;
/// <summary>Copyright.</summary>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 14)] public byte[] copyright;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 14)]
public byte[] copyright;
/// <summary>BPB for whole disk.</summary>
public ApricotParameterBlock mainBPB;
/// <summary>Name of FONT file.</summary>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)] public byte[] fontName;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]
public byte[] fontName;
/// <summary>Name of KEYBOARD file.</summary>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)] public byte[] keyboardName;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]
public byte[] keyboardName;
/// <summary>Minor BIOS version.</summary>
public byte biosMinorVersion;
/// <summary>Major BIOS version.</summary>
@@ -2053,7 +2177,8 @@ namespace DiscImageChef.Filesystems
/// <summary>Microscreen mode.</summary>
public byte microscreenMode;
/// <summary>Spare area for keyboard values expansion.</summary>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 11)] public byte[] spareKeyboard;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 11)]
public byte[] spareKeyboard;
/// <summary>Screen line mode.</summary>
public byte lineMode;
/// <summary>Screen line width.</summary>
@@ -2061,7 +2186,8 @@ namespace DiscImageChef.Filesystems
/// <summary>Screen disabled?.</summary>
[MarshalAs(UnmanagedType.U1)] public bool imageOff;
/// <summary>Spare area for screen values expansion.</summary>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 13)] public byte[] spareScreen;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 13)]
public byte[] spareScreen;
/// <summary>TX baud rate.</summary>
public byte txBaudRate;
/// <summary>RX baud rate.</summary>
@@ -2099,7 +2225,8 @@ namespace DiscImageChef.Filesystems
/// <summary>BIOS error report in serial port.</summary>
[MarshalAs(UnmanagedType.U1)] public bool biosErrorReportSerial;
/// <summary>Spare area for serial port values expansion.</summary>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 13)] public byte[] spareSerial;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 13)]
public byte[] spareSerial;
/// <summary>Send LF after CR in parallel port.</summary>
[MarshalAs(UnmanagedType.U1)] public bool lfAfterCrParallel;
/// <summary>Select line supported?.</summary>
@@ -2111,21 +2238,27 @@ namespace DiscImageChef.Filesystems
/// <summary>BIOS error report in parallel port.</summary>
[MarshalAs(UnmanagedType.U1)] public bool biosErrorReportParallel;
/// <summary>Spare area for parallel port values expansion.</summary>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 11)] public byte[] spareParallel;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 11)]
public byte[] spareParallel;
/// <summary>Spare area for Winchester values expansion.</summary>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 14)] public byte[] spareWinchester;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 14)]
public byte[] spareWinchester;
/// <summary>Parking enabled?.</summary>
[MarshalAs(UnmanagedType.U1)] public bool parkingEnabled;
/// <summary>Format protection?.</summary>
[MarshalAs(UnmanagedType.U1)] public bool formatProtection;
/// <summary>Spare area for RAM disk values expansion.</summary>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)] public byte[] spareRamDisk;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]
public byte[] spareRamDisk;
/// <summary>List of bad blocks.</summary>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 32)] public ushort[] badBlocks;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 32)]
public ushort[] badBlocks;
/// <summary>Array of partition BPBs.</summary>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)] public ApricotParameterBlock[] partitions;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
public ApricotParameterBlock[] partitions;
/// <summary>Spare area.</summary>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 63)] public byte[] spare;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 63)]
public byte[] spare;
/// <summary>CP/M double side indicator?.</summary>
public bool cpmDoubleSided;
}
@@ -2162,7 +2295,8 @@ namespace DiscImageChef.Filesystems
/// <summary>Signature must be <see cref="FAT.FSINFO_SIGNATURE1" /></summary>
public uint signature1;
/// <summary>Reserved</summary>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 480)] public byte[] reserved1;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 480)]
public byte[] reserved1;
/// <summary>Signature must be <see cref="FAT.FSINFO_SIGNATURE2" /></summary>
public uint signature2;
/// <summary>Free clusters</summary>
@@ -2170,7 +2304,8 @@ namespace DiscImageChef.Filesystems
/// <summary> cated cluster</summary>
public uint last_cluster;
/// <summary>Reserved</summary>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 12)] public byte[] reserved2;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 12)]
public byte[] reserved2;
/// <summary>Signature must be <see cref="FAT.FSINFO_SIGNATURE3" /></summary>
public uint signature3;
}
@@ -2192,8 +2327,10 @@ namespace DiscImageChef.Filesystems
[StructLayout(LayoutKind.Sequential, Pack = 1)]
struct DirectoryEntry
{
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)] public byte[] filename;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] public byte[] extension;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
public byte[] filename;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
public byte[] extension;
public FatAttributes attributes;
public byte caseinfo;
public byte ctime_ms;