17 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
16 changed files with 262 additions and 217 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
@@ -83,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
@@ -106,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:
@@ -134,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
@@ -123,7 +123,7 @@ read_disk_raw:
ERROR STAGE2_MBR_DISK_READ_ERROR
%endif
.endf:
__CDECL16_EXIT
__CDECL16_PROC_EXIT
ret
%endif

View File

@@ -20,7 +20,7 @@
ALIGN 4, db 0x90
SetTextMode:
.prolog:
__CDECL16_ENTRY
__CDECL16_PROC_ENTRY
pushf
.func:
xor ah, ah ; Set Video mode BIOS function
@@ -33,14 +33,14 @@ SetTextMode:
int 0x10 ; call video interrupt
.endp:
popf
__CDECL16_EXIT
__CDECL16_PROC_EXIT
ret
; disables blinking text mode cursor via crtc pokes
; 0x3D4/0x3D5 for color, mono at 0x3B4/0x3B5
ALIGN 4, db 0x90
disable_cursor_crtc:
__CDECL16_ENTRY
__CDECL16_PROC_ENTRY
.func:
mov dx, 0x3D4
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
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_ENTRY
__CDECL16_PROC_ENTRY
.func:
push bx
mov ah, 03h ; read cursor pos & shape
@@ -68,14 +68,14 @@ disable_cursor_bios:
int 10h
pop bx
.endp:
__CDECL16_EXIT
__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_ENTRY
__CDECL16_PROC_ENTRY
mov di, [bp + 4] ; first arg is char[]
.str_len:
xor cx, cx ; ECX = 0
@@ -91,6 +91,9 @@ PrintString:
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
@@ -101,14 +104,14 @@ PrintString:
jcxz PrintString.endp
jmp PrintString.print_L0 ; Fetch next character from string
.endp:
__CDECL16_EXIT
__CDECL16_PROC_EXIT
ret ; Return from procedure
; Prints a single character
; void PrintCharacter(char c);
ALIGN 4, db 0x90
PrintCharacter:
__CDECL16_ENTRY
__CDECL16_PROC_ENTRY
.func:
mov al, byte [bp + 4] ; AL = character c
mov ah, 0x0E ; INT 0x10, AH=0x0E call
@@ -116,7 +119,7 @@ PrintCharacter:
int 0x10 ; call video interrupt
; TODO: check for carry and clear carry before call
.endp:
__CDECL16_EXIT
__CDECL16_PROC_EXIT
ret
; TODO: fix the prolog, epilog and stack usage to confirm with cdecl16
@@ -124,7 +127,7 @@ PrintCharacter:
; void PrintDWORD(uint32_t val);
ALIGN 4, db 0x90
PrintDWORD:
__CDECL16_ENTRY
__CDECL16_PROC_ENTRY
.func:
mov si, IntToHex_table
mov ebx, 16 ; base-16
@@ -166,7 +169,7 @@ PrintDWORD:
jmp PrintDWORD.print_stack
.endp:
__CDECL16_EXIT
__CDECL16_PROC_EXIT
ret
%endif
%define __INC_VIDEO

View File

@@ -13,8 +13,8 @@
; 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-1
%ifnmacro __CDECL16_PROC_ENTRY
%macro __CDECL16_PROC_ENTRY 0-1
push bp
mov bp, sp
@@ -28,8 +28,8 @@
%endmacro
%endif
%ifnmacro __CDECL16_EXIT
%macro __CDECL16_EXIT 0
%ifnmacro __CDECL16_PROC_EXIT
%macro __CDECL16_PROC_EXIT 0
pop bx
pop di
pop si
@@ -39,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
add 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
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
.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
add 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

@@ -12,7 +12,7 @@ endstruc
; 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
@@ -35,7 +35,7 @@ arena_init:
add sp, 0x6
.endp:
__CDECL16_EXIT
__CDECL16_PROC_EXIT
ret
; size_t align_up(size_t x, size_t a)
@@ -44,7 +44,7 @@ arena_init:
; (x + (a-1)) & ~(a-1)
; return value in ax
arena_align_up:
__CDECL16_ENTRY
__CDECL16_PROC_ENTRY
.func:
; if a == 0 return x
mov ax, [bp + 4] ; x
@@ -81,7 +81,7 @@ arena_align_up:
mov ax, cx ; move to ax and return
.endp:
__CDECL16_EXIT
__CDECL16_PROC_EXIT
ret
; void* arena_alloc(size_t bytes, size_t align)
@@ -89,7 +89,7 @@ arena_align_up:
; bp-4 - aligned_ptr
; bp-6 - new_end
arena_alloc:
__CDECL16_ENTRY 0x10
__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
@@ -133,36 +133,36 @@ arena_alloc:
; 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

@@ -124,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

@@ -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
@@ -135,57 +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_bios
print_string HelloPrompt_info
; setup the early heap
mov ax, early_heap_state
push ax ; address in bss of state structure
call arena_init
add sp, 0x2
__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 (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
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)
@@ -260,8 +250,7 @@ hcf:
ALIGN 4, db 0x90
EnterUnrealMode:
__BOCHS_MAGIC_DEBUG
__CDECL16_ENTRY
__CDECL16_PROC_ENTRY
cli ; no interrupts
.func:
lgdt [((__STAGE2_SEGMENT << 4) + unreal_gdt_info)] ; load unreal gdt
@@ -272,9 +261,6 @@ EnterUnrealMode:
; set cs to a pm code segment (0x8) w/ the following
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:
mov ax, 0x10 ; select descriptor 2
mov ds, ax ; 10h = 0001_0000b
@@ -289,7 +275,7 @@ EnterUnrealMode:
mov eax, cr0
and eax, ~1 ; toggle bit 1 of cr0
mov cr0, eax ; back to realmode
jmp 0x0000:EnterUnrealMode.endp
jmp __STAGE2_SEGMENT:EnterUnrealMode.endp
.endp:
sti ; re-enable interupts
@@ -298,7 +284,7 @@ EnterUnrealMode:
; to easily access data outside of 64KiB boundries using ds/es addressing
__TINY_DS_ES
__CDECL16_EXIT
__CDECL16_PROC_EXIT
ret
end_text: