27 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
918e94689f 2KiB stack 2025-09-17 18:44:55 -04:00
8d2cde0a31 added no planned fat32 error codes and added mbr/vbr reading error codes 2025-09-17 17:02:08 -04:00
8d3788a76e remove unused structure 2025-09-17 16:50:59 -04:00
4a27e09872 use partition entry size constant 2025-09-17 16:24:45 -04:00
59bc1afb7c stick mmap info in SteviaInfo 2025-09-17 16:24:27 -04:00
8b0b73d8a4 start partition table at entry 1 2025-09-17 16:22:47 -04:00
803be58c10 Merge branch 'trunk' into fat_v2 2025-09-16 08:36:46 -04:00
528e3d69fe update github workflow since github includes firefox & snaps in the default runner image, which causes the build to fail.
All checks were successful
Daily Build and trunk tester / debian_update (push) Successful in 1m11s
going to need a custom runner I guess...might as well only do actions on gitea.
2025-09-16 08:34:22 -04:00
51bd250925 minor corrections 2025-09-13 15:30:11 -04:00
460165a8d1 re-naming 2025-09-13 15:07:36 -04:00
935cbd1089 naming changes to ReadMbr/Vbr 2025-09-13 14:56:26 -04:00
7f1b4fa632 more naming changes 2025-09-13 14:51:30 -04:00
14f6788a22 renaming things to a hungarian style and adding "types" 2025-09-13 14:41:09 -04:00
526c3e7ea5 remove define_info macro, improved cstr macro and renamed all the OK/Msg debug strings 2025-09-13 13:45:37 -04:00
17 changed files with 441 additions and 363 deletions

View File

@@ -3,7 +3,7 @@ on:
push: push:
branches: [ $default-branch ] branches: [ $default-branch ]
schedule: schedule:
- cron: "0 7 * * *" # daily 07:00 - cron: "0 7 * * 1" # mondays at 07:00
workflow_dispatch: {} workflow_dispatch: {}
jobs: jobs:

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

@@ -33,35 +33,27 @@ struc AddressRangeDescStruct_t
.ExtType resd 1 .ExtType resd 1
endstruc endstruc
; !!! this procedure changes ES !!!
ALIGN 4, db 0x90 ALIGN 4, db 0x90
GetMemoryMap: GetMemoryMap:
__CDECL16_PROC_ENTRY __CDECL16_PROC_ENTRY
push es ; save segment register push es ; save segment register
.func: .func:
mov dword [SteviaInfo + SteviaInfoStruct_t.MemoryMapEntries], 0 mov word [SteviaInfo + SteviaInfoStruct_t.u16_E820MMapEntryCount], 0
xor ebx, ebx ; Continuation value, 0 for the first call xor ebx, ebx ; Continuation value, 0 for the first call
mov di, BIOSMemoryMap ; destination is es:di, es should == ds
mov dx, BIOSMemoryMap
shr dx, 4
mov es, dx
xor di, di ; (BIOSMemoryMap >> 4):0 makes di an index into BIOSMemoryMap
mov ecx, AddressRangeDescStruct_t_size ; hard request ACPI 3.0 table versions (24 bytes) mov ecx, AddressRangeDescStruct_t_size ; hard request ACPI 3.0 table versions (24 bytes)
.loop_L1: .loop_L1:
mov eax, 0x0000E820 ; select 0xE820 function mov eax, 0x0000E820 ; select 0xE820 function
mov edx, 0x534D4150 ; 'SMAP' magic mov edx, 0x534D4150 ; 'SMAP' magic
clc ; clear carry clc ; clear carry
int 0x15 int 0x15 ; data will be stored at es:di by e820 call
jc GetMemoryMap.error jc GetMemoryMap.error
cmp eax, 0x534D4150 cmp eax, 0x534D4150
jne GetMemoryMap.no_smap_returned jne GetMemoryMap.no_smap_returned
.no_error: .no_error:
mov eax, dword [SteviaInfo + SteviaInfoStruct_t.MemoryMapEntries] inc word [SteviaInfo + SteviaInfoStruct_t.u16_E820MMapEntryCount]
add eax, 1
mov dword [SteviaInfo + SteviaInfoStruct_t.MemoryMapEntries], eax
cmp ecx, 20 ; TODO: maybe this could be handled better than just panicing cmp ecx, 20 ; TODO: maybe this could be handled better than just panicing
jb GetMemoryMap.nonstandard_e820 ; non-standard entry found jb GetMemoryMap.nonstandard_e820 ; non-standard entry found
@@ -89,7 +81,7 @@ GetMemoryMap:
PrintMemoryMap: PrintMemoryMap:
__CDECL16_PROC_ENTRY __CDECL16_PROC_ENTRY
.func: .func:
mov eax, dword [SteviaInfo + SteviaInfoStruct_t.MemoryMapEntries] mov eax, dword [SteviaInfo + SteviaInfoStruct_t.u16_E820MMapEntryCount]
cmp eax, 0 cmp eax, 0
je PrintMemoryMap.endp ; if entries == 0, exit je PrintMemoryMap.endp ; if entries == 0, exit

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
@@ -94,7 +94,7 @@ read_disk_raw:
%elifdef __STEVIA_VBR %elifdef __STEVIA_VBR
ERROR VBR_ERROR_DISK_READ_ERR ERROR VBR_ERROR_DISK_READ_ERR
%else %else
ERROR STAGE2_MBR_DISK_READ_ERROR ERROR STAGE2_INT13_DISK_READ_ERR
%endif %endif
.endf: .endf:
__CDECL16_PROC_EXIT __CDECL16_PROC_EXIT

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,31 +43,31 @@
%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'
%define STAGE2_MM_E820_MISC_ERR 'D' %define STAGE2_MM_E820_MISC_ERR 'D'
%define STAGE2_MM_E820_NONSTANDARD 'E' %define STAGE2_MM_E820_NONSTANDARD 'E'
%define STAGE2_MM_E820_NO_SMAP 'F' %define STAGE2_MM_E820_NO_SMAP 'F'
%define STAGE2_MBR_DISK_READ_ERROR 'G' %define STAGE2_INT13_DISK_READ_ERR 'G'
%define STAGE2_FAT32_INIT_ERROR 'H' %define STAGE2_FAT32_E_FMT 'H'
%define STAGE2_FAT32_NO_FILE 'I' %define STAGE2_FAT32_E_RANGE 'I'
%define STAGE2_FAT32_END_OF_CHAIN 'J' %define STAGE2_FAT32_E_NOSUCH 'J'
%define STAGE2_FAT32_NCLUS_CFDIVZ 'K' %define STAGE2_FAT32_E_ISDIR 'K'
%define STAGE2_FAT32_CLS2LBA_CF 'L' %define STAGE2_FAT32_E_TOOLONG 'L'
%define STAGE2_FAT32_INIT_CF 'M' %define STAGE2_FAT32_E_UNSUPPORTED 'M'
%define STAGE2_ERROR_INFOPRINTER 'N' %define STAGE2_FAT32_E_UNIMPLEMENTED 'N'
%define STAGE2_ERROR_RESERVED_O 'O' %define STAGE2_ERROR_BAD_MBR 'O'
%define STAGE2_ERROR_RESERVED_P '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'

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

@@ -15,6 +15,9 @@
%ifndef __INC_PART_TABLE %ifndef __INC_PART_TABLE
%define DISK_SIGNATURE_OFFSET 0x1B8
%define DISK_PARTITION_TABLE_OFFSET 0x1BE
; Partition table entry format ; Partition table entry format
; Off. Size. Description ; Off. Size. Description
;0x00 1 Drive attributes (bit 7 set = active or bootable) ;0x00 1 Drive attributes (bit 7 set = active or bootable)
@@ -34,8 +37,6 @@ struc PartEntry_t
endstruc endstruc
struc PartTable_t struc PartTable_t
.signature resb 4
.reserved resb 2
.partition1 resb PartEntry_t_size .partition1 resb PartEntry_t_size
.partition2 resb PartEntry_t_size .partition2 resb PartEntry_t_size
.partition3 resb PartEntry_t_size .partition3 resb PartEntry_t_size

View File

@@ -11,9 +11,9 @@ endstruc
; void arena_init(ArenaState *a) ; void arena_init(ArenaState *a)
; ;
arena_init: ArenaInit:
__CDECL16_PROC_ENTRY __CDECL16_PROC_ENTRY
.func: .proc:
mov ax, word [bp + 4] ; ptr to state structure mov ax, word [bp + 4] ; ptr to state structure
mov di, ax mov di, ax
@@ -25,15 +25,11 @@ arena_init:
; zero out heap area on init ; zero out heap area on init
; void* kmemset_byte(void* dst, uint8_t val, uint16_t len); ; void* kmemset_byte(void* dst, uint8_t val, uint16_t len);
; TODO: use word or qword spacing at least to speed this up ; TODO: use word or qword spacing at least to speed this up
mov ax, __ARENA_HEAP_SIZE push __ARENA_HEAP_SIZE ; len
push ax ; len push 0x0 ; val = 0
xor ax, ax push __ARENA_HEAP_START ; dst
push ax ; val = 0
mov ax, __ARENA_HEAP_START
push ax ; dst
call kmemset call kmemset
add sp, 0x6 add sp, 0x6
.endp: .endp:
__CDECL16_PROC_EXIT __CDECL16_PROC_EXIT
ret ret
@@ -43,7 +39,7 @@ arena_init:
; align x up to the nearest specified alignment (a), a should be a power of 2 ; align x up to the nearest specified alignment (a), a should be a power of 2
; (x + (a-1)) & ~(a-1) ; (x + (a-1)) & ~(a-1)
; return value in ax ; return value in ax
arena_align_up: ArenaAlignUp:
__CDECL16_PROC_ENTRY __CDECL16_PROC_ENTRY
.func: .func:
; if a == 0 return x ; if a == 0 return x
@@ -51,7 +47,7 @@ arena_align_up:
mov bx, [bp + 6] ; a mov bx, [bp + 6] ; a
test bx, bx test bx, bx
jz .endp jz .endf
; enforce power-of-two for alignment, return x ; enforce power-of-two for alignment, return x
; for example... ; for example...
@@ -69,7 +65,7 @@ arena_align_up:
mov cx, bx mov cx, bx
dec cx dec cx
test bx, cx test bx, cx
jnz .endp jnz .endf
dec bx ; a - 1 dec bx ; a - 1
@@ -80,7 +76,7 @@ arena_align_up:
and cx, bx ; and with the inverse and cx, bx ; and with the inverse
mov ax, cx ; move to ax and return mov ax, cx ; move to ax and return
.endp: .endf:
__CDECL16_PROC_EXIT __CDECL16_PROC_EXIT
ret ret
@@ -88,9 +84,9 @@ arena_align_up:
; bp-2 - current used arena (i.e 'highmark') ; bp-2 - current used arena (i.e 'highmark')
; bp-4 - aligned_ptr ; bp-4 - aligned_ptr
; bp-6 - new_end ; bp-6 - new_end
arena_alloc: ArenaAlloc:
__CDECL16_PROC_ENTRY 0x10 __CDECL16_PROC_ENTRY 0x10
.func: .proc:
; remove bytes from pool and increment mark to the new cursor location ; remove bytes from pool and increment mark to the new cursor location
; return a pointer to the begining of allocated segment ; return a pointer to the begining of allocated segment
mov bx, early_heap_state mov bx, early_heap_state
@@ -102,11 +98,10 @@ arena_alloc:
push bx ; save heap_state pointer push bx ; save heap_state pointer
mov ax, word [bp + 6] ; requested next allocation alignment
push ax push word [bp + 6] ; requested next allocation alignment
mov ax, word [bp - 2] ; current arena 'highmark' push word [bp - 2] ; current arena 'highmark'
push ax call ArenaAlignUp
call arena_align_up
add sp, 0x4 add sp, 0x4
mov word [bp - 4], ax ; save return value mov word [bp - 4], ax ; save return value
@@ -118,7 +113,7 @@ arena_alloc:
mov dx, word [bx + ArenaStateStruc_t.end] mov dx, word [bx + ArenaStateStruc_t.end]
cmp ax, dx cmp ax, dx
ja arena_alloc.error ; if our heap end is < the requested throw an error, heap is full ja .error ; if our heap end is < the requested throw an error, heap is full
; else update the mark to the new value & return the aligned pointer ; else update the mark to the new value & return the aligned pointer
; mark_delta = new_end - curr_used ; mark_delta = new_end - curr_used
@@ -140,7 +135,7 @@ arena_alloc:
arena_mark: arena_mark:
__CDECL16_PROC_ENTRY __CDECL16_PROC_ENTRY
.func: .proc:
; return the current location of the 'cursor' in the allocator ; return the current location of the 'cursor' in the allocator
ERROR STEVIA_DEBUG_UNIMPLEMENTED ERROR STEVIA_DEBUG_UNIMPLEMENTED
.endp: .endp:
@@ -149,7 +144,7 @@ arena_mark:
arena_reset_to: arena_reset_to:
__CDECL16_PROC_ENTRY __CDECL16_PROC_ENTRY
.func: .proc:
; rewind the arena to a previously marked point ; rewind the arena to a previously marked point
ERROR STEVIA_DEBUG_UNIMPLEMENTED ERROR STEVIA_DEBUG_UNIMPLEMENTED
.endp: .endp:
@@ -158,7 +153,7 @@ arena_reset_to:
arena_reset: arena_reset:
__CDECL16_PROC_ENTRY __CDECL16_PROC_ENTRY
.func: .proc:
; reset the entire heap to a fresh state ; reset the entire heap to a fresh state
ERROR STEVIA_DEBUG_UNIMPLEMENTED ERROR STEVIA_DEBUG_UNIMPLEMENTED
.endp: .endp:

View File

@@ -109,7 +109,7 @@ main:
mov al, byte [bx + PartEntry_t.attributes] mov al, byte [bx + PartEntry_t.attributes]
test al, 0x80 ; 0x80 == 1000_0000b test al, 0x80 ; 0x80 == 1000_0000b
jnz main.active_found jnz main.active_found
add bx, 0x10 ; add 16 bytes to offset add bx, PartEntry_t_size ; add 16 bytes to offset
loop main.find_active_L0 loop main.find_active_L0
ERROR MBR_ERROR_NO_NO_BOOT_PART ERROR MBR_ERROR_NO_NO_BOOT_PART
@@ -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

@@ -39,7 +39,7 @@ begin_text:
ALIGN 16, db 0x90 ALIGN 16, db 0x90
init: init:
cli ; We do not want to be interrupted cli ; We do not want to be interrupted
mov [boot_drive], dl ; copy boot_drive to globals mov [u8_BootDrive], dl ; copy boot_drive to globals
mov ax, __STAGE2_SEGMENT ; set all our segments to the configured segment, except es mov ax, __STAGE2_SEGMENT ; set all our segments to the configured segment, except es
mov ds, ax ; * mov ds, ax ; *
@@ -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
@@ -102,14 +102,10 @@ init:
; structures ; structures
struc SteviaInfoStruct_t struc SteviaInfoStruct_t
.MemoryMapPtr resd 1 .p16_E820MemoryMapPtr resw 1
.MemoryMapEntries resd 1 .u16_E820MMapEntryCount resw 1
endstruc .p16_MbrPtr resw 1
.p16_VbrPtr resw 1
struc EarlyBootStruct_t
.partition_table resb PartTable_t_size
.fat32_bpb resb FAT32_bpb_t_size
.fat32_ebpb resb FAT32_ebpb_t_size
endstruc endstruc
ALIGN 4, db 0x90 ALIGN 4, db 0x90
@@ -126,38 +122,39 @@ main:
; setup the early heap ; setup the early heap
__CDECL16_CALL_ARGS early_heap_state __CDECL16_CALL_ARGS early_heap_state
__CDECL16_CALL arena_init, 1 __CDECL16_CALL ArenaInit, 1
__CDECL16_CALL_ARGS HelloPrompt_info __CDECL16_CALL_ARGS pszHelloPrompt
__CDECL16_CALL PrintString, 1 __CDECL16_CALL PrintString, 1
; setup and store our vbr/mbr (e)bpb ; setup heap space for mbr data
__CDECL16_CALL_ARGS 0x200, 0x10 __CDECL16_CALL_ARGS 0x200, 0x10
__CDECL16_CALL arena_alloc, 2 __CDECL16_CALL ArenaAlloc, 2
mov word [mbr_ptr], ax mov word [SteviaInfo + SteviaInfoStruct_t.p16_MbrPtr], ax
push ax ; dst push ax ; dst
movzx ax, byte [boot_drive] movzx ax, byte [u8_BootDrive]
push ax ; boot_drive push ax ; boot_drive
__CDECL16_CALL read_mbr, 2 ; fill mbr buffer __CDECL16_CALL FAT32_load_mbr, 2 ; fill/validate mbr buffer
; setup heap space for vbr data
__CDECL16_CALL_ARGS 0x200, 0x10 __CDECL16_CALL_ARGS 0x200, 0x10
__CDECL16_CALL arena_alloc, 2 __CDECL16_CALL ArenaAlloc, 2
mov word [vbr_ptr], ax mov word [SteviaInfo + SteviaInfoStruct_t.p16_VbrPtr], ax
push ax ; dst push ax ; dst
movzx ax, byte [boot_drive] movzx ax, byte [u8_BootDrive]
push ax ; boot_drive push ax ; boot_drive
__CDECL16_CALL read_vbr, 2 ; fill vbr buffer __CDECL16_CALL FAT32_load_vbr, 2 ; fill/validate vbr buffer
; enable A20 gate ; enable A20 gate
call EnableA20 call EnableA20
__CDECL16_CALL_ARGS A20_Enabled_OK_info __CDECL16_CALL_ARGS pszA20EnabledOk
__CDECL16_CALL PrintString, 1 __CDECL16_CALL PrintString, 1
; get system memory map ; get system memory map
call GetMemoryMap call GetMemoryMap
__CDECL16_CALL_ARGS MemoryMap_OK_info __CDECL16_CALL_ARGS pszMemoryMapOk
__CDECL16_CALL PrintString, 1 __CDECL16_CALL PrintString, 1
; enter unreal mode (enter PM w/ 16 bit code, 32 bit flat memory model & return to real) ; enter unreal mode (enter PM w/ 16 bit code, 32 bit flat memory model & return to real)
@@ -165,12 +162,12 @@ main:
; use __REFLAT macros to re-flat ds/es for easy transfers to >1MiB ; use __REFLAT macros to re-flat ds/es for easy transfers to >1MiB
; NOTE: if you modify a segment register you will need to re-unreal it ; NOTE: if you modify a segment register you will need to re-unreal it
call EnterUnrealMode call EnterUnrealMode
__CDECL16_CALL_ARGS UnrealMode_OK_info __CDECL16_CALL_ARGS pszUnrealModeOk
__CDECL16_CALL PrintString, 1 __CDECL16_CALL PrintString, 1
; FAT Driver setup ; FAT Driver setup
;call InitFATDriver ;call InitFATDriver
;__CDECL16_CALL_ARGS InitFATSYS_OK_info ;__CDECL16_CALL_ARGS pszInitFAT32Ok
;__CDECL16_CALL PrintString, 1 ;__CDECL16_CALL PrintString, 1
; ;
@@ -178,7 +175,7 @@ main:
;call SearchFATDIR ;call SearchFATDIR
;push dword eax ; save first cluster of bootable file ;push dword eax ; save first cluster of bootable file
;__CDECL16_CALL_ARGS FileFound_OK_info ;__CDECL16_CALL_ARGS pszFileFoundMsg
;__CDECL16_CALL PrintString, 1 ;__CDECL16_CALL PrintString, 1
;pop dword eax ;pop dword eax
@@ -197,87 +194,6 @@ hcf:
; ;
; ############################## ; ##############################
; int read_mbr(int boot_drive, void* dst)
; destination buffer needs 512 bytes of space
read_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 read_disk_raw
add sp, 0xC
.check_sig:
mov bx, [bp + 6]
cmp word [bx + 0x1FE], 0xAA55 ; check for bytes at end
jne read_mbr.error
; TODO: this needs error checking, zero checking, check the sig a bunch of stuff...
.update_globals:
mov ax, [bp + 6]
add ax, 0x1B8 ; offset to start of PartTable
mov [part_table_ptr], ax
.endp:
__CDECL16_PROC_EXIT
ret
.error:
ERROR STEVIA_DEBUG_ERR
; int read_vbr(int boot_drive, void* buf)
read_vbr:
__CDECL16_PROC_ENTRY
.proc:
__BOCHS_MAGIC_DEBUG
; read vbr on boot partition to memory (for fat bpb/ebpb)
.calc_part_offset:
mov bx, word [part_table_ptr] ; base pointer @ partition 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 read_vbr.active_found
add si, 0x10 ; add 16 bytes to offset (next part entry's attributes)
loop read_vbr.find_active_L0
jmp read_vbr.error
.active_found:
add bx, si ; update base to active part
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 read_mbr.error
.check_FAT_size:
test word [bx + FAT32_bpb_t.unused2_ZERO_word], 0 ; TotSectors16 will not be set if FAT32
jnz read_vbr.error
.update_globals:
mov word [fat32_bpb_ptr], bx
add bx, FAT32_bpb_t_size ; offset to ebpb
mov word [fat32_ebpb_ptr], bx
.endp:
__CDECL16_PROC_EXIT
ret
.error:
ERROR STEVIA_DEBUG_ERR
; 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
@@ -291,7 +207,7 @@ read_vbr:
%ifnmacro __REFLAT_DS_ES %ifnmacro __REFLAT_DS_ES
%macro __REFLAT_DS_ES 0 %macro __REFLAT_DS_ES 0
cli ; no interrupts cli ; no interrupts
lgdt [((__STAGE2_SEGMENT << 4) + unreal_gdt_info)] ; load unreal gdt lgdt [((__STAGE2_SEGMENT << 4) + UnrealGdtInfo)] ; load unreal gdt
mov eax, cr0 mov eax, cr0
or eax, 1 ; set pmode bit or eax, 1 ; set pmode bit
@@ -315,7 +231,7 @@ read_vbr:
%ifnmacro __REFLAT_ES %ifnmacro __REFLAT_ES
%macro __REFLAT_ES 0 %macro __REFLAT_ES 0
cli ; no interrupts cli ; no interrupts
lgdt [((__STAGE2_SEGMENT << 4) + unreal_gdt_info)] ; load unreal gdt lgdt [((__STAGE2_SEGMENT << 4) + UnrealGdtInfo)] ; load unreal gdt
mov eax, cr0 mov eax, cr0
or eax, 1 ; set pmode bit or eax, 1 ; set pmode bit
@@ -338,8 +254,8 @@ ALIGN 4, db 0x90
EnterUnrealMode: EnterUnrealMode:
__CDECL16_PROC_ENTRY __CDECL16_PROC_ENTRY
cli ; no interrupts cli ; no interrupts
.func: .proc:
lgdt [((__STAGE2_SEGMENT << 4) + unreal_gdt_info)] ; load unreal gdt lgdt [((__STAGE2_SEGMENT << 4) + UnrealGdtInfo)] ; load unreal gdt
mov eax, cr0 mov eax, cr0
or eax, 1 ; set pmode bit or eax, 1 ; set pmode bit
@@ -385,51 +301,46 @@ begin_data:
; ############# ; #############
%define CRLF 0Dh, 0Ah %define CRLF 0Dh, 0Ah
%macro define_cstr 2 %macro define_cstr 2-*
%if %0 > 2
align 16 align 16
%1_cstr: %1:
db %{2:-1}, 00h
%else
align 16
%1:
db %2, 00h db %2, 00h
%endif
%endmacro %endmacro
%macro define_info 2 define_cstr pszHelloPrompt, "Hello from Stevia Stage2!", CRLF
align 16 define_cstr pszA20EnabledOk, "A20 Enabled OK", CRLF
%1_info: define_cstr pszMemoryMapOk, "Memory map OK", CRLF
db %2, CRLF, 00h define_cstr pszUnrealModeOk, "Unreal mode OK", CRLF
%endmacro define_cstr pszInitFAT32Ok, "FAT32 Driver Init OK", CRLF
define_info HelloPrompt, "Hello from Stevia Stage2!" define_cstr pszFileFoundMsg, "Found SFN entry for bootable binary, first cluster -> ", CRLF
define_info A20_Enabled_OK, "A20 Enabled OK" define_cstr pszSearchFAT32DirMsg, "Searching FAT fs for bootable file...", CRLF
define_info MemoryMap_OK, "Memory map OK" define_cstr pszReadFAT32ClusterMsg, "Attempting to load next FAT", CRLF
define_info UnrealMode_OK, "Unreal mode OK" define_cstr pszMaybeFoundBootMsg, "Maybe found a file...checking...", CRLF
define_info FileFound_OK, "Found SFN entry for bootable binary, first cluster -> "
define_info InitFATSYS_OK, "FAT32 Driver Init..."
define_info SearchFATDIR, "Searching FAT DIR for bootable file..."
define_info NextFATCluster, "Attempting to find next FAT cluster..."
define_info ReadFATCluster, "Attempting to load next FAT"
define_info MaybeFound_Boot, "Maybe found a file...checking..."
define_cstr BootTarget, "BOOT BIN" define_cstr BootTarget, "BOOT BIN"
; set to boot_drive passed from BIOS almost first thing in init ; set to boot_drive passed from BIOS almost first thing in init
align 4, db 0 align 4, db 0
boot_drive: u8_BootDrive:
db 0x00 db 0x00
align 16, db 0
BootTarget:
db 'BOOT BIN'
align 16, db 0 align 16, db 0
IntToHex_table: IntToHex_table:
db '0123456789ABCDEF' db '0123456789ABCDEF'
; see docs/gdt.txt for a quick refresher on GDT ; see docs/gdt.txt for a quick refresher on GDT
align 16, db 0 align 16, db 0
unreal_gdt_info: UnrealGdtInfo:
unreal_gdt_size: dw (unreal_gdt_end - unreal_gdt_start) - 1 u16_UnrealGdt_size: dw (UnrealGdtEnd - UnrealGdtStart) - 1
unreal_gdt_ptr: dd ((__STAGE2_SEGMENT << 4) + unreal_gdt_start) pF_UnrealGdtPtr: dd ((__STAGE2_SEGMENT << 4) + UnrealGdtStart)
unreal_gdt_start: UnrealGdtStart:
; entry 0 (null descriptor) ; entry 0 (null descriptor)
dq 0 ; first entry is null dq 0 ; first entry is null
@@ -446,14 +357,14 @@ unreal_gdt_start:
db 1001_0010b ; Access Byte: Present, ring0, S = 1, data (0), non-confirming, writable, present db 1001_0010b ; Access Byte: Present, ring0, S = 1, data (0), non-confirming, writable, present
db 1000_1111b ; Flags: GR = 4KiB, attr = <16-bit/?/?>, Granularity = 4KiB & 16:19 of limit db 1000_1111b ; Flags: GR = 4KiB, attr = <16-bit/?/?>, Granularity = 4KiB & 16:19 of limit
db 0x00 ; Base Address(31:24) db 0x00 ; Base Address(31:24)
unreal_gdt_end: UnrealGdtEnd:
align 16, db 0 align 16, db 0
gdt32_info: Gdt32Info:
gdt32_size: dw (gdt32_end - gdt32_start) - 1 gdt32_size: dw (Gdt32End - Gdt32Start) - 1
gdt32_ptr: dd ((__STAGE2_SEGMENT << 4) + gdt32_start) gdt32_ptr: dd ((__STAGE2_SEGMENT << 4) + Gdt32Start)
gdt32_start: Gdt32Start:
dq 0 dq 0 ; null segment
.gdt32_code: .gdt32_code:
dw 0xFFFF ; code segment (RX) dw 0xFFFF ; code segment (RX)
dw 0x0000 dw 0x0000
@@ -482,22 +393,22 @@ gdt32_start:
db 1001_0000b ; Access: readable, not writable db 1001_0000b ; Access: readable, not writable
db 1100_1111b ; 4KB granularity, 32-bit db 1100_1111b ; 4KB granularity, 32-bit
db 0x00 db 0x00
gdt32_end: Gdt32End:
align 16,db 0 align 16,db 0
BUILD_NASM_VER: BuildNasmVer:
db "Stevia Stage2 built with NASM - ", __NASM_VER__, 00h db "Stevia Stage2 built with NASM - ", __NASM_VER__, 00h
align 16,db 0 align 16,db 0
BUILD_DATETIME: BuildDateTime:
db 'Assembled - ', __DATE__, ' ', __TIME__, 00h db 'Assembled - ', __DATE__, ' ', __TIME__, 00h
align 16,db 0 align 16,db 0
BUILD_GIT_VER: BuildGitVer:
db __GIT_VER__, 00h db __GIT_VER__, 00h
align 16,db 0 align 16,db 0
BUILD_GIT_HASH: BuildGitHash:
db __GIT_HASH__, 00h db __GIT_HASH__, 00h
end_data: end_data:
@@ -518,72 +429,22 @@ align 16, resb 1
section .bss follows=.sign section .bss follows=.sign
begin_bss: begin_bss:
align 4, resb 1
mbr_ptr:
resw 1
align 4, resb 1
vbr_ptr:
resw 1
align 4, resb 1
part_table_ptr:
resw 1
align 4, resb 1
fat32_bpb_ptr:
resw 1
align 4, resb 1
fat32_ebpb_ptr:
resw 1
; structures ; structures
align 16, resb 1 align 16, resb 1
partition_table: SteviaInfo:
resb PartTable_t_size resd SteviaInfoStruct_t_size
align 16, resb 1 align 16, resb 1
fat32_bpb: early_heap_state:
resb FAT32_bpb_t_size resb ArenaStateStruc_t_size
fat32_ebpb:
resb FAT32_ebpb_t_size
align 16, resb 1
fat32_nc_data:
resb 16
align 16, resb 1 align 16, resb 1
lba_packet: lba_packet:
resb LBAPkt_t_size resb LBAPkt_t_size
align 16, resb 1
fat32_state:
resb FAT32_State_t_size
align 16, resb 1
SteviaInfo:
resd 4
align 16, resb 1
early_heap_state:
resb ArenaStateStruc_t_size
;
; post-bss init globals
;
; ;
; large continuous allocations ; large continuous allocations
; ;
align 16, resb 1
disk_buffer:
resb 512
fat_buffer:
resb 512
dir_buffer:
resb 512
fat_fsinfo:
resb 512
; TODO: this will hold 42 entries from the map function ; TODO: this will hold 42 entries from the map function
; the e820 function needs to check that it doesn't overflow ; the e820 function needs to check that it doesn't overflow
@@ -592,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 1024
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 0x3000 %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