From db66b8bc3c73f0d621929347cb705778dba2363579013f544be5bb3e17b5b059 Mon Sep 17 00:00:00 2001 From: Armin Friedl Date: Sat, 11 Jan 2025 19:54:50 +0100 Subject: [PATCH] Bootloader --- README.md | 77 +++++++++++++++++++++++++++++++++++++++++++++++-- boot1.asm | 18 ++++++++++++ boot2.asm | 66 ++++++++++++++++++++++++++++++++++++++++++ boot3.asm | 81 ++++++++++++++++++++++++++++++++++++++++++++++++++++ boot4.asm | 85 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ fun.zig | 8 ++++++ linker.ld | 25 ++++++++++++++++ 7 files changed, 357 insertions(+), 3 deletions(-) create mode 100644 boot1.asm create mode 100644 boot2.asm create mode 100644 boot3.asm create mode 100644 boot4.asm create mode 100644 fun.zig create mode 100644 linker.ld diff --git a/README.md b/README.md index d794347..e969305 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,76 @@ # bootloader -A tiny 32-bit x86 operating system kernel - -http://3zanders.co.uk/2017/10/13/writing-a-bootloader/ \ No newline at end of file +A tiny 32-bit x86 operating system kernel + +http://3zanders.co.uk/2017/10/13/writing-a-bootloader/ + +## Real Mode Boot 1 + +16-bit mode. + +Assemble with + +``` shell +nasm -f bin boot1.asm -o boot1.bin +``` + +Run with + +``` shell +qemu-system-x86_64 -fda boot1.bin +``` + +## Protected Mode Boot 2 + +32-bit mode. + +Assemble with + +``` shell +nasm -f bin boot2.asm -o bin2.bin +``` + +Run with + +``` shell +qemu-system-x86_64 -fda boot2.bin +``` + +## Extended Boot 3 + +32-bit, 1024 byte. + +Assemble with + +``` shell +nasm -f bin boot3.asm -o boot3.bin +``` + +Run with + +``` shell +qemu-system-x86_64 -fda boot3.bin +``` + +## Linking with Zig + +32-bit, 1024 byte, building and linking in Zig code. + +Build with + +``` shell +zig build-exe boot4.o fun.zig -T linker.ld -nostdlib -target x86-freestanding +``` + +Convert to raw binary (strip ELF) + +```shell +objcopy -Obinary fun fun.bin +``` + + +Run with + +``` shell +qemu-system-x86_64 -fda fun.bin +``` diff --git a/boot1.asm b/boot1.asm new file mode 100644 index 0000000..485a226 --- /dev/null +++ b/boot1.asm @@ -0,0 +1,18 @@ +bits 16 +org 0x7c00 +boot: + mov si,hello + mov ah,0x0e +.loop: + lodsb + or al,al + jz halt + int 0x10 + jmp .loop +halt: + cli + hlt +hello: db "Hello world!",0 + +times 510 - ($-$$) db 0 +dw 0xaa55 diff --git a/boot2.asm b/boot2.asm new file mode 100644 index 0000000..e08b42b --- /dev/null +++ b/boot2.asm @@ -0,0 +1,66 @@ +bits 16 +org 0x7c00 + +boot: + mov ax, 0x2401 + int 0x15 + mov ax, 0x3 + int 0x10 + cli + lgdt [gdt_pointer] + mov eax, cr0 + or eax,0x1 + mov cr0, eax + jmp CODE_SEG:boot2 + +gdt_start: + dq 0x0 +gdt_code: + dw 0xFFFF + dw 0x0 + db 0x0 + db 10011010b + db 11001111b + db 0x0 +gdt_data: + dw 0xFFFF + dw 0x0 + db 0x0 + db 10010010b + db 11001111b + db 0x0 +gdt_end: + +gdt_pointer: + dw gdt_end - gdt_start + dd gdt_start + +CODE_SEG equ gdt_code - gdt_start +DATA_SEG equ gdt_data - gdt_start + +bits 32 +boot2: + mov ax, DATA_SEG + mov ds, ax + mov es, ax + mov fs, ax + mov gs, ax + mov ss, ax + mov esi,hello + mov ebx,0xb8000 + +.loop: + lodsb + or al,al + jz halt + or eax,0x0100 + mov word [ebx], ax + add ebx,2 + jmp .loop +halt: + cli + hlt +hello: db "Hello world!",0 + +times 510 - ($-$$) db 0 +dw 0xaa55 diff --git a/boot3.asm b/boot3.asm new file mode 100644 index 0000000..9f856c1 --- /dev/null +++ b/boot3.asm @@ -0,0 +1,81 @@ +bits 16 +org 0x7c00 + +boot: + mov ax, 0x2401 + int 0x15 + + mov ax, 0x3 + int 0x10 + + mov [disk],dl + + mov ah, 0x2 ;read sectors + mov al, 1 ;sectors to read + mov ch, 0 ;cylinder idx + mov dh, 0 ;head idx + mov cl, 2 ;sector idx + mov dl, [disk] ;disk idx + mov bx, copy_target;target pointer + int 0x13 + cli + lgdt [gdt_pointer] + mov eax, cr0 + or eax,0x1 + mov cr0, eax + mov ax, DATA_SEG + mov ds, ax + mov es, ax + mov fs, ax + mov gs, ax + mov ss, ax + jmp CODE_SEG:boot2 + +gdt_start: + dq 0x0 +gdt_code: + dw 0xFFFF + dw 0x0 + db 0x0 + db 10011010b + db 11001111b + db 0x0 +gdt_data: + dw 0xFFFF + dw 0x0 + db 0x0 + db 10010010b + db 11001111b + db 0x0 +gdt_end: +gdt_pointer: + dw gdt_end - gdt_start + dd gdt_start +disk: + db 0x0 +CODE_SEG equ gdt_code - gdt_start +DATA_SEG equ gdt_data - gdt_start + +times 510 - ($-$$) db 0 +dw 0xaa55 + +copy_target: +bits 32 + hello: db "Hello more than 512 bytes world!!",0 +boot2: + mov esi,hello + mov ebx,0xb8000 + +.loop: + lodsb + or al,al + jz halt + or eax,0x0100 + mov word [ebx], ax + add ebx,2 + jmp .loop +halt: + cli + hlt + +times 1024 - ($-$$) db 0 diff --git a/boot4.asm b/boot4.asm new file mode 100644 index 0000000..8033462 --- /dev/null +++ b/boot4.asm @@ -0,0 +1,85 @@ +section .boot +bits 16 +global boot +boot: + mov ax, 0x2401 + int 0x15 + + mov ax, 0x3 + int 0x10 + + mov [disk],dl + + mov ah, 0x2 ;read sectors + mov al, 6 ;sectors to read + mov ch, 0 ;cylinder idx + mov dh, 0 ;head idx + mov cl, 2 ;sector idx + mov dl, [disk] ;disk idx + mov bx, copy_target;target pointer + int 0x13 + cli + lgdt [gdt_pointer] + mov eax, cr0 + or eax,0x1 + mov cr0, eax + mov ax, DATA_SEG + mov ds, ax + mov es, ax + mov fs, ax + mov gs, ax + mov ss, ax + jmp CODE_SEG:boot2 +gdt_start: + dq 0x0 +gdt_code: + dw 0xFFFF + dw 0x0 + db 0x0 + db 10011010b + db 11001111b + db 0x0 +gdt_data: + dw 0xFFFF + dw 0x0 + db 0x0 + db 10010010b + db 11001111b + db 0x0 +gdt_end: +gdt_pointer: + dw gdt_end - gdt_start + dd gdt_start +disk: + db 0x0 +CODE_SEG equ gdt_code - gdt_start +DATA_SEG equ gdt_data - gdt_start + +times 510 - ($-$$) db 0 +dw 0xaa55 +copy_target: +bits 32 + hello: db "Hello more than 512 bytes world!!",0 +boot2: + mov esi,hello + mov ebx,0xb8000 +.loop: + lodsb + or al,al + jz halt + or eax,0x0F00 + mov word [ebx], ax + add ebx,2 + jmp .loop +halt: + mov esp,kernel_stack_top + extern kmain + call kmain + cli + hlt + +section .bss +align 4 +kernel_stack_bottom: equ $ + resb 16384 ; 16 KB +kernel_stack_top: diff --git a/fun.zig b/fun.zig new file mode 100644 index 0000000..0c0aa2d --- /dev/null +++ b/fun.zig @@ -0,0 +1,8 @@ +export fn kmain() callconv(.C) void { + const color: c_short = @intCast(0x0F00); + const hello: [*:0]const u8 = "Hello zig world!"; + var vga: [*]c_short = @ptrFromInt(0xb8000); + for (0..16) |i| { + vga[i+80] = color | hello[i]; + } +} diff --git a/linker.ld b/linker.ld new file mode 100644 index 0000000..005f38d --- /dev/null +++ b/linker.ld @@ -0,0 +1,25 @@ +ENTRY(boot) +SECTIONS { + . = 0x7c00; + .text : + { + *(.boot) + *(.text) + } + + .rodata : + { + *(.rodata) + } + + .data : + { + *(.data) + } + + .bss : + { + *(.bss) + } +} +