mirror of
https://github.com/Tom-on64/kern.git
synced 2026-11-03 18:22:22 +00:00
168 lines
3.8 KiB
ArmAsm
168 lines
3.8 KiB
ArmAsm
[bits 16]
|
|
[org 0x7c00]
|
|
|
|
%define SUPERBLOCK 0x8c00
|
|
%define FIRST_INODE_BLOCK (SUPERBLOCK) + 18
|
|
%define STAGE3_INODE 0xb000 + (2 * 64)
|
|
%define EXTENT0 (STAGE3_INODE) + 14 ; Offset of extent[0] in inode_t
|
|
|
|
start:
|
|
xor ax, ax
|
|
mov es, ax
|
|
mov ds, ax
|
|
|
|
mov byte [driveNum], dl
|
|
|
|
; Clear screen
|
|
mov ax, 0x03
|
|
int 0x10
|
|
|
|
;; Read in the boot block and the superblock to memory for 2nd stage bootloader
|
|
mov al, 15 ; 8 - 1 for boot block - bootsector & 8 for super block
|
|
mov bl, al
|
|
dec bl ; Number of sectors - 1
|
|
mov di, 0x7E00 ; Destination 0x7c00-0x8c00 = boot block, 0x8c00-0x9c00 = superblock
|
|
|
|
mov dx, 0x1F6 ; flags
|
|
mov al, 0xE0 ; 0b0111 0000, bits: 0-3 = LBA bits 24-27, 4 = drive, 5 = always set, 6 = set for LBA, 7 = always set
|
|
out dx, al
|
|
|
|
mov dx, 0x1F2 ; Sector count port
|
|
mov al, 15 ; number of sectors to read
|
|
out dx, al
|
|
|
|
inc dx ; 0x1F3 - LBA low
|
|
mov al, 1 ; LBA 1 = 2nd disk sector (0-based), bits 0-7 of LBA
|
|
out dx, al
|
|
|
|
inc dx ; 0x1F4 - LBA mid
|
|
xor ax, ax ; bits 8-15 of LBA
|
|
out dx, al
|
|
|
|
inc dx ; 0x1F5 - LBA high
|
|
; xor ax, ax ; bits 16-23 of LBA
|
|
out dx, al
|
|
|
|
inc dx
|
|
inc dx ; 0x1F7 - Command port
|
|
mov al, 0x20 ; Read with retry
|
|
out dx, al
|
|
|
|
call loadSectorLoop
|
|
|
|
;; Parse superblock for first inode block, offset to reserved bootloader
|
|
|
|
;; Read first inode block to memory
|
|
;; Each disk block is 4KB or 8 sectors of 512 bytes
|
|
imul cx, [FIRST_INODE_BLOCK], 8 ; CX = disk sector/LBA of first inode block
|
|
|
|
mov bl, 7 ; 8 sectors for a block - 1
|
|
mov di, 0xb000 ; Address to read into, first inode block = 0xB000-0xC000
|
|
|
|
mov dx, 0x1F6 ; flags
|
|
mov al, 0xE0
|
|
out dx, al
|
|
|
|
mov dx, 0x1F2
|
|
mov al, 8
|
|
out dx, al
|
|
|
|
inc dx
|
|
mov al, cl
|
|
out dx, al
|
|
|
|
inc dx
|
|
mov al, ch
|
|
out dx, al
|
|
|
|
inc dx
|
|
xor ax, ax
|
|
out dx, al
|
|
|
|
inc dx
|
|
inc dx
|
|
mov al, 0x20
|
|
out dx, al
|
|
|
|
call loadSectorLoop
|
|
|
|
;; Read boot loader inode to memory
|
|
;; inode 2, each inode is 64 bytes in size
|
|
imul ecx, [EXTENT0], 8 ; first_block translated to disk sector/LBA
|
|
imul ebx, [EXTENT0+4], 8 ; length_blocks translated to disk sectors/LBAs
|
|
|
|
mov dx, 0x1F2
|
|
mov al, bl
|
|
out dx, al
|
|
|
|
inc dx
|
|
mov al, cl
|
|
out dx, al
|
|
|
|
inc dx
|
|
mov al, ch
|
|
out dx, al
|
|
|
|
inc dx
|
|
shr ecx, 16
|
|
mov al, cl
|
|
out dx, al
|
|
|
|
inc dx
|
|
and ch, 0x0F
|
|
mov al, ch
|
|
or al, 0xE0
|
|
out dx, al
|
|
|
|
inc dx
|
|
mov al, 0x20
|
|
out dx, al
|
|
|
|
dec bl
|
|
mov ax, 0x5000
|
|
mov es, ax
|
|
xor di, di
|
|
|
|
call loadSectorLoop
|
|
|
|
xor ax, ax
|
|
mov es, ax ; ES = 0x0000
|
|
|
|
;; Jump to 2nd stage bootloader here, does not return
|
|
mov dl, [driveNum]
|
|
jmp 0x0000:0x7E00
|
|
|
|
;; Poll status port after reading 1 sector
|
|
loadSectorLoop:
|
|
in al, dx ; Status register (reading port 1F7h)
|
|
test al, 8 ; Sector buffer requires servicing
|
|
je loadSectorLoop ; Keep trying until sector buffer is ready
|
|
|
|
mov cx, 256 ; # of words to read for 1 sector
|
|
mov dx, 0x1F0 ; Data port, reading
|
|
rep insw ; Read bytes from DX port # into DI, CX # of times
|
|
|
|
;; 400ns delay - Read alternate status register
|
|
mov dx, 0x3F6
|
|
in al, dx
|
|
in al, dx
|
|
in al, dx
|
|
in al, dx
|
|
|
|
cmp bl, 0 ; Sector # to still read
|
|
je .return
|
|
|
|
dec bl
|
|
mov dx, 0x1F7
|
|
jmp loadSectorLoop
|
|
.return:
|
|
ret
|
|
|
|
;; VARIABLES
|
|
driveNum: db 0
|
|
|
|
;; Boot sector magic
|
|
times 510-($-$$) db 0 ; Padding
|
|
dw 0xaa55
|
|
|