Compare commits
1 Commits
7cd6baa74d
...
trunk
| Author | SHA1 | Date | |
|---|---|---|---|
| 528e3d69fe |
2
.github/workflows/daily.yaml
vendored
2
.github/workflows/daily.yaml
vendored
@@ -3,7 +3,7 @@ on:
|
|||||||
push:
|
push:
|
||||||
branches: [ $default-branch ]
|
branches: [ $default-branch ]
|
||||||
schedule:
|
schedule:
|
||||||
- cron: "0 7 * * *" # daily 07:00
|
- cron: "0 7 * * 1" # mondays at 07:00
|
||||||
workflow_dispatch: {}
|
workflow_dispatch: {}
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
|
|||||||
159
Makefile
159
Makefile
@@ -13,111 +13,74 @@
|
|||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
INCDIR := include
|
include := './include'
|
||||||
BUILD_DIR := build
|
|
||||||
IMG := $(BUILD_DIR)/disk.img
|
mbr_source_files := $(wildcard src/mbr/*.nasm)
|
||||||
IMGZ := $(BUILD_DIR)/disk.img.gz
|
vbr_source_files := $(wildcard src/vbr/*.nasm)
|
||||||
DEP_DIR := $(BUILD_DIR)/deps
|
stage2_source_files := $(wildcard src/stage2/*.nasm)
|
||||||
|
boottest_source_files := $(wildcard src/miniboot32/*.nasm)
|
||||||
|
|
||||||
|
mbr_binary_files := $(patsubst src/mbr/%.nasm, build/%.bin, $(mbr_source_files))
|
||||||
|
vbr_binary_files := $(patsubst src/vbr/%.nasm, build/%.bin, $(vbr_source_files))
|
||||||
|
stage2_binary_files := $(patsubst src/stage2/%.nasm, build/%.bin, $(stage2_source_files))
|
||||||
|
boottest_binary_files := $(patsubst src/miniboot32/%.nasm, build/%.bin, $(boottest_source_files))
|
||||||
|
|
||||||
|
build_dir := 'build'
|
||||||
|
|
||||||
# Get current Git version (tag) and hash
|
# Get current Git version (tag) and hash
|
||||||
GIT_VERSION := $(shell git describe --tags --always --dirty 2>/dev/null || echo unknown)
|
GIT_VERSION := $(shell git describe --tags)
|
||||||
GIT_HASH := $(shell git rev-parse HEAD 2>/dev/null || echo unknown)
|
GIT_HASH := $(shell git rev-parse HEAD)
|
||||||
GIT_NASM_DEFINES := -D __GIT_VER__='"$(GIT_VERSION)"' -D __GIT_HASH__='"$(GIT_HASH)"'
|
GIT_NASM_DEFINES := -D __GIT_VER__='"$(GIT_VERSION)"' -D __GIT_HASH__='"$(GIT_HASH)"'
|
||||||
|
|
||||||
NASMFLAGS := -Wall -f bin -i$(INCDIR)/ $(GIT_NASM_DEFINES)
|
iso := 'build/disk.img'
|
||||||
|
isoz := 'build/output/disk.img.gz'
|
||||||
|
|
||||||
QEMU ?= qemu-system-i386
|
qemu_args := -L ./bin/ -bios bios.bin -cpu pentium3 -m 128 -S -s -monitor stdio -nic none
|
||||||
QEMU_ARGS := \
|
.PHONY: all mbr vbr stage2 boottest clean run run_bochs iso isoz
|
||||||
-M pc-i440fx-8.2,accel=tcg \
|
|
||||||
-cpu pentium3 \
|
|
||||||
-m 64M \
|
|
||||||
-rtc base=localtime \
|
|
||||||
-boot c \
|
|
||||||
-vga std \
|
|
||||||
-display gtk,gl=off \
|
|
||||||
-device e1000,netdev=n0,mac=52:54:00:12:34:56 \
|
|
||||||
-netdev user,id=n0 \
|
|
||||||
-device piix3-usb-uhci \
|
|
||||||
-device usb-ohci,id=ohci0 \
|
|
||||||
-device usb-ehci,id=ehci0 \
|
|
||||||
-device pcspk \
|
|
||||||
-parallel null \
|
|
||||||
-serial null -serial none -serial none -serial none \
|
|
||||||
-chardev file,id=dbg,path=bochs-e9.log,append=on \
|
|
||||||
-device isa-debugcon,iobase=0xe9,chardev=dbg \
|
|
||||||
-msg timestamp=on
|
|
||||||
|
|
||||||
MBR_SRCS := $(wildcard src/mbr/*.nasm)
|
all: $(iso) $(isoz) $(mbr_binary_files) $(vbr_binary_files) $(stage2_binary_files)
|
||||||
VBR_SRCS := $(wildcard src/vbr/*.nasm)
|
mbr: $(mbr_binary_files)
|
||||||
STAGE2_SRCS := $(wildcard src/stage2/*.nasm)
|
vbr: $(vbr_binary_files)
|
||||||
BOOTTEST_SRCS := $(wildcard src/miniboot32/*.nasm)
|
stage2: $(stage2_binary_files)
|
||||||
|
boottest: $(boottest_binary_files)
|
||||||
MBR_BINS := $(patsubst src/mbr/%.nasm, $(BUILD_DIR)/mbr/%.bin, $(MBR_SRCS))
|
|
||||||
VBR_BINS := $(patsubst src/vbr/%.nasm, $(BUILD_DIR)/vbr/%.bin, $(VBR_SRCS))
|
|
||||||
STAGE2_BINS := $(patsubst src/stage2/%.nasm, $(BUILD_DIR)/stage2/%.bin, $(STAGE2_SRCS))
|
|
||||||
BOOTTEST_BINS := $(patsubst src/miniboot32/%.nasm, $(BUILD_DIR)/miniboot32/%.bin, $(BOOTTEST_SRCS))
|
|
||||||
|
|
||||||
ALL_BINS := $(MBR_BINS) $(VBR_BINS) $(STAGE2_BINS) $(BOOTTEST_BINS)
|
|
||||||
|
|
||||||
.DEFAULT_GOAL := all
|
|
||||||
.DELETE_ON_ERROR:
|
|
||||||
|
|
||||||
.PHONY: all mbr vbr stage2 boottest clean run run_qemu run_bochs img imgz help
|
|
||||||
all: $(IMG) $(IMGZ) $(ALL_BINS)
|
|
||||||
mbr: $(MBR_BINS)
|
|
||||||
vbr: $(VBR_BINS)
|
|
||||||
stage2: $(STAGE2_BINS)
|
|
||||||
boottest: $(BOOTTEST_BINS)
|
|
||||||
|
|
||||||
# Build Rules
|
|
||||||
|
|
||||||
$(BUILD_DIR)/mbr/%.bin: src/mbr/%.nasm | $(DEP_DIR)
|
|
||||||
@mkdir -p $(@D)
|
|
||||||
@nasm $(NASMFLAGS) -MD $(DEP_DIR)/$*.d -MT $@ $< -o $@
|
|
||||||
|
|
||||||
$(BUILD_DIR)/vbr/%.bin: src/vbr/%.nasm | $(DEP_DIR)
|
|
||||||
@mkdir -p $(@D)
|
|
||||||
@nasm $(NASMFLAGS) -MD $(DEP_DIR)/$*.d -MT $@ $< -o $@
|
|
||||||
|
|
||||||
$(BUILD_DIR)/stage2/%.bin: src/stage2/%.nasm | $(DEP_DIR)
|
|
||||||
@mkdir -p $(@D)
|
|
||||||
@nasm $(NASMFLAGS) -MD $(DEP_DIR)/$*.d -MT $@ $< -o $@
|
|
||||||
|
|
||||||
$(BUILD_DIR)/miniboot32/%.bin: src/miniboot32/%.nasm | $(DEP_DIR)
|
|
||||||
@mkdir -p $(@D)
|
|
||||||
@nasm $(NASMFLAGS) -MD $(DEP_DIR)/$*.d -MT $@ $< -o $@
|
|
||||||
|
|
||||||
|
|
||||||
$(DEP_DIR):
|
|
||||||
@mkdir -p $@
|
|
||||||
|
|
||||||
# Disk image's
|
|
||||||
|
|
||||||
$(IMG): $(ALL_BINS) | scripts/create-disk.sh
|
|
||||||
@scripts/create-disk.sh
|
|
||||||
|
|
||||||
$(IMGZ): $(IMG)
|
|
||||||
@gzip -9kc $(IMG) > $(IMGZ)
|
|
||||||
|
|
||||||
img: $(IMG)
|
|
||||||
@file $(IMG)
|
|
||||||
|
|
||||||
imgz: $(IMGZ)
|
|
||||||
@file $(IMGZ)
|
|
||||||
|
|
||||||
# Helpers
|
|
||||||
|
|
||||||
run: $(IMG)
|
|
||||||
@$(QEMU) $(QEMU_ARGS) -drive file=$(IMG),if=ide,index=0,media=disk,format=raw \
|
|
||||||
|
|
||||||
run_bochs: $(IMG)
|
|
||||||
@bochs -q
|
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
@$(RM) -rv $(BUILD_DIR)/
|
@rm -v $(build_dir)/*.bin
|
||||||
|
@rm -v $(build_dir)/*.map
|
||||||
|
@rm -v $(build_dir)/*.img
|
||||||
|
@rm -v $(build_dir)/output/*.img.gz
|
||||||
|
@rm -v $(build_dir)/output/*.tar.gz
|
||||||
|
|
||||||
help:
|
run: $(iso)
|
||||||
@awk '/^[A-Za-z0-9_%-]+:/{print $$1}' $(MAKEFILE_LIST) | sed 's/:$$//' | sort -u
|
@sudo qemu-system-i386 $(qemu_args) -hda $(iso)
|
||||||
|
|
||||||
# Include header deps
|
run_bochs: $(iso)
|
||||||
-include $(wildcard $(DEP_DIR)/*.d)
|
@bochs -q
|
||||||
|
|
||||||
|
iso: $(iso)
|
||||||
|
@file $(iso)
|
||||||
|
|
||||||
|
isoz: $(isoz)
|
||||||
|
@file $(isoz)
|
||||||
|
|
||||||
|
build/%.bin: src/mbr/%.nasm
|
||||||
|
@mkdir -p $(shell dirname $@)
|
||||||
|
@nasm -i$(include) -Wall -f bin $(GIT_NASM_DEFINES) $< -o $@
|
||||||
|
|
||||||
|
build/%.bin: src/vbr/%.nasm
|
||||||
|
@mkdir -p $(shell dirname $@)
|
||||||
|
@nasm -i$(include) -Wall -f bin $(GIT_NASM_DEFINES) $< -o $@
|
||||||
|
|
||||||
|
build/%.bin: src/stage2/%.nasm
|
||||||
|
@mkdir -p $(shell dirname $@)
|
||||||
|
@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)
|
||||||
|
@scripts/create-disk.sh
|
||||||
|
|
||||||
|
$(isoz): $(iso)
|
||||||
|
@gzip -9kc $(iso) > $(isoz)
|
||||||
|
|||||||
@@ -1,8 +1,6 @@
|
|||||||
# Stevia Bootloader
|
# Stevia Bootloader
|
||||||
|
|
||||||
Stevia is a lightweight, hobby bootloader written in Assembly (NASM) and is designed for educational purposes. It targets 686+ and aims to be simple, approachable, and understandable, focusing on minimalism and core functionality.
|
Stevia is a lightweight, hobby bootloader written in Assembly and C, designed for educational purposes. It targets 686+ and aims to be simple, approachable, and understandable, focusing on minimalism and core functionality.
|
||||||
|
|
||||||
Please note: **Most development currently takes place in Bochs (and maybe is tested on QEMU), due to this, the code in this repo has not been tested throughly aginist real hardware. As with most projects of this nature, there is a risk of damage due to improper programing of hardware, while careful effort is taken to not break the computer...accidents and mistakes can/do happen.**
|
|
||||||
|
|
||||||
## Features
|
## Features
|
||||||
|
|
||||||
@@ -58,8 +56,6 @@ To build and run Stevia, you will need the following tools installed on your sys
|
|||||||
|
|
||||||
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.
|
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.
|
||||||
|
|
||||||
You are welcome to fork/review the code base but I am generally not accepting PR's/Contributions to the code at this time.
|
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
This project is licensed under the GPLv3 License. See the [LICENSE](LICENSE.md) or [COPYING](COPYING) file for more details.
|
This project is licensed under the GPLv3 License. See the [LICENSE](LICENSE.md) or [COPYING](COPYING) file for more details.
|
||||||
|
|||||||
0
build/.keep_dir
Normal file
0
build/.keep_dir
Normal file
0
build/output/.keep_dir
Normal file
0
build/output/.keep_dir
Normal file
@@ -31,6 +31,29 @@ struc LBAPkt_t
|
|||||||
.lower_lba resd 1
|
.lower_lba resd 1
|
||||||
.upper_lba resd 1
|
.upper_lba resd 1
|
||||||
endstruc
|
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)
|
; Wrapper for AH=0x42 INT13h (Extended Read)
|
||||||
;
|
;
|
||||||
@@ -47,6 +70,7 @@ endstruc
|
|||||||
; disk address packet's block count field set to number of blocks
|
; disk address packet's block count field set to number of blocks
|
||||||
; successfully transferred
|
; successfully transferred
|
||||||
;
|
;
|
||||||
|
;
|
||||||
; uint8_t read_stage2_raw(uint16_t buf_segment, uint16_t buf_offset,
|
; uint8_t read_stage2_raw(uint16_t buf_segment, uint16_t buf_offset,
|
||||||
; uint32_t lba,
|
; uint32_t lba,
|
||||||
; uint16_t count, uint8_t drive_num)
|
; uint16_t count, uint8_t drive_num)
|
||||||
@@ -54,10 +78,13 @@ ALIGN 4, db 0x90
|
|||||||
read_disk_raw:
|
read_disk_raw:
|
||||||
__CDECL16_PROC_ENTRY
|
__CDECL16_PROC_ENTRY
|
||||||
.func:
|
.func:
|
||||||
push LBAPkt_t_size ; len
|
mov ax, LBAPkt_t_size
|
||||||
push 0x00 ; val = 0
|
push ax ; len
|
||||||
push lba_packet ; dest = lba_packet address
|
xor ax, ax
|
||||||
call kmemset ; kmemset(dst, val, len)
|
push ax ; val = 0
|
||||||
|
mov ax, lba_packet
|
||||||
|
push ax ; dest = lba_packet address
|
||||||
|
call kmemset
|
||||||
add sp, 0x06
|
add sp, 0x06
|
||||||
|
|
||||||
mov bx, lba_packet
|
mov bx, lba_packet
|
||||||
@@ -70,8 +97,7 @@ read_disk_raw:
|
|||||||
mov dword [bx + LBAPkt_t.lower_lba], eax
|
mov dword [bx + LBAPkt_t.lower_lba], eax
|
||||||
|
|
||||||
; upper_lba is zero from kmemset
|
; upper_lba is zero from kmemset
|
||||||
; TODO: possiblly support >32bit LBA addresses in the future
|
; TODO: possiblly support >32bit LBA addresses in the future, this limits us to 4GiB
|
||||||
; this will limit us to (4GiB * sector size) of readable lba's from the disk
|
|
||||||
|
|
||||||
mov ax, [bp + 6]
|
mov ax, [bp + 6]
|
||||||
mov word [bx + LBAPkt_t.offset], ax
|
mov word [bx + LBAPkt_t.offset], ax
|
||||||
|
|||||||
@@ -42,7 +42,6 @@
|
|||||||
; __CDECL16_PROC_ARGS nargs
|
; __CDECL16_PROC_ARGS nargs
|
||||||
; Creates %$arg1 .. %$argN as [bp+4], [bp+6], ...
|
; Creates %$arg1 .. %$argN as [bp+4], [bp+6], ...
|
||||||
; for use inside of function bodies
|
; for use inside of function bodies
|
||||||
; BUG: still needs to be tested
|
|
||||||
%ifnmacro __CDECL16_PROC_ARGS
|
%ifnmacro __CDECL16_PROC_ARGS
|
||||||
%macro __CDECL16_PROC_ARGS 1
|
%macro __CDECL16_PROC_ARGS 1
|
||||||
%push __CDECL16_PROC_ARGS
|
%push __CDECL16_PROC_ARGS
|
||||||
@@ -79,7 +78,6 @@
|
|||||||
; __CDECL16_CALL_ARGS_SIZED func, size1[, size2 ...] ; sizes in BYTES
|
; __CDECL16_CALL_ARGS_SIZED func, size1[, size2 ...] ; sizes in BYTES
|
||||||
; if you *need* to pass dword sized args in 16-bit mode, use this to properly
|
; if you *need* to pass dword sized args in 16-bit mode, use this to properly
|
||||||
; count the stack frame to restore later!
|
; count the stack frame to restore later!
|
||||||
; BUG: still needs to be tested
|
|
||||||
%ifnmacro __CDECL16_CALL_ARGS_SIZED
|
%ifnmacro __CDECL16_CALL_ARGS_SIZED
|
||||||
%macro __CDECL16_CALL_ARGS_SIZED 2-*
|
%macro __CDECL16_CALL_ARGS_SIZED 2-*
|
||||||
%push __CDECL16_CALL_ARGS_SIZED
|
%push __CDECL16_CALL_ARGS_SIZED
|
||||||
@@ -126,21 +124,13 @@
|
|||||||
%endmacro
|
%endmacro
|
||||||
%endif
|
%endif
|
||||||
|
|
||||||
;
|
|
||||||
; Only setup the minimum stack frame
|
|
||||||
; unlike the above, everything is caller save
|
|
||||||
;
|
|
||||||
%ifnmacro __FASTCALL16_ENTRY
|
%ifnmacro __FASTCALL16_ENTRY
|
||||||
%macro __FASTCALL16_ENTRY 0-1
|
%macro __FASTCALL16_ENTRY 0
|
||||||
push bp
|
push bp
|
||||||
mov bp, sp
|
mov bp, sp
|
||||||
%if %0 = 1
|
|
||||||
sub sp, %1 ; reserve locals only when needed
|
|
||||||
%endif
|
|
||||||
%endmacro
|
%endmacro
|
||||||
%endif
|
%endif
|
||||||
|
|
||||||
; restore minimum stack frame, all regs are caller save
|
|
||||||
%ifnmacro __FASTCALL16_EXIT
|
%ifnmacro __FASTCALL16_EXIT
|
||||||
%macro __FASTCALL16_EXIT 0
|
%macro __FASTCALL16_EXIT 0
|
||||||
mov sp, bp
|
mov sp, bp
|
||||||
|
|||||||
28
include/early_mem.inc
Executable file
28
include/early_mem.inc
Executable file
@@ -0,0 +1,28 @@
|
|||||||
|
; Copyright (C) 2025 Elaina Claus
|
||||||
|
;
|
||||||
|
; This program is free software: you can redistribute it and/or modify
|
||||||
|
; it under the terms of the GNU General Public License as published by
|
||||||
|
; the Free Software Foundation, either version 3 of the License, or
|
||||||
|
; (at your option) any later version.
|
||||||
|
;
|
||||||
|
; This program is distributed in the hope that it will be useful,
|
||||||
|
; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
; GNU General Public License for more details.
|
||||||
|
;
|
||||||
|
; You should have received a copy of the GNU General Public License
|
||||||
|
; along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
%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
|
||||||
@@ -15,7 +15,7 @@
|
|||||||
|
|
||||||
%ifndef __INC_ENTRY
|
%ifndef __INC_ENTRY
|
||||||
|
|
||||||
%define MBR_ENTRY 0x6C00
|
%define MBR_ENTRY 0x8C00
|
||||||
%define VBR_ENTRY 0x7C00
|
%define VBR_ENTRY 0x7C00
|
||||||
%define STAGE2_ENTRY 0x0500
|
%define STAGE2_ENTRY 0x0500
|
||||||
|
|
||||||
|
|||||||
@@ -1,160 +0,0 @@
|
|||||||
; Copyright (C) 2025 Elaina Claus
|
|
||||||
;
|
|
||||||
; This program is free software: you can redistribute it and/or modify
|
|
||||||
; it under the terms of the GNU General Public License as published by
|
|
||||||
; the Free Software Foundation, either version 3 of the License, or
|
|
||||||
; (at your option) any later version.
|
|
||||||
;
|
|
||||||
; This program is distributed in the hope that it will be useful,
|
|
||||||
; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
; GNU General Public License for more details.
|
|
||||||
;
|
|
||||||
; You should have received a copy of the GNU General Public License
|
|
||||||
; along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
%ifndef __INC_FAT32_SYS
|
|
||||||
|
|
||||||
%include "partition_table.inc"
|
|
||||||
%include "fat32/bpb_offset_bx.inc"
|
|
||||||
%include "fat32/fat32_structures.inc"
|
|
||||||
|
|
||||||
; Prototyping for now...
|
|
||||||
|
|
||||||
; TODO:
|
|
||||||
; - bio_read_sectors (BIOS int13h LBA or CHS) + tiny sector cache.
|
|
||||||
; - mount: parse BPB, derive fat0_lba, data_lba, cluster0_lba.
|
|
||||||
; - FAT read: fat32_read_fat, fat32_next_clus.
|
|
||||||
; - dir iterator (SFN only) + path lookup.
|
|
||||||
; - file reader (fopen/fread) with cluster crossing.
|
|
||||||
; - contiguity probe for speed (optional).
|
|
||||||
; - (later) LFN support & code page handling.
|
|
||||||
|
|
||||||
|
|
||||||
; keep count <= 127
|
|
||||||
; int bio_read_sectors(uint64_t lba, uint16_t count, void* dst);
|
|
||||||
; will also need a bio_bios_int13h() (refactor ext_disk_read?)
|
|
||||||
; to abstract the backend 'sector getter'
|
|
||||||
|
|
||||||
; Error codes
|
|
||||||
|
|
||||||
; FS_OK 0
|
|
||||||
; FS_E_IO 1 (bio read failed)
|
|
||||||
; FS_E_FMT 2 (not FAT32 or bad BPB)
|
|
||||||
; FS_E_RANGE 3 (bad cluster or out of range)
|
|
||||||
; FS_E_END 4 (iterator end)
|
|
||||||
; FS_E_NOSUCH 5 (file/dir not found)
|
|
||||||
; FS_E_ISDIR 6 (opened dir as file)
|
|
||||||
; FS_E_TOOLONG 7 (path segment too long for 8.3)
|
|
||||||
; FS_E_UNSUPPORTED 8 (LFN present but disabled)
|
|
||||||
; FS_E_UNIMPLEMENTED 0xffff (procedure call unimplmented)
|
|
||||||
|
|
||||||
;
|
|
||||||
; Cache methods
|
|
||||||
;
|
|
||||||
; TODO: make a cache for ~4-8 disk sectors
|
|
||||||
; TODO: make a cache for FATs to avoid having to re-read the FAT
|
|
||||||
;
|
|
||||||
; // uses bio_read_sectors + cache
|
|
||||||
; int cache_read_sector(uint64_t lba, void* dst);
|
|
||||||
; int cache_invalidate_all(void);
|
|
||||||
|
|
||||||
; what a 'mount' should probably do at this point...
|
|
||||||
; - read VBR at partition_lba
|
|
||||||
; - validate FAT32 signatures
|
|
||||||
; - fill fat32_bpb_t and compute derived fields
|
|
||||||
; - read FSInfo (free count/next free)
|
|
||||||
; - ???
|
|
||||||
; int fat32_mount(uint32_t partition_lba, fat32_bpb_t* out);
|
|
||||||
|
|
||||||
|
|
||||||
;
|
|
||||||
; Accessors
|
|
||||||
;
|
|
||||||
|
|
||||||
; // Convert cluster -> LBA of first sector of that cluster
|
|
||||||
; uint64_t clus_to_lba(const fat32_bpb_t* v, uint32_t clus) {
|
|
||||||
; return v->data_lba + (uint64_t)(clus - 2) * v->secs_per_clus;
|
|
||||||
; }
|
|
||||||
|
|
||||||
; FAT32 entry is 32-bits; only low 28 bits are meaningful.
|
|
||||||
; EOC if (val & 0x0FFFFFFF) >= 0x0FFFFFF8.
|
|
||||||
; bad if == 0x0FFFFFF7.
|
|
||||||
; free if == 0x00000000.
|
|
||||||
|
|
||||||
; // Read 32-bit FAT entry for cluster n
|
|
||||||
; int fat32_read_fat(const fat32_bpb_t* v, uint32_t clus, uint32_t* out);
|
|
||||||
|
|
||||||
; // Walk to next cluster in chain (validates EOC/bad)
|
|
||||||
; int fat32_next_clus(const fat32_bpb_t* v, uint32_t clus, uint32_t* out_next);
|
|
||||||
|
|
||||||
;
|
|
||||||
; SFN directories
|
|
||||||
;
|
|
||||||
|
|
||||||
; typedef struct {
|
|
||||||
; char name83[12]; // "FILENAMEEXT" (no dot), NUL-terminated
|
|
||||||
; uint8_t attr; // ATTR_DIRECTORY=0x10, ATTR_VOLUME=0x08
|
|
||||||
; uint32_t first_clus; // (hi<<16)|lo
|
|
||||||
; uint32_t size; // bytes
|
|
||||||
; } fat32_dirent_sfn_t;
|
|
||||||
|
|
||||||
; typedef struct { // iterator
|
|
||||||
; fat32_bpb_t* v;
|
|
||||||
; uint32_t cur_clus;
|
|
||||||
; uint32_t offs_in_clus; // byte offset
|
|
||||||
; } fat32_dir_iter_t;
|
|
||||||
|
|
||||||
;int fat32_dir_iter_open_root(fat32_bpb_t* v, fat32_dir_iter_t* it);
|
|
||||||
;int fat32_dir_iter_open(fat32_bpb_t* v, uint32_t first_clus, fat32_dir_iter_t* it);
|
|
||||||
;int fat32_dir_iter_next(fat32_dir_iter_t* it, fat32_dirent_sfn_t* out); // FS_OK or FS_E_END
|
|
||||||
|
|
||||||
|
|
||||||
; typedef struct {
|
|
||||||
; uint32_t first_clus;
|
|
||||||
; uint32_t size;
|
|
||||||
; uint8_t attr; // dir or file
|
|
||||||
; } fat32_node_t;
|
|
||||||
|
|
||||||
; split by / or \.
|
|
||||||
; start at root (v->root_clus).
|
|
||||||
; for each component:
|
|
||||||
; iterate directory with dir_iter_* to find case-insensitive 8.3 match (fold to upper and space-pad during compare).
|
|
||||||
; if final component: return file’s cluster & size.
|
|
||||||
; if intermediate: ensure ATTR_DIRECTORY and descend.
|
|
||||||
;
|
|
||||||
; int fat32_path_lookup(fat32_bpb_t* v, const char* path, fat32_node_t* out);
|
|
||||||
|
|
||||||
; an example 'do the thing' proc to load a file to a location
|
|
||||||
;
|
|
||||||
; // loads file at path into dst, up to max_bytes; returns size read.
|
|
||||||
; int fat32_load_file(fat32_bpb_t* v, const char* path, void* dst,
|
|
||||||
; uint32_t max_bytes, uint32_t* out_size);
|
|
||||||
|
|
||||||
; streamed reads
|
|
||||||
;
|
|
||||||
; typedef struct {
|
|
||||||
; fat32_bpb_t* v;
|
|
||||||
; uint32_t first_clus;
|
|
||||||
; uint32_t cur_clus;
|
|
||||||
; uint32_t cur_clus_index; // which cluster within file we’re on
|
|
||||||
; uint32_t size; // total bytes
|
|
||||||
; uint32_t pos; // current byte position
|
|
||||||
; } fat32_file_t;
|
|
||||||
;
|
|
||||||
;
|
|
||||||
; int fat32_fopen(fat32_bpb_t* v, const char* path, fat32_file_t* f);
|
|
||||||
; int fat32_fread(fat32_file_t* f, void* dst, uint32_t nbytes, uint32_t* out_read);
|
|
||||||
; int fat32_fseek(fat32_file_t* f, uint32_t new_pos); // forward seeks only is fine
|
|
||||||
; int fat32_fclose(fat32_file_t* f);
|
|
||||||
|
|
||||||
|
|
||||||
; an example 'do the thing' proc to load a file to a location
|
|
||||||
;
|
|
||||||
; // loads file at path into dst, up to max_bytes; returns size read.
|
|
||||||
; int fat32_load_file(fat32_bpb_t* v, const char* path, void* dst,
|
|
||||||
; uint32_t max_bytes, uint32_t* out_size);
|
|
||||||
|
|
||||||
|
|
||||||
%endif
|
|
||||||
%define __INC_FAT32_SYS
|
|
||||||
@@ -1,228 +0,0 @@
|
|||||||
; Copyright (C) 2025 Elaina Claus
|
|
||||||
;
|
|
||||||
; This program is free software: you can redistribute it and/or modify
|
|
||||||
; it under the terms of the GNU General Public License as published by
|
|
||||||
; the Free Software Foundation, either version 3 of the License, or
|
|
||||||
; (at your option) any later version.
|
|
||||||
;
|
|
||||||
; This program is distributed in the hope that it will be useful,
|
|
||||||
; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
; GNU General Public License for more details.
|
|
||||||
;
|
|
||||||
; You should have received a copy of the GNU General Public License
|
|
||||||
; along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
%ifndef __INC_FAT32_STRUCT
|
|
||||||
|
|
||||||
; ## FAT32 Info ##
|
|
||||||
; total_sectors = bsSectorsHuge
|
|
||||||
; fat_size = bsSectorsPerFat
|
|
||||||
;
|
|
||||||
; first_data_sector = bsResSectors + (bsFATs * bsSectPerFAT);
|
|
||||||
; total_data_sectors = bsSectorsHuge - (bsResSectors + (bsFATs * bsSectPerFAT));
|
|
||||||
; total_clusters = total_data_sectors / bsSectsPerClust
|
|
||||||
; first_fat_sector = bsResSectors
|
|
||||||
;
|
|
||||||
; ## FAT32 Table information ##
|
|
||||||
;
|
|
||||||
; fat_offset = active_cluster * 4
|
|
||||||
; fat_sector = first_fat_sector + (fat_offset / sector_size)
|
|
||||||
; entry_offset = fat_offset % sector_size
|
|
||||||
;
|
|
||||||
; table_value = fat_table[entry_offset] & 0x0FFF_FFFF
|
|
||||||
;
|
|
||||||
; ## FAT32 Directory Entries ##
|
|
||||||
; root_dir_cluster = bsRootDirCluster
|
|
||||||
; root_dir_sectors = ? (this is varible on FAT32 since the root dir is a cluster chain)
|
|
||||||
; first_sector_of_cluster = ((cluster - 2) * bsSectPerClust) + first_data_sector;
|
|
||||||
|
|
||||||
; BPB Information
|
|
||||||
; Size Description
|
|
||||||
; 8 OEM identifier.
|
|
||||||
; 2 The number of Bytes per sector (remember, all numbers are in the little-endian format).
|
|
||||||
; 1 Number of sectors per cluster.
|
|
||||||
; 2 Number of reserved sectors. The boot record sectors are included in this value.
|
|
||||||
; 1 Number of File Allocation Tables (FAT's) on the storage media. Often this value is 2.
|
|
||||||
; 2 Number of directory entries (must be set so that the root directory occupies entire sectors).
|
|
||||||
; 2 The total sectors in the logical volume.
|
|
||||||
; If this value is 0, it means there are more than 65535 sectors in the volume,
|
|
||||||
; and the actual count is stored in the Large Sector Count entry at 0x20.
|
|
||||||
;
|
|
||||||
; 1 This Byte indicates the media descriptor type.
|
|
||||||
; 2 Number of sectors per FAT. FAT12/FAT16 only.
|
|
||||||
; 2 Number of sectors per track.
|
|
||||||
; 2 Number of heads or sides on the storage media.
|
|
||||||
; 4 Number of hidden sectors. (i.e. the LBA of the beginning of the partition.)
|
|
||||||
; 4 Large sector count. This field is set if there are more than 65535 sectors in the volume,
|
|
||||||
; resulting in a value which does not fit in the Number of Sectors entry at 0x13.
|
|
||||||
|
|
||||||
struc FAT32_bpb_t
|
|
||||||
.reserved_jmpboot resb 3
|
|
||||||
.ident resb 8
|
|
||||||
.bytes_per_sector_word resb 2
|
|
||||||
.sectors_per_cluster_byte resb 1
|
|
||||||
.reserved_sectors_word resb 2
|
|
||||||
.fat_count_byte resb 1
|
|
||||||
.unused1_ZERO_word resb 2 ; Root entry count field, 0 on fat32
|
|
||||||
.unused2_ZERO_word resb 2 ; total sectors size 16, 0 on fat32
|
|
||||||
.media_desc_byte resb 1
|
|
||||||
.unused3_ZERO_word resb 2 ; FAT size 16, 0 on fat32
|
|
||||||
.sectors_per_track_word resb 2
|
|
||||||
.head_count_word resb 2
|
|
||||||
.hidden_sectors_dword resb 4
|
|
||||||
.total_sectors_dword resb 4
|
|
||||||
endstruc
|
|
||||||
|
|
||||||
; EBPB Information (FAT32)
|
|
||||||
; Size Description
|
|
||||||
; 4 Sectors per FAT. The size of the FAT in sectors.
|
|
||||||
; 2 Flags.
|
|
||||||
; 2 FAT version number. The high byte is the major version and the low byte is the minor version. FAT drivers should respect this field.
|
|
||||||
; 4 The cluster number of the root directory. Often this field is set to 2.
|
|
||||||
; 2 The sector number of the FSInfo structure.
|
|
||||||
; 2 The sector number of the backup boot sector.
|
|
||||||
; 12 Reserved. When the volume is formated these bytes should be zero.
|
|
||||||
; 1 Drive number. The values here are identical to the values returned by the BIOS interrupt 0x13. 0x00 for a floppy disk and 0x80 for hard disks.
|
|
||||||
; 1 Flags in Windows NT. Reserved otherwise.
|
|
||||||
; 1 Signature (must be 0x28 or 0x29).
|
|
||||||
; 4 Volume ID 'Serial' number. Used for tracking volumes between computers. You can ignore this if you want.
|
|
||||||
; 11 Volume label string. This field is padded with spaces.
|
|
||||||
; 8 System identifier string. Always "FAT32 ". The spec says never to trust the contents of this string for any use.
|
|
||||||
|
|
||||||
struc FAT32_ebpb_t
|
|
||||||
.FATSz_dword resb 4
|
|
||||||
.extflags_word resb 2
|
|
||||||
.FSVersion_word resb 2
|
|
||||||
.root_clus_dword resb 4
|
|
||||||
.FSInfo_word resb 2
|
|
||||||
.BkBootSec_word resb 2
|
|
||||||
.reserved1 resb 12
|
|
||||||
.drive_number_byte resb 1
|
|
||||||
.nt_flags_byte resb 1
|
|
||||||
.signature_byte resb 1
|
|
||||||
.volume_id_dword resb 4
|
|
||||||
.volume_label_bytea resb 11
|
|
||||||
.system_ident_bytea resb 8
|
|
||||||
endstruc
|
|
||||||
|
|
||||||
; ## Standard 8.3 structure ###
|
|
||||||
; Offset Length (Bytes) Description
|
|
||||||
; 0 11 8.3 file name. The first 8 characters are the name and the last 3 are the extension.
|
|
||||||
; 11 1 File Atrributes
|
|
||||||
; READ_ONLY=0x01
|
|
||||||
; HIDDEN=0x02
|
|
||||||
; SYSTEM=0x04
|
|
||||||
; VOLUME_ID=0x08
|
|
||||||
; DIRECTORY=0x10
|
|
||||||
; ARCHIVE=0x20
|
|
||||||
; LFN=READ_ONLY|HIDDEN|SYSTEM|VOLUME_ID == 0x0F
|
|
||||||
;
|
|
||||||
; 12 1 NT Reserved
|
|
||||||
; 13 1 Creation time in tenths of a second.
|
|
||||||
; 14 2 File creation time, Hour 5 bits, Minutes 6 bits, Seconds 5 Bits, multiply seconds by 2
|
|
||||||
; 16 2 File creation date, Year 7 bits, month 4 bits, day 5 bits
|
|
||||||
; 18 2 Last Accessed date. same format at creation date
|
|
||||||
; 20 2 High 16 bits of entry's first cluster
|
|
||||||
; 22 2 Last modification time. same format at creation time
|
|
||||||
; 24 2 Last modification date. same format as creation date
|
|
||||||
; 26 2 Low 16 bits of entry's first cluster
|
|
||||||
; 28 4 File size in bytes
|
|
||||||
|
|
||||||
; FSInfo
|
|
||||||
; 0 0x0 4 Lead signature (must be 0x41615252 to indicate a valid FSInfo structure)
|
|
||||||
; 4 0x4 480 Reserved, these bytes should never be used
|
|
||||||
; 484 0x1E4 4 Another signature (must be 0x61417272)
|
|
||||||
; 488 0x1E8 4 Contains the last known free cluster count on the volume. If the value is 0xFFFFFFFF, then the free count is unknown and must be computed.
|
|
||||||
; However, this value might be incorrect and should at least be range checked (<= volume cluster count)
|
|
||||||
;
|
|
||||||
; 492 0x1EC 4 Indicates the cluster number at which the filesystem driver should start looking for available clusters.
|
|
||||||
; If the value is 0xFFFFFFFF, then there is no hint and the driver should start searching at 2.
|
|
||||||
; Typically this value is set to the last allocated cluster number. As the previous field, this value should be range checked.
|
|
||||||
;
|
|
||||||
; 496 0x1F0 12 Reserved
|
|
||||||
; 508 0x1FC 4 Trail signature (0xAA550000)
|
|
||||||
|
|
||||||
struc FAT32_FSInfo_t
|
|
||||||
.head_sig_dword resd 1 ; 0x41615252
|
|
||||||
.reserved1 resb 480 ; fill zero
|
|
||||||
.body_sig_dword resd 1 ; 0x61417272
|
|
||||||
.free_count_dword resd 1
|
|
||||||
.next_free_dword resd 1
|
|
||||||
.reserved2 resb 12 ; fill zero
|
|
||||||
.tail_sig_dword resd 1 ; 0xAA550000
|
|
||||||
endstruc
|
|
||||||
|
|
||||||
struc FAT32_SFN_t
|
|
||||||
.label_83 resb 11
|
|
||||||
.attributes_byte resb 1
|
|
||||||
.nt_res_byte resb 1
|
|
||||||
.csec_byte resb 1
|
|
||||||
.ctime_word resb 2
|
|
||||||
.cdate_word resb 2
|
|
||||||
.adate_word resb 2
|
|
||||||
.cluster_16_high resb 2
|
|
||||||
.mtime_word resb 2
|
|
||||||
.mdate_word resb 2
|
|
||||||
.cluster_16_low resb 2
|
|
||||||
.size_dword resb 4
|
|
||||||
endstruc
|
|
||||||
|
|
||||||
; ## Long file name (LFN) structure format ##
|
|
||||||
;
|
|
||||||
; 0 1 The order of this entry in the sequence of long file name entries. This value helps you to know where in the file's name the characters from this entry should be placed.
|
|
||||||
; 1 10 The first 5, 2-byte characters of this entry.
|
|
||||||
; 11 1 Attribute. Always equals 0x0F. (the long file name attribute)
|
|
||||||
; 12 1 Long entry type. Zero for name entries.
|
|
||||||
; 13 1 Checksum generated of the short file name when the file was created. The short filename can change without changing the long filename in cases where the partition is mounted on a system which does not support long filenames.
|
|
||||||
; 14 12 The next 6, 2-byte characters of this entry.
|
|
||||||
; 26 2 Always zero.
|
|
||||||
; 28 4 The final 2, 2-byte characters of this entry.
|
|
||||||
;
|
|
||||||
; LFN entries are always placed immediately before their respective 8.3 entry
|
|
||||||
;
|
|
||||||
; LAST_LFN_ENTRY == 0x40
|
|
||||||
; Max of 20 in sequence == 0x14
|
|
||||||
|
|
||||||
struc FAT32_LFN_t
|
|
||||||
.order resb 1
|
|
||||||
.lfn_first5 resb 10
|
|
||||||
.attributes_8 resb 1
|
|
||||||
.zero1 resb 1
|
|
||||||
.checksum resb 1
|
|
||||||
.lfn_next6 resb 12
|
|
||||||
.zero2 resb 2
|
|
||||||
.lfn_last2 resb 4
|
|
||||||
endstruc
|
|
||||||
|
|
||||||
; 32 bytes
|
|
||||||
struc FAT32_State_t
|
|
||||||
.first_data_sector_32 resd 1
|
|
||||||
.first_fat_sector_32 resd 1
|
|
||||||
.fat_size_32 resd 1
|
|
||||||
.curr_FAT_cluster_32 resd 1
|
|
||||||
.curr_dir_cluster_32 resd 1
|
|
||||||
.curr_drive_lba_32 resd 1
|
|
||||||
endstruc
|
|
||||||
|
|
||||||
; 16 bytes
|
|
||||||
struc FAT32_NextClusterData_t
|
|
||||||
.fat_offset resd 1
|
|
||||||
.fat_sector resd 1
|
|
||||||
.entry_offset resd 1
|
|
||||||
.reserved_1 resd 1
|
|
||||||
endstruc
|
|
||||||
|
|
||||||
; FAT32 Attributes
|
|
||||||
%define FAT32_ATTR_RO 0x01
|
|
||||||
%define FAT32_ATTR_HIDDEN 0x02
|
|
||||||
%define FAT32_ATTR_SYSTEM 0x04
|
|
||||||
%define FAT32_ATTR_VOLID 0x08
|
|
||||||
%define FAT32_ATTR_DIR 0x10
|
|
||||||
%define FAT32_ATTR_ARC 0x20
|
|
||||||
|
|
||||||
; LFN == RO | HIDDEN | SYSTEM | VOLID == 0x0F
|
|
||||||
%define FAT32_ATTR_LFN 0x0F
|
|
||||||
|
|
||||||
%endif
|
|
||||||
%define __INC_FAT32_STRUCT
|
|
||||||
@@ -21,10 +21,10 @@ if [ $(id -u) = 0 ]; then
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
# paths to bootcode
|
# paths to bootcode
|
||||||
mbr_file=build/mbr/mbr.bin
|
mbr_file=build/mbr.bin
|
||||||
vbr_file=build/vbr/vbr.bin
|
vbr_file=build/vbr.bin
|
||||||
stage2_file=build/stage2/stage2.bin
|
stage2_file=build/stage2.bin
|
||||||
boottest_file=build/miniboot32/BOOTi686.bin
|
boottest_file=build/BOOTi686.bin
|
||||||
|
|
||||||
# Disk creation options
|
# Disk creation options
|
||||||
disk_img=build/disk.img
|
disk_img=build/disk.img
|
||||||
@@ -161,14 +161,9 @@ if [[ "$OSTYPE" == "linux-gnu"* ]]; then
|
|||||||
dd if="$part_img" of="$disk_img" bs=$disk_sector_size seek=$part_start conv=notrunc
|
dd if="$part_img" of="$disk_img" bs=$disk_sector_size seek=$part_start conv=notrunc
|
||||||
|
|
||||||
echo " *** Outputing disk images will be in ./build/output/* *** "
|
echo " *** Outputing disk images will be in ./build/output/* *** "
|
||||||
|
|
||||||
if [ ! -d ./build/output ]; then
|
|
||||||
echo "./build/output does not exist. creating"
|
|
||||||
mkdir -p ./build/output
|
|
||||||
fi
|
|
||||||
gzip -9c "$disk_img" > "$disk_img_final"
|
gzip -9c "$disk_img" > "$disk_img_final"
|
||||||
gzip -9c "$part_img" > "$part_img_final"
|
gzip -9c "$part_img" > "$part_img_final"
|
||||||
tar caf "$artifacts_archive" --exclude ./build/output ./build/
|
tar caf "$artifacts_archive" build/*.bin build/*.map
|
||||||
else
|
else
|
||||||
# Unknown.
|
# Unknown.
|
||||||
echo "Unknown OS type! Supported build hosts systems are GNU/Linux (& WSL)"
|
echo "Unknown OS type! Supported build hosts systems are GNU/Linux (& WSL)"
|
||||||
|
|||||||
@@ -14,7 +14,7 @@
|
|||||||
; along with this program. If not, see <https://www.gnu.org/licenses/>.
|
; along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
[BITS 16]
|
[BITS 16]
|
||||||
[ORG 0x6C00]
|
[ORG 0x8C00]
|
||||||
[CPU KATMAI]
|
[CPU KATMAI]
|
||||||
[WARNING -reloc-abs-byte]
|
[WARNING -reloc-abs-byte]
|
||||||
[WARNING -reloc-abs-word] ; Yes, we use absolute addresses. surpress these warnings.
|
[WARNING -reloc-abs-word] ; Yes, we use absolute addresses. surpress these warnings.
|
||||||
@@ -33,10 +33,10 @@ nop
|
|||||||
%include "config.inc"
|
%include "config.inc"
|
||||||
%include "error_codes.inc"
|
%include "error_codes.inc"
|
||||||
%include "partition_table.inc"
|
%include "partition_table.inc"
|
||||||
|
%include "fat32/fat32_structures.inc"
|
||||||
|
|
||||||
%undef __STEVIA_DEV_DEBUG
|
%undef __STEVIA_DEV_DEBUG
|
||||||
|
|
||||||
; BIOS will load 1st sector of boot drive to 0x7c00, init and relocate
|
|
||||||
ALIGN 4
|
ALIGN 4
|
||||||
init:
|
init:
|
||||||
cli ; We do not want to be interrupted
|
cli ; We do not want to be interrupted
|
||||||
@@ -58,14 +58,14 @@ init:
|
|||||||
cld
|
cld
|
||||||
rep stosb ; zero bss section
|
rep stosb ; zero bss section
|
||||||
|
|
||||||
sub sp, 0x10 ; local varible space (32 bytes)
|
sub sp, 0x20 ; local varible space (32 bytes)
|
||||||
push bp ; setup top of stack frame
|
push bp ; setup top of stack frame
|
||||||
|
|
||||||
xor cx, cx
|
xor cx, cx
|
||||||
mov ch, 0x02 ; 0x0200 in cx
|
mov ch, 0x02 ; 0x0200 in cx
|
||||||
mov si, 0x7C00 ; Current MBR Address (loaded here by BIOS)
|
mov si, 0x7C00 ; Current MBR Address (loaded here by BIOS)
|
||||||
mov di, MBR_ENTRY ; New MBR Address (our new relocation address)
|
mov di, MBR_ENTRY ; New MBR Address (our new relocation address)
|
||||||
rep movsb ; copy 512 bytes from 0x0000:7c00 to 0x0000:MBR_ENTRY (6C00 as of writing)
|
rep movsb ; copy 512 bytes from 0x0000:7c00 to 0x0000:MBR_ENTRY (7A00 as of writing)
|
||||||
|
|
||||||
sti
|
sti
|
||||||
|
|
||||||
@@ -121,14 +121,19 @@ main:
|
|||||||
mov word [bp - 4], ax ; update part_offset
|
mov word [bp - 4], ax ; update part_offset
|
||||||
.read_data:
|
.read_data:
|
||||||
movzx ax, byte [bp - 2]
|
movzx ax, byte [bp - 2]
|
||||||
push ax ; drive_num (2)
|
push ax ; drive_num
|
||||||
push 0x01 ; count (2)
|
|
||||||
|
mov ax, 0x1
|
||||||
|
push ax ; count
|
||||||
|
|
||||||
mov dword eax, dword [bx + PartEntry_t.lba_start]
|
mov dword eax, dword [bx + PartEntry_t.lba_start]
|
||||||
push dword eax ; lba (4)
|
push dword eax ; lba
|
||||||
|
|
||||||
push word 0x7C00 ; offset = 0x7c00 (2)
|
mov ax, VBR_ENTRY
|
||||||
push 0x00 ; segment = 0 (2)
|
push ax ; offset = 0x7c00
|
||||||
|
|
||||||
|
xor ax, ax
|
||||||
|
push ax ; segment = 0
|
||||||
|
|
||||||
; uint8_t read_stage2_raw(uint16_t buf_segment, uint16_t buf_offset,
|
; uint8_t read_stage2_raw(uint16_t buf_segment, uint16_t buf_offset,
|
||||||
; uint32_t lba,
|
; uint32_t lba,
|
||||||
@@ -138,9 +143,20 @@ main:
|
|||||||
.goto_vbr:
|
.goto_vbr:
|
||||||
cmp word [VBR_ENTRY + 0x1FE], 0xAA55
|
cmp word [VBR_ENTRY + 0x1FE], 0xAA55
|
||||||
je main.sig_ok
|
je main.sig_ok
|
||||||
ERROR MBR_ERROR_NO_VBR_SIG ; no signature present
|
ERROR MBR_ERROR_NO_VBR_SIG ; no signature present
|
||||||
.sig_ok:
|
.sig_ok:
|
||||||
mov dl, byte [bp - 2] ; pass drive # from BIOS to VBR in dl
|
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
|
jmp word 0x0000:VBR_ENTRY
|
||||||
|
|
||||||
; ###############
|
; ###############
|
||||||
@@ -169,15 +185,18 @@ PartEntry4:
|
|||||||
times 16 db 0x00
|
times 16 db 0x00
|
||||||
BootSig:
|
BootSig:
|
||||||
dw 0xAA55 ; Add boot signature at the end of bootloader
|
dw 0xAA55 ; Add boot signature at the end of bootloader
|
||||||
; !!! end of MBR !!!
|
|
||||||
section .bss follows=.text
|
section .bss follows=.text
|
||||||
begin_bss:
|
begin_bss:
|
||||||
|
|
||||||
|
align 16, resb 1
|
||||||
|
partition_table resb PartTable_t_size
|
||||||
|
|
||||||
align 16, resb 1
|
align 16, resb 1
|
||||||
lba_packet resb LBAPkt_t_size
|
lba_packet resb LBAPkt_t_size
|
||||||
|
|
||||||
align 512, resb 1
|
align 512, resb 1
|
||||||
stack_bottom resb 1024 - 16 ; 512 byte stack early on
|
stack_bottom resb 512 ; 512 byte stack early on
|
||||||
stack_top:
|
stack_top:
|
||||||
mbr_redzone resb 16
|
mbr_redzone resb 32
|
||||||
end_bss:
|
end_bss:
|
||||||
@@ -31,15 +31,24 @@
|
|||||||
%include "cdecl16.inc"
|
%include "cdecl16.inc"
|
||||||
%include "entry.inc"
|
%include "entry.inc"
|
||||||
%include "config.inc"
|
%include "config.inc"
|
||||||
|
%include "early_mem.inc"
|
||||||
%include "error_codes.inc"
|
%include "error_codes.inc"
|
||||||
|
|
||||||
section .text
|
section .text
|
||||||
begin_text:
|
begin_text:
|
||||||
; dl = byte boot_drive
|
; 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
|
ALIGN 4, db 0x90
|
||||||
init:
|
init:
|
||||||
cli ; We do not want to be interrupted
|
cli ; We do not want to be interrupted
|
||||||
mov [boot_drive], dl ; copy boot_drive to globals
|
|
||||||
|
; 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 ax, __STAGE2_SEGMENT ; set all our segments to the configured segment, except es
|
||||||
mov ds, ax ; *
|
mov ds, ax ; *
|
||||||
@@ -89,9 +98,7 @@ init:
|
|||||||
; FAT32 Driver
|
; FAT32 Driver
|
||||||
; ###############
|
; ###############
|
||||||
|
|
||||||
%include "partition_table.inc"
|
%include 'fat32/FAT32_SYS.inc'
|
||||||
%include "fat32/fat32_structures.inc"
|
|
||||||
;%include 'fat32/FAT32_SYS.inc'
|
|
||||||
|
|
||||||
; ###############
|
; ###############
|
||||||
; BIOS functions
|
; BIOS functions
|
||||||
@@ -121,34 +128,22 @@ main:
|
|||||||
je main.stage2_main
|
je main.stage2_main
|
||||||
ERROR STAGE2_SIGNATURE_MISSING
|
ERROR STAGE2_SIGNATURE_MISSING
|
||||||
.stage2_main:
|
.stage2_main:
|
||||||
|
; copy partition table data to .data section in stage2
|
||||||
|
__CDECL16_CALL_ARGS partition_table, word [vbr_part_table_ptr], PartTable_t_size
|
||||||
|
__CDECL16_CALL kmemcpy, 3
|
||||||
|
|
||||||
|
; copy bpb & ebpb to memory
|
||||||
|
__CDECL16_CALL_ARGS fat32_bpb, word [vbr_fat32_bpb_ptr], (FAT32_bpb_t_size + FAT32_ebpb_t_size)
|
||||||
|
__CDECL16_CALL kmemcpy, 3
|
||||||
|
|
||||||
call SetTextMode
|
call SetTextMode
|
||||||
call disable_cursor_bios
|
call disable_cursor_bios
|
||||||
|
|
||||||
; setup the early heap
|
|
||||||
__CDECL16_CALL_ARGS early_heap_state
|
|
||||||
__CDECL16_CALL arena_init, 1
|
|
||||||
|
|
||||||
__CDECL16_CALL_ARGS HelloPrompt_info
|
__CDECL16_CALL_ARGS HelloPrompt_info
|
||||||
__CDECL16_CALL PrintString, 1
|
__CDECL16_CALL PrintString, 1
|
||||||
|
|
||||||
; setup and store our vbr/mbr (e)bpb
|
; setup the early heap
|
||||||
__CDECL16_CALL_ARGS 0x200, 0x10
|
__CDECL16_CALL_ARGS early_heap_state
|
||||||
__CDECL16_CALL arena_alloc, 2
|
|
||||||
mov word [mbr_ptr], ax
|
|
||||||
|
|
||||||
push ax ; dst
|
|
||||||
movzx ax, byte [boot_drive]
|
|
||||||
push ax ; boot_drive
|
|
||||||
__CDECL16_CALL read_mbr, 2 ; fill mbr buffer
|
|
||||||
|
|
||||||
__CDECL16_CALL_ARGS 0x200, 0x10
|
|
||||||
__CDECL16_CALL arena_alloc, 2
|
|
||||||
mov word [vbr_ptr], ax
|
|
||||||
|
|
||||||
push ax ; dst
|
|
||||||
movzx ax, byte [boot_drive]
|
|
||||||
push ax ; boot_drive
|
|
||||||
__CDECL16_CALL read_vbr, 2 ; fill vbr buffer
|
|
||||||
|
|
||||||
; enable A20 gate
|
; enable A20 gate
|
||||||
call EnableA20
|
call EnableA20
|
||||||
@@ -169,22 +164,22 @@ main:
|
|||||||
__CDECL16_CALL PrintString, 1
|
__CDECL16_CALL PrintString, 1
|
||||||
|
|
||||||
; FAT Driver setup
|
; FAT Driver setup
|
||||||
;call InitFATDriver
|
call InitFATDriver
|
||||||
;__CDECL16_CALL_ARGS InitFATSYS_OK_info
|
__CDECL16_CALL_ARGS InitFATSYS_OK_info
|
||||||
;__CDECL16_CALL PrintString, 1
|
__CDECL16_CALL PrintString, 1
|
||||||
|
|
||||||
;
|
;
|
||||||
; Find first cluster of bootable file
|
; Find first cluster of bootable file
|
||||||
;call SearchFATDIR
|
call SearchFATDIR
|
||||||
;push dword eax ; save first cluster of bootable file
|
push dword eax ; save first cluster of bootable file
|
||||||
|
|
||||||
;__CDECL16_CALL_ARGS FileFound_OK_info
|
__CDECL16_CALL_ARGS FileFound_OK_info
|
||||||
;__CDECL16_CALL PrintString, 1
|
__CDECL16_CALL PrintString, 1
|
||||||
|
|
||||||
;pop dword eax
|
pop dword eax
|
||||||
;push dword eax ; print Cluster of boot file
|
push dword eax ; print Cluster of boot file
|
||||||
;call PrintDWORD ; void PrintDWORD(uint32_t dword)
|
call PrintDWORD ; void PrintDWORD(uint32_t dword)
|
||||||
;add sp, 0x4
|
add sp, 0x4
|
||||||
|
|
||||||
; TODO: using first cluster information, start loading the kernel to memory
|
; 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
|
; TODO: going to need an elf parser, some unreal mode file buffer functions to move the data
|
||||||
@@ -197,87 +192,6 @@ hcf:
|
|||||||
;
|
;
|
||||||
; ##############################
|
; ##############################
|
||||||
|
|
||||||
; int read_mbr(int boot_drive, void* dst)
|
|
||||||
; destination buffer needs 512 bytes of space
|
|
||||||
read_mbr:
|
|
||||||
__CDECL16_PROC_ENTRY
|
|
||||||
.proc:
|
|
||||||
; read mbr on boot drive to memory (for the partition table)
|
|
||||||
movzx ax, byte [bp + 4]
|
|
||||||
push ax ; drive_num (2)
|
|
||||||
push 0x01 ; count (2)
|
|
||||||
|
|
||||||
push dword 0x0 ; lba (4)
|
|
||||||
|
|
||||||
push word [bp + 6] ; offset = dst
|
|
||||||
push __STAGE2_SEGMENT ; this segment
|
|
||||||
call read_disk_raw
|
|
||||||
add sp, 0xC
|
|
||||||
|
|
||||||
.check_sig:
|
|
||||||
mov bx, [bp + 6]
|
|
||||||
cmp word [bx + 0x1FE], 0xAA55 ; check for bytes at end
|
|
||||||
jne read_mbr.error
|
|
||||||
; TODO: this needs error checking, zero checking, check the sig a bunch of stuff...
|
|
||||||
.update_globals:
|
|
||||||
mov ax, [bp + 6]
|
|
||||||
add ax, 0x1B8 ; offset to start of PartTable
|
|
||||||
mov [part_table_ptr], ax
|
|
||||||
.endp:
|
|
||||||
__CDECL16_PROC_EXIT
|
|
||||||
ret
|
|
||||||
.error:
|
|
||||||
ERROR STEVIA_DEBUG_ERR
|
|
||||||
|
|
||||||
; int read_vbr(int boot_drive, void* buf)
|
|
||||||
read_vbr:
|
|
||||||
__CDECL16_PROC_ENTRY
|
|
||||||
.proc:
|
|
||||||
__BOCHS_MAGIC_DEBUG
|
|
||||||
; read vbr on boot partition to memory (for fat bpb/ebpb)
|
|
||||||
.calc_part_offset:
|
|
||||||
mov bx, word [part_table_ptr] ; base pointer @ partition table
|
|
||||||
mov cx, 4 ; only checking 4 entries
|
|
||||||
mov si, PartEntry_t.attributes
|
|
||||||
.find_active_L0:
|
|
||||||
mov al, byte [bx + si]
|
|
||||||
test al, 0x80 ; 0x80 == 1000_0000b
|
|
||||||
je read_vbr.active_found
|
|
||||||
add si, 0x10 ; add 16 bytes to offset (next part entry's attributes)
|
|
||||||
loop read_vbr.find_active_L0
|
|
||||||
jmp read_vbr.error
|
|
||||||
.active_found:
|
|
||||||
add bx, si ; update base to active part
|
|
||||||
|
|
||||||
movzx ax, byte [bp + 4]
|
|
||||||
push ax ; drive_num (2)
|
|
||||||
push 0x01 ; count (2)
|
|
||||||
|
|
||||||
mov eax, dword [bx + PartEntry_t.lba_start]
|
|
||||||
push dword eax ; lba (4)
|
|
||||||
|
|
||||||
push word [bp + 6] ; offset = dst
|
|
||||||
push __STAGE2_SEGMENT ; this segment
|
|
||||||
call read_disk_raw
|
|
||||||
add sp, 0xC
|
|
||||||
; vbr (with fat bpb/ebpb) is at the buffer now
|
|
||||||
.check_sig:
|
|
||||||
mov bx, [bp + 6]
|
|
||||||
cmp word [bx + 0x1FE], 0xAA55 ; check for bytes at end
|
|
||||||
jne read_mbr.error
|
|
||||||
.check_FAT_size:
|
|
||||||
test word [bx + FAT32_bpb_t.unused2_ZERO_word], 0 ; TotSectors16 will not be set if FAT32
|
|
||||||
jnz read_vbr.error
|
|
||||||
.update_globals:
|
|
||||||
mov word [fat32_bpb_ptr], bx
|
|
||||||
add bx, FAT32_bpb_t_size ; offset to ebpb
|
|
||||||
mov word [fat32_ebpb_ptr], bx
|
|
||||||
.endp:
|
|
||||||
__CDECL16_PROC_EXIT
|
|
||||||
ret
|
|
||||||
.error:
|
|
||||||
ERROR STEVIA_DEBUG_ERR
|
|
||||||
|
|
||||||
; set ds and es segments back to the base of the loader
|
; set ds and es segments back to the base of the loader
|
||||||
%ifnmacro __TINY_DS_ES
|
%ifnmacro __TINY_DS_ES
|
||||||
%macro __TINY_DS_ES 0
|
%macro __TINY_DS_ES 0
|
||||||
@@ -415,14 +329,25 @@ BootTarget:
|
|||||||
db 'BOOT BIN'
|
db 'BOOT BIN'
|
||||||
|
|
||||||
;
|
;
|
||||||
; pre-bss init globals
|
; pre-bss init globals (generally const...but there are exceptions)
|
||||||
;
|
;
|
||||||
|
|
||||||
; set to boot_drive passed from BIOS almost first thing in init
|
align 8, db 0
|
||||||
align 4, db 0
|
|
||||||
boot_drive:
|
boot_drive:
|
||||||
db 0x00
|
db 0x00
|
||||||
|
|
||||||
|
align 8, db 0
|
||||||
|
partition_offset:
|
||||||
|
dw 0x0000
|
||||||
|
|
||||||
|
align 8, db 0
|
||||||
|
vbr_fat32_bpb_ptr:
|
||||||
|
dw 0x0000
|
||||||
|
|
||||||
|
align 8, db 0
|
||||||
|
vbr_part_table_ptr:
|
||||||
|
dw 0x0000
|
||||||
|
|
||||||
align 16, db 0
|
align 16, db 0
|
||||||
IntToHex_table:
|
IntToHex_table:
|
||||||
db '0123456789ABCDEF'
|
db '0123456789ABCDEF'
|
||||||
@@ -504,39 +429,19 @@ BUILD_GIT_HASH:
|
|||||||
db __GIT_HASH__, 00h
|
db __GIT_HASH__, 00h
|
||||||
end_data:
|
end_data:
|
||||||
|
|
||||||
%assign bytes_remaining ((MAX_STAGE2_BYTES - 512) - (($ - $$) + (end_text - begin_text)))
|
%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)
|
%warning STAGE2 has bytes_remaining bytes remaining for code/data (MAX: MAX_STAGE2_BYTES)
|
||||||
|
|
||||||
; section start location needs to be a 'critical expression'
|
; section start location needs to be a 'critical expression'
|
||||||
; i.e resolvable at build time, we are setting 0x0500 as the offset since
|
; i.e resolvable at build time, we are setting 0x7E00 as the offset since
|
||||||
section .sign start=((MAX_STAGE2_BYTES - 512) + 0x0500)
|
section .sign start=((MAX_STAGE2_BYTES - 512) + 0x0500)
|
||||||
times ((512 - 4) - ($ -$$) ) db 0x90 ; nop
|
times ((512 - 4) - ($ -$$) ) db 0x90 ; nop
|
||||||
STAGE2_SIG: dd 0xDEADBEEF ; Signature to mark the end of the stage2
|
STAGE2_SIG: dd 0xDEADBEEF ; Signature to mark the end of the stage2
|
||||||
|
|
||||||
section .bss follows=.sign
|
section .bss follows=.sign
|
||||||
begin_bss:
|
begin_bss:
|
||||||
|
|
||||||
align 4, resb 1
|
|
||||||
mbr_ptr:
|
|
||||||
resw 1
|
|
||||||
|
|
||||||
align 4, resb 1
|
|
||||||
vbr_ptr:
|
|
||||||
resw 1
|
|
||||||
|
|
||||||
align 4, resb 1
|
|
||||||
part_table_ptr:
|
|
||||||
resw 1
|
|
||||||
|
|
||||||
align 4, resb 1
|
|
||||||
fat32_bpb_ptr:
|
|
||||||
resw 1
|
|
||||||
|
|
||||||
align 4, resb 1
|
|
||||||
fat32_ebpb_ptr:
|
|
||||||
resw 1
|
|
||||||
|
|
||||||
; structures
|
; structures
|
||||||
|
|
||||||
align 16, resb 1
|
align 16, resb 1
|
||||||
partition_table:
|
partition_table:
|
||||||
resb PartTable_t_size
|
resb PartTable_t_size
|
||||||
|
|||||||
@@ -21,7 +21,6 @@
|
|||||||
%define __STEVIA_VBR
|
%define __STEVIA_VBR
|
||||||
section .text
|
section .text
|
||||||
__ENTRY:
|
__ENTRY:
|
||||||
phy_bpb_start:
|
|
||||||
jmp short (init - $$)
|
jmp short (init - $$)
|
||||||
nop
|
nop
|
||||||
|
|
||||||
@@ -42,6 +41,7 @@ times 54 db 0x00
|
|||||||
%include "cdecl16.inc"
|
%include "cdecl16.inc"
|
||||||
%include "entry.inc"
|
%include "entry.inc"
|
||||||
%include "config.inc"
|
%include "config.inc"
|
||||||
|
%include "early_mem.inc"
|
||||||
%include "error_codes.inc"
|
%include "error_codes.inc"
|
||||||
%include "partition_table.inc"
|
%include "partition_table.inc"
|
||||||
%include "fat32/fat32_structures.inc"
|
%include "fat32/fat32_structures.inc"
|
||||||
@@ -72,7 +72,7 @@ init:
|
|||||||
cld
|
cld
|
||||||
rep stosb
|
rep stosb
|
||||||
|
|
||||||
sub sp, 0x10 ; local varible space (32 bytes)
|
sub sp, 0x20 ; local varible space (32 bytes)
|
||||||
push bp
|
push bp
|
||||||
|
|
||||||
sti ; all done with inital setup and relocation, reenable interupts
|
sti ; all done with inital setup and relocation, reenable interupts
|
||||||
@@ -86,15 +86,41 @@ init:
|
|||||||
%include "util/kmem_func.nasm"
|
%include "util/kmem_func.nasm"
|
||||||
%include "util/error_func.nasm"
|
%include "util/error_func.nasm"
|
||||||
|
|
||||||
|
; ###############
|
||||||
|
; End Section
|
||||||
|
; ###############
|
||||||
|
|
||||||
;
|
;
|
||||||
; byte boot_drive @ bp - 2
|
; byte boot_drive @ bp - 2
|
||||||
; word part_offset @ bp - 4
|
; word part_offset @ bp - 4
|
||||||
; ptr partition_table
|
; ptr partition_table
|
||||||
ALIGN 4, db 0x90
|
ALIGN 4, db 0x90
|
||||||
main:
|
main:
|
||||||
mov byte [bp - 2], dl ; boot_drive
|
mov byte [bp - 2], dl ; boot_drive
|
||||||
.check_FAT_size: ; we only support a very specific setup of FAT32
|
mov word [bp - 4], si ; part_offset
|
||||||
mov bx, phy_bpb_start
|
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
|
||||||
test word [bx + FAT32_bpb_t.unused2_ZERO_word], 0 ; TotSectors16 will not be set if FAT32
|
test word [bx + FAT32_bpb_t.unused2_ZERO_word], 0 ; TotSectors16 will not be set if FAT32
|
||||||
jz main.load_stage2
|
jz main.load_stage2
|
||||||
ERROR VBR_ERROR_WRONG_FAT_SIZE
|
ERROR VBR_ERROR_WRONG_FAT_SIZE
|
||||||
@@ -103,13 +129,17 @@ main:
|
|||||||
movzx ax, byte [bp - 2]
|
movzx ax, byte [bp - 2]
|
||||||
push ax ; drive_num
|
push ax ; drive_num
|
||||||
|
|
||||||
push STAGE2_SECTOR_COUNT ; count
|
mov ax, STAGE2_SECTOR_COUNT
|
||||||
|
push ax ; count
|
||||||
|
|
||||||
mov dword eax, 0x1
|
mov dword eax, 0x1
|
||||||
push dword eax ; lba
|
push dword eax ; lba
|
||||||
|
|
||||||
push STAGE2_ENTRY ; offset
|
mov ax, STAGE2_ENTRY
|
||||||
push 0x00 ; segment = 0
|
push ax ; offset
|
||||||
|
|
||||||
|
xor ax, ax
|
||||||
|
push ax ; segment = 0
|
||||||
|
|
||||||
; uint8_t read_stage2_raw(uint16_t buf_segment, uint16_t buf_offset,
|
; uint8_t read_stage2_raw(uint16_t buf_segment, uint16_t buf_offset,
|
||||||
; uint32_t lba,
|
; uint32_t lba,
|
||||||
@@ -117,7 +147,10 @@ main:
|
|||||||
call read_disk_raw
|
call read_disk_raw
|
||||||
add sp, 0xC
|
add sp, 0xC
|
||||||
.enter_stage2:
|
.enter_stage2:
|
||||||
mov dl, byte [bp - 2] ; byte boot_drive
|
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
|
jmp word 0x0000:STAGE2_ENTRY
|
||||||
|
|
||||||
; ###############
|
; ###############
|
||||||
@@ -133,16 +166,25 @@ times (510 - ($ - $$)) nop ; Fill the rest of sector with nop
|
|||||||
|
|
||||||
BootSig:
|
BootSig:
|
||||||
dw 0xAA55 ; Add boot signature at the end of bootloader
|
dw 0xAA55 ; Add boot signature at the end of bootloader
|
||||||
; !!! END VBR !!!
|
|
||||||
|
|
||||||
section .bss follows=.text
|
section .bss follows=.text
|
||||||
begin_bss:
|
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
|
align 16, resb 1
|
||||||
lba_packet resb LBAPkt_t_size
|
lba_packet resb LBAPkt_t_size
|
||||||
|
|
||||||
align 512, resb 1
|
align 512, resb 1
|
||||||
stack_bottom resb (1024 - 16) ; 512b stack early on
|
stack_bottom resb 512 ; 512b stack early on
|
||||||
stack_top:
|
stack_top:
|
||||||
vbr_redzone resb 16
|
vbr_redzone resb 32
|
||||||
end_bss:
|
end_bss:
|
||||||
Reference in New Issue
Block a user