Files
osc2025/lib/dtb.c
2025-04-08 06:59:49 +08:00

82 lines
2.2 KiB
C

#include <errcode.h>
#include <dtb.h>
#include <utils.h>
#include <string.h>
#include <uart.h>
#include <kmalloc.h>
#include <vector.h>
void *dtb_addr;
void fdt_callback(const char *path, const vector_t *cbs, const vector_t *props)
{
for (int i = 0; i < (int)cbs->size; ++i)
if (!strcmp(path, VEC_AT(fdt_callback_t, cbs, i)->name))
VEC_AT(fdt_callback_t, cbs, i)->func(props);
}
uint32_t *fdt_struct_cur;
#define nextnode(ptr) (void *)((((uint64_t)(ptr) >> 2) + 1) << 2)
void traverse(const char *path, const vector_t *cbs)
{
vector_t *props = make_vector(0);
fdt_prop_t *prop;
const fdt_prop_header_t *prop_header;
const char *fdt_node_path = 0x0;
for (;;) {
fdt_struct_cur = ALIGN4(fdt_struct_cur);
switch (ntoh32(*fdt_struct_cur)) {
case FDT_BEGIN_NODE:
BUMP(uint32_t, uint32_t, fdt_struct_cur);
fdt_node_path = (void *)fdt_struct_cur;
do {
BUMP(uint32_t, char, fdt_struct_cur);
} while (*(char *)fdt_struct_cur != '\0');
BUMP(uint32_t, char, fdt_struct_cur); // '\0'
fdt_struct_cur = ALIGN4(fdt_struct_cur);
traverse(fdt_node_path, cbs);
break;
case FDT_END_NODE:
fdt_struct_cur = nextnode(fdt_struct_cur);
goto traverse_callback;
case FDT_PROP:
BUMP(uint32_t, uint32_t, fdt_struct_cur);
prop_header = BUMP(uint32_t, fdt_prop_header_t, fdt_struct_cur);
prop = kmalloc(sizeof(fdt_prop_t));
prop->len = ntoh32(prop_header->len);
prop->name = dtb_addr +
ntoh32(((fdt_header_t *)dtb_addr)->off_dt_strings) +
ntoh32(prop_header->nameoff);
prop->value = (void *)fdt_struct_cur;
VEC_PUSH(props, prop);
fdt_struct_cur = (void *)((uint64_t)fdt_struct_cur +
ntoh32(prop_header->len));
fdt_struct_cur = ALIGN4(fdt_struct_cur);
break;
case FDT_NOP:
fdt_struct_cur = nextnode(fdt_struct_cur);
break;
case FDT_END:
return;
default:
exit(ERR_UNREACHABLE);
}
}
traverse_callback:
fdt_callback(path, cbs, props);
}
void fdt_traverse(const vector_t *cbs)
{
fdt_struct_cur = dtb_addr + ntoh32(((fdt_header_t *)dtb_addr)->off_dt_struct);
traverse("", cbs);
}