From e16da3adc87e34bab07763589cb601667b5b9679 Mon Sep 17 00:00:00 2001
From: Jarkko Toivanen <jt@jakest.us>
Date: Mon, 24 Jul 2023 21:48:21 +0300
Subject: [PATCH] Multiboot parsing and uitoa impl

---
 Makefile          |   2 +-
 src/itoa.asm      |  98 ++++++++++++++++++++++++++++++++++++++
 src/mbootinfo.asm | 118 ++++++++++++++++++++++++++++++++++++++++++++++
 src/start32.asm   | 118 +++++++++++++++++++++++++++++-----------------
 4 files changed, 291 insertions(+), 45 deletions(-)
 create mode 100644 src/itoa.asm
 create mode 100644 src/mbootinfo.asm

diff --git a/Makefile b/Makefile
index 1e50876..33d69be 100644
--- a/Makefile
+++ b/Makefile
@@ -2,7 +2,7 @@ all: build/kernel-i386.elf
 clean:
 	-@rm *.bin 2> /dev/null || true
 
-start32.bin: src/start32.asm src/serial.asm
+start32.bin: src/*
 	fasm src/start32.asm start32.bin
 image: start32.bin mount
 	cp start32.bin mnt/koalemos/
diff --git a/src/itoa.asm b/src/itoa.asm
new file mode 100644
index 0000000..914b214
--- /dev/null
+++ b/src/itoa.asm
@@ -0,0 +1,98 @@
+;; Modified from: https://gist.github.com/SplittyDev/8e728627012e57ac0deac196660014fb
+
+;
+; Routine to convert a 32-bit integer to a string.
+; Registers are preserved.
+;
+; EAX: Source integer
+; EBX: Target address
+; ECX: Base
+;
+; Internal register layout:
+; start:
+; EAX: Source integer
+; ECX: Target address
+; EDX: Base
+; checknegative:
+; EAX: Source integer
+; EBX: Target address (original)
+; ECX: Target address (active)
+; divrem:
+; EAX: Source integer
+; ECX: Target address (active)
+; EDX: Base / Result
+; reverse:
+; EBX: Target address (original)
+; ECX: Target address (active)
+; EDX: Target address (temporary)
+;
+__uitoa:
+.start:
+	push ebp
+	mov ebp, esp
+
+	push eax
+	push ebx
+	push ecx
+	push edx
+
+	mov eax, [ebp+8]
+	mov ecx, [ebp+12]
+	mov ebx, [ebp+16]
+
+	mov edx, ecx
+	mov ecx, ebx
+;.checknegative:
+;    test eax, eax
+;    jns .divrem
+;    mov byte [ecx], 0x2D
+;    inc ecx
+;    mov ebx, ecx
+;    neg eax
+.divrem:
+	push edx
+	push ecx
+	mov ecx, edx
+	xor edx, edx
+	div ecx
+	mov byte dl, [__itoacvt + edx]
+	pop ecx
+	mov byte [ecx], dl
+	pop edx
+	inc ecx
+	cmp eax, 0x00
+	jne .divrem
+	mov byte [ecx], 0x00
+	dec ecx
+.reverse:
+	cmp ebx, ecx
+	jge .end
+	mov byte dl, [ebx]
+	mov byte al, [ecx]
+	mov byte [ebx], al
+	mov byte [ecx], dl
+	inc ebx
+	dec ecx
+	jmp .reverse
+.end:
+	pop edx
+	pop ecx
+	pop ebx
+	pop eax
+
+	pop ebp
+	ret
+
+;
+; Conversion table for __itoa.
+; Works for bases [2 ... 36].
+;
+__itoacvt:
+	db '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+
+;
+; Buffer to store the result of __itoa in.
+;
+align 64
+__itoabuf32:
+	rb 36
diff --git a/src/mbootinfo.asm b/src/mbootinfo.asm
new file mode 100644
index 0000000..a12504a
--- /dev/null
+++ b/src/mbootinfo.asm
@@ -0,0 +1,118 @@
+mbootgetinfo:
+	push ebp
+	mov ebp, esp
+	push ebx
+	push esi
+	push edi
+	cld
+
+	mov eax, [ebp+8]
+	cmp eax, 0x2badb002
+	jne mbootnomagic
+
+	mov ebx, [ebp+12]
+	mov eax, [ebx]
+	mov [mbootinfo.flags], eax
+
+	;; Get memoryinformation
+	test eax, 1b
+	jz mbootnomeminfo
+	mov eax, [ebx+4]
+	mov [mbootinfo.mem_lower], eax
+	mov eax, [ebx+8]
+	mov [mbootinfo.mem_upper], eax
+
+	;; Get videoinformation
+	test [mbootinfo.flags], (1 shl 02)
+	jz mbootnovideoinfo
+
+	mov esi, ebx
+	add esi, 88
+	mov eax, [esi]
+	mov [mbootinfo.fb_addr], eax
+	add esi, 8
+
+	mov eax, [esi]
+	mov [mbootinfo.fb_pitch], eax
+	add esi, 4
+
+	mov eax, [esi]
+	mov [mbootinfo.fb_width], eax
+	add esi, 4
+
+	mov eax, [esi]
+	mov [mbootinfo.fb_height], eax
+	add esi, 4
+
+	mov al, [esi]
+	cmp al, 32
+	je .bppokay
+	cmp al, 24
+	je .bppokay
+	jmp mbootunsupportedfbbpp
+.bppokay:
+	mov [mbootinfo.fb_bpp], al
+	inc esi
+
+	mov al, [esi]
+	cmp al, 1
+	jne mbootunsupportedfbtype
+	mov [mbootinfo.fb_type], al
+	inc esi
+
+	;; r/g/b positions and masks
+	mov ecx, 6
+	mov edi, mbootinfo.fb_rpos
+	rep movsb
+
+.done:
+	pop edi
+	pop esi
+	pop ebx
+	pop ebp
+	ret
+
+
+mbootnomagic:
+	push .msg
+	call serialwrite
+	jmp hang
+.msg db "No multiboot magic!", 10, 0
+mbootnomeminfo:
+	push .msg
+	call serialwrite
+	jmp hang
+.msg db "No memoryinfo!", 10, 0
+mbootnovideoinfo:
+	push .msg
+	call serialwrite
+	jmp hang
+.msg db "No videoryinfo!", 10, 0
+mbootunsupportedfbtype:
+	push .msg
+	call serialwrite
+	jmp hang
+.msg db "Unsupported framebuffer type: only direct RGB is supported!", 10, 0
+mbootunsupportedfbbpp:
+	push .msg
+	call serialwrite
+	jmp hang
+.msg db "Unsupported bitdepth: only 24 and 32 bpp supported!", 10, 0
+
+
+mbootinfo:
+	.flags dd 0
+	.mem_lower dd 0
+	.mem_upper dd 0
+	.fb_addr dd 0
+	.fb_pitch dd 0
+	.fb_width dd 0
+	.fb_height dd 0
+	.fb_bpp db 0
+	.fb_type db 0
+	.fb_rpos db 0
+	.fb_rmasksize db 0
+	.fb_gpos db 0
+	.fb_gmasksize db 0
+	.fb_bpos db 0
+	.fb_bmasksize db 0
diff --git a/src/start32.asm b/src/start32.asm
index fc19dc0..9eb28a9 100644
--- a/src/start32.asm
+++ b/src/start32.asm
@@ -5,7 +5,7 @@ org 0x100000
 MULTIBOOT_HEADER_MAGIC      equ 0x1BADB002
 MULTIBOOT_PAGE_ALIGN        equ (1 shl 0)
 MULTIBOOT_MEMORY_INFO       equ (1 shl 1)
-MULTIBOOT_VIDEO_REQUEST     equ (0 shl 2)
+MULTIBOOT_VIDEO_REQUEST     equ (1 shl 2)
 MULTIBOOT_AOUT_KLUDGE       equ (1 shl 16)
 MULTIBOOT_HEADER_FLAGS      equ MULTIBOOT_PAGE_ALIGN or MULTIBOOT_MEMORY_INFO or MULTIBOOT_VIDEO_REQUEST
 MULTIBOOT_HEADER_FLAGS      equ MULTIBOOT_PAGE_ALIGN or MULTIBOOT_MEMORY_INFO or MULTIBOOT_VIDEO_REQUEST or MULTIBOOT_AOUT_KLUDGE
@@ -27,68 +27,98 @@ multiboot:
 
 start:
 	; Setup stack
-	mov ebp, stack_bottom
+	mov ebp, stack_top
 	mov esp, stack_top
 
 	push ebx
 	push eax
 
-	cmp eax, 0x2badb002
-	jne multibootnomagic
-
-	mov byte [0xb8000], '!'
-
-	push stuff.bootmsg
-	call printbootmsg
 	call serialinit
+	push stuff.bootmsg
 	call serialwrite
 	add esp, 4
 
+	call mbootgetinfo
+	add esp, 2*4
+
+	mov eax, [mbootinfo.fb_addr]
+	mov dword [eax], 0xffffffff
+
+
+	push stuff.fbaddrmsgpfx
+	call serialwrite
+	add esp, 4
+
+	sub esp, 36	;Reserve stack for return
+	push dword esp	;Destination address
+	push dword 16	;Base
+	push dword [mbootinfo.fb_addr]	;source
+	call __uitoa
+	add esp, 3*4
+	push esp
+	call serialwrite
+	add esp, 4
+
+	push stuff.fbdimensionsmsgpfx
+	call serialwrite
+	add esp, 4
+	push dword esp	;destination address
+	push dword 10	;base
+	push dword [mbootinfo.fb_width]
+	call __uitoa
+	add esp, 3*4
+	push esp
+	call serialwrite
+	add esp, 4
+	push stuff.x
+	call serialwrite
+	add esp, 4
+
+	push dword esp	;destination address
+	push dword 10	;base
+	push dword [mbootinfo.fb_height]
+	call __uitoa
+	add esp, 3*4
+	push esp
+	call serialwrite
+	add esp, 4
+	push stuff.x
+	call serialwrite
+
+	add esp, 4
+	push dword esp	;destination address
+	push dword 10	;base
+	xor eax, eax
+	mov al, [mbootinfo.fb_bpp]
+	push dword eax
+	call __uitoa
+	add esp, 3*4
+	push esp
+	call serialwrite
+	add esp, 4
+
+	add esp, 36	;Clean reserved uitoa return string from stack
+
 	jmp hang
 
 hang:
+	push .msg
+	call serialwrite
 	cli
+.loop:
 	hlt
-	jmp hang
-
-multibootnomagic:
-	mov esi, .msg
-	mov edi, 0xb8000
-	mov ah, 64
-	cld
-.loop:
-	lodsb
-	or al, al
-	jz .done
-	stosw
 	jmp .loop
-.done:
-	jmp hang
-.msg db "No multiboot magic", 0
-
-printbootmsg:
-	push ebp
-	mov ebp, esp
-	pushad
-	mov esi, [ebp+8]
-	mov edi, 0xb8000
-	cld
-.loop:
-	lodsb
-	or al, al
-	jz .done
-	stosb
-	inc edi
-	jmp .loop
-.done:
-	popad
-	pop ebp
-	ret
+.msg db 10, "Halting...", 10, 0
 
 include "src/serial.asm"
+include "src/mbootinfo.asm"
+include "src/itoa.asm"
 
 stuff:
-	.bootmsg db "=== KoalemOS ===", 10, 0
+	.bootmsg db 10, "=== KoalemOS ===", 10, 0
+	.fbaddrmsgpfx db 10, "Framebuffer address: 0x", 0
+	.fbdimensionsmsgpfx db 10, "Framebuffer dimensions: ", 0
+	.x db "x", 0
 
 
 stack_bottom: