diff options
-rw-r--r-- | .gitignore | 1 | ||||
-rw-r--r-- | Makefile.toml | 10 | ||||
-rw-r--r-- | boot.asm | 240 |
3 files changed, 251 insertions, 0 deletions
@@ -1 +1,2 @@ /target +boot.bin diff --git a/Makefile.toml b/Makefile.toml new file mode 100644 index 0000000..64819c2 --- /dev/null +++ b/Makefile.toml @@ -0,0 +1,10 @@ +[tasks.boot] +command = "nasm" +args = ["-f", "bin", "-o", "boot.bin", "boot.asm"] + +[tasks.build] +dependencies = ["boot"] + +[tasks.clean] +command = "rm" +args = ["-f", "boot.bin"] diff --git a/boot.asm b/boot.asm new file mode 100644 index 0000000..d3653f0 --- /dev/null +++ b/boot.asm @@ -0,0 +1,240 @@ +; Minimal Linux Bootloader +; ======================== + +; @ author: Sebastian Plotz +; @ version: 1.0 +; @ date: 24.07.2012 + +; Copyright (C) 2012 Sebastian Plotz + +; Minimal Linux Bootloader is free software: you can redistribute it and/or modify +; it under the terms of the GNU General Public License as published by +; the Free Software Foundation, either version 3 of the License, or +; (at your option) any later version. + +; Minimal Linux Bootloader is distributed in the hope that it will be useful, +; but WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +; GNU General Public License for more details. + +; You should have received a copy of the GNU General Public License +; along with Minimal Linux Bootloader. If not, see <http://www.gnu.org/licenses/>. + +; Memory layout +; ============= + +; 0x07c00 - 0x07dff Mininal Linux Bootloader +; + partition table +; + MBR signature +; 0x10000 - 0x17fff Real mode kernel +; 0x18000 - 0x1dfff Stack and heap +; 0x1e000 - 0x1ffff Kernel command line +; 0x20000 - 0x2fdff temporal space for +; protected-mode kernel + +; base_ptr = 0x10000 +; heap_end = 0xe000 +; heap_end_ptr = heap_end - 0x200 = 0xde00 +; cmd_line_ptr = base_ptr + heap_end = 0x1e000 + +org 0x7c00 + + cli + xor ax, ax + mov ds, ax + mov ss, ax + mov sp, 0x7c00 ; setup stack ... + mov ax, 0x1000 + mov es, ax + sti + +read_cmdline: + + mov eax, 0x0001 ; load one sector + xor bx, bx ; no offset + mov cx, 0x1e00 ; load Kernel command line at 0x1e000 + mov esi, cmd_lba + call read_from_hdd + +read_kernel_bootsector: + + mov eax, 0x0001 ; load one sector + xor bx, bx ; no offset + mov cx, 0x1000 ; load Kernel boot sector at 0x10000 + mov esi, current_lba + call read_from_hdd + +read_kernel_setup: + + xor eax, eax + mov al, [es:0x1f1] ; no. of sectors to load + cmp ax, 0 ; 4 if setup_sects = 0 + jne read_kernel_setup.next + mov ax, 4 +.next: + mov bx, 512 ; 512 byte offset + mov cx, 0x1000 + mov esi, current_lba + call read_from_hdd + +check_version: + + cmp word [es:0x206], 0x204 ; we need protocol version >= 2.04 + jb error + test byte [es:0x211], 1 + jz error + +set_header_fields: + + mov byte [es:0x210], 0xe1 ; set type_of_loader + or byte [es:0x211], 0x80 ; set CAN_USE_HEAP + mov word [es:0x224], 0xde00 ; set heap_end_ptr + ;mov byte [es:0x226], 0x00 ; set ext_loader_ver + mov byte [es:0x227], 0x01 ; set ext_loader_type (bootloader id: 0x11) + mov dword [es:0x228], 0x1e000 ; set cmd_line_ptr + cld ; copy cmd_line + +read_protected_mode_kernel: + + mov edx, [es:0x1f4] ; edx stores the number of bytes to load + shl edx, 4 +.loop: + cmp edx, 0 + je run_kernel + cmp edx, 0xfe00 ; less than 127*512 bytes remaining? + jb read_protected_mode_kernel_2 + mov eax, 0x7f ; load 127 sectors (maximum) + xor bx, bx ; no offset + mov cx, 0x2000 ; load temporary to 0x20000 + mov esi, current_lba + call read_from_hdd + mov cx, 0x7f00 ; move 65024 bytes (127*512 byte) + call do_move + sub edx, 0xfe00 ; update the number of bytes to load + add word [gdt.dest], 0xfe00 + adc byte [gdt.dest+2], 0 + jmp short read_protected_mode_kernel.loop + +read_protected_mode_kernel_2: + + mov eax, edx + shr eax, 9 + test edx, 511 + jz read_protected_mode_kernel_2.next + inc eax +.next: + xor bx, bx + mov cx, 0x2000 + mov esi, current_lba + call read_from_hdd + mov ecx, edx + shr ecx, 1 + call do_move + +run_kernel: + + cli + mov ax, 0x1000 + mov ds, ax + mov es, ax + mov fs, ax + mov gs, ax + mov ss, ax + mov sp, 0xe000 + jmp 0x1020:0 + + ;; read_from_hdd: + ;; ax: count in 512-byte sectors [1, 127] + ;; bx: destination: offset + ;; cx: destination: segment + ;; esi: lba pointer (typically current_lba) +read_from_hdd: + + push edx + mov [dap.count], ax + mov [dap.offset], bx + mov [dap.segment], cx + mov edx, [esi] + mov [dap.lba], edx + add [esi], eax ; update current_lba + mov ah, 0x42 + mov si, dap + mov dl, 0x80 ; first hard disk + int 0x13 + jc error + pop edx + ret + +do_move: + + push edx + push es + xor ax, ax + mov es, ax + mov ah, 0x87 + mov si, gdt + int 0x15 + jc error + pop es + pop edx + ret + +error: + + mov si, error_msg + +msg_loop: + + lodsb + and al, al + jz reboot + mov ah, 0xe + mov bx, 7 + int 0x10 + jmp short msg_loop + +reboot: + + xor ax, ax + int 0x16 + int 0x19 + jmp 0xf000:0xfff0 ; BIOS reset code + +; Global Descriptor Table + +gdt: + + times 16 db 0 + dw 0xffff ; segment limit +.src: + dw 0 + db 2 + db 0x93 ; data access rights + dw 0 + dw 0xffff ; segment limit +.dest: + dw 0 + db 0x10 ; load protected-mode kernel to 100000h + db 0x93 ; data access rights + dw 0 + times 16 db 0 + +; Disk Address Packet + +dap: + + db 0x10 ; size of DAP + db 0 ; unused +.count: + dw 0 ; number of sectors +.offset: + dw 0 ; destination: offset +.segment: + dw 0 ; destination: segment +.lba: + dd 0 ; low bytes of LBA address + dd 0 ; high bytes of LBA address + +error_msg db 'er', 0 ; /* FIXME: newline */ +current_lba dd 8218 ; initialize to first LBA address +cmd_lba dd 8218 ; initialize to LBA address of cmdline.txt |