Merge pull request #15 from os-k-team/loader

Loader
This commit is contained in:
Adrien Bourmault 2019-01-16 11:08:36 +01:00 committed by GitHub
commit 0c9aaec6df
19 changed files with 723 additions and 609 deletions

5
.gitignore vendored
View File

@ -11,12 +11,11 @@ test-*.c
*.elf
*.S
# Linker output
*.ilk
*.map
*.exp
*.bin
*.img
# Precompiled Headers
*.gch
@ -41,6 +40,8 @@ test-*.c
*.i*86
*.x86_64
*.hex
*.bin
*.img
# Debug files
*.dSYM/

View File

@ -29,15 +29,16 @@ ASM=nasm
ASMFLAGS=
BOOTFLAGS=-f bin
BOOTDIR=boot
MBRDIR=boot/mbr
LOADERDIR=boot/loader
OBJDIR=build/obj
BINDIR=build/bin
boot.mbr.asm: $(BOOTDIR)/mbr.asm $(BOOTDIR)/mbr.inc
$(ASM) $(BOOTFLAGS) $(BOOTDIR)/mbr.asm -o $(OBJDIR)/boot/mbr.bin
boot.mbr.asm: $(MBRDIR)/mbr.asm $(MBRDIR)/mbr.inc
$(ASM) $(BOOTFLAGS) $(MBRDIR)/mbr.asm -o $(OBJDIR)/boot/mbr.bin
boot.loader.asm: $(BOOTDIR)/loader.asm
$(ASM) $(BOOTFLAGS) $(BOOTDIR)/loader.asm -o $(OBJDIR)/boot/loader.bin
boot.loader.asm: $(LOADERDIR)/loader.asm
$(ASM) $(BOOTFLAGS) $(LOADERDIR)/loader.asm -o $(OBJDIR)/boot/loader.bin
bootloader: boot.mbr.asm boot.loader.asm
cp $(OBJDIR)/boot/mbr.bin $(BINDIR)/mbr.bin

View File

@ -1,357 +0,0 @@
;=----------------------------------------------------------------------------=;
; GNU GPL OS/K ;
; ;
; Authors: spectral` ;
; NeoX ;
; ;
; Desc: Kernel (second stage) Loader for OS/K ;
; (x86_64 architecture only) ;
;=----------------------------------------------------------------------------=;
;;VIDEO
%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
[BITS 16]
[ORG 0x1000]
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
;; 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 0x0000FFFF ; Segment Limit
db 0x0, 0x0, 0x0 ; Base Address
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
DATA_SELECTOR: ;; flat data selector (ring 0)
dw 0x0000FFFF ; Segment Limit
db 0x0, 0x0, 0x0 ; Base Address
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
LONG_SELECTOR: ;; 64-bit code selector (ring 0)
dw 0x0000FFFF ; Segment Limit
db 0x0, 0x0, 0x0 ; Base Address
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
GDT_LENGTH:
%include "boot/loader16.inc"
main:
;; compatibility check
push si
mov si, Init
call PrintB
pop si
call Is64bits
jc ErrorNo64
push si
mov si, Pass
call PrintB
pop si
;; 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
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
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]
;; 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]
%include "boot/loader64.inc"
;; 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
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
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
NextTRAM dq 0x0B8000 ; Last position of cursor
VIDEO_MODE64 dq 0
VGA_HEIGHT64 dq 0
VGA_X dq 0
A20_OK db 0
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
cmp BYTE [A20_OK], 1
je .A20Success
mov bl, 0x0C
mov esi, Fail
call write
jmp Die
.A20Success:
mov bl, 0x0A
mov esi, Pass
call write
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
mov rcx, 2
.looping:
nop
nop
nop
loop .looping ; Temporized because the ATA drive must be ready
call ata_read
jmp Die
; times 1024 nop
; XXX ;
; It seems impossible to have an executable > 2.0 kB...

22
boot/loader/cpu/cpu.asm Normal file
View File

@ -0,0 +1,22 @@
;=----------------------------------------------------------------------------=;
; GNU GPL OS/K ;
; ;
; Authors: spectral` ;
; NeoX ;
; ;
; Desc: Basic longmode CPU functions ;
; (x86_64 architecture only) ;
;=----------------------------------------------------------------------------=;
[BITS 64]
temporize:
push rcx
mov rcx, 2000
.looping:
nop
nop
nop
loop .looping
pop rcx
ret

50
boot/loader/cpu/cpuid.asm Normal file
View File

@ -0,0 +1,50 @@
;=----------------------------------------------------------------------------=;
; GNU GPL OS/K ;
; ;
; Authors: spectral` ;
; NeoX ;
; ;
; Desc: Basic realmode CPU Detection ;
; (x86_64 architecture only) ;
;=----------------------------------------------------------------------------=;
[BITS 16]
;; GLOBAL DATA
NoLongMode db 0x0A, 0x0D, "ERROR : Your computer is not designed for x64 OS", 0
;; TEXT
Is64bits:
;-----------------------------------------------------------------------;
; 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 ;
;-----------------------------------------------------------------------;
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

View File

@ -7,4 +7,4 @@
// Desc: ELF64 Parser and Loader //
//----------------------------------------------------------------------------//
//STUB
int stub;

18
boot/loader/fs/fat.asm Normal file
View File

@ -0,0 +1,18 @@
;=----------------------------------------------------------------------------=;
; GNU GPL OS/K ;
; ;
; Authors: spectral` ;
; NeoX ;
; ;
; Desc: Basic File Allocation Table Long mode Driver ;
; (x86_64 architecture only) ;
;=----------------------------------------------------------------------------=;
[BITS 64]
;; GLOBAL DATA
UserData dw 0
;; TEXT
nop

138
boot/loader/io/ata.asm Normal file
View File

@ -0,0 +1,138 @@
;=----------------------------------------------------------------------------=;
; GNU GPL OS/K ;
; ;
; Authors: spectral` ;
; NeoX ;
; ;
; Desc: Basic Read Only ATA Long mode Driver ;
; (x86_64 architecture only) ;
;=----------------------------------------------------------------------------=;
[BITS 64]
;; 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
;; GLOBAL DATA
Bootdrv db 0
end db "[End of Sector]", 0x0
buffer: times 513 db "_"
;; TEXT
ata_read:
;-----------------------------------------------------------------------;
; x64/LM ATA Reading function ;
; ;
; ;
;-----------------------------------------------------------------------;
; Technical infos about the ports (Intel Doc):
;
; Port Access Mode Misc
;
; 1f0 r/w Data register, the bytes of the disk itself
; 1f1 r Error register that can be handled
; 1f2 r/w Sector count, how many sectors to read
; 1f3 r/w Sector number, the actual sector wanted
; 1f4 r/w Cylinder low, cylinders is 0-1024
; 1f5 r/w Cylinder high, this makes up the rest of the 1024
; 1f6 r/w Drive/head
; bit 7 = 1
; bit 6 = 0
; bit 5 = 1
; bit 4 = 0 drive 0 select
; = 1 drive 1 select
; bit 3-0 head select bits
; 1f7 r Status register
; bit 7 = 1 controller is executing a command
; bit 6 = 1 drive is ready
; bit 5 = 1 write fault
; bit 4 = 1 seek complete
; bit 3 = 1 sector buffer requires servicing
; bit 2 = 1 disk data read corrected
; bit 1 = 1 index - set to 1 each revolution
; bit 0 = 1 previous command ended in an error
; 1f7 w Command register
; commands:
; 50h format track
; 20h read sectors with retry
; 21h read sectors without retry
; 22h read long with retry
; 23h read long without retry
; 30h write sectors with retry
; 31h write sectors without retry
; 32h write long with retry
; 33h write long without retry
;
push rax
push rbx
push rdx
push rcx
push rdi
mov dx, 0x1f6 ; Drive and head port
mov al, 0x0a0 ; Drive 0, head 0
out dx,al
mov dx, 0x1f2 ; Sector count port
mov al, 1 ; Read one sector
out dx, al
mov dx, 0x1f3 ; Sector number port
mov al, 1 ; Read sector one
out dx, al
mov dx, 0x1f4 ; Cylinder low port
mov al, 0 ; Cylinder 0
out dx, al
mov dx, 0x1f5 ; Cylinder high port
mov al, 0 ; The rest of the cylinder 0
out dx, al
mov dx, 0x1f7 ; Command port
mov al, 0x20 ; Read with retry.
out dx, al
still_going:
in al, dx
test al, 8 ; This means the sector buffer requires
;servicing.
jz still_going ; Don't continue until the sector buffer
;is ready.
mov cx, 512/2 ; One sector /2 because it copies words
mov rdi, buffer
mov dx, 0x1f0 ; Data port - data comes in and out of here.
rep insw
pop rdi
pop rcx
pop rdx
pop rbx
pop rax
mov bl, 0x0F
mov esi, buffer
call dump
mov bl, 0x0A
mov esi, end
call write
ret

28
boot/loader/io/lmmem.asm Normal file
View File

@ -0,0 +1,28 @@
;=----------------------------------------------------------------------------=;
; GNU GPL OS/K ;
; ;
; Authors: spectral` ;
; NeoX ;
; ;
; Desc: Basic Memory Long mode Functions ;
; (x86_64 architecture only) ;
;=----------------------------------------------------------------------------=;
[BITS 64]
;; GLOBAL DATA
A20_OK db 0
;; TEXT
check_a20:
cmp BYTE [A20_OK], 1
je .A20Success
mov bl, 0x0C
mov esi, Fail
call write
jmp Die
.A20Success:
mov bl, 0x0A
mov esi, Pass
call write
ret

116
boot/loader/io/lmterm.asm Normal file
View File

@ -0,0 +1,116 @@
;=----------------------------------------------------------------------------=;
; GNU GPL OS/K ;
; ;
; Authors: spectral` ;
; NeoX ;
; ;
; Desc: Basic Colored VGA Terminal Long mode Driver ;
; (x86_64 architecture only) ;
;=----------------------------------------------------------------------------=;
;;VIDEO
%define TRAM 0x0B8000 ; [T]ext[RAM]
%define VRAM 0x0A0000 ; [V]ideo[RAM]
;; GLOBAL DATA
VGA_HEIGHT dq 0
VIDEO_MODE dw 0
VIDEO_MODE32 dw 0
VGA_HEIGHT32 dw 0
NextTRAM dq 0x0B8000 ; Last position of cursor
VIDEO_MODE64 dq 0
VGA_HEIGHT64 dq 0
VGA_X dq 0
;; TEXT
[BITS 64]
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
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:
; XXX I don't think I'll implement this, but never know...;
jmp .pLoop
dump:
;-----------------------------------------------------------------------;
; x64/LM Dump Printing Functions ;
; bl : color code ;
; esi : string address ;
;-----------------------------------------------------------------------;
mov edi, [NextTRAM] ; TRAM ADDRESS
push rsi
push rdi
push rcx
mov rcx, 512
.pLoop:
lodsb
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
loop .pLoop
pop rcx
pop rdi
pop rsi
ret

98
boot/loader/io/rmmem.asm Normal file
View File

@ -0,0 +1,98 @@
;=----------------------------------------------------------------------------=;
; GNU GPL OS/K ;
; ;
; Authors: spectral` ;
; NeoX ;
; ;
; Desc: Basic Memory Realmode Driver ;
; (x86_64 architecture only) ;
;=----------------------------------------------------------------------------=;
[BITS 16]
;; 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 0x0000FFFF ; Segment Limit
db 0x0, 0x0, 0x0 ; Base Address
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
DATA_SELECTOR: ;; flat data selector (ring 0)
dw 0x0000FFFF ; Segment Limit
db 0x0, 0x0, 0x0 ; Base Address
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
LONG_SELECTOR: ;; 64-bit code selector (ring 0)
dw 0x0000FFFF ; Segment Limit
db 0x0, 0x0, 0x0 ; Base Address
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
GDT_LENGTH:
;; TEXT
set_a20:
push ax
in al, 0x92
or al, 2
out 0x92, al
pop ax
ret

View File

@ -4,7 +4,7 @@
; Authors: spectral` ;
; NeoX ;
; ;
; Desc: Kernel (second stage) Loader for OS/K INCLUDED FUNCTIONS ;
; Desc: Basic realmode terminal functions ;
; (x86_64 architecture only) ;
;=----------------------------------------------------------------------------=;
@ -36,40 +36,6 @@ get_dimensions:
pop eax
ret
Is64bits:
;-----------------------------------------------------------------------;
; 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 ;
;-----------------------------------------------------------------------;
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
PrintB:
;---------------------------------------------------;
; Print out a simple string. ;

233
boot/loader/loader.asm Normal file
View File

@ -0,0 +1,233 @@
;=----------------------------------------------------------------------------=;
; GNU GPL OS/K ;
; ;
; Authors: spectral` ;
; NeoX ;
; ;
; Desc: Kernel (second stage) Loader for OS/K ;
; (x86_64 architecture only) ;
;=----------------------------------------------------------------------------=;
[BITS 16]
[ORG 0x1000]
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
%include "boot/loader/cpu/cpuid.asm"
%include "boot/loader/io/rmterm.asm"
%include "boot/loader/io/rmmem.asm"
main:
;; compatibility check
push si
mov si, Init
call PrintB
pop si
call Is64bits
jc ErrorNo64
push si
mov si, Pass
call PrintB
pop si
;; Enabling A20
push si
mov si, EnA20
call PrintB
pop si
call set_a20
push si
mov si, Pass
call PrintB
pop si
;; 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
;; THE HOLE ----------------------------------------------------------------- ;;
ErrorNo64:
mov si, NoLongMode
call PrintB
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
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
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
call ata_read
jmp Die
; times 1024 nop
; XXX ;
; It seems impossible to have an executable > 2.0 kB...

View File

@ -1,200 +0,0 @@
;=----------------------------------------------------------------------------=;
; GNU GPL OS/K ;
; ;
; Authors: spectral` ;
; NeoX ;
; ;
; Desc: Kernel (second stage) Loader for OS/K INCLUDED FUNCTIONS ;
; (x86_64 architecture only) ;
;=----------------------------------------------------------------------------=;
[BITS 64]
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
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:
; XXX I don't think I'll implement this, but never know...;
jmp .pLoop
dump:
;-----------------------------------------------------------------------;
; x64/LM Dump Printing Functions ;
; bl : color code ;
; esi : string address ;
;-----------------------------------------------------------------------;
mov edi, [NextTRAM] ; TRAM ADDRESS
push rsi
push rdi
push rcx
mov rcx, 512
.pLoop:
lodsb
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
loop .pLoop
pop rcx
pop rdi
pop rsi
ret
ata_read:
;-----------------------------------------------------------------------;
; x64/LM ATA Reading function ;
; ;
; ;
;-----------------------------------------------------------------------;
; Technical infos about the ports (Intel Doc):
;
; Port Access Mode Misc
;
; 1f0 r/w Data register, the bytes of the disk itself
; 1f1 r Error register that can be handled
; 1f2 r/w Sector count, how many sectors to read
; 1f3 r/w Sector number, the actual sector wanted
; 1f4 r/w Cylinder low, cylinders is 0-1024
; 1f5 r/w Cylinder high, this makes up the rest of the 1024
; 1f6 r/w Drive/head
; bit 7 = 1
; bit 6 = 0
; bit 5 = 1
; bit 4 = 0 drive 0 select
; = 1 drive 1 select
; bit 3-0 head select bits
; 1f7 r Status register
; bit 7 = 1 controller is executing a command
; bit 6 = 1 drive is ready
; bit 5 = 1 write fault
; bit 4 = 1 seek complete
; bit 3 = 1 sector buffer requires servicing
; bit 2 = 1 disk data read corrected
; bit 1 = 1 index - set to 1 each revolution
; bit 0 = 1 previous command ended in an error
; 1f7 w Command register
; commands:
; 50h format track
; 20h read sectors with retry
; 21h read sectors without retry
; 22h read long with retry
; 23h read long without retry
; 30h write sectors with retry
; 31h write sectors without retry
; 32h write long with retry
; 33h write long without retry
;
push rax
push rbx
push rdx
push rcx
push rdi
mov dx, 0x1f6 ;Drive and head port
mov al, 0x0a0 ;Drive 0, head 0
out dx,al
mov dx, 0x1f2 ;Sector count port
mov al, 1 ;Read one sector
out dx, al
mov dx, 0x1f3 ;Sector number port
mov al, 1 ;Read sector one
out dx, al
mov dx, 0x1f4 ;Cylinder low port
mov al, 0 ;Cylinder 0
out dx, al
mov dx, 0x1f5 ;Cylinder high port
mov al, 0 ;The rest of the cylinder 0
out dx, al
mov dx, 0x1f7 ;Command port
mov al, 20 ;Read with retry.
out dx, al
still_going:
in al, dx
test al, 8 ;This means the sector buffer requires
;servicing.
jz still_going ;Don't continue until the sector buffer
;is ready.
mov cx, 512/2 ;One sector /2
mov rdi, buffer
mov dx, 0x1f0 ;Data port - data comes in and out of here.
rep insw
pop rdi
pop rcx
pop rdx
pop rbx
pop rax
mov bl, 0x0F
mov esi, buffer
call dump
mov bl, 0x0A
mov esi, end
call write
ret
buffer: times 512 db "_"
end: db "[End of Sector]", 0x0

View File

@ -59,11 +59,11 @@ BPB:
;; ENTRY POINT
_start:
jmp BOOT_SEG:$+5 ; Fix the cs:ip registers with a vaudou magical trip
bootstrap:
jmp go
;; LOVELY DATA
;; LOVELY DATA
FileNotFound db "First Stage ERROR : NO LOADER", 0
DiskError db "First Stage ERROR : DISK", 0
UserData dw 0
@ -84,7 +84,7 @@ go:
mov sp, STACK_OFF ; Ok man, the stack is in 4K :O
sti
mov bp, (0x7c0-STACK_SEG) << 4 ; Correct bp (the disk description table)
;; INITIALIZE BOOT DISK
or dl, dl ; Verifying dl points actually to the boot drive
jz load_root
@ -113,7 +113,7 @@ load_root:
add ax, word [reservedSectors] ; increase ax by the reserved sectors
mov word [UserData], ax ; Start of user data = startOfRoot + numberOfRoot
add word [UserData], cx ; Add the size and location of the root directory
mov di, BUFFER_SEG ; Set the extra segment to the disk buffer
mov es, di
mov di, BUFFER_OFF ; Set es:di and load the root directory into the disk buffer
@ -134,14 +134,14 @@ search_root:
add di, ax ; Add the offset to point to the next entry
xchg dx, cx
loop search_root ; Continue to search for the file
;; ERROR...
mov si, FileNotFound ; Could not find the file
call print
call reboot
;; LOAD THE FAT FROM THE FILE
load_fat:
load_fat:
mov ax, word [es:di + 15] ; Get the file cluster at offset 26
push ax ; Store the FAT cluster
xor ax, ax ; Size of fat = (fats * fatSectors)
@ -168,7 +168,7 @@ load_fat:
; ...
call reboot
%include "boot/mbr.inc"
%include "boot/mbr/mbr.inc"
;; END
times 510 - ($ - $$) db 0 ; Pad remainder of boot sector with zeros

Binary file not shown.

Binary file not shown.

Binary file not shown.