diff options
| author | Richard Qin <richard.qin.x@gmail.com> | 2026-07-10 11:31:46 +0800 |
|---|---|---|
| committer | Richard Qin <richard.qin.x@gmail.com> | 2026-07-10 11:31:46 +0800 |
| commit | e90b72ec3082588b296956730bd2930cf8d5d671 (patch) | |
| tree | 36ff6916af9b4176ea5a9662219d11e721f0b691 /src/kernel/fdt.cc | |
| parent | 1767d390fbf3d0c65389de46caf0b6d43ef3b6ad (diff) | |
| download | lume-e90b72ec3082588b296956730bd2930cf8d5d671.tar.gz lume-e90b72ec3082588b296956730bd2930cf8d5d671.tar.xz | |
refactor: promote new architecture to repository root
Archive the deprecated implementation under lume-legacy, make the new kernel the default root-level build, and update repository entry points without changing kernel behavior.
Diffstat (limited to 'src/kernel/fdt.cc')
| -rw-r--r-- | src/kernel/fdt.cc | 273 |
1 files changed, 0 insertions, 273 deletions
diff --git a/src/kernel/fdt.cc b/src/kernel/fdt.cc deleted file mode 100644 index ae09c84..0000000 --- a/src/kernel/fdt.cc +++ /dev/null @@ -1,273 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -/* - * Copyright (C) 2026 Richard Qin - * LumeOS - FDT Parser - * - * Parses the Flattened Device Tree to discover hardware. - * Populates g_devices for use by all drivers. - */ -#include "common/types.h" -#include "kernel/fdt.h" -#include "lib/string.h" - -// Global device registry -DeviceRegistry g_devices; - -// Keep g_dtb_addr for PMM to protect DTB pages -// g_dtb_addr is defined in entry.S, g_uart_base in config.cc -extern "C" uint64 g_dtb_addr; -extern uint64 g_uart_base; - -static inline uint32 bswap(uint32 x) -{ - return ((x & 0xFF) << 24) | ((x & 0xFF00) << 8) | - ((x & 0xFF0000) >> 8) | ((x >> 24) & 0xFF); -} - -struct fdt_header -{ - uint32 magic; - uint32 totalsize; - uint32 off_dt_struct; - uint32 off_dt_strings; - uint32 off_mem_rsvmap; - uint32 version; - uint32 last_comp_version; - uint32 boot_cpuid_phys; - uint32 size_dt_strings; - uint32 size_dt_struct; -}; - -#define FDT_MAGIC 0xd00dfeed -#define FDT_BEGIN_NODE 1 -#define FDT_END_NODE 2 -#define FDT_PROP 3 -#define FDT_NOP 4 -#define FDT_END 9 - -// Check if 'str' starts with 'prefix' -static bool starts_with(const char *str, const char *prefix) -{ - while (*prefix) - { - if (*str != *prefix) - return false; - str++; - prefix++; - } - return true; -} - -// Check if 'haystack' contains 'needle' as a substring within 'len' bytes -// (compatible strings may have multiple null-separated entries) -static bool compat_match(const uint8 *data, uint32 len, const char *needle) -{ - uint32 nlen = strlen(needle); - for (uint32 i = 0; i + nlen <= len; i++) - { - if (memcmp(data + i, needle, nlen) == 0) - return true; - } - return false; -} - -// Add a MMIO region to the registry (avoids duplicates) -static void add_mmio_region(uint64 base, uint64 size) -{ - if (base == 0 || size == 0) - return; - // Only track I/O regions below RAM - if (base >= 0x80000000ULL) - return; - if (g_devices.mmio_count >= DeviceRegistry::MAX_MMIO) - return; - - // Check for overlap/duplicate - for (int i = 0; i < g_devices.mmio_count; i++) - { - if (g_devices.mmio_regions[i].base == base) - return; - } - - g_devices.mmio_regions[g_devices.mmio_count].base = base; - g_devices.mmio_regions[g_devices.mmio_count].size = size; - g_devices.mmio_count++; -} - -void fdt_parse(uint64 dtb) -{ - // Clear registry - memset(&g_devices, 0, sizeof(g_devices)); - - if (dtb == 0) - return; - - g_dtb_addr = dtb; - - struct fdt_header *header = (struct fdt_header *)dtb; - if (bswap(header->magic) != FDT_MAGIC) - return; - - uint8 *struct_ptr = (uint8 *)(dtb + bswap(header->off_dt_struct)); - char *strings_ptr = (char *)(dtb + bswap(header->off_dt_strings)); - - // Parsing state - char current_node_name[64]; - current_node_name[0] = '\0'; - - // Per-node state - uint64 current_reg_addr = 0; - uint64 current_reg_size = 0; - uint32 current_irq = 0; - const uint8 *current_compat = nullptr; - uint32 current_compat_len = 0; - bool has_reg = false; - bool has_compat = false; - // bool has_irq = false; // Unused - - // Depth tracking (for #address-cells / #size-cells) - // Default for root: 2 address-cells, 2 size-cells - int depth = 0; - - while (1) - { - uint32 token = bswap(*(uint32 *)struct_ptr); - struct_ptr += 4; - - if (token == FDT_END) - break; - if (token == FDT_NOP) - continue; - - if (token == FDT_BEGIN_NODE) - { - // Save node name - // char *name = (char *)struct_ptr; - int i = 0; - while (*struct_ptr != 0 && i < 63) - { - current_node_name[i++] = *struct_ptr; - struct_ptr++; - } - current_node_name[i] = '\0'; - while (*struct_ptr != 0) - struct_ptr++; - struct_ptr++; - struct_ptr = (uint8 *)(((uint64)struct_ptr + 3) & ~3); - - // Reset per-node state - current_reg_addr = 0; - current_reg_size = 0; - current_irq = 0; - current_compat = nullptr; - current_compat_len = 0; - has_reg = false; - has_compat = false; - // has_irq = false; - - depth++; - } - else if (token == FDT_END_NODE) - { - // Process the node we just finished - if (has_reg && has_compat) - { - // UART: ns16550a - if (compat_match(current_compat, current_compat_len, "ns16550")) - { - g_devices.uart.base_addr = current_reg_addr; - g_devices.uart.size = current_reg_size ? current_reg_size : 0x100; - g_devices.uart.irq = current_irq; - add_mmio_region(current_reg_addr, g_devices.uart.size); - } - // PLIC - else if (compat_match(current_compat, current_compat_len, "plic")) - { - g_devices.plic.base_addr = current_reg_addr; - g_devices.plic.size = current_reg_size ? current_reg_size : 0x4000000; - g_devices.plic.irq = 0; - add_mmio_region(current_reg_addr, g_devices.plic.size); - } - // CLINT - else if (compat_match(current_compat, current_compat_len, "clint")) - { - g_devices.clint.base_addr = current_reg_addr; - g_devices.clint.size = current_reg_size ? current_reg_size : 0x10000; - g_devices.clint.irq = 0; - add_mmio_region(current_reg_addr, g_devices.clint.size); - } - // VirtIO - else if (compat_match(current_compat, current_compat_len, "virtio")) - { - if (g_devices.virtio_count < DeviceRegistry::MAX_VIRTIO) - { - int idx = g_devices.virtio_count++; - g_devices.virtio[idx].base_addr = current_reg_addr; - g_devices.virtio[idx].size = current_reg_size ? current_reg_size : 0x1000; - g_devices.virtio[idx].irq = current_irq; - add_mmio_region(current_reg_addr, g_devices.virtio[idx].size); - } - } - } - - // Memory node: name starts with "memory" - if (has_reg && starts_with(current_node_name, "memory")) - { - g_devices.mem_base = current_reg_addr; - g_devices.mem_size = current_reg_size; - } - - depth--; - } - else if (token == FDT_PROP) - { - uint32 len = bswap(*(uint32 *)struct_ptr); - struct_ptr += 4; - uint32 nameoff = bswap(*(uint32 *)struct_ptr); - struct_ptr += 4; - - char *name = strings_ptr + nameoff; - uint8 *data = struct_ptr; - - struct_ptr += len; - struct_ptr = (uint8 *)(((uint64)struct_ptr + 3) & ~3); - - if (strcmp(name, "reg") == 0 && len >= 8) - { - // Assume 2 address-cells, 2 size-cells (standard for QEMU virt) - uint32 hi = bswap(*(uint32 *)data); - uint32 lo = bswap(*(uint32 *)(data + 4)); - current_reg_addr = ((uint64)hi << 32) | lo; - - if (len >= 16) - { - uint32 shi = bswap(*(uint32 *)(data + 8)); - uint32 slo = bswap(*(uint32 *)(data + 12)); - current_reg_size = ((uint64)shi << 32) | slo; - } - has_reg = true; - } - else if (strcmp(name, "compatible") == 0) - { - current_compat = data; - current_compat_len = len; - has_compat = true; - } - else if (strcmp(name, "interrupts") == 0 && len >= 4) - { - current_irq = bswap(*(uint32 *)data); - // has_irq = true; - } - else if (strcmp(name, "interrupts-extended") == 0 && len >= 8) - { - // interrupts-extended = <&phandle irq_num> - // IRQ number is typically the second cell - current_irq = bswap(*(uint32 *)(data + 4)); - // has_irq = true; - } - } - } - - // Legacy compat - g_uart_base = g_devices.uart.base_addr; -}
\ No newline at end of file |
