Moved stuff around and added a makefile also got a custom bootloader
based on the JazzOS bootloader (modified a bit)
This commit is contained in:
297
source/bootload/boot.asm
Normal file
297
source/bootload/boot.asm
Normal file
@@ -0,0 +1,297 @@
|
||||
ORG 7C00h
|
||||
BITS 16
|
||||
|
||||
jmp short main
|
||||
nop
|
||||
|
||||
; Define Fat12 header
|
||||
bdb_oem: db 'MSWIN4.1'
|
||||
bdb_bytes_per_sector: dw 512
|
||||
bdb_sectors_per_cluster: db 1
|
||||
bdb_reserved_sectors: dw 1
|
||||
bdb_fat_count: db 2
|
||||
bdb_dir_entries_count: dw 0E0h
|
||||
bdb_total_sectors: dw 2880
|
||||
bdb_media_descriptor_type: db 0F0h
|
||||
bdb_sectors_per_fat: dw 9
|
||||
bdb_sectors_per_track: dw 18
|
||||
bdb_heads: dw 2
|
||||
bdb_hidden_sectors: dd 0
|
||||
bdb_large_sector_count: dd 0
|
||||
|
||||
; extended boot record
|
||||
ebr_drive_number: db 0
|
||||
db 0
|
||||
ebr_signature: db 29h
|
||||
ebr_volume_id: db 12h, 34h, 56h, 78h
|
||||
ebr_volume_label: db 'CrawShaw OS'
|
||||
ebr_system_id: db 'FAT12 '
|
||||
|
||||
main:
|
||||
; Setup registers
|
||||
mov ax, 0
|
||||
mov ds, ax ; ds = data segment pointer
|
||||
mov es, ax ; es = extra segment pointer
|
||||
mov ss, ax ; ss = stack pointer
|
||||
|
||||
mov sp, 7C00h
|
||||
|
||||
; Read from disk
|
||||
;mov [ebr_drive_number], dl
|
||||
;mov ax, 1
|
||||
;mov cl, 1
|
||||
;mov bx, 7E00h
|
||||
;call disk_read
|
||||
|
||||
; Output boot text
|
||||
mov si, boot_text
|
||||
call print_string
|
||||
|
||||
; Load kernel
|
||||
; 4 segments:
|
||||
; reserved segment (bdb_reserved_segments, 1)
|
||||
; FAT: (sectors_per_fat * fat_count) 9*2=18
|
||||
; root dir: gives location of data
|
||||
; data: stores the actual data
|
||||
|
||||
; Get LBA of root dir
|
||||
mov ax, [bdb_sectors_per_fat]
|
||||
mov bl, [bdb_fat_count]
|
||||
xor bh,bh ; clear bh
|
||||
mul bx ; 9 * 2 = 18
|
||||
add ax, [bdb_reserved_sectors] ; The LBA of root dir
|
||||
push ax ; Push to stack
|
||||
|
||||
mov ax, [bdb_dir_entries_count]
|
||||
shl ax,5 ; ax *= 32 (shifting 5 times)
|
||||
xor dx,dx ; Clear dx
|
||||
div word [bdb_bytes_per_sector] ;32*num of entries)/bytes per sector
|
||||
test dx,dx ; See if there's a remainder
|
||||
jz root_dir_after
|
||||
inc ax ; Add one if there's a remainder
|
||||
|
||||
root_dir_after:
|
||||
mov cl, al
|
||||
pop ax ; LBA of root dir
|
||||
mov dl, [ebr_drive_number]
|
||||
mov bx, buffer
|
||||
call disk_read
|
||||
|
||||
xor bx,bx ; clear bx
|
||||
mov di, buffer ; Loaded root dir into memory
|
||||
|
||||
search_for_kernel:
|
||||
mov si, file_kernel_bin ; Move the name of the kernel into si
|
||||
mov cx, 11
|
||||
push di ; Preserve di
|
||||
repe cmpsb ; Repeat a comparison of bytes between kernel name and current bytes until it finds a match
|
||||
pop di ; Retrieve di
|
||||
je found_kernel
|
||||
|
||||
add di, 32 ; Next directory entry
|
||||
inc bx
|
||||
cmp bx, [bdb_dir_entries_count] ; Have we reached the number of directories that exist
|
||||
jl search_for_kernel ; Repeat search
|
||||
|
||||
jmp kernel_not_found ; If the last dir has been searched, then there is no kernel
|
||||
kernel_not_found:
|
||||
mov si, kernel_load_error
|
||||
call print_string
|
||||
|
||||
hlt
|
||||
jmp halt
|
||||
|
||||
found_kernel:
|
||||
mov si, kernel_found_text
|
||||
call print_string
|
||||
; Find kernel cluster
|
||||
mov ax, [di+26]
|
||||
mov [kernel_cluster], ax
|
||||
|
||||
mov ax, [bdb_reserved_sectors]
|
||||
mov bx, buffer
|
||||
mov cl, [bdb_sectors_per_fat]
|
||||
mov dl, [ebr_drive_number]
|
||||
|
||||
call disk_read ; Load FAT from disk into memory
|
||||
|
||||
; Load kernel into memory
|
||||
mov bx, kernel_load_segment
|
||||
mov es, bx
|
||||
mov bx, kernel_load_offset ; Setup memory that kernel will be loaded into
|
||||
|
||||
load_kernel_loop:
|
||||
mov ax, [kernel_cluster]
|
||||
add ax, 31 ; Setup offset so we can read the particular cluster
|
||||
mov cl, 1 ;sectors to read
|
||||
mov dl, [ebr_drive_number]
|
||||
|
||||
call disk_read
|
||||
|
||||
add bx, [bdb_bytes_per_sector]
|
||||
|
||||
; (kernel_cluster * 3) / 2
|
||||
mov ax, [kernel_cluster]
|
||||
mov cx, 3
|
||||
mul cx
|
||||
mov cx, 2
|
||||
div cx
|
||||
|
||||
; setup buffers
|
||||
mov si, buffer
|
||||
add si, ax
|
||||
mov ax, [ds:si]
|
||||
|
||||
or dx,dx
|
||||
jz even
|
||||
|
||||
odd:
|
||||
shr ax, 4 ;shift ax 4
|
||||
jmp next_cluster_after
|
||||
|
||||
even:
|
||||
and ax, 0fffh ; Gives the other 12 bits
|
||||
|
||||
next_cluster_after:
|
||||
cmp ax, 0ff8h ; If the value is ff8h or bigger then we've reached the end of FAT
|
||||
jae read_finish
|
||||
|
||||
mov [kernel_cluster], ax
|
||||
jmp load_kernel_loop
|
||||
|
||||
read_finish: ; Load kernel
|
||||
mov dl, [ebr_drive_number]
|
||||
mov ax, kernel_load_segment
|
||||
mov ds, ax
|
||||
mov es, ax
|
||||
|
||||
jmp kernel_load_segment:kernel_load_offset ; Jump to the kernel code
|
||||
hlt
|
||||
|
||||
|
||||
halt:
|
||||
jmp halt
|
||||
|
||||
; LBA = index of data segment on disk
|
||||
; CHS = cylinder, header, sector
|
||||
; input, LBA index: ax
|
||||
; sector number: cx [0-5]
|
||||
; cylinder: cx [6-15]
|
||||
; head: dh
|
||||
lba_to_chs:
|
||||
push ax
|
||||
push dx
|
||||
|
||||
xor dx,dx ; clear dx
|
||||
div word [bdb_sectors_per_track] ;(LBA % sectors per track) + 1 = sector
|
||||
inc dx ; sector, dx stores the remainder so we increment that.
|
||||
mov cx,dx
|
||||
|
||||
xor dx,dx ; clear dx
|
||||
div word [bdb_heads]
|
||||
|
||||
mov dh,dl ; head
|
||||
mov ch,al
|
||||
shl ah, 6
|
||||
or CL, AH ; cylinder
|
||||
|
||||
pop ax
|
||||
mov dl,al
|
||||
pop ax
|
||||
|
||||
RET
|
||||
|
||||
disk_read:
|
||||
push ax
|
||||
push bx
|
||||
push cx
|
||||
push dx
|
||||
push di
|
||||
|
||||
|
||||
call lba_to_chs
|
||||
|
||||
mov ah, 02h
|
||||
|
||||
; repeat drive read 3 times (incase of random error)
|
||||
mov di, 3 ; counter
|
||||
|
||||
retry:
|
||||
stc
|
||||
int 13h
|
||||
jnc done_read
|
||||
|
||||
call disk_reset ; Reset drivers of disk
|
||||
|
||||
dec di
|
||||
test di, di
|
||||
jnz retry
|
||||
|
||||
fail_disk_read:
|
||||
mov si, disk_read_fail
|
||||
call print_string
|
||||
hlt
|
||||
jmp halt
|
||||
|
||||
disk_reset:
|
||||
pusha
|
||||
mov ah, 0 ; Reset drive
|
||||
stc
|
||||
int 13h
|
||||
jc fail_disk_read
|
||||
popa
|
||||
ret
|
||||
|
||||
done_read:
|
||||
pop di
|
||||
pop dx
|
||||
pop cx
|
||||
pop bx
|
||||
pop ax
|
||||
ret
|
||||
|
||||
; SI = pointer to start of string to be printed
|
||||
print_string:
|
||||
push si
|
||||
push ax
|
||||
push bx
|
||||
|
||||
mov ah, 0Eh ; int 10h teletype function, we're telling the BIOS we will print something
|
||||
|
||||
.repeat:
|
||||
lodsb ; Get char from si into al
|
||||
cmp al, 0 ; Compare al to 0
|
||||
je .done ; If char is zero, end of string
|
||||
|
||||
mov bh, 0
|
||||
int 10h ; Otherwise, print it
|
||||
jmp .repeat ; And move on to next char
|
||||
|
||||
.done:
|
||||
; Print newline
|
||||
mov ah, 0Eh
|
||||
mov al, 13
|
||||
int 10h
|
||||
mov al, 10
|
||||
int 10h
|
||||
; Exit function
|
||||
pop bx
|
||||
pop ax
|
||||
pop si
|
||||
ret
|
||||
|
||||
boot_text: db '[OK] Boot sequence begun...', 0
|
||||
kernel_found_text: db '[OK] Kernel located...', 0
|
||||
disk_read_fail: db '[ERR] Failed to read disk!', 0
|
||||
file_kernel_bin: db 'KERNEL BIN' ; Must have a double space between KERNEL and BIN
|
||||
kernel_load_error: db '[ERR] Kernel not found!', 0
|
||||
|
||||
kernel_cluster: dw 0
|
||||
kernel_load_segment: equ 2000h
|
||||
kernel_load_offset: equ 0
|
||||
|
||||
|
||||
times 510-($-$$) db 0 ; Fill up the next 510 bits with 0's
|
||||
dw 0AA55h ; D
|
||||
|
||||
buffer:
|
||||
Reference in New Issue
Block a user