diff --git a/CMakeLists.txt b/CMakeLists.txt index 97c33c0..4cf1f5c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -39,7 +39,6 @@ SET(src_files ${CMAKE_SOURCE_DIR}/src/drivers/devices/input/keyboard.cpp ${CMAKE_SOURCE_DIR}/src/drivers/devices/io/apic.cpp ${CMAKE_SOURCE_DIR}/src/drivers/devices/storage/ata.cpp - ${CMAKE_SOURCE_DIR}/src/global/core-att.s ) SET(lib_files @@ -57,6 +56,7 @@ SET(src_no_sse ) SET(src_as + ${CMAKE_SOURCE_DIR}/src/global/core-att.s ) SET(src_preamble @@ -78,6 +78,6 @@ set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/bin) add_executable(kernel) -target_sources(kernel PUBLIC ${src_preamble} PUBLIC ${src_files} PUBLIC ${src_no_sse} PUBLIC ${lib_files} PUBLIC ${src_as} PUBLIC ${src_epilogue}) +target_sources(kernel PUBLIC ${src_preamble} PUBLIC ${src_files} PUBLIC ${src_no_sse} PUBLIC ${lib_files} PUBLIC ${src_epilogue}) target_compile_options(kernel PRIVATE -ffreestanding -O0 -Wall -Wextra -Wall -Werror -fPIC -fno-exceptions -fno-omit-frame-pointer -mno-red-zone -fno-stack-protector $<$:-fno-rtti> -ggdb3) target_link_options(kernel PRIVATE -T ${CMAKE_SOURCE_DIR}/linker.ld -ffreestanding -O2 -nostdlib -nostartfiles -lgcc) diff --git a/README.md b/README.md index 5280173..435f7a8 100644 --- a/README.md +++ b/README.md @@ -38,10 +38,55 @@ It will compile the kernel, and create an OS image with `mkbootimg`. ### Linux The system for linux is a lot easier, but you *do* need an x86_64-elf-gcc cross compiler. You can get one from the AUR on Arch-based distros (like Manjaro), or make one yourself using [the OSDev Wiki guide](https://wiki.osdev.org/GCC_Cross-Compiler) -Simply run the `init.sh` to generate a makefile, then `make` to create the image file. + +On the Chroma side, Simply run the `init.sh` to generate a makefile, then `make` to create the image file. The generated IMG works in QEMU, or on a physical test device (unlike a lot of other hobby OSes!) This means you can use any emulator or hypervisor to run it. +## Project structure + +The repository has a lot of files and folders after setting up a workspace. This is a guide to all the files and folders. + +``` + + File Location | Description +/ +├── bin/ | Binary Output folder +│ └── img/ | Image Output folder. +│ └── chroma.img | Disk Image file, as an alternative to ISO below. +│ | +├── inc/ | Global header include folder. +│ ├── driver/ | Header files for the default driver implementations. +│ ├── editor/ | Header files for the builtin editor and debugger. +│ ├── kernel/ | Header files for the Chroma kernel itself. +│ └── lainlib/ | Header files for the Lainlib standard library. +│ | +├── src/ | Source files. +│ ├── assets/ | Assorted linkable files that will be bundled with the built image. +│ ├── drivers/ | Handling of the default driver implementations. +│ ├── editor/ | Handling of the builtin editor and debugger. +│ ├── global/ | Various files used in global objects (ie. the C RunTime, new core bootstrapping, etc) +│ ├── lainlib/ | Handling of the Lainlib standard library. +│ ├── system/ | Core Kernel files. +│ ├── video/ | Writing and drawing on the screen. +│ └── kernel.cpp | The primary kernel entry point. +│ | +├── tools/ | Auxiliary tools used in the buildsystem. +│ └── mkbootimg/ | Creates a bootable .img file based on the chroma.json configuration file below. +│ | +├── .gitignore | Git Repository Ignored Files +├── build_and_run.sh | shell script that builds the img file and runs it using run.sh below. +├── choma.bxrc | bxrc (Bochs Runtime Config) file for the Bochs emulator and debugger. +├── chroma.iso | ISO disc image file that can be loaded into a VM or onto a boot disk. +├── chroma.json | MkBootImg configuration file +├── CMakeLists.txt | Buildscript and CMake project configuration file. +├── LICENSE | Chroma's License. MIT License. +├── linker.ld | GCC linkerscript that places files and addresses at their expected positions. +├── post.sh | Postprocessing script; Generates the final img file, and attempts to update a VirtualBox configuration named "Chroma" to run this new file instead. +├── pre.sh | First-time setup script; generates the font file binary and generates the CMake buildscripts. +├── README.md | This file. +└── run.bat | Attempts to start a Virtualbox VM named "chroma". +``` \ No newline at end of file diff --git a/inc/kernel/system/acpi/madt.h b/inc/kernel/system/acpi/madt.h index 82cd7f9..f94a7a1 100644 --- a/inc/kernel/system/acpi/madt.h +++ b/inc/kernel/system/acpi/madt.h @@ -90,7 +90,7 @@ namespace ACPI { MADT(); void LogDump(); - void Initialize(); + void Init(); // Get the byte of the end of the table. size_t GetEndOfTable(); // Get all of the entries in the table, as an array. diff --git a/inc/kernel/system/acpi/rsdt.h b/inc/kernel/system/acpi/rsdt.h index a4cc61e..33c0374 100644 --- a/inc/kernel/system/acpi/rsdt.h +++ b/inc/kernel/system/acpi/rsdt.h @@ -47,7 +47,7 @@ namespace ACPI { // RSDP Entries themselves. struct RSDT { ACPIHeader Header; - uint32_t* OtherSDTs; + uint32_t OtherSDTs[]; } __attribute__((packed)); RSDP(); diff --git a/src/drivers/devices/io/apic.cpp b/src/drivers/devices/io/apic.cpp index 203f3a1..7882615 100644 --- a/src/drivers/devices/io/apic.cpp +++ b/src/drivers/devices/io/apic.cpp @@ -59,14 +59,14 @@ bool APIC::IsReady() { } void APIC::Init() { - SerialPrintf("[ACPI] Enabling APICs..."); + SerialPrintf("[ ACPI] Enabling APICs...\r\n"); Address = (void*) ACPI::MADT::instance->LocalAPICBase; // TODO: Check whether the identity mapping covers this address if (Address == nullptr) { - SerialPrintf("[ACPI] Unable to locate APICs."); + SerialPrintf("[ ACPI] Unable to locate APICs.\r\n"); for (;;) { } } @@ -78,9 +78,9 @@ void APIC::Init() { WritePort(0x21, 0xFF, 1); WritePort(0xA1, 0xFF, 1); - SerialPrintf("[ACPI] Enabling Global APIC.."); + SerialPrintf("[ ACPI] Enabling Global APIC..\r\n"); IOAPICs = ACPI::MADT::instance->GetIOApicEntries(); - SerialPrintf("[ACPI] Enabling Interrupt Source Overrides.."); + SerialPrintf("[ ACPI] Enabling Interrupt Source Overrides..\r\n"); ISOs = ACPI::MADT::instance->GetISOEntries(); Ready = true; diff --git a/src/global/core-att.s b/src/global/core-att.s index 0e6c74e..575de0e 100644 --- a/src/global/core-att.s +++ b/src/global/core-att.s @@ -18,7 +18,9 @@ .extern initcpu .extern coreidt -.extern CoreGDT + +.extern ProtectedGDT +.extern LongGDT # 16-bit startup. # Initialize registers. @@ -35,9 +37,9 @@ startCore: mov %ax, %fs mov %ax, %gs mov %ax, %ss - - lgdtl gdt_protected - +.code64 + lgdt ProtectedGDT +.code16 mov %cr0, %eax or $0x1, %ax mov %eax, %cr0 @@ -74,8 +76,9 @@ startCore32: mov %cr0, %eax or $2147483648, %eax # 1 << 31 mov %eax, %cr0 - - lgdt gdt_long +.code64 + lgdt LongGDT +.code32 ljmp $0x8, $startCore64 # Long mode setup. @@ -95,7 +98,7 @@ startCore64: mov %ax, %ds mov %ax, %gs - lgdt CoreGDT + lgdt LongGDT lidt coreidt mov $0x0, %rbp diff --git a/src/kernel.cpp b/src/kernel.cpp index 34d74be..f78a90f 100644 --- a/src/kernel.cpp +++ b/src/kernel.cpp @@ -2,6 +2,9 @@ #include #include #include +#include "kernel/system/acpi/rsdt.h" +#include "kernel/system/acpi/madt.h" +#include "driver/io/apic.h" /************************ *** Team Kitty, 2020 *** @@ -21,7 +24,6 @@ static bool KernelLoaded = false; address_space_t KernelAddressSpace; - size_t KernelAddr = (size_t) &LoadAddr; size_t KernelEnd = (size_t) &end; @@ -42,7 +44,7 @@ char* InternalBuffer; * This is a temporary measure to experiment with the Editor system. */ -extern "C" int Main(void) { +extern "C" [[noreturn]] int Main(void) { KernelAddressSpace.Lock.NextTicket = 0; KernelAddressSpace.Lock.NowServing = 0; KernelAddressSpace.PML4 = nullptr; @@ -86,13 +88,15 @@ extern "C" int Main(void) { SetForegroundColor(0x00FFFFFF); + ACPI::RSDP::instance->Init(0); + ACPI::MADT::instance->Init(); + Device::APIC::driver->Init(); + CharPrinterCallbackID = SetupKBCallback(&PrintPressedChar); InternalBufferID = SetupKBCallback(&TrackInternalBuffer); for (;;) { } - - return 0; } extern "C" void PrintPressedChar(KeyboardData data) { diff --git a/src/system/acpi/MADT.cpp b/src/system/acpi/MADT.cpp index 2955a61..402327b 100644 --- a/src/system/acpi/MADT.cpp +++ b/src/system/acpi/MADT.cpp @@ -18,8 +18,8 @@ size_t MADT::GetEndOfTable() { return ((size_t) &Header->Header) + Header->Header.Length; } -void MADT::Initialize() { - SerialPrintf("[ACPI] Loading Multiple APIC Descriptor Tables.."); +void MADT::Init() { + SerialPrintf("[ ACPI] Loading Multiple APIC Descriptor Tables..\r\n"); Address = ACPI::RSDP::instance->FindEntry("APIC"); Header = reinterpret_cast(Address); diff --git a/src/system/acpi/RSDP.cpp b/src/system/acpi/RSDP.cpp index 1fbf3d5..b295372 100644 --- a/src/system/acpi/RSDP.cpp +++ b/src/system/acpi/RSDP.cpp @@ -61,23 +61,28 @@ void* RSDP::GetFACP(RSDT* Root) { void RSDP::Init(size_t RSDP) { UNUSED(RSDP); - SerialPrintf("[ACPI] Loading ACPI subsystem.."); + SerialPrintf("[ ACPI] Loading ACPI subsystem..\r\n"); Descriptor = (DescriptorV2*) GetRSDP(); Table = (RSDT *) TO_DIRECT(Descriptor->Header.RSDT); - SerialPrintf("[RSDP] Dumping RSDT.."); - auto* table = reinterpret_cast(TO_DIRECT(Descriptor->Header.RSDT)); - size_t entries = (table->Header.Length - sizeof(table->Header)) / 4; - + SerialPrintf("[ RSDP] Dumping RSDT. Table at 0x%p..\r\n", (size_t) Table); + size_t entries = (Table->Header.Length - sizeof(Table->Header)) / 4; + SerialPrintf("[ RSDP] Found %u entries.\r\n", entries); // For each entry: if valid, search for the specified name. for (size_t i = 0; i < entries; i++) { - if (table->OtherSDTs[i] == 0x0) + if (Table->OtherSDTs[i] == 0x0) continue; - ACPIHeader* header = reinterpret_cast(table->OtherSDTs[i]); - SerialPrintf("[RSDP] Entry %d: Signature %.4s, OEM %.6s\n", i, header->Signature, header->OEMID); + ACPIHeader* header = (ACPIHeader*) ((size_t) 0 + (uint32_t) Table->OtherSDTs[i]); + char signature[5]; + memcpy(signature, header->Signature, 4); + signature[4] = '\0'; + char oem[7]; + memcpy(oem, header->OEMID, 6); + oem[6] = '\0'; + SerialPrintf("[ RSDP] Entry %d: Signature %s, OEM %s\n", i, signature, oem); } } diff --git a/src/system/core.cpp b/src/system/core.cpp index 34785cd..5b69b63 100644 --- a/src/system/core.cpp +++ b/src/system/core.cpp @@ -17,7 +17,7 @@ Core Core::Processors[Constants::Core::MAX_CORES]; TSS64 Tasks[Constants::Core::MAX_CORES]; ACPI::MADT::LAPICEntry* LAPICs[Constants::Core::MAX_CORES]; -extern "C" void initcpu() { +extern "C" [[noreturn]] void initcpu() { // Init APIC WriteModelSpecificRegister(0x1B, (ReadModelSpecificRegister(0x1B) | 0x800) & ~(1 << 10)); Device::APIC::driver->Enable(); @@ -39,9 +39,9 @@ Core::Core(size_t APIC, size_t ID) { Bootstrap(); SetupData(ID); - Device::APIC::driver->InitializeCore(APIC, CORE_BOOTSTRAP); + Device::APIC::driver->InitializeCore(APIC, reinterpret_cast(initcpu)); - while (Ready != true) { + while (!Ready) { __asm__ ("nop"); } @@ -94,12 +94,7 @@ void Core::Init() { } void Core::Bootstrap() { - size_t coreStarterLen = endCore - startCore; - - for (size_t i = 0; i < coreStarterLen + 2; i += PAGE_SIZE) - MapVirtualPage(AddressSpace, CORE_BOOTSTRAP + i, CORE_BOOTSTRAP + i, 0); - - memcpy((void*) CORE_BOOTSTRAP, &startCore, coreStarterLen); + // TODO } void Core::SetupData(size_t Core) { diff --git a/src/system/cpu.cpp b/src/system/cpu.cpp index e9ba325..bb926b9 100644 --- a/src/system/cpu.cpp +++ b/src/system/cpu.cpp @@ -73,48 +73,11 @@ void PrepareCPU() { SetupInitialGDT(); SetupIDT(); - //SetupExtensions(); InitInterrupts(); - } -/*void SetupExtensions() { - - // Enable SSE - size_t CR0 = ReadControlRegister(0); - - CR0 &= ~(1 << 2); - CR0 |= 1; - - WriteControlRegister(0, CR0); - - // Enable OSXSAVE and gang - size_t CR4 = ReadControlRegister(4); - CR4 |= (1 << 9); - CR4 |= (1 << 10); - CR4 |= (1 << 18); - - WriteControlRegister(4, CR4); - - // Enable AVX (and AVX-512 in future) - - CR0 = ReadExtendedControlRegister(0); - SerialPrintf("XCR0 is currently %x.\n", CR0); - CR0 |= (1 << 0); - CR0 |= (1 << 1); - CR0 |= (1 << 2); - - CR0 |= (1 << 5); - CR0 |= (1 << 6); - CR0 |= (1 << 7); - - SerialPrintf("About to write xcr0: %x\n", CR0); - WriteExtendedControlRegister(0, CR0); -} -*/ - void SetupInitialGDT() { size_t TSSBase = (uint64_t) (&TSSEntries); diff --git a/src/system/interrupts.cpp b/src/system/interrupts.cpp index 126fe3c..60baee6 100644 --- a/src/system/interrupts.cpp +++ b/src/system/interrupts.cpp @@ -368,7 +368,7 @@ __attribute__((interrupt)) void ISR14Handler(INTERRUPT_FRAME* Frame, size_t Erro SerialPrintf("[FAULT] } at address\n[FAULT] 0x%p\r\n\n", ReadControlRegister(2)); - Core::GetCurrent()->StackTrace(6); + Core::GetCurrent()->StackTrace(10); ISR_Error_Common(Frame, ErrorCode, 14); // Page Fault } diff --git a/src/system/memory/abstract_allocator.cpp b/src/system/memory/abstract_allocator.cpp index 9dd02a2..739059b 100644 --- a/src/system/memory/abstract_allocator.cpp +++ b/src/system/memory/abstract_allocator.cpp @@ -1,6 +1,4 @@ #include -#include -#include #include #include diff --git a/src/system/memory/liballoc.cpp b/src/system/memory/liballoc.cpp index d5cb361..59f7115 100644 --- a/src/system/memory/liballoc.cpp +++ b/src/system/memory/liballoc.cpp @@ -69,29 +69,29 @@ static int liballoc_free(void* ptr, size_t count) { /** This macro will conveniently align our pointer upwards */ #define ALIGN(ptr) \ - if ( ALIGNMENT > 1 ) \ - { \ - uintptr_t diff; \ - ptr = (void*)((uintptr_t)ptr + ALIGN_INFO); \ - diff = (uintptr_t)ptr & (ALIGNMENT-1); \ - if ( diff != 0 ) \ - { \ - diff = ALIGNMENT - diff; \ - ptr = (void*)((uintptr_t)ptr + diff); \ - } \ - *((ALIGN_TYPE*)((uintptr_t)ptr - ALIGN_INFO)) = \ - diff + ALIGN_INFO; \ + if ( ALIGNMENT > 1 ) \ + { \ + uintptr_t ldiff; \ + ptr = (void*)((uintptr_t)ptr + ALIGN_INFO); \ + ldiff = (uintptr_t)ptr & (ALIGNMENT-1); \ + if ( diff != 0 ) \ + { \ + ldiff = ALIGNMENT - ldiff; \ + ptr = (void*)((uintptr_t)ptr + ldiff); \ + } \ + *((ALIGN_TYPE*)((uintptr_t)ptr - ALIGN_INFO)) = \ + ldiff + ALIGN_INFO; \ } -#define UNALIGN(ptr) \ - if ( ALIGNMENT > 1 ) \ - { \ - uintptr_t diff = *((ALIGN_TYPE*)((uintptr_t)ptr - ALIGN_INFO)); \ - if ( diff < (ALIGNMENT + ALIGN_INFO) ) \ - { \ - ptr = (void*)((uintptr_t)ptr - diff); \ - } \ +#define UNALIGN(ptr) \ + if ( ALIGNMENT > 1 ) \ + { \ + uintptr_t diff = *((ALIGN_TYPE*)((uintptr_t)ptr - ALIGN_INFO)); \ + if ( diff < (ALIGNMENT + ALIGN_INFO) ) \ + { \ + ptr = (void*)((uintptr_t)ptr - diff); \ + } \ } diff --git a/src/system/memory/paging.cpp b/src/system/memory/paging.cpp index 031d17e..fb87290 100644 --- a/src/system/memory/paging.cpp +++ b/src/system/memory/paging.cpp @@ -58,6 +58,16 @@ void InitPaging() { MapVirtualPageNoDirect(&KernelAddressSpace, Addr, TO_DIRECT(Addr), DEFAULT_PAGE_FLAGS); } + SerialPrintf("[ Mem] Identity mapping the entire BIOS memory map.\r\n"); + for (MMapEnt* MapEntry = &bootldr.mmap; (size_t) MapEntry < (size_t) &bootldr + bootldr.size; MapEntry++) { + size_t entry_from = MMapEnt_Ptr(MapEntry); + size_t entry_to = MMapEnt_Ptr(MapEntry) + MMapEnt_Size(MapEntry); + for (size_t i = entry_from; i < entry_to; i += PAGE_SIZE) { + MapVirtualPageNoDirect(&KernelAddressSpace, i, i, DEFAULT_PAGE_FLAGS); + MapVirtualPageNoDirect(&KernelAddressSpace, i, TO_DIRECT(i), DEFAULT_PAGE_FLAGS); + } + } + SerialPrintf("[ Mem] Mapping 0x%x bytes of bootloader structure, starting at 0x%p\r\n", bootldr.size, BootldrAddress); for (size_t i = BootldrAddress; i < (BootldrAddress + bootldr.size); i += PAGE_SIZE) diff --git a/src/system/memory/physmem.c b/src/system/memory/physmem.c index 9b020ac..4a6cbf5 100644 --- a/src/system/memory/physmem.c +++ b/src/system/memory/physmem.c @@ -175,7 +175,7 @@ void InitMemoryManager() { MemoryPages = FreeMemorySize / PAGE_SIZE; - SerialPrintf("[ Mem] %u MB of memory detected.\r\n", (FreeMemorySize / 1024) / 1024); + SerialPrintf("[ Mem] %u MB of usable memory detected, %u MB total.\r\n", (FreeMemorySize / 1024) / 1024, (FullMemorySize / 1024) / 1024); }