essence-os/boot/x86/esfs-stage1.s

183 lines
2.9 KiB
ArmAsm

; This file is part of the Essence operating system.
; It is released under the terms of the MIT license -- see LICENSE.md.
; Written by: nakst.
[bits 16]
[org 0x7C00]
%define superblock 0x8000
%define temporary_load_buffer 0x9000
%define block_group_descriptor_table 0x10000
%define directory_load_location 0x1000
%define stage2_load_location 0x1000
%define inode_table_load_buffer 0x20000
%define magic_breakpoint xchg bx,bx
;%define magic_breakpoint
start:
; Setup segment registers
cli
mov ax,0
mov ds,ax
mov es,ax
mov fs,ax
mov gs,ax
mov ss,ax
mov sp,0x7C00
jmp 0x0:.continue
.continue:
sti
; Save the information passed from the MBR
mov [drive_number],dl
mov [partition_entry],si
mov [use_emu_read],dh
; Get drive parameters.
or dh,dh
jz .skip_params
mov ah,0x08
xor di,di
int 0x13
mov si,error_cannot_read_disk
jc error
and cx,63
mov [max_sectors],cx
inc dh
shr dx,8
mov [max_heads],dx
.skip_params:
; Print a startup message
mov si,startup_message
.loop:
lodsb
or al,al
jz .end
mov ah,0xE
int 0x10
jmp .loop
.end:
; Load the second stage
mov cx,15
mov eax,1
mov edi,stage2_load_location
call load_sectors
mov dl,[drive_number]
mov si,[partition_entry]
mov dh,[use_emu_read]
mov bx,[max_sectors]
mov cx,[max_heads]
jmp 0:stage2_load_location
load_sectors:
; Load CX sectors from sector EAX to buffer [EDI]. Returns end of buffer in EDI.
pusha
push edi
; Add the partition offset to EAX
mov bx,[partition_entry]
mov ebx,[bx + 8]
add eax,ebx
; Load 1 sector
mov [read_structure.lba],eax
mov ah,0x42
mov dl,[drive_number]
mov si,read_structure
cmp byte [use_emu_read],1
je .use_emu
int 0x13
jmp .done_read
.use_emu:
call load_sector_emu
.done_read:
; Check for error
mov si,error_cannot_read_disk
jc error
; Copy the data to its destination
pop edi
mov cx,0x200
mov eax,edi
shr eax,4
and eax,0xF000
mov es,ax
mov si,temporary_load_buffer
rep movsb
; Go to the next sector
popa
add edi,0x200
inc eax
loop load_sectors
ret
load_sector_emu:
mov di,[read_structure.lba]
xor ax,ax
mov es,ax
mov bx,0x9000
; Calculate cylinder and head.
mov ax,di
xor dx,dx
div word [max_sectors]
xor dx,dx
div word [max_heads]
push dx ; remainder - head
mov ch,al ; quotient - cylinder
shl ah,6
mov cl,ah
; Calculate sector.
mov ax,di
xor dx,dx
div word [max_sectors]
inc dx
or cl,dl
; Load the sector.
pop dx
mov dh,dl
mov dl,[drive_number]
mov ax,0x0201
int 0x13
ret
error:
; Print an error message
lodsb
or al,al
jz .break
mov ah,0xE
int 0x10
jmp error
; Break indefinitely
.break:
cli
hlt
startup_message: db "Booting operating system...",10,13,0
drive_number: db 0
use_emu_read: db 0
partition_entry: dw 0
max_sectors: dw 0
max_heads: dw 0
read_structure: ; Data for the extended read calls
dw 0x10
dw 1
dd temporary_load_buffer
.lba: dq 0
error_cannot_read_disk: db "Error: The disk could not be read. (S1)",0
times (0x200 - ($-$$)) nop