├── .gdbinit ├── .gitignore ├── .gitmodules ├── CONTRIBUTING.md ├── LICENSE ├── Makefile ├── README.md ├── limine.cfg ├── screenshots ├── KnutOS interrupt screen.png ├── KnutOS serial communication.png ├── KnutOS shell.png ├── KnutOS silent boot.png └── KnutOS verbose boot.png ├── sfn_fonts ├── 3270.sfn ├── symbola.sfn └── unifont.sfn └── src ├── kernel ├── assembly │ └── definitions.inc ├── boot │ ├── boot_screen.c │ ├── boot_screen.h │ ├── stivale2.h │ ├── stivale2_boot.c │ └── stivale2_boot.h ├── devices │ ├── apic │ │ ├── apic.c │ │ └── apic.h │ ├── cpu │ │ ├── cpu.c │ │ └── cpu.h │ ├── framebuffer │ │ ├── framebuffer.c │ │ └── framebuffer.h │ ├── pic │ │ ├── pic.c │ │ └── pic.h │ ├── ps2 │ │ └── keyboard │ │ │ ├── keyboard.c │ │ │ └── keyboard.h │ └── serial │ │ ├── serial.c │ │ └── serial.h ├── firmware │ └── acpi │ │ ├── acpi.c │ │ ├── acpi.h │ │ └── tables │ │ ├── madt.c │ │ ├── madt.h │ │ ├── rsdp.c │ │ ├── rsdp.h │ │ ├── rsdt.h │ │ └── sdth.h ├── gdt │ ├── gdt.c │ ├── gdt.h │ └── gdt_asm.s ├── interrupts │ ├── idt.c │ ├── idt.h │ ├── idt_asm.s │ ├── interrupts.c │ ├── interrupts.h │ └── isr_asm.s ├── kernel.c ├── linker.ld ├── logo.c ├── logo.h ├── memory │ ├── mem.h │ ├── pmm.c │ ├── pmm.h │ ├── slab.c │ ├── slab.h │ ├── vmm.c │ └── vmm.h └── shell │ ├── shell_screen.c │ └── shell_screen.h └── libs └── libk ├── alloc ├── bitmap.c ├── bitmap.h ├── kmalloc.c └── kmalloc.h ├── debug ├── debug.c └── debug.h ├── definitions.h ├── graphics ├── double_buffering.c └── double_buffering.h ├── io ├── io.c └── io.h ├── kprintf ├── kprintf.c └── kprintf.h ├── log ├── log.c └── log.h ├── math ├── math.c └── math.h ├── ssfn.h ├── stdio ├── stdio.c └── stdio.h └── string ├── string.c └── string.h /.gdbinit: -------------------------------------------------------------------------------- 1 | file src/kernel/kernel.elf 2 | target remote localhost:1234 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | logo_stuff 2 | original_fonts 3 | *.elf 4 | *.iso 5 | *.o 6 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "third_party/limine"] 2 | path = third_party/limine 3 | url = https://github.com/limine-bootloader/limine/ 4 | branch = v2.0-branch-binary 5 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing to KnutOS 2 | 3 | When contributing to KnutOS, it is important that the changes you wish to make are in line with the project direction. If you are not sure about this, use GitHub Discussions, so we can talk about your ideas. 4 | 5 | For your first pull request, start with something small to get familiar with the project and its development processes. 6 | 7 | **NOTE: I would be very glad if someone could help me get the PIT to work or test 5-level paging (as QEMU isn't capable of it) :)** 8 | 9 | ## Coding style 10 | 11 | It is also important that the coding style is the same across the whole project. Because of that, we make use of the syntax formatting tool [Artistic Style](http://astyle.sourceforge.net/). 12 | 13 | It is expected that you run this tool before committing; the command can be conveniently invoked using ```make format```. The package "astyle" must be installed in order for that to work. 14 | 15 | Commits which have not done this will be rejected. 16 | 17 | ## Comments 18 | 19 | The next important thing is that your code must be documented with short and consise comments. 20 | 21 | ## Copyright headers 22 | 23 | We greatly appreciate your contributions, however you must understand that a `[fix] typo` commit cannot be credited in the copyright header. 24 | 25 | ``` 26 | /* 27 | This file is part of an x86_64 hobbyist operating system called KnutOS 28 | Everything is openly developed on GitHub: https://github.com/Tix3Dev/KnutOS/ 29 | 30 | Copyright (C) 2021-2022 Yves Vollmeier 31 | This program is free software: you can redistribute it and/or modify 32 | it under the terms of the GNU General Public License as published by 33 | the Free Software Foundation, either version 3 of the License, or 34 | (at your option) any later version. 35 | This program is distributed in the hope that it will be useful, 36 | but WITHOUT ANY WARRANTY; without even the implied warranty of 37 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 38 | GNU General Public License for more details. 39 | You should have received a copy of the GNU General Public License 40 | along with this program. If not, see . 41 | 42 | Contributor(s): foo 43 | */ 44 | ``` 45 | 46 | - If you have made a *significant* contribution place your name (`Prename Name `) next to the `Contributer(s)` field where it says `foo`. If this fieled doesn't exist, please create it. 47 | Multiple contributers should be separated by commas and a newline may be inserted where the list gets too lengthy (if you have to scroll sideways to see your name). 48 | If a newline has been inserted please indent it with 1 tab of the length of 4 spaces 49 | 50 | - What does and doesn't qualify for you to place your name in the `Contributer(s)` field: 51 | - Does: Fixing a security bug, adding some new notable feature (emphasis on notable), or a nasty bug (something that has a very negative impact on the kernel/OS such as a corruption of xyz due to faulty code) 52 | 53 | - Doesn't: Fixing a typo, correcting a constant, adding variables, refactoring code, adding minor features (a minor feature would be something like a utility function or a wrapper function) 54 | 55 | ## Commiting 56 | 57 | Now that you have followed all of the rules mentioned earlier, you are ready to commit. But it is important to know how. 58 | 59 | First of all, split your work into logically seperated commits. 60 | 61 | Then describe the commit as short and consise as possible in the commit message. They have to follow the following structure: 62 | 63 | ```[new] short and consise description``` for new features 64 | 65 | ```[fix] short and consise description``` for stuff that you had to change in order to make something work 66 | 67 | ```[refactor] short and consise description``` for stuff that you changed in order to make it better 68 | 69 | ```[doc] short and consise description``` for changes in the documentation 70 | 71 | ## Communication 72 | 73 | In case you have any questions or desires about/for the project, please use GitHub Discussions to talk to us. 74 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # This file is part of an x86_64 hobbyist operating system called KnutOS 2 | # Everything is openly developed on GitHub: https://github.com/Tix3Dev/KnutOS/ 3 | # 4 | # Copyright (C) 2021-2022 Yves Vollmeier 5 | # This program is free software: you can redistribute it and/or modify 6 | # it under the terms of the GNU General Public License as published by 7 | # the Free Software Foundation, either version 3 of the License, or 8 | # (at your option) any later version. 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU General Public License for more details. 13 | # You should have received a copy of the GNU General Public License 14 | # along with this program. If not, see . 15 | 16 | TARGET := src/kernel/kernel.elf 17 | ISO_IMAGE := disk.iso 18 | 19 | ARCH = @x86_64-elf 20 | 21 | CC = $(ARCH)-gcc 22 | AS = @nasm 23 | LD = $(ARCH)-ld 24 | 25 | # for full optimization use -O3 and don't use -ggdb 26 | # currently it's balanced out between optimization and debugging 27 | CC_FLAGS = -Wall -Wextra -O2 -pipe -ggdb 28 | AS_FLAGS = -felf64 29 | LD_FLAGS = 30 | 31 | INTERNAL_LD_FLAGS := \ 32 | -Tsrc/kernel/linker.ld \ 33 | -nostdlib \ 34 | -static \ 35 | -zmax-page-size=0x1000 \ 36 | --no-dynamic-linker \ 37 | -ztext 38 | # -pie 39 | 40 | INTERNAL_CC_FLAGS := \ 41 | -Isrc/kernel/ \ 42 | -Isrc/libs \ 43 | -std=gnu11 \ 44 | -ffreestanding \ 45 | -fno-stack-protector \ 46 | -fno-pic -fpie \ 47 | -mno-80387 \ 48 | -mno-mmx \ 49 | -mno-3dnow \ 50 | -mno-sse \ 51 | -mno-sse2 \ 52 | -mno-red-zone 53 | 54 | C_FILES := $(shell find src/ -type f -name '*.c') 55 | AS_FILES := $(shell find src/ -type f -name '*.s') 56 | 57 | C_OBJ = $(C_FILES:.c=.o) 58 | AS_OBJ = $(AS_FILES:.s=.o) 59 | OBJ = $(C_OBJ) $(AS_OBJ) 60 | 61 | .PHONY: all clean format run 62 | 63 | all: $(TARGET) 64 | 65 | run: $(ISO_IMAGE) 66 | qemu-system-x86_64 -M q35 -m 2G -serial stdio -cdrom $(ISO_IMAGE) 67 | 68 | debug: $(ISO_IMAGE) 69 | qemu-system-x86_64 -M q35 -m 2G -serial stdio -cdrom $(ISO_IMAGE) -s -S 70 | 71 | limine: 72 | make -C third_party/limine 73 | 74 | $(TARGET): $(OBJ) 75 | $(LD) -r -b binary -o src/kernel/devices/framebuffer/font_unifont.o sfn_fonts/unifont.sfn 76 | $(LD) src/kernel/devices/framebuffer/font_unifont.o $(OBJ) $(LD_FLAGS) $(INTERNAL_LD_FLAGS) -o $@ 77 | @printf "\n\n \(^ᴗ^)/ Kernel compiled and linked successfully \(^ᴗ^)/ \n\n" 78 | 79 | 80 | $(ISO_IMAGE): limine $(TARGET) 81 | rm -rf iso_root 82 | mkdir -p iso_root 83 | cp $(TARGET) \ 84 | limine.cfg third_party/limine/limine.sys \ 85 | third_party/limine/limine-cd.bin \ 86 | third_party/limine/limine-eltorito-efi.bin iso_root/ 87 | xorriso -as mkisofs -b limine-cd.bin \ 88 | -no-emul-boot -boot-load-size 4 -boot-info-table \ 89 | --efi-boot limine-eltorito-efi.bin \ 90 | -efi-boot-part --efi-boot-image --protective-msdos-label \ 91 | iso_root -o $(ISO_IMAGE) 92 | third_party/limine/limine-install $(ISO_IMAGE) 93 | rm -rf iso_root 94 | 95 | %.o: %.c 96 | @printf " [CC]\t$<\n"; 97 | $(CC) $(CC_FLAGS) $(INTERNAL_CC_FLAGS) -c $< -o $@ 98 | 99 | %.o: %.s 100 | @printf " [AS]\t$<\n"; 101 | $(AS) $(AS_FLAGS) $< -o $@ 102 | 103 | clean: 104 | rm -rf $(TARGET) $(OBJ) $(ISO_IMAGE) 105 | 106 | format: 107 | astyle --mode=c -nA1fpxgHxbxjxpS $(C_FILES) 108 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |
2 | 3 | # KnutOS 4 | 5 | #### _An x86_64 hobbyist OS made for FUN and LEARNING! It is written in C and Assembly and features a monolithic kernel._ 6 | 7 |

8 | 9 | ## Screenshots 10 | 11 | 12 | *⤷ Silent boot* 13 | 14 | 15 | *⤷ Verbose boot* 16 | 17 | 18 | *⤷ Shell* 19 | 20 | 21 | *⤷ Interrupt screen* 22 | 23 | 24 | *⤷ Local terminal showing serial communication* 25 | 26 | ## Features 27 | 28 | - Limine bootloader 29 | - Stivale2 boot protocol 30 | - GDT 31 | - TSS 32 | - IDT & ISR's 33 | - Physical memory manager -> Bitmap based 34 | - Virtual memory manager -> 4- & 5-level paging 35 | - Slab allocator 36 | - ACPI table parsing 37 | - Local APIC 38 | - Serial communication 39 | - Basic framebuffer 40 | - Basic keyboard driver with a small shell 41 | - Basic kernel libraries 42 | 43 | ## Future Features 44 | 45 | - ACPI Parser (custom or ACPICA) 46 | - C standard library port 47 | - ELF loader 48 | - IPC support 49 | - SMP 50 | - Double buffering 51 | - Compositor 52 | - GUI library 53 | 54 | ## Dependencies 55 | 56 | **NOTE: Depending on your Linux Distribution the package names might be different (supposing you are using Linux)** 57 | 58 | - x86_64-elf-binutils 59 | - x86_64-elf-gcc 60 | - nasm-git 61 | - make 62 | - xorriso 63 | - qemu 64 | 65 | ## Installation 66 | 67 | - Install the dependencies 68 | - Get the repository 69 | - git clone https://github.com/Tix3Dev/KnutOS --recursive 70 | - cd KnutOS 71 | - Build it 72 | - make all 73 | - Run it 74 | - make run 75 | 76 | ## Contributing 77 | 78 | For those interested in contributing, please refer to the [contributing guidelines](https://github.com/Tix3Dev/KnutOS/blob/main/CONTRIBUTING.md). 79 | -------------------------------------------------------------------------------- /limine.cfg: -------------------------------------------------------------------------------- 1 | TIMEOUT=10 2 | 3 | :KnutOS 4 | 5 | KASLR=no 6 | 7 | PROTOCOL=stivale2 8 | 9 | KERNEL_PATH=boot:///kernel.elf 10 | -------------------------------------------------------------------------------- /screenshots/KnutOS interrupt screen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tix3Dev/KnutOS/30b71e99912de6c2bbe21a7313fceb4ace55bcb5/screenshots/KnutOS interrupt screen.png -------------------------------------------------------------------------------- /screenshots/KnutOS serial communication.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tix3Dev/KnutOS/30b71e99912de6c2bbe21a7313fceb4ace55bcb5/screenshots/KnutOS serial communication.png -------------------------------------------------------------------------------- /screenshots/KnutOS shell.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tix3Dev/KnutOS/30b71e99912de6c2bbe21a7313fceb4ace55bcb5/screenshots/KnutOS shell.png -------------------------------------------------------------------------------- /screenshots/KnutOS silent boot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tix3Dev/KnutOS/30b71e99912de6c2bbe21a7313fceb4ace55bcb5/screenshots/KnutOS silent boot.png -------------------------------------------------------------------------------- /screenshots/KnutOS verbose boot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tix3Dev/KnutOS/30b71e99912de6c2bbe21a7313fceb4ace55bcb5/screenshots/KnutOS verbose boot.png -------------------------------------------------------------------------------- /sfn_fonts/3270.sfn: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tix3Dev/KnutOS/30b71e99912de6c2bbe21a7313fceb4ace55bcb5/sfn_fonts/3270.sfn -------------------------------------------------------------------------------- /sfn_fonts/symbola.sfn: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tix3Dev/KnutOS/30b71e99912de6c2bbe21a7313fceb4ace55bcb5/sfn_fonts/symbola.sfn -------------------------------------------------------------------------------- /sfn_fonts/unifont.sfn: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tix3Dev/KnutOS/30b71e99912de6c2bbe21a7313fceb4ace55bcb5/sfn_fonts/unifont.sfn -------------------------------------------------------------------------------- /src/kernel/assembly/definitions.inc: -------------------------------------------------------------------------------- 1 | ; This file is part of an x86_64 hobbyist operating system called KnutOS 2 | ; Everything is openly developed on GitHub: https://github.com/Tix3Dev/KnutOS/ 3 | ; 4 | ; Copyright (C) 2021-2022 Yves Vollmeier 5 | ; This program is free software: you can redistribute it and/or modify 6 | ; it under the terms of the GNU General Public License as published by 7 | ; the Free Software Foundation, either version 3 of the License, or 8 | ; (at your option) any later version. 9 | ; This program is distributed in the hope that it will be useful, 10 | ; but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | ; GNU General Public License for more details. 13 | ; You should have received a copy of the GNU General Public License 14 | ; along with this program. If not, see . 15 | 16 | %macro pusha64 0 17 | push rax 18 | push rbx 19 | push rcx 20 | push rdx 21 | push rbp 22 | push rdi 23 | push rsi 24 | push r8 25 | push r9 26 | push r10 27 | push r11 28 | push r12 29 | push r13 30 | push r14 31 | push r15 32 | %endmacro 33 | 34 | %macro popa64 0 35 | pop rax 36 | pop rbx 37 | pop rcx 38 | pop rdx 39 | pop rbp 40 | pop rdi 41 | pop rsi 42 | pop r8 43 | pop r9 44 | pop r10 45 | pop r11 46 | pop r12 47 | pop r13 48 | pop r14 49 | pop r15 50 | %endmacro 51 | -------------------------------------------------------------------------------- /src/kernel/boot/boot_screen.c: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of an x86_64 hobbyist operating system called KnutOS 3 | Everything is openly developed on GitHub: https://github.com/Tix3Dev/KnutOS/ 4 | 5 | Copyright (C) 2021-2022 Yves Vollmeier 6 | This program is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see . 16 | */ 17 | 18 | #include 19 | #include 20 | #include 21 | #include 22 | 23 | // show splashscreen aka silent bootscreen 24 | void silent_boot_screen(void) 25 | { 26 | printk(GFX_BLUE, "\nWelcome to:\n"); 27 | printk(GFX_BLUE, "%s", big_logo); 28 | 29 | // printk(GFX_BLACK, "█color█ "); /* same color as background so no need to show it */ 30 | printk(GFX_RED, "█color█ "); 31 | printk(GFX_GREEN, "█color█ "); 32 | printk(GFX_YELLOW, "█color█ "); 33 | printk(GFX_BLUE, "█color█ "); 34 | printk(GFX_PURPLE, "█color█ "); 35 | printk(GFX_CYAN, "█color█ "); 36 | printk(GFX_WHITE, "█color█\n"); 37 | } 38 | 39 | // show scrolling text information (like in the serial console) 40 | void verbose_boot_screen(void) 41 | { 42 | // 43 | } 44 | 45 | // switch bootscreen by pressing f1 46 | void switch_boot_screen(void) 47 | { 48 | // 49 | } 50 | -------------------------------------------------------------------------------- /src/kernel/boot/boot_screen.h: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of an x86_64 hobbyist operating system called KnutOS 3 | Everything is openly developed on GitHub: https://github.com/Tix3Dev/KnutOS/ 4 | 5 | Copyright (C) 2021-2022 Yves Vollmeier 6 | This program is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see . 16 | */ 17 | 18 | #ifndef BOOT_SCREEN_H 19 | #define BOOT_SCREEN_H 20 | 21 | void silent_boot_screen(void); 22 | void verbose_boot_screen(void); 23 | void switch_boot_screen(void); 24 | 25 | #endif 26 | -------------------------------------------------------------------------------- /src/kernel/boot/stivale2.h: -------------------------------------------------------------------------------- 1 | #ifndef __STIVALE__STIVALE2_H__ 2 | #define __STIVALE__STIVALE2_H__ 3 | 4 | #include 5 | 6 | // Anchor for non ELF kernels 7 | struct stivale2_anchor { 8 | uint8_t anchor[15]; 9 | uint8_t bits; 10 | uint64_t phys_load_addr; 11 | uint64_t phys_bss_start; 12 | uint64_t phys_bss_end; 13 | uint64_t phys_stivale2hdr; 14 | } __attribute__((__packed__)); 15 | 16 | struct stivale2_tag { 17 | uint64_t identifier; 18 | uint64_t next; 19 | } __attribute__((__packed__)); 20 | 21 | /* --- Header --------------------------------------------------------------- */ 22 | /* Information passed from the kernel to the bootloader */ 23 | 24 | struct stivale2_header { 25 | uint64_t entry_point; 26 | uint64_t stack; 27 | uint64_t flags; 28 | uint64_t tags; 29 | } __attribute__((__packed__)); 30 | 31 | #define STIVALE2_HEADER_TAG_ANY_VIDEO_ID 0xc75c9fa92a44c4db 32 | 33 | struct stivale2_header_tag_any_video { 34 | struct stivale2_tag tag; 35 | uint64_t preference; 36 | } __attribute__((packed)); 37 | 38 | #define STIVALE2_HEADER_TAG_FRAMEBUFFER_ID 0x3ecc1bc43d0f7971 39 | 40 | struct stivale2_header_tag_framebuffer { 41 | struct stivale2_tag tag; 42 | uint16_t framebuffer_width; 43 | uint16_t framebuffer_height; 44 | uint16_t framebuffer_bpp; 45 | } __attribute__((__packed__)); 46 | 47 | #define STIVALE2_HEADER_TAG_FB_MTRR_ID 0x4c7bb07731282e00 48 | 49 | #define STIVALE2_HEADER_TAG_TERMINAL_ID 0xa85d499b1823be72 50 | 51 | struct stivale2_header_tag_terminal { 52 | struct stivale2_tag tag; 53 | uint64_t flags; 54 | uint64_t callback; 55 | } __attribute__((__packed__)); 56 | 57 | #define STIVALE2_TERM_CB_DEC 10 58 | #define STIVALE2_TERM_CB_BELL 20 59 | 60 | #define STIVALE2_HEADER_TAG_SMP_ID 0x1ab015085f3273df 61 | 62 | struct stivale2_header_tag_smp { 63 | struct stivale2_tag tag; 64 | uint64_t flags; 65 | } __attribute__((__packed__)); 66 | 67 | #define STIVALE2_HEADER_TAG_5LV_PAGING_ID 0x932f477032007e8f 68 | 69 | #define STIVALE2_HEADER_TAG_UNMAP_NULL_ID 0x92919432b16fe7e7 70 | 71 | /* --- Struct --------------------------------------------------------------- */ 72 | /* Information passed from the bootloader to the kernel */ 73 | 74 | struct stivale2_struct { 75 | #define STIVALE2_BOOTLOADER_BRAND_SIZE 64 76 | char bootloader_brand[STIVALE2_BOOTLOADER_BRAND_SIZE]; 77 | 78 | #define STIVALE2_BOOTLOADER_VERSION_SIZE 64 79 | char bootloader_version[STIVALE2_BOOTLOADER_VERSION_SIZE]; 80 | 81 | uint64_t tags; 82 | } __attribute__((__packed__)); 83 | 84 | #define STIVALE2_STRUCT_TAG_PMRS_ID 0x5df266a64047b6bd 85 | 86 | #define STIVALE2_PMR_EXECUTABLE ((uint64_t)1 << 0) 87 | #define STIVALE2_PMR_WRITABLE ((uint64_t)1 << 1) 88 | #define STIVALE2_PMR_READABLE ((uint64_t)1 << 2) 89 | 90 | struct stivale2_pmr { 91 | uint64_t base; 92 | uint64_t length; 93 | uint64_t permissions; 94 | } __attribute__((packed)); 95 | 96 | struct stivale2_struct_tag_pmrs { 97 | struct stivale2_tag tag; 98 | uint64_t entries; 99 | struct stivale2_pmr pmrs[]; 100 | } __attribute__((packed)); 101 | 102 | #define STIVALE2_STRUCT_TAG_CMDLINE_ID 0xe5e76a1b4597a781 103 | 104 | struct stivale2_struct_tag_cmdline { 105 | struct stivale2_tag tag; 106 | uint64_t cmdline; 107 | } __attribute__((__packed__)); 108 | 109 | #define STIVALE2_STRUCT_TAG_MEMMAP_ID 0x2187f79e8612de07 110 | 111 | #define STIVALE2_MMAP_USABLE 1 112 | #define STIVALE2_MMAP_RESERVED 2 113 | #define STIVALE2_MMAP_ACPI_RECLAIMABLE 3 114 | #define STIVALE2_MMAP_ACPI_NVS 4 115 | #define STIVALE2_MMAP_BAD_MEMORY 5 116 | #define STIVALE2_MMAP_BOOTLOADER_RECLAIMABLE 0x1000 117 | #define STIVALE2_MMAP_KERNEL_AND_MODULES 0x1001 118 | #define STIVALE2_MMAP_FRAMEBUFFER 0x1002 119 | 120 | struct stivale2_mmap_entry { 121 | uint64_t base; 122 | uint64_t length; 123 | uint32_t type; 124 | uint32_t unused; 125 | } __attribute__((__packed__)); 126 | 127 | struct stivale2_struct_tag_memmap { 128 | struct stivale2_tag tag; 129 | uint64_t entries; 130 | struct stivale2_mmap_entry memmap[]; 131 | } __attribute__((__packed__)); 132 | 133 | #define STIVALE2_STRUCT_TAG_FRAMEBUFFER_ID 0x506461d2950408fa 134 | 135 | #define STIVALE2_FBUF_MMODEL_RGB 1 136 | 137 | struct stivale2_struct_tag_framebuffer { 138 | struct stivale2_tag tag; 139 | uint64_t framebuffer_addr; 140 | uint16_t framebuffer_width; 141 | uint16_t framebuffer_height; 142 | uint16_t framebuffer_pitch; 143 | uint16_t framebuffer_bpp; 144 | uint8_t memory_model; 145 | uint8_t red_mask_size; 146 | uint8_t red_mask_shift; 147 | uint8_t green_mask_size; 148 | uint8_t green_mask_shift; 149 | uint8_t blue_mask_size; 150 | uint8_t blue_mask_shift; 151 | } __attribute__((__packed__)); 152 | 153 | #define STIVALE2_STRUCT_TAG_EDID_ID 0x968609d7af96b845 154 | 155 | struct stivale2_struct_tag_edid { 156 | struct stivale2_tag tag; 157 | uint64_t edid_size; 158 | uint8_t edid_information[]; 159 | } __attribute__((__packed__)); 160 | 161 | #define STIVALE2_STRUCT_TAG_TEXTMODE_ID 0x38d74c23e0dca893 162 | 163 | struct stivale2_struct_tag_textmode { 164 | struct stivale2_tag tag; 165 | uint64_t address; 166 | uint16_t unused; 167 | uint16_t rows; 168 | uint16_t cols; 169 | uint16_t bytes_per_char; 170 | } __attribute__((packed)); 171 | 172 | #define STIVALE2_STRUCT_TAG_FB_MTRR_ID 0x6bc1a78ebe871172 173 | 174 | #define STIVALE2_STRUCT_TAG_TERMINAL_ID 0xc2b3f4c3233b0974 175 | 176 | struct stivale2_struct_tag_terminal { 177 | struct stivale2_tag tag; 178 | uint32_t flags; 179 | uint16_t cols; 180 | uint16_t rows; 181 | uint64_t term_write; 182 | uint64_t max_length; 183 | } __attribute__((__packed__)); 184 | 185 | #define STIVALE2_STRUCT_TAG_MODULES_ID 0x4b6fe466aade04ce 186 | 187 | struct stivale2_module { 188 | uint64_t begin; 189 | uint64_t end; 190 | 191 | #define STIVALE2_MODULE_STRING_SIZE 128 192 | char string[STIVALE2_MODULE_STRING_SIZE]; 193 | } __attribute__((__packed__)); 194 | 195 | struct stivale2_struct_tag_modules { 196 | struct stivale2_tag tag; 197 | uint64_t module_count; 198 | struct stivale2_module modules[]; 199 | } __attribute__((__packed__)); 200 | 201 | #define STIVALE2_STRUCT_TAG_RSDP_ID 0x9e1786930a375e78 202 | 203 | struct stivale2_struct_tag_rsdp { 204 | struct stivale2_tag tag; 205 | uint64_t rsdp; 206 | } __attribute__((__packed__)); 207 | 208 | #define STIVALE2_STRUCT_TAG_EPOCH_ID 0x566a7bed888e1407 209 | 210 | struct stivale2_struct_tag_epoch { 211 | struct stivale2_tag tag; 212 | uint64_t epoch; 213 | } __attribute__((__packed__)); 214 | 215 | #define STIVALE2_STRUCT_TAG_FIRMWARE_ID 0x359d837855e3858c 216 | 217 | #define STIVALE2_FIRMWARE_BIOS (1 << 0) 218 | 219 | struct stivale2_struct_tag_firmware { 220 | struct stivale2_tag tag; 221 | uint64_t flags; 222 | } __attribute__((__packed__)); 223 | 224 | #define STIVALE2_STRUCT_TAG_EFI_SYSTEM_TABLE_ID 0x4bc5ec15845b558e 225 | 226 | struct stivale2_struct_tag_efi_system_table { 227 | struct stivale2_tag tag; 228 | uint64_t system_table; 229 | } __attribute__((__packed__)); 230 | 231 | #define STIVALE2_STRUCT_TAG_KERNEL_FILE_ID 0xe599d90c2975584a 232 | 233 | struct stivale2_struct_tag_kernel_file { 234 | struct stivale2_tag tag; 235 | uint64_t kernel_file; 236 | } __attribute__((__packed__)); 237 | 238 | #define STIVALE2_STRUCT_TAG_KERNEL_SLIDE_ID 0xee80847d01506c57 239 | 240 | struct stivale2_struct_tag_kernel_slide { 241 | struct stivale2_tag tag; 242 | uint64_t kernel_slide; 243 | } __attribute__((packed)); 244 | 245 | #define STIVALE2_STRUCT_TAG_SMBIOS_ID 0x274bd246c62bf7d1 246 | 247 | struct stivale2_struct_tag_smbios { 248 | struct stivale2_tag tag; 249 | uint64_t flags; 250 | uint64_t smbios_entry_32; 251 | uint64_t smbios_entry_64; 252 | } __attribute__((packed)); 253 | 254 | #define STIVALE2_STRUCT_TAG_SMP_ID 0x34d1d96339647025 255 | 256 | struct stivale2_smp_info { 257 | uint32_t processor_id; 258 | uint32_t lapic_id; 259 | uint64_t target_stack; 260 | uint64_t goto_address; 261 | uint64_t extra_argument; 262 | } __attribute__((__packed__)); 263 | 264 | struct stivale2_struct_tag_smp { 265 | struct stivale2_tag tag; 266 | uint64_t flags; 267 | uint32_t bsp_lapic_id; 268 | uint32_t unused; 269 | uint64_t cpu_count; 270 | struct stivale2_smp_info smp_info[]; 271 | } __attribute__((__packed__)); 272 | 273 | #define STIVALE2_STRUCT_TAG_PXE_SERVER_INFO 0x29d1e96239247032 274 | 275 | struct stivale2_struct_tag_pxe_server_info { 276 | struct stivale2_tag tag; 277 | uint32_t server_ip; 278 | } __attribute__((__packed__)); 279 | 280 | #define STIVALE2_STRUCT_TAG_MMIO32_UART 0xb813f9b8dbc78797 281 | 282 | struct stivale2_struct_tag_mmio32_uart { 283 | struct stivale2_tag tag; 284 | uint64_t addr; 285 | } __attribute__((__packed__)); 286 | 287 | #define STIVALE2_STRUCT_TAG_DTB 0xabb29bd49a2833fa 288 | 289 | struct stivale2_struct_tag_dtb { 290 | struct stivale2_tag tag; 291 | uint64_t addr; 292 | uint64_t size; 293 | } __attribute__((__packed__)); 294 | 295 | #define STIVALE2_STRUCT_TAG_VMAP 0xb0ed257db18cb58f 296 | 297 | struct stivale2_struct_vmap { 298 | struct stivale2_tag tag; 299 | uint64_t addr; 300 | } __attribute__((__packed__)); 301 | 302 | #endif 303 | -------------------------------------------------------------------------------- /src/kernel/boot/stivale2_boot.c: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of an x86_64 hobbyist operating system called KnutOS 3 | Everything is openly developed on GitHub: https://github.com/Tix3Dev/KnutOS/ 4 | 5 | Copyright (C) 2021-2022 Yves Vollmeier 6 | This program is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see . 16 | */ 17 | 18 | #include 19 | 20 | #include 21 | 22 | static uint8_t stack[4096]; 23 | 24 | 25 | static struct stivale2_tag la57_tag = 26 | { 27 | .identifier = STIVALE2_HEADER_TAG_5LV_PAGING_ID, 28 | .next = 0 29 | }; 30 | 31 | static struct stivale2_header_tag_framebuffer framebuffer_hdr_tag = 32 | { 33 | .tag = 34 | { 35 | .identifier = STIVALE2_HEADER_TAG_FRAMEBUFFER_ID, 36 | .next = (uintptr_t)&la57_tag 37 | }, 38 | // bootloader automatically finds best values 39 | .framebuffer_width = 0, 40 | .framebuffer_height = 0, 41 | .framebuffer_bpp = 0 42 | }; 43 | 44 | __attribute__((section(".stivale2hdr"), used)) 45 | static struct stivale2_header stivale_hdr = 46 | { 47 | .entry_point = 0, 48 | .stack = (uintptr_t)stack + sizeof(stack), 49 | .flags = (1 << 1) | (1 << 2), 50 | .tags = (uintptr_t)&framebuffer_hdr_tag 51 | }; 52 | 53 | void *stivale2_get_tag(struct stivale2_struct *stivale2_struct, uint64_t id) 54 | { 55 | struct stivale2_tag *current_tag = (void *)stivale2_struct->tags; 56 | 57 | for (;;) 58 | { 59 | if (current_tag == NULL) 60 | return NULL; 61 | 62 | if (current_tag->identifier == id) 63 | return current_tag; 64 | 65 | current_tag = (void *)current_tag->next; 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /src/kernel/boot/stivale2_boot.h: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of an x86_64 hobbyist operating system called KnutOS 3 | Everything is openly developed on GitHub: https://github.com/Tix3Dev/KnutOS/ 4 | 5 | Copyright (C) 2021-2022 Yves Vollmeier 6 | This program is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see . 16 | */ 17 | 18 | #ifndef STIVALE2_BOOT_H 19 | #define STIVALE2_BOOT_H 20 | 21 | void *stivale2_get_tag(struct stivale2_struct *stivale2_struct, uint64_t id); 22 | 23 | #endif 24 | -------------------------------------------------------------------------------- /src/kernel/devices/apic/apic.c: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of an x86_64 hobbyist operating system called KnutOS 3 | Everything is openly developed on GitHub: https://github.com/Tix3Dev/KnutOS/ 4 | 5 | Copyright (C) 2021-2022 Yves Vollmeier 6 | This program is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see . 16 | */ 17 | 18 | #include 19 | 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | 29 | uintptr_t lapic_base; 30 | 31 | /* General APIC functions */ 32 | 33 | void apic_init(void) 34 | { 35 | if (!apic_is_available()) 36 | { 37 | serial_log(ERROR, "No APIC was found on this computer!\n"); 38 | kernel_log(ERROR, "No APIC was found on this computer!\n"); 39 | 40 | 41 | serial_log(ERROR, "Kernel halted!\n"); 42 | kernel_log(ERROR, "Kernel halted!\n"); 43 | 44 | for (;;) 45 | asm ("hlt"); 46 | } 47 | 48 | lapic_base = phys_to_higher_half_data((uintptr_t)madt->lapic_address); 49 | 50 | pic_remap(); 51 | pic_disable(); 52 | 53 | lapic_enable(); 54 | } 55 | 56 | bool apic_is_available(void) 57 | { 58 | cpuid_registers_t *regs = &(cpuid_registers_t) 59 | { 60 | .leaf = CPUID_GET_FEATURES, 61 | .subleaf = 0, 62 | 63 | .eax = 0, 64 | .ebx = 0, 65 | .ecx = 0, 66 | .edx = 0 67 | }; 68 | 69 | cpuid(regs); 70 | 71 | if (regs->edx & CPUID_FEAT_EDX_APIC) 72 | return true; 73 | 74 | return false; 75 | } 76 | 77 | /* LAPIC functions */ 78 | 79 | // returns the value of a local apic register 80 | // currently not laid out for x2apic, otherwise would check 81 | // if supported and then use msr 82 | uint32_t lapic_read_register(uint32_t reg) 83 | { 84 | return *((volatile uint32_t *)lapic_base + reg); 85 | } 86 | 87 | // write to a local apic manager 88 | // currently not laid out for x2apic, otherwise would check 89 | // if supported and then use msr 90 | void lapic_write_register(uint32_t reg, uint32_t data) 91 | { 92 | *((volatile uint32_t *)(lapic_base + reg)) = data; 93 | } 94 | 95 | // enable lapic to make it receive interrupts 96 | void lapic_enable(void) 97 | { 98 | lapic_write_register(APIC_SPURIOUS_VECTOR_REGISTER, APIC_SOFTWARE_ENABLE | SPURIOUS_INTERRUPT); 99 | } 100 | 101 | // signal an end of interrupt to continue execution 102 | void lapic_signal_eoi(void) 103 | { 104 | lapic_write_register(APIC_EOI_REGISTER, 0); 105 | } 106 | 107 | void lapic_send_ipi(void) 108 | { 109 | // send a raw inter processor interrupt to a specific APIC ID 110 | } 111 | 112 | /* IO APIC functions */ 113 | 114 | // returns the value of a ioapic register 115 | uint32_t io_apic_read_register(size_t io_apic_i, uint8_t reg_offset) 116 | { 117 | uint32_t volatile *current_io_apic_base = (uint32_t volatile *)madt_io_apics[io_apic_i]; 118 | 119 | // IOREGSEL 120 | *current_io_apic_base = reg_offset; 121 | 122 | // IOWIN 123 | return *(current_io_apic_base + 0x10); 124 | } 125 | 126 | void io_apic_write_register(size_t io_apic_i, uint8_t reg_offset, uint32_t data) 127 | { 128 | uint32_t volatile *current_io_apic_base = (uint32_t volatile *)madt_io_apics[io_apic_i]; 129 | 130 | // IOREGSEL 131 | *current_io_apic_base = reg_offset; 132 | 133 | // IOWIN 134 | *(current_io_apic_base + 0x10) = data; 135 | } 136 | -------------------------------------------------------------------------------- /src/kernel/devices/apic/apic.h: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of an x86_64 hobbyist operating system called KnutOS 3 | Everything is openly developed on GitHub: https://github.com/Tix3Dev/KnutOS/ 4 | 5 | Copyright (C) 2021-2022 Yves Vollmeier 6 | This program is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see . 16 | */ 17 | 18 | #include 19 | #include 20 | #include 21 | 22 | #ifndef APIC_H 23 | #define APIC_H 24 | 25 | #define APIC_SPURIOUS_VECTOR_REGISTER 0xF 26 | #define APIC_EOI_REGISTER 0xB0 27 | #define APIC_SOFTWARE_ENABLE (1 << 8) 28 | 29 | void apic_init(void); 30 | bool apic_is_available(void); 31 | uint32_t lapic_read_register(uint32_t reg); 32 | void lapic_write_register(uint32_t reg, uint32_t data); 33 | void lapic_enable(void); 34 | void lapic_signal_eoi(void); 35 | void lapic_send_ipi(void); 36 | uint32_t io_apic_read_register(size_t io_apic_i, uint8_t reg_offset); 37 | void io_apic_write_register(size_t io_apic_i, uint8_t reg_offset, uint32_t data); 38 | 39 | #endif 40 | -------------------------------------------------------------------------------- /src/kernel/devices/cpu/cpu.c: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of an x86_64 hobbyist operating system called KnutOS 3 | Everything is openly developed on GitHub: https://github.com/Tix3Dev/KnutOS/ 4 | 5 | Copyright (C) 2021-2022 Yves Vollmeier 6 | This program is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see . 16 | */ 17 | -------------------------------------------------------------------------------- /src/kernel/devices/cpu/cpu.h: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of an x86_64 hobbyist operating system called KnutOS 3 | Everything is openly developed on GitHub: https://github.com/Tix3Dev/KnutOS/ 4 | 5 | Copyright (C) 2021-2022 Yves Vollmeier 6 | This program is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see . 16 | */ 17 | 18 | #include 19 | #include 20 | 21 | #include 22 | #include 23 | 24 | #ifndef CPU_H 25 | #define CPU_H 26 | 27 | typedef struct 28 | { 29 | uint64_t r15; 30 | uint64_t r14; 31 | uint64_t r13; 32 | uint64_t r12; 33 | uint64_t r11; 34 | uint64_t r10; 35 | uint64_t r9; 36 | uint64_t r8; 37 | uint64_t rbp; 38 | uint64_t rdi; 39 | uint64_t rsi; 40 | uint64_t rdx; 41 | uint64_t rcx; 42 | uint64_t rbx; 43 | uint64_t rax; 44 | 45 | uint64_t isr_number; 46 | uint64_t error_code; 47 | 48 | uint64_t rip; 49 | uint64_t cs; 50 | uint64_t rflags; 51 | uint64_t rsp; 52 | uint64_t ss; 53 | } interrupt_cpu_state_t; 54 | 55 | typedef struct 56 | { 57 | uint32_t leaf; 58 | uint32_t subleaf; 59 | 60 | uint32_t eax; 61 | uint32_t ebx; 62 | uint32_t ecx; 63 | uint32_t edx; 64 | } cpuid_registers_t; 65 | 66 | typedef enum 67 | { 68 | CPUID_GET_VENDOR_STRING, 69 | CPUID_GET_FEATURES 70 | } cpuid_requests_t; 71 | 72 | // https://wiki.osdev.org/CPUID 73 | typedef enum 74 | { 75 | CPUID_FEAT_ECX_SSE3 = 1 << 0, 76 | CPUID_FEAT_ECX_PCLMUL = 1 << 1, 77 | CPUID_FEAT_ECX_DTES64 = 1 << 2, 78 | CPUID_FEAT_ECX_MONITOR = 1 << 3, 79 | CPUID_FEAT_ECX_DS_CPL = 1 << 4, 80 | CPUID_FEAT_ECX_VMX = 1 << 5, 81 | CPUID_FEAT_ECX_SMX = 1 << 6, 82 | CPUID_FEAT_ECX_EST = 1 << 7, 83 | CPUID_FEAT_ECX_TM2 = 1 << 8, 84 | CPUID_FEAT_ECX_SSSE3 = 1 << 9, 85 | CPUID_FEAT_ECX_CID = 1 << 10, 86 | CPUID_FEAT_ECX_SDBG = 1 << 11, 87 | CPUID_FEAT_ECX_FMA = 1 << 12, 88 | CPUID_FEAT_ECX_CX16 = 1 << 13, 89 | CPUID_FEAT_ECX_XTPR = 1 << 14, 90 | CPUID_FEAT_ECX_PDCM = 1 << 15, 91 | CPUID_FEAT_ECX_PCID = 1 << 17, 92 | CPUID_FEAT_ECX_DCA = 1 << 18, 93 | CPUID_FEAT_ECX_SSE4_1 = 1 << 19, 94 | CPUID_FEAT_ECX_SSE4_2 = 1 << 20, 95 | CPUID_FEAT_ECX_X2APIC = 1 << 21, 96 | CPUID_FEAT_ECX_MOVBE = 1 << 22, 97 | CPUID_FEAT_ECX_POPCNT = 1 << 23, 98 | CPUID_FEAT_ECX_TSC = 1 << 24, 99 | CPUID_FEAT_ECX_AES = 1 << 25, 100 | CPUID_FEAT_ECX_XSAVE = 1 << 26, 101 | CPUID_FEAT_ECX_OSXSAVE = 1 << 27, 102 | CPUID_FEAT_ECX_AVX = 1 << 28, 103 | CPUID_FEAT_ECX_F16C = 1 << 29, 104 | CPUID_FEAT_ECX_RDRAND = 1 << 30, 105 | CPUID_FEAT_ECX_HYPERVISOR = 1 << 31, 106 | 107 | CPUID_FEAT_EDX_FPU = 1 << 0, 108 | CPUID_FEAT_EDX_VME = 1 << 1, 109 | CPUID_FEAT_EDX_DE = 1 << 2, 110 | CPUID_FEAT_EDX_PSE = 1 << 3, 111 | CPUID_FEAT_EDX_TSC = 1 << 4, 112 | CPUID_FEAT_EDX_MSR = 1 << 5, 113 | CPUID_FEAT_EDX_PAE = 1 << 6, 114 | CPUID_FEAT_EDX_MCE = 1 << 7, 115 | CPUID_FEAT_EDX_CX8 = 1 << 8, 116 | CPUID_FEAT_EDX_APIC = 1 << 9, 117 | CPUID_FEAT_EDX_SEP = 1 << 11, 118 | CPUID_FEAT_EDX_MTRR = 1 << 12, 119 | CPUID_FEAT_EDX_PGE = 1 << 13, 120 | CPUID_FEAT_EDX_MCA = 1 << 14, 121 | CPUID_FEAT_EDX_CMO = 1 << 15, 122 | CPUID_FEAT_EDX_PAT = 1 << 16, 123 | CPUID_FEAT_EDX_PSE36 = 1 << 17, 124 | CPUID_FEAT_EDX_PSN = 1 << 18, 125 | CPUID_FEAT_EDX_CLFLUSH = 1 << 19, 126 | CPUID_FEAT_EDX_DS = 1 << 21, 127 | CPUID_FEAT_EDX_ACPI = 1 << 22, 128 | CPUID_FEAT_EDX_MMX = 1 << 23, 129 | CPUID_FEAT_EDX_FXSR = 1 << 24, 130 | CPUID_FEAT_EDX_SSE = 1 << 25, 131 | CPUID_FEAT_EDX_SSE2 = 1 << 26, 132 | CPUID_FEAT_EDX_SS = 1 << 27, 133 | CPUID_FEAT_EDX_HTT = 1 << 28, 134 | CPUID_FEAT_EDX_TM = 1 << 29, 135 | CPUID_FEAT_EDX_IA64 = 1 << 30, 136 | CPUID_FEAT_EDX_PBE = 1 << 31 137 | } cpuid_features_t; 138 | 139 | // https://github.com/qword-os/qword/blob/2e7899093d597dc55d8ed0d101f5c0509293d62f/src/sys/cpu.h#L67 140 | // leaf is equivalent to a CPUID request 141 | static inline int cpuid(cpuid_registers_t *registers) 142 | { 143 | uint32_t cpuid_max; 144 | 145 | asm volatile("cpuid" 146 | : "=a" (cpuid_max) 147 | : "a" (registers->leaf & 0x80000000) 148 | : "rbx", "rcx", "rdx"); 149 | 150 | if (registers->leaf > cpuid_max) 151 | return 0; 152 | 153 | asm volatile("cpuid" 154 | : "=a" (registers->eax), "=b" (registers->ebx), "=c" (registers->ecx), "=d" (registers->edx) 155 | : "a" (registers->leaf), "c" (registers->subleaf)); 156 | 157 | return 1; 158 | } 159 | 160 | // get cpu vendor id string by using cpuid 161 | static inline char *cpu_get_vendor_string(void) 162 | { 163 | cpuid_registers_t *regs = &(cpuid_registers_t) 164 | { 165 | .leaf = CPUID_GET_VENDOR_STRING, 166 | .subleaf = 0, 167 | 168 | .eax = 0, 169 | .ebx = 0, 170 | .ecx = 0, 171 | .edx = 0 172 | }; 173 | 174 | cpuid(regs); 175 | 176 | char *vendor_string = slab_alloc(16); // TODO: currently using slab with next power of two (rounded from 13 to 16) 177 | snprintf(vendor_string, 13, "%.4s%.4s%.4s", 178 | (char *)®s->ebx, (char *)®s->edx, (char *)®s->ecx); 179 | 180 | return vendor_string; 181 | } 182 | 183 | #endif 184 | -------------------------------------------------------------------------------- /src/kernel/devices/framebuffer/framebuffer.c: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of an x86_64 hobbyist operating system called KnutOS 3 | Everything is openly developed on GitHub: https://github.com/Tix3Dev/KnutOS/ 4 | 5 | Copyright (C) 2021-2022 Yves Vollmeier 6 | This program is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see . 16 | */ 17 | 18 | #include 19 | #include 20 | 21 | #include 22 | #include 23 | #include 24 | // #include 25 | 26 | #define SSFN_CONSOLEBITMAP_TRUECOLOR // use the special renderer for 32 bit truecolor packed pixels 27 | #define SSFN_NOIMPLEMENTATION // dont' use the normal renderer implementation 28 | #include 29 | 30 | // this name follows the SSFN rule: _binary_(filename)_start 31 | // we also need to do a few things in the makefile: 32 | // first we turn the .sfn font into an object file 33 | // then we have to link it as any other object file 34 | extern uint8_t _binary_sfn_fonts_unifont_sfn_start; 35 | 36 | struct GFX_Struct gfx; 37 | 38 | // save information about the framebuffer in a struct 39 | // set the basic SSFN variables 40 | // change the background color 41 | void framebuffer_init(struct stivale2_struct *stivale2_struct, uint32_t background_color) 42 | { 43 | struct stivale2_struct_tag_framebuffer *framebuffer_info = stivale2_get_tag(stivale2_struct, 44 | STIVALE2_STRUCT_TAG_FRAMEBUFFER_ID); 45 | 46 | gfx.fb_addr = framebuffer_info->framebuffer_addr; 47 | gfx.fb_width = framebuffer_info->framebuffer_width; 48 | gfx.fb_height = framebuffer_info->framebuffer_height; 49 | gfx.fb_pitch = framebuffer_info->framebuffer_pitch; 50 | gfx.fb_bpp = framebuffer_info->framebuffer_bpp; 51 | gfx.glyph_width = 8; 52 | gfx.glyph_height = 16; 53 | 54 | ssfn_src = (ssfn_font_t *)&_binary_sfn_fonts_unifont_sfn_start; 55 | ssfn_dst.ptr = (uint8_t *)gfx.fb_addr; 56 | ssfn_dst.w = gfx.fb_width; 57 | ssfn_dst.h = gfx.fb_height; 58 | ssfn_dst.p = gfx.fb_pitch; 59 | ssfn_dst.x = 0; 60 | ssfn_dst.y = 0; 61 | 62 | framebuffer_set_background_color(background_color); 63 | 64 | // serial_log(INFO, "Framebuffer initialized\n"); 65 | // kernel_log(INFO, "Framebuffer initialized\n"); 66 | } 67 | 68 | // draw one pixel at coordinate x, y (0, 0 is top left corner) in a certain color 69 | void framebuffer_draw_pixel(int x, int y, uint32_t color) 70 | { 71 | size_t fb_index = y * (gfx.fb_pitch / sizeof(uint32_t)) + x; 72 | uint32_t *fb = (uint32_t *)gfx.fb_addr; 73 | 74 | fb[fb_index] = color; 75 | } 76 | 77 | // set the 'global' background color and turn every pixel into that color 78 | void framebuffer_set_background_color(uint32_t background_color) 79 | { 80 | ssfn_dst.bg = background_color; 81 | 82 | for (int y = 0; y < gfx.fb_height; y++) 83 | { 84 | for (int x = 0; x < gfx.fb_width; x++) 85 | framebuffer_draw_pixel(x, y, ssfn_dst.bg); 86 | } 87 | } 88 | 89 | // reset pen position and turn every pixel into the default background color 90 | void framebuffer_reset_screen(void) 91 | { 92 | ssfn_dst.x = 0; 93 | ssfn_dst.y = 0; 94 | 95 | framebuffer_set_background_color(ssfn_dst.bg); 96 | } 97 | 98 | // draw a line to the framebuffer with start coordinates and end coordinates 99 | // making use of bresenham's line algorithm 100 | void framebuffer_draw_line(int x_start_pos, int y_start_pos, int x_end_pos, int y_end_pos, uint32_t color) 101 | { 102 | int dx; 103 | int dy; 104 | int sx; 105 | int sy; 106 | int error1; 107 | int error2; 108 | 109 | if (x_start_pos == x_end_pos) 110 | { 111 | if (y_start_pos < y_end_pos) 112 | for (int y = y_start_pos; y <= y_end_pos; y++) 113 | framebuffer_draw_pixel(x_start_pos, y, color); 114 | else 115 | for (int y = y_end_pos; y <= y_start_pos; y++) 116 | framebuffer_draw_pixel(x_start_pos, y, color); 117 | 118 | return; 119 | } 120 | 121 | if (y_start_pos == y_end_pos) 122 | { 123 | if (x_start_pos < x_end_pos) 124 | for (int x = x_start_pos; x <= x_end_pos; x++) 125 | framebuffer_draw_pixel(x, y_start_pos, color); 126 | else 127 | for (int x = x_end_pos; x <= x_start_pos; x++) 128 | framebuffer_draw_pixel(x, y_start_pos, color); 129 | 130 | return; 131 | } 132 | 133 | if (x_start_pos < x_end_pos) 134 | { 135 | dx = x_end_pos - x_start_pos; 136 | sx = 1; 137 | } 138 | else 139 | { 140 | dx = x_start_pos - x_end_pos; 141 | sx = -1; 142 | } 143 | 144 | if (y_start_pos < y_end_pos) 145 | { 146 | dy = -(y_end_pos - y_start_pos); 147 | sy = 1; 148 | } 149 | else 150 | { 151 | dy = -(y_start_pos - y_end_pos); 152 | sy = -1; 153 | } 154 | 155 | error1 = dx + dy; 156 | 157 | framebuffer_draw_pixel(x_start_pos, y_start_pos, color); 158 | 159 | while (x_start_pos != x_end_pos && y_start_pos != y_end_pos) 160 | { 161 | error2 = 2 * error1; 162 | 163 | if (error2 >= dy) 164 | { 165 | error1 += dy; 166 | x_start_pos += sx; 167 | } 168 | 169 | if (error2 <= dx) 170 | { 171 | error1 += dx; 172 | y_start_pos += sy; 173 | } 174 | 175 | framebuffer_draw_pixel(x_start_pos, y_start_pos, color); 176 | } 177 | } 178 | 179 | // divide the circle into 8 parts 180 | void draw_circle_helper(int xc, int yc, int x, int y, uint32_t color) 181 | { 182 | framebuffer_draw_pixel(xc + x, yc + y, color); 183 | framebuffer_draw_pixel(xc - x, yc + y, color); 184 | framebuffer_draw_pixel(xc + x, yc - y, color); 185 | framebuffer_draw_pixel(xc - x, yc - y, color); 186 | framebuffer_draw_pixel(xc + y, yc + x, color); 187 | framebuffer_draw_pixel(xc - y, yc + x, color); 188 | framebuffer_draw_pixel(xc + y, yc - x, color); 189 | framebuffer_draw_pixel(xc - y, yc - x, color); 190 | } 191 | 192 | // draw a circle with the x, y coordinate being the center 193 | void framebuffer_draw_circle(int x_center, int y_center, int radius, uint32_t color) 194 | { 195 | int x = 0; 196 | int y = radius; 197 | int d = 3 - 2 * radius; 198 | 199 | draw_circle_helper(x_center, y_center, x, y, color); 200 | 201 | while (y >= x) 202 | { 203 | x += 1; 204 | 205 | if (d > 0) 206 | { 207 | y -= 1; 208 | d = d + 4 * (x - y) + 10; 209 | } 210 | else 211 | d = d + 4 * x + 6; 212 | 213 | draw_circle_helper(x_center, y_center, x, y, color); 214 | } 215 | } 216 | 217 | // memmove the screen by one 'glyph height' 218 | void framebuffer_move_one_row_up(void) 219 | { 220 | uint32_t *fb = (uint32_t *)gfx.fb_addr; 221 | 222 | for (int column = gfx.glyph_height; column < gfx.fb_height; column++) 223 | { 224 | for (int row = 0; row < gfx.fb_width; row++) 225 | { 226 | size_t current_index = column * (gfx.fb_pitch / sizeof(uint32_t)) + row; 227 | uint32_t current_color = fb[current_index]; 228 | fb[current_index] = ssfn_dst.bg; 229 | 230 | size_t new_index = (column - gfx.glyph_height) * (gfx.fb_pitch / sizeof(uint32_t)) + row; 231 | fb[new_index] = current_color; 232 | } 233 | } 234 | } 235 | 236 | // print a glyph to the screen in a certain color 237 | void framebuffer_print_char(uint32_t unicode, int x, int y, uint32_t foreground_color) 238 | { 239 | ssfn_dst.x = x; 240 | ssfn_dst.y = y; 241 | 242 | if (ssfn_dst.x + gfx.glyph_width > gfx.fb_width) // here too problematic 243 | { 244 | ssfn_dst.x = 0; 245 | ssfn_dst.y += gfx.glyph_height; 246 | } 247 | 248 | if (ssfn_dst.y >= gfx.fb_height) // this is problematic cuz don't do this when backspace 249 | { 250 | ssfn_dst.x = 0; 251 | ssfn_dst.y = gfx.fb_height - gfx.glyph_height; 252 | framebuffer_move_one_row_up(); 253 | } 254 | 255 | // if the unicode character is a tab we print four spaces 256 | if (unicode == '\t') 257 | { 258 | for (int i = 0; i < 4; i++) 259 | framebuffer_print_string(" ", foreground_color); 260 | 261 | return; 262 | } 263 | 264 | // if the unicode character is a backspace we check where the cursor is and then 265 | // replace the last character with space and put the cursor there 266 | if (unicode == '\b') 267 | { 268 | if (ssfn_dst.x == 0) 269 | { 270 | if (ssfn_dst.y == 0) 271 | return; 272 | 273 | ssfn_dst.x = gfx.fb_width - gfx.glyph_width; 274 | ssfn_dst.y -= gfx.glyph_height; 275 | 276 | ssfn_putc(' '); 277 | 278 | ssfn_dst.x -= gfx.glyph_width; 279 | } 280 | else 281 | { 282 | ssfn_dst.x -= gfx.glyph_width; 283 | 284 | ssfn_putc(' '); 285 | 286 | ssfn_dst.x -= gfx.glyph_width; 287 | } 288 | 289 | return; 290 | } 291 | 292 | ssfn_dst.fg = foreground_color; 293 | 294 | ssfn_putc(unicode); 295 | } 296 | 297 | // print a string of glyphs to the screen in a certain color 298 | void framebuffer_print_string(char *string, uint32_t foreground_color) 299 | { 300 | while (*string) 301 | framebuffer_print_char(ssfn_utf8(&string), ssfn_dst.x, ssfn_dst.y, foreground_color); 302 | } 303 | -------------------------------------------------------------------------------- /src/kernel/devices/framebuffer/framebuffer.h: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of an x86_64 hobbyist operating system called KnutOS 3 | Everything is openly developed on GitHub: https://github.com/Tix3Dev/KnutOS/ 4 | 5 | Copyright (C) 2021-2022 Yves Vollmeier 6 | This program is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see . 16 | */ 17 | 18 | #ifndef FRAMEBUFFER_H 19 | #define FRAMEBUFFER_H 20 | 21 | #define GFX_BLACK 0xFF3B4252 22 | #define GFX_RED 0xFFBF616A 23 | #define GFX_GREEN 0xFFA3BE8C 24 | #define GFX_YELLOW 0xFFEBCA8B 25 | #define GFX_BLUE 0xFF81A1C1 26 | #define GFX_PURPLE 0xFFB48EAD 27 | #define GFX_CYAN 0xFF88C0D0 28 | #define GFX_WHITE 0xFFE5E9F0 29 | 30 | struct GFX_Struct 31 | { 32 | uint64_t fb_addr; 33 | uint16_t fb_width; 34 | uint16_t fb_height; 35 | uint16_t fb_pitch; 36 | uint16_t fb_bpp; 37 | 38 | int glyph_width; 39 | int glyph_height; 40 | }; 41 | 42 | void framebuffer_init(struct stivale2_struct *stivale2_struct, uint32_t background_color); 43 | void framebuffer_draw_pixel(int x, int y, uint32_t color); 44 | void framebuffer_set_background_color(uint32_t background_color); 45 | void framebuffer_reset_screen(void); 46 | void framebuffer_draw_line(int x_start_pos, int y_start_pos, int x_end_pos, int y_end_pos, uint32_t color); 47 | void framebuffer_draw_circle(int x_center, int y_center, int radius, uint32_t color); 48 | void framebuffer_move_one_row_up(void); 49 | void framebuffer_print_char(uint32_t unicode_character, int x, int y, uint32_t foreground_color); 50 | void framebuffer_print_string(char *string, uint32_t foreground_color); 51 | 52 | #endif 53 | -------------------------------------------------------------------------------- /src/kernel/devices/pic/pic.c: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of an x86_64 hobbyist operating system called KnutOS 3 | Everything is openly developed on GitHub: https://github.com/Tix3Dev/KnutOS/ 4 | 5 | Copyright (C) 2021-2022 Yves Vollmeier 6 | This program is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see . 16 | */ 17 | 18 | #include 19 | 20 | #include 21 | #include 22 | 23 | // disable PIC in order to use LAPIC and IOAPIC 24 | void pic_disable(void) 25 | { 26 | io_outb(PIC2_DATA, 0xFF); 27 | io_outb(PIC1_DATA, 0xFF); 28 | } 29 | 30 | // remap the programmable interrupt controller 31 | void pic_remap(void) 32 | { 33 | uint8_t mask1 = io_inb(PIC1_DATA); 34 | uint8_t mask2 = io_inb(PIC2_DATA); 35 | 36 | 37 | io_outb(PIC1_COMMAND, 0x11); 38 | io_outb(PIC2_COMMAND, 0x11); 39 | io_wait(); 40 | 41 | 42 | io_outb(PIC1_DATA, 0x20); 43 | io_outb(PIC2_DATA, 0x28); 44 | io_wait(); 45 | 46 | io_outb(PIC1_DATA, 0x04); 47 | io_outb(PIC2_DATA, 0x02); 48 | io_wait(); 49 | 50 | io_outb(PIC1_DATA, 0x01); 51 | io_outb(PIC2_DATA, 0x01); 52 | io_wait(); 53 | 54 | io_outb(PIC1_DATA, 0x00); 55 | io_outb(PIC2_DATA, 0x00); 56 | io_wait(); 57 | 58 | 59 | io_outb(PIC1_DATA, ICW4_8086); 60 | io_wait(); 61 | io_outb(PIC2_DATA, ICW4_8086); 62 | io_wait(); 63 | 64 | 65 | io_outb(PIC1_DATA, mask1); 66 | io_outb(PIC2_DATA, mask2); 67 | } 68 | 69 | // use internel PIC register: IMR to ignore irq_lines 70 | void pic_set_mask(uint8_t irq_line) 71 | { 72 | uint16_t port; 73 | uint8_t value; 74 | 75 | if (irq_line < 8) 76 | port = PIC1_DATA; 77 | 78 | else 79 | { 80 | port = PIC2_DATA; 81 | irq_line -= 8; 82 | } 83 | 84 | value = io_inb(port) | (1 << irq_line); 85 | io_outb(port, value); 86 | } 87 | 88 | // "undo" pic_set_mask 89 | void pic_clear_mask(uint8_t irq_line) 90 | { 91 | uint16_t port; 92 | uint8_t value; 93 | 94 | if (irq_line < 8) 95 | port = PIC1_DATA; 96 | 97 | else 98 | { 99 | port = PIC2_DATA; 100 | irq_line -= 8; 101 | } 102 | 103 | value = io_inb(port) & ~(1 << irq_line); 104 | io_outb(port, value); 105 | } 106 | 107 | // signal an end of interrupt 108 | void pic_signal_EOI(uint64_t isr_number) 109 | { 110 | if (isr_number >= 40) // if the IRQ came from the slave PIC 111 | io_outb(PIC2_COMMAND, 0x20); 112 | 113 | io_outb(PIC1_COMMAND, 0x20); // if the IRQ came from the master and/or the slave PIC 114 | } 115 | -------------------------------------------------------------------------------- /src/kernel/devices/pic/pic.h: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of an x86_64 hobbyist operating system called KnutOS 3 | Everything is openly developed on GitHub: https://github.com/Tix3Dev/KnutOS/ 4 | 5 | Copyright (C) 2021-2022 Yves Vollmeier 6 | This program is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see . 16 | */ 17 | 18 | #ifndef PIC_H 19 | #define PIC_H 20 | 21 | #define PIC1 0x20 // I/O base address for master PIC 22 | #define PIC2 0xA0 // I/O base address for slave PIC 23 | #define PIC1_COMMAND PIC1 // master PIC command port 24 | #define PIC1_DATA (PIC1+1) // master PIC data port 25 | #define PIC2_COMMAND PIC2 // slave PIC command port 26 | #define PIC2_DATA (PIC2+1) // slave PIC data port 27 | #define ICW4_8086 0x01 // 8086/88 (MCS-80/85) mode 28 | 29 | void pic_disable(void); 30 | void pic_remap(void); 31 | void pic_set_mask(unsigned char irq_line); 32 | void pic_clear_mask(unsigned char irq_line); 33 | void pic_signal_EOI(uint64_t isr_number); 34 | 35 | #endif 36 | -------------------------------------------------------------------------------- /src/kernel/devices/ps2/keyboard/keyboard.c: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of an x86_64 hobbyist operating system called KnutOS 3 | Everything is openly developed on GitHub: https://github.com/Tix3Dev/KnutOS/ 4 | 5 | Copyright (C) 2021-2022 Yves Vollmeier 6 | This program is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see . 16 | */ 17 | 18 | // The standard_keycodes array + the KEY enum is from this tutorial: 19 | // http://www.brokenthorn.com/Resources/OSDev19.html 20 | 21 | #include 22 | 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | 29 | static uint8_t is_keyboard_active = 0; // boolean whether keyboard IRQ should get processed 30 | 31 | static void (*final_handler)(KEY_INFO_t); 32 | 33 | static uint32_t standard_keycodes[] = 34 | { 35 | // key scancode 36 | KEY_UNKNOWN, //0x0 37 | KEY_ESCAPE, //0x1 38 | KEY_1, //0x2 39 | KEY_2, //0x3 40 | KEY_3, //0x4 41 | KEY_4, //0x5 42 | KEY_5, //0x6 43 | KEY_6, //0x7 44 | KEY_7, //0x8 45 | KEY_8, //0x9 46 | KEY_9, //0xa 47 | KEY_0, //0xb 48 | KEY_MINUS, //0xc 49 | KEY_EQUAL, //0xd 50 | KEY_BACKSPACE, //0xe 51 | KEY_TAB, //0xf 52 | KEY_Q, //0x10 53 | KEY_W, //0x11 54 | KEY_E, //0x12 55 | KEY_R, //0x13 56 | KEY_T, //0x14 57 | KEY_Y, //0x15 58 | KEY_U, //0x16 59 | KEY_I, //0x17 60 | KEY_O, //0x18 61 | KEY_P, //0x19 62 | KEY_LEFTBRACKET, //0x1a 63 | KEY_RIGHTBRACKET, //0x1b 64 | KEY_RETURN, //0x1c 65 | KEY_LCTRL, //0x1d 66 | KEY_A, //0x1e 67 | KEY_S, //0x1f 68 | KEY_D, //0x20 69 | KEY_F, //0x21 70 | KEY_G, //0x22 71 | KEY_H, //0x23 72 | KEY_J, //0x24 73 | KEY_K, //0x25 74 | KEY_L, //0x26 75 | KEY_SEMICOLON, //0x27 76 | KEY_QUOTE, //0x28 77 | KEY_GRAVE, //0x29 78 | KEY_LSHIFT, //0x2a 79 | KEY_BACKSLASH, //0x2b 80 | KEY_Z, //0x2c 81 | KEY_X, //0x2d 82 | KEY_C, //0x2e 83 | KEY_V, //0x2f 84 | KEY_B, //0x30 85 | KEY_N, //0x31 86 | KEY_M, //0x32 87 | KEY_COMMA, //0x33 88 | KEY_DOT, //0x34 89 | KEY_SLASH, //0x35 90 | KEY_RSHIFT, //0x36 91 | KEY_KP_ASTERISK, //0x37 92 | KEY_RALT, //0x38 93 | KEY_SPACE, //0x39 94 | KEY_CAPSLOCK, //0x3a 95 | KEY_F1, //0x3b 96 | KEY_F2, //0x3c 97 | KEY_F3, //0x3d 98 | KEY_F4, //0x3e 99 | KEY_F5, //0x3f 100 | KEY_F6, //0x40 101 | KEY_F7, //0x41 102 | KEY_F8, //0x42 103 | KEY_F9, //0x43 104 | KEY_F10, //0x44 105 | KEY_KP_NUMLOCK, //0x45 106 | KEY_SCROLLLOCK, //0x46 107 | KEY_HOME, //0x47 108 | KEY_KP_8, //0x48 109 | KEY_PAGEUP, //0x49 110 | KEY_KP_2, //0x50 111 | KEY_KP_3, //0x51 112 | KEY_KP_0, //0x52 113 | KEY_KP_DECIMAL, //0x53 114 | KEY_UNKNOWN, //0x54 115 | KEY_UNKNOWN, //0x55 116 | KEY_UNKNOWN, //0x56 117 | KEY_F11, //0x57 118 | KEY_F12 //0x58 119 | }; 120 | 121 | static uint8_t ctrl = 0; 122 | static uint8_t alt = 0; 123 | static uint8_t shift = 0; 124 | 125 | static uint8_t capslock = 0; 126 | static uint8_t numlock = 0; 127 | static uint8_t scrolllock = 0; 128 | 129 | // initialize the keyboard 130 | void keyboard_init(void) 131 | { 132 | // clear the set mask for the keyboard IRQ 133 | pic_clear_mask(1); 134 | 135 | // clear the data register of the keyboard controller 136 | while (io_inb(KB_CONTROLLER_COMMAND) & 0x1) 137 | io_inb(KB_CONTROLLER_DATA); 138 | 139 | // enable scanning (so that the keyboard will send scan codes) 140 | keyboard_send_command(0xF4); 141 | 142 | serial_log(INFO, "Keyboard driver initialized\n"); 143 | kernel_log(INFO, "Keyboard driver initialized\n"); 144 | } 145 | 146 | // send a command byte to the keyboard controller 147 | void keyboard_send_command(uint8_t command_byte) 148 | { 149 | // wait until keyboard is ready 150 | while (io_inb(KB_CONTROLLER_COMMAND) & 0x2) 151 | io_outb(KB_CONTROLLER_DATA, command_byte); 152 | } 153 | 154 | // gets called whenever a keyboard IRQ occurrs 155 | void keyboard_irq_handler(void) 156 | { 157 | // read from keyboard controller so that in any case it will be able to send more IRQs 158 | uint8_t scancode = io_inb(KB_CONTROLLER_DATA); 159 | 160 | // check if keyboard IRQ should get processed 161 | if (!is_keyboard_active) 162 | return; 163 | 164 | KEY_INFO_t key_info; 165 | 166 | key_info.keycode = KEY_UNKNOWN; 167 | key_info.ascii_character = '\0'; 168 | 169 | // check for breakcode 170 | if (scancode & 0x80) 171 | { 172 | scancode -= 0x80; 173 | 174 | uint32_t key = standard_keycodes[scancode]; 175 | 176 | if (key == KEY_LCTRL || key == KEY_RCTRL) 177 | ctrl = 0; 178 | else if (key == KEY_LALT || key == KEY_RALT) 179 | alt = 0; 180 | else if (key == KEY_LSHIFT || key == KEY_RSHIFT) 181 | shift = 0; 182 | } 183 | else 184 | { 185 | uint32_t key = standard_keycodes[scancode]; 186 | 187 | key_info.keycode = key; 188 | 189 | if (key == KEY_LCTRL || key == KEY_RCTRL) 190 | ctrl = 1; 191 | else if (key == KEY_LALT || key == KEY_RALT) 192 | alt = 1; 193 | else if (key == KEY_LSHIFT || key == KEY_RSHIFT) 194 | shift = 1; 195 | else if (key == KEY_CAPSLOCK) 196 | capslock = capslock ? 0 : 1; 197 | else if (key == KEY_KP_NUMLOCK) 198 | numlock = numlock ? 0 : 1; 199 | else if (key == KEY_SCROLLLOCK) 200 | scrolllock = scrolllock ? 0 : 1; 201 | // else if (key == KEY_RETURN) 202 | // key_info.ascii_character = '\n'; 203 | else if (key <= 0x7F) 204 | key_info.ascii_character = keycode_to_ascii(key); 205 | } 206 | 207 | final_handler(key_info); 208 | 209 | /* 210 | if () 211 | { 212 | serial_set_color(TERM_RED); 213 | debug("\n──────────────────────────────\n"); 214 | debug("⚠ UNKNOWN SCANCODE RECEIVED! ⚠\n\n"); 215 | debug("⤷ Scancode: 0x%x | Set: %d\n", scancode, scancode_set); 216 | serial_set_color(TERM_COLOR_RESET); 217 | } 218 | */ 219 | } 220 | 221 | // type change and conversion for upper- or lowercase if shift or capslock is pressed 222 | char keycode_to_ascii(KEYCODE_t keycode) 223 | { 224 | uint8_t character = keycode; 225 | 226 | if (shift && capslock) 227 | { 228 | if (character == '0') 229 | character = KEY_RIGHTPARENTHESIS; 230 | else if (character == '1') 231 | character = KEY_EXCLAMATION; 232 | else if (character == '2') 233 | character = KEY_AT; 234 | else if (character == '3') 235 | character = KEY_HASH; 236 | else if (character == '4') 237 | character = KEY_DOLLAR; 238 | else if (character == '5') 239 | character = KEY_PERCENT; 240 | else if (character == '6') 241 | character = KEY_CARRET; 242 | else if (character == '7') 243 | character = KEY_AMPERSAND; 244 | else if (character == '8') 245 | character = KEY_ASTERISK; 246 | else if (character == '9') 247 | character = KEY_LEFTPARENTHESIS; 248 | else if (character == KEY_COMMA) 249 | character = KEY_LESS; 250 | else if (character == KEY_DOT) 251 | character = KEY_GREATER; 252 | else if (character == KEY_SLASH) 253 | character = KEY_QUESTION; 254 | else if (character == KEY_SEMICOLON) 255 | character = KEY_COLON; 256 | else if (character == KEY_QUOTE) 257 | character = KEY_QUOTEDOUBLE; 258 | else if (character == KEY_LEFTBRACKET) 259 | character = KEY_LEFTCURL; 260 | else if (character == KEY_RIGHTBRACKET) 261 | character = KEY_RIGHTCURL; 262 | else if (character == KEY_GRAVE) 263 | character = KEY_TILDE; 264 | else if (character == KEY_MINUS) 265 | character = KEY_UNDERSCORE; 266 | else if (character == KEY_EQUAL) 267 | character = KEY_PLUS; 268 | else if (character == KEY_BACKSLASH) 269 | character = KEY_BAR; 270 | } 271 | else if (shift && !capslock) 272 | { 273 | if (character >= 'a' && character <= 'z') 274 | character -= 32; 275 | 276 | if (character == '0') 277 | character = KEY_RIGHTPARENTHESIS; 278 | else if (character == '1') 279 | character = KEY_EXCLAMATION; 280 | else if (character == '2') 281 | character = KEY_AT; 282 | else if (character == '3') 283 | character = KEY_HASH; 284 | else if (character == '4') 285 | character = KEY_DOLLAR; 286 | else if (character == '5') 287 | character = KEY_PERCENT; 288 | else if (character == '6') 289 | character = KEY_CARRET; 290 | else if (character == '7') 291 | character = KEY_AMPERSAND; 292 | else if (character == '8') 293 | character = KEY_ASTERISK; 294 | else if (character == '9') 295 | character = KEY_LEFTPARENTHESIS; 296 | else if (character == KEY_COMMA) 297 | character = KEY_LESS; 298 | else if (character == KEY_DOT) 299 | character = KEY_GREATER; 300 | else if (character == KEY_SLASH) 301 | character = KEY_QUESTION; 302 | else if (character == KEY_SEMICOLON) 303 | character = KEY_COLON; 304 | else if (character == KEY_QUOTE) 305 | character = KEY_QUOTEDOUBLE; 306 | else if (character == KEY_LEFTBRACKET) 307 | character = KEY_LEFTCURL; 308 | else if (character == KEY_RIGHTBRACKET) 309 | character = KEY_RIGHTCURL; 310 | else if (character == KEY_GRAVE) 311 | character = KEY_TILDE; 312 | else if (character == KEY_MINUS) 313 | character = KEY_UNDERSCORE; 314 | else if (character == KEY_EQUAL) 315 | character = KEY_PLUS; 316 | else if (character == KEY_BACKSLASH) 317 | character = KEY_BAR; 318 | 319 | } 320 | else if (!shift && capslock) 321 | { 322 | if (character >= 'a' && character <= 'z') 323 | character -= 32; 324 | } 325 | 326 | return character; 327 | } 328 | 329 | // KEY_INFO_t struct will be passed to handler so it must take it as argument 330 | // the x, y coordinates are optional, if not used pass NULL otherwise it will set a writable area 331 | // -> set a barrier 332 | void activate_keyboard_processing(void *handler) 333 | { 334 | final_handler = handler; 335 | 336 | is_keyboard_active = 1; 337 | } 338 | 339 | // to undo activate_keyboard_processing (otherwise no change because 0 is default state) 340 | void disable_keyboard_processing(void) 341 | { 342 | is_keyboard_active = 0; 343 | } 344 | -------------------------------------------------------------------------------- /src/kernel/devices/ps2/keyboard/keyboard.h: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of an x86_64 hobbyist operating system called KnutOS 3 | Everything is openly developed on GitHub: https://github.com/Tix3Dev/KnutOS/ 4 | 5 | Copyright (C) 2021-2022 Yves Vollmeier 6 | This program is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see . 16 | */ 17 | 18 | // The standard_keycodes array + the KEY enum is from this tutorial: 19 | // http://www.brokenthorn.com/Resources/OSDev19.html 20 | 21 | #include 22 | 23 | #ifndef KEYBOARD_H 24 | #define KEYBOARD_H 25 | 26 | #define KB_CONTROLLER_DATA 0x60 // keyboard controller data register 27 | #define KB_CONTROLLER_COMMAND 0x64 // keyboard controller command register 28 | 29 | typedef enum { 30 | KEY_SPACE = ' ', 31 | 32 | KEY_0 = '0', 33 | KEY_1 = '1', 34 | KEY_2 = '2', 35 | KEY_3 = '3', 36 | KEY_4 = '4', 37 | KEY_5 = '5', 38 | KEY_6 = '6', 39 | KEY_7 = '7', 40 | KEY_8 = '8', 41 | KEY_9 = '9', 42 | 43 | KEY_A = 'a', 44 | KEY_B = 'b', 45 | KEY_C = 'c', 46 | KEY_D = 'd', 47 | KEY_E = 'e', 48 | KEY_F = 'f', 49 | KEY_G = 'g', 50 | KEY_H = 'h', 51 | KEY_I = 'i', 52 | KEY_J = 'j', 53 | KEY_K = 'k', 54 | KEY_L = 'l', 55 | KEY_M = 'm', 56 | KEY_N = 'n', 57 | KEY_O = 'o', 58 | KEY_P = 'p', 59 | KEY_Q = 'q', 60 | KEY_R = 'r', 61 | KEY_S = 's', 62 | KEY_T = 't', 63 | KEY_U = 'u', 64 | KEY_V = 'v', 65 | KEY_W = 'w', 66 | KEY_X = 'x', 67 | KEY_Y = 'y', 68 | KEY_Z = 'z', 69 | 70 | KEY_RETURN = '\r', 71 | KEY_ESCAPE = 0x1001, 72 | KEY_BACKSPACE = '\b', 73 | 74 | KEY_UP = 0x1100, 75 | KEY_DOWN = 0x1101, 76 | KEY_LEFT = 0x1102, 77 | KEY_RIGHT = 0x1103, 78 | 79 | KEY_F1 = 0x1201, 80 | KEY_F2 = 0x1202, 81 | KEY_F3 = 0x1203, 82 | KEY_F4 = 0x1204, 83 | KEY_F5 = 0x1205, 84 | KEY_F6 = 0x1206, 85 | KEY_F7 = 0x1207, 86 | KEY_F8 = 0x1208, 87 | KEY_F9 = 0x1209, 88 | KEY_F10 = 0x120a, 89 | KEY_F11 = 0x120b, 90 | KEY_F12 = 0x120b, 91 | KEY_F13 = 0x120c, 92 | KEY_F14 = 0x120d, 93 | KEY_F15 = 0x120e, 94 | 95 | KEY_DOT = '.', 96 | KEY_COMMA = ',', 97 | KEY_COLON = ':', 98 | KEY_SEMICOLON = ';', 99 | KEY_SLASH = '/', 100 | KEY_BACKSLASH = '\\', 101 | KEY_PLUS = '+', 102 | KEY_MINUS = '-', 103 | KEY_ASTERISK = '*', 104 | KEY_EXCLAMATION = '!', 105 | KEY_QUESTION = '?', 106 | KEY_QUOTEDOUBLE = '\"', 107 | KEY_QUOTE = '\'', 108 | KEY_EQUAL = '=', 109 | KEY_HASH = '#', 110 | KEY_PERCENT = '%', 111 | KEY_AMPERSAND = '&', 112 | KEY_UNDERSCORE = '_', 113 | KEY_LEFTPARENTHESIS = '(', 114 | KEY_RIGHTPARENTHESIS = ')', 115 | KEY_LEFTBRACKET = '[', 116 | KEY_RIGHTBRACKET = ']', 117 | KEY_LEFTCURL = '{', 118 | KEY_RIGHTCURL = '}', 119 | KEY_DOLLAR = '$', 120 | KEY_POUND = '$', // WARNING! not used because it's a multi-character character 121 | KEY_EURO = '$', // WARNING! not used because it's a multi-character character 122 | KEY_LESS = '<', 123 | KEY_GREATER = '>', 124 | KEY_BAR = '|', 125 | KEY_GRAVE = '`', 126 | KEY_TILDE = '~', 127 | KEY_AT = '@', 128 | KEY_CARRET = '^', 129 | 130 | KEY_KP_0 = '0', 131 | KEY_KP_1 = '1', 132 | KEY_KP_2 = '2', 133 | KEY_KP_3 = '3', 134 | KEY_KP_4 = '4', 135 | KEY_KP_5 = '5', 136 | KEY_KP_6 = '6', 137 | KEY_KP_7 = '7', 138 | KEY_KP_8 = '8', 139 | KEY_KP_9 = '9', 140 | KEY_KP_PLUS = '+', 141 | KEY_KP_MINUS = '-', 142 | KEY_KP_DECIMAL = '.', 143 | KEY_KP_DIVIDE = '/', 144 | KEY_KP_ASTERISK = '*', 145 | KEY_KP_NUMLOCK = 0x300f, 146 | KEY_KP_ENTER = 0x3010, 147 | 148 | KEY_TAB = '\t', 149 | KEY_CAPSLOCK = 0x4001, 150 | 151 | KEY_LSHIFT = 0x4002, 152 | KEY_LCTRL = 0x4003, 153 | KEY_LALT = 0x4004, 154 | KEY_LWIN = 0x4005, 155 | KEY_RSHIFT = 0x4006, 156 | KEY_RCTRL = 0x4007, 157 | KEY_RALT = 0x4008, 158 | KEY_RWIN = 0x4009, 159 | 160 | KEY_INSERT = 0x400a, 161 | KEY_DELETE = 0x400b, 162 | KEY_HOME = 0x400c, 163 | KEY_END = 0x400d, 164 | KEY_PAGEUP = 0x400e, 165 | KEY_PAGEDOWN = 0x400f, 166 | KEY_SCROLLLOCK = 0x4010, 167 | KEY_PAUSE = 0x4011, 168 | 169 | KEY_UNKNOWN, 170 | KEY_NUMKEYCODES 171 | } KEYCODE_t; 172 | 173 | typedef struct 174 | { 175 | uint32_t keycode; 176 | char ascii_character; 177 | } KEY_INFO_t; 178 | 179 | void keyboard_init(void); 180 | void keyboard_send_command(uint8_t command_byte); 181 | void keyboard_irq_handler(void); 182 | char keycode_to_ascii(KEYCODE_t keycode); 183 | void activate_keyboard_processing(void *handler); 184 | void disable_keyboard_processing(void); 185 | 186 | #endif 187 | -------------------------------------------------------------------------------- /src/kernel/devices/serial/serial.c: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of an x86_64 hobbyist operating system called KnutOS 3 | Everything is openly developed on GitHub: https://github.com/Tix3Dev/KnutOS/ 4 | 5 | Copyright (C) 2021-2022 Yves Vollmeier 6 | This program is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see . 16 | */ 17 | 18 | #include 19 | 20 | // #include 21 | #include 22 | #include 23 | // #include 24 | // #include 25 | 26 | // set COM1 offsets to init value 27 | void serial_init(void) 28 | { 29 | io_outb(COM1 + 1, 0x00); 30 | io_outb(COM1 + 3, 0x80); 31 | io_outb(COM1 + 0, 0x03); 32 | io_outb(COM1 + 1, 0x00); 33 | io_outb(COM1 + 3, 0x03); 34 | io_outb(COM1 + 2, 0xC7); 35 | io_outb(COM1 + 4, 0x0B); 36 | 37 | // serial_log(INFO, "Serial initialized\n"); 38 | // kernel_log(INFO, "Serial initialized\n"); 39 | } 40 | 41 | // check if transmission buffer is not empty 42 | int is_serial_received(void) 43 | { 44 | return io_inb(COM1 + 5) & 1; 45 | } 46 | 47 | // read data from COM1 48 | char serial_recv(void) 49 | { 50 | while (is_serial_received() == 0); 51 | 52 | return io_inb(COM1); 53 | } 54 | 55 | // check if transmission buffer is empty 56 | int is_transmit_empty(void) 57 | { 58 | return io_inb(COM1 + 5) & 0x20; 59 | } 60 | 61 | // send data to COM1 62 | void serial_send_char(char c) 63 | { 64 | while (is_transmit_empty() == 0); 65 | 66 | io_outb(COM1, c); 67 | } 68 | 69 | // send even more data to COM1 70 | void serial_send_string(char *str) 71 | { 72 | for (int i = 0; str[i] != '\0'; i++) 73 | serial_send_char(str[i]); 74 | } 75 | 76 | // send bash color codes to COM1 77 | void serial_set_color(char *color_code) 78 | { 79 | if (color_code[0] != '\e' || color_code[1] != '[') 80 | return; 81 | 82 | serial_send_string(color_code); 83 | } 84 | -------------------------------------------------------------------------------- /src/kernel/devices/serial/serial.h: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of an x86_64 hobbyist operating system called KnutOS 3 | Everything is openly developed on GitHub: https://github.com/Tix3Dev/KnutOS/ 4 | 5 | Copyright (C) 2021-2022 Yves Vollmeier 6 | This program is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see . 16 | */ 17 | 18 | #ifndef SERIAL_H 19 | #define SERIAL_H 20 | 21 | #define COM1 0x3f8 22 | 23 | // bash color codes 24 | #define TERM_BLACK "\e[0;30m" 25 | #define TERM_RED "\e[0;31m" 26 | #define TERM_GREEN "\e[0;32m" 27 | #define TERM_YELLOW "\e[0;33m" 28 | #define TERM_BLUE "\e[0;34m" 29 | #define TERM_PURPLE "\e[0;35m" 30 | #define TERM_CYAN "\e[0;36m" 31 | #define TERM_WHITE "\e[0;37m" 32 | #define TERM_COLOR_RESET "\e[0m" 33 | 34 | void serial_init(void); 35 | char serial_recv(void); 36 | void serial_send_char(char c); 37 | void serial_send_string(char *str); 38 | void serial_set_color(char *color_code); 39 | 40 | #endif 41 | -------------------------------------------------------------------------------- /src/kernel/firmware/acpi/acpi.c: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of an x86_64 hobbyist operating system called KnutOS 3 | Everything is openly developed on GitHub: https://github.com/Tix3Dev/KnutOS/ 4 | 5 | Copyright (C) 2021-2022 Yves Vollmeier 6 | This program is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see . 16 | */ 17 | 18 | #include 19 | 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | 33 | static rsdt_structure_t *rsdt; 34 | 35 | // TODO: write description when fully done (at least when MADT and APIC are done) 36 | void acpi_init(struct stivale2_struct *stivale2_struct) 37 | { 38 | struct stivale2_struct_tag_rsdp *rsdp_tag = stivale2_get_tag(stivale2_struct, 39 | STIVALE2_STRUCT_TAG_RSDP_ID); 40 | 41 | rsdp_init(rsdp_tag->rsdp); 42 | 43 | rsdt = (rsdt_structure_t *)phys_to_higher_half_data((uintptr_t)get_rsdp_structure()->rsdt_address); 44 | 45 | // having a RSDT is equivalent to having ACPI supported 46 | if (acpi_check_sdt_header(&rsdt->header, "RSDT") != 0) 47 | { 48 | serial_log(ERROR, "No ACPI was found on this computer!\n"); 49 | kernel_log(ERROR, "No ACPI was found on this computer!\n"); 50 | 51 | 52 | serial_log(ERROR, "Kernel halted!\n"); 53 | kernel_log(ERROR, "Kernel halted!\n"); 54 | 55 | for (;;) 56 | asm ("hlt"); 57 | } 58 | 59 | madt_init(); 60 | 61 | serial_log(INFO, "ACPI initialized\n"); 62 | kernel_log(INFO, "ACPI initialized\n"); 63 | } 64 | 65 | // check if the signature of the SDT header matches the parameter (signature) and 66 | // verify it's checksum 67 | int acpi_check_sdt_header(sdt_header_t *sdt_header, const char *signature) 68 | { 69 | if (memcmp(sdt_header->signature, signature, 4) == 0 && 70 | acpi_verify_sdt_header_checksum(sdt_header, signature) == 0) 71 | return 0; 72 | 73 | return 1; 74 | } 75 | 76 | // check if the sum of all bytes in a SDT header is equal to zero 77 | int acpi_verify_sdt_header_checksum(sdt_header_t *sdt_header, const char *signature) 78 | { 79 | uint8_t checksum = 0; 80 | uint8_t *ptr = (uint8_t *)sdt_header; 81 | uint8_t current_byte; 82 | 83 | serial_log(INFO, "Verifying %s checksum:\n", signature); 84 | kernel_log(INFO, "Verifying %s checksum:\n", signature); 85 | 86 | serial_set_color(TERM_PURPLE); 87 | 88 | debug("First %d bytes are being checked: ", sdt_header->length); 89 | printk(GFX_PURPLE, "First %d bytes are being checked: ", sdt_header->length); 90 | 91 | for (uint8_t i = 0; i < sdt_header->length; i++) 92 | { 93 | current_byte = ptr[i]; 94 | debug("%x ", current_byte); 95 | printk(GFX_PURPLE, "%x ", current_byte); 96 | 97 | checksum += current_byte; 98 | } 99 | 100 | debug("\n"); 101 | printk(GFX_PURPLE, "\n"); 102 | 103 | serial_set_color(TERM_COLOR_RESET); 104 | 105 | checksum = checksum & 0xFF; 106 | 107 | if (checksum == 0) 108 | { 109 | serial_log(INFO, "%s checksum is verified.\n", signature); 110 | kernel_log(INFO, "%s checksum is verified.\n", signature); 111 | 112 | return 0; 113 | } 114 | else 115 | { 116 | serial_log(ERROR, "%s checksum isn't 0! Checksum: 0x%x\n", signature, checksum); 117 | kernel_log(ERROR, "%s checksum isn't 0! Checksum: 0x%x\n", signature, checksum); 118 | 119 | return 1; 120 | } 121 | } 122 | 123 | // traverse RSDT to find table according to identifier 124 | sdt_header_t *acpi_find_sdt_table(const char *signature) 125 | { 126 | size_t entry_count = (rsdt->header.length - sizeof(rsdt->header)) / (has_xsdt() ? 8 : 4); 127 | sdt_header_t *current_entry; 128 | 129 | for (size_t i = 0; i < entry_count; i++) 130 | { 131 | current_entry = (sdt_header_t *)(uintptr_t)rsdt->entries[i]; 132 | 133 | if (acpi_check_sdt_header(current_entry, signature) == 0) 134 | return (sdt_header_t *)phys_to_higher_half_data((uintptr_t)current_entry); 135 | } 136 | 137 | serial_log(ERROR, "Could not find SDT with signature '%s'!\n", signature); 138 | kernel_log(ERROR, "Could not find SDT with signature '%s'!\n", signature); 139 | 140 | return NULL; 141 | } 142 | -------------------------------------------------------------------------------- /src/kernel/firmware/acpi/acpi.h: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of an x86_64 hobbyist operating system called KnutOS 3 | Everything is openly developed on GitHub: https://github.com/Tix3Dev/KnutOS/ 4 | 5 | Copyright (C) 2021-2022 Yves Vollmeier 6 | This program is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see . 16 | */ 17 | 18 | #include 19 | 20 | #ifndef ACPI_H 21 | #define ACPI_H 22 | 23 | void acpi_init(struct stivale2_struct *stivale2_struct); 24 | int acpi_check_sdt_header(sdt_header_t *sdt_header, const char *signature); 25 | int acpi_verify_sdt_header_checksum(sdt_header_t *sdt_header, const char *signature); 26 | sdt_header_t *acpi_find_sdt_table(const char *signature); 27 | 28 | #endif 29 | -------------------------------------------------------------------------------- /src/kernel/firmware/acpi/tables/madt.c: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of an x86_64 hobbyist operating system called KnutOS 3 | Everything is openly developed on GitHub: https://github.com/Tix3Dev/KnutOS/ 4 | 5 | Copyright (C) 2021-2022 Yves Vollmeier 6 | This program is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see . 16 | */ 17 | 18 | #include 19 | 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | 27 | madt_structure_t *madt; 28 | 29 | madt_lapic_t **madt_lapics; 30 | madt_io_apic_t **madt_io_apics; 31 | madt_iso_t **madt_isos; 32 | madt_lapic_nmi_t **madt_lapic_nmis; 33 | 34 | size_t madt_lapics_i = 0; 35 | size_t madt_io_apics_i = 0; 36 | size_t madt_isos_i = 0; 37 | size_t madt_lapic_nmis_i = 0; 38 | 39 | void madt_init(void) 40 | { 41 | madt = (madt_structure_t *)(uintptr_t)acpi_find_sdt_table("APIC"); 42 | 43 | if (madt == NULL) 44 | { 45 | serial_log(ERROR, "No MADT was found on this computer!\n"); 46 | kernel_log(ERROR, "No MADT was found on this computer!\n"); 47 | 48 | 49 | serial_log(ERROR, "Kernel halted!\n"); 50 | kernel_log(ERROR, "Kernel halted!\n"); 51 | 52 | for (;;) 53 | asm ("hlt"); 54 | } 55 | 56 | 57 | madt_lapics = kmalloc(256); 58 | madt_io_apics = kmalloc(256); 59 | madt_isos = kmalloc(256); 60 | madt_lapic_nmis = kmalloc(256); 61 | 62 | 63 | size_t madt_table_length = (size_t)&madt->header + madt->header.length; 64 | 65 | uint8_t *table_ptr = (uint8_t *)&madt->table; 66 | 67 | while ((size_t)table_ptr < madt_table_length) 68 | { 69 | switch (*table_ptr) 70 | { 71 | case PROCESSOR_LOCAL_APIC: 72 | serial_log(INFO, "MADT Initialization: Found local APIC\n"); 73 | kernel_log(INFO, "MADT Initialization: Found local APIC\n"); 74 | 75 | madt_lapics[madt_lapics_i++] = (madt_lapic_t *)table_ptr; 76 | 77 | break; 78 | 79 | case IO_APIC: 80 | serial_log(INFO, "MADT Initialization: Found IO APIC\n"); 81 | kernel_log(INFO, "MADT Initialization: Found IO APIC\n"); 82 | 83 | madt_io_apics[madt_io_apics_i++] = (madt_io_apic_t *)table_ptr; 84 | 85 | break; 86 | 87 | case INTERRUPT_SOURCE_OVERRIDE: 88 | serial_log(INFO, "MADT Initialization: Found interrupt source override\n"); 89 | kernel_log(INFO, "MADT Initialization: Found interrupt source override\n"); 90 | 91 | madt_isos[madt_isos_i++] = (madt_iso_t *)table_ptr; 92 | 93 | break; 94 | 95 | case LAPIC_NMI: 96 | serial_log(INFO, "MADT Initialization: Found local APIC non maskable interrupt\n"); 97 | kernel_log(INFO, "MADT Initialization: Found local APIC non maskable interrupt\n"); 98 | 99 | madt_lapic_nmis[madt_lapic_nmis_i++] = (madt_lapic_nmi_t *)table_ptr; 100 | 101 | break; 102 | } 103 | 104 | table_ptr += *(table_ptr + 1); 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /src/kernel/firmware/acpi/tables/madt.h: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of an x86_64 hobbyist operating system called KnutOS 3 | Everything is openly developed on GitHub: https://github.com/Tix3Dev/KnutOS/ 4 | 5 | Copyright (C) 2021-2022 Yves Vollmeier 6 | This program is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see . 16 | */ 17 | 18 | #include 19 | 20 | #include 21 | 22 | #ifndef MADT_H 23 | #define MADT_H 24 | 25 | typedef struct __attribute__((__packed__)) 26 | { 27 | uint8_t entry_type; // according to madt_entry_type_t 28 | uint8_t record_length; 29 | } madt_record_table_entry_t; 30 | 31 | // uncommented the ones I probably won't be using for a long time 32 | // -> because of that I didn't add the tables for them 33 | typedef enum 34 | { 35 | PROCESSOR_LOCAL_APIC = 0x0, 36 | IO_APIC = 0x1, 37 | INTERRUPT_SOURCE_OVERRIDE = 0x2, 38 | // NMI_SOURCE = 0x3, 39 | LAPIC_NMI = 0x4, 40 | // LAPIC_ADDRESS_OVERRIDE = 0x5, 41 | // IO_SAPIC = 0x6, 42 | // LOCAL_SAPIC = 0x7, 43 | // PLATFORM_INTERRUPT_SOURCES = 0x8, 44 | // PROCESSOR_LOCAL_x2APIC = 0x9 45 | // LOCAL_x2APIC_NMI = 0xA, 46 | // GIC_CPU_INTERFACE = 0xB, 47 | // GIC_DISTRIBUTOR = 0xC, 48 | // GIC_MSI_FRAME = 0xD 49 | // GIC_REDISTRIBUTOR = 0xE, 50 | // GIC_INTERRUPT_TRANSLATION_SERVICE = 0xF, 51 | // MULTIPROCESSOR_WAKEUP = 0x10 52 | } madt_entry_type_t; 53 | 54 | // entry type 0x0 - processor local apic 55 | typedef struct __attribute__((__packed__)) 56 | { 57 | madt_record_table_entry_t record; 58 | uint8_t acpi_processor_id; 59 | uint8_t acpi_id; 60 | uint32_t flags; 61 | } madt_lapic_t; 62 | 63 | // entry type 0x1 - IO apic 64 | typedef struct __attribute__((__packed__)) 65 | { 66 | madt_record_table_entry_t record; 67 | uint8_t io_apic_id; 68 | uint8_t reserved; 69 | uint8_t io_apic_address; 70 | uint8_t global_system_interrupt_base; 71 | } madt_io_apic_t; 72 | 73 | // entry type 0x2 - interrupt source override 74 | typedef struct __attribute__((__packed__)) 75 | { 76 | madt_record_table_entry_t record; 77 | uint8_t bus_source; 78 | uint8_t irq_source; 79 | uint32_t global_system_interrupt; 80 | uint16_t flags; 81 | } madt_iso_t; 82 | 83 | // entry type 0x4 - non maskable interrupts 84 | typedef struct __attribute__((__packed__)) 85 | { 86 | madt_record_table_entry_t record; 87 | uint8_t acpi_processor_id; 88 | uint16_t flags; 89 | uint8_t lint; 90 | } madt_lapic_nmi_t; 91 | 92 | typedef struct __attribute__((__packed__)) 93 | { 94 | sdt_header_t header; 95 | uint32_t lapic_address; 96 | uint32_t flags; 97 | madt_record_table_entry_t table[]; 98 | } madt_structure_t; 99 | 100 | extern madt_structure_t *madt; 101 | 102 | extern madt_lapic_t **madt_lapics; 103 | extern madt_io_apic_t **madt_io_apics; 104 | extern madt_iso_t **madt_isos; 105 | extern madt_lapic_nmi_t **madt_lapic_nmis; 106 | 107 | extern size_t madt_lapics_i; 108 | extern size_t madt_io_apics_i; 109 | extern size_t madt_isos_i; 110 | extern size_t madt_lapic_nmis_i; 111 | 112 | void madt_init(void); 113 | 114 | #endif 115 | -------------------------------------------------------------------------------- /src/kernel/firmware/acpi/tables/rsdp.c: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of an x86_64 hobbyist operating system called KnutOS 3 | Everything is openly developed on GitHub: https://github.com/Tix3Dev/KnutOS/ 4 | 5 | Copyright (C) 2021-2022 Yves Vollmeier 6 | This program is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see . 16 | */ 17 | 18 | #include 19 | 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | 27 | static rsdp_structure_t *rsdp; 28 | static bool has_xsdt_var = false; 29 | 30 | // verify only the first 20 bytes of RSDP, setting global struct and checking ACPI version 31 | void rsdp_init(uint64_t rsdp_address) 32 | { 33 | rsdp_verify_checksum(rsdp_address); 34 | 35 | rsdp = (rsdp_structure_t *)rsdp_address; 36 | 37 | serial_set_color(TERM_PURPLE); 38 | 39 | // debug("ACPI Revision number: %d\n", rsdp->revision); 40 | if (rsdp->revision >= 2) // if revision is 2, then acpi version is 2.0 or above 41 | { 42 | has_xsdt_var = true; 43 | 44 | serial_log(INFO, "ACPI Version 2.0 or above is used\n"); 45 | kernel_log(INFO, "ACPI Version 2.0 or above is used\n"); 46 | } 47 | else // if revision is 0, then acpi version is 1.0 48 | { 49 | serial_log(INFO, "ACPI Version 1.0 is used\n"); 50 | kernel_log(INFO, "ACPI Version 1.0 is used\n"); 51 | } 52 | 53 | serial_set_color(TERM_COLOR_RESET); 54 | } 55 | 56 | // sum up the first 20 bytes of RSDP (starting with rsdp_address) 57 | // and check if this number is equal to zero 58 | void rsdp_verify_checksum(uint64_t rsdp_address) 59 | { 60 | uint8_t checksum = 0; 61 | uint8_t *ptr = (uint8_t *)rsdp_address; 62 | uint8_t current_byte; 63 | 64 | serial_log(INFO, "Verifying RSDP checksum:\n"); 65 | kernel_log(INFO, "Verifying RSDP checksum:\n"); 66 | 67 | serial_set_color(TERM_PURPLE); 68 | 69 | debug("20 first bytes are being checked: "); 70 | printk(GFX_PURPLE, "20 first bytes are being checked: "); 71 | 72 | for (uint8_t i = 0; i < 20; i++) 73 | { 74 | current_byte = ptr[i]; 75 | debug("%x ", current_byte); 76 | printk(GFX_PURPLE, "%x ", current_byte); 77 | 78 | checksum += current_byte; 79 | } 80 | 81 | debug("\n"); 82 | printk(GFX_PURPLE, "\n"); 83 | 84 | serial_set_color(TERM_COLOR_RESET); 85 | 86 | if ((checksum & 0xFF) == 0x00) 87 | { 88 | serial_log(INFO, "RSDP checksum is verified\n"); 89 | kernel_log(INFO, "RSDP checksum is verified\n"); 90 | } 91 | else 92 | { 93 | serial_log(ERROR, "RSDP checksum isn't 0! Checksum: 0x%x\n", checksum & 0xFF); 94 | kernel_log(ERROR, "RSDP checksum isn't 0! Checksum: 0x%x\n", checksum & 0xFF); 95 | 96 | serial_log(ERROR, "Kernel halted!\n"); 97 | kernel_log(ERROR, "Kernel halted!\n"); 98 | 99 | for (;;) 100 | asm ("hlt"); 101 | } 102 | } 103 | 104 | // return the RSDP structure 105 | rsdp_structure_t *get_rsdp_structure(void) 106 | { 107 | return rsdp; 108 | } 109 | 110 | // return whether the Extended Root System Description Table is available or not 111 | // (otherwise we just use the Root System Description Table) 112 | bool has_xsdt(void) 113 | { 114 | return has_xsdt_var; 115 | } 116 | -------------------------------------------------------------------------------- /src/kernel/firmware/acpi/tables/rsdp.h: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of an x86_64 hobbyist operating system called KnutOS 3 | Everything is openly developed on GitHub: https://github.com/Tix3Dev/KnutOS/ 4 | 5 | Copyright (C) 2021-2022 Yves Vollmeier 6 | This program is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see . 16 | */ 17 | 18 | #include 19 | 20 | #ifndef RSDP_H 21 | #define RSDP_H 22 | 23 | typedef struct __attribute__((__packed__)) 24 | { 25 | // ACPI version 1.0 26 | char signature[8]; 27 | uint8_t checksum; 28 | char oemid[6]; 29 | uint8_t revision; 30 | uint32_t rsdt_address; 31 | 32 | // ACPI version 2.0+ 33 | uint32_t length; 34 | uint64_t xsdt_address; 35 | uint8_t extended_checksum; 36 | uint8_t reserved[3]; 37 | 38 | } rsdp_structure_t; 39 | 40 | void rsdp_init(uint64_t rsdp_address); 41 | void rsdp_verify_checksum(uint64_t rsdp_address); 42 | rsdp_structure_t *get_rsdp_structure(void); 43 | bool has_xsdt(void); 44 | 45 | #endif 46 | -------------------------------------------------------------------------------- /src/kernel/firmware/acpi/tables/rsdt.h: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of an x86_64 hobbyist operating system called KnutOS 3 | Everything is openly developed on GitHub: https://github.com/Tix3Dev/KnutOS/ 4 | 5 | Copyright (C) 2021-2022 Yves Vollmeier 6 | This program is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see . 16 | */ 17 | 18 | #include 19 | 20 | #ifndef RSDT_H 21 | #define RSDT_H 22 | 23 | typedef struct __attribute__((__packed__)) 24 | { 25 | sdt_header_t header; 26 | uint32_t entries[]; 27 | } rsdt_structure_t; 28 | 29 | #endif 30 | -------------------------------------------------------------------------------- /src/kernel/firmware/acpi/tables/sdth.h: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of an x86_64 hobbyist operating system called KnutOS 3 | Everything is openly developed on GitHub: https://github.com/Tix3Dev/KnutOS/ 4 | 5 | Copyright (C) 2021-2022 Yves Vollmeier 6 | This program is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see . 16 | */ 17 | 18 | #ifndef SDTH_H 19 | #define SDTH_H 20 | 21 | typedef struct __attribute__((__packed__)) 22 | { 23 | char signature[4]; 24 | uint32_t length; 25 | uint8_t revision; 26 | uint8_t checksum; 27 | char oem_string[6]; 28 | char oem_table_id[8]; 29 | uint32_t oem_revision; 30 | char creator_id[4]; 31 | uint32_t creator_revision; 32 | } sdt_header_t; 33 | 34 | #endif 35 | -------------------------------------------------------------------------------- /src/kernel/gdt/gdt.c: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of an x86_64 hobbyist operating system called KnutOS 3 | Everything is openly developed on GitHub: https://github.com/Tix3Dev/KnutOS/ 4 | 5 | Copyright (C) 2021-2022 Yves Vollmeier 6 | This program is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see . 16 | */ 17 | 18 | // special thanks to this site (as parts of the code are from there): 19 | // https://blog.llandsmeer.com/tech/2019/07/21/uefi-x64-userland.html 20 | 21 | #include 22 | 23 | #include 24 | #include 25 | 26 | extern void _load_gdt_and_tss_asm(struct GDT_Pointer *ptr); 27 | 28 | static struct TSS tss; 29 | static struct GDT gdt; 30 | static struct GDT_Pointer gdt_pointer; 31 | 32 | // set the arguments for a given segment 33 | void create_descriptors(void) 34 | { 35 | // 0x00: null 36 | gdt.null.limit_15_0 = 0; 37 | gdt.null.base_15_0 = 0; 38 | gdt.null.base_23_16 = 0; 39 | gdt.null.type = 0x00; 40 | gdt.null.limit_19_16_and_flags = 0x00; 41 | gdt.null.base_31_24 = 0; 42 | 43 | // 0x08: kernel code (kernel base selector) 44 | gdt.kernel_code.limit_15_0 = 0; 45 | gdt.kernel_code.base_15_0 = 0; 46 | gdt.kernel_code.base_23_16 = 0; 47 | gdt.kernel_code.type = 0x9A; 48 | gdt.kernel_code.limit_19_16_and_flags = 0xA0; 49 | gdt.kernel_code.base_31_24 = 0; 50 | 51 | // 0x10: kernel data 52 | gdt.kernel_data.limit_15_0 = 0; 53 | gdt.kernel_data.base_15_0 = 0; 54 | gdt.kernel_data.base_23_16 = 0; 55 | gdt.kernel_data.type = 0x92; 56 | gdt.kernel_data.limit_19_16_and_flags = 0xA0; 57 | gdt.kernel_data.base_31_24 = 0; 58 | 59 | // 0x18: null (user base selector) 60 | gdt.null2.limit_15_0 = 0; 61 | gdt.null2.base_15_0 = 0; 62 | gdt.null2.base_23_16 = 0; 63 | gdt.null2.type = 0x00; 64 | gdt.null2.limit_19_16_and_flags = 0x00; 65 | gdt.null2.base_31_24 = 0; 66 | 67 | // 0x20: user data 68 | gdt.user_data.limit_15_0 = 0; 69 | gdt.user_data.base_15_0 = 0; 70 | gdt.user_data.base_23_16 = 0; 71 | gdt.user_data.type = 0x92; 72 | gdt.user_data.limit_19_16_and_flags = 0xA0; 73 | gdt.user_data.base_31_24 = 0; 74 | 75 | // 0x28: user code 76 | gdt.user_code.limit_15_0 = 0; 77 | gdt.user_code.base_15_0 = 0; 78 | gdt.user_code.base_23_16 = 0; 79 | gdt.user_code.type = 0x9A; 80 | gdt.user_code.limit_19_16_and_flags = 0xA0; 81 | gdt.user_code.base_31_24 = 0; 82 | 83 | // 0x30: ovmf data 84 | gdt.ovmf_data.limit_15_0 = 0; 85 | gdt.ovmf_data.base_15_0 = 0; 86 | gdt.ovmf_data.base_23_16 = 0; 87 | gdt.ovmf_data.type = 0x92; 88 | gdt.ovmf_data.limit_19_16_and_flags = 0xA0; 89 | gdt.ovmf_data.base_31_24 = 0; 90 | 91 | // 0x38: ovmf code 92 | gdt.ovmf_code.limit_15_0 = 0; 93 | gdt.ovmf_code.base_15_0 = 0; 94 | gdt.ovmf_code.base_23_16 = 0; 95 | gdt.ovmf_code.type = 0x9A; 96 | gdt.ovmf_code.limit_19_16_and_flags = 0xA0; 97 | gdt.ovmf_code.base_31_24 = 0; 98 | 99 | // 0x40: tss low 100 | gdt.tss_low.limit_15_0 = 0; 101 | gdt.tss_low.base_15_0 = 0; 102 | gdt.tss_low.base_23_16 = 0; 103 | gdt.tss_low.type = 0x89; 104 | gdt.tss_low.limit_19_16_and_flags = 0xA0; 105 | gdt.tss_low.base_31_24 = 0; 106 | 107 | // 0x48: tss high 108 | gdt.tss_high.limit_15_0 = 0; 109 | gdt.tss_high.base_15_0 = 0; 110 | gdt.tss_high.base_23_16 = 0; 111 | gdt.tss_high.type = 0x00; 112 | gdt.tss_high.limit_19_16_and_flags = 0x00; 113 | gdt.tss_high.base_31_24 = 0; 114 | } 115 | 116 | // create descriptors and load GDT and TSS 117 | void gdt_init(void) 118 | { 119 | create_descriptors(); 120 | 121 | // memzero the TSS 122 | for (uint64_t i = 0; i < sizeof(tss); i++) 123 | ((uint8_t *)(void *)&tss)[i] = 0; 124 | 125 | uint64_t tss_base = ((uint64_t)&tss); 126 | 127 | gdt.tss_low.base_15_0 = tss_base & 0xffff; 128 | gdt.tss_low.base_23_16 = (tss_base >> 16) & 0xff; 129 | gdt.tss_low.base_31_24 = (tss_base >> 24) & 0xff; 130 | gdt.tss_low.limit_15_0 = sizeof(tss); 131 | gdt.tss_high.limit_15_0 = (tss_base >> 32) & 0xffff; 132 | gdt.tss_high.base_15_0 = (tss_base >> 48) & 0xffff; 133 | 134 | gdt_pointer.limit = sizeof(gdt) - 1; 135 | gdt_pointer.base = (uint64_t)&gdt; 136 | 137 | _load_gdt_and_tss_asm(&gdt_pointer); 138 | 139 | serial_log(INFO, "GDT initialized\n"); 140 | kernel_log(INFO, "GDT initialized\n"); 141 | } 142 | -------------------------------------------------------------------------------- /src/kernel/gdt/gdt.h: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of an x86_64 hobbyist operating system called KnutOS 3 | Everything is openly developed on GitHub: https://github.com/Tix3Dev/KnutOS/ 4 | 5 | Copyright (C) 2021-2022 Yves Vollmeier 6 | This program is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see . 16 | */ 17 | 18 | #ifndef GDT_H 19 | #define GDT_H 20 | 21 | // describes the attributes of a given segment 22 | struct GDT_Descriptor 23 | { 24 | uint16_t limit_15_0; 25 | uint16_t base_15_0; 26 | uint8_t base_23_16; 27 | uint8_t type; 28 | uint8_t limit_19_16_and_flags; 29 | uint8_t base_31_24; 30 | } __attribute__((packed)); // for no special compiler optimization 31 | 32 | // task state segment (for graphical layout see Intel SDM Figure 7-11) 33 | struct TSS 34 | { 35 | uint32_t reserved0; 36 | uint64_t rsp0; 37 | uint64_t rsp1; 38 | uint64_t rsp2; 39 | uint64_t reserved1; 40 | uint64_t ist1; 41 | uint64_t ist2; 42 | uint64_t ist3; 43 | uint64_t ist4; 44 | uint64_t ist5; 45 | uint64_t ist6; 46 | uint64_t ist7; 47 | uint64_t reserved2; 48 | uint16_t reserved3; 49 | uint16_t iopb_offset; 50 | } __attribute__((packed)); // for no special compiler optimization 51 | 52 | // combines everything 53 | __attribute__((aligned(4096))) 54 | struct GDT 55 | { 56 | struct GDT_Descriptor null; 57 | struct GDT_Descriptor kernel_code; 58 | struct GDT_Descriptor kernel_data; 59 | struct GDT_Descriptor null2; 60 | struct GDT_Descriptor user_data; 61 | struct GDT_Descriptor user_code; 62 | struct GDT_Descriptor ovmf_data; 63 | struct GDT_Descriptor ovmf_code; 64 | struct GDT_Descriptor tss_low; 65 | struct GDT_Descriptor tss_high; 66 | } __attribute__((packed)); // for no special compiler optimization 67 | 68 | // used to load the GDT into the gdtr register 69 | struct GDT_Pointer 70 | { 71 | uint16_t limit; 72 | uint64_t base; 73 | } __attribute__((packed)); // for no special compiler optimization 74 | 75 | void gdt_init(void); 76 | 77 | #endif 78 | -------------------------------------------------------------------------------- /src/kernel/gdt/gdt_asm.s: -------------------------------------------------------------------------------- 1 | ; This file is part of an x86_64 hobbyist operating system called KnutOS 2 | ; Everything is openly developed on GitHub: https://github.com/Tix3Dev/KnutOS/ 3 | ; 4 | ; Copyright (C) 2021-2022 Yves Vollmeier 5 | ; This program is free software: you can redistribute it and/or modify 6 | ; it under the terms of the GNU General Public License as published by 7 | ; the Free Software Foundation, either version 3 of the License, or 8 | ; (at your option) any later version. 9 | ; This program is distributed in the hope that it will be useful, 10 | ; but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | ; GNU General Public License for more details. 13 | ; You should have received a copy of the GNU General Public License 14 | ; along with this program. If not, see . 15 | 16 | global _load_gdt_and_tss_asm 17 | 18 | _load_gdt_and_tss_asm: 19 | lgdt [rdi] ; load GDT -> rdi is the first argument passed 20 | ; _load_gdt_and_tss_asm(struct GDT_Pointer *ptr) 21 | 22 | mov ax, 0x40 ; 0x40 is the TSS segment 23 | ltr ax ; load TSS 24 | 25 | mov ax, 0x10 ; 0x10 is the kernel data segment 26 | mov ds, ax ; load kernel data segment (into data segment registers) 27 | mov es, ax 28 | mov fs, ax 29 | mov gs, ax 30 | mov ss, ax 31 | 32 | pop rdi ; pop return address 33 | mov rax, 0x08 ; 0x08 is the kernel code segment 34 | push rax ; push the kernel code segment 35 | push rdi ; push return address 36 | retfq ; far return 37 | -------------------------------------------------------------------------------- /src/kernel/interrupts/idt.c: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of an x86_64 hobbyist operating system called KnutOS 3 | Everything is openly developed on GitHub: https://github.com/Tix3Dev/KnutOS/ 4 | 5 | Copyright (C) 2021-2022 Yves Vollmeier 6 | This program is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see . 16 | */ 17 | 18 | #include 19 | 20 | #include 21 | #include 22 | #include 23 | #include 24 | 25 | extern void _load_idt_asm(struct IDT_Pointer *ptr); 26 | extern uintptr_t _isr_names_asm[]; 27 | 28 | static struct IDT_Descriptor idt[256]; 29 | static struct IDT_Pointer idt_pointer; 30 | 31 | // set the arguments for a IDT entry 32 | void create_descriptor(uint8_t index, uint8_t type_and_attributes) 33 | { 34 | uint64_t offset = _isr_names_asm[index]; 35 | 36 | idt[index].offset_15_0 = offset & 0xFFFF; 37 | idt[index].selector = 0x08; 38 | idt[index].ist = 0; 39 | idt[index].type_and_attributes = type_and_attributes; 40 | idt[index].offset_31_16 = (offset >> 16) & 0xFFFF; 41 | idt[index].offset_63_32 = (offset >> 32) & 0xFFFFFFFF; 42 | idt[index].zero = 0; 43 | } 44 | 45 | // create descriptors, remap the PIC and load IDT 46 | void idt_init(void) 47 | { 48 | // create 32 descriptors for exceptions 49 | create_descriptor(0, 0x8E); 50 | create_descriptor(1, 0x8E); 51 | create_descriptor(2, 0x8E); 52 | create_descriptor(3, 0x8E); 53 | create_descriptor(4, 0x8E); 54 | create_descriptor(5, 0x8E); 55 | create_descriptor(6, 0x8E); 56 | create_descriptor(7, 0x8E); 57 | create_descriptor(8, 0x8E); 58 | create_descriptor(9, 0x8E); 59 | create_descriptor(10, 0x8E); 60 | create_descriptor(11, 0x8E); 61 | create_descriptor(12, 0x8E); 62 | create_descriptor(13, 0x8E); 63 | create_descriptor(14, 0x8E); 64 | create_descriptor(15, 0x8E); 65 | create_descriptor(16, 0x8E); 66 | create_descriptor(17, 0x8E); 67 | create_descriptor(18, 0x8E); 68 | create_descriptor(19, 0x8E); 69 | create_descriptor(20, 0x8E); 70 | create_descriptor(21, 0x8E); 71 | create_descriptor(22, 0x8E); 72 | create_descriptor(23, 0x8E); 73 | create_descriptor(24, 0x8E); 74 | create_descriptor(25, 0x8E); 75 | create_descriptor(26, 0x8E); 76 | create_descriptor(27, 0x8E); 77 | create_descriptor(28, 0x8E); 78 | create_descriptor(29, 0x8E); 79 | create_descriptor(30, 0x8E); 80 | create_descriptor(31, 0x8E); 81 | 82 | // remap the PIC 83 | pic_remap(); 84 | 85 | // create 16 descriptors IRQ (the 16 standard ISA IRQs) 86 | create_descriptor(32, 0x8E); 87 | create_descriptor(33, 0x8E); 88 | create_descriptor(34, 0x8E); 89 | create_descriptor(35, 0x8E); 90 | create_descriptor(36, 0x8E); 91 | create_descriptor(37, 0x8E); 92 | create_descriptor(38, 0x8E); 93 | create_descriptor(39, 0x8E); 94 | create_descriptor(40, 0x8E); 95 | create_descriptor(41, 0x8E); 96 | create_descriptor(42, 0x8E); 97 | create_descriptor(43, 0x8E); 98 | create_descriptor(44, 0x8E); 99 | create_descriptor(45, 0x8E); 100 | create_descriptor(46, 0x8E); 101 | create_descriptor(47, 0x8E); 102 | 103 | // apic spurious interrupt 104 | create_descriptor(255, 0x8E); 105 | 106 | // mask keyboard IRQ 107 | pic_set_mask(1); 108 | 109 | // load IDT into idtr register 110 | idt_pointer.limit = sizeof(idt) - 1; 111 | idt_pointer.base = (uint64_t)&idt; 112 | 113 | _load_idt_asm(&idt_pointer); 114 | 115 | serial_log(INFO, "IDT initialized\n"); 116 | kernel_log(INFO, "IDT initialized\n"); 117 | } 118 | -------------------------------------------------------------------------------- /src/kernel/interrupts/idt.h: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of an x86_64 hobbyist operating system called KnutOS 3 | Everything is openly developed on GitHub: https://github.com/Tix3Dev/KnutOS/ 4 | 5 | Copyright (C) 2021-2022 Yves Vollmeier 6 | This program is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see . 16 | */ 17 | 18 | #ifndef IDT_H 19 | #define IDT_H 20 | 21 | // describes the attributes of an IDT entry 22 | struct IDT_Descriptor 23 | { 24 | uint16_t offset_15_0; // offset bits 0..15 25 | uint16_t selector; // a code segment selector in GDT or LDT 26 | uint8_t ist; // bits 0..2 holds Interrupt Stack Table offset, rest of bits zero. 27 | uint8_t type_and_attributes; // type and attributes 28 | uint16_t offset_31_16; // offset bits 16..31 29 | uint32_t offset_63_32; // offset bits 32..63 30 | uint32_t zero; // reserved 31 | }__attribute__((packed)); // for no special compiler optimization 32 | 33 | // used to load the IDT into the idtr register 34 | struct IDT_Pointer 35 | { 36 | uint16_t limit; 37 | uint64_t base; 38 | }__attribute__((packed)); // for no special compiler optimization 39 | 40 | void idt_init(void); 41 | 42 | #endif 43 | -------------------------------------------------------------------------------- /src/kernel/interrupts/idt_asm.s: -------------------------------------------------------------------------------- 1 | ; This file is part of an x86_64 hobbyist operating system called KnutOS 2 | ; Everything is openly developed on GitHub: https://github.com/Tix3Dev/KnutOS/ 3 | ; 4 | ; Copyright (C) 2021-2022 Yves Vollmeier 5 | ; This program is free software: you can redistribute it and/or modify 6 | ; it under the terms of the GNU General Public License as published by 7 | ; the Free Software Foundation, either version 3 of the License, or 8 | ; (at your option) any later version. 9 | ; This program is distributed in the hope that it will be useful, 10 | ; but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | ; GNU General Public License for more details. 13 | ; You should have received a copy of the GNU General Public License 14 | ; along with this program. If not, see . 15 | 16 | global _load_idt_asm 17 | 18 | _load_idt_asm: 19 | lidt [rdi] ; load IDT -> rdi is the first argument passed 20 | sti ; store interrupts 21 | ret ; return 22 | -------------------------------------------------------------------------------- /src/kernel/interrupts/interrupts.c: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of an x86_64 hobbyist operating system called KnutOS 3 | Everything is openly developed on GitHub: https://github.com/Tix3Dev/KnutOS/ 4 | 5 | Copyright (C) 2021-2022 Yves Vollmeier 6 | This program is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see . 16 | */ 17 | 18 | #include 19 | 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | 27 | static const char *exceptions[] = 28 | { 29 | "#DE: Divide Error", 30 | "#DB: Debug Exception", 31 | " — : NMI Interrupt", 32 | "#BP: Breakpoint", 33 | "#OF: Overflow", 34 | "#BR: BOUND Range Exceeded", 35 | "#UD: Invalid Opcode (Undefined Opcode)", 36 | "#NM: Device Not Available (No Math Coprocessor)", 37 | "#DF: Double Fault", 38 | "— : Coprocessor Segment Overrun (reserved)", 39 | "#TS: Invalid TSS", 40 | "#NP: Segment Not Present", 41 | "#SS: Stack-Segment Fault", 42 | "#GP: General Protection", 43 | "#PF: Page Fault", 44 | "— : (Intel reserved. Do not use.)", 45 | "#MF: x87 FPU Floating-Point Error (Math Fault)", 46 | "#AC: Alignment Check", 47 | "#MC: Machine Check", 48 | "#XM: SIMD Floating-Point Exception", 49 | "#VE: Virtualization Exception", 50 | "#CP: Control Protection Exception", 51 | "— : Intel reserved. Do not use.", 52 | "— : Intel reserved. Do not use.", 53 | "— : Intel reserved. Do not use.", 54 | "— : Intel reserved. Do not use.", 55 | "— : Intel reserved. Do not use.", 56 | "— : Intel reserved. Do not use.", 57 | "— : Intel reserved. Do not use.", 58 | "— : Intel reserved. Do not use.", 59 | "— : Intel reserved. Do not use.", 60 | "— : Intel reserved. Do not use." 61 | }; 62 | 63 | uint64_t isr_handler(uint64_t rsp) 64 | { 65 | interrupt_cpu_state_t *cpu = (interrupt_cpu_state_t*)rsp; 66 | 67 | // handle exceptions 68 | if (cpu->isr_number <= 31) 69 | { 70 | serial_set_color(TERM_RED); 71 | debug("\n────────────────────────\n"); 72 | debug("⚠ EXCEPTION OCCURRED! ⚠\n\n"); 73 | debug("⤷ ISR-No. %d: %s\n", cpu->isr_number, exceptions[cpu->isr_number]); 74 | debug("⤷ Error code: 0x%.16llx\n\n\n", cpu->error_code); 75 | serial_set_color(TERM_CYAN); 76 | debug("ℹ Register dump:\n\n"); 77 | debug("⤷ rax: 0x%.16llx, rbx: 0x%.16llx, rcx: 0x%.16llx, rdx: 0x%.16llx\n" 78 | "⤷ rsi: 0x%.16llx, rdi: 0x%.16llx, rbp: 0x%.16llx, r8 : 0x%.16llx\n" 79 | "⤷ r9 : 0x%.16llx, r10: 0x%.16llx, r11: 0x%.16llx, r12: 0x%.16llx\n" 80 | "⤷ r13: 0x%.16llx, r14: 0x%.16llx, r15: 0x%.16llx, ss : 0x%.16llx\n" 81 | "⤷ rsp: 0x%.16llx, rflags: 0x%.16llx, cs : 0x%.16llx, rip: 0x%.16llx\n", 82 | cpu->rax, cpu->rbx, cpu->rcx, cpu->rdx, 83 | cpu->rsi, cpu->rdi, cpu->rbp, cpu->r8, 84 | cpu->r9, cpu->r10, cpu->r11, cpu->r12, 85 | cpu->r13, cpu->r14, cpu->r15, cpu->ss, 86 | cpu->rsp, cpu->rflags, cpu->cs, cpu->rip); 87 | 88 | serial_set_color(TERM_COLOR_RESET); 89 | 90 | framebuffer_reset_screen(); 91 | printk(GFX_RED, "\n────────────────────────\n"); 92 | printk(GFX_RED, "⚠ EXCEPTION OCCURRED! ⚠\n\n"); 93 | printk(GFX_RED, "⤷ ISR-No. %d: %s\n", cpu->isr_number, exceptions[cpu->isr_number]); 94 | printk(GFX_RED, "⤷ Error code: 0x%.16llx\n\n\n", cpu->error_code); 95 | printk(GFX_CYAN, "ℹ Register dump:\n\n"); 96 | printk(GFX_CYAN, "⤷ rax: 0x%.16llx, rbx: 0x%.16llx, rcx: 0x%.16llx, rdx: 0x%.16llx\n" 97 | "⤷ rsi: 0x%.16llx, rdi: 0x%.16llx, rbp: 0x%.16llx, r8 : 0x%.16llx\n" 98 | "⤷ r9 : 0x%.16llx, r10: 0x%.16llx, r11: 0x%.16llx, r12: 0x%.16llx\n" 99 | "⤷ r13: 0x%.16llx, r14: 0x%.16llx, r15: 0x%.16llx, ss : 0x%.16llx\n" 100 | "⤷ rsp: 0x%.16llx, rflags: 0x%.16llx, cs : 0x%.16llx, rip: 0x%.16llx\n", 101 | cpu->rax, cpu->rbx, cpu->rcx, cpu->rdx, 102 | cpu->rsi, cpu->rdi, cpu->rbp, cpu->r8, 103 | cpu->r9, cpu->r10, cpu->r11, cpu->r12, 104 | cpu->r13, cpu->r14, cpu->r15, cpu->ss, 105 | cpu->rsp, cpu->rflags, cpu->cs, cpu->rip); 106 | 107 | // clear interrupts and halt forever 108 | while (1) 109 | asm volatile("cli; hlt"); 110 | } 111 | // handle IRQ's / hardware interrupts 112 | else if (cpu->isr_number >= 32 && cpu->isr_number <= 47) 113 | { 114 | // keyboard IRQ check -> call handler 115 | if (cpu->isr_number == 33) 116 | keyboard_irq_handler(); 117 | 118 | pic_signal_EOI(cpu->isr_number); 119 | } 120 | else if (cpu->isr_number == 255) 121 | { 122 | // apic spurious interrupt 123 | } 124 | 125 | return rsp; 126 | } 127 | -------------------------------------------------------------------------------- /src/kernel/interrupts/interrupts.h: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of an x86_64 hobbyist operating system called KnutOS 3 | Everything is openly developed on GitHub: https://github.com/Tix3Dev/KnutOS/ 4 | 5 | Copyright (C) 2021-2022 Yves Vollmeier 6 | This program is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see . 16 | */ 17 | 18 | #include 19 | 20 | #ifndef INTERRUPTS_H 21 | #define INTERRUPTS_H 22 | 23 | #define SPURIOUS_INTERRUPT 255 24 | 25 | #endif 26 | -------------------------------------------------------------------------------- /src/kernel/interrupts/isr_asm.s: -------------------------------------------------------------------------------- 1 | ; This file is part of an x86_64 hobbyist operating system called KnutOS 2 | ; Everything is openly developed on GitHub: https://github.com/Tix3Dev/KnutOS/ 3 | ; 4 | ; Copyright (C) 2021-2022 Yves Vollmeier 5 | ; This program is free software: you can redistribute it and/or modify 6 | ; it under the terms of the GNU General Public License as published by 7 | ; the Free Software Foundation, either version 3 of the License, or 8 | ; (at your option) any later version. 9 | ; This program is distributed in the hope that it will be useful, 10 | ; but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | ; GNU General Public License for more details. 13 | ; You should have received a copy of the GNU General Public License 14 | ; along with this program. If not, see . 15 | 16 | %include "src/kernel/assembly/definitions.inc" 17 | 18 | extern isr_handler 19 | 20 | global _isr_handler_asm 21 | global _isr_names_asm 22 | 23 | _isr_handler_asm: 24 | cld ; c code following the sysV ABI requires DF to be clear on function entry 25 | pusha64 ; push all 26 | 27 | mov rdi, rsp ; pass the stack pointer as an argument to the c function 28 | call isr_handler ; call the c function 29 | mov rsp, rax ; get the new stack pointer returned 30 | 31 | popa64 ; pop all 32 | add rsp, 16 ; pop error code and int number 33 | 34 | iretq ; return 35 | 36 | %macro ISR_NAME 1 37 | dq _ISR%1 38 | %endmacro 39 | 40 | %macro ISR_STUB_ERR 1 41 | _ISR%1: 42 | push %1 43 | jmp _isr_handler_asm 44 | %endmacro 45 | 46 | %macro ISR_STUB_NO_ERR 1 47 | _ISR%1: 48 | push 0 49 | push %1 50 | jmp _isr_handler_asm 51 | %endmacro 52 | 53 | 54 | ISR_STUB_NO_ERR 0 55 | ISR_STUB_NO_ERR 1 56 | ISR_STUB_NO_ERR 2 57 | ISR_STUB_NO_ERR 3 58 | ISR_STUB_NO_ERR 4 59 | ISR_STUB_NO_ERR 5 60 | ISR_STUB_NO_ERR 6 61 | ISR_STUB_NO_ERR 7 62 | ISR_STUB_ERR 8 63 | ISR_STUB_NO_ERR 9 64 | ISR_STUB_ERR 10 65 | ISR_STUB_ERR 11 66 | ISR_STUB_ERR 12 67 | ISR_STUB_ERR 13 68 | ISR_STUB_ERR 14 69 | ISR_STUB_NO_ERR 15 70 | ISR_STUB_NO_ERR 16 71 | ISR_STUB_ERR 17 72 | ISR_STUB_NO_ERR 18 73 | ISR_STUB_NO_ERR 19 74 | ISR_STUB_NO_ERR 20 75 | ISR_STUB_ERR 21 76 | ISR_STUB_NO_ERR 22 77 | ISR_STUB_NO_ERR 23 78 | ISR_STUB_NO_ERR 24 79 | ISR_STUB_NO_ERR 25 80 | ISR_STUB_NO_ERR 26 81 | ISR_STUB_NO_ERR 27 82 | ISR_STUB_NO_ERR 28 83 | ISR_STUB_NO_ERR 29 84 | ISR_STUB_NO_ERR 30 85 | ISR_STUB_NO_ERR 31 86 | 87 | ISR_STUB_NO_ERR 32 88 | ISR_STUB_NO_ERR 33 89 | ISR_STUB_NO_ERR 34 90 | ISR_STUB_NO_ERR 35 91 | ISR_STUB_NO_ERR 36 92 | ISR_STUB_NO_ERR 37 93 | ISR_STUB_NO_ERR 38 94 | ISR_STUB_NO_ERR 39 95 | ISR_STUB_NO_ERR 40 96 | ISR_STUB_NO_ERR 41 97 | ISR_STUB_NO_ERR 42 98 | ISR_STUB_NO_ERR 43 99 | ISR_STUB_NO_ERR 44 100 | ISR_STUB_NO_ERR 45 101 | ISR_STUB_NO_ERR 46 102 | ISR_STUB_NO_ERR 47 103 | 104 | _isr_names_asm: 105 | ISR_NAME 0 106 | ISR_NAME 1 107 | ISR_NAME 2 108 | ISR_NAME 3 109 | ISR_NAME 4 110 | ISR_NAME 5 111 | ISR_NAME 6 112 | ISR_NAME 7 113 | ISR_NAME 8 114 | ISR_NAME 9 115 | ISR_NAME 10 116 | ISR_NAME 11 117 | ISR_NAME 12 118 | ISR_NAME 13 119 | ISR_NAME 14 120 | ISR_NAME 15 121 | ISR_NAME 16 122 | ISR_NAME 17 123 | ISR_NAME 18 124 | ISR_NAME 19 125 | ISR_NAME 20 126 | ISR_NAME 21 127 | ISR_NAME 22 128 | ISR_NAME 23 129 | ISR_NAME 24 130 | ISR_NAME 25 131 | ISR_NAME 26 132 | ISR_NAME 27 133 | ISR_NAME 28 134 | ISR_NAME 29 135 | ISR_NAME 30 136 | ISR_NAME 31 137 | 138 | ISR_NAME 32 139 | ISR_NAME 33 140 | ISR_NAME 34 141 | ISR_NAME 35 142 | ISR_NAME 36 143 | ISR_NAME 37 144 | ISR_NAME 38 145 | ISR_NAME 39 146 | ISR_NAME 40 147 | ISR_NAME 41 148 | ISR_NAME 42 149 | ISR_NAME 43 150 | ISR_NAME 44 151 | ISR_NAME 45 152 | ISR_NAME 46 153 | ISR_NAME 47 154 | -------------------------------------------------------------------------------- /src/kernel/kernel.c: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of an x86_64 hobbyist operating system called KnutOS 3 | Everything is openly developed on GitHub: https://github.com/Tix3Dev/KnutOS/ 4 | 5 | Copyright (C) 2021-2022 Yves Vollmeier 6 | This program is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see . 16 | */ 17 | 18 | #include 19 | #include 20 | 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | 39 | void kmain(struct stivale2_struct *stivale2_struct) 40 | { 41 | framebuffer_init(stivale2_struct, GFX_BLACK); 42 | serial_init(); 43 | 44 | serial_log(INFO, "Framebuffer and serial initialized\n"); 45 | kernel_log(INFO, "Framebuffer and serial initialized\n"); 46 | 47 | serial_set_color(TERM_BLUE); 48 | debug("Welcome to:\n"); 49 | debug("%s", small_logo_text); 50 | serial_set_color(TERM_COLOR_RESET); 51 | 52 | serial_log(INFO, "Kernel started\n"); 53 | kernel_log(INFO, "Kernel started\n"); 54 | 55 | pmm_init(stivale2_struct); 56 | vmm_init(); 57 | gdt_init(); 58 | idt_init(); 59 | 60 | slab_init(); 61 | 62 | char *vendor_string = cpu_get_vendor_string(); 63 | serial_log(INFO, "CPU Vendor ID String: %s\n", vendor_string); 64 | kernel_log(INFO, "CPU Vendor ID String: %s\n", vendor_string); 65 | 66 | acpi_init(stivale2_struct); 67 | 68 | apic_init(); 69 | 70 | // keyboard_init(); // NOTE: is_keyboard_active is still false so no processing 71 | 72 | // TODO: proper timer 73 | // for (long i = 0; i < 5500000000; i++) // ~10 seconds 74 | // asm ("nop"); 75 | 76 | // shell_screen_init(); 77 | 78 | for (;;) 79 | asm ("hlt"); 80 | } 81 | -------------------------------------------------------------------------------- /src/kernel/linker.ld: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of an x86_64 hobbyist operating system called KnutOS 3 | Everything is openly developed on GitHub: https://github.com/Tix3Dev/KnutOS/ 4 | 5 | Copyright (C) 2021-2022 Yves Vollmeier 6 | This program is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see . 16 | */ 17 | 18 | OUTPUT_FORMAT(elf64-x86-64) 19 | OUTPUT_ARCH(i386:x86-64) 20 | 21 | ENTRY(kmain) 22 | 23 | PHDRS 24 | { 25 | null PT_NULL FLAGS(0) ; 26 | text PT_LOAD FLAGS((1 << 0) | (1 << 2)) ; 27 | rodata PT_LOAD FLAGS((1 << 2)) ; 28 | data PT_LOAD FLAGS((1 << 1) | (1 << 2)) ; 29 | dynamic PT_DYNAMIC FLAGS((1 << 1) | (1 << 2)) ; 30 | } 31 | 32 | SECTIONS 33 | { 34 | . = 0xffffffff80200000; 35 | 36 | .text : { 37 | *(.text*) 38 | } :text 39 | 40 | . += 0x1000; 41 | 42 | .stivale2hdr : { 43 | KEEP(*(.stivale2hdr)) 44 | } :rodata 45 | 46 | .rodata : { 47 | *(.rodata*) 48 | } :rodata 49 | 50 | . += 0x1000; 51 | 52 | .data : { 53 | *(.data*) 54 | } :data 55 | 56 | .dynamic : { 57 | *(.dynamic) 58 | } :data :dynamic 59 | 60 | .bss : { 61 | *(COMMON) 62 | *(.bss*) 63 | } :data 64 | } 65 | -------------------------------------------------------------------------------- /src/kernel/logo.c: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of an x86_64 hobbyist operating system called KnutOS 3 | Everything is openly developed on GitHub: https://github.com/Tix3Dev/KnutOS/ 4 | 5 | Copyright (C) 2021-2022 Yves Vollmeier 6 | This program is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see . 16 | */ 17 | 18 | const char *small_logo_text = "┌┐┌─┐ ┌┐ ┌───┐┌───┐\n" 19 | "│││┌┘ ┌┘└┐│┌─┐││┌─┐│\n" 20 | "│└┘┘ ┌─┐ ┌┐┌┐└┐┌┘││ │││└──┐\n" 21 | "│┌┐│ │┌┐┐││││ ││ ││ ││└──┐│\n" 22 | "│││└┐│││││└┘│ │└┐│└─┘││└─┘│\n" 23 | "└┘└─┘└┘└┘└──┘ └─┘└───┘└───┘\n"; 24 | 25 | const char *big_logo = "MMMMMMMMMMMMMMMMMMMMMMMNKkdoooloolloox0WMMMMMMMMMMMMMMMMMMMXkl;'.. ..':oxKWMMMMMMMMMMMMMMMMMMMMMM\n" 26 | "MMMMMMMMMMMMMMMMMMMMWKd::lc;'...'..,:c;lKMMMMMMMMMMMMMMMMXd,. 'lc;cOWMMMMMMMMMMMMMMMMMMMM\n" 27 | "MMMMMMMMMMMMMMMMMMMNd;:kXk, .co;:0NXXK00O000KKKXk;;:. .kWKl,oNMMMMMMMMMMMMMMMMMMM\n" 28 | "MMMMMMMMMMMMMMMMMMXl,xNMNc ,:.'clloooooooooll,.:c. .xMMNd'oNMMMMMMMMMMMMMMMMMM\n" 29 | "MMMMMMMMMMMMMMMMMWd'xWMMWk' .:oOXNWMMMMMMMMMWNXOdl;' .oXMMMNo'xWMMMMMMMMMMMMMMMMM\n" 30 | "MMMMMMMMMMMMMMMMMXc'dkxxddc. .. 'oOXWMMMMMMMMMMMMMMMMMMMMW0,;xxoc;'..;x0NMMMK;cNMMMMMMMMMMMMMMMMM\n" 31 | "MMMMMMMMMMMMMN0xlc;:looddxxo,.'o0d'dWMMMMMMMMMMMMMMMMMMMMMMMMO,oWMMMWN0:.':cld0k,lNMMMMMMMMMMMMMMMMM\n" 32 | "MMMMMMMMMWXkl:cld0NWMMMMNOl::xXMMO,dWMMMMMMMMMMMMMMMMMMMMMMMM0;oWMMMMMMK:,x0kl:'.lXWMMMMMMMMMMMMMMMM\n" 33 | "MMMMMMMW0l:cd0NMMMMMWXkl::o0NMMMM0,oWMMMMMMMMMMMMMMMMMMMMMMMMK;cNMMMMMMMKc,xNMNOoc:cdOXWMMMMMMMMMMMM\n" 34 | "MMMMMW0l;l0WMMMMMWKxl:cd0NMMMMMMM0,lWMMMMMMMMMMMMMMMMMMMMMMMMNl,OMMMMMMMMNo,lKMMMWKkocccxXMMMMMMMMMM\n" 35 | "MMMWKo;c0WMMMWKkoc:lxKWMMMMMMMMMM0,lWMMMMMMMMMMMMMMMMMMMMMMMMMK;;0MMMMMMMMWO:;xNMMMMMWXx:;dXMMMMMMMM\n" 36 | "MMKo;cOWMMMXxc:cdONMMMMMMMMMMMMMM0,lWMMMMMMMMMMMMMMMMMMMMMMMMMWO,cXMMMMMMMMMXd;:OWMMMMMMNk:;kNMMMMMM\n" 37 | "MK:;kWMMMXd;:xXWMMMMMMMMMMMMMMMMM0,lWMMMMMMMMMMMMMMMMMMMMMMMMMMWd'xWMMMMMMMMMWKl,oXMMMMMMMXo,lKWMMMM\n" 38 | "Nl,OMMMW0:;xNMMMMMMMMMMMMMMMMMMMMO,oWMMMMMMMMMMMMMMMMMMMMMMMMMMMX:;KMMMMMMMMMMMWk,cKMMMMMMMW0:;xNMMM\n" 39 | "O,oWMMWk,:0WMMMMMMMMMMMMMMMMMMMMWd,kMMMMMMMMMMMMMMMMMMMMMMMMMMMMMk,oWMMMMMMMMMMMWO,cXMMMMMMMMXo,lXMM\n" 40 | "o,OMMWx,lXMMMMMMMMMMMMMMMMMMMMMM0;cXMMMMMMMMMMMMMMMMMMMMMMMMMMMMMNc;0MMMMMMMMMMMMWx,oNMMMMMMMWNx,lNM\n" 41 | ";:XMMO,cNMMMMMMMMMMMMMMMMMMMMMMNl,OMM┌┐┌─┐MMMMMMMMM┌┐M┌───┐┌───┐MMk,dWMMMMMMMMMMMMNl,OMMMMMMNddXo,OM\n" 42 | ",oWMNl,0MMMMMMMMMMMMMMMMMMMMMMMk,oWMM│││┌┘MMMMMMMM┌┘└┐│┌─┐││┌─┐│MMX::XMMMMMMMMMMMMMO,oWXKNMMK;cNk,dW\n" 43 | ",oXXK::XMMMMMMMMMMMMMMMMMMMMMMX:;KMMM│└┘┘M┌─┐M┌┐┌┐└┐┌┘││M│││└──┐MMWo,OMMMMMMMMMMMMMK;,o;lXW0:,OMO,oW\n" 44 | ";cx::,:XMMMMMMMMMMMMMMMMMMMMMMk,dWMMM│┌┐│M│┌┐┐││││M││ ││M││└──┐│MMMO,oWMMMMMMMMMMMMX;.,dXWO,:0WMX:;K\n" 45 | "::0x' .dKNMMMMMMMMMMMMMMMMMMMNc,0MMMM│││└┐│││││└┘│M│└┐│└─┘││└─┘│MMMX::XMMMMMMMMMMMNo,oXMMK;;KWNNXx'o\n" 46 | "l,do,,clcclkNMMMMMMMMMMMMMMMM0,lNMMMM└┘└─┘└┘└┘└──┘M└─┘└───┘└───┘MMMWd,kMMMMMMMMMMNo'oXWNx,.:lcloll,;\n" 47 | "d'lxOXMMW0o::dXMMMMMMMMMMMMMMx,xMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMK;:XMMMMMMNklc;,cllc'';,.,oONO;:\n" 48 | "0;cXMMMMMMMXx:;xNMMMMMMMMMMMWo,OMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWd,kMMMMMXc,oKNNNNXXXXNN0xd0No,x\n" 49 | "Wx'oNMMMMMMMMNd,c0WMMMMMMMMMNc;KMMMMMMMW0ONMMMMMMMMMMMMWK0NMMMMMMMMMMk,dWMMMXc,kWMMMMMMMMMMMMMMNd,lN\n" 50 | "MNd'lXMMMMMMMMW0c,dXMMMMMMMMO,lWMMMMMMMNc;KMMMMMMMMMMMMNl;KMMMMMMMMMMx,xMMMNl,kWMMMMMMMMMMMMMNk:;dNM\n" 51 | "MMWk,:KMMMMMMMMMNk:;xXMMMMMWd,kMMMMMMMMNl:KMMMMMMMMMMMMWd'xWMMMMMMMMK::KMW0c,xWMMMMMMMMMMMMXd::dKWMM\n" 52 | "MMMW0;;0MMMMMMMMMMNx:;oKWMMWo;0MMMMMMMMWK0WMMMMMMMMMMMMMXxOWMMMMMMMMd,xXkc;l0WMMMMMMMMMMMWk;;kNMMMMM\n" 53 | "MMMMMK:;OWMMMMMMMMMMNOl;cdO0c;KMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWNO;.;::dKWMMMMMMMMMMMMNo'lXMMMMMMM\n" 54 | "MMMMMMKc,xNMMMMMMMMMMMWXkolc''lddxO0KXXNNWWMMMMMMMMMMMMWWNNX0kdoll:. .ckNMMMMMMMMMMMMMW0c,dNMMMMMMMM\n" 55 | "MMMMMMMXd,c0WMMMMMMMMMMMMMWNKkd:..clc,..',;:ccccccc:::;;,'...,oxkd;,oKWMMMMMMMMMMMMMMNd,c0WMMMMMMMMM\n" 56 | "MMMMMMMMW0c,oXMMMMMMMMMMMMMMMMMNd;:dko. .cKWKl,l0WMMMMMMMMMMMMMMWO:;xNMMMMMMMMMMM\n" 57 | "MMMMMMMMMMWk:;xXMMMMMMMMMMMMMMMMMXkl;:;'..''............';lxOxl;cOWMMMMMMMMMMMMMMMXl,lKMMMMMMMMMMMMM\n" 58 | "MMMMMMMMMMMMNx:;dXWMMMMMMMMMMMMMMMMWXkollllcccccccc;.,cclllllld0WMMMMMMMMMMMMMMMNx;:OWMMMMMMMMMMMMMM\n" 59 | "MMMMMMMMMMMMMMNkc;oKWMMMMMMMMMMMMMMMMMMMWWNNNNNNNNNd'dNWWWWWMMMMMMMMMMMMMMMMMMXx:;xXMMMMMMMMMMMMMMMM\n" 60 | "MMMMMMMMMMMMMMMMWOc;l0WMMMMMMMMMMMMMMMMMMMMMMMMMMWNl,OMMMMMMMMMMMMMMMMMMMMMWKo;:xXMMMMMMMMMMMMMMMMMM\n" 61 | "MMMMMMMMMMMMMMMMMMW0l;lONMMMMMMMMMMMMMMMMMMMMMMMMKx;cXMMMMMMMMMMMMMMMMMMMNkc;ckNMMMMMMMMMMMMMMMMMMMM\n" 62 | "MMMMMMMMMMMMMMMMMMMMW0o::dKWMMMMMMMMMMMMMMMMMMMMMx',xMMMMMMMMMMMMMMMMMWKd::dKWMMMMMMMMMMMMMMMMMMMMMM\n" 63 | "MMMMMMMMMMMMMMMMMMMMMMMXkc:coxKNMMMMMMMMMMMMMMMMNc ;KMMMMMMMMMMMMMMMNkc;ckNMMMMMMMMMMMMMMMMMMMMMMMMM\n" 64 | "MMMMMMMMMMMMMMMMMMMMMMMMMWXOdl:clxKNMMMMMMMMMMMMX: cNMMMMMMMMMMMWNOo::dKWMMMMMMMMMMMMMMMMMMMMMMMMMMM\n" 65 | "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMWN0xlcclox0XWMMMMMMK;.lNMMMMMMMMN0dlcclONMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\n" 66 | "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWNKOdocccldOKNWX: :XMWWNXOdlc:lxKWMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\n" 67 | "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWX0xolllll,.'loollllox0NMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\n" 68 | "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWX0OkkkkOO0KNWMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\n"; 69 | -------------------------------------------------------------------------------- /src/kernel/logo.h: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of an x86_64 hobbyist operating system called KnutOS 3 | Everything is openly developed on GitHub: https://github.com/Tix3Dev/KnutOS/ 4 | 5 | Copyright (C) 2021-2022 Yves Vollmeier 6 | This program is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see . 16 | */ 17 | 18 | #ifndef LOGO_H 19 | #define LOGO_H 20 | 21 | extern const char *small_logo_text; 22 | extern const char *big_logo; 23 | 24 | #endif 25 | -------------------------------------------------------------------------------- /src/kernel/memory/mem.h: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of an x86_64 hobbyist operating system called KnutOS 3 | Everything is openly developed on GitHub: https://github.com/Tix3Dev/KnutOS/ 4 | 5 | Copyright (C) 2021-2022 Yves Vollmeier 6 | This program is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see . 16 | */ 17 | 18 | #include 19 | 20 | #ifndef MEM_H 21 | #define MEM_H 22 | 23 | #define HIGHER_HALF_DATA_LV5 0xFF00000000000000UL 24 | #define HIGHER_HALF_DATA_LV4 0xFFFF800000000000UL 25 | #define HIGHER_HALF_CODE 0xFFFFFFFF80000000UL 26 | 27 | #define PAGE_SIZE 4096 28 | #define TABLES_PER_DIRECTORY 512 29 | #define PAGES_PER_TABLE 512 // TODO: do I need this??? 30 | 31 | #define KB_TO_PAGES(kb) (((kb) * 1024) / PAGE_SIZE) 32 | #define ALIGN_DOWN(addr, align) ((addr) & ~((align)-1)) 33 | #define ALIGN_UP(addr, align) (((addr) + (align)-1) & ~((align)-1)) 34 | 35 | #define IS_PAGE_ALIGNED(num) ((num % PAGE_SIZE) == 0) 36 | 37 | // get cr4 and return la57 = bit 12 38 | static inline bool is_la57_enabled(void) 39 | { 40 | uint64_t cr4; 41 | 42 | asm volatile("mov %%cr4, %0" : "=rax"(cr4)); 43 | 44 | return (cr4 >> 12) & 1; 45 | } 46 | 47 | /* those functions are important, as KnutOS is a higher half kernel */ 48 | 49 | static inline uintptr_t phys_to_higher_half_data(uintptr_t address) 50 | { 51 | if (is_la57_enabled()) 52 | return HIGHER_HALF_DATA_LV5 + address; 53 | 54 | return HIGHER_HALF_DATA_LV4 + address; 55 | } 56 | 57 | static inline uintptr_t phys_to_higher_half_code(uintptr_t address) 58 | { 59 | return HIGHER_HALF_CODE + address; 60 | } 61 | 62 | static inline uintptr_t higher_half_data_to_phys(uintptr_t address) 63 | { 64 | if (is_la57_enabled()) 65 | return address - HIGHER_HALF_DATA_LV5; 66 | 67 | return address - HIGHER_HALF_DATA_LV4; 68 | } 69 | 70 | static inline uintptr_t higher_half_code_to_phys(uintptr_t address) 71 | { 72 | return address - HIGHER_HALF_CODE; 73 | } 74 | 75 | #endif 76 | -------------------------------------------------------------------------------- /src/kernel/memory/pmm.c: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of an x86_64 hobbyist operating system called KnutOS 3 | Everything is openly developed on GitHub: https://github.com/Tix3Dev/KnutOS/ 4 | 5 | Copyright (C) 2021-2022 Yves Vollmeier 6 | This program is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see . 16 | */ 17 | 18 | #include 19 | #include 20 | 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | 30 | struct PMM_Info_Struct pmm_info; 31 | BITMAP_t bitmap; 32 | 33 | size_t highest_page; 34 | 35 | // setup the bitmap 36 | void pmm_init(struct stivale2_struct *stivale2_struct) 37 | { 38 | // --- step 1 --- 39 | 40 | // set basic values 41 | struct stivale2_struct_tag_memmap *memory_map = stivale2_get_tag(stivale2_struct, 42 | STIVALE2_STRUCT_TAG_MEMMAP_ID); 43 | 44 | pmm_info.memory_map = memory_map; 45 | 46 | struct stivale2_mmap_entry *current_entry; 47 | 48 | 49 | // --- step 2 --- 50 | 51 | serial_log(INFO, "Memory map layout:\n"); 52 | kernel_log(INFO, "Memory map layout:\n"); 53 | 54 | size_t top = 0; 55 | 56 | // iterate through memory map entries and print info about them 57 | // & find highest page 58 | for (uint64_t i = 0; i < pmm_info.memory_map->entries; i++) 59 | { 60 | current_entry = &pmm_info.memory_map->memmap[i]; 61 | 62 | 63 | serial_set_color(TERM_PURPLE); 64 | 65 | debug("Memory map entry No. %.16d: Base: 0x%.16llx | Length: 0x%.16llx | Type: %s\n", 66 | i, current_entry->base, current_entry->length, get_memory_map_entry_type(current_entry->type)); 67 | printk(GFX_PURPLE, "Memory map entry No. %.16d: Base: 0x%.16llx | Length: 0x%.16llx | Type: %s\n", 68 | i, current_entry->base, current_entry->length, get_memory_map_entry_type(current_entry->type)); 69 | 70 | serial_set_color(TERM_COLOR_RESET); 71 | 72 | 73 | // TODO: potential hazard/bug 74 | if (current_entry->type != STIVALE2_MMAP_USABLE && 75 | current_entry->type != STIVALE2_MMAP_BOOTLOADER_RECLAIMABLE && 76 | current_entry->type != STIVALE2_MMAP_KERNEL_AND_MODULES) 77 | continue; 78 | 79 | top = current_entry->base + current_entry->length; 80 | 81 | if (top > highest_page) 82 | highest_page = top; 83 | } 84 | 85 | pmm_info.memory_size = highest_page; 86 | pmm_info.max_pages = KB_TO_PAGES(pmm_info.memory_size); 87 | pmm_info.used_pages = pmm_info.max_pages; 88 | 89 | 90 | // --- step 3 --- 91 | 92 | // calculate bitmap size 93 | size_t bitmap_byte_size = ALIGN_UP(ALIGN_DOWN(highest_page, PAGE_SIZE) / PAGE_SIZE / 8, PAGE_SIZE); 94 | 95 | bitmap.size = bitmap_byte_size; 96 | 97 | serial_log(INFO, "Memory specifications:\n"); 98 | kernel_log(INFO, "Memory specifications:\n"); 99 | 100 | serial_set_color(TERM_PURPLE); 101 | 102 | current_entry = &pmm_info.memory_map->memmap[0]; 103 | 104 | debug("Total amount of memory: %d kB\n", current_entry->base + current_entry->length - 1); 105 | printk(GFX_PURPLE, "Total amount of memory: %d kB\n", current_entry->base + current_entry->length - 1); 106 | 107 | debug("Size of bitmap: %d kB\n", bitmap.size / 1024); 108 | printk(GFX_PURPLE, "Size of bitmap: %d kB\n", bitmap.size / 1024); 109 | 110 | serial_set_color(TERM_COLOR_RESET); 111 | 112 | 113 | // --- step 4 --- 114 | 115 | // search for first large enough page of memory to host the bitmap 116 | for (uint64_t i = 0; i < pmm_info.memory_map->entries; i++) 117 | { 118 | current_entry = &pmm_info.memory_map->memmap[i]; 119 | 120 | if (current_entry->type != STIVALE2_MMAP_USABLE) 121 | continue; 122 | 123 | if (current_entry->length >= bitmap.size) 124 | { 125 | serial_set_color(TERM_PURPLE); 126 | debug("Found big enough block of memory to host the bitmap!\n"); 127 | debug("Bitmap stored between 0x%.8lx and 0x%.8lx\n", current_entry->base, current_entry->base + current_entry->length - 1); 128 | serial_set_color(TERM_COLOR_RESET); 129 | 130 | bitmap.map = (uint8_t *)(phys_to_higher_half_data(current_entry->base)); 131 | 132 | current_entry->base += bitmap.size; 133 | current_entry->length -= bitmap.size; 134 | 135 | break; 136 | } 137 | } 138 | 139 | 140 | // --- step 5 --- 141 | 142 | // set bitmap to default - all bits used 143 | memset((void *)bitmap.map, 0xFF, bitmap.size); 144 | 145 | 146 | // --- step 6 --- 147 | 148 | // set all usable entries in the bitmap to free 149 | for (uint64_t i = 0; i < pmm_info.memory_map->entries; i++) 150 | { 151 | current_entry = &pmm_info.memory_map->memmap[i]; 152 | 153 | if (current_entry->type == STIVALE2_MMAP_USABLE) 154 | pmm_free((void *)current_entry->base, current_entry->length / PAGE_SIZE); 155 | } 156 | 157 | 158 | // --- step 7 --- 159 | 160 | // reserve the null pointer 161 | bitmap_set_bit(&bitmap, 0); 162 | 163 | 164 | // --- done --- 165 | 166 | serial_log(INFO, "PMM initialized\n"); 167 | kernel_log(INFO, "PMM initialized\n"); 168 | } 169 | 170 | // return matching string for memory map entry type passed 171 | const char *get_memory_map_entry_type(uint32_t type) 172 | { 173 | switch (type) 174 | { 175 | case STIVALE2_MMAP_USABLE: 176 | return "Usable"; 177 | 178 | case STIVALE2_MMAP_RESERVED: 179 | return "Reserved"; 180 | 181 | case STIVALE2_MMAP_ACPI_RECLAIMABLE: 182 | return "ACPI Reclaimable"; 183 | 184 | case STIVALE2_MMAP_ACPI_NVS: 185 | return "ACPI Non Volatile Storage"; 186 | 187 | case STIVALE2_MMAP_BAD_MEMORY: 188 | return "Bad Memory"; 189 | 190 | case STIVALE2_MMAP_BOOTLOADER_RECLAIMABLE: 191 | return "Bootloader Reclaimable"; 192 | 193 | case STIVALE2_MMAP_KERNEL_AND_MODULES: 194 | return "Kernel And Modules"; 195 | 196 | case STIVALE2_MMAP_FRAMEBUFFER: 197 | return "Framebuffer"; 198 | 199 | default: 200 | return "Unknown"; 201 | } 202 | } 203 | 204 | // traverse the bitmap -> for each bit and check if bit is free or used 205 | // return index 206 | void *pmm_find_first_free_page(size_t page_count) 207 | { 208 | // can't find in no memory 209 | if (page_count == 0) 210 | return NULL; 211 | 212 | for (size_t counter = 0; counter < page_count; counter++) 213 | { 214 | for (size_t i = 0; i < PAGE_TO_BIT(highest_page); i++) 215 | { 216 | if (!bitmap_check_bit(&bitmap, i)) 217 | return (void *)BIT_TO_PAGE(i); 218 | } 219 | } 220 | 221 | // nothing big enough 222 | return NULL; 223 | } 224 | 225 | // check if there is still memory left 226 | // find first free page 227 | // mark it as used 228 | // return address 229 | // -> physical memory allocation for n pages 230 | void *pmm_alloc(size_t page_count) 231 | { 232 | if (pmm_info.used_pages <= 0) 233 | return NULL; 234 | 235 | void *pointer = pmm_find_first_free_page(page_count); 236 | 237 | if (pointer == NULL) 238 | return NULL; 239 | 240 | 241 | uint64_t index = (uint64_t)pointer / PAGE_SIZE; 242 | 243 | for (size_t i = 0; i < page_count; i++) 244 | bitmap_set_bit(&bitmap, index + i); 245 | 246 | pmm_info.used_pages += page_count; 247 | 248 | return (void *)(uint64_t)(phys_to_higher_half_data(index * PAGE_SIZE)); 249 | } 250 | 251 | // convert pointer to index 252 | // unset the matching bit 253 | // -> physical memory freeing for n pages 254 | void pmm_free(void *pointer, size_t page_count) 255 | { 256 | uint64_t index = higher_half_data_to_phys((uint64_t)pointer) / PAGE_SIZE; 257 | 258 | for (size_t i = 0; i < page_count; i++) 259 | bitmap_unset_bit(&bitmap, index + i); 260 | 261 | pmm_info.used_pages -= page_count; 262 | } 263 | -------------------------------------------------------------------------------- /src/kernel/memory/pmm.h: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of an x86_64 hobbyist operating system called KnutOS 3 | Everything is openly developed on GitHub: https://github.com/Tix3Dev/KnutOS/ 4 | 5 | Copyright (C) 2021-2022 Yves Vollmeier 6 | This program is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see . 16 | */ 17 | 18 | #include 19 | 20 | #ifndef PMM_H 21 | #define PMM_H 22 | 23 | struct PMM_Info_Struct 24 | { 25 | size_t memory_size; 26 | uint32_t max_pages; 27 | uint32_t used_pages; 28 | struct stivale2_struct_tag_memmap *memory_map; 29 | }; 30 | 31 | void pmm_init(struct stivale2_struct *stivale2_struct); 32 | const char *get_memory_map_entry_type(uint32_t type); 33 | void *pmm_find_first_free_page(size_t page_count); 34 | void *pmm_alloc(size_t page_count); 35 | void pmm_free(void *pointer, size_t page_count); 36 | 37 | #endif 38 | -------------------------------------------------------------------------------- /src/kernel/memory/slab.c: -------------------------------------------------------------------------------- 1 | /* 2 | BSD 3-Clause License 3 | 4 | Copyright (c) 2022, V01D 5 | All rights reserved. 6 | 7 | https://github.com/V01D-NULL/MoonOS/blob/c82b2a4d179077dfc0f7210902abd879f80377df/kernel/mm/slab.c 8 | */ 9 | 10 | /* 11 | The first version was developed by Yves Vollmeier and Tim Thompson (in collaboration) 12 | and the code can be seen here: 13 | https://github.com/V01D-NULL/slab_allocator 14 | This version was first developed by Tim Thompson and modified by 15 | Yves Vollmeier. Copyright header at the top is just for sanity. 16 | */ 17 | 18 | #include 19 | #include 20 | #include 21 | 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | 32 | /* Explanation of the method used here for slab allocations: 33 | Instead of a linked list which would normally be used, this allocator 34 | is based on an array. It holds 11 slabs. The smallest size is 2^1 35 | and the biggest is 2^11. 36 | Each slab contains an array of objects. 37 | Each object is either 38 | free - holding an address of free memory 39 | or 40 | used - holding NULL. 41 | 42 | Now, when allocating memory, we search for a free object in the slab 43 | of the machting size (parameter). If we find one, we set it to used 44 | and return it's pointer. So, that it's memory can't be used anymore. 45 | 46 | UNTIL we free the memory (by passing it's pointer) in slab_free. 47 | For that we just search for a used object and then set it to the 48 | passed pointer. The memory which the pointer points to, can now be 49 | overwritten i.e. used again once somebody allocates memory again. 50 | */ 51 | 52 | static slab_t slabs[SLAB_COUNT]; 53 | 54 | /* utility functions */ 55 | 56 | static int32_t find_free_object(int32_t slab_index); 57 | static int32_t find_allocated_object(int32_t slab_index); 58 | 59 | /* core functions */ 60 | 61 | // create array of slabs, which all are of different sizes 62 | // ranging from 2 to 2048 but only power of 2 63 | 64 | void *internal_mem_ptr = NULL; 65 | size_t internal_mem_len = 0; 66 | uint32_t page_alloc_count = 0; 67 | 68 | void slab_init(void) 69 | { 70 | for (int32_t i = 0; i < SLAB_COUNT; i++) 71 | { 72 | slabs[i].size = pow(2, i + 1); 73 | slabs[i].is_full = false; 74 | 75 | int32_t objects_per_slab = MAX_SLAB_SIZE / pow(2, i + 1); 76 | 77 | for (int j = 0; j < objects_per_slab; j++) 78 | { 79 | if (!internal_mem_ptr || internal_mem_ptr == (void *)internal_mem_len) 80 | { 81 | internal_mem_ptr = pmm_alloc(1); 82 | internal_mem_len = (size_t)internal_mem_ptr + PAGE_SIZE; 83 | 84 | page_alloc_count++; 85 | } 86 | 87 | slabs[i].objects[j] = internal_mem_ptr; 88 | internal_mem_ptr += slabs[i].size; 89 | } 90 | 91 | slabs[i].address_range.start = slabs[i].objects[0]; 92 | slabs[i].address_range.end = slabs[i].objects[0] + 1024 - slabs[i].size; 93 | } 94 | 95 | serial_log(INFO, "Slab allocator statistics:\n"); 96 | kernel_log(INFO, "Slab allocator statistics:\n"); 97 | 98 | serial_set_color(TERM_PURPLE); 99 | 100 | debug("Slabs created: %d\n", SLAB_COUNT); 101 | printk(GFX_PURPLE, "Slabs created: %d\n", SLAB_COUNT); 102 | 103 | debug("Smallest slab: 2 bytes | Biggest slab: %d bytes\n", MAX_SLAB_SIZE); 104 | printk(GFX_PURPLE, "Smallest slab: 2 bytes | Biggest slab: %d bytes\n", MAX_SLAB_SIZE); 105 | 106 | debug("Memory used to create slabs: %d bytes = %d pages\n", page_alloc_count * PAGE_SIZE, page_alloc_count); 107 | printk(GFX_PURPLE, "Memory used to create slabs: %d bytes = %d pages\n", page_alloc_count * PAGE_SIZE, page_alloc_count); 108 | 109 | serial_set_color(TERM_COLOR_RESET); 110 | 111 | serial_log(INFO, "Slab allocator initialized\n"); 112 | kernel_log(INFO, "Slab allocator initialized\n"); 113 | } 114 | 115 | // search for a free object in the matching slab according to the 116 | // size parameter and allocate it by setting it's value to NULL 117 | void *slab_alloc(size_t size) 118 | { 119 | void *return_value = NULL; 120 | 121 | for (int32_t i = 0; i < SLAB_COUNT; i++) 122 | { 123 | if (slabs[i].size != size) 124 | continue; 125 | 126 | if (slabs[i].is_full) 127 | return return_value; 128 | 129 | int32_t free_object_index = find_free_object(i); 130 | 131 | if (free_object_index == -1) 132 | slabs[i].is_full = true; 133 | else 134 | { 135 | return_value = slabs[i].objects[free_object_index]; 136 | slabs[i].objects[free_object_index] = NULL; 137 | } 138 | 139 | return return_value; 140 | } 141 | 142 | return return_value; 143 | } 144 | 145 | // search for a slab of matching size according to the ptr paramater 146 | // free it by setting it's value to the ptr which was previously checked 147 | void slab_free(void *ptr) 148 | { 149 | if (!ptr) 150 | return; 151 | 152 | void *ptr_without_base; 153 | 154 | for (int32_t i = 0; i < SLAB_COUNT; i++) 155 | { 156 | ptr_without_base = ptr - slabs[i].address_range.start + (void *)slabs[i].size; 157 | 158 | if (ptr >= slabs[i].address_range.start && ptr <= slabs[i].address_range.end) 159 | { 160 | // yes, ptr is in the range of a slab 161 | 162 | if ((size_t)ptr_without_base % slabs[i].size == 0) 163 | { 164 | // yes, ptr is an object of the slab 165 | 166 | int32_t allocated_object_index = find_allocated_object(i); 167 | 168 | if (allocated_object_index == -1) 169 | return; 170 | 171 | slabs[i].objects[allocated_object_index] = ptr; 172 | } 173 | } 174 | } 175 | } 176 | 177 | /* utility functions */ 178 | 179 | // find an object in the matching slab, i.e. by searching for 180 | // non-NULL values 181 | static int32_t find_free_object(int32_t slab_index) 182 | { 183 | int32_t objects_per_slab = MAX_SLAB_SIZE / pow(2, slab_index + 1); 184 | 185 | for (int32_t i = 0; i < objects_per_slab; i++) 186 | if (slabs[slab_index].objects[i] != NULL) 187 | return i; 188 | 189 | return -1; 190 | } 191 | 192 | // find an object in the matching slab, i.e. by searching for 193 | // NULL values 194 | static int32_t find_allocated_object(int32_t slab_index) 195 | { 196 | int32_t objects_per_slab = MAX_SLAB_SIZE / pow(2, slab_index + 1); 197 | 198 | for (int32_t i = 0; i < objects_per_slab; i++) 199 | if (slabs[slab_index].objects[i] == NULL) 200 | return i; 201 | 202 | return -1; 203 | } 204 | -------------------------------------------------------------------------------- /src/kernel/memory/slab.h: -------------------------------------------------------------------------------- 1 | /* 2 | BSD 3-Clause License 3 | 4 | Copyright (c) 2022, V01D 5 | All rights reserved. 6 | 7 | https://github.com/V01D-NULL/3ds-firmware/blob/main/src/arm11/core/mm/slab.c 8 | */ 9 | 10 | /* 11 | The first version was developed by Yves Vollmeier and Tim Thompson (in collaboration) 12 | and the code can be seen here: 13 | https://github.com/V01D-NULL/slab_allocator 14 | This version was first developed by Tim Thompson and modified by 15 | Yves Vollmeier. Copyright header at the top is just for sanity. 16 | */ 17 | 18 | #include 19 | 20 | #include 21 | 22 | #ifndef SLAB_H 23 | #define SLAB_H 24 | 25 | #define SLAB_COUNT 11 // how many slab_t's there will be 26 | #define MAX_SLAB_SIZE 2048 // until pow(2, SLAB_COUNT) 27 | #define MAX_OBJECTS_PER_SLAB 1024 // smallest slab possible is 2 -> MAX_SLAB_SIZE / 2 28 | 29 | // an object in the objects array either is a pointer to 30 | // free memory, or NULL which means it's allocated 31 | typedef struct 32 | { 33 | addr_range_t address_range; 34 | 35 | size_t size; 36 | bool is_full; 37 | void *objects[MAX_OBJECTS_PER_SLAB]; 38 | } slab_t; 39 | 40 | void slab_init(void); 41 | void *slab_alloc(size_t size); 42 | void slab_free(void *ptr); 43 | 44 | #endif 45 | -------------------------------------------------------------------------------- /src/kernel/memory/vmm.c: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of an x86_64 hobbyist operating system called KnutOS 3 | Everything is openly developed on GitHub: https://github.com/Tix3Dev/KnutOS/ 4 | 5 | Copyright (C) 2021-2022 Yves Vollmeier 6 | This program is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see . 16 | */ 17 | 18 | #include 19 | #include 20 | 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | 30 | static PAGE_DIR root_page_directory; 31 | 32 | // create and activate page directory + map important memory areas 33 | void vmm_init(void) 34 | { 35 | root_page_directory = vmm_create_page_directory(); 36 | 37 | 38 | serial_log(INFO, "Paging - Multilevel support:\n"); 39 | kernel_log(INFO, "Paging - Multilevel support:\n"); 40 | 41 | 42 | serial_set_color(TERM_PURPLE); 43 | 44 | // check if la57 bit is enabled for 5-level paging 45 | if (is_la57_enabled()) 46 | { 47 | debug("5-level paging supported!\n"); 48 | printk(GFX_PURPLE, "5-level paging supported!\n"); 49 | } 50 | else 51 | { 52 | debug("5-level paging not supported! Continuing with 4-level paging.\n"); 53 | printk(GFX_PURPLE, "5-level paging not supported! Continuing with 4-level paging.\n"); 54 | } 55 | 56 | serial_set_color(TERM_COLOR_RESET); 57 | 58 | 59 | serial_log(INFO, "Paging - Mapped areas:\n"); 60 | kernel_log(INFO, "Paging - Mapped areas:\n"); 61 | 62 | serial_set_color(TERM_PURPLE); 63 | 64 | // map first 4 GiB 65 | for (uint64_t i = 0; i < 4 * GB; i += PAGE_SIZE) 66 | vmm_map_page(root_page_directory, i, i, PTE_PRESENT | PTE_READ_WRITE); 67 | 68 | debug("1/3: Mapped first 4 GiB of memory\n"); 69 | printk(GFX_PURPLE, "1/3: Mapped first 4 GiB of memory\n"); 70 | 71 | // map higher half kernel address space 72 | for (uint64_t i = 0; i < 4 * GB; i += PAGE_SIZE) 73 | vmm_map_page(root_page_directory, i, phys_to_higher_half_data(i), PTE_PRESENT | PTE_READ_WRITE); 74 | 75 | debug("2/3: Mapped higher half kernel address space\n"); 76 | printk(GFX_PURPLE, "2/3: Mapped higher half kernel address space\n"); 77 | 78 | // map protected memory ranges (PMR's) - keep them read only for safety 79 | for (uint64_t i = 0; i < 0x80000000; i += PAGE_SIZE) 80 | vmm_map_page(root_page_directory, i, phys_to_higher_half_code(i), PTE_PRESENT); 81 | 82 | debug("3/3: Mapped protected memory ranges\n"); 83 | printk(GFX_PURPLE, "3/3: Mapped protected memory ranges\n"); 84 | 85 | serial_set_color(TERM_COLOR_RESET); 86 | 87 | 88 | vmm_activate_page_directory(root_page_directory); 89 | 90 | // no need to enable paging 91 | // (= set bit 31 in cr0) 92 | // as limine already handled that 93 | 94 | serial_log(INFO, "VMM initialized\n"); 95 | kernel_log(INFO, "VMM initialized\n"); 96 | } 97 | 98 | // set each table in the page directory to not used 99 | PAGE_DIR vmm_create_page_directory(void) 100 | { 101 | PAGE_DIR new_page_directory = pmm_alloc(1); 102 | 103 | // "clean" the page directory by setting everything to zero 104 | memset((void *)higher_half_data_to_phys((uint64_t)new_page_directory), 0, PAGE_SIZE); 105 | 106 | return new_page_directory; 107 | } 108 | 109 | // return a new page directory made with higher (X) page directory 110 | static PAGE_DIR vmm_get_page_map_level(PAGE_DIR page_map_level_X, uintptr_t index_X, int flags) 111 | { 112 | // NOTE: if you are unfamiliar with this syntax 113 | // *x = NULL; 114 | // x[i] = y 115 | // just means 116 | // *(x + i) = y 117 | 118 | if (page_map_level_X[index_X] & 1) 119 | return (PAGE_DIR)(page_map_level_X[index_X] & ~(511)); 120 | else 121 | { 122 | page_map_level_X[index_X] = higher_half_data_to_phys((uint64_t)pmm_alloc(1)) | flags; 123 | 124 | return (PAGE_DIR)(page_map_level_X[index_X] & ~(511)); 125 | } 126 | } 127 | 128 | // TODO: do more testing especially for 5-level paging 129 | 130 | // map physical memory to virtual memory by using 4-level paging 131 | void vmm_map_page(PAGE_DIR current_page_directory, uintptr_t physical_address, uintptr_t virtual_address, int flags) 132 | { 133 | if (is_la57_enabled()) // 5-level paging is enabled 134 | { 135 | uintptr_t index5 = (virtual_address & ((uintptr_t)0x1ff << 48)) >> 48; 136 | uintptr_t index4 = (virtual_address & ((uintptr_t)0x1ff << 39)) >> 39; 137 | uintptr_t index3 = (virtual_address & ((uintptr_t)0x1ff << 30)) >> 30; 138 | uintptr_t index2 = (virtual_address & ((uintptr_t)0x1ff << 21)) >> 21; 139 | uintptr_t index1 = (virtual_address & ((uintptr_t)0x1ff << 12)) >> 12; 140 | 141 | PAGE_DIR page_map_level5 = current_page_directory; 142 | PAGE_DIR page_map_level4 = NULL; 143 | PAGE_DIR page_map_level3 = NULL; 144 | PAGE_DIR page_map_level2 = NULL; 145 | PAGE_DIR page_map_level1 = NULL; 146 | 147 | page_map_level4 = vmm_get_page_map_level(page_map_level5, index5, flags); 148 | page_map_level3 = vmm_get_page_map_level(page_map_level4, index4, flags); 149 | page_map_level2 = vmm_get_page_map_level(page_map_level3, index3, flags); 150 | page_map_level1 = vmm_get_page_map_level(page_map_level2, index2, flags); 151 | 152 | // if (page_map_level1[index1] != 0) 153 | // { 154 | // serial_log(ERROR, "Virtual page 0x%lX is already mapped to physical page 0x%lX! - page_map_level1[%d]: 0x%lX\n", 155 | // virtual_address, physical_address, index1, page_map_level1 156 | // ); 157 | // serial_log(ERROR, "Kernel halted!\n"); 158 | 159 | // kernel_log(ERROR, "Virtual page 0x%lX is already mapped to physical page 0x%lX! - page_map_level1[%d]: 0x%lX\n", 160 | // virtual_address, physical_address, index1, page_map_level1 161 | // ); 162 | // kernel_log(ERROR, "Kernel halted!\n"); 163 | 164 | // asm volatile("hlt"); 165 | // } 166 | 167 | page_map_level1[index1] = physical_address | flags; // level 1 points to the mapped (physical) frame 168 | } 169 | else // otherwise use standard 4-level paging 170 | { 171 | uintptr_t index4 = (virtual_address & ((uintptr_t)0x1ff << 39)) >> 39; 172 | uintptr_t index3 = (virtual_address & ((uintptr_t)0x1ff << 30)) >> 30; 173 | uintptr_t index2 = (virtual_address & ((uintptr_t)0x1ff << 21)) >> 21; 174 | uintptr_t index1 = (virtual_address & ((uintptr_t)0x1ff << 12)) >> 12; 175 | 176 | PAGE_DIR page_map_level4 = current_page_directory; 177 | PAGE_DIR page_map_level3 = NULL; 178 | PAGE_DIR page_map_level2 = NULL; 179 | PAGE_DIR page_map_level1 = NULL; 180 | 181 | page_map_level3 = vmm_get_page_map_level(page_map_level4, index4, flags); 182 | page_map_level2 = vmm_get_page_map_level(page_map_level3, index3, flags); 183 | page_map_level1 = vmm_get_page_map_level(page_map_level2, index2, flags); 184 | 185 | // if (page_map_level1[index1] != 0) 186 | // { 187 | // serial_log(ERROR, "Virtual page 0x%lX is already mapped to physical page 0x%lX! - page_map_level1[%d]: 0x%lX\n", 188 | // virtual_address, physical_address, index1, page_map_level1 189 | // ); 190 | // serial_log(ERROR, "Kernel halted!\n"); 191 | 192 | // kernel_log(ERROR, "Virtual page 0x%lX is already mapped to physical page 0x%lX! - page_map_level1[%d]: 0x%lX\n", 193 | // virtual_address, physical_address, index1, page_map_level1 194 | // ); 195 | // kernel_log(ERROR, "Kernel halted!\n"); 196 | 197 | // asm volatile("hlt"); 198 | // } 199 | 200 | page_map_level1[index1] = physical_address | flags; // level 1 points to the mapped (physical) frame 201 | } 202 | 203 | vmm_flush_tlb((void *)virtual_address); 204 | } 205 | 206 | void vmm_unmap_page(PAGE_DIR current_page_directory, uintptr_t virtual_address) 207 | { 208 | if (is_la57_enabled()) // 5-level paging is enabled 209 | { 210 | uintptr_t index5 = (virtual_address & ((uintptr_t)0x1ff << 48)) >> 48; 211 | uintptr_t index4 = (virtual_address & ((uintptr_t)0x1ff << 39)) >> 39; 212 | uintptr_t index3 = (virtual_address & ((uintptr_t)0x1ff << 30)) >> 30; 213 | uintptr_t index2 = (virtual_address & ((uintptr_t)0x1ff << 21)) >> 21; 214 | uintptr_t index1 = (virtual_address & ((uintptr_t)0x1ff << 12)) >> 12; 215 | 216 | PAGE_DIR page_map_level5 = current_page_directory; 217 | PAGE_DIR page_map_level4 = NULL; 218 | PAGE_DIR page_map_level3 = NULL; 219 | PAGE_DIR page_map_level2 = NULL; 220 | PAGE_DIR page_map_level1 = NULL; 221 | 222 | // flag argument is set to zero because it won't be used 223 | page_map_level4 = vmm_get_page_map_level(page_map_level5, index5, 0); 224 | page_map_level3 = vmm_get_page_map_level(page_map_level4, index4, 0); 225 | page_map_level2 = vmm_get_page_map_level(page_map_level3, index3, 0); 226 | page_map_level1 = vmm_get_page_map_level(page_map_level2, index2, 0); 227 | 228 | page_map_level1[index1] = 0; 229 | } 230 | else // otherwise use standard 4-level paging 231 | { 232 | uintptr_t index4 = (virtual_address & ((uintptr_t)0x1ff << 39)) >> 39; 233 | uintptr_t index3 = (virtual_address & ((uintptr_t)0x1ff << 30)) >> 30; 234 | uintptr_t index2 = (virtual_address & ((uintptr_t)0x1ff << 21)) >> 21; 235 | uintptr_t index1 = (virtual_address & ((uintptr_t)0x1ff << 12)) >> 12; 236 | 237 | PAGE_DIR page_map_level4 = current_page_directory; 238 | PAGE_DIR page_map_level3 = NULL; 239 | PAGE_DIR page_map_level2 = NULL; 240 | PAGE_DIR page_map_level1 = NULL; 241 | 242 | // flag argument is set to zero because it won't be used 243 | page_map_level3 = vmm_get_page_map_level(page_map_level4, index4, 0); 244 | page_map_level2 = vmm_get_page_map_level(page_map_level3, index3, 0); 245 | page_map_level1 = vmm_get_page_map_level(page_map_level2, index2, 0); 246 | 247 | page_map_level1[index1] = 0; 248 | } 249 | 250 | vmm_flush_tlb((void *)virtual_address); 251 | } 252 | 253 | // invalidate a single page in the translation lookaside buffer 254 | void vmm_flush_tlb(void *address) 255 | { 256 | asm volatile("invlpg (%0)" : : "r" (address)); 257 | } 258 | 259 | // write the page directory address to cr3 260 | void vmm_activate_page_directory(PAGE_DIR current_page_directory) 261 | { 262 | asm volatile("mov %0, %%cr3" : : "r" (higher_half_data_to_phys((uint64_t)current_page_directory)) : "memory"); 263 | } 264 | -------------------------------------------------------------------------------- /src/kernel/memory/vmm.h: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of an x86_64 hobbyist operating system called KnutOS 3 | Everything is openly developed on GitHub: https://github.com/Tix3Dev/KnutOS/ 4 | 5 | Copyright (C) 2021-2022 Yves Vollmeier 6 | This program is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see . 16 | */ 17 | 18 | #include 19 | 20 | #ifndef VMM_H 21 | #define VMM_H 22 | 23 | #define GB 0x40000000UL 24 | 25 | // page table entry flags 26 | #define PTE_PRESENT 1 27 | #define PTE_READ_WRITE 2 28 | #define PTE_USER_SUPERVISOR 4 29 | #define PTE_WRITE_THROUGH 8 30 | #define PTE_CHACHE_DISABLED 16 31 | #define PTE_ACCESSED 32 32 | #define PTE_DIRTY 64 33 | #define PTE_PAT 128 34 | #define PTE_GLOBAL 256 35 | 36 | typedef uint64_t *PAGE_DIR; 37 | 38 | bool is_la57_enabled(void); 39 | void vmm_init(void); 40 | PAGE_DIR vmm_create_page_directory(void); 41 | void vmm_map_page(PAGE_DIR vmm, uintptr_t physical_address, uintptr_t virtual_address, int flags); 42 | void vmm_unmap_page(PAGE_DIR current_page_directory, uintptr_t virtual_address); 43 | void vmm_flush_tlb(void *address); 44 | void vmm_activate_page_directory(PAGE_DIR vmm); 45 | 46 | #endif 47 | -------------------------------------------------------------------------------- /src/kernel/shell/shell_screen.c: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of an x86_64 hobbyist operating system called KnutOS 3 | Everything is openly developed on GitHub: https://github.com/Tix3Dev/KnutOS/ 4 | 5 | Copyright (C) 2021-2022 Yves Vollmeier 6 | This program is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see . 16 | */ 17 | 18 | #include 19 | 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | 26 | static int shell_prompt_x_barrier; 27 | static int shell_prompt_y_barrier; 28 | 29 | // create a "new" screen and print a basic shell prompt 30 | // after that activate keyboard processing and configure it to call 31 | // shell_print_char 32 | void shell_screen_init(void) 33 | { 34 | framebuffer_reset_screen(); 35 | shell_prompt(); 36 | 37 | activate_keyboard_processing(*shell_print_char); 38 | } 39 | 40 | // print basic shell prompt 41 | void shell_prompt(void) 42 | { 43 | printk(GFX_PURPLE, "\n┌─ KnutOS\n"); 44 | printk(GFX_PURPLE, "└→ "); 45 | 46 | // set x, y barrier to last know cursor position 47 | shell_prompt_x_barrier = ssfn_dst.x; 48 | shell_prompt_y_barrier = ssfn_dst.y; 49 | } 50 | 51 | // get informations about what was being pressed 52 | // and just print if it is a valid ascii_character 53 | void shell_print_char(KEY_INFO_t key_info) 54 | { 55 | // if it's nothing to print, return 56 | if (key_info.ascii_character == '\0') 57 | return; 58 | // if return is pressed, make a newline and create a new prompt 59 | else if (key_info.ascii_character == KEY_RETURN) 60 | { 61 | // move barrier if screen scolls 62 | if (ssfn_dst.y + gfx.glyph_height == gfx.fb_height) 63 | shell_prompt_y_barrier += gfx.glyph_height; 64 | 65 | printk(GFX_BLUE, "\n"); 66 | shell_prompt(); 67 | } 68 | // if backspace is pressed check for barrier (prompt) 69 | else if (key_info.ascii_character == KEY_BACKSPACE) 70 | { 71 | if (ssfn_dst.x == shell_prompt_x_barrier && ssfn_dst.y == shell_prompt_y_barrier) 72 | return; 73 | 74 | printk(GFX_BLUE, "\b"); 75 | } 76 | else 77 | { 78 | // move barrier if screen scrolls 79 | if (ssfn_dst.y + gfx.glyph_height == gfx.fb_height && ssfn_dst.x + gfx.glyph_width == gfx.fb_width) 80 | shell_prompt_y_barrier -= gfx.glyph_height; 81 | 82 | printk(GFX_BLUE, "%c", key_info.ascii_character); 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /src/kernel/shell/shell_screen.h: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of an x86_64 hobbyist operating system called KnutOS 3 | Everything is openly developed on GitHub: https://github.com/Tix3Dev/KnutOS/ 4 | 5 | Copyright (C) 2021-2022 Yves Vollmeier 6 | This program is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see . 16 | */ 17 | 18 | #ifndef SHELL_SCREEN_H 19 | #define SHELL_SCREEN_H 20 | 21 | extern struct GFX_Struct gfx; 22 | 23 | void shell_screen_init(void); 24 | void shell_prompt(void); 25 | void shell_print_char(KEY_INFO_t key_info); 26 | 27 | #endif 28 | -------------------------------------------------------------------------------- /src/libs/libk/alloc/bitmap.c: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of an x86_64 hobbyist operating system called KnutOS 3 | Everything is openly developed on GitHub: https://github.com/Tix3Dev/KnutOS/ 4 | 5 | Copyright (C) 2021-2022 Yves Vollmeier 6 | This program is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see . 16 | */ 17 | 18 | #include 19 | #include 20 | 21 | #include 22 | #include 23 | 24 | // set exactly one bit to 1 in the bitmap 25 | void bitmap_set_bit(BITMAP_t *bitmap, int bit) 26 | { 27 | bitmap->map[bit / 8] |= (1 << (bit % 8)); 28 | } 29 | 30 | // set exactly one bit to 0 in the bitmap 31 | void bitmap_unset_bit(BITMAP_t *bitmap, int bit) 32 | { 33 | bitmap->map[bit / 8] &= ~(1 << (bit % 8)); 34 | } 35 | 36 | // check the value (either 0 or 1) for exactly one bit in the bitmap 37 | uint8_t bitmap_check_bit(BITMAP_t *bitmap, int bit) 38 | { 39 | return bitmap->map[bit / 8] & (1 << (bit % 8)); 40 | } 41 | -------------------------------------------------------------------------------- /src/libs/libk/alloc/bitmap.h: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of an x86_64 hobbyist operating system called KnutOS 3 | Everything is openly developed on GitHub: https://github.com/Tix3Dev/KnutOS/ 4 | 5 | Copyright (C) 2021-2022 Yves Vollmeier 6 | This program is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see . 16 | */ 17 | 18 | #ifndef BITMAP_H 19 | #define BITMAP_H 20 | 21 | #define BIT_TO_PAGE(bit) ((size_t)bit * 0x1000) 22 | #define PAGE_TO_BIT(page) ((size_t)page / 0x1000) 23 | 24 | typedef struct 25 | { 26 | uint8_t *map; 27 | size_t size; 28 | } BITMAP_t; 29 | 30 | void bitmap_set_bit(BITMAP_t *bitmap, int bit); 31 | void bitmap_unset_bit(BITMAP_t *bitmap, int bit); 32 | uint8_t bitmap_check_bit(BITMAP_t *bitmap, int bit); 33 | 34 | #endif 35 | -------------------------------------------------------------------------------- /src/libs/libk/alloc/kmalloc.c: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of an x86_64 hobbyist operating system called KnutOS 3 | Everything is openly developed on GitHub: https://github.com/Tix3Dev/KnutOS/ 4 | 5 | Copyright (C) 2021-2022 Yves Vollmeier 6 | This program is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see . 16 | */ 17 | 18 | #include 19 | #include 20 | #include 21 | 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | 29 | #include 30 | 31 | size_t next_pow_of_two(size_t num); 32 | 33 | // use pmm_alloc (page based) for big size parameters 34 | // use slab_alloc (byte based) for small size parameters 35 | void *kmalloc(size_t size) 36 | { 37 | void *ptr = NULL; 38 | 39 | size_t new_size = next_pow_of_two(size); 40 | 41 | if (new_size >= PAGE_SIZE) 42 | { 43 | debug("kmalloc(%d) rounded to %d (+ metadata %d) - big alloc\n", size, new_size, PAGE_SIZE); 44 | 45 | ptr = pmm_alloc((new_size / PAGE_SIZE) + 1); 46 | 47 | kmalloc_metadata_t *metadata = ptr; 48 | metadata->size = new_size; 49 | 50 | ptr += PAGE_SIZE; 51 | 52 | debug("(big alloc) alloc size: %d\n", metadata->size); 53 | } 54 | else 55 | { 56 | debug("kmalloc(%d) rounded to %d (+ metadata %d) - small alloc\n", size, new_size, sizeof(kmalloc_metadata_t)); 57 | 58 | new_size = next_pow_of_two(size + sizeof(kmalloc_metadata_t)); 59 | 60 | ptr = slab_alloc(new_size); 61 | 62 | kmalloc_metadata_t *metadata = ptr; 63 | metadata->size = new_size; 64 | 65 | ptr += sizeof(kmalloc_metadata_t); 66 | 67 | debug("(small alloc) alloc size: %d\n", metadata->size); 68 | } 69 | 70 | debug("allocated memory at: 0x%.16llx\n", ptr); 71 | 72 | return ptr; 73 | 74 | } 75 | 76 | // find out if the pointers belongs to a pmm_alloc or a slab_alloc 77 | // use pmm_free / slab_alloc accordingly 78 | void kfree(void *ptr) 79 | { 80 | if (!ptr) 81 | return; 82 | 83 | // using AND 0xFFF will return whether the last three digits (in hex) are zero 84 | // if yes big alloc has been used 85 | // OUTDATED: if no small alloc has been used and we need to toggle them to zero by 86 | // OUTDATED: using AND ~0xFF 87 | // OUTDATED: see bottom of file to see how it works using an example 88 | 89 | if (((uint64_t)ptr & 0xFFF) == 0) 90 | { 91 | kmalloc_metadata_t *metadata = ptr - PAGE_SIZE; 92 | 93 | pmm_free(metadata, (metadata->size / 4096) + 1); 94 | 95 | 96 | debug("free size: %d\n", metadata->size); 97 | debug("(big free) freed memory at: 0x%.16llx\n", ptr); 98 | 99 | return; 100 | } 101 | 102 | // OUTDATED: ptr = (void *)((uint64_t)ptr & ~(0xFFF)); 103 | 104 | kmalloc_metadata_t *metadata = ptr - sizeof(kmalloc_metadata_t); 105 | 106 | slab_free(metadata); // we don't need metadata->size, automatically found by slab_free 107 | 108 | debug("free size: %d\n", metadata->size); 109 | debug("(small free) freed memory at: 0x%.16llx\n", ptr); 110 | } 111 | 112 | // get the next power of two 113 | size_t next_pow_of_two(size_t num) 114 | { 115 | // TODO: might want to make this more efficient 116 | // x <<= 1 is at least better than x *= 2 117 | // note the result for 0 and 1 is 2 118 | // note after this size will be page aligned 119 | size_t result = 2; 120 | 121 | while (result < num) 122 | result <<= 1; 123 | 124 | return result; 125 | } 126 | 127 | /* Example for bitwise manipulation used to determine whether big alloc or small alloc has been used */ 128 | 129 | /* main.c 130 | #include 131 | #include 132 | 133 | int main() { 134 | uint64_t ptr = 0xffff80000169f000; 135 | 136 | printf("first:\t%lx\n", ptr); 137 | 138 | if (((uint64_t)ptr & 0xfff) == 0) 139 | printf("true\n"); 140 | 141 | printf("second:\t%lx\n", ptr); 142 | 143 | ptr = (uint64_t)ptr & ~(0xfff); 144 | 145 | printf("third:\t%lx\n", ptr); 146 | 147 | return 0; 148 | } 149 | */ 150 | 151 | /* output 152 | first: ffff80000169f000 153 | true 154 | second: ffff80000169f000 155 | third: ffff80000169f000 156 | */ 157 | -------------------------------------------------------------------------------- /src/libs/libk/alloc/kmalloc.h: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of an x86_64 hobbyist operating system called KnutOS 3 | Everything is openly developed on GitHub: https://github.com/Tix3Dev/KnutOS/ 4 | 5 | Copyright (C) 2021-2022 Yves Vollmeier 6 | This program is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see . 16 | */ 17 | 18 | #ifndef KMALLOC_H 19 | #define KMALLOC_H 20 | 21 | typedef struct 22 | { 23 | size_t size; 24 | } kmalloc_metadata_t; 25 | 26 | void *kmalloc(size_t size); 27 | void kfree(void *ptr); 28 | 29 | #endif 30 | -------------------------------------------------------------------------------- /src/libs/libk/debug/debug.c: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of an x86_64 hobbyist operating system called KnutOS 3 | Everything is openly developed on GitHub: https://github.com/Tix3Dev/KnutOS/ 4 | 5 | Copyright (C) 2021-2022 Yves Vollmeier 6 | This program is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see . 16 | */ 17 | 18 | #include 19 | 20 | #include 21 | #include 22 | 23 | const char debug_buffer[5120]; // big buffer so that big_logo from logo.h fits 24 | 25 | // variadic function for format specifiers to print to the serial console 26 | void debug(char *fmt, ...) 27 | { 28 | va_list ptr; 29 | va_start(ptr, fmt); 30 | vsnprintf((char *)&debug_buffer, -1, fmt, ptr); 31 | 32 | serial_send_string((char *)debug_buffer); 33 | 34 | va_end(ptr); 35 | } 36 | -------------------------------------------------------------------------------- /src/libs/libk/debug/debug.h: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of an x86_64 hobbyist operating system called KnutOS 3 | Everything is openly developed on GitHub: https://github.com/Tix3Dev/KnutOS/ 4 | 5 | Copyright (C) 2021-2022 Yves Vollmeier 6 | This program is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see . 16 | */ 17 | 18 | #ifndef DEBUG_H 19 | #define DEBUG_H 20 | 21 | #include 22 | 23 | void debug(char *fmt, ...); 24 | 25 | #endif 26 | -------------------------------------------------------------------------------- /src/libs/libk/definitions.h: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of an x86_64 hobbyist operating system called KnutOS 3 | Everything is openly developed on GitHub: https://github.com/Tix3Dev/KnutOS/ 4 | 5 | Copyright (C) 2021-2022 Yves Vollmeier 6 | This program is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see . 16 | */ 17 | 18 | #ifndef DEFINITIONS_H 19 | #define DEFINITIONS_H 20 | 21 | // address range 22 | typedef struct 23 | { 24 | void *start; 25 | void *end; 26 | } addr_range_t; 27 | 28 | #endif 29 | -------------------------------------------------------------------------------- /src/libs/libk/graphics/double_buffering.c: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of an x86_64 hobbyist operating system called KnutOS 3 | Everything is openly developed on GitHub: https://github.com/Tix3Dev/KnutOS/ 4 | 5 | Copyright (C) 2021-2022 Yves Vollmeier 6 | This program is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see . 16 | */ 17 | -------------------------------------------------------------------------------- /src/libs/libk/graphics/double_buffering.h: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of an x86_64 hobbyist operating system called KnutOS 3 | Everything is openly developed on GitHub: https://github.com/Tix3Dev/KnutOS/ 4 | 5 | Copyright (C) 2021-2022 Yves Vollmeier 6 | This program is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see . 16 | */ 17 | 18 | #ifndef DOUBLE_BUFFERING_H 19 | #define DOUBLE_BUFFERING_H 20 | 21 | 22 | 23 | #endif 24 | -------------------------------------------------------------------------------- /src/libs/libk/io/io.c: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of an x86_64 hobbyist operating system called KnutOS 3 | Everything is openly developed on GitHub: https://github.com/Tix3Dev/KnutOS/ 4 | 5 | Copyright (C) 2021-2022 Yves Vollmeier 6 | This program is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see . 16 | */ 17 | 18 | #include 19 | 20 | // sends data to a IO port 21 | void io_outb(uint16_t port, uint8_t value) 22 | { 23 | asm volatile("outb %0, %1" : : "a"(value), "Nd"(port)); 24 | } 25 | 26 | // receives data from a IO port 27 | uint8_t io_inb(uint16_t port) 28 | { 29 | uint8_t ret; 30 | asm volatile("inb %1, %0" 31 | : "=a"(ret) 32 | : "Nd"(port)); 33 | 34 | return ret; 35 | } 36 | 37 | // another I/0 cycle on an unused, CPU-speed independent port 38 | void io_wait(void) 39 | { 40 | io_inb(0x80); 41 | } 42 | -------------------------------------------------------------------------------- /src/libs/libk/io/io.h: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of an x86_64 hobbyist operating system called KnutOS 3 | Everything is openly developed on GitHub: https://github.com/Tix3Dev/KnutOS/ 4 | 5 | Copyright (C) 2021-2022 Yves Vollmeier 6 | This program is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see . 16 | */ 17 | 18 | #ifndef IO_H 19 | #define IO_H 20 | 21 | void io_outb(uint16_t port, uint8_t value); 22 | uint8_t io_inb(uint16_t port); 23 | void io_wait(void); 24 | 25 | #endif 26 | -------------------------------------------------------------------------------- /src/libs/libk/kprintf/kprintf.h: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////////////// 2 | // \author (c) Marco Paland (info@paland.com) 3 | // 2014-2019, PALANDesign Hannover, Germany 4 | // 5 | // \license The MIT License (MIT) 6 | // 7 | // Permission is hereby granted, free of charge, to any person obtaining a copy 8 | // of this software and associated documentation files (the "Software"), to deal 9 | // in the Software without restriction, including without limitation the rights 10 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | // copies of the Software, and to permit persons to whom the Software is 12 | // furnished to do so, subject to the following conditions: 13 | // 14 | // The above copyright notice and this permission notice shall be included in 15 | // all copies or substantial portions of the Software. 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | // THE SOFTWARE. 24 | // 25 | // \brief Tiny printf, sprintf and snprintf implementation, optimized for speed on 26 | // embedded systems with a very limited resources. 27 | // Use this instead of bloated standard/newlib printf. 28 | // These routines are thread safe and reentrant. 29 | // 30 | /////////////////////////////////////////////////////////////////////////////// 31 | 32 | #ifndef _PRINTF_H_ 33 | #define _PRINTF_H_ 34 | 35 | #include 36 | #include 37 | 38 | 39 | #ifdef __cplusplus 40 | extern "C" { 41 | #endif 42 | 43 | 44 | /** 45 | * Output a character to a custom device like UART, used by the printf() function 46 | * This function is declared here only. You have to write your custom implementation somewhere 47 | * \param character Character to output 48 | */ 49 | void _putchar(char character); 50 | 51 | 52 | /** 53 | * Tiny printf implementation 54 | * You have to implement _putchar if you use printf() 55 | * To avoid conflicts with the regular printf() API it is overridden by macro defines 56 | * and internal underscore-appended functions like printf_() are used 57 | * \param format A string that specifies the format of the output 58 | * \return The number of characters that are written into the array, not counting the terminating null character 59 | */ 60 | #define printf printf_ 61 | int printf_(const char* format, ...); 62 | 63 | 64 | /** 65 | * Tiny sprintf implementation 66 | * Due to security reasons (buffer overflow) YOU SHOULD CONSIDER USING (V)SNPRINTF INSTEAD! 67 | * \param buffer A pointer to the buffer where to store the formatted string. MUST be big enough to store the output! 68 | * \param format A string that specifies the format of the output 69 | * \return The number of characters that are WRITTEN into the buffer, not counting the terminating null character 70 | */ 71 | #define sprintf sprintf_ 72 | int sprintf_(char* buffer, const char* format, ...); 73 | 74 | 75 | /** 76 | * Tiny snprintf/vsnprintf implementation 77 | * \param buffer A pointer to the buffer where to store the formatted string 78 | * \param count The maximum number of characters to store in the buffer, including a terminating null character 79 | * \param format A string that specifies the format of the output 80 | * \param va A value identifying a variable arguments list 81 | * \return The number of characters that COULD have been written into the buffer, not counting the terminating 82 | * null character. A value equal or larger than count indicates truncation. Only when the returned value 83 | * is non-negative and less than count, the string has been completely written. 84 | */ 85 | #define snprintf snprintf_ 86 | #define vsnprintf vsnprintf_ 87 | int snprintf_(char* buffer, size_t count, const char* format, ...); 88 | int vsnprintf_(char* buffer, size_t count, const char* format, va_list va); 89 | 90 | 91 | /** 92 | * Tiny vprintf implementation 93 | * \param format A string that specifies the format of the output 94 | * \param va A value identifying a variable arguments list 95 | * \return The number of characters that are WRITTEN into the buffer, not counting the terminating null character 96 | */ 97 | #define vprintf vprintf_ 98 | int vprintf_(const char* format, va_list va); 99 | 100 | 101 | /** 102 | * printf with output function 103 | * You may use this as dynamic alternative to printf() with its fixed _putchar() output 104 | * \param out An output function which takes one character and an argument pointer 105 | * \param arg An argument pointer for user data passed to output function 106 | * \param format A string that specifies the format of the output 107 | * \return The number of characters that are sent to the output function, not counting the terminating null character 108 | */ 109 | int fctprintf(void (*out)(char character, void* arg), void* arg, const char* format, ...); 110 | 111 | 112 | #ifdef __cplusplus 113 | } 114 | #endif 115 | 116 | 117 | #endif // _PRINTF_H_ 118 | -------------------------------------------------------------------------------- /src/libs/libk/log/log.c: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of an x86_64 hobbyist operating system called KnutOS 3 | Everything is openly developed on GitHub: https://github.com/Tix3Dev/KnutOS/ 4 | 5 | Copyright (C) 2021-2022 Yves Vollmeier 6 | This program is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see . 16 | */ 17 | 18 | #include 19 | #include 20 | 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | 27 | const char log_buffer[5120]; 28 | 29 | // variadic function for format specifiers 30 | // serial logging - print log message to serial console 31 | void serial_log_impl(char *description, int line_nr, STATUS status, char *fmt, ...) 32 | { 33 | va_list ptr; 34 | va_start(ptr, fmt); 35 | vsnprintf((char *)&log_buffer, -1, fmt, ptr); 36 | 37 | if (status == INFO) 38 | { 39 | serial_set_color(TERM_CYAN); 40 | debug("[INFO] | "); 41 | } 42 | else if (status == WARNING) 43 | { 44 | serial_set_color(TERM_YELLOW); 45 | debug("[WARNING] | "); 46 | } 47 | else if (status == ERROR) 48 | { 49 | serial_set_color(TERM_RED); 50 | debug("[ERROR] | "); 51 | } 52 | 53 | debug("%s:%d ─→ %s", description, line_nr, (char *)log_buffer); 54 | serial_set_color(TERM_COLOR_RESET); 55 | } 56 | 57 | // variadic function for format specifiers 58 | // kernel logging - print log message to framebuffer 59 | void kernel_log_impl(char *description, int line_nr, STATUS status, char *fmt, ...) 60 | { 61 | va_list ptr; 62 | va_start(ptr, fmt); 63 | vsnprintf((char *)&log_buffer, -1, fmt, ptr); 64 | 65 | if (status == INFO) 66 | printk(GFX_CYAN, "[INFO] | %s:%d ─→ %s", description, line_nr, (char *)log_buffer); 67 | else if (status == WARNING) 68 | printk(GFX_YELLOW, "[WARNING] | %s:%d ─→ %s", description, line_nr, (char *)log_buffer); 69 | else if (status == ERROR) 70 | printk(GFX_RED, "[ERROR] | %s:%d ─→ %s", description, line_nr, (char *)log_buffer); 71 | } 72 | -------------------------------------------------------------------------------- /src/libs/libk/log/log.h: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of an x86_64 hobbyist operating system called KnutOS 3 | Everything is openly developed on GitHub: https://github.com/Tix3Dev/KnutOS/ 4 | 5 | Copyright (C) 2021-2022 Yves Vollmeier 6 | This program is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see . 16 | */ 17 | 18 | #ifndef LOG_H 19 | #define LOG_H 20 | 21 | #define serial_log(...) serial_log_impl(__FILE__, __LINE__, __VA_ARGS__); 22 | #define kernel_log(...) kernel_log_impl(__FILE__, __LINE__, __VA_ARGS__); 23 | 24 | typedef enum { 25 | INFO, 26 | WARNING, 27 | ERROR 28 | } STATUS; 29 | 30 | void serial_log_impl(char *file, int line_nr, STATUS status, char *fmt, ...); 31 | void kernel_log_impl(char *file, int line_nr, STATUS status, char *fmt, ...); 32 | 33 | #endif 34 | -------------------------------------------------------------------------------- /src/libs/libk/math/math.c: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of an x86_64 hobbyist operating system called KnutOS 3 | Everything is openly developed on GitHub: https://github.com/Tix3Dev/KnutOS/ 4 | 5 | Copyright (C) 2021-2022 Yves Vollmeier 6 | This program is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see . 16 | */ 17 | 18 | #include 19 | 20 | // calculate the power of a number using a given base and exponent 21 | // note that the result will always we 0, if the exponent is negative 22 | // algorithm used: https://en.wikipedia.org/wiki/Exponentiation_by_squaring 23 | uint32_t pow(int32_t base, int32_t exponent) 24 | { 25 | if (exponent == 0) 26 | return 1; 27 | 28 | if (exponent < 0) 29 | { 30 | base = 1 / base; 31 | exponent = -exponent; 32 | } 33 | 34 | int32_t temp = 1; 35 | 36 | while (exponent > 1) 37 | { 38 | if (exponent % 2 == 0) 39 | { 40 | base = base * base; 41 | exponent = exponent / 2; 42 | } 43 | else 44 | { 45 | temp = base * temp; 46 | base = base * base; 47 | exponent = (exponent - 1) / 2; 48 | } 49 | } 50 | 51 | return base * temp; 52 | } 53 | -------------------------------------------------------------------------------- /src/libs/libk/math/math.h: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of an x86_64 hobbyist operating system called KnutOS 3 | Everything is openly developed on GitHub: https://github.com/Tix3Dev/KnutOS/ 4 | 5 | Copyright (C) 2021-2022 Yves Vollmeier 6 | This program is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see . 16 | */ 17 | 18 | #ifndef MATH_H 19 | #define MATH_H 20 | 21 | uint32_t pow(int32_t base, int32_t exponent); 22 | 23 | #endif 24 | -------------------------------------------------------------------------------- /src/libs/libk/stdio/stdio.c: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of an x86_64 hobbyist operating system called KnutOS 3 | Everything is openly developed on GitHub: https://github.com/Tix3Dev/KnutOS/ 4 | 5 | Copyright (C) 2021-2022 Yves Vollmeier 6 | This program is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see . 16 | */ 17 | 18 | #include 19 | #include 20 | 21 | #include 22 | #include 23 | #include 24 | 25 | const char printk_buffer[5120]; // big buffer so that big_logo from logo.h fits 26 | 27 | // variadic function for format specifiers to print to the framebuffer 28 | void printk(uint32_t foreground_color, char *fmt, ...) 29 | { 30 | va_list ptr; 31 | va_start(ptr, fmt); 32 | vsnprintf((char *)&printk_buffer, -1, fmt, ptr); 33 | 34 | framebuffer_print_string((char *)printk_buffer, foreground_color); 35 | 36 | va_end(ptr); 37 | } 38 | -------------------------------------------------------------------------------- /src/libs/libk/stdio/stdio.h: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of an x86_64 hobbyist operating system called KnutOS 3 | Everything is openly developed on GitHub: https://github.com/Tix3Dev/KnutOS/ 4 | 5 | Copyright (C) 2021-2022 Yves Vollmeier 6 | This program is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see . 16 | */ 17 | 18 | #ifndef PRINTK_H 19 | #define PRINTK_H 20 | 21 | #include 22 | 23 | void printk(uint32_t foreground_color, char *fmt, ...); 24 | 25 | #endif 26 | -------------------------------------------------------------------------------- /src/libs/libk/string/string.c: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of an x86_64 hobbyist operating system called KnutOS 3 | Everything is openly developed on GitHub: https://github.com/Tix3Dev/KnutOS/ 4 | 5 | Copyright (C) 2021-2022 Yves Vollmeier 6 | This program is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see . 16 | */ 17 | 18 | #include 19 | #include 20 | 21 | // fill a block of memory with a certain value 22 | void *memset(void *pointer, uint32_t value, size_t size) 23 | { 24 | uint8_t *buffer_pointer = (uint8_t *)pointer; 25 | 26 | for (size_t i = 0; i < size; i++) 27 | *buffer_pointer++ = value; 28 | 29 | return pointer; 30 | } 31 | 32 | // compares the first n bytes of memory area string1 and memory are string2 33 | // return value is 34 | // < 0 when string1 is less than string2 35 | // > 0 when string1 is greater than string2 36 | // = 0 when string1 is equal to string2 37 | // return value is based of fist non-matching character (e.g. abc aBc -> b/B) 38 | int memcmp(const void *string1, const void *string2, size_t n) 39 | { 40 | const unsigned char *str1 = string1; 41 | const unsigned char *str2 = string2; 42 | 43 | for (size_t i = 0; i < n; i++, str1++, str2++) 44 | { 45 | if (*str1 != *str2) 46 | return (*str1 - *str2); 47 | } 48 | 49 | return 0; 50 | } 51 | -------------------------------------------------------------------------------- /src/libs/libk/string/string.h: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of an x86_64 hobbyist operating system called KnutOS 3 | Everything is openly developed on GitHub: https://github.com/Tix3Dev/KnutOS/ 4 | 5 | Copyright (C) 2021-2022 Yves Vollmeier 6 | This program is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see . 16 | */ 17 | 18 | #ifndef STRING_H 19 | #define STRING_H 20 | 21 | void *memset(uint32_t *pointer, uint32_t value, size_t size); 22 | int memcmp(const void *string1, const void *string2, size_t n); 23 | 24 | #endif 25 | --------------------------------------------------------------------------------