X-Git-Url: https://scm.lunaixsky.com/lunaix-os.git/blobdiff_plain/35a7d633d3f16c1e0539af6ca5d8e7482926cd93..7e13988c1113d38bec17bd79b71757d78d977e76:/lunaix-os/hal/devtree/dt.c diff --git a/lunaix-os/hal/devtree/dt.c b/lunaix-os/hal/devtree/dt.c index f1d6860..a426551 100644 --- a/lunaix-os/hal/devtree/dt.c +++ b/lunaix-os/hal/devtree/dt.c @@ -9,152 +9,317 @@ LOG_MODULE("dtb") static morph_t* devtree_obj_root; static struct dt_context dtctx; -void -fdt_itbegin(struct fdt_iter* fdti, struct fdt_header* fdt_hdr) +void +fdt_load(struct fdt_blob* fdt, ptr_t base) { - unsigned int off_struct, off_str; - struct fdt_token* tok; - const char* str_blk; + struct fdt_header* hdr; - off_str = le(fdt_hdr->off_dt_strings); - off_struct = le(fdt_hdr->off_dt_struct); + fdt->fdt_base = base; - tok = offset_t(fdt_hdr, struct fdt_token, off_struct); - str_blk = offset_t(fdt_hdr, const char, off_str); - - *fdti = (struct fdt_iter) { - .pos = tok, - .str_block = str_blk - }; -} + hdr = fdt->header; + if (hdr->magic != FDT_MAGIC) { + FATAL("invalid dtb, unexpected magic: 0x%x, expect: 0x%x", + hdr->magic, FDT_MAGIC); + } -void -fdt_itend(struct fdt_iter* fdti) -{ - fdti->pos = NULL; + fdt->plat_rsvd_base = base + hdr->off_mem_rsvmap; + fdt->str_block_base = base + hdr->off_dt_strings; + fdt->root.ptr = base + hdr->off_dt_struct; } bool -fdt_itnext(struct fdt_iter* fdti) +fdt_next_boot_rsvdmem(struct fdt_blob* fdt, fdt_loc_t* loc, + struct dt_memory_node* mem) { - struct fdt_token *current; - struct fdt_prop *prop; + fdt_loc_t current; - current = fdti->pos; - if (!current) { + current = *loc; + + if (!current.rsvd_ent->addr && !current.rsvd_ent->addr) { return false; } + mem->base = current.rsvd_ent->addr; + mem->size = current.rsvd_ent->size; + mem->type = FDT_MEM_RSVD; + + current.rsvd_ent++; + *loc = current; + + return true; +} + +fdt_loc_t +fdt_next_token(fdt_loc_t loc, int* delta_depth) +{ + int d = 0; + + do { + if (fdt_node(loc.token)) { + d++; + loc.ptr += strlen(loc.node->name) + 1; + loc.ptr = ROUNDUP(loc.ptr, sizeof(int)); + } + else if (fdt_node_end(loc.token)) { + d--; + } + else if (fdt_prop(loc.token)) { + loc.ptr += loc.prop->len + 2 * sizeof(int); + loc.ptr = ROUNDUP(loc.ptr, sizeof(int)); + } + + loc.token++; + } while (fdt_nope(loc.token)); + + *delta_depth = d; + return loc; +} + +bool +fdt_next_sibling(fdt_loc_t loc, fdt_loc_t* loc_out) +{ + int depth = 0, new_depth = 0; + + do { + loc = fdt_next_token(loc, &new_depth); + depth += new_depth; + } while (depth > 0); + + *loc_out = loc; + return !fdt_node_end(loc.token); +} + +fdt_loc_t +fdt_descend_into(fdt_loc_t loc) +{ + fdt_loc_t new_loc; + int depth = 0; + + new_loc = fdt_next_token(loc, &depth); + + return depth != 1 ? loc : new_loc; +} + +bool +fdt_find_prop(const struct fdt_blob* fdt, fdt_loc_t loc, + const char* name, struct dtp_val* val) +{ + char* prop_name; + + loc = fdt_descend_into(loc); + do { - if (fdt_nope(current)) { + if (!fdt_prop(loc.token)) { continue; } - if (fdt_prop(current)) { - prop = (struct fdt_prop*) current; - current = offset(current, prop->len); - continue; - } + prop_name = fdt_prop_key(fdt, loc); - if (fdt_node_end(current)) { - fdti->depth--; + if (!streq(prop_name, name)) { continue; } - // node begin - - fdti->depth++; - if (fdti->depth == 1) { - // enter root node - break; - } - - while (!fdt_prop(current) && !fdt_node_end(current)) { - current++; - } - - if (fdt_prop(current)) { - break; + if (likely(val)) { + val->encoded = (dt_enc_t)loc.prop->val; + val->size = loc.prop->len; } + return true; - current++; - - } while (fdt_nope(current) && fdti->depth > 0); + } while (fdt_next_sibling(loc, &loc)); - return fdti->depth > 0; + return false; } -bool -fdt_itnext_at(struct fdt_iter* fdti, int level) +bool +fdt_memscan_begin(struct fdt_memscan* mscan, const struct fdt_blob* fdt) { - while (fdti->depth != level && fdt_itnext(fdti)); - - return fdti->depth == level; + struct dtp_val val; + fdt_loc_t loc; + + loc = fdt->root; + loc = fdt_descend_into(loc); + + if (fdt_find_prop(fdt, loc, "#address-cells", &val)) + { + mscan->root_addr_c = val.ref->u32_val; + } + + if (fdt_find_prop(fdt, loc, "#size-cells", &val)) + { + mscan->root_size_c = val.ref->u32_val; + } + + mscan->loc = loc; + mscan->node_type = FDT_MEM_FREE; } -void -fdt_memrsvd_itbegin(struct fdt_memrsvd_iter* rsvdi, - struct fdt_header* fdt_hdr) +#define get_size(mscan, val) \ + (mscan->root_size_c == 1 ? (val)->ref->u32_val : (val)->ref->u64_val) + +#define get_addr(mscan, val) \ + (mscan->root_addr_c == 1 ? (val)->ref->u32_val : (val)->ref->u64_val) + +bool +fdt_memscan_nextnode(struct fdt_memscan* mscan, struct fdt_blob* fdt) { - size_t off = le(fdt_hdr->off_mem_rsvmap); + char* prop_name; + + struct dtp_val val, reg_val; + fdt_loc_t loc, next; + struct dtpropi dtpi; + bool has_reg = false, found = false; + + next = mscan->loc; + +restart: + do + { + loc = next; + + if (!fdt_node(loc.token)) + continue; + + if (mscan->node_type != FDT_MEM_FREE) { + found = true; + continue; + } + + if (streq(loc.node->name, "reserved-memory")) { + // dived into /reserved-memory, walking for childrens + mscan->node_type = FDT_MEM_RSVD; + loc = fdt_descend_into(loc); + continue; + } + + if (!fdt_find_prop(fdt, loc, "device_type", &val)) + continue; + + if (!streq(val.str_val, "memory")) + continue; + + found = true; + } while (fdt_next_sibling(loc, &next) && !found); + + if (found) goto _found; + + // emerged from /reserved-memory, resume walking for /memory + if (mscan->node_type != FDT_MEM_FREE) { + mscan->node_type = FDT_MEM_FREE; + goto restart; + } + + return false; + +_found: + + dtpi_init_empty(&mscan->regit); + mscan->found = loc; + mscan->loc = next; + + has_reg = fdt_find_prop(fdt, loc, "reg", &val); + if (mscan->node_type == FDT_MEM_RSVD) { + goto do_rsvd_child; + } + + if (!has_reg) + { + WARN("malformed memory node"); + goto restart; + } + + dtpi_init(&mscan->regit, &val); + + return true; + +do_rsvd_child: + + mscan->node_attr.nomap = fdt_find_prop(fdt, loc, "no-map", NULL); + mscan->node_attr.reusable = fdt_find_prop(fdt, loc, "reusable", NULL); + + if (has_reg) + { + dtpi_init(&mscan->regit, &val); + mscan->node_type = FDT_MEM_RSVD; + return true; + } - rsvdi->block = - offset_t(fdt_hdr, typeof(*rsvdi->block), off); + if (!fdt_find_prop(fdt, loc, "size", &val)) + { + WARN("malformed reserved memory child node"); + goto restart; + } - rsvdi->block = &rsvdi->block[-1]; + mscan->node_type = FDT_MEM_RSVD_DYNAMIC; + mscan->node_attr.total_size = get_size(mscan, &val); + + if (fdt_find_prop(fdt, loc, "alignment", &val)) { + mscan->node_attr.alignment = get_size(mscan, &val); + } + + if (fdt_find_prop(fdt, loc, "alloc-ranges", &val)) { + dtpi_init(&mscan->regit, &val); + } + + return true; } bool -fdt_memrsvd_itnext(struct fdt_memrsvd_iter* rsvdi) +fdt_memscan_nextrange(struct fdt_memscan* mscan, struct dt_memory_node* mem) { - struct fdt_memrsvd_ent* ent; + struct dtp_val val; - ent = rsvdi->block; - if (!ent) { + if (dtpi_is_empty(&mscan->regit)) { return false; } - rsvdi->block++; + if (!dtpi_has_next(&mscan->regit)) { + return false; + } - return ent->addr || ent->size; -} + if (dtpi_next_val(&mscan->regit, &val, mscan->root_addr_c)) { + mem->base = get_addr(mscan, &val); + } -void -fdt_memrsvd_itend(struct fdt_memrsvd_iter* rsvdi) -{ - rsvdi->block = NULL; + if (dtpi_next_val(&mscan->regit, &val, mscan->root_size_c)) { + mem->size = get_size(mscan, &val); + } + + mem->type = mscan->node_type; + + if (mem->type == FDT_MEM_RSVD_DYNAMIC) { + mem->dyn_alloc_attr = mscan->node_attr; + } + + return true; } static bool -__parse_stdbase_prop(struct fdt_iter* it, struct dt_node_base* node) +__parse_stdbase_prop(struct fdt_blob* fdt, fdt_loc_t loc, + struct dtn_base* node) { - struct fdt_prop* prop; - - prop = it->prop; - - if (propeq(it, "compatible")) { - __mkprop_ptr(it, &node->compat); + if (propeq(fdt, loc, "compatible")) { + __mkprop_ptr(loc, &node->compat); } - else if (propeq(it, "phandle")) { - node->phandle = __prop_getu32(it); + else if (propeq(fdt, loc, "phandle")) { + node->phandle = __prop_getu32(loc); } - else if (propeq(it, "#address-cells")) { - node->addr_c = (char)__prop_getu32(it); + else if (propeq(fdt, loc, "#address-cells")) { + node->addr_c = (char)__prop_getu32(loc); } - else if (propeq(it, "#size-cells")) { - node->sz_c = (char)__prop_getu32(it); + else if (propeq(fdt, loc, "#size-cells")) { + node->sz_c = (char)__prop_getu32(loc); } - else if (propeq(it, "#interrupt-cells")) { - node->intr_c = (char)__prop_getu32(it); + else if (propeq(fdt, loc, "#interrupt-cells")) { + node->intr_c = (char)__prop_getu32(loc); } - else if (propeq(it, "status")) { - char peek = *(char*)&it->prop[1]; + else if (propeq(fdt, loc, "status")) { + char peek = loc.prop->val_str[0]; if (peek == 'o') { node->status = STATUS_OK; } @@ -177,22 +342,18 @@ __parse_stdbase_prop(struct fdt_iter* it, struct dt_node_base* node) } static bool -__parse_stdnode_prop(struct fdt_iter* it, struct dt_node* node) +__parse_stdnode_prop(struct fdt_blob* fdt, fdt_loc_t loc, struct dtn* node) { - if (propeq(it, "reg")) { - __mkprop_ptr(it, &node->reg); - } - - else if (propeq(it, "virtual-reg")) { - __mkprop_ptr(it, &node->vreg); + if (propeq(fdt, loc, "reg")) { + __mkprop_ptr(loc, &node->reg); } - else if (propeq(it, "ranges")) { - __mkprop_ptr(it, &node->ranges); + else if (propeq(fdt, loc, "ranges")) { + __mkprop_ptr(loc, &node->ranges); } - else if (propeq(it, "dma-ranges")) { - __mkprop_ptr(it, &node->dma_ranges); + else if (propeq(fdt, loc, "dma-ranges")) { + __mkprop_ptr(loc, &node->dma_ranges); } else { @@ -203,17 +364,17 @@ __parse_stdnode_prop(struct fdt_iter* it, struct dt_node* node) } static bool -__parse_stdflags(struct fdt_iter* it, struct dt_node_base* node) +__parse_stdflags(struct fdt_blob* fdt, fdt_loc_t loc, struct dtn_base* node) { - if (propeq(it, "dma-coherent")) { + if (propeq(fdt, loc, "dma-coherent")) { node->dma_coherent = true; } - else if (propeq(it, "dma-noncoherent")) { + else if (propeq(fdt, loc, "dma-noncoherent")) { node->dma_ncoherent = true; } - else if (propeq(it, "interrupt-controller")) { + else if (propeq(fdt, loc, "interrupt-controller")) { node->intr_controll = true; } @@ -225,18 +386,20 @@ __parse_stdflags(struct fdt_iter* it, struct dt_node_base* node) } static inline void -__dt_node_set_name(struct dt_node_base* node, const char* name) +__dt_node_set_name(struct dtn* node, const char* name) { changeling_setname(&node->mobj, name); } static inline void -__init_prop_table(struct dt_node_base* node) +__init_prop_table(struct dtn_base* node) { - struct dt_prop_table* propt; + struct dtp_table* propt; propt = valloc(sizeof(*propt)); hashtable_init(propt->_op_bucket); + + node->props = propt; } #define prop_table_add(node, prop) \ @@ -244,17 +407,17 @@ __init_prop_table(struct dt_node_base* node) &(prop)->ht, (prop)->key.hash); static void -__parse_other_prop(struct fdt_iter* it, struct dt_node_base* node) +__parse_other_prop(struct fdt_blob* fdt, fdt_loc_t loc, struct dtn_base* node) { - struct dt_prop* prop; + struct dtp* prop; const char* key; unsigned int hash; prop = valloc(sizeof(*prop)); - key = fdtit_prop_key(it); + key = fdt_prop_key(fdt, loc); prop->key = HSTR(key, strlen(key)); - __mkprop_ptr(it, &prop->val); + __mkprop_ptr(loc, &prop->val); hstr_rehash(&prop->key, HSTR_FULL_HASH); @@ -262,137 +425,116 @@ __parse_other_prop(struct fdt_iter* it, struct dt_node_base* node) } static void -__fill_node(struct fdt_iter* it, struct dt_node* node) +__fill_node(struct fdt_blob* fdt, fdt_loc_t loc, struct dtn* node) { - if (__parse_stdflags(it, &node->base)) { + if (__parse_stdflags(fdt, loc, &node->base)) { return; } - if (__parse_stdbase_prop(it, &node->base)) { + if (__parse_stdbase_prop(fdt, loc, &node->base)) { return; } - if (__parse_stdnode_prop(it, node)) { + if (__parse_stdnode_prop(fdt, loc, node)) { return; } - if (parse_stdintr_prop(it, &node->intr)) { + if (parse_stdintr_prop(fdt, loc, &node->intr)) { return; } - __parse_other_prop(it, &node->base); -} - -static void -__fill_root(struct fdt_iter* it, struct dt_root* node) -{ - if (__parse_stdflags(it, &node->base)) { - return; - } - - if (__parse_stdbase_prop(it, &node->base)) { - return; - } - - struct fdt_prop* prop; - - prop = it->prop; - if (propeq(it, "serial-number")) { - node->serial = (const char*)&prop[1]; - } - - else if (propeq(it, "chassis-type")) { - node->chassis = (const char*)&prop[1]; - } - - __parse_other_prop(it, &node->base); + __parse_other_prop(fdt, loc, &node->base); } static inline void -__init_node(struct dt_node_base* node) +__set_parent(struct dtn_base* parent, struct dtn_base* node) { - morph_t* parent; - - parent = devtree_obj_root; - if (node->parent) { - parent = node->mobj.parent; - node->_std = node->parent->_std; + morph_t* parent_obj; + + parent_obj = devtree_obj_root; + node->parent = parent; + + if (parent) { + node->addr_c = parent->addr_c; + node->sz_c = parent->sz_c; + node->intr_c = parent->intr_c; + parent_obj = dt_mobj(parent); } - __init_prop_table(node); - changeling_morph_anon(parent, node->mobj, dt_morpher); + changeling_attach(parent_obj, dt_mobj(node)); } static inline void -__init_node_regular(struct dt_node* node) +__init_node_regular(struct dtn* node) { - __init_node(&node->base); + __init_prop_table(&node->base); + changeling_morph_anon(NULL, node->mobj, dt_morpher); + node->intr.parent_hnd = PHND_NULL; } static void -__expand_extended_intr(struct dt_intr_node* intrupt) +__expand_extended_intr(struct dtn_intr* intrupt) { - struct dt_prop_iter it; - struct dt_prop_val arr; - struct dt_node *node; - struct dt_node *master; - struct dt_intr_prop* intr_prop; + struct dtpropi it; + struct dtp_val arr; + struct dtn *domain; + struct dtspec_intr* ispec; + int nr_intrs = 0; - if (!intrupt->intr.extended) { - return; + if (!intrupt->extended) { + nr_intrs = intrupt->raw_ispecs.size / sizeof(u32_t); + nr_intrs /= intrupt->parent->base.intr_c; + goto done; } - arr = intrupt->intr.arr; - node = INTR_TO_DTNODE(intrupt); + arr = intrupt->raw_ispecs; - llist_init_head(&intrupt->intr.values); + llist_init_head(&intrupt->ext_ispecs); - dt_decode(&it, &node->base, &arr, 1); - - dt_phnd_t phnd; - do { - phnd = dtprop_to_u32(it.prop_loc); - master = dt_resolve_phandle(phnd); + dtpi_init(&it, &arr); - if (!master) { - WARN("dtb: (intr_extended) malformed phandle: %d", phnd); + while(dtpi_has_next(&it)) + { + domain = dtpi_next_hnd(&it); + + if (!domain) { + WARN("(intr_extended) malformed phandle"); continue; } - intr_prop = valloc(sizeof(*intr_prop)); - - intr_prop->master = &master->intr; - intr_prop->val = (struct dt_prop_val) { - .encoded = it.prop_loc_next, - .size = master->base.intr_c - }; - - llist_append(&intrupt->intr.values, &intr_prop->props); - dtprop_next_n(&it, intr_prop->val.size); + ispec = valloc(sizeof(*ispec)); - } while(dtprop_next(&it)); + ispec->domain = domain; + dtpi_next_val(&it, &ispec->val, domain->base.intr_c); + + llist_append(&intrupt->ext_ispecs, &ispec->ispecs); + nr_intrs++; + }; + +done: + intrupt->nr_intrs = nr_intrs; } static void __resolve_phnd_references() { - struct dt_node_base *pos, *n; - struct dt_node *node, *parent, *default_parent; - struct dt_intr_node* intrupt; + struct dtn_base *pos, *n; + struct dtn *node, *parent, *default_parent; + struct dtn_intr* intrupt; dt_phnd_t phnd; llist_for_each(pos, n, &dtctx.nodes, nodes) { - node = BASE_TO_DTNODE(pos); + node = dtn_from(pos); intrupt = &node->intr; - if (!node->base.intr_c) { + if (intrupt->parent_hnd == PHND_NULL) { continue; } phnd = intrupt->parent_hnd; - default_parent = (struct dt_node*)node->base.parent; + default_parent = (struct dtn*)node->base.parent; parent = default_parent; if (phnd != PHND_NULL) { @@ -404,7 +546,7 @@ __resolve_phnd_references() parent = default_parent; } - intrupt->parent = &parent->intr; + intrupt->parent = parent; __expand_extended_intr(intrupt); } @@ -413,100 +555,98 @@ __resolve_phnd_references() static void __resolve_inter_map() { - struct dt_node_base *pos, *n; + struct dtn_base *pos, *n; llist_for_each(pos, n, &dtctx.nodes, nodes) { - dt_resolve_interrupt_map(BASE_TO_DTNODE(pos)); + dt_resolve_interrupt_map(dtn_from(pos)); } } bool dt_load(ptr_t dtb_dropoff) { - dtctx.reloacted_dtb = dtb_dropoff; - - if (dtctx.fdt->magic != FDT_MAGIC) { - ERROR("invalid dtb, unexpected magic: 0x%x", dtctx.fdt->magic); - return false; - } - - size_t str_off = le(dtctx.fdt->size_dt_strings); - dtctx.str_block = offset_t(dtb_dropoff, const char, str_off); - llist_init_head(&dtctx.nodes); hashtable_init(dtctx.phnds_table); - struct fdt_iter it; - struct fdt_token* tok; - struct dt_node_base *node, *prev; + struct fdt_blob *fdt; + struct dtn *node, + *stack[16] = { NULL }; - struct dt_node_base* depth[16]; - bool is_root_level, filled; + int depth = 0, delta = 0, nr_nodes = 0; + fdt_loc_t loc, next_loc; + + fdt = &dtctx.fdt; + fdt_load(&dtctx.fdt, dtb_dropoff); - node = NULL; - depth[0] = NULL; - fdt_itbegin(&it, dtctx.fdt); + loc = fdt->root; - while (fdt_itnext(&it)) { - is_root_level = it.depth == 1; + while (!fdt_eof(loc.token)) + { + next_loc = fdt_next_token(loc, &delta); - if (it.depth >= 16) { + if (depth >= 16) { // tree too deep ERROR("strange dtb, too deep to dive."); return false; } - depth[it.depth] = NULL; - node = depth[it.depth - 1]; + assert(depth >= 0); + node = stack[depth]; - if (!node) { - // need new node - if (unlikely(is_root_level)) { - node = vzalloc(sizeof(struct dt_root)); - __init_node(node); - } - else { - node = vzalloc(sizeof(struct dt_node)); - prev = depth[it.depth - 2]; - node->parent = prev; + if (fdt_node(loc.token)) + { + assert(!node); - __init_node_regular((struct dt_node*)node); + node = vzalloc(sizeof(struct dtn)); + __init_node_regular(node); + llist_append(&dtctx.nodes, &node->base.nodes); - llist_append(&dtctx.nodes, &node->nodes); + __dt_node_set_name(node, loc.node->name); + + if (depth) { + __set_parent(&stack[depth - 1]->base, &node->base); } - __dt_node_set_name(node, (const char*)&it.pos[1]); + nr_nodes++; + stack[depth] = node; } - if (unlikely(is_root_level)) { - __fill_root(&it, (struct dt_root*)node); + else if (depth > 1 && fdt_node_end(loc.token)) + { + stack[depth - 1] = NULL; } - else { - __fill_node(&it, (struct dt_node*)node); + + else if (fdt_prop(loc.token)) + { + node = stack[depth - 1]; + + assert(depth && node); + __fill_node(fdt, loc, node); } - } - fdt_itend(&it); + depth += delta; + loc = next_loc; + } - dtctx.root = (struct dt_root*)depth[0]; + dtctx.root = stack[0]; __resolve_phnd_references(); __resolve_inter_map(); - INFO("device tree loaded"); + INFO("%d nodes loaded.", nr_nodes); return true; } -struct dt_node* +struct dtn* dt_resolve_phandle(dt_phnd_t phandle) { - struct dt_node_base *pos, *n; + struct dtn_base *pos, *n; llist_for_each(pos, n, &dtctx.nodes, nodes) { if (pos->phandle == phandle) { - return (struct dt_node*)pos; + return (struct dtn*)pos; } } @@ -514,7 +654,7 @@ dt_resolve_phandle(dt_phnd_t phandle) } static bool -__byname_predicate(struct dt_node_iter* iter, struct dt_node_base* node) +__byname_predicate(struct dtn_iter* iter, struct dtn_base* node) { int i = 0; const char* be_matched = HSTR_VAL(node->mobj.name); @@ -533,17 +673,17 @@ __byname_predicate(struct dt_node_iter* iter, struct dt_node_base* node) } void -dt_begin_find_byname(struct dt_node_iter* iter, - struct dt_node* node, const char* name) +dt_begin_find_byname(struct dtn_iter* iter, + struct dtn* node, const char* name) { dt_begin_find(iter, node, __byname_predicate, name); } void -dt_begin_find(struct dt_node_iter* iter, struct dt_node* node, +dt_begin_find(struct dtn_iter* iter, struct dtn* node, node_predicate_t pred, void* closure) { - node = node ? : (struct dt_node*)dtctx.root; + node = node ? : (struct dtn*)dtctx.root; iter->head = &node->base; iter->matched = NULL; @@ -551,7 +691,7 @@ dt_begin_find(struct dt_node_iter* iter, struct dt_node* node, iter->pred = pred; morph_t *pos, *n; - struct dt_node_base* base; + struct dtn_base* base; changeling_for_each(pos, n, &node->mobj) { base = &changeling_reveal(pos, dt_morpher)->base; @@ -563,14 +703,14 @@ dt_begin_find(struct dt_node_iter* iter, struct dt_node* node, } bool -dt_find_next(struct dt_node_iter* iter, - struct dt_node_base** matched) +dt_find_next(struct dtn_iter* iter, + struct dtn_base** matched) { if (!dt_found_any(iter)) { return false; } - struct dt_node *node; + struct dtn *node; morph_t *pos, *head; head = dt_mobj(iter->head); @@ -593,11 +733,11 @@ dt_find_next(struct dt_node_iter* iter, return false; } -struct dt_prop_val* -dt_getprop(struct dt_node_base* base, const char* name) +struct dtp_val* +dt_getprop(struct dtn_base* base, const char* name) { struct hstr hashed_name; - struct dt_prop *pos, *n; + struct dtp *pos, *n; unsigned int hash; hashed_name = HSTR(name, strlen(name)); @@ -614,6 +754,148 @@ dt_getprop(struct dt_node_base* base, const char* name) return NULL; } +void +dtpx_compile_proplet(struct dtprop_def* proplet) +{ + int i; + unsigned int acc = 0; + + for (i = 0; proplet[i].type && i < 10; ++i) + { + proplet[i].acc_sz = acc; + acc += proplet[i].cell; + } + + if (proplet[i - 1].type && i == 10) { + FATAL("invalid proplet: no terminator detected"); + } + + proplet[i].acc_sz = acc; +} + +void +dtpx_prepare_with(struct dtpropx* propx, struct dtp_val* prop, + struct dtprop_def* proplet) +{ + int i; + bool has_str = false; + + for (i = 0; proplet[i].type; ++i); + + propx->proplet = proplet; + propx->proplet_len = i; + propx->proplet_sz = proplet[i].acc_sz; + propx->raw = prop; + propx->row_loc = 0; +} + +bool +dtpx_goto_row(struct dtpropx* propx, int row) +{ + off_t loc; + + loc = propx->proplet_sz; + loc *= row; + + if (loc * sizeof(u32_t) >= propx->raw->size) { + return false; + } + + propx->row_loc = loc; + return true; +} + +bool +dtpx_next_row(struct dtpropx* propx) +{ + off_t loc; + + loc = propx->row_loc; + loc += propx->proplet_sz; + + if (loc * sizeof(u32_t) >= propx->raw->size) { + return false; + } + + propx->row_loc = loc; + return true; +} + +bool +dtpx_extract_at(struct dtpropx* propx, + struct dtprop_xval* val, int col) +{ + struct dtprop_def* def; + union dtp_baseval* raw; + dt_enc_t enc; + + if (unlikely(col >= propx->proplet_len)) { + return false; + } + + def = &propx->proplet[col]; + enc = &propx->raw->encoded[propx->row_loc + def->acc_sz]; + raw = (union dtp_baseval*)enc; + + val->archetype = def; + + switch (def->type) + { + case DTP_U32: + val->u32 = raw->u32_val; + break; + + case DTP_U64: + val->u64 = raw->u64_val; + break; + + case DTP_PHANDLE: + { + ptr_t hnd = raw->phandle; + val->phandle = dt_resolve_phandle(hnd); + } break; + + case DTP_COMPX: + val->composite = enc; + break; + + default: + break; + } + + return true; +} + +bool +dtpx_extract_loc(struct dtpropx* propx, + struct dtprop_xval* val, int row, int col) +{ + ptr_t loc = propx->row_loc; + + if (!dtpx_goto_row(propx, row)) + return false; + + + bool r = dtpx_extract_at(propx, val, col); + propx->row_loc = loc; + return r; +} + +bool +dtpx_extract_row(struct dtpropx* propx, struct dtprop_xval* vals, int len) +{ + assert(len == propx->proplet_len); + + for (int i = 0; i < len; i++) + { + if (!dtpx_extract_at(propx, &vals[i], i)) { + return false; + } + } + + return true; +} + struct dt_context* dt_main_context() {