Beispiel #1
0
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);
}
Beispiel #2
0
/* 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;
}
Beispiel #3
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);
}
Beispiel #4
0
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);
}
Beispiel #5
0
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));
}
Beispiel #6
0
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);
}
Beispiel #7
0
/* 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;
}
Beispiel #8
0
/*
 * 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", &params->glk);
    acpi_set_private(child, params);

    /* Finish the attach process. */
    if (device_probe_and_attach(child) != 0)
	device_delete_child(parent, child);
}
Beispiel #9
0
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;
}
Beispiel #10
0
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);
}
Beispiel #12
0
/*
 * 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;
}
Beispiel #13
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;
    }
}
Beispiel #14
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);
	}
}
Beispiel #15
0
/*
 * 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));
}
Beispiel #16
0
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);
}
Beispiel #17
0
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);
}
Beispiel #18
0
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;
	}
}
Beispiel #19
0
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;
}
Beispiel #21
0
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);
}
Beispiel #22
0
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);
}
Beispiel #23
0
/* 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);
			}
		}
	}
}
Beispiel #24
0
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;
}
Beispiel #25
0
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;
}
Beispiel #27
0
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);
	}
Beispiel #28
0
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;
	}
}
Beispiel #29
0
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;
}
Beispiel #30
0
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);
}