/*
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 "kernel.h"
#ifdef DEBUG
#include "tests/t.h"
#endif
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include "mapi.hpp"
#include "Fex.hpp"
using vfs::Node;
using vfs::NodeType;
Disk::Manager *DiskManager = nullptr;
Module::Module *ModuleManager = nullptr;
NetworkInterfaceManager::NetworkInterface *NIManager = nullptr;
int SpawnInit()
{
const char *envp[5] = {
"PATH=/bin:/usr/bin",
"TERM=tty",
"HOME=/root",
"USER=root",
nullptr};
const char *argv[4] = {
Config.InitPath,
"--init",
"--critical",
nullptr};
return Execute::Spawn(Config.InitPath, argv, envp,
nullptr,
Tasking::TaskCompatibility::Native,
true);
}
void CleanupProcessesThreadWrapper()
{
TaskManager->CleanupProcessesThread();
}
void KernelMainThread()
{
Tasking::TCB *clnThd =
TaskManager->CreateThread(thisProcess,
Tasking::IP(CleanupProcessesThreadWrapper));
clnThd->SetPriority(Tasking::Idle);
TaskManager->SetCleanupThread(clnThd);
thisThread->SetPriority(Tasking::Critical);
Tasking::TCB *blaThread = nullptr;
if (Config.BootAnimation)
{
blaThread =
TaskManager->CreateThread(thisProcess,
Tasking::IP(BootLogoAnimationThread));
blaThread->Rename("Logo Animation");
}
#ifdef DEBUG
// TaskManager->CreateThread(thisProcess, Tasking::IP(tasking_test_fb));
// TaskManager->CreateThread(thisProcess, Tasking::IP(tasking_test_mutex));
// ilp;
TaskManager->CreateThread(thisProcess, Tasking::IP(TaskMgr));
TaskManager->CreateThread(thisProcess, Tasking::IP(lsof));
TreeFS(fs->GetRootNode(), 0);
#endif
KPrint("Kernel Compiled at: %s %s with C++ Standard: %d",
__DATE__, __TIME__, CPP_LANGUAGE_STANDARD);
KPrint("C++ Language Version (__cplusplus): %ld", __cplusplus);
if (IsVirtualizedEnvironment())
KPrint("Running in a virtualized environment");
KPrint("Initializing Disk Manager...");
DiskManager = new Disk::Manager;
KPrint("Loading Modules...");
ModuleManager = new Module::Module;
ModuleManager->LoadModules();
KPrint("Fetching Disks...");
if (ModuleManager->GetModules().size() > 0)
{
foreach (auto mod in ModuleManager->GetModules())
if (((FexExtended *)mod.ExtendedHeaderAddress)->Module.Type == FexModuleType::FexModuleType_Storage)
DiskManager->FetchDisks(mod.modUniqueID);
}
else
KPrint("\eE85230No disk modules found! Cannot fetch disks!");
KPrint("Initializing Network Interface Manager...");
NIManager = new NetworkInterfaceManager::NetworkInterface;
KPrint("Starting Network Interface Manager...");
NIManager->StartService();
KPrint("Setting up userspace");
int ExitCode = -1;
Tasking::TCB *initThread = nullptr;
int tid = SpawnInit();
if (tid < 0)
{
KPrint("\eE85230Failed to start %s! Code: %d", Config.InitPath, tid);
goto Exit;
}
KPrint("Waiting for \e22AAFF%s\eCCCCCC to start...", Config.InitPath);
thisThread->SetPriority(Tasking::Idle);
initThread = TaskManager->GetThreadByID(tid);
initThread->KeepInMemory = true;
TaskManager->WaitForThread(initThread);
ExitCode = initThread->GetExitCode();
Exit:
if (ExitCode == 0)
{
KPrint("\eFF7900%s process exited with code %d and it didn't invoked the shutdown function.",
Config.InitPath, ExitCode);
KPrint("System Halted");
CPU::Halt(true);
}
KPrint("\eE85230Userspace process exited with code %d (%#x)",
ExitCode, ExitCode < 0 ? -ExitCode : ExitCode);
KPrint("Dropping to kernel shell...");
TaskManager->Sleep(1000);
TaskManager->WaitForThread(blaThread);
TaskManager->CreateThread(thisProcess,
Tasking::IP(KShellThread))
->Rename("Kernel Shell");
if (initThread)
initThread->KeepInMemory = false;
CPU::Halt(true);
}
NewLock(ShutdownLock);
void __no_stack_protector KernelShutdownThread(bool Reboot)
{
SmartLock(ShutdownLock);
debug("KernelShutdownThread(%s)", Reboot ? "true" : "false");
if (Config.BootAnimation && TaskManager)
{
Tasking::TCB *elaThread =
TaskManager->CreateThread(thisProcess,
Tasking::IP(ExitLogoAnimationThread));
elaThread->Rename("Logo Animation");
TaskManager->WaitForThread(elaThread);
}
BeforeShutdown(Reboot);
trace("%s...", Reboot ? "Rebooting" : "Shutting down");
if (Reboot)
PowerManager->Reboot();
else
PowerManager->Shutdown();
CPU::Stop();
}
void KST_Reboot() { KernelShutdownThread(true); }
void KST_Shutdown() { KernelShutdownThread(false); }