Clean-up and conveniance for mbr and loader
This commit is contained in:
parent
a805431f7c
commit
cb3e4fd15d
|
@ -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
|
|
@ -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
|
|
@ -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
|
Loading…
Reference in New Issue