2018-12-20 18:03:39 +01:00
|
|
|
;=----------------------------------------------------------------------------=;
|
|
|
|
; 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-20 18:03:39 +01:00
|
|
|
|
2018-12-21 23:57:41 +01:00
|
|
|
[BITS 16]
|
2018-12-20 18:03:39 +01:00
|
|
|
[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
|
2018-12-20 18:03:39 +01:00
|
|
|
|
|
|
|
;; DATA
|
2018-12-21 23:57:41 +01:00
|
|
|
|
|
|
|
Bootdrv db 0
|
2018-12-20 18:03:39 +01:00
|
|
|
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:
|
2018-12-20 18:03:39 +01:00
|
|
|
|
|
|
|
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
|
|
|
|
|
2018-12-20 18:03:39 +01:00
|
|
|
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
|
|
|
|
2018-12-20 18:19:51 +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-20 18:03:39 +01:00
|
|
|
|
2018-12-21 23:57:41 +01:00
|
|
|
main:
|
|
|
|
;; compatibility check
|
2018-12-20 18:19:51 +01:00
|
|
|
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
|
2018-12-20 18:19:51 +01:00
|
|
|
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
|
2018-12-20 18:03:39 +01:00
|
|
|
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
|
|
|
|
2018-12-20 18:03:39 +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
|
2018-12-20 18:03:39 +01:00
|
|
|
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
|
2018-12-20 18:03:39 +01:00
|
|
|
|
|
|
|
;; 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
|
2018-12-20 18:03:39 +01:00
|
|
|
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
|
2018-12-20 18:03:39 +01:00
|
|
|
|
|
|
|
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
|
2018-12-20 18:03:39 +01:00
|
|
|
.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
|
2018-12-20 18:03:39 +01:00
|
|
|
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
|
2018-12-20 18:19:51 +01:00
|
|
|
Pass db " OK", 0x0A, 0x0D, 0
|
2018-12-21 23:57:41 +01:00
|
|
|
NextTRAM dq 0x0B8000 ; Last position of cursor
|
2018-12-20 18:03:39 +01:00
|
|
|
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-20 18:03:39 +01:00
|
|
|
|
2018-12-21 23:57:41 +01:00
|
|
|
;; Printing
|
2018-12-20 18:03:39 +01:00
|
|
|
mov bl, 0x0B
|
2018-12-21 23:57:41 +01:00
|
|
|
mov esi, Reinit
|
2018-12-20 18:03:39 +01:00
|
|
|
call write
|
|
|
|
|
2018-12-21 23:57:41 +01:00
|
|
|
mov bl, 0x0F
|
|
|
|
mov esi, CPUIDD
|
2018-12-20 18:03:39 +01:00
|
|
|
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
|
2018-12-20 18:03:39 +01:00
|
|
|
call write
|
|
|
|
|
2018-12-21 23:57:41 +01:00
|
|
|
mov bl, 0x0D
|
2018-12-20 18:03:39 +01:00
|
|
|
mov esi, msg
|
|
|
|
call write
|
2018-12-21 23:57:41 +01:00
|
|
|
|
|
|
|
jmp Die
|
2018-12-20 18:19:51 +01:00
|
|
|
|
|
|
|
[BITS 16]
|
|
|
|
ErrorNo64:
|
|
|
|
mov si, NoLongMode
|
|
|
|
call PrintB
|
|
|
|
Die:
|
|
|
|
cli
|
|
|
|
hlt ; die nooooow
|
2018-12-22 12:19:17 +01:00
|
|
|
retf
|
2018-12-20 18:03:39 +01:00
|
|
|
KERNEL:
|