/*
This file is part of Fennix Kernel.
Fennix Kernel 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.
Fennix Kernel 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 Fennix Kernel. If not, see .
*/
#include
#include
#include
#include
#include
#include "kernel.h"
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 = 'p',
.access_letters = "pP",
.access_name = "ioapicirq",
.value_name = "VALUE",
.description = "Which core will be used for I/O APIC interrupts"},
{.identifier = 't',
.access_letters = "tT",
.access_name = "tasking",
.value_name = "MODE",
.description = "Tasking mode (multi, single)"},
{.identifier = 'd',
.access_letters = "dD",
.access_name = "drvdir",
.value_name = "PATH",
.description = "Directory to load drivers from"},
{.identifier = 'i',
.access_letters = "iI",
.access_name = "init",
.value_name = "PATH",
.description = "Path to init program"},
{.identifier = 'y',
.access_letters = "yY",
.access_name = "linux",
.value_name = "BOOL",
.description = "Use Linux syscalls by default"},
{.identifier = 'l',
.access_letters = NULL,
.access_name = "udl",
.value_name = "BOOL",
.description = "Unlock the deadlock after 10 retries"},
{.identifier = 'o',
.access_letters = NULL,
.access_name = "ioc",
.value_name = "BOOL",
.description = "Enable Interrupts On Crash. If enabled, the navigation keys will be enabled on crash"},
{.identifier = 's',
.access_letters = NULL,
.access_name = "simd",
.value_name = "BOOL",
.description = "Enable SIMD instructions"},
{.identifier = 'b',
.access_letters = NULL,
.access_name = "quiet",
.value_name = "BOOL",
.description = "Enable quiet boot"},
{.identifier = 'h',
.access_letters = "h",
.access_name = "help",
.value_name = NULL,
.description = "Show help on screen and halt"}};
void ParseConfig(char *ConfigString, KernelConfig *ModConfig)
{
if (ConfigString == NULL ||
strlen(ConfigString) == 0)
{
KPrint("Empty kernel parameters!");
return;
}
if (ModConfig == NULL)
{
KPrint("ModConfig is NULL!");
return;
}
KPrint("Kernel parameters: %s", ConfigString);
debug("Kernel parameters: %s", ConfigString);
char *argv[32];
int argc = 0;
/* Not sure if the quotes are being parsed correctly. */
targp_parse(ConfigString, argv, &argc);
#ifdef DEBUG
for (int i = 0; i < argc; i++)
debug("argv[%d] = %s", i, argv[i]);
debug("argc = %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("Using XallocV1 as memory allocator");
ModConfig->AllocatorType = Memory::XallocV1;
}
else if (strcmp(value, "xallocv2") == 0)
{
KPrint("Using XallocV2 as memory allocator");
ModConfig->AllocatorType = Memory::XallocV2;
}
else if (strcmp(value, "liballoc11") == 0)
{
KPrint("Using Liballoc11 as memory allocator");
ModConfig->AllocatorType = Memory::liballoc11;
}
else if (strcmp(value, "pages") == 0)
{
KPrint("Using Pages as memory allocator");
ModConfig->AllocatorType = Memory::Pages;
}
break;
}
case 'c':
{
value = cag_option_get_value(&context);
KPrint("Using %s cores", atoi(value) ? value : "all");
ModConfig->Cores = atoi(value);
break;
}
case 'p':
{
value = cag_option_get_value(&context);
KPrint("Redirecting I/O APIC interrupts to %s%s",
atoi(value) ? "core " : "", atoi(value) ? value : "BSP");
ModConfig->IOAPICInterruptCore = atoi(value);
break;
}
case 't':
{
value = cag_option_get_value(&context);
if (strcmp(value, "multi") == 0)
{
KPrint("Using Multi-Tasking Scheduler");
ModConfig->SchedulerType = Multi;
}
else if (strcmp(value, "single") == 0)
{
KPrint("Using Single-Tasking Scheduler");
ModConfig->SchedulerType = Mono;
}
else
{
KPrint("Unknown scheduler: %s", value);
ModConfig->SchedulerType = Multi;
}
break;
}
case 'd':
{
value = cag_option_get_value(&context);
strncpy(ModConfig->DriverDirectory, value, strlen(value));
KPrint("Using %s as module directory", value);
break;
}
case 'i':
{
value = cag_option_get_value(&context);
strncpy(ModConfig->InitPath, value, strlen(value));
KPrint("Using %s as init program", value);
break;
}
case 'y':
{
value = cag_option_get_value(&context);
strcmp(value, "true") == 0
? ModConfig->UseLinuxSyscalls = true
: ModConfig->UseLinuxSyscalls = false;
KPrint("Use Linux syscalls by default: %s", value);
break;
}
case 'o':
{
value = cag_option_get_value(&context);
strcmp(value, "true") == 0
? ModConfig->InterruptsOnCrash = true
: ModConfig->InterruptsOnCrash = false;
KPrint("Interrupts on crash: %s", value);
break;
}
case 'l':
{
value = cag_option_get_value(&context);
strcmp(value, "true") == 0
? ModConfig->UnlockDeadLock = true
: ModConfig->UnlockDeadLock = false;
KPrint("Unlocking the deadlock after 10 retries");
break;
}
case 's':
{
value = cag_option_get_value(&context);
strcmp(value, "true") == 0 ? ModConfig->SIMD = true
: ModConfig->SIMD = false;
KPrint("Single Instruction, Multiple Data (SIMD): %s", value);
break;
}
case 'b':
{
value = cag_option_get_value(&context);
strcmp(value, "true") == 0 ? ModConfig->Quiet = true
: ModConfig->Quiet = false;
KPrint("Quiet boot: %s", value);
break;
}
case 'h':
{
KPrint("\n---------------------------------------------------------------------------\nUsage: fennix.elf [OPTION]...\nKernel configuration.");
cag_option_print(ConfigOptions, CAG_ARRAY_SIZE(ConfigOptions),
nullptr);
KPrint("\x1b[1;31;41mSystem Halted.");
CPU::Stop();
}
default:
{
KPrint("\x1b[31mUnknown option: %c", identifier);
break;
}
}
}
debug("Config loaded");
}