From 7adc0c7ce11c6c46c5e6c4cb01a94af1edb6b6d5 Mon Sep 17 00:00:00 2001
From: Robert <robert.altner@einweckglas.com>
Date: Sun, 3 Sep 2023 20:11:33 +0200
Subject: [PATCH] port clipper to boot using grub

---
 Makefile              |  44 ++++-----
 grub/grub.cfg         |   3 +
 linker.ld             |  28 ++++++
 src/boot/boot.asm     | 217 ------------------------------------------
 src/kernel/boot.asm   |  36 +++++++
 src/kernel/kernel.asm |   0
 src/kernel/kmain.c    |  15 +++
 7 files changed, 104 insertions(+), 239 deletions(-)
 create mode 100644 grub/grub.cfg
 create mode 100644 linker.ld
 delete mode 100644 src/boot/boot.asm
 create mode 100644 src/kernel/boot.asm
 delete mode 100644 src/kernel/kernel.asm
 create mode 100644 src/kernel/kmain.c

diff --git a/Makefile b/Makefile
index 9302292..697e49f 100644
--- a/Makefile
+++ b/Makefile
@@ -1,37 +1,37 @@
 ASM=nasm
+CC=$(HOME)/opt/cross/bin/i686-elf-gcc
 
 SRC_DIR=src
 BUILD_DIR=build
+ISO_DIR=$(BUILD_DIR)/iso
 
-BOOT_FILES 		= $(shell find $(SRC_DIR)/boot/ -type f -name "*.asm")
-KERN_ASM_FILES 	= $(shell find $(SRC_DIR)/kernel/ -type f -name "*.asm")
+KERNEL_ASM		:= $(shell find $(SRC_DIR)/kernel -name "*.asm")
+KERNEL_C		:= $(shell find $(SRC_DIR)/kernel -name "*.c")
 
-BOOT_BIN_FILES 	= $(patsubst src/%.asm, $(BUILD_DIR)/%.bin, $(BOOT_FILES))
-KERN_BIN_FILES 	= $(patsubst src/%.asm, $(BUILD_DIR)/%.bin, $(KERN_ASM_FILES))
+KERNEL_ASM_O	:= $(patsubst $(SRC_DIR)/kernel/%.asm, $(BUILD_DIR)/kernel/%.asm.o, $(KERNEL_ASM))
+KERNEL_C_O		:= $(patsubst $(SRC_DIR)/kernel/%.c, $(BUILD_DIR)/kernel/%.c.o, $(KERNEL_C))
 
-BOOTLOADER 		= $(BUILD_DIR)/boot.bin
-KERNEL 			= $(BUILD_DIR)/kernel.bin
-IMAGE			= $(BUILD_DIR)/clipper.img
+KERNEL 			= $(BUILD_DIR)/clipper.bin
+IMAGE			= $(BUILD_DIR)/clipper.iso
 
-.PHONY: all clipper kernel bootloader clean always
+.PHONY: all clipper kernel clean always
 
-clipper: $(IMAGE)
+clipper: kernel
+	mkdir -p $(ISO_DIR)/boot/grub
+	cp $(KERNEL) $(ISO_DIR)/boot/clipper.bin
+	cp grub/grub.cfg $(ISO_DIR)/boot/grub/grub.cfg
+	grub-mkrescue -o $(IMAGE) $(ISO_DIR)
 
-$(IMAGE): bootloader kernel
-	dd if=/dev/zero of=$(IMAGE) bs=512 count=2880
-	mkfs.fat -F 12 -n "CLPR" $(IMAGE)
-	dd if=$(BOOTLOADER) of=$(IMAGE) conv=notrunc
-	mcopy -i $(IMAGE) $(KERNEL) "::kernel.bin"
+kernel: $(KERNEL_ASM_O) $(KERNEL_C_O)
+	$(CC) -T linker.ld -o $(KERNEL) -ffreestanding -O2 -nostdlib $^ -lgcc
 
-bootloader: $(BOOT_BIN_FILES)
-	cp $(BUILD_DIR)/boot/boot.bin $(BOOTLOADER)
-
-kernel: $(KERN_BIN_FILES)
-	cp $(BUILD_DIR)/kernel/kernel.bin $(KERNEL)
-
-$(BUILD_DIR)/%.bin: $(SRC_DIR)/%.asm
+$(BUILD_DIR)/%.asm.o: $(SRC_DIR)/%.asm
 	@mkdir -p "$(@D)"
-	$(ASM) $< -f bin -o $@
+	$(ASM) -felf32 $< -o $@
+
+$(BUILD_DIR)/%.c.o: $(SRC_DIR)/%.c
+	@mkdir -p "$(@D)"
+	$(CC) -c $< -o $@ -std=gnu99 -ffreestanding -O2 -Wall -Wextra
 
 clean:
 	rm -rf $(BUILD_DIR)/*
diff --git a/grub/grub.cfg b/grub/grub.cfg
new file mode 100644
index 0000000..a61dd4a
--- /dev/null
+++ b/grub/grub.cfg
@@ -0,0 +1,3 @@
+menuentry "clipper" {
+	multiboot /boot/clipper.bin
+}
diff --git a/linker.ld b/linker.ld
new file mode 100644
index 0000000..0e93f9b
--- /dev/null
+++ b/linker.ld
@@ -0,0 +1,28 @@
+ENTRY(_start)
+
+SECTIONS
+{
+	. = 1M;
+
+	.text BLOCK(4K) : ALIGN(4K)
+	{
+		*(.multiboot)
+		*(.text)
+	}
+
+	.rodata BLOCK(4K) : ALIGN(4K)
+	{
+		*(.rodata)
+	}
+
+	.data BLOCK(4K) : ALIGN(4K)
+	{
+		*(.data)
+	}
+
+	.bss BLOCK(4K) : ALIGN(4K)
+	{
+		*(COMMON)
+		*(.bss)
+	}
+}
diff --git a/src/boot/boot.asm b/src/boot/boot.asm
deleted file mode 100644
index d71a580..0000000
--- a/src/boot/boot.asm
+++ /dev/null
@@ -1,217 +0,0 @@
-org 0x7C00
-bits 16
-
-%define ENDL 0x0D, 0x0A
-
-; FAT 12 BIOS PARAMETER BLOCK
-jmp short start
-nop
-bpb_oem:					db "CLPROS01"
-bpb_bytes_per_sector:		dw 512
-bpb_sectors_per_cluster:	db 1
-bpb_reserved_sectors:		dw 1
-bpb_fat_count:				db 2
-bpb_dir_entries_count:		dw 0E0h
-bpb_total_sectors:			dw 2880
-bpb_media_descriptor_type:	db 0F0h
-bpb_sectors_per_fat:		dw 9
-bpb_sectors_per_track:		dw 18
-bpb_heads:					dw 2
-bpb_hidden_sectors:			dd 0
-bpb_large_sector_count:		dd 0
-
-; EXTENDED BOOT RECORD
-ebr_drive_number:			db 0
-							db 0
-ebr_signature:				db 28h
-ebr_volume_id:				db 63h, 6Ch, 70h, 72h
-ebr_volume_label:			db "Clipper    "
-ebr_system_identifier:		db "FAT12   "
-
-start:
-	jmp main
-
-;
-; Prints a string to the screen
-; Params:
-;	- ds:si points to string
-puts:
-	push si
-	push ax
-
-	mov ah, 0Eh
-
-.loop:
-	lodsb		; load byte at ds:si into al
-	or al, al	; is null?
-	jz .done
-
-	int 10h
-	jmp .loop
-
-.done:
-	pop si
-	pop ax
-	ret
-	
-
-main:
-	; setup data segment
-	mov ax, 0
-	mov ds, ax
-	mov es, ax
-
-	; setup stack
-	mov ss, ax
-	mov sp, 0x7C00
-
-	; print message
-	mov si, msg_hello
-	call puts
-
-	; read something from disk
-	mov [ebr_drive_number], dl
-	mov ax, 1
-	mov cl, 1
-	mov bx, 0x7E00
-	call disk_read
-
-	mov di, 0
-	mov cl, [ebr_drive_number]
-.loop:
-	xor ch, ch
-	shl cx, 4
-	add ch, 30h
-	test cx, 9
-	jle .write_disk_number
-	add ch, 11h 
-
-.write_disk_number:
-	mov byte [msg_drive_number_value + di], ch
-	inc di
-	cmp di, 2
-	jne .loop
-
-	mov si, msg_drive_number
-	call puts
-
-	hlt
-	jmp halt
-
-floppy_error:
-	mov si, msg_read_failed
-	call puts
-	jmp wait_key_and_reboot
-	
-wait_key_and_reboot:
-	mov ah, 0
-	int 16h
-	jmp 0FFFFh:0 
-	hlt
-
-halt:
-	cli
-	hlt
-
-;
-; Convert LBA address to CHS
-; Parameters:
-;	- ax: LBA address
-; Returns:
-;	- cx [bits 0-5]: sector
-;	- cx [bits 6-15]: cylinder
-;	- dh: head
-;
-lba_to_chs:
-	push ax
-	push dx
-
-	xor dx, dx
-	div word [bpb_sectors_per_track]
-
-	inc dx
-	mov cx, dx
-
-	xor dx, dx
-	div word [bpb_heads]
-
-	mov dh, dl
-	mov ch, al
-	shl ah, 6
-	or cl, ah
-
-	pop ax
-	mov dl, al
-	pop ax
-	ret
-
-;
-; Reads from disk
-; Parameters:
-; 	- ax: LBA address
-;	- cl: number of sectors to read (max 128)
-;	- dl: drive number
-;	- es:bx: memory address where to store data
-;
-disk_read:
-	push ax
-	push bx
-	push cx
-	push dx
-	push di
-
-	push cx
-	call lba_to_chs
-	pop ax
-
-	mov ah, 02h
-	mov di, 3
-
-.retry:
-	pusha
-	stc 
-	int 13h
-	jnc .done
-
-	popa
-	call disk_reset
-
-	dec di
-	jnz .retry
-
-.fail:
-	jmp floppy_error
-
-.done:
-	popa
-
-	pop di
-	pop dx
-	pop cx
-	pop bx
-	pop ax
-	ret
-
-;
-; Resets a disk controller
-; Parameters:
-;	dl: drive number
-;
-disk_reset:
-	pusha
-	mov ah, 0
-	stc
-	int 13h
-	jc floppy_error
-	popa
-	ret
-
-
-msg_hello: 				db "Hello, Clipper!", ENDL, 0
-msg_read_failed:		db "Failed to read from disk.", ENDL, 0
-msg_drive_number:		db "Disk number: "
-msg_drive_number_value: dw 0
-msg_drive_number_end:	db ENDL, 0
-
-times 510-($-$$) db 0
-dw 0AA55h
diff --git a/src/kernel/boot.asm b/src/kernel/boot.asm
new file mode 100644
index 0000000..d3ef922
--- /dev/null
+++ b/src/kernel/boot.asm
@@ -0,0 +1,36 @@
+;
+; Bootstrap code for the Clipper operating system
+;
+
+MBALIGN		equ		1 << 0
+MEMINFO 	equ		1 << 1
+FLAGS   	equ 	MBALIGN | MEMINFO
+MAGIC   	equ 	0x1BADB002
+CHECKSUM 	equ		-(MAGIC + FLAGS)
+
+; multiboot header
+section .multiboot
+align 4
+	dd MAGIC
+	dd FLAGS
+	dd CHECKSUM
+
+section .bss
+align 16
+stack_bottom:
+	resb 16384
+stack_top:
+
+section .text
+global _start: function (_start.end - _start)
+_start:
+	mov esp, stack_top
+
+	extern kmain
+	call kmain
+
+	cli
+.hang:
+	hlt
+	jmp .hang
+.end:
diff --git a/src/kernel/kernel.asm b/src/kernel/kernel.asm
deleted file mode 100644
index e69de29..0000000
diff --git a/src/kernel/kmain.c b/src/kernel/kmain.c
new file mode 100644
index 0000000..b146843
--- /dev/null
+++ b/src/kernel/kmain.c
@@ -0,0 +1,15 @@
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdint.h>
+
+#if defined(__linux__)
+#	error "Please use a platform agnostic compiler"
+#endif
+
+#if !defined(__i386__)
+#	error "Please use an ix86-elf compiler"
+#endif
+
+void kmain(void) {
+	return;
+}