os-k/src/boot/mbr.s

189 lines
6.7 KiB
ArmAsm
Raw Normal View History

;=----------------------------------------------------------------------------=;
; GNU GPL OS/K ;
; ;
; Authors: spectral` ;
; NeoX ;
; ;
; Desc: Master Boot Record for OS/K ;
; (x86_64 architecture only) ;
;=----------------------------------------------------------------------------=;
2018-12-21 14:17:06 +01:00
%define SECOND_STAGE 0x100 ;about to change
[BITS 16] ; real mode
[ORG 0x7C00] ; address where the BIOS/UEFI CSM is loading us
jmp short Start
;; File Allocation Table Disk Identifiers
nop
OEM_ID db "GPL OS/K"
BytesPerSector dw 0x0200
SectorsPerCluster db 0x08
ReservedSectors dw 0x0020
TotalFATs db 0x02
MaxRootEntries dw 0x0000
NumberOfSectors dw 0x0000
MediaDescriptor db 0xF8
SectorsPerFAT dw 0x0000
SectorsPerTrack dw 0x003D
SectorsPerHead dw 0x0002
HiddenSectors dd 0x00000000
TotalSectors dd 0x00FE3B1F
BigSectorsPerFAT dd 0x00000778
Flags dw 0x0000
FSVersion dw 0x0000
RootDirectoryStart dd 0x00000002
FSInfoSector dw 0x0001
BackupBootSector dw 0x0006
TIMES 12 DB 0 ; going to the next offset
DriveNumber db 0x00
ReservedByte db 0x00
Signature db 0x29
VolumeID dd 0xFFFFFFFF
VolumeLabel db "OS/K BDISK "
SystemID db "FAT32 "
Start:
;; saving registers for future
pushad
pushfd
pushf
;; dl contains the boot drive. Saving it.
mov [Bootdrv], dl
;; hello world
push si
mov si, Starting
call PrintB
;; SWITCHING TO LOADER
mov si, Switch
call PrintB
pop si
mov cx, word [SectorsPerCluster] ; size of a cluster in sectors is stored in cx
; computing location of the begining of the Data area and store in ax
mov al, byte [TotalFATs] ; Total number of FATs
mul word [BigSectorsPerFAT] ; Number of sectors for a FAT
add ax, word [ReservedSectors] ; Find the start of the Data area
mov word [Datasector], ax ; Store the begining of the Data area
; reading 1st data cluster into memory (7C00:0200)
mov ax, word [RootDirectoryStart]
call ClusterLBA
mov bx, 0x0200 ; copy 1st data cluter above bootcode
call ReadSectors
; Point Index register to 1st File Entry
mov di, 0x0200 + 0x20
;Point to the offset where the file location information contains
mov dx, word [di + 0x001A]
mov word [Cluster], dx
;Set up the segments where the loader needs to be loaded ;)
mov ax, 0100h ; set ES:BX = 0100:0000
mov es, ax
xor bx, bx
;Read the cluster which contains the loader
mov cx, 0x0008
mov ax, word [Cluster]
call ClusterLBA
call ReadSectors
;Jump to the location where the loader was loded
popf
popfd
popad
push word [Bootdrv]
call dword SECOND_STAGE:0000
; Exiting
mov ah, 0x00
int 0x19 ; warm boot computer
;;END OF MBR
;;----------------------------------------------------------------------------;;
;; DATA
Starting db 0x0A, 0x0D, 0x07, "GNU GPL OS/K", 0x0A, 0x0D, 0x0A, 0x0D, 0
Switch db 0x09, " Loading Second Stage", 0
AbsoluteSector db 0x00
AbsoluteHead db 0x00
AbsoluteTrack db 0x00
Cluster dw 0x0000
Datasector dw 0x0000
Bootdrv db 0x00
;; INCLUDES
%include "boot/common.inc" ; for PrintB
;; INTERNAL FUNCTIONS
;-------------------------------------------------------------------;
; loading second stage loader (loader.s) ;
;-------------------------------------------------------------------;
ReadSectors:
.main:
mov di, 0x0005 ; five retries for error
.sectorloop:
push ax
push bx
push cx
call LbaToChs
mov ah, 0x02 ; BIOS read sector
mov al, 0x01 ; read one sector
mov ch, BYTE [AbsoluteTrack] ; track
mov cl, BYTE [AbsoluteSector] ; sector
mov dh, BYTE [AbsoluteHead] ; head
int 0x13 ; invoke BIOS
jnc .success ; test for read error
xor ax, ax ; BIOS reset disk
int 0x13 ; invoke BIOS
dec di ; decrement error counter
pop cx
pop bx
pop ax
jnz .sectorloop ; attempt to read again
int 0x18
.success:
pop cx
pop bx
pop ax
add bx, WORD [BytesPerSector] ; queue next buffer
inc ax ; queue next sector
loop .main ; read next sector
ret
;-------------------------------------------------------------------;
; Converts LBA Adresses to CHS ;
;-------------------------------------------------------------------;
LbaToChs:
xor dx, dx ; prepare dx:ax for operation
div WORD [SectorsPerTrack] ; calculate
inc dl ; adjust for sector 0
mov BYTE [AbsoluteSector], dl
xor dx, dx ; prepare dx:ax for operation
div WORD [SectorsPerHead] ; calculate
mov BYTE [AbsoluteHead], dl
mov BYTE [AbsoluteTrack], al
ret
;-------------------------------------------------------------------;
; Converts FAT Adresses to LBA ;
;-------------------------------------------------------------------;
ClusterLBA:
sub ax, 0x0002 ; zero base cluster number
xor cx, cx
mov cl, BYTE [SectorsPerCluster] ; convert byte to word
mul cx
add ax, WORD [Datasector] ; base data sector
ret
End:
times 510-($-$$) db 144 ; NOP until 510
dw 0xAA55 ; magic word