diff --git a/README.md b/README.md index 43ca733..6be777d 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ - `make` - `i386-elf-gcc` - `i386-elf-ld` -- `i386-elf-as` +- `nasm` ### Creating a disk image diff --git a/makefile b/makefile index f2d10ed..b2e0c4b 100644 --- a/makefile +++ b/makefile @@ -1,16 +1,14 @@ CC = i386-elf-gcc -AS = i386-elf-as LD = i386-elf-ld CFLAGS = -m32 -ffreestanding -fno-builtin -Wall -Wextra -Wshadow -std=c23 LDFLAGS = -ASFLAGS = SRC_C := src/kernel.c src/string.c src/vga.c -SRC_ASM := src/boot.s +SRC_ASM := src/boot.asm OBJ_C := $(SRC_C:src/%.c=.build/%.o) -OBJ_ASM := $(SRC_ASM:src/%.s=.build/%.o) +OBJ_ASM := $(SRC_ASM:src/%.asm=.build/%.o) OBJS := $(OBJ_C) $(OBJ_ASM) kernel: .build/kernel @@ -37,5 +35,5 @@ build-dir: .build/%.o: src/%.c | build-dir $(CC) $(CFLAGS) -c -o $@ $< -.build/%.o: src/%.s | build-dir - $(AS) $(ASFLAGS) -o $@ $< \ No newline at end of file +.build/%.o: src/%.asm | build-dir + nasm -f elf32 -o $@ $< \ No newline at end of file diff --git a/src/boot.asm b/src/boot.asm new file mode 100644 index 0000000..17f9984 --- /dev/null +++ b/src/boot.asm @@ -0,0 +1,106 @@ +global _start +extern kernel_main + +%define FLAGS 0b10 +%define MAGIC 0x1BADB002 +%define CHECKSUM -(MAGIC + FLAGS) + +section .multiboot + align 4 + dd MAGIC + dd FLAGS + dd CHECKSUM + +section .bss + align 4096 + pml4_table: + resb 4096 + pdpt_table: + resb 4096 + pd_table: + resb 4096 + +section .bss + align 16 + stack_bottom: + resb 16384 + stack_top: + +section .data + align 8 + gdt64: + dq 0x0000000000000000 + .code: + dq 0x00AF9A000000FFFF + .descriptor: + dw .end - gdt64 - 1 + dq gdt64 + .end: + +section .text + bits 32 + _start: + mov esp, stack_top + + ; Multiboot will place a magic value in eax + ; If this magic value is not present, then we might not have multiboot info in ebx, + ; therefore we throw an error + cmp eax, 0x2BADB002 + jne error + + ; Check if cpuid is available by flipping the 22-nth youngest bit + ; in the eflags register and checking if the cpu flipped it back + pushfd + pop eax + mov ecx, eax + xor eax, 1 << 21 + push eax + popfd + pushfd + pop eax + ; If cpuid is available, eax should be different than ecx + xor eax, ecx + jz error + ; Finally restore eflags register to the original value + push ecx + popfd + + ; Check if extended cpuid is available by calling cpuid with 0x80000000, + ; If cpuid is available, eax will be greater than 0x80000000 after the call + mov eax, 0x80000000 + cpuid + cmp eax, 0x80000001 + jb error + + ; Check if long mode is available by calling cpuid with 0x80000001 + ; this will place the extended features of the cpu in edx + ; The 30-nth youngest bit tells us if long mode is supported or not + mov eax, 0x80000001 + cpuid + test edx, 1 << 29 + jz error + + ; todo(nub31): setup paging + ; todo(nub31): enter long mode + + ; Load global descriptor table which is set up for 64 bit + lgdt [gdt64.descriptor] + + call kernel_main + jmp error + + error: + cli + mov byte [0xb8000], 'B' + mov byte [0xb8002], 'O' + mov byte [0xb8004], 'O' + mov byte [0xb8006], 'T' + mov byte [0xb8008], ' ' + mov byte [0xb800a], 'E' + mov byte [0xb800c], 'R' + mov byte [0xb800e], 'R' + mov byte [0xb8010], 'O' + mov byte [0xb8012], 'R' + hang: + hlt + jmp hang diff --git a/src/boot.s b/src/boot.s deleted file mode 100644 index fc096f4..0000000 --- a/src/boot.s +++ /dev/null @@ -1,108 +0,0 @@ -.intel_syntax noprefix - -.set ALIGN, 1<<0 -.set MEMINFO, 1<<1 -.set FLAGS, ALIGN | MEMINFO -.set MAGIC, 0x1BADB002 -.set CHECKSUM, -(MAGIC + FLAGS) - -.section .multiboot -.align 4 -.long MAGIC -.long FLAGS -.long CHECKSUM - -.section .bss -.align 4096 -pml4_table: - .zero 4096 -pdpt_table: - .zero 4096 -pd_table: - .zero 4096 - -.section .bss -.align 16 -stack_bottom: - .skip 16384 -stack_top: - -.section .data -.align 8 -gdt64: - .quad 0x0000000000000000 -gdt64_code: - .quad 0x00AF9A000000FFFF -gdt64_descriptor: - .word gdt64_end - gdt64 - 1 - .long gdt64 -gdt64_end: - -.section .text -.code32 -.global _start -_start: - mov esp, stack_top - - // Multiboot will place a magic value in eax - // If this magic value is not present, then we might not have multiboot info in ebx, - // therefore we throw an error - cmp eax, 0x2BADB002 - jne error - - // Check if cpuid is available by flipping the 22-nth youngest bit - // in the eflags register and checking if the cpu flipped it back - pushfd - pop eax - mov ecx, eax - xor eax, 1 << 21 - push eax - popfd - pushfd - pop eax - // If cpuid is available, eax should be different than ecx - xor eax, ecx - jz error - // Finally restore eflags register to the original value - push ecx - popfd - - // Check if extended cpuid is available by calling cpuid with 0x80000000, - // If cpuid is available, eax will be greater than 0x80000000 after the call - mov eax, 0x80000000 - cpuid - cmp eax, 0x80000001 - jb error - - // Check if long mode is available by calling cpuid with 0x80000001 - // this will place the extended features of the cpu in edx - // The 30-nth youngest bit tells us if long mode is supported or not - mov eax, 0x80000001 - cpuid - test edx, 1 << 29 - jz error - - // todo(nub31): setup paging - // todo(nub31): enter long mode - - // Load global descriptor table which is set up for 64 bit - lgdt [gdt64_descriptor] - - call kernel_main - jmp error - -error: - cli - mov byte ptr [0xb8000], 'B' - mov byte ptr [0xb8002], 'O' - mov byte ptr [0xb8004], 'O' - mov byte ptr [0xb8006], 'T' - mov byte ptr [0xb8008], ' ' - mov byte ptr [0xb800a], 'E' - mov byte ptr [0xb800c], 'R' - mov byte ptr [0xb800e], 'R' - mov byte ptr [0xb8010], 'O' - mov byte ptr [0xb8012], 'R' -hang: - hlt - jmp hang