diff --git a/.gitignore b/.gitignore index 50f8de6..18b5e56 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ build cmake-build-debug -.idea \ No newline at end of file +.idea +noxos.log \ No newline at end of file diff --git a/README.md b/README.md index 32fbcf5..f062817 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # NoxOS ## Copyright / License -Copyright (C) Antifallobst +Copyright (C) 2023 Antifallobst NoxOS is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -15,4 +15,7 @@ See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . +## Contribution Welcome :D +Install instructions and Code Documentation can be found in the [wiki](https://codeberg.org/antifallobst/noxos/wiki/). +If you want to contribute, filtering the [issues](https://codeberg.org/antifallobst/noxos/issues/) for the `Good First Issue` label would be a good way to start :) diff --git a/build.sh b/build.sh index 5eb6822..1235497 100755 --- a/build.sh +++ b/build.sh @@ -51,23 +51,20 @@ generate_image() { -efi-boot-part --efi-boot-image --protective-msdos-label \ iso -o noxos.iso + ./limine/limine-deploy noxos.iso + rm -rfv iso cd .. echo "" } -emulate() { - qemu-system-x86_64 -cdrom build/noxos.iso -chardev stdio,id=log,logfile=noxos.log -serial chardev:log -} - echo "!=====[ NoxOS build script ]=====!" workspace_setup kernel_build [ ! -d "build/limine" ] && limine_install generate_image -emulate echo "!=====[ Finished ]=====!" diff --git a/kernel/CMakeLists.txt b/kernel/CMakeLists.txt index 9bb5f5d..669f967 100644 --- a/kernel/CMakeLists.txt +++ b/kernel/CMakeLists.txt @@ -11,7 +11,7 @@ file(GLOB_RECURSE kernel_inc "**/*.h") file(GLOB_RECURSE kernel_src_asm "**/*.asm") -target_compile_options(kernel PRIVATE -fno-stack-protector -fno-stack-check -mno-red-zone -ffreestanding -m64 -march=x86-64 -mabi=sysv) +target_compile_options(kernel PRIVATE -g -fno-stack-protector -fno-stack-check -mno-red-zone -ffreestanding -m64 -march=x86-64 -mabi=sysv) target_link_options(kernel PRIVATE -nostdlib -static -T "${CMAKE_CURRENT_LIST_DIR}/kernel.ld") enable_language(ASM_NASM) diff --git a/kernel/inc/boot/boot_info.h b/kernel/inc/boot/boot_info.h index d6632e3..7ef341f 100644 --- a/kernel/inc/boot/boot_info.h +++ b/kernel/inc/boot/boot_info.h @@ -20,11 +20,10 @@ #include "limine.h" typedef struct { - struct limine_framebuffer* framebuffer; - struct limine_terminal* terminal; - struct limine_memmap_entry** memory_map; - uint64_t memory_map_size; - void* rsdp; + struct limine_framebuffer_response* framebuffer; + struct limine_terminal_response* terminal; + struct limine_memmap_response* memory_map; + void* rsdp; } boot_info_T; #endif //NOX_BOOT_INFO_H diff --git a/kernel/inc/mm/memory_map.h b/kernel/inc/mm/memory_map.h new file mode 100644 index 0000000..bb48714 --- /dev/null +++ b/kernel/inc/mm/memory_map.h @@ -0,0 +1,24 @@ +/* Copyright (C) Antifallobst + * + * NoxOS is free software: + * you can redistribute it and/or modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, either version 3 of the License, + * or (at your option) any later version. + * + * NoxOS is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with this program. + * If not, see . + */ + +#ifndef NOX_MEMORY_MAP_H +#define NOX_MEMORY_MAP_H + +#include "utils/stdtypes.h" +#include "boot/boot_info.h" + +uint64_t memory_map_get_total_memory_size(boot_info_T* boot_info); + +#endif //NOX_MEMORY_MAP_H diff --git a/kernel/inc/mm/page_frame.h b/kernel/inc/mm/page_frame.h new file mode 100644 index 0000000..1a579aa --- /dev/null +++ b/kernel/inc/mm/page_frame.h @@ -0,0 +1,43 @@ +/* Copyright (C) Antifallobst + * + * NoxOS is free software: + * you can redistribute it and/or modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, either version 3 of the License, + * or (at your option) any later version. + * + * NoxOS is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with this program. + * If not, see . + */ + +#ifndef NOX_PAGE_FRAME_H +#define NOX_PAGE_FRAME_H + +#include "utils/stdtypes.h" +#include "utils/bitmap.h" +#include "boot/boot_info.h" + +#define PFRAME_SIZE 4096 // The size of a page frame + +typedef struct { + uint64_t free_memory; + uint64_t reserved_memory; + uint64_t used_memory; + uint64_t page_bitmap_index; + bitmap_T page_bitmap; + bool blocked; +} page_frame_manager_T; + +void pframe_manager_init (boot_info_T* boot_info); +void pframe_reserve (void* address); +void pframe_reserve_multi (void* address, uint32_t n); +void pframe_unreserve (void* address); +void pframe_unreserve_multi (void* address, uint32_t n); +void pframe_free (void* address); +void pframe_free_multi (void* address, uint32_t n); +void* pframe_request (); + +#endif //NOX_PAGE_FRAME_H diff --git a/kernel/inc/platform/cpu.h b/kernel/inc/platform/cpu.h new file mode 100644 index 0000000..9264dd4 --- /dev/null +++ b/kernel/inc/platform/cpu.h @@ -0,0 +1,65 @@ +/* Copyright (C) Antifallobst + * + * NoxOS is free software: + * you can redistribute it and/or modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, either version 3 of the License, + * or (at your option) any later version. + * + * NoxOS is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with this program. + * If not, see . + */ + +#ifndef NOX_CPU_H +#define NOX_CPU_H + +#include "utils/stdtypes.h" + +typedef enum { + CPU_FLAG_CARRY = 0, + CPU_FLAG_PARITY = 2, + CPU_FLAG_AUXILIARY = 4, + CPU_FLAG_ZERO = 6, + CPU_FLAG_SIGN = 7, + CPU_FLAG_TRAP = 8, + CPU_FLAG_INTERRUPT_ENABLE = 9, + CPU_FLAG_DIRECTION = 10, + CPU_FLAG_OVERFLOW = 11, + CPU_FLAG_IO_PRIVILEGE_0 = 12, + CPU_FLAG_IO_PRIVILEGE_1 = 13, + CPU_FLAG_NESTED_TASK = 14, + CPU_FLAG_RESUME = 16, + CPU_FLAG_VIRTUAL_8086 = 17, + CPU_FLAG_ALIGNMENT_CHECK = 18, + CPU_FLAG_VIRTUAL_INTERRUPT = 19, + CPU_FLAG_VIRTUAL_INTERRUPT_PENDING = 20, + CPU_FLAG_CPUID = 21 +} cpu_flags_E; + +typedef struct { + // Registers saved by assembly function + uint64_t cr3; + uint64_t rax; + uint64_t rbx; + uint64_t rcx; + uint64_t rdx; + uint64_t rsi; + uint64_t rdi; + uint64_t rbp; + + // Manually pushed + uint64_t interrupt_id; + uint64_t error_code; + + // Saved by CPU + uint64_t rip; + uint64_t crs; + uint64_t flags; + uint64_t rsp; + uint64_t ss; +} cpu_state_T; + +#endif //NOX_CPU_H diff --git a/kernel/inc/platform/gdt.h b/kernel/inc/platform/gdt.h new file mode 100644 index 0000000..420fa06 --- /dev/null +++ b/kernel/inc/platform/gdt.h @@ -0,0 +1,48 @@ +/* Copyright (C) Antifallobst + * + * NoxOS is free software: + * you can redistribute it and/or modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, either version 3 of the License, + * or (at your option) any later version. + * + * NoxOS is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with this program. + * If not, see . + */ + +#ifndef NOX_GDT_H +#define NOX_GDT_H + +#include "utils/stdtypes.h" + +typedef struct { + uint16_t size; + uint64_t offset; +}__attribute__((packed)) gdt_descriptor_T; + +typedef struct { + uint16_t limit0; + uint16_t base0; + uint8_t base1; + uint8_t access; + uint8_t limit1_flags; + uint8_t base2; +}__attribute__((packed)) gdt_entry_T; + +typedef struct { + gdt_entry_T null; // 0x00 + gdt_entry_T kernel_code; // 0x08 + gdt_entry_T kernel_data; // 0x10 + gdt_entry_T user_null; // 0x18 + gdt_entry_T user_code; // 0x20 + gdt_entry_T user_data; // 0x28 +}__attribute__((packed)) __attribute__((aligned(0x1000))) gdt_T; + +extern gdt_T g_default_gdt; + +void gdt_init(); + +#endif //NOX_GDT_H diff --git a/kernel/inc/platform/interrupts.h b/kernel/inc/platform/interrupts.h new file mode 100644 index 0000000..2587f7a --- /dev/null +++ b/kernel/inc/platform/interrupts.h @@ -0,0 +1,42 @@ +/* Copyright (C) Antifallobst + * + * NoxOS is free software: + * you can redistribute it and/or modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, either version 3 of the License, + * or (at your option) any later version. + * + * NoxOS is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with this program. + * If not, see . + */ + +#ifndef NOX_INTERRUPTS_H +#define NOX_INTERRUPTS_H + +#include "utils/stdtypes.h" + +#define IDT_ENTRY_INTR_GATE 0b10001110 +#define IDT_ENTRY_CALL_GATE 0b10001100 +#define IDT_ENTRY_TRAP_GATE 0b10001111 + +typedef struct { + uint16_t limit; + uint64_t offset; +} __attribute__((packed)) idt_register_T; + +typedef struct { + uint16_t offset0; + uint16_t selector; + uint8_t ist; + uint8_t type_attribute; + uint16_t offset1; + uint32_t offset2; + uint32_t ignore; +} idt_descriptor_entry_T; + +void idt_init(); + +#endif //NOX_INTERRUPTS_H diff --git a/kernel/inc/utils/bitmap.h b/kernel/inc/utils/bitmap.h new file mode 100644 index 0000000..ffd89a8 --- /dev/null +++ b/kernel/inc/utils/bitmap.h @@ -0,0 +1,32 @@ +/* Copyright (C) Antifallobst + * + * NoxOS is free software: + * you can redistribute it and/or modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, either version 3 of the License, + * or (at your option) any later version. + * + * NoxOS is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with this program. + * If not, see . + */ + +#ifndef NOX_BITMAP_H +#define NOX_BITMAP_H + +#include "stdtypes.h" + +typedef struct { + uint32_t size; + uint8_t* buffer; +} bitmap_T; + +bitmap_T bitmap_init_from_buffer (void* buffer, uint32_t size); +bitmap_T bitmap_init (uint32_t size); +void bitmap_destruct (bitmap_T* bitmap); +bool bitmap_set (bitmap_T* bitmap, uint32_t index, bool value); +bool bitmap_get (bitmap_T* bitmap, uint32_t index); + +#endif //NOX_BITMAP_H diff --git a/kernel/inc/utils/core.h b/kernel/inc/utils/core.h new file mode 100644 index 0000000..853620c --- /dev/null +++ b/kernel/inc/utils/core.h @@ -0,0 +1,22 @@ +/* Copyright (C) Antifallobst + * + * NoxOS is free software: + * you can redistribute it and/or modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, either version 3 of the License, + * or (at your option) any later version. + * + * NoxOS is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with this program. + * If not, see . + */ + +#ifndef NOX_CORE_H +#define NOX_CORE_H + +#define CORE_HALT_FOREVER while(1) { asm("hlt"); } +#define CORE_HALT_WHILE(a) while(a) { asm("hlt"); } + +#endif //NOX_CORE_H diff --git a/kernel/inc/utils/math.h b/kernel/inc/utils/math.h index 8e70708..ababdf2 100644 --- a/kernel/inc/utils/math.h +++ b/kernel/inc/utils/math.h @@ -16,7 +16,13 @@ #ifndef NOX_MATH_H #define NOX_MATH_H -#define max(a, b) (a > b ? a : b) -#define min(a, b) (a > b ? b : a) +#include "stdtypes.h" + +#define MAX(a, b) (a > b ? a : b) +#define MIN(a, b) (a > b ? b : a) +#define CEIL_TO(a, b) (a + b - (a % b)) +#define FLOOR_TO(a, b) (a - (a % b)) + +uint64_t pow(uint64_t base, uint64_t exp); #endif //NOX_MATH_H diff --git a/kernel/src/boot/limine.c b/kernel/src/boot/limine.c index 6882bd3..402c553 100644 --- a/kernel/src/boot/limine.c +++ b/kernel/src/boot/limine.c @@ -44,20 +44,19 @@ void _start() { halt(); } log(LOG_INFO, "( LimineEntry ) Found Terminal"); - boot_info.terminal = terminal_request.response->terminals[0]; + boot_info.terminal = terminal_request.response; if (framebuffer_request.response == NULL || framebuffer_request.response->framebuffer_count < 0) { halt(); } log(LOG_INFO, "( LimineEntry ) Found Framebuffer"); - boot_info.framebuffer = framebuffer_request.response->framebuffers[0]; + boot_info.framebuffer = framebuffer_request.response; if (memmap_request.response == NULL || memmap_request.response->entry_count < 0) { halt(); } log(LOG_INFO, "( LimineEntry ) Found Memory Map"); - boot_info.memory_map_size = memmap_request.response->entry_count; - boot_info.memory_map = memmap_request.response->entries; + boot_info.memory_map = memmap_request.response; kmain(boot_info); } \ No newline at end of file diff --git a/kernel/src/kmain.c b/kernel/src/kmain.c index 7f9f44d..c19ad4d 100644 --- a/kernel/src/kmain.c +++ b/kernel/src/kmain.c @@ -13,14 +13,32 @@ * If not, see . */ -#include "utils/stdtypes.h" #include "utils/logger.h" +#include "utils/core.h" #include "boot/boot_info.h" +#include "platform/gdt.h" +#include "platform/interrupts.h" +#include "mm/page_frame.h" + +void limine_terminal_print(boot_info_T* boot_info, string_t string) { + boot_info->terminal->write(boot_info->terminal->terminals[0], string, string_length(string)); +} + +void kernel_init(boot_info_T* boot_info) { + gdt_init(); + pframe_manager_init(boot_info); + idt_init(); +} void kmain(boot_info_T boot_info) { -// terminal_request.response->write(terminal, "Booting NoxOS...", 16); + limine_terminal_print(&boot_info, "Booting NoxOS..."); log(LOG_DEBUG, "Booting NoxOS"); - while(true) asm("hlt"); + kernel_init(&boot_info); + + log(LOG_DEBUG, "FIRING TEST INTERRUPT"); + asm("int $0x01"); + + CORE_HALT_FOREVER } diff --git a/kernel/src/mm/memory_map.c b/kernel/src/mm/memory_map.c new file mode 100644 index 0000000..2c99d8d --- /dev/null +++ b/kernel/src/mm/memory_map.c @@ -0,0 +1,32 @@ +/* Copyright (C) Antifallobst + * + * NoxOS is free software: + * you can redistribute it and/or modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, either version 3 of the License, + * or (at your option) any later version. + * + * NoxOS is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with this program. + * If not, see . + */ + +#include "mm/memory_map.h" +#include "utils/logger.h" + +uint64_t memory_map_get_total_memory_size(boot_info_T* boot_info) { + static uint64_t size = 0; + if (size > 0) { + log(LOG_INFO, "Memory size is already calculated, returning known value"); + return size; + }; + + for (int i = 0; i < boot_info->memory_map->entry_count; i++) { + struct limine_memmap_entry* entry = boot_info->memory_map->entries[i]; + size += entry->length; + } + + return size; +} \ No newline at end of file diff --git a/kernel/src/mm/page_frame.c b/kernel/src/mm/page_frame.c new file mode 100644 index 0000000..37d9f8f --- /dev/null +++ b/kernel/src/mm/page_frame.c @@ -0,0 +1,187 @@ +/* Copyright (C) Antifallobst + * + * NoxOS is free software: + * you can redistribute it and/or modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, either version 3 of the License, + * or (at your option) any later version. + * + * NoxOS is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with this program. + * If not, see . + */ + +#include "mm/page_frame.h" +#include "mm/memory_map.h" +#include "utils/logger.h" +#include "utils/math.h" +#include "utils/core.h" + +page_frame_manager_T g_page_frame_manager; + +void pframe_reserve(void* address) { + CORE_HALT_WHILE(g_page_frame_manager.blocked) + g_page_frame_manager.blocked = true; + + uint64_t index = (uint64_t)address / PFRAME_SIZE; + + if (bitmap_get(&g_page_frame_manager.page_bitmap, index)) { + g_page_frame_manager.blocked = false; + return; + } + + if (bitmap_set(&g_page_frame_manager.page_bitmap, index, true)) { + g_page_frame_manager.free_memory -= PFRAME_SIZE; + g_page_frame_manager.reserved_memory += PFRAME_SIZE; + } + + g_page_frame_manager.blocked = false; +} + +void pframe_reserve_multi(void* address, uint32_t n) { + for (uint32_t i = 0; i < n; i++) { + pframe_reserve(&address[i * PFRAME_SIZE]); + } +} + +void pframe_unreserve(void* address) { + CORE_HALT_WHILE(g_page_frame_manager.blocked) + g_page_frame_manager.blocked = true; + + uint64_t index = (uint64_t)address / PFRAME_SIZE; + + if (!bitmap_get(&g_page_frame_manager.page_bitmap, index)) { + g_page_frame_manager.blocked = false; + return; + } + + if (bitmap_set(&g_page_frame_manager.page_bitmap, index, false)) { + g_page_frame_manager.free_memory += PFRAME_SIZE; + g_page_frame_manager.reserved_memory -= PFRAME_SIZE; + + if (g_page_frame_manager.page_bitmap_index > index) { + g_page_frame_manager.page_bitmap_index = index; + } + } + + g_page_frame_manager.blocked = false; +} + +void pframe_unreserve_multi(void* address, uint32_t n) { + for (uint32_t i = 0; i < n; i++) { + pframe_unreserve(&address[i * PFRAME_SIZE]); + } +} + +// this function should only be used by functions, that blocks the pframe manager +void pframe_lock(void* address) { + uint64_t index = (uint64_t)address / PFRAME_SIZE; + + if (bitmap_get(&g_page_frame_manager.page_bitmap, index)) { + return; + } + + if (bitmap_set(&g_page_frame_manager.page_bitmap, index, true)) { + g_page_frame_manager.free_memory -= PFRAME_SIZE; + g_page_frame_manager.used_memory += PFRAME_SIZE; + } +} + +void pframe_lock_multi(void* address, uint32_t n) { + for (uint32_t i = 0; i < n; i++) { + pframe_lock(&address[i * PFRAME_SIZE]); + } +} + +void pframe_free(void* address) { + CORE_HALT_WHILE(g_page_frame_manager.blocked) + g_page_frame_manager.blocked = true; + + uint64_t index = (uint64_t)address / PFRAME_SIZE; + + if (!bitmap_get(&g_page_frame_manager.page_bitmap, index)) { + g_page_frame_manager.blocked = false; + return; + } + + if (bitmap_set(&g_page_frame_manager.page_bitmap, index, false)) { + g_page_frame_manager.free_memory += PFRAME_SIZE; + g_page_frame_manager.used_memory -= PFRAME_SIZE; + + if (g_page_frame_manager.page_bitmap_index > index) { + g_page_frame_manager.page_bitmap_index = index; + } + } + + g_page_frame_manager.blocked = false; +} + +void pframe_free_multi(void* address, uint32_t n) { + for (uint32_t i = 0; i < n; i++) { + pframe_free(&address[i * PFRAME_SIZE]); + } +} + +void* pframe_request() { + CORE_HALT_WHILE(g_page_frame_manager.blocked) + g_page_frame_manager.blocked = true; + + while (g_page_frame_manager.page_bitmap_index < g_page_frame_manager.page_bitmap.size * 8) { + if (bitmap_get(&g_page_frame_manager.page_bitmap, g_page_frame_manager.page_bitmap_index)) { + g_page_frame_manager.page_bitmap_index++; + continue; + } + void* address = (void*)(g_page_frame_manager.page_bitmap_index * PFRAME_SIZE); + + pframe_lock(address); + + g_page_frame_manager.blocked = false; + return address; + } + + g_page_frame_manager.blocked = false; + return NULL; +} + +void pframe_manager_init(boot_info_T* boot_info) { + log(LOG_INFO, " Initializing"); + + struct limine_memmap_entry* largest_usable_entry = NULL; + + for (int i = 0; i < boot_info->memory_map->entry_count; i++) { + struct limine_memmap_entry* entry = boot_info->memory_map->entries[i]; + + if (entry->type != LIMINE_MEMMAP_USABLE) { continue; } + if (largest_usable_entry != NULL && largest_usable_entry->length > entry->length) { continue; } + + largest_usable_entry = entry; + } + + uint64_t total_memory = memory_map_get_total_memory_size(boot_info); + log(LOG_INFO, " * Total Memory size: 'size'"); // TODO: replace with format string + + g_page_frame_manager.page_bitmap = bitmap_init_from_buffer((void*)largest_usable_entry->base, total_memory / PFRAME_SIZE / 8 + 1); + g_page_frame_manager.page_bitmap_index = 0; + g_page_frame_manager.reserved_memory = 0; + g_page_frame_manager.used_memory = 0; + g_page_frame_manager.free_memory = total_memory; + + pframe_reserve_multi(0, total_memory / PFRAME_SIZE + 1); + log(LOG_INFO, " * Reserved all pages"); + + for (int i = 0; i < boot_info->memory_map->entry_count; i++) { + struct limine_memmap_entry* entry = boot_info->memory_map->entries[i]; + if (entry->type != LIMINE_MEMMAP_USABLE) { continue; } + + pframe_unreserve_multi((void*)entry->base, entry->length / PFRAME_SIZE); + } + log(LOG_INFO, " * Unreserved usable pages"); + + pframe_lock_multi(g_page_frame_manager.page_bitmap.buffer, g_page_frame_manager.page_bitmap.size / PFRAME_SIZE); + log(LOG_INFO, " * Locked page_bitmap pages"); + + log(LOG_INFO, " * Finished initialization"); + g_page_frame_manager.blocked = false; +} \ No newline at end of file diff --git a/kernel/src/platform/gdt.c b/kernel/src/platform/gdt.c new file mode 100644 index 0000000..cac09eb --- /dev/null +++ b/kernel/src/platform/gdt.c @@ -0,0 +1,39 @@ +/* Copyright (C) Antifallobst + * + * NoxOS is free software: + * you can redistribute it and/or modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, either version 3 of the License, + * or (at your option) any later version. + * + * NoxOS is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with this program. + * If not, see . + */ + +#include "platform/gdt.h" +#include "utils/logger.h" + +extern void gdt_load(gdt_descriptor_T* gdt_descriptor); + +__attribute__((aligned(0x1000))) +gdt_T g_default_gdt = { + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x00, 0x00, 0x00, 0x9A, 0xA0, 0x00}, + {0x00, 0x00, 0x00, 0x92, 0xA0, 0x00}, + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x00, 0x00, 0x00, 0x9A, 0xA0, 0x00}, + {0x00, 0x00, 0x00, 0x92, 0xA0, 0x00} +}; + +void gdt_init() { + gdt_descriptor_T descriptor; + + descriptor.size = sizeof(gdt_T) - 1; + descriptor.offset = (uint64_t)&g_default_gdt; + + gdt_load(&descriptor); + log(LOG_INFO, "GDT loaded"); +} \ No newline at end of file diff --git a/kernel/src/platform/interrupts.c b/kernel/src/platform/interrupts.c new file mode 100644 index 0000000..8d5ad66 --- /dev/null +++ b/kernel/src/platform/interrupts.c @@ -0,0 +1,124 @@ +/* Copyright (C) Antifallobst + * + * NoxOS is free software: + * you can redistribute it and/or modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, either version 3 of the License, + * or (at your option) any later version. + * + * NoxOS is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with this program. + * If not, see . + */ + +#include "platform/interrupts.h" +#include "platform/cpu.h" +#include "mm/page_frame.h" +#include "utils/logger.h" + +idt_register_T g_idt_register; + +extern void idt_load(idt_register_T* idt_register); +extern void interrupt_stub_0x00(); +extern void interrupt_stub_0x01(); +extern void interrupt_stub_0x02(); +extern void interrupt_stub_0x03(); +extern void interrupt_stub_0x04(); +extern void interrupt_stub_0x05(); +extern void interrupt_stub_0x06(); +extern void interrupt_stub_0x07(); +extern void interrupt_stub_0x08(); +extern void interrupt_stub_0x09(); +extern void interrupt_stub_0x0A(); +extern void interrupt_stub_0x0B(); +extern void interrupt_stub_0x0C(); +extern void interrupt_stub_0x0D(); +extern void interrupt_stub_0x0E(); +extern void interrupt_stub_0x0F(); +extern void interrupt_stub_0x10(); +extern void interrupt_stub_0x11(); +extern void interrupt_stub_0x12(); +extern void interrupt_stub_0x13(); +extern void interrupt_stub_0x14(); +extern void interrupt_stub_0x15(); +extern void interrupt_stub_0x16(); +extern void interrupt_stub_0x17(); +extern void interrupt_stub_0x18(); +extern void interrupt_stub_0x19(); +extern void interrupt_stub_0x1A(); +extern void interrupt_stub_0x1B(); +extern void interrupt_stub_0x1C(); +extern void interrupt_stub_0x1D(); +extern void interrupt_stub_0x1E(); +extern void interrupt_stub_0x1F(); + +void idt_set_descriptor_entry_offset(idt_descriptor_entry_T* entry, uint64_t offset) { + entry->offset0 = (uint16_t) (offset & 0x000000000000ffff); + entry->offset1 = (uint16_t) ((offset & 0x00000000ffff0000) >> 16); + entry->offset2 = (uint32_t) ((offset & 0xffffffff00000000) >> 32); +} + +uint64_t idt_get_descriptor_entry_offset(idt_descriptor_entry_T* entry) { + uint64_t offset = 0; + offset |= (uint64_t)entry->offset0; + offset |= (uint64_t)entry->offset1 << 16; + offset |= (uint64_t)entry->offset2 << 32; + return offset; +} + +void idt_set_gate(void* handler, uint8_t entry_offset, uint8_t type_attribute, uint8_t selector) { + idt_descriptor_entry_T* entry = (idt_descriptor_entry_T*)(g_idt_register.offset + entry_offset * sizeof(idt_descriptor_entry_T)); + idt_set_descriptor_entry_offset(entry, (uint64_t)handler); + entry->type_attribute = type_attribute; + entry->selector = selector; +} + +void idt_init() { + g_idt_register.limit = 0x0FFF; + g_idt_register.offset = (uint64_t)pframe_request(); + + + idt_set_gate((void*)interrupt_stub_0x00, 0x00, IDT_ENTRY_INTR_GATE, 0x08); + idt_set_gate((void*)interrupt_stub_0x01, 0x01, IDT_ENTRY_INTR_GATE, 0x08); + idt_set_gate((void*)interrupt_stub_0x02, 0x02, IDT_ENTRY_INTR_GATE, 0x08); + idt_set_gate((void*)interrupt_stub_0x03, 0x03, IDT_ENTRY_INTR_GATE, 0x08); + idt_set_gate((void*)interrupt_stub_0x04, 0x04, IDT_ENTRY_INTR_GATE, 0x08); + idt_set_gate((void*)interrupt_stub_0x05, 0x05, IDT_ENTRY_INTR_GATE, 0x08); + idt_set_gate((void*)interrupt_stub_0x06, 0x06, IDT_ENTRY_INTR_GATE, 0x08); + idt_set_gate((void*)interrupt_stub_0x07, 0x07, IDT_ENTRY_INTR_GATE, 0x08); + idt_set_gate((void*)interrupt_stub_0x08, 0x08, IDT_ENTRY_INTR_GATE, 0x08); + idt_set_gate((void*)interrupt_stub_0x09, 0x09, IDT_ENTRY_INTR_GATE, 0x08); + idt_set_gate((void*)interrupt_stub_0x0A, 0x0A, IDT_ENTRY_INTR_GATE, 0x08); + idt_set_gate((void*)interrupt_stub_0x0B, 0x0B, IDT_ENTRY_INTR_GATE, 0x08); + idt_set_gate((void*)interrupt_stub_0x0C, 0x0C, IDT_ENTRY_INTR_GATE, 0x08); + idt_set_gate((void*)interrupt_stub_0x0D, 0x0D, IDT_ENTRY_INTR_GATE, 0x08); + idt_set_gate((void*)interrupt_stub_0x0E, 0x0E, IDT_ENTRY_INTR_GATE, 0x08); + idt_set_gate((void*)interrupt_stub_0x0F, 0x0F, IDT_ENTRY_INTR_GATE, 0x08); + idt_set_gate((void*)interrupt_stub_0x10, 0x10, IDT_ENTRY_INTR_GATE, 0x08); + idt_set_gate((void*)interrupt_stub_0x11, 0x11, IDT_ENTRY_INTR_GATE, 0x08); + idt_set_gate((void*)interrupt_stub_0x12, 0x12, IDT_ENTRY_INTR_GATE, 0x08); + idt_set_gate((void*)interrupt_stub_0x13, 0x13, IDT_ENTRY_INTR_GATE, 0x08); + idt_set_gate((void*)interrupt_stub_0x14, 0x14, IDT_ENTRY_INTR_GATE, 0x08); + idt_set_gate((void*)interrupt_stub_0x15, 0x15, IDT_ENTRY_INTR_GATE, 0x08); + idt_set_gate((void*)interrupt_stub_0x16, 0x16, IDT_ENTRY_INTR_GATE, 0x08); + idt_set_gate((void*)interrupt_stub_0x17, 0x17, IDT_ENTRY_INTR_GATE, 0x08); + idt_set_gate((void*)interrupt_stub_0x18, 0x18, IDT_ENTRY_INTR_GATE, 0x08); + idt_set_gate((void*)interrupt_stub_0x19, 0x19, IDT_ENTRY_INTR_GATE, 0x08); + idt_set_gate((void*)interrupt_stub_0x1A, 0x1A, IDT_ENTRY_INTR_GATE, 0x08); + idt_set_gate((void*)interrupt_stub_0x1B, 0x1B, IDT_ENTRY_INTR_GATE, 0x08); + idt_set_gate((void*)interrupt_stub_0x1C, 0x1C, IDT_ENTRY_INTR_GATE, 0x08); + idt_set_gate((void*)interrupt_stub_0x1D, 0x1D, IDT_ENTRY_INTR_GATE, 0x08); + idt_set_gate((void*)interrupt_stub_0x1E, 0x1E, IDT_ENTRY_INTR_GATE, 0x08); + idt_set_gate((void*)interrupt_stub_0x1F, 0x1F, IDT_ENTRY_INTR_GATE, 0x08); + + idt_load(&g_idt_register); + log(LOG_INFO, "Interrupts initialized"); +} + +cpu_state_T* interrupts_handle(cpu_state_T* state) { + log(LOG_DEBUG, "Interrupt"); + while(true)asm("hlt"); +} + diff --git a/kernel/src/platform/x86/gdt.asm b/kernel/src/platform/x86/gdt.asm new file mode 100644 index 0000000..8be7854 --- /dev/null +++ b/kernel/src/platform/x86/gdt.asm @@ -0,0 +1,4 @@ +gdt_load: + lgdt [rax] + ret +GLOBAL gdt_load \ No newline at end of file diff --git a/kernel/src/platform/x86/interrupts.asm b/kernel/src/platform/x86/interrupts.asm new file mode 100644 index 0000000..82fa5b5 --- /dev/null +++ b/kernel/src/platform/x86/interrupts.asm @@ -0,0 +1,93 @@ +extern interrupts_handle + +idt_load: + lidt [rax] + ret +GLOBAL idt_load + +interrupt_common_handler: + ; save CPU state + push rbp + push rdi + push rsi + push rdx + push rcx + push rbx + push rax + + ; save page map + mov rax, cr3 + push rax + + ; call handler + mov rdi, rsp + call interrupts_handle + mov rsp, rax + + ; load cpu_state + pop rax + mov cr3, rax + + ; restore CPU state + pop rax + pop rbx + pop rcx + pop rdx + pop rsi + pop rdi + pop rbp + + ; remove error_code and interrupt number from stack + add rsp, 16 + + iretq +GLOBAL interrupt_common_handler + +%macro interrupt_stub 1 + interrupt_stub_%1: + push qword 0 + push qword %1 + jmp interrupt_common_handler + GLOBAL interrupt_stub_%1 + %endmacro + +%macro interrupt_stub_error_code 1 + interrupt_stub_%1: + push qword %1 + jmp interrupt_common_handler + GLOBAL interrupt_stub_%1 + %endmacro + +; Exceptions +interrupt_stub 0x00 +interrupt_stub 0x01 +interrupt_stub 0x02 +interrupt_stub 0x03 +interrupt_stub 0x04 +interrupt_stub 0x05 +interrupt_stub 0x06 +interrupt_stub 0x07 +interrupt_stub_error_code 0x08 +interrupt_stub 0x09 +interrupt_stub_error_code 0x0A +interrupt_stub_error_code 0x0B +interrupt_stub_error_code 0x0C +interrupt_stub_error_code 0x0D +interrupt_stub_error_code 0x0E +interrupt_stub 0x0F +interrupt_stub 0x10 +interrupt_stub_error_code 0x11 +interrupt_stub 0x12 +interrupt_stub 0x13 +interrupt_stub 0x14 +interrupt_stub 0x15 +interrupt_stub 0x16 +interrupt_stub 0x17 +interrupt_stub 0x18 +interrupt_stub 0x19 +interrupt_stub 0x1A +interrupt_stub 0x1B +interrupt_stub 0x1C +interrupt_stub 0x1D +interrupt_stub 0x1E +interrupt_stub 0x1F \ No newline at end of file diff --git a/kernel/src/platform/x86/test.asm b/kernel/src/platform/x86/test.asm deleted file mode 100644 index 8ccdb20..0000000 --- a/kernel/src/platform/x86/test.asm +++ /dev/null @@ -1,5 +0,0 @@ -lol: - hlt - jmp lol - -GLOBAL lol diff --git a/kernel/src/utils/bitmap.c b/kernel/src/utils/bitmap.c new file mode 100644 index 0000000..76342b4 --- /dev/null +++ b/kernel/src/utils/bitmap.c @@ -0,0 +1,55 @@ +/* Copyright (C) Antifallobst + * + * NoxOS is free software: + * you can redistribute it and/or modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, either version 3 of the License, + * or (at your option) any later version. + * + * NoxOS is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with this program. + * If not, see . + */ + +#include "utils/bitmap.h" + +bitmap_T bitmap_init_from_buffer(void* buffer, uint32_t size) { + bitmap_T bitmap; + bitmap.buffer = buffer; + bitmap.size = size; + return bitmap; +} + +bitmap_T bitmap_init(uint32_t size) { + // TODO: implement bitmap malloc constructor +} + +void bitmap_destruct(bitmap_T* bitmap) { + +} + +bool bitmap_set(bitmap_T* bitmap, uint32_t index, bool value) { + if (index >= bitmap->size) { return false; } + + uint32_t index_byte = index / 8; + uint8_t index_bit = index % 8; + + bitmap->buffer[index_byte] &= ~(0b10000000 >> index_bit); + + if (value) { + bitmap->buffer[index_byte] |= (0b10000000 >> index_bit); + } + + return true; +} + +bool bitmap_get(bitmap_T* bitmap, uint32_t index) { + if (index >= bitmap->size) { return false; } + + uint32_t index_byte = index / 8; + uint8_t index_bit = index % 8; + + return (bitmap->buffer[index_byte] & (0b10000000 >> index_bit)) > 0; +} \ No newline at end of file diff --git a/kernel/src/utils/math.c b/kernel/src/utils/math.c new file mode 100644 index 0000000..8af2d8b --- /dev/null +++ b/kernel/src/utils/math.c @@ -0,0 +1,24 @@ +/* Copyright (C) Antifallobst + * + * NoxOS is free software: + * you can redistribute it and/or modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, either version 3 of the License, + * or (at your option) any later version. + * + * NoxOS is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with this program. + * If not, see . + */ + +#include "utils/math.h" + +uint64_t pow(uint64_t base, uint64_t exp) { + uint64_t n = 1; + for (uint64_t i = 0; i < exp; i++) { + n *= base; + } + return n; +} \ No newline at end of file diff --git a/limine.cfg b/limine.cfg index 9985f1b..6f5f22f 100644 --- a/limine.cfg +++ b/limine.cfg @@ -1,4 +1,4 @@ -TIMEOUT=5 +TIMEOUT=2 :NoxOS PROTOCOL=limine diff --git a/run.sh b/run.sh new file mode 100644 index 0000000..3194a8b --- /dev/null +++ b/run.sh @@ -0,0 +1,14 @@ +#!/bin/bash + +EMUFLAGS="-no-reboot -m 256M -cdrom build/noxos.iso -chardev stdio,id=log,logfile=noxos.log -serial chardev:log" + +emulate() { + qemu-system-x86_64 $EMUFLAGS +} + +# qemu will wait for gdb to connect, before booting +emulate_debug() { + qemu-system-x86_64 -s -S $EMUFLAGS +} + +emulate_debug \ No newline at end of file