|
|
|
|
@ -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
|
|
|
|
|
|