Compare commits
33 Commits
3da2af2d2d
...
fat_v2
| Author | SHA1 | Date | |
|---|---|---|---|
| 4a944bc493 | |||
| 137735431a | |||
| 6caaf6aa6d | |||
| 1e9de446f0 | |||
| 5f2ca55af7 | |||
| 11656c2827 | |||
| f87f88a0dc | |||
| 7baa53178a | |||
| 8002d1cb54 | |||
| d8a89cfd2b | |||
| 6c402b5c4f | |||
| a3c9897291 | |||
| 831d45c33c | |||
| 918e94689f | |||
| 8d2cde0a31 | |||
| 8d3788a76e | |||
| 4a27e09872 | |||
| 59bc1afb7c | |||
| 8b0b73d8a4 | |||
| 803be58c10 | |||
| 528e3d69fe | |||
| 51bd250925 | |||
| 460165a8d1 | |||
| 935cbd1089 | |||
| 7f1b4fa632 | |||
| 14f6788a22 | |||
| 526c3e7ea5 | |||
| 721ff2e62d | |||
| a50af35abd | |||
| 7cd6baa74d | |||
| 40fa4062ce | |||
| a8b24c7b01 | |||
| 58fc4a08dd |
2
.github/workflows/daily.yaml
vendored
2
.github/workflows/daily.yaml
vendored
@@ -3,7 +3,7 @@ on:
|
||||
push:
|
||||
branches: [ $default-branch ]
|
||||
schedule:
|
||||
- cron: "0 7 * * *" # daily 07:00
|
||||
- cron: "0 7 * * 1" # mondays at 07:00
|
||||
workflow_dispatch: {}
|
||||
|
||||
jobs:
|
||||
|
||||
3
.gitignore
vendored
3
.gitignore
vendored
@@ -10,4 +10,5 @@ stevia-log
|
||||
*.map
|
||||
compose-dev.yaml
|
||||
eth_null-tx.log
|
||||
eth_null-txdump.txt
|
||||
eth_null-txdump.txt
|
||||
*.log
|
||||
3
Makefile
3
Makefile
@@ -38,9 +38,6 @@ QEMU_ARGS := \
|
||||
-device e1000,netdev=n0,mac=52:54:00:12:34:56 \
|
||||
-netdev user,id=n0 \
|
||||
-device piix3-usb-uhci \
|
||||
-device usb-ohci,id=ohci0 \
|
||||
-device usb-ehci,id=ehci0 \
|
||||
-device pcspk \
|
||||
-parallel null \
|
||||
-serial null -serial none -serial none -serial none \
|
||||
-chardev file,id=dbg,path=bochs-e9.log,append=on \
|
||||
|
||||
@@ -207,24 +207,45 @@ Each GDT entry is 8 bytes:
|
||||
|
||||
## **5. Memory Layout Example**
|
||||
|
||||
### **Low Memory (First MiB)**
|
||||
### **Low Memory/Upper Memory map (<= 1MiB)**
|
||||
|
||||
| Start | End | Size | Type | Description |
|
||||
|-------------|-------------|-----------------|-----------------------|----------------------------------|
|
||||
| 0x00000000 | 0x000003FF | 1 KiB | RAM (partially unusable) | Real Mode IVT (Interrupt Vector Table) |
|
||||
| 0x00000400 | 0x000004FF | 256 bytes | RAM (partially unusable) | BDA (BIOS data area) |
|
||||
| 0x00000500 | 0x00007BFF | almost 30 KiB | RAM - free for use | Conventional memory |
|
||||
| 0x00007C00 | 0x00007DFF | 512 bytes | RAM (partially unusable) | OS BootSector |
|
||||
| 0x00007E00 | 0x0007FFFF | 480.5 KiB | RAM - free for use | Conventional memory |
|
||||
| 0x00080000 | 0x0009FFFF | 128 KiB | RAM (partially unusable) | EBDA (Extended BIOS Data Area) |
|
||||
| 0x000A0000 | 0x000FFFFF | 384 KiB | various (unusable) | Video memory, ROM Area |
|
||||
| Start | End | Size | Type | Description |
|
||||
|-------------|-------------|-----------------|----------------------|--------------------------------|
|
||||
| 0x00000000 | 0x000003FF | 1 KiB | RAM reclaimable~1~ | Real Mode IVT |
|
||||
| 0x00000400 | 0x000004FF | 256 bytes | RAM reclaimable~1~ | BDA |
|
||||
| 0x00000500 | 0x00007BFF | 29 KiB + 767b | RAM - free | Conventional memory |
|
||||
| 0x00007C00 | 0x00007DFF | 512 bytes | RAM reclaimable~2~ | OS BootSector |
|
||||
| 0x00007E00 | 0x0007FFFF | 480.5 KiB | RAM - free | Conventional memory |
|
||||
| 0x00080000 | 0x0009FFFF | 128 KiB | RAM (unusable)~1~ | EBDA (Extended BIOS Data Area) |
|
||||
| 0x000A0000 | 0x000FFFFF | 384 KiB | Upper RAM (unusable) | Video memory, ROM Area |
|
||||
|
||||
### **Extended Memory (Above 1 MiB)**
|
||||
1. Reclaimable in the event that you *never* need the BIOS again & once the CPU is in protected mode.
|
||||
2. Reclaimable after you are done with with the MBR/VBR stages.
|
||||
|
||||
| Start | End | Size | Description |
|
||||
|-------------|-------------|-----------------|------------------------|
|
||||
| 0x00100000 | 0x00EFFFFF | 14 MiB | RAM - free for use |
|
||||
### **Extended Memory (> 1 MiB)**
|
||||
|
||||
This is only an example, you should always check the memory map.
|
||||
|
||||
| Start | End | Size | Description |
|
||||
|-------------|-------------|-----------------|---------------------------------------|
|
||||
| 0x00100000 | 0x00EFFFFF | 14 MiB | RAM(?) - free for use |
|
||||
| 0x00F00000 | 0x00FFFFFF | 1 MiB | Possible memory-mapped hardware (ISA) |
|
||||
| 0x01000000 | ? | ? | More extended memory |
|
||||
| 0x01000000 | ? | ? | More extended memory |
|
||||
| 0xC0000000 | 0xFFFFFFFF | 1 GiB | Memory mapped PCI devices, BIOS, etc. |
|
||||
| 0x0000000100000000 | ? | ? | RAM - usable in PAE/64-bit mode |
|
||||
| 0x0000000100000000 | ? | ? | RAM(?) - usable in PAE/64-bit mode |
|
||||
|
||||
|
||||
## **6. Stage2 Memory Layout **
|
||||
|
||||
Overall, Tiny (64 KiB page) Code/Data, Flat 4GiB mapping in gs/fs after unreal switch
|
||||
|
||||
| Start | End | Size (Bytes) | Type | Description |
|
||||
|-------------|-------------|--------------|--------------------|----------------------------|
|
||||
| 0x00000000 | 0x000003FF | 0x400 | RAM - (BIOS) | Real Mode IVT |
|
||||
| 0x00000400 | 0x000004FF | 0x100 | RAM - (BIOS) | BDA |
|
||||
| 0x00000500 | 0x000042FF | 0x3E00 | RAM - .text/.data | Code and constants/strings |
|
||||
| 0x00004300 | 0x000044FF | 0x100 | RAM - .sign | EOF marker/signature |
|
||||
| 0x00004500 | 0x000074FF | 0x3000 | RAM - bss | Runtime data/stack |
|
||||
| 0x00007500 | 0x00007FFF | 0xB00 | RAM - reserved | Reserved |
|
||||
| 0x00008000 | 0x0000DFFF | 0x6000 | RAM - heap | Conventional memory |
|
||||
| 0x0000F000 | 0x0000FFFF | 0x1000 | RAM - reserved | Reserved |
|
||||
24
docs/okteta/structures/mbr/main.osd
Normal file
24
docs/okteta/structures/mbr/main.osd
Normal 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>
|
||||
12
docs/okteta/structures/mbr/metadata.desktop
Normal file
12
docs/okteta/structures/mbr/metadata.desktop
Normal 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
|
||||
57
docs/okteta/structures/vbr/main.osd
Normal file
57
docs/okteta/structures/vbr/main.osd
Normal 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>
|
||||
12
docs/okteta/structures/vbr/metadata.desktop
Normal file
12
docs/okteta/structures/vbr/metadata.desktop
Normal 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
|
||||
@@ -33,35 +33,27 @@ struc AddressRangeDescStruct_t
|
||||
.ExtType resd 1
|
||||
endstruc
|
||||
|
||||
; !!! this procedure changes ES !!!
|
||||
ALIGN 4, db 0x90
|
||||
GetMemoryMap:
|
||||
__CDECL16_PROC_ENTRY
|
||||
push es ; save segment register
|
||||
.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
|
||||
|
||||
mov dx, BIOSMemoryMap
|
||||
shr dx, 4
|
||||
mov es, dx
|
||||
xor di, di ; (BIOSMemoryMap >> 4):0 makes di an index into BIOSMemoryMap
|
||||
|
||||
mov di, BIOSMemoryMap ; destination is es:di, es should == ds
|
||||
mov ecx, AddressRangeDescStruct_t_size ; hard request ACPI 3.0 table versions (24 bytes)
|
||||
|
||||
.loop_L1:
|
||||
mov eax, 0x0000E820 ; select 0xE820 function
|
||||
mov edx, 0x534D4150 ; 'SMAP' magic
|
||||
clc ; clear carry
|
||||
int 0x15
|
||||
int 0x15 ; data will be stored at es:di by e820 call
|
||||
jc GetMemoryMap.error
|
||||
cmp eax, 0x534D4150
|
||||
jne GetMemoryMap.no_smap_returned
|
||||
.no_error:
|
||||
mov eax, dword [SteviaInfo + SteviaInfoStruct_t.MemoryMapEntries]
|
||||
add eax, 1
|
||||
mov dword [SteviaInfo + SteviaInfoStruct_t.MemoryMapEntries], eax
|
||||
inc word [SteviaInfo + SteviaInfoStruct_t.u16_E820MMapEntryCount]
|
||||
|
||||
cmp ecx, 20 ; TODO: maybe this could be handled better than just panicing
|
||||
jb GetMemoryMap.nonstandard_e820 ; non-standard entry found
|
||||
@@ -89,7 +81,7 @@ GetMemoryMap:
|
||||
PrintMemoryMap:
|
||||
__CDECL16_PROC_ENTRY
|
||||
.func:
|
||||
mov eax, dword [SteviaInfo + SteviaInfoStruct_t.MemoryMapEntries]
|
||||
mov eax, dword [SteviaInfo + SteviaInfoStruct_t.u16_E820MMapEntryCount]
|
||||
cmp eax, 0
|
||||
je PrintMemoryMap.endp ; if entries == 0, exit
|
||||
|
||||
|
||||
@@ -51,7 +51,7 @@ endstruc
|
||||
; uint32_t lba,
|
||||
; uint16_t count, uint8_t drive_num)
|
||||
ALIGN 4, db 0x90
|
||||
read_disk_raw:
|
||||
BIOS_int13h_ext_read:
|
||||
__CDECL16_PROC_ENTRY
|
||||
.func:
|
||||
push LBAPkt_t_size ; len
|
||||
@@ -94,7 +94,7 @@ read_disk_raw:
|
||||
%elifdef __STEVIA_VBR
|
||||
ERROR VBR_ERROR_DISK_READ_ERR
|
||||
%else
|
||||
ERROR STAGE2_MBR_DISK_READ_ERROR
|
||||
ERROR STAGE2_INT13_DISK_READ_ERR
|
||||
%endif
|
||||
.endf:
|
||||
__CDECL16_PROC_EXIT
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
|
||||
%ifndef __INC_STEVIA_CONFIG
|
||||
|
||||
%define SECTOR_SIZE 512
|
||||
%define SECTOR_SIZE 0x200
|
||||
%define STAGE2_SECTOR_COUNT 0x20
|
||||
; 16 KiB
|
||||
%define MAX_STAGE2_BYTES (SECTOR_SIZE * STAGE2_SECTOR_COUNT)
|
||||
|
||||
@@ -15,8 +15,7 @@
|
||||
|
||||
%ifndef __INC_ERROR_CODES
|
||||
|
||||
; Errors
|
||||
; 12 Errors, 5 in use
|
||||
; MBR Error codes
|
||||
%define MBR_ERROR_DISK_T_ERR 'a'
|
||||
%define MBR_ERROR_NO_INT32E 'b'
|
||||
%define MBR_ERROR_NO_NO_BOOT_PART 'c'
|
||||
@@ -30,7 +29,7 @@
|
||||
%define MBR_ERROR_RESERVED_k 'k'
|
||||
%define MBR_ERROR_INT13h_EREAD_ERR 'l'
|
||||
|
||||
; 12 Error
|
||||
; VBR Error codes
|
||||
%define VBR_ERROR_WRONG_FAT_SIZE 'm'
|
||||
%define VBR_ERROR_NO_SIGNATURE 'n'
|
||||
%define VBR_ERROR_DISK_READ_ERR 'o'
|
||||
@@ -44,35 +43,35 @@
|
||||
%define VBR_ERROR_RESERVED_w 'w'
|
||||
%define VBR_ERROR_RESERVED_x 'x'
|
||||
|
||||
; 22 errors, 8 in use
|
||||
; Stage2 Error codes
|
||||
%define STAGE2_A20_FAILED 'A'
|
||||
%define STAGE2_SIGNATURE_MISSING 'B'
|
||||
%define STAGE2_MM_E820_NO_SUPPORT 'C'
|
||||
%define STAGE2_MM_E820_MISC_ERR 'D'
|
||||
%define STAGE2_MM_E820_NONSTANDARD 'E'
|
||||
%define STAGE2_MM_E820_NO_SMAP 'F'
|
||||
%define STAGE2_MBR_DISK_READ_ERROR 'G'
|
||||
%define STAGE2_FAT32_INIT_ERROR 'H'
|
||||
%define STAGE2_FAT32_NO_FILE 'I'
|
||||
%define STAGE2_FAT32_END_OF_CHAIN 'J'
|
||||
%define STAGE2_FAT32_NCLUS_CFDIVZ 'K'
|
||||
%define STAGE2_FAT32_CLS2LBA_CF 'L'
|
||||
%define STAGE2_FAT32_INIT_CF 'M'
|
||||
%define STAGE2_ERROR_INFOPRINTER 'N'
|
||||
%define STAGE2_ERROR_RESERVED_O 'O'
|
||||
%define STAGE2_ERROR_RESERVED_P 'P'
|
||||
%define STAGE2_ERROR_RESERVED_Q 'Q'
|
||||
%define STAGE2_ERROR_RESERVED_R 'R'
|
||||
%define STAGE2_ERROR_RESERVED_S 'S'
|
||||
%define STAGE2_ERROR_RESERVED_T 'T'
|
||||
%define STAGE2_ERROR_RESERVED_U 'U'
|
||||
%define STAGE2_ERROR_RESERVED_V 'V'
|
||||
%define STAGE2_INT13_DISK_READ_ERR 'G'
|
||||
%define STAGE2_FAT32_E_FMT 'H'
|
||||
%define STAGE2_FAT32_E_RANGE 'I'
|
||||
%define STAGE2_FAT32_E_NOSUCH 'J'
|
||||
%define STAGE2_FAT32_E_ISDIR 'K'
|
||||
%define STAGE2_FAT32_E_TOOLONG 'L'
|
||||
%define STAGE2_FAT32_E_UNSUPPORTED 'M'
|
||||
%define STAGE2_FAT32_E_UNIMPLEMENTED 'N'
|
||||
%define STAGE2_ERROR_BAD_MBR 'O'
|
||||
%define STAGE2_VBR_E_ACTIVE 'P'
|
||||
%define STAGE2_VBR_E_SIGN 'Q'
|
||||
%define STAGE2_VBR_E_TOT 'R'
|
||||
%define STAGE2_VBR_E_FATSZ 'S'
|
||||
%define STAGE2_VBR_E_DIRENT 'T'
|
||||
%define STAGE2_VBR_E_PARTTYPE 'U'
|
||||
%define STAGE2_RESERVED_E_V 'V'
|
||||
|
||||
; for development only, specific errors should be above.
|
||||
%define STEVIA_DEBUG_OK 'W'
|
||||
%define STEVIA_DEBUG_ERR 'X'
|
||||
%define STEVIA_DEBUG_UNIMPLEMENTED 'Y'
|
||||
%define STEVIA_DEBUG_HALT 'Z'
|
||||
; Debug error codes
|
||||
%define STEVIA_DEBUG_OK 'W'
|
||||
%define STEVIA_DEBUG_ERR 'X'
|
||||
%define STEVIA_DEBUG_UNIMPLEMENTED 'Y'
|
||||
%define STEVIA_DEBUG_HALT 'Z'
|
||||
|
||||
%endif
|
||||
%define __INC_ERROR_CODES
|
||||
@@ -16,9 +16,169 @@
|
||||
%ifndef __INC_FAT32_SYS
|
||||
|
||||
%include "partition_table.inc"
|
||||
%include "fat32/bpb_offset_bx.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...
|
||||
|
||||
; TODO:
|
||||
@@ -59,35 +219,6 @@
|
||||
; int cache_read_sector(uint64_t lba, void* dst);
|
||||
; 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
|
||||
;
|
||||
@@ -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_next(fat32_dir_iter_t* it, fat32_dirent_sfn_t* out); // FS_OK or FS_E_END
|
||||
|
||||
|
||||
; typedef struct {
|
||||
; uint32_t first_clus;
|
||||
; uint32_t size;
|
||||
|
||||
@@ -58,20 +58,18 @@
|
||||
; resulting in a value which does not fit in the Number of Sectors entry at 0x13.
|
||||
|
||||
struc FAT32_bpb_t
|
||||
.reserved_jmpboot resb 3
|
||||
.ident resb 8
|
||||
.bytes_per_sector_word resb 2
|
||||
.sectors_per_cluster_byte resb 1
|
||||
.reserved_sectors_word resb 2
|
||||
.fat_count_byte resb 1
|
||||
.unused1_ZERO_word resb 2 ; Root entry count field, 0 on fat32
|
||||
.unused2_ZERO_word resb 2 ; total sectors size 16, 0 on fat32
|
||||
.media_desc_byte resb 1
|
||||
.unused3_ZERO_word resb 2 ; FAT size 16, 0 on fat32
|
||||
.sectors_per_track_word resb 2
|
||||
.head_count_word resb 2
|
||||
.hidden_sectors_dword resb 4
|
||||
.total_sectors_dword resb 4
|
||||
.u16_BytesPerSector resw 1
|
||||
.u8_SectorsPerCluster resb 1
|
||||
.u16_ReservedSectors resw 1
|
||||
.u8_FatCount resb 1
|
||||
.u16_RootEntryCount16 resw 1 ; Root dir entry count field, 0 on fat32
|
||||
.u16_TotalSectors16 resw 1 ; total number of sectors size, 0 on fat32
|
||||
.u8_MediaDesc resb 1
|
||||
.u16_FATSize16 resw 1 ; FAT size 16, 0 on fat32
|
||||
.u16_SectorsPerTrack resw 1
|
||||
.u16_HeadCount resw 1
|
||||
.u32_HiddenSectors resd 1
|
||||
.u32_TotalSectors32 resd 1
|
||||
endstruc
|
||||
|
||||
; 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.
|
||||
|
||||
struc FAT32_ebpb_t
|
||||
.FATSz_dword resb 4
|
||||
.extflags_word resb 2
|
||||
.FSVersion_word resb 2
|
||||
.root_clus_dword resb 4
|
||||
.FSInfo_word resb 2
|
||||
.BkBootSec_word resb 2
|
||||
.reserved1 resb 12
|
||||
.drive_number_byte resb 1
|
||||
.nt_flags_byte resb 1
|
||||
.signature_byte resb 1
|
||||
.volume_id_dword resb 4
|
||||
.volume_label_bytea resb 11
|
||||
.system_ident_bytea resb 8
|
||||
.u32_FATSize32 resd 1 ; size of *each* fat in sectors, total = FATSz * (# of FATs)
|
||||
.u16_ExtFlags resw 1
|
||||
.u16_FSVersion resw 1
|
||||
.u32_RootDirCluster resd 1
|
||||
.u16_FSInfoSector resw 1
|
||||
.u16_BkBootSector resw 1
|
||||
.reserved0 resb 12
|
||||
.u8_DriveNumber resb 1
|
||||
.u8_NtFlags resb 1
|
||||
.u8_Signature resb 1
|
||||
.u32_VolumeId resd 1
|
||||
.volume_label resb 11
|
||||
.system_ident resb 8 ; Should always be 'FAT32 '
|
||||
endstruc
|
||||
|
||||
; ## Standard 8.3 structure ###
|
||||
@@ -197,20 +195,11 @@ endstruc
|
||||
|
||||
; 32 bytes
|
||||
struc FAT32_State_t
|
||||
.first_data_sector_32 resd 1
|
||||
.first_fat_sector_32 resd 1
|
||||
.fat_size_32 resd 1
|
||||
.curr_FAT_cluster_32 resd 1
|
||||
.curr_dir_cluster_32 resd 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
|
||||
.u32_TotalClusters resd 1
|
||||
.u32_DataAreaStartSector resd 1
|
||||
.u32_FATAreaStartSector resd 1
|
||||
.p16_FATBuffer resw 1
|
||||
.p16_ClustBuffer resw 1
|
||||
endstruc
|
||||
|
||||
; FAT32 Attributes
|
||||
|
||||
@@ -15,6 +15,9 @@
|
||||
|
||||
%ifndef __INC_PART_TABLE
|
||||
|
||||
%define DISK_SIGNATURE_OFFSET 0x1B8
|
||||
%define DISK_PARTITION_TABLE_OFFSET 0x1BE
|
||||
|
||||
; Partition table entry format
|
||||
; Off. Size. Description
|
||||
;0x00 1 Drive attributes (bit 7 set = active or bootable)
|
||||
@@ -34,8 +37,6 @@ struc PartEntry_t
|
||||
endstruc
|
||||
|
||||
struc PartTable_t
|
||||
.signature resb 4
|
||||
.reserved resb 2
|
||||
.partition1 resb PartEntry_t_size
|
||||
.partition2 resb PartEntry_t_size
|
||||
.partition3 resb PartEntry_t_size
|
||||
|
||||
@@ -11,9 +11,9 @@ endstruc
|
||||
|
||||
; void arena_init(ArenaState *a)
|
||||
;
|
||||
arena_init:
|
||||
ArenaInit:
|
||||
__CDECL16_PROC_ENTRY
|
||||
.func:
|
||||
.proc:
|
||||
mov ax, word [bp + 4] ; ptr to state structure
|
||||
mov di, ax
|
||||
|
||||
@@ -25,15 +25,11 @@ arena_init:
|
||||
; zero out heap area on init
|
||||
; void* kmemset_byte(void* dst, uint8_t val, uint16_t len);
|
||||
; TODO: use word or qword spacing at least to speed this up
|
||||
mov ax, __ARENA_HEAP_SIZE
|
||||
push ax ; len
|
||||
xor ax, ax
|
||||
push ax ; val = 0
|
||||
mov ax, __ARENA_HEAP_START
|
||||
push ax ; dst
|
||||
push __ARENA_HEAP_SIZE ; len
|
||||
push 0x0 ; val = 0
|
||||
push __ARENA_HEAP_START ; dst
|
||||
call kmemset
|
||||
add sp, 0x6
|
||||
|
||||
.endp:
|
||||
__CDECL16_PROC_EXIT
|
||||
ret
|
||||
@@ -43,7 +39,7 @@ arena_init:
|
||||
; align x up to the nearest specified alignment (a), a should be a power of 2
|
||||
; (x + (a-1)) & ~(a-1)
|
||||
; return value in ax
|
||||
arena_align_up:
|
||||
ArenaAlignUp:
|
||||
__CDECL16_PROC_ENTRY
|
||||
.func:
|
||||
; if a == 0 return x
|
||||
@@ -51,7 +47,7 @@ arena_align_up:
|
||||
mov bx, [bp + 6] ; a
|
||||
|
||||
test bx, bx
|
||||
jz .endp
|
||||
jz .endf
|
||||
|
||||
; enforce power-of-two for alignment, return x
|
||||
; for example...
|
||||
@@ -69,7 +65,7 @@ arena_align_up:
|
||||
mov cx, bx
|
||||
dec cx
|
||||
test bx, cx
|
||||
jnz .endp
|
||||
jnz .endf
|
||||
|
||||
dec bx ; a - 1
|
||||
|
||||
@@ -80,7 +76,7 @@ arena_align_up:
|
||||
and cx, bx ; and with the inverse
|
||||
|
||||
mov ax, cx ; move to ax and return
|
||||
.endp:
|
||||
.endf:
|
||||
__CDECL16_PROC_EXIT
|
||||
ret
|
||||
|
||||
@@ -88,9 +84,9 @@ arena_align_up:
|
||||
; bp-2 - current used arena (i.e 'highmark')
|
||||
; bp-4 - aligned_ptr
|
||||
; bp-6 - new_end
|
||||
arena_alloc:
|
||||
ArenaAlloc:
|
||||
__CDECL16_PROC_ENTRY 0x10
|
||||
.func:
|
||||
.proc:
|
||||
; remove bytes from pool and increment mark to the new cursor location
|
||||
; return a pointer to the begining of allocated segment
|
||||
mov bx, early_heap_state
|
||||
@@ -102,11 +98,10 @@ arena_alloc:
|
||||
|
||||
push bx ; save heap_state pointer
|
||||
|
||||
mov ax, word [bp + 6] ; requested next allocation alignment
|
||||
push ax
|
||||
mov ax, word [bp - 2] ; current arena 'highmark'
|
||||
push ax
|
||||
call arena_align_up
|
||||
|
||||
push word [bp + 6] ; requested next allocation alignment
|
||||
push word [bp - 2] ; current arena 'highmark'
|
||||
call ArenaAlignUp
|
||||
add sp, 0x4
|
||||
mov word [bp - 4], ax ; save return value
|
||||
|
||||
@@ -118,7 +113,7 @@ arena_alloc:
|
||||
|
||||
mov dx, word [bx + ArenaStateStruc_t.end]
|
||||
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
|
||||
|
||||
; mark_delta = new_end - curr_used
|
||||
@@ -140,7 +135,7 @@ arena_alloc:
|
||||
|
||||
arena_mark:
|
||||
__CDECL16_PROC_ENTRY
|
||||
.func:
|
||||
.proc:
|
||||
; return the current location of the 'cursor' in the allocator
|
||||
ERROR STEVIA_DEBUG_UNIMPLEMENTED
|
||||
.endp:
|
||||
@@ -149,7 +144,7 @@ arena_mark:
|
||||
|
||||
arena_reset_to:
|
||||
__CDECL16_PROC_ENTRY
|
||||
.func:
|
||||
.proc:
|
||||
; rewind the arena to a previously marked point
|
||||
ERROR STEVIA_DEBUG_UNIMPLEMENTED
|
||||
.endp:
|
||||
@@ -158,7 +153,7 @@ arena_reset_to:
|
||||
|
||||
arena_reset:
|
||||
__CDECL16_PROC_ENTRY
|
||||
.func:
|
||||
.proc:
|
||||
; reset the entire heap to a fresh state
|
||||
ERROR STEVIA_DEBUG_UNIMPLEMENTED
|
||||
.endp:
|
||||
|
||||
@@ -109,7 +109,7 @@ main:
|
||||
mov al, byte [bx + PartEntry_t.attributes]
|
||||
test al, 0x80 ; 0x80 == 1000_0000b
|
||||
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
|
||||
|
||||
ERROR MBR_ERROR_NO_NO_BOOT_PART
|
||||
@@ -133,22 +133,14 @@ main:
|
||||
; uint8_t read_stage2_raw(uint16_t buf_segment, uint16_t buf_offset,
|
||||
; uint32_t lba,
|
||||
; uint16_t count, uint16_t drive_num)
|
||||
call read_disk_raw
|
||||
call BIOS_int13h_ext_read
|
||||
add sp, 0xC
|
||||
.goto_vbr:
|
||||
cmp word [VBR_ENTRY + 0x1FE], 0xAA55
|
||||
je main.sig_ok
|
||||
ERROR MBR_ERROR_NO_VBR_SIG ; no signature present
|
||||
.sig_ok:
|
||||
push PartTable_t_size ; len
|
||||
push DiskSig ; src -> start of partition table
|
||||
push partition_table ; dst -> addr in bss
|
||||
call kmemcpy ; copy partition table to bss
|
||||
add sp, 0x6
|
||||
|
||||
mov si, word [bp - 4] ; partition_offset address
|
||||
mov dl, byte [bp - 2] ; pass drive # from BIOS to VBR in dl
|
||||
mov bx, partition_table ; partition_table address
|
||||
jmp word 0x0000:VBR_ENTRY
|
||||
|
||||
; ###############
|
||||
@@ -181,14 +173,11 @@ BootSig:
|
||||
section .bss follows=.text
|
||||
begin_bss:
|
||||
|
||||
align 16, resb 1
|
||||
partition_table resb PartTable_t_size
|
||||
|
||||
align 16, resb 1
|
||||
lba_packet resb LBAPkt_t_size
|
||||
|
||||
align 512, resb 1
|
||||
stack_bottom resb 512 - 16 ; 512 byte stack early on
|
||||
stack_bottom resb 1024 - 16 ; 512 byte stack early on
|
||||
stack_top:
|
||||
mbr_redzone resb 16
|
||||
end_bss:
|
||||
@@ -36,18 +36,10 @@
|
||||
section .text
|
||||
begin_text:
|
||||
; dl = byte boot_drive
|
||||
; ax = word part_offset (active partition offset)
|
||||
; si = ptr PartTable_t partition_table
|
||||
; di = ptr FAT32_bpb_t fat32_bpb
|
||||
ALIGN 4, db 0x90
|
||||
ALIGN 16, db 0x90
|
||||
init:
|
||||
cli ; We do not want to be interrupted
|
||||
|
||||
; these 4 are stored in the .data section and are effectivly const types
|
||||
mov [vbr_part_table_ptr], si ; pointer to partition_table
|
||||
mov [vbr_fat32_bpb_ptr], di ; pointer to fat32_bpb
|
||||
mov [boot_drive], dl ; copy boot_drive to globals
|
||||
mov [partition_offset], ax ; copy partition_offset 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 ds, ax ; *
|
||||
@@ -99,7 +91,7 @@ init:
|
||||
|
||||
%include "partition_table.inc"
|
||||
%include "fat32/fat32_structures.inc"
|
||||
;%include 'fat32/FAT32_SYS.inc'
|
||||
%include 'fat32/FAT32_SYS.nasm'
|
||||
|
||||
; ###############
|
||||
; BIOS functions
|
||||
@@ -110,14 +102,10 @@ init:
|
||||
; structures
|
||||
|
||||
struc SteviaInfoStruct_t
|
||||
.MemoryMapPtr resd 1
|
||||
.MemoryMapEntries resd 1
|
||||
endstruc
|
||||
|
||||
struc EarlyBootStruct_t
|
||||
.partition_table resb PartTable_t_size
|
||||
.fat32_bpb resb FAT32_bpb_t_size
|
||||
.fat32_ebpb resb FAT32_ebpb_t_size
|
||||
.p16_E820MemoryMapPtr resw 1
|
||||
.u16_E820MMapEntryCount resw 1
|
||||
.p16_MbrPtr resw 1
|
||||
.p16_VbrPtr resw 1
|
||||
endstruc
|
||||
|
||||
ALIGN 4, db 0x90
|
||||
@@ -129,31 +117,44 @@ main:
|
||||
je main.stage2_main
|
||||
ERROR STAGE2_SIGNATURE_MISSING
|
||||
.stage2_main:
|
||||
; copy partition table data to .data section in stage2
|
||||
__CDECL16_CALL_ARGS partition_table, word [vbr_part_table_ptr], PartTable_t_size
|
||||
__CDECL16_CALL kmemcpy, 3
|
||||
|
||||
; copy bpb & ebpb to memory
|
||||
__CDECL16_CALL_ARGS fat32_bpb, word [vbr_fat32_bpb_ptr], (FAT32_bpb_t_size + FAT32_ebpb_t_size)
|
||||
__CDECL16_CALL kmemcpy, 3
|
||||
|
||||
call SetTextMode
|
||||
call disable_cursor_bios
|
||||
|
||||
__CDECL16_CALL_ARGS HelloPrompt_info
|
||||
__CDECL16_CALL PrintString, 1
|
||||
|
||||
; setup the early heap
|
||||
__CDECL16_CALL_ARGS early_heap_state
|
||||
|
||||
__CDECL16_CALL ArenaInit, 1
|
||||
|
||||
__CDECL16_CALL_ARGS pszHelloPrompt
|
||||
__CDECL16_CALL PrintString, 1
|
||||
|
||||
; setup heap space for mbr data
|
||||
__CDECL16_CALL_ARGS 0x200, 0x10
|
||||
__CDECL16_CALL ArenaAlloc, 2
|
||||
mov word [SteviaInfo + SteviaInfoStruct_t.p16_MbrPtr], ax
|
||||
|
||||
push ax ; dst
|
||||
movzx ax, byte [u8_BootDrive]
|
||||
push ax ; boot_drive
|
||||
__CDECL16_CALL FAT32_load_mbr, 2 ; fill/validate mbr buffer
|
||||
|
||||
; setup heap space for vbr data
|
||||
__CDECL16_CALL_ARGS 0x200, 0x10
|
||||
__CDECL16_CALL ArenaAlloc, 2
|
||||
mov word [SteviaInfo + SteviaInfoStruct_t.p16_VbrPtr], ax
|
||||
|
||||
push ax ; dst
|
||||
movzx ax, byte [u8_BootDrive]
|
||||
push ax ; boot_drive
|
||||
__CDECL16_CALL FAT32_load_vbr, 2 ; fill/validate vbr buffer
|
||||
|
||||
; enable A20 gate
|
||||
call EnableA20
|
||||
__CDECL16_CALL_ARGS A20_Enabled_OK_info
|
||||
__CDECL16_CALL_ARGS pszA20EnabledOk
|
||||
__CDECL16_CALL PrintString, 1
|
||||
|
||||
; get system memory map
|
||||
call GetMemoryMap
|
||||
__CDECL16_CALL_ARGS MemoryMap_OK_info
|
||||
__CDECL16_CALL_ARGS pszMemoryMapOk
|
||||
__CDECL16_CALL PrintString, 1
|
||||
|
||||
; enter unreal mode (enter PM w/ 16 bit code, 32 bit flat memory model & return to real)
|
||||
@@ -161,12 +162,12 @@ main:
|
||||
; 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
|
||||
call EnterUnrealMode
|
||||
__CDECL16_CALL_ARGS UnrealMode_OK_info
|
||||
__CDECL16_CALL_ARGS pszUnrealModeOk
|
||||
__CDECL16_CALL PrintString, 1
|
||||
|
||||
; FAT Driver setup
|
||||
;call InitFATDriver
|
||||
;__CDECL16_CALL_ARGS InitFATSYS_OK_info
|
||||
;__CDECL16_CALL_ARGS pszInitFAT32Ok
|
||||
;__CDECL16_CALL PrintString, 1
|
||||
|
||||
;
|
||||
@@ -174,7 +175,7 @@ main:
|
||||
;call SearchFATDIR
|
||||
;push dword eax ; save first cluster of bootable file
|
||||
|
||||
;__CDECL16_CALL_ARGS FileFound_OK_info
|
||||
;__CDECL16_CALL_ARGS pszFileFoundMsg
|
||||
;__CDECL16_CALL PrintString, 1
|
||||
|
||||
;pop dword eax
|
||||
@@ -206,7 +207,7 @@ hcf:
|
||||
%ifnmacro __REFLAT_DS_ES
|
||||
%macro __REFLAT_DS_ES 0
|
||||
cli ; no interrupts
|
||||
lgdt [((__STAGE2_SEGMENT << 4) + unreal_gdt_info)] ; load unreal gdt
|
||||
lgdt [((__STAGE2_SEGMENT << 4) + UnrealGdtInfo)] ; load unreal gdt
|
||||
|
||||
mov eax, cr0
|
||||
or eax, 1 ; set pmode bit
|
||||
@@ -230,7 +231,7 @@ hcf:
|
||||
%ifnmacro __REFLAT_ES
|
||||
%macro __REFLAT_ES 0
|
||||
cli ; no interrupts
|
||||
lgdt [((__STAGE2_SEGMENT << 4) + unreal_gdt_info)] ; load unreal gdt
|
||||
lgdt [((__STAGE2_SEGMENT << 4) + UnrealGdtInfo)] ; load unreal gdt
|
||||
|
||||
mov eax, cr0
|
||||
or eax, 1 ; set pmode bit
|
||||
@@ -253,8 +254,8 @@ ALIGN 4, db 0x90
|
||||
EnterUnrealMode:
|
||||
__CDECL16_PROC_ENTRY
|
||||
cli ; no interrupts
|
||||
.func:
|
||||
lgdt [((__STAGE2_SEGMENT << 4) + unreal_gdt_info)] ; load unreal gdt
|
||||
.proc:
|
||||
lgdt [((__STAGE2_SEGMENT << 4) + UnrealGdtInfo)] ; load unreal gdt
|
||||
|
||||
mov eax, cr0
|
||||
or eax, 1 ; set pmode bit
|
||||
@@ -290,7 +291,8 @@ EnterUnrealMode:
|
||||
end_text:
|
||||
|
||||
section .data follows=.text
|
||||
align 512
|
||||
align 16, db 0
|
||||
|
||||
begin_data:
|
||||
; #############
|
||||
;
|
||||
@@ -299,66 +301,46 @@ begin_data:
|
||||
; #############
|
||||
%define CRLF 0Dh, 0Ah
|
||||
|
||||
%macro define_cstr 2
|
||||
%macro define_cstr 2-*
|
||||
%if %0 > 2
|
||||
align 16
|
||||
%1_cstr:
|
||||
%1:
|
||||
db %{2:-1}, 00h
|
||||
%else
|
||||
align 16
|
||||
%1:
|
||||
db %2, 00h
|
||||
%endif
|
||||
%endmacro
|
||||
|
||||
%macro define_info 2
|
||||
align 16
|
||||
%1_info:
|
||||
db %2, CRLF, 00h
|
||||
%endmacro
|
||||
define_cstr pszHelloPrompt, "Hello from Stevia Stage2!", CRLF
|
||||
define_cstr pszA20EnabledOk, "A20 Enabled OK", CRLF
|
||||
define_cstr pszMemoryMapOk, "Memory map OK", CRLF
|
||||
define_cstr pszUnrealModeOk, "Unreal mode OK", CRLF
|
||||
define_cstr pszInitFAT32Ok, "FAT32 Driver Init OK", CRLF
|
||||
|
||||
define_info HelloPrompt, "Hello from Stevia Stage2!"
|
||||
define_info A20_Enabled_OK, "A20 Enabled OK"
|
||||
define_info MemoryMap_OK, "Memory map OK"
|
||||
define_info UnrealMode_OK, "Unreal mode OK"
|
||||
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 pszFileFoundMsg, "Found SFN entry for bootable binary, first cluster -> ", CRLF
|
||||
define_cstr pszSearchFAT32DirMsg, "Searching FAT fs for bootable file...", CRLF
|
||||
define_cstr pszReadFAT32ClusterMsg, "Attempting to load next FAT", CRLF
|
||||
define_cstr pszMaybeFoundBootMsg, "Maybe found a file...checking...", CRLF
|
||||
|
||||
define_cstr BootTarget, "BOOT BIN"
|
||||
|
||||
align 16, db 0
|
||||
BootTarget:
|
||||
db 'BOOT BIN'
|
||||
|
||||
;
|
||||
; pre-bss init globals (generally const...but there are exceptions)
|
||||
;
|
||||
|
||||
align 8, db 0
|
||||
boot_drive:
|
||||
; set to boot_drive passed from BIOS almost first thing in init
|
||||
align 4, db 0
|
||||
u8_BootDrive:
|
||||
db 0x00
|
||||
|
||||
align 8, db 0
|
||||
partition_offset:
|
||||
dw 0x0000
|
||||
|
||||
align 8, db 0
|
||||
vbr_fat32_bpb_ptr:
|
||||
dw 0x0000
|
||||
|
||||
align 8, db 0
|
||||
vbr_part_table_ptr:
|
||||
dw 0x0000
|
||||
|
||||
align 16, db 0
|
||||
IntToHex_table:
|
||||
db '0123456789ABCDEF'
|
||||
|
||||
; see docs/gdt.txt for a quick refresher on GDT
|
||||
align 16, db 0
|
||||
unreal_gdt_info:
|
||||
unreal_gdt_size: dw (unreal_gdt_end - unreal_gdt_start) - 1
|
||||
unreal_gdt_ptr: dd ((__STAGE2_SEGMENT << 4) + unreal_gdt_start)
|
||||
unreal_gdt_start:
|
||||
UnrealGdtInfo:
|
||||
u16_UnrealGdt_size: dw (UnrealGdtEnd - UnrealGdtStart) - 1
|
||||
pF_UnrealGdtPtr: dd ((__STAGE2_SEGMENT << 4) + UnrealGdtStart)
|
||||
UnrealGdtStart:
|
||||
; entry 0 (null descriptor)
|
||||
dq 0 ; first entry is null
|
||||
|
||||
@@ -375,14 +357,14 @@ unreal_gdt_start:
|
||||
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 0x00 ; Base Address(31:24)
|
||||
unreal_gdt_end:
|
||||
UnrealGdtEnd:
|
||||
|
||||
align 16, db 0
|
||||
gdt32_info:
|
||||
gdt32_size: dw (gdt32_end - gdt32_start) - 1
|
||||
gdt32_ptr: dd ((__STAGE2_SEGMENT << 4) + gdt32_start)
|
||||
gdt32_start:
|
||||
dq 0
|
||||
Gdt32Info:
|
||||
gdt32_size: dw (Gdt32End - Gdt32Start) - 1
|
||||
gdt32_ptr: dd ((__STAGE2_SEGMENT << 4) + Gdt32Start)
|
||||
Gdt32Start:
|
||||
dq 0 ; null segment
|
||||
.gdt32_code:
|
||||
dw 0xFFFF ; code segment (RX)
|
||||
dw 0x0000
|
||||
@@ -411,83 +393,58 @@ gdt32_start:
|
||||
db 1001_0000b ; Access: readable, not writable
|
||||
db 1100_1111b ; 4KB granularity, 32-bit
|
||||
db 0x00
|
||||
gdt32_end:
|
||||
Gdt32End:
|
||||
|
||||
align 16,db 0
|
||||
BUILD_NASM_VER:
|
||||
BuildNasmVer:
|
||||
db "Stevia Stage2 built with NASM - ", __NASM_VER__, 00h
|
||||
|
||||
align 16,db 0
|
||||
BUILD_DATETIME:
|
||||
BuildDateTime:
|
||||
db 'Assembled - ', __DATE__, ' ', __TIME__, 00h
|
||||
|
||||
align 16,db 0
|
||||
BUILD_GIT_VER:
|
||||
BuildGitVer:
|
||||
db __GIT_VER__, 00h
|
||||
|
||||
align 16,db 0
|
||||
BUILD_GIT_HASH:
|
||||
BuildGitHash:
|
||||
db __GIT_HASH__, 00h
|
||||
end_data:
|
||||
|
||||
%assign bytes_remaining ((MAX_STAGE2_BYTES - 512) - (($ - $$) + (end_text - begin_text)))
|
||||
%warning STAGE2 has bytes_remaining bytes remaining for code/data (MAX: MAX_STAGE2_BYTES)
|
||||
%define SIG_BYTES 0x4
|
||||
|
||||
; Optional: fail fast if we overflowed
|
||||
%if ((MAX_STAGE2_BYTES - 512) - (($ - $$) + (end_text - begin_text))) < 0
|
||||
%error "Stage2 overflow: code+data exceed MAX_STAGE2_BYTES - SIG_BYTES"
|
||||
%endif
|
||||
|
||||
; section start location needs to be a 'critical expression'
|
||||
; i.e resolvable at build time, we are setting 0x0500 as the offset since
|
||||
section .sign start=((MAX_STAGE2_BYTES - 512) + 0x0500)
|
||||
times ((512 - 4) - ($ -$$) ) db 0x90 ; nop
|
||||
STAGE2_SIG: dd 0xDEADBEEF ; Signature to mark the end of the stage2
|
||||
|
||||
; !!! END Stage2 .text/.data !!!
|
||||
align 16, resb 1
|
||||
section .bss follows=.sign
|
||||
begin_bss:
|
||||
|
||||
; structures
|
||||
align 16, resb 1
|
||||
SteviaInfo:
|
||||
resd SteviaInfoStruct_t_size
|
||||
|
||||
align 16, resb 1
|
||||
partition_table:
|
||||
resb PartTable_t_size
|
||||
|
||||
align 16, resb 1
|
||||
fat32_bpb:
|
||||
resb FAT32_bpb_t_size
|
||||
fat32_ebpb:
|
||||
resb FAT32_ebpb_t_size
|
||||
|
||||
align 16, resb 1
|
||||
fat32_nc_data:
|
||||
resb 16
|
||||
early_heap_state:
|
||||
resb ArenaStateStruc_t_size
|
||||
|
||||
align 16, resb 1
|
||||
lba_packet:
|
||||
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
|
||||
;
|
||||
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
|
||||
; the e820 function needs to check that it doesn't overflow
|
||||
@@ -496,9 +453,19 @@ align 16, resb 1
|
||||
%define BIOSMemoryMap_SIZE 1024
|
||||
BIOSMemoryMap:
|
||||
resb BIOSMemoryMap_SIZE
|
||||
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).
|
||||
; If BSS_SIZE > BSS_MAX_BYTES, this becomes negative and NASM errors out.
|
||||
%define BSS_MAX_BYTES (0x2000 - STACK_SIZE)
|
||||
resb (BSS_MAX_BYTES - (end_bss - begin_bss))
|
||||
|
||||
align 16, resb 1
|
||||
stack_bottom:
|
||||
resb 1024
|
||||
resb STACK_SIZE
|
||||
stack_top:
|
||||
end_bss:
|
||||
|
||||
; Optional: keep a label for later math:
|
||||
bss_cap_end:
|
||||
@@ -21,14 +21,21 @@
|
||||
%define __STEVIA_VBR
|
||||
section .text
|
||||
__ENTRY:
|
||||
; 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 - $$)
|
||||
nop
|
||||
|
||||
; fill BPB area with 0x00 since we skip writing this part to disk
|
||||
; but we need it for the 'jmp short entry; nop' above
|
||||
times 33 db 0x00
|
||||
; 8 ascii bytes, "MSWIN 4.1", ""
|
||||
phy_bs_ident:
|
||||
times 8 db 0x00
|
||||
|
||||
phy_bpb_start:
|
||||
times 25 db 0x00
|
||||
|
||||
phy_ebpb_start:
|
||||
; fill eBPB area with 0x00 since we skip writing this part to disk
|
||||
times 54 db 0x00
|
||||
|
||||
; ###############
|
||||
@@ -85,36 +92,16 @@ init:
|
||||
%include "util/kmem_func.nasm"
|
||||
%include "util/error_func.nasm"
|
||||
|
||||
; ###############
|
||||
; End Section
|
||||
; ###############
|
||||
|
||||
;
|
||||
; byte boot_drive @ bp - 2
|
||||
; word part_offset @ bp - 4
|
||||
; ptr partition_table
|
||||
ALIGN 4, db 0x90
|
||||
main:
|
||||
mov byte [bp - 2], dl ; boot_drive
|
||||
mov word [bp - 4], si ; part_offset
|
||||
mov word [bp - 6], bx ; partition_table
|
||||
|
||||
.load_fs_data:
|
||||
push PartTable_t_size ; count=
|
||||
push word [bp - 6] ; src= ptr partition_table
|
||||
push partition_table ; dst=
|
||||
call kmemcpy ; copy partition table data to bss
|
||||
add sp, 0x6
|
||||
|
||||
push (FAT32_bpb_t_size + FAT32_ebpb_t_size) ; size in byte, should be 90 bytes
|
||||
push __ENTRY ; src
|
||||
push fat32_bpb ; dst
|
||||
call kmemcpy ; copy bpb & ebpb to bss
|
||||
add sp, 0x6
|
||||
|
||||
.check_FAT_size: ; we only support a very specific setup of FAT32
|
||||
mov bx, fat32_bpb
|
||||
test word [bx + FAT32_bpb_t.unused2_ZERO_word], 0 ; TotSectors16 will not be set if FAT32
|
||||
mov byte [bp - 2], dl ; boot_drive
|
||||
.check_FAT_size: ; we only support a very specific setup of FAT32
|
||||
mov bx, phy_bpb_start
|
||||
test word [bx + FAT32_bpb_t.u16_TotalSectors16], 0 ; TotSectors16 will not be set if FAT32
|
||||
jz main.load_stage2
|
||||
ERROR VBR_ERROR_WRONG_FAT_SIZE
|
||||
.load_stage2:
|
||||
@@ -133,14 +120,10 @@ main:
|
||||
; uint8_t read_stage2_raw(uint16_t buf_segment, uint16_t buf_offset,
|
||||
; uint32_t lba,
|
||||
; uint16_t count, uint16_t drive_num)
|
||||
call read_disk_raw
|
||||
call BIOS_int13h_ext_read
|
||||
add sp, 0xC
|
||||
.enter_stage2:
|
||||
; TODO: review what we pass to stage2, do we need to do this?
|
||||
mov dl, byte [bp - 2] ; byte boot_drive
|
||||
mov ax, word [bp - 4] ; word part_offset
|
||||
mov si, partition_table ; ptr partition_table
|
||||
mov di, fat32_bpb ; ptr fat32_bpb
|
||||
mov dl, byte [bp - 2] ; byte boot_drive
|
||||
jmp word 0x0000:STAGE2_ENTRY
|
||||
|
||||
; ###############
|
||||
@@ -161,18 +144,11 @@ BootSig:
|
||||
section .bss follows=.text
|
||||
begin_bss:
|
||||
|
||||
align 16, resb 1
|
||||
partition_table resb PartTable_t_size
|
||||
|
||||
align 16, resb 1
|
||||
fat32_bpb resb FAT32_bpb_t_size
|
||||
fat32_ebpb resb FAT32_ebpb_t_size
|
||||
|
||||
align 16, resb 1
|
||||
lba_packet resb LBAPkt_t_size
|
||||
|
||||
align 512, resb 1
|
||||
stack_bottom resb (512 - 16) ; 512b stack early on
|
||||
stack_bottom resb (1024 - 16) ; 512b stack early on
|
||||
stack_top:
|
||||
vbr_redzone resb 16
|
||||
end_bss:
|
||||
Reference in New Issue
Block a user