Esempio n. 1
0
void acpi_tb_check_dsdt_header(void)
{

	/* Compare original length and checksum to current values */

	if (acpi_gbl_original_dsdt_header.length != acpi_gbl_DSDT->length ||
	    acpi_gbl_original_dsdt_header.checksum != acpi_gbl_DSDT->checksum) {
		ACPI_BIOS_ERROR((AE_INFO,
				 "The DSDT has been corrupted or replaced - "
				 "old, new headers below"));
		acpi_tb_print_table_header(0, &acpi_gbl_original_dsdt_header);
		acpi_tb_print_table_header(0, acpi_gbl_DSDT);

		ACPI_ERROR((AE_INFO,
			    "Please send DMI info to [email protected]\n"
			    "If system does not work as expected, please boot with acpi=copy_dsdt"));

		/* Disable further error messages */

		acpi_gbl_original_dsdt_header.length = acpi_gbl_DSDT->length;
		acpi_gbl_original_dsdt_header.checksum =
		    acpi_gbl_DSDT->checksum;
	}
}
Esempio n. 2
0
void acpi_db_display_table_info(char *table_arg)
{
	u32 i;
	struct acpi_table_desc *table_desc;
	acpi_status status;

	/* Header */

	acpi_os_printf("Idx ID  Status Type                    "
		       "TableHeader (Sig, Address, Length, Misc)\n");

	/* Walk the entire root table list */

	for (i = 0; i < acpi_gbl_root_table_list.current_table_count; i++) {
		table_desc = &acpi_gbl_root_table_list.tables[i];

		/* Index and Table ID */

		acpi_os_printf("%3u %.2u ", i, table_desc->owner_id);

		/* Decode the table flags */

		if (!(table_desc->flags & ACPI_TABLE_IS_LOADED)) {
			acpi_os_printf("NotLoaded ");
		} else {
			acpi_os_printf(" Loaded ");
		}

		switch (table_desc->flags & ACPI_TABLE_ORIGIN_MASK) {
		case ACPI_TABLE_ORIGIN_EXTERNAL_VIRTUAL:

			acpi_os_printf("External/virtual ");
			break;

		case ACPI_TABLE_ORIGIN_INTERNAL_PHYSICAL:

			acpi_os_printf("Internal/physical ");
			break;

		case ACPI_TABLE_ORIGIN_INTERNAL_VIRTUAL:

			acpi_os_printf("Internal/virtual ");
			break;

		default:

			acpi_os_printf("INVALID TYPE    ");
			break;
		}

		/* Make sure that the table is mapped */

		status = acpi_tb_validate_table(table_desc);
		if (ACPI_FAILURE(status)) {
			return;
		}

		/* Dump the table header */

		if (table_desc->pointer) {
			acpi_tb_print_table_header(table_desc->address,
						   table_desc->pointer);
		} else {
			/* If the pointer is null, the table has been unloaded */

			ACPI_INFO((AE_INFO, "%4.4s - Table has been unloaded",
				   table_desc->signature.ascii));
		}
	}
}
Esempio n. 3
0
acpi_status
acpi_tb_add_table(struct acpi_table_desc *table_desc, u32 *table_index)
{
	u32 i;
	acpi_status status = AE_OK;

	ACPI_FUNCTION_TRACE(tb_add_table);

	if (!table_desc->pointer) {
		status = acpi_tb_verify_table(table_desc);
		if (ACPI_FAILURE(status) || !table_desc->pointer) {
			return_ACPI_STATUS(status);
		}
	}

	/*
	 * Validate the incoming table signature.
	 *
	 * 1) Originally, we checked the table signature for "SSDT" or "PSDT".
	 * 2) We added support for OEMx tables, signature "OEM".
	 * 3) Valid tables were encountered with a null signature, so we just
	 *    gave up on validating the signature, (05/2008).
	 * 4) We encountered non-AML tables such as the MADT, which caused
	 *    interpreter errors and kernel faults. So now, we once again allow
	 *    only "SSDT", "OEMx", and now, also a null signature. (05/2011).
	 */
	if ((table_desc->pointer->signature[0] != 0x00) &&
	    (!ACPI_COMPARE_NAME(table_desc->pointer->signature, ACPI_SIG_SSDT))
	    && (ACPI_STRNCMP(table_desc->pointer->signature, "OEM", 3))) {
		ACPI_ERROR((AE_INFO,
			    "Table has invalid signature [%4.4s] (0x%8.8X), must be SSDT or OEMx",
			    acpi_ut_valid_acpi_name(*(u32 *)table_desc->
						    pointer->
						    signature) ? table_desc->
			    pointer->signature : "????",
			    *(u32 *)table_desc->pointer->signature));

		return_ACPI_STATUS(AE_BAD_SIGNATURE);
	}

	(void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);

	/* Check if table is already registered */

	for (i = 0; i < acpi_gbl_root_table_list.current_table_count; ++i) {
		if (!acpi_gbl_root_table_list.tables[i].pointer) {
			status =
			    acpi_tb_verify_table(&acpi_gbl_root_table_list.
						 tables[i]);
			if (ACPI_FAILURE(status)
			    || !acpi_gbl_root_table_list.tables[i].pointer) {
				continue;
			}
		}

		/*
		 * Check for a table match on the entire table length,
		 * not just the header.
		 */
		if (table_desc->length !=
		    acpi_gbl_root_table_list.tables[i].length) {
			continue;
		}

		if (ACPI_MEMCMP(table_desc->pointer,
				acpi_gbl_root_table_list.tables[i].pointer,
				acpi_gbl_root_table_list.tables[i].length)) {
			continue;
		}

		/*
		 * Note: the current mechanism does not unregister a table if it is
		 * dynamically unloaded. The related namespace entries are deleted,
		 * but the table remains in the root table list.
		 *
		 * The assumption here is that the number of different tables that
		 * will be loaded is actually small, and there is minimal overhead
		 * in just keeping the table in case it is needed again.
		 *
		 * If this assumption changes in the future (perhaps on large
		 * machines with many table load/unload operations), tables will
		 * need to be unregistered when they are unloaded, and slots in the
		 * root table list should be reused when empty.
		 */

		/*
		 * Table is already registered.
		 * We can delete the table that was passed as a parameter.
		 */
		acpi_tb_delete_table(table_desc);
		*table_index = i;

		if (acpi_gbl_root_table_list.tables[i].
		    flags & ACPI_TABLE_IS_LOADED) {

			/* Table is still loaded, this is an error */

			status = AE_ALREADY_EXISTS;
			goto release;
		} else {
			/* Table was unloaded, allow it to be reloaded */

			table_desc->pointer =
			    acpi_gbl_root_table_list.tables[i].pointer;
			table_desc->address =
			    acpi_gbl_root_table_list.tables[i].address;
			status = AE_OK;
			goto print_header;
		}
	}

	/*
	 * ACPI Table Override:
	 * Allow the host to override dynamically loaded tables.
	 * NOTE: the table is fully mapped at this point, and the mapping will
	 * be deleted by tb_table_override if the table is actually overridden.
	 */
	(void)acpi_tb_table_override(table_desc->pointer, table_desc);

	/* Add the table to the global root table list */

	status = acpi_tb_store_table(table_desc->address, table_desc->pointer,
				     table_desc->length, table_desc->flags,
				     table_index);
	if (ACPI_FAILURE(status)) {
		goto release;
	}

      print_header:
	acpi_tb_print_table_header(table_desc->address, table_desc->pointer);

      release:
	(void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
	return_ACPI_STATUS(status);
}
Esempio n. 4
0
/*******************************************************************************
 *
 * FUNCTION:    acpi_tb_load_namespace
 *
 * PARAMETERS:  None
 *
 * RETURN:      Status
 *
 * DESCRIPTION: Load the namespace from the DSDT and all SSDTs/PSDTs found in
 *              the RSDT/XSDT.
 *
 ******************************************************************************/
static acpi_status acpi_tb_load_namespace(void)
{
	acpi_status status;
	struct acpi_table_header *table;
	u32 i;

	ACPI_FUNCTION_TRACE(tb_load_namespace);

	(void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);

	/*
	 * Load the namespace. The DSDT is required, but any SSDT and PSDT tables
	 * are optional.
	 */
	if (!acpi_gbl_root_table_list.count ||
	    !ACPI_COMPARE_NAME(&
			       (acpi_gbl_root_table_list.
				tables[ACPI_TABLE_INDEX_DSDT].signature),
			       ACPI_SIG_DSDT)
	    ||
	    ACPI_FAILURE(acpi_tb_verify_table
			 (&acpi_gbl_root_table_list.
			  tables[ACPI_TABLE_INDEX_DSDT]))) {
		status = AE_NO_ACPI_TABLES;
		goto unlock_and_exit;
	}

	/*
	 * Find DSDT table
	 */
	status =
	    acpi_os_table_override(acpi_gbl_root_table_list.
				   tables[ACPI_TABLE_INDEX_DSDT].pointer,
				   &table);
	if (ACPI_SUCCESS(status) && table) {
		/*
		 * DSDT table has been found
		 */
		acpi_tb_delete_table(&acpi_gbl_root_table_list.
				     tables[ACPI_TABLE_INDEX_DSDT]);
		acpi_gbl_root_table_list.tables[ACPI_TABLE_INDEX_DSDT].pointer =
		    table;
		acpi_gbl_root_table_list.tables[ACPI_TABLE_INDEX_DSDT].length =
		    table->length;
		acpi_gbl_root_table_list.tables[ACPI_TABLE_INDEX_DSDT].flags =
		    ACPI_TABLE_ORIGIN_UNKNOWN;

		ACPI_INFO((AE_INFO, "Table DSDT replaced by host OS"));
		acpi_tb_print_table_header(0, table);

		if (no_auto_ssdt == 0) {
			printk(KERN_WARNING "ACPI: DSDT override uses original SSDTs unless \"acpi_no_auto_ssdt\"\n");
		}
	}

	status =
	    acpi_tb_verify_table(&acpi_gbl_root_table_list.
				 tables[ACPI_TABLE_INDEX_DSDT]);
	if (ACPI_FAILURE(status)) {

		/* A valid DSDT is required */

		status = AE_NO_ACPI_TABLES;
		goto unlock_and_exit;
	}

	(void)acpi_ut_release_mutex(ACPI_MTX_TABLES);

	/*
	 * Load and parse tables.
	 */
	status = acpi_ns_load_table(ACPI_TABLE_INDEX_DSDT, acpi_gbl_root_node);
	if (ACPI_FAILURE(status)) {
		return_ACPI_STATUS(status);
	}

	/*
	 * Load any SSDT or PSDT tables. Note: Loop leaves tables locked
	 */
	(void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
	for (i = 0; i < acpi_gbl_root_table_list.count; ++i) {
		if ((!ACPI_COMPARE_NAME
		     (&(acpi_gbl_root_table_list.tables[i].signature),
		      ACPI_SIG_SSDT)
		     &&
		     !ACPI_COMPARE_NAME(&
					(acpi_gbl_root_table_list.tables[i].
					 signature), ACPI_SIG_PSDT))
		    ||
		    ACPI_FAILURE(acpi_tb_verify_table
				 (&acpi_gbl_root_table_list.tables[i]))) {
			continue;
		}

		if (no_auto_ssdt) {
			printk(KERN_WARNING "ACPI: SSDT ignored due to \"acpi_no_auto_ssdt\"\n");
			continue;
		}

		/* Ignore errors while loading tables, get as many as possible */

		(void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
		(void)acpi_ns_load_table(i, acpi_gbl_root_node);
		(void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
	}

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

      unlock_and_exit:
	(void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
	return_ACPI_STATUS(status);
}
acpi_status
acpi_tb_add_table(struct acpi_table_desc *table_desc, u32 *table_index)
{
	u32 i;
	acpi_status status = AE_OK;

	ACPI_FUNCTION_TRACE(tb_add_table);

	if (!table_desc->pointer) {
		status = acpi_tb_verify_table(table_desc);
		if (ACPI_FAILURE(status) || !table_desc->pointer) {
			return_ACPI_STATUS(status);
		}
	}

	if ((table_desc->pointer->signature[0] != 0x00) &&
	    (!ACPI_COMPARE_NAME(table_desc->pointer->signature, ACPI_SIG_SSDT))
	    && (ACPI_STRNCMP(table_desc->pointer->signature, "OEM", 3))) {
		ACPI_ERROR((AE_INFO,
			    "Table has invalid signature [%4.4s] (0x%8.8X), must be SSDT or OEMx",
			    acpi_ut_valid_acpi_name(*(u32 *)table_desc->
						    pointer->
						    signature) ? table_desc->
			    pointer->signature : "????",
			    *(u32 *)table_desc->pointer->signature));

		return_ACPI_STATUS(AE_BAD_SIGNATURE);
	}

	(void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);

	

	for (i = 0; i < acpi_gbl_root_table_list.current_table_count; ++i) {
		if (!acpi_gbl_root_table_list.tables[i].pointer) {
			status =
			    acpi_tb_verify_table(&acpi_gbl_root_table_list.
						 tables[i]);
			if (ACPI_FAILURE(status)
			    || !acpi_gbl_root_table_list.tables[i].pointer) {
				continue;
			}
		}

		if (table_desc->length !=
		    acpi_gbl_root_table_list.tables[i].length) {
			continue;
		}

		if (ACPI_MEMCMP(table_desc->pointer,
				acpi_gbl_root_table_list.tables[i].pointer,
				acpi_gbl_root_table_list.tables[i].length)) {
			continue;
		}


		acpi_tb_delete_table(table_desc);
		*table_index = i;

		if (acpi_gbl_root_table_list.tables[i].
		    flags & ACPI_TABLE_IS_LOADED) {

			

			status = AE_ALREADY_EXISTS;
			goto release;
		} else {
			

			table_desc->pointer =
			    acpi_gbl_root_table_list.tables[i].pointer;
			table_desc->address =
			    acpi_gbl_root_table_list.tables[i].address;
			status = AE_OK;
			goto print_header;
		}
	}

	(void)acpi_tb_table_override(table_desc->pointer, table_desc);

	

	status = acpi_tb_store_table(table_desc->address, table_desc->pointer,
				     table_desc->length, table_desc->flags,
				     table_index);
	if (ACPI_FAILURE(status)) {
		goto release;
	}

      print_header:
	acpi_tb_print_table_header(table_desc->address, table_desc->pointer);

      release:
	(void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
	return_ACPI_STATUS(status);
}