Compare commits
47 Commits
aa0efe5ff8
...
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 | |||
| 3da2af2d2d | |||
| 75d77e92e1 | |||
| 8e6c823a00 | |||
| fca8a5d573 | |||
| f341a50b78 | |||
| ef22bc9cd3 | |||
| 507a05949f | |||
| caed66a243 | |||
| d5cd8d6c45 | |||
| b0f118b139 | |||
| 71d50cdbd8 | |||
| 3c654b1be0 | |||
| 0d90b3efd6 | |||
| b08605f295 |
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:
|
||||
|
||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -11,3 +11,4 @@ stevia-log
|
||||
compose-dev.yaml
|
||||
eth_null-tx.log
|
||||
eth_null-txdump.txt
|
||||
*.log
|
||||
5
Makefile
5
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 \
|
||||
@@ -108,7 +105,7 @@ imgz: $(IMGZ)
|
||||
# Helpers
|
||||
|
||||
run: $(IMG)
|
||||
@$(QEMU) $(QEMU_OPTS) -drive file=$(IMG),if=ide,index=0,media=disk,format=raw \
|
||||
@$(QEMU) $(QEMU_ARGS) -drive file=$(IMG),if=ide,index=0,media=disk,format=raw \
|
||||
|
||||
run_bochs: $(IMG)
|
||||
@bochs -q
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
# Stevia Bootloader
|
||||
|
||||
Stevia is a lightweight, hobby bootloader written in Assembly and C, designed for educational purposes. It targets 686+ and aims to be simple, approachable, and understandable, focusing on minimalism and core functionality.
|
||||
Stevia is a lightweight, hobby bootloader written in Assembly (NASM) and is designed for educational purposes. It targets 686+ and aims to be simple, approachable, and understandable, focusing on minimalism and core functionality.
|
||||
|
||||
Please note: **Most development currently takes place in Bochs (and maybe is tested on QEMU), due to this, the code in this repo has not been tested throughly aginist real hardware. As with most projects of this nature, there is a risk of damage due to improper programing of hardware, while careful effort is taken to not break the computer...accidents and mistakes can/do happen.**
|
||||
|
||||
## Features
|
||||
|
||||
@@ -56,6 +58,8 @@ To build and run Stevia, you will need the following tools installed on your sys
|
||||
|
||||
Stevia is intended to be a learning tool for those interested in low-level programming, focusing on understanding the basics of how a computer starts up and manages early system resources.
|
||||
|
||||
You are welcome to fork/review the code base but I am generally not accepting PR's/Contributions to the code at this time.
|
||||
|
||||
## License
|
||||
|
||||
This project is licensed under the GPLv3 License. See the [LICENSE](LICENSE.md) or [COPYING](COPYING) file for more details.
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -31,29 +31,6 @@ struc LBAPkt_t
|
||||
.lower_lba resd 1
|
||||
.upper_lba resd 1
|
||||
endstruc
|
||||
; call_read_disk_raw <word segment> <word offset> <dword lba> <word count> <word drive_num>
|
||||
%macro call_read_disk_raw 5
|
||||
movzx ax, %5
|
||||
push ax ; drive_num
|
||||
|
||||
movzx ax, %4
|
||||
push ax ; count
|
||||
|
||||
movzx dword eax, %3
|
||||
push dword eax ; lba
|
||||
|
||||
movzx ax, %2
|
||||
push ax ; offset
|
||||
|
||||
movzx ax, %1
|
||||
push ax ; segment = 0
|
||||
|
||||
; 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
|
||||
add sp, 0xC
|
||||
%endmacro
|
||||
|
||||
; Wrapper for AH=0x42 INT13h (Extended Read)
|
||||
;
|
||||
@@ -70,21 +47,17 @@ endstruc
|
||||
; disk address packet's block count field set to number of blocks
|
||||
; successfully transferred
|
||||
;
|
||||
;
|
||||
; uint8_t read_stage2_raw(uint16_t buf_segment, uint16_t buf_offset,
|
||||
; 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:
|
||||
mov ax, LBAPkt_t_size
|
||||
push ax ; len
|
||||
xor ax, ax
|
||||
push ax ; val = 0
|
||||
mov ax, lba_packet
|
||||
push ax ; dest = lba_packet address
|
||||
call kmemset
|
||||
push LBAPkt_t_size ; len
|
||||
push 0x00 ; val = 0
|
||||
push lba_packet ; dest = lba_packet address
|
||||
call kmemset ; kmemset(dst, val, len)
|
||||
add sp, 0x06
|
||||
|
||||
mov bx, lba_packet
|
||||
@@ -97,7 +70,8 @@ read_disk_raw:
|
||||
mov dword [bx + LBAPkt_t.lower_lba], eax
|
||||
|
||||
; upper_lba is zero from kmemset
|
||||
; TODO: possiblly support >32bit LBA addresses in the future, this limits us to 4GiB
|
||||
; TODO: possiblly support >32bit LBA addresses in the future
|
||||
; this will limit us to (4GiB * sector size) of readable lba's from the disk
|
||||
|
||||
mov ax, [bp + 6]
|
||||
mov word [bx + LBAPkt_t.offset], ax
|
||||
@@ -120,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
|
||||
|
||||
@@ -42,6 +42,7 @@
|
||||
; __CDECL16_PROC_ARGS nargs
|
||||
; Creates %$arg1 .. %$argN as [bp+4], [bp+6], ...
|
||||
; for use inside of function bodies
|
||||
; BUG: still needs to be tested
|
||||
%ifnmacro __CDECL16_PROC_ARGS
|
||||
%macro __CDECL16_PROC_ARGS 1
|
||||
%push __CDECL16_PROC_ARGS
|
||||
@@ -78,6 +79,7 @@
|
||||
; __CDECL16_CALL_ARGS_SIZED func, size1[, size2 ...] ; sizes in BYTES
|
||||
; if you *need* to pass dword sized args in 16-bit mode, use this to properly
|
||||
; count the stack frame to restore later!
|
||||
; BUG: still needs to be tested
|
||||
%ifnmacro __CDECL16_CALL_ARGS_SIZED
|
||||
%macro __CDECL16_CALL_ARGS_SIZED 2-*
|
||||
%push __CDECL16_CALL_ARGS_SIZED
|
||||
@@ -124,13 +126,21 @@
|
||||
%endmacro
|
||||
%endif
|
||||
|
||||
;
|
||||
; Only setup the minimum stack frame
|
||||
; unlike the above, everything is caller save
|
||||
;
|
||||
%ifnmacro __FASTCALL16_ENTRY
|
||||
%macro __FASTCALL16_ENTRY 0
|
||||
%macro __FASTCALL16_ENTRY 0-1
|
||||
push bp
|
||||
mov bp, sp
|
||||
%if %0 = 1
|
||||
sub sp, %1 ; reserve locals only when needed
|
||||
%endif
|
||||
%endmacro
|
||||
%endif
|
||||
|
||||
; restore minimum stack frame, all regs are caller save
|
||||
%ifnmacro __FASTCALL16_EXIT
|
||||
%macro __FASTCALL16_EXIT 0
|
||||
mov sp, bp
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -1,28 +0,0 @@
|
||||
; Copyright (C) 2025 Elaina Claus
|
||||
;
|
||||
; This program is free software: you can redistribute it and/or modify
|
||||
; it under the terms of the GNU General Public License as published by
|
||||
; the Free Software Foundation, either version 3 of the License, or
|
||||
; (at your option) any later version.
|
||||
;
|
||||
; This program is distributed in the hope that it will be useful,
|
||||
; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
; GNU General Public License for more details.
|
||||
;
|
||||
; You should have received a copy of the GNU General Public License
|
||||
; along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
%ifndef __INC_EARLY_MEM
|
||||
|
||||
;PhysicalAddress = Segment * 16 + Offset
|
||||
%define SEG_TO_LINEAR(s,o) ((s << 4) + o)
|
||||
|
||||
; Offset = physical / (Segment * 16)
|
||||
%define LINEAR_TO_OFFSET(p,s) ((p / (s << 4)))
|
||||
|
||||
; Seg = (physical - offset) / 16
|
||||
%define LINEAR_TO_SEGMENT(p,o) ((p - o) >> 4)
|
||||
|
||||
%endif
|
||||
%define __INC_EARLY_MEM
|
||||
@@ -15,7 +15,7 @@
|
||||
|
||||
%ifndef __INC_ENTRY
|
||||
|
||||
%define MBR_ENTRY 0x8C00
|
||||
%define MBR_ENTRY 0x6C00
|
||||
%define VBR_ENTRY 0x7C00
|
||||
%define STAGE2_ENTRY 0x0500
|
||||
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
; along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
[BITS 16]
|
||||
[ORG 0x8C00]
|
||||
[ORG 0x6C00]
|
||||
[CPU KATMAI]
|
||||
[WARNING -reloc-abs-byte]
|
||||
[WARNING -reloc-abs-word] ; Yes, we use absolute addresses. surpress these warnings.
|
||||
@@ -33,10 +33,10 @@ nop
|
||||
%include "config.inc"
|
||||
%include "error_codes.inc"
|
||||
%include "partition_table.inc"
|
||||
%include "fat32/fat32_structures.inc"
|
||||
|
||||
%undef __STEVIA_DEV_DEBUG
|
||||
|
||||
; BIOS will load 1st sector of boot drive to 0x7c00, init and relocate
|
||||
ALIGN 4
|
||||
init:
|
||||
cli ; We do not want to be interrupted
|
||||
@@ -58,14 +58,14 @@ init:
|
||||
cld
|
||||
rep stosb ; zero bss section
|
||||
|
||||
sub sp, 0x20 ; local varible space (32 bytes)
|
||||
sub sp, 0x10 ; local varible space (32 bytes)
|
||||
push bp ; setup top of stack frame
|
||||
|
||||
xor cx, cx
|
||||
mov ch, 0x02 ; 0x0200 in cx
|
||||
mov si, 0x7C00 ; Current MBR Address (loaded here by BIOS)
|
||||
mov di, MBR_ENTRY ; New MBR Address (our new relocation address)
|
||||
rep movsb ; copy 512 bytes from 0x0000:7c00 to 0x0000:MBR_ENTRY (7A00 as of writing)
|
||||
rep movsb ; copy 512 bytes from 0x0000:7c00 to 0x0000:MBR_ENTRY (6C00 as of writing)
|
||||
|
||||
sti
|
||||
|
||||
@@ -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
|
||||
@@ -121,42 +121,26 @@ main:
|
||||
mov word [bp - 4], ax ; update part_offset
|
||||
.read_data:
|
||||
movzx ax, byte [bp - 2]
|
||||
push ax ; drive_num
|
||||
|
||||
mov ax, 0x1
|
||||
push ax ; count
|
||||
push ax ; drive_num (2)
|
||||
push 0x01 ; count (2)
|
||||
|
||||
mov dword eax, dword [bx + PartEntry_t.lba_start]
|
||||
push dword eax ; lba
|
||||
push dword eax ; lba (4)
|
||||
|
||||
mov ax, VBR_ENTRY
|
||||
push ax ; offset = 0x7c00
|
||||
|
||||
xor ax, ax
|
||||
push ax ; segment = 0
|
||||
push word 0x7C00 ; offset = 0x7c00 (2)
|
||||
push 0x00 ; segment = 0 (2)
|
||||
|
||||
; 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
|
||||
ERROR MBR_ERROR_NO_VBR_SIG ; no signature present
|
||||
.sig_ok:
|
||||
mov ax, PartTable_t_size
|
||||
push ax
|
||||
mov ax, DiskSig ; start of partition table
|
||||
push ax
|
||||
mov ax, partition_table
|
||||
push ax
|
||||
call kmemcpy ; copy partition table to bss
|
||||
add sp, 0x6
|
||||
|
||||
mov si, word [bp - 4]
|
||||
mov dl, byte [bp - 2]
|
||||
mov bx, partition_table
|
||||
mov dl, byte [bp - 2] ; pass drive # from BIOS to VBR in dl
|
||||
jmp word 0x0000:VBR_ENTRY
|
||||
|
||||
; ###############
|
||||
@@ -185,18 +169,15 @@ PartEntry4:
|
||||
times 16 db 0x00
|
||||
BootSig:
|
||||
dw 0xAA55 ; Add boot signature at the end of bootloader
|
||||
|
||||
; !!! end of MBR !!!
|
||||
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 ; 512 byte stack early on
|
||||
stack_bottom resb 1024 - 16 ; 512 byte stack early on
|
||||
stack_top:
|
||||
mbr_redzone resb 32
|
||||
mbr_redzone resb 16
|
||||
end_bss:
|
||||
@@ -31,24 +31,15 @@
|
||||
%include "cdecl16.inc"
|
||||
%include "entry.inc"
|
||||
%include "config.inc"
|
||||
%include "early_mem.inc"
|
||||
%include "error_codes.inc"
|
||||
|
||||
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,9 +90,8 @@ init:
|
||||
; ###############
|
||||
|
||||
%include "partition_table.inc"
|
||||
%include "fat32/bpb_offset_bx.inc"
|
||||
%include "fat32/fat32_structures.inc"
|
||||
;%include 'fat32/FAT32_SYS.inc'
|
||||
%include 'fat32/FAT32_SYS.nasm'
|
||||
|
||||
; ###############
|
||||
; BIOS functions
|
||||
@@ -112,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
|
||||
@@ -131,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)
|
||||
@@ -163,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
|
||||
|
||||
;
|
||||
@@ -176,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
|
||||
@@ -208,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
|
||||
@@ -232,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
|
||||
@@ -255,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
|
||||
@@ -292,7 +291,8 @@ EnterUnrealMode:
|
||||
end_text:
|
||||
|
||||
section .data follows=.text
|
||||
align 512
|
||||
align 16, db 0
|
||||
|
||||
begin_data:
|
||||
; #############
|
||||
;
|
||||
@@ -301,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
|
||||
|
||||
@@ -377,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
|
||||
@@ -413,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 - 4) - (($ - $$) + (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 0x7E00 as the offset since
|
||||
; 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
|
||||
@@ -498,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
|
||||
|
||||
; ###############
|
||||
@@ -41,7 +48,6 @@ times 54 db 0x00
|
||||
%include "cdecl16.inc"
|
||||
%include "entry.inc"
|
||||
%include "config.inc"
|
||||
%include "early_mem.inc"
|
||||
%include "error_codes.inc"
|
||||
%include "partition_table.inc"
|
||||
%include "fat32/fat32_structures.inc"
|
||||
@@ -72,7 +78,7 @@ init:
|
||||
cld
|
||||
rep stosb
|
||||
|
||||
sub sp, 0x20 ; local varible space (32 bytes)
|
||||
sub sp, 0x10 ; local varible space (32 bytes)
|
||||
push bp
|
||||
|
||||
sti ; all done with inital setup and relocation, reenable interupts
|
||||
@@ -86,42 +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:
|
||||
mov ax, PartTable_t_size ; count=
|
||||
push ax
|
||||
mov ax, [bp - 6] ; src= ptr partition_table
|
||||
push ax
|
||||
mov ax, partition_table ; dst=
|
||||
push ax
|
||||
call kmemcpy ; copy partition table data
|
||||
add sp, 0x6
|
||||
|
||||
mov ax, (FAT32_bpb_t_size + FAT32_ebpb_t_size) ; size in byte, should be 90 bytes
|
||||
push ax
|
||||
mov ax, __ENTRY
|
||||
push ax
|
||||
mov ax, fat32_bpb ;
|
||||
push ax
|
||||
call kmemcpy ; copy bpb & ebpb to memory
|
||||
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:
|
||||
@@ -129,28 +109,21 @@ main:
|
||||
movzx ax, byte [bp - 2]
|
||||
push ax ; drive_num
|
||||
|
||||
mov ax, STAGE2_SECTOR_COUNT
|
||||
push ax ; count
|
||||
push STAGE2_SECTOR_COUNT ; count
|
||||
|
||||
mov dword eax, 0x1
|
||||
push dword eax ; lba
|
||||
|
||||
mov ax, STAGE2_ENTRY
|
||||
push ax ; offset
|
||||
|
||||
xor ax, ax
|
||||
push ax ; segment = 0
|
||||
push STAGE2_ENTRY ; offset
|
||||
push 0x00 ; segment = 0
|
||||
|
||||
; 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:
|
||||
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
|
||||
|
||||
; ###############
|
||||
@@ -166,25 +139,16 @@ times (510 - ($ - $$)) nop ; Fill the rest of sector with nop
|
||||
|
||||
BootSig:
|
||||
dw 0xAA55 ; Add boot signature at the end of bootloader
|
||||
; !!! END VBR !!!
|
||||
|
||||
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
|
||||
fat32_nc_data resb 16
|
||||
|
||||
align 16, resb 1
|
||||
lba_packet resb LBAPkt_t_size
|
||||
|
||||
align 512, resb 1
|
||||
stack_bottom resb 512 ; 512b stack early on
|
||||
stack_bottom resb (1024 - 16) ; 512b stack early on
|
||||
stack_top:
|
||||
vbr_redzone resb 32
|
||||
vbr_redzone resb 16
|
||||
end_bss:
|
||||
Reference in New Issue
Block a user