diff --git a/Makefile b/Makefile index d0bec82..5635782 100644 --- a/Makefile +++ b/Makefile @@ -84,14 +84,6 @@ make_disk: @echo ${CL2}[make_disk]${CL} OK${CL3} testloader: loader - @qemu-system-x86_64 -hda build/bin/disk.img -d cpu_reset,guest_errors,pcall,int -enable-kvm 2> qemu.log & - @ndisasm $(OBJDIR)/boot/loader.bin -b 32 > loader_dism.asm - -testloader32: loader - @qemu-system-i386 -hda build/bin/disk.img -d cpu_reset,guest_errors,pcall,int -enable-kvm 2> qemu.log & - @ndisasm $(OBJDIR)/boot/loader.bin -b 32 > loader_dism.asm - -debugloader: loader @qemu-system-x86_64 -hda build/bin/disk.img -d cpu_reset,guest_errors,pcall,int -s -S -enable-kvm 2> qemu.log & @ndisasm $(OBJDIR)/boot/loader.bin -b 32 > loader_dism.asm diff --git a/boot/loader/cpu/cpu.asm b/boot/loader/cpu/cpu.asm new file mode 100644 index 0000000..b875758 --- /dev/null +++ b/boot/loader/cpu/cpu.asm @@ -0,0 +1,46 @@ +;=----------------------------------------------------------------------------=; +; GNU GPL OS/K ; +; ; +; Desc: Basic longmode CPU functions ; +; (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 . ; +;=----------------------------------------------------------------------------=; + +[BITS 64] + +temporize: + push rcx + mov rcx, 2000 +.looping: + nop + nop + nop + loop .looping + pop rcx + ret + +bitemporize: + push rcx + mov rcx, 2000 +.looping: + call temporize + loop .looping + pop rcx + ret diff --git a/boot/loader/cpu/cpuid.inc b/boot/loader/cpu/cpuid.inc index 7dabd42..44e19e7 100644 --- a/boot/loader/cpu/cpuid.inc +++ b/boot/loader/cpu/cpuid.inc @@ -44,7 +44,7 @@ Is64Bits: jz .no_64 ; If it's not set, there is no long mode ret .no_64: - mov ax, "01" ; ERROR 01 : 64bits unsupported + mov al, "2" ; ERROR 1 : 64bits unsupported jmp Error ; ---------------------------------------------------------------------------- ; @@ -66,5 +66,5 @@ Check_cpuid: je .no_cpuid ret .no_cpuid: - mov ax, "02" ; ERROR 02 : CPUID UNSUPPORTED + mov al, "1" ; ERROR 1 : CPUID UNSUPPORTED jmp Error diff --git a/boot/loader/io/ata.asm b/boot/loader/io/ata.asm new file mode 100644 index 0000000..c37cfc6 --- /dev/null +++ b/boot/loader/io/ata.asm @@ -0,0 +1,159 @@ +;=----------------------------------------------------------------------------=; +; GNU GPL OS/K ; +; ; +; Desc: Basic Read Only ATA Long mode Driver ; +; (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 . ; +;=----------------------------------------------------------------------------=; + +[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 +ended db "[End of Sector]", 0x0A, 0x0A, 0x0D, 0x0 +buffer: times 513 db "_" + +;; TEXT + +ata_read: +;-----------------------------------------------------------------------; +; x64/LM ATA Reading function ; +; bl : number of sectors to read XXX ; +; bh : the first sector to read ; +;-----------------------------------------------------------------------; + +; 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 rcx + push rdx + 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, bl ; Read bl(s) sector + out dx, al + + mov dx, 0x1f3 ; Sector number port + mov al, bh ; Read from sector n°bh + 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, QWORD buffer + mov dx, 0x1f0 ; Data port - data comes in and out of here. + rep insw + pop rdi +%ifdef DEBUG + mov bl, 0x0F + mov esi, buffer + call dump + mov bl, 0x0A + mov esi, ended + call write + add qword [NextTRAM], 120 ; Cursor moving : 1120 = 80 * 2 * 7 lignes +%else + mov bl, 0x0A + mov esi, Pass + call write +%endif + pop rdx + pop rcx + pop rbx + pop rax + ret diff --git a/boot/loader/io/lmmem.asm b/boot/loader/io/lmmem.asm new file mode 100644 index 0000000..e77e4c2 --- /dev/null +++ b/boot/loader/io/lmmem.asm @@ -0,0 +1,43 @@ +;=----------------------------------------------------------------------------=; +; GNU GPL OS/K ; +; ; +; Desc: Basic Memory Long mode Functions ; +; (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 . ; +;=----------------------------------------------------------------------------=; +[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 diff --git a/boot/loader/io/lmterm.asm b/boot/loader/io/lmterm.asm new file mode 100644 index 0000000..c5805d8 --- /dev/null +++ b/boot/loader/io/lmterm.asm @@ -0,0 +1,131 @@ +;=----------------------------------------------------------------------------=; +; GNU GPL OS/K ; +; ; +; Desc: Basic Colored VGA Terminal Long mode Driver ; +; (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 . ; +;=----------------------------------------------------------------------------=; + + +;;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 512 bytes of a buffer ; +; bl : color code ; +; esi : buffer 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 + loop .pLoop + pop rcx + pop rdi + pop rsi + add qword [NextTRAM], 1000 ; Cursor moving : 1120 = 80 * 2 * 7 lignes + ret diff --git a/boot/loader/loader.asm b/boot/loader/loader.asm index d421bd0..2040668 100644 --- a/boot/loader/loader.asm +++ b/boot/loader/loader.asm @@ -31,7 +31,7 @@ %include "boot/loader/multiboot/header.inc" -;; NORMAL ENTRY POINT, BUT A LITTLE BIT UNUSED SINCE WE NEVER USE IT BECAUSE... +;; Normal entry point, but a little bit unused since we never use it because... _start: mov ax, cs ; correcting cs after the horrible far jump mov ds, ax ; hm... And ds too @@ -40,7 +40,7 @@ _start: xor dl, dl jmp 0x0000:_loader ; pas sûr -;; MAGNIFICENT MULTIBOOT HEADER FOR GRUB ------------------------------------ ;; +;; Magnificent multiboot header for GRUB ------------------------------------ ;; MB_header: align 4 dd MB_HEADER_MAGIC @@ -52,7 +52,7 @@ MB_header: dd 00 ; (bss) not necessary dd MB_start ; entry address GRUB will start at -;; MULTIBOOT POINT ENTRY FOR GRUB ------------------------------------------- ;; +;; Multiboot entry point for Grub ------------------------------------------- ;; MB_start: mov esp, KERNEL_STACK ; Setup the stack push 0 ; Reset EFLAGS @@ -65,22 +65,13 @@ MB_start: jmp Die ; Aufwiedersehen ;; THE HOLES ---------------------------------------------------------------- ;; - -; ---------------------------------------------------------------------------- ; -; Prints 'ERR:XX' where 'XX' is the str in AX ; -; ---------------------------------------------------------------------------- ; Error: mov dword [0xb8000], 0x4f524f45 mov dword [0xb8004], 0x4f3a4f52 mov dword [0xb8008], 0x4f204f20 mov byte [0xb800a], al - mov byte [0xb800c], ah - mov byte [0xb800d], 0x4f jmp Die -; ---------------------------------------------------------------------------- ; -; Kills the mind of your computer to get it prostrated ; -; ---------------------------------------------------------------------------- ; Die: cli hlt ; die nooooow @@ -104,57 +95,24 @@ _loader: jmp lbegin %include "boot/loader/multiboot/check.inc" -%include "boot/loader/cpu/cpuid.inc" -%include "boot/loader/mem/structures.inc" -%include "boot/loader/mem/management.inc" - lbegin: call MB_check + jmp lnext +%include "boot/loader/cpu/cpuid.inc" +lnext: call Check_cpuid call Is64Bits - call CheckA20 + jmp lnext2 +%include "boot/loader/mem/structures.inc" +lnext2: call Setup_paging call Go64 + jmp lnext3 +%include "boot/loader/mem/management.inc" - lgdt [GDT64.pointer] - jmp GDT64.code:l64 +lnext3: + mov dword [0xb8000], 0x2f4b2f4f + ret -[BITS 64] -%include "boot/loader/io/terminal.inc" -%include "boot/loader/io/ata.inc" -%include "boot/loader/cpu/cpu.inc" - -Salut db 0x09, " Booting OS/K ", 0x09, 0x0A, 0x0D, 0x0 -ReadAttempt db 0x09, " Attempt to read a sector with ATA commands...", 0 - -l64: - ;; Some cleanup - mov ax, 0 - mov ss, ax - mov ds, ax - mov es, ax - mov fs, ax - mov gs, ax - - ;; Hello world - mov bl, 0x0A - mov esi, Salut - call write - - ;; Read ATA - mov bl, 0x0F - mov esi, ReadAttempt - call write - - call temporize - - - - ;; Reading a sector of the disk - mov bl, 1 - mov bh, 1 - call ata_read - - jmp Die diff --git a/boot/loader/mem/management.inc b/boot/loader/mem/management.inc index 57f86d7..48ff4cc 100644 --- a/boot/loader/mem/management.inc +++ b/boot/loader/mem/management.inc @@ -87,22 +87,3 @@ Go64: popa ret - -; ---------------------------------------------------------------------------- ; -; Checks if Grub has enabled A20 line ; -; ---------------------------------------------------------------------------- ; -CheckA20: - 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. - jmp .A20_err -.A20_on: - ret -.A20_err: - mov ax, "03" ; ERROR 03 : A20 line failed - jmp Error diff --git a/boot/loader/mem/structures.inc b/boot/loader/mem/structures.inc index e1be0bd..4947b9d 100644 --- a/boot/loader/mem/structures.inc +++ b/boot/loader/mem/structures.inc @@ -28,20 +28,80 @@ ;; GDT WITH DOC ALIGN 4096 GDT64: - ;; Null selector within 64 bits - .null: - dq 0x0 ; Zero entry - ;; 64-bit code selector (ring 0) - .code: equ $ - GDT64 - dq (1<<43) | (1<<44) | (1<<47) | (1<<53) - ; | | | | - ; | | | `------ 64-bit selector - ; | | `---------------- Present selector - ; | `-------------------------- Descriptor type - ; `------------------------------------ Executable segment - .pointer: - dw $ - GDT64 - 1 - dq 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: ;; EMPTY PAGE TABLES (identity of the first 1GiB) ALIGN 4096 diff --git a/boot/loader/multiboot/check.inc b/boot/loader/multiboot/check.inc index c045e64..e1b42e3 100644 --- a/boot/loader/multiboot/check.inc +++ b/boot/loader/multiboot/check.inc @@ -31,5 +31,5 @@ MB_check: jne .no_MB ret .no_MB: - mov ax, "01" ; ERROR 01 : No multiboot + mov al, "0" ; ERROR 0 : No multiboot jmp Error diff --git a/build/obj/boot/loader.bin b/build/obj/boot/loader.bin index aa06194..1b1f118 100644 Binary files a/build/obj/boot/loader.bin and b/build/obj/boot/loader.bin differ