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 (likely(val)) {
+ val->encoded = (dt_enc_t)loc.prop->val;
+ val->size = loc.prop->len;
}
-
- if (fdt_prop(current)) {
- break;
- }
-
- current++;
+ return true;
- } 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;
}
}
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);
+ if (propeq(fdt, loc, "reg")) {
+ __mkprop_ptr(loc, &node->reg);
}
- else if (propeq(it, "virtual-reg")) {
- __mkprop_ptr(it, &node->vreg);
+ else if (propeq(fdt, loc, "ranges")) {
+ __mkprop_ptr(loc, &node->ranges);
}
- else if (propeq(it, "ranges")) {
- __mkprop_ptr(it, &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 {
}
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;
}
}
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) \
&(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);
}
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)) {
- return;
- }
-
- if (__parse_stdbase_prop(it, &node->base)) {
+ if (__parse_stdflags(fdt, loc, &node->base)) {
return;
}
- if (__parse_stdnode_prop(it, node)) {
+ if (__parse_stdbase_prop(fdt, loc, &node->base)) {
return;
}
- if (parse_stdintr_prop(it, &node->intr)) {
+ if (__parse_stdnode_prop(fdt, loc, node)) {
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)) {
+ if (parse_stdintr_prop(fdt, loc, &node->intr)) {
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);
+
+ while(dtpi_has_next(&it))
+ {
+ domain = dtpi_next_hnd(&it);
- if (!master) {
- WARN("dtb: (intr_extended) malformed phandle: %d", phnd);
+ 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) {
parent = default_parent;
}
- intrupt->parent = &parent->intr;
+ intrupt->parent = parent;
__expand_extended_intr(intrupt);
}
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;
- node = NULL;
- depth[0] = NULL;
- fdt_itbegin(&it, dtctx.fdt);
+ fdt = &dtctx.fdt;
+ fdt_load(&dtctx.fdt, dtb_dropoff);
+
+ 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);
+
+ node = vzalloc(sizeof(struct dtn));
+ __init_node_regular(node);
+ llist_append(&dtctx.nodes, &node->base.nodes);
- __init_node_regular((struct dt_node*)node);
+ __dt_node_set_name(node, loc.node->name);
- llist_append(&dtctx.nodes, &node->nodes);
+ 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;
}
}
}
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);
}
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;
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;
}
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);
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));
return NULL;
}
+void
+dtpx_compile_proplet(struct dtprop_def* proplet)
+{
+ int i;
+ unsigned int acc = 0;
+ struct dtprop_def* pl;
+
+ for (i = 0; proplet[i].type && i < 10; ++i)
+ {
+ pl = &proplet[i];
+
+ if (pl->type == DTP_COMPX) {
+ if (pl->cell == 1)
+ pl->type = DTP_U32;
+ else if (pl->cell == 2)
+ pl->type = DTP_U64;
+ }
+
+ pl->acc_sz = acc;
+ acc += pl->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()
{