os-k/src/boot/loader.s

374 lines
12 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) ;
;=----------------------------------------------------------------------------=;
[ORG 0x1000]
pop word [Bootdrv]
jmp main
;; DATA
%define TRAM 0x0B8000 ; [T]ext[RAM]
%define VRAM 0x0A0000 ; [V]ideo[RAM]
Bootdrv db 0x00
VGA_HEIGHT dq 0
VIDEO_MODE dw 0
;; GDT WITH DOC
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:
[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
;-----------------------------------------------------------------------;
; 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
;; INCLUDES
%include "boot/common.inc" ; for PrintB
main:
;; compatibility check
mov si, Init
call PrintB
pop si
call Is64bits
jc ErrorNo64
push si
mov si, Pass
call PrintB
;; 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
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
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
add eax, 0x1000
loop .make_page_entries
;; pointing pml4
mov eax, 0x70000 ; Bass address of PML4
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
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
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:
jmp .pLoop
;; DATA
txt db 0x09, " Switching to Long Mode... OK", 0x0A, 0x0D, 0
Init 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
NextTRAM dq 0x0B8AA0 ; 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
;; NOTIFYING
mov bl, 0x0A
mov esi, txt
call write
mov bl, 0x0B
mov esi, msg
call write
mov bl, 0x0C
mov esi, msg
call write
mov bl, 0x0D
mov esi, msg
call write
mov bl, 0x0E
mov esi, msg
call write
;call KERNEL
jmp $
[BITS 16]
ErrorNo64:
mov si, NoLongMode
call PrintB
Die:
cli
hlt ; die nooooow
retf
times 1024-($-$$) db 144
KERNEL: