Boot screen & change shutting down/rebooting procedure

This commit is contained in:
Alex 2023-03-25 12:05:33 +02:00
parent cef9d89965
commit 028115a1b0
Signed by untrusted user who does not match committer: enderice2
GPG Key ID: EACC3AD603BAB4DD
9 changed files with 322 additions and 53 deletions

View File

@ -61,15 +61,10 @@ namespace ACPI
}
else if (Event & ACPI_POWER_BUTTON)
{
BeforeShutdown();
this->Shutdown();
Time::Clock tm = Time::ReadClock();
while (tm.Second == Time::ReadClock().Second)
;
outw(0xB004, 0x2000);
outw(0x604, 0x2000);
outw(0x4004, 0x3400);
CPU::Stop();
if (TaskManager)
TaskManager->CreateThread(TaskManager->GetCurrentProcess(), (Tasking::IP)KST_Shutdown);
else
KernelShutdownThread(false);
}
else if (Event & ACPI_SLEEP_BUTTON)
{

View File

@ -14,8 +14,6 @@ namespace Power
{
void Power::Reboot()
{
BeforeShutdown();
if (((ACPI::ACPI *)this->acpi)->FADT)
if (((ACPI::DSDT *)this->dsdt)->ACPIShutdownSupported)
((ACPI::DSDT *)this->dsdt)->Reboot();
@ -44,8 +42,6 @@ namespace Power
void Power::Shutdown()
{
BeforeShutdown();
if (((ACPI::ACPI *)this->acpi)->FADT)
if (((ACPI::DSDT *)this->dsdt)->ACPIShutdownSupported)
((ACPI::DSDT *)this->dsdt)->Shutdown();

View File

@ -636,6 +636,7 @@ namespace GraphicalUserInterface
GUI::~GUI()
{
debug("Destructor called");
delete this->mem, this->mem = nullptr;
delete this->BackBuffer, this->BackBuffer = nullptr;
delete this->DesktopBuffer, this->DesktopBuffer = nullptr;

View File

@ -8,6 +8,14 @@
#include <exec.hpp>
#include <cwalk.h>
#define STB_IMAGE_IMPLEMENTATION
#define STBI_NO_STDIO
#define STBI_NO_LINEAR
#define STBI_NO_THREAD_LOCALS
#define STBI_NO_HDR
#define STBI_ONLY_TGA
#include <stb/image.h>
#include "DAPI.hpp"
#include "Fex.hpp"
@ -24,6 +32,8 @@ VirtualFileSystem::Node *DevFS = nullptr;
VirtualFileSystem::Node *MntFS = nullptr;
VirtualFileSystem::Node *ProcFS = nullptr;
NewLock(ShutdownLock);
#ifdef DEBUG
void TreeFS(Node *node, int Depth)
{
@ -31,7 +41,8 @@ void TreeFS(Node *node, int Depth)
foreach (auto Chld in node->Children)
{
printf("%*c %s\eFFFFFF\n", Depth, ' ', Chld->Name);
Display->SetBuffer(0);
if (!Config.BootAnimation)
Display->SetBuffer(0);
TaskManager->Sleep(100);
TreeFS(Chld, Depth + 1);
}
@ -102,7 +113,8 @@ void TaskMgr()
if (sanity > 1000)
sanity = 0;
Display->SetBufferCursor(0, tmpX, tmpY);
Display->SetBuffer(0);
if (!Config.BootAnimation)
Display->SetBuffer(0);
CPU::Interrupts(CPU::Enable);
}
}
@ -130,10 +142,185 @@ Execute::SpawnData SpawnInit()
return Execute::Spawn(Config.InitPath, argv, envp);
}
/* Files: 0.tga 1.tga ... 40.tga */
void *Frames[41];
uint32_t FrameSizes[41];
uint32_t FrameCount = 1;
void BootLogoAnimationThread()
{
char BootAnimPath[16];
while (FrameCount < 41)
{
sprintf(BootAnimPath, "%d.tga", FrameCount);
std::shared_ptr<File> ba = bootanim_vfs->Open(BootAnimPath);
if (ba->Status != FileStatus::OK)
{
bootanim_vfs->Close(ba);
debug("Failed to load boot animation frame %s", BootAnimPath);
break;
}
FrameSizes[FrameCount] = ba->node->Length;
Frames[FrameCount] = new uint8_t[ba->node->Length];
memcpy((void *)Frames[FrameCount], (void *)ba->node->Address, ba->node->Length);
bootanim_vfs->Close(ba);
FrameCount++;
}
uint32_t DispX = Display->GetBuffer(1)->Width;
uint32_t DispY = Display->GetBuffer(1)->Height;
for (size_t i = 1; i < FrameCount; i++)
{
int x, y, channels;
if (!stbi_info_from_memory((uint8_t *)Frames[i], FrameSizes[i], &x, &y, &channels))
continue;
uint8_t *img = stbi_load_from_memory((uint8_t *)Frames[i], FrameSizes[i], &x, &y, &channels, 4);
if (img == NULL)
continue;
int offsetX = DispX / 2 - x / 2;
int offsetY = DispY / 2 - y / 2;
for (int i = 0; i < x * y; i++)
{
uint32_t pixel = ((uint32_t *)img)[i];
uint8_t r = (pixel >> 16) & 0xFF;
uint8_t g = (pixel >> 8) & 0xFF;
uint8_t b = (pixel >> 0) & 0xFF;
uint8_t a = (pixel >> 24) & 0xFF;
if (a != 0xFF)
{
r = (r * a) / 0xFF;
g = (g * a) / 0xFF;
b = (b * a) / 0xFF;
}
Display->SetPixel((i % x) + offsetX, (i / x) + offsetY, (r << 16) | (g << 8) | (b << 0), 1);
}
free(img);
Display->SetBuffer(1);
}
int brightness = 100;
while (brightness >= 0)
{
brightness -= 10;
Display->SetBrightness(brightness, 1);
Display->SetBuffer(1);
}
}
void ExitLogoAnimationThread()
{
Display->SetBrightness(100, 1);
Display->SetBuffer(1);
/* Files: 26.tga 25.tga ... 1.tga */
uint32_t DispX = Display->GetBuffer(1)->Width;
uint32_t DispY = Display->GetBuffer(1)->Height;
// for (size_t i = 26; i > 0; i--)
// {
// int x, y, channels;
// if (!stbi_info_from_memory((uint8_t *)Frames[i], FrameSizes[i], &x, &y, &channels))
// continue;
// uint8_t *img = stbi_load_from_memory((uint8_t *)Frames[i], FrameSizes[i], &x, &y, &channels, 4);
// if (img == NULL)
// continue;
// int offsetX = DispX / 2 - x / 2;
// int offsetY = DispY / 2 - y / 2;
// for (int i = 0; i < x * y; i++)
// {
// uint32_t pixel = ((uint32_t *)img)[i];
// uint8_t r = (pixel >> 16) & 0xFF;
// uint8_t g = (pixel >> 8) & 0xFF;
// uint8_t b = (pixel >> 0) & 0xFF;
// uint8_t a = (pixel >> 24) & 0xFF;
// if (a != 0xFF)
// {
// r = (r * a) / 0xFF;
// g = (g * a) / 0xFF;
// b = (b * a) / 0xFF;
// }
// Display->SetPixel((i % x) + offsetX, (i / x) + offsetY, (r << 16) | (g << 8) | (b << 0), 1);
// }
// free(img);
// Display->SetBuffer(1);
// }
for (size_t i = 40; i > 25; i--)
{
int x, y, channels;
if (!stbi_info_from_memory((uint8_t *)Frames[i], FrameSizes[i], &x, &y, &channels))
continue;
uint8_t *img = stbi_load_from_memory((uint8_t *)Frames[i], FrameSizes[i], &x, &y, &channels, 4);
if (img == NULL)
continue;
int offsetX = DispX / 2 - x / 2;
int offsetY = DispY / 2 - y / 2;
for (int i = 0; i < x * y; i++)
{
uint32_t pixel = ((uint32_t *)img)[i];
uint8_t r = (pixel >> 16) & 0xFF;
uint8_t g = (pixel >> 8) & 0xFF;
uint8_t b = (pixel >> 0) & 0xFF;
uint8_t a = (pixel >> 24) & 0xFF;
if (a != 0xFF)
{
r = (r * a) / 0xFF;
g = (g * a) / 0xFF;
b = (b * a) / 0xFF;
}
Display->SetPixel((i % x) + offsetX, (i / x) + offsetY, (r << 16) | (g << 8) | (b << 0), 1);
}
free(img);
Display->SetBuffer(1);
}
int brightness = 100;
while (brightness >= 0)
{
brightness -= 10;
Display->SetBrightness(brightness, 1);
Display->SetBuffer(1);
}
}
void KernelMainThread()
{
TaskManager->GetCurrentThread()->SetPriority(Tasking::Critical);
Tasking::TCB *blaThread = nullptr;
if (Config.BootAnimation)
{
blaThread = TaskManager->CreateThread(TaskManager->GetCurrentProcess(), (Tasking::IP)BootLogoAnimationThread);
blaThread->Rename("Logo Animation");
}
#ifdef DEBUG
/* TODO: This should not be enabled because it may cause a deadlock. Not sure where or how. */
// Tasking::PCB *tskMgr = TaskManager->CreateProcess(TaskManager->GetCurrentProcess(), "Debug Task Manager", Tasking::TaskTrustLevel::Kernel);
@ -171,7 +358,8 @@ void KernelMainThread()
const char *USpace_msg = "Setting up userspace";
for (size_t i = 0; i < strlen(USpace_msg); i++)
Display->Print(USpace_msg[i], 0);
Display->SetBuffer(0);
if (!Config.BootAnimation)
Display->SetBuffer(0);
Execute::SpawnData ret = {Execute::ExStatus::Unknown, nullptr, nullptr};
Tasking::TCB *ExecuteThread = nullptr;
@ -182,12 +370,14 @@ void KernelMainThread()
ExecuteThread->SetPriority(Tasking::Idle);
Display->Print('.', 0);
Display->SetBuffer(0);
if (!Config.BootAnimation)
Display->SetBuffer(0);
ret = SpawnInit();
Display->Print('.', 0);
Display->SetBuffer(0);
if (!Config.BootAnimation)
Display->SetBuffer(0);
if (ret.Status != Execute::ExStatus::OK)
{
@ -200,7 +390,8 @@ void KernelMainThread()
Display->Print('.', 0);
Display->Print('\n', 0);
Display->SetBuffer(0);
if (!Config.BootAnimation)
Display->SetBuffer(0);
KPrint("Waiting for \e22AAFF%s\eCCCCCC to start...", Config.InitPath);
TaskManager->GetCurrentThread()->SetPriority(Tasking::Idle);
@ -213,6 +404,7 @@ Exit:
KPrint("\eE85230Userspace process exited with code %d", ExitCode);
KPrint("Dropping to recovery screen...");
TaskManager->Sleep(2500);
TaskManager->WaitForThread(blaThread);
RecoveryScreen = new Recovery::KernelRecovery;
}
else
@ -224,9 +416,21 @@ Exit:
CPU::Halt(true);
}
void KernelShutdownThread(bool Reboot)
void __no_stack_protector KernelShutdownThread(bool Reboot)
{
BeforeShutdown();
SmartLock(ShutdownLock);
debug("KernelShutdownThread(%s)", Reboot ? "true" : "false");
if (Config.BootAnimation && TaskManager)
{
if (RecoveryScreen)
delete RecoveryScreen, RecoveryScreen = nullptr;
Tasking::TCB *elaThread = TaskManager->CreateThread(TaskManager->GetCurrentProcess(), (Tasking::IP)ExitLogoAnimationThread);
elaThread->Rename("Logo Animation");
TaskManager->WaitForThread(elaThread);
}
BeforeShutdown(Reboot);
trace("%s...", Reboot ? "Rebooting" : "Shutting down");
if (Reboot)
@ -235,3 +439,6 @@ void KernelShutdownThread(bool Reboot)
PowerManager->Shutdown();
CPU::Stop();
}
void KST_Reboot() { KernelShutdownThread(true); }
void KST_Shutdown() { KernelShutdownThread(false); }

View File

@ -15,8 +15,6 @@
#include "Core/smbios.hpp"
#include "Tests/t.h"
NewLock(ShutdownLock);
bool DebuggerIsAttached = false;
#ifdef DEBUG
@ -49,6 +47,7 @@ LockClass mExtTrkLock;
* - [ ] Colors in crash screen are not following the kernel color scheme.
* - [ ] Find a way to add intrinsics.
* - [ ] Rework PSF1 font loader.
* - [ ] The cleanup should be done by a thread (tasking). This is done to avoid a deadlock.
*
* ISSUES:
* - [ ] Kernel stack is smashed when an interrupt occurs. (this bug it occurs when an interrupt like IRQ1 or IRQ12 occurs)
@ -160,14 +159,28 @@ PCI::PCI *PCIManager = nullptr;
Tasking::Task *TaskManager = nullptr;
Time::time *TimeManager = nullptr;
VirtualFileSystem::Virtual *vfs = nullptr;
VirtualFileSystem::Virtual *bootanim_vfs = nullptr;
KernelConfig Config;
Time::Clock BootClock;
KernelConfig Config = {
.AllocatorType = Memory::MemoryAllocatorType::XallocV1,
.SchedulerType = 0,
.DriverDirectory = {'/', 's', 'y', 's', 't', 'e', 'm', '/', 'd', 'r', 'i', 'v', 'e', 'r', 's', '\0'},
.InitPath = {'/', 's', 'y', 's', 't', 'e', 'm', '/', 'i', 'n', 'i', 't', '\0'},
.InterruptsOnCrash = true,
.Cores = 0,
.IOAPICInterruptCore = 0,
.UnlockDeadLock = false,
.SIMD = false,
.BootAnimation = false,
};
extern bool EnableProfiler;
// For the Display class. Printing on first buffer as default.
EXTERNC void putchar(char c) { Display->Print(c, 0); }
int PutCharBufferIndex = 0;
EXTERNC void putchar(char c) { Display->Print(c, PutCharBufferIndex); }
EXTERNC void KPrint(const char *Format, ...)
{
@ -182,7 +195,8 @@ EXTERNC void KPrint(const char *Format, ...)
va_end(args);
putchar('\n');
Display->SetBuffer(0);
if (!Config.BootAnimation)
Display->SetBuffer(0);
}
EXTERNC NIF void Main(BootInfo *Info)
@ -204,7 +218,20 @@ EXTERNC NIF void Main(BootInfo *Info)
Interrupts::Initialize(0);
KPrint("Reading Kernel Parameters");
Config = ParseConfig((char *)bInfo->Kernel.CommandLine);
ParseConfig((char *)bInfo->Kernel.CommandLine, &Config);
if (Config.BootAnimation)
{
Display->CreateBuffer(0, 0, 1);
Video::ScreenBuffer *buf = Display->GetBuffer(1);
Video::FontInfo fi = Display->GetCurrentFont()->GetInfo();
Display->SetBufferCursor(1, 0, buf->Height - fi.Height);
PutCharBufferIndex = 1;
printf("Fennix Operating System - %s [\e058C19%s\eFFFFFF]\n", KERNEL_VERSION, GIT_COMMIT_SHORT);
Display->SetBuffer(1);
PutCharBufferIndex = 0;
}
KPrint("Initializing CPU Features");
CPU::InitializeFeatures(0);
@ -320,7 +347,30 @@ EXTERNC NIF void Main(BootInfo *Info)
KPrint("Initializing Filesystem...");
vfs = new VirtualFileSystem::Virtual;
new VirtualFileSystem::USTAR((uintptr_t)bInfo->Modules[0].Address, vfs); // TODO: Detect initrd
if (Config.BootAnimation)
bootanim_vfs = new VirtualFileSystem::Virtual;
for (size_t i = 0; i < MAX_MODULES; i++)
{
if (!bInfo->Modules[i].Address)
continue;
if (strcmp(bInfo->Modules[i].CommandLine, "initrd") == 0)
{
debug("Found initrd at %p", bInfo->Modules[i].Address);
static char initrd = 0;
if (!initrd++)
new VirtualFileSystem::USTAR((uintptr_t)bInfo->Modules[i].Address, vfs);
}
if (strcmp(bInfo->Modules[i].CommandLine, "bootanim") == 0 && Config.BootAnimation)
{
debug("Found bootanim at %p", bInfo->Modules[i].Address);
static char bootanim = 0;
if (!bootanim++)
new VirtualFileSystem::USTAR((uintptr_t)bInfo->Modules[i].Address, bootanim_vfs);
}
}
if (!vfs->PathExists("/system"))
vfs->Create("/system", NodeFlags::DIRECTORY);
@ -404,23 +454,41 @@ EXTERNC __no_stack_protector NIF void Entry(BootInfo *Info)
#pragma GCC diagnostic ignored "-Wdelete-non-virtual-dtor"
EXTERNC __no_stack_protector NIF void BeforeShutdown()
EXTERNC __no_stack_protector void BeforeShutdown(bool Reboot)
{
SmartLock(ShutdownLock);
/* TODO: Announce shutdown */
trace("\n\n\n#################### SYSTEM SHUTTING DOWN ####################\n\n");
delete NIManager, NIManager = nullptr;
delete DiskManager, DiskManager = nullptr;
delete DriverManager, DriverManager = nullptr;
TaskManager->SignalShutdown();
delete TaskManager, TaskManager = nullptr;
if (RecoveryScreen)
delete RecoveryScreen, RecoveryScreen = nullptr;
delete vfs, vfs = nullptr;
delete TimeManager, TimeManager = nullptr;
delete Display, Display = nullptr;
if (NIManager)
delete NIManager, NIManager = nullptr;
if (DiskManager)
delete DiskManager, DiskManager = nullptr;
if (DriverManager)
delete DriverManager, DriverManager = nullptr;
if (TaskManager)
{
TaskManager->SignalShutdown();
delete TaskManager, TaskManager = nullptr;
}
if (vfs)
delete vfs, vfs = nullptr;
if (bootanim_vfs)
delete bootanim_vfs, bootanim_vfs = nullptr;
if (TimeManager)
delete TimeManager, TimeManager = nullptr;
if (Display)
delete Display, Display = nullptr;
// PowerManager should not be called
// https://wiki.osdev.org/Calling_Global_Constructors

View File

@ -285,17 +285,8 @@ namespace Recovery
RecoveryScreen->RecoveryThread();
}
void RebootCommandThread()
{
CriticalSection cs;
PowerManager->Reboot();
}
void ShutdownCommandThread()
{
CriticalSection cs;
PowerManager->Shutdown();
}
void RebootCommandThread() { KST_Reboot(); }
void ShutdownCommandThread() { KST_Shutdown(); }
void RebootCommandWrapper() { TaskManager->CreateThread(TaskManager->GetCurrentProcess(), (IP)RebootCommandThread); }
void ShutdownCommandWrapper() { TaskManager->CreateThread(TaskManager->GetCurrentProcess(), (IP)ShutdownCommandThread); }
@ -309,7 +300,7 @@ namespace Recovery
gui = new GraphicalUserInterface::GUI;
TCB *guiThread = TaskManager->CreateThread(TaskManager->GetCurrentProcess(), (IP)GUIWrapper);
guiThread = TaskManager->CreateThread(TaskManager->GetCurrentProcess(), (IP)GUIWrapper);
guiThread->Rename("GUI Thread");
guiThread->SetPriority(Tasking::TaskPriority::Critical);
@ -339,12 +330,16 @@ namespace Recovery
wdgDbgWin = new WidgetCollection(DbgWin);
Video::Font *NewFont = new Video::Font(&_binary_Files_tamsyn_font_1_11_Tamsyn7x14r_psf_start, &_binary_Files_tamsyn_font_1_11_Tamsyn7x14r_psf_end, Video::FontType::PCScreenFont2);
wdgDbgWin->ReplaceFont(NewFont);
TaskManager->CreateThread(TaskManager->GetCurrentProcess(), (IP)RecoveryThreadWrapper)->SetPriority(Tasking::TaskPriority::Idle);
recoveryThread = TaskManager->CreateThread(TaskManager->GetCurrentProcess(), (IP)RecoveryThreadWrapper);
recoveryThread->Rename("Recovery Thread");
recoveryThread->SetPriority(Tasking::TaskPriority::Idle);
}
KernelRecovery::~KernelRecovery()
{
debug("Destructor called");
TaskManager->KillThread(guiThread, 0);
TaskManager->KillThread(recoveryThread, 0);
delete gui, gui = nullptr;
}
}

View File

@ -54,7 +54,8 @@ static int sys_print(SyscallsFrame *Frame, char Char, int Index)
char ret = Display->Print(Char, Index, true);
#ifdef DEBUG
Display->SetBuffer(Index);
if (!Config.BootAnimation && Index != 0)
Display->SetBuffer(Index);
#endif
UNUSED(Frame);
return ret;

View File

@ -3,6 +3,7 @@
#include <types.h>
#include <memory.hpp>
#include <task.hpp>
namespace Recovery
{
@ -10,6 +11,8 @@ namespace Recovery
{
private:
Memory::MemMgr *mem;
Tasking::TCB *guiThread;
Tasking::TCB *recoveryThread;
public:
void RecoveryThread();

View File

@ -38,6 +38,7 @@ extern KernelConfig Config;
extern Tasking::Task *TaskManager;
extern Time::time *TimeManager;
extern VirtualFileSystem::Virtual *vfs;
extern VirtualFileSystem::Virtual *bootanim_vfs;
extern Driver::Driver *DriverManager;
extern Disk::Manager *DiskManager;
extern NetworkInterfaceManager::NetworkInterface *NIManager;
@ -54,10 +55,12 @@ extern VirtualFileSystem::Node *ProcFS;
EXTERNC void putchar(char c);
EXTERNC void KPrint(const char *format, ...);
EXTERNC void Entry(struct BootInfo *Info);
EXTERNC void BeforeShutdown();
EXTERNC void BeforeShutdown(bool Reboot);
EXTERNC void TaskingPanic();
EXTERNC void KernelMainThread();
EXTERNC void KernelShutdownThread(bool Reboot);
EXTERNC void KST_Reboot();
EXTERNC void KST_Shutdown();
#endif // !__FENNIX_KERNEL_KERNEL_H__