1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-27 12:27:35 +00:00

Kernel/FileSystem/FATFS: Support for FAT12/16 DOS BIOS Parameter Blocks

This commit is contained in:
Taj Morton 2023-07-08 22:10:10 -07:00 committed by Andrew Kaster
parent 02edd240ae
commit 67f567348f
4 changed files with 332 additions and 44 deletions

View file

@ -9,27 +9,60 @@
#include <AK/DOSPackedTime.h>
#include <AK/EnumBits.h>
#include <AK/Types.h>
#include <Kernel/Library/KBuffer.h>
namespace Kernel {
struct [[gnu::packed]] FAT32BootRecord {
// This structure represents the DOS 3.31 BIOS Partition Block.
// While DOS 3.31 predates FAT verions 12/16/32 (the versions supported by this driver),
// the fields in this block are common with the DOS 4 and DOS 7 BIOS Parameter blocks.
// This structure will be followed by an "Extended BIOS Partition Block" (EBPB).
//
// The DOS 4 EBPB is *typically* used by FAT 12/16 file systems, while the DOS 7 EBPB
// is *typically* used by FAT 32. _However_, any combination is possible, as the FAT
// version is only determined by the number of clusters.
//
// Note that the DOS 4 and DOS 7 EBPB extensions are incompatible with each other
// (contain fields in different orders and of different lenghts) and do not contain
// an explicit indication to differentiate them.
// This driver uses heuristics to identify the EBPB version (based on the signature bytes
// and sector counts).
// FIXME: Consider also using the MBR parition type field in the future.
struct [[gnu::packed]] DOS3BIOSParameterBlock {
u8 boot_jump[3];
char oem_identifier[8];
u16 bytes_per_sector;
u16 bytes_per_sector; // Offset 0x0B -- beginning of DOS 3.31 BPB.
u8 sectors_per_cluster;
u16 reserved_sector_count;
u8 fat_count;
u16 root_directory_entry_count;
u16 unused1;
u16 sector_count_16bit;
u8 media_descriptor_type;
u16 unused2;
u16 sectors_per_fat_16bit;
u16 sectors_per_track;
u16 head_count;
u32 hidden_sector_count;
u32 sector_count;
u32 sectors_per_fat;
u32 sector_count_32bit; // 0x020 -- end of DOS 3.31 BPB.
};
// 11 is the boot jump/OEM identifier prefix prior to the official BPB.
static_assert(sizeof(DOS3BIOSParameterBlock) == 11 + 25);
struct [[gnu::packed]] DOS4BIOSParameterBlock {
// Begins at sector offset 0x024.
u8 drive_number; // 0x024
u8 flags;
u8 signature;
u32 volume_id;
char volume_label_string[11];
char file_system_type[8];
};
static_assert(sizeof(DOS4BIOSParameterBlock) == 26);
struct [[gnu::packed]] DOS7BIOSParameterBlock {
// Begins at sector offset 0x024.
u32 sectors_per_fat_32bit; // 0x024
u16 flags;
u16 fat_version;
u16 fat_version; // Expected value 0x2b2a.
u32 root_directory_cluster;
u16 fs_info_sector;
u16 backup_boot_sector;
@ -39,9 +72,22 @@ struct [[gnu::packed]] FAT32BootRecord {
u8 signature;
u32 volume_id;
char volume_label_string[11];
char system_identifier_string[8];
char file_system_type[8];
};
static_assert(sizeof(DOS7BIOSParameterBlock) == 54);
enum DOSBIOSParameterBlockVersion {
DOS_BPB_UNKNOWN,
DOS_BPB_3, // Version 3.4.
DOS_BPB_4, // Version 4.0
DOS_BPB_7 // Version 7.0
};
enum class FATVersion {
FAT12,
FAT16,
FAT32,
};
static_assert(sizeof(FAT32BootRecord) == 90);
enum class FATAttributes : u8 {
ReadOnly = 0x01,