summaryrefslogtreecommitdiff
path: root/kernel/core/kernel.cpp
diff options
context:
space:
mode:
authorArseney300 <Arseney300@gmail.com>2026-04-11 17:48:52 +0700
committerArseney300 <Arseney300@gmail.com>2026-04-11 17:48:52 +0700
commit496246c92dabe6757480147016490ea6ae43bb66 (patch)
treecb922a0b1569410db44f6da17862b7e949df9fad /kernel/core/kernel.cpp
parent2f95320e0859029f520d46f777591751dcd39634 (diff)
bastion: add Kernel, Processor, AcpiTables, DeviceTree classesHEADmaster
Kernel: main singleton object, that provide access to core kernel entities Processor: empty class, that will be used later for per-CPU entities AcpiTables: class for acpi access (can be obtained through the kernel object) DeviceTree: class for dt access (can be obtained through the kernel object)
Diffstat (limited to 'kernel/core/kernel.cpp')
-rw-r--r--kernel/core/kernel.cpp283
1 files changed, 283 insertions, 0 deletions
diff --git a/kernel/core/kernel.cpp b/kernel/core/kernel.cpp
new file mode 100644
index 0000000..c2d1806
--- /dev/null
+++ b/kernel/core/kernel.cpp
@@ -0,0 +1,283 @@
+// ============================================================================
+// core/kernel.cpp - Kernel singleton implementation
+// ============================================================================
+
+#include <kernel/kernel.h>
+#include <kernel/kprint.h>
+
+using namespace kernel;
+
+// ── Static instance (lives in .bss, zero-initialized) ─────────────────────
+
+static Kernel g_kernel;
+
+Kernel& kernel::GetKernel() {
+ return g_kernel;
+}
+namespace {
+// ── Version string formatting ─────────────────────────────────────────────
+
+// TODO: move it to string lib
+// Hand-rolled integer-to-string (no sprintf in freestanding)
+static char* format_uint(char* buf, uint16_t val) {
+ if (val == 0) {
+ *buf++ = '0';
+ return buf;
+ }
+
+ char tmp[6];
+ int len = 0;
+ while (val > 0) {
+ tmp[len++] = '0' + (val % 10);
+ val /= 10;
+ }
+ for (int i = len - 1; i >= 0; i--) {
+ *buf++ = tmp[i];
+ }
+ return buf;
+}
+
+static void build_version_string(VersionInfo& ver) {
+ char* p = ver.string;
+ char* end = ver.string + sizeof(ver.string) - 1;
+
+ p = format_uint(p, ver.major);
+ if (p < end) *p++ = '.';
+ p = format_uint(p, ver.minor);
+ if (p < end) *p++ = '.';
+ p = format_uint(p, ver.patch);
+
+ if (ver.codename && p < end) {
+ *p++ = '-';
+ const char* s = ver.codename;
+ while (*s && p < end) {
+ *p++ = *s++;
+ }
+ }
+
+ *p = '\0';
+}
+
+// ── Command line helpers ──────────────────────────────────────────────────
+
+extern "C" size_t strlen(const char* s);
+
+// Check if a word (space-delimited token) is present in the command line.
+static bool cmdline_has(const char* cmdline, const char* token) {
+ size_t token_len = strlen(token);
+ const char* p = cmdline;
+
+ while (*p) {
+ // Skip leading spaces
+ while (*p == ' ') p++;
+ if (!*p) break;
+
+ // Find end of current word
+ const char* word = p;
+ while (*p && *p != ' ') p++;
+ size_t word_len = static_cast<size_t>(p - word);
+
+ if (word_len == token_len) {
+ bool match = true;
+ for (size_t i = 0; i < token_len; i++) {
+ if (word[i] != token[i]) { match = false; break; }
+ }
+ if (match) return true;
+ }
+ }
+ return false;
+}
+
+// Parse "key=<decimal>" from command line. Returns 0 if not found.
+static uint64_t cmdline_get_uint(const char* cmdline, const char* key) {
+ size_t key_len = strlen(key);
+ const char* p = cmdline;
+
+ while (*p) {
+ while (*p == ' ') p++;
+ if (!*p) break;
+
+ // Check if current word starts with "key="
+ bool prefix_match = true;
+ for (size_t i = 0; i < key_len && p[i]; i++) {
+ if (p[i] != key[i]) { prefix_match = false; break; }
+ }
+
+ if (prefix_match && p[key_len] == '=') {
+ const char* val = p + key_len + 1;
+ uint64_t result = 0;
+ while (*val >= '0' && *val <= '9') {
+ result = result * 10 + (*val - '0');
+ val++;
+ }
+ // Handle M/G suffixes
+ if (*val == 'M' || *val == 'm') result *= 1024ULL * 1024;
+ else if (*val == 'G' || *val == 'g') result *= 1024ULL * 1024 * 1024;
+ return result;
+ }
+
+ // Skip to next word
+ while (*p && *p != ' ') p++;
+ }
+ return 0;
+}
+
+static void copy_cmdline(char* dst, const char* src, size_t max_len) {
+ size_t i = 0;
+ for (; i < max_len - 1 && src[i]; i++)
+ dst[i] = src[i];
+ dst[i] = '\0';
+}
+
+} //!namespace
+
+// ── Kernel::init ──────────────────────────────────────────────────────────
+void Kernel::init(const BootInfo& boot_info) {
+ state = KernelState::Booting;
+
+ // Version info
+ version.major = CONFIG_KERNEL_VERSION_MAJOR;
+ version.minor = CONFIG_KERNEL_VERSION_MINOR;
+ version.patch = CONFIG_KERNEL_VERSION_PATCH;
+ version.codename = CONFIG_KERNEL_VERSION_NAME;
+ build_version_string(version);
+
+ // Boot parameters — parse command line if provided
+ if (boot_info.cmdline) {
+ copy_cmdline(boot_params.cmdline, boot_info.cmdline, sizeof(boot_params.cmdline));
+ boot_params.verbose = cmdline_has(boot_params.cmdline, "verbose");
+ boot_params.nosmp = cmdline_has(boot_params.cmdline, "nosmp");
+ boot_params.noacpi = cmdline_has(boot_params.cmdline, "noacpi");
+ boot_params.mem_limit = cmdline_get_uint(boot_params.cmdline, "mem");
+ }
+
+ // Log level — from boot params or compile-time config
+ if (boot_params.verbose) {
+ log_level = LogLevel::Debug;
+ }
+#ifdef CONFIG_DEBUG_VERBOSE_BOOT //TODO: fix it
+ else {
+ log_level = LogLevel::Debug;
+ }
+#endif
+
+ // Framebuffer (plain struct copy)
+ framebuffer = boot_info.framebuffer;
+
+ // Kernel load info
+ kernel_phys_base = boot_info.kernel_phys_base;
+ kernel_virt_base = boot_info.kernel_virt_base;
+ kernel_size = boot_info.kernel_size;
+ hhdm_base = boot_info.hhdm_base;
+
+ // Init Firmware
+ //TODO: when get heap fix it
+ if(boot_info.rsdp_address) {
+ tmp_acpitable[0].Init(boot_info.rsdp_address);
+ acpi = &tmp_acpitable[0];
+ dt = nullptr;
+ }
+ if(boot_info.fdt_address) {
+ tmp_devicetree[0].Init(boot_info.fdt_address);
+ dt = &tmp_devicetree[0];
+ acpi = nullptr;
+ }
+
+}
+
+// ── Boot data accessors ───────────────────────────────────────────────────
+//TODO: don't forget to remove FrameBuffer
+const FramebufferInfo& Kernel::GetFramebuffer() const {
+ return framebuffer;
+}
+
+PhysAddr Kernel::GetKernelPhysBase() const {
+ return kernel_phys_base;
+}
+
+VirtAddr Kernel::GetKernelVirtBase() const {
+ return kernel_virt_base;
+}
+
+uint64_t Kernel::GetKernelSize() const {
+ return kernel_size;
+}
+
+VirtAddr Kernel::GetHhdmBase() const {
+ return hhdm_base;
+}
+
+// ── Firmware subsystem accessors ─────────────────────────────────────────
+
+AcpiTables* Kernel::GetAcpiTables() const {
+ return acpi;
+}
+
+DeviceTree* Kernel::GetDeviceTree() const {
+ return dt;
+}
+
+// ── Accessors ─────────────────────────────────────────────────────────────
+KernelState Kernel::GetState() const {
+ return state;
+}
+
+const VersionInfo& Kernel::GetVersion() const{
+ return version;
+}
+
+const char* Kernel::GetArchName() const{
+ return arch::name();
+}
+
+// ── Boot params & log level accessors ─────────────────────────────────────
+
+const BootParams& Kernel::GetBootParams() const {
+ return boot_params;
+}
+
+LogLevel Kernel::GetLogLevel() const {
+ return log_level;
+}
+
+void Kernel::SetLogLevel(LogLevel level) {
+ log_level = level;
+}
+
+// ── State transitions ─────────────────────────────────────────────────────
+
+void Kernel::SetRunning() {
+ if (state == KernelState::Booting)
+ state = KernelState::Running;
+}
+
+void Kernel::SetHalt() {
+ if (state != KernelState::Panicked)
+ state = KernelState::Halted;
+}
+
+// ── Panic ─────────────────────────────────────────────────────────────────
+// ATM it's useless
+const PanicInfo& Kernel::GetPanicInfo() const {
+ return panic_info;
+}
+
+[[noreturn]] void Kernel::Panic(const char* msg, const char* file, const char* func, uint32_t line) {
+ state = KernelState::Panicked;
+
+ panic_info.message = msg;
+ panic_info.file = file;
+ panic_info.line = line;
+ panic_info.func = func;
+ panic_info.cpu_id = 0; // TODO: get actual CPU id when SMP is added
+
+ // Print panic banner — kcon may or may not be initialized yet
+ kcon::putchar('\n');
+ kcon::println("!!! KERNEL PANIC !!!");
+ kcon::kprintf(" %s\n", msg);
+ kcon::kprintf(" at %s:%s:%u\n", file, func, line);
+ kcon::putchar('\n');
+
+ arch::halt();
+}
+