forked from AbleOS/ableos
165 lines
4 KiB
Plaintext
165 lines
4 KiB
Plaintext
|
stn := @use("../../../libraries/stn/src/lib.hb");
|
||
|
.{string, memory, buffer, log} := stn
|
||
|
|
||
|
VALID_JUMP_BYTES := [u8].(0xEB, 0x3C, 0x90)
|
||
|
|
||
|
OemIdent := struct {
|
||
|
dos_version: [u8; 8],
|
||
|
dos_version_name: [u8; 8],
|
||
|
}
|
||
|
|
||
|
new_oem_ident := fn(major: int, minor: int): OemIdent {
|
||
|
ver := [u8].(0, 0, 0, 0, 0, 0, 0, 0)
|
||
|
return OemIdent.(ver, ver)
|
||
|
}
|
||
|
|
||
|
BiosParameterBlock := struct {
|
||
|
jump_bytes: [u8; 3],
|
||
|
oem_ident: OemIdent,
|
||
|
bytes_per_sector: u16,
|
||
|
sectors_per_cluster: u8,
|
||
|
reserved_sectors: u16,
|
||
|
// The amount of FileAllocationTables on the disk. Often 2.
|
||
|
fat_count: u8,
|
||
|
root_directory_count: u16,
|
||
|
// if 0 then refer to large_sector_count
|
||
|
total_sectors: u16,
|
||
|
media_type: u8,
|
||
|
// if 0 refer to sectors_per_fat in the ExtendedBootRecord
|
||
|
sectors_per_fat: u16,
|
||
|
sectors_per_track: u16,
|
||
|
head_count: u16,
|
||
|
hidden_sectors: u32,
|
||
|
large_sector_count: u32,
|
||
|
}
|
||
|
|
||
|
bpb_sanity_check := fn(bpb: BiosParameterBlock): int {
|
||
|
return 0
|
||
|
}
|
||
|
|
||
|
new_bpb := fn(): BiosParameterBlock {
|
||
|
oem := new_oem_ident(0, 0)
|
||
|
|
||
|
return BiosParameterBlock.(VALID_JUMP_BYTES, oem, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
|
||
|
}
|
||
|
|
||
|
sector_count := fn(bpb: BiosParameterBlock): u32 {
|
||
|
if bpb.total_sectors == 0 {
|
||
|
return bpb.large_sector_count
|
||
|
} else {
|
||
|
return bpb.total_sectors
|
||
|
}
|
||
|
}
|
||
|
|
||
|
FatVersionNumber := struct {
|
||
|
major_version: u8,
|
||
|
minor_version: u8,
|
||
|
}
|
||
|
|
||
|
FormatReservation := [u8; 12]
|
||
|
|
||
|
// Padded with spaces.
|
||
|
VolumeName := [u8; 11]
|
||
|
|
||
|
SystemIdentifierString := [u8; 8]
|
||
|
VALID_SYSTEM_IDENTIFIER_STRING := [u8].(46, 41, 54, 33, 32, 20, 20, 20)
|
||
|
BOOTABLE_PARTITION_SIGNATURE := 0xAA55
|
||
|
|
||
|
BootCode := [u8; 420]
|
||
|
|
||
|
ExtendedBootRecord := struct {
|
||
|
sectors_per_fat: u32,
|
||
|
flags: u16,
|
||
|
fat_version_number: FatVersionNumber,
|
||
|
// Typically set to 2.
|
||
|
root_directory_cluster_number: u32,
|
||
|
fsinfo_structure: u16,
|
||
|
backup_boot_sector: u16,
|
||
|
// When a volume is formated these bytes should be zero. As a sanity check I guess?
|
||
|
format_reserved: FormatReservation,
|
||
|
// 0x00 floppy or 0x80 hard disk
|
||
|
drive_number: u8,
|
||
|
nt_reserved: u8,
|
||
|
// must be 0x28 or 0x29
|
||
|
signature: u8,
|
||
|
volume_id_serial: u32,
|
||
|
volume_id_name: VolumeName,
|
||
|
// The spec says this is always FAT32. Untrustworthy and another sanity check I guess.
|
||
|
system_identifier_string: SystemIdentifierString,
|
||
|
boot_code: BootCode,
|
||
|
partition_signature: u16,
|
||
|
}
|
||
|
|
||
|
ebr_sanity_check := fn(ebr: ExtendedBootRecord): int {
|
||
|
ret := 0
|
||
|
if ebr.drive_number != 0x0 | ebr.drive_number != 0x80 {
|
||
|
log.warn("EBR-Drive-Number sanity check failed\0")
|
||
|
}
|
||
|
|
||
|
if ebr.signature != 0x28 | ebr.signature != 0x29 {
|
||
|
log.warn("EBR-Signature sanity check failed\0")
|
||
|
}
|
||
|
|
||
|
if ebr.system_identifier_string != VALID_SYSTEM_IDENTIFIER_STRING {
|
||
|
log.warn("EBR-Signature-Identifier-String sanity check failed\0")
|
||
|
}
|
||
|
return 0
|
||
|
}
|
||
|
|
||
|
new_ebr := fn(): ExtendedBootRecord {
|
||
|
version := FatVersionNumber.(0, 0)
|
||
|
fmt_res := FormatReservation.(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
|
||
|
vol_name := @as([u8; 11], idk)
|
||
|
boot_code := @as([u8; 420], idk)
|
||
|
|
||
|
return ExtendedBootRecord.(
|
||
|
0,
|
||
|
0,
|
||
|
version,
|
||
|
0,
|
||
|
0,
|
||
|
0,
|
||
|
fmt_res,
|
||
|
0,
|
||
|
0,
|
||
|
0,
|
||
|
0,
|
||
|
vol_name,
|
||
|
VALID_SYSTEM_IDENTIFIER_STRING,
|
||
|
boot_code,
|
||
|
0,
|
||
|
)
|
||
|
}
|
||
|
|
||
|
VALID_LEAD_FS_INFO := 0x41615252
|
||
|
VALID_TRAIL_FS_INFO := 0xAA550000
|
||
|
|
||
|
FSInfo := struct {
|
||
|
// Must be 0x41615252 to indicate a valid FSInfo structure
|
||
|
lead_signature: u32,
|
||
|
lead_reserved: [u8; 480],
|
||
|
// If the value is 0xFFFFFFFF, then the free count is unknown and must be computed. However, this value might be incorrect and should at least be range checked (<= volume cluster count)
|
||
|
last_known_free_cluster_count: u32,
|
||
|
last_known_avalible_cluster: u32,
|
||
|
trail_reserved: [u8; 12],
|
||
|
trail_signature: u32,
|
||
|
}
|
||
|
|
||
|
fs_info_sanity_check := fn(fs_info: FSInfo): int {
|
||
|
ret := 0
|
||
|
if fs_info.last_known_free_cluster_count == 0xFFFFFFFF {
|
||
|
ret &= 1
|
||
|
log.warn("Last known free cluster count unknown\0")
|
||
|
}
|
||
|
if fs_info.last_known_avalible_cluster == 0xFFFFFFFF {
|
||
|
ret &= 2
|
||
|
log.warn("Last known avalible cluster count unknown\0")
|
||
|
}
|
||
|
return ret
|
||
|
}
|
||
|
|
||
|
new_fs_info := fn(): FSInfo {
|
||
|
lead_reserved := @as([u8; 480], idk)
|
||
|
trail_reserved := @as([u8; 12], idk)
|
||
|
return FSInfo.(0, lead_reserved, 0, 0, trail_reserved, 0)
|
||
|
}
|