ACPI_STATUS AeInstallTables ( void) { ACPI_STATUS Status; ACPI_TABLE_HEADER Header; ACPI_TABLE_HEADER *Table; Status = AcpiInitializeTables (Tables, ACPI_MAX_INIT_TABLES, TRUE); AE_CHECK_OK (AcpiInitializeTables, Status); Status = AcpiReallocateRootTable (); AE_CHECK_OK (AcpiReallocateRootTable, Status); Status = AcpiLoadTables (); AE_CHECK_OK (AcpiLoadTables, Status); /* * Test run-time control method installation. Do it twice to test code * for an existing name. */ Status = AcpiInstallMethod (MethodCode); if (ACPI_FAILURE (Status)) { AcpiOsPrintf ("%s, Could not install method\n", AcpiFormatException (Status)); } Status = AcpiInstallMethod (MethodCode); if (ACPI_FAILURE (Status)) { AcpiOsPrintf ("%s, Could not install method\n", AcpiFormatException (Status)); } /* Test multiple table/UEFI support. First, get the headers */ Status = AcpiGetTableHeader (ACPI_SIG_UEFI, 1, &Header); AE_CHECK_OK (AcpiGetTableHeader, Status); Status = AcpiGetTableHeader (ACPI_SIG_UEFI, 2, &Header); AE_CHECK_OK (AcpiGetTableHeader, Status); Status = AcpiGetTableHeader (ACPI_SIG_UEFI, 3, &Header); AE_CHECK_STATUS (AcpiGetTableHeader, Status, AE_NOT_FOUND); /* Now get the actual tables */ Status = AcpiGetTable (ACPI_SIG_UEFI, 1, &Table); AE_CHECK_OK (AcpiGetTable, Status); Status = AcpiGetTable (ACPI_SIG_UEFI, 2, &Table); AE_CHECK_OK (AcpiGetTable, Status); Status = AcpiGetTable (ACPI_SIG_UEFI, 3, &Table); AE_CHECK_STATUS (AcpiGetTable, Status, AE_NOT_FOUND); return (AE_OK); }
/* Early ACPI Table Access */ int acpitables_init(void) { kprintf("acpitables_init()\n"); ACPI_STATUS r; ACPI_TABLE_HEADER *hdr; if (ACPI_FAILURE(r = AcpiInitializeTables(NULL, 16, FALSE))) panic("acpi: AcpiInitializeTables failed: %s", AcpiFormatException(r)); // Get the MADT r = AcpiGetTable((char*)ACPI_SIG_MADT, 0, &hdr); if (ACPI_FAILURE(r) && r != AE_NOT_FOUND) panic("acpi: AcpiGetTable failed: %s", AcpiFormatException(r)); if (r == AE_OK) hdr_madt = (ACPI_TABLE_MADT*)hdr; // Get the SRAT r = AcpiGetTable((char*)ACPI_SIG_SRAT, 0, &hdr); if (ACPI_FAILURE(r) && r != AE_NOT_FOUND) panic("acpi: AcpiGetTable failed: %s", AcpiFormatException(r)); if (r == AE_OK) hdr_srat = (ACPI_TABLE_SRAT*)hdr; // Get the DMAR (DMA remapping reporting table) r = AcpiGetTable((char*)ACPI_SIG_DMAR, 0, &hdr); if (ACPI_FAILURE(r) && r != AE_NOT_FOUND) panic("acpi: AcpiGetTable failed: %s", AcpiFormatException(r)); if (r == AE_OK) hdr_dmar = (ACPI_TABLE_DMAR*)hdr; table_inited = 1; return 0; }
ACPI_STATUS AeInstallTables ( void) { ACPI_STATUS Status; ACPI_TABLE_HEADER Header; ACPI_TABLE_HEADER *Table; UINT32 i; Status = AcpiInitializeTables (NULL, ACPI_MAX_INIT_TABLES, TRUE); ACPI_CHECK_OK (AcpiInitializeTables, Status); if (AcpiGbl_LoadTestTables) { /* Test multiple table/UEFI support. First, get the headers */ Status = AcpiGetTableHeader (ACPI_SIG_UEFI, 1, &Header); ACPI_CHECK_OK (AcpiGetTableHeader, Status); Status = AcpiGetTableHeader (ACPI_SIG_UEFI, 2, &Header); ACPI_CHECK_OK (AcpiGetTableHeader, Status); Status = AcpiGetTableHeader (ACPI_SIG_UEFI, 3, &Header); ACPI_CHECK_STATUS (AcpiGetTableHeader, Status, AE_NOT_FOUND); /* Now get the actual tables */ Status = AcpiGetTable (ACPI_SIG_UEFI, 1, &Table); ACPI_CHECK_OK (AcpiGetTable, Status); Status = AcpiGetTable (ACPI_SIG_UEFI, 2, &Table); ACPI_CHECK_OK (AcpiGetTable, Status); Status = AcpiGetTable (ACPI_SIG_UEFI, 3, &Table); ACPI_CHECK_STATUS (AcpiGetTable, Status, AE_NOT_FOUND); } /* Check that we can get all of the ACPI tables */ for (i = 0; ; i++) { Status = AcpiGetTableByIndex (i, &Table); if ((Status == AE_BAD_PARAMETER) || !Table) { break; } ACPI_CHECK_OK (AcpiGetTableByIndex, Status); } return (AE_OK); }
static ACPI_STATUS acpidev_cpu_pre_probe(acpidev_walk_info_t *infop) { uint32_t count = 0; /* Parse and cache APIC info in MADT on the first probe at boot time. */ ASSERT(infop != NULL); if (infop->awi_op_type == ACPIDEV_OP_BOOT_PROBE && acpidev_cpu_map_hdl == NULL) { /* Parse CPU relative information in the ACPI MADT table. */ (void) acpidev_walk_apic(NULL, NULL, NULL, acpidev_cpu_count_MADT, &acpidev_cpu_map_count); acpidev_cpu_map = kmem_zalloc(sizeof (acpidev_cpu_map[0]) * acpidev_cpu_map_count, KM_SLEEP); (void) acpidev_walk_apic(NULL, NULL, NULL, acpidev_cpu_parse_MADT, &count); ASSERT(count == acpidev_cpu_map_count); acpidev_cpu_map_hdl = infop->awi_hdl; /* Cache pointer to the ACPI SRAT table. */ if (ACPI_FAILURE(AcpiGetTable(ACPI_SIG_SRAT, 1, (ACPI_TABLE_HEADER **)&acpidev_srat_tbl_ptr))) { acpidev_srat_tbl_ptr = NULL; } } return (AE_OK); }
static void get_pcie_confspace(struct acpi_binding* b) { ACPI_DEBUG("get_pcie_confspace\n"); errval_t err; ACPI_STATUS as; ACPI_TABLE_HEADER *mcfg_header; as = AcpiGetTable("MCFG", 1, &mcfg_header); if (ACPI_SUCCESS(as) && mcfg_correct_length(mcfg_header->Length)) { ACPI_MCFG_ALLOCATION *mcfg = (void*) mcfg_header + sizeof(ACPI_TABLE_MCFG); ACPI_DEBUG( "PCIe enhanced configuration region at 0x%"PRIx64" " "(segment %u, buses %u-%u)\n", mcfg->Address, mcfg->PciSegment, mcfg->StartBusNumber, mcfg->EndBusNumber); err = b->tx_vtbl.get_pcie_confspace_response(b, NOP_CONT, SYS_ERR_OK, mcfg->Address, mcfg->PciSegment, mcfg->StartBusNumber, mcfg->EndBusNumber); } else { ACPI_DEBUG("No MCFG table found -> no PCIe enhanced configuration\n"); err = b->tx_vtbl.get_pcie_confspace_response(b, NOP_CONT, ACPI_ERR_NO_MCFG_TABLE, 0, 0, 0, 0); } assert(err_is_ok(err)); }
static void dmar_iterate_tbl(dmar_iter_t iter, void *arg) { ACPI_TABLE_DMAR *dmartbl; ACPI_DMAR_HEADER *dmarh; char *ptr, *ptrend; ACPI_STATUS status; status = AcpiGetTable(ACPI_SIG_DMAR, 1, (ACPI_TABLE_HEADER **)&dmartbl); if (ACPI_FAILURE(status)) return; ptr = (char *)dmartbl + sizeof(*dmartbl); ptrend = (char *)dmartbl + dmartbl->Header.Length; for (;;) { if (ptr >= ptrend) break; dmarh = (ACPI_DMAR_HEADER *)ptr; if (dmarh->Length <= 0) { printf("dmar_identify: corrupted DMAR table, l %d\n", dmarh->Length); break; } ptr += dmarh->Length; if (!iter(dmarh, arg)) break; } AcpiPutTable((ACPI_TABLE_HEADER *)dmartbl); }
/* auto init */ static int BattClock_Init(struct BattClockBase *BattClockBase) { InitSemaphore(&BattClockBase->sem); BattClockBase->century = CENTURY; /* Default offset */ if ((ACPICABase = OpenLibrary("acpica.library",0))) { ACPI_TABLE_FADT *fadt; ACPI_STATUS err; err = AcpiGetTable("FACP", 1, (ACPI_TABLE_HEADER **)&fadt); if (err == AE_OK) { if ((fadt->Header.Length >= offsetof(ACPI_TABLE_FADT, Century)) && fadt->Century) { D(bug("[BattClock] Got RTC century offset 0x%02X from ACPI\n", fadt->Century)); BattClockBase->century = fadt->Century; } } CloseLibrary(ACPICABase); ACPICABase = NULL; } return 1; }
/* * Look for an ECDT and if we find one, set up default GPE and * space handlers to catch attempts to access EC space before * we have a real driver instance in place. * * TODO: Some old Gateway laptops need us to fake up an ECDT or * otherwise attach early so that _REG methods can run. */ void acpi_ec_ecdt_probe(device_t parent) { ACPI_TABLE_ECDT *ecdt; ACPI_STATUS status; device_t child; ACPI_HANDLE h; struct acpi_ec_params *params; ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__); /* Find and validate the ECDT. */ status = AcpiGetTable(ACPI_SIG_ECDT, 1, (ACPI_TABLE_HEADER **)&ecdt); if (ACPI_FAILURE(status) || ecdt->Control.BitWidth != 8 || ecdt->Data.BitWidth != 8) { return; } /* Create the child device with the given unit number. */ child = BUS_ADD_CHILD(parent, parent, 0, "acpi_ec", ecdt->Uid); if (child == NULL) { kprintf("%s: can't add child\n", __func__); return; } /* Find and save the ACPI handle for this device. */ status = AcpiGetHandle(NULL, ecdt->Id, &h); if (ACPI_FAILURE(status)) { device_delete_child(parent, child); kprintf("%s: can't get handle\n", __func__); return; } acpi_set_handle(child, h); /* Set the data and CSR register addresses. */ bus_set_resource(child, SYS_RES_IOPORT, 0, ecdt->Data.Address, /*count*/1, -1); bus_set_resource(child, SYS_RES_IOPORT, 1, ecdt->Control.Address, /*count*/1, -1); /* * Store values for the probe/attach routines to use. Store the * ECDT GPE bit and set the global lock flag according to _GLK. * Note that it is not perfectly correct to be evaluating a method * before initializing devices, but in practice this function * should be safe to call at this point. */ params = kmalloc(sizeof(struct acpi_ec_params), M_TEMP, M_WAITOK | M_ZERO); params->gpe_handle = NULL; params->gpe_bit = ecdt->Gpe; params->uid = ecdt->Uid; acpi_GetInteger(h, "_GLK", ¶ms->glk); acpi_set_private(child, params); /* Finish the attach process. */ if (device_probe_and_attach(child) != 0) device_delete_child(parent, child); }
static bool radeon_acpi_vfct_bios(struct radeon_device *rdev) { bool ret = false; ACPI_TABLE_HEADER *hdr; ACPI_SIZE tbl_size; UEFI_ACPI_VFCT *vfct; GOP_VBIOS_CONTENT *vbios; VFCT_IMAGE_HEADER *vhdr; ACPI_STATUS status; DRM_INFO("%s: ===> Try VFCT...\n", __func__); DRM_INFO("%s: Get \"VFCT\" ACPI table\n", __func__); status = AcpiGetTable("VFCT", 1, &hdr); if (!ACPI_SUCCESS(status)) { DRM_INFO("%s: Failed to get \"VFCT\" table: %s\n", __func__, AcpiFormatException(status)); return false; } tbl_size = hdr->Length; if (tbl_size < sizeof(UEFI_ACPI_VFCT)) { DRM_ERROR("ACPI VFCT table present but broken (too short #1)\n"); goto out_unmap; } vfct = (UEFI_ACPI_VFCT *)hdr; if (vfct->VBIOSImageOffset + sizeof(VFCT_IMAGE_HEADER) > tbl_size) { DRM_ERROR("ACPI VFCT table present but broken (too short #2)\n"); goto out_unmap; } vbios = (GOP_VBIOS_CONTENT *)((char *)hdr + vfct->VBIOSImageOffset); vhdr = &vbios->VbiosHeader; DRM_INFO("ACPI VFCT contains a BIOS for %02x:%02x.%d %04x:%04x, size %d\n", vhdr->PCIBus, vhdr->PCIDevice, vhdr->PCIFunction, vhdr->VendorID, vhdr->DeviceID, vhdr->ImageLength); if (vhdr->PCIBus != rdev->ddev->pci_bus || vhdr->PCIDevice != rdev->ddev->pci_slot || vhdr->PCIFunction != rdev->ddev->pci_func || vhdr->VendorID != rdev->ddev->pci_vendor || vhdr->DeviceID != rdev->ddev->pci_device) { DRM_INFO("ACPI VFCT table is not for this card\n"); goto out_unmap; }; if (vfct->VBIOSImageOffset + sizeof(VFCT_IMAGE_HEADER) + vhdr->ImageLength > tbl_size) { DRM_ERROR("ACPI VFCT image truncated\n"); goto out_unmap; } rdev->bios = malloc(vhdr->ImageLength, DRM_MEM_DRIVER, M_NOWAIT); if (rdev->bios) memcpy(rdev->bios, &vbios->VbiosContent, vhdr->ImageLength); ret = !!rdev->bios; out_unmap: return ret; }
static void dmar_identify(driver_t *driver, device_t parent) { ACPI_TABLE_DMAR *dmartbl; ACPI_DMAR_HARDWARE_UNIT *dmarh; ACPI_STATUS status; int i, error; if (acpi_disabled("dmar")) return; TUNABLE_INT_FETCH("hw.dmar.enable", &dmar_enable); if (!dmar_enable) return; #ifdef INVARIANTS TUNABLE_INT_FETCH("hw.dmar.check_free", &dmar_check_free); #endif TUNABLE_INT_FETCH("hw.dmar.match_verbose", &dmar_match_verbose); status = AcpiGetTable(ACPI_SIG_DMAR, 1, (ACPI_TABLE_HEADER **)&dmartbl); if (ACPI_FAILURE(status)) return; haw = dmartbl->Width + 1; if ((1ULL << (haw + 1)) > BUS_SPACE_MAXADDR) dmar_high = BUS_SPACE_MAXADDR; else dmar_high = 1ULL << (haw + 1); if (bootverbose) { printf("DMAR HAW=%d flags=<%b>\n", dmartbl->Width, (unsigned)dmartbl->Flags, "\020\001INTR_REMAP\002X2APIC_OPT_OUT"); } AcpiPutTable((ACPI_TABLE_HEADER *)dmartbl); dmar_iterate_tbl(dmar_count_iter, NULL); if (dmar_devcnt == 0) return; dmar_devs = malloc(sizeof(device_t) * dmar_devcnt, M_DEVBUF, M_WAITOK | M_ZERO); for (i = 0; i < dmar_devcnt; i++) { dmarh = dmar_find_by_index(i); if (dmarh == NULL) { printf("dmar_identify: cannot find HWUNIT %d\n", i); continue; } dmar_devs[i] = BUS_ADD_CHILD(parent, 1, "dmar", i); if (dmar_devs[i] == NULL) { printf("dmar_identify: cannot create instance %d\n", i); continue; } error = bus_set_resource(dmar_devs[i], SYS_RES_MEMORY, DMAR_REG_RID, dmarh->Address, PAGE_SIZE); if (error != 0) { printf( "dmar%d: unable to alloc register window at 0x%08jx: error %d\n", i, (uintmax_t)dmarh->Address, error); device_delete_child(parent, dmar_devs[i]); dmar_devs[i] = NULL; } } }
/* * Query the MCFG table using ACPI. If MCFG is found, setup the * 'ecfg' property accordingly. Otherwise, set the values * to the default values. */ void npe_query_acpi_mcfg(dev_info_t *dip) { MCFG_TABLE *mcfgp; CFG_BASE_ADDR_ALLOC *cfg_baap; char *cfg_baa_endp; int64_t ecfginfo[4]; int ecfg_found = 0; /* Query the MCFG table using ACPI */ if (AcpiGetTable(ACPI_SIG_MCFG, 1, (ACPI_TABLE_HEADER **)&mcfgp) == AE_OK) { cfg_baap = (CFG_BASE_ADDR_ALLOC *)mcfgp->CfgBaseAddrAllocList; cfg_baa_endp = ((char *)mcfgp) + mcfgp->Length; while ((char *)cfg_baap < cfg_baa_endp) { if (cfg_baap->base_addr != (uint64_t)0 && cfg_baap->segment == 0) { /* * Set up the 'ecfg' property to hold * base_addr, segment, and first/last bus. * We only do the first entry that maps * segment 0; nonzero segments are not yet * known, or handled. If they appear, * we'll need to figure out which bus node * should have which entry by examining the * ACPI _SEG method on each bus node. */ ecfginfo[0] = cfg_baap->base_addr; ecfginfo[1] = cfg_baap->segment; ecfginfo[2] = cfg_baap->start_bno; ecfginfo[3] = cfg_baap->end_bno; (void) ndi_prop_update_int64_array( DDI_DEV_T_NONE, dip, "ecfg", ecfginfo, 4); ecfg_found = 1; break; } cfg_baap++; } } if (ecfg_found) return; /* * If MCFG is not found or ecfga_base is not found in MCFG table, * set the property to the default values. */ ecfginfo[0] = npe_default_ecfga_base; ecfginfo[1] = 0; /* segment 0 */ ecfginfo[2] = 0; /* first bus 0 */ ecfginfo[3] = 0xff; /* last bus ff */ (void) ndi_prop_update_int64_array(DDI_DEV_T_NONE, dip, "ecfg", ecfginfo, 4); }
/* * Locate the ACPI timer using the FADT, set up and allocate the I/O resources * we will be using. */ static int acpi_hpet_identify(driver_t *driver, device_t parent) { ACPI_TABLE_HPET *hpet; ACPI_TABLE_HEADER *hdr; ACPI_STATUS status; device_t child; /* * Just try once, do nothing if the 'acpi' bus is rescanned. */ if (device_get_state(parent) == DS_ATTACHED) return 0; ACPI_FUNCTION_TRACE((char *)(uintptr_t) __func__); /* Only one HPET device can be added. */ if (devclass_get_device(acpi_hpet_devclass, 0)) return ENXIO; /* Currently, ID and minimum clock tick info is unused. */ status = AcpiGetTable(ACPI_SIG_HPET, 1, &hdr); if (ACPI_FAILURE(status)) return ENXIO; /* * The unit number could be derived from hdr->Sequence but we only * support one HPET device. */ hpet = (ACPI_TABLE_HPET *)hdr; if (hpet->Sequence != 0) { kprintf("ACPI HPET table warning: Sequence is non-zero (%d)\n", hpet->Sequence); } child = BUS_ADD_CHILD(parent, parent, 0, "acpi_hpet", 0); if (child == NULL) { device_printf(parent, "%s: can't add acpi_hpet0\n", __func__); return ENXIO; } /* Record a magic value so we can detect this device later. */ acpi_set_magic(child, (uintptr_t)&acpi_hpet_devclass); acpi_hpet_res_start = hpet->Address.Address; if (bus_set_resource(child, SYS_RES_MEMORY, 0, hpet->Address.Address, HPET_MEM_WIDTH, -1)) { device_printf(child, "could not set iomem resources: " "0x%jx, %d\n", (uintmax_t)hpet->Address.Address, HPET_MEM_WIDTH); return ENOMEM; } return 0; }
ACPI_TABLE_MADT * acpi_get_madt() { ACPI_TABLE_HEADER * table; ACPI_STATUS status = AcpiGetTable(ACPI_SIG_MADT, 1, &table); if(ACPI_FAILURE(status)) { return 0; } else if(strncmp(table->Signature, ACPI_SIG_MADT, ACPI_NAME_SIZE) == 0) { return (ACPI_TABLE_MADT*)table; } else { kprintf("spurious acpi table name while looking for MADT: %s\n", table->Signature); return 0; } }
/* * Iterate IVRS table for IVHD and IVMD device type. */ static void ivrs_hdr_iterate_tbl(ivhd_iter_t iter, void *arg) { ACPI_TABLE_IVRS *ivrs; ACPI_IVRS_HEADER *ivrs_hdr, *end; ACPI_STATUS status; status = AcpiGetTable(ACPI_SIG_IVRS, 1, (ACPI_TABLE_HEADER **)&ivrs); if (ACPI_FAILURE(status)) return; if (ivrs->Header.Length == 0) { return; } ivrs_hdr = (ACPI_IVRS_HEADER *)(ivrs + 1); end = (ACPI_IVRS_HEADER *)((char *)ivrs + ivrs->Header.Length); while (ivrs_hdr < end) { if ((uint8_t *)ivrs_hdr + ivrs_hdr->Length > (uint8_t *)end) { printf("AMD-Vi:IVHD/IVMD is corrupted, length : %d\n", ivrs_hdr->Length); break; } switch (ivrs_hdr->Type) { case IVRS_TYPE_HARDWARE_LEGACY: /* Legacy */ case IVRS_TYPE_HARDWARE_EFR: case IVRS_TYPE_HARDWARE_MIXED: if (!iter(ivrs_hdr, arg)) return; break; case ACPI_IVRS_TYPE_MEMORY1: case ACPI_IVRS_TYPE_MEMORY2: case ACPI_IVRS_TYPE_MEMORY3: if (!iter(ivrs_hdr, arg)) return; break; default: printf("AMD-Vi:Not IVHD/IVMD type(%d)", ivrs_hdr->Type); } ivrs_hdr = (ACPI_IVRS_HEADER *)((uint8_t *)ivrs_hdr + ivrs_hdr->Length); } }
/* * Check for Metropolis systems with BIOSes older than 10/12/04 * return TRUE if BIOS requires legacy mode, FALSE otherwise */ static int acpica_metro_old_bios() { ACPI_TABLE_HEADER *fadt; /* get the FADT */ if (AcpiGetTable(ACPI_SIG_FADT, 1, (ACPI_TABLE_HEADER **)&fadt) != AE_OK) return (FALSE); /* compare OEM Table ID to "SUNmetro" - no match, return false */ if (strncmp("SUNmetro", fadt->OemTableId, 8)) return (FALSE); /* On a Metro - return FALSE if later than 10/12/04 */ return (!acpica_check_bios_date(2004, 10, 12)); }
static PyObject *bits_acpi_get_table(PyObject *self, PyObject *args) { char *signature; U32 instance = 1; ACPI_TABLE_HEADER *table_header; if (!PyArg_ParseTuple(args, "s|I", &signature, &instance)) return NULL; if (acpica_init() != GRUB_ERR_NONE) return PyErr_Format(PyExc_RuntimeError, "ACPICA module failed to initialize."); if (ACPI_FAILURE(AcpiGetTable(signature, instance, &table_header))) return Py_BuildValue(""); return Py_BuildValue("s#", table_header, table_header->Length); }
void acpica_find_ioapics(void) { int madt_seen, madt_size; ACPI_SUBTABLE_HEADER *ap; ACPI_MADT_IO_APIC *mia; if (acpi_mapic_dtp != NULL) return; /* already parsed table */ if (AcpiGetTable(ACPI_SIG_MADT, 1, (ACPI_TABLE_HEADER **) &acpi_mapic_dtp) != AE_OK) return; napics_found = 0; /* * Search the MADT for ioapics */ ap = (ACPI_SUBTABLE_HEADER *) (acpi_mapic_dtp + 1); madt_size = acpi_mapic_dtp->Header.Length; madt_seen = sizeof (*acpi_mapic_dtp); while (madt_seen < madt_size) { switch (ap->Type) { case ACPI_MADT_TYPE_IO_APIC: mia = (ACPI_MADT_IO_APIC *) ap; if (napics_found < MAX_IO_APIC) { ioapic_paddr[napics_found++] = (ACPI_PHYSICAL_ADDRESS) (mia->Address & PAGEMASK); } break; default: break; } /* advance to next entry */ madt_seen += ap->Length; ap = (ACPI_SUBTABLE_HEADER *)(((char *)ap) + ap->Length); } if (dummy_ioapicadr == NULL) dummy_ioapicadr = kmem_zalloc(PAGESIZE, KM_SLEEP); }
void bootOtherProcessors() { ACPI_TABLE_HEADER *madt; ACPICA_CHECK(AcpiGetTable(const_cast<char *>("APIC"), 0, &madt)); frigg::infoLogger() << "thor: Booting APs." << frigg::endLog; size_t offset = sizeof(ACPI_TABLE_HEADER) + sizeof(MadtHeader); while(offset < madt->Length) { auto generic = (MadtGenericEntry *)((uint8_t *)madt + offset); if(generic->type == 0) { // local APIC auto entry = (MadtLocalEntry *)generic; // TODO: Support BSPs with APIC ID != 0. if((entry->flags & local_flags::enabled) && entry->localApicId) // We ignore the BSP here. bootSecondary(entry->localApicId); } offset += generic->length; } }
void acpi_init() { ACPI_STATUS status; status = AcpiInitializeTables(TableArray, ACPI_MAX_INIT_TABLES, FALSE); LRT_Assert(status == AE_OK); madt *madt_ptr; status = AcpiGetTable("APIC", 0, (ACPI_TABLE_HEADER **)&madt_ptr); LRT_Assert(status == AE_OK); uint32_t size = madt_ptr->header.Length - sizeof(madt); uint8_t *ptr = (uint8_t *)(madt_ptr + 1); uint8_t ioapics = 0; do { if (*ptr == PROCESSOR_LOCAL_APIC) { lapic_structure *ls = (lapic_structure *)ptr; size -= ls->length; ptr += ls->length; //do nothing with the structure } else if (*ptr == IO_APIC) { ioapic_structure *is = (ioapic_structure *)ptr; size -= is->length; ptr += is->length; init_ioapic((ioapic *)(uintptr_t)is->ioapic_address); LRT_Assert(++ioapics < 2); lrt_printf("found ioapic table\n"); } else if (*ptr == INTERRUPT_SOURCE_OVERRIDE) { iso_structure *is = (iso_structure *)ptr; size -= is->length; ptr += is->length; lrt_printf("IRQ %d is mapped to I/O APIC input %d\n", is->source, is->global_system_interrupt); } else { //No definitions for other structures yet! lrt_printf("Found MADT structed unimplimented: %d\n", *ptr); LRT_Assert(0); } } while (size > 0); }
static int acpi_wdrt_match(device_t parent, cfdata_t match, void *opaque) { ACPI_TABLE_WDRT *wdrt; ACPI_STATUS rv; uint32_t val; rv = AcpiGetTable(ACPI_SIG_WDRT, 1, (ACPI_TABLE_HEADER **)&wdrt); if (ACPI_FAILURE(rv)) return 0; /* Only system memory address spaces are allowed */ if (wdrt->ControlRegister.SpaceId != ACPI_ADR_SPACE_SYSTEM_MEMORY || wdrt->CountRegister.SpaceId != ACPI_ADR_SPACE_SYSTEM_MEMORY) { return 0; } /* Sanity check control & count register addresses */ if (wdrt->ControlRegister.Address == 0 || wdrt->ControlRegister.Address == 0xffffffff || wdrt->ControlRegister.Address == 0xffffffffffffffff || wdrt->CountRegister.Address == 0 || wdrt->CountRegister.Address == 0xffffffff || wdrt->CountRegister.Address == 0xffffffffffffffff) { return 0; } /* Read control regster */ rv = AcpiOsReadMemory(wdrt->ControlRegister.Address, &val, wdrt->ControlRegister.BitWidth); if (ACPI_FAILURE(rv)) return 0; /* Make sure the hardware watchdog is enabled */ if ((val & ACPI_WDRT_CSR_WDOGEN) == ACPI_WDRT_WDOGEN_DISABLE) return 0; return 1; }
void initializeBasicSystem() { ACPICA_CHECK(AcpiInitializeSubsystem()); ACPICA_CHECK(AcpiInitializeTables(nullptr, 16, FALSE)); ACPICA_CHECK(AcpiLoadTables()); frigg::infoLogger() << "thor: ACPICA initialized." << frigg::endLog; dumpMadt(); ACPI_TABLE_HEADER *madt; ACPICA_CHECK(AcpiGetTable(const_cast<char *>("APIC"), 0, &madt)); // Configure all interrupt controllers. // TODO: This should be done during thor's initialization in order to avoid races. frigg::infoLogger() << "thor: Configuring I/O APICs." << frigg::endLog; size_t offset = sizeof(ACPI_TABLE_HEADER) + sizeof(MadtHeader); while(offset < madt->Length) { auto generic = (MadtGenericEntry *)((uint8_t *)madt + offset); if(generic->type == 1) { // I/O APIC auto entry = (MadtIoEntry *)generic; assert(!entry->systemIntBase); setupIoApic(entry->mmioAddress); } offset += generic->length; } // Determine IRQ override configuration. for(int i = 0; i < 16; i++) irqOverrides[i].initialize(); offset = sizeof(ACPI_TABLE_HEADER) + sizeof(MadtHeader); while(offset < madt->Length) { auto generic = (MadtGenericEntry *)((uint8_t *)madt + offset); if(generic->type == 2) { // interrupt source override auto entry = (MadtIntOverrideEntry *)generic; // ACPI defines only ISA IRQ overrides. assert(entry->bus == 0); assert(entry->sourceIrq < 16); IrqLine line; line.gsi = entry->systemInt; auto trigger = entry->flags & OverrideFlags::triggerMask; auto polarity = entry->flags & OverrideFlags::polarityMask; if(trigger == OverrideFlags::triggerDefault && polarity == OverrideFlags::polarityDefault) { line.configuration.trigger = TriggerMode::edge; line.configuration.polarity = Polarity::high; }else{ assert(trigger != OverrideFlags::triggerDefault); assert(polarity != OverrideFlags::polarityDefault); switch(trigger) { case OverrideFlags::triggerEdge: line.configuration.trigger = TriggerMode::edge; break; case OverrideFlags::triggerLevel: line.configuration.trigger = TriggerMode::level; break; default: frigg::panicLogger() << "Illegal IRQ trigger mode in MADT" << frigg::endLog; } switch(polarity) { case OverrideFlags::polarityHigh: line.configuration.polarity = Polarity::high; break; case OverrideFlags::polarityLow: line.configuration.polarity = Polarity::low; break; default: frigg::panicLogger() << "Illegal IRQ polarity in MADT" << frigg::endLog; } } assert(!(*irqOverrides[entry->sourceIrq])); *irqOverrides[entry->sourceIrq] = line; } offset += generic->length; } // Initialize the HPET. frigg::infoLogger() << "thor: Setting up HPET." << frigg::endLog; ACPI_TABLE_HEADER *hpet_table; ACPICA_CHECK(AcpiGetTable(const_cast<char *>("HPET"), 0, &hpet_table)); auto hpet_entry = (HpetEntry *)((uintptr_t)hpet_table + sizeof(ACPI_TABLE_HEADER)); assert(hpet_entry->address.SpaceId == ACPI_ADR_SPACE_SYSTEM_MEMORY); setupHpet(hpet_entry->address.Address); }
ACPI_STATUS AdAmlDisassemble ( BOOLEAN OutToFile, char *Filename, char *Prefix, char **OutFilename, BOOLEAN GetAllTables) { ACPI_STATUS Status; char *DisasmFilename = NULL; char *ExternalFilename; ACPI_EXTERNAL_FILE *ExternalFileList = AcpiGbl_ExternalFileList; FILE *File = NULL; ACPI_TABLE_HEADER *Table = NULL; ACPI_TABLE_HEADER *ExternalTable; ACPI_OWNER_ID OwnerId; /* * Input: AML code from either a file or via GetTables (memory or * registry) */ if (Filename) { Status = AcpiDbGetTableFromFile (Filename, &Table); if (ACPI_FAILURE (Status)) { return (Status); } /* * External filenames separated by commas * Example: iasl -e file1,file2,file3 -d xxx.aml */ while (ExternalFileList) { ExternalFilename = ExternalFileList->Path; if (!ACPI_STRCMP (ExternalFilename, Filename)) { /* Next external file */ ExternalFileList = ExternalFileList->Next; continue; } Status = AcpiDbGetTableFromFile (ExternalFilename, &ExternalTable); if (ACPI_FAILURE (Status)) { return (Status); } /* Load external table for symbol resolution */ if (ExternalTable) { Status = AdParseTable (ExternalTable, &OwnerId, TRUE, TRUE); if (ACPI_FAILURE (Status)) { AcpiOsPrintf ("Could not parse external ACPI tables, %s\n", AcpiFormatException (Status)); return (Status); } /* * Load namespace from names created within control methods * Set owner id of nodes in external table */ AcpiDmFinishNamespaceLoad (AcpiGbl_ParseOpRoot, AcpiGbl_RootNode, OwnerId); AcpiPsDeleteParseTree (AcpiGbl_ParseOpRoot); } /* Next external file */ ExternalFileList = ExternalFileList->Next; } /* Clear external list generated by Scope in external tables */ if (AcpiGbl_ExternalFileList) { AcpiDmClearExternalList (); } } else { Status = AdGetLocalTables (Filename, GetAllTables); if (ACPI_FAILURE (Status)) { AcpiOsPrintf ("Could not get ACPI tables, %s\n", AcpiFormatException (Status)); return (Status); } if (!AcpiGbl_DbOpt_disasm) { return (AE_OK); } /* Obtained the local tables, just disassemble the DSDT */ Status = AcpiGetTable (ACPI_SIG_DSDT, 0, &Table); if (ACPI_FAILURE (Status)) { AcpiOsPrintf ("Could not get DSDT, %s\n", AcpiFormatException (Status)); return (Status); } AcpiOsPrintf ("\nDisassembly of DSDT\n"); Prefix = AdGenerateFilename ("dsdt", Table->OemTableId); } /* * Output: ASL code. Redirect to a file if requested */ if (OutToFile) { /* Create/Open a disassembly output file */ DisasmFilename = FlGenerateFilename (Prefix, FILE_SUFFIX_DISASSEMBLY); if (!OutFilename) { fprintf (stderr, "Could not generate output filename\n"); Status = AE_ERROR; goto Cleanup; } File = fopen (DisasmFilename, "w+"); if (!File) { fprintf (stderr, "Could not open output file %s\n", DisasmFilename); Status = AE_ERROR; goto Cleanup; } AcpiOsRedirectOutput (File); } *OutFilename = DisasmFilename; if (!AcpiUtIsAmlTable (Table)) { AdDisassemblerHeader (Filename); AcpiOsPrintf (" * ACPI Data Table [%4.4s]\n *\n", Table->Signature); AcpiOsPrintf (" * Format: [HexOffset DecimalOffset ByteLength] " "FieldName : FieldValue\n */\n\n"); AcpiDmDumpDataTable (Table); fprintf (stderr, "Acpi Data Table [%4.4s] decoded\n", Table->Signature); fprintf (stderr, "Formatted output: %s - %u bytes\n", DisasmFilename, AdGetFileSize (File)); } else { /* Always parse the tables, only option is what to display */ Status = AdParseTable (Table, &OwnerId, TRUE, FALSE); if (ACPI_FAILURE (Status)) { AcpiOsPrintf ("Could not parse ACPI tables, %s\n", AcpiFormatException (Status)); goto Cleanup; } if (AslCompilerdebug) { AcpiOsPrintf ("/**** Before second load\n"); NsSetupNamespaceListing (File); NsDisplayNamespace (); AcpiOsPrintf ("*****/\n"); } /* Load namespace from names created within control methods */ AcpiDmFinishNamespaceLoad (AcpiGbl_ParseOpRoot, AcpiGbl_RootNode, OwnerId); /* * Cross reference the namespace here, in order to * generate External() statements */ AcpiDmCrossReferenceNamespace (AcpiGbl_ParseOpRoot, AcpiGbl_RootNode, OwnerId); if (AslCompilerdebug) { AcpiDmDumpTree (AcpiGbl_ParseOpRoot); } /* Find possible calls to external control methods */ AcpiDmFindOrphanMethods (AcpiGbl_ParseOpRoot); /* * If we found any external control methods, we must reparse * the entire tree with the new information (namely, the * number of arguments per method) */ if (AcpiDmGetExternalMethodCount ()) { fprintf (stderr, "\nFound %u external control methods, " "reparsing with new information\n", AcpiDmGetExternalMethodCount ()); /* Reparse, rebuild namespace. no need to xref namespace */ AcpiPsDeleteParseTree (AcpiGbl_ParseOpRoot); AcpiNsDeleteNamespaceSubtree (AcpiGbl_RootNode); AcpiGbl_RootNode = NULL; AcpiGbl_RootNodeStruct.Name.Integer = ACPI_ROOT_NAME; AcpiGbl_RootNodeStruct.DescriptorType = ACPI_DESC_TYPE_NAMED; AcpiGbl_RootNodeStruct.Type = ACPI_TYPE_DEVICE; AcpiGbl_RootNodeStruct.Parent = NULL; AcpiGbl_RootNodeStruct.Child = NULL; AcpiGbl_RootNodeStruct.Peer = NULL; AcpiGbl_RootNodeStruct.Object = NULL; AcpiGbl_RootNodeStruct.Flags = 0; Status = AcpiNsRootInitialize (); AcpiDmAddExternalsToNamespace (); /* Parse the table again. No need to reload it, however */ Status = AdParseTable (Table, NULL, FALSE, FALSE); if (ACPI_FAILURE (Status)) { AcpiOsPrintf ("Could not parse ACPI tables, %s\n", AcpiFormatException (Status)); goto Cleanup; } if (AslCompilerdebug) { AcpiOsPrintf ("/**** After second load and resource conversion\n"); NsSetupNamespaceListing (File); NsDisplayNamespace (); AcpiOsPrintf ("*****/\n"); AcpiDmDumpTree (AcpiGbl_ParseOpRoot); } } /* * Now that the namespace is finalized, we can perform namespace * transforms. * * 1) Convert fixed-offset references to resource descriptors * to symbolic references (Note: modifies namespace) */ AcpiDmConvertResourceIndexes (AcpiGbl_ParseOpRoot, AcpiGbl_RootNode); /* Optional displays */ if (AcpiGbl_DbOpt_disasm) { /* This is the real disassembly */ AdDisplayTables (Filename, Table); /* Dump hex table if requested (-vt) */ AcpiDmDumpDataTable (Table); fprintf (stderr, "Disassembly completed\n"); fprintf (stderr, "ASL Output: %s - %u bytes\n", DisasmFilename, AdGetFileSize (File)); } } Cleanup: if (Table && !AcpiUtIsAmlTable (Table)) { ACPI_FREE (Table); } if (OutToFile && File) { if (AslCompilerdebug) /* Display final namespace, with transforms */ { NsSetupNamespaceListing (File); NsDisplayNamespace (); } fclose (File); AcpiOsRedirectOutput (stdout); } AcpiPsDeleteParseTree (AcpiGbl_ParseOpRoot); AcpiGbl_ParseOpRoot = NULL; return (Status); }
/* First of all, devices exists on TWO different * busses. PCI and PCI Express. */ void PciEnumerate(void) { /* We need these */ ACPI_TABLE_MCFG *McfgTable = NULL; ACPI_TABLE_HEADER *Header = NULL; uint8_t Function; uint8_t Bus; uint8_t HeaderType; /* Init list, this is "bus 0" */ GlbPciDevices = list_create(LIST_SAFE); /* Pci Express */ #ifdef PCI_EXPRESS if (ACPI_SUCCESS(AcpiGetTable(ACPI_SIG_MCFG, 0, &Header))) #else if (Header != NULL && McfgTable != NULL) #endif { /* Woah, there exists Pci Express Controllers */ uint32_t EntryCount = (McfgTable->Header.Length - sizeof(ACPI_TABLE_MCFG) / sizeof(McfgEntry_t)); uint32_t Itr = 0; McfgEntry_t *Entry = (McfgEntry_t*)((uint8_t*)McfgTable + sizeof(ACPI_TABLE_MCFG)); /* Iterate */ for (Itr = 0; Itr < EntryCount; Itr++) { /* Allocate entry */ PciBus_t *Bus = (PciBus_t*)kmalloc(sizeof(PciBus_t)); /* Get size, which is the rest of the bytes */ int PageCount = (1024 * 1024 * 256) / PAGE_SIZE; /* Memory Map 256 MB!!!!! Oh f*****g god */ Bus->IoSpace = IoSpaceCreate(DEVICE_IO_SPACE_MMIO, (Addr_t)Entry->BaseAddress, PageCount); Bus->IsExtended = 1; Bus->BusStart = Entry->StartBus; Bus->BusEnd = Entry->EndBus; Bus->Segment = Entry->SegmentGroup; /* Enumerate devices */ /* Next */ Entry++; } } else { /* Pci Legacy */ HeaderType = PciReadHeaderType(0, 0, 0); if ((HeaderType & 0x80) == 0) { /* Single PCI host controller */ PciCheckBus(GlbPciDevices, 0); } else { /* Multiple PCI host controllers */ for (Function = 0; Function < 8; Function++) { if (PciReadVendorId(0, 0, Function) != 0xFFFF) break; /* Check bus */ Bus = Function; PciCheckBus(GlbPciDevices, Bus); } } } }
static int process_acpi_tables (void) { extern uint32 mp_LAPIC_addr; extern uint32 mp_num_IOAPICs; extern uint32 mp_IOAPIC_addr; extern mp_IOAPIC_info mp_IOAPICs[]; extern uint32 mp_num_overrides; extern mp_int_override mp_overrides[]; ACPI_STATUS status; status = AcpiInitializeTables (TableArray, ACPI_MAX_INIT_TABLES, FALSE); if (status == AE_OK) { ACPI_TABLE_MADT *madt; ACPI_TABLE_FADT *fadt; ACPI_TABLE_BOOT *boot; ACPI_TABLE_ASF *asf; ACPI_TABLE_MCFG *mcfg; ACPI_TABLE_HPET *hpet; ACPI_TABLE_TCPA *tcpa; ACPI_TABLE_SRAT *srat; ACPI_TABLE_DMAR *dmar; if (AcpiGetTable (ACPI_SIG_FADT, 0, (ACPI_TABLE_HEADER **) & fadt) == AE_OK) { /* Fixed ACPI Description Table */ DLOG_COM1 ("Bootflags: %s %s %s\n", (fadt->BootFlags & ACPI_FADT_LEGACY_DEVICES) ? "HAS_LEGACY_DEVICES" : "NO_LEGACY_DEVICES", (fadt->BootFlags & ACPI_FADT_8042) ? "HAS_KBD_8042" : "NO_KBD_8042", (fadt->BootFlags & ACPI_FADT_NO_VGA) ? "NO_VGA_PROBING" : "VGA_PROBING_OK"); DLOG_COM1 ("Flags=0x%X SCI_IRQ=0x%X Pm1aEvt=0x%p Pm1aCtl=0x%p\n", fadt->Flags, fadt->SciInterrupt, fadt->Pm1aEventBlock, fadt->Pm1aControlBlock); DLOG_COM1 ("ResetReg=0x%llX ResetSpace=%d ResetVal=0x%X\n", fadt->ResetRegister.Address, fadt->ResetRegister.SpaceId, fadt->ResetValue); acpi_sci_irq = fadt->SciInterrupt; } else { DLOG_COM1 ("AcpiGetTable FADT: FAILED\n"); } mp_ISA_bus_id = 0; if (AcpiGetTable (ACPI_SIG_MADT, 0, (ACPI_TABLE_HEADER **) & madt) == AE_OK) { /* Multiple APIC Description Table */ uint8 *ptr, *lim = (uint8 *) madt + madt->Header.Length; DLOG_COM1 ("ACPI OEM: %.6s Compiler: %.4s LAPIC: %p Flags:%s\n", madt->Header.OemId, madt->Header.AslCompilerId, madt->Address, (madt->Flags & ACPI_MADT_PCAT_COMPAT) ? " PCAT_COMPAT" : ""); mp_LAPIC_addr = madt->Address; ptr = (uint8 *) madt + sizeof (ACPI_TABLE_MADT); while (ptr < lim) { switch (((ACPI_SUBTABLE_HEADER *) ptr)->Type) { case ACPI_MADT_TYPE_LOCAL_APIC:{ /* Processor entry */ ACPI_MADT_LOCAL_APIC *sub = (ACPI_MADT_LOCAL_APIC *) ptr; DLOG_COM1 ("Processor: 0x%X APIC-ID: 0x%X %s", sub->ProcessorId, sub->Id, sub->LapicFlags & 1 ? "(enabled)" : "(disabled)"); if (acpi_add_processor (sub)) { DLOG_COM1 (" (booted)"); } DLOG_COM1 ("\n"); break; } case ACPI_MADT_TYPE_IO_APIC:{ /* IO-APIC entry */ ACPI_MADT_IO_APIC *sub = (ACPI_MADT_IO_APIC *) ptr; DLOG_COM1 ("IO-APIC ID: %X Address: %X IRQBase: %X\n", sub->Id, sub->Address, sub->GlobalIrqBase); if (mp_num_IOAPICs == MAX_IOAPICS) panic ("Too many IO-APICs."); mp_IOAPIC_addr = sub->Address; mp_IOAPICs[mp_num_IOAPICs].id = sub->Id; mp_IOAPICs[mp_num_IOAPICs].address = sub->Address; mp_IOAPICs[mp_num_IOAPICs].startGSI = sub->GlobalIrqBase; mp_IOAPICs[mp_num_IOAPICs].numGSIs = IOAPIC_num_entries(); mp_num_IOAPICs++; break; } case ACPI_MADT_TYPE_INTERRUPT_OVERRIDE:{ /* Interrupt Override entry */ ACPI_MADT_INTERRUPT_OVERRIDE *sub = (ACPI_MADT_INTERRUPT_OVERRIDE *) ptr; DLOG_COM1 ("Int. Override: Bus: %X SourceIRQ: %X GlobalIRQ: %X Flags: %X\n", sub->Bus, sub->SourceIrq, sub->GlobalIrq, sub->IntiFlags); if (mp_num_overrides == MAX_INT_OVERRIDES) panic ("Too many interrupt overrides."); mp_overrides[mp_num_overrides].src_bus = sub->Bus; mp_overrides[mp_num_overrides].src_IRQ = sub->SourceIrq; mp_overrides[mp_num_overrides].dest_GSI = sub->GlobalIrq; mp_num_overrides++; /* (special case) SCI interrupt: it can be different in ACPI * tables vs Intel MPS tables. */ if (sub->SourceIrq == acpi_sci_irq) { acpi_sci_irq = sub->GlobalIrq; acpi_sci_flags = sub->IntiFlags; } break; } default: DLOG_COM1 ("MADT sub-entry: %X\n", ((ACPI_SUBTABLE_HEADER *) ptr)->Type); break; } ptr += ((ACPI_SUBTABLE_HEADER *) ptr)->Length; } } else { DLOG_COM1 ("AcpiGetTable MADT: FAILED\n"); return 0; } if (AcpiGetTable (ACPI_SIG_BOOT, 0, (ACPI_TABLE_HEADER **) & boot) == AE_OK) { /* Simple Boot Information Table */ DLOG_COM1 ("BOOT: CmosIndex=0x%X\n", boot->CmosIndex); } if (AcpiGetTable (ACPI_SIG_TCPA, 0, (ACPI_TABLE_HEADER **) & tcpa) == AE_OK) { /* Trusted Computing Platform Alliance table */ DLOG_COM1 ("TCPA: MaxLog=0x%X Addr: 0x%llX\n", tcpa->MaxLogLength, tcpa->LogAddress); } if (AcpiGetTable (ACPI_SIG_HPET, 0, (ACPI_TABLE_HEADER **) & hpet) == AE_OK) { /* High Precision Event Timer table */ DLOG_COM1 ("HPET: ID: 0x%X Addr: 0x%p Seq#: 0x%X MinTick: 0x%X Flags: 0x%X\n", hpet->Id, hpet->Address, (uint32) hpet->Sequence, (uint32) hpet->MinimumTick, (uint32) hpet->Flags); } if (AcpiGetTable (ACPI_SIG_MCFG, 0, (ACPI_TABLE_HEADER **) & mcfg) == AE_OK) { /* PCI Memory Mapped Configuration table */ DLOG_COM1 ("MCFG: Length: %d Reserved: 0x%llX\n", mcfg->Header.Length, mcfg->Reserved); } if (AcpiGetTable (ACPI_SIG_ASF, 0, (ACPI_TABLE_HEADER **) & asf) == AE_OK) { /* Alert Standard Format table */ DLOG_COM1 ("ASF: Length: %d\n", mcfg->Header.Length); } if (AcpiGetTable (ACPI_SIG_SRAT, 0, (ACPI_TABLE_HEADER **) & srat) == AE_OK) { /* System Resource Affinity Table */ DLOG_COM1 ("SRAT: Length: %d\n", srat->Header.Length); acpi_parse_srat (srat); } if (AcpiGetTable (ACPI_SIG_DMAR, 0, (ACPI_TABLE_HEADER **) & dmar) == AE_OK) { /* DMA Remapping */ DLOG_COM1 ("DMAR: Length: %d Flags: 0x%X Width: %d\n", dmar->Header.Length, dmar->Flags, dmar->Width); } } else return 0; return mp_num_cpus; }
static void AcpiEvOrphanEcRegMethod ( void) { ACPI_TABLE_ECDT *Table; ACPI_STATUS Status; ACPI_OBJECT_LIST Args; ACPI_OBJECT Objects[2]; ACPI_NAMESPACE_NODE *EcDeviceNode; ACPI_NAMESPACE_NODE *RegMethod; ACPI_NAMESPACE_NODE *NextNode; ACPI_FUNCTION_TRACE (EvOrphanEcRegMethod); /* Get the ECDT (if present in system) */ Status = AcpiGetTable (ACPI_SIG_ECDT, 0, ACPI_CAST_INDIRECT_PTR (ACPI_TABLE_HEADER, &Table)); if (ACPI_FAILURE (Status)) { return_VOID; } /* We need a valid EC_ID string */ if (!(*Table->Id)) { return_VOID; } /* Namespace is currently locked, must release */ (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); /* Get a handle to the EC device referenced in the ECDT */ Status = AcpiGetHandle (NULL, ACPI_CAST_PTR (char, Table->Id), ACPI_CAST_PTR (ACPI_HANDLE, &EcDeviceNode)); if (ACPI_FAILURE (Status)) { goto Exit; } /* Get a handle to a _REG method immediately under the EC device */ Status = AcpiGetHandle (EcDeviceNode, METHOD_NAME__REG, ACPI_CAST_PTR (ACPI_HANDLE, &RegMethod)); if (ACPI_FAILURE (Status)) { goto Exit; } /* * Execute the _REG method only if there is no Operation Region in * this scope with the Embedded Controller space ID. Otherwise, it * will already have been executed. Note, this allows for Regions * with other space IDs to be present; but the code below will then * execute the _REG method with the EC space ID argument. */ NextNode = AcpiNsGetNextNode (EcDeviceNode, NULL); while (NextNode) { if ((NextNode->Type == ACPI_TYPE_REGION) && (NextNode->Object) && (NextNode->Object->Region.SpaceId == ACPI_ADR_SPACE_EC)) { goto Exit; /* Do not execute _REG */ } NextNode = AcpiNsGetNextNode (EcDeviceNode, NextNode); } /* Evaluate the _REG(EC,Connect) method */ Args.Count = 2; Args.Pointer = Objects; Objects[0].Type = ACPI_TYPE_INTEGER; Objects[0].Integer.Value = ACPI_ADR_SPACE_EC; Objects[1].Type = ACPI_TYPE_INTEGER; Objects[1].Integer.Value = ACPI_REG_CONNECT; Status = AcpiEvaluateObject (RegMethod, NULL, &Args, NULL); Exit: /* We ignore all errors from above, don't care */ Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); return_VOID; }
static void acpi_wdrt_attach(device_t parent, device_t self, void *opaque) { struct acpi_wdrt_softc *sc = device_private(self); ACPI_TABLE_WDRT *wdrt; ACPI_STATUS rv; sc->sc_dev = self; pmf_device_register(self, acpi_wdrt_suspend, NULL); rv = AcpiGetTable(ACPI_SIG_WDRT, 1, (ACPI_TABLE_HEADER **)&wdrt); if (ACPI_FAILURE(rv)) { aprint_error(": couldn't get WDRT (%s)\n", AcpiFormatException(rv)); return; } /* Maximum counter value must be 511 - 65535 */ if (wdrt->MaxCount < 511) { aprint_error(": maximum counter value out of range (%d)\n", wdrt->MaxCount); return; } /* Counter units can be 1s, 100ms, or 10ms */ switch (wdrt->Units) { case ACPI_WDRT_UNITS_1S: case ACPI_WDRT_UNITS_100MS: case ACPI_WDRT_UNITS_10MS: break; default: aprint_error(": units not supported (0x%x)\n", wdrt->Units); return; } sc->sc_control_reg = wdrt->ControlRegister; sc->sc_count_reg = wdrt->CountRegister; aprint_naive("\n"); aprint_normal(": mem 0x%" PRIx64 ",0x%" PRIx64 "\n", sc->sc_control_reg.Address, sc->sc_count_reg.Address); if (wdrt->PciVendorId != 0xffff && wdrt->PciDeviceId != 0xffff) { aprint_verbose_dev(sc->sc_dev, "PCI %u:%03u:%02u:%01u", wdrt->PciSegment, wdrt->PciBus, wdrt->PciDevice, wdrt->PciFunction); aprint_verbose(" vendor 0x%04x product 0x%04x\n", wdrt->PciVendorId, wdrt->PciDeviceId); } sc->sc_max_period = wdrt->MaxCount; sc->sc_period_scale = 1; if (wdrt->Units == ACPI_WDRT_UNITS_100MS) sc->sc_period_scale = 10; if (wdrt->Units == ACPI_WDRT_UNITS_10MS) sc->sc_period_scale = 100; sc->sc_max_period /= sc->sc_period_scale; aprint_normal_dev(self, "watchdog interval 1-%d sec.\n", sc->sc_max_period); sc->sc_smw.smw_name = device_xname(self); sc->sc_smw.smw_cookie = sc; sc->sc_smw.smw_setmode = acpi_wdrt_setmode; sc->sc_smw.smw_tickle = acpi_wdrt_tickle; sc->sc_smw.smw_period = sc->sc_max_period; if (sysmon_wdog_register(&sc->sc_smw)) aprint_error_dev(self, "couldn't register with sysmon\n"); else sc->sc_smw_valid = true; }
ACPI_STATUS acpica_get_sci(int *sci_irq, iflag_t *sci_flags) { ACPI_SUBTABLE_HEADER *ap; ACPI_TABLE_MADT *mat; ACPI_MADT_INTERRUPT_OVERRIDE *mio; ACPI_TABLE_FADT *fadt; int madt_seen, madt_size; /* * Make sure user options are processed, * then return error if ACPI CA has been * disabled or system is not running in ACPI * and won't need/understand SCI */ acpica_process_user_options(); if ((!acpica_enable) || (acpi_init_level & ACPI_NO_ACPI_ENABLE)) return (AE_ERROR); /* * according to Intel ACPI developers, SCI * conforms to PCI bus conventions; level/low * unless otherwise directed by overrides. */ sci_flags->intr_el = INTR_EL_LEVEL; sci_flags->intr_po = INTR_PO_ACTIVE_LOW; sci_flags->bustype = BUS_PCI; /* we *do* conform to PCI */ /* get the SCI from the FADT */ if (AcpiGetTable(ACPI_SIG_FADT, 1, (ACPI_TABLE_HEADER **)&fadt) != AE_OK) return (AE_ERROR); *sci_irq = fadt->SciInterrupt; /* search for ISOs that modify it */ /* if we don't find a MADT, that's OK; no ISOs then */ if (AcpiGetTable(ACPI_SIG_MADT, 1, (ACPI_TABLE_HEADER **) &mat) != AE_OK) return (AE_OK); ap = (ACPI_SUBTABLE_HEADER *) (mat + 1); madt_size = mat->Header.Length; madt_seen = sizeof (*mat); while (madt_seen < madt_size) { switch (ap->Type) { case ACPI_MADT_TYPE_INTERRUPT_OVERRIDE: mio = (ACPI_MADT_INTERRUPT_OVERRIDE *) ap; if (mio->SourceIrq == *sci_irq) { *sci_irq = mio->GlobalIrq; sci_flags->intr_el = (mio->IntiFlags & ACPI_MADT_TRIGGER_MASK) >> 2; sci_flags->intr_po = mio->IntiFlags & ACPI_MADT_POLARITY_MASK; } break; } /* advance to next entry */ madt_seen += ap->Length; ap = (ACPI_SUBTABLE_HEADER *)(((char *)ap) + ap->Length); }
void dumpMadt() { ACPI_TABLE_HEADER *madt; ACPICA_CHECK(AcpiGetTable(const_cast<char *>("APIC"), 0, &madt)); frigg::infoLogger() << "thor: Dumping MADT" << frigg::endLog; size_t offset = sizeof(ACPI_TABLE_HEADER) + sizeof(MadtHeader); while(offset < madt->Length) { auto generic = (MadtGenericEntry *)((uintptr_t)madt + offset); if(generic->type == 0) { // local APIC auto entry = (MadtLocalEntry *)generic; frigg::infoLogger() << " Local APIC id: " << (int)entry->localApicId << ((entry->flags & local_flags::enabled) ? "" :" (disabled)") << frigg::endLog; // TODO: This has to be refactored. // uint32_t id = entry->localApicId; // if(seen_bsp) // helControlKernel(kThorSubArch, kThorIfBootSecondary, // &id, nullptr); // seen_bsp = 1; }else if(generic->type == 1) { // I/O APIC auto entry = (MadtIoEntry *)generic; frigg::infoLogger() << " I/O APIC id: " << (int)entry->ioApicId << ", sytem interrupt base: " << (int)entry->systemIntBase << frigg::endLog; }else if(generic->type == 2) { // interrupt source override auto entry = (MadtIntOverrideEntry *)generic; const char *bus, *polarity, *trigger; if(entry->bus == 0) { bus = "ISA"; }else{ frigg::panicLogger() << "Unexpected bus in MADT interrupt override" << frigg::endLog; } if((entry->flags & OverrideFlags::polarityMask) == OverrideFlags::polarityDefault) { polarity = "default"; }else if((entry->flags & OverrideFlags::polarityMask) == OverrideFlags::polarityHigh) { polarity = "high"; }else if((entry->flags & OverrideFlags::polarityMask) == OverrideFlags::polarityLow) { polarity = "low"; }else{ frigg::panicLogger() << "Unexpected polarity in MADT interrupt override" << frigg::endLog; } if((entry->flags & OverrideFlags::triggerMask) == OverrideFlags::triggerDefault) { trigger = "default"; }else if((entry->flags & OverrideFlags::triggerMask) == OverrideFlags::triggerEdge) { trigger = "edge"; }else if((entry->flags & OverrideFlags::triggerMask) == OverrideFlags::triggerLevel) { trigger = "level"; }else{ frigg::panicLogger() << "Unexpected trigger mode in MADT interrupt override" << frigg::endLog; } frigg::infoLogger() << " Int override: " << bus << " IRQ " << (int)entry->sourceIrq << " is mapped to GSI " << entry->systemInt << " (Polarity: " << polarity << ", trigger mode: " << trigger << ")" << frigg::endLog; }else if(generic->type == 4) { // local APIC NMI source auto entry = (MadtLocalNmiEntry *)generic; frigg::infoLogger() << " Local APIC NMI: processor " << (int)entry->processorId << ", lint: " << (int)entry->localInt << frigg::endLog; }else{ frigg::infoLogger() << " Unexpected MADT entry of type " << generic->type << frigg::endLog; } offset += generic->length; } }
status_t get_table(const char* signature, uint32 instance, void** tableHeader) { return AcpiGetTable((char*)signature, instance, (ACPI_TABLE_HEADER**)tableHeader) == AE_OK ? B_OK : B_ERROR; }
ACPI_STATUS AdAmlDisassemble ( BOOLEAN OutToFile, char *Filename, char *Prefix, char **OutFilename) { ACPI_STATUS Status; char *DisasmFilename = NULL; FILE *File = NULL; ACPI_TABLE_HEADER *Table = NULL; ACPI_NEW_TABLE_DESC *ListHead = NULL; /* * Input: AML code from either a file or via GetTables (memory or * registry) */ if (Filename) { /* Get the list of all AML tables in the file */ Status = AcGetAllTablesFromFile (Filename, ACPI_GET_ALL_TABLES, &ListHead); if (ACPI_FAILURE (Status)) { AcpiOsPrintf ("Could not get ACPI tables from %s, %s\n", Filename, AcpiFormatException (Status)); return (Status); } /* Process any user-specified files for external objects */ Status = AdDoExternalFileList (Filename); if (ACPI_FAILURE (Status)) { return (Status); } } else { Status = AdGetLocalTables (); if (ACPI_FAILURE (Status)) { AcpiOsPrintf ("Could not get ACPI tables, %s\n", AcpiFormatException (Status)); return (Status); } if (!AcpiGbl_DmOpt_Disasm) { return (AE_OK); } /* Obtained the local tables, just disassemble the DSDT */ Status = AcpiGetTable (ACPI_SIG_DSDT, 0, &Table); if (ACPI_FAILURE (Status)) { AcpiOsPrintf ("Could not get DSDT, %s\n", AcpiFormatException (Status)); return (Status); } AcpiOsPrintf ("\nDisassembly of DSDT\n"); Prefix = AdGenerateFilename ("dsdt", Table->OemTableId); } /* * Output: ASL code. Redirect to a file if requested */ if (OutToFile) { /* Create/Open a disassembly output file */ DisasmFilename = FlGenerateFilename (Prefix, FILE_SUFFIX_DISASSEMBLY); if (!DisasmFilename) { fprintf (stderr, "Could not generate output filename\n"); Status = AE_ERROR; goto Cleanup; } File = fopen (DisasmFilename, "w+"); if (!File) { fprintf (stderr, "Could not open output file %s\n", DisasmFilename); Status = AE_ERROR; goto Cleanup; } AcpiOsRedirectOutput (File); } *OutFilename = DisasmFilename; /* Disassemble all AML tables within the file */ while (ListHead) { Status = AdDisassembleOneTable (ListHead->Table, File, Filename, DisasmFilename); if (ACPI_FAILURE (Status)) { break; } ListHead = ListHead->Next; } Cleanup: if (Table && !AcpiGbl_ForceAmlDisassembly && !AcpiUtIsAmlTable (Table)) { ACPI_FREE (Table); } if (File) { fclose (File); AcpiOsRedirectOutput (stdout); } AcpiPsDeleteParseTree (AcpiGbl_ParseOpRoot); AcpiGbl_ParseOpRoot = NULL; return (Status); }