os-k/src/boot/loader.s

420 lines
16 KiB
ArmAsm
Raw Normal View History

;=----------------------------------------------------------------------------=;
; GNU GPL OS/K ;
; ;
; Authors: spectral` ;
; NeoX ;
; ;
; Desc: Kernel (second stage) Loader for OS/K ;
; (x86_64 architecture only) ;
;=----------------------------------------------------------------------------=;
2018-12-21 23:57:41 +01:00
%define TRAM 0x0B8000 ; [T]ext[RAM]
%define VRAM 0x0A0000 ; [V]ideo[RAM]
2018-12-21 23:57:41 +01:00
[BITS 16]
[ORG 0x1000]
2018-12-21 23:57:41 +01:00
mov ax, cs
mov ds, ax
mov es, ax
mov [Bootdrv], dl
jmp 0x0000:main
;; DATA
2018-12-21 23:57:41 +01:00
Bootdrv db 0
VGA_HEIGHT dq 0
VIDEO_MODE dw 0
;; GDT WITH DOC
2018-12-21 23:57:41 +01:00
GDT64:
NULL_SELECTOR: ;; null selector within 64 bits
dw GDT_LENGTH ; limit of GDT
dw GDT64 ; linear address of GDT
dd 0x0
CODE_SELECTOR: ;; 32-bit code selector (ring 0)
dw 0x0FFFF ; Segment Limit 15:00
db 0x0, 0x0, 0x0 ; Base Address 23:00
db 10011010b ; |7|6|5|4|3|2|1|0|
; | | | | | | | `----- 1 when segment used.
; | | | | | | `------ 1 when writable.
; | | | | | `------- 1 if "conformant". Don't know what is it... spectral ? xD
; | | | | `-------- 1 always
; | | | `--------- 1 for segment descriptor, 0 for system descriptor
; | | `---------- DPL !!! 0 for ring 0
; | `----------- DPL (2/2)
; `------------ 1 if in physical memory, 0 if page fault
db 11001111b ; |7|6|5|4|3|2|1|0|
; | | | | | | | `----- Limit 16
; | | | | | | `------ Limit 17
; | | | | | `------- Limit 18
; | | | | `-------- Limit 19
; | | | `--------- available for use
; | | `---------- 0 always
; | `----------- size of data. 1 for 32bits
; `------------ 0 if limit is in Bytes, 1 if it's in pages (4ko)
db 0x0 ; Base Address 31:24
DATA_SELECTOR: ;; flat data selector (ring 0)
dw 0x0FFFF ; Segment Limit 15:00
db 0x0, 0x0, 0x0 ; Base Address 23:00
db 10010010b ; |7|6|5|4|3|2|1|0|
; | | | | | | | `----- 1 when segment used.
; | | | | | | `------ 1 when writable.
; | | | | | `------- expansion direction. 1 for a LIFO
; | | | | `-------- 1 always
; | | | `--------- 1 for segment descriptor, 0 for system descriptor
; | | `---------- DPL !!! 0 for ring 0
; | `----------- DPL (2/2)
; `------------ 1 if in physical memory, 0 if page fault
db 10001111b ; |7|6|5|4|3|2|1|0|
; | | | | | | | `----- Limit 16
; | | | | | | `------ Limit 17
; | | | | | `------- Limit 18
; | | | | `-------- Limit 19
; | | | `--------- available for use
; | | `---------- 0 always
; | `----------- size of data. 1 for 32bits
; `------------ 0 if limit is in Bytes, 1 if it's in pages (4ko)
db 0x0 ; Base Address 31:24
LONG_SELECTOR: ;; 64-bit code selector (ring 0)
dw 0x0FFFF ; Segment Limit 15:00
db 0x0, 0x0, 0x0 ; Base Address 23:00
db 10011010b ; |7|6|5|4|3|2|1|0|
; | | | | | | | `----- 1 when segment used.
; | | | | | | `------ 1 when writable.
; | | | | | `------- 1 if "conformant". Don't know what is it... spectral ? xD
; | | | | `-------- 1 always
; | | | `--------- 1 for segment descriptor, 0 for system descriptor
; | | `---------- DPL !!! 0 for ring 0
; | `----------- DPL (2/2)
; `------------ 1 if in physical memory, 0 if page fault
db 10101111b ; |7|6|5|4|3|2|1|0|
; | | | | | | | `----- Limit 16
; | | | | | | `------ Limit 17
; | | | | | `------- Limit 18
; | | | | `-------- Limit 19
; | | | `--------- available for use
; | | `---------- 0 always
; | `----------- size of data. 1 for 32bits
; `------------ 0 if limit is in Bytes, 1 if it's in pages (4ko)
db 0x0 ; Base Address 31:24
GDT_LENGTH:
disable_cursor:
2018-12-21 23:57:41 +01:00
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
2018-12-21 23:57:41 +01:00
;-----------------------------------------------------------------------;
; 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 ;
;-----------------------------------------------------------------------;
Is64bits:
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
2018-12-21 23:57:41 +01:00
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
2018-12-21 23:57:41 +01:00
main:
;; compatibility check
mov si, Init
call PrintB
pop si
call Is64bits
jc ErrorNo64
push si
mov si, Pass
call PrintB
2018-12-21 23:57:41 +01:00
;; Enabling A20
mov si, EnA20
call PrintB
pop si
in al, 0x92
or al, 2
out 0x92, al
push si
mov si, Pass
call PrintB
;; DISABLING CURSOR BLINKING AND GETTING INFOS
2018-12-21 23:57:41 +01:00
call get_dimensions
call disable_cursor
;;GO GDT64
cli ; disable interrupts
lgdt [GDT64]
;; ACTIVATE PROTECTED MODE
mov eax, cr0
or al, 1b ; PE = 1
mov cr0, eax
;; DISABLE PAGING
mov eax, cr0
and eax, 0x7FFFFFFF ; PG = 0
; |0|111111111111111111111111111111
; |
; `------ Paging bit
mov cr0, eax
2018-12-21 23:57:41 +01:00
push dword [VIDEO_MODE]
push dword [VGA_HEIGHT]
jmp (CODE_SELECTOR-GDT64):main32
[BITS 32]
VIDEO_MODE32 dw 0
VGA_HEIGHT32 dw 0
main32:
pop dword [VGA_HEIGHT32]
pop dword [VIDEO_MODE32]
;; INITIALIZE PROTECTED MODE SEGMENT REGISTERS
mov ax, DATA_SELECTOR-GDT64
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
mov ss, ax
;; ACTIVATE PHYSICAL ADRESS EXTENSION
mov eax, cr4
or eax, 100000b ; PAE = 1 = 4 Mo / page. 0 = 4 Ko
mov cr4, eax
;;cleanup
mov edi, 0x70000
mov ecx, 0x10000
xor eax, eax
rep stosd
;;formatting
mov dword [0x70000], 0x71000 + 7 ; first PDP table
mov dword [0x71000], 0x72000 + 7 ; first page directory
mov dword [0x72000], 0x73000 + 7 ; first page table
mov edi, 0x73000 ; address of first page table
mov eax, 7
mov ecx, 256 ; number of pages to map (1 MB)
.make_page_entries:
stosd
add edi, 4
2018-12-21 23:57:41 +01:00
add eax, 0x1000
loop .make_page_entries
;; pointing pml4
mov eax, 0x70000 ; Bass address of PML4
2018-12-21 23:57:41 +01:00
mov cr3, eax ; load page-map level-4 base
;; ACTIVATE LONG MODE
mov ecx, 0xC0000080 ; address of MSR
rdmsr ; read MSR
or eax, 100000000b ; LME = 1. (Long Mode Enable)
wrmsr ; write MSR
;; ACTIVATE PAGING
2018-12-21 23:57:41 +01:00
mov eax, cr0
or eax, 0x80000000 ; make bit 31 (PG = Paging) to 1 :
; |1|000000000000000000000000000000
; |
; `------ Paging bit
mov cr0, eax
push dword 0
push dword [VIDEO_MODE]
push dword 0
push dword [VGA_HEIGHT]
jmp (LONG_SELECTOR-GDT64):main64
[BITS 64]
;; FUNCTIONS
2018-12-21 23:57:41 +01:00
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
2018-12-21 23:57:41 +01:00
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:
jmp .pLoop
2018-12-21 23:57:41 +01:00
;; DATA
txt db 0x09, " Switching to Long Mode... OK", 0x0A, 0x0D, 0
2018-12-21 23:57:41 +01:00
Init db "Booting OS/K !", 0x0D, 0x0A, 0x0D, 0x0A, 0x09, " Checking CPUID...",0
Reinit db "Booting OS/K !", 0x0D, 0x0A, 0x0D, 0x0A, 0
CPUIDD db 0x09, " Checking CPUID...", 0
EnA20 db 0x09, " Enabling A20 line...", 0
NoLongMode db 0x0A, 0x0D, "ERROR : Your computer is not designed for x64 OS", 0
Pass db " OK", 0x0A, 0x0D, 0
2018-12-21 23:57:41 +01:00
NextTRAM dq 0x0B8000 ; Last position of cursor
VIDEO_MODE64 dq 0
VGA_HEIGHT64 dq 0
VGA_X dq 0x0
msg db "The system is now in x64 mode. Is this not beautiful ?", 0x0A, 0x0D, 0
main64:
pop qword [VGA_HEIGHT64]
pop qword [VIDEO_MODE64]
;; INITIALIZE STACK
mov rsp, 0x9F000
2018-12-21 23:57:41 +01:00
call clear
2018-12-21 23:57:41 +01:00
;; Printing
mov bl, 0x0B
2018-12-21 23:57:41 +01:00
mov esi, Reinit
call write
2018-12-21 23:57:41 +01:00
mov bl, 0x0F
mov esi, CPUIDD
call write
2018-12-21 23:57:41 +01:00
mov bl, 0x0A
mov esi, Pass
call write
mov bl, 0x0F
mov esi, EnA20
call write
mov bl, 0x0A
mov esi, Pass
call write
mov bl, 0x0A
mov esi, txt
call write
2018-12-21 23:57:41 +01:00
mov bl, 0x0D
mov esi, msg
call write
2018-12-21 23:57:41 +01:00
jmp Die
[BITS 16]
ErrorNo64:
mov si, NoLongMode
call PrintB
Die:
cli
hlt ; die nooooow
2018-12-22 10:37:05 +01:00
retf ; For conveniance
KERNEL: