diff --git a/README.md b/README.md new file mode 100644 index 0000000..74acca9 --- /dev/null +++ b/README.md @@ -0,0 +1,21 @@ +# bootler + +hobby bootloader written in asm. It's just for playing around... for now :p + +### memory map + ++------ 0x00100000 ------+ +| hardware, bios stuff | ++------ 0x00080000 ------+ +| pm stack (esp) | from boot.asm ++------ 0x00010200 ------+ +| kernel (kernel.asm) | ++------ 0x00010000 ------+ +| free | ++------ 0x00007E00 ------+ +| bootloader (boot.asm) | ++------ 0x00007C00 ------+ +| real mode stack (sp) | from boot.asm ++------ 0x00000500 ------+ +| bios stuff | ++------ 0x00000000 ------+ diff --git a/boot.asm b/boot.asm index b5c50cb..bb852ef 100644 --- a/boot.asm +++ b/boot.asm @@ -1,28 +1,158 @@ -; yoinked from osdev.org -mov ax, 0x07C0 +; bootler +; legacy bootloader in nasm-flavoured asm +; 2026 Andromeda +; GPL licensed + +[bits 16] +[org 0x7C00] ; address where bootloader is loaded + +xor ax, ax mov ds, ax +mov es, ax +mov ss, ax +mov sp, 0x7C00 -mov si, msg -cld +mov ah, 0x0E +mov al, 'R' +int 0x10 +mov al, 'e' +int 0x10 +mov al, 'a' +int 0x10 +mov al, 'l' +int 0x10 +mov al, 0x0D +int 0x10 +mov al, 0x0A +int 0x10 +mov al, 0x00 ; stops serial and bios output from overlapping in qemu -nographic +int 0x10 ; output -ch_loop: - lodsb - ; hang if at null terminator - or al, al - jz hang +; activate a20 +mov ax, 0x2401 +int 0x15 +jc error - ; BIOS interrupt prints al - mov ah, 0x0E - mov bh, 0 +; load kernel +; 'docs' from https://www.ctyme.com/intr/rb-0607.htm +mov ah, 0x02 +mov al, 1 ; number of sectors to read (must be nonzero) +mov ch, 0 ; low eight bits of cylinder number +mov cl, 2 ; sector number 1-63 (bits 0-5); high two bits of cylinder (bits 6-7, + ; hard disk only) +mov dh, 0 ; head number +; dl is already set by bios +mov bx, 0x1000 ; data buffer +mov es, bx +xor bx, bx +int 0x13 ; read disk +jc error + +; load gdt +lgdt [gdt_descriptor] + +; jump to pm +cli +mov eax, cr0 +or eax, 1 +mov cr0, eax +jmp 0x08:pm_start + +error: + mov al, 'e' int 0x10 + mov al, 'r' + int 0x10 + mov al, 'r' + int 0x10 + mov al, 'o' + int 0x10 + mov al, 'r' + int 0x10 + jmp $ - jmp ch_loop +gdt_data: + ; null segment + dq 0x0000000000000000 + ; code segment + dw 0xFFFF + dw 0x0000 -hang: - jmp hang + db 0x00 + db 10011010b ; 32-bit code segment, present, ring 0 + db 11001111b ; limit bits 16-19 + db 0x00 -msg db 'Hello World', 0 + ; data segment + dw 0xFFFF + dw 0x0000 + db 0x00 + db 10010010b ; 32-bit data segment, present, ring 0 + db 11001111b ; limit bits 16-19 + db 0x00 + +gdt_descriptor: + dw $ - gdt_data - 1 ; size + dd gdt_data ; start + +[bits 32] + +; entry point +pm_start: + ; data segment registers + mov ax, 0x10 + mov ds, ax + mov es, ax + mov fs, ax + mov gs, ax + mov ss, ax + mov esp, 0x80000 + + ; TODO actually configure COM1 + mov dx, 0x3F8 ; COM1 + mov al, 'P' + out dx, al + mov al, 'r' + out dx, al + mov al, 'o' + out dx, al + mov al, 't' + out dx, al + mov al, 'e' + out dx, al + mov al, 'c' + out dx, al + mov al, 't' + out dx, al + mov al, 'e' + out dx, al + mov al, 'd' + out dx, al + mov al, 0x0D + out dx, al + mov al, 0x0A + out dx, al + + jmp 0x08:0x10000 + +pm_error: + mov al, 'p' + out dx, al + mov al, 'm' + out dx, al + mov al, 'e' + out dx, al + mov al, 'r' + out dx, al + mov al, 'r' + out dx, al + mov al, 'o' + out dx, al + mov al, 'r' + out dx, al + jmp $ + times 510-($-$$) db 0 ; 2 bytes less now db 0x55 db 0xAA diff --git a/kernel.asm b/kernel.asm new file mode 100644 index 0000000..23c0d5d --- /dev/null +++ b/kernel.asm @@ -0,0 +1,23 @@ +[bits 32] + +mov al, 'K' +out dx, al +mov al, 'e' +out dx, al +mov al, 'r' +out dx, al +mov al, 'n' +out dx, al +mov al, 'e' +out dx, al +mov al, 'l' +out dx, al +mov al, 0x0D +out dx, al +mov al, 0x0A +out dx, al +mov al, 0x00 +out dx, al +jmp $ + +times 512-($-$$) db 0 diff --git a/package.nix b/package.nix index 150b46b..1cef31a 100644 --- a/package.nix +++ b/package.nix @@ -11,7 +11,12 @@ in version = "0.1.0"; src = ./.; buildPhase = '' - ${nasm}/bin/nasm boot.asm -o ${bootImg} + ${nasm}/bin/nasm boot.asm -o boot.bin + ${nasm}/bin/nasm kernel.asm -o kernel.bin + + dd if=/dev/zero of=${bootImg} bs=512 count=2 + dd if=boot.bin of=${bootImg} conv=notrunc + dd if=kernel.bin of=${bootImg} bs=512 seek=1 conv=notrunc ''; installPhase = '' mkdir -p $out/bin @@ -26,13 +31,10 @@ in cp $(echo $out)/bin/${bootImg} ./.bootler/${bootImg} chmod a+w ./.bootler/${bootImg} - echo "press any key to continue. Qemu will clear the screen..." - read -s -n 1 - # run image ${qemu}/bin/qemu-system-x86_64 \ -nographic \ - -hda ./.bootler/${bootImg} + -drive file=./.bootler/${bootImg},format=raw,index=0,media=disk # clean up rm ./.bootler -r