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
This commit is contained in:
+58
-28
@@ -1,49 +1,79 @@
|
|||||||
|
/*
|
||||||
|
* Panic.cpp
|
||||||
|
* Copyright (c) 2025 Daniel Hammer
|
||||||
|
*/
|
||||||
|
|
||||||
#include "Panic.hpp"
|
#include "Panic.hpp"
|
||||||
|
#include "../CppLib/BoxUI.hpp"
|
||||||
|
|
||||||
void Panic(const char *meditationString, System::PanicFrame* frame) {
|
void Panic(const char *meditationString, System::PanicFrame* frame) {
|
||||||
kerr << "\nKernel panic" << "\n" << "\n";
|
const int boxWidth = 72;
|
||||||
|
|
||||||
kerr << "\t" << meditationString << Kt::newline;
|
// 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 defined (__x86_64__)
|
||||||
if (frame != nullptr) {
|
if (frame != nullptr) {
|
||||||
kerr << "\t" << "InterruptVector: " << "0x" << base::hex << frame->InterruptVector << "\n";
|
PrintBoxedSeparator(kerr, boxWidth);
|
||||||
if (frame->InterruptVector == 0xE) { // In case of #PF the CPU pushes an error code to the frame
|
PrintBoxedLine(kerr, "CPU State:", boxWidth, true);
|
||||||
|
PrintBoxedHex(kerr, "Interrupt Vector", frame->InterruptVector, boxWidth);
|
||||||
|
|
||||||
|
if (frame->InterruptVector == 0xE) {
|
||||||
auto pf_frame = (System::PageFaultPanicFrame*)frame;
|
auto pf_frame = (System::PageFaultPanicFrame*)frame;
|
||||||
frame = (System::PanicFrame*)&pf_frame->IP;
|
frame = (System::PanicFrame*)&pf_frame->IP;
|
||||||
|
PrintBoxedLine(kerr, "Page Fault Error:", boxWidth, true);
|
||||||
/* Page fault error details */
|
PrintBoxedDec(kerr, "Present", pf_frame->PageFaultError.Present, boxWidth);
|
||||||
kerr << "\t" << "PageFaultPresent: " << base::dec << pf_frame->PageFaultError.Present << "\n";
|
PrintBoxedDec(kerr, "Write", pf_frame->PageFaultError.Write, boxWidth);
|
||||||
kerr << "\t" << "PageFaultWrite: " << base::dec << pf_frame->PageFaultError.Write << "\n";
|
PrintBoxedDec(kerr, "User", pf_frame->PageFaultError.User, boxWidth);
|
||||||
kerr << "\t" << "PageFaultUser: " << base::dec << pf_frame->PageFaultError.User << "\n";
|
PrintBoxedDec(kerr, "Reserved Write", pf_frame->PageFaultError.ReservedWrite, boxWidth);
|
||||||
kerr << "\t" << "PageFaultReservedWrite: " << base::dec << pf_frame->PageFaultError.ReservedWrite << "\n";
|
PrintBoxedDec(kerr, "Instruction Fetch", pf_frame->PageFaultError.InstructionFetch, boxWidth);
|
||||||
kerr << "\t" << "PageFaultInstructionFetch: " << base::dec << pf_frame->PageFaultError.InstructionFetch << "\n";
|
PrintBoxedDec(kerr, "Protection Key", pf_frame->PageFaultError.ProtectionKey, boxWidth);
|
||||||
kerr << "\t" << "PageFaultProtectionKey: " << base::dec << pf_frame->PageFaultError.ProtectionKey << "\n";
|
PrintBoxedDec(kerr, "Shadow Stack", pf_frame->PageFaultError.ShadowStack, boxWidth);
|
||||||
kerr << "\t" << "PageFaultShadowStack: " << base::dec << pf_frame->PageFaultError.ShadowStack << "\n";
|
PrintBoxedDec(kerr, "SGX", pf_frame->PageFaultError.SGX, boxWidth);
|
||||||
kerr << "\t" << "PageFaultSGX: " << base::dec << pf_frame->PageFaultError.ShadowStack << "\n";
|
} else if (frame->InterruptVector == 0xD) {
|
||||||
}
|
|
||||||
else if (frame->InterruptVector == 0xD) {
|
|
||||||
auto gpf_frame = (System::GPFPanicFrame*)frame;
|
auto gpf_frame = (System::GPFPanicFrame*)frame;
|
||||||
frame = (System::PanicFrame*)&frame->IP;
|
frame = (System::PanicFrame*)&frame->IP;
|
||||||
|
PrintBoxedLine(kerr, "General Protection Fault:", boxWidth, true);
|
||||||
kerr << "\t" << "ErrorCode: " << base::dec << gpf_frame->GeneralProtectionFaultError << "\n";
|
PrintBoxedDec(kerr, "Error Code", gpf_frame->GeneralProtectionFaultError, boxWidth);
|
||||||
}
|
}
|
||||||
|
|
||||||
kerr << "\t" << "InstructionPointer: " << "0x" << base::hex << frame->IP << "\n";
|
PrintBoxedSeparator(kerr, boxWidth);
|
||||||
kerr << "\t" << "CodeSegment: " << "0x" << base::hex << frame->CS << "\n";
|
PrintBoxedLine(kerr, "Registers:", boxWidth, true);
|
||||||
kerr << "\t" << "Flags: " << "0x" << base::hex << frame->Flags << "\n";
|
PrintBoxedHex(kerr, "Instruction Pointer", frame->IP, boxWidth);
|
||||||
kerr << "\t" << "StackPointer: " << "0x" << base::hex << frame->SP << "\n";
|
PrintBoxedHex(kerr, "Code Segment", frame->CS, boxWidth);
|
||||||
kerr << "\t" << "StackSegment: " << "0x" << base::hex << frame->SS << "\n";
|
PrintBoxedHex(kerr, "Flags", frame->Flags, boxWidth);
|
||||||
|
PrintBoxedHex(kerr, "Stack Pointer", frame->SP, boxWidth);
|
||||||
|
PrintBoxedHex(kerr, "Stack Segment", frame->SS, boxWidth);
|
||||||
}
|
}
|
||||||
#endif
|
#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) {
|
while (true) {
|
||||||
#if defined (__x86_64__)
|
#if defined (__x86_64__)
|
||||||
asm ("cli");
|
asm ("cli");
|
||||||
asm ("hlt");
|
asm ("hlt");
|
||||||
#elif defined (__aarch64__) || defined (__riscv)
|
#elif defined (__aarch64__) || defined (__riscv)
|
||||||
asm ("wfi");
|
asm ("wfi");
|
||||||
#elif defined (__loongarch64)
|
#elif defined (__loongarch64)
|
||||||
asm ("idle 0");
|
asm ("idle 0");
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -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<typename T>
|
||||||
|
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<typename T>
|
||||||
|
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";
|
||||||
|
}
|
||||||
+250
-2
@@ -5,18 +5,247 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
#include <Memory/HHDM.hpp>
|
||||||
|
#include <Timekeeping/Time.hpp>
|
||||||
|
|
||||||
namespace Efi {
|
namespace Efi {
|
||||||
typedef void* EFI_HANDLE;
|
typedef void* EFI_HANDLE;
|
||||||
|
|
||||||
|
struct EfiHeaderRevision {
|
||||||
|
uint16_t MinorRevision;
|
||||||
|
uint16_t MajorRevision;
|
||||||
|
} __attribute__((packed));
|
||||||
|
|
||||||
struct TableHeader {
|
struct TableHeader {
|
||||||
std::uint64_t Signature;
|
std::uint64_t Signature;
|
||||||
std::uint32_t Revision;
|
EfiHeaderRevision Revision;
|
||||||
std::uint32_t HeaderSize;
|
std::uint32_t HeaderSize;
|
||||||
std::uint32_t CRC32;
|
std::uint32_t CRC32;
|
||||||
std::uint32_t Reserved;
|
std::uint32_t Reserved;
|
||||||
}__attribute__((packed));
|
}__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 {
|
struct SystemTable {
|
||||||
TableHeader Header;
|
TableHeader Header;
|
||||||
void* FirmwareVendor; // Pointer to a CHAR16 string of the fw vendor name string
|
void* FirmwareVendor; // Pointer to a CHAR16 string of the fw vendor name string
|
||||||
@@ -31,7 +260,7 @@ namespace Efi {
|
|||||||
void* StdErr;
|
void* StdErr;
|
||||||
|
|
||||||
// Jackpot
|
// Jackpot
|
||||||
void *RuntimeServices;
|
RuntimeServicesTable *RuntimeServices;
|
||||||
|
|
||||||
void *BootServices;
|
void *BootServices;
|
||||||
|
|
||||||
@@ -39,4 +268,23 @@ namespace Efi {
|
|||||||
|
|
||||||
void *ConfigurationTable;
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
@@ -23,17 +23,18 @@ namespace Io {
|
|||||||
asm ("outl %0, %1" : : "a"(value), "Nd"(port) : "memory");
|
asm ("outl %0, %1" : : "a"(value), "Nd"(port) : "memory");
|
||||||
}
|
}
|
||||||
|
|
||||||
inline uint8_t In8(uint16_t port) {
|
/* TODO fix */
|
||||||
asm ("inb %0" : : "Nd"(port) : "memory");
|
// inline uint8_t In8(uint16_t port) {
|
||||||
}
|
// asm ("inb %0" : : "Nd"(port) : "memory");
|
||||||
|
// }
|
||||||
|
|
||||||
inline uint16_t In16(uint16_t port) {
|
// inline uint16_t In16(uint16_t port) {
|
||||||
asm ("inw %0" : : "Nd"(port) : "memory");
|
// asm ("inw %0" : : "Nd"(port) : "memory");
|
||||||
}
|
// }
|
||||||
|
|
||||||
inline uint32_t In32(uint16_t port) {
|
// inline uint32_t In32(uint16_t port) {
|
||||||
asm ("inl %0" : : "Nd"(port) : "memory");
|
// asm ("inl %0" : : "Nd"(port) : "memory");
|
||||||
}
|
// }
|
||||||
|
|
||||||
inline void IoPortWait() {
|
inline void IoPortWait() {
|
||||||
Out8(0x80, 0);
|
Out8(0x80, 0);
|
||||||
|
|||||||
+5
-2
@@ -27,6 +27,7 @@
|
|||||||
#include <Io/IoPort.hpp>
|
#include <Io/IoPort.hpp>
|
||||||
#include <Memory/Paging.hpp>
|
#include <Memory/Paging.hpp>
|
||||||
#include <ACPI/ACPI.hpp>
|
#include <ACPI/ACPI.hpp>
|
||||||
|
#include <CppLib/BoxUI.hpp>
|
||||||
|
|
||||||
using namespace Kt;
|
using namespace Kt;
|
||||||
|
|
||||||
@@ -76,6 +77,7 @@ extern "C" void kmain() {
|
|||||||
framebuffer->blue_mask_shift
|
framebuffer->blue_mask_shift
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
#if defined (__x86_64__)
|
#if defined (__x86_64__)
|
||||||
Hal::PrepareGDT();
|
Hal::PrepareGDT();
|
||||||
Hal::BridgeLoadGDT();
|
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);
|
g_paging.Init((uint64_t)&KernelStartSymbol, ((uint64_t)&KernelEndSymbol - (uint64_t)&KernelStartSymbol), memmap_request.response);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
Hal::ACPI g_acpi((Hal::ACPI::XSDP*)Memory::HHDM(rsdp_request.response->address));
|
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();
|
Hal::Halt();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,7 +21,6 @@
|
|||||||
namespace Memory
|
namespace Memory
|
||||||
{
|
{
|
||||||
HeapAllocator::Header* HeapAllocator::GetHeader(void* block) {
|
HeapAllocator::Header* HeapAllocator::GetHeader(void* block) {
|
||||||
uintptr_t ptr = (uintptr_t)block;
|
|
||||||
return (Header*)(block - sizeof(Header));
|
return (Header*)(block - sizeof(Header));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,11 +1,33 @@
|
|||||||
|
/*
|
||||||
|
* Terminal.cpp
|
||||||
|
* Terminal implementation
|
||||||
|
* Copyright (c) 2025 Daniel Hammer
|
||||||
|
*/
|
||||||
|
|
||||||
#include "Terminal.hpp"
|
#include "Terminal.hpp"
|
||||||
#include "../Libraries/flanterm/src/flanterm_backends/fb.h"
|
#include "../Libraries/flanterm/src/flanterm_backends/fb.h"
|
||||||
#include "../Libraries/flanterm/src/flanterm.h"
|
#include "../Libraries/flanterm/src/flanterm.h"
|
||||||
|
|
||||||
#include "../Libraries/String.hpp"
|
#include "../Libraries/String.hpp"
|
||||||
|
#include <CppLib/CString.hpp>
|
||||||
|
|
||||||
namespace Kt {
|
namespace Kt {
|
||||||
flanterm_context *ctx;
|
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<int>(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,
|
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,
|
std::uint8_t red_mask_size, std::uint8_t red_mask_shift,
|
||||||
@@ -29,6 +51,11 @@ namespace Kt {
|
|||||||
0, 0,
|
0, 0,
|
||||||
0
|
0
|
||||||
);
|
);
|
||||||
|
|
||||||
|
g_terminal_width = width;
|
||||||
|
|
||||||
|
UpdatePanelBar("Initializing...");
|
||||||
|
kout << "\n\n\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
void Putchar(char c) {
|
void Putchar(char c) {
|
||||||
@@ -38,4 +65,5 @@ namespace Kt {
|
|||||||
void Print(const char *text) {
|
void Print(const char *text) {
|
||||||
flanterm_write(ctx, text, Lib::strlen(text));
|
flanterm_write(ctx, text, Lib::strlen(text));
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
@@ -1,3 +1,9 @@
|
|||||||
|
/*
|
||||||
|
* Terminal.hpp
|
||||||
|
* Terminal implementation
|
||||||
|
* Copyright (c) 2025 Daniel Hammer
|
||||||
|
*/
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
@@ -36,6 +42,8 @@ namespace Kt
|
|||||||
void Putchar(char c);
|
void Putchar(char c);
|
||||||
void Print(const char *text);
|
void Print(const char *text);
|
||||||
|
|
||||||
|
void UpdatePanelBar(const char* panelText);
|
||||||
|
|
||||||
inline base base_custom(int custom)
|
inline base base_custom(int custom)
|
||||||
{
|
{
|
||||||
return (base)custom;
|
return (base)custom;
|
||||||
|
|||||||
@@ -0,0 +1,42 @@
|
|||||||
|
/*
|
||||||
|
* Time.cpp
|
||||||
|
* Copyright (c) 2025 Daniel Hammer
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "Time.hpp"
|
||||||
|
#include <Terminal/Terminal.hpp>
|
||||||
|
#include <CppLib/Stream.hpp>
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
/*
|
||||||
|
* Time.hpp
|
||||||
|
* Copyright (c) 2025 Daniel Hammer
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include <CppLib/CString.hpp>
|
||||||
|
|
||||||
|
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);
|
||||||
|
};
|
||||||
Reference in New Issue
Block a user