45 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
b9b3e92632 actually set cs to 16-bit segment for a bit in-case we want to run some pm code 2025-09-05 15:26:24 -04:00
5fac10f02c use easier to read logic 2025-09-05 14:40:44 -04:00
fa4524aa59 add macros to go from real <-> unreal 2025-09-05 14:39:16 -04:00
01ec6da0cc make unreal mode unreal again 2025-09-05 11:45:46 -04:00
2e2b4f991d add cursor manipulation via bios or crtc 2025-09-05 11:45:20 -04:00
d7b29d9113 __CDECL16_ENTRY now takes 0-1 params, if you give it a size it sets up local varible redzone 2025-09-05 11:44:30 -04:00
69d82dc0c2 small comment update 2025-09-05 11:43:41 -04:00
a53534acd2 clear the carry flag before calling BIOS functions 2025-09-05 10:33:42 -04:00
c3871d2b7d move string functions to video.nasm
caught a bug where SetTextMode was setting mono text not 16-color mode
2025-09-05 10:33:03 -04:00
d824493ba2 small clarification on what "unreal" mode really is 2025-09-05 09:12:55 -04:00
cb089681cf make arena_align_up use 16-bit values 2025-09-05 09:12:26 -04:00
d868008726 another oopsie from when I changed the calling convention... 2025-09-05 08:43:41 -04:00
935427509a inital code for align_up function 2025-09-05 08:27:56 -04:00
f5e4927d70 add basic arena area init code
Some checks failed
Daily Build and trunk tester / debian_update (push) Failing after 1m14s
2025-09-04 20:04:25 -04:00
b106eae066 fix alignment macros 2025-09-04 20:04:03 -04:00
f2657fdc01 seems I found a /little/ oopsie in the fat32 system 2025-09-04 19:59:36 -04:00
18 changed files with 625 additions and 388 deletions

View File

@@ -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:

2
.gitignore vendored
View File

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

View File

@@ -1,6 +1,6 @@
# 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
@@ -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.
- **Basic Filesystem Support**: Initial filesystem recognition (details depend on implemented filesystem support).
- **Memory Map Parsing**: Detects available memory regions via BIOS interrupts.
- **GDT Initialization**: Sets up the Global Descriptor Table for protected mode.
### In Progress
- **Interrupt Descriptor Table (IDT) Setup**: Setting up basic interrupt handling.
- **Basic Keyboard Input**: Initial support for capturing keystrokes.
- **GDT Initialization**: Sets up the Global Descriptor Table for protected/unreal mode.
### 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.
- **More Robust Driver Support**: Additional hardware drivers, such as for storage devices.
## 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:
- **Assembler**: NASM for assembling bootloader components.
- **C Compiler**: GCC (cross-compiler recommended).
- **Emulator**: Bochs or QEMU for testing.
- **GNU Make**: For building the project.
- **Utilities**:
- **dd**: For creating raw disk images.
- **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.
- **Assembler**: NASM for assembling bootloader components, you could use a compatible assembler but YMMV.
- **GNU make**: For building the project.
- **mtools**: To access the FAT partition
- **fdisk**: To create disk images and setup partition tables
- **dosfstools**: FAT32 creation
- **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.
### Building and Running
1. **Clone the repository**:
```sh
git clone https://github.com/Nivirx/stevia.git
cd stevia
```
2. **Build the bootloader and create a bootable disk image**:
```sh
sudo make
make
```
3. **Run using Bochs**:
```sh
bochs -f bochsrc.txt
bochs -q -f bochsrc.txt
```
## 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.
## 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.
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.
## 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
display_library: x, options=gui_debug
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/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
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
print_timestamps: enabled=1
private_colormap: enabled=0
clock: sync=none, time0=local, rtc_sync=0
# no cmosimage
log: -
logprefix: %t%e%d
debug: action=ignore
info: action=report
error: action=report
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
mouse: type=none, enabled=false, toggle=ctrl+mbutton
sound: waveoutdrv=dummy, waveout=none, waveindrv=dummy, wavein=none, midioutdrv=dummy, midiout=none
@@ -48,6 +48,4 @@ parport2: enabled=false
com1: enabled=true, mode=null
com2: enabled=false
com3: enabled=false
com4: enabled=false
magic_break: enabled=1
port_e9_hack: enabled=1, all_rings=false
com4: enabled=false

View File

@@ -35,7 +35,7 @@ endstruc
ALIGN 4, db 0x90
GetMemoryMap:
__CDECL16_ENTRY
__CDECL16_PROC_ENTRY
push es ; save segment register
.func:
mov dword [SteviaInfo + SteviaInfoStruct_t.MemoryMapEntries], 0
@@ -53,6 +53,7 @@ GetMemoryMap:
.loop_L1:
mov eax, 0x0000E820 ; select 0xE820 function
mov edx, 0x534D4150 ; 'SMAP' magic
clc ; clear carry
int 0x15
jc GetMemoryMap.error
cmp eax, 0x534D4150
@@ -82,11 +83,11 @@ GetMemoryMap:
ERROR STAGE2_MM_E820_NO_SMAP
.endp:
pop es
__CDECL16_EXIT
__CDECL16_PROC_EXIT
ret
PrintMemoryMap:
__CDECL16_ENTRY
__CDECL16_PROC_ENTRY
.func:
mov eax, dword [SteviaInfo + SteviaInfoStruct_t.MemoryMapEntries]
cmp eax, 0
@@ -105,15 +106,15 @@ PrintMemoryMap:
; print_string strformat_buffer
.endp:
__CDECL16_EXIT
__CDECL16_PROC_EXIT
ret
FormatMemoryMapEntry:
__CDECL16_ENTRY
__CDECL16_PROC_ENTRY
.func:
; create a string buffer somewhere and return address to result string in ax
.endp:
__CDECL16_EXIT
__CDECL16_PROC_EXIT
ret

View File

@@ -64,7 +64,7 @@
; Bits 6-7 - 00: HDD activity LED off; any other value is "on"
ALIGN 4, db 0x90
EnableA20:
__CDECL16_ENTRY
__CDECL16_PROC_ENTRY
push ds
push es
.a20_check:
@@ -105,6 +105,7 @@ EnableA20:
je EnableA20.endp ; A20 is already enabled
mov ax, 0x2403
clc ; clear carry
int 0x15
jc EnableA20.do_fallback_a20 ; carry = error...not supported?
cmp ah, 0
@@ -121,6 +122,7 @@ EnableA20:
ERROR STAGE2_A20_FAILED
.do_bios_a20:
mov ax, 0x2401
clc ; clear carry
int 0x15
jmp EnableA20.a20_check
.do_fast_a20:
@@ -132,7 +134,7 @@ EnableA20:
.endp:
pop es
pop ds
__CDECL16_EXIT
__CDECL16_PROC_EXIT
ret
%endif

View File

@@ -76,7 +76,7 @@ endstruc
; uint16_t count, uint8_t drive_num)
ALIGN 4, db 0x90
read_disk_raw:
__CDECL16_ENTRY
__CDECL16_PROC_ENTRY
.func:
mov ax, LBAPkt_t_size
push ax ; len
@@ -111,6 +111,7 @@ read_disk_raw:
mov ah, 0x42 ; call #
mov dl, byte [bp + 14] ; drive #
clc ; clear carry
int 0x13
jnc .endf
@@ -122,7 +123,7 @@ read_disk_raw:
ERROR STAGE2_MBR_DISK_READ_ERROR
%endif
.endf:
__CDECL16_EXIT
__CDECL16_PROC_EXIT
ret
%endif

View File

@@ -20,25 +20,27 @@
ALIGN 4, db 0x90
SetTextMode:
.prolog:
__CDECL16_ENTRY
__CDECL16_PROC_ENTRY
pushf
.func:
xor ah, ah ; Set Video mode BIOS function
mov al, 0x02 ; 16 color 80x25 Text mode
mov al, 0x03 ; 16 color 80x25 Text mode
int 0x10 ; Call video interrupt
mov ah, 0x05 ; Select active display page BIOS function
xor al, al ; page 0
int 0x10 ; call video interrupt
.endp:
popf
__CDECL16_EXIT
__CDECL16_PROC_EXIT
ret
; disables blinking text mode cursor
; disables blinking text mode cursor via crtc pokes
; 0x3D4/0x3D5 for color, mono at 0x3B4/0x3B5
ALIGN 4, db 0x90
disable_cursor:
__CDECL16_ENTRY
disable_cursor_crtc:
__CDECL16_PROC_ENTRY
.func:
mov dx, 0x3D4
mov al, 0xA ; low cursor shape register
@@ -48,8 +50,126 @@ disable_cursor:
mov al, 0x20 ; bits 6-7 unused, bit 5 disables the cursor, bits 0-4 control the cursor shape
out dx, al
.endp:
__CDECL16_EXIT
__CDECL16_PROC_EXIT
ret
; disables blinking text mode cursor via BIOS int 10h, ah = 01
ALIGN 4, db 0x90
disable_cursor_bios:
__CDECL16_PROC_ENTRY
.func:
push bx
mov ah, 03h ; read cursor pos & shape
xor bh, bh
int 10h ; CH=top scanline, CL=bottom
or ch, 20h ; set bit 5 = disable
mov ah, 01h ; set leaf 01h
int 10h
pop bx
.endp:
__CDECL16_PROC_EXIT
ret
; Prints a C-Style string (null terminated) using BIOS vga teletype call
; void PrintString(char* buf)
ALIGN 4, db 0x90
PrintString:
__CDECL16_PROC_ENTRY
mov di, [bp + 4] ; first arg is char[]
.str_len:
xor cx, cx ; ECX = 0
not cx ; ECX = -1 == 0xFFFF
xor ax, ax ; search for al = 0x0
cld
repne scasb ; deincrement cx while searching for al
not cx ; the inverse of a neg number = abs(x) - 1
dec cx ; CX contains the length of the string - nul byte at end
.print:
mov si, [bp + 4] ; source string
.print_L0:
movzx ax, byte [si]
%ifdef __STEVIA_DEV_DEBUG
out 0xe9, byte al ; bochs magic debug port
%endif
push ax
call PrintCharacter
add sp, 0x2
inc si
dec cx
jcxz PrintString.endp
jmp PrintString.print_L0 ; Fetch next character from string
.endp:
__CDECL16_PROC_EXIT
ret ; Return from procedure
; Prints a single character
; void PrintCharacter(char c);
ALIGN 4, db 0x90
PrintCharacter:
__CDECL16_PROC_ENTRY
.func:
mov al, byte [bp + 4] ; AL = character c
mov ah, 0x0E ; INT 0x10, AH=0x0E call
mov bx, 0x0007 ; BH = page no. BL =Text attribute
int 0x10 ; call video interrupt
; TODO: check for carry and clear carry before call
.endp:
__CDECL16_PROC_EXIT
ret
; TODO: fix the prolog, epilog and stack usage to confirm with cdecl16
; prints the hex representation of of val
; void PrintDWORD(uint32_t val);
ALIGN 4, db 0x90
PrintDWORD:
__CDECL16_PROC_ENTRY
.func:
mov si, IntToHex_table
mov ebx, 16 ; base-16
mov eax, dword [bp + 4] ;val
xor edx, edx
xor cx, cx
.next_digit:
div ebx ; dividend in edx:eax -> quotient in eax, remainder in edx
push dx ; save remainder
inc cx
xor dx, dx
test eax, eax
jnz PrintDWORD.next_digit
.zero_pad:
cmp cx, 0x0008
je PrintDWORD.print_stack
xor ax, ax
push ax
inc cx
jmp PrintDWORD.zero_pad
.print_stack:
pop bx
dec cx
push cx
movzx ax, byte [bx+si+0] ; bx = index into Hex lookup table
push ax
call PrintCharacter
add sp, 0x2
pop cx
jcxz PrintDWORD.endp
jmp PrintDWORD.print_stack
.endp:
__CDECL16_PROC_EXIT
ret
%endif
%define __INC_VIDEO

View File

@@ -13,20 +13,23 @@
; You should have received a copy of the GNU General Public License
; along with this program. If not, see <https://www.gnu.org/licenses/>.
%ifnmacro __CDECL16_ENTRY
%macro __CDECL16_ENTRY 0
%ifnmacro __CDECL16_PROC_ENTRY
%macro __CDECL16_PROC_ENTRY 0-1
push bp
mov bp, sp
sub sp, 0x10
push si
push di
push bx
%if %0 = 1
sub sp, %1 ; reserve locals only when needed
%endif
%endmacro
%endif
%ifnmacro __CDECL16_EXIT
%macro __CDECL16_EXIT 0
%ifnmacro __CDECL16_PROC_EXIT
%macro __CDECL16_PROC_EXIT 0
pop bx
pop di
pop si
@@ -36,19 +39,88 @@
%endmacro
%endif
%ifnmacro __CDECL16_CALLER_SAVE
%macro __CDECL16_CALLER_SAVE 0
push ax
push cx
push dx
; __CDECL16_PROC_ARGS nargs
; Creates %$arg1 .. %$argN as [bp+4], [bp+6], ...
; for use inside of function bodies
%ifnmacro __CDECL16_PROC_ARGS
%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
%endif
%ifnmacro __CDECL16_CALLER_RESTORE
%macro __CDECL16_CALLER_RESTORE 0
pop dx
pop cx
pop ax
; __CDECL16_CALL_ARGS a,b,c ==> push c / push b / push a
; handles pushing values to the stack in the correct order
%ifnmacro __CDECL16_CALL_ARGS
%macro __CDECL16_CALL_ARGS 1-*
%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
%endif

View File

@@ -23,16 +23,11 @@
; returns: none
ALIGN 4, db 0x90
InitFATDriver:
__CDECL16_ENTRY
__CDECL16_PROC_ENTRY
.func:
mov ax, FAT32_State_t_size
push ax ; length of fat32_state structure
xor ax, ax
push ax ; init fat32_state with zero
mov ax, fat32_state
push ax ; address of structure
call kmemset
sub sp, 0x6
__CDECL16_CALL_ARGS fat32_state, 0x0000, FAT32_State_t_size
__CDECL16_CALL kmemset, 3
.calc_active_part:
mov ax, word [partition_offset]
@@ -70,14 +65,14 @@ InitFATDriver:
mov eax, dword [bx + FAT32_ebpb_t.root_clus_dword]
mov dword [di + FAT32_State_t.curr_dir_cluster_32], eax
.endp:
__CDECL16_EXIT
__CDECL16_PROC_EXIT
ret
.error:
ERROR STAGE2_FAT32_INIT_CF
ALIGN 4, db 0x90
FSInfoPrinter:
__CDECL16_ENTRY
__CDECL16_PROC_ENTRY
.func:
;info we want to print to validate we are loading stuff from the disk correctly
; boot_drive # (i.e 0x80)
@@ -88,7 +83,7 @@ FSInfoPrinter:
; print entire FAT32 state
;
.endp:
__CDECL16_EXIT
__CDECL16_PROC_EXIT
ret
.error:
ERROR STAGE2_ERROR_INFOPRINTER
@@ -104,18 +99,19 @@ FSInfoPrinter:
; uint32_t SearchFATDIR(uint8_t* SFN);
ALIGN 4, db 0x90
SearchFATDIR:
__CDECL16_ENTRY
__CDECL16_PROC_ENTRY
.file_lookup:
print_string SearchFATDIR_info
__CDECL16_CALL_ARGS SearchFATDIR_info
__CDECL16_CALL PrintString, 1
mov bx, fat32_state
.load_first_dir:
mov eax, dword [bx + FAT32_State_t.curr_dir_cluster_32]
push dword eax ; cluster
mov ax, dir_buffer
push ax ; offset
xor ax, ax
push ax ; segment
call ReadFATCluster ; uint8_t ReadFATCluster(uint16_t seg, uint16_t offset, uint32_t cluster)
; uint8_t ReadFATCluster(uint16_t seg, uint16_t offset, uint32_t cluster)
push dword [bx + FAT32_State_t.curr_dir_cluster_32] ; cluster
push dir_buffer ; offset
push 0x0000 ; segment
call ReadFATCluster
add sp, 0x8
mov si, dir_buffer
@@ -124,10 +120,10 @@ SearchFATDIR:
.load_next_dir:
; 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
mov eax, dword [bx + FAT32_State_t.curr_dir_cluster_32]
push dword eax
call NextCluster ; uint32_t NextCluster(uint32_t active_cluster);
; uint32_t NextCluster(uint32_t active_cluster);
push dword [bx + FAT32_State_t.curr_dir_cluster_32]
call NextCluster
add sp, 0x4
cmp eax, 0x0fff_fff7
@@ -137,16 +133,14 @@ SearchFATDIR:
.load_next_dir_next_OK:
; 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
push ax ; offset
; uint8_t ReadFATCluster(uint16_t seg, uint16_t offset, uint32_t cluster)
push dword [bx + FAT32_State_t.curr_dir_cluster_32] ; cluster
push dir_buffer ; offset
push 0x0000 ; segment
call ReadFATCluster
add sp, 0x8
xor ax, ax
push ax ; segment
call ReadFATCluster ; uint8_t ReadFATCluster(uint16_t seg, uint16_t offset, uint32_t cluster)
sub sp, 0x8
.empty_dir_entry:
; 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
@@ -176,7 +170,9 @@ SearchFATDIR:
; TODO: move this to a seperate string search function
.parse_dir:
print_string MaybeFound_Boot_info
__CDECL16_CALL_ARGS MaybeFound_Boot_info
__CDECL16_CALL PrintString, 1
.lfn_check:
; 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
@@ -201,7 +197,7 @@ SearchFATDIR:
mov ax, [si + FAT32_SFN_t.cluster_16_low]
; eax == first cluster of file
.endp:
__CDECL16_EXIT
__CDECL16_PROC_EXIT
ret
; BUG: this function needs review
@@ -210,20 +206,15 @@ SearchFATDIR:
; if eax == 0x0FFFFFF7 then this is a cluster that is marked as bad
ALIGN 4, db 0x90
NextCluster:
__CDECL16_ENTRY
__CDECL16_PROC_ENTRY
.func:
print_string NextFATCluster_info
__CDECL16_CALL_ARGS NextFATCluster_info
__CDECL16_CALL PrintString, 1
mov ax, FAT32_NextClusterData_t_size
push ax ; length
xor ax, ax
push ax ; init with zero
mov ax, fat32_nc_data
push ax ; address of structure
call kmemset
sub sp, 0x6
__CDECL16_CALL_ARGS fat32_nc_data, 0x0000, FAT32_NextClusterData_t_size
__CDECL16_CALL kmemset, 3
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 di, fat32_bpb ; load si & di then use xchg
mov bx, fat32_state
@@ -270,12 +261,13 @@ NextCluster:
; uint32_t lba,
; uint16_t count, uint16_t drive_num)
.read_cluster:
; next_cluster = fat_buffer[entry_offset]
; next_cluster = fat_buffer[entry_offset]
mov ebx, dword [si + FAT32_NextClusterData_t.entry_offset]
mov si, fat_buffer
mov eax, dword [bx+si+0]
; BUG: ???
.endp:
__CDECL16_EXIT
__CDECL16_PROC_EXIT
ret
.error_cfdivz:
ERROR STAGE2_FAT32_NCLUS_CFDIVZ
@@ -283,9 +275,10 @@ NextCluster:
; uint8_t ReadFATCluster(uint16_t seg, uint16_t offset, uint32_t cluster)
ALIGN 4, db 0x90
ReadFATCluster:
__CDECL16_ENTRY
__CDECL16_PROC_ENTRY
.func:
print_string ReadFATCluster_info
__CDECL16_CALL_ARGS ReadFATCluster_info
__CDECL16_CALL PrintString, 1
mov bx, fat32_bpb
mov si, fat32_ebpb
@@ -318,7 +311,7 @@ ReadFATCluster:
call read_disk_raw
add sp, 0xC
.endp:
__CDECL16_EXIT
__CDECL16_PROC_EXIT
ret
.error:
ERROR STAGE2_FAT32_CLS2LBA_CF

View File

@@ -9,57 +9,160 @@ struc ArenaStateStruc_t
.mark resw 1
endstruc
; void arena_init(void *mem, size_t bytes)
; void arena_init(ArenaState *a)
;
arena_init:
__CDECL16_ENTRY
__CDECL16_PROC_ENTRY
.func:
mov ax, word [bp + 4] ; ptr to state structure
mov di, ax
xor ax, ax
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.start], __ARENA_HEAP_START
; 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
call kmemset
add sp, 0x6
.endp:
__CDECL16_EXIT
__CDECL16_PROC_EXIT
ret
; size_t align_up(size_t x, size_t a)
; ax, bx. cx are all clobbered
; 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:
__CDECL16_ENTRY
__CDECL16_PROC_ENTRY
.func:
; align the mark to the nearest specified alignment
; if a == 0 return x
mov ax, [bp + 4] ; x
mov bx, [bp + 6] ; a
test bx, bx
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
add cx, bx ; x + (a-1)
not bx ; ~(a-1)
and cx, bx ; and with the inverse
mov ax, cx ; move to ax and return
.endp:
__CDECL16_EXIT
__CDECL16_PROC_EXIT
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:
__CDECL16_ENTRY
__CDECL16_PROC_ENTRY 0x10
.func:
; 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
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:
__CDECL16_EXIT
__CDECL16_PROC_EXIT
ret
.error:
ERROR STEVIA_DEBUG_ERR
arena_mark:
__CDECL16_ENTRY
__CDECL16_PROC_ENTRY
.func:
; return the current location of the 'cursor' in the allocator
ERROR STEVIA_DEBUG_UNIMPLEMENTED
.endp:
__CDECL16_EXIT
__CDECL16_PROC_EXIT
ret
arena_reset_to:
__CDECL16_ENTRY
__CDECL16_PROC_ENTRY
.func:
; rewind the arena to a previously marked point
ERROR STEVIA_DEBUG_UNIMPLEMENTED
.endp:
__CDECL16_EXIT
__CDECL16_PROC_EXIT
ret
arena_reset:
__CDECL16_ENTRY
__CDECL16_PROC_ENTRY
.func:
; reset the entire heap to a fresh state
ERROR STEVIA_DEBUG_UNIMPLEMENTED
.endp:
__CDECL16_EXIT
__CDECL16_PROC_EXIT
ret
%endif

View File

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

View File

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

View File

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

View File

@@ -17,8 +17,7 @@ set -euo pipefail
# along with this program. If not, see <https://www.gnu.org/licenses/>.
if [ $(id -u) = 0 ]; then
echo "Script should not be run as root, it could break something! Exiting!" >&2
exit 1
echo "Script should not be run as root, it could break something!" >&2
fi
# paths to bootcode
@@ -125,8 +124,11 @@ if [[ "$OSTYPE" == "linux-gnu"* ]]; then
echo "[2/7] Write DOS partition table (single FAT32 LBA @ 2048)"
"$SF" --no-reread "$disk_img" < /tmp/pt.sfdisk
echo "[3/7] Make FAT32 filesystem in partition image"
"$MKFS" -v -F32 -s 1 -n 'STEVIAFS' "$part_img"
# BUG: the default disk img is 256MiB which mkfs.fat wants to create
# 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)"

View File

@@ -58,7 +58,7 @@ init:
cld
rep stosb ; zero bss section
sub sp, 0x20 ; local varible space
sub sp, 0x20 ; local varible space (32 bytes)
push bp ; setup top of stack frame
xor cx, cx
@@ -96,6 +96,8 @@ main:
mov ah, 0x41
mov bx, 0x55AA
mov dl, 0x80
clc
int 0x13
jnc main.find_active
ERROR MBR_ERROR_NO_INT32E ; no extended function support

View File

@@ -15,7 +15,7 @@
[BITS 16]
[ORG 0x0500] ; IF YOU CHANGE ORG CHANGE THE SIGN OFFSET AT THE END
[CPU KATMAI]
[CPU 686]
[map all build/stage2.map]
[WARNING -reloc-abs-byte]
[WARNING -reloc-abs-word]
@@ -34,13 +34,6 @@
%include "early_mem.inc"
%include "error_codes.inc"
%macro print_string 1
mov ax, %1
push ax
call PrintString
add sp, 0x2
%endmacro
section .text
begin_text:
; dl = byte boot_drive
@@ -88,7 +81,7 @@ init:
jmp word __STAGE2_SEGMENT:main
; ###############
; Functions
; Core Functions
; ###############
%include "util/kmem_func.nasm"
@@ -96,6 +89,11 @@ init:
%include "util/kmemset4_func.nasm"
%include "util/error_func.nasm"
; ###############
; Functions
; ###############
%include "util/arena_alloc.nasm"
; ###############
; FAT32 Driver
; ###############
@@ -130,51 +128,54 @@ main:
je main.stage2_main
ERROR STAGE2_SIGNATURE_MISSING
.stage2_main:
mov ax, PartTable_t_size
push ax ; len = PartTable_t_size
mov ax, word [vbr_part_table_ptr] ; src = ptr to vbr partition_table
push ax
mov ax, partition_table ; dst
push ax
call kmemcpy ; copy partition table data to .data section in stage2
add sp, 0x6
; 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
mov ax, (FAT32_bpb_t_size + FAT32_ebpb_t_size) ; len
push ax
mov ax, word [vbr_fat32_bpb_ptr] ; src
push ax
mov ax, fat32_bpb ; dst
push ax
call kmemcpy ; copy bpb & ebpb to memory
add sp, 0x6
; 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
print_string HelloPrompt_info
call disable_cursor_bios
__CDECL16_CALL_ARGS HelloPrompt_info
__CDECL16_CALL PrintString, 1
; setup the early heap
__CDECL16_CALL_ARGS early_heap_state
; enable A20 gate
call EnableA20
print_string A20_Enabled_OK_info
__CDECL16_CALL_ARGS A20_Enabled_OK_info
__CDECL16_CALL PrintString, 1
; get system memory map
call GetMemoryMap
print_string MemoryMap_OK_info
__CDECL16_CALL_ARGS MemoryMap_OK_info
__CDECL16_CALL PrintString, 1
; enter unreal mode
; 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
print_string UnrealMode_OK_info
__CDECL16_CALL_ARGS UnrealMode_OK_info
__CDECL16_CALL PrintString, 1
; FAT Driver setup
call InitFATDriver
print_string InitFATSYS_OK_info
__CDECL16_CALL_ARGS InitFATSYS_OK_info
__CDECL16_CALL PrintString, 1
;
; Find first cluster of bootable file
call SearchFATDIR
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
push dword eax ; print Cluster of boot file
call PrintDWORD ; void PrintDWORD(uint32_t dword)
@@ -187,166 +188,103 @@ hcf:
; ##############################
;
; SYSTEM CONFIGURATION FUNCTIONS
; SYSTEM CONFIGURATION FUNCTIONS & MACROS
;
; ##############################
; Prints a C-Style string (null terminated) using BIOS vga teletype call
; void PrintString(char* buf)
ALIGN 4, db 0x90
PrintString:
__CDECL16_ENTRY
mov di, [bp + 4] ; first arg is char[]
.str_len:
xor cx, cx ; ECX = 0
not cx ; ECX = -1 == 0xFFFF
xor ax, ax ; search for al = 0x0
cld
repne scasb ; deincrement cx while searching for al
not cx ; the inverse of a neg number = abs(x) - 1
dec cx ; CX contains the length of the string - nul byte at end
.print:
mov si, [bp + 4] ; source string
.print_L0:
movzx ax, byte [si]
push ax
call PrintCharacter
add sp, 0x2
inc si
dec cx
jcxz PrintString.endp
jmp PrintString.print_L0 ; Fetch next character from string
.endp:
__CDECL16_EXIT
ret ; Return from procedure
; Prints a single character
; void PrintCharacter(char c);
ALIGN 4, db 0x90
PrintCharacter:
__CDECL16_ENTRY
.func:
movzx ax, byte [bp + 4] ; AL = character c
mov ah, 0x0E ; INT 0x10, AH=0x0E call
mov bx, 0x0007 ; BH = page no. BL =Text attribute 0x07 is lightgrey font on black background
int 0x10 ; call video interrupt
.endp:
__CDECL16_EXIT
ret
; TODO: fix the prolog, epilog and stack usage to confirm with cdecl16
; prints the hex representation of of val
; void PrintDWORD(uint32_t val);
ALIGN 4, db 0x90
PrintDWORD:
__CDECL16_ENTRY
.func:
mov si, IntToHex_table
mov ebx, 16 ; base-16
mov eax, dword [bp + 4] ;val
xor edx, edx
xor cx, cx
.next_digit:
div ebx ; dividend in edx:eax -> quotient in eax, remainder in edx
push dx ; save remainder
inc cx
xor dx, dx
test eax, eax
jnz PrintDWORD.next_digit
.zero_pad:
cmp cx, 0x0008
je PrintDWORD.print_stack
xor ax, ax
push ax
inc cx
jmp PrintDWORD.zero_pad
.print_stack:
pop bx
dec cx
push cx
movzx ax, byte [bx+si+0] ; bx = index into Hex lookup table
push ax
call PrintCharacter
add sp, 0x2
pop cx
jcxz PrintDWORD.endp
jmp PrintDWORD.print_stack
.endp:
__CDECL16_EXIT
ret
; ##############################
;
; SYSTEM CONFIGURATION FUNCTIONS
;
; ##############################
ALIGN 4, db 0x90
EnterUnrealMode:
__CDECL16_ENTRY
.func:
cli ; no interrupts
push ds ; save real mode data/stack selectors
push es
push fs
push gs
push ss
push cs ; save real mode code selector
xor ax, ax ;
pop ax ; save cs to ax to setup far jump
mov word [__UNREAL_SEGMENT], ax
; 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 al,1 ; set pmode bit
or eax, 1 ; set pmode bit
mov cr0, eax ; switch to pmode
jmp short $+2
jmp short $+2 ; i-cache flush
;jmp far 0x0008:EnterUnrealMode.load_cs
db 0xEA ; jmp far imm16:imm16
dw EnterUnrealMode.load_cs ; error_far_ptr
dw 0x0008 ; error_far_seg
.load_cs:
mov bx, 0x10 ; select descriptor 2
mov ds, bx ; 10h = 0001_0000b
mov ss, bx
mov es, bx
mov fs, bx
mov gs, bx ; other data/stack to index 2 (off 0x10)
and al,0xFE ; toggle bit 1 of cr0
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
;jmp far 0x0008:EnterUnrealMode.unload_cs
db 0xEA ; jmp far imm16:imm16
dw EnterUnrealMode.unload_cs ; error_far_ptr
__UNREAL_SEGMENT:
dw 0x0000 ; error_far_seg
EnterUnrealMode.unload_cs:
pop ss
pop gs
pop fs
pop es
pop ds ; get back old segments
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
EnterUnrealMode:
__CDECL16_PROC_ENTRY
cli ; no interrupts
.func:
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
; set cs to a pm code segment (0x8) w/ the following
jmp 0x0008:EnterUnrealMode.set_segs
.set_segs:
mov ax, 0x10 ; select descriptor 2
mov ds, ax ; 10h = 0001_0000b
mov es, ax ; es to big data
mov fs, ax
mov gs, ax ; extra segments to big data as well
.pm_start:
; code here is running in protected mode w/ descriptor 0x8
; insert any PM test code needed here
.pm_end:
mov eax, cr0
and eax, ~1 ; toggle bit 1 of cr0
mov cr0, eax ; back to realmode
jmp __STAGE2_SEGMENT:EnterUnrealMode.endp
.endp:
__CDECL16_EXIT
sti ; re-enable interupts
; 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
end_text:
@@ -361,13 +299,13 @@ begin_data:
%define CRLF 0Dh, 0Ah
%macro define_cstr 2
ALIGN 16
align 16
%1_cstr:
db %2, 00h
%endmacro
%macro define_info 2
ALIGN 16
align 16
%1_info:
db %2, CRLF, 00h
%endmacro
@@ -386,7 +324,7 @@ define_info MaybeFound_Boot, "Maybe found a file...checking..."
define_cstr BootTarget, "BOOT BIN"
ALIGN 16, db 0
align 16, db 0
BootTarget:
db 'BOOT BIN'
@@ -394,28 +332,28 @@ BootTarget:
; pre-bss init globals (generally const...but there are exceptions)
;
align 8, db 0x00
align 8, db 0
boot_drive:
db 0x00
align 8, db 0x00
align 8, db 0
partition_offset:
dw 0x0000
align 8, db 0x00
align 8, db 0
vbr_fat32_bpb_ptr:
dw 0x0000
align 8, db 0x00
align 8, db 0
vbr_part_table_ptr:
dw 0x0000
ALIGN 16
align 16, db 0
IntToHex_table:
db '0123456789ABCDEF'
; see docs/gdt.txt for a quick refresher on GDT
ALIGN 16, db 0
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)
@@ -423,14 +361,14 @@ unreal_gdt_start:
; entry 0 (null descriptor)
dq 0 ; first entry is null
; entry 1 (16bit code 64KiB limit)
; entry 1 (0x8) (16bit code 64KiB limit)
dd 0x0000FFFF ; Base Address(15:0) 31:16, Segment Limit(15:0) 15:0
db 0x00 ; Base Address 23:16
db 1001_1010b ; Access Byte: Present, ring0, S = 1, executable (1), non-conforming, readable, Accessed
db 0000_0000b ; Flags: GR = 4KiB, attr = <DB/L/Avl>, Granularity = 4KiB & 16:19 of limit
db 0x00 ; Base Address 31:24
; entry 2 (16bit data segment with 4 GiB flat mapping)
; entry 2 (0x10) (16bit data segment with 4 GiB flat mapping)
dd 0x0000FFFF ; Base Address(15:0) 31:16, Segment Limit(15:0) 15:0
db 0x00 ; Base Address(23:16)
db 1001_0010b ; Access Byte: Present, ring0, S = 1, data (0), non-confirming, writable, present
@@ -438,7 +376,7 @@ unreal_gdt_start:
db 0x00 ; Base Address(31:24)
unreal_gdt_end:
ALIGN 16, db 0
align 16, db 0
gdt32_info:
gdt32_size: dw (gdt32_end - gdt32_start) - 1
gdt32_ptr: dd ((__STAGE2_SEGMENT << 4) + gdt32_start)
@@ -474,19 +412,19 @@ gdt32_start:
db 0x00
gdt32_end:
ALIGN 8,db 0x00
align 16,db 0
BUILD_NASM_VER:
db "Stevia Stage2 built with NASM - ", __NASM_VER__, 00h
ALIGN 8,db 0x00
align 16,db 0
BUILD_DATETIME:
db 'Assembled - ', __DATE__, ' ', __TIME__, 00h
ALIGN 8,db 0x00
align 16,db 0
BUILD_GIT_VER:
db __GIT_VER__, 00h
ALIGN 8,db 0x00
align 16,db 0
BUILD_GIT_HASH:
db __GIT_HASH__, 00h
end_data:
@@ -504,26 +442,35 @@ section .bss follows=.sign
begin_bss:
; structures
alignb 16
partition_table resb PartTable_t_size
align 16, resb 1
partition_table:
resb PartTable_t_size
alignb 16
fat32_bpb resb FAT32_bpb_t_size
fat32_ebpb resb FAT32_ebpb_t_size
align 16, resb 1
fat32_bpb:
resb FAT32_bpb_t_size
fat32_ebpb:
resb FAT32_ebpb_t_size
alignb 16
fat32_nc_data resb 16
align 16, resb 1
fat32_nc_data:
resb 16
alignb 16
lba_packet resb LBAPkt_t_size
align 16, resb 1
lba_packet:
resb LBAPkt_t_size
alignb 16
align 16, resb 1
fat32_state:
resb FAT32_State_t_size
alignb 16
align 16, resb 1
SteviaInfo:
resd 4
align 16, resb 1
early_heap_state:
resb ArenaStateStruc_t_size
;
; post-bss init globals
;
@@ -531,7 +478,7 @@ SteviaInfo:
;
; large continuous allocations
;
alignb 16
align 16, resb 1
disk_buffer:
resb 512
fat_buffer:
@@ -541,12 +488,15 @@ dir_buffer:
fat_fsinfo:
resb 512
alignb 16
; TODO: this will hold 42 entries from the map function
; the e820 function needs to check that it doesn't overflow
; but realisticly 42 entries is enough for dev work
align 16, resb 1
%define BIOSMemoryMap_SIZE 1024
BIOSMemoryMap:
resb BIOSMemoryMap_SIZE
alignb 512
align 16, resb 1
stack_bottom:
resb 1024
stack_top:

View File

@@ -72,7 +72,7 @@ init:
cld
rep stosb
sub sp, 0x20 ; local varible space
sub sp, 0x20 ; local varible space (32 bytes)
push bp
sti ; all done with inital setup and relocation, reenable interupts