Clean-up and conveniance for mbr and loader

This commit is contained in:
Adrien Bourmault 2018-12-22 23:58:57 +01:00
parent a805431f7c
commit cb3e4fd15d
3 changed files with 322 additions and 0 deletions

88
src/boot/loader16.inc Normal file
View File

@ -0,0 +1,88 @@
;=----------------------------------------------------------------------------=;
; GNU GPL OS/K ;
; ;
; Authors: spectral` ;
; NeoX ;
; ;
; Desc: Kernel (second stage) Loader for OS/K INCLUDED FUNCTIONS ;
; (x86_64 architecture only) ;
;=----------------------------------------------------------------------------=;
[BITS 16]
disable_cursor:
pushf
push eax
push edx
mov dx, 0x3D4
mov al, 0xA ; low cursor shape register
out dx, al
inc dx
mov al, 0x20 ; bits 6-7 unused, bit 5 disables the cursor, bits 0-4 control the cursor shape
out dx, al
pop edx
pop eax
popf
ret
get_dimensions:
push eax
push ebx
mov ah, 0x0F
int 0x10
mov [VGA_HEIGHT], ah
mov [VIDEO_MODE], al
pop ebx
pop eax
ret
Is64bits:
;-----------------------------------------------------------------------;
; Checks if the CPU is compatible with 64-bits operating systems ;
; If the 21th bit of the eax register is set, then CPUID is supported ;
; We then test CPUID's result to see if long mode is supported ;
;-----------------------------------------------------------------------;
pushfd ; recovering the flags in eax
pop eax
mov ecx, eax
xor eax, 0x200000
push eax
popfd
pushfd
pop eax
xor eax, ecx
shr eax, 21
and eax, 1 ; magical spell of murta
push ecx
popfd
test eax, eax
jz .NonCompat ; if (CPUID non supporté) goto NonCompat
mov eax, 0x80000000
cpuid
cmp eax, 0x80000001
jb .NonCompat ; if (eax <= 0x80000001) goto NonCompat
mov eax, 0x80000001
cpuid
test edx, 1 << 29
jz .NonCompat ; if (edx != 1 << 29) goto NonCompat
ret ; back to mbr.s
.NonCompat:
stc
ret
PrintB:
;---------------------------------------------------;
; Print out a simple string. ;
; ;
; Expects: DS:SI = String to print ;
; ;
; Returns: None ;
; ;
;---------------------------------------------------;
lodsb ; Load byte from ds:si to al
or al, al ; If al is empty stop looping
jz .done ; Done looping and return
mov ah, 0x0e ; Teletype output
int 0x10 ; Video interupt
jmp PrintB ; Loop untill string is null
.done:
ret

74
src/boot/loader64.inc Normal file
View File

@ -0,0 +1,74 @@
;=----------------------------------------------------------------------------=;
; GNU GPL OS/K ;
; ;
; Authors: spectral` ;
; NeoX ;
; ;
; Desc: Kernel (second stage) Loader for OS/K INCLUDED FUNCTIONS ;
; (x86_64 architecture only) ;
;=----------------------------------------------------------------------------=;
[BITS 64]
clear:
;-----------------------------------------------------------------------;
; x64/LM Clear Text Screen Function ;
;-----------------------------------------------------------------------;
mov qword [NextTRAM], TRAM
mov edi, TRAM
push rsi
push rdi
push rcx
mov ah, 0
mov al, 0
mov rcx, 0x4000 ; traditionnal value
rep stosw ; fill screen with al while cx > 0
pop rcx
pop rsi
pop rdi
ret
write:
;-----------------------------------------------------------------------;
; x64/LM Text Printing Functions ;
; bl : color code ;
; esi : string address ;
;-----------------------------------------------------------------------;
mov edi, [NextTRAM] ;TRAM ADDRESS
push rsi
push rdi
.pLoop:
lodsb
cmp al, 0 ; while @al, i.e. while we're not hitting '\0'
je .pEnd
cmp al, 0x0A ; LF
je .lf
cmp al, 0x0D ; CR
je .cr
stosb ; text subpixel
mov al, bl
stosb ; color subpixel
add qword [NextTRAM], 0x2 ; Cursor moving
add qword [VGA_X], 0x2 ; coord + 2 because 2 subpixels
jmp .pLoop
.pEnd:
pop rdi
pop rsi
ret
.lf:
mov rax, [VGA_HEIGHT64]
add [NextTRAM], rax ; Cursor moving
add [NextTRAM], rax
add edi, eax ; Address moving
add edi, eax
jmp .pLoop
.cr:
push rax
mov rax, qword [VGA_X]
sub qword [NextTRAM], rax ; pos = X + Y * VGA_HEIGHT64. Donc pos - X = début de ligne
sub edi, edx
mov qword [VGA_X], 0
pop rax
jmp .pLoop
.scroll:
; XXX ;
jmp .pLoop

160
src/boot/mbr.inc Normal file
View File

@ -0,0 +1,160 @@
;=----------------------------------------------------------------------------=;
; GNU GPL OS/K ;
; ;
; Authors: spectral` ;
; NeoX ;
; ;
; Desc: Bootsector for OS/K INCLUDED FUNCTIONS ;
; (x86_64 architecture only) ;
;=----------------------------------------------------------------------------=;
read_clusters:
;---------------------------------------------------;
; Read file clusters, starting at the given cluster,;
; expects FAT to be loaded into the disk buffer. ;
; Please note that this may allocate up to 128KB ;
; of ram. ;
; ;
; Expects: AX = Starting cluster ;
; ES:DI = Location to load clusters ;
; ;
; Returns: None ;
; ;
;---------------------------------------------------;
pusha
push es
.cluster_loop:
xor bh, bh
xor dx, dx
push ax ; Get the cluster start = (cluster - 2) * sectorsPerCluster + UserData
sub ax, 2 ; Subtract 2
mov bl, byte [sectorsPerCluster] ; Sectors per cluster is a byte value
mul bx ; multiply (cluster - 2) * sectorsPerCluster
add ax, word [UserData] ; add the UserData
xor ch, ch
mov cl, byte [sectorsPerCluster] ; Sectors to read
call read_sectors ; Read the sectors
pop ax ; Current cluster number
xor dx, dx
;; Calculate next sector for FAT16 (cluster * 2)
mov bx, 2 ; Multiply the cluster by two (cluster is in ax)
mul bx
;; Load sector in RAM
push ds
push si
mov si, BUFFER_SEG
mov ds, si ; Temporarly set ds:si to the FAT buffer
mov si, BUFFER_OFF
add si, ax ; Point to the next cluster in the FAT entry
mov ax, word [ds:si] ; Load ax to the next cluster in FAT
pop si
pop ds
;; Next
cmp ax, 0xfff8 ; Check if we are at the end of the file?
jae .done
add di, 512 ; Add to the pointer offset
jnc .cluster_loop
;; Correct the buffer because an error will occur if the buffer in memory
mov dx, es ; overlaps a 64k page boundry, when di overflows
add dh, 0x10 ; it will trigger the carry flag, so correct
mov es, dx ; extra segment by 0x1000
jmp .cluster_loop ; Load the next file cluster
.done:
pop es
popa
ret
read_sectors:
;---------------------------------------------------;
; Read sectors starting at a given sector by ;
; the given times and load into a buffer. Please ;
; note that this may allocate up to 128KB of ram. ;
; ;
; Expects: AX = Starting sector ;
; CX = Number of sectors to read ;
; ES:DI = Location to load sectors ;
; ;
; Returns: None ;
; ;
;---------------------------------------------------;
pusha
push es
mov bx, di ; Convert es:di to es:bx for int 13h
.sector_loop:
push ax
push cx
xor dx, dx
div word [sectorsPerTrack] ; Divide the lba (value in ax) by sectorsPerTrack
mov cx, dx ; Save the absolute sector value
inc cx
xor dx, dx ; Divide by the number of heads
div word [heads] ; to get absolute head and track values
mov dh, dl ; Move the absolute head into dh
mov ch, al ; Low 8 bits of absolute track
shl ah, 1 ; High 2 bits of absolute track
shl ah, 1
shl ah, 1
shl ah, 1
shl ah, 1
shl ah, 1
or cl, ah ; Now cx is set with respective track and sector numbers
mov dl, byte [Bootdrv] ; Set correct Bootdrv for int 13h
mov di, 5 ; Try five times to read the sector because i love 5
.attempt_read:
mov ax, 0x0201 ; Read Sectors func of int 13h, read one sector
int 0x13 ; Call int 13h (BIOS disk I/O)
jnc .read_ok ; If no carry set, the sector has been read
xor ah, ah ; Reset Bootdrv func of int 13h
int 0x13 ; Call int 13h (BIOS disk I/O)
dec di ; Decrease read attempt counter
jnz .attempt_read ; Try to read the sector again
mov si, DiskError ; Error reading the disk :/
call print
jmp reboot
.read_ok:
pop cx
pop ax
inc ax ; Increase the next sector to read
add bx, word [bytesPerSector] ; Add to the buffer address for the next sector
jnc .next_sector
;; Fixing buffer because an error will occur if the buffer in memory
mov dx, es ; overlaps a 64k page boundry, when bx overflows
add dh, 0x10 ; it will trigger the carry flag, so correct
mov es, dx ; es segment by 0x1000
.next_sector:
loop .sector_loop
pop es
popa
ret
print:
;---------------------------------------------------;
; Print out a simple string. ;
; ;
; Expects: DS:SI = String to print ;
; ;
; Returns: None ;
; ;
;---------------------------------------------------;
lodsb ; Load byte from ds:si to al
or al, al ; If al is empty stop looping
jz .done ; Done looping and return
mov ah, 0x0e ; Teletype output
int 0x10 ; Video interupt
jmp print ; Loop untill string is null
.done:
ret
reboot:
xor ax, ax
int 0x16 ; Get a single keypress
mov ah, 0x0e ; Teletype output
mov al, 0x0d ; Carriage return
int 0x10 ; Video interupt
mov al, 0x0a ; Line feed
int 0x10 ; Video interupt
mov al, 0x0a ; Line feed
int 0x10 ; Video interupt
xor ax, ax
int 0x19 ; Reboot the system