From 320a0c820a129a39cc6a8a383ea4e2770f3ee50b Mon Sep 17 00:00:00 2001
From: =?utf8?q?Duje=20Mihanovi=C4=87?= <duje.mihanovic@skole.hr>
Date: Sat, 18 Jun 2022 15:38:14 +0200
Subject: [PATCH] Compile stage3 in ELF format

During linking it gets converted to a good old flat binary. This was done so
that the ELF loading code can be written in C, which will save me plenty of
headaches later.

Also, since with ELF that's possible, stack space for stage3 is now reserved and
set up in a similar (same) fashion to the kernel.
---
 boot/x86/Makefile         | 14 +++++++++++---
 boot/x86/stage3/a20.s     |  3 +++
 boot/x86/stage3/e820.s    |  2 ++
 boot/x86/stage3/gdt.s     |  3 +++
 boot/x86/stage3/loader.s  | 16 +++++++++++-----
 boot/x86/stage3/print.s   |  3 +++
 boot/x86/stage3/stage3.ld | 17 +++++++++++++++++
 boot/x86/stage3/unreal.s  |  5 +++++
 8 files changed, 55 insertions(+), 8 deletions(-)
 create mode 100644 boot/x86/stage3/stage3.ld

diff --git a/boot/x86/Makefile b/boot/x86/Makefile
index 1de8199..0e5ac00 100644
--- a/boot/x86/Makefile
+++ b/boot/x86/Makefile
@@ -1,15 +1,23 @@
 default: mbr vbr-fat32 stage3/LOADER.BIN
 
+LD=i686-elf-gcc
+LDFLAGS=-T stage3/stage3.ld -nostdlib
+
+STAGE3_OBJ=stage3/loader.o
+
 mbr: mbr.s
 	$(AS) $(ASFLAGS) -w-zeroing -o $@ $<
 
 vbr-fat32: vbr-fat32.s fat32/*.s
 	$(AS) $(ASFLAGS) -o $@ $<
 
-stage3/LOADER.BIN: stage3/loader.s stage3/*.s
-	$(AS) $(ASFLAGS) -DGIT_REVISION=\"$(GIT_REV)\" -o $@ $<
+stage3/LOADER.BIN: $(STAGE3_OBJ)
+	$(LD) $(LDFLAGS) -o $@ $<
+
+stage3/loader.o: stage3/loader.s stage3/*.s
+	$(AS) $(ASFLAGS) -f elf -g dwarf2 -DGIT_REVISION=\"$(GIT_REV)\" -o $@ $<
 
 clean:
-	-rm mbr vbr-fat32 stage3/LOADER.BIN disk.img
+	-rm mbr vbr-fat32 stage3/LOADER.BIN $(STAGE3_OBJ) disk.img
 
 .PHONY : default clean
diff --git a/boot/x86/stage3/a20.s b/boot/x86/stage3/a20.s
index 8748dde..392e83d 100644
--- a/boot/x86/stage3/a20.s
+++ b/boot/x86/stage3/a20.s
@@ -1,3 +1,6 @@
+bits 16
+section .text
+
 %macro in_wait 0
 	push ax
 %%loop:
diff --git a/boot/x86/stage3/e820.s b/boot/x86/stage3/e820.s
index 247b361..2d1780b 100644
--- a/boot/x86/stage3/e820.s
+++ b/boot/x86/stage3/e820.s
@@ -1,6 +1,7 @@
 ; Code for getting the BIOS E820 memory map
 
 bits 16
+section .text
 
 ; Return: ECX - number of entries, DI - pointer to map
 get_e820_map:
@@ -61,5 +62,6 @@ get_e820_map:
 		hlt
 		jmp $-1
 
+section .rodata
 no_e820: db "BIOS does not support E820, cannot proceed!", 0xd, 0xa, 0
 e820_unexpected: db "Unexpected value in EAX after getting map entry: expected SMAP, got ", 0
diff --git a/boot/x86/stage3/gdt.s b/boot/x86/stage3/gdt.s
index d81bb64..843df7b 100644
--- a/boot/x86/stage3/gdt.s
+++ b/boot/x86/stage3/gdt.s
@@ -1,4 +1,7 @@
 ; Initial GDT for kernel, which wants a flat code and data descriptor
+
+section .rodata
+
 gdt:
 	dw .end-.start-1
 	dd .start
diff --git a/boot/x86/stage3/loader.s b/boot/x86/stage3/loader.s
index 747905d..cdecbaa 100644
--- a/boot/x86/stage3/loader.s
+++ b/boot/x86/stage3/loader.s
@@ -1,7 +1,7 @@
 bits 16
 cpu 686
-org 0x1800
 
+section .text
 %include "../fat32/fat32-structs.s"
 
 %macro print 1
@@ -11,7 +11,11 @@ org 0x1800
 	pop si
 %endmacro
 
+extern __STACK_BOTTOM__
+
+global _start
 _start:
+	mov sp, __STACK_BOTTOM__
 	mov [BOOT_DRIVE], dl
 	call enable_unreal
 	print begin
@@ -147,7 +151,6 @@ memcpy:
 	pop esi
 	ret
 
-
 %include "unreal.s"
 %include "a20.s"
 %include "../fat32/fat32.s"
@@ -155,8 +158,9 @@ memcpy:
 %include "print.s"
 %include "e820.s"
 
-in_protected:
 bits 32
+section .text
+in_protected:
 	mov ax, 0x10
 	mov ds, ax
 	mov es, ax
@@ -170,6 +174,10 @@ bits 32
 	jmp 0x8:0xc0000000
 	nop
 
+%include "paging.s"
+
+section .rodata
+
 kernel_name: db "KERNEL  BIN"
 begin: db "Nameless Bootloader revision ", GIT_REVISION, 0xd, 0xa, 0
 a20_enabled: db "A20 has been enabled", 0xd, 0xa, "Searching for kernel...", 0xd, 0xa, 0
@@ -192,5 +200,3 @@ ss_s: db "SS: ", 0
 space: db " ", 0
 hex_delm: db "0x", 0
 newline: db 0xd, 0xa, 0
-
-%include "paging.s"
diff --git a/boot/x86/stage3/print.s b/boot/x86/stage3/print.s
index 73b34d5..edc7107 100644
--- a/boot/x86/stage3/print.s
+++ b/boot/x86/stage3/print.s
@@ -1,5 +1,8 @@
 ; Routines for printing
 
+bits 16
+section .text
+
 print_str:
 	push ax
 	push bx
diff --git a/boot/x86/stage3/stage3.ld b/boot/x86/stage3/stage3.ld
new file mode 100644
index 0000000..1accdc0
--- /dev/null
+++ b/boot/x86/stage3/stage3.ld
@@ -0,0 +1,17 @@
+ENTRY(_start)
+OUTPUT_FORMAT(binary)
+
+SECTIONS {
+	. = 0x1800;
+	.text : {
+		stage3/loader.o(.text)
+		*(.text)
+	}
+	.rodata : { *(.rodata) }
+	.data : { *(.data) }
+	.bss : {
+		*(.bss)
+		. += 1K;
+		PROVIDE(__STACK_BOTTOM__ = .);
+	}
+}
diff --git a/boot/x86/stage3/unreal.s b/boot/x86/stage3/unreal.s
index cdd361b..1fbe1f9 100644
--- a/boot/x86/stage3/unreal.s
+++ b/boot/x86/stage3/unreal.s
@@ -1,5 +1,8 @@
 ; Routine for enabling unreal mode, which allows using 32-bit offsets in real mode
 
+bits 16
+section .text
+
 enable_unreal:
 	cli
 	push eax
@@ -25,6 +28,8 @@ enable_unreal:
 	sti
 	ret
 
+section .rodata
+
 ; GDT with 1 flat data segment descriptor
 gdt_info:
 	dw gdt_end-gdt_start-1
-- 
2.39.5