mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-11-23 08:00:20 +00:00
f3c8821b0f
This is starting to get cramped. I wonder how much longer this hilarious frankenloader will be able to boot us.
252 lines
4 KiB
NASM
Executable file
252 lines
4 KiB
NASM
Executable file
; asmsyntax=nasm
|
|
|
|
[org 0x7c00]
|
|
[bits 16]
|
|
|
|
boot:
|
|
cli
|
|
mov ax, 0x8000
|
|
mov ss, ax
|
|
mov sp, 0xffff
|
|
|
|
push cs
|
|
pop ds
|
|
xor bx, bx
|
|
mov ah, 0x0e
|
|
mov si, message
|
|
lodsb
|
|
.lewp:
|
|
int 0x10
|
|
lodsb
|
|
cmp al, 0
|
|
jne .lewp
|
|
|
|
; Enable A20
|
|
mov ax, 0x2401
|
|
int 0x15
|
|
|
|
; HACK: Load the ELF kernel at 0xf000. Assuming that the first
|
|
; LOAD header has a file offset of 0x1000, this puts _start
|
|
; at 0x10000 which we jump to later.
|
|
; This is all quite rickety.
|
|
mov bx, 0xf00
|
|
mov es, bx
|
|
xor bx, bx
|
|
|
|
mov cx, word [cur_lba]
|
|
.sector_loop:
|
|
call convert_lba_to_chs
|
|
|
|
mov ah, 0x02 ; cmd 0x02 - Read Disk Sectors
|
|
mov al, 1 ; 1 sector at a time
|
|
mov dl, 0 ; drive 0 (fd0)
|
|
int 0x13
|
|
|
|
jc fug
|
|
|
|
mov ah, 0x0e
|
|
mov al, '.'
|
|
int 0x10
|
|
|
|
inc word [cur_lba]
|
|
mov cx, word [cur_lba]
|
|
cmp cx, 900
|
|
jz .sector_loop_end
|
|
|
|
mov bx, es
|
|
add bx, 0x20
|
|
mov es, bx
|
|
xor bx, bx
|
|
|
|
jmp .sector_loop
|
|
|
|
.sector_loop_end:
|
|
|
|
call durk
|
|
|
|
; Turn off the floppy motor.
|
|
mov dx, 0x3f2
|
|
xor al, al
|
|
out dx, al
|
|
|
|
; Let's look at the ELF header.
|
|
mov bx, 0xf00
|
|
mov fs, bx
|
|
cmp [fs:0], dword 0x464c457f ; ELF magic: { 0x7f "ELF" }
|
|
jne fug
|
|
|
|
cmp [fs:24], dword 0x10000 ; Entry should be 0x10000
|
|
jne fug
|
|
|
|
mov ebx, dword [fs:28] ; EBX <- program header table
|
|
mov ecx, dword [fs:44] ; ECX <- program header count
|
|
|
|
; Let's find the BSS and clear it.
|
|
|
|
parse_program_header:
|
|
cmp [fs:ebx], dword 0x1 ; Is Load segment?
|
|
jne .next
|
|
|
|
cmp [fs:ebx+24], dword 0x6 ; Is read+write but not execute?
|
|
jne .next
|
|
|
|
mov edi, [fs:ebx+8] ; EDI <- p_vaddr
|
|
add edi, [fs:ebx+16] ; skip over 'p_filesz' bytes (leave them intact)
|
|
|
|
push ecx
|
|
|
|
sub edi, [fs:ebx+16] ; skip over 'p_filesz' bytes (see above)
|
|
|
|
; Since we're in 16-bit real mode, create a segment address.
|
|
mov eax, edi
|
|
shr eax, 4
|
|
mov es, ax
|
|
and edi, 0xf
|
|
|
|
mov ecx, [fs:ebx+20] ; ECX <- p_memsz
|
|
xor al, al
|
|
rep stosb
|
|
|
|
pop ecx
|
|
|
|
.next:
|
|
add ebx, 32
|
|
loop parse_program_header
|
|
|
|
; Okay we're all set to go!
|
|
|
|
lets_go:
|
|
lgdt [cs:test_gdt_ptr]
|
|
|
|
mov eax, cr0
|
|
or al, 1
|
|
mov cr0, eax
|
|
|
|
jmp 0x08:pmode
|
|
|
|
durk:
|
|
push cs
|
|
pop ds
|
|
xor bx, bx
|
|
mov ah, 0x0e
|
|
mov si, msg_sectors_loaded
|
|
lodsb
|
|
.lewp:
|
|
int 0x10
|
|
lodsb
|
|
cmp al, 0
|
|
jne .lewp
|
|
ret
|
|
|
|
pmode:
|
|
[bits 32]
|
|
mov ax, 0x10
|
|
mov ds, ax
|
|
mov es, ax
|
|
mov fs, ax
|
|
mov gs, ax
|
|
|
|
mov ss, ax
|
|
mov esp, 0x4000
|
|
|
|
xor eax, eax
|
|
xor ebx, ebx
|
|
xor ecx, ecx
|
|
xor edx, edx
|
|
xor ebp, ebp
|
|
xor esi, esi
|
|
xor edi, edi
|
|
|
|
jmp 0x10000
|
|
|
|
hlt
|
|
|
|
test_gdt_ptr:
|
|
dw (test_gdt_end-test_gdt)
|
|
dd test_gdt
|
|
|
|
test_gdt:
|
|
dd 0
|
|
dd 0
|
|
dd 0x0000ffff
|
|
dd 0x00cf9a00
|
|
dd 0x0000ffff
|
|
dd 0x00cf9200
|
|
dd 0
|
|
dd 0
|
|
dd 0
|
|
dd 0
|
|
test_gdt_end:
|
|
|
|
[bits 16]
|
|
fug:
|
|
xor bx, bx
|
|
mov ah, 0x0e
|
|
mov si, fug_message
|
|
lodsb
|
|
.lewp:
|
|
int 0x10
|
|
lodsb
|
|
cmp al, 0
|
|
jne .lewp
|
|
|
|
cli
|
|
hlt
|
|
|
|
; Input:
|
|
;
|
|
; AX = LBA
|
|
;
|
|
; Output:
|
|
;
|
|
; CX and DH = C/H/S address formatted for Int13,2
|
|
|
|
; CL = sector (LBA % sectors_per_track) + 1
|
|
;
|
|
; 1.44M floppy stats:
|
|
; (sectors_per_track: 18)
|
|
; (heads: 2)
|
|
; (sectors: 2880)
|
|
|
|
convert_lba_to_chs:
|
|
mov ax, cx
|
|
|
|
; AX = LBA/spt, DX = LBA%spt
|
|
xor dx, dx
|
|
div word [sectors_per_track]
|
|
|
|
; CL = sector (LBA % sectors_per_track) + 1
|
|
mov cl, dl
|
|
inc cl
|
|
|
|
; CH = track (LBA / sectors_per_track) / heads
|
|
mov ch, al
|
|
shr ch, 1
|
|
|
|
; AX = (LBA/spt)/heads, DX = (LBA/spt)%heads
|
|
xor dx, dx
|
|
div word [heads]
|
|
|
|
; DH = sector (LBA / sectors_per_track) % heads
|
|
mov dh, dl
|
|
|
|
ret
|
|
|
|
cur_lba:
|
|
dw 1
|
|
sectors_per_track:
|
|
dw 18
|
|
heads:
|
|
dw 2
|
|
|
|
msg_sectors_loaded:
|
|
db "done!", 0x0d, 0x0a, 0
|
|
|
|
message:
|
|
db "Loading kernel", 0
|
|
|
|
fug_message:
|
|
db "FUG!", 0x0d, 0x0a, 0
|
|
|
|
times 510-($-$$) db 0
|
|
dw 0xaa55
|