From ea61229b18afcb68c21219a2b132a0f16211d3f5 Mon Sep 17 00:00:00 2001 From: Alex Date: Thu, 20 Oct 2022 01:07:39 +0300 Subject: [PATCH] Added better kernel arguments reading --- .../amd64/cpu/SymmetricMultiprocessing.cpp | 10 +- KConfig.cpp | 317 ++++++++++++++++++ Kernel.cpp | 20 +- include/kconfig.hpp | 16 + kernel.h | 2 + 5 files changed, 356 insertions(+), 9 deletions(-) create mode 100644 KConfig.cpp create mode 100644 include/kconfig.hpp diff --git a/Architecture/amd64/cpu/SymmetricMultiprocessing.cpp b/Architecture/amd64/cpu/SymmetricMultiprocessing.cpp index f0e981fb..07facd66 100644 --- a/Architecture/amd64/cpu/SymmetricMultiprocessing.cpp +++ b/Architecture/amd64/cpu/SymmetricMultiprocessing.cpp @@ -84,7 +84,15 @@ namespace SMP KPrint("VirtualBox detected, disabling SMP"); return; } - for (uint16_t i = 0; i < ((ACPI::MADT *)madt)->CPUCores + 1; i++) + + int Cores = ((ACPI::MADT *)madt)->CPUCores + 1; + + if (Config.Cores > ((ACPI::MADT *)madt)->CPUCores + 1) + KPrint("More cores requested than available. Using %d cores", ((ACPI::MADT *)madt)->CPUCores + 1); + else + Cores = Config.Cores; + + for (uint16_t i = 0; i < Cores; i++) { debug("Initializing CPU %d", i); if ((((APIC::APIC *)Interrupts::apic[0])->Read(APIC::APIC_ID) >> 24) != ((ACPI::MADT *)madt)->lapic[i]->ACPIProcessorId) diff --git a/KConfig.cpp b/KConfig.cpp new file mode 100644 index 00000000..0d99b76f --- /dev/null +++ b/KConfig.cpp @@ -0,0 +1,317 @@ +#include + +#include +#include +#include + +#include "kernel.h" + +// TODO: Implement proper fprintf +EXTERNC void fprintf(FILE *stream, const char *Format, ...) +{ + va_list args; + va_start(args, Format); + vprintf_(Format, args); + va_end(args); +} + +// TODO: Implement proper fputs +EXTERNC void fputs(const char *s, FILE *stream) { printf_("%s", s); } + +static struct cag_option ConfigOptions[] = { + {.identifier = 'a', + .access_letters = "aA", + .access_name = "alloc", + .value_name = "TYPE", + .description = "Memory allocator to use"}, + + {.identifier = 'c', + .access_letters = "cC", + .access_name = "cores", + .value_name = "VALUE", + .description = "Number of cores to use (0 = all; 1 is the first code, not 0)"}, + + {.identifier = 't', + .access_letters = "tT", + .access_name = "tasking", + .value_name = "MODE", + .description = "Tasking mode (multi, single)"}, + + {.identifier = 'h', + .access_letters = "h", + .access_name = "help", + .value_name = NULL, + .description = "Show help on screen and halt"}}; + +KernelConfig ParseConfig(char *Config) +{ + int argc = 0; + char **argv = nullptr; + + struct KernelConfig config = {Memory::MemoryAllocatorType::Pages, 0, 0}; + + if (Config == NULL) + { + KPrint("Warning! Empty kernel parameters! Using default values."); + return config; + } + else + goto Parse; + +Parse: +{ + // Based on https://stackoverflow.com/a/2568792 + char *DestinationBuffer; + char *TempScan; + + char **TempBuffer = (char **)kmalloc(sizeof(char *) * 10); + char **ArgvTemp = TempBuffer; + + while (isspace((unsigned char)*Config)) + Config++; + + Config = TempScan = strdup(Config); + + int Itr = 10; + while (1) + { + while (isspace((unsigned char)*TempScan)) + TempScan++; + if (*TempScan == '\0') + break; + + if (++argc >= Itr) + { + Itr += Itr / 2; + TempBuffer = (char **)krealloc(TempBuffer, Itr * sizeof(char *)); + ArgvTemp = TempBuffer + (argc - 1); + } + + *(ArgvTemp++) = DestinationBuffer = TempScan; + + while (1) + { + char TempChar0 = *(TempScan++); + switch (TempChar0) + { + case '\0': + goto Completed; + case ' ': + case '\t': + case '\n': + case '\f': + case '\r': + case '\v': + case '\b': + goto EmptyBufferAndComplete; + case '\\': + { + if ((*(DestinationBuffer++) = *(TempScan++)) == '\0') + goto Completed; + break; + } + case '\'': + { + while (1) + { + char TempChar1 = (*TempScan)++; + switch (TempChar1) + { + case '\0': + { + KPrint("\eFF2200Unterminated string constant in kernel parameters."); + CPU::Stop(); + break; + } + case '\'': + *DestinationBuffer = '\0'; + goto OutsideLoop; + case '\\': + TempChar1 = (*TempScan)++; + switch (TempChar1) + { + case '\0': + { + KPrint("\eFF2200Unterminated string constant in kernel parameters."); + CPU::Stop(); + break; + } + default: + *(DestinationBuffer++) = '\\'; + break; + + case '\\': + case '\'': + break; + } + [[fallthrough]]; + default: + *(DestinationBuffer++) = TempChar1; + break; + } + } + OutsideLoop: + break; + } + case '"': + { + while (1) + { + char TempChar2 = *(TempScan++); + switch (TempChar2) + { + case '\0': + { + KPrint("\eFF2200Unterminated string constant in kernel parameters."); + CPU::Stop(); + break; + } + case '"': + (*DestinationBuffer) = '\0'; + goto OutsideLoop2; + case '\\': + { + char TempChar3 = (*TempScan)++; + switch (TempChar3) + { + case 'a': + TempChar3 = '\a'; + break; + case 'b': + TempChar3 = '\b'; + break; + case 't': + TempChar3 = '\t'; + break; + case 'n': + TempChar3 = '\n'; + break; + case 'v': + TempChar3 = '\v'; + break; + case 'f': + TempChar3 = '\f'; + break; + case 'r': + TempChar3 = '\r'; + break; + case '\0': + { + KPrint("\eFF2200Unterminated string constant in kernel parameters."); + CPU::Stop(); + } + } + TempChar2 = TempChar3; + [[fallthrough]]; + } + default: + *(DestinationBuffer++) = TempChar2; + break; + } + OutsideLoop2: + break; + } + break; + } + default: + *(DestinationBuffer++) = TempChar0; + } + } + + EmptyBufferAndComplete: + *DestinationBuffer = '\0'; + } + + KPrint("Failed to parse kernel parameters string: %s", Config); + CPU::Stop(); + +Completed: + argv = TempBuffer; + if (argc == 0) + kfree((void *)Config); + + goto ParseSuccess; +} + +ParseSuccess: +{ +#ifdef DEBUG + for (int i = 0; i < argc; i++) + KPrint("\e22AAFFargv[%d] = %s", i, argv[i]); + KPrint("\e22AAFFargc = %d", argc); +#endif + char identifier; + const char *value; + cag_option_context context; + + cag_option_prepare(&context, ConfigOptions, CAG_ARRAY_SIZE(ConfigOptions), argc, argv); + while (cag_option_fetch(&context)) + { + identifier = cag_option_get(&context); + switch (identifier) + { + case 'a': + { + value = cag_option_get_value(&context); + if (strcmp(value, "xallocv1") == 0) + { + KPrint("\eAAFFAAUsing XallocV1 as memory allocator"); + config.AllocatorType = Memory::MemoryAllocatorType::XallocV1; + } + else if (strcmp(value, "liballoc11") == 0) + { + KPrint("\eAAFFAAUsing Liballoc11 as memory allocator"); + config.AllocatorType = Memory::MemoryAllocatorType::liballoc11; + } + else if (strcmp(value, "pages") == 0) + { + KPrint("\eAAFFAAUsing Pages as memory allocator"); + config.AllocatorType = Memory::MemoryAllocatorType::Pages; + } + else + { + KPrint("\eAAFFAAUnknown memory allocator: %s", value); + config.AllocatorType = Memory::MemoryAllocatorType::None; + } + break; + } + case 'c': + { + value = cag_option_get_value(&context); + KPrint("\eAAFFAAUsing %s cores", atoi(value) ? value : "all"); + config.Cores = atoi(value); + break; + } + case 't': + { + value = cag_option_get_value(&context); + if (strcmp(value, "multi") == 0) + { + KPrint("\eAAFFAAUsing Multi-Tasking Scheduler"); + config.SchedulerType = 1; + } + else if (strcmp(value, "single") == 0) + { + KPrint("\eAAFFAAUsing Mono-Tasking Scheduler"); + config.SchedulerType = 0; + } + else + { + KPrint("\eAAFFAAUnknown scheduler: %s", value); + config.SchedulerType = 0; + } + break; + } + case 'h': + { + KPrint("\n---------------------------------------------------------------------------\nUsage: kernel.fsys [OPTION]...\nKernel configuration."); + cag_option_print(ConfigOptions, CAG_ARRAY_SIZE(ConfigOptions), nullptr); + KPrint("\eFF2200System Halted."); + CPU::Stop(); + } + } + } + return config; +} + return config; +} diff --git a/Kernel.cpp b/Kernel.cpp index f08d7716..6c0d085d 100644 --- a/Kernel.cpp +++ b/Kernel.cpp @@ -3,12 +3,13 @@ #include #include #include -#include +#include #include #include #include #include #include +#include #include NEWLOCK(KernelLock); @@ -19,6 +20,7 @@ SymbolResolver::Symbols *KernelSymbolTable = nullptr; Power::Power *PowerManager = nullptr; PCI::PCI *PCIManager = nullptr; +KernelConfig Config; Time BootClock; // For the Display class. Printing on first buffer as default. @@ -39,8 +41,8 @@ EXTERNC void KPrint(const char *Format, ...) EXTERNC void Entry(BootInfo *Info) { - InitializeMemoryManagement(Info); trace("Hello, World!"); + InitializeMemoryManagement(Info); BootClock = ReadClock(); bInfo = (BootInfo *)KernelAllocator.RequestPages(TO_PAGES(sizeof(BootInfo))); memcpy(bInfo, Info, sizeof(BootInfo)); @@ -61,18 +63,20 @@ EXTERNC void Entry(BootInfo *Info) CPU::InitializeFeatures(); KPrint("Loading kernel symbols"); KernelSymbolTable = new SymbolResolver::Symbols((uint64_t)Info->Kernel.FileBase); + KPrint("Reading kernel parameters"); + Config = ParseConfig((char *)bInfo->Kernel.CommandLine); KPrint("Initializing Power Manager"); PowerManager = new Power::Power; KPrint("Initializing PCI Manager"); PCIManager = new PCI::PCI; - foreach (auto hdr in PCIManager->GetDevices()) + foreach (auto Device in PCIManager->GetDevices()) { KPrint("PCI: \e8888FF%s \eCCCCCC/ \e8888FF%s \eCCCCCC/ \e8888FF%s \eCCCCCC/ \e8888FF%s \eCCCCCC/ \e8888FF%s", - PCI::Descriptors::GetVendorName(hdr->VendorID), - PCI::Descriptors::GetDeviceName(hdr->VendorID, hdr->DeviceID), - PCI::Descriptors::DeviceClasses[hdr->Class], - PCI::Descriptors::GetSubclassName(hdr->Class, hdr->Subclass), - PCI::Descriptors::GetProgIFName(hdr->Class, hdr->Subclass, hdr->ProgIF)); + PCI::Descriptors::GetVendorName(Device->VendorID), + PCI::Descriptors::GetDeviceName(Device->VendorID, Device->DeviceID), + PCI::Descriptors::DeviceClasses[Device->Class], + PCI::Descriptors::GetSubclassName(Device->Class, Device->Subclass), + PCI::Descriptors::GetProgIFName(Device->Class, Device->Subclass, Device->ProgIF)); } KPrint("Enabling interrupts"); Interrupts::Enable(0); diff --git a/include/kconfig.hpp b/include/kconfig.hpp new file mode 100644 index 00000000..cbb2322a --- /dev/null +++ b/include/kconfig.hpp @@ -0,0 +1,16 @@ +#ifndef __FENNIX_KERNEL_KERNEL_CONFIG_H__ +#define __FENNIX_KERNEL_KERNEL_CONFIG_H__ + +#include +#include + +struct KernelConfig +{ + Memory::MemoryAllocatorType AllocatorType; + bool SchedulerType; + int Cores; +}; + +KernelConfig ParseConfig(char *Config); + +#endif // !__FENNIX_KERNEL_KERNEL_CONFIG_H__ diff --git a/kernel.h b/kernel.h index 6c014c21..c3451fef 100644 --- a/kernel.h +++ b/kernel.h @@ -7,6 +7,7 @@ #ifdef __cplusplus #include #include +#include #include #include #endif @@ -17,6 +18,7 @@ extern Video::Display *Display; extern SymbolResolver::Symbols *KernelSymbolTable; extern Power::Power *PowerManager; extern PCI::PCI *PCIManager; +extern KernelConfig Config; #endif EXTERNC void KPrint(const char *format, ...);