summaryrefslogtreecommitdiff
path: root/src/kernel/fdt.cc
diff options
context:
space:
mode:
authorRichard Qin <richard.qin.x@gmail.com>2025-12-13 23:21:03 +0800
committerRichard Qin <richard.qin.x@gmail.com>2025-12-13 23:21:03 +0800
commit28fd88e0dd66728b22cd792deb5a1e8636f36ed3 (patch)
tree059cc8350adb68ca994de2c6ccf402895b575d88 /src/kernel/fdt.cc
parent27fc7bda593c8bd2c24a334a368772b5f15d4e9e (diff)
downloadlume-28fd88e0dd66728b22cd792deb5a1e8636f36ed3.tar.gz
lume-28fd88e0dd66728b22cd792deb5a1e8636f36ed3.tar.xz
feat: add preemptive scheduling, SBI timer support and FDT parser.
Diffstat (limited to 'src/kernel/fdt.cc')
-rw-r--r--src/kernel/fdt.cc134
1 files changed, 134 insertions, 0 deletions
diff --git a/src/kernel/fdt.cc b/src/kernel/fdt.cc
new file mode 100644
index 0000000..93922a7
--- /dev/null
+++ b/src/kernel/fdt.cc
@@ -0,0 +1,134 @@
+#include "common/types.h"
+#include "drivers/uart.h"
+#include "kernel/config.h"
+
+inline uint32_t bswap(uint32_t 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
+
+int strcmp(const char* s1, const char* s2)
+{
+ while (*s1 && (*s1 == *s2))
+ {
+ s1++;
+ s2++;
+ }
+ return *(const unsigned char*)s1 - *(const unsigned char*)s2;
+}
+
+int memcmp(const void *ptr1, const void *ptr2, uint32 num)
+{
+ const unsigned char *p1 = (const unsigned char *)ptr1;
+ const unsigned char *p2 = (const unsigned char *)ptr2;
+ for (uint32 i = 0; i < num; i++)
+ {
+ if (p1[i] != p2[i])
+ return p1[i] - p2[i];
+ }
+ return 0;
+}
+
+void fdt_init(uint64 dtb)
+{
+ if (dtb == 0) return;
+
+ 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));
+
+ uint64 current_reg_addr = 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)
+ {
+ while (*struct_ptr != 0)struct_ptr++;
+ struct_ptr++;
+ struct_ptr = (uint8*)(((uint64)struct_ptr + 3) & ~3);
+ }
+ else if(token == FDT_END_NODE)
+ {
+
+ }
+ 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)
+ {
+ uint32 hi = bswap(*(uint32*)data);
+ uint32 lo = bswap(*(uint32*)(data + 4));
+ current_reg_addr = ((uint64)hi << 32) | lo;
+ }
+
+ if(strcmp(name, "compatible") == 0)
+ {
+ if (g_uart_base == 0)
+ {
+ for(uint32 i = 0; i < len; i++)
+ {
+ if (data[i] == 'n' && data[i + 1] == 's' && data[i + 2] == '1')
+ {
+ g_uart_base = current_reg_addr;
+ break;
+ }
+ }
+ }
+
+ // if (g_clint_base == 0)
+ // {
+ // for (uint32 i = 0; i < len; i++)
+ // {
+ // if (data[i] == 'c' && data[i + 1] == 'l' && data[i + 2] == 'i' && data[i + 3] == 'n')
+ // {
+ // g_clint_base = current_reg_addr;
+ // break;
+ // }
+ // }
+ // }
+ }
+ }
+ }
+
+} \ No newline at end of file