public new static Fat32BiosParameterBlock?ContinueParsing(BiosParameterBlock bpb, BinaryReader reader) { var fat32bpb = new Fat32BiosParameterBlock(bpb); fat32bpb.ReadFat32BpbFields(reader); return(fat32bpb.ReadEbpbFields(reader) ? fat32bpb : null); }
/// <summary> /// Parse a BIOS Parameter Block from a stream /// </summary> /// <param name="reader">A binary reader around the stream</param> /// <param name="offset">The offset in the stream of the BPB</param> /// <returns>A BIOS Parameter block</returns> public static BiosParameterBlock Parse(BinaryReader reader, long offset) { reader.BaseStream.Seek(offset, SeekOrigin.Begin); //BPB offset var bpb = new BiosParameterBlock { BytesPerLogicalSector = reader.ReadUInt16(), LogicalSectorsPerCluster = reader.ReadByte(), ReservedLogicalSectors = reader.ReadUInt16(), NumberOfFATs = reader.ReadByte(), RootDirectoryEntries = reader.ReadUInt16(), TotalLogicalSectors = reader.ReadUInt16(), MediaDescriptor = reader.ReadByte(), LogicalSectorsPerFAT = reader.ReadUInt16() }; //Parsing a standard BPB if (offset == 0x0B) { bpb.PhysicalSectorsPerTrack = reader.ReadUInt16(); bpb.NumberOfHeads = reader.ReadUInt16(); if (bpb.TotalLogicalSectors != 0) { bpb.HiddenSectors = reader.ReadUInt16(); reader.BaseStream.Seek(6, SeekOrigin.Current); } else { bpb.HiddenSectors = reader.ReadUInt32(); bpb.TotalLogicalSectors = reader.ReadUInt32(); } } //Parsing an Apricot BPB, which doesn't have the number of heads and SPT, so we have to make some manual adjustments else if (offset == 0x50) { if (bpb.MediaDescriptor == 0xFC) //315k { bpb.NumberOfHeads = 1; bpb.PhysicalSectorsPerTrack = 70; } else if (bpb.MediaDescriptor == 0xFE) //720k { bpb.NumberOfHeads = 2; bpb.PhysicalSectorsPerTrack = 80; } } if (!bpb.Validate()) { throw new InvalidDataException("At least one of BPB parameters is 0"); } uint tracks = (uint)(bpb.TotalLogicalSectors / bpb.NumberOfHeads / bpb.PhysicalSectorsPerTrack); // TODO: This probably needs reviewing to better check BPB params match the correct size if (tracks == 0) { throw new InvalidDataException("BPB paramaters don't match image size"); } // Parsing a standard BPB, read boot sector if (offset == 0x0B) { long endOffset = reader.BaseStream.Position; reader.BaseStream.Seek(0, SeekOrigin.Begin); bpb.BootJump = reader.ReadBytes(3); bpb.OemId = new string(reader.ReadChars(8)).TrimEnd(' ').ToUpper(); reader.BaseStream.Seek(endOffset, SeekOrigin.Begin); } if (bpb.LogicalSectorsPerFAT == 0) { // This could be a FAT32 BPB. return(Fat32BiosParameterBlock.ContinueParsing(bpb, reader) ?? throw new InvalidDataException("FAT size is 0")); } else { //So far, the BPB seems to be OK, so try to read it further as a DOS 4.0 BPB. return(ExtendedBiosParameterBlock.ContinueParsing(bpb, reader) ?? bpb); } }