cherry pick device tree modifications from isa/arm64
[lunaix-os.git] / lunaix-os / hal / devtree.c
diff --git a/lunaix-os/hal/devtree.c b/lunaix-os/hal/devtree.c
deleted file mode 100644 (file)
index 81712ec..0000000
+++ /dev/null
@@ -1,629 +0,0 @@
-#include <lunaix/mm/valloc.h>
-#include <lunaix/syslog.h>
-
-#include <klibc/string.h>
-
-#include <hal/devtree.h>
-
-LOG_MODULE("dtb")
-
-static struct dt_context dtctx;
-
-void 
-fdt_itbegin(struct fdt_iter* fdti, struct fdt_header* fdt_hdr)
-{
-    unsigned int off_struct, off_str;
-    struct fdt_token* tok;
-    const char* str_blk;
-
-    off_str    = le(fdt_hdr->off_dt_strings);
-    off_struct = le(fdt_hdr->off_dt_struct);
-
-    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
-    };
-}
-
-void 
-fdt_itend(struct fdt_iter* fdti)
-{
-    fdti->pos = NULL;
-}
-
-bool
-fdt_itnext(struct fdt_iter* fdti)
-{
-    struct fdt_token *current;
-    struct fdt_prop  *prop;
-
-    current = fdti->pos;
-    if (!current) {
-        return false;
-    }
-
-    do
-    {
-        if (fdt_nope(current)) {
-            continue;
-        }
-
-        if (fdt_prop(current)) {
-            prop    = (struct fdt_prop*) current;
-            current = offset(current, prop->len);
-            continue;
-        }
-        
-        if (fdt_node_end(current)) {
-            fdti->depth--;
-            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;
-        }
-        
-        current++;
-        
-    } while (fdt_nope(current) && fdti->depth > 0);
-
-    return fdti->depth > 0;
-}
-
-bool 
-fdt_itnext_at(struct fdt_iter* fdti, int level)
-{
-    while (fdti->depth != level && fdt_itnext(fdti));
-    
-    return fdti->depth == level;
-}
-
-void
-fdt_memrsvd_itbegin(struct fdt_memrsvd_iter* rsvdi, 
-                    struct fdt_header* fdt_hdr)
-{
-    size_t off = le(fdt_hdr->off_mem_rsvmap);
-    
-    rsvdi->block = 
-        offset_t(fdt_hdr, typeof(*rsvdi->block), off);
-    
-    rsvdi->block = &rsvdi->block[-1];
-}
-
-bool
-fdt_memrsvd_itnext(struct fdt_memrsvd_iter* rsvdi)
-{
-    struct fdt_memrsvd_ent* ent;
-
-    ent = rsvdi->block;
-    if (!ent) {
-        return false;
-    }
-
-    rsvdi->block++;
-
-    return ent->addr || ent->size;
-}
-
-void
-fdt_memrsvd_itend(struct fdt_memrsvd_iter* rsvdi)
-{
-    rsvdi->block = NULL;
-}
-
-static inline bool
-propeq(struct fdt_iter* it, const char* key)
-{
-    return streq(fdtit_prop_key(it), key);
-}
-
-static inline void
-__mkprop_val32(struct fdt_iter* it, struct dt_prop_val* val)
-{
-    val->u32_val = le(*(u32_t*)&it->prop[1]);
-    val->size = le(it->prop->len);
-}
-
-static inline void
-__mkprop_val64(struct fdt_iter* it, struct dt_prop_val* val)
-{
-    val->u64_val = le64(*(u64_t*)&it->prop[1]);
-    val->size = le(it->prop->len);
-}
-
-static inline void
-__mkprop_ptr(struct fdt_iter* it, struct dt_prop_val* val)
-{
-    val->ptr_val = __ptr(&it->prop[1]);
-    val->size = le(it->prop->len);
-}
-
-static inline u32_t
-__prop_getu32(struct fdt_iter* it)
-{
-    return le(*(u32_t*)&it->prop[1]);
-}
-
-static bool
-__parse_stdbase_prop(struct fdt_iter* it, struct dt_node_base* node)
-{
-    struct fdt_prop* prop;
-
-    prop = it->prop;
-
-    if (propeq(it, "compatible")) {
-        __mkprop_ptr(it, &node->compat);
-    } 
-    
-    else if (propeq(it, "model")) {
-        node->model = (const char*)&prop[1];
-    } 
-
-    else if (propeq(it, "phandle")) {
-        node->phandle = __prop_getu32(it);
-        hashtable_hash_in(dtctx.phnds_table, 
-                          &node->phnd_link, node->phandle);
-    }
-    
-    else if (propeq(it, "#address-cells")) {
-        node->addr_c = (char)__prop_getu32(it);
-    } 
-    
-    else if (propeq(it, "#size-cells")) {
-        node->sz_c = (char)__prop_getu32(it);
-    } 
-    
-    else if (propeq(it, "#interrupt-cells")) {
-        node->intr_c = (char)__prop_getu32(it);
-    } 
-    
-    else if (propeq(it, "status")) {
-        char peek = *(char*)&it->prop[1];
-        if (peek == 'o') {
-            node->status = STATUS_OK;
-        }
-        else if (peek == 'r') {
-            node->status = STATUS_RSVD;
-        }
-        else if (peek == 'd') {
-            node->status = STATUS_DISABLE;
-        }
-        else if (peek == 'f') {
-            node->status = STATUS_FAIL;
-        }
-    }
-
-    else {
-        return false;
-    }
-
-    return true;
-}
-
-static bool
-__parse_stdnode_prop(struct fdt_iter* it, struct dt_node* node)
-{
-    if (propeq(it, "reg")) {
-        __mkprop_ptr(it, &node->reg);
-    }
-
-    else if (propeq(it, "virtual-reg")) {
-        __mkprop_ptr(it, &node->vreg);
-    }
-
-    else if (propeq(it, "ranges")) {
-        __mkprop_ptr(it, &node->ranges);
-    }
-
-    else if (propeq(it, "dma-ranges")) {
-        __mkprop_ptr(it, &node->dma_ranges);
-    }
-
-    else {
-        return false;
-    }
-
-    return true;
-}
-
-static bool
-__parse_stdintr_prop(struct fdt_iter* it, struct dt_intr_node* node)
-{
-    if (propeq(it, "interrupt-map")) {
-        __mkprop_ptr(it, &node->intr_map);
-    }
-
-    else if (propeq(it, "interrupt-map-mask")) {
-        __mkprop_ptr(it, &node->intr_map_mask);
-    }
-
-    else if (propeq(it, "interrupt-parent")) {
-        node->parent_hnd = __prop_getu32(it);
-    }
-
-    else if (propeq(it, "interrupt-extended")) {
-        node->intr.extended = true;
-        __mkprop_ptr(it, &node->intr.arr);
-    }
-
-    else if (!node->intr.extended && propeq(it, "interrupts")) {
-        __mkprop_ptr(it, &node->intr.arr);
-    }
-
-    else {
-        return false;
-    }
-
-    return true;
-}
-
-static bool
-__parse_stdflags(struct fdt_iter* it, struct dt_node_base* node)
-{
-    if (propeq(it, "dma-coherent")) {
-        node->dma_coherent = true;
-    }
-
-    else if (propeq(it, "dma-noncoherent")) {
-        node->dma_ncoherent = true;
-    }
-
-    else if (propeq(it, "interrupt-controller")) {
-        node->intr_controll = true;
-    }
-
-    else {
-        return false;
-    }
-
-    return true;
-}
-
-static void
-__parse_other_prop(struct fdt_iter* it, struct dt_node_base* node)
-{
-    struct dt_prop* prop;
-    const char* key;
-    unsigned int hash;
-
-    prop = valloc(sizeof(*prop));
-    key  = fdtit_prop_key(it);
-
-    prop->key = HSTR(key, strlen(key));
-    __mkprop_ptr(it, &prop->val);
-
-    hstr_rehash(&prop->key, HSTR_FULL_HASH);
-    hash = prop->key.hash;
-
-    hashtable_hash_in(node->_op_bucket, &prop->ht, hash);
-}
-
-static void
-__fill_node(struct fdt_iter* it, struct dt_node* node)
-{
-    if (__parse_stdflags(it, &node->base)) {
-        return;
-    }
-
-    if (__parse_stdbase_prop(it, &node->base)) {
-        return;
-    }
-
-    if (__parse_stdnode_prop(it, node)) {
-        return;
-    }
-
-    if (__parse_stdintr_prop(it, &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);
-}
-
-static inline void
-__init_node(struct dt_node_base* node)
-{
-    hashtable_init(node->_op_bucket);
-    llist_init_head(&node->children);
-}
-
-static inline void
-__init_node_regular(struct dt_node* node)
-{
-    __init_node(&node->base);
-    node->intr.parent_hnd = PHND_NULL;
-}
-
-static void
-__expand_extended_intr(struct dt_intr_node* 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;
-
-    if (!intrupt->intr.extended) {
-        return;
-    }
-
-    arr = intrupt->intr.arr;
-    node = DT_NODE(intrupt);
-
-    llist_init_head(&intrupt->intr.values);
-    
-    dt_decode(&it, &node->base, &arr, 1);
-    
-    dt_phnd_t phnd;
-    while(dtprop_next(&it)) {
-        phnd   = dtprop_to_u32(it.prop_loc);
-        master = dt_resolve_phandle(phnd);
-
-        if (!master) {
-            WARN("dtb: (intr_extended) malformed phandle: %d", phnd);
-            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);
-    }
-}
-
-static void
-__resolve_phnd_references()
-{
-    struct dt_node_base *pos, *n;
-    struct dt_node *node, *parent, *default_parent;
-    struct dt_intr_node* intrupt;
-    dt_phnd_t phnd;
-    
-    llist_for_each(pos, n, &dtctx.nodes, nodes)
-    {
-        node = (struct dt_node*)pos;
-        intrupt = &node->intr;
-        if (!node->base.intr_c) {
-            continue;
-        }
-
-        phnd = intrupt->parent_hnd;
-        default_parent = (struct dt_node*)node->base.parent;
-        parent = default_parent;
-
-        if (phnd != PHND_NULL) {
-            parent = dt_resolve_phandle(phnd);
-        }
-
-        if (!parent) {
-            WARN("dtb: (phnd_resolve) malformed phandle: %d", phnd);
-            parent = default_parent;
-        }
-
-        intrupt->parent = &parent->intr;
-
-        __expand_extended_intr(intrupt);
-    }
-}
-
-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 dt_node_base* depth[16];
-    bool is_root_level, filled;
-
-    node = NULL;
-    depth[0] = NULL;
-    fdt_itbegin(&it, dtctx.fdt);
-    
-    while (fdt_itnext(&it)) {
-        is_root_level = it.depth == 1;
-
-        if (it.depth >= 16) {
-            // tree too deep
-            ERROR("strange dtb, too deep to dive.");
-            return false;
-        }
-
-        depth[it.depth] = NULL;
-        node = depth[it.depth - 1];
-
-        if (!node) {
-            // need new node
-            if (unlikely(is_root_level)) {
-                node = valloc(sizeof(struct dt_root));
-                __init_node(node);
-            }
-            else {
-                node = valloc(sizeof(struct dt_node));
-                prev = depth[it.depth - 2];
-
-                __init_node_regular((struct dt_node*)node);
-                llist_append(&prev->children, &node->siblings);
-                node->parent = prev;
-
-                llist_append(&dtctx.nodes, &node->nodes);
-            }
-
-            node->name = (const char*)&it.pos[1];
-        }
-
-        if (unlikely(is_root_level)) {
-            __fill_root(&it, (struct dt_root*)node);
-        }
-        else {
-            __fill_node(&it, (struct dt_node*)node);
-        }
-    }
-
-    fdt_itend(&it);
-
-    dtctx.root = (struct dt_root*)depth[0];
-
-    __resolve_phnd_references();
-
-    return true;
-}
-
-static bool
-__name_starts_with(struct dt_node_base* node, const char* name)
-{
-    int i = 0;
-    const char* be_matched = node->name;
-
-    while (be_matched[i] && name[i])
-    {
-        if (be_matched[i] != name[i]) {
-            return false;
-        }
-    }
-
-    return true;
-}
-
-struct dt_node*
-dt_resolve_phandle(dt_phnd_t phandle)
-{
-    struct dt_node_base *pos, *n;
-    hashtable_hash_foreach(dtctx.phnds_table, phandle, pos, n, phnd_link)
-    {
-        if (pos->phandle == phandle) {
-            return (struct dt_node*)pos;
-        }
-    }
-
-    return NULL;
-}
-
-void
-dt_begin_find(struct dt_node_iter* iter, 
-              struct dt_node* node, const char* name)
-{
-    node = node ? : (struct dt_node*)dtctx.root;
-
-    iter->head = &node->base;
-    iter->matched = NULL;
-    iter->name = name;
-
-    struct dt_node_base *pos, *n;
-    llist_for_each(pos, n, &node->base.children, siblings)
-    {
-        if (__name_starts_with(pos, name)) {
-            iter->matched = pos;
-            break;
-        }
-    }
-}
-
-bool
-dt_find_next(struct dt_node_iter* iter,
-             struct dt_node_base** matched)
-{
-    if (!dt_found_any(iter)) {
-        return false;
-    }
-
-    struct dt_node_base *pos, *head;
-
-    head = iter->head;
-    pos = iter->matched;
-    *matched = pos;
-
-    while (&pos->siblings != &head->children)
-    {
-        pos = list_next(pos, struct dt_node_base, siblings);
-
-        if (!__name_starts_with(pos, iter->name)) {
-            continue;
-        }
-
-        iter->matched = pos;
-        return true;
-    }
-
-    return false;
-}
-
-struct dt_prop_val*
-dt_getprop(struct dt_node* node, const char* name)
-{
-    struct hstr hashed_name;
-    struct dt_prop *pos, *n;
-    unsigned int hash;
-
-    hashed_name = HSTR(name, strlen(name));
-    hstr_rehash(&hashed_name, HSTR_FULL_HASH);
-    hash = hashed_name.hash;
-
-    hashtable_hash_foreach(node->base._op_bucket, hash, pos, n, ht)
-    {
-        if (HSTR_EQ(&pos->key, &hashed_name)) {
-            return &pos->val;
-        }
-    }
-
-    return NULL;
-}
\ No newline at end of file