Nightloader/i386/bootsector/bootsector.asm

253 lines
4.4 KiB
NASM
Executable File

PARTITION_IDENTIFIER equ 0x9e
bits 16
org 0x7c00
entry:
mov bx, 0x7e00
mov ss, bx
mov bp, 512
mov sp, 512
push dx
push bp
mov bp, sp
call find_partition
mov sp, bp
pop bp
cmp ax, 0xff
je write_error.partition_not_found
pop dx
push bp
mov bp, sp
push ax
push dx
call load_partition
mov sp, bp
pop bp
jmp jump_to_partition
find_partition:
xor si, si
.finder_loop:
mov ax, si
shl ax, 4
add ax, (0x7c00 + 446)
mov bx, ax
add bx, 4
cmp [bx], byte PARTITION_IDENTIFIER
je .partition_found
inc si
cmp si, 4
jb .finder_loop
.partition_not_found:
mov ax, 0xff
ret
.partition_found:
mov ax, si
ret
; Arguments:
; FURTHEST FROM BP
; 4) Start LBA, less significant half
; 3) Output Segment
; 2) Output Offset
; 1) Disk ID
; NEAREST TO BP
load_sector:
push ax
push bx
push cx
push dx
push di
push si
; Allocate Disk Address Packet
sub sp, 16
mov bx, sp
mov [bx], byte 0x10 ; Length of DAP
mov [bx + 1], byte 0 ; Unused byte
mov [bx + 2], word 1 ; Sector count
; Write offset of the output buffer
mov ax, [bp - 4]
mov [bx + 4], ax
; Write segment of the output buffer
mov ax, [bp - 6]
mov [bx + 6], ax
; Write LBA of sector to read
; mov [bx + 8], word 0
; mov [bx + 10], word 0
; mov ax, [bp - 8]
; mov [bx + 12], ax
; mov ax, [bp - 9]
; mov [bx + 14], ax
mov si, [bp - 8]
mov [bx + 8], si
mov [bx + 10], word 0
mov [bx + 12], word 0
mov [bx + 14], word 0
; Perform the interrupt
mov si, bx
mov dl, [bp - 2]
mov ah, 0x42 ; Extended Read from sectors
int 0x13
add sp, 16
pop si
pop di
pop dx
pop cx
pop bx
pop ax
ret
load_partition:
sub sp, 16
mov di, sp
mov [di], word 0 ; Sector Index
; Store the start sector
mov bx, [bp - 2] ; Partition Index
shl bx, 4 ; Get the offset from the MBR-table's tsart
add bx, (0x7c00 + 446) ; Point into MBR table
mov [di + 2], bx ; Partition Table Entry Pointer
mov ax, [bx + 8]
mov [di + 4], ax ; Lower Partition Start LBA
mov ax, [bx + 10]
mov [di + 6], ax ; Higher Partition Start LBA
mov ax, [bx + 12]
mov [di + 8], ax ; Lower Partition Sector Count
; mov ax, [bx + 6]
; mov [di + 10], ax ; Higher Partition Sector Count
.loader_loop:
mov bx, [di] ; Sector Index
mov dx, [bp - 4] ; Disk Identifier
; Segment Address
mov cx, [di]
shl cx, 5
add cx, 0x0a00
; mov ax, [di]
; shl ax, 4
; sub cx, ax
mov bx, 0
; This alternative snippet uses only the address into the segment
; at 0x0000, rather than only the segment address. Both achieves
; exactly the same, though.
;
; Output Buffer Address
; mov bx, [di]
; shl bx, 7
; add bx, 0x0a00
push bp
mov bp, sp
push dx
push bx
push cx
mov ax, [di + 4]
add ax, [di]
push ax
call load_sector
mov sp, bp
pop bp
mov ax, [di]
cmp ax, [di + 8]
; Increment and write-back the sector index.
inc ax
mov [di], ax
jb .loader_loop
.finished:
add sp, 16
ret
jump_to_partition:
jmp 0xa000
cli
hlt
write_error:
.partition_not_found:
mov si, .partition_not_found_text
jmp .write_text
.partition_not_found_text:
db "Failed finding Partition!", 0x00
; SI: Text-Address
.write_text:
; Reset Display
mov ah, 0x00
mov al, 0x03
int 0x10
xor di, di
.text_writer_loop:
; Move Cursor
mov ah, 0x02 ; Interrupt Function (move cursor)
mov bh, 0 ; Display Page
mov dx, 3 ; Start Column
add dx, di
mov dh, 2 ; Line
int 0x10
; Gather character and check if it is the null-terminator.
mov bx, si
add bx, di
mov al, [bx]
cmp al, 0x00
je .halt
; Display the character
mov ah, 0x0a
mov bh, 0
mov cx, 1
int 0x10
inc di
jmp .text_writer_loop
.halt:
cli
hlt
times 446 - ($ - $$) nop
loader_partition:
db 0x80
db 0x00, 0x00, 0x00
db PARTITION_IDENTIFIER
db 0x00, 0x00, 0x00
dd 1
dd 63
system_partition:
db 0x80
db 0x00, 0x00, 0x00
db 1 ; FAT12 partition ID
db 0x00, 0x00, 0x00
dd 64
dd 1024
times 510 - ($ - $$) db 0x00
db 0x55, 0xaa