From 18ab6286828165cfdae1d04f2c38e2cff1e99b19 Mon Sep 17 00:00:00 2001 From: Daniel Hammer Date: Thu, 14 Aug 2025 12:36:56 +0200 Subject: [PATCH] feat(Terminal): Enhance terminal UI with panel updates and new BoxUI utility functions feat(Timekeeping): Implement time initialization and month string representation refactor(Panic): Improve panic output formatting and add boxed UI elements refactor(UEFI): Expand UEFI header and structure definitions for better clarity refactor(IoPort): Comment out unimplemented IO functions for future work --- kernel/src/Common/Panic.cpp | 86 +++++++---- kernel/src/CppLib/BoxUI.hpp | 94 ++++++++++++ kernel/src/Efi/UEFI.hpp | 252 ++++++++++++++++++++++++++++++- kernel/src/Io/IoPort.hpp | 19 +-- kernel/src/Main.cpp | 7 +- kernel/src/Memory/Heap.cpp | 1 - kernel/src/Terminal/Terminal.cpp | 28 ++++ kernel/src/Terminal/Terminal.hpp | 8 + kernel/src/Timekeeping/Time.cpp | 42 ++++++ kernel/src/Timekeeping/Time.hpp | 27 ++++ 10 files changed, 522 insertions(+), 42 deletions(-) create mode 100644 kernel/src/CppLib/BoxUI.hpp create mode 100644 kernel/src/Timekeeping/Time.cpp create mode 100644 kernel/src/Timekeeping/Time.hpp diff --git a/kernel/src/Common/Panic.cpp b/kernel/src/Common/Panic.cpp index df8e1b5..31e9859 100644 --- a/kernel/src/Common/Panic.cpp +++ b/kernel/src/Common/Panic.cpp @@ -1,49 +1,79 @@ +/* + * Panic.cpp + * Copyright (c) 2025 Daniel Hammer +*/ + #include "Panic.hpp" +#include "../CppLib/BoxUI.hpp" void Panic(const char *meditationString, System::PanicFrame* frame) { - kerr << "\nKernel panic" << "\n" << "\n"; - - kerr << "\t" << meditationString << Kt::newline; + const int boxWidth = 72; + + // Header + kerr << BOXUI_ANSI_RED_BG << BOXUI_ANSI_WHITE_FG << BOXUI_ANSI_BOLD << "\n"; + kerr << BOXUI_TL; + for (int i = 0; i < boxWidth - 2; ++i) kerr << BOXUI_H; + kerr << BOXUI_TR << "\n"; + PrintBoxedLine(kerr, "!!! KERNEL PANIC !!!", boxWidth, true); + PrintBoxedLine(kerr, "", boxWidth); + PrintBoxedLine(kerr, "System halted. Please reboot.", boxWidth, true); + PrintBoxedLine(kerr, "", boxWidth); + PrintBoxedSeparator(kerr, boxWidth); + PrintBoxedLine(kerr, "Meditation:", boxWidth, true); + PrintBoxedLine(kerr, meditationString, boxWidth); + PrintBoxedLine(kerr, "", boxWidth); #if defined (__x86_64__) if (frame != nullptr) { - kerr << "\t" << "InterruptVector: " << "0x" << base::hex << frame->InterruptVector << "\n"; - if (frame->InterruptVector == 0xE) { // In case of #PF the CPU pushes an error code to the frame + PrintBoxedSeparator(kerr, boxWidth); + PrintBoxedLine(kerr, "CPU State:", boxWidth, true); + PrintBoxedHex(kerr, "Interrupt Vector", frame->InterruptVector, boxWidth); + + if (frame->InterruptVector == 0xE) { auto pf_frame = (System::PageFaultPanicFrame*)frame; frame = (System::PanicFrame*)&pf_frame->IP; - - /* Page fault error details */ - kerr << "\t" << "PageFaultPresent: " << base::dec << pf_frame->PageFaultError.Present << "\n"; - kerr << "\t" << "PageFaultWrite: " << base::dec << pf_frame->PageFaultError.Write << "\n"; - kerr << "\t" << "PageFaultUser: " << base::dec << pf_frame->PageFaultError.User << "\n"; - kerr << "\t" << "PageFaultReservedWrite: " << base::dec << pf_frame->PageFaultError.ReservedWrite << "\n"; - kerr << "\t" << "PageFaultInstructionFetch: " << base::dec << pf_frame->PageFaultError.InstructionFetch << "\n"; - kerr << "\t" << "PageFaultProtectionKey: " << base::dec << pf_frame->PageFaultError.ProtectionKey << "\n"; - kerr << "\t" << "PageFaultShadowStack: " << base::dec << pf_frame->PageFaultError.ShadowStack << "\n"; - kerr << "\t" << "PageFaultSGX: " << base::dec << pf_frame->PageFaultError.ShadowStack << "\n"; - } - else if (frame->InterruptVector == 0xD) { + PrintBoxedLine(kerr, "Page Fault Error:", boxWidth, true); + PrintBoxedDec(kerr, "Present", pf_frame->PageFaultError.Present, boxWidth); + PrintBoxedDec(kerr, "Write", pf_frame->PageFaultError.Write, boxWidth); + PrintBoxedDec(kerr, "User", pf_frame->PageFaultError.User, boxWidth); + PrintBoxedDec(kerr, "Reserved Write", pf_frame->PageFaultError.ReservedWrite, boxWidth); + PrintBoxedDec(kerr, "Instruction Fetch", pf_frame->PageFaultError.InstructionFetch, boxWidth); + PrintBoxedDec(kerr, "Protection Key", pf_frame->PageFaultError.ProtectionKey, boxWidth); + PrintBoxedDec(kerr, "Shadow Stack", pf_frame->PageFaultError.ShadowStack, boxWidth); + PrintBoxedDec(kerr, "SGX", pf_frame->PageFaultError.SGX, boxWidth); + } else if (frame->InterruptVector == 0xD) { auto gpf_frame = (System::GPFPanicFrame*)frame; frame = (System::PanicFrame*)&frame->IP; - - kerr << "\t" << "ErrorCode: " << base::dec << gpf_frame->GeneralProtectionFaultError << "\n"; + PrintBoxedLine(kerr, "General Protection Fault:", boxWidth, true); + PrintBoxedDec(kerr, "Error Code", gpf_frame->GeneralProtectionFaultError, boxWidth); } - kerr << "\t" << "InstructionPointer: " << "0x" << base::hex << frame->IP << "\n"; - kerr << "\t" << "CodeSegment: " << "0x" << base::hex << frame->CS << "\n"; - kerr << "\t" << "Flags: " << "0x" << base::hex << frame->Flags << "\n"; - kerr << "\t" << "StackPointer: " << "0x" << base::hex << frame->SP << "\n"; - kerr << "\t" << "StackSegment: " << "0x" << base::hex << frame->SS << "\n"; + PrintBoxedSeparator(kerr, boxWidth); + PrintBoxedLine(kerr, "Registers:", boxWidth, true); + PrintBoxedHex(kerr, "Instruction Pointer", frame->IP, boxWidth); + PrintBoxedHex(kerr, "Code Segment", frame->CS, boxWidth); + PrintBoxedHex(kerr, "Flags", frame->Flags, boxWidth); + PrintBoxedHex(kerr, "Stack Pointer", frame->SP, boxWidth); + PrintBoxedHex(kerr, "Stack Segment", frame->SS, boxWidth); } #endif + + PrintBoxedLine(kerr, "", boxWidth); + + // Footer + kerr << BOXUI_BL; + for (int i = 0; i < boxWidth - 2; ++i) kerr << BOXUI_H; + kerr << BOXUI_BR << "\n"; + kerr << BOXUI_ANSI_RESET; + while (true) { - #if defined (__x86_64__) +#if defined (__x86_64__) asm ("cli"); asm ("hlt"); - #elif defined (__aarch64__) || defined (__riscv) +#elif defined (__aarch64__) || defined (__riscv) asm ("wfi"); - #elif defined (__loongarch64) +#elif defined (__loongarch64) asm ("idle 0"); - #endif +#endif } } \ No newline at end of file diff --git a/kernel/src/CppLib/BoxUI.hpp b/kernel/src/CppLib/BoxUI.hpp new file mode 100644 index 0000000..63d4330 --- /dev/null +++ b/kernel/src/CppLib/BoxUI.hpp @@ -0,0 +1,94 @@ +/* + * BoxUI.hpp + * Copyright (c) 2025 Daniel Hammer +*/ + +#pragma once + +// ANSI escape codes for color and formatting +#define BOXUI_ANSI_RESET "\033[0m" +#define BOXUI_ANSI_BOLD "\033[1m" +#define BOXUI_ANSI_RED_BG "\033[41m" +#define BOXUI_ANSI_WHITE_FG "\033[97m" +#define BOXUI_H "─" +#define BOXUI_V "│" +#define BOXUI_TL "┌" +#define BOXUI_TR "┐" +#define BOXUI_BL "└" +#define BOXUI_BR "┘" + +constexpr int BOXUI_LABEL_WIDTH = 28; + +// Print a boxed line with padding and optional bold +inline void PrintBoxedLine(auto& out, const char* content, int width, bool bold = false, const char* bg = nullptr) { + out << BOXUI_V << " "; + int len = 0; + if (bold) out << BOXUI_ANSI_BOLD; + for (const char* p = content; *p && len < width - 6; ++p, ++len) out << *p; + if (bold) { + out << BOXUI_ANSI_RESET; + if (bg) out << bg << BOXUI_ANSI_WHITE_FG; + } + for (int i = len; i < width - 4; ++i) out << " "; + out << " " << BOXUI_V << "\n"; +} + +// Print a boxed separator line +inline void PrintBoxedSeparator(auto& out, int width) { + out << BOXUI_V << " "; + for (int i = 0; i < width - 4; ++i) out << BOXUI_H; + out << " " << BOXUI_V << "\n"; +} + +// Print a boxed line with a label and a hex value, aligned +template +inline void PrintBoxedHex(auto& out, const char* label, T value, int width) { + out << BOXUI_V << " "; + int len = 0; + for (const char* p = label; *p; ++p, ++len) out << *p; + for (; len < BOXUI_LABEL_WIDTH; ++len) out << " "; + out << ": 0x"; + len += 4 + (BOXUI_LABEL_WIDTH - len); + bool started = false; + int hexLen = 0; + for (int i = (sizeof(T) * 2) - 1; i >= 0; --i) { + char c = ((value >> (i * 4)) & 0xF); + if (c || started || i == 0) { + started = true; + out << (char)(c < 10 ? '0' + c : 'A' + (c - 10)); + ++hexLen; + } + } + len += hexLen; + for (int i = len; i < width - 4; ++i) out << " "; + out << " " << BOXUI_V << "\n"; +} + +// Print a boxed line with a label and a decimal value, aligned +template +inline void PrintBoxedDec(auto& out, const char* label, T value, int width) { + out << BOXUI_V << " "; + int len = 0; + for (const char* p = label; *p; ++p, ++len) out << *p; + for (; len < BOXUI_LABEL_WIDTH; ++len) out << " "; + out << ": "; + len += 2 + (BOXUI_LABEL_WIDTH - len); + char buf[32]; + int idx = 0; + T v = value; + if (v == 0) { + buf[idx++] = '0'; + } else { + char tmp[32]; + int t = 0; + while (v > 0 && t < 31) { + tmp[t++] = '0' + (v % 10); + v /= 10; + } + for (int i = t - 1; i >= 0; --i) buf[idx++] = tmp[i]; + } + buf[idx] = 0; + for (int i = 0; i < idx; ++i, ++len) out << buf[i]; + for (int i = len; i < width - 4; ++i) out << " "; + out << " " << BOXUI_V << "\n"; +} \ No newline at end of file diff --git a/kernel/src/Efi/UEFI.hpp b/kernel/src/Efi/UEFI.hpp index 87970cb..30cf7f2 100644 --- a/kernel/src/Efi/UEFI.hpp +++ b/kernel/src/Efi/UEFI.hpp @@ -5,18 +5,247 @@ #pragma once #include +#include +#include namespace Efi { typedef void* EFI_HANDLE; + struct EfiHeaderRevision { + uint16_t MinorRevision; + uint16_t MajorRevision; + } __attribute__((packed)); + struct TableHeader { std::uint64_t Signature; - std::uint32_t Revision; + EfiHeaderRevision Revision; std::uint32_t HeaderSize; std::uint32_t CRC32; std::uint32_t Reserved; }__attribute__((packed)); + /* EFI typedefs (unsigned ints) */ + + typedef uint8_t UINT8; + typedef uint16_t UINT16; + typedef uint32_t UINT32; + typedef uint64_t UINT64; + + /* EFI typedefs (signed ints) */ + + typedef int8_t INT8; + typedef int16_t INT16; + typedef int32_t INT32; + typedef int64_t INT64; + + /* EFI typedefs (misc) */ + typedef bool BOOLEAN; + typedef void VOID; + + typedef INT64 INTN; + typedef UINT64 UINTN; + + typedef UINTN RETURN_STATUS; + typedef RETURN_STATUS EFI_STATUS; + + typedef unsigned short CHAR16; + + /// + /// 64-bit physical memory address. + /// + typedef UINT64 EFI_PHYSICAL_ADDRESS; + + /// + /// 64-bit virtual memory address. + /// + typedef UINT64 EFI_VIRTUAL_ADDRESS; + + #define EFIAPI __attribute__((__ms_abi__)) + + /* EFI structs */ + typedef struct { + UINT16 Year; + UINT8 Month; + UINT8 Day; + UINT8 Hour; + UINT8 Minute; + UINT8 Second; + UINT8 Pad1; + UINT32 Nanosecond; + INT16 TimeZone; + UINT8 Daylight; + UINT8 Pad2; + } EFI_TIME; + + typedef struct { + /// + /// Provides the reporting resolution of the real-time clock device in + /// counts per second. For a normal PC-AT CMOS RTC device, this + /// value would be 1 Hz, or 1, to indicate that the device only reports + /// the time to the resolution of 1 second. + /// + UINT32 Resolution; + /// + /// Provides the timekeeping accuracy of the real-time clock in an + /// error rate of 1E-6 parts per million. For a clock with an accuracy + /// of 50 parts per million, the value in this field would be + /// 50,000,000. + /// + UINT32 Accuracy; + /// + /// A TRUE indicates that a time set operation clears the device's + /// time below the Resolution reporting level. A FALSE + /// indicates that the state below the Resolution level of the + /// device is not cleared when the time is set. Normal PC-AT CMOS + /// RTC devices set this value to FALSE. + /// + BOOLEAN SetsToZero; + } EFI_TIME_CAPABILITIES; + + /// + /// Definition of an EFI memory descriptor. + /// + typedef struct { + /// + /// Type of the memory region. + /// Type EFI_MEMORY_TYPE is defined in the + /// AllocatePages() function description. + /// + UINT32 Type; + /// + /// Physical address of the first byte in the memory region. PhysicalStart must be + /// aligned on a 4 KiB boundary, and must not be above 0xfffffffffffff000. Type + /// EFI_PHYSICAL_ADDRESS is defined in the AllocatePages() function description + /// + EFI_PHYSICAL_ADDRESS PhysicalStart; + /// + /// Virtual address of the first byte in the memory region. + /// VirtualStart must be aligned on a 4 KiB boundary, + /// and must not be above 0xfffffffffffff000. + /// + EFI_VIRTUAL_ADDRESS VirtualStart; + /// + /// NumberOfPagesNumber of 4 KiB pages in the memory region. + /// NumberOfPages must not be 0, and must not be any value + /// that would represent a memory page with a start address, + /// either physical or virtual, above 0xfffffffffffff000. + /// + UINT64 NumberOfPages; + /// + /// Attributes of the memory region that describe the bit mask of capabilities + /// for that memory region, and not necessarily the current settings for that + /// memory region. + /// + UINT64 Attribute; + } EFI_MEMORY_DESCRIPTOR; + + /// + /// 128 bit buffer containing a unique identifier value. + /// Unless otherwise specified, aligned on a 64 bit boundary. + /// + typedef struct { + UINT32 Data1; + UINT16 Data2; + UINT16 Data3; + UINT8 Data4[8]; + } GUID; + + typedef GUID EFI_GUID; + + /// + /// Enumeration of reset types. + /// + typedef enum { + /// + /// Used to induce a system-wide reset. This sets all circuitry within the + /// system to its initial state. This type of reset is asynchronous to system + /// operation and operates withgout regard to cycle boundaries. EfiColdReset + /// is tantamount to a system power cycle. + /// + EfiResetCold, + /// + /// Used to induce a system-wide initialization. The processors are set to their + /// initial state, and pending cycles are not corrupted. If the system does + /// not support this reset type, then an EfiResetCold must be performed. + /// + EfiResetWarm, + /// + /// Used to induce an entry into a power state equivalent to the ACPI G2/S5 or G3 + /// state. If the system does not support this reset type, then when the system + /// is rebooted, it should exhibit the EfiResetCold attributes. + /// + EfiResetShutdown, + /// + /// Used to induce a system-wide reset. The exact type of the reset is defined by + /// the EFI_GUID that follows the Null-terminated Unicode string passed into + /// ResetData. If the platform does not recognize the EFI_GUID in ResetData the + /// platform must pick a supported reset type to perform. The platform may + /// optionally log the parameters from any non-normal reset that occurs. + /// + EfiResetPlatformSpecific + } EFI_RESET_TYPE; + + /// + /// EFI Capsule Header. + /// + typedef struct { + /// + /// A GUID that defines the contents of a capsule. + /// + EFI_GUID CapsuleGuid; + /// + /// The size of the capsule header. This may be larger than the size of + /// the EFI_CAPSULE_HEADER since CapsuleGuid may imply + /// extended header entries + /// + UINT32 HeaderSize; + /// + /// Bit-mapped list describing the capsule attributes. The Flag values + /// of 0x0000 - 0xFFFF are defined by CapsuleGuid. Flag values + /// of 0x10000 - 0xFFFFFFFF are defined by this specification + /// + UINT32 Flags; + /// + /// Size in bytes of the capsule (including capsule header). + /// + UINT32 CapsuleImageSize; + } EFI_CAPSULE_HEADER; + + + /* Typedefs EFI runtime service APIs */ + typedef EFI_STATUS(EFIAPI *EFI_GET_TIME) (EFI_TIME *Time, EFI_TIME_CAPABILITIES *Capabilities); + typedef EFI_STATUS(EFIAPI *EFI_SET_TIME) (EFI_TIME *Time); + typedef EFI_STATUS(EFIAPI *EFI_GET_WAKEUP_TIME) (BOOLEAN *Enabled, BOOLEAN *Pending, EFI_TIME *Time); + typedef EFI_STATUS(EFIAPI *EFI_SET_WAKEUP_TIME) (BOOLEAN Enable, EFI_TIME *Time); + typedef EFI_STATUS(EFIAPI * EFI_SET_VIRTUAL_ADDRESS_MAP) (UINTN MemoryMapSize, UINTN DescriptorSize, UINT32 DescriptorVersion, EFI_MEMORY_DESCRIPTOR *VirtualMap); + typedef EFI_STATUS(EFIAPI * EFI_CONVERT_POINTER) (UINTN DebugDisposition, VOID **Address); + typedef EFI_STATUS(EFIAPI * EFI_GET_VARIABLE) (CHAR16 *VariableName, EFI_GUID *VendorGuid, UINT32 *Attributes, UINTN *DataSize, VOID *Data); + typedef EFI_STATUS(EFIAPI * EFI_GET_NEXT_VARIABLE_NAME) (UINTN *VariableNameSize, CHAR16 *VariableName, EFI_GUID *VendorGuid); + typedef EFI_STATUS(EFIAPI * EFI_SET_VARIABLE) (CHAR16 *VariableName, EFI_GUID *VendorGuid, UINT32 Attributes, UINTN DataSize, VOID *Data); + typedef EFI_STATUS(EFIAPI * EFI_GET_NEXT_HIGH_MONO_COUNT) (UINT32 *HighCount); + typedef VOID(EFIAPI * EFI_RESET_SYSTEM) (EFI_RESET_TYPE ResetType, EFI_STATUS ResetStatus, UINTN DataSize, VOID *ResetData); + typedef EFI_STATUS(EFIAPI * EFI_UPDATE_CAPSULE) (EFI_CAPSULE_HEADER **CapsuleHeaderArray, UINTN CapsuleCount, EFI_PHYSICAL_ADDRESS ScatterGatherList); + typedef EFI_STATUS(EFIAPI * EFI_QUERY_CAPSULE_CAPABILITIES) (EFI_CAPSULE_HEADER **CapsuleHeaderArray, UINTN CapsuleCount, UINT64 *MaximumCapsuleSize, EFI_RESET_TYPE *ResetType); + typedef EFI_STATUS(EFIAPI * EFI_QUERY_VARIABLE_INFO) (UINT32 Attributes, UINT64 *MaximumVariableStorageSize, UINT64 *RemainingVariableStorageSize, UINT64 *MaximumVariableSize); + + struct RuntimeServicesTable { + TableHeader Header; + EFI_GET_TIME GetTime; + EFI_SET_TIME SetTime; + EFI_GET_WAKEUP_TIME GetWakeupTime; + EFI_SET_WAKEUP_TIME SetWakeupTime; + EFI_SET_VIRTUAL_ADDRESS_MAP SetVirtualAddressMap; + EFI_CONVERT_POINTER ConvertPointer; + EFI_GET_VARIABLE GetVariable; + EFI_GET_NEXT_VARIABLE_NAME GetNextVariableName; + EFI_SET_VARIABLE SetVariable; + EFI_GET_NEXT_HIGH_MONO_COUNT GetNextHighMonotonicCount; + EFI_RESET_SYSTEM ResetSystem; + EFI_UPDATE_CAPSULE UpdateCapsule; + EFI_QUERY_CAPSULE_CAPABILITIES QueryCapsuleCapabilities; + EFI_QUERY_VARIABLE_INFO QueryVariableInfo; + }; + struct SystemTable { TableHeader Header; void* FirmwareVendor; // Pointer to a CHAR16 string of the fw vendor name string @@ -31,7 +260,7 @@ namespace Efi { void* StdErr; // Jackpot - void *RuntimeServices; + RuntimeServicesTable *RuntimeServices; void *BootServices; @@ -39,4 +268,23 @@ namespace Efi { void *ConfigurationTable; }; + + inline void Init(SystemTable* ST) { + Kt::KernelLogStream(Kt::OK, "UEFI") << "ST Minor Revision: " << ST->Header.Revision.MinorRevision; + Kt::KernelLogStream(Kt::OK, "UEFI") << "ST Major Revision: " << ST->Header.Revision.MajorRevision; + + RuntimeServicesTable* RT = (RuntimeServicesTable*)Memory::HHDM(ST->RuntimeServices); + + if (ST->RuntimeServices != nullptr) { + Kt::KernelLogStream(Kt::OK, "UEFI") << "EFI Runtime Service API is available."; + + EFI_TIME Time; + EFI_TIME_CAPABILITIES TimeCapabilities; + + EFI_GET_TIME _GetTime = (EFI_GET_TIME)Memory::HHDM((void*)RT->GetTime); + _GetTime(&Time, &TimeCapabilities); + + Timekeeping::Init(Time.Year, Time.Month, Time.Day, Time.Hour, Time.Minute, Time.Second); + } + } }; \ No newline at end of file diff --git a/kernel/src/Io/IoPort.hpp b/kernel/src/Io/IoPort.hpp index 3170784..5c4064a 100644 --- a/kernel/src/Io/IoPort.hpp +++ b/kernel/src/Io/IoPort.hpp @@ -23,17 +23,18 @@ namespace Io { asm ("outl %0, %1" : : "a"(value), "Nd"(port) : "memory"); } - inline uint8_t In8(uint16_t port) { - asm ("inb %0" : : "Nd"(port) : "memory"); - } + /* TODO fix */ + // inline uint8_t In8(uint16_t port) { + // asm ("inb %0" : : "Nd"(port) : "memory"); + // } - inline uint16_t In16(uint16_t port) { - asm ("inw %0" : : "Nd"(port) : "memory"); - } + // inline uint16_t In16(uint16_t port) { + // asm ("inw %0" : : "Nd"(port) : "memory"); + // } - inline uint32_t In32(uint16_t port) { - asm ("inl %0" : : "Nd"(port) : "memory"); - } + // inline uint32_t In32(uint16_t port) { + // asm ("inl %0" : : "Nd"(port) : "memory"); + // } inline void IoPortWait() { Out8(0x80, 0); diff --git a/kernel/src/Main.cpp b/kernel/src/Main.cpp index fc00b0e..d64c255 100644 --- a/kernel/src/Main.cpp +++ b/kernel/src/Main.cpp @@ -27,6 +27,7 @@ #include #include #include +#include using namespace Kt; @@ -76,6 +77,7 @@ extern "C" void kmain() { framebuffer->blue_mask_shift ); + #if defined (__x86_64__) Hal::PrepareGDT(); Hal::BridgeLoadGDT(); @@ -108,8 +110,9 @@ extern "C" void kmain() { g_paging.Init((uint64_t)&KernelStartSymbol, ((uint64_t)&KernelEndSymbol - (uint64_t)&KernelStartSymbol), memmap_request.response); #endif - Hal::ACPI g_acpi((Hal::ACPI::XSDP*)Memory::HHDM(rsdp_request.response->address)); - + Efi::SystemTable* ST = (Efi::SystemTable*)Memory::HHDM(system_table_request.response->address); + Efi::Init(ST); + Hal::Halt(); } diff --git a/kernel/src/Memory/Heap.cpp b/kernel/src/Memory/Heap.cpp index 935ecab..64eb03a 100644 --- a/kernel/src/Memory/Heap.cpp +++ b/kernel/src/Memory/Heap.cpp @@ -21,7 +21,6 @@ namespace Memory { HeapAllocator::Header* HeapAllocator::GetHeader(void* block) { - uintptr_t ptr = (uintptr_t)block; return (Header*)(block - sizeof(Header)); } diff --git a/kernel/src/Terminal/Terminal.cpp b/kernel/src/Terminal/Terminal.cpp index 032933f..573ea47 100644 --- a/kernel/src/Terminal/Terminal.cpp +++ b/kernel/src/Terminal/Terminal.cpp @@ -1,11 +1,33 @@ +/* + * Terminal.cpp + * Terminal implementation + * Copyright (c) 2025 Daniel Hammer +*/ + #include "Terminal.hpp" #include "../Libraries/flanterm/src/flanterm_backends/fb.h" #include "../Libraries/flanterm/src/flanterm.h" #include "../Libraries/String.hpp" +#include namespace Kt { flanterm_context *ctx; + std::size_t g_terminal_width = 0; + + void UpdatePanelBar(CString panelText) { + kout << "\033[s"; + kout << "\033[H"; + + int panelWidth = g_terminal_width / 9; + + kout << "\033[44m" << "\033[97m"; + kout << panelText; + for (int i = static_cast(Lib::strlen(panelText)); i < panelWidth; ++i) + kout << " "; + kout << "\033[0m"; + kout << "\033[u"; + } void Initialize(std::uint32_t *framebuffer, std::size_t width, std::size_t height, std::size_t pitch, std::uint8_t red_mask_size, std::uint8_t red_mask_shift, @@ -29,6 +51,11 @@ namespace Kt { 0, 0, 0 ); + + g_terminal_width = width; + + UpdatePanelBar("Initializing..."); + kout << "\n\n\n"; } void Putchar(char c) { @@ -38,4 +65,5 @@ namespace Kt { void Print(const char *text) { flanterm_write(ctx, text, Lib::strlen(text)); } + }; \ No newline at end of file diff --git a/kernel/src/Terminal/Terminal.hpp b/kernel/src/Terminal/Terminal.hpp index 185824c..a9a0bdd 100644 --- a/kernel/src/Terminal/Terminal.hpp +++ b/kernel/src/Terminal/Terminal.hpp @@ -1,3 +1,9 @@ +/* + * Terminal.hpp + * Terminal implementation + * Copyright (c) 2025 Daniel Hammer +*/ + #pragma once #include #include @@ -36,6 +42,8 @@ namespace Kt void Putchar(char c); void Print(const char *text); + void UpdatePanelBar(const char* panelText); + inline base base_custom(int custom) { return (base)custom; diff --git a/kernel/src/Timekeeping/Time.cpp b/kernel/src/Timekeeping/Time.cpp new file mode 100644 index 0000000..0f50afe --- /dev/null +++ b/kernel/src/Timekeeping/Time.cpp @@ -0,0 +1,42 @@ +/* + * Time.cpp + * Copyright (c) 2025 Daniel Hammer +*/ + +#include "Time.hpp" +#include +#include + +using namespace Kt; + +void Timekeeping::Init(uint16_t Year, uint8_t Month, uint8_t Day, uint8_t Hour, uint8_t Minute, uint8_t Second) { + kcp::cstringstream minuteStream; + if (Minute < 10) { + minuteStream << "0"; + } + minuteStream << Minute; + CString minuteStr = minuteStream.c_str(); + + kcp::cstringstream secondStream; + if (Second < 10) { + secondStream << "0"; + } + secondStream << Second; + CString secondStr = secondStream.c_str(); + + kcp::cstringstream panelStr; + panelStr + << " " + << Day << " " + << Months[Month] << " " + << Year << ", " + << Hour << ":" + + << minuteStr << ":" + << secondStr; + + + CString dateString = panelStr.c_str(); + + UpdatePanelBar(dateString); +} \ No newline at end of file diff --git a/kernel/src/Timekeeping/Time.hpp b/kernel/src/Timekeeping/Time.hpp new file mode 100644 index 0000000..9a6588a --- /dev/null +++ b/kernel/src/Timekeeping/Time.hpp @@ -0,0 +1,27 @@ +/* + * Time.hpp + * Copyright (c) 2025 Daniel Hammer +*/ + +#pragma once +#include + +namespace Timekeeping { + const CString Months[] = { + nullptr, + "January", + "February", + "March", + "April", + "May", + "June", + "July", + "August", + "September", + "October", + "November", + "December" + }; + + void Init(uint16_t Year, uint8_t Month, uint8_t Day, uint8_t Hour, uint8_t Minute, uint8_t Second); +};