249 lines
8.6 KiB
NASM
249 lines
8.6 KiB
NASM
;=----------------------------------------------------------------------------=;
|
|
; GNU GPL OS/K ;
|
|
; ;
|
|
; Desc: Kernel (second stage) Loader for OS/K ;
|
|
; (x86_64 architecture only) ;
|
|
; ;
|
|
; ;
|
|
; Copyright © 2018-2019 The OS/K Team ;
|
|
; ;
|
|
; This file is part of OS/K. ;
|
|
; ;
|
|
; OS/K is free software: you can redistribute it and/or modify ;
|
|
; it under the terms of the GNU General Public License as published by ;
|
|
; the Free Software Foundation, either version 3 of the License, or ;
|
|
; (at your option) any later version. ;
|
|
; ;
|
|
; OS/K is distributed in the hope that it will be useful, ;
|
|
; but WITHOUT ANY WARRANTY; without even the implied warranty of ;
|
|
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;
|
|
; GNU General Public License for more details. ;
|
|
; ;
|
|
; You should have received a copy of the GNU General Public License ;
|
|
; along with OS/K. If not, see <https://www.gnu.org/licenses/>. ;
|
|
;=----------------------------------------------------------------------------=;
|
|
|
|
%define DEBUG
|
|
|
|
[BITS 32]
|
|
[global _start]
|
|
[ORG 0x100000] ; Where GRUB loads us.
|
|
|
|
%include "boot/loader/multiboot.inc"
|
|
|
|
_start:
|
|
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
|
|
|
|
mov [Bootdrv], dl
|
|
xor dl, dl
|
|
jmp 0x0000:main ; pas sûr
|
|
|
|
[align 4]
|
|
dd MULTIBOOT_HEADER_MAGIC
|
|
dd MULTIBOOT_HEADER_FLAGS
|
|
dd CHECKSUM
|
|
dd multiboot_header ; Header address
|
|
dd _start ; Address of code entry point
|
|
dd 00 ; (end of code) not necessary
|
|
dd 00 ; (bss) not necessary
|
|
dd MB_start ; entry address GRUB will start at
|
|
|
|
MB_start:
|
|
mov esp, KERNEL_STACK ; Setup the stack
|
|
push 0 ; Reset EFLAGS
|
|
popf
|
|
push eax ; 2nd argument is magic number
|
|
push ebx ; 1st argument multiboot info pointer
|
|
call main
|
|
add esp, 8 ; Cleanup 8 bytes pushed as arguments
|
|
jmp Die
|
|
|
|
%include "boot/loader/cpu/cpuid.asm"
|
|
%include "boot/loader/io/rmterm.asm"
|
|
%include "boot/loader/io/rmmem.asm"
|
|
|
|
main:
|
|
|
|
;;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
|
|
|
|
Die:
|
|
cli
|
|
hlt ; die nooooow
|
|
jmp 0xF000:0xFFF0
|
|
;; END OF THE HOLE ---------------------------------------------------------- ;;
|
|
|
|
[BITS 32]
|
|
main32:
|
|
pop dword [VGA_HEIGHT32]
|
|
pop dword [VIDEO_MODE32]
|
|
|
|
;; 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
|
|
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]
|
|
|
|
;; 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
|
|
%ifdef DEBUG
|
|
ReadAttempt db 0x09, " Attempt to read a sector with ATA commands...", 0x0A, 0x0D, 0x0A, 0x0D, 0
|
|
%else
|
|
ReadAttempt db 0x09, " Attempt to read a sector with ATA commands...", 0
|
|
%endif
|
|
txt db 0x09, " Switching to Long Mode... ", 0
|
|
EndOfLoader db "End of loader.bin. System will halt !", 0x0A, 0x0D, 0
|
|
Reinit db "Booting OS/K !", 0x0D, 0x0A, 0x0D, 0x0A, 0
|
|
Pass db " OK", 0x0A, 0x0D, 0
|
|
Fail db " FAIL!", 0x0A, 0x0D, 0
|
|
msg db "The system is now in x64 mode. Is this not beautiful ?", 0x0A, 0x0D, 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"
|
|
|
|
%include "boot/loader/io/lmmem.asm"
|
|
%include "boot/loader/io/lmterm.asm"
|
|
%include "boot/loader/io/ata.asm"
|
|
%include "boot/loader/cpu/cpu.asm"
|
|
%include "boot/loader/fs/fat.asm"
|
|
|
|
main64:
|
|
pop qword [VGA_HEIGHT64]
|
|
pop qword [VIDEO_MODE64]
|
|
;; INITIALIZE STACK
|
|
mov rsp, 0x9F000
|
|
|
|
call clear
|
|
|
|
;; Printing
|
|
mov bl, 0x0B
|
|
mov esi, Reinit
|
|
call write
|
|
|
|
mov bl, 0x0F
|
|
mov esi, CPUIDD
|
|
call write
|
|
|
|
mov bl, 0x0A
|
|
mov esi, Pass
|
|
call write
|
|
|
|
mov bl, 0x0F
|
|
mov esi, EnA20
|
|
call write
|
|
|
|
call check_a20
|
|
|
|
mov bl, 0x0F
|
|
mov esi, txt
|
|
call write
|
|
|
|
mov bl, 0x0A
|
|
mov esi, Pass
|
|
call write
|
|
|
|
mov bl, 0x0D
|
|
mov esi, msg
|
|
call write
|
|
|
|
mov bl, 0x0F
|
|
mov esi, ReadAttempt
|
|
call write
|
|
|
|
call temporize ; Temporized because the ATA drive must be ready
|
|
|
|
mov bl, 1
|
|
mov bh, 1
|
|
call ata_read
|
|
|
|
mov bl, 0x0D
|
|
mov esi, EndOfLoader
|
|
call write
|
|
|
|
jmp Die
|
|
|