summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIan Moffett <ian@osmora.org>2025-11-10 23:19:38 -0500
committerIan Moffett <ian@osmora.org>2025-11-10 23:19:38 -0500
commit2b4d74005690b074ffe95f50e9f01fd70cd1e605 (patch)
tree2cc959650ac50d5d131f046e23fb4b0a76bc1d72
initial commit
Signed-off-by: Ian Moffett <ian@osmora.org>
-rw-r--r--.gitignore2
-rw-r--r--Makefile27
-rw-r--r--link.ld21
-rw-r--r--mbr/stage1.asm79
-rw-r--r--src/entry.c5
5 files changed, 134 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..98f5968
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,2 @@
+*.bin
+*.o
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..cf4e41d
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,27 @@
+AS = nasm
+CC = clang
+CFILES = $(shell find src/ -name "*.c")
+OFILES = $(CFILES:.c=.o)
+
+LDFLAGS = -nostdlib -Tlink.ld -no-pie
+CFLAGS = -ffreestanding -nostdinc -fno-pic -mno-sse -mno-sse2 \
+ -mno-mmx -mno-80387 -fno-stack-protector
+
+.PHONY: all
+all: $(OFILES) stage1.bin stage2.bin
+ cat stage1.bin stage2.bin >boot.bin
+
+.PHONY: stage1.bin
+stage1.bin:
+ $(AS) -fbin mbr/stage1.asm -o $@
+
+.PHONY: stage2.bin
+stage2.bin:
+ $(CC) $(LDFLAGS) $(OFILES) -o $@
+
+%.o: %.c
+ $(CC) -c $(CFLAGS) $< -o $@
+
+.PHONY: test
+test:
+ qemu-system-i386 -hda boot.bin --enable-kvm
diff --git a/link.ld b/link.ld
new file mode 100644
index 0000000..5eeb34f
--- /dev/null
+++ b/link.ld
@@ -0,0 +1,21 @@
+OUTPUT_FORMAT(binary)
+ENTRY(main)
+
+SECTIONS {
+ . = 0x8000;
+
+ .text : {
+ *(.text)
+ }
+
+ .data : {
+ *(.data)
+ }
+
+ .bss : {
+ __bss_start = .;
+ *(COMMON)
+ *(.bss)
+ __bss_end = .;
+ }
+}
diff --git a/mbr/stage1.asm b/mbr/stage1.asm
new file mode 100644
index 0000000..ea51f22
--- /dev/null
+++ b/mbr/stage1.asm
@@ -0,0 +1,79 @@
+[org 0x7C00]
+
+_start:
+ xor ax, ax
+ mov ds, ax
+ mov es, ax
+ mov ss, ax
+ mov fs, ax
+ mov gs, ax
+
+ cli ;; Disable all interrupts
+ cld ;; Strings shall increment
+ mov [boot_drive], dl ;; Save the boot drive
+
+ mov si, boot_sig
+ call print_str
+ call enable_a20
+ call disk_load
+
+ jmp 0x0000:0x8000
+ hlt
+ jmp $
+
+;;
+;; Write a string to the screen
+;;
+;; [SI]: Base address of string
+;;
+print_str:
+ lodsb ;; Load *(SI++) -> AL
+ or al, al ;; Null byte?
+ jz .done ;; Yup, finish
+ mov ah, 0x0E ;; Print char
+ int 0x10 ;; BIOS call
+ jmp print_str ;; Loop again until NUL
+.done:
+ ret
+
+;;
+;; Enable the A20 gate to access the full
+;; 16 megs
+;;
+enable_a20:
+ in al, 0x92 ;; Check the state
+ test al, 2 ;; is it already set?
+ jnz .done ;; Yes, no need to re-enable
+ or al, 2 ;; No, enable it
+ out 0x92, al ;; Write the new value back
+.done:
+ ret
+
+DAP:
+ .size: db 0x10
+ .reserved: db 0x00
+ .count: dw 1
+ .buffer: dw 0x8000
+ .segment: dw 0
+ .lba_lo: dd 1
+ .lba_hi: dd 0
+disk_load:
+ mov si, DAP
+ mov ah, 0x42
+ mov dl, [boot_drive]
+ int 0x13
+ jc .disk_err
+ ret
+.disk_err:
+ mov si, disk_errmsg
+ call print_str
+.hang:
+ hlt
+ jmp .hang
+
+boot_sig: db "* beepboot stage0", 0x0A, 0x0D, 0x00
+disk_errmsg: db "[!] failed to read disk", 0x0A, 0x0D, 0x00
+boot_drive: db 0
+
+times 510 - ($ - $$) db 0
+dw 0xAA55
diff --git a/src/entry.c b/src/entry.c
new file mode 100644
index 0000000..45698fd
--- /dev/null
+++ b/src/entry.c
@@ -0,0 +1,5 @@
+int
+main(void)
+{
+ for (;;);
+}