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; }
void acpi_init(void) { int s, i; read_func = acpi_phys_copy; if (!get_acpi_rsdp()) { printf("WARNING : Cannot configure ACPI\n"); return; } s = acpi_read_sdt_at(acpi_rsdp.rsdt_addr, (struct acpi_sdt_header *) &rsdt, sizeof(struct acpi_rsdt), ACPI_SDT_SIGNATURE(RSDT)); sdt_count = (s - sizeof(struct acpi_sdt_header)) / sizeof(u32_t); for (i = 0; i < sdt_count; i++) { struct acpi_sdt_header hdr; int j; if (read_func(rsdt.data[i], &hdr, sizeof(struct acpi_sdt_header))) { printf("ERROR acpi cannot read header at 0x%x\n", rsdt.data[i]); return; } for (j = 0 ; j < ACPI_SDT_SIGNATURE_LEN; j++) sdt_trans[i].signature[j] = hdr.signature[j]; sdt_trans[i].signature[ACPI_SDT_SIGNATURE_LEN] = '\0'; sdt_trans[i].length = hdr.length; } acpi_init_poweroff(); }
int __init acpi_init(void) { int i, nr_sys_hdr, ret = VMM_EFAIL; struct acpi_rsdp *root_desc = NULL; struct acpi_rsdt rsdt, *prsdt; vmm_printf("Starting to parse ACPI tables...\n"); root_desc = (struct acpi_rsdp *)find_root_system_descriptor(); if (root_desc == NULL) { vmm_printf("ACPI ERROR: No root system descriptor" " table found!\n"); goto rdesc_fail; } if (root_desc->rsdt_addr == 0) { vmm_printf("ACPI ERROR: No root descriptor found" " in RSD Pointer!\n"); goto rsdt_fail; } prsdt = (struct acpi_rsdt *)vmm_host_iomap(root_desc->rsdt_addr, PAGE_SIZE); if (unlikely(!prsdt)) { vmm_printf("ACPI ERROR: Failed to map physical address 0x%x.\n", __func__, root_desc->rsdt_addr); goto rsdt_fail; } if (acpi_read_sdt_at(prsdt, (struct acpi_sdt_hdr *)&rsdt, sizeof(struct acpi_rsdt), RSDT_SIGNATURE) < 0) { goto sdt_fail; } nr_sys_hdr = (rsdt.hdr.len - sizeof(struct acpi_sdt_hdr))/sizeof(u32); for (i = 0; i < nr_sys_hdr; i++) { struct acpi_sdt_hdr *hdr; char sign[32]; memset(sign, 0, sizeof(sign)); hdr = (struct acpi_sdt_hdr *) vmm_host_iomap(rsdt.data[i], PAGE_SIZE); if (hdr == NULL) { vmm_printf("ACPI ERROR: Cannot read header at 0x%x\n", rsdt.data[i]); goto sdt_fail; } memcpy(sign, hdr->signature, SDT_SIGN_LEN); sign[SDT_SIGN_LEN] = 0; if (process_acpi_sdt_table((char *)sign, (u32 *)hdr) != VMM_OK) { vmm_host_iounmap((virtual_addr_t)hdr); goto sdt_fail; } vmm_host_iounmap((virtual_addr_t)hdr); } ret = VMM_OK; sdt_fail: vmm_host_iounmap((virtual_addr_t)prsdt); rsdt_fail: vmm_host_iounmap((virtual_addr_t)root_desc); rdesc_fail: return ret; }
int acpi_init(void) { int i; if (!acpi_ctxt) { acpi_ctxt = vmm_malloc(sizeof(struct acpi_context)); if (!acpi_ctxt) { vmm_printf("ACPI ERROR: Failed to allocate memory for" " ACPI context.\n"); return VMM_EFAIL; } acpi_ctxt->root_desc = (struct acpi_rsdp *)find_root_system_descriptor(); acpi_ctxt->rsdt = NULL; if (acpi_ctxt->root_desc == NULL) { vmm_printf("ACPI ERROR: No root system descriptor" " table found!\n"); goto rdesc_fail; } if (acpi_ctxt->root_desc->rsdt_addr == 0) { vmm_printf("ACPI ERROR: No root descriptor found" " in RSD Pointer!\n"); goto rsdt_fail; } acpi_ctxt->rsdt = (struct acpi_rsdt *)vmm_malloc(sizeof(struct acpi_rsdt)); if (!acpi_ctxt->rsdt) goto rsdt_fail; if (acpi_read_sdt_at(acpi_ctxt->root_desc->rsdt_addr, (struct acpi_sdt_hdr *)acpi_ctxt->rsdt, sizeof(struct acpi_rsdt), RSDT_SIGNATURE) < 0) { goto sdt_fail; } acpi_ctxt->nr_sys_hdr = (acpi_ctxt->rsdt->hdr.len - sizeof(struct acpi_sdt_hdr))/sizeof(u32); for (i = 0; i < acpi_ctxt->nr_sys_hdr; i++) { struct acpi_sdt_hdr *hdr; hdr = (struct acpi_sdt_hdr *) vmm_host_iomap(acpi_ctxt->rsdt->data[i], PAGE_SIZE); if (hdr == NULL) { vmm_printf("ACPI ERROR: Cannot read header at 0x%x\n", acpi_ctxt->rsdt->data[i]); goto sdt_fail; } vmm_memcpy(&acpi_ctxt->sdt_trans[i].signature, &hdr->signature, SDT_SIGN_LEN); acpi_ctxt->sdt_trans[i].signature[SDT_SIGN_LEN] = '\0'; acpi_ctxt->sdt_trans[i].length = hdr->len; //vmm_host_iounmap((virtual_addr_t)hdr, PAGE_SIZE); } acpi_ctxt->madt_hdr = (struct acpi_madt_hdr *) vmm_host_iomap(acpi_get_table_base("APIC"), PAGE_SIZE); if (acpi_ctxt->madt_hdr == NULL) goto sdt_fail; } return VMM_OK; sdt_fail: vmm_free(acpi_ctxt->rsdt); rsdt_fail: vmm_host_iounmap((virtual_addr_t)acpi_ctxt->root_desc, PAGE_SIZE); rdesc_fail: vmm_free(acpi_ctxt); acpi_ctxt = NULL; return VMM_EFAIL; }