static int __init process_acpi_sdt_table(char *tab_sign, u32 *tab_data) { struct vmm_devtree_node *node = vmm_devtree_getnode(VMM_DEVTREE_PATH_SEPARATOR_STRING VMM_DEVTREE_MOTHERBOARD_NODE_NAME); /* FIXME: First find if tab_size already exists. */ struct vmm_devtree_node *cnode = vmm_devtree_addnode(node, tab_sign); vmm_devtree_dref_node(node); if (!strncmp(tab_sign, APIC_SIGNATURE, strlen(APIC_SIGNATURE))) { struct acpi_madt_hdr *madt_hdr; madt_hdr = (struct acpi_madt_hdr *)tab_data; if (acpi_populate_ioapic_devtree(madt_hdr, cnode) != VMM_OK) return VMM_EFAIL; if (acpi_populate_lapic_devtree(madt_hdr, cnode) != VMM_OK) return VMM_EFAIL; } else if (!strncmp(tab_sign, HPET_SIGNATURE, strlen(HPET_SIGNATURE))) { struct acpi_hpet hpet_chip, *hpet; int nr_hpet_blks, i; char hpet_nm[256]; if (acpi_read_sdt_at(tab_data, (struct acpi_sdt_hdr *)&hpet_chip, sizeof(struct acpi_hpet), HPET_SIGNATURE) < 0) { return VMM_EFAIL; } hpet = (struct acpi_hpet *)tab_data; nr_hpet_blks = (hpet->hdr.len - sizeof(struct acpi_sdt_hdr)) /sizeof(struct acpi_timer_blocks); vmm_devtree_setattr(cnode, VMM_DEVTREE_NR_HPET_ATTR_NAME, &nr_hpet_blks, VMM_DEVTREE_ATTRTYPE_UINT32, sizeof(nr_hpet_blks), FALSE); for (i = 0; i < nr_hpet_blks; i++) { memset(hpet_nm, 0, sizeof(hpet_nm)); vmm_sprintf(hpet_nm, VMM_DEVTREE_HPET_NODE_FMT, i); struct vmm_devtree_node *nnode = vmm_devtree_addnode(cnode, hpet_nm); BUG_ON(nnode == NULL); if (vmm_devtree_setattr(nnode, VMM_DEVTREE_HPET_ID_ATTR_NAME, &hpet->tmr_blks[i].asid, VMM_DEVTREE_ATTRTYPE_UINT32, sizeof(hpet->tmr_blks[i].asid), FALSE) != VMM_OK) { return VMM_EFAIL; } if (vmm_devtree_setattr(nnode, VMM_DEVTREE_HPET_PADDR_ATTR_NAME, &hpet->tmr_blks[i].base, VMM_DEVTREE_ATTRTYPE_PHYSADDR, sizeof(physical_addr_t), FALSE) != VMM_OK) { return VMM_EFAIL; } } } return VMM_OK; }
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 int __init acpi_populate_lapic_devtree(struct acpi_madt_hdr *madt_hdr, struct vmm_devtree_node *cnode) { unsigned int idx = 0; int ret = VMM_OK; struct acpi_madt_lapic *lapic; char lapic_nm[256]; for (;;) { lapic = (struct acpi_madt_lapic *) acpi_madt_get_typed_item(madt_hdr, ACPI_MADT_TYPE_LAPIC, idx); if (!lapic) break; memset(lapic_nm, 0, sizeof(lapic_nm)); vmm_sprintf(lapic_nm, VMM_DEVTREE_LAPIC_PCPU_NODE_FMT, idx); struct vmm_devtree_node *nnode = vmm_devtree_addnode(cnode, lapic_nm); if (vmm_devtree_setattr(nnode, VMM_DEVTREE_LAPIC_CPU_ID_ATTR_NAME, &lapic->acpi_cpu_id, VMM_DEVTREE_ATTRTYPE_UINT32, sizeof(lapic->acpi_cpu_id), FALSE) != VMM_OK) { ret = VMM_EFAIL; break; } if (vmm_devtree_setattr(nnode, VMM_DEVTREE_LAPIC_LAPIC_ID_ATTR_NAME, &lapic->apic_id, VMM_DEVTREE_ATTRTYPE_UINT32, sizeof(lapic->apic_id), FALSE) != VMM_OK) { ret = VMM_EFAIL; break; } idx++; } vmm_devtree_setattr(cnode, VMM_DEVTREE_NR_LAPIC_ATTR_NAME, &idx, VMM_DEVTREE_ATTRTYPE_UINT32, sizeof(idx), FALSE); return ret; }
static int __init acpi_populate_ioapic_devtree(struct acpi_madt_hdr *madt_hdr, struct vmm_devtree_node *cnode) { unsigned int idx = 0; int ret = VMM_OK; struct acpi_madt_ioapic *ioapic; char ioapic_nm[256]; for (;;) { ioapic = (struct acpi_madt_ioapic *) acpi_madt_get_typed_item(madt_hdr, ACPI_MADT_TYPE_IOAPIC, idx); if (!ioapic) break; memset(ioapic_nm, 0, sizeof(ioapic_nm)); vmm_sprintf(ioapic_nm, VMM_DEVTREE_IOAPIC_NODE_FMT, idx); struct vmm_devtree_node *nnode = vmm_devtree_addnode(cnode, ioapic_nm); if (vmm_devtree_setattr(nnode, VMM_DEVTREE_IOAPIC_PADDR_ATTR_NAME, &ioapic->address, VMM_DEVTREE_ATTRTYPE_PHYSADDR, sizeof(physical_addr_t), FALSE) != VMM_OK) { ret = VMM_EFAIL; break; } if (vmm_devtree_setattr(nnode, VMM_DEVTREE_IOAPIC_GINT_BASE_ATTR_NAME, &ioapic->global_int_base, VMM_DEVTREE_ATTRTYPE_UINT32, sizeof(ioapic->global_int_base), FALSE) != VMM_OK) { ret = VMM_EFAIL; break; } idx++; } vmm_devtree_setattr(cnode, VMM_DEVTREE_NR_IOAPIC_ATTR_NAME, &idx, VMM_DEVTREE_ATTRTYPE_UINT32, sizeof(idx), FALSE); return ret; }
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; }