#include #include #include #include #include #include #include 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); }