Created
January 20, 2023 10:52
-
-
Save NSG650/1db6230997956bffbb03ade9377135f1 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| ; this bootloader only loads and runs the kernel | |
| ; this does not load an initrd so the kernel will kernel panic stating it failed to mount the rootfs | |
| ; build instructions | |
| ; nasm -f bin slkboot.asm | |
| ; running instructions | |
| ; cat slkboot kernel_file > fun | |
| ; qemu-system-x86_64 -hda fun | |
| [BITS 16] | |
| ORG 0x7c00 | |
| jmp start | |
| nop | |
| ; Fast A20 Enable | |
| a20_enable: | |
| in al, 0x92 | |
| or al, 0x0e | |
| out 0x92, al | |
| ret | |
| highaddr dd 0x100000 | |
| high_move: | |
| mov esi, 0x20000 | |
| mov edi, [highaddr] | |
| shl eax, 9 | |
| .loop: | |
| mov edx, [ds:esi] | |
| mov [ds:edi], edx | |
| add edi, 4 | |
| add esi, 4 | |
| sub eax, 4 | |
| jnz high_move.loop | |
| mov [highaddr], edi | |
| ret | |
| ; eax is the sector that need to be loaded in high addr | |
| high_load: | |
| shr eax, 9 | |
| inc eax | |
| mov ecx, 0x7f | |
| xor edx, edx | |
| div ecx | |
| push dx | |
| .loop: | |
| push ax | |
| mov ax, 0x7f | |
| mov bx, 0x2000 | |
| xor dx, dx | |
| call disk_read | |
| call high_move | |
| pop ax | |
| dec ax | |
| jnz high_load.loop | |
| pop ax | |
| test ax, ax | |
| jz high_load.done | |
| mov bx, 0x2000 | |
| xor dx, dx | |
| call disk_read | |
| call high_move | |
| .done: | |
| ret | |
| ; extended disk read | |
| disk_read: | |
| push ax | |
| mov word [dap.count], ax | |
| mov word [dap.offset], dx | |
| mov word [dap.segment], bx | |
| mov ah, 0x42 | |
| mov dl, [bootdrive] | |
| lea si, [dap] | |
| int 0x13 | |
| ; add newly read sectors | |
| mov edx, [dap.lba] | |
| movzx eax, word [dap.count] | |
| add edx, eax | |
| mov [dap.lba], edx | |
| pop ax | |
| ret | |
| unreal_mode: | |
| .protected_mode: | |
| lgdt [gdt_desc] | |
| mov eax, cr0 | |
| or al, 1 | |
| mov cr0, eax | |
| mov bx, 0x8 | |
| mov ds, bx | |
| mov es, bx | |
| .enter_unreal: | |
| mov eax, cr0 | |
| and al, 0xFE | |
| mov cr0, eax | |
| xor ax, ax ; new limits were cached, restore segment values | |
| mov ds, ax | |
| mov es, ax | |
| ret | |
| start: | |
| mov [bootdrive], dl | |
| cli | |
| cld | |
| xor ax, ax | |
| mov ds, ax | |
| mov ss, ax | |
| mov sp, 0xe000 | |
| mov es, ax | |
| ; This segment helps us jump in unreal mode | |
| ; This is so we can still be in real mode but have 32 bit addressing | |
| ; Useful for loading the kernel at a high address | |
| call a20_enable | |
| call unreal_mode | |
| ; Command line parameters to pass to the kernel | |
| lea si, [cmdline] | |
| mov cx, cmdline_size | |
| mov di, 0xff00 | |
| rep movsb ; we are literally doing a memcpy((char *)0xff00, cmdline, cmdline_size); here | |
| ; we are loading the kernel at 0x7e00 | |
| mov bx, 0x7e0 | |
| mov es, bx | |
| xor dx, dx | |
| mov ax, 1 | |
| call disk_read | |
| mov al, [es:0x1f1] ; setup_sects | |
| mov dx, 0x200 ; load in memory after 1 sectors | |
| call disk_read | |
| mov bx, [es:0x20e] | |
| cmp bx, 0 | |
| jz load_params | |
| load_params: | |
| ; The real mode kernel header | |
| ; Fill out the only ones needed | |
| mov byte [es:0x210], 0xff ; type_of_loader | |
| mov byte [es:0x211], 0x80 ; loadflags - CAN_USE_HEAP | |
| mov word [es:0x224], 0xde00 ; heap_end_ptr | |
| mov dword [es:0x228], 0xff00 ; cmd_line_ptr | |
| mov eax, [es:0x1f4] ; syssize | |
| shl eax, 4 | |
| call high_load | |
| ; **** RUNNING THE KERNEL | |
| ; The kernel is started by jumping to the kernel entry point, which is | |
| ; located at *segment* offset 0x20 from the start of the real mode | |
| ; kernel. This means that if you loaded your real-mode kernel code at | |
| ; 0x90000, the kernel entry point is 9020:0000. | |
| ; from Documentation/x86/boot.txt | |
| ; as we have loaded the kernel at 0x7e00 we have to jump to 0x8000 | |
| mov sp, 0xe000 | |
| mov ax, 0x7e0 | |
| mov es, ax | |
| mov ds, ax | |
| mov fs, ax | |
| mov gs, ax | |
| jmp 0x800:0 | |
| hlt | |
| dap: | |
| db 0x10 ; dap size | |
| db 0 ; reserved | |
| .count: | |
| dw 0 | |
| .offset: | |
| dw 0 | |
| .segment: | |
| dw 0 | |
| .lba: | |
| dd 1 ; LBA low bits | |
| dd 0 ; LBA high bits | |
| cmdline db "auto", 0x0 | |
| cmdline_size equ $-cmdline | |
| bootdrive db 0x0 | |
| ; Unreal mode GDT | |
| gdt_desc: | |
| dw gdt_end - gdt | |
| dd gdt | |
| gdt: | |
| gdt_null: | |
| dq 0 | |
| gdt_data: | |
| dw 0xFFFF | |
| dw 0 | |
| db 0 | |
| db 10010010b | |
| db 11001111b | |
| db 0 | |
| gdt_end: | |
| times 510-($-$$) db 0 | |
| dw 0xAA55 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment