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 := @as(u32, 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") } // ! comparison between [u8] is not supported in hblang // 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 := @as(u32, 0x41615252) VALID_TRAIL_FS_INFO := @as(u32, 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): uint { ret := 0 if fs_info.lead_signature != VALID_LEAD_FS_INFO { ret &= 1 log.warn("Invalid leading signature in FSInfo.\0") } if fs_info.last_known_free_cluster_count == 0xFFFFFFFF { ret &= 2 log.warn("Last known free cluster count unknown.\0") } if fs_info.last_known_avalible_cluster == 0xFFFFFFFF { ret &= 4 log.warn("Last known avalible cluster count unknown.\0") } if fs_info.trail_signature != VALID_TRAIL_FS_INFO { ret &= 8 log.warn("Invalid trailing signature in FSInfo.\0") } return ret } new_fs_info := fn(): FSInfo { lead_reserved := @as([u8; 480], idk) trail_reserved := @as([u8; 12], idk) return FSInfo.( VALID_LEAD_FS_INFO, lead_reserved, 0, 0, trail_reserved, VALID_TRAIL_FS_INFO, ) }