Compare commits
210 Commits
fat32_sys_
...
81a3442ac5
| Author | SHA1 | Date | |
|---|---|---|---|
| 81a3442ac5 | |||
| 3ec55f5a39 | |||
| 9493aefa68 | |||
| 6f2fc627be | |||
| 20c715fadd | |||
| 920c623a93 | |||
| af8e7d74d3 | |||
| fde7abc544 | |||
| 69223a1ad2 | |||
| 130cd22ff1 | |||
| 4e5112b45b | |||
| 66e8e3c7fc | |||
| b0bd4b27b0 | |||
| cd316afdd1 | |||
| 9a478aa4d4 | |||
| 31d05c35e5 | |||
| 534e04ef34 | |||
| f58bf93507 | |||
| b5ae11f850 | |||
| b9b3e92632 | |||
| 5fac10f02c | |||
| fa4524aa59 | |||
| 01ec6da0cc | |||
| 2e2b4f991d | |||
| d7b29d9113 | |||
| 69d82dc0c2 | |||
| a53534acd2 | |||
| c3871d2b7d | |||
| d824493ba2 | |||
| cb089681cf | |||
| d868008726 | |||
| 935427509a | |||
| f5e4927d70 | |||
| b106eae066 | |||
| f2657fdc01 | |||
| 86d966811b | |||
| c10394a0cd | |||
| 28b23b9ce2 | |||
| 105ceb8b8b | |||
| 7fd5b9b85d | |||
| a618a837d4 | |||
| 930d49c353 | |||
| 06d00d02e2 | |||
| 61379e8116 | |||
| 828428e73b | |||
| 402bf9974d | |||
| 5dfc3533d9 | |||
| d9225718c2 | |||
| 8a6730bc9c | |||
| 67523208b3 | |||
| ffe887b6a9 | |||
| c45e62ecc2 | |||
| d7c50575cf | |||
| 39148869bc | |||
| 81e6b6e835 | |||
| 63c5e0d00e | |||
| 29a2a598ba | |||
| 47b18de37e | |||
| 8129a71fdd | |||
| ef42ae084b | |||
| 578e9934d8 | |||
| 2a6792ae01 | |||
| 2c5e5ccbee | |||
| a830191547 | |||
| 38bcd93ced | |||
| f1842d0cbc | |||
| e085cbbab7 | |||
| 915ac4c8ae | |||
| e65220fece | |||
| 6731e03e38 | |||
| 47a47051b2 | |||
| 8e2ca06406 | |||
| 2b9d0d9946 | |||
| 1ce3f67263 | |||
| f81f358987 | |||
| 41db11cc64 | |||
| fd7754bc60 | |||
| 0f04e682df | |||
| 36fcb5faf0 | |||
| a5296bb438 | |||
| 933cccb88e | |||
| ad2d37c63b | |||
| f32745a7e3 | |||
| 8537d6cd5e | |||
| e57c2cc67d | |||
| e4b9c5d77f | |||
| e3a646675f | |||
| 9d33469e32 | |||
| dd1a74bff0 | |||
| 29db27925f | |||
| 7f06d47f32 | |||
| 4faffbf7fe | |||
| 832141efb4 | |||
| c919144496 | |||
| a62f3de26f | |||
| 0983ec3fd5 | |||
| bd40d6d324 | |||
| 3d3bcc6ea5 | |||
| d1f8ec4a9e | |||
| 2fa03c31d7 | |||
| f535840572 | |||
| 54b7a81648 | |||
| 1d84f52690 | |||
| 276fe70572 | |||
| 73b42c66fd | |||
| 9656a9465b | |||
| bd80f48b1b | |||
| 3fbfcbef53 | |||
| 31c45051e6 | |||
| a523e17d27 | |||
| 65e5a83eb4 | |||
| cd048933ec | |||
| e648fd0de6 | |||
| 2581e50c8b | |||
| 60aaf5cdd9 | |||
| 59678149e0 | |||
| 075e51c8bc | |||
| 48cd0f742d | |||
| e5fb1b41eb | |||
| 208729ed01 | |||
| 086cf9d8ea | |||
| 095822fa27 | |||
| 71f13fd6b5 | |||
| 802d47fbf7 | |||
| 4af0637c7f | |||
| 07197b0d5b | |||
| 056551fdd1 | |||
| 0aae0616fd | |||
| aff631f3db | |||
| a3a768adf4 | |||
| d684d4f11f | |||
| 75c046f9cd | |||
| 00daf92df5 | |||
| 5ab7e70455 | |||
| 6ae68d1a19 | |||
| 586f3f0106 | |||
| 8301fc20a8 | |||
| 4218a08658 | |||
| 2bbdaddb68 | |||
| 213ea11209 | |||
| e41b597056 | |||
| f33ecbcea2 | |||
| 03a09ed54b | |||
| 145e9fbaa9 | |||
| 8f95c8f267 | |||
| 5440a1ae61 | |||
| d6af15a7a6 | |||
| a4fa48949c | |||
| 0a1123c5b5 | |||
| e162e268c4 | |||
| 62f036b645 | |||
| fdbfd811d5 | |||
| d93236d298 | |||
| 86fd76e909 | |||
| 3f029e6b4c | |||
| 30c4f1b82c | |||
| 597132df9f | |||
| 63e6f1fac8 | |||
| 4ee766304b | |||
| d5aa70daf3 | |||
| ec1f40c305 | |||
| 36e3bd968a | |||
| 36b8869140 | |||
| 41b9bf5134 | |||
| b96f587921 | |||
| 89ebe30ad8 | |||
| e98cc41403 | |||
| 27c41c8b0a | |||
| 015def8d52 | |||
| 8157dd301c | |||
| 4d05d2ae4c | |||
| de5b0ddc5d | |||
| 2cfe86efac | |||
| c8ca94d7ba | |||
| ac6110aa40 | |||
| 46717935a1 | |||
| f691000a31 | |||
| c524d8801d | |||
| 0084747765 | |||
| 929962eaca | |||
| 054f4320ba | |||
| 2f6bd2e2d8 | |||
| 7c446ef3b2 | |||
| 2bbfa0931b | |||
| 8e595e8eba | |||
| 5e4e40f7de | |||
| 6db97e3258 | |||
| d42ee1df60 | |||
| 96a8103e11 | |||
| a5702bd92e | |||
| bdc1fc5bf0 | |||
| 1c27b665b0 | |||
| abc79adeb7 | |||
| 7fd4a89d96 | |||
| 355ceb49a7 | |||
| b590edd3ff | |||
| 30b71d2e6e | |||
| b2857ff9fd | |||
| 4e9e58c430 | |||
| 5916b46a9e | |||
| d162d5dc4c | |||
| d4dc46d770 | |||
| ad828ac1f4 | |||
| 5fdde61dd3 | |||
| 90ced63cba | |||
| 2c55ed5c04 | |||
| 94a2fb08ca | |||
| b9850f7ab9 | |||
|
|
f181f21e41 | ||
|
|
309a5fb95c |
40
.gitea/workflows/onpush.yaml
Normal file
40
.gitea/workflows/onpush.yaml
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
name: Daily Build and trunk tester
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [ $default-branch ]
|
||||||
|
pull_request:
|
||||||
|
branches: [ $default-branch ]
|
||||||
|
schedule:
|
||||||
|
- cron: "0 7 * * *" # daily 07:00
|
||||||
|
workflow_dispatch: {}
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
debian_update:
|
||||||
|
runs-on: debian-trixie
|
||||||
|
steps:
|
||||||
|
- name: Checkout (if needed)
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Install CHTM apt cache endpoint into container
|
||||||
|
run: |
|
||||||
|
echo 'Acquire::http::Proxy "http://chtm-aptcache-01.lan.chtm.me:3142";' | tee /etc/apt/apt.conf.d/01aptproxy
|
||||||
|
|
||||||
|
- name: Ensure image is up to date and install build tools and deps
|
||||||
|
run: |
|
||||||
|
bash -c "apt update && apt upgrade -y"
|
||||||
|
apt install -y build-essential nasm mtools fdisk dosfstools
|
||||||
|
|
||||||
|
- name: Build stevia
|
||||||
|
run: make
|
||||||
|
|
||||||
|
- name: Upload build artifacts
|
||||||
|
if: always() # still keep logs/artifacts even if build fails
|
||||||
|
uses: actions/upload-artifact@v3
|
||||||
|
with:
|
||||||
|
name: stevia-${{ github.run_number }}
|
||||||
|
path: |
|
||||||
|
build/output/artifacts.tar.gz
|
||||||
|
build/output/disk.img.gz
|
||||||
|
build/output/part.img.gz
|
||||||
|
if-no-files-found: error
|
||||||
|
retention-days: 30 # override server default if you like
|
||||||
35
.github/workflows/daily.yaml
vendored
Normal file
35
.github/workflows/daily.yaml
vendored
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
name: Daily Build and trunk tester
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [ $default-branch ]
|
||||||
|
schedule:
|
||||||
|
- cron: "0 7 * * *" # daily 07:00
|
||||||
|
workflow_dispatch: {}
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
debian_update:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout (if needed)
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Update and install build tools and deps
|
||||||
|
run: |
|
||||||
|
sudo bash -c "apt update && apt upgrade -y"
|
||||||
|
sudo apt install -y build-essential nasm mtools fdisk dosfstools
|
||||||
|
|
||||||
|
- name: Build stevia
|
||||||
|
run: make
|
||||||
|
|
||||||
|
- name: Upload build artifacts
|
||||||
|
if: always() # still keep logs/artifacts even if build fails
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: stevia-${{ github.run_number }}
|
||||||
|
path: |
|
||||||
|
build/output/artifacts.tar.gz
|
||||||
|
build/output/disk.img.gz
|
||||||
|
build/output/part.img.gz
|
||||||
|
if-no-files-found: error
|
||||||
|
retention-days: 7 # override server default if you like
|
||||||
|
|
||||||
3
.gitignore
vendored
3
.gitignore
vendored
@@ -1,7 +1,8 @@
|
|||||||
out/*
|
|
||||||
build/*
|
build/*
|
||||||
|
build/output/*
|
||||||
*.img
|
*.img
|
||||||
*.img.gz
|
*.img.gz
|
||||||
|
*.img.gz
|
||||||
*.elf
|
*.elf
|
||||||
bx_enh_dbg.ini
|
bx_enh_dbg.ini
|
||||||
stevia-log
|
stevia-log
|
||||||
|
|||||||
14
LICENSE.md
14
LICENSE.md
@@ -1,14 +0,0 @@
|
|||||||
Copyright (C) 2025 Elaina Claus
|
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
16
Makefile
16
Makefile
@@ -32,8 +32,8 @@ GIT_VERSION := $(shell git describe --tags)
|
|||||||
GIT_HASH := $(shell git rev-parse HEAD)
|
GIT_HASH := $(shell git rev-parse HEAD)
|
||||||
GIT_NASM_DEFINES := -D __GIT_VER__='"$(GIT_VERSION)"' -D __GIT_HASH__='"$(GIT_HASH)"'
|
GIT_NASM_DEFINES := -D __GIT_VER__='"$(GIT_VERSION)"' -D __GIT_HASH__='"$(GIT_HASH)"'
|
||||||
|
|
||||||
iso := '/tmp/disk.img'
|
iso := 'build/disk.img'
|
||||||
isoz := 'disk.img.gz'
|
isoz := 'build/output/disk.img.gz'
|
||||||
|
|
||||||
qemu_args := -L ./bin/ -bios bios.bin -cpu pentium3 -m 128 -S -s -monitor stdio -nic none
|
qemu_args := -L ./bin/ -bios bios.bin -cpu pentium3 -m 128 -S -s -monitor stdio -nic none
|
||||||
.PHONY: all mbr vbr stage2 boottest clean run run_bochs iso isoz
|
.PHONY: all mbr vbr stage2 boottest clean run run_bochs iso isoz
|
||||||
@@ -45,10 +45,11 @@ stage2: $(stage2_binary_files)
|
|||||||
boottest: $(boottest_binary_files)
|
boottest: $(boottest_binary_files)
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
@rm -rvf *.map
|
@rm -v $(build_dir)/*.bin
|
||||||
@rm -rvf $(build_dir)/*
|
@rm -v $(build_dir)/*.map
|
||||||
@rm -rvf $(iso)
|
@rm -v $(build_dir)/*.img
|
||||||
@rm -rvf $(isoz)
|
@rm -v $(build_dir)/output/*.img.gz
|
||||||
|
@rm -v $(build_dir)/output/*.tar.gz
|
||||||
|
|
||||||
run: $(iso)
|
run: $(iso)
|
||||||
@sudo qemu-system-i386 $(qemu_args) -hda $(iso)
|
@sudo qemu-system-i386 $(qemu_args) -hda $(iso)
|
||||||
@@ -79,8 +80,7 @@ build/%.bin: src/miniboot32/%.nasm
|
|||||||
@nasm -i$(include) -Wall -f bin $(GIT_NASM_DEFINES) $< -o $@
|
@nasm -i$(include) -Wall -f bin $(GIT_NASM_DEFINES) $< -o $@
|
||||||
|
|
||||||
$(iso): $(mbr_binary_files) $(vbr_binary_files) $(stage2_binary_files) $(boottest_binary_files)
|
$(iso): $(mbr_binary_files) $(vbr_binary_files) $(stage2_binary_files) $(boottest_binary_files)
|
||||||
@echo root access needed to create disk image...
|
@scripts/create-disk.sh
|
||||||
@sudo scripts/create-disk.sh
|
|
||||||
|
|
||||||
$(isoz): $(iso)
|
$(isoz): $(iso)
|
||||||
@gzip -9kc $(iso) > $(isoz)
|
@gzip -9kc $(iso) > $(isoz)
|
||||||
|
|||||||
47
README.md
47
README.md
@@ -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,42 +24,38 @@ 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
|
||||||
|
|
||||||
This project is licensed under the MIT License. See the [LICENSE](LICENSE) file for more details.
|
This project is licensed under the GPLv3 License. See the [LICENSE](LICENSE.md) or [COPYING](COPYING) file for more details.
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
# configuration file generated by Bochs
|
# 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
|
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
|
||||||
config_interface: textconfig
|
config_interface: textconfig
|
||||||
display_library: wx
|
display_library: x, options=gui_debug
|
||||||
memory: guest=64, host=64, block_size=128
|
memory: guest=64, host=64, block_size=128
|
||||||
romimage: file="/usr/share/bochs/BIOS-bochs-legacy", address=0x00000000, options=none, flash_data=none
|
romimage: file="/usr/share/bochs/BIOS-bochs-legacy", address=0x00000000, options=none, flash_data=none
|
||||||
vgaromimage: file="/usr/share/bochs/VGABIOS-lgpl-latest"
|
vgaromimage: file="/usr/share/bochs/VGABIOS-lgpl-latest"
|
||||||
@@ -10,7 +10,7 @@ floppy_bootsig_check: disabled=0
|
|||||||
floppya: type=1_44
|
floppya: type=1_44
|
||||||
# no floppyb
|
# no floppyb
|
||||||
ata0: enabled=true, ioaddr1=0x1f0, ioaddr2=0x3f0, irq=14
|
ata0: enabled=true, ioaddr1=0x1f0, ioaddr2=0x3f0, irq=14
|
||||||
ata0-master: type=disk, path="./disk.img", mode=flat, cylinders=0, heads=0, spt=0, sect_size=512, model="Stevia Disk", biosdetect=auto, translation=lba
|
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
|
ata0-slave: type=none
|
||||||
ata1: enabled=false
|
ata1: enabled=false
|
||||||
ata1-master: type=none
|
ata1-master: type=none
|
||||||
|
|||||||
0
build/.keep_dir
Normal file
0
build/.keep_dir
Normal file
0
build/output/.keep_dir
Normal file
0
build/output/.keep_dir
Normal file
@@ -35,28 +35,33 @@ 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
|
||||||
|
|
||||||
mov eax, 0xE820 ; select 0xE820 function
|
|
||||||
xor ebx, ebx ; Continuation value, 0 for the first call
|
xor ebx, ebx ; Continuation value, 0 for the first call
|
||||||
|
|
||||||
lea dx, [BIOSMemoryMap]
|
mov dx, BIOSMemoryMap
|
||||||
shr dx, 4
|
shr dx, 4
|
||||||
mov es, dx
|
mov es, dx
|
||||||
xor di, di ; (BIOSMemoryMap >> 4):0 makes di an index into BIOSMemoryMap
|
xor di, di ; (BIOSMemoryMap >> 4):0 makes di an index into BIOSMemoryMap
|
||||||
|
|
||||||
mov ecx, AddressRangeDescStruct_t_size
|
mov ecx, AddressRangeDescStruct_t_size ; hard request ACPI 3.0 table versions (24 bytes)
|
||||||
mov edx, 0x534D4150 ; 'SMAP' magic
|
|
||||||
.loop_L1:
|
.loop_L1:
|
||||||
|
mov eax, 0x0000E820 ; select 0xE820 function
|
||||||
|
mov edx, 0x534D4150 ; 'SMAP' magic
|
||||||
|
clc ; clear carry
|
||||||
int 0x15
|
int 0x15
|
||||||
jc GetMemoryMap.error
|
jc GetMemoryMap.error
|
||||||
cmp eax, 0x534D4150
|
cmp eax, 0x534D4150
|
||||||
jne GetMemoryMap.no_smap_returned
|
jne GetMemoryMap.no_smap_returned
|
||||||
.no_error:
|
.no_error:
|
||||||
inc dword [SteviaInfo + SteviaInfoStruct_t.MemoryMapEntries]
|
mov eax, dword [SteviaInfo + SteviaInfoStruct_t.MemoryMapEntries]
|
||||||
|
add eax, 1
|
||||||
|
mov dword [SteviaInfo + SteviaInfoStruct_t.MemoryMapEntries], eax
|
||||||
|
|
||||||
cmp ecx, 20 ; TODO: maybe this could be handled better than just panicing
|
cmp ecx, 20 ; TODO: maybe this could be handled better than just panicing
|
||||||
jb GetMemoryMap.nonstandard_e820 ; non-standard entry found
|
jb GetMemoryMap.nonstandard_e820 ; non-standard entry found
|
||||||
@@ -64,9 +69,11 @@ GetMemoryMap:
|
|||||||
cmp ebx, 0
|
cmp ebx, 0
|
||||||
je GetMemoryMap.endp ; 0 in ebx means we have reached the end of memory ranges
|
je GetMemoryMap.endp ; 0 in ebx means we have reached the end of memory ranges
|
||||||
|
|
||||||
add di, AddressRangeDescStruct_t_size ; increment di to next descriptor
|
; setup for next loop, ebx is our next index and has already been set.
|
||||||
mov edx, eax ; 'SMAP' to edx
|
xor ecx, ecx
|
||||||
mov eax, 0xE820 ; select E820 function
|
mov ecx, AddressRangeDescStruct_t_size ; set ecx (requested_size) to 24 bytes
|
||||||
|
add di, cx ; increment di to next descriptor so es:di points to the next free space
|
||||||
|
|
||||||
jmp GetMemoryMap.loop_L1
|
jmp GetMemoryMap.loop_L1
|
||||||
.error:
|
.error:
|
||||||
ERROR STAGE2_MM_E820_MISC_ERR
|
ERROR STAGE2_MM_E820_MISC_ERR
|
||||||
@@ -76,8 +83,40 @@ 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:
|
||||||
|
__CDECL16_PROC_ENTRY
|
||||||
|
.func:
|
||||||
|
mov eax, dword [SteviaInfo + SteviaInfoStruct_t.MemoryMapEntries]
|
||||||
|
cmp eax, 0
|
||||||
|
je PrintMemoryMap.endp ; if entries == 0, exit
|
||||||
|
|
||||||
|
mov ecx, eax ; store # of entries in counter
|
||||||
|
mov eax, BIOSMemoryMap ; address to start of e820 mmap
|
||||||
|
|
||||||
|
push dword ecx
|
||||||
|
push dword eax
|
||||||
|
call FormatMemoryMapEntry
|
||||||
|
add sp, 0x8
|
||||||
|
|
||||||
|
; ax contains segment offset to string after call
|
||||||
|
; TODO: going to need an allocator for strings and stuff...
|
||||||
|
; print_string strformat_buffer
|
||||||
|
|
||||||
|
.endp:
|
||||||
|
__CDECL16_PROC_EXIT
|
||||||
|
ret
|
||||||
|
|
||||||
|
FormatMemoryMapEntry:
|
||||||
|
__CDECL16_PROC_ENTRY
|
||||||
|
.func:
|
||||||
|
; create a string buffer somewhere and return address to result string in ax
|
||||||
|
.endp:
|
||||||
|
__CDECL16_PROC_EXIT
|
||||||
|
ret
|
||||||
|
|
||||||
|
|
||||||
%endif
|
%endif
|
||||||
%define __INC_E820MEMORY_MAP
|
%define __INC_E820MEMORY_MAP
|
||||||
@@ -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:
|
||||||
@@ -105,6 +105,7 @@ EnableA20:
|
|||||||
je EnableA20.endp ; A20 is already enabled
|
je EnableA20.endp ; A20 is already enabled
|
||||||
|
|
||||||
mov ax, 0x2403
|
mov ax, 0x2403
|
||||||
|
clc ; clear carry
|
||||||
int 0x15
|
int 0x15
|
||||||
jc EnableA20.do_fallback_a20 ; carry = error...not supported?
|
jc EnableA20.do_fallback_a20 ; carry = error...not supported?
|
||||||
cmp ah, 0
|
cmp ah, 0
|
||||||
@@ -121,6 +122,7 @@ EnableA20:
|
|||||||
ERROR STAGE2_A20_FAILED
|
ERROR STAGE2_A20_FAILED
|
||||||
.do_bios_a20:
|
.do_bios_a20:
|
||||||
mov ax, 0x2401
|
mov ax, 0x2401
|
||||||
|
clc ; clear carry
|
||||||
int 0x15
|
int 0x15
|
||||||
jmp EnableA20.a20_check
|
jmp EnableA20.a20_check
|
||||||
.do_fast_a20:
|
.do_fast_a20:
|
||||||
@@ -132,7 +134,7 @@ EnableA20:
|
|||||||
.endp:
|
.endp:
|
||||||
pop es
|
pop es
|
||||||
pop ds
|
pop ds
|
||||||
__CDECL16_EXIT
|
__CDECL16_PROC_EXIT
|
||||||
ret
|
ret
|
||||||
|
|
||||||
%endif
|
%endif
|
||||||
|
|||||||
@@ -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
|
||||||
@@ -111,6 +111,7 @@ read_disk_raw:
|
|||||||
mov ah, 0x42 ; call #
|
mov ah, 0x42 ; call #
|
||||||
mov dl, byte [bp + 14] ; drive #
|
mov dl, byte [bp + 14] ; drive #
|
||||||
|
|
||||||
|
clc ; clear carry
|
||||||
int 0x13
|
int 0x13
|
||||||
jnc .endf
|
jnc .endf
|
||||||
|
|
||||||
@@ -122,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
|
||||||
|
|||||||
@@ -20,25 +20,27 @@
|
|||||||
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
|
||||||
mov al, 0x02 ; 16 color 80x25 Text mode
|
mov al, 0x03 ; 16 color 80x25 Text mode
|
||||||
int 0x10 ; Call video interrupt
|
int 0x10 ; Call video interrupt
|
||||||
|
|
||||||
|
|
||||||
mov ah, 0x05 ; Select active display page BIOS function
|
mov ah, 0x05 ; Select active display page BIOS function
|
||||||
xor al, al ; page 0
|
xor al, al ; page 0
|
||||||
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
|
; disables blinking text mode cursor via crtc pokes
|
||||||
|
; 0x3D4/0x3D5 for color, mono at 0x3B4/0x3B5
|
||||||
ALIGN 4, db 0x90
|
ALIGN 4, db 0x90
|
||||||
disable_cursor:
|
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
|
||||||
@@ -48,8 +50,123 @@ disable_cursor:
|
|||||||
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
|
||||||
|
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]
|
||||||
|
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
|
%endif
|
||||||
%define __INC_VIDEO
|
%define __INC_VIDEO
|
||||||
@@ -13,20 +13,23 @@
|
|||||||
; 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
|
%macro __CDECL16_PROC_ENTRY 0-1
|
||||||
push bp
|
push bp
|
||||||
mov bp, sp
|
mov bp, sp
|
||||||
sub sp, 0x10
|
|
||||||
|
|
||||||
push si
|
push si
|
||||||
push di
|
push di
|
||||||
push bx
|
push bx
|
||||||
|
|
||||||
|
%if %0 = 1
|
||||||
|
sub sp, %1 ; reserve locals only when needed
|
||||||
|
%endif
|
||||||
%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
|
||||||
@@ -36,19 +39,98 @@
|
|||||||
%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
|
||||||
|
%assign %$__i 1
|
||||||
|
%rep %1
|
||||||
|
%xdefine %$arg%$__i [bp + 4 + 2*(%$__i-1)]
|
||||||
|
%assign %$__i %$__i + 1
|
||||||
|
%endrep
|
||||||
%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
|
%assign %$__i %0
|
||||||
|
%rep %0
|
||||||
|
push %[%$__i]
|
||||||
|
%assign %$__i %$__i - 1
|
||||||
|
%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-*
|
||||||
|
call %1
|
||||||
|
%assign %$__sum 0
|
||||||
|
%assign %$__i 2
|
||||||
|
%rep %0-1
|
||||||
|
%assign %$__sum %$__sum + %[%$__i]
|
||||||
|
%assign %$__i %$__i + 1
|
||||||
|
%endrep
|
||||||
|
add sp, %$__sum
|
||||||
|
%endmacro
|
||||||
|
%endif
|
||||||
|
|
||||||
|
; __CDECL16_INVOKE func, arg1[, arg2 ...]
|
||||||
|
; pushes args right-to-left, calls, then add sp by (#args)*2
|
||||||
|
; !!! warning for word sized args only !!!
|
||||||
|
%ifnmacro __CDECL16_INVOKE
|
||||||
|
%macro __CDECL16_INVOKE 1-*
|
||||||
|
%assign %$__argc %0-1
|
||||||
|
%if %$__argc > 0
|
||||||
|
; push args right-to-left
|
||||||
|
%assign %$__i %0
|
||||||
|
%rep %$__argc
|
||||||
|
push %[%$__i]
|
||||||
|
%assign %$__i %$__i - 1
|
||||||
|
%endrep
|
||||||
|
call %1
|
||||||
|
add sp, %$__argc*2
|
||||||
|
%else
|
||||||
|
call %1
|
||||||
|
%endif
|
||||||
|
%endmacro
|
||||||
|
%endif
|
||||||
|
|
||||||
|
%ifnmacro __CDECL16_CLOB
|
||||||
|
; e.g CLOB ax dx ... inside func entry, then UNCLOB ax dx at all exits
|
||||||
|
; ordering is already taken care of
|
||||||
|
; i.e if you CLOB ax cx dx then UNCLOB ax cx dx, the unclob is reversed
|
||||||
|
%macro __CDECL16_CLOB 1-*
|
||||||
|
%assign %$i 1
|
||||||
|
%rep %0
|
||||||
|
push %[%$i]
|
||||||
|
%assign %$i %$i+1
|
||||||
|
%endrep
|
||||||
|
%endmacro
|
||||||
|
%endif
|
||||||
|
|
||||||
|
%ifnmacro __CDECL16_UNCLOB
|
||||||
|
%macro __CDECL16_UNCLOB 1-*
|
||||||
|
%assign %$i %0
|
||||||
|
%rep %0
|
||||||
|
pop %[%$i]
|
||||||
|
%assign %$i %$i-1
|
||||||
|
%endrep
|
||||||
%endmacro
|
%endmacro
|
||||||
%endif
|
%endif
|
||||||
|
|
||||||
|
|||||||
@@ -23,7 +23,7 @@
|
|||||||
; 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
|
mov ax, FAT32_State_t_size
|
||||||
push ax ; length of fat32_state structure
|
push ax ; length of fat32_state structure
|
||||||
@@ -32,7 +32,7 @@ InitFATDriver:
|
|||||||
mov ax, fat32_state
|
mov ax, fat32_state
|
||||||
push ax ; address of structure
|
push ax ; address of structure
|
||||||
call kmemset
|
call kmemset
|
||||||
sub sp, 0x6
|
add sp, 0x6
|
||||||
|
|
||||||
.calc_active_part:
|
.calc_active_part:
|
||||||
mov ax, word [partition_offset]
|
mov ax, word [partition_offset]
|
||||||
@@ -70,14 +70,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 +88,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,7 +104,7 @@ 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
|
print_string SearchFATDIR_info
|
||||||
mov bx, fat32_state
|
mov bx, fat32_state
|
||||||
@@ -146,7 +146,7 @@ SearchFATDIR:
|
|||||||
xor ax, ax
|
xor ax, ax
|
||||||
push ax ; segment
|
push ax ; segment
|
||||||
call ReadFATCluster ; uint8_t ReadFATCluster(uint16_t seg, uint16_t offset, uint32_t cluster)
|
call ReadFATCluster ; uint8_t ReadFATCluster(uint16_t seg, uint16_t offset, uint32_t cluster)
|
||||||
sub 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
|
||||||
@@ -201,7 +201,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,7 +210,7 @@ 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
|
print_string NextFATCluster_info
|
||||||
|
|
||||||
@@ -221,7 +221,7 @@ NextCluster:
|
|||||||
mov ax, fat32_nc_data
|
mov ax, fat32_nc_data
|
||||||
push ax ; address of structure
|
push ax ; address of structure
|
||||||
call kmemset
|
call kmemset
|
||||||
sub sp, 0x6
|
add sp, 0x6
|
||||||
|
|
||||||
mov edx, dword [bp + 4]
|
mov edx, dword [bp + 4]
|
||||||
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
|
||||||
@@ -275,7 +275,7 @@ NextCluster:
|
|||||||
mov si, fat_buffer
|
mov si, fat_buffer
|
||||||
mov eax, dword [bx+si+0]
|
mov eax, dword [bx+si+0]
|
||||||
.endp:
|
.endp:
|
||||||
__CDECL16_EXIT
|
__CDECL16_PROC_EXIT
|
||||||
ret
|
ret
|
||||||
.error_cfdivz:
|
.error_cfdivz:
|
||||||
ERROR STAGE2_FAT32_NCLUS_CFDIVZ
|
ERROR STAGE2_FAT32_NCLUS_CFDIVZ
|
||||||
@@ -283,7 +283,7 @@ 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
|
print_string ReadFATCluster_info
|
||||||
|
|
||||||
@@ -318,7 +318,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
|
||||||
|
|||||||
169
include/util/arena_alloc.nasm
Normal file
169
include/util/arena_alloc.nasm
Normal file
@@ -0,0 +1,169 @@
|
|||||||
|
%ifndef __INC_ARENA_ALLOC_FUNC
|
||||||
|
|
||||||
|
%define __ARENA_HEAP_START 0x8000
|
||||||
|
%define __ARENA_HEAP_SIZE 0x6000 ; 0x8000 -> 0xE000 = 24KiB of Heap
|
||||||
|
|
||||||
|
struc ArenaStateStruc_t
|
||||||
|
.start resw 1
|
||||||
|
.end resw 1
|
||||||
|
.mark resw 1
|
||||||
|
endstruc
|
||||||
|
|
||||||
|
; void arena_init(ArenaState *a)
|
||||||
|
;
|
||||||
|
arena_init:
|
||||||
|
__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_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_PROC_ENTRY
|
||||||
|
.func:
|
||||||
|
; 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_PROC_EXIT
|
||||||
|
ret
|
||||||
|
|
||||||
|
; 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_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_PROC_EXIT
|
||||||
|
ret
|
||||||
|
.error:
|
||||||
|
ERROR STEVIA_DEBUG_ERR
|
||||||
|
|
||||||
|
arena_mark:
|
||||||
|
__CDECL16_PROC_ENTRY
|
||||||
|
.func:
|
||||||
|
; return the current location of the 'cursor' in the allocator
|
||||||
|
ERROR STEVIA_DEBUG_UNIMPLEMENTED
|
||||||
|
.endp:
|
||||||
|
__CDECL16_PROC_EXIT
|
||||||
|
ret
|
||||||
|
|
||||||
|
arena_reset_to:
|
||||||
|
__CDECL16_PROC_ENTRY
|
||||||
|
.func:
|
||||||
|
; rewind the arena to a previously marked point
|
||||||
|
ERROR STEVIA_DEBUG_UNIMPLEMENTED
|
||||||
|
.endp:
|
||||||
|
__CDECL16_PROC_EXIT
|
||||||
|
ret
|
||||||
|
|
||||||
|
arena_reset:
|
||||||
|
__CDECL16_PROC_ENTRY
|
||||||
|
.func:
|
||||||
|
; reset the entire heap to a fresh state
|
||||||
|
ERROR STEVIA_DEBUG_UNIMPLEMENTED
|
||||||
|
.endp:
|
||||||
|
__CDECL16_PROC_EXIT
|
||||||
|
ret
|
||||||
|
|
||||||
|
%endif
|
||||||
|
%define __INC_ARENA_ALLOC_FUNC
|
||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
# Copyright (C) 2025 Elaina Claus
|
# Copyright (C) 2025 Elaina Claus
|
||||||
#
|
#
|
||||||
@@ -15,9 +16,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/>.
|
||||||
|
|
||||||
if ! [ $(id -u) = 0 ]; then
|
if [ $(id -u) = 0 ]; then
|
||||||
echo "Script must be run as root!" >&2
|
echo "Script should not be run as root, it could break something!" >&2
|
||||||
exit 1
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# paths to bootcode
|
# paths to bootcode
|
||||||
@@ -26,235 +26,143 @@ vbr_file=build/vbr.bin
|
|||||||
stage2_file=build/stage2.bin
|
stage2_file=build/stage2.bin
|
||||||
boottest_file=build/BOOTi686.bin
|
boottest_file=build/BOOTi686.bin
|
||||||
|
|
||||||
|
|
||||||
# Disk creation options
|
# Disk creation options
|
||||||
mount_point=/tmp/stevia_disk
|
disk_img=build/disk.img
|
||||||
disk_tmp_file=/tmp/disk.img
|
disk_img_final=build/output/disk.img.gz
|
||||||
disk_file_final=./disk.img.gz
|
|
||||||
|
part_img=build/part.img
|
||||||
|
part_img_final=build/output/part.img.gz
|
||||||
|
|
||||||
|
artifacts_archive=build/output/artifacts.tar.gz
|
||||||
|
|
||||||
# $disk_sector_size * $disk_size = total bytes, default is 256MiB
|
# $disk_sector_size * $disk_size = total bytes, default is 256MiB
|
||||||
disk_size=(524288 * 2)
|
disk_sectors=(524288 * 2)
|
||||||
disk_sector_size=512
|
disk_sector_size=512
|
||||||
|
part_start=2048
|
||||||
|
part_sectors=$((disk_sectors - part_start))
|
||||||
|
|
||||||
if ! [ -e $disk_tmp_file ]; then
|
#
|
||||||
|
# Build sanity section
|
||||||
|
#
|
||||||
|
|
||||||
|
echo "*** Performing pre-build sanity checks ***"
|
||||||
|
|
||||||
|
# Tools needed:
|
||||||
|
# sfdisk dosfstools (mkfs.fat), mtools (mcopy,mmd), gzip, dd, truncate, awk
|
||||||
|
for t in mcopy mmd gzip dd truncate awk; do
|
||||||
|
command -v "$t" >/dev/null || { echo "Missing tool: $t" >&2; exit 1; }
|
||||||
|
done
|
||||||
|
|
||||||
|
# these are normally in the sbin paths so I've had issues detecting them with command -v
|
||||||
|
SF=$(command -v sfdisk || echo /usr/sbin/sfdisk)
|
||||||
|
MKFS=$(command -v mkfs.fat || echo /usr/sbin/mkfs.fat)
|
||||||
|
|
||||||
|
[[ -x "$SF" ]] || { echo "sfdisk not found"; exit 1; }
|
||||||
|
[[ -x "$MKFS" ]] || { echo "mkfs.fat not found"; exit 1; }
|
||||||
|
|
||||||
|
# check that required build files exist
|
||||||
|
for f in "$mbr_file" "$vbr_file" "$stage2_file" "$boottest_file"; do
|
||||||
|
[[ -f "$f" ]] || { echo "missing $f" >&2; exit 1; }
|
||||||
|
done
|
||||||
|
|
||||||
|
cat > /tmp/pt.sfdisk <<EOF
|
||||||
|
label: dos
|
||||||
|
unit: sectors
|
||||||
|
sector-size: $disk_sector_size
|
||||||
|
label-id: 0xa0b0c0d0
|
||||||
|
|
||||||
|
start=$part_start, size=$((disk_sectors - part_start)), type=c, bootable
|
||||||
|
EOF
|
||||||
|
|
||||||
|
mtool_src=/tmp/mtools.conf
|
||||||
|
cat > $mtool_src <<EOF
|
||||||
|
drive c: file="$part_img"
|
||||||
|
EOF
|
||||||
|
|
||||||
|
#
|
||||||
|
# Create disk images
|
||||||
|
#
|
||||||
|
|
||||||
|
echo "[1/7] Create disk.img and part.img"
|
||||||
|
|
||||||
|
if ! [ -e "$disk_img" ]; then
|
||||||
# create raw disk image
|
# create raw disk image
|
||||||
if ! dd if=/dev/zero of=$disk_tmp_file bs=$disk_sector_size count=$disk_size; then
|
if ! truncate -s $((disk_sectors * disk_sector_size)) "$disk_img"; then
|
||||||
echo "Failed creating blank disk image." >&2
|
echo "Failed creating blank disk image." >&2
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
sync
|
sync
|
||||||
else
|
else
|
||||||
echo "Removing old disk image..."
|
echo "Removing old disk image..."
|
||||||
rm -rfv $disk_tmp_file
|
rm -rfv "$disk_img"
|
||||||
if ! dd if=/dev/zero of=$disk_tmp_file bs=$disk_sector_size count=$disk_size; then
|
if ! truncate -s $((disk_sectors * disk_sector_size)) "$disk_img"; then
|
||||||
echo "Failed creating blank disk image." >&2
|
echo "Failed creating blank disk image." >&2
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
sync
|
sync
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ "$OSTYPE" == "linux-gnu"* ]]; then
|
if ! [ -e "$part_img" ]; then
|
||||||
if [ -e $mbr_file ] && [ -e $vbr_file ]; then
|
# create raw partition disk image
|
||||||
# get next loop device and mount it
|
if ! truncate -s $((part_sectors * disk_sector_size)) "$part_img"; then
|
||||||
ld=$(losetup -f)
|
echo "Failed creating blank partition image." >&2
|
||||||
losetup -P -b 512 $ld $disk_tmp_file
|
|
||||||
|
|
||||||
# create a DOS disk, with 1 FAT32 partition that is bootable, part1 starts at sector 2048
|
|
||||||
sfdisk $ld < scripts/loop_setup.sfdisk
|
|
||||||
|
|
||||||
# get first partition, this is sloppy might need to review this...
|
|
||||||
firstpart=$(lsblk -ilp -o NAME $ld | tr '\n' ' ' | awk '{print $3}')
|
|
||||||
mkfs.fat -v -F32 -s 1 -n 'STEVIAFS' $firstpart
|
|
||||||
|
|
||||||
#
|
|
||||||
# MBR setup
|
|
||||||
#
|
|
||||||
|
|
||||||
# copy MBR while preserving partition table
|
|
||||||
if ! dd if=$mbr_file of=$ld bs=1 count=440; then
|
|
||||||
echo "Failed to write MBR to disk. (part 1)" >&2
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# copy MBR 0xAA55
|
|
||||||
if ! dd if=$mbr_file of=$ld bs=1 seek=510 skip=510 count=2; then
|
|
||||||
echo "Failed to write MBR to disk. (part 2)" >&2
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
#
|
|
||||||
# VBR Setup & backup VBR
|
|
||||||
#
|
|
||||||
|
|
||||||
# copy VBR to partition 1 while preserving partition information
|
|
||||||
# copy jmp short entry; nop
|
|
||||||
if ! dd if=$vbr_file of=$firstpart bs=1 count=3; then
|
|
||||||
echo "Failed to write VBR to disk. (part 1)" >&2
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
# copy bootcode
|
|
||||||
if ! dd if=$vbr_file of=$firstpart bs=1 seek=90 skip=90 count=420; then
|
|
||||||
echo "Failed to write VBR to disk. (part 2)" >&2
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
# copy 0xAA55
|
|
||||||
if ! dd if=$vbr_file of=$firstpart bs=1 seek=510 skip=510 count=2; then
|
|
||||||
echo "Failed to write VBR to disk. (part 3)" >&2
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# write backup VBR
|
|
||||||
if ! dd if=$firstpart of=$firstpart bs=$disk_sector_size count=1 seek=6; then
|
|
||||||
echo "Failed to copy VBR (sector 1) to backup VBR." >&2
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
|
|
||||||
#
|
|
||||||
# Stage2 Setup
|
|
||||||
#
|
|
||||||
|
|
||||||
#stage2 to sectors 1-64
|
|
||||||
if ! dd if=$stage2_file of=$ld bs=$disk_sector_size seek=1; then
|
|
||||||
echo "Failed to write Stage2 to disk." >&2
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# copy boot32 boot test file to disk image
|
|
||||||
if ! [ -e $mount_point ]; then
|
|
||||||
mkdir $mount_point
|
|
||||||
fi
|
|
||||||
mount $firstpart $mount_point
|
|
||||||
|
|
||||||
# ensure mountpoint is actually a mountpoint
|
|
||||||
if ! mountpoint -q $mount_point; then
|
|
||||||
echo "Failed to mount partition at $mount_point." >&2
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# copy kernel to filesystem
|
|
||||||
if [ -e $boottest_file ]; then
|
|
||||||
cp -v $boottest_file $mount_point/BOOT.BIN
|
|
||||||
else
|
|
||||||
echo "Failed to write $boottest_file to disk image" >&2
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
#
|
|
||||||
# Final Cleanup
|
|
||||||
#
|
|
||||||
|
|
||||||
# detach loop device
|
|
||||||
umount $mount_point
|
|
||||||
sync
|
|
||||||
sleep 1
|
|
||||||
losetup -d $ld
|
|
||||||
|
|
||||||
# chown to the real user to prevent issues with reading/writing the file later
|
|
||||||
# BUG: ${logname}:$(id $(logname -g)) doesn't work right on WSL because of runlevel hacks in WSL
|
|
||||||
# BUG: https://github.com/microsoft/WSL/issues/1761
|
|
||||||
# as a work around I'll just reference LICENSE.md...WHICH SHOULD ALWAYS BE THERE 👀
|
|
||||||
chown --from=root:root --reference=LICENSE.md $disk_tmp_file
|
|
||||||
|
|
||||||
else
|
|
||||||
echo "unable to find MBR/VBR binaries!" >&2
|
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
# requires util-linux from homebrew
|
sync
|
||||||
elif [[ "$OSTYPE" == "darwin"* ]]; then
|
else
|
||||||
sfdisk_path="/usr/local/opt/util-linux/sbin/sfdisk"
|
echo "Removing old (partition) disk image..."
|
||||||
if [ -e $mbr_file ] && [ -e $vbr_file ]; then
|
rm -rfv "$part_img"
|
||||||
# use hdiutil to attach our empty disk image
|
if ! truncate -s $((part_sectors * disk_sector_size)) "$part_img"; then
|
||||||
ld_path_raw=$(hdiutil attach -readwrite -imagekey diskimage-class=CRawDiskImage -nomount -blocksize 512 -noverify /tmp/disk.img)
|
echo "Failed creating blank partition image." >&2
|
||||||
ld=$(echo $ld_path_raw | sed s:/dev/::)
|
exit 1
|
||||||
ld_path="/dev/$ld"
|
|
||||||
|
|
||||||
# create a DOS disk, with 1 FAT32 partition
|
|
||||||
if ! [ -e $sfdisk_path ]; then
|
|
||||||
echo "sfdisk utility was not found...We cannot use diskutil to make disks due to the fact that it only makes Hybrid MBR's & GPT disks...blame Apple"
|
|
||||||
exit 4
|
|
||||||
else
|
|
||||||
$sfdisk_path $ld_path < scripts/loop_setup.sfdisk
|
|
||||||
fi
|
|
||||||
|
|
||||||
# give stuff a chance to settle, macOS has problems here
|
|
||||||
sync
|
|
||||||
sleep .5
|
|
||||||
|
|
||||||
# reattch the raw image file since macOS doesn't have a partprobe...
|
|
||||||
# this is the only way I know to get macOS to reprobe the disk
|
|
||||||
hdiutil eject $ld
|
|
||||||
unset ld_path
|
|
||||||
unset ld
|
|
||||||
unset ld_path_raw
|
|
||||||
|
|
||||||
ld_path_raw=$(hdiutil attach -readwrite -imagekey diskimage-class=CRawDiskImage -nomount -blocksize 512 -noverify /tmp/disk.img)
|
|
||||||
ld=$(echo $ld_path_raw | grep "FDisk_partition_scheme" | awk '{print $1}' | sed s:/dev/::)
|
|
||||||
ld_path="/dev/$ld"
|
|
||||||
|
|
||||||
if ! [ -b /dev/$ld ]; then
|
|
||||||
echo "Unable to remount disk! exitting before I do some damage!"
|
|
||||||
exit 5
|
|
||||||
fi
|
|
||||||
|
|
||||||
# get first partition and format as FAT32
|
|
||||||
firstpart=$(diskutil list $ld | grep 1: | awk '{print $6}')
|
|
||||||
firstpart_direct="r$firstpart"
|
|
||||||
|
|
||||||
newfs_msdos -F 32 /dev/$firstpart_direct
|
|
||||||
sync
|
|
||||||
|
|
||||||
# copy MBR while preserving partition table
|
|
||||||
dd if=$mbr_file of=$ld_path bs=1 count=440 conv=sync
|
|
||||||
# copy MBR 0xAA55
|
|
||||||
dd if=$mbr_file of=$ld_path bs=1 seek=510 skip=510 count=2 conv=sync
|
|
||||||
|
|
||||||
# copy VBR to partition 1 while preserving partition information
|
|
||||||
# copy jmp short entry; nop
|
|
||||||
dd if=$vbr_file of=/dev/$firstpart bs=1 count=3 conv=sync
|
|
||||||
# copy bootcode
|
|
||||||
dd if=$vbr_file of=/dev/$firstpart bs=1 seek=90 skip=90 count=420 conv=sync
|
|
||||||
# copy 0xAA55
|
|
||||||
dd if=$vbr_file of=/dev/$firstpart bs=1 seek=510 skip=510 count=2 conv=sync
|
|
||||||
|
|
||||||
#stage2 to sectors 1-64
|
|
||||||
dd if=$stage2_file of=$ld_path bs=$disk_sector_size seek=1 conv=sync
|
|
||||||
|
|
||||||
#sync pending dd stuff
|
|
||||||
sync
|
|
||||||
|
|
||||||
# copy boot32 boot test file to disk image
|
|
||||||
if ! [ -e $mount_point ]; then
|
|
||||||
mkdir $mount_point
|
|
||||||
else
|
|
||||||
echo "$mount_point exists! clearing contents..."
|
|
||||||
rm -rfv $mount_point
|
|
||||||
mkdir $mount_point
|
|
||||||
fi
|
|
||||||
mount -t msdos /dev/$firstpart $mount_point
|
|
||||||
|
|
||||||
if [ -e $boottest_file ]; then
|
|
||||||
cp -v $boottest_file $mount_point
|
|
||||||
else
|
|
||||||
echo "unable to find boot32.bin!"
|
|
||||||
exit 3
|
|
||||||
fi
|
|
||||||
|
|
||||||
# detach loop device
|
|
||||||
sync
|
|
||||||
umount /dev/$firstpart
|
|
||||||
hdiutil eject $ld
|
|
||||||
|
|
||||||
# chown to the real user to prevent issues with reading/writing the file later
|
|
||||||
SUDOUSER=$(logname)
|
|
||||||
chown ${SUDOUSER}:staff disk.img
|
|
||||||
gzip -9kc $disk_tmp_file > $disk_file_final
|
|
||||||
else
|
|
||||||
echo "unable to find MBR/VBR binaries!"
|
|
||||||
exit 2
|
|
||||||
fi
|
fi
|
||||||
|
sync
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
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"
|
||||||
|
|
||||||
|
echo "[4/7] Patch VBR inside partition image (preserve BPB)"
|
||||||
|
|
||||||
|
# copy jmp short entry; nop
|
||||||
|
dd if=$vbr_file of="$part_img" bs=1 count=3 conv=notrunc
|
||||||
|
# copy bootcode
|
||||||
|
dd if=$vbr_file of="$part_img" bs=1 seek=90 skip=90 count=420 conv=notrunc
|
||||||
|
# copy signature (should be 0xAA55)
|
||||||
|
dd if=$vbr_file of="$part_img" bs=1 seek=510 skip=510 count=2 conv=notrunc
|
||||||
|
|
||||||
|
# copy backup VBR within the created partition image
|
||||||
|
# Linux dosfstools will complain (read: not work) unless this is done it seems
|
||||||
|
# HACK: sector 6 is the **default** location of the BPB_BkBootSec, it **can** be different.
|
||||||
|
dd if="$part_img" of="$part_img" bs=$disk_sector_size count=1 seek=6 conv=notrunc
|
||||||
|
|
||||||
|
echo "[5/7] Copy boot payload to FAT32 filesystem using mtools as BOOT.BIN"
|
||||||
|
MTOOLSRC="$mtool_src" mcopy "$boottest_file" C:BOOT.BIN
|
||||||
|
MTOOLSRC="$mtool_src" mdir C:
|
||||||
|
|
||||||
|
echo "[6/7] Patch MBR and install stage2 loader to disk image"
|
||||||
|
# patch MBR+signature while preserving partition table
|
||||||
|
dd if="$mbr_file" of="$disk_img" bs=1 count=440 conv=notrunc
|
||||||
|
dd if="$mbr_file" of="$disk_img" bs=1 seek=510 skip=510 count=2 conv=notrunc
|
||||||
|
|
||||||
|
# copy stage2 to absolute LBA 1
|
||||||
|
dd if="$stage2_file" of="$disk_img" bs=$disk_sector_size seek=1 conv=notrunc
|
||||||
|
|
||||||
|
echo "[7/7] Assembling final disk image"
|
||||||
|
# place partition at it's place in the disk image
|
||||||
|
dd if="$part_img" of="$disk_img" bs=$disk_sector_size seek=$part_start conv=notrunc
|
||||||
|
|
||||||
|
echo " *** Outputing disk images will be in ./build/output/* *** "
|
||||||
|
gzip -9c "$disk_img" > "$disk_img_final"
|
||||||
|
gzip -9c "$part_img" > "$part_img_final"
|
||||||
|
tar caf "$artifacts_archive" build/*.bin build/*.map
|
||||||
else
|
else
|
||||||
# Unknown.
|
# Unknown.
|
||||||
echo "Unknown OS type! Supported build hosts systems are GNU/Linux (WSL) and macOS."
|
echo "Unknown OS type! Supported build hosts systems are GNU/Linux (& WSL)"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
label: dos
|
|
||||||
unit: sectors
|
|
||||||
sector-size: 512
|
|
||||||
|
|
||||||
start= 2048, type=c, bootable
|
|
||||||
@@ -18,7 +18,7 @@
|
|||||||
[CPU KATMAI]
|
[CPU KATMAI]
|
||||||
[WARNING -reloc-abs-byte]
|
[WARNING -reloc-abs-byte]
|
||||||
[WARNING -reloc-abs-word] ; Yes, we use absolute addresses. surpress these warnings.
|
[WARNING -reloc-abs-word] ; Yes, we use absolute addresses. surpress these warnings.
|
||||||
[map all mbr.map]
|
[map all build/mbr.map]
|
||||||
%define __STEVIA_MBR
|
%define __STEVIA_MBR
|
||||||
jmp short (init - $$)
|
jmp short (init - $$)
|
||||||
nop
|
nop
|
||||||
@@ -58,7 +58,7 @@ init:
|
|||||||
cld
|
cld
|
||||||
rep stosb ; zero bss section
|
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
|
push bp ; setup top of stack frame
|
||||||
|
|
||||||
xor cx, cx
|
xor cx, cx
|
||||||
@@ -96,6 +96,8 @@ main:
|
|||||||
mov ah, 0x41
|
mov ah, 0x41
|
||||||
mov bx, 0x55AA
|
mov bx, 0x55AA
|
||||||
mov dl, 0x80
|
mov dl, 0x80
|
||||||
|
|
||||||
|
clc
|
||||||
int 0x13
|
int 0x13
|
||||||
jnc main.find_active
|
jnc main.find_active
|
||||||
ERROR MBR_ERROR_NO_INT32E ; no extended function support
|
ERROR MBR_ERROR_NO_INT32E ; no extended function support
|
||||||
|
|||||||
@@ -15,8 +15,8 @@
|
|||||||
|
|
||||||
[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 stage2.map]
|
[map all build/stage2.map]
|
||||||
[WARNING -reloc-abs-byte]
|
[WARNING -reloc-abs-byte]
|
||||||
[WARNING -reloc-abs-word]
|
[WARNING -reloc-abs-word]
|
||||||
[WARNING -reloc-abs-dword] ; Yes, we use absolute addresses. surpress these warnings.
|
[WARNING -reloc-abs-dword] ; Yes, we use absolute addresses. surpress these warnings.
|
||||||
@@ -88,7 +88,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 +96,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
|
||||||
; ###############
|
; ###############
|
||||||
@@ -149,9 +154,15 @@ main:
|
|||||||
add sp, 0x6
|
add sp, 0x6
|
||||||
|
|
||||||
call SetTextMode
|
call SetTextMode
|
||||||
call disable_cursor
|
call disable_cursor_bios
|
||||||
print_string HelloPrompt_info
|
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
|
||||||
|
|
||||||
; enable A20 gate
|
; enable A20 gate
|
||||||
call EnableA20
|
call EnableA20
|
||||||
print_string A20_Enabled_OK_info
|
print_string A20_Enabled_OK_info
|
||||||
@@ -160,7 +171,10 @@ main:
|
|||||||
call GetMemoryMap
|
call GetMemoryMap
|
||||||
print_string MemoryMap_OK_info
|
print_string MemoryMap_OK_info
|
||||||
|
|
||||||
; 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
|
call EnterUnrealMode
|
||||||
print_string UnrealMode_OK_info
|
print_string UnrealMode_OK_info
|
||||||
|
|
||||||
@@ -187,166 +201,106 @@ hcf:
|
|||||||
|
|
||||||
; ##############################
|
; ##############################
|
||||||
;
|
;
|
||||||
; SYSTEM CONFIGURATION FUNCTIONS
|
; SYSTEM CONFIGURATION FUNCTIONS & MACROS
|
||||||
;
|
;
|
||||||
; ##############################
|
; ##############################
|
||||||
|
|
||||||
; Prints a C-Style string (null terminated) using BIOS vga teletype call
|
; set ds and es segments back to the base of the loader
|
||||||
; void PrintString(char* buf)
|
%ifnmacro __TINY_DS_ES
|
||||||
ALIGN 4, db 0x90
|
%macro __TINY_DS_ES 0
|
||||||
PrintString:
|
mov ax, __STAGE2_SEGMENT
|
||||||
__CDECL16_ENTRY
|
mov ds, ax
|
||||||
mov di, [bp + 4] ; first arg is char[]
|
mov es, ax
|
||||||
.str_len:
|
%endmacro
|
||||||
xor cx, cx ; ECX = 0
|
%endif
|
||||||
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
|
|
||||||
|
|
||||||
|
; 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
|
lgdt [((__STAGE2_SEGMENT << 4) + unreal_gdt_info)] ; load unreal gdt
|
||||||
|
|
||||||
mov eax, cr0
|
mov eax, cr0
|
||||||
or al,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
|
jmp short $+2 ; i-cache flush
|
||||||
|
|
||||||
;jmp far 0x0008:EnterUnrealMode.load_cs
|
mov ax, 0x10 ; select descriptor 2
|
||||||
db 0xEA ; jmp far imm16:imm16
|
mov ds, ax
|
||||||
dw EnterUnrealMode.load_cs ; error_far_ptr
|
mov es, ax
|
||||||
dw 0x0008 ; error_far_seg
|
|
||||||
.load_cs:
|
|
||||||
mov bx, 0x10 ; select descriptor 2
|
|
||||||
mov ds, bx ; 10h = 0001_0000b
|
|
||||||
|
|
||||||
mov ss, bx
|
mov eax, cr0
|
||||||
mov es, bx
|
and eax, ~1 ; toggle bit 1 of cr0
|
||||||
mov fs, bx
|
|
||||||
mov gs, bx ; other data/stack to index 2 (off 0x10)
|
|
||||||
|
|
||||||
and al,0xFE ; toggle bit 1 of cr0
|
|
||||||
mov cr0, eax ; back to realmode
|
mov cr0, eax ; back to realmode
|
||||||
jmp short $+2
|
jmp short $+2 ; i-cache flush
|
||||||
|
|
||||||
;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
|
|
||||||
sti
|
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
|
||||||
|
;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
|
||||||
|
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 0x0000:EnterUnrealMode.endp
|
||||||
.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
|
ret
|
||||||
end_text:
|
end_text:
|
||||||
|
|
||||||
@@ -361,13 +315,13 @@ begin_data:
|
|||||||
%define CRLF 0Dh, 0Ah
|
%define CRLF 0Dh, 0Ah
|
||||||
|
|
||||||
%macro define_cstr 2
|
%macro define_cstr 2
|
||||||
ALIGN 16
|
align 16
|
||||||
%1_cstr:
|
%1_cstr:
|
||||||
db %2, 00h
|
db %2, 00h
|
||||||
%endmacro
|
%endmacro
|
||||||
|
|
||||||
%macro define_info 2
|
%macro define_info 2
|
||||||
ALIGN 16
|
align 16
|
||||||
%1_info:
|
%1_info:
|
||||||
db %2, CRLF, 00h
|
db %2, CRLF, 00h
|
||||||
%endmacro
|
%endmacro
|
||||||
@@ -386,7 +340,7 @@ define_info MaybeFound_Boot, "Maybe found a file...checking..."
|
|||||||
|
|
||||||
define_cstr BootTarget, "BOOT BIN"
|
define_cstr BootTarget, "BOOT BIN"
|
||||||
|
|
||||||
ALIGN 16, db 0
|
align 16, db 0
|
||||||
BootTarget:
|
BootTarget:
|
||||||
db 'BOOT BIN'
|
db 'BOOT BIN'
|
||||||
|
|
||||||
@@ -394,28 +348,28 @@ BootTarget:
|
|||||||
; pre-bss init globals (generally const...but there are exceptions)
|
; pre-bss init globals (generally const...but there are exceptions)
|
||||||
;
|
;
|
||||||
|
|
||||||
align 8, db 0x00
|
align 8, db 0
|
||||||
boot_drive:
|
boot_drive:
|
||||||
db 0x00
|
db 0x00
|
||||||
|
|
||||||
align 8, db 0x00
|
align 8, db 0
|
||||||
partition_offset:
|
partition_offset:
|
||||||
dw 0x0000
|
dw 0x0000
|
||||||
|
|
||||||
align 8, db 0x00
|
align 8, db 0
|
||||||
vbr_fat32_bpb_ptr:
|
vbr_fat32_bpb_ptr:
|
||||||
dw 0x0000
|
dw 0x0000
|
||||||
|
|
||||||
align 8, db 0x00
|
align 8, db 0
|
||||||
vbr_part_table_ptr:
|
vbr_part_table_ptr:
|
||||||
dw 0x0000
|
dw 0x0000
|
||||||
|
|
||||||
ALIGN 16
|
align 16, db 0
|
||||||
IntToHex_table:
|
IntToHex_table:
|
||||||
db '0123456789ABCDEF'
|
db '0123456789ABCDEF'
|
||||||
|
|
||||||
; see docs/gdt.txt for a quick refresher on GDT
|
; see docs/gdt.txt for a quick refresher on GDT
|
||||||
ALIGN 16, db 0
|
align 16, db 0
|
||||||
unreal_gdt_info:
|
unreal_gdt_info:
|
||||||
unreal_gdt_size: dw (unreal_gdt_end - unreal_gdt_start) - 1
|
unreal_gdt_size: dw (unreal_gdt_end - unreal_gdt_start) - 1
|
||||||
unreal_gdt_ptr: dd ((__STAGE2_SEGMENT << 4) + unreal_gdt_start)
|
unreal_gdt_ptr: dd ((__STAGE2_SEGMENT << 4) + unreal_gdt_start)
|
||||||
@@ -423,14 +377,14 @@ unreal_gdt_start:
|
|||||||
; entry 0 (null descriptor)
|
; entry 0 (null descriptor)
|
||||||
dq 0 ; first entry is null
|
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
|
dd 0x0000FFFF ; Base Address(15:0) 31:16, Segment Limit(15:0) 15:0
|
||||||
db 0x00 ; Base Address 23:16
|
db 0x00 ; Base Address 23:16
|
||||||
db 1001_1010b ; Access Byte: Present, ring0, S = 1, executable (1), non-conforming, readable, Accessed
|
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 0000_0000b ; Flags: GR = 4KiB, attr = <DB/L/Avl>, Granularity = 4KiB & 16:19 of limit
|
||||||
db 0x00 ; Base Address 31:24
|
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
|
dd 0x0000FFFF ; Base Address(15:0) 31:16, Segment Limit(15:0) 15:0
|
||||||
db 0x00 ; Base Address(23:16)
|
db 0x00 ; Base Address(23:16)
|
||||||
db 1001_0010b ; Access Byte: Present, ring0, S = 1, data (0), non-confirming, writable, present
|
db 1001_0010b ; Access Byte: Present, ring0, S = 1, data (0), non-confirming, writable, present
|
||||||
@@ -438,7 +392,7 @@ unreal_gdt_start:
|
|||||||
db 0x00 ; Base Address(31:24)
|
db 0x00 ; Base Address(31:24)
|
||||||
unreal_gdt_end:
|
unreal_gdt_end:
|
||||||
|
|
||||||
ALIGN 16, db 0
|
align 16, db 0
|
||||||
gdt32_info:
|
gdt32_info:
|
||||||
gdt32_size: dw (gdt32_end - gdt32_start) - 1
|
gdt32_size: dw (gdt32_end - gdt32_start) - 1
|
||||||
gdt32_ptr: dd ((__STAGE2_SEGMENT << 4) + gdt32_start)
|
gdt32_ptr: dd ((__STAGE2_SEGMENT << 4) + gdt32_start)
|
||||||
@@ -474,19 +428,19 @@ gdt32_start:
|
|||||||
db 0x00
|
db 0x00
|
||||||
gdt32_end:
|
gdt32_end:
|
||||||
|
|
||||||
ALIGN 8,db 0x00
|
align 16,db 0
|
||||||
BUILD_NASM_VER:
|
BUILD_NASM_VER:
|
||||||
db "Stevia Stage2 built with NASM - ", __NASM_VER__, 00h
|
db "Stevia Stage2 built with NASM - ", __NASM_VER__, 00h
|
||||||
|
|
||||||
ALIGN 8,db 0x00
|
align 16,db 0
|
||||||
BUILD_DATETIME:
|
BUILD_DATETIME:
|
||||||
db 'Assembled - ', __DATE__, ' ', __TIME__, 00h
|
db 'Assembled - ', __DATE__, ' ', __TIME__, 00h
|
||||||
|
|
||||||
ALIGN 8,db 0x00
|
align 16,db 0
|
||||||
BUILD_GIT_VER:
|
BUILD_GIT_VER:
|
||||||
db __GIT_VER__, 00h
|
db __GIT_VER__, 00h
|
||||||
|
|
||||||
ALIGN 8,db 0x00
|
align 16,db 0
|
||||||
BUILD_GIT_HASH:
|
BUILD_GIT_HASH:
|
||||||
db __GIT_HASH__, 00h
|
db __GIT_HASH__, 00h
|
||||||
end_data:
|
end_data:
|
||||||
@@ -504,26 +458,35 @@ section .bss follows=.sign
|
|||||||
begin_bss:
|
begin_bss:
|
||||||
; structures
|
; structures
|
||||||
|
|
||||||
align 8, resb 1
|
align 16, resb 1
|
||||||
partition_table resb PartTable_t_size
|
partition_table:
|
||||||
|
resb PartTable_t_size
|
||||||
|
|
||||||
align 8, resb 1
|
align 16, resb 1
|
||||||
fat32_bpb resb FAT32_bpb_t_size
|
fat32_bpb:
|
||||||
fat32_ebpb resb FAT32_ebpb_t_size
|
resb FAT32_bpb_t_size
|
||||||
|
fat32_ebpb:
|
||||||
|
resb FAT32_ebpb_t_size
|
||||||
|
|
||||||
align 8, resb 1
|
align 16, resb 1
|
||||||
fat32_nc_data resb 16
|
fat32_nc_data:
|
||||||
|
resb 16
|
||||||
|
|
||||||
align 8, resb 1
|
align 16, resb 1
|
||||||
lba_packet resb LBAPkt_t_size
|
lba_packet:
|
||||||
|
resb LBAPkt_t_size
|
||||||
|
|
||||||
align 8, resb 1
|
align 16, resb 1
|
||||||
fat32_state:
|
fat32_state:
|
||||||
resb FAT32_State_t_size
|
resb FAT32_State_t_size
|
||||||
|
|
||||||
align 8, 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
|
||||||
;
|
;
|
||||||
@@ -541,12 +504,15 @@ dir_buffer:
|
|||||||
fat_fsinfo:
|
fat_fsinfo:
|
||||||
resb 512
|
resb 512
|
||||||
|
|
||||||
|
; 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
|
align 16, resb 1
|
||||||
%define BIOSMemoryMap_SIZE 2048
|
%define BIOSMemoryMap_SIZE 1024
|
||||||
BIOSMemoryMap:
|
BIOSMemoryMap:
|
||||||
resb 2048
|
resb BIOSMemoryMap_SIZE
|
||||||
|
|
||||||
align 512, resb 1
|
align 16, resb 1
|
||||||
stack_bottom:
|
stack_bottom:
|
||||||
resb 1024
|
resb 1024
|
||||||
stack_top:
|
stack_top:
|
||||||
|
|||||||
@@ -17,7 +17,7 @@
|
|||||||
[CPU KATMAI]
|
[CPU KATMAI]
|
||||||
[WARNING -reloc-abs-byte]
|
[WARNING -reloc-abs-byte]
|
||||||
[WARNING -reloc-abs-word]
|
[WARNING -reloc-abs-word]
|
||||||
[map all vbr.map] ; Yes, we use absolute addresses. surpress these warnings.
|
[map all build/vbr.map] ; Yes, we use absolute addresses. surpress these warnings.
|
||||||
%define __STEVIA_VBR
|
%define __STEVIA_VBR
|
||||||
section .text
|
section .text
|
||||||
__ENTRY:
|
__ENTRY:
|
||||||
@@ -72,7 +72,7 @@ init:
|
|||||||
cld
|
cld
|
||||||
rep stosb
|
rep stosb
|
||||||
|
|
||||||
sub sp, 0x20 ; local varible space
|
sub sp, 0x20 ; local varible space (32 bytes)
|
||||||
push bp
|
push bp
|
||||||
|
|
||||||
sti ; all done with inital setup and relocation, reenable interupts
|
sti ; all done with inital setup and relocation, reenable interupts
|
||||||
|
|||||||
Reference in New Issue
Block a user