commit 1934e66796e6abc27f7209f2a8d528d1db0792b6 Author: AfonsoCMSousa Date: Fri Nov 14 22:20:27 2025 +0000 Initial commit: kernel source and build scripts diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..819a294 --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +*.o +*.bin +*.elf +*.map + diff --git a/boot.asm b/boot.asm new file mode 100644 index 0000000..e204bce --- /dev/null +++ b/boot.asm @@ -0,0 +1,77 @@ +; File: boot.asm +global _start +extern kmain + +section .multiboot + ; Multiboot header + dd 0x1BADB002 ; magic number + dd 0x00000003 ; flags + dd -(0x1BADB002 + 0x00000003) ; checksum + + +section .text +[bits 32] +_start: + mov esp, kernel_stack_top + + ; Load the gdt_ptr + lgdt [gdt_ptr] + + mov cr3, pml4_table + + mov rax, cr4 + or rax, 0x20 ; Enable PAE + mov cr4, rax + + mov ecx, 0xC0000080 ; IA32_EFER MSR + rdmsr + or rax, 0x00000100 ; Set LME (Long Mode Enable) bit + wrmsr + + ; Enable long mode + mov rax, cr0 + or rax, 0x80000000 ; Set the Long Mode Enable (LME) bit + mov cr0, rax + + ; Jump to 64-bit code Segment + jmp 0x08:long_mode_start + +section .bss +; We define the stack size and labels in the uninitialized data section (.bss) +kernel_stack_bottom: + ; Reserve 16 KB for the stack + resb 16 * 1024 +kernel_stack_top: + +gdt_ptr: + dw 0 ; Limit (set by linker/code later) + dq 0 ; Base Address (set by linker/code later) +gdt_start: ; Start of the actual GDT entries + ; Entry 0: Null Descriptor + dq 0x0000000000000000 + ; Entry 1: 64-bit Code Segment Descriptor + ; Entry 2: 64-bit Data Segment Descriptor +gdt_end: + +pml4_table: + ; Define a simple PML4 table here (identity mapping for simplicity) + ; In a real kernel, you would set up proper paging structures + resb 4096 ; Reserve 4 KB for the PML4 table +pml4_end: + +section .text +[bits 64] ; Tell NASM to assemble in 64-bit mode + +long_mode_start: + ; 1. Pass GRUB's Multiboot info (in ebx) as the first C argument (in rdi) + ; We must use the 64-bit register RDI, but the data is in the 32-bit EBX. + ; Moving ebx to rdi automatically clears the upper 32 bits of rdi. + mov rdi, rbx + + ; 2. Call the C kernel's main function + call kmain + + ; 3. If kmain ever returns, halt the CPU + hlt + + diff --git a/build.sh b/build.sh new file mode 100755 index 0000000..e6b90e2 --- /dev/null +++ b/build.sh @@ -0,0 +1,8 @@ +echo ">>> Compiling bootloader" +nasm boot.asm -o boot.o -f elf64 + +echo ">>> Compiling kernel" +gcc kernel.c -o kernel.o -c -m64 -ffreestanding -nostdlib + +echo ">>> Linking kernel" +ld -T linker.ld -o SoraOS boot.o kernel.o diff --git a/kernel.c b/kernel.c new file mode 100644 index 0000000..b248273 --- /dev/null +++ b/kernel.c @@ -0,0 +1,15 @@ +// file: kerlnel.c + +void kmain(void) { + // Kernel main function + // Set VGA memory address + unsigned short *VGA_mem = (unsigned short *)0xB8000; + + VGA_mem[0] = (0x07 << 8) | 'S'; + VGA_mem[1] = (0x07 << 8) | 'O'; + VGA_mem[2] = (0x07 << 8) | 'R'; + VGA_mem[3] = (0x07 << 8) | 'A'; + VGA_mem[4] = (0x07 << 8) | ' '; + VGA_mem[5] = (0x07 << 8) | 'O'; + VGA_mem[6] = (0x07 << 8) | 'S'; +} diff --git a/kernel.o b/kernel.o new file mode 100644 index 0000000..ddcc3d6 Binary files /dev/null and b/kernel.o differ diff --git a/linker.ld b/linker.ld new file mode 100644 index 0000000..28e2a91 --- /dev/null +++ b/linker.ld @@ -0,0 +1,31 @@ +ENTRY(_start); +FORMAT(elf64-x86-64); + +SECTIONS +{ +/* Set the location counter to 0x100000 (1MB) */ +. = 0x100000; + +/* Define the .text section at the current location */ +.text : +{ + /* Put all .text sections from all input files here */ + *(.text) +} + +/* Define the .data section immediately after .text */ +.data : +{ + /* Put all .data sections from all input files here */ + *(.data) +} + +/* Define the .bss section immediately after .data */ +.bss : +{ + /* Put all .bss sections from all input files here */ + *(.bss) +} + +/* End of the linker script */ +}