feat(bootload): load next stage and preload kernel from FAT
This commit is contained in:
parent
d94d9fb5bb
commit
7f88017ed7
80
Makefile
80
Makefile
|
@ -1,39 +1,43 @@
|
||||||
TOPDIR := $(dir $(realpath $(lastword $(MAKEFILE_LIST))))
|
TOPDIR := $(dir $(realpath $(lastword $(MAKEFILE_LIST))))
|
||||||
SYSROOTDIR := $(TOPDIR)/sysroot
|
SYSROOTDIR := $(TOPDIR)/sysroot
|
||||||
TOOLSDIR := $(TOPDIR)/tools
|
TOOLSDIR := $(TOPDIR)/tools
|
||||||
|
|
||||||
RM = echo
|
RM = echo
|
||||||
|
|
||||||
SUBDIRS := boot kernel lib bin
|
SUBDIRS := boot kernel lib bin
|
||||||
|
|
||||||
TARGET = stupid.tar.gz floppy_boot.img
|
TARGET = stupid.tar.gz floppy_boot.img
|
||||||
ifneq ($(OS),Windows_NT)
|
ifneq ($(OS),Windows_NT)
|
||||||
TARGET += stupid.iso
|
TARGET += stupid.iso
|
||||||
endif
|
endif
|
||||||
|
|
||||||
.PHONY: all
|
.PHONY: all
|
||||||
all: $(TARGET)
|
all: $(TARGET)
|
||||||
|
|
||||||
GOAL:=install
|
GOAL:=install
|
||||||
clean: GOAL:=clean
|
clean: GOAL:=clean
|
||||||
|
|
||||||
.PHONY: $(SUBDIRS)
|
.PHONY: $(SUBDIRS)
|
||||||
$(SUBDIRS):
|
$(SUBDIRS):
|
||||||
@echo "📁 $@"
|
@echo "📁 $@"
|
||||||
DESTDIR=$(SYSROOTDIR) $(MAKE) -C $@ $(GOAL)
|
DESTDIR=$(SYSROOTDIR) $(MAKE) -C $@ $(GOAL)
|
||||||
|
|
||||||
.PHONY: stupid.iso
|
.PHONY: stupid.iso
|
||||||
stupid.iso: $(SUBDIRS)
|
stupid.iso: $(SUBDIRS)
|
||||||
$(TOPDIR)/tools/create-iso $@ sysroot
|
$(TOPDIR)/tools/create-iso $@ sysroot
|
||||||
|
|
||||||
.PHONY: stupid.tar.gz
|
.PHONY: stupid.tar.gz
|
||||||
stupid.tar.gz: $(SUBDIRS)
|
stupid.tar.gz: $(SUBDIRS)
|
||||||
tar -czvf $@ sysroot
|
tar -czvf $@ sysroot
|
||||||
|
|
||||||
.PHONY: floppy_boot.img
|
.PHONY: floppy_boot.img
|
||||||
floppy_boot.img:
|
floppy_boot.img:
|
||||||
@ echo
|
dd if=/dev/zero of=$@ bs=512 count=1440
|
||||||
|
mformat -C -f 1440 -i $@
|
||||||
.PHONY: clean
|
dd if=boot/bootsector.bin of=$@ conv=notrunc
|
||||||
clean: $(SUBDIRS)
|
mcopy -i $@ boot/stpdboot.sys ::/STPDBOOT.SYS
|
||||||
|
mcopy -i $@ kernel/vmstupid ::/VMSTUPID.SYS
|
||||||
|
|
||||||
|
.PHONY: clean
|
||||||
|
clean: $(SUBDIRS)
|
||||||
$(RM) $(TARGET) $(SYSROOTDIR)
|
$(RM) $(TARGET) $(SYSROOTDIR)
|
|
@ -1,22 +1,29 @@
|
||||||
AS = fasm
|
AS = fasm
|
||||||
RM = rm
|
RM = rm
|
||||||
|
|
||||||
TARGET = bootcode.bin
|
TARGET = bootsector.bin stpdboot.sys
|
||||||
|
|
||||||
SRCS = boot.asm \
|
STAGE0_SRCS = boot0.asm \
|
||||||
const.inc \
|
const.inc \
|
||||||
a20.inc
|
fat12.inc
|
||||||
|
|
||||||
.PHONY: all
|
STAGE1_SRCS = boot1.asm \
|
||||||
all: $(TARGET)
|
const.inc \
|
||||||
|
a20.inc
|
||||||
$(TARGET): $(SRCS)
|
|
||||||
$(AS) boot.asm $@
|
.PHONY: all
|
||||||
|
all: $(TARGET)
|
||||||
.PHONY: clean
|
|
||||||
clean:
|
bootsector.bin: $(STAGE0_SRCS)
|
||||||
$(RM) $(TARGET)
|
$(AS) boot0.asm $@
|
||||||
|
|
||||||
.PHONY: install
|
stpdboot.sys: $(STAGE1_SRCS)
|
||||||
install: $(TARGET)
|
$(AS) boot1.asm $@
|
||||||
@ mkdir -p $(DESTDIR)
|
|
||||||
|
.PHONY: clean
|
||||||
|
clean:
|
||||||
|
$(RM) $(TARGET)
|
||||||
|
|
||||||
|
.PHONY: install
|
||||||
|
install: $(TARGET)
|
||||||
|
@ mkdir -p $(DESTDIR)
|
||||||
|
|
2
boot/README.org
Normal file
2
boot/README.org
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
#+TITLE: StupidOS Bootloader
|
||||||
|
|
340
boot/a20.inc
340
boot/a20.inc
|
@ -1,171 +1,171 @@
|
||||||
; copy/pasted from https://wiki.osdev.org/A20_Line
|
; copy/pasted from https://wiki.osdev.org/A20_Line
|
||||||
; .... sorry I was lazy :x
|
; .... sorry I was lazy :x
|
||||||
|
|
||||||
a20_get_state:
|
a20_get_state:
|
||||||
pushf
|
pushf
|
||||||
push si
|
push si
|
||||||
push di
|
push di
|
||||||
push ds
|
push ds
|
||||||
push es
|
push es
|
||||||
|
|
||||||
cli
|
cli
|
||||||
|
|
||||||
xor ax, ax
|
xor ax, ax
|
||||||
mov ds, ax
|
mov ds, ax
|
||||||
mov si, 0x500
|
mov si, 0x500
|
||||||
|
|
||||||
not ax
|
not ax
|
||||||
mov es, ax
|
mov es, ax
|
||||||
mov di, 0x0510
|
mov di, 0x0510
|
||||||
|
|
||||||
mov al, [ds:si] ; save old values
|
mov al, [ds:si] ; save old values
|
||||||
mov byte [.BufferBelowMB], al
|
mov byte [.BufferBelowMB], al
|
||||||
mov al, [es:di]
|
mov al, [es:di]
|
||||||
mov byte [.BufferOverMB], al
|
mov byte [.BufferOverMB], al
|
||||||
|
|
||||||
mov ah, 1 ; check byte [0x00100500] == byte [0x0500]
|
mov ah, 1 ; check byte [0x00100500] == byte [0x0500]
|
||||||
mov byte [ds:si], 0
|
mov byte [ds:si], 0
|
||||||
mov byte [es:di], 1
|
mov byte [es:di], 1
|
||||||
mov al, [ds:si]
|
mov al, [ds:si]
|
||||||
cmp al, [es:di]
|
cmp al, [es:di]
|
||||||
jne .exit
|
jne .exit
|
||||||
dec ah
|
dec ah
|
||||||
.exit:
|
.exit:
|
||||||
mov al, [.BufferBelowMB]
|
mov al, [.BufferBelowMB]
|
||||||
mov [ds:si], al
|
mov [ds:si], al
|
||||||
mov al, [.BufferOverMB]
|
mov al, [.BufferOverMB]
|
||||||
mov [es:di], al
|
mov [es:di], al
|
||||||
shr ax, 8
|
shr ax, 8
|
||||||
sti
|
sti
|
||||||
pop es
|
pop es
|
||||||
pop ds
|
pop ds
|
||||||
pop di
|
pop di
|
||||||
pop si
|
pop si
|
||||||
popf
|
popf
|
||||||
ret
|
ret
|
||||||
|
|
||||||
.BufferBelowMB: db 0
|
.BufferBelowMB: db 0
|
||||||
.BufferOverMB db 0
|
.BufferOverMB db 0
|
||||||
|
|
||||||
|
|
||||||
a20_query_support:
|
a20_query_support:
|
||||||
push bx
|
push bx
|
||||||
clc
|
clc
|
||||||
|
|
||||||
mov ax, 0x2403
|
mov ax, 0x2403
|
||||||
int 0x15
|
int 0x15
|
||||||
jc .error
|
jc .error
|
||||||
|
|
||||||
test ah, ah
|
test ah, ah
|
||||||
jnz .error
|
jnz .error
|
||||||
|
|
||||||
mov ax, bx
|
mov ax, bx
|
||||||
pop bx
|
pop bx
|
||||||
ret
|
ret
|
||||||
.error:
|
.error:
|
||||||
stc
|
stc
|
||||||
pop bx
|
pop bx
|
||||||
ret
|
ret
|
||||||
|
|
||||||
a20_enable_keyboard_controller:
|
a20_enable_keyboard_controller:
|
||||||
cli
|
cli
|
||||||
|
|
||||||
call .wait_io1
|
call .wait_io1
|
||||||
mov al, 0xad
|
mov al, 0xad
|
||||||
out 0x64, al
|
out 0x64, al
|
||||||
|
|
||||||
call .wait_io1
|
call .wait_io1
|
||||||
mov al, 0xd0
|
mov al, 0xd0
|
||||||
out 0x64, al
|
out 0x64, al
|
||||||
|
|
||||||
call .wait_io2
|
call .wait_io2
|
||||||
in al, 0x60
|
in al, 0x60
|
||||||
push eax
|
push eax
|
||||||
|
|
||||||
call .wait_io1
|
call .wait_io1
|
||||||
mov al, 0xd1
|
mov al, 0xd1
|
||||||
out 0x64, al
|
out 0x64, al
|
||||||
|
|
||||||
call .wait_io1
|
call .wait_io1
|
||||||
pop eax
|
pop eax
|
||||||
or al, 2
|
or al, 2
|
||||||
out 0x60, al
|
out 0x60, al
|
||||||
|
|
||||||
call .wait_io1
|
call .wait_io1
|
||||||
mov al, 0xae
|
mov al, 0xae
|
||||||
out 0x64, al
|
out 0x64, al
|
||||||
|
|
||||||
call .wait_io1
|
call .wait_io1
|
||||||
sti
|
sti
|
||||||
ret
|
ret
|
||||||
.wait_io1:
|
.wait_io1:
|
||||||
in al, 0x64
|
in al, 0x64
|
||||||
test al, 2
|
test al, 2
|
||||||
jnz .wait_io1
|
jnz .wait_io1
|
||||||
ret
|
ret
|
||||||
.wait_io2:
|
.wait_io2:
|
||||||
in al, 0x64
|
in al, 0x64
|
||||||
test al, 1
|
test al, 1
|
||||||
jz .wait_io2
|
jz .wait_io2
|
||||||
ret
|
ret
|
||||||
|
|
||||||
; out:
|
; out:
|
||||||
; cf - set on error
|
; cf - set on error
|
||||||
a20_enable:
|
a20_enable:
|
||||||
clc ; clear cf
|
clc ; clear cf
|
||||||
pusha
|
pusha
|
||||||
mov bh, 0 ; clear bh
|
mov bh, 0 ; clear bh
|
||||||
|
|
||||||
call a20_get_state
|
call a20_get_state
|
||||||
jc .fast_gate
|
jc .fast_gate
|
||||||
|
|
||||||
test ax, ax
|
test ax, ax
|
||||||
jnz .done
|
jnz .done
|
||||||
|
|
||||||
call a20_query_support
|
call a20_query_support
|
||||||
mov bl, al
|
mov bl, al
|
||||||
test bl, 1 ; enable A20 using keyboard controller
|
test bl, 1 ; enable A20 using keyboard controller
|
||||||
jnz .keybord_controller
|
jnz .keybord_controller
|
||||||
|
|
||||||
test bl, 2 ; enable A20 using fast A20 gate
|
test bl, 2 ; enable A20 using fast A20 gate
|
||||||
jnz .fast_gate
|
jnz .fast_gate
|
||||||
.bios_int:
|
.bios_int:
|
||||||
mov ax, 0x2401
|
mov ax, 0x2401
|
||||||
int 0x15
|
int 0x15
|
||||||
jc .fast_gate
|
jc .fast_gate
|
||||||
test ah, ah
|
test ah, ah
|
||||||
jnz .failed
|
jnz .failed
|
||||||
call a20_get_state
|
call a20_get_state
|
||||||
test ax, ax
|
test ax, ax
|
||||||
jnz .done
|
jnz .done
|
||||||
.fast_gate:
|
.fast_gate:
|
||||||
in al, 0x92
|
in al, 0x92
|
||||||
test al, 2
|
test al, 2
|
||||||
jnz .done
|
jnz .done
|
||||||
|
|
||||||
or al, 2
|
or al, 2
|
||||||
and al, 0xfe
|
and al, 0xfe
|
||||||
out 0x92, al
|
out 0x92, al
|
||||||
|
|
||||||
call a20_get_state
|
call a20_get_state
|
||||||
test ax, ax
|
test ax, ax
|
||||||
jnz .done
|
jnz .done
|
||||||
|
|
||||||
test bh, bh ; test if there was an attempt using the keyboard controller
|
test bh, bh ; test if there was an attempt using the keyboard controller
|
||||||
jnz .failed
|
jnz .failed
|
||||||
.keybord_controller:
|
.keybord_controller:
|
||||||
call a20_enable_keyboard_controller
|
call a20_enable_keyboard_controller
|
||||||
call a20_get_state
|
call a20_get_state
|
||||||
test ax, ax
|
test ax, ax
|
||||||
jnz .done
|
jnz .done
|
||||||
|
|
||||||
mov bh, 1 ; flag enable attempt with keyboard controller
|
mov bh, 1 ; flag enable attempt with keyboard controller
|
||||||
|
|
||||||
test bl, 2
|
test bl, 2
|
||||||
jnz .fast_gate
|
jnz .fast_gate
|
||||||
jmp .failed
|
jmp .failed
|
||||||
.failed:
|
.failed:
|
||||||
stc
|
stc
|
||||||
.done:
|
.done:
|
||||||
popa
|
popa
|
||||||
ret
|
ret
|
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,8 +1,9 @@
|
||||||
|
CR = 0x0D
|
||||||
; -------- Address ----------
|
LF = 0x0A
|
||||||
STAGE0_BASE = 0x7C00
|
; -------- Address ----------
|
||||||
STAGE1_BASE = 0x1000
|
STAGE0_BASE = 0x7C00
|
||||||
DISK_BUFFER = 0x8000
|
STAGE1_BASE = 0x1000
|
||||||
KERNEL_PRELOAD = 0xF000
|
DISK_BUFFER = 0x8000
|
||||||
STACK_TOP = 0x7000
|
KERNEL_PRELOAD = 0xF000
|
||||||
|
STACK_TOP = 0x7000
|
||||||
|
|
||||||
|
|
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