示例#1
0
int __init
acpi_table_parse_entries(char *id,
			     unsigned long table_size,
			     int entry_id,
			     acpi_table_entry_handler handler,
			     unsigned int max_entries)
{
	struct acpi_table_header *table_header = NULL;
	struct acpi_subtable_header *entry;
	unsigned int count = 0;
	unsigned long table_end;
	acpi_size tbl_size;

	if (acpi_disabled && !acpi_ht)
		return -ENODEV;

	if (!handler)
		return -EINVAL;

	if (strncmp(id, ACPI_SIG_MADT, 4) == 0)
		acpi_get_table_with_size(id, acpi_apic_instance, &table_header, &tbl_size);
	else
		acpi_get_table_with_size(id, 0, &table_header, &tbl_size);

	if (!table_header) {
		printk(KERN_WARNING PREFIX "%4.4s not present\n", id);
		return -ENODEV;
	}

	table_end = (unsigned long)table_header + table_header->length;

	/* Parse all entries looking for a match. */

	entry = (struct acpi_subtable_header *)
	    ((unsigned long)table_header + table_size);

	while (((unsigned long)entry) + sizeof(struct acpi_subtable_header) <
	       table_end) {
		if (entry->type == entry_id
		    && (!max_entries || count++ < max_entries))
			if (handler(entry, table_end)) {
				early_acpi_os_unmap_memory((char *)table_header, tbl_size);
				return -EINVAL;
			}

		entry = (struct acpi_subtable_header *)
		    ((unsigned long)entry + entry->length);
	}
	if (max_entries && count > max_entries) {
		printk(KERN_WARNING PREFIX "[%4.4s:0x%02x] ignored %i entries of "
		       "%i found\n", id, entry_id, count - max_entries, count);
	}

	early_acpi_os_unmap_memory((char *)table_header, tbl_size);
	return count;
}
示例#2
0
int __init
acpi_table_parse_entries(char *id,
			 unsigned long table_size,
			 int entry_id,
			 acpi_tbl_entry_handler handler,
			 unsigned int max_entries)
{
	struct acpi_table_header *table_header = NULL;
	acpi_size tbl_size;
	int count;
	u32 instance = 0;

	if (acpi_disabled)
		return -ENODEV;

	if (!id || !handler)
		return -EINVAL;

	if (!strncmp(id, ACPI_SIG_MADT, 4))
		instance = acpi_apic_instance;

	acpi_get_table_with_size(id, instance, &table_header, &tbl_size);
	if (!table_header) {
		pr_warn("%4.4s not present\n", id);
		return -ENODEV;
	}

	count = acpi_parse_entries(id, table_size, handler, table_header,
			entry_id, max_entries);

	early_acpi_os_unmap_memory((char *)table_header, tbl_size);
	return count;
}
示例#3
0
/**
 * acpi_table_parse - find table with @id, run @handler on it
 *
 * @id: table id to find
 * @handler: handler to run
 *
 * Scan the ACPI System Descriptor Table (STD) for a table matching @id,
 * run @handler on it.  Return 0 if table found, return on if not.
 */
int 
acpi_table_parse (char *id, acpi_table_handler handler, void * arg)
{
	struct acpi_table_header *table = NULL;
	acpi_size tbl_size;

	if (acpi_disabled) {
        //printk("[ACPI DISABLED]\n");
		return -ENODEV;
    }

	if (!handler) {
		return -EINVAL;
    }

	acpi_get_table_with_size(id, 0, &table, &tbl_size);

	if (table) {
		handler(table, arg);
		//early_acpi_os_unmap_memory(table, tbl_size);
		return 0;
	} else {
		return 1;
    }
}
static int __init find_unisys_acpi_oem_table(unsigned long *oem_addr)
{
    struct acpi_table_header *header = NULL;
    struct es7000_oem_table *table;
    acpi_size tbl_size;
    acpi_status ret;
    int i = 0;

    for (;;) {
        ret = acpi_get_table_with_size("OEM1", i++, &header, &tbl_size);
        if (!ACPI_SUCCESS(ret))
            return -1;

        if (!memcmp((char *) &header->oem_id, "UNISYS", 6))
            break;

        early_acpi_os_unmap_memory(header, tbl_size);
    }

    table = (void *)header;

    oem_addrX	= table->OEMTableAddr;
    oem_size	= table->OEMTableSize;

    early_acpi_os_unmap_memory(header, tbl_size);

    *oem_addr	= (unsigned long)__acpi_map_table(oem_addrX, oem_size);

    return 0;
}
示例#5
0
static bool radeon_acpi_vfct_bios(struct radeon_device *rdev)
{
	bool ret = false;
	struct acpi_table_header *hdr;
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
	acpi_size tbl_size;
#else
	/* acpi_get_table_with_size() not exported on kernels < 3.6 */
	acpi_size tbl_size = 0x7fffffff;
#endif
	UEFI_ACPI_VFCT *vfct;
	GOP_VBIOS_CONTENT *vbios;
	VFCT_IMAGE_HEADER *vhdr;

#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
	if (!ACPI_SUCCESS(acpi_get_table_with_size("VFCT", 1, &hdr, &tbl_size)))
#else
	if (!ACPI_SUCCESS(acpi_get_table("VFCT", 1, &hdr)))
#endif
		return false;
	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->pdev->bus->number ||
	    vhdr->PCIDevice != PCI_SLOT(rdev->pdev->devfn) ||
	    vhdr->PCIFunction != PCI_FUNC(rdev->pdev->devfn) ||
	    vhdr->VendorID != rdev->pdev->vendor ||
	    vhdr->DeviceID != rdev->pdev->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 = kmemdup(&vbios->VbiosContent, vhdr->ImageLength, GFP_KERNEL);
	ret = !!rdev->bios;

out_unmap:
	return ret;
}
示例#6
0
文件: tbxface.c 项目: 7799/linux
acpi_status
acpi_get_table(char *signature,
	       u32 instance, struct acpi_table_header **out_table)
{
	acpi_size tbl_size;

	return acpi_get_table_with_size(signature,
		       instance, out_table, &tbl_size);
}
示例#7
0
/**
 * acpi_table_parse - find table with @id, run @handler on it
 *
 * @id: table id to find
 * @handler: handler to run
 *
 * Scan the ACPI System Descriptor Table (STD) for a table matching @id,
 * run @handler on it.  Return 0 if table found, return on if not.
 */
int __init acpi_table_parse(char *id, acpi_table_handler handler)
{
	struct acpi_table_header *table = NULL;
	acpi_size tbl_size;

	if (!handler)
		return -EINVAL;

	if (strncmp(id, ACPI_SIG_MADT, 4) == 0)
		acpi_get_table_with_size(id, acpi_apic_instance, &table, &tbl_size);
	else
		acpi_get_table_with_size(id, 0, &table, &tbl_size);

	if (table) {
		handler(table);
		early_acpi_os_unmap_memory(table, tbl_size);
		return 0;
	} else
		return 1;
}
示例#8
0
文件: pcc.c 项目: Krostazino/linux
/**
 * acpi_pcc_probe - Parse the ACPI tree for the PCCT.
 *
 * Return: 0 for Success, else errno.
 */
static int __init acpi_pcc_probe(void)
{
	acpi_size pcct_tbl_header_size;
	struct acpi_table_header *pcct_tbl;
	struct acpi_subtable_header *pcct_entry;
	int count, i;
	acpi_status status = AE_OK;

	/* Search for PCCT */
	status = acpi_get_table_with_size(ACPI_SIG_PCCT, 0,
			&pcct_tbl,
			&pcct_tbl_header_size);

	if (ACPI_FAILURE(status) || !pcct_tbl) {
		pr_warn("PCCT header not found.\n");
		return -ENODEV;
	}

	count = acpi_table_parse_entries(ACPI_SIG_PCCT,
			sizeof(struct acpi_table_pcct),
			ACPI_PCCT_TYPE_HW_REDUCED_SUBSPACE,
			parse_pcc_subspace, MAX_PCC_SUBSPACES);

	if (count <= 0) {
		pr_err("Error parsing PCC subspaces from PCCT\n");
		return -EINVAL;
	}

	pcc_mbox_channels = kzalloc(sizeof(struct mbox_chan) *
			count, GFP_KERNEL);

	if (!pcc_mbox_channels) {
		pr_err("Could not allocate space for PCC mbox channels\n");
		return -ENOMEM;
	}

	/* Point to the first PCC subspace entry */
	pcct_entry = (struct acpi_subtable_header *) (
		(unsigned long) pcct_tbl + sizeof(struct acpi_table_pcct));

	for (i = 0; i < count; i++) {
		pcc_mbox_channels[i].con_priv = pcct_entry;
		pcct_entry = (struct acpi_subtable_header *)
			((unsigned long) pcct_entry + pcct_entry->length);
	}

	pcc_mbox_ctrl.num_chans = count;

	pr_info("Detected %d PCC Subspaces\n", pcc_mbox_ctrl.num_chans);

	return 0;
}
示例#9
0
phys_cpuid_t __init acpi_map_madt_entry(u32 acpi_id)
{
	struct acpi_table_madt *madt = NULL;
	acpi_size tbl_size;
	phys_cpuid_t rv;

	acpi_get_table_with_size(ACPI_SIG_MADT, 0,
				 (struct acpi_table_header **)&madt,
				 &tbl_size);
	if (!madt)
		return PHYS_CPUID_INVALID;

	rv = map_madt_
示例#10
0
文件: acpi.c 项目: Artox/linux
/*
 * acpi_fadt_sanity_check() - Check FADT presence and carry out sanity
 *			      checks on it
 *
 * Return 0 on success,  <0 on failure
 */
static int __init acpi_fadt_sanity_check(void)
{
	struct acpi_table_header *table;
	struct acpi_table_fadt *fadt;
	acpi_status status;
	acpi_size tbl_size;
	int ret = 0;

	/*
	 * FADT is required on arm64; retrieve it to check its presence
	 * and carry out revision and ACPI HW reduced compliancy tests
	 */
	status = acpi_get_table_with_size(ACPI_SIG_FADT, 0, &table, &tbl_size);
	if (ACPI_FAILURE(status)) {
		const char *msg = acpi_format_exception(status);

		pr_err("Failed to get FADT table, %s\n", msg);
		return -ENODEV;
	}

	fadt = (struct acpi_table_fadt *)table;

	/*
	 * Revision in table header is the FADT Major revision, and there
	 * is a minor revision of FADT which was introduced by ACPI 5.1,
	 * we only deal with ACPI 5.1 or newer revision to get GIC and SMP
	 * boot protocol configuration data.
	 */
	if (table->revision < 5 ||
	   (table->revision == 5 && fadt->minor_revision < 1)) {
		pr_err("Unsupported FADT revision %d.%d, should be 5.1+\n",
		       table->revision, fadt->minor_revision);
		ret = -EINVAL;
		goto out;
	}

	if (!(fadt->flags & ACPI_FADT_HW_REDUCED)) {
		pr_err("FADT not ACPI hardware reduced compliant\n");
		ret = -EINVAL;
	}

out:
	/*
	 * acpi_get_table_with_size() creates FADT table mapping that
	 * should be released after parsing and before resuming boot
	 */
	early_acpi_os_unmap_memory(table, tbl_size);
	return ret;
}
示例#11
0
static bool amdgpu_acpi_vfct_bios(struct amdgpu_device *adev)
{
	bool ret = false;
	struct acpi_table_header *hdr;
	acpi_size tbl_size;
	UEFI_ACPI_VFCT *vfct;
	GOP_VBIOS_CONTENT *vbios;
	VFCT_IMAGE_HEADER *vhdr;

	if (!ACPI_SUCCESS(acpi_get_table_with_size("VFCT", 1, &hdr, &tbl_size)))
		return false;
	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 != adev->pdev->bus->number ||
	    vhdr->PCIDevice != PCI_SLOT(adev->pdev->devfn) ||
	    vhdr->PCIFunction != PCI_FUNC(adev->pdev->devfn) ||
	    vhdr->VendorID != adev->pdev->vendor ||
	    vhdr->DeviceID != adev->pdev->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;
	}

	adev->bios = kmemdup(&vbios->VbiosContent, vhdr->ImageLength, GFP_KERNEL);
	adev->bios_size = vhdr->ImageLength;
	ret = !!adev->bios;

out_unmap:
	return ret;
}
示例#12
0
void* KCL_ACPI_GetVfctBios(unsigned long *size)
{
    struct acpi_table_header *hdr;
    acpi_size tbl_size ;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,3)    
    if (!ACPI_SUCCESS(acpi_get_table_with_size("VFCT", 1, &hdr, &tbl_size)))
#else
    tbl_size = 0x7fffffff;
    if (!ACPI_SUCCESS(acpi_get_table("VFCT", 1, &hdr)))
#endif
    {
        return NULL;
    }
    *size = tbl_size;
    return hdr;
}
示例#13
0
/* 
 * The BIOS is supposed to supply a single APIC/MADT,
 * but some report two.  Provide a knob to use either.
 * (don't you wish instance 0 and 1 were not the same?)
 */
static void __init check_multiple_madt(void)
{
	struct acpi_table_header *table = NULL;
	acpi_size tbl_size;

	acpi_get_table_with_size(ACPI_SIG_MADT, 2, &table, &tbl_size);
	if (table) {
		pr_warn("BIOS bug: multiple APIC/MADT found, using %d\n",
			acpi_apic_instance);
		pr_warn("If \"acpi_apic_instance=%d\" works better, "
			"notify [email protected]\n",
			acpi_apic_instance ? 0 : 2);
		early_acpi_os_unmap_memory(table, tbl_size);

	} else
		acpi_apic_instance = 0;

	return;
}
示例#14
0
文件: acpi.c 项目: 01org/prd
void __init acpi_gic_init(void)
{
	struct acpi_table_header *table;
	acpi_status status;
	acpi_size tbl_size;
	int err;

	if (acpi_disabled)
		return;

	status = acpi_get_table_with_size(ACPI_SIG_MADT, 0, &table, &tbl_size);
	if (ACPI_FAILURE(status)) {
		const char *msg = acpi_format_exception(status);

		pr_err("Failed to get MADT table, %s\n", msg);
		return;
	}

	err = gic_v2_acpi_init(table);
	if (err)
		pr_err("Failed to initialize GIC IRQ controller");

	early_acpi_os_unmap_memory((char *)table, tbl_size);
}
示例#15
0
文件: pcc.c 项目: guanhe0/kernel
/**
 * acpi_pcc_probe - Parse the ACPI tree for the PCCT.
 *
 * Return: 0 for Success, else errno.
 */
static int __init acpi_pcc_probe(void)
{
	acpi_size pcct_tbl_header_size;
	struct acpi_table_header *pcct_tbl;
	struct acpi_subtable_header *pcct_entry;
	int count, i;
	acpi_status status = AE_OK;

	/* Search for PCCT */
	status = acpi_get_table_with_size(ACPI_SIG_PCCT, 0,
			&pcct_tbl,
			&pcct_tbl_header_size);

	if (ACPI_FAILURE(status) || !pcct_tbl) {
		pr_warn("PCCT header not found.\n");
		return -ENODEV;
	}

	count = acpi_table_parse_entries(ACPI_SIG_PCCT,
			sizeof(struct acpi_table_pcct),
			ACPI_PCCT_TYPE_HW_REDUCED_SUBSPACE,
			parse_pcc_subspace, MAX_PCC_SUBSPACES);

	if (count <= 0) {
		pr_err("Error parsing PCC subspaces from PCCT\n");
		return -EINVAL;
	}

	pcc_mbox_channels = kzalloc(sizeof(struct mbox_chan) *
			count, GFP_KERNEL);

	if (!pcc_mbox_channels) {
		pr_err("Could not allocate space for PCC mbox channels\n");
		return -ENOMEM;
	}

	pcc_doorbell_vaddr = kcalloc(count, sizeof(void *), GFP_KERNEL);
	if (!pcc_doorbell_vaddr) {
		kfree(pcc_mbox_channels);
		return -ENOMEM;
	}

	/* Point to the first PCC subspace entry */
	pcct_entry = (struct acpi_subtable_header *) (
		(unsigned long) pcct_tbl + sizeof(struct acpi_table_pcct));

	for (i = 0; i < count; i++) {
		struct acpi_generic_address *db_reg;
		struct acpi_pcct_hw_reduced *pcct_ss;
		pcc_mbox_channels[i].con_priv = pcct_entry;
		pcct_entry = (struct acpi_subtable_header *)
			((unsigned long) pcct_entry + pcct_entry->length);

		/* If doorbell is in system memory cache the virt address */
		pcct_ss = (struct acpi_pcct_hw_reduced *)pcct_entry;
		db_reg = &pcct_ss->doorbell_register;
		if (db_reg->space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY)
			pcc_doorbell_vaddr[i] = acpi_os_ioremap(db_reg->address,
							db_reg->bit_width/8);
	}

	pcc_mbox_ctrl.num_chans = count;

	pr_info("Detected %d PCC Subspaces\n", pcc_mbox_ctrl.num_chans);

	return 0;
}
示例#16
0
文件: spcr.c 项目: guanhe0/kernel
/**
 * parse_spcr() - parse ACPI SPCR table and add preferred console
 *
 * @earlycon: set up earlycon for the console specified by the table
 *
 * For the architectures with support for ACPI, CONFIG_ACPI_SPCR_TABLE may be
 * defined to parse ACPI SPCR table.  As a result of the parsing preferred
 * console is registered and if @earlycon is true, earlycon is set up.
 *
 * When CONFIG_ACPI_SPCR_TABLE is defined, this function should should be called
 * from arch inintialization code as soon as the DT/ACPI decision is made.
 *
 */
int __init parse_spcr(bool earlycon)
{
	static char opts[64];
	struct acpi_table_spcr *table;
	acpi_size table_size;
	acpi_status status;
	char *uart;
	char *iotype;
	int baud_rate;
	int err;

	if (acpi_disabled)
		return -ENODEV;

	status = acpi_get_table_with_size(ACPI_SIG_SPCR, 0,
					  (struct acpi_table_header **)&table,
					  &table_size);

	if (ACPI_FAILURE(status))
		return -ENOENT;

	if (table->header.revision < 2) {
		err = -ENOENT;
		pr_err("wrong table version\n");
		goto done;
	}

	iotype = table->serial_port.space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY ?
			"mmio" : "io";

	switch (table->interface_type) {
	case ACPI_DBG2_ARM_SBSA_32BIT:
		iotype = "mmio32";
		/* fall through */
	case ACPI_DBG2_ARM_PL011:
	case ACPI_DBG2_ARM_SBSA_GENERIC:
	case ACPI_DBG2_BCM2835:
		uart = "pl011";
		break;
	case ACPI_DBG2_16550_COMPATIBLE:
	case ACPI_DBG2_16550_SUBSET:
		if (table->serial_port.space_id ==
			ACPI_ADR_SPACE_SYSTEM_MEMORY &&
		    table->serial_port.bit_width == 32)
			iotype = "mmio32";
		uart = "uart";
		break;
	default:
		err = -ENOENT;
		goto done;
	}

	switch (table->baud_rate) {
	case 3:
		baud_rate = 9600;
		break;
	case 4:
		baud_rate = 19200;
		break;
	case 6:
		baud_rate = 57600;
		break;
	case 7:
		baud_rate = 115200;
		break;
	default:
		err = -ENOENT;
		goto done;
	}

	snprintf(opts, sizeof(opts), "%s,%s,0x%llx", uart, iotype,
		 table->serial_port.address);

	pr_info("console: %s", opts);

	if (earlycon)
		setup_earlycon(opts);

	err = add_preferred_console(uart, 0, opts + strlen(uart) + 1);

done:
	early_acpi_os_unmap_memory((void __iomem *)table, table_size);
	return err;
}