📄 of-devtree.c
字号:
/* get the component length */ sz = ofd_pathsplit_right(s, '/', 0); /* check for an alias */ asz = ofd_pathsplit_right(s, ':', sz); if ( s[asz] == ':' ) { /* * s points to an alias and &s[sz] points to the alias * args. */ assert(0); /* aliases no supported */ return 0; } } else if ( s[1] == '\0' ) { return n; } n = ofd_node_child(m, n); if ( n == 0 ) { return 0; } return ofd_node_walk(m, n, s);}static struct ofd_prop *ofd_prop_get(struct ofd_mem *m, ofdn_t p){ if ( p < m->om_next ) { struct ofd_prop *r; r = (struct ofd_prop *)&m->om_mem[p]; if ( r->op_ima == PROP_PAT ) { return r; } assert(r->op_ima == PROP_PAT); /* bad object */ } return NULL;}static ofdn_t ofd_prop_create( struct ofd_mem *m, ofdn_t node, const char *name, const void *src, size_t sz){ struct ofd_node *n; struct ofd_prop *p; size_t len = strlen(name) + 1; size_t sum = sizeof (*p) + sz + len; ofdn_t cells; char *dst; ofdn_t pos; cells = (sum + sizeof (m->om_mem[0]) - 1) / sizeof (m->om_mem[0]); if ( m->om_next + cells >= m->om_num ) { return 0; } /* actual data structure */ pos = m->om_next; assert(ofd_check(&m->om_mem[pos], cells)); /* non-zero */ p = (struct ofd_prop *)&m->om_mem[pos]; m->om_next += cells; assert(p->op_ima == 0); /* new node not empty */ p->op_ima = PROP_PAT; p->op_next = 0; p->op_objsz = sz; p->op_namesz = len; /* the rest of the data */ dst = p->op_data; /* zero what will be the pad, cheap and cannot hurt */ m->om_mem[m->om_next - 1] = 0; if ( sz > 0 ) { /* some props have no data, just a name */ memcpy(dst, src, sz); dst += sz; } memcpy(dst, name, len); /* now place it in the tree */ n = ofd_node_get(m, node); assert(n != NULL); if ( n->on_prop == 0 ) { n->on_prop = pos; } else { ofdn_t pn = n->on_prop; struct ofd_prop *nxt; for (;;) { nxt = ofd_prop_get(m, pn); if (nxt->op_next == 0) { nxt->op_next = pos; break; } pn = nxt->op_next; } } return pos;}void ofd_prop_remove(void *mem, ofdn_t node, ofdn_t prop){ struct ofd_mem *m = (struct ofd_mem *)mem; struct ofd_node *n = ofd_node_get(m, node); struct ofd_prop *p = ofd_prop_get(m, prop); if (n == NULL) return; if (p == NULL) return; if ( n->on_prop == prop ) { n->on_prop = p->op_next; } else { ofdn_t pn = n->on_prop; struct ofd_prop *nxt; for ( ; ; ) { nxt = ofd_prop_get(m, pn); if ( nxt->op_next == prop ) { nxt->op_next = p->op_next; break; } pn = nxt->op_next; } } return;}ofdn_t ofd_prop_find(void *mem, ofdn_t n, const char *name){ struct ofd_mem *m = (struct ofd_mem *)mem; ofdn_t p = ofd_node_prop(m, n); struct ofd_prop *r; char *s; size_t len; if ( name == NULL || *name == '\0' ) { return OFD_ROOT; } len = strlen(name) + 1; while ( p != 0 ) { r = ofd_prop_get(m, p); s = &r->op_data[r->op_objsz]; if ( len == r->op_namesz ) { if ( strncmp(name, s, r->op_namesz) == 0 ) { break; } } p = r->op_next; } return p;}static ofdn_t ofd_prop_next(struct ofd_mem *m, ofdn_t n, const char *prev){ ofdn_t p; if ( prev == NULL || *prev == '\0' ) { /* give the first */ p = ofd_node_prop(m, n); } else { struct ofd_prop *r; /* look for the name */ p = ofd_prop_find(m, n, prev); if ( p != 0 ) { /* get the data for prev */ r = ofd_prop_get(m, p); /* now get next */ p = r->op_next; } else { p = -1; } } return p;}ofdn_t ofd_nextprop(void *mem, ofdn_t n, const char *prev, char *name){ struct ofd_mem *m = (struct ofd_mem *)mem; ofdn_t p = ofd_prop_next(m, n, prev); struct ofd_prop *r; char *s; if ( p > 0 ) { r = ofd_prop_get(m, p); s = &r->op_data[r->op_objsz]; memcpy(name, s, r->op_namesz); } return p;}/* * It is valid to call with NULL pointers, in case you want only one * cell size. */int ofd_getcells(void* mem, ofdn_t n, u32* addr_cells, u32* size_cells){ if ( addr_cells != NULL ) *addr_cells = 0; if ( size_cells != NULL ) *size_cells = 0;retry: if ( addr_cells != NULL && *addr_cells == 0 ) { ofd_getprop(mem, n, "#address-cells", addr_cells, sizeof(u32)); } if ( size_cells != NULL && *size_cells == 0 ) { ofd_getprop(mem, n, "#size-cells", size_cells, sizeof(u32)); } if ( ( size_cells != NULL && *size_cells == 0 ) || ( addr_cells != NULL && *addr_cells == 0 ) ) { if ( n != OFD_ROOT ) { n = ofd_node_parent(mem, n); goto retry; } return -1; } return 1;}int ofd_getprop(void *mem, ofdn_t n, const char *name, void *buf, size_t sz){ struct ofd_mem *m = (struct ofd_mem *)mem; ofdn_t p = ofd_prop_find(m, n, name); struct ofd_prop *r; if ( p == 0 ) { return -1; } r = ofd_prop_get(m, p); if ( sz > r->op_objsz ) { sz = r->op_objsz; } memcpy(buf, r->op_data, sz); return r->op_objsz;}int ofd_getproplen(void *mem, ofdn_t n, const char *name){ struct ofd_mem *m = (struct ofd_mem *)mem; ofdn_t p = ofd_prop_find(m, n, name); struct ofd_prop *r; if ( p == 0 ) { return -1; } r = ofd_prop_get(m, p); return r->op_objsz;}static ofdn_t ofd_prop_set( void *mem, ofdn_t n, const char *name, const void *src, size_t sz){ struct ofd_mem *m = (struct ofd_mem *)mem; ofdn_t p = ofd_prop_find(m, n, name); struct ofd_prop *r; char *dst; r = ofd_prop_get(m, p); if ( sz <= r->op_objsz ) { /* we can reuse */ memcpy(r->op_data, src, sz); if ( sz < r->op_objsz ) { /* need to move name */ dst = r->op_data + sz; /* * use the name arg size we may have overlap with the * original */ memcpy(dst, name, r->op_namesz); r->op_objsz = sz; } } else { /* * Sadly, we remove from the list, wasting the space and then * we can creat a new one */ ofd_prop_remove(m, n, p); p = ofd_prop_create(mem, n, name, src, sz); } return p;}int ofd_setprop( void *mem, ofdn_t n, const char *name, const void *buf, size_t sz){ struct ofd_mem *m = (struct ofd_mem *)mem; ofdn_t r; r = ofd_prop_find(m, n, name); if ( r == 0 ) { r = ofd_prop_create(mem, n, name, buf, sz); } else { r = ofd_prop_set(mem, n, name, buf, sz); } if ( r > 0 ) { struct ofd_prop *pp = ofd_prop_get(m, r); return pp->op_objsz; } return OF_FAILURE;}static ofdn_t ofd_find_by_prop( struct ofd_mem *m, ofdn_t head, ofdn_t *prev_p, ofdn_t n, const char *name, const void *val, size_t sz){ struct ofd_node *np; struct ofd_prop *pp; ofdn_t p;retry: p = ofd_prop_find(m, n, name); if ( p > 0 ) { int match = 0; /* a property exists by that name */ if ( val == NULL ) { match = 1; } else { /* need to compare values */ pp = ofd_prop_get(m, p); if ( sz == pp->op_objsz && memcmp(pp->op_data, val, sz) == 0 ) { match = 1; } } if ( match == 1 ) { if ( *prev_p >= 0 ) { np = ofd_node_get(m, *prev_p); np->on_next = n; } else { head = n; } np = ofd_node_get(m, n); np->on_prev = *prev_p; np->on_next = -1; *prev_p = n; } } p = ofd_node_child(m, n); if ( p > 0 ) { head = ofd_find_by_prop(m, head, prev_p, p, name, val, sz); } p = ofd_node_peer(m, n); if ( p > 0 ) { n = p; goto retry; } return head;}ofdn_t ofd_node_find_by_prop( void *mem, ofdn_t n, const char *name, const void *val, size_t sz){ struct ofd_mem *m = (struct ofd_mem *)mem; ofdn_t prev = -1; if ( n <= 0 ) { n = OFD_ROOT; } return ofd_find_by_prop(m, -1, &prev, n, name, val, sz);}ofdn_t ofd_node_find_next(void *mem, ofdn_t n){ struct ofd_mem *m = (struct ofd_mem *)mem; struct ofd_node *np; np = ofd_node_get(m, n); if (np == NULL) return 0; return np->on_next;}ofdn_t ofd_node_find_prev(void *mem, ofdn_t n){ struct ofd_mem *m = (struct ofd_mem *)mem; struct ofd_node *np; np = ofd_node_get(m, n); if (np == NULL) return 0; return np->on_prev;}ofdn_t ofd_io_create(void *mem, ofdn_t node, u64 open){ struct ofd_mem *m = (struct ofd_mem *)mem; struct ofd_node *n; struct ofd_io *i; ofdn_t pos; ofdn_t cells; cells = (sizeof (*i) + sizeof (m->om_mem[0]) - 1) / sizeof(m->om_mem[0]); n = ofd_node_get(m, node); if ( n == NULL ) return 0; if ( m->om_next + cells >= m->om_num ) { return 0; } pos = m->om_next; assert(ofd_check(&m->om_mem[pos], cells)); /* non-zero */ m->om_next += cells; i = (struct ofd_io *)&m->om_mem[pos]; assert(i->oi_ima == 0); /* new node not empty */ i->oi_ima = IO_PAT; i->oi_node = node; i->oi_open = open; n->on_io = pos; return pos;}static struct ofd_io *ofd_io_get(struct ofd_mem *m, ofdn_t i){ if ( i < m->om_next ) { struct ofd_io *r; r = (struct ofd_io *)&m->om_mem[i]; if ( r->oi_ima == IO_PAT ) { return r; } assert(r->oi_ima == IO_PAT); /* bad object */ } return NULL;}ofdn_t ofd_node_io(void *mem, ofdn_t n){ struct ofd_mem *m = (struct ofd_mem *)mem; struct ofd_node *r = ofd_node_get(m, n); if (r == NULL) return 0; return r->on_io;}uint ofd_io_open(void *mem, ofdn_t n){ struct ofd_mem *m = (struct ofd_mem *)mem; struct ofd_io *r = ofd_io_get(m, n); if (r == NULL) return 0; return r->oi_open;}void ofd_io_close(void *mem, ofdn_t n){ struct ofd_mem *m = (struct ofd_mem *)mem; struct ofd_io *o = ofd_io_get(m, n); struct ofd_node *r = ofd_node_get(m, o->oi_node); assert(o != NULL); assert(r != NULL); o->oi_open = 0; r->on_io = 0;}ofdn_t ofd_node_add(void *m, ofdn_t p, const char *path, size_t sz){ ofdn_t n; n = ofd_node_child(m, p); if ( n > 0 ) { n = ofd_node_peer_last(m, n); if ( n > 0 ) { n = ofd_node_peer_create(m, n, path, sz); } } else { n = ofd_node_child_create(m, p, path, sz); } return n;}ofdn_t ofd_prop_add( void *mem, ofdn_t n, const char *name, const void *buf, size_t sz){ struct ofd_mem *m = (struct ofd_mem *)mem; ofdn_t r; r = ofd_prop_find(m, n, name); if ( r == 0 ) { r = ofd_prop_create(mem, n, name, buf, sz); } else { r = ofd_prop_set(mem, n, name, buf, sz); } return r;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -