diff --git a/boot1.s b/boot1.s index 86f9365..0bfba99 100644 --- a/boot1.s +++ b/boot1.s @@ -37,17 +37,17 @@ self_load: ; Panic if the partition / boot1 starting LBA overflows 16 bits. or ebx, ebx - jnz panic + jnz panic_simple ror eax, 16 or ax, ax - jnz panic + jnz panic_simple ror eax, 16 ; Calculate the boot1 end LBA and panic if it overflows 16 bits. ; n.b. ebx is zero before this so both bx and ebx can be used as the boot1 end LBA. mov bx, ax add bx, BOOT1_TOTAL_SECTORS - jc panic + jc panic_simple ; Panic if the boot1 end LBA is after the partition end LBA. ; If the upper 32 bits of the partition end LBA are nonzero, then it must be greater than our @@ -56,7 +56,7 @@ self_load: jnz .end_lba_ok ; Compare the boot1 end LBA to the lower 32 bits of the partition end LBA. cmp ebx, ecx - ja panic + ja panic_simple .end_lba_ok: @@ -74,7 +74,7 @@ self_load: mov ecx, ebx call read_sector - jc panic + jc panic_simple add ebx, 512 inc word [bp - 0x02] @@ -82,32 +82,15 @@ self_load: .self_load_done: - mov ebx, cafebabe + ; Check the magic bytes at the end of boot1. + push es + mov ebx, boot1_magic call addr32_to_addr16 - mov eax, es:[ebx] - hlt - - call test_a20 - add al, 0x30 - mov byte fs:[0x0000], al - hlt + cmp dword es:[bx], BOOT1_MAGIC + pop es + jne panic_simple -pr_womble: - ; Reveal the true nature of jen - xor bx, bx -.loop: - cmp bx, WOMBLE_LEN - jae .done - lea si, [womble + bx] - mov dh, [si] - mov di, bx - shl di, 1 - mov byte fs:[di], dh - mov byte fs:[di + 0x01], 0x1f - inc bx - jmp .loop -.done: - hlt + jmp main ; Converts a 32-bit address to a 16-bit sector and offset. @@ -119,8 +102,7 @@ pr_womble: ; - cf: unset on success, set on failure ; Clobber: none addr32_to_addr16: - push bp - mov bp, sp + fnstart push es push eax @@ -152,9 +134,8 @@ addr32_to_addr16: .fail: pop eax pop es - pop bp stc - ret + fnret ; Reads a single sector at the given LBA into memory. @@ -170,8 +151,7 @@ read_sector: ; head = temp % n_heads ; cylinder = temp / n_heads - push bp - mov bp, sp + fnstart push es push ebx @@ -203,8 +183,14 @@ read_sector: .return: pop ebx pop es - pop bp - ret + fnret + + +panic_simple: + mov ax, 0x0003 + int 0x10 + mov word fs:[0x0000], 0x4f21 + hlt %if ($ - $$) > 512 @@ -212,7 +198,183 @@ read_sector: %endif +main: + ; Set VGA mode + ; https://mendelson.org/wpdos/videomodes.txt + mov ax, 0x0003 + int 0x10 + + ; Disable the cursor (don't want to look at the blink blink blink) + mov ax, 0x0100 + mov cx, 0x3f00 + int 0x10 + + mov word [GLOBALS + VGA_COL], 0x1f00 + + call vga_clear + + mov ax, msg_boot1_loaded + mov cx, MSG_BOOT1_LOADED_LEN + call vga_println + + call test_a20 + test ax, ax + jnz .a20_enabled + + mov ax, msg_a20_disabled + mov cx, MSG_A20_DISABLED_LEN + call vga_println + + ; TODO: enable a20 + hlt + +.a20_enabled + mov ax, msg_a20_enabled + mov cx, MSG_A20_ENABLED_LEN + call vga_println + + hlt + + +; Clear the VGA text buffer. +; Arguments: none +; Return: none +; Clobber: none +vga_clear: + fnstart + push di + push es + push ax + push cx + + mov ax, 0xb800 + mov es, ax + mov ax, [GLOBALS + VGA_COL] + mov cx, VGA_WIDTH * VGA_HEIGHT + xor di, di + rep stosw + mov word [GLOBALS + TEXTBUF_LINE], 0 + + pop cx + pop ax + pop es + pop di + fnret + + +; Scroll the VGA text buffer up one line. +; Arguments: none +; Return: none +; Clobber: none +vga_scroll: + fnstart + push si + push di + push ax + push cx + push es + push ds + + mov ax, 0xb800 + mov ds, ax + mov es, ax + + ; Copy everything up one line. + mov cx, VGA_WIDTH * (VGA_HEIGHT - 1) + mov si, VGA_WIDTH * 2 + mov di, 0 + rep movsw + + ; Clear the last line. + mov ax, [GLOBALS + VGA_COL] + mov cx, VGA_WIDTH + mov di, VGA_WIDTH * (VGA_HEIGHT - 1) * 2 + rep stosw + + pop ds + pop es + + ; Decrement the current textbuf line if it's greater than 0. + mov cx, [GLOBALS + TEXTBUF_LINE] + xor ax, ax + sub cx, 1 + cmovae ax, cx + mov [GLOBALS + TEXTBUF_LINE], ax + + pop cx + pop ax + pop di + pop si + fnret + + +; Write one line to the VGA text buffer. +; Arguments: +; - ax: pointer to the string to print +; - cx: string length +; Return: none +; Clobber: ax, cx +vga_println: + fnstart + push si + push di + push dx + push es + + cmp word [GLOBALS + TEXTBUF_LINE], VGA_HEIGHT + jb .scroll_done + call vga_scroll +.scroll_done: + + mov si, ax + mov ax, VGA_WIDTH + cmp cx, ax + cmova cx, ax + mov di, VGA_WIDTH * (VGA_HEIGHT - 1) * 2 + + xor dx, dx + mov ax, [GLOBALS + TEXTBUF_LINE] + mov di, VGA_WIDTH * 2 + mul di + mov di, ax + + mov ax, 0xb800 + mov es, ax + mov ah, [GLOBALS + VGA_COL + 1] + +.loop: + or cx, cx + jz .done + mov al, [si] + mov es:[di], ax + add di, 2 + inc si + dec cx + jmp .loop + +.done: + inc word [GLOBALS + TEXTBUF_LINE] + + pop es + pop dx + pop di + pop si + fnret + + +enable_a20: + fnstart + fnret + + +; Check whether the A20 line is enabled. Writes to the boot sector identifier. +; Arguments: none +; Return: +; - ax: 0 if A20 disabled, nonzero if A20 enabled +; Clobber: none test_a20: + push bp + mov bp, sp push gs ; Restore the boot sector identifier in case it was overwritten by anything. @@ -238,22 +400,20 @@ test_a20: .return: pop gs + pop bp ret -panic: - mov ax, 0x0003 - int 0x10 - mov word fs:[0x0000], 0x4f21 - hlt - - -womble db "jen is a womble!" -WOMBLE_LEN equ $ - womble +msg_boot1_loaded db "boot1 loaded. hello!" +MSG_BOOT1_LOADED_LEN equ $ - msg_boot1_loaded +msg_a20_enabled db "a20 enabled" +MSG_A20_ENABLED_LEN equ $ - msg_a20_enabled +msg_a20_disabled db "a20 disabled" +MSG_A20_DISABLED_LEN equ $ - msg_a20_disabled +msg_panic db "fuck" +MSG_PANIC_LEN equ $ - msg_panic - times 409600 db 0 -cafebabe: - dd 0xfeedface +boot1_magic dd BOOT1_MAGIC BOOT1_TOTAL_LEN equ $ - $$ BOOT1_TOTAL_SECTORS equ (BOOT1_TOTAL_LEN + 511) / 512 diff --git a/defines.s b/defines.s index 39a3b3f..1a20f89 100644 --- a/defines.s +++ b/defines.s @@ -6,6 +6,11 @@ %define EBDA_START 0x080000 +%define BOOT1_MAGIC 0x544e4150 + +%define VGA_WIDTH 80 +%define VGA_HEIGHT 25 + ; boot0 base stack frame variable offsets / globals ; (we use the same offsets once we copy the variables to the globals section) ; ------------------------------------------------------------------------------------------------- @@ -29,3 +34,18 @@ %define GPT_SECTORS_LOADED 0x16 %define GPT_CURRENT_LBA 0x18 %define BOOT1_GPT_ENTRY_ADDR 0x1a + +; Globals +; ------------------------------------------------------------------------------------------------ +%define VGA_COL 0x1c +%define TEXTBUF_LINE 0x1e + +%macro fnstart 0 + push bp + mov bp, sp +%endmacro + +%macro fnret 0 + pop bp + ret +%endmacro