29 Commits

Author SHA1 Message Date
528e3d69fe update github workflow since github includes firefox & snaps in the default runner image, which causes the build to fail.
All checks were successful
Daily Build and trunk tester / debian_update (push) Successful in 1m11s
going to need a custom runner I guess...might as well only do actions on gitea.
2025-09-16 08:34:22 -04:00
9a6fea658d bugs
All checks were successful
Daily Build and trunk tester / debian_update (push) Successful in 51s
2025-09-07 18:43:03 -04:00
891bff9509 use __CDECL16 macros and clean up a few proc calls 2025-09-07 17:38:21 -04:00
1e181bc22c remove print_string macro 2025-09-07 16:25:08 -04:00
68c8200aa4 remove invoke macro for now 2025-09-07 16:21:19 -04:00
766c67c041 first calls to use the new cdecl16 macros 2025-09-07 16:11:18 -04:00
49d82be0e8 use rotate instead of stack context in macros 2025-09-07 16:10:59 -04:00
69bd7d8f56 small clean up and use configured segment for return to real mode 2025-09-07 14:50:40 -04:00
875527aa98 output to bochs magic debug port as well 2025-09-07 14:49:21 -04:00
c0d47d4db0 re-organize bochs config, added USB 1.0/1.1/2.0 and e1000 network 2025-09-07 14:48:35 -04:00
81a3442ac5 remove magic debug from unrealmode entry 2025-09-07 13:51:23 -04:00
3ec55f5a39 change some macro names to make them more clear 2025-09-07 13:33:26 -04:00
9493aefa68 rename __CDECL16_ENTRY and EXIT 2025-09-07 13:29:24 -04:00
6f2fc627be new fancy macros to make it nicer to call functions 2025-09-07 13:16:37 -04:00
20c715fadd update notes on unreal entry 2025-09-07 13:15:40 -04:00
920c623a93 update README.md
All checks were successful
Daily Build and trunk tester / debian_update (push) Successful in 1m5s
2025-09-06 13:56:00 -04:00
af8e7d74d3 I don't plan on using mmx/sse, set the minimum cpu to a 686 2025-09-06 13:55:45 -04:00
fde7abc544 replace or opcode with test
test only updates flags
2025-09-06 08:38:16 -04:00
69223a1ad2 explaination on the power of two stuff
All checks were successful
Daily Build and trunk tester / debian_update (push) Successful in 1m21s
2025-09-05 20:54:29 -04:00
130cd22ff1 remove unreal mode stuff from cdecl16.inc 2025-09-05 20:33:00 -04:00
4e5112b45b move unreal mode hackery back to stage2.nasm 2025-09-05 20:32:19 -04:00
66e8e3c7fc prototype allocate function 2025-09-05 19:55:08 -04:00
b0bd4b27b0 🎉 simple allocator init in the code 2025-09-05 16:48:24 -04:00
cd316afdd1 basic arena allocator implementation 2025-09-05 16:42:25 -04:00
9a478aa4d4 added another __REFLAT variant 2025-09-05 16:28:01 -04:00
31d05c35e5 move __TINY_DS_ES to unreal_mode function
also some cleanup
2025-09-05 16:18:34 -04:00
534e04ef34 fix a typo 2025-09-05 15:48:43 -04:00
f58bf93507 don't exit if we are running as root
just warn
2025-09-05 15:45:33 -04:00
b5ae11f850 set ds/es to a tiny memory model after entering Unreal mode
ss/fs/gs will all be huge/flat model after
2025-09-05 15:43:22 -04:00
16 changed files with 414 additions and 257 deletions

View File

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

2
.gitignore vendored
View File

@@ -9,3 +9,5 @@ stevia-log
.vscode/ .vscode/
*.map *.map
compose-dev.yaml compose-dev.yaml
eth_null-tx.log
eth_null-txdump.txt

View File

@@ -1,6 +1,6 @@
# Stevia Bootloader # Stevia Bootloader
Stevia is a lightweight, hobby bootloader written in Assembly and C, designed for educational purposes. It targets x86 (Pentium III era) and aims to be simple, approachable, and understandable, focusing on minimalism and core functionality. 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.
## Features ## Features
@@ -10,18 +10,13 @@ Stevia is a lightweight, hobby bootloader written in Assembly and C, designed fo
- **Stage 2 Bootloader**: Loads the kernel into memory and passes control. - **Stage 2 Bootloader**: Loads the kernel into memory and passes control.
- **Basic Filesystem Support**: Initial filesystem recognition (details depend on implemented filesystem support). - **Basic Filesystem Support**: Initial filesystem recognition (details depend on implemented filesystem support).
- **Memory Map Parsing**: Detects available memory regions via BIOS interrupts. - **Memory Map Parsing**: Detects available memory regions via BIOS interrupts.
- **GDT Initialization**: Sets up the Global Descriptor Table for protected mode. - **GDT Initialization**: Sets up the Global Descriptor Table for protected/unreal mode.
### In Progress
- **Interrupt Descriptor Table (IDT) Setup**: Setting up basic interrupt handling.
- **Basic Keyboard Input**: Initial support for capturing keystrokes.
### Planned Features ### Planned Features
- **Task Scheduling**: Basic round-robin task switching. - **Interrupt Descriptor Table (IDT) Setup**: Setting up basic interrupt handling.
- **Basic Keyboard Input**: Initial support for capturing keystrokes.
- **Filesystem Expansion**: Support for additional filesystems. - **Filesystem Expansion**: Support for additional filesystems.
- **More Robust Driver Support**: Additional hardware drivers, such as for storage devices.
## Installation ## Installation
@@ -29,41 +24,37 @@ Stevia is a lightweight, hobby bootloader written in Assembly and C, designed fo
To build and run Stevia, you will need the following tools installed on your system: To build and run Stevia, you will need the following tools installed on your system:
- **Assembler**: NASM for assembling bootloader components. - **Assembler**: NASM for assembling bootloader components, you could use a compatible assembler but YMMV.
- **C Compiler**: GCC (cross-compiler recommended). - **GNU make**: For building the project.
- **Emulator**: Bochs or QEMU for testing. - **mtools**: To access the FAT partition
- **GNU Make**: For building the project. - **fdisk**: To create disk images and setup partition tables
- **Utilities**: - **dosfstools**: FAT32 creation
- **dd**: For creating raw disk images. - **an x86 Emulator**: Bochs is the primary dev target, but stevia should run on any x86 emulator/hardware with at least a Pentium 3 and 640KiB of memory.
- **losetup** (Linux only): For associating loop devices with disk images.
- **sfdisk**: For creating DOS disk partitions.
- **mkfs.fat**: For formatting partitions as FAT32.
- **hdiutil** (macOS only): For attaching disk images.
- **newfs\_msdos** (macOS only): For formatting FAT32 partitions.
### Building and Running ### Building and Running
1. **Clone the repository**: 1. **Clone the repository**:
```sh ```sh
git clone https://github.com/Nivirx/stevia.git git clone https://github.com/Nivirx/stevia.git
cd stevia cd stevia
``` ```
2. **Build the bootloader and create a bootable disk image**: 2. **Build the bootloader and create a bootable disk image**:
```sh ```sh
sudo make make
``` ```
3. **Run using Bochs**: 3. **Run using Bochs**:
```sh ```sh
bochs -f bochsrc.txt bochs -q -f bochsrc.txt
``` ```
## Project Goals ## Project Goals
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. Contributions and forks are welcome, especially from those interested in expanding the functionality. 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.
## Contributing
We welcome contributions! Feel free to open issues for bugs or feature requests, and submit pull requests for any improvements. Please ensure that your code follows the existing style and includes appropriate comments.
## License ## License

View File

@@ -1,44 +1,44 @@
# configuration file generated by Bochs #
plugin_ctrl: voodoo=false, unmapped=true, biosdev=true, speaker=true, extfpuirq=true, parallel=true, serial=true, busmouse=false, e1000=false, es1370=false, gameport=true, ne2k=false, sb16=false, usb_uhci=false, usb_ohci=false, usb_ehci=false, usb_xhci=false # Bochs config
#
config_interface: textconfig config_interface: textconfig
display_library: x, options=gui_debug display_library: x, options=gui_debug
memory: guest=64, host=64, block_size=128 plugin_ctrl: voodoo=false, unmapped=true, biosdev=true, speaker=true, extfpuirq=true, parallel=true, serial=true, busmouse=false, e1000=true, es1370=false, gameport=true, ne2k=false, sb16=false, usb_uhci=true, usb_ohci=false, usb_ehci=false, usb_xhci=false
romimage: file="/usr/share/bochs/BIOS-bochs-legacy", address=0x00000000, options=none, flash_data=none print_timestamps: enabled=1
vgaromimage: file="/usr/share/bochs/VGABIOS-lgpl-latest"
boot: disk
floppy_bootsig_check: disabled=0
floppya: type=1_44
# no floppyb
ata0: enabled=true, ioaddr1=0x1f0, ioaddr2=0x3f0, irq=14
ata0-master: type=disk, path="./build/disk.img", mode=flat, cylinders=0, heads=0, spt=0, sect_size=512, model="Stevia Disk", biosdetect=auto, translation=lba
ata0-slave: type=none
ata1: enabled=false
ata1-master: type=none
ata1-slave: type=none
ata2: enabled=false
ata3: enabled=false
optromimage1: file=none
optromimage2: file=none
optromimage3: file=none
optromimage4: file=none
optramimage1: file=none
optramimage2: file=none
optramimage3: file=none
optramimage4: file=none
pci: enabled=1, chipset=i440fx, slot1=none, slot2=none, slot3=none, slot4=none, slot5=none
vga: extension=vbe, update_freq=10, realtime=1, ddc=builtin
cpu: count=1, ips=1000000, model=p3_katmai, reset_on_triple_fault=1, cpuid_limit_winnt=0, ignore_bad_msrs=1, mwait_is_nop=0
print_timestamps: enabled=0
port_e9_hack: enabled=false, all_rings=false
private_colormap: enabled=0 private_colormap: enabled=0
clock: sync=none, time0=local, rtc_sync=0
# no cmosimage
log: - log: -
logprefix: %t%e%d logprefix: %t%e%d
debug: action=ignore debug: action=ignore
info: action=report info: action=report
error: action=report error: action=report
panic: action=ask panic: action=ask
magic_break: enabled=1
port_e9_hack: enabled=1, all_rings=false
#
# Machine Spec
# 1x Pentium 3 @ (1M IPS) w/ 64MiB of System memory on the i440fx
cpu: count=1, ips=1000000, model=p3_katmai, reset_on_triple_fault=0, cpuid_limit_winnt=0, ignore_bad_msrs=1, mwait_is_nop=0
memory: guest=64, host=64, block_size=128
romimage: file="/usr/share/bochs/BIOS-bochs-legacy", address=0x00000000, options=none, flash_data=none
vgaromimage: file="/usr/share/vgabios/vgabios-stdvga.bin"
pci: enabled=1, chipset=i440fx
vga: extension=vbe, update_freq=10, realtime=1, ddc=builtin
clock: sync=none, time0=local, rtc_sync=0
#
# Disks
#
boot: disk
floppy_bootsig_check: disabled=0
floppya: type=1_44
floppyb: type=1_44
ata0: enabled=true, ioaddr1=0x1f0, ioaddr2=0x3f0, irq=14
ata0-master: type=disk, path="./build/disk.img", mode=flat, cylinders=0, heads=0, spt=0, sect_size=512, model="Stevia Disk", biosdetect=auto, translation=lba
ata0-slave: type=none
#
# Other hardware
#
usb_ehci: enabled=1, companion=ohci
e1000: enabled=1, mac=52:54:00:12:34:56, ethmod=null
keyboard: type=mf, serial_delay=150, paste_delay=100000, user_shortcut=none keyboard: type=mf, serial_delay=150, paste_delay=100000, user_shortcut=none
mouse: type=none, enabled=false, toggle=ctrl+mbutton mouse: type=none, enabled=false, toggle=ctrl+mbutton
sound: waveoutdrv=dummy, waveout=none, waveindrv=dummy, wavein=none, midioutdrv=dummy, midiout=none sound: waveoutdrv=dummy, waveout=none, waveindrv=dummy, wavein=none, midioutdrv=dummy, midiout=none
@@ -49,5 +49,3 @@ com1: enabled=true, mode=null
com2: enabled=false com2: enabled=false
com3: enabled=false com3: enabled=false
com4: enabled=false com4: enabled=false
magic_break: enabled=1
port_e9_hack: enabled=1, all_rings=false

View File

@@ -35,7 +35,7 @@ endstruc
ALIGN 4, db 0x90 ALIGN 4, db 0x90
GetMemoryMap: GetMemoryMap:
__CDECL16_ENTRY __CDECL16_PROC_ENTRY
push es ; save segment register push es ; save segment register
.func: .func:
mov dword [SteviaInfo + SteviaInfoStruct_t.MemoryMapEntries], 0 mov dword [SteviaInfo + SteviaInfoStruct_t.MemoryMapEntries], 0
@@ -83,11 +83,11 @@ GetMemoryMap:
ERROR STAGE2_MM_E820_NO_SMAP ERROR STAGE2_MM_E820_NO_SMAP
.endp: .endp:
pop es pop es
__CDECL16_EXIT __CDECL16_PROC_EXIT
ret ret
PrintMemoryMap: PrintMemoryMap:
__CDECL16_ENTRY __CDECL16_PROC_ENTRY
.func: .func:
mov eax, dword [SteviaInfo + SteviaInfoStruct_t.MemoryMapEntries] mov eax, dword [SteviaInfo + SteviaInfoStruct_t.MemoryMapEntries]
cmp eax, 0 cmp eax, 0
@@ -106,15 +106,15 @@ PrintMemoryMap:
; print_string strformat_buffer ; print_string strformat_buffer
.endp: .endp:
__CDECL16_EXIT __CDECL16_PROC_EXIT
ret ret
FormatMemoryMapEntry: FormatMemoryMapEntry:
__CDECL16_ENTRY __CDECL16_PROC_ENTRY
.func: .func:
; create a string buffer somewhere and return address to result string in ax ; create a string buffer somewhere and return address to result string in ax
.endp: .endp:
__CDECL16_EXIT __CDECL16_PROC_EXIT
ret ret

View File

@@ -64,7 +64,7 @@
; Bits 6-7 - 00: HDD activity LED off; any other value is "on" ; Bits 6-7 - 00: HDD activity LED off; any other value is "on"
ALIGN 4, db 0x90 ALIGN 4, db 0x90
EnableA20: EnableA20:
__CDECL16_ENTRY __CDECL16_PROC_ENTRY
push ds push ds
push es push es
.a20_check: .a20_check:
@@ -134,7 +134,7 @@ EnableA20:
.endp: .endp:
pop es pop es
pop ds pop ds
__CDECL16_EXIT __CDECL16_PROC_EXIT
ret ret
%endif %endif

View File

@@ -76,7 +76,7 @@ endstruc
; uint16_t count, uint8_t drive_num) ; uint16_t count, uint8_t drive_num)
ALIGN 4, db 0x90 ALIGN 4, db 0x90
read_disk_raw: read_disk_raw:
__CDECL16_ENTRY __CDECL16_PROC_ENTRY
.func: .func:
mov ax, LBAPkt_t_size mov ax, LBAPkt_t_size
push ax ; len push ax ; len
@@ -123,7 +123,7 @@ read_disk_raw:
ERROR STAGE2_MBR_DISK_READ_ERROR ERROR STAGE2_MBR_DISK_READ_ERROR
%endif %endif
.endf: .endf:
__CDECL16_EXIT __CDECL16_PROC_EXIT
ret ret
%endif %endif

View File

@@ -20,7 +20,7 @@
ALIGN 4, db 0x90 ALIGN 4, db 0x90
SetTextMode: SetTextMode:
.prolog: .prolog:
__CDECL16_ENTRY __CDECL16_PROC_ENTRY
pushf pushf
.func: .func:
xor ah, ah ; Set Video mode BIOS function xor ah, ah ; Set Video mode BIOS function
@@ -33,14 +33,14 @@ SetTextMode:
int 0x10 ; call video interrupt int 0x10 ; call video interrupt
.endp: .endp:
popf popf
__CDECL16_EXIT __CDECL16_PROC_EXIT
ret ret
; disables blinking text mode cursor via crtc pokes ; disables blinking text mode cursor via crtc pokes
; 0x3D4/0x3D5 for color, mono at 0x3B4/0x3B5 ; 0x3D4/0x3D5 for color, mono at 0x3B4/0x3B5
ALIGN 4, db 0x90 ALIGN 4, db 0x90
disable_cursor_crtc: disable_cursor_crtc:
__CDECL16_ENTRY __CDECL16_PROC_ENTRY
.func: .func:
mov dx, 0x3D4 mov dx, 0x3D4
mov al, 0xA ; low cursor shape register mov al, 0xA ; low cursor shape register
@@ -50,13 +50,13 @@ disable_cursor_crtc:
mov al, 0x20 ; bits 6-7 unused, bit 5 disables the cursor, bits 0-4 control the cursor shape mov al, 0x20 ; bits 6-7 unused, bit 5 disables the cursor, bits 0-4 control the cursor shape
out dx, al out dx, al
.endp: .endp:
__CDECL16_EXIT __CDECL16_PROC_EXIT
ret ret
; disables blinking text mode cursor via BIOS int 10h, ah = 01 ; disables blinking text mode cursor via BIOS int 10h, ah = 01
ALIGN 4, db 0x90 ALIGN 4, db 0x90
disable_cursor_bios: disable_cursor_bios:
__CDECL16_ENTRY __CDECL16_PROC_ENTRY
.func: .func:
push bx push bx
mov ah, 03h ; read cursor pos & shape mov ah, 03h ; read cursor pos & shape
@@ -68,14 +68,14 @@ disable_cursor_bios:
int 10h int 10h
pop bx pop bx
.endp: .endp:
__CDECL16_EXIT __CDECL16_PROC_EXIT
ret ret
; Prints a C-Style string (null terminated) using BIOS vga teletype call ; Prints a C-Style string (null terminated) using BIOS vga teletype call
; void PrintString(char* buf) ; void PrintString(char* buf)
ALIGN 4, db 0x90 ALIGN 4, db 0x90
PrintString: PrintString:
__CDECL16_ENTRY __CDECL16_PROC_ENTRY
mov di, [bp + 4] ; first arg is char[] mov di, [bp + 4] ; first arg is char[]
.str_len: .str_len:
xor cx, cx ; ECX = 0 xor cx, cx ; ECX = 0
@@ -91,6 +91,9 @@ PrintString:
mov si, [bp + 4] ; source string mov si, [bp + 4] ; source string
.print_L0: .print_L0:
movzx ax, byte [si] movzx ax, byte [si]
%ifdef __STEVIA_DEV_DEBUG
out 0xe9, byte al ; bochs magic debug port
%endif
push ax push ax
call PrintCharacter call PrintCharacter
add sp, 0x2 add sp, 0x2
@@ -101,14 +104,14 @@ PrintString:
jcxz PrintString.endp jcxz PrintString.endp
jmp PrintString.print_L0 ; Fetch next character from string jmp PrintString.print_L0 ; Fetch next character from string
.endp: .endp:
__CDECL16_EXIT __CDECL16_PROC_EXIT
ret ; Return from procedure ret ; Return from procedure
; Prints a single character ; Prints a single character
; void PrintCharacter(char c); ; void PrintCharacter(char c);
ALIGN 4, db 0x90 ALIGN 4, db 0x90
PrintCharacter: PrintCharacter:
__CDECL16_ENTRY __CDECL16_PROC_ENTRY
.func: .func:
mov al, byte [bp + 4] ; AL = character c mov al, byte [bp + 4] ; AL = character c
mov ah, 0x0E ; INT 0x10, AH=0x0E call mov ah, 0x0E ; INT 0x10, AH=0x0E call
@@ -116,7 +119,7 @@ PrintCharacter:
int 0x10 ; call video interrupt int 0x10 ; call video interrupt
; TODO: check for carry and clear carry before call ; TODO: check for carry and clear carry before call
.endp: .endp:
__CDECL16_EXIT __CDECL16_PROC_EXIT
ret ret
; TODO: fix the prolog, epilog and stack usage to confirm with cdecl16 ; TODO: fix the prolog, epilog and stack usage to confirm with cdecl16
@@ -124,7 +127,7 @@ PrintCharacter:
; void PrintDWORD(uint32_t val); ; void PrintDWORD(uint32_t val);
ALIGN 4, db 0x90 ALIGN 4, db 0x90
PrintDWORD: PrintDWORD:
__CDECL16_ENTRY __CDECL16_PROC_ENTRY
.func: .func:
mov si, IntToHex_table mov si, IntToHex_table
mov ebx, 16 ; base-16 mov ebx, 16 ; base-16
@@ -166,7 +169,7 @@ PrintDWORD:
jmp PrintDWORD.print_stack jmp PrintDWORD.print_stack
.endp: .endp:
__CDECL16_EXIT __CDECL16_PROC_EXIT
ret ret
%endif %endif
%define __INC_VIDEO %define __INC_VIDEO

View File

@@ -13,8 +13,8 @@
; You should have received a copy of the GNU General Public License ; You should have received a copy of the GNU General Public License
; along with this program. If not, see <https://www.gnu.org/licenses/>. ; along with this program. If not, see <https://www.gnu.org/licenses/>.
%ifnmacro __CDECL16_ENTRY %ifnmacro __CDECL16_PROC_ENTRY
%macro __CDECL16_ENTRY 0-1 %macro __CDECL16_PROC_ENTRY 0-1
push bp push bp
mov bp, sp mov bp, sp
@@ -28,8 +28,8 @@
%endmacro %endmacro
%endif %endif
%ifnmacro __CDECL16_EXIT %ifnmacro __CDECL16_PROC_EXIT
%macro __CDECL16_EXIT 0 %macro __CDECL16_PROC_EXIT 0
pop bx pop bx
pop di pop di
pop si pop si
@@ -39,19 +39,88 @@
%endmacro %endmacro
%endif %endif
%ifnmacro __CDECL16_CALLER_SAVE ; __CDECL16_PROC_ARGS nargs
%macro __CDECL16_CALLER_SAVE 0 ; Creates %$arg1 .. %$argN as [bp+4], [bp+6], ...
push ax ; for use inside of function bodies
push cx %ifnmacro __CDECL16_PROC_ARGS
push dx %macro __CDECL16_PROC_ARGS 1
%push __CDECL16_PROC_ARGS
%assign %$__i 1
%rep %1
%xdefine %$arg%$__i [bp + 4 + 2*(%$__i-1)]
%assign %$__i %$__i + 1
%endrep
%pop
%endmacro %endmacro
%endif %endif
%ifnmacro __CDECL16_CALLER_RESTORE ; __CDECL16_CALL_ARGS a,b,c ==> push c / push b / push a
%macro __CDECL16_CALLER_RESTORE 0 ; handles pushing values to the stack in the correct order
pop dx %ifnmacro __CDECL16_CALL_ARGS
pop cx %macro __CDECL16_CALL_ARGS 1-*
pop ax %rep %0
%rotate -1 ; move the last argument into %1
push %1 ; push last, then next-to-last, ...
%endrep
%endmacro
%endif
; __CDECL16_CALL func, nargs ; adds sp by nargs*2 after call
; adds up word pushes to restore stack frame
; WARNING: if you push a dword it will only count 2, use __CDECL16_CALL_ARGS_SIZED
%ifnmacro __CDECL16_CALL
%macro __CDECL16_CALL 2
call %1
add sp, %2*2
%endmacro
%endif
; __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!
%ifnmacro __CDECL16_CALL_ARGS_SIZED
%macro __CDECL16_CALL_ARGS_SIZED 2-*
%push __CDECL16_CALL_ARGS_SIZED
call %1
%assign %$__sum 0
%assign %$__i 2
%rep %0-1
%assign %$__sum %$__sum + %[%$__i] ; sizes may be expressions
%assign %$__i %$__i + 1
%endrep
%if %$__sum & 1
%error "__CDECL16_CALL_ARGS_SIZED: total size is odd; pushes must sum to whole bytes actually pushed (usually even)."
%endif
add sp, %$__sum
%pop
%endmacro
%endif
%ifnmacro __CDECL16_CLOB
; Save registers in the order listed. Supports "flags" as a pseudo-reg.
%macro __CDECL16_CLOB 1-*
%rep %0
%ifidni %1, flags
pushf
%else
push %1
%endif
%rotate 1
%endrep
%endmacro
%endif
%ifnmacro __CDECL16_UNCLOB
; Restore in reverse order of CLOB. Supports "flags".
%macro __CDECL16_UNCLOB 1-*
%rep %0
%rotate -1
%ifidni %1, flags
popf
%else
pop %1
%endif
%endrep
%endmacro %endmacro
%endif %endif
@@ -68,34 +137,3 @@
pop bp pop bp
%endmacro %endmacro
%endif %endif
%ifnmacro __DEFLAT_DS_ES
%macro __DEFLAT_DS_ES 0
mov ax, __STAGE2_SEGMENT
mov ds, ax
mov es, ax
%endmacro
%endif
%ifnmacro __REFLAT_DS_ES
%macro __REFLAT_ES 0
cli ; no interrupts
lgdt [((__STAGE2_SEGMENT << 4) + unreal_gdt_info)] ; load unreal gdt
mov eax, cr0
or eax, 1 ; set pmode bit
mov cr0, eax ; switch to pmode
jmp short $+2 ; i-cache flush
mov ax, 0x10 ; select descriptor 2
mov ds, ax ; 10h = 0001_0000b
mov es, ax ; es to big data
mov eax, cr0
and eax, ~1 ; toggle bit 1 of cr0
mov cr0, eax ; back to realmode
jmp short $+2 ; i-cache flush
sti
%endmacro
%endif

View File

@@ -23,16 +23,11 @@
; returns: none ; returns: none
ALIGN 4, db 0x90 ALIGN 4, db 0x90
InitFATDriver: InitFATDriver:
__CDECL16_ENTRY __CDECL16_PROC_ENTRY
.func: .func:
mov ax, FAT32_State_t_size
push ax ; length of fat32_state structure __CDECL16_CALL_ARGS fat32_state, 0x0000, FAT32_State_t_size
xor ax, ax __CDECL16_CALL kmemset, 3
push ax ; init fat32_state with zero
mov ax, fat32_state
push ax ; address of structure
call kmemset
add sp, 0x6
.calc_active_part: .calc_active_part:
mov ax, word [partition_offset] mov ax, word [partition_offset]
@@ -70,14 +65,14 @@ InitFATDriver:
mov eax, dword [bx + FAT32_ebpb_t.root_clus_dword] mov eax, dword [bx + FAT32_ebpb_t.root_clus_dword]
mov dword [di + FAT32_State_t.curr_dir_cluster_32], eax mov dword [di + FAT32_State_t.curr_dir_cluster_32], eax
.endp: .endp:
__CDECL16_EXIT __CDECL16_PROC_EXIT
ret ret
.error: .error:
ERROR STAGE2_FAT32_INIT_CF ERROR STAGE2_FAT32_INIT_CF
ALIGN 4, db 0x90 ALIGN 4, db 0x90
FSInfoPrinter: FSInfoPrinter:
__CDECL16_ENTRY __CDECL16_PROC_ENTRY
.func: .func:
;info we want to print to validate we are loading stuff from the disk correctly ;info we want to print to validate we are loading stuff from the disk correctly
; boot_drive # (i.e 0x80) ; boot_drive # (i.e 0x80)
@@ -88,7 +83,7 @@ FSInfoPrinter:
; print entire FAT32 state ; print entire FAT32 state
; ;
.endp: .endp:
__CDECL16_EXIT __CDECL16_PROC_EXIT
ret ret
.error: .error:
ERROR STAGE2_ERROR_INFOPRINTER ERROR STAGE2_ERROR_INFOPRINTER
@@ -104,18 +99,19 @@ FSInfoPrinter:
; uint32_t SearchFATDIR(uint8_t* SFN); ; uint32_t SearchFATDIR(uint8_t* SFN);
ALIGN 4, db 0x90 ALIGN 4, db 0x90
SearchFATDIR: SearchFATDIR:
__CDECL16_ENTRY __CDECL16_PROC_ENTRY
.file_lookup: .file_lookup:
print_string SearchFATDIR_info __CDECL16_CALL_ARGS SearchFATDIR_info
__CDECL16_CALL PrintString, 1
mov bx, fat32_state mov bx, fat32_state
.load_first_dir: .load_first_dir:
mov eax, dword [bx + FAT32_State_t.curr_dir_cluster_32]
push dword eax ; cluster ; uint8_t ReadFATCluster(uint16_t seg, uint16_t offset, uint32_t cluster)
mov ax, dir_buffer push dword [bx + FAT32_State_t.curr_dir_cluster_32] ; cluster
push ax ; offset push dir_buffer ; offset
xor ax, ax push 0x0000 ; segment
push ax ; segment call ReadFATCluster
call ReadFATCluster ; uint8_t ReadFATCluster(uint16_t seg, uint16_t offset, uint32_t cluster)
add sp, 0x8 add sp, 0x8
mov si, dir_buffer mov si, dir_buffer
@@ -125,9 +121,9 @@ SearchFATDIR:
; if eax >= 0x0FFFFFF8 then there are no more clusters (end of chain) ; if eax >= 0x0FFFFFF8 then there are no more clusters (end of chain)
; if eax == 0x0FFFFFF7 then this is a cluster that is marked as bad ; if eax == 0x0FFFFFF7 then this is a cluster that is marked as bad
mov eax, dword [bx + FAT32_State_t.curr_dir_cluster_32] ; uint32_t NextCluster(uint32_t active_cluster);
push dword eax push dword [bx + FAT32_State_t.curr_dir_cluster_32]
call NextCluster ; uint32_t NextCluster(uint32_t active_cluster); call NextCluster
add sp, 0x4 add sp, 0x4
cmp eax, 0x0fff_fff7 cmp eax, 0x0fff_fff7
@@ -137,16 +133,14 @@ SearchFATDIR:
.load_next_dir_next_OK: .load_next_dir_next_OK:
; load 512 bytes of directory entries from data sector ; load 512 bytes of directory entries from data sector
mov eax, [bx + FAT32_State_t.curr_dir_cluster_32]
push dword eax ; cluster
mov ax, dir_buffer ; uint8_t ReadFATCluster(uint16_t seg, uint16_t offset, uint32_t cluster)
push ax ; offset push dword [bx + FAT32_State_t.curr_dir_cluster_32] ; cluster
push dir_buffer ; offset
xor ax, ax push 0x0000 ; segment
push ax ; segment call ReadFATCluster
call ReadFATCluster ; uint8_t ReadFATCluster(uint16_t seg, uint16_t offset, uint32_t cluster)
add sp, 0x8 add sp, 0x8
.empty_dir_entry: .empty_dir_entry:
; check for 0x0 in first byte, if true then there are no more files ; check for 0x0 in first byte, if true then there are no more files
; if true we did not find the file, we should error here ; if true we did not find the file, we should error here
@@ -176,7 +170,9 @@ SearchFATDIR:
; TODO: move this to a seperate string search function ; TODO: move this to a seperate string search function
.parse_dir: .parse_dir:
print_string MaybeFound_Boot_info __CDECL16_CALL_ARGS MaybeFound_Boot_info
__CDECL16_CALL PrintString, 1
.lfn_check: .lfn_check:
; check for ATTR_READ_ONLY | ATTR_HIDDEN | ATTR_SYSTEM | ATTR_VOLUME_ID (0x0F) in offset 11 ; check for ATTR_READ_ONLY | ATTR_HIDDEN | ATTR_SYSTEM | ATTR_VOLUME_ID (0x0F) in offset 11
; TODO: going to skip LFN for now, since all valid volumes will have SFN's ; TODO: going to skip LFN for now, since all valid volumes will have SFN's
@@ -201,7 +197,7 @@ SearchFATDIR:
mov ax, [si + FAT32_SFN_t.cluster_16_low] mov ax, [si + FAT32_SFN_t.cluster_16_low]
; eax == first cluster of file ; eax == first cluster of file
.endp: .endp:
__CDECL16_EXIT __CDECL16_PROC_EXIT
ret ret
; BUG: this function needs review ; BUG: this function needs review
@@ -210,20 +206,15 @@ SearchFATDIR:
; if eax == 0x0FFFFFF7 then this is a cluster that is marked as bad ; if eax == 0x0FFFFFF7 then this is a cluster that is marked as bad
ALIGN 4, db 0x90 ALIGN 4, db 0x90
NextCluster: NextCluster:
__CDECL16_ENTRY __CDECL16_PROC_ENTRY
.func: .func:
print_string NextFATCluster_info __CDECL16_CALL_ARGS NextFATCluster_info
__CDECL16_CALL PrintString, 1
mov ax, FAT32_NextClusterData_t_size __CDECL16_CALL_ARGS fat32_nc_data, 0x0000, FAT32_NextClusterData_t_size
push ax ; length __CDECL16_CALL kmemset, 3
xor ax, ax
push ax ; init with zero
mov ax, fat32_nc_data
push ax ; address of structure
call kmemset
add sp, 0x6
mov edx, dword [bp + 4] mov edx, dword [bp + 4] ; active_cluster
mov si, fat32_nc_data ; instead of push/pop and moving the data back mov si, fat32_nc_data ; instead of push/pop and moving the data back
mov di, fat32_bpb ; load si & di then use xchg mov di, fat32_bpb ; load si & di then use xchg
mov bx, fat32_state mov bx, fat32_state
@@ -270,12 +261,13 @@ NextCluster:
; uint32_t lba, ; uint32_t lba,
; uint16_t count, uint16_t drive_num) ; uint16_t count, uint16_t drive_num)
.read_cluster: .read_cluster:
; next_cluster = fat_buffer[entry_offset] ; next_cluster = fat_buffer[entry_offset]
mov ebx, dword [si + FAT32_NextClusterData_t.entry_offset] mov ebx, dword [si + FAT32_NextClusterData_t.entry_offset]
mov si, fat_buffer mov si, fat_buffer
mov eax, dword [bx+si+0] mov eax, dword [bx+si+0]
; BUG: ???
.endp: .endp:
__CDECL16_EXIT __CDECL16_PROC_EXIT
ret ret
.error_cfdivz: .error_cfdivz:
ERROR STAGE2_FAT32_NCLUS_CFDIVZ ERROR STAGE2_FAT32_NCLUS_CFDIVZ
@@ -283,9 +275,10 @@ NextCluster:
; uint8_t ReadFATCluster(uint16_t seg, uint16_t offset, uint32_t cluster) ; uint8_t ReadFATCluster(uint16_t seg, uint16_t offset, uint32_t cluster)
ALIGN 4, db 0x90 ALIGN 4, db 0x90
ReadFATCluster: ReadFATCluster:
__CDECL16_ENTRY __CDECL16_PROC_ENTRY
.func: .func:
print_string ReadFATCluster_info __CDECL16_CALL_ARGS ReadFATCluster_info
__CDECL16_CALL PrintString, 1
mov bx, fat32_bpb mov bx, fat32_bpb
mov si, fat32_ebpb mov si, fat32_ebpb
@@ -318,7 +311,7 @@ ReadFATCluster:
call read_disk_raw call read_disk_raw
add sp, 0xC add sp, 0xC
.endp: .endp:
__CDECL16_EXIT __CDECL16_PROC_EXIT
ret ret
.error: .error:
ERROR STAGE2_FAT32_CLS2LBA_CF ERROR STAGE2_FAT32_CLS2LBA_CF

View File

@@ -12,18 +12,19 @@ endstruc
; void arena_init(ArenaState *a) ; void arena_init(ArenaState *a)
; ;
arena_init: arena_init:
__CDECL16_ENTRY __CDECL16_PROC_ENTRY
.func: .func:
movzx eax, word [bp + 4] ; ptr to state structure mov ax, word [bp + 4] ; ptr to state structure
mov di, ax mov di, ax
xor eax, eax xor ax, ax
mov word [di + ArenaStateStruc_t.mark], eax mov word [di + ArenaStateStruc_t.mark], ax
mov word [di + ArenaStateStruc_t.end], word (__ARENA_HEAP_START + __ARENA_HEAP_SIZE) mov word [di + ArenaStateStruc_t.end], word (__ARENA_HEAP_START + __ARENA_HEAP_SIZE)
mov word [di + ArenaStateStruc_t.start], __ARENA_HEAP_START mov word [di + ArenaStateStruc_t.start], __ARENA_HEAP_START
; zero out heap area on init ; zero out heap area on init
; void* kmemset_byte(void* dst, uint8_t val, uint16_t len); ; void* kmemset_byte(void* dst, uint8_t val, uint16_t len);
; TODO: use word or qword spacing at least to speed this up
mov ax, __ARENA_HEAP_SIZE mov ax, __ARENA_HEAP_SIZE
push ax ; len push ax ; len
xor ax, ax xor ax, ax
@@ -34,7 +35,7 @@ arena_init:
add sp, 0x6 add sp, 0x6
.endp: .endp:
__CDECL16_EXIT __CDECL16_PROC_EXIT
ret ret
; size_t align_up(size_t x, size_t a) ; size_t align_up(size_t x, size_t a)
@@ -43,57 +44,125 @@ arena_init:
; (x + (a-1)) & ~(a-1) ; (x + (a-1)) & ~(a-1)
; return value in ax ; return value in ax
arena_align_up: arena_align_up:
__CDECL16_ENTRY __CDECL16_PROC_ENTRY
.func: .func:
; if a == 0 return x
mov ax, [bp + 4] ; x mov ax, [bp + 4] ; x
mov bx, [bp + 6] ; a
mov bx, [bp + 6] test bx, bx
sub bx, 1 ; a - 1 jz .endp
; enforce power-of-two for alignment, return x
; for example...
; alignment = 0x0010,
; 0x0010 & (0x0010 - 0x0001)
; 0x0010 & 0x000F -> 1_0000000b & 0_11111111b => 0b == zero
;
; alignment = 0x0006
; 0x0006 & (0x0006 - 0x0001)
; 0x0006 & 0x0005 -> 00000110b & 00000101b => 00000100b != 0
;
; i.e any power of 2 has only 1 bit set in binary (2 = 0010b, 4 = 0100b, 8 = 1000b and so on)
; subtracting 1 from a power of 2 'flips' lower bits ( 7 = 0111b, 15 = 1111b ...)
; so 'and'ing a power of two with (itself - 1) will result in none of the bit's being set
mov cx, bx
dec cx
test bx, cx
jnz .endp
dec bx ; a - 1
mov cx, ax mov cx, ax
add cx, bx ; x + (a+1) add cx, bx ; x + (a-1)
not bx ; ~(a-1) not bx ; ~(a-1)
and cx, bx ; and with the inverse and cx, bx ; and with the inverse
mov ax, cx ; move to ax and return mov ax, cx ; move to ax and return
.endp: .endp:
__CDECL16_EXIT __CDECL16_PROC_EXIT
ret ret
; void* arena_alloc(void* a, size_t bytes, size_t align) ; void* arena_alloc(size_t bytes, size_t align)
; bp-2 - current used arena (i.e 'highmark')
; bp-4 - aligned_ptr
; bp-6 - new_end
arena_alloc: arena_alloc:
__CDECL16_ENTRY __CDECL16_PROC_ENTRY 0x10
.func: .func:
; remove bytes from pool and increment mark to the new cursor location ; remove bytes from pool and increment mark to the new cursor location
; return a pointer to the begining of allocated segment ; return a pointer to the begining of allocated segment
mov bx, early_heap_state
mov ax, word [bx + ArenaStateStruc_t.start]
mov dx, word [bx + ArenaStateStruc_t.mark]
add ax, dx ; i.e the total used arena
mov word [bp - 2], ax ; save as a local
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
add sp, 0x4
mov word [bp - 4], ax ; save return value
pop bx ; restore heap_state pointer
; new_end = aligned_ptr + bytes
add ax, word [bp + 4] ; add to total (so current aligned mark + bytes)
mov word [bp - 6], ax ; save as local
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
; else update the mark to the new value & return the aligned pointer
; mark_delta = new_end - curr_used
mov dx, word [bp - 6]
sub dx, word [bp - 2]
; mark += mark_delta
mov ax, word [bx + ArenaStateStruc_t.mark]
add ax, dx
mov word [bx + ArenaStateStruc_t.mark], ax
; return aligned_ptr
mov ax, word [bp - 4]
.endp: .endp:
__CDECL16_EXIT __CDECL16_PROC_EXIT
ret ret
.error:
ERROR STEVIA_DEBUG_ERR
arena_mark: arena_mark:
__CDECL16_ENTRY __CDECL16_PROC_ENTRY
.func: .func:
; return the current location of the 'cursor' in the allocator ; return the current location of the 'cursor' in the allocator
ERROR STEVIA_DEBUG_UNIMPLEMENTED
.endp: .endp:
__CDECL16_EXIT __CDECL16_PROC_EXIT
ret ret
arena_reset_to: arena_reset_to:
__CDECL16_ENTRY __CDECL16_PROC_ENTRY
.func: .func:
; rewind the arena to a previously marked point ; rewind the arena to a previously marked point
ERROR STEVIA_DEBUG_UNIMPLEMENTED
.endp: .endp:
__CDECL16_EXIT __CDECL16_PROC_EXIT
ret ret
arena_reset: arena_reset:
__CDECL16_ENTRY __CDECL16_PROC_ENTRY
.func: .func:
; reset the entire heap to a fresh state ; reset the entire heap to a fresh state
ERROR STEVIA_DEBUG_UNIMPLEMENTED
.endp: .endp:
__CDECL16_EXIT __CDECL16_PROC_EXIT
ret ret
%endif %endif

View File

@@ -19,7 +19,7 @@
; void* kmemset_byte(void* dst, uint8_t val, uint16_t len); ; void* kmemset_byte(void* dst, uint8_t val, uint16_t len);
ALIGN 4, db 0x90 ALIGN 4, db 0x90
kmemset: kmemset:
__CDECL16_ENTRY __CDECL16_PROC_ENTRY
.func: .func:
mov cx, [bp + 8] ; uint16_t len mov cx, [bp + 8] ; uint16_t len
mov al, byte [bp + 6] ; uint8_t val mov al, byte [bp + 6] ; uint8_t val
@@ -29,14 +29,14 @@ kmemset:
rep stosb rep stosb
mov ax, di ; return pointer to dest + len (last elem of dest) mov ax, di ; return pointer to dest + len (last elem of dest)
.endp: .endp:
__CDECL16_EXIT __CDECL16_PROC_EXIT
ret ret
; uint8_t* kmemset(uint16_t* dest, uint16_t* src, uint16_t len); ; uint8_t* kmemset(uint16_t* dest, uint16_t* src, uint16_t len);
; not overlap safe ; not overlap safe
ALIGN 4, db 0x90 ALIGN 4, db 0x90
kmemcpy: kmemcpy:
__CDECL16_ENTRY __CDECL16_PROC_ENTRY
.func: .func:
mov cx, [bp + 8] ; len mov cx, [bp + 8] ; len
mov si, [bp + 6] ; src mov si, [bp + 6] ; src
@@ -46,7 +46,7 @@ kmemcpy:
rep movsb rep movsb
mov ax, di ; return pointer to dest mov ax, di ; return pointer to dest
.endf: .endf:
__CDECL16_EXIT __CDECL16_PROC_EXIT
ret ret
%endif %endif

View File

@@ -20,7 +20,7 @@
; not overlap safe, only for ; not overlap safe, only for
ALIGN 4, db 0x90 ALIGN 4, db 0x90
kmemcpy5: kmemcpy5:
__CDECL16_ENTRY __CDECL16_PROC_ENTRY
push ds push ds
push es push es
.setup_segments: .setup_segments:
@@ -41,7 +41,7 @@ kmemcpy5:
pop es pop es
pop ds pop ds
.endf: .endf:
__CDECL16_EXIT __CDECL16_PROC_EXIT
ret ret
%define __INC_KMEMCPY5_FUNC %define __INC_KMEMCPY5_FUNC

View File

@@ -19,7 +19,7 @@
; word kmemset_byte(word segment, word dst, byte val, word len); ; word kmemset_byte(word segment, word dst, byte val, word len);
ALIGN 4, db 0x90 ALIGN 4, db 0x90
kmemset4: kmemset4:
__CDECL16_ENTRY __CDECL16_PROC_ENTRY
.setup_segment: .setup_segment:
push es push es
mov ax, [bp + 4] mov ax, [bp + 4]
@@ -35,7 +35,7 @@ kmemset4:
.restore_segments: .restore_segments:
pop es pop es
.endf: .endf:
__CDECL16_EXIT __CDECL16_PROC_EXIT
ret ret
%endif %endif

View File

@@ -17,8 +17,7 @@ set -euo pipefail
# along with this program. If not, see <https://www.gnu.org/licenses/>. # along with this program. If not, see <https://www.gnu.org/licenses/>.
if [ $(id -u) = 0 ]; then if [ $(id -u) = 0 ]; then
echo "Script should not be run as root, it could break something! Exiting!" >&2 echo "Script should not be run as root, it could break something!" >&2
exit 1
fi fi
# paths to bootcode # paths to bootcode
@@ -125,8 +124,11 @@ if [[ "$OSTYPE" == "linux-gnu"* ]]; then
echo "[2/7] Write DOS partition table (single FAT32 LBA @ 2048)" echo "[2/7] Write DOS partition table (single FAT32 LBA @ 2048)"
"$SF" --no-reread "$disk_img" < /tmp/pt.sfdisk "$SF" --no-reread "$disk_img" < /tmp/pt.sfdisk
echo "[3/7] Make FAT32 filesystem in partition image" # BUG: the default disk img is 256MiB which mkfs.fat wants to create
"$MKFS" -v -F32 -s 1 -n 'STEVIAFS' "$part_img" # a FAT16 FS by default. it needs to be at least 2GiB to to 'lock out'
# FAT16 as an option. Force FAT32 here, might(?) break some things.
echo "[3/7] Make FAT filesystem in partition image"
"$MKFS" -F32 -v -n 'STEVIAFS' "$part_img"
echo "[4/7] Patch VBR inside partition image (preserve BPB)" echo "[4/7] Patch VBR inside partition image (preserve BPB)"

View File

@@ -15,7 +15,7 @@
[BITS 16] [BITS 16]
[ORG 0x0500] ; IF YOU CHANGE ORG CHANGE THE SIGN OFFSET AT THE END [ORG 0x0500] ; IF YOU CHANGE ORG CHANGE THE SIGN OFFSET AT THE END
[CPU KATMAI] [CPU 686]
[map all build/stage2.map] [map all build/stage2.map]
[WARNING -reloc-abs-byte] [WARNING -reloc-abs-byte]
[WARNING -reloc-abs-word] [WARNING -reloc-abs-word]
@@ -34,13 +34,6 @@
%include "early_mem.inc" %include "early_mem.inc"
%include "error_codes.inc" %include "error_codes.inc"
%macro print_string 1
mov ax, %1
push ax
call PrintString
add sp, 0x2
%endmacro
section .text section .text
begin_text: begin_text:
; dl = byte boot_drive ; dl = byte boot_drive
@@ -88,7 +81,7 @@ init:
jmp word __STAGE2_SEGMENT:main jmp word __STAGE2_SEGMENT:main
; ############### ; ###############
; Functions ; Core Functions
; ############### ; ###############
%include "util/kmem_func.nasm" %include "util/kmem_func.nasm"
@@ -96,6 +89,11 @@ init:
%include "util/kmemset4_func.nasm" %include "util/kmemset4_func.nasm"
%include "util/error_func.nasm" %include "util/error_func.nasm"
; ###############
; Functions
; ###############
%include "util/arena_alloc.nasm"
; ############### ; ###############
; FAT32 Driver ; FAT32 Driver
; ############### ; ###############
@@ -130,50 +128,53 @@ main:
je main.stage2_main je main.stage2_main
ERROR STAGE2_SIGNATURE_MISSING ERROR STAGE2_SIGNATURE_MISSING
.stage2_main: .stage2_main:
mov ax, PartTable_t_size ; copy partition table data to .data section in stage2
push ax ; len = PartTable_t_size __CDECL16_CALL_ARGS partition_table, word [vbr_part_table_ptr], PartTable_t_size
mov ax, word [vbr_part_table_ptr] ; src = ptr to vbr partition_table __CDECL16_CALL kmemcpy, 3
push ax
mov ax, partition_table ; dst
push ax
call kmemcpy ; copy partition table data to .data section in stage2
add sp, 0x6
mov ax, (FAT32_bpb_t_size + FAT32_ebpb_t_size) ; len ; copy bpb & ebpb to memory
push ax __CDECL16_CALL_ARGS fat32_bpb, word [vbr_fat32_bpb_ptr], (FAT32_bpb_t_size + FAT32_ebpb_t_size)
mov ax, word [vbr_fat32_bpb_ptr] ; src __CDECL16_CALL kmemcpy, 3
push ax
mov ax, fat32_bpb ; dst
push ax
call kmemcpy ; copy bpb & ebpb to memory
add sp, 0x6
call SetTextMode call SetTextMode
call disable_cursor_bios call disable_cursor_bios
print_string HelloPrompt_info
__CDECL16_CALL_ARGS HelloPrompt_info
__CDECL16_CALL PrintString, 1
; setup the early heap
__CDECL16_CALL_ARGS early_heap_state
; enable A20 gate ; enable A20 gate
call EnableA20 call EnableA20
print_string A20_Enabled_OK_info __CDECL16_CALL_ARGS A20_Enabled_OK_info
__CDECL16_CALL PrintString, 1
; get system memory map ; get system memory map
call GetMemoryMap call GetMemoryMap
print_string MemoryMap_OK_info __CDECL16_CALL_ARGS MemoryMap_OK_info
__CDECL16_CALL PrintString, 1
; enter unreal mode (16 bit code, 32 bit flat memory model) ; enter unreal mode (enter PM w/ 16 bit code, 32 bit flat memory model & return to real)
; ds, es will be set to the 64KiB STAGE2_SEGMENT, fs/gs will be flat/huge memory (4GiB)
; 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 call EnterUnrealMode
print_string UnrealMode_OK_info __CDECL16_CALL_ARGS UnrealMode_OK_info
__CDECL16_CALL PrintString, 1
; FAT Driver setup ; FAT Driver setup
call InitFATDriver call InitFATDriver
print_string InitFATSYS_OK_info __CDECL16_CALL_ARGS InitFATSYS_OK_info
__CDECL16_CALL PrintString, 1
; ;
; Find first cluster of bootable file ; Find first cluster of bootable file
call SearchFATDIR call SearchFATDIR
push dword eax ; save first cluster of bootable file push dword eax ; save first cluster of bootable file
print_string FileFound_OK_info __CDECL16_CALL_ARGS FileFound_OK_info
__CDECL16_CALL PrintString, 1
pop dword eax pop dword eax
push dword eax ; print Cluster of boot file push dword eax ; print Cluster of boot file
@@ -187,13 +188,69 @@ hcf:
; ############################## ; ##############################
; ;
; SYSTEM CONFIGURATION FUNCTIONS ; SYSTEM CONFIGURATION FUNCTIONS & MACROS
; ;
; ############################## ; ##############################
; set ds and es segments back to the base of the loader
%ifnmacro __TINY_DS_ES
%macro __TINY_DS_ES 0
mov ax, __STAGE2_SEGMENT
mov ds, ax
mov es, ax
%endmacro
%endif
; for copying between locations in high memory
%ifnmacro __REFLAT_DS_ES
%macro __REFLAT_DS_ES 0
cli ; no interrupts
lgdt [((__STAGE2_SEGMENT << 4) + unreal_gdt_info)] ; load unreal gdt
mov eax, cr0
or eax, 1 ; set pmode bit
mov cr0, eax ; switch to pmode
jmp short $+2 ; i-cache flush
mov ax, 0x10 ; select descriptor 2
mov ds, ax
mov es, ax
mov eax, cr0
and eax, ~1 ; toggle bit 1 of cr0
mov cr0, eax ; back to realmode
jmp short $+2 ; i-cache flush
sti
%endmacro
%endif
; for copying from low memory to high memory (ds on a real segment, es in flat mode)
%ifnmacro __REFLAT_ES
%macro __REFLAT_ES 0
cli ; no interrupts
lgdt [((__STAGE2_SEGMENT << 4) + unreal_gdt_info)] ; load unreal gdt
mov eax, cr0
or eax, 1 ; set pmode bit
mov cr0, eax ; switch to pmode
jmp short $+2 ; i-cache flush
mov ax, 0x10 ; select descriptor 2
mov es, ax
mov eax, cr0
and eax, ~1 ; toggle bit 1 of cr0
mov cr0, eax ; back to realmode
jmp short $+2 ; i-cache flush
sti
%endmacro
%endif
ALIGN 4, db 0x90 ALIGN 4, db 0x90
EnterUnrealMode: EnterUnrealMode:
__BOCHS_MAGIC_DEBUG __CDECL16_PROC_ENTRY
__CDECL16_ENTRY
cli ; no interrupts cli ; no interrupts
.func: .func:
lgdt [((__STAGE2_SEGMENT << 4) + unreal_gdt_info)] ; load unreal gdt lgdt [((__STAGE2_SEGMENT << 4) + unreal_gdt_info)] ; load unreal gdt
@@ -201,19 +258,14 @@ EnterUnrealMode:
mov eax, cr0 mov eax, cr0
or eax, 1 ; set pmode bit or eax, 1 ; set pmode bit
mov cr0, eax ; switch to pmode mov cr0, eax ; switch to pmode
;jmp short $+2 ; i-cache flush
; set cs to a pm code segment (0x8) w/ the following ; set cs to a pm code segment (0x8) w/ the following
jmp 0x0008:EnterUnrealMode.set_segs jmp 0x0008:EnterUnrealMode.set_segs
;db 0xEA ; jmp far imm16:imm16
;dw EnterUnrealMode.set_segs ; error_far_ptr
;dw 0x0008 ; error_far_seg
.set_segs: .set_segs:
mov ax, 0x10 ; select descriptor 2 mov ax, 0x10 ; select descriptor 2
mov ds, ax ; 10h = 0001_0000b mov ds, ax ; 10h = 0001_0000b
mov es, ax ; es to big data mov es, ax ; es to big data
mov ss, ax ; big stack
mov fs, ax mov fs, ax
mov gs, ax ; extra segments to big data as well mov gs, ax ; extra segments to big data as well
.pm_start: .pm_start:
@@ -223,11 +275,16 @@ EnterUnrealMode:
mov eax, cr0 mov eax, cr0
and eax, ~1 ; toggle bit 1 of cr0 and eax, ~1 ; toggle bit 1 of cr0
mov cr0, eax ; back to realmode mov cr0, eax ; back to realmode
jmp 0x0000:EnterUnrealMode.endp jmp __STAGE2_SEGMENT:EnterUnrealMode.endp
;jmp short $+2 ; i-cache flush
.endp: .endp:
sti ; re-enable interupts sti ; re-enable interupts
__CDECL16_EXIT
; set ds, es to the STAGE2_SEGMENT, for our model (generally) ds == es == cs
; fs, gs & ss are all still huge data model, and the macro(s) "__REFLAT_xxx" exists
; to easily access data outside of 64KiB boundries using ds/es addressing
__TINY_DS_ES
__CDECL16_PROC_EXIT
ret ret
end_text: end_text:
@@ -410,6 +467,10 @@ fat32_state:
align 16, resb 1 align 16, resb 1
SteviaInfo: SteviaInfo:
resd 4 resd 4
align 16, resb 1
early_heap_state:
resb ArenaStateStruc_t_size
; ;
; post-bss init globals ; post-bss init globals
; ;