Ejemplo n.º 1
0
u8 ap_is_valid_checksum(struct acpi_table_header *table)
{
	acpi_status status;
	struct acpi_table_rsdp *rsdp;

	if (ACPI_VALIDATE_RSDP_SIG(table->signature)) {
		/*
		 * Checksum for RSDP.
		 * Note: Other checksums are computed during the table dump.
		 */
		rsdp = ACPI_CAST_PTR(struct acpi_table_rsdp, table);
		status = acpi_tb_validate_rsdp(rsdp);
	} else {
Ejemplo n.º 2
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);
}
Ejemplo n.º 3
0
/*******************************************************************************
 *
 * FUNCTION:    acpi_tb_verify_rsdp
 *
 * PARAMETERS:  Address         - RSDP (Pointer to RSDT)
 *
 * RETURN:      Status
 *
 * DESCRIPTION: Load and validate the RSDP (ptr) and RSDT (table)
 *
 ******************************************************************************/
acpi_status acpi_tb_verify_rsdp(struct acpi_pointer *address)
{
	struct acpi_table_desc table_info;
	acpi_status status;
	struct rsdp_descriptor *rsdp;

	ACPI_FUNCTION_TRACE(tb_verify_rsdp);

	switch (address->pointer_type) {
	case ACPI_LOGICAL_POINTER:

		rsdp = address->pointer.logical;
		break;

	case ACPI_PHYSICAL_POINTER:
		/*
		 * Obtain access to the RSDP structure
		 */
		status = acpi_os_map_memory(address->pointer.physical,
					    sizeof(struct rsdp_descriptor),
					    ACPI_CAST_PTR(void, &rsdp));
		if (ACPI_FAILURE(status)) {
			return_ACPI_STATUS(status);
		}
		break;

	default:
		return_ACPI_STATUS(AE_BAD_PARAMETER);
	}

	/* Verify RSDP signature and checksum */

	status = acpi_tb_validate_rsdp(rsdp);
	if (ACPI_FAILURE(status)) {
		goto cleanup;
	}

	/* RSDP is ok. Init the table info */

	table_info.pointer = ACPI_CAST_PTR(struct acpi_table_header, rsdp);
	table_info.length = sizeof(struct rsdp_descriptor);

	if (address->pointer_type == ACPI_PHYSICAL_POINTER) {
		table_info.allocation = ACPI_MEM_MAPPED;
	} else {
		table_info.allocation = ACPI_MEM_NOT_ALLOCATED;
	}

	/* Save the table pointers and allocation info */

	status = acpi_tb_init_table_descriptor(ACPI_TABLE_ID_RSDP, &table_info);
	if (ACPI_FAILURE(status)) {
		goto cleanup;
	}

	/* Save the RSDP in a global for easy access */

	acpi_gbl_RSDP =
	    ACPI_CAST_PTR(struct rsdp_descriptor, table_info.pointer);
	return_ACPI_STATUS(status);

	/* Error exit */
      cleanup:

	if (acpi_gbl_table_flags & ACPI_PHYSICAL_POINTER) {
		acpi_os_unmap_memory(rsdp, sizeof(struct rsdp_descriptor));
	}
	return_ACPI_STATUS(status);
}