diff options
| author | Richard Qin <richard.qin.x@gmail.com> | 2025-12-13 23:21:03 +0800 |
|---|---|---|
| committer | Richard Qin <richard.qin.x@gmail.com> | 2025-12-13 23:21:03 +0800 |
| commit | 28fd88e0dd66728b22cd792deb5a1e8636f36ed3 (patch) | |
| tree | 059cc8350adb68ca994de2c6ccf402895b575d88 /src/kernel/fdt.cc | |
| parent | 27fc7bda593c8bd2c24a334a368772b5f15d4e9e (diff) | |
| download | lume-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.cc | 134 |
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 |
