Esempio n. 1
0
/*******************************************************************************
 *
 * FUNCTION:    acpi_load_tables
 *
 * PARAMETERS:  None
 *
 * RETURN:      Status
 *
 * DESCRIPTION: This function is called to load the ACPI tables from the
 *              provided RSDT
 *
 ******************************************************************************/
acpi_status acpi_load_tables(void)
{
	struct acpi_pointer rsdp_address;
	acpi_status status;

	ACPI_FUNCTION_TRACE(acpi_load_tables);

	/* Get the RSDP */

	status = acpi_os_get_root_pointer(ACPI_LOGICAL_ADDRESSING,
					  &rsdp_address);
	if (ACPI_FAILURE(status)) {
		ACPI_EXCEPTION((AE_INFO, status, "Could not get the RSDP"));
		goto error_exit;
	}

	/* Map and validate the RSDP */

	acpi_gbl_table_flags = rsdp_address.pointer_type;

	status = acpi_tb_verify_rsdp(&rsdp_address);
	if (ACPI_FAILURE(status)) {
		ACPI_EXCEPTION((AE_INFO, status, "During RSDP validation"));
		goto error_exit;
	}

	/* Get the RSDT via the RSDP */

	status = acpi_tb_get_table_rsdt();
	if (ACPI_FAILURE(status)) {
		ACPI_EXCEPTION((AE_INFO, status, "Could not load RSDT"));
		goto error_exit;
	}

	/* Now get the tables needed by this subsystem (FADT, DSDT, etc.) */

	status = acpi_tb_get_required_tables();
	if (ACPI_FAILURE(status)) {
		ACPI_EXCEPTION((AE_INFO, status,
				"Could not get all required tables (DSDT/FADT/FACS)"));
		goto error_exit;
	}

	ACPI_DEBUG_PRINT((ACPI_DB_INIT, "ACPI Tables successfully acquired\n"));

	/* Load the namespace from the tables */

	status = acpi_ns_load_namespace();
	if (ACPI_FAILURE(status)) {
		ACPI_EXCEPTION((AE_INFO, status, "Could not load namespace"));
		goto error_exit;
	}

	return_ACPI_STATUS(AE_OK);

      error_exit:
	ACPI_EXCEPTION((AE_INFO, status, "Could not load tables"));
	return_ACPI_STATUS(status);
}
Esempio n. 2
0
acpi_status __init
acpi_initialize_tables(struct acpi_table_desc * initial_table_array,
		       u32 initial_table_count, u8 allow_resize)
{
	acpi_physical_address rsdp_address;
	acpi_status status;

	ACPI_FUNCTION_TRACE(acpi_initialize_tables);

	/*
	 * Set up the Root Table Array
	 * Allocate the table array if requested
	 */
	if (!initial_table_array) {
		/* 
		 * ACPI code allows for much flexibility. Kitten doesn't need it
		 * that desperately.
		 */
		ACPI_ERROR((AE_INFO,
			"Don't give me a NULL table for storing headers.\n"));
		return_ACPI_STATUS(AE_BAD_PARAMETER);
	} else {
		/* Root Table Array has been statically allocated by the host */

		ACPI_MEMSET(initial_table_array, 0,
			    (acpi_size) initial_table_count *
			    sizeof(struct acpi_table_desc));

		acpi_gbl_root_table_list.tables = initial_table_array;
		acpi_gbl_root_table_list.max_table_count = initial_table_count;
		acpi_gbl_root_table_list.flags = ACPI_ROOT_ORIGIN_UNKNOWN;
		if (allow_resize) {
			acpi_gbl_root_table_list.flags |=
			    ACPI_ROOT_ALLOW_RESIZE;
		}
	}

	/* Get the address of the RSDP */

	rsdp_address = acpi_os_get_root_pointer();
	if (!rsdp_address) {
		ACPI_ERROR((AE_INFO, "Could not find RSDP\n"));
		return_ACPI_STATUS(AE_NOT_FOUND);
	}

	/*
	 * Get the root table (RSDT or XSDT) and extract all entries to the local
	 * Root Table Array. This array contains the information of the RSDT/XSDT
	 * in a common, more useable format.
	 */
	status = acpi_tb_parse_root_table(rsdp_address);
	return_ACPI_STATUS(status);
}
Esempio n. 3
0
acpi_status __init
acpi_initialize_tables(struct acpi_table_desc * initial_table_array,
		       u32 initial_table_count, u8 allow_resize)
{
	acpi_physical_address rsdp_address;
	acpi_status status;

	ACPI_FUNCTION_TRACE(acpi_initialize_tables);

	/*
	 * Set up the Root Table Array
	 * Allocate the table array if requested
	 */
	if (!initial_table_array) {
		status = acpi_allocate_root_table(initial_table_count);
		if (ACPI_FAILURE(status)) {
			return_ACPI_STATUS(status);
		}
	} else {
		/* Root Table Array has been statically allocated by the host */

		ACPI_MEMSET(initial_table_array, 0,
			    (acpi_size) initial_table_count *
			    sizeof(struct acpi_table_desc));

		acpi_gbl_root_table_list.tables = initial_table_array;
		acpi_gbl_root_table_list.size = initial_table_count;
		acpi_gbl_root_table_list.flags = ACPI_ROOT_ORIGIN_UNKNOWN;
		if (allow_resize) {
			acpi_gbl_root_table_list.flags |=
			    ACPI_ROOT_ALLOW_RESIZE;
		}
	}

	/* Get the address of the RSDP */

	rsdp_address = acpi_os_get_root_pointer();
	if (!rsdp_address) {
		return_ACPI_STATUS(AE_NOT_FOUND);
	}

	/*
	 * Get the root table (RSDT or XSDT) and extract all entries to the local
	 * Root Table Array. This array contains the information of the RSDT/XSDT
	 * in a common, more useable format.
	 */
	status =
	    acpi_tb_parse_root_table(rsdp_address, ACPI_TABLE_ORIGIN_MAPPED);
	return_ACPI_STATUS(status);
}
Esempio n. 4
0
static int __init pvh_setup_acpi(struct domain *d, paddr_t start_info)
{
    unsigned long pfn, nr_pages;
    paddr_t madt_paddr, xsdt_paddr, rsdp_paddr;
    unsigned int i;
    int rc;
    struct acpi_table_rsdp *native_rsdp, rsdp = {
        .signature = ACPI_SIG_RSDP,
        .revision = 2,
        .length = sizeof(rsdp),
    };


    /* Scan top-level tables and add their regions to the guest memory map. */
    for( i = 0; i < acpi_gbl_root_table_list.count; i++ )
    {
        const char *sig = acpi_gbl_root_table_list.tables[i].signature.ascii;
        unsigned long addr = acpi_gbl_root_table_list.tables[i].address;
        unsigned long size = acpi_gbl_root_table_list.tables[i].length;

        /*
         * Make sure the original MADT is also mapped, so that Dom0 can
         * properly access the data returned by _MAT methods in case it's
         * re-using MADT memory.
         */
        if ( strncmp(sig, ACPI_SIG_MADT, ACPI_NAME_SIZE)
             ? pvh_acpi_table_allowed(sig)
             : !acpi_memory_banned(addr, size) )
             pvh_add_mem_range(d, addr, addr + size, E820_ACPI);
    }

    /* Identity map ACPI e820 regions. */
    for ( i = 0; i < d->arch.nr_e820; i++ )
    {
        if ( d->arch.e820[i].type != E820_ACPI &&
             d->arch.e820[i].type != E820_NVS )
            continue;

        pfn = PFN_DOWN(d->arch.e820[i].addr);
        nr_pages = PFN_UP((d->arch.e820[i].addr & ~PAGE_MASK) +
                          d->arch.e820[i].size);

        rc = modify_identity_mmio(d, pfn, nr_pages, true);
        if ( rc )
        {
            printk("Failed to map ACPI region [%#lx, %#lx) into Dom0 memory map\n",
                   pfn, pfn + nr_pages);
            return rc;
        }
    }

    rc = pvh_setup_acpi_madt(d, &madt_paddr);
    if ( rc )
        return rc;

    rc = pvh_setup_acpi_xsdt(d, madt_paddr, &xsdt_paddr);
    if ( rc )
        return rc;

    /* Craft a custom RSDP. */
    native_rsdp = acpi_os_map_memory(acpi_os_get_root_pointer(), sizeof(rsdp));
    if ( !native_rsdp )
    {
        printk("Failed to map native RSDP\n");
        return -ENOMEM;
    }
    memcpy(rsdp.oem_id, native_rsdp->oem_id, sizeof(rsdp.oem_id));
    acpi_os_unmap_memory(native_rsdp, sizeof(rsdp));
    rsdp.xsdt_physical_address = xsdt_paddr;
    /*
     * Calling acpi_tb_checksum here is a layering violation, but
     * introducing a wrapper for such simple usage seems overkill.
     */
    rsdp.checksum -= acpi_tb_checksum(ACPI_CAST_PTR(u8, &rsdp),
                                      ACPI_RSDP_REV0_SIZE);
    rsdp.extended_checksum -= acpi_tb_checksum(ACPI_CAST_PTR(u8, &rsdp),
                                               sizeof(rsdp));

    /*
     * Place the new RSDP in guest memory space.
     *
     * NB: this RSDP is not going to replace the original RSDP, which should
     * still be accessible to the guest. However that RSDP is going to point to
     * the native RSDT, and should not be used for the Dom0 kernel's boot
     * purposes (we keep it visible for post boot access).
     */
    if ( pvh_steal_ram(d, sizeof(rsdp), 0, GB(4), &rsdp_paddr) )
    {
        printk("Unable to allocate guest RAM for RSDP\n");
        return -ENOMEM;
    }

    /* Mark this region as E820_ACPI. */
    if ( pvh_add_mem_range(d, rsdp_paddr, rsdp_paddr + sizeof(rsdp),
                           E820_ACPI) )
        printk("Unable to add RSDP region to memory map\n");

    /* Copy RSDP into guest memory. */
    rc = hvm_copy_to_guest_phys(rsdp_paddr, &rsdp, sizeof(rsdp), d->vcpu[0]);
    if ( rc )
    {
        printk("Unable to copy RSDP into guest memory\n");
        return rc;
    }

    /* Copy RSDP address to start_info. */
    rc = hvm_copy_to_guest_phys(start_info +
                                offsetof(struct hvm_start_info, rsdp_paddr),
                                &rsdp_paddr,
                                sizeof(((struct hvm_start_info *)
                                        0)->rsdp_paddr),
                                d->vcpu[0]);
    if ( rc )
    {
        printk("Unable to copy RSDP into guest memory\n");
        return rc;
    }

    return 0;
}

int __init dom0_construct_pvh(struct domain *d, const module_t *image,
                              unsigned long image_headroom,
                              module_t *initrd,
                              void *(*bootstrap_map)(const module_t *),
                              char *cmdline)
{
    paddr_t entry, start_info;
    int rc;

    printk("** Building a PVH Dom0 **\n");

    iommu_hwdom_init(d);

    rc = pvh_setup_p2m(d);
    if ( rc )
    {
        printk("Failed to setup Dom0 physical memory map\n");
        return rc;
    }

    rc = pvh_load_kernel(d, image, image_headroom, initrd, bootstrap_map(image),
                         cmdline, &entry, &start_info);
    if ( rc )
    {
        printk("Failed to load Dom0 kernel\n");
        return rc;
    }

    rc = pvh_setup_cpus(d, entry, start_info);
    if ( rc )
    {
        printk("Failed to setup Dom0 CPUs: %d\n", rc);
        return rc;
    }

    rc = pvh_setup_acpi(d, start_info);
    if ( rc )
    {
        printk("Failed to setup Dom0 ACPI tables: %d\n", rc);
        return rc;
    }

    panic("Building a PVHv2 Dom0 is not yet supported.");
    return 0;
}
Esempio n. 5
0
static int __init pvh_setup_acpi_xsdt(struct domain *d, paddr_t madt_addr,
                                      paddr_t *addr)
{
    struct acpi_table_xsdt *xsdt;
    struct acpi_table_header *table;
    struct acpi_table_rsdp *rsdp;
    unsigned long size = sizeof(*xsdt);
    unsigned int i, j, num_tables = 0;
    paddr_t xsdt_paddr;
    int rc;

    /*
     * Restore original DMAR table signature, we are going to filter it from
     * the new XSDT that is presented to the guest, so it is no longer
     * necessary to have it's signature zapped.
     */
    acpi_dmar_reinstate();

    /* Count the number of tables that will be added to the XSDT. */
    for( i = 0; i < acpi_gbl_root_table_list.count; i++ )
    {
        const char *sig = acpi_gbl_root_table_list.tables[i].signature.ascii;

        if ( pvh_acpi_table_allowed(sig) )
            num_tables++;
    }

    /*
     * No need to add or subtract anything because struct acpi_table_xsdt
     * includes one array slot already, and we have filtered out the original
     * MADT and we are going to add a custom built MADT.
     */
    size += num_tables * sizeof(xsdt->table_offset_entry[0]);

    xsdt = xzalloc_bytes(size);
    if ( !xsdt )
    {
        printk("Unable to allocate memory for XSDT table\n");
        rc = -ENOMEM;
        goto out;
    }

    /* Copy the native XSDT table header. */
    rsdp = acpi_os_map_memory(acpi_os_get_root_pointer(), sizeof(*rsdp));
    if ( !rsdp )
    {
        printk("Unable to map RSDP\n");
        rc = -EINVAL;
        goto out;
    }
    xsdt_paddr = rsdp->xsdt_physical_address;
    acpi_os_unmap_memory(rsdp, sizeof(*rsdp));
    table = acpi_os_map_memory(xsdt_paddr, sizeof(*table));
    if ( !table )
    {
        printk("Unable to map XSDT\n");
        rc = -EINVAL;
        goto out;
    }
    xsdt->header = *table;
    acpi_os_unmap_memory(table, sizeof(*table));

    /* Add the custom MADT. */
    xsdt->table_offset_entry[0] = madt_addr;

    /* Copy the addresses of the rest of the allowed tables. */
    for( i = 0, j = 1; i < acpi_gbl_root_table_list.count; i++ )
    {
        const char *sig = acpi_gbl_root_table_list.tables[i].signature.ascii;

        if ( pvh_acpi_table_allowed(sig) )
            xsdt->table_offset_entry[j++] =
                acpi_gbl_root_table_list.tables[i].address;
    }

    xsdt->header.revision = 1;
    xsdt->header.length = size;
    /*
     * Calling acpi_tb_checksum here is a layering violation, but
     * introducing a wrapper for such simple usage seems overkill.
     */
    xsdt->header.checksum -= acpi_tb_checksum(ACPI_CAST_PTR(u8, xsdt), size);

    /* Place the new XSDT in guest memory space. */
    if ( pvh_steal_ram(d, size, 0, GB(4), addr) )
    {
        printk("Unable to find guest RAM for XSDT\n");
        rc = -ENOMEM;
        goto out;
    }

    /* Mark this region as E820_ACPI. */
    if ( pvh_add_mem_range(d, *addr, *addr + size, E820_ACPI) )
        printk("Unable to add XSDT region to memory map\n");

    rc = hvm_copy_to_guest_phys(*addr, xsdt, size, d->vcpu[0]);
    if ( rc )
    {
        printk("Unable to copy XSDT into guest memory\n");
        goto out;
    }

    rc = 0;

 out:
    xfree(xsdt);

    return rc;
}
acpi_status
acpi_load_tables (void)
{
    struct acpi_pointer             rsdp_address;
    acpi_status                     status;


    ACPI_FUNCTION_TRACE ("acpi_load_tables");


    /* Get the RSDP */

    status = acpi_os_get_root_pointer (ACPI_LOGICAL_ADDRESSING,
                                       &rsdp_address);
    if (ACPI_FAILURE (status)) {
        ACPI_REPORT_ERROR (("acpi_load_tables: Could not get RSDP, %s\n",
                            acpi_format_exception (status)));
        goto error_exit;
    }

    /* Map and validate the RSDP */

    acpi_gbl_table_flags = rsdp_address.pointer_type;

    status = acpi_tb_verify_rsdp (&rsdp_address);
    if (ACPI_FAILURE (status)) {
        ACPI_REPORT_ERROR (("acpi_load_tables: RSDP Failed validation: %s\n",
                            acpi_format_exception (status)));
        goto error_exit;
    }

    /* Get the RSDT via the RSDP */

    status = acpi_tb_get_table_rsdt ();
    if (ACPI_FAILURE (status)) {
        ACPI_REPORT_ERROR (("acpi_load_tables: Could not load RSDT: %s\n",
                            acpi_format_exception (status)));
        goto error_exit;
    }

    /* Now get the tables needed by this subsystem (FADT, DSDT, etc.) */

    status = acpi_tb_get_required_tables ();
    if (ACPI_FAILURE (status)) {
        ACPI_REPORT_ERROR (("acpi_load_tables: Error getting required tables (DSDT/FADT/FACS): %s\n",
                            acpi_format_exception (status)));
        goto error_exit;
    }

    ACPI_DEBUG_PRINT ((ACPI_DB_INIT, "ACPI Tables successfully acquired\n"));


    /* Load the namespace from the tables */

    status = acpi_ns_load_namespace ();
    if (ACPI_FAILURE (status)) {
        ACPI_REPORT_ERROR (("acpi_load_tables: Could not load namespace: %s\n",
                            acpi_format_exception (status)));
        goto error_exit;
    }

    return_ACPI_STATUS (AE_OK);


error_exit:
    ACPI_REPORT_ERROR (("acpi_load_tables: Could not load tables: %s\n",
                        acpi_format_exception (status)));

    return_ACPI_STATUS (status);
}
Esempio n. 7
0
acpi_status
acpi_get_firmware_table (
	acpi_string                     signature,
	u32                             instance,
	u32                             flags,
	struct acpi_table_header        **table_pointer)
{
	struct acpi_pointer             rsdp_address;
	struct acpi_pointer             address;
	acpi_status                     status;
	struct acpi_table_header        header;
	struct acpi_table_desc          table_info;
	struct acpi_table_desc          rsdt_info;
	u32                             table_count;
	u32                             i;
	u32                             j;


	ACPI_FUNCTION_TRACE ("acpi_get_firmware_table");


	/*
	 * Ensure that at least the table manager is initialized.  We don't
	 * require that the entire ACPI subsystem is up for this interface
	 */

	/*
	 *  If we have a buffer, we must have a length too
	 */
	if ((instance == 0)                 ||
		(!signature)                    ||
		(!table_pointer)) {
		return_ACPI_STATUS (AE_BAD_PARAMETER);
	}

	rsdt_info.pointer = NULL;

	if (!acpi_gbl_RSDP) {
		/* Get the RSDP */

		status = acpi_os_get_root_pointer (flags, &rsdp_address);
		if (ACPI_FAILURE (status)) {
			ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "RSDP  not found\n"));
			return_ACPI_STATUS (AE_NO_ACPI_TABLES);
		}

		/* Map and validate the RSDP */

		if ((flags & ACPI_MEMORY_MODE) == ACPI_LOGICAL_ADDRESSING) {
			status = acpi_os_map_memory (rsdp_address.pointer.physical, sizeof (struct rsdp_descriptor),
					  (void *) &acpi_gbl_RSDP);
			if (ACPI_FAILURE (status)) {
				return_ACPI_STATUS (status);
			}
		}
		else {
			acpi_gbl_RSDP = rsdp_address.pointer.logical;
		}

		/*
		 *  The signature and checksum must both be correct
		 */
		if (ACPI_STRNCMP ((char *) acpi_gbl_RSDP, RSDP_SIG, sizeof (RSDP_SIG)-1) != 0) {
			/* Nope, BAD Signature */

			return_ACPI_STATUS (AE_BAD_SIGNATURE);
		}

		if (acpi_tb_checksum (acpi_gbl_RSDP, ACPI_RSDP_CHECKSUM_LENGTH) != 0) {
			/* Nope, BAD Checksum */

			return_ACPI_STATUS (AE_BAD_CHECKSUM);
		}
	}

	/* Get the RSDT and validate it */

	acpi_tb_get_rsdt_address (&address);

	ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
		"RSDP located at %p, RSDT physical=%8.8X%8.8X \n",
		acpi_gbl_RSDP,
		ACPI_HIDWORD (address.pointer.value),
		ACPI_LODWORD (address.pointer.value)));

	/* Insert processor_mode flags */

	address.pointer_type |= flags;

	status = acpi_tb_get_table (&address, &rsdt_info);
	if (ACPI_FAILURE (status)) {
		return_ACPI_STATUS (status);
	}

	status = acpi_tb_validate_rsdt (rsdt_info.pointer);
	if (ACPI_FAILURE (status)) {
		goto cleanup;
	}

	/* Get the number of table pointers within the RSDT */

	table_count = acpi_tb_get_table_count (acpi_gbl_RSDP, rsdt_info.pointer);

	address.pointer_type = acpi_gbl_table_flags | flags;

	/*
	 * Search the RSDT/XSDT for the correct instance of the
	 * requested table
	 */
	for (i = 0, j = 0; i < table_count; i++) {
		/* Get the next table pointer, handle RSDT vs. XSDT */

		if (acpi_gbl_RSDP->revision < 2) {
			address.pointer.value = ((RSDT_DESCRIPTOR *) rsdt_info.pointer)->table_offset_entry[i];
		}
		else {
			address.pointer.value =
				((XSDT_DESCRIPTOR *) rsdt_info.pointer)->table_offset_entry[i];
		}

		/* Get the table header */

		status = acpi_tb_get_table_header (&address, &header);
		if (ACPI_FAILURE (status)) {
			goto cleanup;
		}

		/* Compare table signatures and table instance */

		if (!ACPI_STRNCMP (header.signature, signature, ACPI_NAME_SIZE)) {
			/* An instance of the table was found */

			j++;
			if (j >= instance) {
				/* Found the correct instance, get the entire table */

				status = acpi_tb_get_table_body (&address, &header, &table_info);
				if (ACPI_FAILURE (status)) {
					goto cleanup;
				}

				*table_pointer = table_info.pointer;
				goto cleanup;
			}
		}
	}

	/* Did not find the table */

	status = AE_NOT_EXIST;


cleanup:
	acpi_os_unmap_memory (rsdt_info.pointer, (acpi_size) rsdt_info.pointer->length);
	return_ACPI_STATUS (status);
}
Esempio n. 8
0
int __init get_memcfg_from_srat(void)
{
    struct acpi_table_header *header = NULL;
    struct acpi_table_rsdp *rsdp = NULL;
    struct acpi_table_rsdt *rsdt = NULL;
    acpi_native_uint rsdp_address = 0;
    struct acpi_static_rsdt saved_rsdt;
    int tables = 0;
    int i = 0;

    rsdp_address = acpi_os_get_root_pointer();
    if (!rsdp_address) {
        printk("%s: System description tables not found\n",
               __func__);
        goto out_err;
    }

    printk("%s: assigning address to rsdp\n", __func__);
    rsdp = (struct acpi_table_rsdp *)(u32)rsdp_address;
    if (!rsdp) {
        printk("%s: Didn't find ACPI root!\n", __func__);
        goto out_err;
    }

    printk(KERN_INFO "%.8s v%d [%.6s]\n", rsdp->signature, rsdp->revision,
        rsdp->oem_id);

    if (strncmp(rsdp->signature, ACPI_SIG_RSDP,strlen(ACPI_SIG_RSDP))) {
        printk(KERN_WARNING "%s: RSDP table signature incorrect\n", __func__);
        goto out_err;
    }

    rsdt = (struct acpi_table_rsdt *)
        early_ioremap(rsdp->rsdt_physical_address, sizeof(struct acpi_table_rsdt));

    if (!rsdt) {
        printk(KERN_WARNING
               "%s: ACPI: Invalid root system description tables (RSDT)\n",
               __func__);
        goto out_err;
    }

    header = &rsdt->header;

    if (strncmp(header->signature, ACPI_SIG_RSDT, strlen(ACPI_SIG_RSDT))) {
        printk(KERN_WARNING "ACPI: RSDT signature incorrect\n");
        goto out_err;
    }

    /* 
     * The number of tables is computed by taking the 
     * size of all entries (header size minus total 
     * size of RSDT) divided by the size of each entry
     * (4-byte table pointers).
     */
    tables = (header->length - sizeof(struct acpi_table_header)) / 4;

    if (!tables)
        goto out_err;

    memcpy(&saved_rsdt, rsdt, sizeof(saved_rsdt));

    if (saved_rsdt.table.header.length > sizeof(saved_rsdt)) {
        printk(KERN_WARNING "ACPI: Too big length in RSDT: %d\n",
               saved_rsdt.table.header.length);
        goto out_err;
    }

    printk("Begin SRAT table scan....\n");

    for (i = 0; i < tables; i++) {
        /* Map in header, then map in full table length. */
        header = (struct acpi_table_header *)
            early_ioremap(saved_rsdt.table.table_offset_entry[i], sizeof(struct acpi_table_header));
        if (!header)
            break;
        header = (struct acpi_table_header *)
            early_ioremap(saved_rsdt.table.table_offset_entry[i], header->length);
        if (!header)
            break;

        if (strncmp((char *) &header->signature, ACPI_SIG_SRAT, 4))
            continue;

        /* we've found the srat table. don't need to look at any more tables */
        return acpi20_parse_srat((struct acpi_table_srat *)header);
    }
out_err:
    remove_all_active_ranges();
    printk("failed to get NUMA memory information from SRAT table\n");
    return 0;
}
Esempio n. 9
0
acpi_status
acpi_get_firmware_table(acpi_string signature,
			u32 instance,
			u32 flags, struct acpi_table_header **table_pointer)
{
	acpi_status status;
	struct acpi_pointer address;
	struct acpi_table_header *header = NULL;
	struct acpi_table_desc *table_info = NULL;
	struct acpi_table_desc *rsdt_info;
	u32 table_count;
	u32 i;
	u32 j;

	ACPI_FUNCTION_TRACE("acpi_get_firmware_table");

	/*
	 * Ensure that at least the table manager is initialized.  We don't
	 * require that the entire ACPI subsystem is up for this interface.
	 * If we have a buffer, we must have a length too
	 */
	if ((instance == 0) || (!signature) || (!table_pointer)) {
		return_ACPI_STATUS(AE_BAD_PARAMETER);
	}

	/* Ensure that we have a RSDP */

	if (!acpi_gbl_RSDP) {
		/* Get the RSDP */

		status = acpi_os_get_root_pointer(flags, &address);
		if (ACPI_FAILURE(status)) {
			ACPI_DEBUG_PRINT((ACPI_DB_INFO, "RSDP not found\n"));
			return_ACPI_STATUS(AE_NO_ACPI_TABLES);
		}

		/* Map and validate the RSDP */

		if ((flags & ACPI_MEMORY_MODE) == ACPI_LOGICAL_ADDRESSING) {
			status = acpi_os_map_memory(address.pointer.physical,
						    sizeof(struct
							   rsdp_descriptor),
						    (void *)&acpi_gbl_RSDP);
			if (ACPI_FAILURE(status)) {
				return_ACPI_STATUS(status);
			}
		} else {
			acpi_gbl_RSDP = address.pointer.logical;
		}

		/* The RDSP signature and checksum must both be correct */

		status = acpi_tb_validate_rsdp(acpi_gbl_RSDP);
		if (ACPI_FAILURE(status)) {
			return_ACPI_STATUS(status);
		}
	}

	/* Get the RSDT address via the RSDP */

	acpi_tb_get_rsdt_address(&address);
	ACPI_DEBUG_PRINT((ACPI_DB_INFO,
			  "RSDP located at %p, RSDT physical=%8.8X%8.8X \n",
			  acpi_gbl_RSDP,
			  ACPI_FORMAT_UINT64(address.pointer.value)));

	/* Insert processor_mode flags */

	address.pointer_type |= flags;

	/* Get and validate the RSDT */

	rsdt_info = ACPI_MEM_CALLOCATE(sizeof(struct acpi_table_desc));
	if (!rsdt_info) {
		return_ACPI_STATUS(AE_NO_MEMORY);
	}

	status = acpi_tb_get_table(&address, rsdt_info);
	if (ACPI_FAILURE(status)) {
		goto cleanup;
	}

	status = acpi_tb_validate_rsdt(rsdt_info->pointer);
	if (ACPI_FAILURE(status)) {
		goto cleanup;
	}

	/* Allocate a scratch table header and table descriptor */

	header = ACPI_MEM_ALLOCATE(sizeof(struct acpi_table_header));
	if (!header) {
		status = AE_NO_MEMORY;
		goto cleanup;
	}

	table_info = ACPI_MEM_ALLOCATE(sizeof(struct acpi_table_desc));
	if (!table_info) {
		status = AE_NO_MEMORY;
		goto cleanup;
	}

	/* Get the number of table pointers within the RSDT */

	table_count =
	    acpi_tb_get_table_count(acpi_gbl_RSDP, rsdt_info->pointer);
	address.pointer_type = acpi_gbl_table_flags | flags;

	/*
	 * Search the RSDT/XSDT for the correct instance of the
	 * requested table
	 */
	for (i = 0, j = 0; i < table_count; i++) {
		/*
		 * Get the next table pointer, handle RSDT vs. XSDT
		 * RSDT pointers are 32 bits, XSDT pointers are 64 bits
		 */
		if (acpi_gbl_root_table_type == ACPI_TABLE_TYPE_RSDT) {
			address.pointer.value =
			    (ACPI_CAST_PTR
			     (RSDT_DESCRIPTOR,
			      rsdt_info->pointer))->table_offset_entry[i];
		} else {
			address.pointer.value =
			    (ACPI_CAST_PTR
			     (XSDT_DESCRIPTOR,
			      rsdt_info->pointer))->table_offset_entry[i];
		}

		/* Get the table header */

		status = acpi_tb_get_table_header(&address, header);
		if (ACPI_FAILURE(status)) {
			goto cleanup;
		}

		/* Compare table signatures and table instance */

		if (!ACPI_STRNCMP(header->signature, signature, ACPI_NAME_SIZE)) {
			/* An instance of the table was found */

			j++;
			if (j >= instance) {
				/* Found the correct instance, get the entire table */

				status =
				    acpi_tb_get_table_body(&address, header,
							   table_info);
				if (ACPI_FAILURE(status)) {
					goto cleanup;
				}

				*table_pointer = table_info->pointer;
				goto cleanup;
			}
		}
	}

	/* Did not find the table */

	status = AE_NOT_EXIST;

      cleanup:
	if (rsdt_info->pointer) {
		acpi_os_unmap_memory(rsdt_info->pointer,
				     (acpi_size) rsdt_info->pointer->length);
	}
	ACPI_MEM_FREE(rsdt_info);

	if (header) {
		ACPI_MEM_FREE(header);
	}
	if (table_info) {
		ACPI_MEM_FREE(table_info);
	}
	return_ACPI_STATUS(status);
}
Esempio n. 10
0
acpi_status
acpi_load_tables (void)
{
	ACPI_PHYSICAL_ADDRESS   rsdp_physical_address;
	acpi_status             status;
	u32                     number_of_tables = 0;


	FUNCTION_TRACE ("Acpi_load_tables");


	/* Get the RSDP */

	status = acpi_os_get_root_pointer (ACPI_LOGICAL_ADDRESSING,
			  &rsdp_physical_address);
	if (ACPI_FAILURE (status)) {
		REPORT_ERROR (("Acpi_load_tables: Could not get RSDP, %s\n",
				  acpi_format_exception (status)));
		goto error_exit;
	}

	/* Map and validate the RSDP */

	status = acpi_tb_verify_rsdp (rsdp_physical_address);
	if (ACPI_FAILURE (status)) {
		REPORT_ERROR (("Acpi_load_tables: RSDP Failed validation: %s\n",
				  acpi_format_exception (status)));
		goto error_exit;
	}

	/* Get the RSDT via the RSDP */

	status = acpi_tb_get_table_rsdt (&number_of_tables);
	if (ACPI_FAILURE (status)) {
		REPORT_ERROR (("Acpi_load_tables: Could not load RSDT: %s\n",
				  acpi_format_exception (status)));
		goto error_exit;
	}

	/* Now get the rest of the tables */

	status = acpi_tb_get_all_tables (number_of_tables, NULL);
	if (ACPI_FAILURE (status)) {
		REPORT_ERROR (("Acpi_load_tables: Error getting required tables (DSDT/FADT/FACS): %s\n",
				  acpi_format_exception (status)));
		goto error_exit;
	}

	ACPI_DEBUG_PRINT ((ACPI_DB_OK, "ACPI Tables successfully loaded\n"));


	/* Load the namespace from the tables */

	status = acpi_ns_load_namespace ();
	if (ACPI_FAILURE (status)) {
		REPORT_ERROR (("Acpi_load_tables: Could not load namespace: %s\n",
				  acpi_format_exception (status)));
		goto error_exit;
	}

	return_ACPI_STATUS (AE_OK);


error_exit:
	REPORT_ERROR (("Acpi_load_tables: Could not load tables: %s\n",
			  acpi_format_exception (status)));

	return_ACPI_STATUS (status);
}