int libfdt_parse_devtree(struct fdt_fileinfo *fdt, struct vmm_devtree_node **root) { char *data; /* Sanity check */ if (!fdt) { return VMM_EFAIL; } /* Get data pointer */ data = fdt->data; /* Sanity check */ if (LIBFDT_DATA32(data) != FDT_BEGIN_NODE) return VMM_EFAIL; /* Point to root node name */ data += sizeof(fdt_cell_t); /* Create root node */ *root = vmm_devtree_addnode(NULL, data); /* Skip root node name */ data += strlen(data) + 1; while ((virtual_addr_t) (data) % sizeof(fdt_cell_t) != 0) { (data)++; } /* Parse FDT recursively */ libfdt_parse_devtree_recursive(fdt, *root, &data); return VMM_OK; }
static void libfdt_parse_devtree_recursive(struct fdt_fileinfo * fdt, struct vmm_devtree_node * node, char **data) { u32 type, len; const char * name; struct vmm_devtree_node *child; if (!fdt || !node) { return; } while (LIBFDT_DATA32(*data) != FDT_END_NODE) { switch (LIBFDT_DATA32(*data)) { case FDT_PROP: *data += sizeof(fdt_cell_t); len = LIBFDT_DATA32(*data); *data += sizeof(fdt_cell_t); name = &fdt->str[LIBFDT_DATA32(*data)]; *data += sizeof(fdt_cell_t); type = vmm_devtree_estimate_attrtype(name); vmm_devtree_setattr(node, name, *data, type, len); *data += len; while ((virtual_addr_t) (*data) % sizeof(fdt_cell_t) != 0) (*data)++; break; case FDT_NOP: *data += sizeof(fdt_cell_t); break; case FDT_BEGIN_NODE: *data += sizeof(fdt_cell_t); type = VMM_DEVTREE_NODETYPE_UNKNOWN; child = vmm_devtree_addnode(node, *data, type, NULL); *data += vmm_strlen(*data) + 1; while ((virtual_addr_t) (*data) % sizeof(fdt_cell_t) != 0) { (*data)++; } libfdt_parse_devtree_recursive(fdt, child, data); break; default: return; break; }; } *data += sizeof(fdt_cell_t); return; }
int libfdt_parse_devtree(struct fdt_fileinfo *fdt, struct vmm_devtree_node **root, const char *root_name, struct vmm_devtree_node *root_parent) { char *data; struct vmm_devtree_node *node; /* Sanity check */ if (!fdt || !root_name) { return VMM_EFAIL; } /* Get data pointer */ data = fdt->data; /* Sanity check */ if (LIBFDT_DATA32(data) != FDT_BEGIN_NODE) return VMM_EFAIL; /* Skip root node name */ data += sizeof(fdt_cell_t); /* Create root node */ node = vmm_devtree_addnode(root_parent, root_name); if (!node) { return VMM_ENOMEM; } /* Update return pointer for root node */ if (root) { *root = node; } /* Skip root node name */ data += strlen(data) + 1; while ((virtual_addr_t) (data) % sizeof(fdt_cell_t) != 0) { (data)++; } /* Parse FDT recursively */ libfdt_parse_devtree_recursive(fdt, node, &data); return VMM_OK; }
static void libfdt_parse_devtree_recursive(struct fdt_fileinfo *fdt, struct vmm_devtree_node *node, char **data) { void *val; const char *name; u32 type, len, alen, addr_cells, size_cells; struct vmm_devtree_node *child; if (!fdt || !node) { return; } if (vmm_devtree_read_u32(node->parent, "#address-cells", &addr_cells)) { addr_cells = sizeof(physical_addr_t) / sizeof(fdt_cell_t); } if (vmm_devtree_read_u32(node->parent, "#size-cells", &size_cells)) { size_cells = sizeof(physical_size_t) / sizeof(fdt_cell_t); } while (LIBFDT_DATA32(*data) != FDT_END_NODE) { switch (LIBFDT_DATA32(*data)) { case FDT_PROP: *data += sizeof(fdt_cell_t); len = LIBFDT_DATA32(*data); *data += sizeof(fdt_cell_t); name = &fdt->str[LIBFDT_DATA32(*data)]; *data += sizeof(fdt_cell_t); type = vmm_devtree_estimate_attrtype(name); alen = libfdt_property_len(name, addr_cells, size_cells, len); val = vmm_zalloc(alen); libfdt_property_read(name, val, *data, addr_cells, size_cells, len); vmm_devtree_setattr(node, name, val, type, alen); vmm_free(val); *data += len; while ((virtual_addr_t) (*data) % sizeof(fdt_cell_t) != 0) (*data)++; break; case FDT_NOP: *data += sizeof(fdt_cell_t); break; case FDT_BEGIN_NODE: *data += sizeof(fdt_cell_t); child = vmm_devtree_addnode(node, *data); *data += strlen(*data) + 1; while ((virtual_addr_t) (*data) % sizeof(fdt_cell_t) != 0) { (*data)++; } libfdt_parse_devtree_recursive(fdt, child, data); break; default: return; break; }; } *data += sizeof(fdt_cell_t); return; }