Compare commits
150 Commits
v0.0.1
...
578e9934d8
| Author | SHA1 | Date | |
|---|---|---|---|
| 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 |
6
.gitignore
vendored
6
.gitignore
vendored
@@ -1,5 +1,9 @@
|
|||||||
out/*
|
out/*
|
||||||
build/*
|
build/*
|
||||||
*.img
|
*.img
|
||||||
|
*.img.gz
|
||||||
*.elf
|
*.elf
|
||||||
bx_enh_dbg.ini
|
bx_enh_dbg.ini
|
||||||
|
stevia-log
|
||||||
|
.vscode/
|
||||||
|
*.map
|
||||||
59
Makefile
59
Makefile
@@ -1,31 +1,39 @@
|
|||||||
iso := 'disk.img'
|
|
||||||
|
|
||||||
include := './include'
|
include := './include'
|
||||||
|
|
||||||
mbr_source_files := $(wildcard src/mbr/*.s)
|
mbr_source_files := $(wildcard src/mbr/*.nasm)
|
||||||
vbr_source_files := $(wildcard src/vbr/*.s)
|
vbr_source_files := $(wildcard src/vbr/*.nasm)
|
||||||
stage2_source_files := $(wildcard src/stage2/*.s)
|
stage2_source_files := $(wildcard src/stage2/*.nasm)
|
||||||
boottest_source_files := $(wildcard src/miniboot32/*.s)
|
boottest_source_files := $(wildcard src/miniboot32/*.nasm)
|
||||||
|
|
||||||
mbr_binary_files := $(patsubst src/mbr/%.s, build/%.bin, $(mbr_source_files))
|
mbr_binary_files := $(patsubst src/mbr/%.nasm, build/%.bin, $(mbr_source_files))
|
||||||
vbr_binary_files := $(patsubst src/vbr/%.s, build/%.bin, $(vbr_source_files))
|
vbr_binary_files := $(patsubst src/vbr/%.nasm, build/%.bin, $(vbr_source_files))
|
||||||
stage2_binary_files := $(patsubst src/stage2/%.s, build/%.bin, $(stage2_source_files))
|
stage2_binary_files := $(patsubst src/stage2/%.nasm, build/%.bin, $(stage2_source_files))
|
||||||
boottest_binary_files := $(patsubst src/miniboot32/%.s, build/%.bin, $(boottest_source_files))
|
boottest_binary_files := $(patsubst src/miniboot32/%.nasm, build/%.bin, $(boottest_source_files))
|
||||||
|
|
||||||
build_dir := 'build'
|
build_dir := 'build'
|
||||||
|
|
||||||
qemu_args := -L ./bin/ -bios bios.bin -cpu pentium3 -m 64 -S -s -monitor stdio -nic none
|
# Get current Git version (tag) and hash
|
||||||
.PHONY: all mbr vbr stage2 boottest clean run run_bochs iso
|
GIT_VERSION := $(shell git describe --tags)
|
||||||
|
GIT_HASH := $(shell git rev-parse HEAD)
|
||||||
|
GIT_NASM_DEFINES := -D __GIT_VER__='"$(GIT_VERSION)"' -D __GIT_HASH__='"$(GIT_HASH)"'
|
||||||
|
|
||||||
all: $(iso) $(mbr_binary_files) $(vbr_binary_files) $(stage2_binary_files)
|
iso := '/tmp/disk.img'
|
||||||
|
isoz := 'disk.img.gz'
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
all: $(iso) $(isoz) $(mbr_binary_files) $(vbr_binary_files) $(stage2_binary_files)
|
||||||
mbr: $(mbr_binary_files)
|
mbr: $(mbr_binary_files)
|
||||||
vbr: $(vbr_binary_files)
|
vbr: $(vbr_binary_files)
|
||||||
stage2: $(stage2_binary_files)
|
stage2: $(stage2_binary_files)
|
||||||
boottest: $(boottest_binary_files)
|
boottest: $(boottest_binary_files)
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
|
@rm -rvf *.map
|
||||||
@rm -rvf $(build_dir)/*
|
@rm -rvf $(build_dir)/*
|
||||||
@rm -rvf $(iso)
|
@rm -rvf $(iso)
|
||||||
|
@rm -rvf $(isoz)
|
||||||
|
|
||||||
run: $(iso)
|
run: $(iso)
|
||||||
@sudo qemu-system-i386 $(qemu_args) -hda $(iso)
|
@sudo qemu-system-i386 $(qemu_args) -hda $(iso)
|
||||||
@@ -34,25 +42,30 @@ run_bochs: $(iso)
|
|||||||
@bochs -q
|
@bochs -q
|
||||||
|
|
||||||
iso: $(iso)
|
iso: $(iso)
|
||||||
@file disk.img
|
@file $(iso)
|
||||||
|
|
||||||
build/%.bin: src/mbr/%.s
|
isoz: $(isoz)
|
||||||
@mkdir -p $(shell dirname $@)
|
@file $(isoz)
|
||||||
@nasm -i$(include) -Wall -f bin $< -o $@
|
|
||||||
|
|
||||||
build/%.bin: src/vbr/%.s
|
build/%.bin: src/mbr/%.nasm
|
||||||
@mkdir -p $(shell dirname $@)
|
@mkdir -p $(shell dirname $@)
|
||||||
@nasm -i$(include) -Wall -f bin $< -o $@
|
@nasm -i$(include) -Wall -f bin $(GIT_NASM_DEFINES) $< -o $@
|
||||||
|
|
||||||
build/%.bin: src/stage2/%.s
|
build/%.bin: src/vbr/%.nasm
|
||||||
@mkdir -p $(shell dirname $@)
|
@mkdir -p $(shell dirname $@)
|
||||||
@nasm -i$(include) -Wall -f bin $< -o $@
|
@nasm -i$(include) -Wall -f bin $(GIT_NASM_DEFINES) $< -o $@
|
||||||
|
|
||||||
build/%.bin: src/miniboot32/%.s
|
build/%.bin: src/stage2/%.nasm
|
||||||
@mkdir -p $(shell dirname $@)
|
@mkdir -p $(shell dirname $@)
|
||||||
@nasm -i$(include) -Wall -f bin $< -o $@
|
@nasm -i$(include) -Wall -f bin $(GIT_NASM_DEFINES) $< -o $@
|
||||||
|
|
||||||
|
build/%.bin: src/miniboot32/%.nasm
|
||||||
|
@mkdir -p $(shell dirname $@)
|
||||||
|
@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...
|
@echo root access needed to create disk image...
|
||||||
@sudo scripts/create-disk.sh
|
@sudo scripts/create-disk.sh
|
||||||
|
|
||||||
|
$(isoz): $(iso)
|
||||||
|
@gzip -9kc $(iso) > $(isoz)
|
||||||
|
|||||||
125
README.md
125
README.md
@@ -1,85 +1,70 @@
|
|||||||
# stevia
|
# Stevia Bootloader
|
||||||
|
|
||||||
This is a hobby project that aims to create a simple and lightweight operating system kernel. It is written in Assembly and C, and uses the GNU toolchain and Bochs emulator. The project features (or is hoping to feature):
|
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.
|
||||||
|
|
||||||
- A boot loader that loads the kernel from a floppy disk image
|
## Features
|
||||||
- A kernel that implements basic functions, such as printing messages, handling interrupts, and managing memory
|
|
||||||
- A shell that allows user input and execution of commands
|
|
||||||
- A simple text editor that can create and edit files
|
|
||||||
- A calculator that can perform arithmetic operations
|
|
||||||
- (big maybe) micropython or some other language, cross compiling, etc...
|
|
||||||
|
|
||||||
## Why?
|
### Currently Implemented
|
||||||
|
|
||||||
I enjoy bare metal programing and I have an old Dell system with a Pentium 3, I did this mostly to learn how to write a legacy style bootloader (I am also kinda working on a UEFI bootloader/utility as well!)
|
- **Stage 1 Bootloader**: Loads from the Master Boot Record (MBR) and prepares the system for Stage 2.
|
||||||
|
- **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.
|
||||||
|
|
||||||
|
### Planned Features
|
||||||
|
|
||||||
|
- **Task Scheduling**: Basic round-robin task switching.
|
||||||
|
- **Filesystem Expansion**: Support for additional filesystems.
|
||||||
|
- **More Robust Driver Support**: Additional hardware drivers, such as for storage devices.
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
To build and run this project, you need to have the following tools installed:
|
### Prerequisites
|
||||||
|
|
||||||
- A host system running Linux, macOS (should work 🤷♀️), or Windows 11 with WSL2/WSLg
|
To build and run Stevia, you will need the following tools installed on your system:
|
||||||
- GNU Binutils
|
|
||||||
- GNU GCC
|
|
||||||
- GNU Make
|
|
||||||
- NASM
|
|
||||||
- Bochs (for testing, project might run on other virtuization/emulation platforms, I target the Pentium 3 Era with this project)
|
|
||||||
|
|
||||||
To build the project, run `make` in the root directory. This will generate a floppy disk image named `stevia.img` that contains the boot loader and the kernel.
|
- **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.
|
||||||
|
|
||||||
To run the project, run `bochs -f bochsrc.txt` in the root directory. This will launch the Bochs emulator and load the floppy disk image. You should see the boot loader message, followed by the kernel message, and then the shell prompt.
|
### Building and Running
|
||||||
|
|
||||||
To exit the emulator, press `Ctrl+C` in the terminal where you launched Bochs.
|
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
|
||||||
|
```
|
||||||
|
3. **Run using Bochs**:
|
||||||
|
```sh
|
||||||
|
bochs -f bochsrc.txt
|
||||||
|
```
|
||||||
|
|
||||||
To run the project on real hardware I use a SD card to IDE interface for my test system which is a ~700Mhz P3 with 256 MB of ram. You will need to write the 'stevia.img' to the disk with 'dd'. On real hardware you may encounter issues that are not accounted for since most of the development happens on bochs, please report any issues you encounter.
|
## 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.
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
This project is licensed under the MIT License. See the [LICENSE.md](^2^) file for details.
|
This project is licensed under the MIT License. See the [LICENSE](LICENSE) file for more details.
|
||||||
|
|
||||||
### mbr/mbr.s
|
|
||||||
|
|
||||||
This file contains the code for a Master Boot Record (MBR) that attempts to find an active partition to load. The CPU is assumed to be in 16-bit real mode at this point and the bios has loaded the 1st sector of the disk (512 bytes) to 0x0000:0x7C00. First the mbr code relocates from 0x7C00 to 0x0600 and then jumps to the entry point. the loader attempts to load the first active partition it can find and loads the vbr to 0x7c00 (512 bytes) and then jumps to 0x0000:0x7C00. It is written in Assembly and uses BIOS interrupts to read sectors from disk.[^note]
|
|
||||||
|
|
||||||
### vbr/vbr.s
|
|
||||||
|
|
||||||
This file contains the code for a Volume Boot Record (VBR) that loads the stage2 loader code from the booted disk. It reads disk sectors 1-63 into memory to STAGE2_ENTRY(defaults to 0x7E00 in config.inc) this currently allows for stevia to load up to 32KiB of code to perform bootloader duties. It is written in Assembly and uses BIOS interrupts to read sectors from disk.[^note]
|
|
||||||
|
|
||||||
### stage2/stage2.s
|
|
||||||
|
|
||||||
This file contains the code for a second-stage boot loader that loads additional modules from disk, performs some system sanity checks, and provides a simple boot interface for options/configuration. It is written in Assembly and uses BIOS interrupts to read sectors from disk.[^note]
|
|
||||||
|
|
||||||
### miniboot32/BOOT_386.s
|
|
||||||
|
|
||||||
This file contains the code for a 32-bit binary that can be loaded and ran with stevia as a mini demo. It is written in Assembly.[^note]
|
|
||||||
|
|
||||||
### scripts/create-disk.sh
|
|
||||||
|
|
||||||
This script creates a disk image file for stevia. The disk image file can be used to boot stevia on an emulator or a real machine.
|
|
||||||
|
|
||||||
#### Requirements
|
|
||||||
|
|
||||||
- Bash shell
|
|
||||||
- Root privileges
|
|
||||||
- dd utility
|
|
||||||
- sfdisk utility (for Linux) or hdiutil & util-linux utility (for macOS, util-linux is needed for sfdisk because hdiutil only creates hybrid disks on newer versions afaik)
|
|
||||||
- newfs_msdos utility (for macOS)
|
|
||||||
- mkfs.vfat utility (for Linux)
|
|
||||||
|
|
||||||
#### Usage
|
|
||||||
|
|
||||||
Run the script as root (or just allow the make script to do its business):
|
|
||||||
|
|
||||||
```bash
|
|
||||||
sudo ./create_disk_image.sh
|
|
||||||
```
|
|
||||||
|
|
||||||
The script will create a disk image file named `disk.img` in the current directory. The disk image file will have the following characteristics:
|
|
||||||
|
|
||||||
- Size: 128 MiB
|
|
||||||
- Partition table: DOS
|
|
||||||
- Partition 1: FAT32, bootable, starts at sector 2048, contains the boot32 boot test file (`BOOT_386.bin`)
|
|
||||||
- Boot code: MBR (`mbr.bin`), VBR (`vbr.bin`), stage2 (sectors 1-63) (`stage2.bin`)
|
|
||||||
|
|
||||||
The script will also copy the necessary files from the `build` directory to the disk image file. If the files are not found, the script will exit with an error.
|
|
||||||
|
|
||||||
[^note]: **Note:** Please note that the assembly code is strictly targeting the Pentium 3 Katmai uArch, but it might run elsewhere. Your mileage may vary.
|
|
||||||
|
|||||||
52
bochsrc.bxrc
Normal file
52
bochsrc.bxrc
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
# 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, iodebug=true, ne2k=false, sb16=false, usb_uhci=false, usb_ohci=false, usb_ehci=false, usb_xhci=false
|
||||||
|
config_interface: win32config
|
||||||
|
display_library: win32
|
||||||
|
memory: guest=64, host=64, block_size=128
|
||||||
|
romimage: file="C:\Program Files\Bochs-2.8\BIOS-bochs-legacy", address=0x00000000, options=none, flash_data=none
|
||||||
|
vgaromimage: file="C:\Program Files\Bochs-2.8\VGABIOS-lgpl-latest"
|
||||||
|
boot: disk
|
||||||
|
floppy_bootsig_check: disabled=1
|
||||||
|
floppya: type=1_44
|
||||||
|
# no floppyb
|
||||||
|
ata0: enabled=true, ioaddr1=0x1f0, ioaddr2=0x3f0, irq=14
|
||||||
|
ata0-master: type=disk, path=".\disk.img", mode=flat, cylinders=0, heads=16, spt=63, sect_size=512, model="Stevia Disk", biosdetect=auto, translation=auto
|
||||||
|
ata0-slave: type=none
|
||||||
|
ata1: enabled=false
|
||||||
|
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
|
||||||
|
debugger_log: -
|
||||||
|
magic_break: enabled=1
|
||||||
|
port_e9_hack: enabled=true, all_rings=false
|
||||||
|
iodebug: all_rings=0
|
||||||
|
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
|
||||||
|
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
|
||||||
|
speaker: enabled=true, mode=sound, volume=15
|
||||||
|
parport1: enabled=false
|
||||||
|
parport2: enabled=false
|
||||||
|
com1: enabled=false
|
||||||
|
com2: enabled=false
|
||||||
|
com3: enabled=false
|
||||||
|
com4: enabled=false
|
||||||
53
bochsrc.dbg.txt
Executable file
53
bochsrc.dbg.txt
Executable file
@@ -0,0 +1,53 @@
|
|||||||
|
# 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
|
||||||
|
config_interface: textconfig
|
||||||
|
display_library: sdl2, 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="./disk.img", mode=flat, cylinders=0, heads=0, spt=0, sect_size=512, model="Stevia Disk", biosdetect=auto, translation=auto
|
||||||
|
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=0, cpuid_limit_winnt=0, ignore_bad_msrs=1, mwait_is_nop=0
|
||||||
|
print_timestamps: enabled=0
|
||||||
|
private_colormap: enabled=0
|
||||||
|
clock: sync=none, time0=local, rtc_sync=0
|
||||||
|
# no cmosimage
|
||||||
|
log: stevia-log
|
||||||
|
#logcontrol: disk=1, rombios=1, pci=0, cpu=0, keyboard=0, io=0
|
||||||
|
logprefix: %t%e%d
|
||||||
|
debug: action=ignore
|
||||||
|
info: action=report
|
||||||
|
error: action=report
|
||||||
|
panic: action=ask
|
||||||
|
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
|
||||||
|
speaker: enabled=true, mode=sound, volume=15
|
||||||
|
parport1: enabled=true, file=none
|
||||||
|
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
|
||||||
43
bochsrc.txt
43
bochsrc.txt
@@ -1,25 +1,35 @@
|
|||||||
# configuration file generated by Bochs
|
# configuration file generated by Bochs
|
||||||
plugin_ctrl: unmapped=true, biosdev=true, speaker=true, extfpuirq=true, parallel=true, serial=true, gameport=true, iodebug=true
|
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: wx
|
config_interface: textconfig
|
||||||
display_library: wx
|
display_library: wx
|
||||||
memory: host=64, guest=64
|
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
|
boot: disk
|
||||||
floppy_bootsig_check: disabled=0
|
floppy_bootsig_check: disabled=0
|
||||||
# no floppya
|
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="Generic 1234", biosdetect=auto, translation=auto
|
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-slave: type=none
|
ata0-slave: type=none
|
||||||
ata1: enabled=false
|
ata1: enabled=false
|
||||||
|
ata1-master: type=none
|
||||||
|
ata1-slave: type=none
|
||||||
ata2: enabled=false
|
ata2: enabled=false
|
||||||
ata3: enabled=false
|
ata3: enabled=false
|
||||||
pci: enabled=0
|
optromimage1: file=none
|
||||||
vga: extension=vbe, update_freq=5, realtime=1
|
optromimage2: file=none
|
||||||
cpu: count=1:1:1, ips=1000000, quantum=16, model=p3_katmai, reset_on_triple_fault=1, cpuid_limit_winnt=0, ignore_bad_msrs=1, mwait_is_nop=0
|
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
|
print_timestamps: enabled=0
|
||||||
debugger_log: -
|
port_e9_hack: enabled=false, all_rings=false
|
||||||
magic_break: enabled=0
|
|
||||||
port_e9_hack: enabled=0
|
|
||||||
private_colormap: enabled=0
|
private_colormap: enabled=0
|
||||||
clock: sync=none, time0=local, rtc_sync=0
|
clock: sync=none, time0=local, rtc_sync=0
|
||||||
# no cmosimage
|
# no cmosimage
|
||||||
@@ -29,12 +39,15 @@ debug: action=ignore
|
|||||||
info: action=report
|
info: action=report
|
||||||
error: action=report
|
error: action=report
|
||||||
panic: action=ask
|
panic: action=ask
|
||||||
keyboard: type=mf, serial_delay=250, paste_delay=100000, user_shortcut=none
|
keyboard: type=mf, serial_delay=150, paste_delay=100000, user_shortcut=none
|
||||||
mouse: type=ps2, enabled=false, toggle=ctrl+mbutton
|
mouse: type=none, enabled=false, toggle=ctrl+mbutton
|
||||||
speaker: enabled=true, mode=system
|
sound: waveoutdrv=dummy, waveout=none, waveindrv=dummy, wavein=none, midioutdrv=dummy, midiout=none
|
||||||
parport1: enabled=false
|
speaker: enabled=true, mode=sound, volume=15
|
||||||
|
parport1: enabled=true, file=none
|
||||||
parport2: enabled=false
|
parport2: enabled=false
|
||||||
com1: enabled=true, mode=null
|
com1: enabled=true, mode=null
|
||||||
com2: enabled=false
|
com2: enabled=false
|
||||||
com3: enabled=false
|
com3: enabled=false
|
||||||
com4: enabled=false
|
com4: enabled=false
|
||||||
|
magic_break: enabled=1
|
||||||
|
port_e9_hack: enabled=1, all_rings=false
|
||||||
|
|||||||
230
docs/Stevia Notes.md
Normal file
230
docs/Stevia Notes.md
Normal file
@@ -0,0 +1,230 @@
|
|||||||
|
# **Bootloader Documentation**
|
||||||
|
|
||||||
|
## **1. Calling Conventions**
|
||||||
|
|
||||||
|
### __cdecl16near Calling Convention
|
||||||
|
|
||||||
|
- **Purpose**: For calling near (within the same segment) functions in 16-bit code.
|
||||||
|
- **Stack Management**: Caller cleans up the stack after the function call.
|
||||||
|
- **Parameter Passing**: Parameters are pushed onto the stack from right to left.
|
||||||
|
- **Return Address**: A near return address (16-bit) is pushed onto the stack.
|
||||||
|
- **Return Value**: Placed in the AX register.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
```assembly
|
||||||
|
; Caller
|
||||||
|
push param2
|
||||||
|
push param1
|
||||||
|
call near_func
|
||||||
|
add sp, 4 ; Clean up the stack (2 parameters * 2 bytes each)
|
||||||
|
|
||||||
|
; Callee (near_func)
|
||||||
|
near_func:
|
||||||
|
push bp
|
||||||
|
mov bp, sp
|
||||||
|
; Function body
|
||||||
|
mov sp, bp
|
||||||
|
pop bp
|
||||||
|
ret
|
||||||
|
```
|
||||||
|
|
||||||
|
### __cdecl16far Calling Convention
|
||||||
|
|
||||||
|
- **Purpose**: For calling far (across different segments) functions in 16-bit code.
|
||||||
|
- **Stack Management**: Caller cleans up the stack after the function call.
|
||||||
|
- **Parameter Passing**: Parameters are pushed onto the stack from right to left.
|
||||||
|
- **Return Address**: A far return address (32-bit, consisting of a segment and an offset) is pushed onto the stack.
|
||||||
|
- **Return Value**: Placed in the AX register.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
```assembly
|
||||||
|
; Caller
|
||||||
|
push param2
|
||||||
|
push param1
|
||||||
|
call far_func
|
||||||
|
add sp, 4 ; Clean up the stack (2 parameters * 2 bytes each)
|
||||||
|
|
||||||
|
; Callee (far_func)
|
||||||
|
far_func:
|
||||||
|
push bp
|
||||||
|
mov bp, sp
|
||||||
|
; Function body
|
||||||
|
mov sp, bp
|
||||||
|
pop bp
|
||||||
|
retf ; Far return
|
||||||
|
```
|
||||||
|
|
||||||
|
### **Key Differences**
|
||||||
|
|
||||||
|
- **Return Address**: `__cdecl16near` uses a 16-bit return address; `__cdecl16far` uses a 32-bit return address (segment:offset).
|
||||||
|
- **Function Scope**: `__cdecl16near` is for functions within the same segment; `__cdecl16far` is for functions that may be in different segments.
|
||||||
|
- **Return Instruction**: `__cdecl16near` uses `ret`; `__cdecl16far` uses `retf` (far return).
|
||||||
|
|
||||||
|
### **Register Usage**
|
||||||
|
|
||||||
|
#### Caller-Saved (Volatile) Registers
|
||||||
|
|
||||||
|
- **AX**: Accumulator, often used for return values.
|
||||||
|
- **CX**: Counter register.
|
||||||
|
- **DX**: Data register, used for I/O operations.
|
||||||
|
- **SI/DI**: String operation indexes.
|
||||||
|
|
||||||
|
#### Callee-Saved (Non-Volatile) Registers
|
||||||
|
|
||||||
|
- **BP**: Base pointer, used for stack frame management.
|
||||||
|
- **SP**: Stack pointer.
|
||||||
|
- **BX**: Base register.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
```assembly
|
||||||
|
; Caller
|
||||||
|
push param2
|
||||||
|
push param1
|
||||||
|
call near_func
|
||||||
|
add sp, 4 ; Clean up the stack (2 parameters * 2 bytes each)
|
||||||
|
|
||||||
|
; Callee (near_func)
|
||||||
|
near_func:
|
||||||
|
push bp
|
||||||
|
mov bp, sp
|
||||||
|
; Save callee-saved registers if used
|
||||||
|
push bx
|
||||||
|
push si
|
||||||
|
push di
|
||||||
|
; Function body
|
||||||
|
; Use AX, CX, DX freely
|
||||||
|
; Restore callee-saved registers
|
||||||
|
pop di
|
||||||
|
pop si
|
||||||
|
pop bx
|
||||||
|
mov sp, bp
|
||||||
|
pop bp
|
||||||
|
ret
|
||||||
|
```
|
||||||
|
|
||||||
|
## **2. E820 Memory Map Usage**
|
||||||
|
|
||||||
|
### **Address Range Descriptor Structure**
|
||||||
|
|
||||||
|
| Offset | Name | Description |
|
||||||
|
|--------|---------------|---------------------------------------|
|
||||||
|
| 0 | BaseAddrLow | Low 32 bits of base address |
|
||||||
|
| 4 | BaseAddrHigh | High 32 bits of base address |
|
||||||
|
| 8 | LengthLow | Low 32 bits of length in bytes |
|
||||||
|
| 12 | LengthHigh | High 32 bits of length in bytes |
|
||||||
|
| 16 | Type | Address type of this range |
|
||||||
|
|
||||||
|
### **E820 Function Call**
|
||||||
|
|
||||||
|
#### Input
|
||||||
|
|
||||||
|
- **EAX**: Function code `E820h`.
|
||||||
|
- **EBX**: Continuation value for physical memory retrieval (0 for the first call).
|
||||||
|
- **ES:DI**: Buffer pointer to an Address Range Descriptor structure.
|
||||||
|
- **ECX**: Buffer size (minimum size 20 bytes).
|
||||||
|
- **EDX**: Signature ('SMAP').
|
||||||
|
|
||||||
|
#### Output
|
||||||
|
|
||||||
|
- **CF**: Carry flag (indicates success/failure).
|
||||||
|
- **EAX**: Signature ('SMAP').
|
||||||
|
- **ECX**: Buffer size (number of bytes returned).
|
||||||
|
- **EBX**: Continuation value for subsequent E820 calls.
|
||||||
|
|
||||||
|
### **Address Type Values**
|
||||||
|
|
||||||
|
| Value | Pneumonic | Description |
|
||||||
|
|-------|----------------------|-----------------------------------------------------------|
|
||||||
|
| 1 | AddressRangeMemory | Available RAM usable by the operating system. |
|
||||||
|
| 2 | AddressRangeReserved | Reserved by the system, unusable by the operating system. |
|
||||||
|
|
||||||
|
## **3. Example Calculations**
|
||||||
|
|
||||||
|
### **Partition Offset**
|
||||||
|
|
||||||
|
- Partition 1 offset = LBA 0x800 = 0x100000
|
||||||
|
- `bsSectorSize = 512`
|
||||||
|
|
||||||
|
### **First FAT Sector**
|
||||||
|
|
||||||
|
- `first_fat_sector = bsResSector = 32 => (32*512) = 0x4000`
|
||||||
|
- `first_fat_sector = 0x100000 + 0x4000 = 0x104000`
|
||||||
|
|
||||||
|
### **Total FAT Sectors**
|
||||||
|
|
||||||
|
- `total_fat_sectors = fat_sectors * number_of_FATs = 2001 * 2 = 4002`
|
||||||
|
- `total_fat_size = total_fat_sectors * bsSectorSize = 0x1F4400`
|
||||||
|
|
||||||
|
### **First Data Sector**
|
||||||
|
|
||||||
|
- `first_data_sector = FatStartSector + FatAreaSize = 0x104000 + 0x1F4400 = 0x2F8400`
|
||||||
|
|
||||||
|
### **FAT Table Look Up**
|
||||||
|
|
||||||
|
```c
|
||||||
|
if the cluster we got from the table entry was cluster 354
|
||||||
|
fat_sector = 354 / 128 = 2
|
||||||
|
fat_entry = 354 mod 128 = 98
|
||||||
|
|
||||||
|
so we load the 3rd (indexed from 0) fat table sector and read the 98th entry
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
```c
|
||||||
|
|
||||||
|
fat_table_offset = (first_fat_sector + 2) * 512
|
||||||
|
fat_table = *(fat_table_offset)
|
||||||
|
disk_read(fat_table[98])
|
||||||
|
```
|
||||||
|
|
||||||
|
## **4. Global Descriptor Table (GDT)**
|
||||||
|
|
||||||
|
### **Segment Attributes**
|
||||||
|
|
||||||
|
- **Pr**: Present bit (must be 1 for valid selectors).
|
||||||
|
- **Privl**: Privilege level (0 = kernel, 3 = user).
|
||||||
|
- **S**: Descriptor type (set for code/data segments, cleared for system segments).
|
||||||
|
- **Ex**: Executable bit (set if segment contains code).
|
||||||
|
- **DC**: Direction/Conforming bit (for data or code segments).
|
||||||
|
- **RW**: Readable/Writable (depends on segment type).
|
||||||
|
|
||||||
|
### **Granularity (Gr)**
|
||||||
|
|
||||||
|
- **Gr**: Granularity bit (0 = byte granularity, 1 = 4 KiB blocks).
|
||||||
|
- **Sz**: Size bit (0 = 16-bit mode, 1 = 32-bit mode).
|
||||||
|
|
||||||
|
### **GDT Entry Construction**
|
||||||
|
|
||||||
|
Each GDT entry is 8 bytes:
|
||||||
|
|
||||||
|
- First DWORD: Limit (0:15), Base (0:15)
|
||||||
|
- Second DWORD: Base (16:31), Attributes (8:12)
|
||||||
|
|
||||||
|
## **5. Memory Layout Example**
|
||||||
|
|
||||||
|
### **Low Memory (First MiB)**
|
||||||
|
|
||||||
|
| Start | End | Size | Type | Description |
|
||||||
|
|-------------|-------------|-----------------|-----------------------|----------------------------------|
|
||||||
|
| 0x00000000 | 0x000003FF | 1 KiB | RAM (partially unusable) | Real Mode IVT (Interrupt Vector Table) |
|
||||||
|
| 0x00000400 | 0x000004FF | 256 bytes | RAM (partially unusable) | BDA (BIOS data area) |
|
||||||
|
| 0x00000500 | 0x00007BFF | almost 30 KiB | RAM - free for use | Conventional memory |
|
||||||
|
| 0x00007C00 | 0x00007DFF | 512 bytes | RAM (partially unusable) | OS BootSector |
|
||||||
|
| 0x00007E00 | 0x0007FFFF | 480.5 KiB | RAM - free for use | Conventional memory |
|
||||||
|
| 0x00080000 | 0x0009FFFF | 128 KiB | RAM (partially unusable) | EBDA (Extended BIOS Data Area) |
|
||||||
|
| 0x000A0000 | 0x000FFFFF | 384 KiB | various (unusable) | Video memory, ROM Area |
|
||||||
|
|
||||||
|
### **Extended Memory (Above 1 MiB)**
|
||||||
|
|
||||||
|
| Start | End | Size | Description |
|
||||||
|
|-------------|-------------|-----------------|------------------------|
|
||||||
|
| 0x00100000 | 0x00EFFFFF | 14 MiB | RAM - free for use |
|
||||||
|
| 0x00F00000 | 0x00FFFFFF | 1 MiB | Possible memory-mapped hardware (ISA) |
|
||||||
|
| 0x01000000 | ? | ? | More extended memory |
|
||||||
|
| 0xC0000000 | 0xFFFFFFFF | 1 GiB | Memory mapped PCI devices, BIOS, etc. |
|
||||||
|
| 0x0000000100000000 | ? | ? | RAM - usable in PAE/64-bit mode |
|
||||||
@@ -1,35 +0,0 @@
|
|||||||
Partition 1 offset = LBA 0x800
|
|
||||||
= 0x100000
|
|
||||||
bsSectorSize = 512
|
|
||||||
|
|
||||||
first_fat_sector = bsResSector
|
|
||||||
= 32 => (32*512) = 0x4000
|
|
||||||
= 0x100000 + 0x4000
|
|
||||||
= 0x104000
|
|
||||||
|
|
||||||
total_fat_sectors = fat_sectors * number_of_FATs
|
|
||||||
= 2001 * 2
|
|
||||||
= 4002
|
|
||||||
|
|
||||||
total_fat_size = total_fat_sectors * bsSectorSize
|
|
||||||
= 0x1F4400
|
|
||||||
|
|
||||||
first_data_sector = FatStartSector + FatAreaSize
|
|
||||||
= 0x104000 + 0x1F4400
|
|
||||||
= 0x2F8400
|
|
||||||
|
|
||||||
FAT table look up
|
|
||||||
|
|
||||||
if the cluster we got from the table entry was cluster 354
|
|
||||||
fat_sector = 354 / 128
|
|
||||||
= 2
|
|
||||||
fat_entry = 354 mod 128
|
|
||||||
= 98
|
|
||||||
|
|
||||||
so we load the 3rd (indexed from 0) fat table sector and read the 98th entry
|
|
||||||
for the cluster chain.
|
|
||||||
|
|
||||||
// bad fake code below
|
|
||||||
fat_table_offset = (first_fat_sector + 2) * 512
|
|
||||||
fat_table = *(fat_table_offset)
|
|
||||||
disk_read(fat_table[98])
|
|
||||||
24
include/BIOS/BIOS_SYS.inc
Normal file
24
include/BIOS/BIOS_SYS.inc
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
; Copyright (c) 2024 Elaina Claus
|
||||||
|
;
|
||||||
|
; Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
; of this software and associated documentation files (the "Software"), to deal
|
||||||
|
; in the Software without restriction, including without limitation the rights
|
||||||
|
; to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
; copies of the Software, and to permit persons to whom the Software is
|
||||||
|
; furnished to do so, subject to the following conditions:
|
||||||
|
;
|
||||||
|
; The above copyright notice and this permission notice shall be included in all
|
||||||
|
; copies or substantial portions of the Software.
|
||||||
|
;
|
||||||
|
; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
; IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
; FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
; AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
; LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
; SOFTWARE.
|
||||||
|
|
||||||
|
%include 'BIOS/func/a20enable.nasm'
|
||||||
|
%include 'BIOS/func/E820_memory_map.nasm'
|
||||||
|
%include 'BIOS/func/ext_read.nasm'
|
||||||
|
%include 'BIOS/func/video.nasm'
|
||||||
88
include/BIOS/func/E820_memory_map.nasm
Normal file
88
include/BIOS/func/E820_memory_map.nasm
Normal file
@@ -0,0 +1,88 @@
|
|||||||
|
; Copyright (c) 2024 Elaina Claus
|
||||||
|
;
|
||||||
|
; Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
; of this software and associated documentation files (the "Software"), to deal
|
||||||
|
; in the Software without restriction, including without limitation the rights
|
||||||
|
; to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
; copies of the Software, and to permit persons to whom the Software is
|
||||||
|
; furnished to do so, subject to the following conditions:
|
||||||
|
;
|
||||||
|
; The above copyright notice and this permission notice shall be included in all
|
||||||
|
; copies or substantial portions of the Software.
|
||||||
|
;
|
||||||
|
; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
; IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
; FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
; AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
; LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
; SOFTWARE.
|
||||||
|
|
||||||
|
%ifndef __INC_E820MEMORY_MAP
|
||||||
|
|
||||||
|
; Address Range Descriptor Structure
|
||||||
|
;
|
||||||
|
; Offset in Bytes Name Description
|
||||||
|
; 0 BaseAddrLow u32 - Low 32 Bits of Base Address
|
||||||
|
; 4 BaseAddrHigh u32 - High 32 Bits of Base Address
|
||||||
|
; 8 LengthLow u32 - Low 32 Bits of Length in Bytes
|
||||||
|
; 12 LengthHigh u32 - High 32 Bits of Length in Bytes
|
||||||
|
; 16 Type u32 - Address type of this range.
|
||||||
|
; 20 ExtType u32 - ACPI 3.0 extended type
|
||||||
|
struc AddressRangeDescStruct_t
|
||||||
|
.BaseAddrLow resd 1
|
||||||
|
.BaseAddrHigh resd 1
|
||||||
|
.LengthLow resd 1
|
||||||
|
.LengthHigh resd 1
|
||||||
|
.Type resd 1
|
||||||
|
.ExtType resd 1
|
||||||
|
endstruc
|
||||||
|
|
||||||
|
ALIGN 4, db 0x90
|
||||||
|
GetMemoryMap:
|
||||||
|
__CDECL16_ENTRY
|
||||||
|
push es ; save segment register
|
||||||
|
.func:
|
||||||
|
mov dword [SteviaInfo + SteviaInfoStruct_t.MemoryMapEntries], 0
|
||||||
|
|
||||||
|
mov eax, 0xE820 ; select 0xE820 function
|
||||||
|
xor ebx, ebx ; Continuation value, 0 for the first call
|
||||||
|
|
||||||
|
lea dx, [BIOSMemoryMap]
|
||||||
|
shr dx, 4
|
||||||
|
mov es, dx
|
||||||
|
xor di, di ; (BIOSMemoryMap >> 4):0 makes di an index into BIOSMemoryMap
|
||||||
|
|
||||||
|
mov ecx, AddressRangeDescStruct_t_size
|
||||||
|
mov edx, 0x534D4150 ; 'SMAP' magic
|
||||||
|
.loop_L1:
|
||||||
|
int 0x15
|
||||||
|
jc GetMemoryMap.error
|
||||||
|
cmp eax, 0x534D4150
|
||||||
|
jne GetMemoryMap.no_smap_returned
|
||||||
|
.no_error:
|
||||||
|
inc dword [SteviaInfo + SteviaInfoStruct_t.MemoryMapEntries]
|
||||||
|
|
||||||
|
cmp ecx, 20 ; TODO: maybe this could be handled better than just panicing
|
||||||
|
jb GetMemoryMap.nonstandard_e820 ; non-standard entry found
|
||||||
|
|
||||||
|
cmp ebx, 0
|
||||||
|
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
|
||||||
|
mov edx, eax ; 'SMAP' to edx
|
||||||
|
mov eax, 0xE820 ; select E820 function
|
||||||
|
jmp GetMemoryMap.loop_L1
|
||||||
|
.error:
|
||||||
|
ERROR STAGE2_MM_E820_MISC_ERR
|
||||||
|
.nonstandard_e820:
|
||||||
|
ERROR STAGE2_MM_E820_NONSTANDARD
|
||||||
|
.no_smap_returned:
|
||||||
|
ERROR STAGE2_MM_E820_NO_SMAP
|
||||||
|
.endp:
|
||||||
|
pop es
|
||||||
|
__CDECL16_EXIT
|
||||||
|
ret
|
||||||
|
|
||||||
|
%endif
|
||||||
|
%define __INC_E820MEMORY_MAP
|
||||||
144
include/BIOS/func/a20enable.nasm
Normal file
144
include/BIOS/func/a20enable.nasm
Normal file
@@ -0,0 +1,144 @@
|
|||||||
|
; Copyright (c) 2024 Elaina Claus
|
||||||
|
;
|
||||||
|
; Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
; of this software and associated documentation files (the "Software"), to deal
|
||||||
|
; in the Software without restriction, including without limitation the rights
|
||||||
|
; to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
; copies of the Software, and to permit persons to whom the Software is
|
||||||
|
; furnished to do so, subject to the following conditions:
|
||||||
|
;
|
||||||
|
; The above copyright notice and this permission notice shall be included in all
|
||||||
|
; copies or substantial portions of the Software.
|
||||||
|
;
|
||||||
|
; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
; IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
; FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
; AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
; LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
; SOFTWARE.
|
||||||
|
|
||||||
|
%ifndef __INC_A20ENABLE
|
||||||
|
;
|
||||||
|
;INT 0x15 Function 2400 - Disable A20
|
||||||
|
;Returns:
|
||||||
|
;
|
||||||
|
; CF = clear if success
|
||||||
|
; AH = 0
|
||||||
|
; CF = set on error
|
||||||
|
; AH = status (01=keyboard controller is in secure mode, 0x86=function not supported)
|
||||||
|
;
|
||||||
|
;INT 0x15 Function 2401 - Enable A20
|
||||||
|
;Returns:
|
||||||
|
;
|
||||||
|
; CF = clear if success
|
||||||
|
; AH = 0
|
||||||
|
; CF = set on error
|
||||||
|
; AH = status (01=keyboard controller is in secure mode, 0x86=function not supported)
|
||||||
|
;
|
||||||
|
;INT 0x15 Function 2402 - A20 Status
|
||||||
|
; Returns:
|
||||||
|
;
|
||||||
|
; CF = clear if success
|
||||||
|
; AH = status (01: keyboard controller is in secure mode; 0x86: function not supported)
|
||||||
|
; AL = current state (00: disabled, 01: enabled)
|
||||||
|
; CX = set to 0xffff is keyboard controller is no ready in 0xc000 read attempts
|
||||||
|
; CF = set on error
|
||||||
|
;
|
||||||
|
;INT 0x15 Function 2403 - Query A20 support
|
||||||
|
;Returns:
|
||||||
|
;
|
||||||
|
;CF = clear if success
|
||||||
|
;AH = status (01: keyboard controller is in secure mode; 0x86: function not supported)
|
||||||
|
;BX = status.
|
||||||
|
;
|
||||||
|
;BX contains a bit pattern:
|
||||||
|
;
|
||||||
|
; Bit 0 - supported on keyboard controller
|
||||||
|
; Bit 1 - if supported on bit 1 of I/O port 0x92
|
||||||
|
; Bits 2:14 - Reserved
|
||||||
|
; Bit 15 - 1 if additional data is available.
|
||||||
|
;
|
||||||
|
; I/O Port 0x92 infomation:
|
||||||
|
;
|
||||||
|
; Bit 0 - Setting to 1 causes a fast reset
|
||||||
|
; Bit 1 - 0: disable A20; 1: enable A20
|
||||||
|
; Bit 2 - Manufacturer defined
|
||||||
|
; Bit 3 - power on password bytes (CMOS bytes 0x38-0x3f or 0x36-0x3f). 0: accessible, 1: inaccessible
|
||||||
|
; Bits 4-5 - Manufacturer defined
|
||||||
|
; Bits 6-7 - 00: HDD activity LED off; any other value is "on"
|
||||||
|
ALIGN 4, db 0x90
|
||||||
|
EnableA20:
|
||||||
|
__CDECL16_ENTRY
|
||||||
|
push ds
|
||||||
|
push es
|
||||||
|
.a20_check:
|
||||||
|
cli
|
||||||
|
|
||||||
|
xor ax, ax
|
||||||
|
mov es, ax
|
||||||
|
|
||||||
|
not ax ; ax = 0xFFFF
|
||||||
|
mov ds, ax
|
||||||
|
|
||||||
|
mov di, 0x0500 ; scratch location 1
|
||||||
|
mov si, 0x0510 ; scratch location 2
|
||||||
|
|
||||||
|
mov al, byte [es:di]
|
||||||
|
push ax ; save whatever is at 0x0000:0500, physical location 0x0500
|
||||||
|
|
||||||
|
mov al, byte [ds:si]
|
||||||
|
push ax ; save whatever is at 0xFFFF:0510 [clarification: 0x100500 physical location (0x100500 - 1MB = 0x0500)]
|
||||||
|
|
||||||
|
mov byte [es:di], 0x00 ; zero non-wraped location and write 0xFF to it after (ab)using wrapping
|
||||||
|
mov byte [ds:si], 0xFF ; if the non-wrapped location is 0xFF, then we wraped and A20 is disabled
|
||||||
|
|
||||||
|
cmp byte [es:di], 0xFF
|
||||||
|
|
||||||
|
pop ax
|
||||||
|
mov byte [ds:si], al ; restore original contents of scratch location 2
|
||||||
|
|
||||||
|
pop ax
|
||||||
|
mov byte [es:di], al ; restore original contents of scratch location 1
|
||||||
|
|
||||||
|
mov ax, 0 ; return 0 if es:di == ds:si (memory wraps)
|
||||||
|
je EnableA20.end_check
|
||||||
|
mov ax, 1 ; return 1 if es:di != ds:si (A20 is enabled)
|
||||||
|
.end_check:
|
||||||
|
sti
|
||||||
|
cmp ax, 1
|
||||||
|
je EnableA20.endp ; A20 is already enabled
|
||||||
|
|
||||||
|
mov ax, 0x2403
|
||||||
|
int 0x15
|
||||||
|
jc EnableA20.do_fallback_a20 ; carry = error...not supported?
|
||||||
|
cmp ah, 0
|
||||||
|
ja EnableA20.do_fallback_a20 ; non-zero return = error as well
|
||||||
|
|
||||||
|
mov al, bl
|
||||||
|
and al, 0000_0010b
|
||||||
|
cmp al, 0000_0010b
|
||||||
|
je EnableA20.do_fast_a20 ; if fast a20 is supported use it
|
||||||
|
|
||||||
|
jmp EnableA20.do_bios_a20 ; else fall back to enabling via BIOS
|
||||||
|
|
||||||
|
.do_fallback_a20:
|
||||||
|
ERROR STAGE2_A20_FAILED
|
||||||
|
.do_bios_a20:
|
||||||
|
mov ax, 0x2401
|
||||||
|
int 0x15
|
||||||
|
jmp EnableA20.a20_check
|
||||||
|
.do_fast_a20:
|
||||||
|
in al, 0x92 ; read from FAST A20 port
|
||||||
|
or al, 2 ; bit 0 is a fast reset, bit 1 is fast A20
|
||||||
|
and al, 0xFE ; make sure bit 0 is 0
|
||||||
|
out 0x92, al ; enable A20
|
||||||
|
jmp EnableA20.a20_check
|
||||||
|
.endp:
|
||||||
|
pop es
|
||||||
|
pop ds
|
||||||
|
__CDECL16_EXIT
|
||||||
|
ret
|
||||||
|
|
||||||
|
%endif
|
||||||
|
%define __INC_A20ENABLE
|
||||||
129
include/BIOS/func/ext_read.nasm
Normal file
129
include/BIOS/func/ext_read.nasm
Normal file
@@ -0,0 +1,129 @@
|
|||||||
|
; Copyright (c) 2024 Elaina Claus
|
||||||
|
;
|
||||||
|
; Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
; of this software and associated documentation files (the "Software"), to deal
|
||||||
|
; in the Software without restriction, including without limitation the rights
|
||||||
|
; to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
; copies of the Software, and to permit persons to whom the Software is
|
||||||
|
; furnished to do so, subject to the following conditions:
|
||||||
|
;
|
||||||
|
; The above copyright notice and this permission notice shall be included in all
|
||||||
|
; copies or substantial portions of the Software.
|
||||||
|
;
|
||||||
|
; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
; IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
; FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
; AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
; LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
; SOFTWARE.
|
||||||
|
|
||||||
|
%ifndef __INC_EXT_READ
|
||||||
|
;Offset Size Description
|
||||||
|
; 0 1 size of packet (16 bytes)
|
||||||
|
; 1 1 always 0
|
||||||
|
; 2 2 number of sectors to transfer (max 127 on some BIOSes)
|
||||||
|
; 4 4 transfer buffer (0xFFFF:0xFFFF)
|
||||||
|
; 8 4 lower 32-bits of starting 48-bit LBA
|
||||||
|
; 12 4 upper 32-bits of starting 48-bit LBA
|
||||||
|
; needs to be aligned to a uint32_t
|
||||||
|
struc LBAPkt_t
|
||||||
|
.size resb 1
|
||||||
|
.res0 resb 1
|
||||||
|
.xfer_size resw 1
|
||||||
|
.offset resw 1
|
||||||
|
.segment resw 1
|
||||||
|
.lower_lba resd 1
|
||||||
|
.upper_lba resd 1
|
||||||
|
endstruc
|
||||||
|
; call_read_disk_raw <word segment> <word offset> <dword lba> <word count> <word drive_num>
|
||||||
|
%macro call_read_disk_raw 5
|
||||||
|
movzx ax, %5
|
||||||
|
push ax ; drive_num
|
||||||
|
|
||||||
|
movzx ax, %4
|
||||||
|
push ax ; count
|
||||||
|
|
||||||
|
movzx dword eax, %3
|
||||||
|
push dword eax ; lba
|
||||||
|
|
||||||
|
movzx ax, %2
|
||||||
|
push ax ; offset
|
||||||
|
|
||||||
|
movzx ax, %1
|
||||||
|
push ax ; segment = 0
|
||||||
|
|
||||||
|
; uint8_t read_stage2_raw(uint16_t buf_segment, uint16_t buf_offset,
|
||||||
|
; uint32_t lba,
|
||||||
|
; uint16_t count, uint16_t drive_num)
|
||||||
|
call read_disk_raw
|
||||||
|
add sp, 0xC
|
||||||
|
%endmacro
|
||||||
|
|
||||||
|
; Wrapper for AH=0x42 INT13h (Extended Read)
|
||||||
|
;
|
||||||
|
; BIOS call details
|
||||||
|
; AH = 42h
|
||||||
|
; DL = drive number
|
||||||
|
; DS:SI -> disk address packet
|
||||||
|
;
|
||||||
|
; Return:
|
||||||
|
; CF clear if successful
|
||||||
|
; AH = 00h
|
||||||
|
; CF set on error
|
||||||
|
; AH = error code
|
||||||
|
; disk address packet's block count field set to number of blocks
|
||||||
|
; successfully transferred
|
||||||
|
;
|
||||||
|
;
|
||||||
|
; uint8_t read_stage2_raw(uint16_t buf_segment, uint16_t buf_offset,
|
||||||
|
; uint32_t lba,
|
||||||
|
; uint16_t count, uint8_t drive_num)
|
||||||
|
ALIGN 4, db 0x90
|
||||||
|
read_disk_raw:
|
||||||
|
__CDECL16_ENTRY
|
||||||
|
.func:
|
||||||
|
mov ax, LBAPkt_t_size
|
||||||
|
push ax ; len
|
||||||
|
xor ax, ax
|
||||||
|
push ax ; val = 0
|
||||||
|
mov ax, lba_packet
|
||||||
|
push ax ; dest = lba_packet address
|
||||||
|
call kmemset
|
||||||
|
add sp, 0x06
|
||||||
|
|
||||||
|
mov bx, lba_packet
|
||||||
|
mov byte [bx + LBAPkt_t.size], LBAPkt_t_size
|
||||||
|
|
||||||
|
mov ax, [bp + 12]
|
||||||
|
mov word [bx + LBAPkt_t.xfer_size], ax
|
||||||
|
|
||||||
|
mov eax, [bp + 8]
|
||||||
|
mov dword [bx + LBAPkt_t.lower_lba], eax
|
||||||
|
|
||||||
|
mov ax, [bp + 6]
|
||||||
|
mov word [bx + LBAPkt_t.offset], ax
|
||||||
|
|
||||||
|
movzx ax, byte [bp + 4]
|
||||||
|
mov word [bx + LBAPkt_t.segment], ax
|
||||||
|
|
||||||
|
mov si, bx ; ds:si LBAPkt_t
|
||||||
|
mov ah, 0x42 ; call #
|
||||||
|
mov dl, byte [bp + 14] ; drive #
|
||||||
|
|
||||||
|
int 0x13
|
||||||
|
jnc .endf
|
||||||
|
|
||||||
|
%ifdef __STEVIA_MBR
|
||||||
|
ERROR MBR_ERROR_DISK_READ_ERR
|
||||||
|
%elifdef __STEVIA_VBR
|
||||||
|
ERROR VBR_ERROR_DISK_READ_ERR
|
||||||
|
%else
|
||||||
|
ERROR STAGE2_MBR_DISK_READ_ERROR
|
||||||
|
%endif
|
||||||
|
.endf:
|
||||||
|
__CDECL16_EXIT
|
||||||
|
ret
|
||||||
|
|
||||||
|
%endif
|
||||||
|
%define __INC_EXT_READ
|
||||||
60
include/BIOS/func/video.nasm
Normal file
60
include/BIOS/func/video.nasm
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
; Copyright (c) 2024 Elaina Claus
|
||||||
|
;
|
||||||
|
; Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
; of this software and associated documentation files (the "Software"), to deal
|
||||||
|
; in the Software without restriction, including without limitation the rights
|
||||||
|
; to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
; copies of the Software, and to permit persons to whom the Software is
|
||||||
|
; furnished to do so, subject to the following conditions:
|
||||||
|
;
|
||||||
|
; The above copyright notice and this permission notice shall be included in all
|
||||||
|
; copies or substantial portions of the Software.
|
||||||
|
;
|
||||||
|
; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
; IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
; FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
; AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
; LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
; SOFTWARE.
|
||||||
|
|
||||||
|
%ifndef __INC_VIDEO
|
||||||
|
; Sets output to 80x25 16 color text mode via BIOS call
|
||||||
|
; also clears screen
|
||||||
|
; void SetTextMode(void)
|
||||||
|
ALIGN 4, db 0x90
|
||||||
|
SetTextMode:
|
||||||
|
.prolog:
|
||||||
|
__CDECL16_ENTRY
|
||||||
|
pushf
|
||||||
|
.func:
|
||||||
|
xor ah, ah ; Set Video mode BIOS function
|
||||||
|
mov al, 0x02 ; 16 color 80x25 Text mode
|
||||||
|
int 0x10 ; Call video interrupt
|
||||||
|
|
||||||
|
mov ah, 0x05 ; Select active display page BIOS function
|
||||||
|
xor al, al ; page 0
|
||||||
|
int 0x10 ; call video interrupt
|
||||||
|
.endp:
|
||||||
|
popf
|
||||||
|
__CDECL16_EXIT
|
||||||
|
ret
|
||||||
|
|
||||||
|
; disables blinking text mode cursor
|
||||||
|
ALIGN 4, db 0x90
|
||||||
|
disable_cursor:
|
||||||
|
__CDECL16_ENTRY
|
||||||
|
.func:
|
||||||
|
mov dx, 0x3D4
|
||||||
|
mov al, 0xA ; low cursor shape register
|
||||||
|
out dx, al
|
||||||
|
|
||||||
|
inc dx
|
||||||
|
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
|
||||||
|
ret
|
||||||
|
|
||||||
|
%endif
|
||||||
|
%define __INC_VIDEO
|
||||||
57
include/cdecl16.inc
Normal file
57
include/cdecl16.inc
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
; Copyright (c) 2024 Elaina Claus
|
||||||
|
;
|
||||||
|
; Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
; of this software and associated documentation files (the "Software"), to deal
|
||||||
|
; in the Software without restriction, including without limitation the rights
|
||||||
|
; to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
; copies of the Software, and to permit persons to whom the Software is
|
||||||
|
; furnished to do so, subject to the following conditions:
|
||||||
|
;
|
||||||
|
; The above copyright notice and this permission notice shall be included in all
|
||||||
|
; copies or substantial portions of the Software.
|
||||||
|
;
|
||||||
|
; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
; IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
; FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
; AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
; LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
; SOFTWARE.
|
||||||
|
%ifnmacro __CDECL16_ENTRY
|
||||||
|
%macro __CDECL16_ENTRY 0
|
||||||
|
push bp
|
||||||
|
mov bp, sp
|
||||||
|
sub sp, 0x10
|
||||||
|
|
||||||
|
push si
|
||||||
|
push di
|
||||||
|
push bx
|
||||||
|
%endmacro
|
||||||
|
%endif
|
||||||
|
|
||||||
|
%ifnmacro __CDECL16_EXIT
|
||||||
|
%macro __CDECL16_EXIT 0
|
||||||
|
pop bx
|
||||||
|
pop di
|
||||||
|
pop si
|
||||||
|
|
||||||
|
mov sp, bp
|
||||||
|
pop bp
|
||||||
|
%endmacro
|
||||||
|
%endif
|
||||||
|
|
||||||
|
%ifnmacro __CDECL16_CALLER_SAVE
|
||||||
|
%macro __CDECL16_CALLER_SAVE 0
|
||||||
|
push ax
|
||||||
|
push cx
|
||||||
|
push dx
|
||||||
|
%endmacro
|
||||||
|
%endif
|
||||||
|
|
||||||
|
%ifnmacro __CDECL16_CALLER_RESTORE
|
||||||
|
%macro __CDECL16_CALLER_RESTORE 0
|
||||||
|
pop dx
|
||||||
|
pop cx
|
||||||
|
pop ax
|
||||||
|
%endmacro
|
||||||
|
%endif
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
; Copyright (c) 2023 Elaina Claus
|
; Copyright (c) 2024 Elaina Claus
|
||||||
;
|
;
|
||||||
; Permission is hereby granted, free of charge, to any person obtaining a copy
|
; Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
; of this software and associated documentation files (the "Software"), to deal
|
; of this software and associated documentation files (the "Software"), to deal
|
||||||
@@ -18,8 +18,12 @@
|
|||||||
; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
; SOFTWARE.
|
; SOFTWARE.
|
||||||
|
|
||||||
|
%ifndef __INC_STEVIA_CONFIG
|
||||||
|
|
||||||
%define SECTOR_SIZE 512
|
%define SECTOR_SIZE 512
|
||||||
%define STAGE2_SECTOR_COUNT 0x40
|
%define STAGE2_SECTOR_COUNT 0x20
|
||||||
; 32 KiB
|
; 16 KiB
|
||||||
%define MAX_STAGE2_BYTES (SECTOR_SIZE * STAGE2_SECTOR_COUNT)
|
%define MAX_STAGE2_BYTES (SECTOR_SIZE * STAGE2_SECTOR_COUNT)
|
||||||
|
|
||||||
|
%endif
|
||||||
|
%define __INC_STEVIA_CONFIG
|
||||||
33
include/early_mem.inc
Executable file
33
include/early_mem.inc
Executable file
@@ -0,0 +1,33 @@
|
|||||||
|
; Copyright (c) 2024 Elaina Claus
|
||||||
|
;
|
||||||
|
; Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
; of this software and associated documentation files (the "Software"), to deal
|
||||||
|
; in the Software without restriction, including without limitation the rights
|
||||||
|
; to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
; copies of the Software, and to permit persons to whom the Software is
|
||||||
|
; furnished to do so, subject to the following conditions:
|
||||||
|
;
|
||||||
|
; The above copyright notice and this permission notice shall be included in all
|
||||||
|
; copies or substantial portions of the Software.
|
||||||
|
;
|
||||||
|
; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
; IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
; FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
; AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
; LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
; SOFTWARE.
|
||||||
|
|
||||||
|
%ifndef __INC_EARLY_MEM
|
||||||
|
|
||||||
|
;PhysicalAddress = Segment * 16 + Offset
|
||||||
|
%define SEG_TO_LINEAR(s,o) ((s << 4) + o)
|
||||||
|
|
||||||
|
; Offset = physical / (Segment * 16)
|
||||||
|
%define LINEAR_TO_OFFSET(p,s) ((p / (s << 4)))
|
||||||
|
|
||||||
|
; Seg = (physical - offset) / 16
|
||||||
|
%define LINEAR_TO_SEGMENT(p,o) ((p - o) >> 4)
|
||||||
|
|
||||||
|
%endif
|
||||||
|
%define __INC_EARLY_MEM
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
; Copyright (c) 2023 Elaina Claus
|
; Copyright (c) 2024 Elaina Claus
|
||||||
;
|
;
|
||||||
; Permission is hereby granted, free of charge, to any person obtaining a copy
|
; Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
; of this software and associated documentation files (the "Software"), to deal
|
; of this software and associated documentation files (the "Software"), to deal
|
||||||
@@ -18,9 +18,11 @@
|
|||||||
; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
; SOFTWARE.
|
; SOFTWARE.
|
||||||
|
|
||||||
|
%ifndef __INC_ENTRY
|
||||||
|
|
||||||
; 8KiB from 0x2500 -> 0x500
|
%define MBR_ENTRY 0x8C00
|
||||||
%define STACK_START 0x2500
|
%define VBR_ENTRY 0x7C00
|
||||||
%define MBR_ENTRY 0x7A00
|
%define STAGE2_ENTRY 0x0500
|
||||||
%define VBR_ENTRY 0x7C00
|
|
||||||
%define STAGE2_ENTRY 0x7E00
|
%endif
|
||||||
|
%define __INC_ENTRY
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
; Copyright (c) 2023 Elaina Claus
|
; Copyright (c) 2024 Elaina Claus
|
||||||
;
|
;
|
||||||
; Permission is hereby granted, free of charge, to any person obtaining a copy
|
; Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
; of this software and associated documentation files (the "Software"), to deal
|
; of this software and associated documentation files (the "Software"), to deal
|
||||||
@@ -18,6 +18,7 @@
|
|||||||
; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
; SOFTWARE.
|
; SOFTWARE.
|
||||||
|
|
||||||
|
%ifndef __INC_ERROR_CODES
|
||||||
|
|
||||||
; Errors
|
; Errors
|
||||||
; 12 Errors, 5 in use
|
; 12 Errors, 5 in use
|
||||||
@@ -32,7 +33,7 @@
|
|||||||
%define MBR_ERROR_RESERVED_i 'i'
|
%define MBR_ERROR_RESERVED_i 'i'
|
||||||
%define MBR_ERROR_RESERVED_j 'j'
|
%define MBR_ERROR_RESERVED_j 'j'
|
||||||
%define MBR_ERROR_RESERVED_k 'k'
|
%define MBR_ERROR_RESERVED_k 'k'
|
||||||
%define MBR_ERROR_RESERVED_l 'l'
|
%define MBR_ERROR_INT13h_EREAD_ERR 'l'
|
||||||
|
|
||||||
; 12 Error
|
; 12 Error
|
||||||
%define VBR_ERROR_WRONG_FAT_SIZE 'm'
|
%define VBR_ERROR_WRONG_FAT_SIZE 'm'
|
||||||
@@ -48,7 +49,7 @@
|
|||||||
%define VBR_ERROR_RESERVED_w 'w'
|
%define VBR_ERROR_RESERVED_w 'w'
|
||||||
%define VBR_ERROR_RESERVED_x 'x'
|
%define VBR_ERROR_RESERVED_x 'x'
|
||||||
|
|
||||||
; 26 errors, 8 in use
|
; 22 errors, 8 in use
|
||||||
%define STAGE2_A20_FAILED 'A'
|
%define STAGE2_A20_FAILED 'A'
|
||||||
%define STAGE2_SIGNATURE_MISSING 'B'
|
%define STAGE2_SIGNATURE_MISSING 'B'
|
||||||
%define STAGE2_MM_E820_NO_SUPPORT 'C'
|
%define STAGE2_MM_E820_NO_SUPPORT 'C'
|
||||||
@@ -59,9 +60,9 @@
|
|||||||
%define STAGE2_FAT32_INIT_ERROR 'H'
|
%define STAGE2_FAT32_INIT_ERROR 'H'
|
||||||
%define STAGE2_FAT32_NO_FILE 'I'
|
%define STAGE2_FAT32_NO_FILE 'I'
|
||||||
%define STAGE2_FAT32_END_OF_CHAIN 'J'
|
%define STAGE2_FAT32_END_OF_CHAIN 'J'
|
||||||
%define STAGE2_ERROR_RESERVED_K 'K'
|
%define STAGE2_FAT32_NCLUS_CFDIVZ 'K'
|
||||||
%define STAGE2_ERROR_RESERVED_L 'L'
|
%define STAGE2_FAT32_CLS2LBA_CF 'L'
|
||||||
%define STAGE2_ERROR_RESERVED_M 'M'
|
%define STAGE2_FAT32_INIT_CF 'M'
|
||||||
%define STAGE2_ERROR_RESERVED_N 'N'
|
%define STAGE2_ERROR_RESERVED_N 'N'
|
||||||
%define STAGE2_ERROR_RESERVED_O 'O'
|
%define STAGE2_ERROR_RESERVED_O 'O'
|
||||||
%define STAGE2_ERROR_RESERVED_P 'P'
|
%define STAGE2_ERROR_RESERVED_P 'P'
|
||||||
@@ -71,30 +72,12 @@
|
|||||||
%define STAGE2_ERROR_RESERVED_T 'T'
|
%define STAGE2_ERROR_RESERVED_T 'T'
|
||||||
%define STAGE2_ERROR_RESERVED_U 'U'
|
%define STAGE2_ERROR_RESERVED_U 'U'
|
||||||
%define STAGE2_ERROR_RESERVED_V 'V'
|
%define STAGE2_ERROR_RESERVED_V 'V'
|
||||||
%define STAGE2_ERROR_RESERVED_W 'W'
|
|
||||||
%define STAGE2_ERROR_RESERVED_X 'X'
|
|
||||||
%define STAGE2_ERROR_RESERVED_Y 'Y'
|
|
||||||
%define STAGE2_ERROR_RESERVED_Z 'Z'
|
|
||||||
|
|
||||||
|
; for development only, specific errors should be above.
|
||||||
|
%define STEVIA_DEBUG_OK 'W'
|
||||||
|
%define STEVIA_DEBUG_ERR 'X'
|
||||||
|
%define STEVIA_DEBUG_UNIMPLEMENTED 'Y'
|
||||||
|
%define STEVIA_DEBUG_HALT 'Z'
|
||||||
|
|
||||||
%macro ERROR 1
|
%endif
|
||||||
mov al, %1
|
%define __INC_ERROR_CODES
|
||||||
jmp error
|
|
||||||
%endmacro
|
|
||||||
|
|
||||||
; pass error as ascii character in al, errors a-zA-Z or 0-9
|
|
||||||
error:
|
|
||||||
; color 0x4F is white on red
|
|
||||||
; fs = 0xb800 => fs:0x0000 = 0xb8000
|
|
||||||
mov dx, 0xB800
|
|
||||||
mov fs, dx
|
|
||||||
|
|
||||||
; the characters are two bytes in the order of 0xb8000: byte c, byte attribute
|
|
||||||
; since x86 is le, we store the attribute in the MSB of dx
|
|
||||||
mov dh, 0x4F
|
|
||||||
mov dl, al
|
|
||||||
mov word [fs:0x0000], dx
|
|
||||||
|
|
||||||
.stop:
|
|
||||||
hlt
|
|
||||||
jmp short error.stop
|
|
||||||
323
include/fat32/FAT32_SYS.inc
Normal file
323
include/fat32/FAT32_SYS.inc
Normal file
@@ -0,0 +1,323 @@
|
|||||||
|
; Copyright (c) 2024 Elaina Claus
|
||||||
|
;
|
||||||
|
; Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
; of this software and associated documentation files (the "Software"), to deal
|
||||||
|
; in the Software without restriction, including without limitation the rights
|
||||||
|
; to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
; copies of the Software, and to permit persons to whom the Software is
|
||||||
|
; furnished to do so, subject to the following conditions:
|
||||||
|
;
|
||||||
|
; The above copyright notice and this permission notice shall be included in all
|
||||||
|
; copies or substantial portions of the Software.
|
||||||
|
;
|
||||||
|
; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
; IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
; FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
; AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
; LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
; SOFTWARE.
|
||||||
|
|
||||||
|
%ifndef __INC_FAT32_SYS
|
||||||
|
|
||||||
|
%include "partition_table.inc"
|
||||||
|
%include "fat32/bpb_offset_bx.inc"
|
||||||
|
%include "fat32/fat32_structures.inc"
|
||||||
|
|
||||||
|
ALIGN 4, db 0x90
|
||||||
|
InitFATDriver:
|
||||||
|
__CDECL16_ENTRY
|
||||||
|
.func:
|
||||||
|
mov ax, FAT32_State_t_size
|
||||||
|
push ax ; length of fat32_state structure
|
||||||
|
xor ax, ax
|
||||||
|
push ax ; init fat32_state with zero
|
||||||
|
mov ax, fat32_state
|
||||||
|
push ax ; address of structure
|
||||||
|
call kmemset
|
||||||
|
sub sp, 0x6
|
||||||
|
|
||||||
|
.calc_active_part:
|
||||||
|
mov ax, word [partition_offset]
|
||||||
|
|
||||||
|
mov dx, partition_table
|
||||||
|
add dx, ax ; dx points to the partition that was booted from
|
||||||
|
mov bx, dx ; set bx, should point at our partition
|
||||||
|
|
||||||
|
mov eax, dword [bx + PartEntry_t.lba_start]
|
||||||
|
mov dword [fat32_state + FAT32_State_t.active_drive_lba_32], eax
|
||||||
|
|
||||||
|
.calc_first_fat:
|
||||||
|
movzx eax, word [fat32_bpb + FAT32_bpb_t.reserved_sectors_16] ; first fat from start of partition
|
||||||
|
add eax, dword [fat32_state + FAT32_State_t.active_drive_lba_32] ; calculate offset from start of drive
|
||||||
|
|
||||||
|
mov dword [fat32_state + FAT32_State_t.first_fat_sector_32], eax
|
||||||
|
.calc_total_fat:
|
||||||
|
mov ebx, dword [fat32_ebpb + FAT32_ebpb_t.sectors_per_fat_32]
|
||||||
|
movzx eax, byte [fat32_bpb + FAT32_bpb_t.fat_count_8]
|
||||||
|
mul ebx ; result in EDX:EAX, CF set on > 32bit return value
|
||||||
|
jc InitFATDriver.error ; as a catch for unhandled overflow, just error if value is greater than 32bits
|
||||||
|
|
||||||
|
mov dword [fat32_state + FAT32_State_t.fat_size_32], eax
|
||||||
|
.calc_first_data:
|
||||||
|
mov edx, dword [fat32_state + FAT32_State_t.first_fat_sector_32]
|
||||||
|
add eax, edx
|
||||||
|
|
||||||
|
mov dword [fat32_state + FAT32_State_t.first_data_sector_32], eax
|
||||||
|
.get_first_root_dir:
|
||||||
|
mov eax, [fat32_ebpb + FAT32_ebpb_t.root_dir_cluster_32]
|
||||||
|
mov dword [fat32_state + FAT32_State_t.first_root_dir_sector_32], eax ; this only works when 1 cluster = 1 sector
|
||||||
|
mov dword [fat32_state + FAT32_State_t.active_dir_cluster_32], eax
|
||||||
|
|
||||||
|
.endp:
|
||||||
|
__CDECL16_EXIT
|
||||||
|
ret
|
||||||
|
.error:
|
||||||
|
ERROR STAGE2_FAT32_INIT_CF
|
||||||
|
|
||||||
|
; this involves using the low memory buffer for the bios call and moving the file sector by sector to high memory
|
||||||
|
;
|
||||||
|
; SFN is a 8.3 file name, all uppercase, and padded with spaces
|
||||||
|
; do not add a null byte to the end of the string
|
||||||
|
; eg. kernel.bin == "KERNEL BIN"
|
||||||
|
;
|
||||||
|
; returns first cluster of file if found
|
||||||
|
; halts/errors if file is not found
|
||||||
|
; uint32_t SearchFATDIR(uint8_t* SFN);
|
||||||
|
ALIGN 4, db 0x90
|
||||||
|
SearchFATDIR:
|
||||||
|
__CDECL16_ENTRY
|
||||||
|
.file_lookup:
|
||||||
|
print_string SearchFATDIR_INFO_cstr
|
||||||
|
|
||||||
|
.load_first_dir:
|
||||||
|
mov eax, dword [fat32_state + FAT32_State_t.active_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)
|
||||||
|
add sp, 0x8
|
||||||
|
|
||||||
|
mov si, dir_buffer
|
||||||
|
jmp SearchFATDIR.empty_dir_entry
|
||||||
|
|
||||||
|
.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 [fat32_state + FAT32_State_t.active_dir_cluster_32]
|
||||||
|
push dword eax
|
||||||
|
call NextCluster ; uint32_t NextCluster(uint32_t active_cluster);
|
||||||
|
add sp, 0x4
|
||||||
|
|
||||||
|
cmp eax, 0x0fff_fff7
|
||||||
|
;je SearchFATDIR.bad_cluster ; TODO: Implement Bad cluster checks
|
||||||
|
jb SearchFATDIR.load_next_dir_next_OK
|
||||||
|
ERROR STAGE2_FAT32_END_OF_CHAIN
|
||||||
|
|
||||||
|
.load_next_dir_next_OK:
|
||||||
|
; load 512 bytes of directory entries from data sector
|
||||||
|
mov eax, [fat32_state + FAT32_State_t.active_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)
|
||||||
|
sub sp, 0x8
|
||||||
|
.empty_dir_entry:
|
||||||
|
; check for 0x0 in first byte, if true then there are no more files
|
||||||
|
; if true we did not find the file, we should error here
|
||||||
|
cmp byte [si], 0
|
||||||
|
jne SearchFATDIR.unused_dir_entry
|
||||||
|
ERROR STAGE2_FAT32_NO_FILE
|
||||||
|
|
||||||
|
.unused_dir_entry:
|
||||||
|
; check for 0xe5 and 0x05 in first byte, if true then this entry is unused, but it is not the last entry.
|
||||||
|
cmp byte [si], 0xe5
|
||||||
|
je SearchFATDIR.next_entry
|
||||||
|
|
||||||
|
cmp byte [si], 0x05
|
||||||
|
je SearchFATDIR.next_entry
|
||||||
|
jmp SearchFATDIR.parse_dir
|
||||||
|
|
||||||
|
.next_entry:
|
||||||
|
; increment offset by 32 bytes to read the next entry in this set of dir entries
|
||||||
|
; if we are at the end of the buffer, then load the next buffer
|
||||||
|
add si, 0x20 ; 32 bytes
|
||||||
|
|
||||||
|
mov ax, dir_buffer
|
||||||
|
add ax, 0x1FF ; 512 - 1 bytes
|
||||||
|
cmp si, ax
|
||||||
|
jae SearchFATDIR.load_next_dir
|
||||||
|
jmp SearchFATDIR.empty_dir_entry
|
||||||
|
|
||||||
|
.parse_dir:
|
||||||
|
print_string MaybeFound_Boot_INFO_cstr
|
||||||
|
.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
|
||||||
|
cmp byte [si+11], 0x0F
|
||||||
|
je SearchFATDIR.next_entry
|
||||||
|
.sfn_file_name_check:
|
||||||
|
push si
|
||||||
|
push di
|
||||||
|
|
||||||
|
mov cx, 0xA ; max of 11 filename length of 11 characters
|
||||||
|
; si points to the start of the current directory entry
|
||||||
|
mov di, BootTarget_str ; current memory location (8.3 name is at offset 0)
|
||||||
|
repe cmpsb ; compare the strings
|
||||||
|
|
||||||
|
pop di
|
||||||
|
pop si
|
||||||
|
jne SearchFATDIR.next_entry
|
||||||
|
|
||||||
|
.sfn_entry_found:
|
||||||
|
mov ax, [si + FAT32_SFN_t.cluster_16_high]
|
||||||
|
shl eax, 16
|
||||||
|
mov ax, [si + FAT32_SFN_t.cluster_16_low]
|
||||||
|
; eax == first cluster of file
|
||||||
|
.endp:
|
||||||
|
__CDECL16_EXIT
|
||||||
|
ret
|
||||||
|
|
||||||
|
; BUG: this function needs review
|
||||||
|
; uint32_t NextCluster(uint32_t active_cluster);
|
||||||
|
; 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
|
||||||
|
ALIGN 4, db 0x90
|
||||||
|
NextCluster:
|
||||||
|
__CDECL16_ENTRY
|
||||||
|
.func:
|
||||||
|
print_string NextFATCluster_INFO_cstr
|
||||||
|
mov edx, dword [bp + 4]
|
||||||
|
mov si, fat32_nc_data ; instead of push/pop and moving the data back
|
||||||
|
mov di, fat32_bpb ; load si & di then use xchg
|
||||||
|
.calc_offset:
|
||||||
|
; fat_offset = active_cluster * 4
|
||||||
|
mov eax, 4
|
||||||
|
mul edx
|
||||||
|
jc NextCluster.error_cfdivz
|
||||||
|
mov dword [si + FAT32_NextClusterData_t.fat_offset], eax ; move lower 32 bits to fat offset
|
||||||
|
|
||||||
|
.calc_fat_sector:
|
||||||
|
; fat_sector = first_fat_sector + (fat_offset / sector_size)
|
||||||
|
; entry_offset = fat_offset % sector_size
|
||||||
|
mov edx, 0xffff_0000
|
||||||
|
and edx, eax
|
||||||
|
shr edx, 16
|
||||||
|
|
||||||
|
xchg si, di ; switch to fat32_bpb in si
|
||||||
|
mov cx, word [si + FAT32_bpb_t.bytes_per_sector_16]
|
||||||
|
xchg si, di
|
||||||
|
|
||||||
|
cmp edx, 0
|
||||||
|
je NextCluster.error_cfdivz
|
||||||
|
div cx ; DX:AX / cx = fat_sector - first_fat_sector in AX
|
||||||
|
; DX = remainder (fat_offset mod sector_size)
|
||||||
|
|
||||||
|
mov ecx, 0x0000_ffff
|
||||||
|
and edx, ecx
|
||||||
|
mov dword [si + FAT32_NextClusterData_t.entry_offset], edx
|
||||||
|
|
||||||
|
xchg si, di ; switch to fat32_bpb in si
|
||||||
|
mov ecx, dword [si + FAT32_State_t.first_fat_sector_32]
|
||||||
|
xchg si, di
|
||||||
|
|
||||||
|
mov edx, 0x0000ffff
|
||||||
|
and eax, edx
|
||||||
|
add eax, ecx ; fat_sector + first_fat_sector
|
||||||
|
mov dword [si + FAT32_NextClusterData_t.fat_sector], eax
|
||||||
|
.load_fat_table:
|
||||||
|
xor ax, ax
|
||||||
|
mov al, byte [boot_drive]
|
||||||
|
push ax
|
||||||
|
|
||||||
|
mov ax, 0x1
|
||||||
|
push ax
|
||||||
|
|
||||||
|
; load correct fat
|
||||||
|
mov eax, dword [si + FAT32_NextClusterData_t.fat_sector]
|
||||||
|
push dword eax
|
||||||
|
|
||||||
|
mov ax, fat_buffer
|
||||||
|
push ax
|
||||||
|
|
||||||
|
xor ax, ax
|
||||||
|
push ax
|
||||||
|
call read_disk_raw
|
||||||
|
add sp, 0xC
|
||||||
|
; uint8_t read_stage2_raw(uint16_t buf_segment, uint16_t buf_offset,
|
||||||
|
; uint32_t lba,
|
||||||
|
; uint16_t count, uint16_t drive_num)
|
||||||
|
.read_cluster:
|
||||||
|
; 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]
|
||||||
|
.endp:
|
||||||
|
__CDECL16_EXIT
|
||||||
|
ret
|
||||||
|
.error_cfdivz:
|
||||||
|
ERROR STAGE2_FAT32_NCLUS_CFDIVZ
|
||||||
|
|
||||||
|
; uint32_t ClusterToLBA(uint32_t cluster)
|
||||||
|
ALIGN 4, db 0x90
|
||||||
|
ClusterToLBA:
|
||||||
|
__CDECL16_ENTRY
|
||||||
|
.func:
|
||||||
|
mov dword eax, [bp + 4]
|
||||||
|
sub eax, 2
|
||||||
|
movzx edx, byte [fat32_bpb + FAT32_bpb_t.sectors_per_cluster_8]
|
||||||
|
mul edx
|
||||||
|
jc ClusterToLBA.error
|
||||||
|
add eax, dword [fat32_state + FAT32_State_t.first_data_sector_32]
|
||||||
|
; eax contains the LBA now
|
||||||
|
.endp:
|
||||||
|
__CDECL16_EXIT
|
||||||
|
ret
|
||||||
|
.error:
|
||||||
|
ERROR STAGE2_FAT32_CLS2LBA_CF
|
||||||
|
|
||||||
|
; bp - 2 - byte boot_drive
|
||||||
|
; uint8_t ReadFATCluster(uint16_t seg, uint16_t offset, uint32_t cluster)
|
||||||
|
ALIGN 4, db 0x90
|
||||||
|
ReadFATCluster:
|
||||||
|
__CDECL16_ENTRY
|
||||||
|
.func:
|
||||||
|
print_string ReadFATCluster_INFO_cstr
|
||||||
|
|
||||||
|
xor ax, ax
|
||||||
|
mov al, byte [boot_drive]
|
||||||
|
push ax
|
||||||
|
|
||||||
|
mov ax, 0x1 ; count = 1
|
||||||
|
push ax
|
||||||
|
|
||||||
|
mov eax, dword [bp + 8]
|
||||||
|
push dword eax
|
||||||
|
call ClusterToLBA
|
||||||
|
add sp, 0x4
|
||||||
|
; eax contains the LBA now
|
||||||
|
push dword eax ; lba = ClusterToLBA(..)
|
||||||
|
|
||||||
|
mov ax, fat_buffer ; offset = fat_buffer (in mem.inc)
|
||||||
|
push ax
|
||||||
|
|
||||||
|
xor ax, ax ; segment = 0x0000, our buffer is in the first 64 KiB
|
||||||
|
push ax
|
||||||
|
; uint8_t read_stage2_raw(uint16_t buf_segment, uint16_t buf_offset,
|
||||||
|
; uint32_t lba,
|
||||||
|
; uint16_t count, uint16_t drive_num)
|
||||||
|
call read_disk_raw
|
||||||
|
add sp, 0xC
|
||||||
|
.endp:
|
||||||
|
__CDECL16_EXIT
|
||||||
|
ret
|
||||||
|
|
||||||
|
%endif
|
||||||
|
%define __INC_FAT32_SYS
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
; Copyright (c) 2023 Elaina Claus
|
; Copyright (c) 2024 Elaina Claus
|
||||||
;
|
;
|
||||||
; Permission is hereby granted, free of charge, to any person obtaining a copy
|
; Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
; of this software and associated documentation files (the "Software"), to deal
|
; of this software and associated documentation files (the "Software"), to deal
|
||||||
@@ -18,6 +18,7 @@
|
|||||||
; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
; SOFTWARE.
|
; SOFTWARE.
|
||||||
|
|
||||||
|
%ifndef __INC_BPD_OFFSET_BX
|
||||||
|
|
||||||
; BPB Information
|
; BPB Information
|
||||||
; Off. Hex Off. Size Description
|
; Off. Hex Off. Size Description
|
||||||
@@ -88,4 +89,7 @@
|
|||||||
%define bsVolumeSerial bx+0x43
|
%define bsVolumeSerial bx+0x43
|
||||||
%define bsVolumeLabel bx+0x47
|
%define bsVolumeLabel bx+0x47
|
||||||
%define bsSystemIdent bx+0x52
|
%define bsSystemIdent bx+0x52
|
||||||
;-- End EBPB
|
;-- End EBPB
|
||||||
|
|
||||||
|
%endif
|
||||||
|
%define __INC_BPD_OFFSET_BX
|
||||||
@@ -18,6 +18,7 @@
|
|||||||
; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
; SOFTWARE.
|
; SOFTWARE.
|
||||||
|
|
||||||
|
%ifndef __INC_FAT32_STRUCT
|
||||||
|
|
||||||
; ## FAT32 Info ##
|
; ## FAT32 Info ##
|
||||||
; total_sectors = bsSectorsHuge
|
; total_sectors = bsSectorsHuge
|
||||||
@@ -62,6 +63,7 @@
|
|||||||
; resulting in a value which does not fit in the Number of Sectors entry at 0x13.
|
; resulting in a value which does not fit in the Number of Sectors entry at 0x13.
|
||||||
|
|
||||||
struc FAT32_bpb_t
|
struc FAT32_bpb_t
|
||||||
|
.reserved_init resb 3
|
||||||
.ident_8 resb 8
|
.ident_8 resb 8
|
||||||
.bytes_per_sector_16 resb 2
|
.bytes_per_sector_16 resb 2
|
||||||
.sectors_per_cluster_8 resb 1
|
.sectors_per_cluster_8 resb 1
|
||||||
@@ -230,4 +232,5 @@ endstruc
|
|||||||
; LFN == RO | HIDDEN | SYSTEM | VOLID == 0x0F
|
; LFN == RO | HIDDEN | SYSTEM | VOLID == 0x0F
|
||||||
%define FAT32_ATTR_LFN 0x0F
|
%define FAT32_ATTR_LFN 0x0F
|
||||||
|
|
||||||
|
%endif
|
||||||
|
%define __INC_FAT32_STRUCT
|
||||||
@@ -1,213 +0,0 @@
|
|||||||
; Copyright (c) 2023 Elaina Claus
|
|
||||||
;
|
|
||||||
; Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
; of this software and associated documentation files (the "Software"), to deal
|
|
||||||
; in the Software without restriction, including without limitation the rights
|
|
||||||
; to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
; copies of the Software, and to permit persons to whom the Software is
|
|
||||||
; furnished to do so, subject to the following conditions:
|
|
||||||
;
|
|
||||||
; The above copyright notice and this permission notice shall be included in all
|
|
||||||
; copies or substantial portions of the Software.
|
|
||||||
;
|
|
||||||
; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
; IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
; FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
; AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
; LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
; SOFTWARE.
|
|
||||||
|
|
||||||
|
|
||||||
; ## Generic Low mem map (from osdev wiki) ##
|
|
||||||
; start end size type description
|
|
||||||
; Low Memory (the first MiB)
|
|
||||||
; 0x00000000 0x000003FF 1 KiB RAM - partially unusable Real Mode IVT (Interrupt Vector Table)
|
|
||||||
; 0x00000400 0x000004FF 256 bytes RAM - partially unusable BDA (BIOS data area)
|
|
||||||
; 0x00000500 0x00007BFF almost 30 KiB RAM - free for use Conventional memory
|
|
||||||
; 0x00007C00 0x00007DFF 512 bytes RAM - partially unusable OS BootSector
|
|
||||||
; 0x00007E00 0x0007FFFF 480.5 KiB RAM - free for use Conventional memory
|
|
||||||
; 0x00080000 0x0009FFFF 128 KiB RAM - partially unusable EBDA (Extended BIOS Data Area)
|
|
||||||
; 0x000A0000 0x000FFFFF 384 KiB various (unusable) Video memory, ROM Area
|
|
||||||
|
|
||||||
; ## A rough overview of high mem ##
|
|
||||||
; Idealy this needs to be probed with the E820 functions
|
|
||||||
; # Start # End # size # description
|
|
||||||
;
|
|
||||||
; 0x00100000 0x00EFFFFF 0x00E00000 (14 MiB) RAM -- free for use (if it exists) Extended memory
|
|
||||||
; 0x00F00000 0x00FFFFFF 0x00100000 (1 MiB) Possible memory mapped hardware ISA Memory Hole 15-16MB
|
|
||||||
; 0x01000000 ???????? ??? (whatever exists) RAM -- free for use More Extended memory
|
|
||||||
; 0xC0000000 (sometimes) 0xFFFFFFFF 0x40000000 (1 GiB) Memory mapped PCI devices, PnP NVRAM?, IO APIC/s, local APIC/s, BIOS, ...
|
|
||||||
; 0x0000000100000000 ??? ??? (whatever exists) RAM -- free for use (PAE/64bit)/More Extended memory
|
|
||||||
; ???????????????? ??? ??? Potentially usable for memory mapped PCI devices in modern hardware (but typically not, due to backward compatibility)
|
|
||||||
|
|
||||||
; 0x2700 -> 0x28FF
|
|
||||||
%define disk_buffer 0x2700
|
|
||||||
; 0x2900 -> 0x2AFF
|
|
||||||
%define fat_buffer 0x2900
|
|
||||||
; 0x2B00 -> 0x2CFF
|
|
||||||
%define dir_buffer 0x2B00
|
|
||||||
|
|
||||||
; copy of partition table, 72 bytes
|
|
||||||
%define partition_table 0x3000
|
|
||||||
%define partition_table_SIZE 72
|
|
||||||
|
|
||||||
; copy of FAT32 BPB, 33 bytes (+1 to the next value to align to uint16_t)
|
|
||||||
;0x3048
|
|
||||||
%define fat32_bpb 0x3050
|
|
||||||
%define fat32_bpb_SIZE 33
|
|
||||||
|
|
||||||
; copy of FAT32 EBPB, 54 bytes
|
|
||||||
;0x306A
|
|
||||||
%define fat32_ebpb 0x3070
|
|
||||||
%define fat32_ebpb_SIZE 54
|
|
||||||
|
|
||||||
; FAT32 FSInfo, 512 bytes
|
|
||||||
;0x30A2
|
|
||||||
%define fat32_fsinfo 0x30B0
|
|
||||||
%define fat32_fsinfo_SIZE 512
|
|
||||||
|
|
||||||
; some stored state for the fat32 driver
|
|
||||||
;0x32A2
|
|
||||||
%define fat32_state 0x32B0
|
|
||||||
%define fat32_state_SIZE 32
|
|
||||||
|
|
||||||
; next free space is 0x32D0
|
|
||||||
%define fat32_nc_data 0x32D0
|
|
||||||
%define fat32_nc_data_size 16
|
|
||||||
|
|
||||||
; lba_packet for raw_disk_read
|
|
||||||
%define lba_packet 0x4000
|
|
||||||
|
|
||||||
%define BIOSMemoryMap 0x4200
|
|
||||||
%define SteviaInfo 0x4400
|
|
||||||
|
|
||||||
|
|
||||||
; High memory addresses for loading kernel (for use with unreal mode and 32bit override)
|
|
||||||
|
|
||||||
; file load buffer at 16MB
|
|
||||||
%define HMEM_load_buffer 0x1000000
|
|
||||||
|
|
||||||
|
|
||||||
;PhysicalAddress = Segment * 16 + Offset
|
|
||||||
%define SEG_TO_LINEAR(s,o) ((s << 4) + o)
|
|
||||||
|
|
||||||
; Offset = physical / (Segment * 16)
|
|
||||||
%define LINEAR_TO_OFFSET(p,s) ((p / (s << 4)))
|
|
||||||
|
|
||||||
; Seg = (physical - offset) / 16
|
|
||||||
%define LINEAR_TO_SEGMENT(p,o) ((p - o) >> 4)
|
|
||||||
|
|
||||||
; create normalized linear addres from seg:off (16:4)
|
|
||||||
; Segement = linear >> 4 (top 16 bits)
|
|
||||||
; offset = linear & 0x0F (low 4 bits)
|
|
||||||
|
|
||||||
; 20 bytes, passed to loaded kernel
|
|
||||||
struc SteviaInfoStruct_t
|
|
||||||
.MemoryMapPtr resd 1
|
|
||||||
.MemoryMapEntries resd 1
|
|
||||||
.BPBDataPtr resd 1
|
|
||||||
.EBPBDataPtr resd 1
|
|
||||||
endstruc
|
|
||||||
|
|
||||||
; Address Range Descriptor Structure
|
|
||||||
;
|
|
||||||
; Offset in Bytes Name Description
|
|
||||||
; 0 BaseAddrLow u32 - Low 32 Bits of Base Address
|
|
||||||
; 4 BaseAddrHigh u32 - High 32 Bits of Base Address
|
|
||||||
; 8 LengthLow u32 - Low 32 Bits of Length in Bytes
|
|
||||||
; 12 LengthHigh u32 - High 32 Bits of Length in Bytes
|
|
||||||
; 16 Type u32 - Address type of this range.
|
|
||||||
; 20 ExtType u32 - ACPI 3.0 extended type
|
|
||||||
struc AddressRangeDescStruct_t
|
|
||||||
.BaseAddrLow resd 1
|
|
||||||
.BaseAddrHigh resd 1
|
|
||||||
.LengthLow resd 1
|
|
||||||
.LengthHigh resd 1
|
|
||||||
.Type resd 1
|
|
||||||
.ExtType resd 1
|
|
||||||
endstruc
|
|
||||||
|
|
||||||
; moves argument into eax then pushes lower 16bits then upper 16 bits of of argument to stack
|
|
||||||
; eax is clobbered
|
|
||||||
%macro PUSH_DWORD 1
|
|
||||||
mov eax, %1
|
|
||||||
push ax
|
|
||||||
shr eax, 16
|
|
||||||
push ax
|
|
||||||
%endmacro
|
|
||||||
|
|
||||||
; same as PUSH_DWORD except no arguments, pushes EAX directly
|
|
||||||
%macro PUSH_DWORD_EAX 0
|
|
||||||
push ax
|
|
||||||
shr eax, 16
|
|
||||||
push ax
|
|
||||||
%endmacro
|
|
||||||
|
|
||||||
; pops upper 16bits then lower 16bits into eax
|
|
||||||
; eax is clobbered
|
|
||||||
%macro POP_DWORD_EAX 0
|
|
||||||
xor eax, eax
|
|
||||||
pop ax
|
|
||||||
shl eax, 16
|
|
||||||
pop ax
|
|
||||||
%endmacro
|
|
||||||
|
|
||||||
; moves data on stack referenced by bp to eax
|
|
||||||
; stack must be organized as follows (tl;dr push lower 16bits first ie. PUSH_DWORD macro)
|
|
||||||
; MOV_DWORD_EAX 2
|
|
||||||
; STACK TOP (0x0)
|
|
||||||
; upper_uint16 [bp-4]
|
|
||||||
; lower_uint16 [bp-2]
|
|
||||||
; --- [bp] ---
|
|
||||||
; ...
|
|
||||||
; STACK BOTTOM
|
|
||||||
;
|
|
||||||
; first argument == starting offset from bp for lower 16bits
|
|
||||||
%macro MOV_DWORD_EAX 1
|
|
||||||
mov ax, [bp-(%1+2)]
|
|
||||||
shl eax, 16
|
|
||||||
mov ax, [bp-%1]
|
|
||||||
; eax contains dword from stack
|
|
||||||
%endmacro
|
|
||||||
|
|
||||||
%macro DEBUG_HCF 0
|
|
||||||
DEBUG_LOOP:
|
|
||||||
hlt
|
|
||||||
jmp short DEBUG_LOOP
|
|
||||||
%endmacro
|
|
||||||
|
|
||||||
|
|
||||||
; uint8_t* kmemset(void* dest, uint8_t val, size_t len);
|
|
||||||
kmemset:
|
|
||||||
push di ; function uses di, so save it.
|
|
||||||
|
|
||||||
mov cx, [bp - 2] ; size_t len
|
|
||||||
mov al, [bp - 4] ; uint8_t val
|
|
||||||
mov di, [bp - 6] ; void * ptr
|
|
||||||
|
|
||||||
cld
|
|
||||||
rep stosb
|
|
||||||
.endf:
|
|
||||||
mov ax, [bp - 6] ; return pointer to dest
|
|
||||||
pop di ; restore di
|
|
||||||
ret
|
|
||||||
|
|
||||||
; uint8_t* kmemset(uint8_t* dest, uint8_t* src, size_t len);
|
|
||||||
; not overlap safe
|
|
||||||
kmemcpy:
|
|
||||||
push di
|
|
||||||
push si ; di, si are callee save
|
|
||||||
|
|
||||||
mov cx, [bp - 2] ; length
|
|
||||||
mov si, [bp - 4] ; source
|
|
||||||
mov di, [bp - 6] ; dest
|
|
||||||
|
|
||||||
cld ; ensure we are incrementing
|
|
||||||
rep movsb
|
|
||||||
|
|
||||||
.endf:
|
|
||||||
mov ax, [bp - 6] ; return pointer to dest
|
|
||||||
pop si
|
|
||||||
pop di
|
|
||||||
ret
|
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
; Copyright (c) 2023 Elaina Claus
|
; Copyright (c) 2024 Elaina Claus
|
||||||
;
|
;
|
||||||
; Permission is hereby granted, free of charge, to any person obtaining a copy
|
; Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
; of this software and associated documentation files (the "Software"), to deal
|
; of this software and associated documentation files (the "Software"), to deal
|
||||||
@@ -18,6 +18,8 @@
|
|||||||
; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
; SOFTWARE.
|
; SOFTWARE.
|
||||||
|
|
||||||
|
%ifndef __INC_PART_TABLE
|
||||||
|
|
||||||
; Partition table entry format
|
; Partition table entry format
|
||||||
; Off. Size. Description
|
; Off. Size. Description
|
||||||
;0x00 1 Drive attributes (bit 7 set = active or bootable)
|
;0x00 1 Drive attributes (bit 7 set = active or bootable)
|
||||||
@@ -32,32 +34,18 @@ struc PartEntry_t
|
|||||||
.chs_start resb 3
|
.chs_start resb 3
|
||||||
.part_type resb 1
|
.part_type resb 1
|
||||||
.chs_end resb 3
|
.chs_end resb 3
|
||||||
.lba_start resb 4
|
.lba_start resd 1
|
||||||
.lba_length resb 4
|
.lba_length resd 1
|
||||||
endstruc
|
endstruc
|
||||||
|
|
||||||
struc PartTable_t
|
struc PartTable_t
|
||||||
.partition1 resb 16
|
.signature resb 4
|
||||||
.partition2 resb 16
|
.reserved resb 2
|
||||||
.partition3 resb 16
|
.partition1 resb PartEntry_t_size
|
||||||
.partition4 resb 16
|
.partition2 resb PartEntry_t_size
|
||||||
|
.partition3 resb PartEntry_t_size
|
||||||
|
.partition4 resb PartEntry_t_size
|
||||||
endstruc
|
endstruc
|
||||||
|
|
||||||
|
%endif
|
||||||
;Offset Size Description
|
%define __INC_PART_TABLE
|
||||||
; 0 1 size of packet (16 bytes)
|
|
||||||
; 1 1 always 0
|
|
||||||
; 2 2 number of sectors to transfer (max 127 on some BIOSes)
|
|
||||||
; 4 4 transfer buffer (0xFFFF:0xFFFF)
|
|
||||||
; 8 4 lower 32-bits of starting 48-bit LBA
|
|
||||||
; 12 4 upper 32-bits of starting 48-bit LBA
|
|
||||||
; needs to be aligned to a uint32_t
|
|
||||||
struc LBAPkt_t
|
|
||||||
.size resb 1
|
|
||||||
.res0 resb 1
|
|
||||||
.xfer_size resw 1
|
|
||||||
.offset resw 1
|
|
||||||
.segment resw 1
|
|
||||||
.lower_lba resd 1
|
|
||||||
.upper_lba resd 1
|
|
||||||
endstruc
|
|
||||||
56
include/util/bochs_magic.inc
Normal file
56
include/util/bochs_magic.inc
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
; Copyright (c) 2024 Elaina Claus
|
||||||
|
;
|
||||||
|
; Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
; of this software and associated documentation files (the "Software"), to deal
|
||||||
|
; in the Software without restriction, including without limitation the rights
|
||||||
|
; to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
; copies of the Software, and to permit persons to whom the Software is
|
||||||
|
; furnished to do so, subject to the following conditions:
|
||||||
|
;
|
||||||
|
; The above copyright notice and this permission notice shall be included in all
|
||||||
|
; copies or substantial portions of the Software.
|
||||||
|
;
|
||||||
|
; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
; IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
; FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
; AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
; LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
; SOFTWARE.
|
||||||
|
|
||||||
|
%ifndef __INC_BOCHS_DEBUG_MAGIC
|
||||||
|
|
||||||
|
; for things like the error printer, opperate differently when we are targeting a dev (bochs) build
|
||||||
|
%define __STEVIA_DEV_DEBUG
|
||||||
|
; port_e9_hack: enabled=1 needs to be set in bochsrc.txt/bxrc
|
||||||
|
;
|
||||||
|
%ifnmacro __BOCHS_PRINTC
|
||||||
|
%macro __BOCHS_PRINTC 1
|
||||||
|
mov al, %1
|
||||||
|
out 0xe9, byte al
|
||||||
|
%endmacro
|
||||||
|
%endif
|
||||||
|
|
||||||
|
;
|
||||||
|
; port_e9_hack: enabled=1 needs to be set in bochsrc.txt/bxrc
|
||||||
|
;
|
||||||
|
%ifnmacro __BOCHS_BREAK
|
||||||
|
%macro __BOCHS_BREAK 0
|
||||||
|
push ax
|
||||||
|
mov ax, 0x8A00
|
||||||
|
out 0x8A00, word ax
|
||||||
|
pop ax
|
||||||
|
%endmacro
|
||||||
|
%endif
|
||||||
|
|
||||||
|
;
|
||||||
|
; magic_break: enabled=1 needs to be set in bochsrc.txt/bxrc
|
||||||
|
;
|
||||||
|
%ifnmacro __BOCHS_MAGIC_DEBUG
|
||||||
|
%macro __BOCHS_MAGIC_DEBUG 0
|
||||||
|
xchg bx, bx
|
||||||
|
%endmacro
|
||||||
|
%endif
|
||||||
|
|
||||||
|
%define __INC_BOCHS_DEBUG_MAGIC
|
||||||
|
%endif
|
||||||
50
include/util/error_func.nasm
Normal file
50
include/util/error_func.nasm
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
; Copyright (c) 2024 Elaina Claus
|
||||||
|
;
|
||||||
|
; Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
; of this software and associated documentation files (the "Software"), to deal
|
||||||
|
; in the Software without restriction, including without limitation the rights
|
||||||
|
; to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
; copies of the Software, and to permit persons to whom the Software is
|
||||||
|
; furnished to do so, subject to the following conditions:
|
||||||
|
;
|
||||||
|
; The above copyright notice and this permission notice shall be included in all
|
||||||
|
; copies or substantial portions of the Software.
|
||||||
|
;
|
||||||
|
; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
; IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
; FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
; AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
; LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
; SOFTWARE.
|
||||||
|
|
||||||
|
%ifndef __INC_ERROR_FUNC
|
||||||
|
|
||||||
|
%macro ERROR 1
|
||||||
|
%ifdef __STEVIA_DEV_DEBUG
|
||||||
|
__BOCHS_MAGIC_DEBUG
|
||||||
|
%endif
|
||||||
|
mov al, %1 ; al = 1 byte error code mapped to ascii values
|
||||||
|
jmp error
|
||||||
|
%endmacro
|
||||||
|
|
||||||
|
; pass error as ascii character in al, errors a-zA-Z or 0-9
|
||||||
|
ALIGN 4, db 0x90
|
||||||
|
error:
|
||||||
|
cmp al, STEVIA_DEBUG_OK
|
||||||
|
jge short .debug ; the 'letter >= W' (W, X, Y, Z) are used as special debug codes
|
||||||
|
mov ah, 0x4F ; color 0x4F is white text/red background
|
||||||
|
jmp short .print
|
||||||
|
.debug:
|
||||||
|
mov ah, 0x5F ; debug case is white text/purple background
|
||||||
|
.print:
|
||||||
|
mov dx, 0xB800
|
||||||
|
mov gs, dx
|
||||||
|
mov word [gs:0x0000], ax ; 0xB8000 = video memory
|
||||||
|
.halt:
|
||||||
|
cli
|
||||||
|
hlt
|
||||||
|
jmp short .halt
|
||||||
|
|
||||||
|
%endif
|
||||||
|
%define __INC_ERROR_FUNC
|
||||||
58
include/util/kmem_func.nasm
Normal file
58
include/util/kmem_func.nasm
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
; Copyright (c) 2024 Elaina Claus
|
||||||
|
;
|
||||||
|
; Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
; of this software and associated documentation files (the "Software"), to deal
|
||||||
|
; in the Software without restriction, including without limitation the rights
|
||||||
|
; to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
; copies of the Software, and to permit persons to whom the Software is
|
||||||
|
; furnished to do so, subject to the following conditions:
|
||||||
|
;
|
||||||
|
; The above copyright notice and this permission notice shall be included in all
|
||||||
|
; copies or substantial portions of the Software.
|
||||||
|
;
|
||||||
|
; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
; IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
; FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
; AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
; LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
; SOFTWARE.
|
||||||
|
|
||||||
|
%ifndef __INC_KMEM_FUNC
|
||||||
|
%include 'cdecl16.inc'
|
||||||
|
|
||||||
|
; uint8_t* kmemset_byte(void* dst, uint8_t val, uint16_t len);
|
||||||
|
ALIGN 4, db 0x90
|
||||||
|
kmemset:
|
||||||
|
__CDECL16_ENTRY
|
||||||
|
.func:
|
||||||
|
mov cx, [bp + 8] ; size_t len
|
||||||
|
mov al, [bp + 6] ; uint8_t val
|
||||||
|
mov di, [bp + 4] ; void * dst
|
||||||
|
|
||||||
|
cld
|
||||||
|
rep stosb
|
||||||
|
mov ax, di ; return pointer to dest
|
||||||
|
.endp:
|
||||||
|
__CDECL16_EXIT
|
||||||
|
ret
|
||||||
|
|
||||||
|
; uint8_t* kmemset(uint8_t* dest, uint8_t* src, uint8_t len);
|
||||||
|
; not overlap safe
|
||||||
|
ALIGN 4, db 0x90
|
||||||
|
kmemcpy:
|
||||||
|
__CDECL16_ENTRY
|
||||||
|
.func:
|
||||||
|
mov cx, [bp + 8] ; len
|
||||||
|
mov si, [bp + 6] ; src
|
||||||
|
mov di, [bp + 4] ; dest
|
||||||
|
|
||||||
|
cld ; ensure we are incrementing
|
||||||
|
rep movsb
|
||||||
|
mov ax, di ; return pointer to dest
|
||||||
|
.endf:
|
||||||
|
__CDECL16_EXIT
|
||||||
|
ret
|
||||||
|
|
||||||
|
%endif
|
||||||
|
%define __INC_KMEM_FUNC
|
||||||
53
include/util/kmemcpy5_func.nasm
Normal file
53
include/util/kmemcpy5_func.nasm
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
; Copyright (c) 2024 Elaina Claus
|
||||||
|
;
|
||||||
|
; Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
; of this software and associated documentation files (the "Software"), to deal
|
||||||
|
; in the Software without restriction, including without limitation the rights
|
||||||
|
; to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
; copies of the Software, and to permit persons to whom the Software is
|
||||||
|
; furnished to do so, subject to the following conditions:
|
||||||
|
;
|
||||||
|
; The above copyright notice and this permission notice shall be included in all
|
||||||
|
; copies or substantial portions of the Software.
|
||||||
|
;
|
||||||
|
; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
; IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
; FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
; AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
; LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
; SOFTWARE.
|
||||||
|
|
||||||
|
%ifndef __INC_KMEMCPY5_FUNC
|
||||||
|
%include 'cdecl16.inc'
|
||||||
|
|
||||||
|
; uint8_t* kmemset(word dest_segment, word dest, word src_segment, word src, byte len);
|
||||||
|
; not overlap safe, only for
|
||||||
|
ALIGN 4, db 0x90
|
||||||
|
kmemcpy5:
|
||||||
|
__CDECL16_ENTRY
|
||||||
|
push ds
|
||||||
|
push es
|
||||||
|
.setup_segments:
|
||||||
|
mov ax, [bp + 4]
|
||||||
|
mov ds, ax ; destination segment
|
||||||
|
|
||||||
|
mov ax, [ bp + 8]
|
||||||
|
mov es, ax ; source segment
|
||||||
|
.func:
|
||||||
|
mov cx, [bp + 12] ; len
|
||||||
|
mov si, [bp + 10] ; src
|
||||||
|
mov di, [bp + 6] ; dest
|
||||||
|
|
||||||
|
cld ; ensure we are incrementing
|
||||||
|
rep movsb ; move ds:si -> es:di
|
||||||
|
mov ax, di ; return pointer to dest
|
||||||
|
.restore_segments:
|
||||||
|
pop es
|
||||||
|
pop ds
|
||||||
|
.endf:
|
||||||
|
__CDECL16_EXIT
|
||||||
|
ret
|
||||||
|
|
||||||
|
%define __INC_KMEMCPY5_FUNC
|
||||||
|
%endif
|
||||||
47
include/util/kmemset4_func.nasm
Normal file
47
include/util/kmemset4_func.nasm
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
; Copyright (c) 2024 Elaina Claus
|
||||||
|
;
|
||||||
|
; Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
; of this software and associated documentation files (the "Software"), to deal
|
||||||
|
; in the Software without restriction, including without limitation the rights
|
||||||
|
; to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
; copies of the Software, and to permit persons to whom the Software is
|
||||||
|
; furnished to do so, subject to the following conditions:
|
||||||
|
;
|
||||||
|
; The above copyright notice and this permission notice shall be included in all
|
||||||
|
; copies or substantial portions of the Software.
|
||||||
|
;
|
||||||
|
; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
; IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
; FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
; AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
; LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
; SOFTWARE.
|
||||||
|
|
||||||
|
%ifndef __INC_KMEMSET4_FUNC
|
||||||
|
%include 'cdecl16.inc'
|
||||||
|
|
||||||
|
; word kmemset_byte(word segment, word dst, byte val, word len);
|
||||||
|
ALIGN 4, db 0x90
|
||||||
|
kmemset4:
|
||||||
|
__CDECL16_ENTRY
|
||||||
|
.setup_segment:
|
||||||
|
push es
|
||||||
|
mov ax, [bp + 4]
|
||||||
|
mov es, ax
|
||||||
|
.func:
|
||||||
|
mov cx, [bp + 10] ; size_t len
|
||||||
|
mov al, [bp + 8] ; uint8_t val
|
||||||
|
mov di, [bp + 6] ; word dst
|
||||||
|
|
||||||
|
cld
|
||||||
|
rep stosb ; move al -> es:di
|
||||||
|
mov ax, di ; return pointer to dest
|
||||||
|
.restore_segments:
|
||||||
|
pop es
|
||||||
|
.endf:
|
||||||
|
__CDECL16_EXIT
|
||||||
|
ret
|
||||||
|
|
||||||
|
%endif
|
||||||
|
%define __INC_KMEMSET4_FUNC
|
||||||
@@ -21,25 +21,40 @@
|
|||||||
# SOFTWARE.
|
# SOFTWARE.
|
||||||
|
|
||||||
if ! [ $(id -u) = 0 ]; then
|
if ! [ $(id -u) = 0 ]; then
|
||||||
echo "Script must be run as root!"
|
echo "Script must be run as root!" >&2
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# paths to bootcode
|
||||||
mbr_file=build/mbr.bin
|
mbr_file=build/mbr.bin
|
||||||
vbr_file=build/vbr.bin
|
vbr_file=build/vbr.bin
|
||||||
stage2_file=build/stage2.bin
|
stage2_file=build/stage2.bin
|
||||||
boottest_file=build/BOOT_386.bin
|
boottest_file=build/BOOTi686.bin
|
||||||
|
|
||||||
|
|
||||||
|
# Disk creation options
|
||||||
mount_point=/tmp/stevia_disk
|
mount_point=/tmp/stevia_disk
|
||||||
|
disk_tmp_file=/tmp/disk.img
|
||||||
|
disk_file_final=./disk.img.gz
|
||||||
|
|
||||||
if ! [ -e disk.img ]; then
|
# $disk_sector_size * $disk_size = total bytes, default is 256MiB
|
||||||
# create raw disk image with 128MiB of space
|
disk_size=(524288 * 2)
|
||||||
dd if=/dev/zero of=disk.img bs=512 count=262144
|
disk_sector_size=512
|
||||||
|
|
||||||
|
if ! [ -e $disk_tmp_file ]; then
|
||||||
|
# create raw disk image
|
||||||
|
if ! dd if=/dev/zero of=$disk_tmp_file bs=$disk_sector_size count=$disk_size; then
|
||||||
|
echo "Failed creating blank disk image." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
sync
|
sync
|
||||||
else
|
else
|
||||||
echo "Removing old disk image..."
|
echo "Removing old disk image..."
|
||||||
rm -rfv disk.img
|
rm -rfv $disk_tmp_file
|
||||||
dd if=/dev/zero of=disk.img bs=512 count=262144
|
if ! dd if=/dev/zero of=$disk_tmp_file bs=$disk_sector_size count=$disk_size; then
|
||||||
|
echo "Failed creating blank disk image." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
sync
|
sync
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -47,33 +62,68 @@ if [[ "$OSTYPE" == "linux-gnu"* ]]; then
|
|||||||
if [ -e $mbr_file ] && [ -e $vbr_file ]; then
|
if [ -e $mbr_file ] && [ -e $vbr_file ]; then
|
||||||
# get next loop device and mount it
|
# get next loop device and mount it
|
||||||
ld=$(losetup -f)
|
ld=$(losetup -f)
|
||||||
losetup -b 512 $ld disk.img
|
losetup -P -b 512 $ld $disk_tmp_file
|
||||||
|
|
||||||
# create a DOS disk, with 1 FAT32 partition that is bootable, part1 starts at sector 2048
|
# create a DOS disk, with 1 FAT32 partition that is bootable, part1 starts at sector 2048
|
||||||
sfdisk $ld < scripts/loop_setup.sfdisk
|
sfdisk $ld < scripts/loop_setup.sfdisk
|
||||||
|
|
||||||
# partprobe the image
|
# get first partition, this is sloppy might need to review this...
|
||||||
partprobe $ld
|
|
||||||
|
|
||||||
# get first partition
|
|
||||||
firstpart=$(lsblk -ilp -o NAME $ld | tr '\n' ' ' | awk '{print $3}')
|
firstpart=$(lsblk -ilp -o NAME $ld | tr '\n' ' ' | awk '{print $3}')
|
||||||
mkfs.vfat -v -F32 $firstpart
|
mkfs.fat -v -F32 -s 1 -n 'STEVIAFS' $firstpart
|
||||||
|
|
||||||
|
#
|
||||||
|
# MBR setup
|
||||||
|
#
|
||||||
|
|
||||||
# copy MBR while preserving partition table
|
# copy MBR while preserving partition table
|
||||||
dd if=$mbr_file of=$ld bs=1 count=440
|
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
|
# copy MBR 0xAA55
|
||||||
dd if=$mbr_file of=$ld bs=1 seek=510 skip=510 count=2
|
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 VBR to partition 1 while preserving partition information
|
||||||
# copy jmp short entry; nop
|
# copy jmp short entry; nop
|
||||||
dd if=$vbr_file of=$firstpart bs=1 count=3
|
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
|
# copy bootcode
|
||||||
dd if=$vbr_file of=$firstpart bs=1 seek=90 skip=90 count=420
|
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
|
# copy 0xAA55
|
||||||
dd if=$vbr_file of=$firstpart bs=1 seek=510 skip=510 count=2
|
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
|
#stage2 to sectors 1-64
|
||||||
dd if=$stage2_file of=$ld bs=512 seek=1
|
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
|
# copy boot32 boot test file to disk image
|
||||||
if ! [ -e $mount_point ]; then
|
if ! [ -e $mount_point ]; then
|
||||||
@@ -81,25 +131,39 @@ if [[ "$OSTYPE" == "linux-gnu"* ]]; then
|
|||||||
fi
|
fi
|
||||||
mount $firstpart $mount_point
|
mount $firstpart $mount_point
|
||||||
|
|
||||||
if [ -e $boottest_file ]; then
|
# ensure mountpoint is actually a mountpoint
|
||||||
cp -v $boottest_file $mount_point
|
if ! mountpoint -q $mount_point; then
|
||||||
else
|
echo "Failed to mount partition at $mount_point." >&2
|
||||||
echo "unable to find boot32.bin!"
|
exit 1
|
||||||
exit 3
|
|
||||||
fi
|
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
|
# detach loop device
|
||||||
umount $mount_point
|
umount $mount_point
|
||||||
sync
|
sync
|
||||||
|
sleep 1
|
||||||
losetup -d $ld
|
losetup -d $ld
|
||||||
|
|
||||||
# chown to the real user to prevent issues with reading/writing the file later
|
# chown to the real user to prevent issues with reading/writing the file later
|
||||||
SUDOUSER=$(logname)
|
# BUG: ${logname}:$(id $(logname -g)) doesn't work right on WSL because of runlevel hacks in WSL
|
||||||
chown --from=root:root ${SUDOUSER}:$(id $SUDOUSER -g) disk.img
|
# 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
|
else
|
||||||
echo "unable to find MBR/VBR binaries!"
|
echo "unable to find MBR/VBR binaries!" >&2
|
||||||
exit 2
|
exit 1
|
||||||
fi
|
fi
|
||||||
# requires util-linux from homebrew
|
# requires util-linux from homebrew
|
||||||
elif [[ "$OSTYPE" == "darwin"* ]]; then
|
elif [[ "$OSTYPE" == "darwin"* ]]; then
|
||||||
@@ -159,7 +223,7 @@ elif [[ "$OSTYPE" == "darwin"* ]]; then
|
|||||||
dd if=$vbr_file of=/dev/$firstpart bs=1 seek=510 skip=510 count=2 conv=sync
|
dd if=$vbr_file of=/dev/$firstpart bs=1 seek=510 skip=510 count=2 conv=sync
|
||||||
|
|
||||||
#stage2 to sectors 1-64
|
#stage2 to sectors 1-64
|
||||||
dd if=$stage2_file of=$ld_path bs=512 seek=1 conv=sync
|
dd if=$stage2_file of=$ld_path bs=$disk_sector_size seek=1 conv=sync
|
||||||
|
|
||||||
#sync pending dd stuff
|
#sync pending dd stuff
|
||||||
sync
|
sync
|
||||||
@@ -189,7 +253,7 @@ elif [[ "$OSTYPE" == "darwin"* ]]; then
|
|||||||
# chown to the real user to prevent issues with reading/writing the file later
|
# chown to the real user to prevent issues with reading/writing the file later
|
||||||
SUDOUSER=$(logname)
|
SUDOUSER=$(logname)
|
||||||
chown ${SUDOUSER}:staff disk.img
|
chown ${SUDOUSER}:staff disk.img
|
||||||
|
gzip -9kc $disk_tmp_file > $disk_file_final
|
||||||
else
|
else
|
||||||
echo "unable to find MBR/VBR binaries!"
|
echo "unable to find MBR/VBR binaries!"
|
||||||
exit 2
|
exit 2
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
label: dos
|
label: dos
|
||||||
unit: sectors
|
unit: sectors
|
||||||
|
sector-size: 512
|
||||||
|
|
||||||
start= 2048, type=b, bootable
|
start= 2048, type=c, bootable
|
||||||
|
|||||||
205
src/mbr/mbr.nasm
Executable file
205
src/mbr/mbr.nasm
Executable file
@@ -0,0 +1,205 @@
|
|||||||
|
; Copyright (c) 2023 Elaina Claus
|
||||||
|
;
|
||||||
|
; Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
; of this software and associated documentation files (the "Software"), to deal
|
||||||
|
; in the Software without restriction, including without limitation the rights
|
||||||
|
; to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
; copies of the Software, and to permit persons to whom the Software is
|
||||||
|
; furnished to do so, subject to the following conditions:
|
||||||
|
;
|
||||||
|
; The above copyright notice and this permission notice shall be included in all
|
||||||
|
; copies or substantial portions of the Software.
|
||||||
|
;
|
||||||
|
; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
; IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
; FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
; AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
; LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
; SOFTWARE.
|
||||||
|
|
||||||
|
[BITS 16]
|
||||||
|
[ORG 0x8C00]
|
||||||
|
[CPU KATMAI]
|
||||||
|
[WARNING -reloc-abs-byte]
|
||||||
|
[WARNING -reloc-abs-word] ; Yes, we use absolute addresses. surpress these warnings.
|
||||||
|
[map all mbr.map]
|
||||||
|
%define __STEVIA_MBR
|
||||||
|
jmp short (init - $$)
|
||||||
|
nop
|
||||||
|
|
||||||
|
; ###############
|
||||||
|
; Headers/Includes/Definitions
|
||||||
|
; ###############
|
||||||
|
|
||||||
|
%include "util/bochs_magic.inc"
|
||||||
|
%include "cdecl16.inc"
|
||||||
|
%include "entry.inc"
|
||||||
|
%include "config.inc"
|
||||||
|
%include "error_codes.inc"
|
||||||
|
%include "partition_table.inc"
|
||||||
|
%include "fat32/fat32_structures.inc"
|
||||||
|
|
||||||
|
%undef __STEVIA_DEV_DEBUG
|
||||||
|
|
||||||
|
ALIGN 4
|
||||||
|
init:
|
||||||
|
cli ; We do not want to be interrupted
|
||||||
|
xor ax, ax
|
||||||
|
mov ds, ax ; Set segment registers to 0x0000
|
||||||
|
mov es, ax
|
||||||
|
mov fs, ax
|
||||||
|
mov gs, ax
|
||||||
|
|
||||||
|
mov ss, ax ; Set Stack Segment to 0
|
||||||
|
mov sp, end_bss ; Setup stack
|
||||||
|
mov bp, sp ; base ptr = stack ptr
|
||||||
|
|
||||||
|
; Zero BSS section
|
||||||
|
mov cx, (end_bss - begin_bss) ; count = bss length
|
||||||
|
mov ax, begin_bss
|
||||||
|
mov di, ax ; es:di is dest
|
||||||
|
xor ax, ax
|
||||||
|
cld
|
||||||
|
rep stosb ; zero bss section
|
||||||
|
|
||||||
|
sub sp, 0x20 ; local varible space
|
||||||
|
push bp ; setup top of stack frame
|
||||||
|
|
||||||
|
xor cx, cx
|
||||||
|
mov ch, 0x02 ; 0x0200 in cx
|
||||||
|
mov si, 0x7C00 ; Current MBR Address (loaded here by BIOS)
|
||||||
|
mov di, MBR_ENTRY ; New MBR Address (our new relocation address)
|
||||||
|
rep movsb ; copy 512 bytes from 0x0000:7c00 to 0x0000:MBR_ENTRY (7A00 as of writing)
|
||||||
|
|
||||||
|
sti
|
||||||
|
|
||||||
|
jmp 0:main
|
||||||
|
|
||||||
|
; ###############
|
||||||
|
; Extra/Shared Functions
|
||||||
|
; ###############
|
||||||
|
|
||||||
|
%include "util/kmem_func.nasm"
|
||||||
|
%include "util/error_func.nasm"
|
||||||
|
|
||||||
|
;
|
||||||
|
; bp - 2 : uint8_t boot_drive
|
||||||
|
; bp - 4 : uint16_t part_offset
|
||||||
|
ALIGN 4, db 0x90
|
||||||
|
main:
|
||||||
|
mov byte [bp - 2], dl ; BIOS passes drive number in DL
|
||||||
|
|
||||||
|
.check_disk:
|
||||||
|
cmp byte [bp - 2], 0x80
|
||||||
|
jae main.check_extentions
|
||||||
|
|
||||||
|
ERROR MBR_ERROR_DISK_T_ERR
|
||||||
|
|
||||||
|
.check_extentions:
|
||||||
|
xor ax, ax
|
||||||
|
mov ah, 0x41
|
||||||
|
mov bx, 0x55AA
|
||||||
|
mov dl, 0x80
|
||||||
|
int 0x13
|
||||||
|
jnc main.find_active
|
||||||
|
ERROR MBR_ERROR_NO_INT32E ; no extended function support
|
||||||
|
|
||||||
|
.find_active:
|
||||||
|
mov bx, PartEntry1 ; base = first partition
|
||||||
|
mov cx, 4 ; there are only 4 entries
|
||||||
|
.find_active_L0:
|
||||||
|
mov al, byte [bx + PartEntry_t.attributes]
|
||||||
|
test al, 0x80 ; 0x80 == 1000_0000b
|
||||||
|
jnz main.active_found
|
||||||
|
add bx, 0x10 ; add 16 bytes to offset
|
||||||
|
loop main.find_active_L0
|
||||||
|
|
||||||
|
ERROR MBR_ERROR_NO_NO_BOOT_PART
|
||||||
|
|
||||||
|
.active_found:
|
||||||
|
mov ax, bx
|
||||||
|
sub ax, DiskSig ; leaves us with the offset relative from start of table
|
||||||
|
; this gives us an offset from the begining of the partition table
|
||||||
|
mov word [bp - 4], ax ; update part_offset
|
||||||
|
.read_data:
|
||||||
|
movzx ax, byte [bp - 2]
|
||||||
|
push ax ; drive_num
|
||||||
|
|
||||||
|
mov ax, 0x1
|
||||||
|
push ax ; count
|
||||||
|
|
||||||
|
mov dword eax, dword [bx + PartEntry_t.lba_start]
|
||||||
|
push dword eax ; lba
|
||||||
|
|
||||||
|
mov ax, VBR_ENTRY
|
||||||
|
push ax ; offset = 0x7c00
|
||||||
|
|
||||||
|
xor ax, ax
|
||||||
|
push ax ; segment = 0
|
||||||
|
|
||||||
|
; uint8_t read_stage2_raw(uint16_t buf_segment, uint16_t buf_offset,
|
||||||
|
; uint32_t lba,
|
||||||
|
; uint16_t count, uint16_t drive_num)
|
||||||
|
call read_disk_raw
|
||||||
|
add sp, 0xC
|
||||||
|
.goto_vbr:
|
||||||
|
cmp word [VBR_ENTRY + 0x1FE], 0xAA55
|
||||||
|
je main.sig_ok
|
||||||
|
ERROR MBR_ERROR_NO_VBR_SIG ; no signature present
|
||||||
|
.sig_ok:
|
||||||
|
mov ax, PartTable_t_size
|
||||||
|
push ax
|
||||||
|
mov ax, DiskSig ; start of partition table
|
||||||
|
push ax
|
||||||
|
mov ax, partition_table
|
||||||
|
push ax
|
||||||
|
call kmemcpy ; copy partition table to bss
|
||||||
|
add sp, 0x6
|
||||||
|
|
||||||
|
mov si, word [bp - 4]
|
||||||
|
mov dl, byte [bp - 2]
|
||||||
|
mov bx, partition_table
|
||||||
|
jmp word 0x0000:VBR_ENTRY
|
||||||
|
|
||||||
|
; ###############
|
||||||
|
;
|
||||||
|
; BIOS Functions
|
||||||
|
;
|
||||||
|
; ###############
|
||||||
|
|
||||||
|
%include 'BIOS/func/ext_read.nasm'
|
||||||
|
|
||||||
|
%assign bytes_remaining (440 - ($ - $$))
|
||||||
|
%warning MBR has bytes_remaining bytes remaining for code (MAX: 440 bytes)
|
||||||
|
times ((512 - 72) - ($ - $$)) nop ; Fill the rest of sector with nop
|
||||||
|
|
||||||
|
DiskSig:
|
||||||
|
times 4 db 0x00
|
||||||
|
Reserved:
|
||||||
|
dw 0x0000
|
||||||
|
PartEntry1:
|
||||||
|
times 16 db 0x00
|
||||||
|
PartEntry2:
|
||||||
|
times 16 db 0x00
|
||||||
|
PartEntry3:
|
||||||
|
times 16 db 0x00
|
||||||
|
PartEntry4:
|
||||||
|
times 16 db 0x00
|
||||||
|
BootSig:
|
||||||
|
dw 0xAA55 ; Add boot signature at the end of bootloader
|
||||||
|
|
||||||
|
section .bss follows=.text
|
||||||
|
begin_bss:
|
||||||
|
|
||||||
|
align 16, resb 1
|
||||||
|
partition_table resb PartTable_t_size
|
||||||
|
|
||||||
|
align 16, resb 1
|
||||||
|
lba_packet resb LBAPkt_t_size
|
||||||
|
|
||||||
|
align 512, resb 1
|
||||||
|
stack_bottom resb 512 ; 512 byte stack early on
|
||||||
|
stack_top:
|
||||||
|
mbr_redzone resb 32
|
||||||
|
end_bss:
|
||||||
244
src/mbr/mbr.s
244
src/mbr/mbr.s
@@ -1,244 +0,0 @@
|
|||||||
; Copyright (c) 2023 Elaina Claus
|
|
||||||
;
|
|
||||||
; Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
; of this software and associated documentation files (the "Software"), to deal
|
|
||||||
; in the Software without restriction, including without limitation the rights
|
|
||||||
; to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
; copies of the Software, and to permit persons to whom the Software is
|
|
||||||
; furnished to do so, subject to the following conditions:
|
|
||||||
;
|
|
||||||
; The above copyright notice and this permission notice shall be included in all
|
|
||||||
; copies or substantial portions of the Software.
|
|
||||||
;
|
|
||||||
; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
; IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
; FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
; AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
; LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
; SOFTWARE.
|
|
||||||
|
|
||||||
[BITS 16]
|
|
||||||
[ORG 0x7A00]
|
|
||||||
[CPU KATMAI]
|
|
||||||
jmp short init
|
|
||||||
nop
|
|
||||||
|
|
||||||
%include "entry.inc"
|
|
||||||
init:
|
|
||||||
cli ; We do not want to be interrupted
|
|
||||||
|
|
||||||
xor ax, ax ; 0 AX
|
|
||||||
mov ds, ax ; Set segment registers to 0
|
|
||||||
mov es, ax ; *
|
|
||||||
|
|
||||||
mov ss, ax ; Set Stack Segment to 0
|
|
||||||
mov sp, STACK_START
|
|
||||||
|
|
||||||
mov ch, 0x01 ; 256 WORDs in MBR (512 bytes), 0x0100 in cx
|
|
||||||
mov si, 0x7C00 ; Current MBR Address (loaded here by BIOS)
|
|
||||||
mov di, MBR_ENTRY ; New MBR Address (our new relocation address)
|
|
||||||
rep movsw ; copy 512 bytes from 0x0000:7c00 to 0x0000:0600
|
|
||||||
|
|
||||||
jmp 0:main
|
|
||||||
nop
|
|
||||||
|
|
||||||
%include "config.inc"
|
|
||||||
%include "memory.inc"
|
|
||||||
%include "partition_table.inc"
|
|
||||||
%include "errors.inc"
|
|
||||||
|
|
||||||
main:
|
|
||||||
sti
|
|
||||||
mov [boot_drive], dl ; BIOS passes drive number in DL
|
|
||||||
|
|
||||||
.check_disk:
|
|
||||||
cmp dl, 0x80
|
|
||||||
jae main.find_active
|
|
||||||
ERROR MBR_ERROR_DISK_T_ERR
|
|
||||||
|
|
||||||
.check_extentions:
|
|
||||||
xor ax, ax
|
|
||||||
mov bx, 0x55AA
|
|
||||||
mov dl, byte [boot_drive]
|
|
||||||
int 0x13
|
|
||||||
jnc main.find_active
|
|
||||||
ERROR MBR_ERROR_NO_INT32E ; no extended function support
|
|
||||||
|
|
||||||
.find_active:
|
|
||||||
mov bx, PartEntry1 ; base = first partition
|
|
||||||
mov cx, 4 ; there are only 4 entries
|
|
||||||
.find_active_L0:
|
|
||||||
mov al, byte [bx + PartEntry_t.attributes]
|
|
||||||
test al, 0x80 ; 0x80 == 1000_0000b
|
|
||||||
jnz main.active_found
|
|
||||||
|
|
||||||
add bx, 0x10 ; add 16 bytes to offset
|
|
||||||
loop main.find_active_L0
|
|
||||||
ERROR MBR_ERROR_NO_NO_BOOT_PART
|
|
||||||
|
|
||||||
.active_found:
|
|
||||||
mov ax, bx
|
|
||||||
sub ax, DiskSig ; leaves us with the offset relative from start of table
|
|
||||||
; this gives us an offset from the begining of the partition table
|
|
||||||
mov word [part_offset], ax ; update part_offset
|
|
||||||
.read_data:
|
|
||||||
push bp
|
|
||||||
mov bp, sp
|
|
||||||
|
|
||||||
;uint8_t read_disk_raw(size_t count, uint16_t buf_segment, uint16_t buf_offset,
|
|
||||||
; uint16_t lower_lower_lba, uint16_t upper_lower_lba)
|
|
||||||
mov eax, dword [bx + PartEntry_t.lba_start]
|
|
||||||
ror eax, 16
|
|
||||||
push ax
|
|
||||||
|
|
||||||
ror eax, 16
|
|
||||||
push ax
|
|
||||||
|
|
||||||
mov ax, VBR_ENTRY
|
|
||||||
push ax
|
|
||||||
|
|
||||||
xor ax, ax
|
|
||||||
push ax ; segment = 0
|
|
||||||
|
|
||||||
mov ax, 1
|
|
||||||
push ax
|
|
||||||
|
|
||||||
call read_disk_raw
|
|
||||||
leave
|
|
||||||
|
|
||||||
jnc main.goto_vbr
|
|
||||||
ERROR MBR_ERROR_DISK_READ_ERR ; error in LBA read
|
|
||||||
.goto_vbr:
|
|
||||||
cmp word [VBR_ENTRY + 0x1FE], 0xAA55
|
|
||||||
je main.sig_ok
|
|
||||||
ERROR MBR_ERROR_NO_VBR_SIG ; no signature present
|
|
||||||
|
|
||||||
.sig_ok:
|
|
||||||
push bp
|
|
||||||
mov bp, sp
|
|
||||||
|
|
||||||
mov ax, partition_table_SIZE ; 72 bytes of data
|
|
||||||
push ax
|
|
||||||
mov ax, DiskSig ; start of partition table
|
|
||||||
push ax
|
|
||||||
mov ax, partition_table ; defined in memory.inc
|
|
||||||
push ax
|
|
||||||
call kmemcpy ; copy partition table to memory
|
|
||||||
leave
|
|
||||||
|
|
||||||
xor ah, ah ; Set Video mode BIOS function
|
|
||||||
mov al, 0x02 ; 16 color 80x25 Text mode
|
|
||||||
int 0x10 ; Call video interrupt
|
|
||||||
|
|
||||||
mov ah, 0x05 ; Select active display page BIOS function
|
|
||||||
xor al, al ; page 0
|
|
||||||
int 0x10 ; call video interrupt
|
|
||||||
|
|
||||||
mov si, word [part_offset]
|
|
||||||
mov dl, byte [boot_drive]
|
|
||||||
jmp 0:0x7C00
|
|
||||||
|
|
||||||
; Wrapper for AH=0x42 INT13h (Extended Read)
|
|
||||||
;
|
|
||||||
; BIOS call details
|
|
||||||
; AH = 42h
|
|
||||||
; DL = drive number
|
|
||||||
; DS:SI -> disk address packet
|
|
||||||
;
|
|
||||||
; Return:
|
|
||||||
; CF clear if successful
|
|
||||||
; AH = 00h
|
|
||||||
; CF set on error
|
|
||||||
; AH = error code
|
|
||||||
; disk address packet's block count field set to number of blocks
|
|
||||||
; successfully transferred
|
|
||||||
;
|
|
||||||
;
|
|
||||||
; uint8_t read_disk_raw(uint16_t buf_segment, uint16_t buf_offset, uint16_t lower_lower_lba, uint16_t upper_lower_lba)
|
|
||||||
; bp-0 = call frame
|
|
||||||
; bp-2 = upper_lower_lba
|
|
||||||
; bp-4 = lower_lower_lba
|
|
||||||
; bp-6 = offset
|
|
||||||
; bp-8 = segment
|
|
||||||
; bp-10 = count
|
|
||||||
; bp-12 = ret ptr
|
|
||||||
read_disk_raw:
|
|
||||||
push si
|
|
||||||
|
|
||||||
; uint8_t* kmemset(void* dest, uint8_t val, size_t len);
|
|
||||||
push bp
|
|
||||||
mov bp, sp
|
|
||||||
|
|
||||||
mov ax, 0x10
|
|
||||||
push ax ; len = 16 bytes
|
|
||||||
xor ax, ax
|
|
||||||
push ax ; val = 0
|
|
||||||
mov ax, lba_packet
|
|
||||||
push ax ; dest = lba_packet address
|
|
||||||
|
|
||||||
call kmemset
|
|
||||||
leave
|
|
||||||
|
|
||||||
mov byte [lba_packet + LBAPkt_t.size], 0x10
|
|
||||||
mov word [lba_packet + LBAPkt_t.xfer_size], STAGE2_SECTOR_COUNT
|
|
||||||
|
|
||||||
mov ax, [bp-2]
|
|
||||||
shl eax, 16
|
|
||||||
mov ax, [bp-4]
|
|
||||||
mov dword [lba_packet + LBAPkt_t.lower_lba], eax
|
|
||||||
|
|
||||||
mov ax, [bp-6]
|
|
||||||
mov word [lba_packet + LBAPkt_t.offset], ax
|
|
||||||
|
|
||||||
mov ax, [bp-8]
|
|
||||||
mov word [lba_packet + LBAPkt_t.segment], ax
|
|
||||||
|
|
||||||
mov si, lba_packet
|
|
||||||
mov ah, 0x42
|
|
||||||
mov dl, byte [boot_drive]
|
|
||||||
int 0x13
|
|
||||||
jnc read_disk_raw.endf
|
|
||||||
|
|
||||||
mov al, 'B'
|
|
||||||
jmp error
|
|
||||||
.endf:
|
|
||||||
pop si
|
|
||||||
ret
|
|
||||||
|
|
||||||
; #############
|
|
||||||
;
|
|
||||||
; Locals
|
|
||||||
;
|
|
||||||
; #############
|
|
||||||
|
|
||||||
boot_drive:
|
|
||||||
db 0x00
|
|
||||||
mbr_reserved1:
|
|
||||||
db 0x00
|
|
||||||
|
|
||||||
; OFFSET from BEGINING of partition table, ie. DiskSig (-6 from PartEntry1)
|
|
||||||
part_offset:
|
|
||||||
dw 0x0000
|
|
||||||
|
|
||||||
%assign bytes_remaining (440 - ($ - $$))
|
|
||||||
%warning MBR has bytes_remaining bytes remaining for code (MAX: 440 bytes)
|
|
||||||
times ((512 - 72) - ($ - $$)) nop ; Fill the rest of sector with nop
|
|
||||||
|
|
||||||
DiskSig:
|
|
||||||
times 4 db 0x00
|
|
||||||
Reserved1:
|
|
||||||
db 0x00
|
|
||||||
Reserved2:
|
|
||||||
db 0x00
|
|
||||||
|
|
||||||
PartEntry1:
|
|
||||||
times 16 db 0x00
|
|
||||||
PartEntry2:
|
|
||||||
times 16 db 0x00
|
|
||||||
PartEntry3:
|
|
||||||
times 16 db 0x00
|
|
||||||
PartEntry4:
|
|
||||||
times 16 db 0x00
|
|
||||||
BootSig:
|
|
||||||
dw 0xAA55 ; Add boot signature at the end of bootloader
|
|
||||||
@@ -1,559 +0,0 @@
|
|||||||
; Copyright (c) 2023 Elaina Claus
|
|
||||||
;
|
|
||||||
; Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
; of this software and associated documentation files (the "Software"), to deal
|
|
||||||
; in the Software without restriction, including without limitation the rights
|
|
||||||
; to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
; copies of the Software, and to permit persons to whom the Software is
|
|
||||||
; furnished to do so, subject to the following conditions:
|
|
||||||
;
|
|
||||||
; The above copyright notice and this permission notice shall be included in all
|
|
||||||
; copies or substantial portions of the Software.
|
|
||||||
;
|
|
||||||
; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
; IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
; FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
; AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
; LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
; SOFTWARE.
|
|
||||||
|
|
||||||
[BITS 32]
|
|
||||||
[ORG 0x100000]
|
|
||||||
[CPU KATMAI]
|
|
||||||
|
|
||||||
jmp short start32
|
|
||||||
nop
|
|
||||||
|
|
||||||
; Unless noted otherwise, functions will be the standard x86 cdecl used in GCC
|
|
||||||
|
|
||||||
; In cdecl, subroutine arguments are passed on the stack.
|
|
||||||
; Integer values and memory addresses are returned in the EAX register,
|
|
||||||
; floating point values in the ST0 x87 register.
|
|
||||||
; Registers EAX, ECX, and EDX are caller-saved,
|
|
||||||
; and the rest are callee-saved.
|
|
||||||
; The x87 floating point registers ST0 to ST7 must be empty (popped or freed)
|
|
||||||
; when calling a new function, and ST1 to ST7 must be empty on exiting a function.
|
|
||||||
; ST0 must also be empty when not used for returning a value.
|
|
||||||
;
|
|
||||||
; EXAMPLE: to call uint8_t* kmemset(uint8_t* dest, uint8_t val, uint8_t size);
|
|
||||||
; => kmemset(*((char*) 0xb8000), 'F', (80*25))
|
|
||||||
;
|
|
||||||
; push ebp ; save old call frame pointer
|
|
||||||
; mov ebp, esp ; new call frame pointer
|
|
||||||
; push 0x000007D0 ; push args RTL, EBP - 4
|
|
||||||
; push 'F' ; * EBP - 8
|
|
||||||
; push 0x000b8000 ; * EBP - 12
|
|
||||||
; call kmemset ; call function, this also places a return pointer on stack
|
|
||||||
; add esp, 12 ; remove call arguments from stack frame
|
|
||||||
; mov esp, ebp ; restore stack frame pointer (callee saves EBP)
|
|
||||||
; pop ebp ; restore call frame pointer
|
|
||||||
;
|
|
||||||
;
|
|
||||||
|
|
||||||
; 33 bytes BPB + 26 Byte EBPB
|
|
||||||
struc BPBStruct
|
|
||||||
.OemName resb 8
|
|
||||||
.BytesPerSect resw 1
|
|
||||||
.SecsPerClust resb 1
|
|
||||||
.ResSectors resw 1
|
|
||||||
.FATs resb 1
|
|
||||||
.RootDirEnts resw 1
|
|
||||||
.Sectors resw 1
|
|
||||||
.Media resb 1
|
|
||||||
.SectPerFAT resw 1
|
|
||||||
.SectPerTrack resw 1
|
|
||||||
.Heads resw 1
|
|
||||||
.Hidden resd 1
|
|
||||||
.SectorHuge resd 1
|
|
||||||
; begin EBPB
|
|
||||||
.DriveNumber resb 1
|
|
||||||
.NTReserved resb 1
|
|
||||||
.Signature resb 1
|
|
||||||
.VolumeID resd 1
|
|
||||||
.VolumeLabel resb 11
|
|
||||||
.SysIdent resb 8
|
|
||||||
endstruc
|
|
||||||
|
|
||||||
; 12 bytes
|
|
||||||
struc FSInfoStruct
|
|
||||||
.first_root_dir_sector resw 1
|
|
||||||
.last_root_dir_sector resw 1
|
|
||||||
.root_dir_len resw 1
|
|
||||||
.first_data_sector resw 1
|
|
||||||
.active_cluster resw 1
|
|
||||||
.active_FAT_cluster resw 1
|
|
||||||
endstruc
|
|
||||||
|
|
||||||
; 20 bytes
|
|
||||||
struc KInfoStruct
|
|
||||||
.load_address resd 1
|
|
||||||
.file_len resd 1
|
|
||||||
.file_name resb 8
|
|
||||||
.file_ext resb 3
|
|
||||||
.reserved1 resb 1
|
|
||||||
endstruc
|
|
||||||
|
|
||||||
; Address Range Descriptor Structure
|
|
||||||
;
|
|
||||||
; Offset in Bytes Name Description
|
|
||||||
; 0 BaseAddrLow u32 - Low 32 Bits of Base Address
|
|
||||||
; 4 BaseAddrHigh u32 - High 32 Bits of Base Address
|
|
||||||
; 8 LengthLow u32 - Low 32 Bits of Length in Bytes
|
|
||||||
; 12 LengthHigh u32 - High 32 Bits of Length in Bytes
|
|
||||||
; 16 Type u32 - Address type of this range.
|
|
||||||
; 20 ExtType u32 - ACPI 3.0 extended type
|
|
||||||
struc AddressRangeDescStruct
|
|
||||||
.BaseAddrLow resd 1
|
|
||||||
.BaseAddrHigh resd 1
|
|
||||||
.LengthLow resd 1
|
|
||||||
.LengthHigh resd 1
|
|
||||||
.Type resd 1
|
|
||||||
.ExtType resd 1
|
|
||||||
endstruc
|
|
||||||
|
|
||||||
; 20 bytes, passed to loaded kernel
|
|
||||||
struc CBootInfoStruct
|
|
||||||
.MemoryMapPtr resd 1
|
|
||||||
.MemoryMapEntries resd 1
|
|
||||||
.BPBDataPtr resd 1
|
|
||||||
.FSInfoPtr resd 1
|
|
||||||
.KInfoPtr resd 1
|
|
||||||
endstruc
|
|
||||||
|
|
||||||
;;;
|
|
||||||
; Errors
|
|
||||||
; 0 = unused
|
|
||||||
; 1 = No CPUID support on this platform (VM or some very old hardware?)
|
|
||||||
; 2 = magic signature not found at end of file
|
|
||||||
; 3 = Unexpected/unhandled artithmetic overflow/carry
|
|
||||||
;;;
|
|
||||||
|
|
||||||
%define MAX_BYTES (1024 * 8)
|
|
||||||
|
|
||||||
%define VGA_BUF 0xb8000
|
|
||||||
;black BG/Green FG
|
|
||||||
%define TTY_COLOR 0x0200
|
|
||||||
;black BG/Red FG
|
|
||||||
%define TTY_ERR_CLR 0x0400
|
|
||||||
;subtract 1 for max array values
|
|
||||||
%define VGA_MAX_Y 25
|
|
||||||
%define VGA_MAX_X 80
|
|
||||||
|
|
||||||
; VGA memory is row-major => offset = (row * MAX_Colums) + colum
|
|
||||||
; macro array is counted from 0,0 = 1,1 => 79,24 is the last usable space in a page
|
|
||||||
%define VGA_OFFSET(x,y) (((y*VGA_MAX_X) + x)*2)
|
|
||||||
|
|
||||||
start32:
|
|
||||||
mov ax, 0x10
|
|
||||||
mov ds, ax
|
|
||||||
mov es, ax
|
|
||||||
mov fs, ax
|
|
||||||
mov gs, ax
|
|
||||||
mov ss, ax ; load data registers with 2nd GDT selector
|
|
||||||
mov esp, stack_top
|
|
||||||
mov ebp, esp
|
|
||||||
|
|
||||||
; debugger hack because gdb doesn't like to switch register sizes
|
|
||||||
; issue a set $eax = 1 to continue
|
|
||||||
%ifdef DEBUG_HACK
|
|
||||||
mov eax, 0
|
|
||||||
.gdb_hack:
|
|
||||||
test eax, eax
|
|
||||||
jz start32.gdb_hack
|
|
||||||
%endif
|
|
||||||
|
|
||||||
mov eax, dword [BOOT_SIG]
|
|
||||||
cmp eax, 0xA0B0C0D0
|
|
||||||
jz start32.signature_present
|
|
||||||
|
|
||||||
mov al, "2"
|
|
||||||
call error
|
|
||||||
|
|
||||||
|
|
||||||
.signature_present:
|
|
||||||
call check_cpuid
|
|
||||||
|
|
||||||
push ebp
|
|
||||||
mov ebp, esp
|
|
||||||
lea eax, [welcome_cstr]
|
|
||||||
push eax
|
|
||||||
call vga_puts
|
|
||||||
leave
|
|
||||||
|
|
||||||
push ebp
|
|
||||||
mov ebp, esp
|
|
||||||
lea eax, [version_cstr]
|
|
||||||
push eax
|
|
||||||
call vga_puts
|
|
||||||
leave
|
|
||||||
|
|
||||||
push ebp
|
|
||||||
mov ebp, esp
|
|
||||||
lea eax, [datetime_cstr]
|
|
||||||
push eax
|
|
||||||
call vga_puts
|
|
||||||
leave
|
|
||||||
|
|
||||||
mov eax, VGA_BUF
|
|
||||||
add eax, VGA_OFFSET(78, 24)
|
|
||||||
mov dword [eax], 0x2f4b2f4f
|
|
||||||
hlt
|
|
||||||
|
|
||||||
; Early error printer. Prints 'ERR: X' where X is an error code in al
|
|
||||||
error:
|
|
||||||
mov eax, VGA_BUF
|
|
||||||
add eax, VGA_OFFSET(73, 24)
|
|
||||||
|
|
||||||
mov dword [eax], 0x4f524f45
|
|
||||||
add eax, 0x2
|
|
||||||
mov dword [eax], 0x4f3a4f52
|
|
||||||
add eax, 0x2
|
|
||||||
mov dword [eax], 0x4f204f20
|
|
||||||
add eax, 0x2
|
|
||||||
mov byte [eax], al
|
|
||||||
hlt
|
|
||||||
|
|
||||||
check_cpuid:
|
|
||||||
; flip cpuid id bit (bit 21) to check for cpuid support
|
|
||||||
|
|
||||||
; copy flags to eax via stack
|
|
||||||
pushfd
|
|
||||||
pop eax
|
|
||||||
|
|
||||||
mov ecx, eax ; copy to ecx for compare
|
|
||||||
|
|
||||||
xor eax, 1 << 21 ; xor eax with the 21st bit set
|
|
||||||
|
|
||||||
push eax ; push new flags and pop to flags register
|
|
||||||
popfd
|
|
||||||
|
|
||||||
pushfd
|
|
||||||
pop eax
|
|
||||||
|
|
||||||
cmp eax, ecx ; can we change the bit?
|
|
||||||
je .no_cpuid
|
|
||||||
ret
|
|
||||||
.no_cpuid:
|
|
||||||
mov al, "1"
|
|
||||||
call error
|
|
||||||
|
|
||||||
; int vga_puts(char* str)
|
|
||||||
;
|
|
||||||
; INPUT:
|
|
||||||
; str: C-Sytle string
|
|
||||||
;
|
|
||||||
; OUTPUT:
|
|
||||||
; EAX = characters printed
|
|
||||||
;
|
|
||||||
vga_puts:
|
|
||||||
; prolog, EBP = SFP (Stack frame pointer), [EBP-4] = char* str
|
|
||||||
push edi
|
|
||||||
push esi
|
|
||||||
push ebx
|
|
||||||
|
|
||||||
.get_str_len:
|
|
||||||
mov edi, [ebp - 4]
|
|
||||||
|
|
||||||
xor ecx, ecx ; ECX = 0
|
|
||||||
not ecx ; ECX = -1 == 0xFFFFFFFF
|
|
||||||
xor eax, eax ; search for al = 0x0
|
|
||||||
cld
|
|
||||||
repne scasb ; deincrement ecx while searching for al
|
|
||||||
not ecx ; the inverse of a neg number = abs(x) - 1
|
|
||||||
dec ecx ; ECX contains the length of the string - nul byte at end
|
|
||||||
|
|
||||||
|
|
||||||
mov edi, VGA_BUF ; load dest index with VGA buffer + calculated offset
|
|
||||||
mov esi, [ebp -4] ; load source index with src string
|
|
||||||
|
|
||||||
; ECX = string length
|
|
||||||
; ESI = source string to print
|
|
||||||
; EDI = destination in the VGA buffer
|
|
||||||
.print_char:
|
|
||||||
cmp ecx, 0x0
|
|
||||||
jle vga_puts.endf
|
|
||||||
|
|
||||||
cmp byte [vga_buf_pos_x], 80
|
|
||||||
je vga_puts.end_of_line
|
|
||||||
|
|
||||||
cmp byte [vga_buf_pos_y], 25
|
|
||||||
je vga_puts.scroll_up
|
|
||||||
|
|
||||||
cmp byte [esi], 0x20
|
|
||||||
jl vga_puts.special_character_switch
|
|
||||||
|
|
||||||
push ebp
|
|
||||||
mov ebp, esp
|
|
||||||
|
|
||||||
xor eax, eax
|
|
||||||
mov al, [vga_buf_pos_y]
|
|
||||||
push eax ; vga_pos_y
|
|
||||||
|
|
||||||
xor eax, eax
|
|
||||||
mov al, [vga_buf_pos_x]
|
|
||||||
push eax ; vga_pos_x
|
|
||||||
|
|
||||||
; uint16_t vga_calc_offset(uint8_t vga_pos_x, uint8_t vga_pos_y)
|
|
||||||
call vga_calc_offset
|
|
||||||
leave
|
|
||||||
|
|
||||||
xor bx, bx
|
|
||||||
mov bl, byte [esi]
|
|
||||||
or bx, TTY_COLOR ; create VGA character
|
|
||||||
|
|
||||||
mov [edi+eax], bx
|
|
||||||
inc esi
|
|
||||||
inc byte [vga_buf_pos_x]
|
|
||||||
|
|
||||||
|
|
||||||
dec ecx
|
|
||||||
jmp vga_puts.print_char ; loop until ECX == 0
|
|
||||||
|
|
||||||
.end_of_line:
|
|
||||||
; advance to next row
|
|
||||||
inc byte [vga_buf_pos_y]
|
|
||||||
mov byte [vga_buf_pos_x], 0
|
|
||||||
jmp vga_puts.print_char
|
|
||||||
.scroll_up:
|
|
||||||
; after 25 rows, move to next page (either swap pages [memcpy] or erase page 0)
|
|
||||||
mov byte [vga_buf_pos_x], 0
|
|
||||||
mov byte [vga_buf_pos_y], 0
|
|
||||||
|
|
||||||
push ebp
|
|
||||||
mov ebp, esp
|
|
||||||
|
|
||||||
mov eax, 0x7D0
|
|
||||||
push eax ; 1 VGA page = 0x7D0 elements
|
|
||||||
|
|
||||||
xor eax, eax
|
|
||||||
push eax ; we want to blank the page with 0x0000
|
|
||||||
|
|
||||||
mov eax, VGA_BUF
|
|
||||||
push eax ; load vga buffer base (0xb8000)
|
|
||||||
|
|
||||||
; uint16_t* kmemset_word(void* dest, uint16_t val, size_t len);
|
|
||||||
call kmemset_byte
|
|
||||||
leave
|
|
||||||
|
|
||||||
jmp vga_puts.print_char
|
|
||||||
|
|
||||||
.special_character_switch:
|
|
||||||
|
|
||||||
cmp byte[esi], 0xA
|
|
||||||
je vga_puts.handle_LF
|
|
||||||
|
|
||||||
cmp byte[esi], 0xD
|
|
||||||
je vga_puts.handle_CR
|
|
||||||
|
|
||||||
; Default case
|
|
||||||
.special_character_endp:
|
|
||||||
dec ecx
|
|
||||||
inc esi
|
|
||||||
|
|
||||||
jmp vga_puts.print_char
|
|
||||||
|
|
||||||
.handle_LF:
|
|
||||||
; advance to next row
|
|
||||||
inc byte [vga_buf_pos_y]
|
|
||||||
jmp vga_puts.special_character_endp
|
|
||||||
|
|
||||||
.handle_CR:
|
|
||||||
mov byte [vga_buf_pos_x], 0
|
|
||||||
jmp vga_puts.special_character_endp
|
|
||||||
|
|
||||||
|
|
||||||
.endf:
|
|
||||||
pop ebx
|
|
||||||
pop esi
|
|
||||||
pop edi
|
|
||||||
|
|
||||||
ret
|
|
||||||
|
|
||||||
; short vga_get_xy(void)
|
|
||||||
;
|
|
||||||
; INPUT:
|
|
||||||
;
|
|
||||||
; OUTPUT:
|
|
||||||
; EAX = xy_pos
|
|
||||||
; > x = xy_pos && 0xFF00
|
|
||||||
; y = xy_pos && 0x00FF
|
|
||||||
; 2 MSB of EAX are 0.
|
|
||||||
;
|
|
||||||
vga_get_xy:
|
|
||||||
.endf:
|
|
||||||
ret
|
|
||||||
|
|
||||||
; void vga_set_xy(short xy_pos)
|
|
||||||
; xy_pos is a byte packed word (16bit value), MSB is x, LSB is y
|
|
||||||
; => x = xy_pos && 0xFF00
|
|
||||||
; y = xy_pos && 0x00FF
|
|
||||||
;
|
|
||||||
; INPUT:
|
|
||||||
; xy_pos
|
|
||||||
;
|
|
||||||
; OUTPUT:
|
|
||||||
; NONE
|
|
||||||
;
|
|
||||||
vga_set_xy:
|
|
||||||
.endf:
|
|
||||||
ret
|
|
||||||
|
|
||||||
; uint16_t vga_calc_offset(uint8_t vga_pos_x, uint8_t vga_pos_y)
|
|
||||||
; VGA_OFFSET(x,y) == (((y*VGA_MAX_X) + x)*2)
|
|
||||||
vga_calc_offset:
|
|
||||||
xor eax, eax
|
|
||||||
xor edx, edx
|
|
||||||
|
|
||||||
mov edx, [ebp-4]
|
|
||||||
mov ax, VGA_MAX_X
|
|
||||||
mul dx ; DX:AX contains (y*VGA_MAX_X)
|
|
||||||
jc vga_calc_offset.artithmetic_error
|
|
||||||
|
|
||||||
mov edx, [ebp-8]
|
|
||||||
add ax, dx
|
|
||||||
jc vga_calc_offset.artithmetic_error
|
|
||||||
|
|
||||||
mov dx, 0x02
|
|
||||||
mul dx ; DX:AX contains (y*VGA_MAX_X) + x) * 2
|
|
||||||
jnc vga_calc_offset.endf
|
|
||||||
|
|
||||||
.artithmetic_error:
|
|
||||||
mov al, '3'
|
|
||||||
call error
|
|
||||||
|
|
||||||
.endf:
|
|
||||||
; (e)AX contains the offset
|
|
||||||
ret
|
|
||||||
|
|
||||||
; uint32_t* kmemset(void* dest, uint32_t val, size_t len);
|
|
||||||
kmemset_dword:
|
|
||||||
push edi ; function uses edi, so save it.
|
|
||||||
; [ebp] = previous call frame
|
|
||||||
mov ecx, [ebp - 4] ; size_t len
|
|
||||||
|
|
||||||
mov eax, [ebp - 8] ; uint32_t val
|
|
||||||
|
|
||||||
mov edi, [ebp - 12] ; void * ptr
|
|
||||||
; [ebp - 16] = return adress
|
|
||||||
; [ebp - 20] = saved EDI
|
|
||||||
rep stosd
|
|
||||||
.endf:
|
|
||||||
mov eax, [ebp - 12] ; return pointer to dest
|
|
||||||
pop edi ; restore edi
|
|
||||||
ret
|
|
||||||
|
|
||||||
; uint16_t* kmemset(void* dest, uint16_t val, size_t len);
|
|
||||||
kmemset_word:
|
|
||||||
push edi ; function uses edi, so save it.
|
|
||||||
; [ebp] = previous call frame
|
|
||||||
mov ecx, [ebp - 4] ; size_t len
|
|
||||||
|
|
||||||
mov ax, [ebp - 8] ; uint16_t val
|
|
||||||
|
|
||||||
mov edi, [ebp - 12] ; void * ptr
|
|
||||||
; [ebp - 16] = return adress
|
|
||||||
; [ebp - 20] = saved EDI
|
|
||||||
rep stosw
|
|
||||||
.endf:
|
|
||||||
mov eax, [ebp - 12] ; return pointer to dest
|
|
||||||
pop edi ; restore edi
|
|
||||||
ret
|
|
||||||
|
|
||||||
; uint8_t* kmemset(void* dest, uint8_t val, size_t len);
|
|
||||||
kmemset_byte:
|
|
||||||
push edi ; function uses edi, so save it.
|
|
||||||
; [ebp] = previous call frame
|
|
||||||
mov ecx, [ebp - 4] ; size_t len
|
|
||||||
|
|
||||||
mov al, [ebp - 8] ; uint8_t val
|
|
||||||
|
|
||||||
mov edi, [ebp - 12] ; void * ptr
|
|
||||||
; [ebp - 16] = return adress
|
|
||||||
; [ebp - 20] = saved EDI
|
|
||||||
rep stosb
|
|
||||||
.endf:
|
|
||||||
mov eax, [ebp - 12] ; return pointer to dest
|
|
||||||
pop edi ; restore edi
|
|
||||||
ret
|
|
||||||
|
|
||||||
; uint32_t* kmemset(uint32_t* dest, uint32_t* src, size_t len);
|
|
||||||
kmemcpy_dword:
|
|
||||||
push edi
|
|
||||||
push esi ; edi, esi are callee save
|
|
||||||
|
|
||||||
mov edi, [ebp-12] ; dest
|
|
||||||
mov esi, [ebp-8] ; source
|
|
||||||
mov ecx, [ebp-4] ; length
|
|
||||||
|
|
||||||
cld ; ensure we are incrementing
|
|
||||||
rep movsd
|
|
||||||
|
|
||||||
.endf:
|
|
||||||
mov eax, [ebp-12] ; return pointer to dest
|
|
||||||
pop esi
|
|
||||||
pop edi
|
|
||||||
ret
|
|
||||||
|
|
||||||
; uint16_t* kmemset(uint16_t* dest, uint16_t* src, size_t len);
|
|
||||||
kmemcpy_word:
|
|
||||||
push edi
|
|
||||||
push esi ; edi, esi are callee save
|
|
||||||
|
|
||||||
mov edi, [ebp-12] ; dest
|
|
||||||
mov esi, [ebp-8] ; source
|
|
||||||
mov ecx, [ebp-4] ; length
|
|
||||||
|
|
||||||
cld ; ensure we are incrementing
|
|
||||||
rep movsw
|
|
||||||
|
|
||||||
.endf:
|
|
||||||
mov eax, [ebp-12] ; return pointer to dest
|
|
||||||
pop esi
|
|
||||||
pop edi
|
|
||||||
ret
|
|
||||||
|
|
||||||
; uint8_t* kmemset(uint8_t* dest, uint8_t* src, size_t len);
|
|
||||||
; not overlap safe
|
|
||||||
kmemcpy_byte:
|
|
||||||
push edi
|
|
||||||
push esi ; edi, esi are callee save
|
|
||||||
|
|
||||||
mov edi, [ebp-12] ; dest
|
|
||||||
mov esi, [ebp-8] ; source
|
|
||||||
mov ecx, [ebp-4] ; length
|
|
||||||
|
|
||||||
cld ; ensure we are incrementing
|
|
||||||
rep movsb
|
|
||||||
|
|
||||||
.endf:
|
|
||||||
mov eax, [ebp-12] ; return pointer to dest
|
|
||||||
pop esi
|
|
||||||
pop edi
|
|
||||||
ret
|
|
||||||
|
|
||||||
; Static Values
|
|
||||||
vga_buf_pos_x:
|
|
||||||
db 0x00
|
|
||||||
vga_buf_pos_y:
|
|
||||||
db 0x00
|
|
||||||
|
|
||||||
; Strings
|
|
||||||
%define StrCRLF_NUL 0Dh, 0Ah, 00h
|
|
||||||
welcome_cstr:
|
|
||||||
db 'CBoot Stage3', StrCRLF_NUL
|
|
||||||
version_cstr:
|
|
||||||
db 'CBoot v0.0.3 ', 'NASM - ', __NASM_VER__, StrCRLF_NUL
|
|
||||||
datetime_cstr:
|
|
||||||
db 'Assembled - ', __DATE__, ' ', __TIME__, StrCRLF_NUL
|
|
||||||
|
|
||||||
ALIGN 16, db 0
|
|
||||||
stack_bottom:
|
|
||||||
times (512 * 8) db 0x00 ; 4KiB stack
|
|
||||||
stack_top:
|
|
||||||
|
|
||||||
%assign bytes_remaining ((MAX_BYTES - 4) - ($ - $$))
|
|
||||||
%warning boot32 has bytes_remaining bytes remaining for code (MAX: MMAX_BYTES)
|
|
||||||
|
|
||||||
times ((MAX_BYTES - 4) - ($ - $$)) db 0xFE
|
|
||||||
BOOT_SIG: dd 0xA0B0C0D0
|
|
||||||
99
src/miniboot32/BOOTi686.nasm
Executable file
99
src/miniboot32/BOOTi686.nasm
Executable file
@@ -0,0 +1,99 @@
|
|||||||
|
; Copyright (c) 2023 Elaina Claus
|
||||||
|
;
|
||||||
|
; Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
; of this software and associated documentation files (the "Software"), to deal
|
||||||
|
; in the Software without restriction, including without limitation the rights
|
||||||
|
; to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
; copies of the Software, and to permit persons to whom the Software is
|
||||||
|
; furnished to do so, subject to the following conditions:
|
||||||
|
;
|
||||||
|
; The above copyright notice and this permission notice shall be included in all
|
||||||
|
; copies or substantial portions of the Software.
|
||||||
|
;
|
||||||
|
; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
; IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
; FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
; AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
; LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
; SOFTWARE.
|
||||||
|
|
||||||
|
[BITS 32]
|
||||||
|
[ORG 0x100000]
|
||||||
|
[CPU KATMAI]
|
||||||
|
jmp short (init32 - $$) ; PI jump
|
||||||
|
nop
|
||||||
|
|
||||||
|
;;;
|
||||||
|
; Errors
|
||||||
|
; 0 = unused
|
||||||
|
; E = General Error
|
||||||
|
; S = magic signature not found at end of file
|
||||||
|
; O = OK
|
||||||
|
;;;
|
||||||
|
|
||||||
|
%define MAX_BYTES (1024 * 8)
|
||||||
|
%define VGA_BUF 0xb8000
|
||||||
|
|
||||||
|
; VGA memory is row-major => offset = (row * MAX_Colums) + colum
|
||||||
|
; macro array is counted from 0,0 = 1,1 => 79,24 is the last usable space in a page
|
||||||
|
%define VGA_OFFSET(x,y) (((y*VGA_MAX_X) + x)*2)
|
||||||
|
;subtract 1 for max array values
|
||||||
|
%define VGA_MAX_Y 25
|
||||||
|
%define VGA_MAX_X 80
|
||||||
|
|
||||||
|
ALIGN 16, db 0
|
||||||
|
init32:
|
||||||
|
mov ax, 0x10 ; 0x10 selector segment
|
||||||
|
mov ds, ax
|
||||||
|
mov es, ax
|
||||||
|
mov fs, ax
|
||||||
|
mov gs, ax
|
||||||
|
mov ss, ax ; load data registers with 2nd GDT selector
|
||||||
|
mov esp, stack_top
|
||||||
|
mov ebp, esp
|
||||||
|
|
||||||
|
mov eax, dword [BOOT_SIG]
|
||||||
|
cmp eax, 0xA0B0C0D0
|
||||||
|
jz .signature_present
|
||||||
|
|
||||||
|
mov dl, "S"
|
||||||
|
jmp .result
|
||||||
|
.signature_present:
|
||||||
|
mov dl, "O"
|
||||||
|
.result:
|
||||||
|
mov eax, VGA_BUF
|
||||||
|
add eax, VGA_OFFSET(73, 24)
|
||||||
|
|
||||||
|
mov dword [eax], 0x1f451f52
|
||||||
|
add eax, 0x4
|
||||||
|
mov dword [eax], 0x1f3e1f53
|
||||||
|
add eax, 0x4
|
||||||
|
; RES> in white-on-blue
|
||||||
|
|
||||||
|
mov ecx, 0x1f201f20
|
||||||
|
and cl, dl ; 0x1f201f(dl)
|
||||||
|
ror ecx, 16 ; 0x1f(dl)1f20 = ' (dl)'
|
||||||
|
mov dword [eax], ecx ; should be a space and contents of dl
|
||||||
|
.endp:
|
||||||
|
hlt
|
||||||
|
jmp .endp - $$
|
||||||
|
|
||||||
|
; Strings
|
||||||
|
ALIGN 16, db 0
|
||||||
|
%define StrCRLF_NUL 0Dh, 0Ah, 00h
|
||||||
|
version_cstr:
|
||||||
|
db 'CBoot v0.0.3 ', 'NASM - ', __NASM_VER__, StrCRLF_NUL
|
||||||
|
datetime_cstr:
|
||||||
|
db 'Assembled - ', __DATE__, ' ', __TIME__, StrCRLF_NUL
|
||||||
|
|
||||||
|
ALIGN 16, db 0
|
||||||
|
stack_bottom:
|
||||||
|
times (512 * 8) db 0x00 ; 4KiB stack
|
||||||
|
stack_top:
|
||||||
|
|
||||||
|
%assign bytes_remaining ((MAX_BYTES - 4) - ($ - $$))
|
||||||
|
%warning boot32 has bytes_remaining bytes remaining for code (MAX: MMAX_BYTES)
|
||||||
|
|
||||||
|
times ((MAX_BYTES - 4) - ($ - $$)) db 0xFE
|
||||||
|
BOOT_SIG: dd 0xA0B0C0D0
|
||||||
564
src/stage2/stage2.nasm
Executable file
564
src/stage2/stage2.nasm
Executable file
@@ -0,0 +1,564 @@
|
|||||||
|
; Copyright (c) 2023 Elaina Claus
|
||||||
|
;
|
||||||
|
; Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
; of this software and associated documentation files (the "Software"), to deal
|
||||||
|
; in the Software without restriction, including without limitation the rights
|
||||||
|
; to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
; copies of the Software, and to permit persons to whom the Software is
|
||||||
|
; furnished to do so, subject to the following conditions:
|
||||||
|
;
|
||||||
|
; The above copyright notice and this permission notice shall be included in all
|
||||||
|
; copies or substantial portions of the Software.
|
||||||
|
;
|
||||||
|
; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
; IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
; FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
; AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
; LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
; SOFTWARE.
|
||||||
|
|
||||||
|
[BITS 16]
|
||||||
|
[ORG 0x0500] ; IF YOU CHANGE ORG CHANGE THE SIGN OFFSET AT THE END
|
||||||
|
[CPU KATMAI]
|
||||||
|
[map all stage2.map]
|
||||||
|
[WARNING -reloc-abs-byte]
|
||||||
|
[WARNING -reloc-abs-word]
|
||||||
|
[WARNING -reloc-abs-dword] ; Yes, we use absolute addresses. surpress these warnings.
|
||||||
|
%define __STEVIA_STAGE2
|
||||||
|
%define __STAGE2_SEGMENT 0x0000
|
||||||
|
|
||||||
|
; ###############
|
||||||
|
; Headers/Includes/Definitions
|
||||||
|
; ###############
|
||||||
|
|
||||||
|
%include "util/bochs_magic.inc"
|
||||||
|
%include "cdecl16.inc"
|
||||||
|
%include "entry.inc"
|
||||||
|
%include "config.inc"
|
||||||
|
%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
|
||||||
|
; ax = word part_offset (active partition offset)
|
||||||
|
; si = ptr PartTable_t partition_table
|
||||||
|
; di = ptr FAT32_bpb_t fat32_bpb
|
||||||
|
ALIGN 4, db 0x90
|
||||||
|
init:
|
||||||
|
cli ; We do not want to be interrupted
|
||||||
|
|
||||||
|
; these 4 are stored in the .data section and are effectivly const types
|
||||||
|
mov [vbr_part_table_ptr], si ; pointer to partition_table
|
||||||
|
mov [vbr_fat32_bpb_ptr], di ; pointer to fat32_bpb
|
||||||
|
mov [boot_drive], dl ; copy boot_drive to globals
|
||||||
|
mov [partition_offset], ax ; copy partition_offset to globals
|
||||||
|
|
||||||
|
mov ax, __STAGE2_SEGMENT ; set all our segments to the configured segment, except es
|
||||||
|
mov ds, ax ; *
|
||||||
|
mov fs, ax ; *
|
||||||
|
mov gs, ax ; *
|
||||||
|
mov ss, ax
|
||||||
|
|
||||||
|
; Zero BSS section
|
||||||
|
mov cx, (end_bss - begin_bss) ; count = bss length
|
||||||
|
|
||||||
|
mov ax, begin_bss
|
||||||
|
shr ax, 4
|
||||||
|
mov es, ax ; es = begining of bss section, remember to restore ES later
|
||||||
|
|
||||||
|
xor ax, ax ; val = 0
|
||||||
|
mov di, ax ; dst = 0 (start of segment)
|
||||||
|
cld
|
||||||
|
rep stosb
|
||||||
|
|
||||||
|
mov ax, __STAGE2_SEGMENT
|
||||||
|
mov es, ax
|
||||||
|
; done zeroing bss section
|
||||||
|
|
||||||
|
mov sp, stack_top
|
||||||
|
mov bp, sp
|
||||||
|
sub sp, 0x10
|
||||||
|
push bp ; setup a somewhat normal stack frame, minus a ret ptr
|
||||||
|
|
||||||
|
sti
|
||||||
|
jmp word __STAGE2_SEGMENT:main
|
||||||
|
|
||||||
|
; ###############
|
||||||
|
; Functions
|
||||||
|
; ###############
|
||||||
|
|
||||||
|
%include "util/kmem_func.nasm"
|
||||||
|
%include "util/kmemcpy5_func.nasm"
|
||||||
|
%include "util/kmemset4_func.nasm"
|
||||||
|
%include "util/error_func.nasm"
|
||||||
|
|
||||||
|
; ###############
|
||||||
|
; FAT32 Driver
|
||||||
|
; ###############
|
||||||
|
|
||||||
|
%include 'fat32/FAT32_SYS.inc'
|
||||||
|
|
||||||
|
; ###############
|
||||||
|
; BIOS functions
|
||||||
|
; ###############
|
||||||
|
|
||||||
|
%include 'BIOS/BIOS_SYS.inc'
|
||||||
|
|
||||||
|
; structures
|
||||||
|
|
||||||
|
struc SteviaInfoStruct_t
|
||||||
|
.MemoryMapPtr resd 1
|
||||||
|
.MemoryMapEntries resd 1
|
||||||
|
endstruc
|
||||||
|
|
||||||
|
struc EarlyBootStruct_t
|
||||||
|
.partition_table resb PartTable_t_size
|
||||||
|
.fat32_bpb resb FAT32_bpb_t_size
|
||||||
|
.fat32_ebpb resb FAT32_ebpb_t_size
|
||||||
|
endstruc
|
||||||
|
|
||||||
|
ALIGN 4, db 0x90
|
||||||
|
main:
|
||||||
|
__BOCHS_MAGIC_DEBUG
|
||||||
|
.check_sig:
|
||||||
|
mov eax, dword [STAGE2_SIG]
|
||||||
|
cmp eax, 0xDEADBEEF
|
||||||
|
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
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
call SetTextMode
|
||||||
|
call disable_cursor
|
||||||
|
print_string HelloPrompt_cstr
|
||||||
|
|
||||||
|
; enable A20 gate
|
||||||
|
call EnableA20
|
||||||
|
print_string A20_Enabled_OK_cstr
|
||||||
|
|
||||||
|
; get system memory map
|
||||||
|
call GetMemoryMap
|
||||||
|
print_string MemoryMap_OK_cstr
|
||||||
|
|
||||||
|
; enter unreal mode
|
||||||
|
call EnterUnrealMode
|
||||||
|
print_string UnrealMode_OK_cstr
|
||||||
|
|
||||||
|
; FAT Driver setup
|
||||||
|
call InitFATDriver
|
||||||
|
print_string InitFATSYS_OK_cstr
|
||||||
|
|
||||||
|
;
|
||||||
|
; Find first cluster of bootable file
|
||||||
|
call SearchFATDIR
|
||||||
|
push dword eax ; save first cluster of bootable file
|
||||||
|
|
||||||
|
print_string FileFound_OK_cstr
|
||||||
|
|
||||||
|
pop dword eax
|
||||||
|
push dword eax ; print Cluster of boot file
|
||||||
|
call PrintDWORD ; void PrintDWORD(uint32_t dword)
|
||||||
|
print_string NewLine_cstr
|
||||||
|
|
||||||
|
; TODO: using first cluster information, start loading the kernel to memory
|
||||||
|
; TODO: going to need an elf parser, some unreal mode file buffer functions to move the data
|
||||||
|
hcf:
|
||||||
|
ERROR STEVIA_DEBUG_OK
|
||||||
|
|
||||||
|
; ##############################
|
||||||
|
;
|
||||||
|
; SYSTEM CONFIGURATION FUNCTIONS
|
||||||
|
;
|
||||||
|
; ##############################
|
||||||
|
|
||||||
|
; Prints a C-Style string (null terminated) using BIOS vga teletype call
|
||||||
|
; void PrintString(char* buf)
|
||||||
|
ALIGN 4, db 0x90
|
||||||
|
PrintString:
|
||||||
|
__CDECL16_ENTRY
|
||||||
|
mov di, [bp + 4] ; first arg is char*
|
||||||
|
.str_len:
|
||||||
|
xor cx, cx ; ECX = 0
|
||||||
|
not cx ; ECX = -1 == 0xFFFF
|
||||||
|
xor ax, ax ; search for al = 0x0
|
||||||
|
|
||||||
|
cld
|
||||||
|
repne scasb ; deincrement cx while searching for al
|
||||||
|
|
||||||
|
not cx ; the inverse of a neg number = abs(x) - 1
|
||||||
|
dec cx ; CX contains the length of the string - nul byte at end
|
||||||
|
.print:
|
||||||
|
mov si, [bp + 4] ; source string
|
||||||
|
.print_L0:
|
||||||
|
movzx ax, byte [si]
|
||||||
|
push ax
|
||||||
|
call PrintCharacter
|
||||||
|
add sp, 0x2
|
||||||
|
|
||||||
|
inc si
|
||||||
|
dec cx
|
||||||
|
|
||||||
|
jcxz PrintString.endp
|
||||||
|
jmp PrintString.print_L0 ; Fetch next character from string
|
||||||
|
.endp:
|
||||||
|
__CDECL16_EXIT
|
||||||
|
ret ; Return from procedure
|
||||||
|
|
||||||
|
; Prints a single character
|
||||||
|
; void PrintCharacter(char c);
|
||||||
|
ALIGN 4, db 0x90
|
||||||
|
PrintCharacter:
|
||||||
|
__CDECL16_ENTRY
|
||||||
|
.func:
|
||||||
|
mov ax, [bp + 4] ; c
|
||||||
|
mov dx, 0x00ff
|
||||||
|
and ax, dx
|
||||||
|
|
||||||
|
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:
|
||||||
|
lea 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
|
||||||
|
|
||||||
|
lgdt [((__STAGE2_SEGMENT << 4) + unreal_gdt_info)] ; load unreal gdt
|
||||||
|
|
||||||
|
mov eax, cr0
|
||||||
|
or al,1 ; set pmode bit
|
||||||
|
mov cr0, eax ; switch to pmode
|
||||||
|
jmp short $+2
|
||||||
|
|
||||||
|
;jmp far 0x0008:EnterUnrealMode.load_cs
|
||||||
|
db 0xEA ; jmp far imm16:imm16
|
||||||
|
dw EnterUnrealMode.load_cs ; error_far_ptr
|
||||||
|
dw 0x0008 ; error_far_seg
|
||||||
|
.load_cs:
|
||||||
|
mov bx, 0x10 ; select descriptor 2
|
||||||
|
mov ds, bx ; 10h = 0001_0000b
|
||||||
|
|
||||||
|
mov ss, bx
|
||||||
|
mov es, bx
|
||||||
|
mov fs, bx
|
||||||
|
mov gs, bx ; other data/stack to index 2 (off 0x10)
|
||||||
|
|
||||||
|
and al,0xFE ; toggle bit 1 of cr0
|
||||||
|
mov cr0, eax ; back to realmode
|
||||||
|
jmp short $+2
|
||||||
|
|
||||||
|
;jmp far 0x0008:EnterUnrealMode.unload_cs
|
||||||
|
db 0xEA ; jmp far imm16:imm16
|
||||||
|
dw EnterUnrealMode.unload_cs ; error_far_ptr
|
||||||
|
__UNREAL_SEGMENT:
|
||||||
|
dw 0x0000 ; error_far_seg
|
||||||
|
EnterUnrealMode.unload_cs:
|
||||||
|
pop ss
|
||||||
|
pop gs
|
||||||
|
pop fs
|
||||||
|
pop es
|
||||||
|
pop ds ; get back old segments
|
||||||
|
sti
|
||||||
|
.endp:
|
||||||
|
__CDECL16_EXIT
|
||||||
|
ret
|
||||||
|
end_text:
|
||||||
|
|
||||||
|
section .data follows=.text
|
||||||
|
align 512
|
||||||
|
begin_data:
|
||||||
|
; #############
|
||||||
|
;
|
||||||
|
; Strings
|
||||||
|
;
|
||||||
|
; #############
|
||||||
|
|
||||||
|
%macro define_str 2
|
||||||
|
ALIGN 16
|
||||||
|
%1_str:
|
||||||
|
db %2
|
||||||
|
%define str_len %strlen(%2) ; string
|
||||||
|
%1_str_len:
|
||||||
|
dd str_len
|
||||||
|
%endmacro
|
||||||
|
|
||||||
|
; TODO: technically this is a cstr but it splices a return and newline on the end
|
||||||
|
; TODO: this probably should be seperated out and the printing functionality should
|
||||||
|
; TODO: place that newline and return
|
||||||
|
%macro define_cstr 2
|
||||||
|
%define CRLF_NUL 0Dh, 0Ah, 00h
|
||||||
|
ALIGN 16
|
||||||
|
%1_cstr:
|
||||||
|
db %2, CRLF_NUL
|
||||||
|
%endmacro
|
||||||
|
|
||||||
|
define_cstr HelloPrompt, "Hello from Stevia Stage2!"
|
||||||
|
define_cstr A20_Enabled_OK, "A20 Enabled OK"
|
||||||
|
define_cstr MemoryMap_OK, "Memory map OK"
|
||||||
|
define_cstr UnrealMode_OK, "Unreal mode OK"
|
||||||
|
define_cstr FileFound_OK, "Found SFN entry for bootable binary, first cluster -> "
|
||||||
|
define_cstr InitFATSYS_OK, "FAT32 Driver Init..."
|
||||||
|
|
||||||
|
define_cstr SearchFATDIR_INFO, "Searching FAT DIR for bootable file..."
|
||||||
|
define_cstr NextFATCluster_INFO, "Attempting to find next FAT cluster..."
|
||||||
|
define_cstr ReadFATCluster_INFO, "Attempting to load next FAT"
|
||||||
|
define_cstr MaybeFound_Boot_INFO, "Maybe found a file...checking..."
|
||||||
|
define_cstr NewLine, ""
|
||||||
|
|
||||||
|
define_str BootTarget, "BOOT BIN"
|
||||||
|
|
||||||
|
;
|
||||||
|
; pre-bss init globals (generally const...but there are exceptions)
|
||||||
|
;
|
||||||
|
|
||||||
|
align 8, db 0x00
|
||||||
|
boot_drive:
|
||||||
|
db 0x00
|
||||||
|
|
||||||
|
align 8, db 0x00
|
||||||
|
partition_offset:
|
||||||
|
dw 0x0000
|
||||||
|
|
||||||
|
align 8, db 0x00
|
||||||
|
vbr_fat32_bpb_ptr:
|
||||||
|
dw 0x0000
|
||||||
|
|
||||||
|
align 8, db 0x00
|
||||||
|
vbr_part_table_ptr:
|
||||||
|
dw 0x0000
|
||||||
|
|
||||||
|
ALIGN 16
|
||||||
|
IntToHex_table:
|
||||||
|
db '0123456789ABCDEF'
|
||||||
|
|
||||||
|
; see docs/gdt.txt for a quick refresher on GDT
|
||||||
|
ALIGN 16, db 0
|
||||||
|
unreal_gdt_info:
|
||||||
|
unreal_gdt_size: dw (unreal_gdt_end - unreal_gdt_start) - 1
|
||||||
|
unreal_gdt_ptr: dd ((__STAGE2_SEGMENT << 4) + unreal_gdt_start)
|
||||||
|
unreal_gdt_start:
|
||||||
|
; entry 0 (null descriptor)
|
||||||
|
dq 0 ; first entry is null
|
||||||
|
|
||||||
|
; entry 1 (16bit code 64KiB limit)
|
||||||
|
dd 0x0000FFFF ; Base Address(15:0) 31:16, Segment Limit(15:0) 15:0
|
||||||
|
db 0x00 ; Base Address 23:16
|
||||||
|
db 1001_1010b ; Access Byte: Present, ring0, S = 1, executable (1), non-conforming, readable, Accessed
|
||||||
|
db 0000_0000b ; Flags: GR = 4KiB, attr = <DB/L/Avl>, Granularity = 4KiB & 16:19 of limit
|
||||||
|
db 0x00 ; Base Address 31:24
|
||||||
|
|
||||||
|
; entry 2 (16bit data segment with 4 GiB flat mapping)
|
||||||
|
dd 0x0000FFFF ; Base Address(15:0) 31:16, Segment Limit(15:0) 15:0
|
||||||
|
db 0x00 ; Base Address(23:16)
|
||||||
|
db 1001_0010b ; Access Byte: Present, ring0, S = 1, data (0), non-confirming, writable, present
|
||||||
|
db 1000_1111b ; Flags: GR = 4KiB, attr = <16-bit/?/?>, Granularity = 4KiB & 16:19 of limit
|
||||||
|
db 0x00 ; Base Address(31:24)
|
||||||
|
unreal_gdt_end:
|
||||||
|
|
||||||
|
ALIGN 16, db 0
|
||||||
|
gdt32_info:
|
||||||
|
gdt32_size: dw (gdt32_end - gdt32_start) - 1
|
||||||
|
gdt32_ptr: dd ((__STAGE2_SEGMENT << 4) + gdt32_start)
|
||||||
|
gdt32_start:
|
||||||
|
dq 0
|
||||||
|
.gdt32_code:
|
||||||
|
dw 0xFFFF ; code segment (RX)
|
||||||
|
dw 0x0000
|
||||||
|
db 0x00
|
||||||
|
db 1001_1000b ; Access: readable, executable
|
||||||
|
db 1100_1111b ; 4KB granularity, 32-bit
|
||||||
|
db 0x00
|
||||||
|
.gdt32_data: ; data segment (RW)
|
||||||
|
dw 0xFFFF
|
||||||
|
dw 0x0000
|
||||||
|
db 0x00
|
||||||
|
db 1001_0010b ; Access: readable, writable
|
||||||
|
db 1100_1111b ; 4KB granularity, 32-bit
|
||||||
|
db 0x00
|
||||||
|
.gdt32_stack: ; Stack segment (RW)
|
||||||
|
dw 0xFFFF
|
||||||
|
dw 0x0000
|
||||||
|
db 0x00
|
||||||
|
db 1001_0010b ; Access: readable, writable
|
||||||
|
db 1100_1111b ; 4KB granularity, 32-bit
|
||||||
|
db 0x00
|
||||||
|
.gdt32_ro_data: ; Read-only data segment (RO)
|
||||||
|
dw 0xFFFF
|
||||||
|
dw 0x0000
|
||||||
|
db 0x00
|
||||||
|
db 1001_0000b ; Access: readable, not writable
|
||||||
|
db 1100_1111b ; 4KB granularity, 32-bit
|
||||||
|
db 0x00
|
||||||
|
gdt32_end:
|
||||||
|
|
||||||
|
ALIGN 8,db 0x00
|
||||||
|
BUILD_NASM_VER:
|
||||||
|
db "Stevia Stage2 built with NASM - ", __NASM_VER__, 00h
|
||||||
|
|
||||||
|
ALIGN 8,db 0x00
|
||||||
|
BUILD_DATETIME:
|
||||||
|
db 'Assembled - ', __DATE__, ' ', __TIME__, 00h
|
||||||
|
|
||||||
|
ALIGN 8,db 0x00
|
||||||
|
BUILD_GIT_VER:
|
||||||
|
db __GIT_VER__, 00h
|
||||||
|
|
||||||
|
ALIGN 8,db 0x00
|
||||||
|
BUILD_GIT_HASH:
|
||||||
|
db __GIT_HASH__, 00h
|
||||||
|
end_data:
|
||||||
|
|
||||||
|
%assign bytes_remaining ((MAX_STAGE2_BYTES - 4) - (($ - $$) + (end_text - begin_text)))
|
||||||
|
%warning STAGE2 has bytes_remaining bytes remaining for code/data (MAX: MAX_STAGE2_BYTES)
|
||||||
|
|
||||||
|
; section start location needs to be a 'critical expression'
|
||||||
|
; i.e resolvable at build time, we are setting 0x7E00 as the offset since
|
||||||
|
section .sign start=((MAX_STAGE2_BYTES - 512) + 0x0500)
|
||||||
|
times ((512 - 4) - ($ -$$) ) db 0x90 ; nop
|
||||||
|
STAGE2_SIG: dd 0xDEADBEEF ; Signature to mark the end of the stage2
|
||||||
|
|
||||||
|
section .bss follows=.sign
|
||||||
|
begin_bss:
|
||||||
|
; structures
|
||||||
|
|
||||||
|
align 8, resb 1
|
||||||
|
partition_table resb PartTable_t_size
|
||||||
|
|
||||||
|
align 8, resb 1
|
||||||
|
fat32_bpb resb FAT32_bpb_t_size
|
||||||
|
fat32_ebpb resb FAT32_ebpb_t_size
|
||||||
|
|
||||||
|
align 8, resb 1
|
||||||
|
fat32_nc_data resb 16
|
||||||
|
|
||||||
|
align 8, resb 1
|
||||||
|
lba_packet resb LBAPkt_t_size
|
||||||
|
|
||||||
|
align 8, resb 1
|
||||||
|
fat32_state:
|
||||||
|
resb FAT32_State_t_size
|
||||||
|
|
||||||
|
align 8, resb 1
|
||||||
|
SteviaInfo:
|
||||||
|
resd 4
|
||||||
|
;
|
||||||
|
; post-bss init globals
|
||||||
|
;
|
||||||
|
|
||||||
|
;
|
||||||
|
; large continuous allocations
|
||||||
|
;
|
||||||
|
align 16, resb 1
|
||||||
|
disk_buffer:
|
||||||
|
resb 512
|
||||||
|
fat_buffer:
|
||||||
|
resb 512
|
||||||
|
dir_buffer:
|
||||||
|
resb 512
|
||||||
|
fat_fsinfo:
|
||||||
|
resb 512
|
||||||
|
|
||||||
|
align 16, resb 1
|
||||||
|
%define BIOSMemoryMap_SIZE 2048
|
||||||
|
BIOSMemoryMap:
|
||||||
|
resb 2048
|
||||||
|
|
||||||
|
align 512, resb 1
|
||||||
|
stack_bottom:
|
||||||
|
resb 1024
|
||||||
|
stack_top:
|
||||||
|
end_bss:
|
||||||
1187
src/stage2/stage2.s
1187
src/stage2/stage2.s
File diff suppressed because it is too large
Load Diff
195
src/vbr/vbr.nasm
Executable file
195
src/vbr/vbr.nasm
Executable file
@@ -0,0 +1,195 @@
|
|||||||
|
; Copyright (c) 2023 Elaina Claus
|
||||||
|
;
|
||||||
|
; Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
; of this software and associated documentation files (the "Software"), to deal
|
||||||
|
; in the Software without restriction, including without limitation the rights
|
||||||
|
; to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
; copies of the Software, and to permit persons to whom the Software is
|
||||||
|
; furnished to do so, subject to the following conditions:
|
||||||
|
;
|
||||||
|
; The above copyright notice and this permission notice shall be included in all
|
||||||
|
; copies or substantial portions of the Software.
|
||||||
|
;
|
||||||
|
; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
; IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
; FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
; AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
; LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
; SOFTWARE.
|
||||||
|
[BITS 16]
|
||||||
|
[ORG 0x7C00]
|
||||||
|
[CPU KATMAI]
|
||||||
|
[WARNING -reloc-abs-byte]
|
||||||
|
[WARNING -reloc-abs-word]
|
||||||
|
[map all vbr.map] ; Yes, we use absolute addresses. surpress these warnings.
|
||||||
|
%define __STEVIA_VBR
|
||||||
|
section .text
|
||||||
|
__ENTRY:
|
||||||
|
jmp short (init - $$)
|
||||||
|
nop
|
||||||
|
|
||||||
|
; fill BPB area with 0x00 since we skip writing this part to disk
|
||||||
|
; but we need it for the 'jmp short entry; nop' above
|
||||||
|
times 33 db 0x00
|
||||||
|
phy_ebpb_start:
|
||||||
|
; fill eBPB area with 0x00 since we skip writing this part to disk
|
||||||
|
times 54 db 0x00
|
||||||
|
|
||||||
|
; ###############
|
||||||
|
;
|
||||||
|
; Headers/Includes/Definitions
|
||||||
|
;
|
||||||
|
; ###############
|
||||||
|
|
||||||
|
%include "util/bochs_magic.inc"
|
||||||
|
%include "cdecl16.inc"
|
||||||
|
%include "entry.inc"
|
||||||
|
%include "config.inc"
|
||||||
|
%include "early_mem.inc"
|
||||||
|
%include "error_codes.inc"
|
||||||
|
%include "partition_table.inc"
|
||||||
|
%include "fat32/fat32_structures.inc"
|
||||||
|
|
||||||
|
%undef __STEVIA_DEV_DEBUG
|
||||||
|
|
||||||
|
; dl = boot_drive
|
||||||
|
; si = part_offset
|
||||||
|
; bx = partition_table location from mbr
|
||||||
|
ALIGN 4
|
||||||
|
init:
|
||||||
|
cli ; We do not want to be interrupted
|
||||||
|
xor ax, ax
|
||||||
|
mov ds, ax ; Set segment registers to 0x0000
|
||||||
|
mov es, ax
|
||||||
|
mov fs, ax
|
||||||
|
mov gs, ax
|
||||||
|
|
||||||
|
mov ss, ax ; Set Stack Segment to 0
|
||||||
|
mov sp, end_bss ; Setup stack
|
||||||
|
mov bp, sp ; base ptr = stack ptr
|
||||||
|
|
||||||
|
; zero bss section
|
||||||
|
mov cx, (end_bss - begin_bss) ; count = bss length
|
||||||
|
mov ax, begin_bss
|
||||||
|
mov di, ax ; es:di is dest
|
||||||
|
xor ax, ax
|
||||||
|
cld
|
||||||
|
rep stosb
|
||||||
|
|
||||||
|
sub sp, 0x20 ; local varible space
|
||||||
|
push bp
|
||||||
|
|
||||||
|
sti ; all done with inital setup and relocation, reenable interupts
|
||||||
|
|
||||||
|
jmp 0:main ; fix up cs:ip just in case and jump to relocated code
|
||||||
|
|
||||||
|
; ###############
|
||||||
|
; Extra/Shared Functions
|
||||||
|
; ###############
|
||||||
|
|
||||||
|
%include "util/kmem_func.nasm"
|
||||||
|
%include "util/error_func.nasm"
|
||||||
|
|
||||||
|
; ###############
|
||||||
|
; End Section
|
||||||
|
; ###############
|
||||||
|
|
||||||
|
;
|
||||||
|
; byte boot_drive @ bp - 2
|
||||||
|
; word part_offset @ bp - 4
|
||||||
|
; ptr partition_table
|
||||||
|
ALIGN 4, db 0x90
|
||||||
|
main:
|
||||||
|
mov byte [bp - 2], dl ; boot_drive
|
||||||
|
mov word [bp - 4], si ; part_offset
|
||||||
|
mov word [bp - 6], bx ; partition_table
|
||||||
|
|
||||||
|
.load_fs_data:
|
||||||
|
mov ax, PartTable_t_size ; count=
|
||||||
|
push ax
|
||||||
|
mov ax, [bp - 6] ; src= ptr partition_table
|
||||||
|
push ax
|
||||||
|
mov ax, partition_table ; dst=
|
||||||
|
push ax
|
||||||
|
call kmemcpy ; copy partition table data
|
||||||
|
add sp, 0x6
|
||||||
|
|
||||||
|
mov ax, (FAT32_bpb_t_size + FAT32_ebpb_t_size) ; size in byte, should be 90 bytes
|
||||||
|
push ax
|
||||||
|
mov ax, __ENTRY
|
||||||
|
push ax
|
||||||
|
mov ax, fat32_bpb ;
|
||||||
|
push ax
|
||||||
|
call kmemcpy ; copy bpb & ebpb to memory
|
||||||
|
add sp, 0x6
|
||||||
|
|
||||||
|
.check_FAT_size: ; we only support a very specific setup of FAT32
|
||||||
|
mov bx, fat32_bpb
|
||||||
|
cmp dword [bx + FAT32_bpb_t.sector_count_32], 0 ; SectorsHuge will not be set if FAT12/16
|
||||||
|
ja main.load_stage2
|
||||||
|
ERROR VBR_ERROR_WRONG_FAT_SIZE
|
||||||
|
.load_stage2:
|
||||||
|
; read sectors 1-(MAX_STAGE2_BYTES / 512) to stage2 entry point
|
||||||
|
movzx ax, byte [bp - 2]
|
||||||
|
push ax ; drive_num
|
||||||
|
|
||||||
|
mov ax, STAGE2_SECTOR_COUNT
|
||||||
|
push ax ; count
|
||||||
|
|
||||||
|
mov dword eax, 0x1
|
||||||
|
push dword eax ; lba
|
||||||
|
|
||||||
|
mov ax, STAGE2_ENTRY
|
||||||
|
push ax ; offset
|
||||||
|
|
||||||
|
xor ax, ax
|
||||||
|
push ax ; segment = 0
|
||||||
|
|
||||||
|
; uint8_t read_stage2_raw(uint16_t buf_segment, uint16_t buf_offset,
|
||||||
|
; uint32_t lba,
|
||||||
|
; uint16_t count, uint16_t drive_num)
|
||||||
|
call read_disk_raw
|
||||||
|
add sp, 0xC
|
||||||
|
.enter_stage2:
|
||||||
|
mov dl, byte [bp - 2] ; byte boot_drive
|
||||||
|
mov ax, word [bp - 4] ; word part_offset
|
||||||
|
mov si, partition_table ; ptr partition_table
|
||||||
|
mov di, fat32_bpb ; ptr fat32_bpb
|
||||||
|
jmp word 0x0000:STAGE2_ENTRY
|
||||||
|
|
||||||
|
; ###############
|
||||||
|
; Required BIOS function(s)
|
||||||
|
; ###############
|
||||||
|
|
||||||
|
%include 'BIOS/func/ext_read.nasm'
|
||||||
|
|
||||||
|
%assign bytes_remaining (420 - ($ - $$))
|
||||||
|
%warning VBR has bytes_remaining bytes remaining for code (MAX: 420 bytes)
|
||||||
|
|
||||||
|
times (510 - ($ - $$)) nop ; Fill the rest of sector with nop
|
||||||
|
|
||||||
|
BootSig:
|
||||||
|
dw 0xAA55 ; Add boot signature at the end of bootloader
|
||||||
|
|
||||||
|
section .bss follows=.text
|
||||||
|
begin_bss:
|
||||||
|
|
||||||
|
align 16, resb 1
|
||||||
|
partition_table resb PartTable_t_size
|
||||||
|
|
||||||
|
align 16, resb 1
|
||||||
|
fat32_bpb resb FAT32_bpb_t_size
|
||||||
|
fat32_ebpb resb FAT32_ebpb_t_size
|
||||||
|
|
||||||
|
align 16, resb 1
|
||||||
|
fat32_nc_data resb 16
|
||||||
|
|
||||||
|
align 16, resb 1
|
||||||
|
lba_packet resb LBAPkt_t_size
|
||||||
|
|
||||||
|
align 512, resb 1
|
||||||
|
stack_bottom resb 512 ; 512b stack early on
|
||||||
|
stack_top:
|
||||||
|
vbr_redzone resb 32
|
||||||
|
end_bss:
|
||||||
225
src/vbr/vbr.s
225
src/vbr/vbr.s
@@ -1,225 +0,0 @@
|
|||||||
; Copyright (c) 2023 Elaina Claus
|
|
||||||
;
|
|
||||||
; Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
; of this software and associated documentation files (the "Software"), to deal
|
|
||||||
; in the Software without restriction, including without limitation the rights
|
|
||||||
; to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
; copies of the Software, and to permit persons to whom the Software is
|
|
||||||
; furnished to do so, subject to the following conditions:
|
|
||||||
;
|
|
||||||
; The above copyright notice and this permission notice shall be included in all
|
|
||||||
; copies or substantial portions of the Software.
|
|
||||||
;
|
|
||||||
; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
; IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
; FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
; AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
; LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
; SOFTWARE.
|
|
||||||
|
|
||||||
|
|
||||||
[BITS 16]
|
|
||||||
[ORG 0x7C00]
|
|
||||||
[CPU KATMAI]
|
|
||||||
jmp short init
|
|
||||||
nop
|
|
||||||
|
|
||||||
bpb_start:
|
|
||||||
; fill BPB area with 0x00 since we skip writing this part to disk
|
|
||||||
; but we need it for the 'jmp short entry; nop' above
|
|
||||||
times 33 db 0x00
|
|
||||||
|
|
||||||
ebpb_start:
|
|
||||||
; fill BPB area with 0x00 since we skip writing this part to disk
|
|
||||||
; but we need it for the 'jmp short entry; nop' above
|
|
||||||
times 54 db 0x00
|
|
||||||
|
|
||||||
%include "entry.inc"
|
|
||||||
init:
|
|
||||||
cli ; We do not want to be interrupted
|
|
||||||
|
|
||||||
xor ax, ax ; 0 AX
|
|
||||||
mov ds, ax ; Set segment registers to 0
|
|
||||||
mov es, ax ; *
|
|
||||||
|
|
||||||
mov ss, ax ; Set Stack Segment to 0
|
|
||||||
mov sp, STACK_START ; Setup stack
|
|
||||||
mov bp, sp ; base ptr = stack ptr
|
|
||||||
|
|
||||||
mov bx, VBR_ENTRY ; move BP to the new start of the initial boot sector
|
|
||||||
|
|
||||||
jmp 0:main ; fix up cs:ip just in case and jump to relocated code
|
|
||||||
|
|
||||||
%include "config.inc"
|
|
||||||
%include "errors.inc"
|
|
||||||
%include "memory.inc"
|
|
||||||
|
|
||||||
%include "partition_table.inc"
|
|
||||||
|
|
||||||
%include "fat32/bpb.inc"
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
main:
|
|
||||||
sti ; all done with inital setup and relocation, reenable interupts
|
|
||||||
mov [bsDriveNumber], dl ; BIOS passes drive number in DL
|
|
||||||
mov [partition_offset], si ; save passed partition entry offset
|
|
||||||
|
|
||||||
.check_FAT_size:
|
|
||||||
cmp dword [bsSectorHuge], 0 ; SectorsHuge will not be set if FAT12/16
|
|
||||||
ja main.load_stage2
|
|
||||||
|
|
||||||
ERROR VBR_ERROR_WRONG_FAT_SIZE
|
|
||||||
|
|
||||||
; read sectors 1-63 to stage2 entry point
|
|
||||||
.load_stage2:
|
|
||||||
push bp
|
|
||||||
mov bp, sp
|
|
||||||
|
|
||||||
;uint8_t read_disk_raw(size_t count, uint16_t buf_segment, uint16_t buf_offset,
|
|
||||||
; uint16_t lower_lower_lba, uint16_t upper_lower_lba)
|
|
||||||
|
|
||||||
xor ax, ax
|
|
||||||
push ax ; upper_lower_lba = 0
|
|
||||||
|
|
||||||
mov ax , 1
|
|
||||||
push ax ; lower_lower_lba = 1
|
|
||||||
|
|
||||||
xor ax, ax
|
|
||||||
push ax ; offset = 0
|
|
||||||
|
|
||||||
; 07E0:0
|
|
||||||
mov ax, STAGE2_ENTRY
|
|
||||||
shr ax, 4
|
|
||||||
push ax ; segment = 7E0
|
|
||||||
|
|
||||||
mov ax, STAGE2_SECTOR_COUNT
|
|
||||||
push ax
|
|
||||||
|
|
||||||
call read_disk_raw
|
|
||||||
leave
|
|
||||||
|
|
||||||
.check_sig:
|
|
||||||
mov ax, 0x7E0
|
|
||||||
mov fs, ax
|
|
||||||
cmp dword [fs:0x7FFC], 0xDEADBEEF
|
|
||||||
je main.sig_ok
|
|
||||||
|
|
||||||
ERROR VBR_ERROR_NO_SIGNATURE ; no signature present in stage2
|
|
||||||
|
|
||||||
.sig_ok:
|
|
||||||
push bp
|
|
||||||
mov bp, sp
|
|
||||||
mov ax, fat32_bpb_SIZE ; size in byte
|
|
||||||
push ax
|
|
||||||
mov ax, bpb_start ; start of bpb
|
|
||||||
push ax
|
|
||||||
mov ax, fat32_bpb ; defined in memory.inc, destination
|
|
||||||
push ax
|
|
||||||
call kmemcpy ; copy bpb to memory
|
|
||||||
leave
|
|
||||||
|
|
||||||
push bp
|
|
||||||
mov bp, sp
|
|
||||||
mov ax, fat32_ebpb_SIZE ; 72 bytes of data
|
|
||||||
push ax
|
|
||||||
mov ax, ebpb_start ; start of ebpb
|
|
||||||
push ax
|
|
||||||
mov ax, fat32_ebpb ; defined in memory.inc, destination
|
|
||||||
push ax
|
|
||||||
call kmemcpy ; copy ebpb to memory
|
|
||||||
leave
|
|
||||||
|
|
||||||
mov si, [partition_offset]
|
|
||||||
mov dl, [bsDriveNumber]
|
|
||||||
jmp 0:0x7E00
|
|
||||||
|
|
||||||
stop:
|
|
||||||
hlt
|
|
||||||
jmp short stop
|
|
||||||
|
|
||||||
; Wrapper for AH=0x42 INT13h (Extended Read)
|
|
||||||
;
|
|
||||||
; BIOS call details
|
|
||||||
; AH = 42h
|
|
||||||
; DL = drive number
|
|
||||||
; DS:SI -> disk address packet
|
|
||||||
;
|
|
||||||
; Return:
|
|
||||||
; CF clear if successful
|
|
||||||
; AH = 00h
|
|
||||||
; CF set on error
|
|
||||||
; AH = error code
|
|
||||||
; disk address packet's block count field set to number of blocks
|
|
||||||
; successfully transferred
|
|
||||||
;
|
|
||||||
;
|
|
||||||
; uint8_t read_disk_raw(uint16_t buf_segment, uint16_t buf_offset, uint16_t lower_lower_lba, uint16_t upper_lower_lba)
|
|
||||||
; bp-0 = call frame
|
|
||||||
; bp-2 = upper_lower_lba
|
|
||||||
; bp-4 = lower_lower_lba
|
|
||||||
; bp-6 = offset
|
|
||||||
; bp-8 = segment
|
|
||||||
; bp-10 = count
|
|
||||||
; bp-12 = ret ptr
|
|
||||||
read_disk_raw:
|
|
||||||
push si
|
|
||||||
|
|
||||||
; uint8_t* kmemset(void* dest, uint8_t val, size_t len);
|
|
||||||
push bp
|
|
||||||
mov bp, sp
|
|
||||||
|
|
||||||
mov ax, 0x10
|
|
||||||
push ax ; len = 16 bytes
|
|
||||||
xor ax, ax
|
|
||||||
push ax ; val = 0
|
|
||||||
mov ax, lba_packet
|
|
||||||
push ax ; dest = lba_packet address
|
|
||||||
|
|
||||||
call kmemset
|
|
||||||
leave
|
|
||||||
|
|
||||||
mov byte [lba_packet + LBAPkt_t.size], 0x10
|
|
||||||
mov word [lba_packet + LBAPkt_t.xfer_size], STAGE2_SECTOR_COUNT
|
|
||||||
|
|
||||||
mov ax, [bp-2]
|
|
||||||
shl eax, 16
|
|
||||||
mov ax, [bp-4]
|
|
||||||
mov dword [lba_packet + LBAPkt_t.lower_lba], eax
|
|
||||||
|
|
||||||
mov ax, [bp-6]
|
|
||||||
mov word [lba_packet + LBAPkt_t.offset], ax
|
|
||||||
|
|
||||||
mov ax, [bp-8]
|
|
||||||
mov word [lba_packet + LBAPkt_t.segment], ax
|
|
||||||
|
|
||||||
mov si, lba_packet
|
|
||||||
mov ah, 0x42
|
|
||||||
mov dl, byte [bsDriveNumber]
|
|
||||||
int 0x13
|
|
||||||
jnc read_disk_raw.endf
|
|
||||||
|
|
||||||
ERROR VBR_ERROR_DISK_READ_ERR
|
|
||||||
.endf:
|
|
||||||
pop si
|
|
||||||
ret
|
|
||||||
; Data
|
|
||||||
|
|
||||||
; #############
|
|
||||||
;
|
|
||||||
; Locals
|
|
||||||
;
|
|
||||||
; #############
|
|
||||||
|
|
||||||
; offset from the begining of sector 0 to the active partition.
|
|
||||||
partition_offset:
|
|
||||||
dw 0x0000
|
|
||||||
|
|
||||||
%assign bytes_remaining (420 - ($ - $$))
|
|
||||||
%warning VBR has bytes_remaining bytes remaining for code (MAX: 420 bytes)
|
|
||||||
|
|
||||||
times (510 - ($ - $$)) nop ; Fill the rest of sector with nop
|
|
||||||
|
|
||||||
BootSig:
|
|
||||||
dw 0xAA55 ; Add boot signature at the end of bootloader
|
|
||||||
Reference in New Issue
Block a user