os-k/boot/loader.asm

358 lines
14 KiB
NASM
Raw Normal View History

;=----------------------------------------------------------------------------=;
; GNU GPL OS/K ;
; ;
; Authors: spectral` ;
; NeoX ;
; ;
; Desc: Kernel (second stage) Loader for OS/K ;
; (x86_64 architecture only) ;
;=----------------------------------------------------------------------------=;
;;VIDEO
2018-12-21 23:57:41 +01:00
%define TRAM 0x0B8000 ; [T]ext[RAM]
%define VRAM 0x0A0000 ; [V]ideo[RAM]
;; BPB
%define OEMName bp+0x03 ; Disk label
%define bytesPerSector bp+0x0b ; Bytes per sector
%define sectorsPerCluster bp+0x0d ; Sectors per cluster
%define reservedSectors bp+0x0e ; Reserved sectors
%define fats bp+0x10 ; Number of fats
%define rootDirEntries bp+0x11 ; Number of entries in root dir
%define sectors bp+0x13 ; Logical sectors
%define mediaType bp+0x15 ; Media descriptor byte
%define fatSectors bp+0x16 ; Sectors per FAT
%define sectorsPerTrack bp+0x18 ; Sectors per track
%define heads bp+0x1a ; Number of sides/heads
%define hiddenSectors bp+0x1c ; Hidden sectors
%define hugeSectors bp+0x20 ; LBA sectors
%define biosBootdrvNum bp+0x24 ; Bootdrv number
%define reserved bp+0x25 ; This is not used
%define bootSignature bp+0x26 ; Bootdrv signature
%define volumeId bp+0x27 ; Volume ID
%define volumeLabel bp+0x2b ; Volume Label
%define fatTypeLabel bp+0x36 ; File system type
2018-12-21 23:57:41 +01:00
[BITS 16]
[ORG 0x1000]
2018-12-21 23:57:41 +01:00
mov ax, cs ; correcting cs after the horrible far jump
mov ds, ax ; hm... And ds too
mov es, ax ; And es because it is jealous
2018-12-21 23:57:41 +01:00
mov [Bootdrv], dl
xor dl, dl
2018-12-21 23:57:41 +01:00
jmp 0x0000:main
;; GDT WITH DOC
2018-12-21 23:57:41 +01:00
GDT64:
NULL_SELECTOR: ;; null selector within 64 bits
2019-01-15 00:23:27 +01:00
dw GDT_LENGTH ; limit of GDT
dw GDT64 ; linear address of GDT
dd 0x0 ;
2018-12-24 18:13:58 +01:00
2018-12-21 23:57:41 +01:00
CODE_SELECTOR: ;; 32-bit code selector (ring 0)
2019-01-15 00:23:27 +01:00
dw 0x0000FFFF ; Segment Limit
db 0x0, 0x0, 0x0 ; Base Address
db 10011010b ; |7|6|5|4|3|2|1|0|
2018-12-21 23:57:41 +01:00
; | | | | | | | `----- 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
2019-01-15 00:23:27 +01:00
db 11001111b ; |7|6|5|4|3|2|1|0|
2018-12-21 23:57:41 +01:00
; | | | | | | | `----- 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)
2019-01-15 00:23:27 +01:00
db 0x0 ; Base Address
2018-12-21 23:57:41 +01:00
DATA_SELECTOR: ;; flat data selector (ring 0)
2019-01-15 00:23:27 +01:00
dw 0x0000FFFF ; Segment Limit
db 0x0, 0x0, 0x0 ; Base Address
db 10010010b ; |7|6|5|4|3|2|1|0|
2018-12-21 23:57:41 +01:00
; | | | | | | | `----- 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
2019-01-15 00:23:27 +01:00
db 10001111b ; |7|6|5|4|3|2|1|0|
2018-12-21 23:57:41 +01:00
; | | | | | | | `----- 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)
2019-01-15 00:23:27 +01:00
db 0x0 ; Base Address
2018-12-21 23:57:41 +01:00
LONG_SELECTOR: ;; 64-bit code selector (ring 0)
2019-01-15 00:23:27 +01:00
dw 0x0000FFFF ; Segment Limit
db 0x0, 0x0, 0x0 ; Base Address
db 10011010b ; |7|6|5|4|3|2|1|0|
2018-12-21 23:57:41 +01:00
; | | | | | | | `----- 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
2019-01-15 00:23:27 +01:00
db 10101111b ; |7|6|5|4|3|2|1|0|
2018-12-21 23:57:41 +01:00
; | | | | | | | `----- 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)
2019-01-15 00:23:27 +01:00
db 0x0 ; Base Address
2018-12-21 23:57:41 +01:00
GDT_LENGTH:
%include "boot/loader16.inc"
2018-12-21 23:57:41 +01:00
main:
2018-12-21 23:57:41 +01:00
;; compatibility check
push si
mov si, Init
call PrintB
pop si
call Is64bits
jc ErrorNo64
push si
mov si, Pass
call PrintB
pop si
2018-12-21 23:57:41 +01:00
;; Enabling A20
push si
mov si, EnA20
call PrintB
pop si
in al, 0x92
or al, 2
out 0x92, al
push si
mov si, Pass
call PrintB
pop si
;; DISABLING CURSOR BLINKING AND GETTING INFOS
2018-12-21 23:57:41 +01:00
call get_dimensions
call disable_cursor
2018-12-21 23:57:41 +01:00
;;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
ErrorNo64:
mov si, NoLongMode
call PrintB
Die:
cli
hlt ; die nooooow
jmp 0xF000:0xFFF0
[BITS 32]
main32:
pop dword [VGA_HEIGHT32]
pop dword [VIDEO_MODE32]
2019-01-15 00:23:27 +01:00
;; VERIFY A20
pushad
mov edi,0x112345 ;odd megabyte address.
mov esi,0x012345 ;even megabyte address.
mov [esi],esi ;making sure that both addresses contain diffrent values.
mov [edi],edi ;(if A20 line is cleared the two pointers would point to the address 0x012345 that would contain 0x112345 (edi))
cmpsd ;compare addresses to see if the're equivalent.
popad
jne .A20_on ;if not equivalent , A20 line is set.
mov WORD [A20_OK], 0
jmp .A20_end
.A20_on:
mov BYTE [A20_OK], 1
.A20_end:
;; 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]
%include "boot/loader64.inc"
2018-12-21 23:57:41 +01:00
;; DATA
Init db "Booting OS/K !", 0x0D, 0x0A, 0x0D, 0x0A, 0x09, " Checking CPUID...",0
CPUIDD db 0x09, " Checking CPUID...", 0
EnA20 db 0x09, " Enabling A20 line...", 0
2019-01-15 12:28:53 +01:00
ReadAttempt db 0x09, " Attempt to read a sector with ATA commands...", 0x0A, 0x0D, 0x0A, 0x0D,0
txt db 0x09, " Switching to Long Mode... ", 0
Reinit db "Booting OS/K !", 0x0D, 0x0A, 0x0D, 0x0A, 0
Pass db " OK", 0x0A, 0x0D, 0
2019-01-15 00:23:27 +01:00
Fail db " FAIL!", 0x0A, 0x0D, 0
msg db "The system is now in x64 mode. Is this not beautiful ?", 0x0A, 0x0D, 0
NoLongMode db 0x0A, 0x0D, "ERROR : Your computer is not designed for x64 OS", 0
FileNotFound db "Second Stage Error : The Kernel was not found.", 0x0A, 0x0D, 0
DiskError db "Second Stage Error : The Disk has crashed.", 0x0A, 0x0D, 0
filename db "KERNEL BIN"
Bootdrv db 0
UserData dw 0
VGA_HEIGHT dq 0
VIDEO_MODE dw 0
VIDEO_MODE32 dw 0
VGA_HEIGHT32 dw 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 0
2019-01-15 00:23:27 +01:00
A20_OK db 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
2019-01-15 00:23:27 +01:00
cmp BYTE [A20_OK], 1
je .A20Success
mov bl, 0x0C
mov esi, Fail
call write
2019-01-15 00:23:27 +01:00
jmp Die
.A20Success:
2018-12-21 23:57:41 +01:00
mov bl, 0x0A
mov esi, Pass
call write
2019-01-15 00:23:27 +01:00
mov bl, 0x0F
2018-12-21 23:57:41 +01:00
mov esi, txt
call write
mov bl, 0x0A
mov esi, Pass
call write
2018-12-21 23:57:41 +01:00
mov bl, 0x0D
mov esi, msg
call write
2019-01-15 12:28:53 +01:00
mov bl, 0x0F
mov esi, ReadAttempt
call write
mov rcx, 2
.looping:
nop
nop
nop
loop .looping ; Temporized because the ATA drive must be ready
call ata_read
2019-01-15 00:23:27 +01:00
2018-12-21 23:57:41 +01:00
jmp Die
; times 1024 nop
; XXX ;
; It seems impossible to have an executable > 2.0 kB...