├── debug.log ├── bochs.sh ├── qemu.sh ├── bochs.bat ├── qemu.bat ├── .gitignore ├── make.sh ├── make.bat ├── README.md ├── zero ├── pit.asm ├── page.asm ├── memory.asm ├── storage.asm ├── pic.asm ├── protected_mode.asm ├── floppy.asm ├── kernel.asm ├── data.asm ├── print.asm ├── idt.asm ├── long_mode.asm ├── ap.asm └── graphics.asm ├── disk.asm ├── bootsector.asm ├── bochsrc-windows.bxrc ├── bochsrc-linux.bxrc ├── kernel.asm └── zero.asm /debug.log: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /bochs.sh: -------------------------------------------------------------------------------- 1 | bochs -f bochsrc-linux.bxrc -q 2 | -------------------------------------------------------------------------------- /qemu.sh: -------------------------------------------------------------------------------- 1 | qemu-system-x86_64 -fda build/cyjon.img -m 32 2 | -------------------------------------------------------------------------------- /bochs.bat: -------------------------------------------------------------------------------- 1 | ..\bochs\bochsdbg.exe -f bochsrc-windows.bxrc -q 2 | -------------------------------------------------------------------------------- /qemu.bat: -------------------------------------------------------------------------------- 1 | ..\qemu\qemu-system-x86_64 -fda build/cyjon.img -m 32 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.dll 2 | *.ini 3 | *.cfg 4 | *.exe 5 | *.lock 6 | *.pdf 7 | *.txt 8 | *.log 9 | -------------------------------------------------------------------------------- /make.sh: -------------------------------------------------------------------------------- 1 | nasm -f bin kernel.asm -o build/kernel 2 | KERNEL_SIZE=`wc -c < build/kernel` 3 | 4 | nasm -f bin zero/ap.asm -o build/ap 5 | nasm -f bin zero.asm -o build/zero -dKERNEL_FILE_SIZE_bytes=${KERNEL_SIZE} 6 | ZERO_SIZE=`wc -c < build/zero` 7 | 8 | nasm -f bin bootsector.asm -o build/bootsector -dZERO_FILE_SIZE_bytes=${ZERO_SIZE} 9 | 10 | nasm -f bin disk.asm -o build/cyjon.img 11 | -------------------------------------------------------------------------------- /make.bat: -------------------------------------------------------------------------------- 1 | ..\nasm -f bin kernel.asm -o build/kernel 2 | FOR /F "usebackq" %%A IN ('build/kernel') DO set KERNEL_SIZE=%%~zA 3 | 4 | ..\nasm -f bin zero/ap.asm -o build/ap 5 | ..\nasm -f bin zero.asm -o build/zero -dKERNEL_FILE_SIZE_bytes=%KERNEL_SIZE% 6 | FOR /F "usebackq" %%A IN ('build/zero') DO set ZERO_SIZE=%%~zA 7 | 8 | ..\nasm -f bin bootsector.asm -o build/bootsector -dZERO_FILE_SIZE_bytes=%ZERO_SIZE% 9 | 10 | ..\nasm -f bin disk.asm -o build/cyjon.img 11 | 12 | pause 13 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Zero 2 | 3 | 64 bit bootloader for Cyjon operating system. 4 | 5 | ### Software: 6 | 7 | - Qemu 5.0.0 or Bochs 2.6.11 (no SMP support on MS/Windows) 8 | - Nasm 2.15.1 9 | - Atom (with package https://atom.io/packages/language-assembly) or your own IDE ;) 10 | 11 | ### Compilation/Exec (GNU/Linux): 12 | 13 | user@hostname:~/Zero$ chmod +x make.sh qemu.sh 14 | user@hostname:~/Zero$ ./make.sh 15 | user@hostname:~/Zero$ ./qemu.sh 16 | 17 | ### Compilation/Exec (MS/Windows): 18 | 19 | C:\Zero> make.bat 20 | C:\Zero> qemu.bat 21 | -------------------------------------------------------------------------------- /zero/pit.asm: -------------------------------------------------------------------------------- 1 | ;=============================================================================== 2 | ; Copyright (C) Andrzej Adamczyk (at https://blackdev.org/). All rights reserved. 3 | ; GPL-3.0 License 4 | ; 5 | ; Main developer: 6 | ; Andrzej Adamczyk 7 | ;=============================================================================== 8 | 9 | ;=============================================================================== 10 | zero_pit: 11 | ; Channel (00b), Access (11b), Operating (000b), Binary Mode (0b) 12 | mov al, 0x00 13 | out 0x0043, al 14 | -------------------------------------------------------------------------------- /disk.asm: -------------------------------------------------------------------------------- 1 | ;=============================================================================== 2 | ; Copyright (C) Andrzej Adamczyk (at https://blackdev.org/). All rights reserved. 3 | ; GPL-3.0 License 4 | ; 5 | ; Main developer: 6 | ; Andrzej Adamczyk 7 | ;=============================================================================== 8 | 9 | ;----------------------------------------------------------------------- 10 | ; pierwsza część programu rozruchowego 11 | ;----------------------------------------------------------------------- 12 | incbin "build/bootsector" 13 | 14 | ;----------------------------------------------------------------------- 15 | ; główny plik programu rozruchowego 16 | ;----------------------------------------------------------------------- 17 | incbin "build/zero" 18 | 19 | ;----------------------------------------------------------------------- 20 | ; plik jądra systemu 21 | ;----------------------------------------------------------------------- 22 | incbin "build/kernel" 23 | 24 | ; VirtualBox wymaga obrazu o rozmiarze min. 1 MiB 25 | 26 | ; wyrównaj rozmiar obrazu dysku do pełnego 1,44 MiB 27 | times 1474560 - ($ - $$) db 0x00 28 | -------------------------------------------------------------------------------- /zero/page.asm: -------------------------------------------------------------------------------- 1 | ;=============================================================================== 2 | ; Copyright (C) Andrzej Adamczyk (at https://blackdev.org/). All rights reserved. 3 | ; GPL-3.0 License 4 | ; 5 | ; Main developer: 6 | ; Andrzej Adamczyk 7 | ;=============================================================================== 8 | 9 | ;=============================================================================== 10 | ; 16 bitowy kod głównego programu rozruchowego ================================= 11 | ;=============================================================================== 12 | [bits 32] 13 | 14 | ;=============================================================================== 15 | ; wejście: 16 | ; edi - adres w przestrzeni logicznej 17 | ; wyjście: 18 | ; edi - adres wyrównany do pełnej strony 19 | zero_page_align_up: 20 | ; utwórz zmienną lokalną 21 | push edi 22 | 23 | ; usuń młodszą część adresu 24 | and edi, 0xF000 25 | 26 | ; sprawdź czy adres jest identyczny z zmienną lokalną 27 | cmp edi, dword [esp] 28 | je .end ; jeśli tak, koniec 29 | 30 | ; przesuń adres o jedną ramkę do przodu 31 | add edi, 0x1000 32 | .end: 33 | ; usuń zmienną lokalną 34 | add esp, 0x04 35 | 36 | ; powrót z procedury 37 | ret 38 | -------------------------------------------------------------------------------- /zero/memory.asm: -------------------------------------------------------------------------------- 1 | ;=============================================================================== 2 | ; Copyright (C) Andrzej Adamczyk (at https://blackdev.org/). All rights reserved. 3 | ; GPL-3.0 License 4 | ; 5 | ; Main developer: 6 | ; Andrzej Adamczyk 7 | ;=============================================================================== 8 | 9 | ;=============================================================================== 10 | zero_memory: 11 | ; pozpocznij mapowanie od początku przestrzeni fizycznej pamięci 12 | xor ebx, ebx 13 | 14 | ; ciąg znaków "SMAP", specjalna wartość wymagana przez procedurę 15 | mov edx, 0x534D4150 16 | 17 | ; utwórz mapę pamięci pod fizycznym adresem końca programu rozruchowego 18 | mov edi, zero_end 19 | call zero_page_align_up 20 | 21 | ; zachowaj adres dla jądra systemu 22 | mov dword [zero_memory_map_address], edi 23 | 24 | .loop: 25 | ; pobierz informacje o przestrzeni pamięci 26 | mov eax, 0xE820 ; funkcja Get System Memory Map 27 | mov ecx, 0x14 ; rozmiar wpisu w Bajtach, generowanej tablicy 28 | int 0x15 29 | 30 | .error: 31 | ; błąd podczas generowania? 32 | jc .error ; tak 33 | 34 | ; przesuń wskaźnik do następnego wpisu 35 | add edi, 0x14 36 | 37 | ; zakończyć generowanie tablicy? 38 | test ebx, ebx 39 | jnz .loop ; nie 40 | 41 | ; wstaw pusty wpis na koniec tablicy 42 | xor al, al 43 | rep stosb 44 | -------------------------------------------------------------------------------- /zero/storage.asm: -------------------------------------------------------------------------------- 1 | ;=============================================================================== 2 | ; Copyright (C) Andrzej Adamczyk (at https://blackdev.org/). All rights reserved. 3 | ; GPL-3.0 License 4 | ; 5 | ; Main developer: 6 | ; Andrzej Adamczyk 7 | ;=============================================================================== 8 | 9 | ;=============================================================================== 10 | zero_storage: 11 | ; zachowaj orginalny segment ekstra 12 | push es 13 | 14 | ; adres docelowy jądra systemu 15 | mov ax, 0x1000 16 | mov es, ax ; segment 17 | xor bx, bx ; przesunięcie 18 | 19 | ; wyświetl informację o aktualnej czynności 20 | mov si, zero_string_header 21 | call zero_print_string 22 | mov si, zero_string_loading 23 | call zero_print_string 24 | 25 | ; plik jądra systemu 26 | mov cl, (((zero_end - zero) + 0x200) / 0x200) + 0x01 ; pozycja pliku jądra systemu za programem rozruchowym 27 | mov di, KERNEL_FILE_SIZE_bytes / 0x0200 ; rozmiar w sektorach 28 | call zero_floppy 29 | jnc .end ; wczytano popwanie 30 | 31 | ; wyświetl komunikat o błędzie 32 | mov si, zero_string_error_kernel 33 | call zero_print_string 34 | 35 | ; zatrzymaj dalsze wykonywanie kodu 36 | jmp $ 37 | 38 | ;----------------------------------------------------------------------- 39 | ; procedura wczytująca plik jądra systemu z nośnika 40 | ;----------------------------------------------------------------------- 41 | %include "zero/floppy.asm" 42 | 43 | zero_storage.end: 44 | ; przywróć oryginalny segment ekstra 45 | pop es 46 | -------------------------------------------------------------------------------- /zero/pic.asm: -------------------------------------------------------------------------------- 1 | ;=============================================================================== 2 | ; Copyright (C) Andrzej Adamczyk (at https://blackdev.org/). All rights reserved. 3 | ; GPL-3.0 License 4 | ; 5 | ; Main developer: 6 | ; Andrzej Adamczyk 7 | ;=============================================================================== 8 | 9 | ;=============================================================================== 10 | zero_pic: 11 | ; przełącz obydwa układy w tryb inicjalizacji 12 | mov al, 0x11 13 | out 0x20, al 14 | out 0xA0, al 15 | 16 | ; przeindeksuj pic0 (master) na przerwania od 0x20 do 0x27 17 | mov al, 0x20 18 | out 0x21, al 19 | 20 | ; przeindeksuj pic1 (slave) na przerwania od 0x28 do 0x2F 21 | mov al, 0x28 22 | out 0xA1, al 23 | 24 | ; pic0 ustaw jako główny (master) i poinformuj o istnieniu pic1 25 | mov al, 4 26 | out 0x21, al 27 | 28 | ; pic1 ustaw jako pomocniczy (slave) 29 | mov al, 2 30 | out 0xA1, al 31 | 32 | ; obydwa kontrolery w tryb 8086 33 | mov al, 1 34 | out 0x21, al 35 | out 0xA1, al 36 | 37 | ; wyłącz tymczasowo wszystkie przerwania sprzętowe 38 | ; nie powinny były być włączone, dmuchamy na zimne 39 | mov al, 11111111b ; irq15, irq14, irq13, irq12, irq11, irq10, irq9, irq8 40 | out 0xA1, al ; pic1 (slave) 41 | 42 | mov al, 11011110b ; irq7, irq6, sound, irq4, irq3, irq2, keyboard, sheduler/clock 43 | out 0x21, al ; pic0 (master) 44 | 45 | ; kontynuuj 46 | jmp zero_pic_end 47 | 48 | ;=============================================================================== 49 | zero_pic_disable: 50 | ; wyłącz przerwania na kontrolerze PIC 51 | mov al, 0xFF 52 | out 0x00A1, al ; Slave 53 | out 0x0021, al ; Master 54 | 55 | ; powrót z procedury 56 | ret 57 | 58 | ;=============================================================================== 59 | zero_pic_end: 60 | -------------------------------------------------------------------------------- /zero/protected_mode.asm: -------------------------------------------------------------------------------- 1 | ;=============================================================================== 2 | ; Copyright (C) Andrzej Adamczyk (at https://blackdev.org/). All rights reserved. 3 | ; GPL-3.0 License 4 | ; 5 | ; Main developer: 6 | ; Andrzej Adamczyk 7 | ;=============================================================================== 8 | 9 | ;=============================================================================== 10 | zero_protected_mode: 11 | ; wyłącz przerwania, jeśli program rozruchowy jest w trybie 16 bitowym 12 | ; zostaną one przywrócone 13 | cli 14 | 15 | ; załaduj globalną tablicę deskryptorów dla trybu 32 bitowego 16 | lgdt [zero_protected_mode_header_gdt_32bit] 17 | 18 | ; przełącz procesor w tryb chroniony 19 | mov eax, cr0 20 | bts eax, 0 ; włącz pierwszy bit rejestru cr0 21 | mov cr0, eax 22 | 23 | ; skocz do 32 bitowego kodu 24 | jmp long 0x0008:zero_protected_mode_entry 25 | 26 | ; wszystkie tablice trzymamy pod pełnym adresem 27 | align 0x10 28 | zero_protected_mode_table_gdt_32bit: 29 | ; deskryptor zerowy 30 | dq 0x0000000000000000 31 | ; deskryptor kodu 32 | dq 0000000011001111100110000000000000000000000000001111111111111111b 33 | ; deskryptor danych 34 | dq 0000000011001111100100100000000000000000000000001111111111111111b 35 | zero_protected_mode_table_gdt_32bit_end: 36 | 37 | zero_protected_mode_header_gdt_32bit: 38 | dw zero_protected_mode_table_gdt_32bit_end - zero_protected_mode_table_gdt_32bit - 0x01 39 | dd zero_protected_mode_table_gdt_32bit 40 | 41 | ;=============================================================================== 42 | ; 32 bitowy kod programu rozruchowego ========================================== 43 | ;=============================================================================== 44 | [bits 32] 45 | 46 | zero_protected_mode_entry: 47 | ; ustaw deskryptory danych, ekstra i stosu na przestrzeń danych 48 | mov ax, 0x10 49 | mov ds, ax ; segment danych 50 | mov es, ax ; segment ekstra 51 | mov ss, ax ; segment stosu 52 | -------------------------------------------------------------------------------- /zero/floppy.asm: -------------------------------------------------------------------------------- 1 | ;=============================================================================== 2 | ; Copyright (C) Andrzej Adamczyk (at https://blackdev.org/). All rights reserved. 3 | ; GPL-3.0 License 4 | ; 5 | ; Main developer: 6 | ; Andrzej Adamczyk 7 | ;=============================================================================== 8 | 9 | ;=============================================================================== 10 | ; wejście: 11 | ; cl - numer sektora 12 | ; es:bx - miejsce docelowe 13 | ; di - ilość sektorów 14 | ; wyjście: 15 | ; Flaga CF - jeśli błąd 16 | zero_floppy: 17 | ; zachowaj oryginalne rejestry 18 | push ax 19 | push bx 20 | push cx 21 | push dx 22 | push di 23 | push bp 24 | push es 25 | 26 | ; czytaj po jednym sektorze na raz 27 | mov al, 0x01 ; ładuj po jednym sektorze na raz 28 | mov ch, 0x00 ; pierwszy cylinder 29 | mov dh, 0x00 ; pierwsza głowica 30 | 31 | .reload: 32 | ; ilość prób odczytu sektora z nośnika 33 | mov bp, 0x03 34 | 35 | .loop: 36 | ; załaduj pierwszy sektor do pamięci 37 | mov ah, 0x02 38 | int 0x13 39 | jc .reset ; nie udało się odczytać sektora, zresetuj kontroler 40 | 41 | ; odczytać kolejne sektory z nośnika? 42 | dec di 43 | jz .end ; nie 44 | 45 | ; załaduj kolejny sektor 46 | inc cl 47 | 48 | ; na następną pozycję 49 | add bx, 0x0200 50 | 51 | ; to był ostatni sektor cylindra? 52 | cmp cl, 18 53 | jbe .reload ; nie 54 | 55 | ; "druga" głowica 56 | not dh 57 | and dh, 00000001b 58 | 59 | ; pierwszy sektor 60 | mov cl, 1 61 | 62 | ; obsłużono obydwie głowice? 63 | test dh, dh 64 | jnz .reload ; nie 65 | 66 | ; następnego cylindra 67 | inc ch 68 | 69 | ; to był ostatni cylinder głowicy? 70 | cmp ch, 80 71 | jb .reload ; nie 72 | 73 | ; flaga, błąd 74 | stc 75 | 76 | ; koniec procedury 77 | jmp .end 78 | 79 | .reset: 80 | ; pierwsza nieudana próba 81 | mov ah, 0x00 ; zresetuj kontroler 82 | int 0x13 83 | jnc .loop ; bez błędów, ponów odczyt sektora 84 | 85 | .end: 86 | ; przywróć oryginalne rejestry 87 | pop es 88 | pop bp 89 | pop di 90 | pop dx 91 | pop cx 92 | pop bx 93 | pop ax 94 | 95 | ; powrót z procedury 96 | ret 97 | -------------------------------------------------------------------------------- /zero/kernel.asm: -------------------------------------------------------------------------------- 1 | ;=============================================================================== 2 | ; Copyright (C) Andrzej Adamczyk (at https://blackdev.org/). All rights reserved. 3 | ; GPL-3.0 License 4 | ; 5 | ; Main developer: 6 | ; Andrzej Adamczyk 7 | ;=============================================================================== 8 | 9 | ;=============================================================================== 10 | zero_kernel: 11 | ; wyłącz przerwania sprzętowe na kontrolerze PIC 12 | call zero_pic_disable 13 | 14 | ; wyłącz obsługę wyjątków procesora i przerwań sprzętowych 15 | cli 16 | 17 | ; kopiuj kod jądra systemu w miejsce docelowe 18 | mov ecx, KERNEL_FILE_SIZE_bytes 19 | mov esi, 0x00010000 20 | mov edi, 0x00100000 21 | rep movsb 22 | 23 | ; kopiuj kod programu rozruchowego dla procesorów logicznych w miejsce docelowe 24 | mov ecx, zero_file_ap_end - zero_file_ap 25 | mov esi, zero_file_ap 26 | mov edi, zero 27 | rep movsb 28 | 29 | ; zwróć informację o adresie i rozmiarze mapy pamięci 30 | mov ebx, dword [zero_memory_map_address] 31 | 32 | ; zwróć informację o adresie tablicy ZERO_STRUCTURE_GRAPHICS_MODE_INFO_BLOCK 33 | mov edx, dword [zero_graphics_mode_info_block_address] 34 | 35 | ; odszukaj nagłówek "Z E R O " w całym pliku jądra systemu 36 | mov rax, "Z E R O " 37 | mov esi, 0x00100000 38 | mov ecx, KERNEL_FILE_SIZE_bytes / 0x08 39 | 40 | .search: 41 | ; przetworzono cały plik jądra systemu? 42 | sub ecx, 0x08 43 | js .error ; tak 44 | 45 | ; przesuń wskaźnik na następną pozycję 46 | add rsi, 0x08 47 | 48 | ; powównaj pierwsze 8 komórek pamięci 49 | cmp qword [rsi - 0x08], rax 50 | 51 | ; znaleziono nagłówek? 52 | jne .search ; nie 53 | 54 | ; zwróć informacje o rozmiarze pliku jądra systemu w Bajtach 55 | mov ecx, KERNEL_FILE_SIZE_bytes 56 | 57 | ; pobierz wskaźnik głównej funkcji jądra systemu 58 | mov rax, qword [rsi] 59 | 60 | ; wyczyść rejestry nie biorące udziału z procesie 61 | xor esi, esi 62 | xor edi, edi 63 | xor ebp, ebp 64 | 65 | ; ustaw tymczasowy szczyt stosu dla jądra systemu 66 | mov esp, zero ; na początek przestrzeni kodu programu rozruchowego Zero 67 | 68 | ; wykonaj kod 69 | jmp rax 70 | 71 | .error: 72 | ; zatrzymaj dalsze wykonywanie kodu 73 | hlt 74 | jmp .error 75 | -------------------------------------------------------------------------------- /bootsector.asm: -------------------------------------------------------------------------------- 1 | ;=============================================================================== 2 | ; Copyright (C) Andrzej Adamczyk (at https://blackdev.org/). All rights reserved. 3 | ; GPL-3.0 License 4 | ; 5 | ; Main developer: 6 | ; Andrzej Adamczyk 7 | ;=============================================================================== 8 | 9 | ;=============================================================================== 10 | ; 16 bitowy kod programu rozruchowego ========================================== 11 | ;=============================================================================== 12 | [bits 16] 13 | 14 | ; pozycja kodu/danych w przestrzeni pamięci fizycznej 15 | [org 0x7C00] 16 | 17 | ;=============================================================================== 18 | bootsector: 19 | ; wyłącz przerwania (modyfikujemy rejestry segmentowe) 20 | cli 21 | 22 | ; ustaw adres segmentu kodu (CS) na początek pamięci fizycznej 23 | jmp 0x0000:.repair_cs 24 | 25 | .header: 26 | ; nagłówek sektora rozruchowego wyrównaj do pełnego adresu 27 | align 0x04 28 | db "ZERO" 29 | 30 | .repair_cs: 31 | ; ustaw adresy segmentów danych (DS), ekstra (ES) i stosu (SS) na początek pamięci fizycznej 32 | xor ax, ax 33 | mov ds, ax ; segment danych 34 | mov es, ax ; segment ekstra 35 | mov ss, ax ; segment stosu 36 | 37 | ; ustaw wskaźnik szczytu stosu na gwarantowaną wolną przestrzeń pamięci 38 | mov sp, bootsector 39 | 40 | ; włącz przerwania 41 | sti 42 | 43 | ; załaduj drugą część programu rozruchowego 44 | mov bx, 0x1000 ; adres docelowy pogramu rozruchowego 45 | mov cl, 2 ; rozpocznij od "drugiego" sektora 46 | mov di, ZERO_FILE_SIZE_bytes / 0x0200 ; rozmiar programu rozruchowego 47 | call zero_floppy 48 | 49 | ; jeśli wczytano poprawnie główny kod programu rozruchowego, wykonaj 50 | jnc 0x1000 51 | 52 | ; zatrzymaj dalsze wykonywanie kodu programu rozruchowego 53 | jmp $ 54 | 55 | ;----------------------------------------------------------------------- 56 | %include "zero/floppy.asm" 57 | ;----------------------------------------------------------------------- 58 | 59 | ;------------------------------------------------------------------------------- 60 | ; znacznik sektora rozruchowego 61 | times 510 - ($ - $$) db 0x00 62 | dw 0xAA55 ; czysta magija ;> 63 | -------------------------------------------------------------------------------- /zero/data.asm: -------------------------------------------------------------------------------- 1 | ;=============================================================================== 2 | ; Copyright (C) Andrzej Adamczyk (at https://blackdev.org/). All rights reserved. 3 | ; GPL-3.0 License 4 | ; 5 | ; Main developer: 6 | ; Andrzej Adamczyk 7 | ;=============================================================================== 8 | 9 | zero_microtime dq 0x0000000000000000 10 | 11 | zero_memory_map_address dd 0x00000000 12 | zero_graphics_mode_info_block_address dd 0x00000000 13 | 14 | zero_string_new_line db 0x0D, 0x0A, " ", 0x00 15 | 16 | zero_string_header db 0x0A, " [Zero Bootloader]", 0x0D, 0x0A, 0x0D, 0x0A, 0x00 17 | zero_string_loading db " Loading kernel file... please wait.", 0x00 18 | zero_string_resolution db " Select (Up/Down)", 0x0D, 0x0A 19 | db " Confirm (Enter)", 0x00 20 | 21 | zero_string_error_kernel db 0x0D, 0x0A, 0x0D, 0x0A, " Please, check consistency of data on floppy disk.", 0x00 22 | zero_string_error_vbe db 0x0D, 0x0A, 0x0D, 0x0A, 0x0D, 0x0A, 0x0D, 0x0A, 0x0D, 0x0A, 0x0D, 0x0A, 0x0D, 0x0A, 0x0D, 0x0A, 0x0D, 0x0A, 0x0D, 0x0A, 0x0D, 0x0A, " VESA BIOS Extension not available. Cannot select graphics resolution.", 0x00 23 | 24 | ;------------------------------------------------------------------------------- 25 | ; format danych w postaci tablicy, wykorzystywany przez funkcję AH=0x42, przerwanie 0x13 26 | ; http://www.ctyme.com/intr/rb-0708.htm 27 | ;------------------------------------------------------------------------------- 28 | ; wszystkie tablice trzymamy pod pełnym adresem 29 | align 0x04 30 | zero_table_disk_address_packet: 31 | db 0x10 ; rozmiar tablicy 32 | db 0x00 ; wartość zastrzeżona 33 | dw 0x0001 ; wczytuj po jednym sektorze 34 | .offset: dw 0x0000 ; przesunięcie 35 | .segment: dw 0x1000 ; segment 36 | .sector: dq ((zero_end - zero) + 0x200) / 0x200 ; adres LBA pierwszego sektora dołączonego pliku jądra systemu 37 | 38 | ; wyrównaj pozycję nagłówka do pełnego adresu 39 | align 0x08, db 0x90 40 | zero_idt_header: 41 | dw 0x1000 42 | dq ZERO_IDT_address 43 | 44 | ; wyrównaj pozycję pliku do pełnego adresu 45 | align 0x08, db 0x90 46 | zero_file_ap: incbin "build/ap" 47 | zero_file_ap_end: 48 | 49 | ; wyrównaj rozmiar programu rozruchowego do pełnego rozmiaru sektora 50 | align 0x0200 51 | -------------------------------------------------------------------------------- /bochsrc-windows.bxrc: -------------------------------------------------------------------------------- 1 | # configuration file generated by Bochs 2 | plugin_ctrl: unmapped=true, biosdev=true, extfpuirq=true, serial=true 3 | config_interface: win32config 4 | display_library: win32, options="gui_debug" 5 | memory: host=8, guest=8 6 | romimage: file="..\bochs/BIOS-bochs-latest", address=0x00000000, options=none 7 | vgaromimage: file="..\bochs/VGABIOS-lgpl-latest" 8 | boot: floppy 9 | floppy_bootsig_check: disabled=0 10 | floppya: type=1_44, 1_44="build/cyjon.img", status=inserted, write_protected=0 11 | # no floppyb 12 | ata0: enabled=true, ioaddr1=0x1f0, ioaddr2=0x3f0, irq=14 13 | ata0-master: type=none 14 | ata0-slave: type=none 15 | ata1: enabled=true, ioaddr1=0x170, ioaddr2=0x370, irq=15 16 | ata1-master: type=none 17 | ata1-slave: type=none 18 | ata2: enabled=false 19 | ata3: enabled=false 20 | optromimage1: file=none 21 | optromimage2: file=none 22 | optromimage3: file=none 23 | optromimage4: file=none 24 | optramimage1: file=none 25 | optramimage2: file=none 26 | optramimage3: file=none 27 | optramimage4: file=none 28 | pci: enabled=1, chipset=i440fx, slot1=pcivga 29 | vga: extension=vbe, update_freq=60, realtime=1 30 | cpu: count=1, ips=4000000, model=bx_generic, reset_on_triple_fault=1, cpuid_limit_winnt=0, ignore_bad_msrs=1, mwait_is_nop=0 31 | cpuid: level=6, stepping=3, model=3, family=6, vendor_string="GenuineIntel", brand_string=" Intel(R) Pentium(R) 4 CPU " 32 | cpuid: mmx=true, apic=xapic_ext, simd=sse2, sse4a=false, misaligned_sse=false, sep=true 33 | cpuid: movbe=false, adx=false, aes=false, sha=false, xsave=false, xsaveopt=false, x86_64=true 34 | cpuid: 1g_pages=false, pcid=false, fsgsbase=false, smep=false, smap=false, mwait=true 35 | cpuid: vmx=1 36 | print_timestamps: enabled=0 37 | debugger_log: - 38 | magic_break: enabled=1 39 | port_e9_hack: enabled=0 40 | private_colormap: enabled=0 41 | clock: sync=realtime, time0=local, rtc_sync=1 42 | # no cmosimage 43 | log: - 44 | logprefix: %t%e%d 45 | debug: action=ignore 46 | info: action=report 47 | error: action=report 48 | panic: action=ask 49 | keyboard: type=mf, serial_delay=250, paste_delay=100000, user_shortcut=none 50 | mouse: type=ps2, enabled=false, toggle=ctrl+mbutton 51 | sound: waveoutdrv=win, waveout=none, waveindrv=win, wavein=none, midioutdrv=win, midiout=none 52 | com1: enabled=true, mode=null 53 | com2: enabled=false 54 | com3: enabled=false 55 | com4: enabled=false 56 | -------------------------------------------------------------------------------- /bochsrc-linux.bxrc: -------------------------------------------------------------------------------- 1 | # configuration file generated by Bochs 2 | plugin_ctrl: unmapped=true, biosdev=true, speaker=true, extfpuirq=true, parallel=true, serial=true, iodebug=true 3 | config_interface: textconfig 4 | display_library: x, options="gui_debug" 5 | memory: host=8, guest=8 6 | romimage: file="/usr/share/bochs/BIOS-bochs-latest", address=0x00000000, options=none 7 | vgaromimage: file="/usr/share/bochs/VGABIOS-lgpl-latest" 8 | boot: floppy 9 | floppy_bootsig_check: disabled=0 10 | floppya: type=1_44, 1_44="build/cyjon.img", status=inserted, write_protected=0 11 | # no floppyb 12 | ata0: enabled=true, ioaddr1=0x1f0, ioaddr2=0x3f0, irq=14 13 | ata0-master: type=none 14 | ata0-slave: type=none 15 | ata1: enabled=true, ioaddr1=0x170, ioaddr2=0x370, irq=15 16 | ata1-master: type=none 17 | ata1-slave: type=none 18 | ata2: enabled=false 19 | ata3: enabled=false 20 | optromimage1: file=none 21 | optromimage2: file=none 22 | optromimage3: file=none 23 | optromimage4: file=none 24 | optramimage1: file=none 25 | optramimage2: file=none 26 | optramimage3: file=none 27 | optramimage4: file=none 28 | pci: enabled=1, chipset=i440fx, slot1=pcivga 29 | vga: extension=vbe, update_freq=60, realtime=1 30 | cpu: count=1:2:1, ips=4000000, quantum=16, model=bx_generic, reset_on_triple_fault=1, cpuid_limit_winnt=0, ignore_bad_msrs=1, mwait_is_nop=0 31 | cpuid: level=6, stepping=3, model=3, family=6, vendor_string="AuthenticAMD", brand_string="AMD Athlon(tm) processor" 32 | cpuid: mmx=true, apic=xapic, simd=sse2, sse4a=false, misaligned_sse=false, sep=true 33 | cpuid: movbe=false, adx=false, aes=false, sha=false, xsave=false, xsaveopt=false, avx_f16c=false 34 | cpuid: avx_fma=false, bmi=0, xop=false, fma4=false, tbm=false, x86_64=true, 1g_pages=false 35 | cpuid: pcid=false, fsgsbase=false, smep=false, smap=false, mwait=true 36 | print_timestamps: enabled=0 37 | debugger_log: - 38 | magic_break: enabled=1 39 | port_e9_hack: enabled=0 40 | private_colormap: enabled=0 41 | clock: sync=realtime, time0=local, rtc_sync=1 42 | # no cmosimage 43 | log: - 44 | logprefix: %t%e%d 45 | debug: action=ignore 46 | info: action=report 47 | error: action=report 48 | panic: action=ask 49 | keyboard: type=mf, serial_delay=250, paste_delay=100000, user_shortcut=none 50 | mouse: type=ps2, enabled=false, toggle=ctrl+mbutton 51 | speaker: enabled=true, mode=system 52 | parport1: enabled=true, file=none 53 | parport2: enabled=false 54 | com1: enabled=true, mode=null 55 | com2: enabled=false 56 | com3: enabled=false 57 | com4: enabled=false 58 | -------------------------------------------------------------------------------- /kernel.asm: -------------------------------------------------------------------------------- 1 | ;=============================================================================== 2 | ; Copyright (C) Andrzej Adamczyk (at https://blackdev.org/). All rights reserved. 3 | ; GPL-3.0 License 4 | ; 5 | ; Main developer: 6 | ; Andrzej Adamczyk 7 | ;=============================================================================== 8 | 9 | struc KERNEL_VIDEO_STRUCTURE_MODE_INFO_BLOCK 10 | .mode_attributes resb 2 11 | .win_a_attributes resb 1 12 | .win_b_attributes resb 1 13 | .win_granularity resb 2 14 | .win_size resb 2 15 | .win_a_segment resb 2 16 | .win_b_segment resb 2 17 | .win_func_ptr resb 4 18 | .bytes_per_scanline resb 2 19 | .x_resolution resb 2 20 | .y_resolution resb 2 21 | .x_char_size resb 1 22 | .y_char_size resb 1 23 | .number_of_planes resb 1 24 | .bits_per_pixel resb 1 25 | .number_of_banks resb 1 26 | .memory_model resb 1 27 | .bank_size resb 1 28 | .number_of_image_pages resb 1 29 | .reserved0 resb 1 30 | .red_mask_size resb 1 31 | .red_field_position resb 1 32 | .green_mask_size resb 1 33 | .green_field_position resb 1 34 | .blue_mask_size resb 1 35 | .blue_field_position resb 1 36 | .rsvd_mask_size resb 1 37 | .direct_color_mode_info resb 2 38 | .physical_base_address resb 4 39 | .reserved1 resb 212 40 | endstruc 41 | 42 | ; 64 bitowy kod jądra systemu 43 | [bits 64] 44 | 45 | ; położenie kodu jądra systemu w pamięci fizycznej 46 | [org 0x0000000000100000] 47 | 48 | ; nagłówek poszukiwany przez program rozruchowy Zero 49 | align 0x08 ; wyrównaj nagłówek do pełnego adresu 50 | header: 51 | db "Z E R O " ; czysta magija 52 | dq kernel ; wskaźnik do głównej procedury jądra systemu 53 | 54 | ;=============================================================================== 55 | kernel: 56 | ; domyślny kolor tła 57 | mov eax, 0x00D400C5 58 | 59 | ; pobierz ilość pikseli na osi Y 60 | mov bx, word [rdx + KERNEL_VIDEO_STRUCTURE_MODE_INFO_BLOCK.y_resolution] 61 | 62 | ; pobierz adres fizyczny przestrzeni pamięci karty graficznej 63 | mov edi, dword [rdx + KERNEL_VIDEO_STRUCTURE_MODE_INFO_BLOCK.physical_base_address] 64 | 65 | .loop: 66 | ; pobierz ilość pikseli na osi X 67 | mov cx, word [rdx + KERNEL_VIDEO_STRUCTURE_MODE_INFO_BLOCK.x_resolution] 68 | rep stosd 69 | 70 | ; wypełniono całą przestrzeń? 71 | dec bx 72 | jnz .loop ; nie 73 | 74 | ; zatrzymaj dalsze wykonywanie kodu jądra systemu 75 | jmp $ 76 | 77 | ; wyrównaj kod jądra systemu do pełnego rozmiaru strony 78 | align 0x1000 79 | -------------------------------------------------------------------------------- /zero/print.asm: -------------------------------------------------------------------------------- 1 | ;=============================================================================== 2 | ; Copyright (C) Andrzej Adamczyk (at https://blackdev.org/). All rights reserved. 3 | ; GPL-3.0 License 4 | ; 5 | ; Main developer: 6 | ; Andrzej Adamczyk 7 | ;=============================================================================== 8 | 9 | ;=============================================================================== 10 | ; 16 bitowy kod 11 | ;=============================================================================== 12 | [bits 16] 13 | 14 | ;=============================================================================== 15 | ; wejście: 16 | ; al - znak ASCII 17 | zero_print_char: 18 | ; zachowaj oryginalne rejestry 19 | push ax 20 | 21 | ; wyświetl znak na ekranie 22 | mov ah, 0x0E 23 | int 0x10 24 | 25 | ; przywróć oryginalne rejestry 26 | pop ax 27 | 28 | ; powrót z procedury 29 | ret 30 | 31 | ;=============================================================================== 32 | ; wejście: 33 | ; si - wskaźnik do ciągu znaków zakończony terminatorem 0x00 34 | zero_print_string: 35 | ; zachowaj oryginalne rejestry 36 | push ax 37 | push si 38 | 39 | .loop: 40 | ; pobierz do AL wartość z adresu pod wskaźnikiem SI, zwiększ wskaźnik SI o 1 41 | lodsb 42 | 43 | ; sprawdź czy koniec tekstu do wyświetlenia 44 | cmp al, 0x00 ; jeśli ZERO, zakończ 45 | je .end 46 | 47 | ; wyświetl znak na ekranie 48 | call zero_print_char 49 | 50 | ; załaduj i wyświetl następny znak 51 | jmp .loop 52 | 53 | .end: 54 | ; przywróć oryginalne rejestry 55 | pop si 56 | pop ax 57 | 58 | ; powrót z procedury 59 | ret 60 | 61 | ;=============================================================================== 62 | ; wejście: 63 | ; ax - wartość do wyświetlenia 64 | zero_print_number: 65 | ; zachowaj oryginalne rejestry 66 | push ax 67 | push cx 68 | push dx 69 | push sp 70 | push bp 71 | 72 | ; system dziesiętny 73 | mov cx, 10 74 | 75 | ; wyczść resztę/ starszą część 76 | xor dx, dx 77 | 78 | ; zapamiętaj koniec bufora danych 79 | mov bp, sp 80 | 81 | .calculate: 82 | ; podziel dx:ax przez cx 83 | div cx 84 | 85 | ; odstaw resztę z dzielenia do bufora 86 | push dx 87 | 88 | ; wyczść resztę/ starszą część 89 | xor dx, dx 90 | 91 | ; sprawdź czy zostało jeszcze coś do przeliczenia 92 | cmp ax, 0x0000 93 | jne .calculate ; jeśli tak, powtórz operacje 94 | 95 | .print: 96 | ; pobierz z bufora najstarszą cyfre 97 | pop ax 98 | 99 | ; procedura - wyświetl znak w miejscu kursora, przesuń kursor w prawo 100 | mov ah, 0x0E 101 | 102 | ; sprawdź czy znak spoza cyfr 103 | cmp al, 0x0A 104 | jb .digit 105 | 106 | ; zamień cyfre na kod ASCII (A..F) 107 | add al, 0x3A 108 | 109 | ; kontynuuj 110 | jmp .continue 111 | 112 | .digit: 113 | ; zamień cyfre na kod ASCII (0..9) 114 | add al, 0x30 115 | 116 | .continue: 117 | ; wyświetl cyfre na ekranie 118 | int 0x10 119 | 120 | ; sprawdź czy zostało coś jeszcze w buforze 121 | cmp bp, sp 122 | jne .print ; jeśli tak, kontynuuj 123 | 124 | ; przywróć oryginalne rejestry 125 | pop bp 126 | pop sp 127 | pop dx 128 | pop cx 129 | pop ax 130 | 131 | ; powrót z procedury 132 | ret 133 | -------------------------------------------------------------------------------- /zero.asm: -------------------------------------------------------------------------------- 1 | ;=============================================================================== 2 | ; Copyright (C) Andrzej Adamczyk (at https://blackdev.org/). All rights reserved. 3 | ; GPL-3.0 License 4 | ; 5 | ; Main developer: 6 | ; Andrzej Adamczyk 7 | ;=============================================================================== 8 | 9 | %define PROGRAM_NAME "zero" 10 | %define PROGRAM_VERSION "1.0" 11 | 12 | ;=============================================================================== 13 | ; 16 bitowy kod głównego programu rozruchowego ================================= 14 | ;=============================================================================== 15 | [bits 16] 16 | 17 | ; pozycja kodu w przestrzeni segmentu CS 18 | [org 0x1000] 19 | 20 | ;=============================================================================== 21 | zero: 22 | ; inicjalizuj tryb tekstowy 80x25 23 | mov ax, 0x0003 24 | int 0x10 25 | 26 | ;----------------------------------------------------------------------- 27 | ; wczytaj plik jadra systemu 28 | ;----------------------------------------------------------------------- 29 | %include "zero/storage.asm" 30 | 31 | ;----------------------------------------------------------------------- 32 | ; przygotuj mapę pamięci 33 | ;----------------------------------------------------------------------- 34 | %include "zero/memory.asm" 35 | 36 | ;----------------------------------------------------------------------- 37 | ; włącz tryb graficzny 38 | ;----------------------------------------------------------------------- 39 | %include "zero/graphics.asm" 40 | 41 | ;----------------------------------------------------------------------- 42 | ; przełącz procesor w tryb 32 bitowy 43 | ;----------------------------------------------------------------------- 44 | %include "zero/protected_mode.asm" 45 | 46 | ;----------------------------------------------------------------------- 47 | ; przełącz procesor w tryb 64 bitowy 48 | ;----------------------------------------------------------------------- 49 | %include "zero/long_mode.asm" 50 | 51 | ;----------------------------------------------------------------------- 52 | ; konfiguruj obslugę wyjątków i przerwań sprzętowych 53 | ;----------------------------------------------------------------------- 54 | %include "zero/idt.asm" 55 | 56 | ;----------------------------------------------------------------------- 57 | ; włącz przerwania sprzętowe na kontrolerze PIC 58 | ;----------------------------------------------------------------------- 59 | %include "zero/pic.asm" 60 | 61 | ;----------------------------------------------------------------------- 62 | ; wyłącz przerwanie na kontrolerze PIT 63 | ;----------------------------------------------------------------------- 64 | %include "zero/pit.asm" 65 | 66 | ;----------------------------------------------------------------------- 67 | ; przekaż wszystkie niezbędne informacje do jadra systemu 68 | ;----------------------------------------------------------------------- 69 | %include "zero/kernel.asm" 70 | 71 | ;----------------------------------------------------------------------- 72 | ; procedura zaokrąglająca adres do pełnej strony 73 | ;----------------------------------------------------------------------- 74 | %include "zero/page.asm" 75 | 76 | ;----------------------------------------------------------------------- 77 | ; procedury wyświetlające litery/znaki/cyfry 78 | ;----------------------------------------------------------------------- 79 | %include "zero/print.asm" 80 | 81 | ;----------------------------------------------------------------------- 82 | ; zmienne programu rozruchowego 83 | ;----------------------------------------------------------------------- 84 | %include "zero/data.asm" 85 | 86 | ;=============================================================================== 87 | zero_end: 88 | -------------------------------------------------------------------------------- /zero/idt.asm: -------------------------------------------------------------------------------- 1 | ;=============================================================================== 2 | ; Copyright (C) Andrzej Adamczyk (at https://blackdev.org/). All rights reserved. 3 | ; GPL-3.0 License 4 | ; 5 | ; Main developer: 6 | ; Andrzej Adamczyk 7 | ;=============================================================================== 8 | 9 | ZERO_IDT_address equ 0x9000 10 | 11 | ZERO_IDT_TYPE_exception equ 0x8E00 12 | ZERO_IDT_TYPE_irq equ 0x8F00 13 | 14 | struc ZERO_STRUCTURE_IDT_HEADER 15 | .limit resb 2 16 | .address resb 8 17 | endstruc 18 | 19 | ;=============================================================================== 20 | zero_idt: 21 | ; zarejestruj wszystkie wyjątki procesora pod domyślną procedurę obsługi 22 | mov rax, zero_idt_default_exception 23 | mov bx, ZERO_IDT_TYPE_exception 24 | mov ecx, 32 ; wszystkie wyjątki procesora 25 | mov edi, ZERO_IDT_address 26 | call zero_idt_set 27 | 28 | ; podłącz procedurę obsługi przerwania zegara 29 | mov rax, zero_idt_clock 30 | mov bx, ZERO_IDT_TYPE_irq 31 | mov ecx, 1 32 | call zero_idt_set 33 | 34 | ; zarejestruj pozostałe przerwania sprzętowe pod domyślną procedurę obsługi 35 | mov rax, zero_idt_default_interrupt 36 | mov ecx, 15 ; pozostałe przerwania sprzętowe 37 | call zero_idt_set 38 | 39 | ; załaduj Tablicę Deskryptorów Przerwań 40 | lidt [zero_idt_header] 41 | 42 | ; włącz obsługę przerwań 43 | sti 44 | 45 | ; kontynuuj 46 | jmp zero_idt_end 47 | 48 | ;=============================================================================== 49 | zero_idt_default_exception: 50 | ; powrót z przerwania wyjątku procesora 51 | iretq 52 | 53 | ;=============================================================================== 54 | zero_idt_default_interrupt: 55 | ; zachowaj oryginalne rejestry 56 | push rax 57 | 58 | ; zaakceptuj przerwnaie 59 | mov al, 0x20 60 | out 0x20, al 61 | 62 | ; przywróćoryginalne rejestry 63 | pop rax 64 | 65 | ; powrót z przerwania sprzętowego 66 | iretq 67 | 68 | ;=============================================================================== 69 | zero_idt_clock: 70 | ; zachowaj oryginalne rejestry 71 | push rax 72 | 73 | ; zwiększ mikrotime 74 | inc qword [zero_microtime] 75 | 76 | ; zaakceptuj przerwnaie 77 | mov al, 0x20 78 | out 0x20, al 79 | 80 | ; przywróćoryginalne rejestry 81 | pop rax 82 | 83 | ; powrót z przerwania sprzętowego 84 | iretq 85 | 86 | ;=============================================================================== 87 | ; wejście: 88 | ; rax - adres logiczny procedury obsługi 89 | ; bx - typ: wyjątek, przerwanie(sprzętowe, programowe) 90 | ; rcx - ilość kolejnych rekordów o tej samej procedurze obsługi 91 | ; rdi - adres rekordu do modyfikacji w Tablicy Deskryptorów Przerwań 92 | ; wyjście: 93 | ; rdi - adres kolejnego rekordu w Tablicy Deskryptorów Przerwań 94 | zero_idt_set: 95 | ; zachowaj oryginalne rejestry 96 | push rcx 97 | 98 | .next: 99 | ; zachowaj adres procedury obsługi 100 | push rax 101 | 102 | ; załaduj do tablicy adres obsługi wyjątku (bity 15...0) 103 | stosw 104 | 105 | ; selektor deskryptora kodu (GDT), wszystkie procedury wywoływane są z uprawnieniami ring0 106 | mov ax, 0x08 107 | stosw 108 | 109 | ; typ: wyjątek, przerwanie(sprzętowe, programowe) 110 | mov ax, bx 111 | stosw 112 | 113 | ; przywróć adres procedury obsługi 114 | mov rax, qword [rsp] 115 | 116 | ; przemieszczamy do ax bity 31...16 117 | shr rax, 16 118 | stosw 119 | 120 | ; przemieszczamy do eax bity 63...32 121 | shr rax, 32 122 | stosd 123 | 124 | ; pola zastrzeżone, zostawiamy puste 125 | xor eax, eax 126 | stosd 127 | 128 | ; przywróć adres procedury obsługi 129 | pop rax 130 | 131 | ; przetwórz pozostałe rekordy 132 | dec rcx 133 | jnz .next 134 | 135 | ; przywróć oryginalne rejestry 136 | pop rcx 137 | 138 | ; powrót z procedury 139 | ret 140 | 141 | ;=============================================================================== 142 | zero_idt_end: 143 | -------------------------------------------------------------------------------- /zero/long_mode.asm: -------------------------------------------------------------------------------- 1 | ;=============================================================================== 2 | ; Copyright (C) Andrzej Adamczyk (at https://blackdev.org/). All rights reserved. 3 | ; GPL-3.0 License 4 | ; 5 | ; Main developer: 6 | ; Andrzej Adamczyk 7 | ;=============================================================================== 8 | 9 | ZERO_LONG_MODE_PML4_address equ 0x0000A000 10 | 11 | ZERO_LONG_MODE_PAGE_SIZE_bytes equ 0x1000 * 0x06 ; tablica PML4, PML3 i cztery razy PML2 (1 GiB opisanej przestrzeni na każdą tablicę PML2) 12 | 13 | ZERO_LONG_MODE_PAGE_FLAG_available equ 00000001b 14 | ZERO_LONG_MODE_PAGE_FLAG_writeable equ 00000010b 15 | ZERO_LONG_MODE_PAGE_FLAG_2MiB_size equ 10000000b 16 | ZERO_LONG_MODE_PAGE_FLAG_default equ ZERO_LONG_MODE_PAGE_FLAG_available | ZERO_LONG_MODE_PAGE_FLAG_writeable 17 | 18 | ;=============================================================================== 19 | zero_long_mode: 20 | ;----------------------------------------------------------------------- 21 | ; utwórz podstawową tablicę stronicowania dla trybu 64 bitowego 22 | ;----------------------------------------------------------------------- 23 | 24 | ; wyczyść wszystkie wpisy w tablicach PML 25 | xor eax, eax 26 | mov ecx, ZERO_LONG_MODE_PAGE_SIZE_bytes / 0x04 27 | mov edi, ZERO_LONG_MODE_PML4_address 28 | rep stosd 29 | 30 | ; przywróć wskaźnik do tabliy PML4 31 | mov edi, ZERO_LONG_MODE_PML4_address 32 | 33 | ; uzupełnij pierwszy wiersz tablicy PML4 wskazujący adres tablicy PML3 (flagi domyślne) 34 | mov dword [edi], edi 35 | add dword [edi], 0x1000 + ZERO_LONG_MODE_PAGE_FLAG_default 36 | 37 | ; uzupełnij 4 wiersze tablicy PML3 wskazujące na adresy tablic PML2 (flagi domyślne) 38 | mov dword [edi + 0x1000], edi 39 | add dword [edi + 0x1000], (0x1000 * 0x02) + ZERO_LONG_MODE_PAGE_FLAG_default 40 | mov dword [edi + 0x1000 + 0x08], edi 41 | add dword [edi + 0x1000 + 0x08], (0x1000 * 0x03) + ZERO_LONG_MODE_PAGE_FLAG_default 42 | mov dword [edi + 0x1000 + 0x10], edi 43 | add dword [edi + 0x1000 + 0x10], (0x1000 * 0x04) + ZERO_LONG_MODE_PAGE_FLAG_default 44 | mov dword [edi + 0x1000 + 0x18], edi 45 | add dword [edi + 0x1000 + 0x18], (0x1000 * 0x05) + ZERO_LONG_MODE_PAGE_FLAG_default 46 | 47 | ; uzupełnij wszystkie wiersze tablic PML2 (flagi domyślne + każdy wpis opisuje przestrzeń fizyczną o rozmiarze 2 MiB) 48 | mov eax, ZERO_LONG_MODE_PAGE_FLAG_default + ZERO_LONG_MODE_PAGE_FLAG_2MiB_size ; flagi: rozmiar strony 2 MiB, zapisywalna, dostępna 49 | mov ecx, 512 * 0x04 ; 512 wierszy na jedną tablicę PML2 50 | add edi, 0x1000 * 0x02 ; adres pierwszej tablicy PML2 51 | 52 | .next: 53 | ; konfiguruj wpis 54 | stosd 55 | 56 | ; przesuń wskaźnik na następny wiersz tablicy 57 | add edi, 0x04 ; każdy wpis ma rozmiar 8 Bajtów (tryb 64 bitowy) 58 | 59 | ; mapuj następne 2 MiB przestrzeni pamięci fizycznej 60 | add eax, 0x00200000 61 | 62 | ; pozostały wiersze do uzupełnienia? 63 | dec ecx 64 | jnz .next ; tak 65 | 66 | ;----------------------------------------------------------------------- 67 | ; załaduj globalną tablicę deskryptorów dla trybu 64 bitowego 68 | ;----------------------------------------------------------------------- 69 | lgdt [zero_long_mode_header_gdt_64bit] 70 | 71 | ; włącz bity NX/PAE, PGE oraz OSFXSR w rejestrze CR4 72 | mov eax, 1010100000b ; NX (bit 5) - blokada wykonania kodu w stronie lub obsługa pamięci fizycznej do 64 GiB 73 | mov cr4, eax ; PGE (bit 7) - obsługa stronicowania 74 | ; OSFXSR (bit 9) - obsługa rejestrów XMM0-15 75 | 76 | ; załaduj do CR3 adres fizyczny tablicy PML4 programu rozruchowego 77 | mov eax, ZERO_LONG_MODE_PML4_address 78 | mov cr3, eax 79 | 80 | ; włącz w rejestrze EFER MSR tryb LME (bit 9) 81 | mov ecx, 0xC0000080 ; adres EFER MSR 82 | rdmsr 83 | or eax, 100000000b 84 | wrmsr 85 | 86 | ; włącz bity PE i PG w rejestrze cr0 87 | mov eax, cr0 88 | or eax, 0x80000001 ; PE (bit 0) - wyłącz tryb rzeczywisty, 89 | mov cr0, eax ; PG (bit 31) - współdzielenie tablic stronicowania 90 | 91 | ; skocz do 64 bitowego kodu programu rozruchowego 92 | jmp 0x0008:zero_long_mode_entry 93 | 94 | ; wszystkie tablice pod adresem wyrównanym do 0x08 Bajtów 95 | align 0x08 96 | zero_long_mode_table_gdt_64bit: 97 | ; deskryptor zerowy 98 | dq 0x0000000000000000 99 | ; deskryptor kodu 100 | dq 0000000000100000100110000000000000000000000000000000000000000000b 101 | ; deskryptor danych 102 | dq 0000000000100000100100100000000000000000000000000000000000000000b 103 | zero_long_mode_table_gdt_64bit_end: 104 | 105 | zero_long_mode_header_gdt_64bit: 106 | dw zero_long_mode_table_gdt_64bit_end - zero_long_mode_table_gdt_64bit - 0x01 107 | dd zero_long_mode_table_gdt_64bit 108 | 109 | ;=============================================================================== 110 | ; 64 bitowy kod programu rozruchowego ========================================== 111 | ;=============================================================================== 112 | [bits 64] 113 | 114 | ;=============================================================================== 115 | zero_long_mode_entry: 116 | -------------------------------------------------------------------------------- /zero/ap.asm: -------------------------------------------------------------------------------- 1 | ;=============================================================================== 2 | ; Copyright (C) Andrzej Adamczyk (at https://blackdev.org/). All rights reserved. 3 | ;=============================================================================== 4 | 5 | ;=============================================================================== 6 | ; 16 bitowy kod programu rozruchowego dla procesorów logicznych ================ 7 | ;=============================================================================== 8 | [BITS 16] 9 | 10 | ; pozycja kodu w przestrzeni segmentu CS 11 | [ORG 0x1000] 12 | 13 | boot: 14 | ;----------------------------------------------------------------------- 15 | ; przygotuj 32 bitowe środowisko produkcyjne 16 | ;----------------------------------------------------------------------- 17 | 18 | ; wyłącz przerwania 19 | cli 20 | 21 | ; ustaw adres segmentu kodu (CS) na początek pamięci fizycznej 22 | jmp 0x0000:.repair_cs 23 | 24 | .repair_cs: 25 | ; ustaw adresy segmentów danych (DS), ekstra (ES) i stosu (SS) na początek pamięci fizycznej 26 | xor ax, ax 27 | mov ds, ax ; segment danych 28 | mov es, ax ; segment ekstra 29 | 30 | ; wyłącz Direction Flag 31 | cld 32 | 33 | ; załaduj globalną tablicę deskryptorów dla trybu 32 bitowego 34 | lgdt [boot_header_gdt_32bit] 35 | 36 | ; przełącz procesor w tryb chroniony 37 | mov eax, cr0 38 | bts eax, 0 ; włącz pierwszy bit rejestru cr0 39 | mov cr0, eax 40 | 41 | ; skocz do 32 bitowego kodu programu rozruchowego 42 | jmp long 0x0008:boot_protected_mode 43 | 44 | ;------------------------------------------------------------------------------- 45 | align 0x10 ; wszystkie tablice trzymamy pod pełnym adresem 46 | boot_table_gdt_32bit: 47 | ; deskryptor zerowy 48 | dq 0x0000000000000000 49 | ; deskryptor kodu 50 | dq 0000000011001111100110000000000000000000000000001111111111111111b 51 | ; deskryptor danych 52 | dq 0000000011001111100100100000000000000000000000001111111111111111b 53 | boot_table_gdt_32bit_end: 54 | 55 | boot_header_gdt_32bit: 56 | dw boot_table_gdt_32bit_end - boot_table_gdt_32bit - 0x01 57 | dd boot_table_gdt_32bit 58 | 59 | ;=============================================================================== 60 | ; 32 bitowy kod programu rozruchowego dla procesorów logicznych ================ 61 | ;=============================================================================== 62 | [BITS 32] 63 | 64 | boot_protected_mode: 65 | ; ustaw deskryptory danych, ekstra i stosu na przestrzeń danych 66 | mov ax, 0x10 67 | mov ds, ax ; segment danych 68 | mov es, ax ; segment ekstra 69 | 70 | ;----------------------------------------------------------------------- 71 | ; załaduj globalną tablicę deskryptorów dla trybu 64 bitowego 72 | ;----------------------------------------------------------------------- 73 | lgdt [boot_header_gdt_64bit] 74 | 75 | ; włącz bity NX/PAE, PGE oraz OSFXSR w rejestrze CR4 76 | mov eax, 1010100000b ; NX (bit 5) - blokada wykonania kodu w stronie lub obsługa pamięci fizycznej do 64 GiB 77 | mov cr4, eax ; PGE (bit 7) - obsługa stronicowania 78 | ; OSFXSR (bit 9) - obsługa rejestrów XMM0-15 79 | 80 | ; załaduj do CR3 adres fizyczny tablicy PML4 programu rozruchowego 81 | mov eax, 0x0000A000 ; adres zależny od tablic stronicowania programu rozruchowego Zero 82 | mov cr3, eax 83 | 84 | ; włącz w rejestrze EFER MSR tryb LME (bit 9) 85 | mov ecx, 0xC0000080 ; adres EFER MSR 86 | rdmsr 87 | or eax, 100000000b 88 | wrmsr 89 | 90 | ; włącz bity PE i PG w rejestrze cr0 91 | mov eax, cr0 92 | or eax, 0x80000001 ; PE (bit 0) - wyłącz tryb rzeczywisty, 93 | mov cr0, eax ; PG (bit 31) - współdzielenie tablic stronicowania 94 | 95 | ; skocz do 64 bitowego kodu programu rozruchowego dla procesorów logicznych 96 | jmp 0x0008:boot_long_mode 97 | 98 | ; wszystkie tablice pod adresem wyrównanym do 0x08 Bajtów 99 | align 0x10 100 | boot_table_gdt_64bit: 101 | ; deskryptor zerowy 102 | dq 0x0000000000000000 103 | ; deskryptor kodu 104 | dq 0000000000100000100110000000000000000000000000000000000000000000b 105 | ; deskryptor danych 106 | dq 0000000000100000100100100000000000000000000000000000000000000000b 107 | boot_table_gdt_64bit_end: 108 | 109 | boot_header_gdt_64bit: 110 | dw boot_table_gdt_64bit_end - boot_table_gdt_64bit - 0x01 111 | dd boot_table_gdt_64bit 112 | 113 | ;=============================================================================== 114 | ; 64 bitowy kod programu rozruchowego dla procesorów logicznych ================ 115 | ;=============================================================================== 116 | [BITS 64] 117 | 118 | ;=============================================================================== 119 | boot_long_mode: 120 | ; odszukaj nagłówek "Z E R O " w całym pliku jądra systemu 121 | mov rax, "Z E R O " 122 | mov esi, 0x00100000 123 | 124 | .search: 125 | ; przesuń wskaźnik na następną pozycję 126 | add rsi, 0x08 127 | 128 | ; powównaj pierwsze 8 komórek pamięci 129 | cmp qword [rsi - 0x08], rax 130 | 131 | ; znaleziono nagłówek? 132 | jne .search ; nie 133 | 134 | ; ustaw tymczasowy szczyt stosu dla jądra systemu 135 | mov esp, boot ; na początek przestrzeni kodu programu rozruchowego 136 | 137 | ; pobierz wskaźnik głównej funkcji jądra systemu 138 | push qword [rsi] 139 | 140 | ; wyczyść rejestry nie biorące udziału z procesie 141 | xor eax, eax 142 | xor ecx, ecx 143 | xor esi, esi 144 | 145 | ; wykonaj główną procedurę jądra systemu 146 | ret 147 | 148 | ; koniec kodu programu rozruchowego dla procesorów logicznych 149 | boot_end: 150 | -------------------------------------------------------------------------------- /zero/graphics.asm: -------------------------------------------------------------------------------- 1 | ;=============================================================================== 2 | ; Copyright (C) Andrzej Adamczyk (at https://blackdev.org/). All rights reserved. 3 | ; GPL-3.0 License 4 | ; 5 | ; Main developer: 6 | ; Andrzej Adamczyk 7 | ;=============================================================================== 8 | 9 | ZERO_GRAPHICS_DEPTH_bit equ 32 10 | ZERO_GRAPHICS_DEPTH_shift equ 2 11 | ZERO_GRAPHICS_MODE_clean equ 0x8000 12 | ZERO_GRAPHICS_MODE_linear equ 0x4000 13 | 14 | ZERO_GRAPHICS_RESOLUTION_list equ 25 15 | 16 | struc ZERO_STRUCTURE_GRAPHICS_VGA_INFO_BLOCK 17 | .vesa_signature resb 4 18 | .vesa_version resb 2 19 | .oem_string_ptr resb 4 20 | .capabilities resb 4 21 | .video_mode_ptr resb 4 22 | .total_memory resb 2 23 | .reserved resb 236 24 | endstruc 25 | 26 | struc ZERO_STRUCTURE_GRAPHICS_MODE_INFO_BLOCK 27 | .mode_attributes resb 2 28 | .win_a_attributes resb 1 29 | .win_b_attributes resb 1 30 | .win_granularity resb 2 31 | .win_size resb 2 32 | .win_a_segment resb 2 33 | .win_b_segment resb 2 34 | .win_func_ptr resb 4 35 | .bytes_per_scanline resb 2 36 | .x_resolution resb 2 37 | .y_resolution resb 2 38 | .x_char_size resb 1 39 | .y_char_size resb 1 40 | .number_of_planes resb 1 41 | .bits_per_pixel resb 1 42 | .number_of_banks resb 1 43 | .memory_model resb 1 44 | .bank_size resb 1 45 | .number_of_image_pages resb 1 46 | .reserved0 resb 1 47 | .red_mask_size resb 1 48 | .red_field_position resb 1 49 | .green_mask_size resb 1 50 | .green_field_position resb 1 51 | .blue_mask_size resb 1 52 | .blue_field_position resb 1 53 | .rsvd_mask_size resb 1 54 | .direct_color_mode_info resb 2 55 | .physical_base_address resb 4 56 | .reserved1 resb 212 57 | .SIZE: 58 | endstruc 59 | 60 | ;=============================================================================== 61 | zero_graphics: 62 | ; wyczyść przestrzeń trybu tekstowego 63 | mov ax, 0x0003 64 | int 0x10 65 | 66 | ; wyrównaj adres końca mapy pamięci do pełnej strony 67 | call zero_page_align_up 68 | 69 | ; zachowaj adres tablicy GRAPHICS_MODE_INFO_BLOCK 70 | mov dword [zero_graphics_mode_info_block_address], edi 71 | 72 | ; pobierz dostępne tryby graficzne 73 | mov ax, 0x4F00 74 | add edi, ZERO_STRUCTURE_GRAPHICS_MODE_INFO_BLOCK.SIZE 75 | int 0x10 76 | 77 | ; funkcja wywołana prawidłowo? 78 | test ax, 0x4F00 79 | jnz .error ; nie 80 | 81 | ; wyświetl dostępne rozdzielczości 82 | mov si, zero_string_header 83 | call zero_print_string 84 | mov si, zero_string_resolution 85 | call zero_print_string 86 | 87 | ; ustaw kursor na początek wtorzonej listy dostępnych rozdzielczości 88 | mov ah, 0x02 89 | mov dx, 0x0002 90 | int 0x10 91 | 92 | ; zmień kształt kursora na "blok" 93 | mov al, 0x0A 94 | mov dx, 0x03D4 95 | out dx, al 96 | mov al, 0x00 97 | inc dx 98 | out dx, al 99 | 100 | ; wyświetl maksymalnie N trybów 101 | mov dx, ZERO_GRAPHICS_RESOLUTION_list 102 | 103 | ; przygotuj przestrzeń pod listę trybów 104 | sub sp, ZERO_GRAPHICS_RESOLUTION_list * 0x02 105 | mov bp, sp 106 | sub bp, 0x02 ; korekcja względem pętli 107 | 108 | ; przeszukaj tablicę dostępnych trybów za porządanym 109 | mov esi, dword [di + ZERO_STRUCTURE_GRAPHICS_VGA_INFO_BLOCK.video_mode_ptr] 110 | 111 | .loop: 112 | ; koniec tablicy? 113 | cmp word [esi], 0xFFFF 114 | je .ready ; tak 115 | 116 | ; pobierz właściwości danego trybu graficznego 117 | mov ax, 0x4F01 118 | mov cx, word [esi] 119 | mov edi, dword [zero_graphics_mode_info_block_address] 120 | int 0x10 121 | 122 | ; oczekiwana głębia kolorów? 123 | cmp byte [di + ZERO_STRUCTURE_GRAPHICS_MODE_INFO_BLOCK.bits_per_pixel], ZERO_GRAPHICS_DEPTH_bit 124 | jne .next ; nie 125 | 126 | ; rozmiar scanline odpowiada szerokości w pikselach? 127 | mov ax, word [di + ZERO_STRUCTURE_GRAPHICS_MODE_INFO_BLOCK.x_resolution] 128 | shl ax, ZERO_GRAPHICS_DEPTH_shift 129 | cmp ax, word [di + ZERO_STRUCTURE_GRAPHICS_MODE_INFO_BLOCK.bytes_per_scanline] 130 | jne .next ; nie 131 | 132 | ; ustaw wskaźnik na wolny rekord 133 | add bp, 0x02 134 | 135 | ; zachowaj identyfikator rozdzielczości 136 | mov ax, word [esi] 137 | mov word [bp], ax 138 | 139 | ; wyświetl dostępną rozdzielczość 140 | call .show 141 | 142 | ; wyświetlono N trybów graficznych? 143 | dec dx 144 | jz .ready ; tak 145 | 146 | .next: 147 | ; przesuń wskaźnik na następny wpis 148 | add esi, 0x02 149 | 150 | ; sprawdź następny tryb 151 | jmp .loop 152 | 153 | .error: 154 | ; wyświetl komunikat błędu 155 | mov si, zero_string_error_vbe 156 | call zero_print_string 157 | 158 | ; zatrzymaj dalsze wykonywanie kodu 159 | jmp $ 160 | 161 | .show: 162 | ; zachowaj oryginalne rejestry 163 | push ax 164 | push si 165 | 166 | ; szerokość w pikselaxch 167 | mov ax, word [di + ZERO_STRUCTURE_GRAPHICS_MODE_INFO_BLOCK.x_resolution] 168 | call zero_print_number 169 | 170 | mov al, "x" 171 | call zero_print_char 172 | 173 | ; wysokość w pikselach 174 | mov ax, word [di + ZERO_STRUCTURE_GRAPHICS_MODE_INFO_BLOCK.y_resolution] 175 | call zero_print_number 176 | 177 | ; ustaw kursor na następną linię 178 | mov si, zero_string_new_line 179 | call zero_print_string 180 | 181 | ; przywróć oryginalne rejestry 182 | pop si 183 | pop ax 184 | 185 | ; powrót z podprocedury 186 | ret 187 | 188 | .select: 189 | ; zachowaj informacje 190 | push cx 191 | 192 | ; rozpocznij od pierwszego trybu 193 | xor cx, cx 194 | 195 | ; ustaw kursor na pierwszy element listy 196 | mov ah, 0x02 197 | xor dx, dx 198 | int 0x10 199 | 200 | .key: 201 | ; pobierz klawisz od użyszkodnika 202 | xor ah, ah 203 | int 0x16 204 | 205 | ; klawisz enter? 206 | cmp al, 0x0D 207 | je .done ; tak 208 | 209 | ; klawisz "strzałka w górę?" 210 | cmp ah, 0x48 211 | jne .no_arrow_up ; nie 212 | 213 | ; kursor znajduje się już na początku listy? 214 | test cx, cx 215 | jz .key ; tak, zignoruj 216 | 217 | ; poprzednia pozycja na liście 218 | dec cx 219 | 220 | ; przesuń wskaźnik na wpis 221 | sub bp, 0x02 222 | 223 | ; ustaw kursor na wybraną pozycję 224 | mov ah, 0x02 225 | dec dh 226 | int 0x10 227 | 228 | ; kontynuuj 229 | jmp .key 230 | 231 | .no_arrow_up: 232 | ; klawisz "strzałka w dół"? 233 | cmp ah, 0x50 234 | jne .key ; nie 235 | 236 | ; kursor znajduje się już na końcu listy? 237 | cmp cx, word [esp] 238 | je .key ; tak, zignoruj 239 | 240 | ; następna pozycja na liście 241 | inc cx 242 | 243 | ; przesuń wskaźnik na wpis 244 | add bp, 0x02 245 | 246 | ; ustaw kursor na wybraną pozycję 247 | mov ah, 0x02 248 | inc dh 249 | int 0x10 250 | 251 | ; kontynuuj 252 | jmp .key 253 | 254 | .done: 255 | ; usuń zmienną lokalną 256 | pop cx 257 | 258 | ; pobierz wybrany tryb graficzny 259 | mov cx, word [bp] 260 | 261 | ; powrót z podprocedury 262 | ret 263 | 264 | .ready: 265 | ; ustaw wskaźnik na początek listy 266 | mov bp, sp 267 | 268 | ; wylicz ilość wyświetlonych trybów 269 | mov cx, ZERO_GRAPHICS_RESOLUTION_list 270 | sub cx, dx 271 | dec cx 272 | 273 | ; czekaj na użyszkodnika aż wybierze jeden z trybów graficznych 274 | call .select 275 | 276 | ; pobierz właściwości danego trybu graficznego 277 | mov ax, 0x4F01 278 | push cx 279 | int 0x10 280 | 281 | ; włącz dany tryb graficzny 282 | mov ax, 0x4F02 283 | pop bx 284 | or bx, ZERO_GRAPHICS_MODE_linear | ZERO_GRAPHICS_MODE_clean 285 | int 0x10 286 | 287 | ; operacja wykonana pomyślnie? 288 | test ah, ah 289 | jnz .error ; nie 290 | --------------------------------------------------------------------------------