diff options
Diffstat (limited to 'x86-bare-metal/mbr-disk-lba/mbr.S')
-rw-r--r-- | x86-bare-metal/mbr-disk-lba/mbr.S | 125 |
1 files changed, 125 insertions, 0 deletions
diff --git a/x86-bare-metal/mbr-disk-lba/mbr.S b/x86-bare-metal/mbr-disk-lba/mbr.S new file mode 100644 index 0000000..df2cef1 --- /dev/null +++ b/x86-bare-metal/mbr-disk-lba/mbr.S @@ -0,0 +1,125 @@ +// -- BOOT TEXT SECTION --------------------------------------------------------- + +.code16 +.intel_syntax noprefix + +.section .boot, "ax", @progbits + // Disable interrupts. + cli + + // Clear segment selectors. + xor ax, ax + mov ds, ax + mov es, ax + mov ss, ax + mov fs, ax + mov gs, ax + + // Set cs to 0x0000, as some BIOSes load the MBR to either 07c0:0000 or 0000:7c000. + jmp 0x0000:entry_rm16 + +// LBA - disk address packet. +lba_pkt: + .byte 0x10 // Size of this disk packet in bytes (16). + .byte 0 // Reserved. + .2byte 2 // Number of blocks to read (sectors 512 bytes?) to read. + .4byte 0x7e00 // Destination address. + .8byte 1 // Starting lba block number (0 indexed, MBR is at 0). + +entry_rm16: + // Disk extended read. + // ah = 42h + // dl = drive number + // ds:si = address of disk packet + // Return + // cf = 0 (success) 1 (failed) + // ah = 0 (success) error code (failed) + + // [1] http://www.ctyme.com/intr/rb-0708.htm + mov ah, 0x42 + //mov dl, #drive // bios puts boot disk into dl + lea si, [lba_pkt] + int 0x13 + + jnc 2f +1: + hlt + jmp 1b +2: + // Get current video mode [1]. + // Return: + // ah number of columns + // al display mode (see table in [2]) + // + // [1] http://www.ctyme.com/intr/rb-0108.htm + // [2] http://www.ctyme.com/intr/rb-0069.htm + mov ah, 0xf + int 0x10 + + // Execpt that the bios initializes text mode 0x3. + // * 80x25 text mode (cols x rows) + // * 2 byte per character + // [15] blink [14:12] bg color [11:8] fg color [7:0] char + // * 0xB80000 screen address + cmp al, 0x3 + // Else we indicate an error with a blue screen. + je 2f + // Set background color [1]. + // + // [1] http://www.ctyme.com/intr/rb-0101.htm + mov ah, 0xb + mov bx, 1 + int 0x10 +1: + hlt + jmp 1b +2: + + // Enable A20 address line. + in al, 0x92 + or al, 2 + out 0x92, al + + // Load GDT descriptor. + lgdt [gdt_desc] + + // Enable protected mode (set CR0.PE bit). + mov eax, cr0 + or eax, (1 << 0) + mov cr0, eax + + // Far jump which loads segment selector (0x0008) into cs. + // 0x0008 -> RPL=0, TI=0(GDT), I=1 + jmp 0x0008:entry_pm32 + +.code32 +entry_pm32: + // Select data segment selector (0x0010) for ds. + mov ax, gdt_data - gdt + mov ds, ax + + // Initialize stack pointer. + // Real Mode memory (https://wiki.osdev.org/Memory_Map_(x86) + // 0x00000500 - 0x00007BFF | 29.75 KiB | conventional memory + mov esp, 0x7c00 + + // Enter zmbr.zig:kmain. + // Should not return, but for safety we emit a call rather than a jmp. + call kmain + +1: + hlt + jmp 1b + +// -- RODATA SECTION ------------------------------------------------------------ + +.section .rodata, "a", @progbits +.balign 8 +gdt: + .8byte 0x0000000000000000 // 0x00 | null descriptor + .8byte 0x00cf9a000000ffff // 0x08 | 32 bit, code (rx), present, dpl=0, g=4K, base=0, limit=fffff +gdt_data: + .8byte 0x00cf92000000ffff // 0x10 | 32 bit, data (rw), present, dpl=0, g=4K, base=0, limit=fffff +gdt_desc: + .2byte (. - gdt - 1) // size + .4byte gdt // address |