13 Commits

Author SHA1 Message Date
4a944bc493 minor changes in fat32 2025-09-20 08:29:43 -04:00
137735431a move stack after bss padding 2025-09-18 19:16:27 -04:00
6caaf6aa6d some structures for okteta
put in $(qtpaths --paths GenericDataLocation)
2025-09-18 17:20:17 -04:00
1e9de446f0 a few fixes to complete the move 2025-09-18 14:25:27 -04:00
5f2ca55af7 move mbr/vbr code to FAT32 system 2025-09-18 14:19:39 -04:00
11656c2827 more error codes and checks in vbr 2025-09-18 14:07:45 -04:00
f87f88a0dc fix qemu launch 2025-09-18 14:06:52 -04:00
7baa53178a update gitignore 2025-09-18 14:06:32 -04:00
8002d1cb54 more fat fs type checks 2025-09-18 11:50:27 -04:00
d8a89cfd2b remove shortjmp and ident from bpb 2025-09-18 11:20:05 -04:00
6c402b5c4f update structures 2025-09-17 21:48:37 -04:00
a3c9897291 prototyping 2025-09-17 20:59:48 -04:00
831d45c33c rename ext_disk_read to BIOS_int13h_ext_read 2025-09-17 18:54:59 -04:00
13 changed files with 339 additions and 186 deletions

1
.gitignore vendored
View File

@@ -11,3 +11,4 @@ stevia-log
compose-dev.yaml compose-dev.yaml
eth_null-tx.log eth_null-tx.log
eth_null-txdump.txt eth_null-txdump.txt
*.log

View File

@@ -38,9 +38,6 @@ QEMU_ARGS := \
-device e1000,netdev=n0,mac=52:54:00:12:34:56 \ -device e1000,netdev=n0,mac=52:54:00:12:34:56 \
-netdev user,id=n0 \ -netdev user,id=n0 \
-device piix3-usb-uhci \ -device piix3-usb-uhci \
-device usb-ohci,id=ohci0 \
-device usb-ehci,id=ehci0 \
-device pcspk \
-parallel null \ -parallel null \
-serial null -serial none -serial none -serial none \ -serial null -serial none -serial none -serial none \
-chardev file,id=dbg,path=bochs-e9.log,append=on \ -chardev file,id=dbg,path=bochs-e9.log,append=on \

View File

@@ -0,0 +1,24 @@
<?xml version="1.0" encoding="UTF-8"?>
<data>
<struct name="MBR">
<!-- 446 bytes: bootstrap code -->
<array name="bootCode" length="446">
<primitive type="UInt8"/>
</array>
<!-- 4 x 16-byte partition entries -->
<array name="partitions" length="4">
<struct name="PartitionEntry">
<primitive name="status" type="UInt8"/> <!-- 0x80=bootable -->
<array name="chsFirst" length="3"><primitive type="UInt8"/></array>
<primitive name="type" type="UInt8"/>
<array name="chsLast" length="3"><primitive type="UInt8"/></array>
<primitive name="lbaStart" type="UInt32"/>
<primitive name="lbaSectors" type="UInt32"/>
</struct>
</array>
<!-- Signature 0x55AA (little-endian UInt16 == 0xAA55 on disk) -->
<primitive name="signature" type="UInt16"/>
</struct>
</data>

View File

@@ -0,0 +1,12 @@
[Desktop Entry]
Icon=application-x-executable
Type=Service
ServiceTypes=KPluginInfo
Name=Stevia MBR Structure
X-KDE-PluginInfo-Author=Elaina Claus
X-KDE-PluginInfo-Name=mbr
X-KDE-PluginInfo-Version=1.0
X-KDE-PluginInfo-Website=https://chtm.me
X-KDE-PluginInfo-Category=structure
X-KDE-PluginInfo-License=MIT
X-KDE-PluginInfo-EnabledByDefault=false

View File

@@ -0,0 +1,57 @@
<?xml version="1.0" encoding="UTF-8"?>
<data>
<struct name="VBR">
<!-- 3 bytes: jmp over bpb code -->
<array name="jmpcode" length="3">
<primitive name="opcode" type="UInt8"/>
</array>
<array name="bs_ident" length="8">
<primitive type="Char"/>
</array>
<struct name="FAT32_bpb">
<primitive name="BytesPerSector" type="UInt16"/>
<primitive name="SectorsPerCluster" type="UInt8"/>
<primitive name="ReservedSectors" type="UInt16"/>
<primitive name="FatCount" type="UInt8"/>
<primitive name="RootEntryCount16" type="UInt16"/>
<primitive name="TotalSectors16" type="UInt16"/>
<primitive name="MediaDesc" type="UInt8"/>
<primitive name="FATSize16" type="UInt16"/>
<primitive name="SectorsPerTrack" type="UInt16"/>
<primitive name="HeadCount" type="UInt16"/>
<primitive name="HiddenSectors" type="UInt32"/>
<primitive name="TotalSectors32" type="UInt32"/>
</struct>
<struct name="FAT32_ebpb">
<primitive name="FATSize32" type="UInt32"/>
<primitive name="ExtFlags" type="UInt16"/>
<primitive name="FSVersion" type="UInt16"/>
<primitive name="RootDirCluster" type="UInt32"/>
<primitive name="FSInfoSector" type="UInt16"/>
<primitive name="BkBootSector" type="UInt16"/>
<array name="reserved0" length="12">
<primitive type="uint8"/>
</array>
<primitive name="DriveNumber" type="UInt8"/>
<primitive name="NtFlags" type="UInt8"/>
<primitive name="Signature" type="UInt8"/>
<primitive name="VolumeId" type="UInt32"/>
<array name="VolumeLabel" length="11">
<primitive type="Char"/>
</array>
<array name="FilesystemIdent" length="8">
<primitive type="Char"/>
</array>
</struct>
<array name="BootCode" length="420">
<primitive type="UInt8"/>
</array>
<!-- Signature 0xAA55 -->
<primitive name="signature" type="UInt16"/>
</struct>
</data>

View File

@@ -0,0 +1,12 @@
[Desktop Entry]
Icon=application-x-executable
Type=Service
ServiceTypes=KPluginInfo
Name=Stevia FAT32 VBR Structure
X-KDE-PluginInfo-Author=Elaina Claus
X-KDE-PluginInfo-Name=vbr32
X-KDE-PluginInfo-Version=1.0
X-KDE-PluginInfo-Website=https://chtm.me
X-KDE-PluginInfo-Category=structure
X-KDE-PluginInfo-License=MIT
X-KDE-PluginInfo-EnabledByDefault=false

View File

@@ -51,7 +51,7 @@ endstruc
; uint32_t lba, ; uint32_t lba,
; uint16_t count, uint8_t drive_num) ; uint16_t count, uint8_t drive_num)
ALIGN 4, db 0x90 ALIGN 4, db 0x90
read_disk_raw: BIOS_int13h_ext_read:
__CDECL16_PROC_ENTRY __CDECL16_PROC_ENTRY
.func: .func:
push LBAPkt_t_size ; len push LBAPkt_t_size ; len

View File

@@ -15,8 +15,7 @@
%ifndef __INC_ERROR_CODES %ifndef __INC_ERROR_CODES
; Errors ; MBR Error codes
; 12 Errors, 5 in use
%define MBR_ERROR_DISK_T_ERR 'a' %define MBR_ERROR_DISK_T_ERR 'a'
%define MBR_ERROR_NO_INT32E 'b' %define MBR_ERROR_NO_INT32E 'b'
%define MBR_ERROR_NO_NO_BOOT_PART 'c' %define MBR_ERROR_NO_NO_BOOT_PART 'c'
@@ -30,7 +29,7 @@
%define MBR_ERROR_RESERVED_k 'k' %define MBR_ERROR_RESERVED_k 'k'
%define MBR_ERROR_INT13h_EREAD_ERR 'l' %define MBR_ERROR_INT13h_EREAD_ERR 'l'
; 12 Error ; VBR Error codes
%define VBR_ERROR_WRONG_FAT_SIZE 'm' %define VBR_ERROR_WRONG_FAT_SIZE 'm'
%define VBR_ERROR_NO_SIGNATURE 'n' %define VBR_ERROR_NO_SIGNATURE 'n'
%define VBR_ERROR_DISK_READ_ERR 'o' %define VBR_ERROR_DISK_READ_ERR 'o'
@@ -44,7 +43,7 @@
%define VBR_ERROR_RESERVED_w 'w' %define VBR_ERROR_RESERVED_w 'w'
%define VBR_ERROR_RESERVED_x 'x' %define VBR_ERROR_RESERVED_x 'x'
; 22 errors, 8 in use ; Stage2 Error codes
%define STAGE2_A20_FAILED 'A' %define STAGE2_A20_FAILED 'A'
%define STAGE2_SIGNATURE_MISSING 'B' %define STAGE2_SIGNATURE_MISSING 'B'
%define STAGE2_MM_E820_NO_SUPPORT 'C' %define STAGE2_MM_E820_NO_SUPPORT 'C'
@@ -60,19 +59,19 @@
%define STAGE2_FAT32_E_UNSUPPORTED 'M' %define STAGE2_FAT32_E_UNSUPPORTED 'M'
%define STAGE2_FAT32_E_UNIMPLEMENTED 'N' %define STAGE2_FAT32_E_UNIMPLEMENTED 'N'
%define STAGE2_ERROR_BAD_MBR 'O' %define STAGE2_ERROR_BAD_MBR 'O'
%define STAGE2_ERROR_BAD_VBR 'P' %define STAGE2_VBR_E_ACTIVE 'P'
%define STAGE2_ERROR_RESERVED_Q 'Q' %define STAGE2_VBR_E_SIGN 'Q'
%define STAGE2_ERROR_RESERVED_R 'R' %define STAGE2_VBR_E_TOT 'R'
%define STAGE2_ERROR_RESERVED_S 'S' %define STAGE2_VBR_E_FATSZ 'S'
%define STAGE2_ERROR_RESERVED_T 'T' %define STAGE2_VBR_E_DIRENT 'T'
%define STAGE2_ERROR_RESERVED_U 'U' %define STAGE2_VBR_E_PARTTYPE 'U'
%define STAGE2_ERROR_RESERVED_V 'V' %define STAGE2_RESERVED_E_V 'V'
; for development only, specific errors should be above. ; Debug error codes
%define STEVIA_DEBUG_OK 'W' %define STEVIA_DEBUG_OK 'W'
%define STEVIA_DEBUG_ERR 'X' %define STEVIA_DEBUG_ERR 'X'
%define STEVIA_DEBUG_UNIMPLEMENTED 'Y' %define STEVIA_DEBUG_UNIMPLEMENTED 'Y'
%define STEVIA_DEBUG_HALT 'Z' %define STEVIA_DEBUG_HALT 'Z'
%endif %endif
%define __INC_ERROR_CODES %define __INC_ERROR_CODES

View File

@@ -16,9 +16,169 @@
%ifndef __INC_FAT32_SYS %ifndef __INC_FAT32_SYS
%include "partition_table.inc" %include "partition_table.inc"
%include "fat32/bpb_offset_bx.inc"
%include "fat32/fat32_structures.inc" %include "fat32/fat32_structures.inc"
; int read_mbr(int boot_drive, void* dst)
; destination buffer needs 512 bytes of space
FAT32_load_mbr:
__CDECL16_PROC_ENTRY
.proc:
; read mbr on boot drive to memory (for the partition table)
movzx ax, byte [bp + 4]
push ax ; drive_num (2)
push 0x01 ; count (2)
push dword 0x0 ; lba (4)
push word [bp + 6] ; offset = dst
push __STAGE2_SEGMENT ; this segment
call BIOS_int13h_ext_read
add sp, 0xC
.check_sig:
mov bx, [bp + 6]
cmp word [bx + 0x1FE], 0xAA55 ; check for bytes at end
jne .error_nosign
; TODO: this needs more error checking, zero checking, check the sig a bunch of stuff...
.endp:
__CDECL16_PROC_EXIT
ret
.error_nosign:
ERROR STAGE2_ERROR_BAD_MBR
; int read_vbr(int boot_drive, void* buf)
; read vbr on boot partition to memory (for fat bpb/ebpb)
; TODO: seperate validation and loading the sector, just check the 0xAA55 at the end here...
FAT32_load_vbr:
__CDECL16_PROC_ENTRY
.proc:
mov bx, SteviaInfo
mov ax, word [bx + SteviaInfoStruct_t.p16_MbrPtr]
add ax, DISK_PARTITION_TABLE_OFFSET
mov bx, ax ; offset to part table
mov cx, 4 ; only checking 4 entries
.find_active_L0:
mov al, [bx + PartEntry_t.attributes]
cmp al, 0x80 ; 0x80 == 1000_0000b
je .check_fstype
add bx, PartEntry_t_size ; next part entry's attributes
loop .find_active_L0
jmp .error_noactive
.check_fstype:
; check for part_type = 0x0C (DOS 7.1+/W95 FAT32 w/ LBA) or 0x1C (Hidden 0x0C)
__BOCHS_MAGIC_DEBUG
mov al, [bx + PartEntry_t.part_type]
cmp al, 0x0C
je .active_ok
; *or*
cmp al, 0x1C
je .active_ok
jmp .error_badparttype ; error if part_type != 0x1C or 0x0C
.active_ok:
movzx ax, byte [bp + 4]
push ax ; drive_num (2)
push 0x01 ; count (2)
mov eax, dword [bx + PartEntry_t.lba_start]
push dword eax ; lba (4)
push word [bp + 6] ; offset = dst
push __STAGE2_SEGMENT ; this segment
call BIOS_int13h_ext_read
add sp, 0xC
; vbr (with fat bpb/ebpb) is at the buffer now
.check_sig:
mov bx, [bp + 6]
cmp word [bx + 0x1FE], 0xAA55 ; check for bytes at end
jne .error_nosign
.check_FAT_sanity:
; we only quickly validate that this is *probably* a FAT32 volume
add bx, 11 ; point bx at start of bpb (skip jmp code and ident)
cmp word [bx + FAT32_bpb_t.u16_TotalSectors16], 0 ; TotalSectors16 should be 0 (use TotalSectors32 in bpb)
jne .error_totsectors
cmp word [bx + FAT32_bpb_t.u16_FATSize16], 0 ; FatSize16 will be 0 if FAT32 (use FATSize32 in ebpb)
jne .error_fatsz
cmp word [bx + FAT32_bpb_t.u16_RootEntryCount16], 0 ; root dir info is in data clusters on fat32
jne .error_rootdir
.endp:
__CDECL16_PROC_EXIT
ret
.error_noactive:
ERROR STAGE2_VBR_E_ACTIVE
.error_nosign:
ERROR STAGE2_VBR_E_SIGN
.error_totsectors:
ERROR STAGE2_VBR_E_TOT
.error_fatsz:
ERROR STAGE2_VBR_E_FATSZ
.error_rootdir:
ERROR STAGE2_VBR_E_DIRENT
.error_badparttype:
ERROR STAGE2_VBR_E_PARTTYPE
; what a 'mount' should probably do at this point...
; - read VBR at partition_lba
; - validate FAT32 signatures
; - fill fat32_bpb_t and compute derived fields
; - read FSInfo (free count/next free)
; - ???
; int fat32_mount(FAT32_State_t* state, uint32_t partition_lba);
FAT32_mountfs:
__CDECL16_PROC_ENTRY
.proc:
; mount: parse BPB, derive fat0_lba, data_lba, cluster0_lba.
.endp:
__CDECL16_PROC_EXIT
ret
.error:
ERROR STEVIA_DEBUG_ERR
; int fat32_read_fat(FAT32_State_t* state, uint32_t clus, uint32_t* out);
FAT32_read_fat:
__CDECL16_PROC_ENTRY
.proc:
; Read 32-bit FAT entry for cluster n
.endp:
__CDECL16_PROC_EXIT
ret
.error:
ERROR STEVIA_DEBUG_ERR
; FAT32 entry is 32-bits; only low 28 bits are meaningful.
; EOC if (val & 0x0FFFFFFF) >= 0x0FFFFFF8.
; bad if == 0x0FFFFFF7.
; free if == 0x00000000.
; int fat32_next_clus(FAT32_State_t* state, uint32_t clus, uint32_t* out_next);
FAT32_next_cluster:
__CDECL16_PROC_ENTRY
.proc:
; Walk to next cluster in chain (validates EOC/bad)
.endp:
__CDECL16_PROC_EXIT
ret
.error:
ERROR STEVIA_DEBUG_ERR
; e.g:
; uint64_t clus_to_lba(FAT32_State_t* state, uint32_t clus) {
; return v->data_lba + (uint64_t)(clus - 2) * v->secs_per_clus;
; }
FAT32_clus_to_lba:
__CDECL16_PROC_ENTRY
.proc:
; Convert cluster -> LBA of first sector of that cluster
.endp:
__CDECL16_PROC_EXIT
ret
.error:
ERROR STEVIA_DEBUG_ERR
; Prototyping for now... ; Prototyping for now...
; TODO: ; TODO:
@@ -59,35 +219,6 @@
; int cache_read_sector(uint64_t lba, void* dst); ; int cache_read_sector(uint64_t lba, void* dst);
; int cache_invalidate_all(void); ; int cache_invalidate_all(void);
; what a 'mount' should probably do at this point...
; - read VBR at partition_lba
; - validate FAT32 signatures
; - fill fat32_bpb_t and compute derived fields
; - read FSInfo (free count/next free)
; - ???
; int fat32_mount(uint32_t partition_lba, fat32_bpb_t* out);
;
; Accessors
;
; // Convert cluster -> LBA of first sector of that cluster
; uint64_t clus_to_lba(const fat32_bpb_t* v, uint32_t clus) {
; return v->data_lba + (uint64_t)(clus - 2) * v->secs_per_clus;
; }
; FAT32 entry is 32-bits; only low 28 bits are meaningful.
; EOC if (val & 0x0FFFFFFF) >= 0x0FFFFFF8.
; bad if == 0x0FFFFFF7.
; free if == 0x00000000.
; // Read 32-bit FAT entry for cluster n
; int fat32_read_fat(const fat32_bpb_t* v, uint32_t clus, uint32_t* out);
; // Walk to next cluster in chain (validates EOC/bad)
; int fat32_next_clus(const fat32_bpb_t* v, uint32_t clus, uint32_t* out_next);
; ;
; SFN directories ; SFN directories
; ;
@@ -109,7 +240,6 @@
;int fat32_dir_iter_open(fat32_bpb_t* v, uint32_t first_clus, fat32_dir_iter_t* it); ;int fat32_dir_iter_open(fat32_bpb_t* v, uint32_t first_clus, fat32_dir_iter_t* it);
;int fat32_dir_iter_next(fat32_dir_iter_t* it, fat32_dirent_sfn_t* out); // FS_OK or FS_E_END ;int fat32_dir_iter_next(fat32_dir_iter_t* it, fat32_dirent_sfn_t* out); // FS_OK or FS_E_END
; typedef struct { ; typedef struct {
; uint32_t first_clus; ; uint32_t first_clus;
; uint32_t size; ; uint32_t size;

View File

@@ -58,20 +58,18 @@
; resulting in a value which does not fit in the Number of Sectors entry at 0x13. ; resulting in a value which does not fit in the Number of Sectors entry at 0x13.
struc FAT32_bpb_t struc FAT32_bpb_t
.reserved_jmpboot resb 3 .u16_BytesPerSector resw 1
.ident resb 8 .u8_SectorsPerCluster resb 1
.bytes_per_sector_word resb 2 .u16_ReservedSectors resw 1
.sectors_per_cluster_byte resb 1 .u8_FatCount resb 1
.reserved_sectors_word resb 2 .u16_RootEntryCount16 resw 1 ; Root dir entry count field, 0 on fat32
.fat_count_byte resb 1 .u16_TotalSectors16 resw 1 ; total number of sectors size, 0 on fat32
.unused1_ZERO_word resb 2 ; Root entry count field, 0 on fat32 .u8_MediaDesc resb 1
.unused2_ZERO_word resb 2 ; total sectors size 16, 0 on fat32 .u16_FATSize16 resw 1 ; FAT size 16, 0 on fat32
.media_desc_byte resb 1 .u16_SectorsPerTrack resw 1
.unused3_ZERO_word resb 2 ; FAT size 16, 0 on fat32 .u16_HeadCount resw 1
.sectors_per_track_word resb 2 .u32_HiddenSectors resd 1
.head_count_word resb 2 .u32_TotalSectors32 resd 1
.hidden_sectors_dword resb 4
.total_sectors_dword resb 4
endstruc endstruc
; EBPB Information (FAT32) ; EBPB Information (FAT32)
@@ -91,19 +89,19 @@ endstruc
; 8 System identifier string. Always "FAT32 ". The spec says never to trust the contents of this string for any use. ; 8 System identifier string. Always "FAT32 ". The spec says never to trust the contents of this string for any use.
struc FAT32_ebpb_t struc FAT32_ebpb_t
.FATSz_dword resb 4 .u32_FATSize32 resd 1 ; size of *each* fat in sectors, total = FATSz * (# of FATs)
.extflags_word resb 2 .u16_ExtFlags resw 1
.FSVersion_word resb 2 .u16_FSVersion resw 1
.root_clus_dword resb 4 .u32_RootDirCluster resd 1
.FSInfo_word resb 2 .u16_FSInfoSector resw 1
.BkBootSec_word resb 2 .u16_BkBootSector resw 1
.reserved1 resb 12 .reserved0 resb 12
.drive_number_byte resb 1 .u8_DriveNumber resb 1
.nt_flags_byte resb 1 .u8_NtFlags resb 1
.signature_byte resb 1 .u8_Signature resb 1
.volume_id_dword resb 4 .u32_VolumeId resd 1
.volume_label_bytea resb 11 .volume_label resb 11
.system_ident_bytea resb 8 .system_ident resb 8 ; Should always be 'FAT32 '
endstruc endstruc
; ## Standard 8.3 structure ### ; ## Standard 8.3 structure ###
@@ -197,20 +195,11 @@ endstruc
; 32 bytes ; 32 bytes
struc FAT32_State_t struc FAT32_State_t
.first_data_sector_32 resd 1 .u32_TotalClusters resd 1
.first_fat_sector_32 resd 1 .u32_DataAreaStartSector resd 1
.fat_size_32 resd 1 .u32_FATAreaStartSector resd 1
.curr_FAT_cluster_32 resd 1 .p16_FATBuffer resw 1
.curr_dir_cluster_32 resd 1 .p16_ClustBuffer resw 1
.curr_drive_lba_32 resd 1
endstruc
; 16 bytes
struc FAT32_NextClusterData_t
.fat_offset resd 1
.fat_sector resd 1
.entry_offset resd 1
.reserved_1 resd 1
endstruc endstruc
; FAT32 Attributes ; FAT32 Attributes

View File

@@ -133,7 +133,7 @@ main:
; uint8_t read_stage2_raw(uint16_t buf_segment, uint16_t buf_offset, ; uint8_t read_stage2_raw(uint16_t buf_segment, uint16_t buf_offset,
; uint32_t lba, ; uint32_t lba,
; uint16_t count, uint16_t drive_num) ; uint16_t count, uint16_t drive_num)
call read_disk_raw call BIOS_int13h_ext_read
add sp, 0xC add sp, 0xC
.goto_vbr: .goto_vbr:
cmp word [VBR_ENTRY + 0x1FE], 0xAA55 cmp word [VBR_ENTRY + 0x1FE], 0xAA55

View File

@@ -91,7 +91,7 @@ init:
%include "partition_table.inc" %include "partition_table.inc"
%include "fat32/fat32_structures.inc" %include "fat32/fat32_structures.inc"
;%include 'fat32/FAT32_SYS.inc' %include 'fat32/FAT32_SYS.nasm'
; ############### ; ###############
; BIOS functions ; BIOS functions
@@ -135,7 +135,7 @@ main:
push ax ; dst push ax ; dst
movzx ax, byte [u8_BootDrive] movzx ax, byte [u8_BootDrive]
push ax ; boot_drive push ax ; boot_drive
__CDECL16_CALL ReadMbrData, 2 ; fill mbr buffer __CDECL16_CALL FAT32_load_mbr, 2 ; fill/validate mbr buffer
; setup heap space for vbr data ; setup heap space for vbr data
__CDECL16_CALL_ARGS 0x200, 0x10 __CDECL16_CALL_ARGS 0x200, 0x10
@@ -145,7 +145,7 @@ main:
push ax ; dst push ax ; dst
movzx ax, byte [u8_BootDrive] movzx ax, byte [u8_BootDrive]
push ax ; boot_drive push ax ; boot_drive
__CDECL16_CALL ReadVbrData, 2 ; fill vbr buffer __CDECL16_CALL FAT32_load_vbr, 2 ; fill/validate vbr buffer
; enable A20 gate ; enable A20 gate
call EnableA20 call EnableA20
@@ -194,82 +194,6 @@ hcf:
; ;
; ############################## ; ##############################
; int read_mbr(int boot_drive, void* dst)
; destination buffer needs 512 bytes of space
ReadMbrData:
__CDECL16_PROC_ENTRY
.proc:
; read mbr on boot drive to memory (for the partition table)
movzx ax, byte [bp + 4]
push ax ; drive_num (2)
push 0x01 ; count (2)
push dword 0x0 ; lba (4)
push word [bp + 6] ; offset = dst
push __STAGE2_SEGMENT ; this segment
call read_disk_raw
add sp, 0xC
.check_sig:
mov bx, [bp + 6]
cmp word [bx + 0x1FE], 0xAA55 ; check for bytes at end
jne ReadMbrData.error_nosign
; TODO: this needs more error checking, zero checking, check the sig a bunch of stuff...
.endp:
__CDECL16_PROC_EXIT
ret
.error_nosign:
ERROR STAGE2_ERROR_BAD_MBR
; int read_vbr(int boot_drive, void* buf)
; read vbr on boot partition to memory (for fat bpb/ebpb)
ReadVbrData:
__CDECL16_PROC_ENTRY
.proc:
mov bx, SteviaInfo
mov ax, word [bx + SteviaInfoStruct_t.p16_MbrPtr]
add ax, DISK_PARTITION_TABLE_OFFSET
mov bx, ax ; offset to part table
mov cx, 4 ; only checking 4 entries
mov si, PartEntry_t.attributes
.find_active_L0:
mov al, byte [bx + si]
test al, 0x80 ; 0x80 == 1000_0000b
je ReadVbrData.active_found
add bx, PartEntry_t_size ; next part entry's attributes
loop ReadVbrData.find_active_L0
jmp ReadVbrData.error_noactive
.active_found:
movzx ax, byte [bp + 4]
push ax ; drive_num (2)
push 0x01 ; count (2)
mov eax, dword [bx + PartEntry_t.lba_start]
push dword eax ; lba (4)
push word [bp + 6] ; offset = dst
push __STAGE2_SEGMENT ; this segment
call read_disk_raw
add sp, 0xC
; vbr (with fat bpb/ebpb) is at the buffer now
.check_sig:
mov bx, [bp + 6]
cmp word [bx + 0x1FE], 0xAA55 ; check for bytes at end
jne ReadVbrData.error_nosign
.check_FAT_size:
test word [bx + FAT32_bpb_t.unused2_ZERO_word], 0 ; TotSectors16 will not be set if FAT32
jnz ReadVbrData.error_badfatfs
.endp:
__CDECL16_PROC_EXIT
ret
.error_noactive:
ERROR STAGE2_ERROR_BAD_VBR
.error_nosign:
ERROR STAGE2_ERROR_BAD_VBR
.error_badfatfs:
ERROR STAGE2_ERROR_BAD_VBR
; set ds and es segments back to the base of the loader ; set ds and es segments back to the base of the loader
%ifnmacro __TINY_DS_ES %ifnmacro __TINY_DS_ES
%macro __TINY_DS_ES 0 %macro __TINY_DS_ES 0
@@ -529,17 +453,19 @@ align 16, resb 1
%define BIOSMemoryMap_SIZE 1024 %define BIOSMemoryMap_SIZE 1024
BIOSMemoryMap: BIOSMemoryMap:
resb BIOSMemoryMap_SIZE resb BIOSMemoryMap_SIZE
align 16, resb 1
stack_bottom:
resb 2048
stack_top:
end_bss: end_bss:
; !!! End bss data !!!
%define STACK_SIZE 0x1000 ; 4 KiB
; Pad to the cap (emits nothing in the file; only increases .bss virtual size). ; Pad to the cap (emits nothing in the file; only increases .bss virtual size).
; If BSS_SIZE > BSS_MAX_BYTES, this becomes negative and NASM errors out. ; If BSS_SIZE > BSS_MAX_BYTES, this becomes negative and NASM errors out.
%define BSS_MAX_BYTES 0x2000 %define BSS_MAX_BYTES (0x2000 - STACK_SIZE)
resb (BSS_MAX_BYTES - (end_bss - begin_bss)) resb (BSS_MAX_BYTES - (end_bss - begin_bss))
align 16, resb 1
stack_bottom:
resb STACK_SIZE
stack_top:
; Optional: keep a label for later math: ; Optional: keep a label for later math:
bss_cap_end: bss_cap_end:

View File

@@ -21,15 +21,21 @@
%define __STEVIA_VBR %define __STEVIA_VBR
section .text section .text
__ENTRY: __ENTRY:
phy_bpb_start: ; try to force encode a short jmp nop: i.e 0xEB 0x5A 0x90
; will jump right 0x5A (90 bytes) after the end of the ebpb
; this could also be encoded as 0xE9 0x?? 0x?? for a near jump
; if init ends up being >= 128 bytes from entry.
jmp short (init - $$) jmp short (init - $$)
nop nop
; fill BPB area with 0x00 since we skip writing this part to disk ; 8 ascii bytes, "MSWIN 4.1", ""
; but we need it for the 'jmp short entry; nop' above phy_bs_ident:
times 33 db 0x00 times 8 db 0x00
phy_bpb_start:
times 25 db 0x00
phy_ebpb_start: phy_ebpb_start:
; fill eBPB area with 0x00 since we skip writing this part to disk
times 54 db 0x00 times 54 db 0x00
; ############### ; ###############
@@ -95,7 +101,7 @@ main:
mov byte [bp - 2], dl ; boot_drive mov byte [bp - 2], dl ; boot_drive
.check_FAT_size: ; we only support a very specific setup of FAT32 .check_FAT_size: ; we only support a very specific setup of FAT32
mov bx, phy_bpb_start mov bx, phy_bpb_start
test word [bx + FAT32_bpb_t.unused2_ZERO_word], 0 ; TotSectors16 will not be set if FAT32 test word [bx + FAT32_bpb_t.u16_TotalSectors16], 0 ; TotSectors16 will not be set if FAT32
jz main.load_stage2 jz main.load_stage2
ERROR VBR_ERROR_WRONG_FAT_SIZE ERROR VBR_ERROR_WRONG_FAT_SIZE
.load_stage2: .load_stage2:
@@ -114,7 +120,7 @@ main:
; uint8_t read_stage2_raw(uint16_t buf_segment, uint16_t buf_offset, ; uint8_t read_stage2_raw(uint16_t buf_segment, uint16_t buf_offset,
; uint32_t lba, ; uint32_t lba,
; uint16_t count, uint16_t drive_num) ; uint16_t count, uint16_t drive_num)
call read_disk_raw call BIOS_int13h_ext_read
add sp, 0xC add sp, 0xC
.enter_stage2: .enter_stage2:
mov dl, byte [bp - 2] ; byte boot_drive mov dl, byte [bp - 2] ; byte boot_drive