feat(bootload): load next stage and preload kernel from FAT
This commit is contained in:
parent
d94d9fb5bb
commit
7f88017ed7
6
Makefile
6
Makefile
|
@ -32,7 +32,11 @@ stupid.tar.gz: $(SUBDIRS)
|
|||
|
||||
.PHONY: floppy_boot.img
|
||||
floppy_boot.img:
|
||||
@ echo
|
||||
dd if=/dev/zero of=$@ bs=512 count=1440
|
||||
mformat -C -f 1440 -i $@
|
||||
dd if=boot/bootsector.bin of=$@ conv=notrunc
|
||||
mcopy -i $@ boot/stpdboot.sys ::/STPDBOOT.SYS
|
||||
mcopy -i $@ kernel/vmstupid ::/VMSTUPID.SYS
|
||||
|
||||
.PHONY: clean
|
||||
clean: $(SUBDIRS)
|
||||
|
|
|
@ -1,17 +1,24 @@
|
|||
AS = fasm
|
||||
RM = rm
|
||||
|
||||
TARGET = bootcode.bin
|
||||
TARGET = bootsector.bin stpdboot.sys
|
||||
|
||||
SRCS = boot.asm \
|
||||
STAGE0_SRCS = boot0.asm \
|
||||
const.inc \
|
||||
fat12.inc
|
||||
|
||||
STAGE1_SRCS = boot1.asm \
|
||||
const.inc \
|
||||
a20.inc
|
||||
|
||||
.PHONY: all
|
||||
all: $(TARGET)
|
||||
|
||||
$(TARGET): $(SRCS)
|
||||
$(AS) boot.asm $@
|
||||
bootsector.bin: $(STAGE0_SRCS)
|
||||
$(AS) boot0.asm $@
|
||||
|
||||
stpdboot.sys: $(STAGE1_SRCS)
|
||||
$(AS) boot1.asm $@
|
||||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
|
|
2
boot/README.org
Normal file
2
boot/README.org
Normal file
|
@ -0,0 +1,2 @@
|
|||
#+TITLE: StupidOS Bootloader
|
||||
|
125
boot/boot.asm
125
boot/boot.asm
|
@ -1,125 +0,0 @@
|
|||
ORG 0x7C00
|
||||
USE16
|
||||
|
||||
jmp short _start
|
||||
nop
|
||||
|
||||
; Boot Record
|
||||
OEM_identifier db 'STUPID '
|
||||
bytes_per_sector dw 512
|
||||
sectors_per_cluster db 1
|
||||
reserved_sectors dw 1
|
||||
FAT_count db 2
|
||||
root_dir_entries dw 224
|
||||
total_sectors dw 2880
|
||||
media_desc_type db 0xF0
|
||||
sectors_per_FAT dw 9
|
||||
sectors_per_track dw 18
|
||||
heads_per_cylinder dw 2
|
||||
hidden_sectors dd 0
|
||||
large_sector_count dd 0
|
||||
|
||||
; Extended Boot Record
|
||||
drive_number db 0x0
|
||||
reserved db 0x0
|
||||
signature db 0x29 ; 0x28 or 0x29
|
||||
volume_id dd 0xB00B135 ; hope mine will grow :'(
|
||||
volume_label db 'Stupid Boot'
|
||||
system_id db 'FAT12 '
|
||||
|
||||
|
||||
_start:
|
||||
cli
|
||||
cld
|
||||
jmp 0x0:.canonicalize_cs
|
||||
|
||||
.canonicalize_cs:
|
||||
xor ax, ax
|
||||
mov ds, ax
|
||||
mov ss, ax
|
||||
mov es, ax
|
||||
mov sp, 0x7c00
|
||||
|
||||
; clear screen
|
||||
mov al, 0x03
|
||||
mov ah, 0
|
||||
int 0x10
|
||||
|
||||
mov si, msg_hello
|
||||
call bios_print
|
||||
|
||||
; reset floppy disk
|
||||
@@:
|
||||
xor ah, ah
|
||||
int 0x13
|
||||
jc @b
|
||||
|
||||
mov si, msg_load_stage
|
||||
call bios_print
|
||||
|
||||
; read sector into ES:BX (0100:0000)
|
||||
mov ax, 0x100 ; 100 segment
|
||||
mov es, ax ; 0100:0000 (0000:1000)
|
||||
xor bx, bx
|
||||
|
||||
mov ah, 0x2 ; read
|
||||
mov al, 0x1 ; one sector
|
||||
mov ch, 0x0 ; cylinder 0
|
||||
mov cl, 0x2 ; second sector
|
||||
mov dh, 0x0 ; head 0
|
||||
int 0x13
|
||||
jc .error
|
||||
|
||||
jmp 0x0:0x1000
|
||||
|
||||
.error:
|
||||
mov si, msg_error_sector
|
||||
call bios_print
|
||||
|
||||
hlt
|
||||
jmp $
|
||||
|
||||
bios_print:
|
||||
lodsb
|
||||
or al, al
|
||||
jz @f
|
||||
mov ah, 0x0E
|
||||
int 0x10
|
||||
jmp bios_print
|
||||
@@:
|
||||
ret
|
||||
|
||||
msg_hello db "StupidOS Bootloader", 0x0D, 0x0A, 0
|
||||
msg_load_stage db "Loading next stage", 0x0D, 0x0A, 0
|
||||
msg_error_sector db "ERROR: Can't read sector", 0x0D, 0x0A, 0
|
||||
|
||||
rb 0x7C00+512-2-$
|
||||
db 0x55, 0xAA
|
||||
|
||||
; ---------- stage 1 --------------
|
||||
|
||||
ORG 0x1000
|
||||
stage2:
|
||||
push cs
|
||||
pop ds
|
||||
|
||||
mov si, msg_stage2
|
||||
call bios_print
|
||||
|
||||
call a20_enable
|
||||
jc .error_a20
|
||||
|
||||
xchg bx, bx
|
||||
|
||||
jmp .hang
|
||||
.error_a20:
|
||||
mov si, msg_error_a20
|
||||
call bios_print
|
||||
.hang:
|
||||
hlt
|
||||
jmp $
|
||||
|
||||
INCLUDE 'a20.inc'
|
||||
|
||||
msg_stage2 db "StupidOS Bootloader (Stage 2)", 0x0D, 0x0A, 0
|
||||
msg_error_a20 db "ERROR: can't enable a20 line", 0x0D, 0x0A, 0
|
120
boot/boot0.asm
Normal file
120
boot/boot0.asm
Normal file
|
@ -0,0 +1,120 @@
|
|||
INCLUDE 'const.inc'
|
||||
|
||||
ORG STAGE0_BASE
|
||||
USE16
|
||||
|
||||
jmp short _start
|
||||
nop
|
||||
|
||||
; Boot Record
|
||||
OEM_identifier db 'STUPID '
|
||||
bytes_per_sector dw 512
|
||||
sectors_per_cluster db 1
|
||||
reserved_sectors dw 1
|
||||
FAT_count db 2
|
||||
root_dir_entries dw 224
|
||||
total_sectors dw 2880
|
||||
media_desc_type db 0xF0
|
||||
sectors_per_FAT dw 9
|
||||
sectors_per_track dw 18
|
||||
heads_per_cylinder dw 2
|
||||
hidden_sectors dd 0
|
||||
large_sector_count dd 0
|
||||
|
||||
; Extended Boot Record
|
||||
drive_number db 0x0
|
||||
reserved db 0x0
|
||||
signature db 0x29 ; 0x28 or 0x29
|
||||
volume_id dd 0xB00B135 ; hope mine will grow :'(
|
||||
volume_label db 'Stupid Boot'
|
||||
system_id db 'FAT12 '
|
||||
|
||||
|
||||
_start:
|
||||
cli
|
||||
cld
|
||||
jmp 0x0:.canonicalize_cs
|
||||
|
||||
.canonicalize_cs:
|
||||
xor ax, ax
|
||||
mov ds, ax
|
||||
mov ss, ax
|
||||
mov es, ax
|
||||
mov sp, 0x7c00
|
||||
|
||||
mov [drive_number], dl
|
||||
|
||||
; reset floppy disk
|
||||
@@:
|
||||
mov dl, [drive_number]
|
||||
xor ah, ah
|
||||
int 0x13
|
||||
jc @b
|
||||
|
||||
call fat_load_root
|
||||
|
||||
; search in root directory
|
||||
|
||||
mov si, kernel_file
|
||||
call fat_search_root
|
||||
jc .error_not_found
|
||||
mov [kernel_start], ax
|
||||
|
||||
mov si, stage1_file
|
||||
call fat_search_root
|
||||
jc .error_not_found
|
||||
mov [stage1_start], ax
|
||||
|
||||
; load fat
|
||||
xor ax, ax
|
||||
mov al, [FAT_count]
|
||||
mul word [sectors_per_FAT]
|
||||
mov cx, ax
|
||||
mov ax, [reserved_sectors]
|
||||
|
||||
xor bx, bx
|
||||
|
||||
call disk_read_sectors
|
||||
|
||||
; preload kernel
|
||||
mov ax, KERNEL_PRELOAD/0x10
|
||||
mov es, ax
|
||||
mov ax, [kernel_start]
|
||||
xor bx, bx
|
||||
call fat_load_binary
|
||||
|
||||
; load stage 2
|
||||
mov ax, STAGE1_BASE/0x10
|
||||
mov es, ax
|
||||
mov ax, [stage1_start]
|
||||
xor bx, bx
|
||||
call fat_load_binary
|
||||
|
||||
jmp 0x0:STAGE1_BASE
|
||||
|
||||
.error_not_found:
|
||||
push si
|
||||
mov si, msg_error
|
||||
call bios_print
|
||||
pop si
|
||||
call bios_print
|
||||
mov si, msg_not_found
|
||||
call bios_print
|
||||
hlt
|
||||
jmp $
|
||||
|
||||
INCLUDE "utils.inc"
|
||||
INCLUDE "fat12.inc"
|
||||
|
||||
msg_error db "ERROR: ", 0
|
||||
msg_not_found db " not found", CR, LF, 0
|
||||
|
||||
kernel_file db "VMSTUPIDSYS", 0
|
||||
stage1_file db "STPDBOOTSYS", 0
|
||||
|
||||
kernel_start dw 0x0
|
||||
stage1_start dw 0x0
|
||||
|
||||
|
||||
rb 0x7C00+512-2-$
|
||||
db 0x55, 0xAA
|
28
boot/boot1.asm
Normal file
28
boot/boot1.asm
Normal file
|
@ -0,0 +1,28 @@
|
|||
INCLUDE 'const.inc'
|
||||
|
||||
ORG STAGE1_BASE
|
||||
USE16
|
||||
|
||||
stage2:
|
||||
push cs
|
||||
pop ds
|
||||
|
||||
mov si, msg_stage2
|
||||
call bios_print
|
||||
|
||||
call a20_enable
|
||||
jc .error_a20
|
||||
|
||||
jmp .hang
|
||||
.error_a20:
|
||||
mov si, msg_error_a20
|
||||
call bios_print
|
||||
.hang:
|
||||
hlt
|
||||
jmp $
|
||||
|
||||
INCLUDE 'a20.inc'
|
||||
INCLUDE 'utils.inc'
|
||||
|
||||
msg_stage2 db "StupidOS Bootloader (Stage 1)", 0x0D, 0x0A, 0
|
||||
msg_error_a20 db "ERROR: can't enable a20 line", 0x0D, 0x0A, 0
|
|
@ -1,4 +1,5 @@
|
|||
|
||||
CR = 0x0D
|
||||
LF = 0x0A
|
||||
; -------- Address ----------
|
||||
STAGE0_BASE = 0x7C00
|
||||
STAGE1_BASE = 0x1000
|
||||
|
|
181
boot/fat12.inc
Normal file
181
boot/fat12.inc
Normal file
|
@ -0,0 +1,181 @@
|
|||
ATTR_READ_ONLY = 0x01
|
||||
ATTR_HIDDEN = 0x02
|
||||
ATTR_SYSTEM = 0x04
|
||||
ATTR_VOLUME_ID = 0x08
|
||||
ATTR_DIRECTORY = 0x10
|
||||
ATTR_ARCHIVE = 0x20
|
||||
|
||||
struc fat_entry
|
||||
{
|
||||
.name db 8 dup ?
|
||||
.ext db 3 dup ?
|
||||
.attrs db ?
|
||||
.reserved dw ?
|
||||
.creation_time dw ?
|
||||
.creation_date dw ?
|
||||
.access_date dw ?
|
||||
.reserved2 dw ?
|
||||
.mod_time dw ?
|
||||
.mod_date dw ?
|
||||
.start dw ?
|
||||
.size dd ?
|
||||
}
|
||||
|
||||
virtual at di
|
||||
|
||||
fat_entry fat_entry
|
||||
end virtual
|
||||
|
||||
|
||||
; CHS to LBA
|
||||
; LBA = (C * HPC + H) * SPT + (S - 1)
|
||||
|
||||
;;; Read sectors from disk to buffer
|
||||
;;;
|
||||
;;; @param AX LBA starting sector
|
||||
;;; @param CX sector count
|
||||
;;; @param ES:BX buffer
|
||||
;;;
|
||||
disk_read_sectors:
|
||||
; https://en.wikipedia.org/wiki/Logical_block_addressing
|
||||
; convert LBA to CHS
|
||||
; HPC = Head per Cluster
|
||||
; SPT = Sector per Track
|
||||
|
||||
; S = (LBA % SPT) + 1
|
||||
push ax
|
||||
push bx
|
||||
push cx
|
||||
xor dx, dx
|
||||
div word [sectors_per_track]
|
||||
inc dx
|
||||
mov [S], dx
|
||||
|
||||
; H = (LBA / SPT) % HPC
|
||||
; C = LBA / (HPC * SPT)
|
||||
xor dx, dx
|
||||
div word [heads_per_cylinder]
|
||||
mov [C], ax
|
||||
mov [H], dx
|
||||
|
||||
; read sectors
|
||||
mov ah, 0x2
|
||||
mov al, 0x1
|
||||
mov ch, byte [C]
|
||||
mov cl, byte [S]
|
||||
mov dh, byte [H]
|
||||
mov dl, [drive_number]
|
||||
|
||||
int 0x13
|
||||
jc @f
|
||||
pop cx
|
||||
pop bx
|
||||
pop ax
|
||||
add bx, word [bytes_per_sector]
|
||||
inc ax
|
||||
loop disk_read_sectors
|
||||
ret
|
||||
@@:
|
||||
mov si, msg_error_sector
|
||||
call bios_print
|
||||
ret
|
||||
|
||||
C dw 0x00
|
||||
H dw 0x00
|
||||
S dw 0x00
|
||||
|
||||
fat_load_root:
|
||||
mov ax, DISK_BUFFER/0x10
|
||||
mov es, ax
|
||||
|
||||
; load root directory
|
||||
mov ax, [sectors_per_FAT]
|
||||
xor cx, cx
|
||||
mov cl, [FAT_count]
|
||||
mul cx
|
||||
add ax, [reserved_sectors]
|
||||
push ax
|
||||
|
||||
mov bx, [bytes_per_sector]
|
||||
mov cl, 0x5
|
||||
shr bx, cl
|
||||
mov ax, [root_dir_entries]
|
||||
xor dx, dx
|
||||
div bx
|
||||
mov cx, ax
|
||||
pop ax
|
||||
|
||||
mov [data_start], ax
|
||||
add [data_start], cx
|
||||
|
||||
xor bx, bx
|
||||
|
||||
call disk_read_sectors
|
||||
|
||||
ret
|
||||
|
||||
;; @param SI filename to search
|
||||
fat_search_root:
|
||||
mov cx, [root_dir_entries]
|
||||
mov di, 0x0
|
||||
@@:
|
||||
push si
|
||||
push cx
|
||||
mov cx, 0xB ; name(8) + ext(3)
|
||||
push di
|
||||
rep cmpsb
|
||||
pop di
|
||||
pop cx
|
||||
pop si
|
||||
je .file_found
|
||||
add di, 0x20
|
||||
loop @b
|
||||
; set carry if not found
|
||||
stc
|
||||
ret
|
||||
.file_found:
|
||||
mov ax, [es:fat_entry.start]
|
||||
clc
|
||||
ret
|
||||
|
||||
;;; @param AX cluster
|
||||
;;; @param ES:BX buffer
|
||||
fat_load_binary:
|
||||
push ax
|
||||
sub ax, 0x2
|
||||
xor cx, cx
|
||||
mov cl, [sectors_per_cluster]
|
||||
mul cx
|
||||
|
||||
add ax, [data_start]
|
||||
xor cx, cx
|
||||
mov cl, [sectors_per_cluster]
|
||||
call disk_read_sectors
|
||||
|
||||
pop ax
|
||||
mov cx, ax
|
||||
mov dx, ax
|
||||
shr dx, 0x1
|
||||
add cx, dx
|
||||
push bx
|
||||
mov bx, DISK_BUFFER
|
||||
add bx, cx
|
||||
mov dx, [bx]
|
||||
pop bx
|
||||
|
||||
test ax, 0x1
|
||||
jnz .odd_cluster
|
||||
.even_cluster:
|
||||
and dx, 0xFFF
|
||||
jmp .end
|
||||
.odd_cluster:
|
||||
shr dx, 0x4
|
||||
.end:
|
||||
mov ax, dx
|
||||
cmp dx, 0xFF0
|
||||
jb fat_load_binary
|
||||
ret
|
||||
|
||||
|
||||
msg_error_sector db "ERROR: reading sector", CR, LF, 0
|
||||
data_start dw 0x0
|
9
boot/utils.inc
Normal file
9
boot/utils.inc
Normal file
|
@ -0,0 +1,9 @@
|
|||
bios_print:
|
||||
lodsb
|
||||
or al, al
|
||||
jz @f
|
||||
mov ah, 0x0E
|
||||
int 0x10
|
||||
jmp bios_print
|
||||
@@:
|
||||
ret
|
Loading…
Reference in a new issue