Esempio n. 1
0
acpi_status
acpi_tb_find_table(char *signature,
		   char *oem_id,
		   char *oem_table_id, struct acpi_table_header ** table_ptr)
{
	acpi_status status;
	struct acpi_table_header *table;

	ACPI_FUNCTION_TRACE("tb_find_table");

	/* Validate string lengths */

	if ((ACPI_STRLEN(signature) > ACPI_NAME_SIZE) ||
	    (ACPI_STRLEN(oem_id) > sizeof(table->oem_id)) ||
	    (ACPI_STRLEN(oem_table_id) > sizeof(table->oem_table_id))) {
		return_ACPI_STATUS(AE_AML_STRING_LIMIT);
	}

	if (!ACPI_STRNCMP(signature, DSDT_SIG, ACPI_NAME_SIZE)) {
		/*
		 * The DSDT pointer is contained in the FADT, not the RSDT.
		 * This code should suffice, because the only code that would perform
		 * a "find" on the DSDT is the data_table_region() AML opcode -- in
		 * which case, the DSDT is guaranteed to be already loaded.
		 * If this becomes insufficient, the FADT will have to be found first.
		 */
		if (!acpi_gbl_DSDT) {
			return_ACPI_STATUS(AE_NO_ACPI_TABLES);
		}
		table = acpi_gbl_DSDT;
	} else {
		/* Find the table */

		status = acpi_get_firmware_table(signature, 1,
						 ACPI_LOGICAL_ADDRESSING,
						 &table);
		if (ACPI_FAILURE(status)) {
			return_ACPI_STATUS(status);
		}
	}

	/* Check oem_id and oem_table_id */

	if ((oem_id[0] && ACPI_STRNCMP(oem_id, table->oem_id,
				       sizeof(table->oem_id))) ||
	    (oem_table_id[0] && ACPI_STRNCMP(oem_table_id, table->oem_table_id,
					     sizeof(table->oem_table_id)))) {
		return_ACPI_STATUS(AE_AML_NAME_NOT_FOUND);
	}

	ACPI_DEBUG_PRINT((ACPI_DB_TABLES, "Found table [%4.4s]\n",
			  table->signature));

	*table_ptr = table;
	return_ACPI_STATUS(AE_OK);
}
Esempio n. 2
0
acpi_status
acpi_tb_validate_rsdt (
	struct acpi_table_header        *table_ptr)
{
	int                             no_match;


	ACPI_FUNCTION_NAME ("tb_validate_rsdt");


	/*
	 * For RSDP revision 0 or 1, we use the RSDT.
	 * For RSDP revision 2 and above, we use the XSDT
	 */
	if (acpi_gbl_RSDP->revision < 2) {
		no_match = ACPI_STRNCMP ((char *) table_ptr, RSDT_SIG,
				  sizeof (RSDT_SIG) -1);
	}
	else {
		no_match = ACPI_STRNCMP ((char *) table_ptr, XSDT_SIG,
				  sizeof (XSDT_SIG) -1);
	}

	if (no_match) {
		/* Invalid RSDT or XSDT signature */

		ACPI_REPORT_ERROR (("Invalid signature where RSDP indicates RSDT/XSDT should be located\n"));

		ACPI_DUMP_BUFFER (acpi_gbl_RSDP, 20);

		ACPI_DEBUG_PRINT_RAW ((ACPI_DB_ERROR,
			"RSDT/XSDT signature at %X (%p) is invalid\n",
			acpi_gbl_RSDP->rsdt_physical_address,
			(void *) (acpi_native_uint) acpi_gbl_RSDP->rsdt_physical_address));

		if (acpi_gbl_RSDP->revision < 2) {
			ACPI_REPORT_ERROR (("Looking for RSDT (RSDP->Rev < 2)\n"))
		}
		else {
			ACPI_REPORT_ERROR (("Looking for XSDT (RSDP->Rev >= 2)\n"))
		}

		ACPI_DUMP_BUFFER ((char *) table_ptr, 48);

		return (AE_BAD_SIGNATURE);
	}

	return (AE_OK);
}
Esempio n. 3
0
acpi_status acpi_tb_validate_rsdp(struct rsdp_descriptor *rsdp)
{
	ACPI_FUNCTION_ENTRY();

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

		return (AE_BAD_SIGNATURE);
	}

	/* Check the standard checksum */

	if (acpi_tb_generate_checksum(rsdp, ACPI_RSDP_CHECKSUM_LENGTH) != 0) {
		return (AE_BAD_CHECKSUM);
	}

	/* Check extended checksum if table version >= 2 */

	if ((rsdp->revision >= 2) &&
	    (acpi_tb_generate_checksum(rsdp, ACPI_RSDP_XCHECKSUM_LENGTH) !=
	     0)) {
		return (AE_BAD_CHECKSUM);
	}

	return (AE_OK);
}
Esempio n. 4
0
static acpi_status acpi_tb_validate_rsdp(struct acpi_table_rsdp *rsdp)
{
	ACPI_FUNCTION_ENTRY();

	/*
	 * The signature and checksum must both be correct
	 *
	 * Note: Sometimes there exists more than one RSDP in memory; the valid
	 * RSDP has a valid checksum, all others have an invalid checksum.
	 */
	if (ACPI_STRNCMP((char *)rsdp, ACPI_SIG_RSDP,
			 sizeof(ACPI_SIG_RSDP) - 1) != 0) {

		/* Nope, BAD Signature */

		return (AE_BAD_SIGNATURE);
	}

	/* Check the standard checksum */

	if (acpi_tb_checksum((u8 *) rsdp, ACPI_RSDP_CHECKSUM_LENGTH) != 0) {
		return (AE_BAD_CHECKSUM);
	}

	/* Check extended checksum if table version >= 2 */

	if ((rsdp->revision >= 2) &&
	    (acpi_tb_checksum((u8 *) rsdp, ACPI_RSDP_XCHECKSUM_LENGTH) != 0)) {
		return (AE_BAD_CHECKSUM);
	}

	return (AE_OK);
}
Esempio n. 5
0
static u8 acpi_ev_match_pci_root_bridge(char *id)
{

    /*
     * Check if this is a PCI root.
     * ACPI 3.0+: check for a PCI Express root also.
     */
    if (!(ACPI_STRNCMP(id,
               PCI_ROOT_HID_STRING,
               sizeof(PCI_ROOT_HID_STRING))) ||
        !(ACPI_STRNCMP(id,
               PCI_EXPRESS_ROOT_HID_STRING,
               sizeof(PCI_EXPRESS_ROOT_HID_STRING)))) {
        return (TRUE);
    }

    return (FALSE);
}
Esempio n. 6
0
ACPI_STATUS
AcpiTbGetSecondaryTable (
    ACPI_POINTER            *Address,
    ACPI_STRING             Signature,
    ACPI_TABLE_DESC         *TableInfo)
{
    ACPI_STATUS             Status;
    ACPI_TABLE_HEADER       Header;


    ACPI_FUNCTION_TRACE_STR ("TbGetSecondaryTable", Signature);


    /* Get the header in order to match the signature */

    Status = AcpiTbGetTableHeader (Address, &Header);
    if (ACPI_FAILURE (Status))
    {
        return_ACPI_STATUS (Status);
    }

    /* Signature must match request */

    if (ACPI_STRNCMP (Header.Signature, Signature, ACPI_NAME_SIZE))
    {
        ACPI_REPORT_ERROR (("Incorrect table signature - wanted [%s] found [%4.4s]\n",
            Signature, Header.Signature));
        return_ACPI_STATUS (AE_BAD_SIGNATURE);
    }

    /*
     * Check the table signature and make sure it is recognized.
     * Also checks the header checksum
     */
    TableInfo->Pointer = &Header;
    Status = AcpiTbRecognizeTable (TableInfo, ACPI_TABLE_SECONDARY);
    if (ACPI_FAILURE (Status))
    {
        return_ACPI_STATUS (Status);
    }

    /* Get the entire table */

    Status = AcpiTbGetTableBody (Address, &Header, TableInfo);
    if (ACPI_FAILURE (Status))
    {
        return_ACPI_STATUS (Status);
    }

    /* Install the table */

    Status = AcpiTbInstallTable (TableInfo);
    return_ACPI_STATUS (Status);
}
static BOOLEAN
AcpiEvMatchPciRootBridge (
    char                    *Id)
{

    /*
     * Check if this is a PCI root.
     * ACPI 3.0+: check for a PCI Express root also.
     */
    if (!(ACPI_STRNCMP (Id,
            PCI_ROOT_HID_STRING,
            sizeof (PCI_ROOT_HID_STRING)))      ||

        !(ACPI_STRNCMP (Id,
            PCI_EXPRESS_ROOT_HID_STRING,
            sizeof (PCI_EXPRESS_ROOT_HID_STRING))))
    {
        return (TRUE);
    }

    return (FALSE);
}
Esempio n. 8
0
static acpi_status
acpi_tb_get_secondary_table (
	struct acpi_pointer             *address,
	acpi_string                     signature,
	struct acpi_table_desc          *table_info)
{
	acpi_status                     status;
	struct acpi_table_header        header;


	ACPI_FUNCTION_TRACE_STR ("tb_get_secondary_table", signature);


	/* Get the header in order to match the signature */

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

	/* Signature must match request */

	if (ACPI_STRNCMP (header.signature, signature, ACPI_NAME_SIZE)) {
		ACPI_REPORT_ERROR ((
			"Incorrect table signature - wanted [%s] found [%4.4s]\n",
			signature, header.signature));
		return_ACPI_STATUS (AE_BAD_SIGNATURE);
	}

	/*
	 * Check the table signature and make sure it is recognized.
	 * Also checks the header checksum
	 */
	table_info->pointer = &header;
	status = acpi_tb_recognize_table (table_info, ACPI_TABLE_SECONDARY);
	if (ACPI_FAILURE (status)) {
		return_ACPI_STATUS (status);
	}

	/* Get the entire table */

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

	/* Install the table */

	status = acpi_tb_install_table (table_info);
	return_ACPI_STATUS (status);
}
Esempio n. 9
0
static ACPI_STATUS
AcpiTbMatchSignature (
    char                    *Signature,
    ACPI_TABLE_DESC         *TableInfo,
    UINT8                   SearchType)
{
    ACPI_NATIVE_UINT        i;


    ACPI_FUNCTION_TRACE (TbMatchSignature);


    /* Search for a signature match among the known table types */

    for (i = 0; i < (ACPI_TABLE_ID_MAX+1); i++)
    {
        if (!(AcpiGbl_TableData[i].Flags & SearchType))
        {
            continue;
        }

        if (!ACPI_STRNCMP (Signature, AcpiGbl_TableData[i].Signature,
                AcpiGbl_TableData[i].SigLength))
        {
            /* Found a signature match, return index if requested */

            if (TableInfo)
            {
                TableInfo->Type = (UINT8) i;
            }

            ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
                "Table [%4.4s] is an ACPI table consumed by the core subsystem\n",
                (char *) AcpiGbl_TableData[i].Signature));

            return_ACPI_STATUS (AE_OK);
        }
    }

    ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
        "Table [%4.4s] is not an ACPI table consumed by the core subsystem - ignored\n",
        (char *) Signature));

    return_ACPI_STATUS (AE_TABLE_NOT_SUPPORTED);
}
Esempio n. 10
0
acpi_status
acpi_tb_match_signature (
    char                            *signature,
    struct acpi_table_desc          *table_info,
    u8                              search_type)
{
    acpi_native_uint                i;


    ACPI_FUNCTION_TRACE ("tb_match_signature");


    /*
     * Search for a signature match among the known table types
     */
    for (i = 0; i < NUM_ACPI_TABLE_TYPES; i++) {
        if (!(acpi_gbl_table_data[i].flags & search_type)) {
            continue;
        }

        if (!ACPI_STRNCMP (signature, acpi_gbl_table_data[i].signature,
                           acpi_gbl_table_data[i].sig_length)) {
            /* Found a signature match, return index if requested */

            if (table_info) {
                table_info->type = (u8) i;
            }

            ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
                               "Table [%4.4s] is an ACPI table consumed by the core subsystem\n",
                               (char *) acpi_gbl_table_data[i].signature));

            return_ACPI_STATUS (AE_OK);
        }
    }

    ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
                       "Table [%4.4s] is not an ACPI table consumed by the core subsystem - ignored\n",
                       (char *) signature));

    return_ACPI_STATUS (AE_TABLE_NOT_SUPPORTED);
}
Esempio n. 11
0
void
AcpiDbUnloadAcpiTable (
    char                    *TableArg,
    char                    *InstanceArg)
{
/* TBD: Need to reimplement for new data structures */

#if 0
    UINT32                  i;
    ACPI_STATUS             Status;


    /* Search all tables for the target type */

    for (i = 0; i < (ACPI_TABLE_ID_MAX+1); i++)
    {
        if (!ACPI_STRNCMP (TableArg, AcpiGbl_TableData[i].Signature,
                AcpiGbl_TableData[i].SigLength))
        {
            /* Found the table, unload it */

            Status = AcpiUnloadTable (i);
            if (ACPI_SUCCESS (Status))
            {
                AcpiOsPrintf ("[%s] unloaded and uninstalled\n", TableArg);
            }
            else
            {
                AcpiOsPrintf ("%s, while unloading [%s]\n",
                    AcpiFormatException (Status), TableArg);
            }

            return;
        }
    }

    AcpiOsPrintf ("Unknown table type [%s]\n", TableArg);
#endif
}
Esempio n. 12
0
static ACPI_STATUS
AcpiTbValidateRsdp (
    ACPI_TABLE_RSDP         *Rsdp)
{
    ACPI_FUNCTION_ENTRY ();


    /*
     * The signature and checksum must both be correct
     *
     * Note: Sometimes there exists more than one RSDP in memory; the valid
     * RSDP has a valid checksum, all others have an invalid checksum.
     */
    if (ACPI_STRNCMP ((char *) Rsdp, ACPI_SIG_RSDP,
            sizeof (ACPI_SIG_RSDP)-1) != 0)
    {
        /* Nope, BAD Signature */

        return (AE_BAD_SIGNATURE);
    }

    /* Check the standard checksum */

    if (AcpiTbChecksum ((UINT8 *) Rsdp, ACPI_RSDP_CHECKSUM_LENGTH) != 0)
    {
        return (AE_BAD_CHECKSUM);
    }

    /* Check extended checksum if table version >= 2 */

    if ((Rsdp->Revision >= 2) &&
        (AcpiTbChecksum ((UINT8 *) Rsdp, ACPI_RSDP_XCHECKSUM_LENGTH) != 0))
    {
        return (AE_BAD_CHECKSUM);
    }

    return (AE_OK);
}
Esempio n. 13
0
UINT8 *
AcpiTbScanMemoryForRsdp (
    UINT8                   *StartAddress,
    UINT32                  Length)
{
    UINT32                  Offset;
    UINT8                   *MemRover;


    ACPI_FUNCTION_TRACE ("TbScanMemoryForRsdp");


    /* Search from given start addr for the requested length  */

    for (Offset = 0, MemRover = StartAddress;
         Offset < Length;
         Offset += ACPI_RSDP_SCAN_STEP, MemRover += ACPI_RSDP_SCAN_STEP)
    {

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

        if (ACPI_STRNCMP ((char *) MemRover,
                RSDP_SIG, sizeof (RSDP_SIG)-1) == 0 &&
            AcpiTbChecksum (MemRover, ACPI_RSDP_CHECKSUM_LENGTH) == 0)
        {
            /* If so, we have found the RSDP */

            ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
                "RSDP located at physical address %p\n",MemRover));
            return_PTR (MemRover);
        }
    }

    /* Searched entire block, no RSDP was found */

    ACPI_DEBUG_PRINT ((ACPI_DB_INFO,"Searched entire block, no RSDP was found.\n"));
    return_PTR (NULL);
}
Esempio n. 14
0
static BOOLEAN
OpcFindName (
    char                    **List,
    char                    *Name,
    UINT64                  *Index)
{
    char                     *Str;
    UINT32                   i;


    OpcStrupr (Name);

    for (i = 0, Str = List[0]; Str; i++, Str = List[i])
    {
        if (!(ACPI_STRNCMP (Str, Name, ACPI_STRLEN (Name))))
        {
            *Index = i;
            return (TRUE);
        }
    }

    return (FALSE);
}
Esempio n. 15
0
u8 *
acpi_tb_scan_memory_for_rsdp (
	u8                              *start_address,
	u32                             length)
{
	u32                             offset;
	u8                              *mem_rover;


	ACPI_FUNCTION_TRACE ("tb_scan_memory_for_rsdp");


	/* Search from given start addr for the requested length  */

	for (offset = 0, mem_rover = start_address;
		 offset < length;
		 offset += ACPI_RSDP_SCAN_STEP, mem_rover += ACPI_RSDP_SCAN_STEP) {

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

		if (ACPI_STRNCMP ((char *) mem_rover,
				RSDP_SIG, sizeof (RSDP_SIG)-1) == 0 &&
			acpi_tb_checksum (mem_rover, ACPI_RSDP_CHECKSUM_LENGTH) == 0) {
			/* If so, we have found the RSDP */

			ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
				"RSDP located at physical address %p\n",mem_rover));
			return_PTR (mem_rover);
		}
	}

	/* Searched entire block, no RSDP was found */

	ACPI_DEBUG_PRINT ((ACPI_DB_INFO,"Searched entire block, no RSDP was found.\n"));
	return_PTR (NULL);
}
Esempio n. 16
0
acpi_status
acpi_walk_resources (
	acpi_handle                             device_handle,
	char                                    *path,
	ACPI_WALK_RESOURCE_CALLBACK     user_function,
	void                                    *context)
{
	acpi_status                         status;
	struct acpi_buffer                  buffer = {ACPI_ALLOCATE_BUFFER, NULL};
	struct acpi_resource                *resource;
	struct acpi_resource                *buffer_end;


	ACPI_FUNCTION_TRACE ("acpi_walk_resources");


	if (!device_handle ||
		(ACPI_STRNCMP (path, METHOD_NAME__CRS, sizeof (METHOD_NAME__CRS)) &&
		 ACPI_STRNCMP (path, METHOD_NAME__PRS, sizeof (METHOD_NAME__PRS)))) {
		return_ACPI_STATUS (AE_BAD_PARAMETER);
	}

	status = acpi_rs_get_method_data (device_handle, path, &buffer);
	if (ACPI_FAILURE (status)) {
		return_ACPI_STATUS (status);
	}

	/* Setup pointers */

	resource  = (struct acpi_resource *) buffer.pointer;
	buffer_end = ACPI_CAST_PTR (struct acpi_resource,
			  ((u8 *) buffer.pointer + buffer.length));

	/* Walk the resource list */

	for (;;) {
		if (!resource || resource->id == ACPI_RSTYPE_END_TAG) {
			break;
		}

		status = user_function (resource, context);

		switch (status) {
		case AE_OK:
		case AE_CTRL_DEPTH:

			/* Just keep going */

			status = AE_OK;
			break;

		case AE_CTRL_TERMINATE:

			/* Exit now, with OK stats */

			status = AE_OK;
			goto cleanup;

		default:

			/* All others are valid exceptions */

			goto cleanup;
		}

		/* Get the next resource descriptor */

		resource = ACPI_NEXT_RESOURCE (resource);

		/* Check for end-of-buffer */

		if (resource >= buffer_end) {
			goto cleanup;
		}
	}

cleanup:

	acpi_os_free (buffer.pointer);
	return_ACPI_STATUS (status);
}
acpi_status
acpi_ex_load_op(union acpi_operand_object *obj_desc,
		union acpi_operand_object *target,
		struct acpi_walk_state *walk_state)
{
	acpi_status status;
	union acpi_operand_object *ddb_handle;
	union acpi_operand_object *buffer_desc = NULL;
	struct acpi_table_header *table_ptr = NULL;
	acpi_physical_address address;
	struct acpi_table_header table_header;
	u32 i;

	ACPI_FUNCTION_TRACE("ex_load_op");

	/* Object can be either an op_region or a Field */

	switch (ACPI_GET_OBJECT_TYPE(obj_desc)) {
	case ACPI_TYPE_REGION:

		ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Load from Region %p %s\n",
				  obj_desc,
				  acpi_ut_get_object_type_name(obj_desc)));

		/*
		 * If the Region Address and Length have not been previously evaluated,
		 * evaluate them now and save the results.
		 */
		if (!(obj_desc->common.flags & AOPOBJ_DATA_VALID)) {
			status = acpi_ds_get_region_arguments(obj_desc);
			if (ACPI_FAILURE(status)) {
				return_ACPI_STATUS(status);
			}
		}

		/* Get the base physical address of the region */

		address = obj_desc->region.address;

		/* Get the table length from the table header */

		table_header.length = 0;
		for (i = 0; i < 8; i++) {
			status =
			    acpi_ev_address_space_dispatch(obj_desc, ACPI_READ,
							   (acpi_physical_address)
							   (i + address), 8,
							   ((u8 *) &
							    table_header) + i);
			if (ACPI_FAILURE(status)) {
				return_ACPI_STATUS(status);
			}
		}

		/* Sanity check the table length */

		if (table_header.length < sizeof(struct acpi_table_header)) {
			return_ACPI_STATUS(AE_BAD_HEADER);
		}

		/* Allocate a buffer for the entire table */

		table_ptr = ACPI_MEM_ALLOCATE(table_header.length);
		if (!table_ptr) {
			return_ACPI_STATUS(AE_NO_MEMORY);
		}

		/* Get the entire table from the op region */

		for (i = 0; i < table_header.length; i++) {
			status =
			    acpi_ev_address_space_dispatch(obj_desc, ACPI_READ,
							   (acpi_physical_address)
							   (i + address), 8,
							   ((u8 *) table_ptr +
							    i));
			if (ACPI_FAILURE(status)) {
				goto cleanup;
			}
		}
		break;

	case ACPI_TYPE_LOCAL_REGION_FIELD:
	case ACPI_TYPE_LOCAL_BANK_FIELD:
	case ACPI_TYPE_LOCAL_INDEX_FIELD:

		ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Load from Field %p %s\n",
				  obj_desc,
				  acpi_ut_get_object_type_name(obj_desc)));

		/*
		 * The length of the field must be at least as large as the table.
		 * Read the entire field and thus the entire table.  Buffer is
		 * allocated during the read.
		 */
		status =
		    acpi_ex_read_data_from_field(walk_state, obj_desc,
						 &buffer_desc);
		if (ACPI_FAILURE(status)) {
			return_ACPI_STATUS(status);
		}

		table_ptr = ACPI_CAST_PTR(struct acpi_table_header,
					  buffer_desc->buffer.pointer);

		/* All done with the buffer_desc, delete it */

		buffer_desc->buffer.pointer = NULL;
		acpi_ut_remove_reference(buffer_desc);

		/* Sanity check the table length */

		if (table_ptr->length < sizeof(struct acpi_table_header)) {
			status = AE_BAD_HEADER;
			goto cleanup;
		}
		break;

	default:
		return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
	}

	/* The table must be either an SSDT or a PSDT */

	if ((!ACPI_STRNCMP(table_ptr->signature,
			   acpi_gbl_table_data[ACPI_TABLE_PSDT].signature,
			   acpi_gbl_table_data[ACPI_TABLE_PSDT].sig_length)) &&
	    (!ACPI_STRNCMP(table_ptr->signature,
			   acpi_gbl_table_data[ACPI_TABLE_SSDT].signature,
			   acpi_gbl_table_data[ACPI_TABLE_SSDT].sig_length))) {
		ACPI_ERROR((AE_INFO,
			    "Table has invalid signature [%4.4s], must be SSDT or PSDT",
			    table_ptr->signature));
		status = AE_BAD_SIGNATURE;
		goto cleanup;
	}

	/* Install the new table into the local data structures */

	status = acpi_ex_add_table(table_ptr, acpi_gbl_root_node, &ddb_handle);
	if (ACPI_FAILURE(status)) {
		/* On error, table_ptr was deallocated above */

		return_ACPI_STATUS(status);
	}

	/* Store the ddb_handle into the Target operand */

	status = acpi_ex_store(ddb_handle, target, walk_state);
	if (ACPI_FAILURE(status)) {
		(void)acpi_ex_unload_table(ddb_handle);

		/* table_ptr was deallocated above */

		return_ACPI_STATUS(status);
	}

      cleanup:
	if (ACPI_FAILURE(status)) {
		ACPI_MEM_FREE(table_ptr);
	}
	return_ACPI_STATUS(status);
}
Esempio n. 18
0
/*******************************************************************************
 *
 * FUNCTION:    acpi_ns_get_device_callback
 *
 * PARAMETERS:  Callback from acpi_get_device
 *
 * RETURN:      Status
 *
 * DESCRIPTION: Takes callbacks from walk_namespace and filters out all non-
 *              present devices, or if they specified a HID, it filters based
 *              on that.
 *
 ******************************************************************************/
static acpi_status
acpi_ns_get_device_callback(acpi_handle obj_handle,
			    u32 nesting_level,
			    void *context, void **return_value)
{
	struct acpi_get_devices_info *info = context;
	acpi_status status;
	struct acpi_namespace_node *node;
	u32 flags;
	struct acpica_device_id hid;
	struct acpi_compatible_id_list *cid;
	acpi_native_uint i;

	status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
	if (ACPI_FAILURE(status)) {
		return (status);
	}

	node = acpi_ns_map_handle_to_node(obj_handle);
	status = acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
	if (ACPI_FAILURE(status)) {
		return (status);
	}

	if (!node) {
		return (AE_BAD_PARAMETER);
	}

	/* Run _STA to determine if device is present */

	status = acpi_ut_execute_STA(node, &flags);
	if (ACPI_FAILURE(status)) {
		return (AE_CTRL_DEPTH);
	}

	if (!(flags & ACPI_STA_DEVICE_PRESENT)) {

		/* Don't examine children of the device if not present */

		return (AE_CTRL_DEPTH);
	}

	/* Filter based on device HID & CID */

	if (info->hid != NULL) {
		status = acpi_ut_execute_HID(node, &hid);
		if (status == AE_NOT_FOUND) {
			return (AE_OK);
		} else if (ACPI_FAILURE(status)) {
			return (AE_CTRL_DEPTH);
		}

		if (ACPI_STRNCMP(hid.value, info->hid, sizeof(hid.value)) != 0) {

			/* Get the list of Compatible IDs */

			status = acpi_ut_execute_CID(node, &cid);
			if (status == AE_NOT_FOUND) {
				return (AE_OK);
			} else if (ACPI_FAILURE(status)) {
				return (AE_CTRL_DEPTH);
			}

			/* Walk the CID list */

			for (i = 0; i < cid->count; i++) {
				if (ACPI_STRNCMP(cid->id[i].value, info->hid,
						 sizeof(struct
							acpi_compatible_id)) !=
				    0) {
					ACPI_FREE(cid);
					return (AE_OK);
				}
			}
			ACPI_FREE(cid);
		}
	}

	status = info->user_function(obj_handle, nesting_level, info->context,
				     return_value);
	return (status);
}
Esempio n. 19
0
static ACPI_STATUS
AcpiDmLoadDescendingOp (
    ACPI_PARSE_OBJECT       *Op,
    UINT32                  Level,
    void                    *Context)
{
    ACPI_OP_WALK_INFO       *Info = Context;
    const ACPI_OPCODE_INFO  *OpInfo;
    ACPI_WALK_STATE         *WalkState;
    ACPI_OBJECT_TYPE        ObjectType;
    ACPI_STATUS             Status;
    char                    *Path = NULL;
    ACPI_PARSE_OBJECT       *NextOp;
    ACPI_NAMESPACE_NODE     *Node;
    char                    FieldPath[5];
    BOOLEAN                 PreDefined = FALSE;
    UINT8                   PreDefineIndex = 0;


    WalkState = Info->WalkState;
    OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
    ObjectType = OpInfo->ObjectType;
    ObjectType = AslMapNamedOpcodeToDataType (Op->Asl.AmlOpcode);

    /* Only interested in operators that create new names */

    if (!(OpInfo->Flags & AML_NAMED) &&
        !(OpInfo->Flags & AML_CREATE))
    {
        goto Exit;
    }

    /* Get the NamePath from the appropriate place */

    if (OpInfo->Flags & AML_NAMED)
    {
        /* For all named operators, get the new name */

        Path = (char *) Op->Named.Path;

        if (!Path && Op->Common.AmlOpcode == AML_INT_NAMEDFIELD_OP)
        {
            *ACPI_CAST_PTR (UINT32, &FieldPath[0]) = Op->Named.Name;
            FieldPath[4] = 0;
            Path = FieldPath;
        }
    }
    else if (OpInfo->Flags & AML_CREATE)
    {
        /* New name is the last child */

        NextOp = Op->Common.Value.Arg;

        while (NextOp->Common.Next)
        {
            NextOp = NextOp->Common.Next;
        }
        Path = NextOp->Common.Value.String;
    }

    if (!Path)
    {
        goto Exit;
    }

    /* Insert the name into the namespace */

    Status = AcpiNsLookup (WalkState->ScopeInfo, Path, ObjectType,
                ACPI_IMODE_LOAD_PASS2, ACPI_NS_DONT_OPEN_SCOPE,
                WalkState, &Node);

    Op->Common.Node = Node;

    if (ACPI_SUCCESS (Status))
    {
        /* Check if it's a predefined node */

        while (AcpiGbl_PreDefinedNames[PreDefineIndex].Name)
        {
            if (!ACPI_STRNCMP (Node->Name.Ascii,
                AcpiGbl_PreDefinedNames[PreDefineIndex].Name, 4))
            {
                PreDefined = TRUE;
                break;
            }

            PreDefineIndex++;
        }

        /*
         * Set node owner id if it satisfies all the following conditions:
         * 1) Not a predefined node, _SB_ etc
         * 2) Not the root node
         * 3) Not a node created by Scope
         */

        if (!PreDefined && Node != AcpiGbl_RootNode &&
            Op->Common.AmlOpcode != AML_SCOPE_OP)
        {
            Node->OwnerId = WalkState->OwnerId;
        }
    }


Exit:

    if (AcpiNsOpensScope (ObjectType))
    {
        if (Op->Common.Node)
        {
            Status = AcpiDsScopeStackPush (Op->Common.Node, ObjectType, WalkState);
            if (ACPI_FAILURE (Status))
            {
                return (Status);
            }
        }
    }

    return (AE_OK);
}
Esempio n. 20
0
static ACPI_STATUS
AcpiNsGetDeviceCallback (
    ACPI_HANDLE             ObjHandle,
    UINT32                  NestingLevel,
    void                    *Context,
    void                    **ReturnValue)
{
    ACPI_GET_DEVICES_INFO   *Info = Context;
    ACPI_STATUS             Status;
    ACPI_NAMESPACE_NODE     *Node;
    UINT32                  Flags;
    ACPI_DEVICE_ID          Hid;
    ACPI_COMPATIBLE_ID_LIST *Cid;
    UINT32                  i;
    BOOLEAN                 Found;


    Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
    if (ACPI_FAILURE (Status))
    {
        return (Status);
    }

    Node = AcpiNsMapHandleToNode (ObjHandle);
    Status = AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
    if (ACPI_FAILURE (Status))
    {
        return (Status);
    }

    if (!Node)
    {
        return (AE_BAD_PARAMETER);
    }

    /* Run _STA to determine if device is present */

    Status = AcpiUtExecute_STA (Node, &Flags);
    if (ACPI_FAILURE (Status))
    {
        return (AE_CTRL_DEPTH);
    }

    if (!(Flags & ACPI_STA_DEVICE_PRESENT) &&
            !(Flags & ACPI_STA_DEVICE_FUNCTIONING))
    {
        /*
         * Don't examine the children of the device only when the
         * device is neither present nor functional. See ACPI spec,
         * description of _STA for more information.
         */
        return (AE_CTRL_DEPTH);
    }

    /* Filter based on device HID & CID */

    if (Info->Hid != NULL)
    {
        Status = AcpiUtExecute_HID (Node, &Hid);
        if (Status == AE_NOT_FOUND)
        {
            return (AE_OK);
        }
        else if (ACPI_FAILURE (Status))
        {
            return (AE_CTRL_DEPTH);
        }

        if (ACPI_STRNCMP (Hid.Value, Info->Hid, sizeof (Hid.Value)) != 0)
        {
            /*
             * HID does not match, attempt match within the
             * list of Compatible IDs (CIDs)
             */
            Status = AcpiUtExecute_CID (Node, &Cid);
            if (Status == AE_NOT_FOUND)
            {
                return (AE_OK);
            }
            else if (ACPI_FAILURE (Status))
            {
                return (AE_CTRL_DEPTH);
            }

            /* Walk the CID list */

            Found = FALSE;
            for (i = 0; i < Cid->Count; i++)
            {
                if (ACPI_STRNCMP (Cid->Id[i].Value, Info->Hid,
                                  sizeof (ACPI_COMPATIBLE_ID)) == 0)
                {
                    /* Found a matching CID */

                    Found = TRUE;
                    break;
                }
            }

            ACPI_FREE (Cid);
            if (!Found)
            {
                return (AE_OK);
            }
        }
    }

    /* We have a valid device, invoke the user function */

    Status = Info->UserFunction (ObjHandle, NestingLevel, Info->Context,
                                 ReturnValue);
    return (Status);
}
Esempio n. 21
0
acpi_status
acpi_ev_pci_config_region_setup(acpi_handle handle,
				u32 function,
				void *handler_context, void **region_context)
{
	acpi_status status = AE_OK;
	acpi_integer pci_value;
	struct acpi_pci_id *pci_id = *region_context;
	union acpi_operand_object *handler_obj;
	struct acpi_namespace_node *parent_node;
	struct acpi_namespace_node *pci_root_node;
	union acpi_operand_object *region_obj =
	    (union acpi_operand_object *)handle;
	struct acpi_device_id object_hID;

	ACPI_FUNCTION_TRACE(ev_pci_config_region_setup);

	handler_obj = region_obj->region.handler;
	if (!handler_obj) {
		/*
		 * No installed handler. This shouldn't happen because the dispatch
		 * routine checks before we get here, but we check again just in case.
		 */
		ACPI_DEBUG_PRINT((ACPI_DB_OPREGION,
				  "Attempting to init a region %p, with no handler\n",
				  region_obj));
		return_ACPI_STATUS(AE_NOT_EXIST);
	}

	*region_context = NULL;
	if (function == ACPI_REGION_DEACTIVATE) {
		if (pci_id) {
			ACPI_FREE(pci_id);
		}
		return_ACPI_STATUS(status);
	}

	parent_node = acpi_ns_get_parent_node(region_obj->region.node);

	/*
	 * Get the _SEG and _BBN values from the device upon which the handler
	 * is installed.
	 *
	 * We need to get the _SEG and _BBN objects relative to the PCI BUS device.
	 * This is the device the handler has been registered to handle.
	 */

	/*
	 * If the address_space.Node is still pointing to the root, we need
	 * to scan upward for a PCI Root bridge and re-associate the op_region
	 * handlers with that device.
	 */
	if (handler_obj->address_space.node == acpi_gbl_root_node) {

		/* Start search from the parent object */

		pci_root_node = parent_node;
		while (pci_root_node != acpi_gbl_root_node) {
			status =
			    acpi_ut_execute_HID(pci_root_node, &object_hID);
			if (ACPI_SUCCESS(status)) {
				/*
				 * Got a valid _HID string, check if this is a PCI root.
				 * New for ACPI 3.0: check for a PCI Express root also.
				 */
				if (!
				    (ACPI_STRNCMP
				     (object_hID.value, PCI_ROOT_HID_STRING,
				      sizeof(PCI_ROOT_HID_STRING))
				     ||
				     !(ACPI_STRNCMP
				       (object_hID.value,
					PCI_EXPRESS_ROOT_HID_STRING,
					sizeof(PCI_EXPRESS_ROOT_HID_STRING)))))
				{

					/* Install a handler for this PCI root bridge */

					status =
					    acpi_install_address_space_handler((acpi_handle) pci_root_node, ACPI_ADR_SPACE_PCI_CONFIG, ACPI_DEFAULT_HANDLER, NULL, NULL);
					if (ACPI_FAILURE(status)) {
						if (status == AE_SAME_HANDLER) {
							/*
							 * It is OK if the handler is already installed on the root
							 * bridge.  Still need to return a context object for the
							 * new PCI_Config operation region, however.
							 */
							status = AE_OK;
						} else {
							ACPI_EXCEPTION((AE_INFO,
									status,
									"Could not install PciConfig handler for Root Bridge %4.4s",
									acpi_ut_get_node_name
									(pci_root_node)));
						}
					}
					break;
				}
			}

			pci_root_node = acpi_ns_get_parent_node(pci_root_node);
		}

		/* PCI root bridge not found, use namespace root node */
	} else {
		pci_root_node = handler_obj->address_space.node;
	}

	/*
	 * If this region is now initialized, we are done.
	 * (install_address_space_handler could have initialized it)
	 */
	if (region_obj->region.flags & AOPOBJ_SETUP_COMPLETE) {
		return_ACPI_STATUS(AE_OK);
	}

	/* Region is still not initialized. Create a new context */

	pci_id = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_pci_id));
	if (!pci_id) {
		return_ACPI_STATUS(AE_NO_MEMORY);
	}

	/*
	 * For PCI_Config space access, we need the segment, bus,
	 * device and function numbers.  Acquire them here.
	 */

	/*
	 * Get the PCI device and function numbers from the _ADR object
	 * contained in the parent's scope.
	 */
	status =
	    acpi_ut_evaluate_numeric_object(METHOD_NAME__ADR, parent_node,
					    &pci_value);

	/*
	 * The default is zero, and since the allocation above zeroed
	 * the data, just do nothing on failure.
	 */
	if (ACPI_SUCCESS(status)) {
		pci_id->device = ACPI_HIWORD(ACPI_LODWORD(pci_value));
		pci_id->function = ACPI_LOWORD(ACPI_LODWORD(pci_value));
	}

	/* The PCI segment number comes from the _SEG method */

	status =
	    acpi_ut_evaluate_numeric_object(METHOD_NAME__SEG, pci_root_node,
					    &pci_value);
	if (ACPI_SUCCESS(status)) {
		pci_id->segment = ACPI_LOWORD(pci_value);
	}

	/* The PCI bus number comes from the _BBN method */

	status =
	    acpi_ut_evaluate_numeric_object(METHOD_NAME__BBN, pci_root_node,
					    &pci_value);
	if (ACPI_SUCCESS(status)) {
		pci_id->bus = ACPI_LOWORD(pci_value);
	}

	/* Complete this device's pci_id */

	acpi_os_derive_pci_id(pci_root_node, region_obj->region.node, &pci_id);

	*region_context = pci_id;
	return_ACPI_STATUS(AE_OK);
}
Esempio n. 22
0
ACPI_STATUS
AcpiGetFirmwareTable (
    ACPI_STRING             Signature,
    UINT32                  Instance,
    UINT32                  Flags,
    ACPI_TABLE_HEADER       **TablePointer)
{
    ACPI_POINTER            RsdpAddress;
    ACPI_POINTER            Address;
    ACPI_STATUS             Status;
    ACPI_TABLE_HEADER       Header;
    ACPI_TABLE_DESC         TableInfo;
    ACPI_TABLE_DESC         RsdtInfo;
    UINT32                  TableCount;
    UINT32                  i;
    UINT32                  j;


    ACPI_FUNCTION_TRACE ("AcpiGetFirmwareTable");


    /*
     * 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)                    ||
        (!TablePointer))
    {
        return_ACPI_STATUS (AE_BAD_PARAMETER);
    }

    RsdtInfo.Pointer = NULL;

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

        Status = AcpiOsGetRootPointer (Flags, &RsdpAddress);
        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 = AcpiOsMapMemory (RsdpAddress.Pointer.Physical, sizeof (RSDP_DESCRIPTOR),
                                        (void **) &AcpiGbl_RSDP);
            if (ACPI_FAILURE (Status))
            {
                return_ACPI_STATUS (Status);
            }
        }
        else
        {
            AcpiGbl_RSDP = RsdpAddress.Pointer.Logical;
        }

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

            return_ACPI_STATUS (AE_BAD_SIGNATURE);
        }

        if (AcpiTbChecksum (AcpiGbl_RSDP, ACPI_RSDP_CHECKSUM_LENGTH) != 0)
        {
            /* Nope, BAD Checksum */

            return_ACPI_STATUS (AE_BAD_CHECKSUM);
        }
    }

    /* Get the RSDT and validate it */

    AcpiTbGetRsdtAddress (&Address);

    ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
        "RSDP located at %p, RSDT physical=%8.8X%8.8X \n",
        AcpiGbl_RSDP,
        ACPI_HIDWORD (Address.Pointer.Value),
        ACPI_LODWORD (Address.Pointer.Value)));

    /* Insert ProcessorMode flags */

    Address.PointerType |= Flags;

    Status = AcpiTbGetTable (&Address, &RsdtInfo);
    if (ACPI_FAILURE (Status))
    {
        return_ACPI_STATUS (Status);
    }

    Status = AcpiTbValidateRsdt (RsdtInfo.Pointer);
    if (ACPI_FAILURE (Status))
    {
        goto Cleanup;
    }

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

    TableCount = AcpiTbGetTableCount (AcpiGbl_RSDP, RsdtInfo.Pointer);

    Address.PointerType = AcpiGbl_TableFlags | Flags;

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

        if (AcpiGbl_RSDP->Revision < 2)
        {
            Address.Pointer.Value = ((RSDT_DESCRIPTOR *) RsdtInfo.Pointer)->TableOffsetEntry[i];
        }
        else
        {
            Address.Pointer.Value = ACPI_GET_ADDRESS (
                ((XSDT_DESCRIPTOR *) RsdtInfo.Pointer)->TableOffsetEntry[i]);
        }

        /* Get the table header */

        Status = AcpiTbGetTableHeader (&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 = AcpiTbGetTableBody (&Address, &Header, &TableInfo);
                if (ACPI_FAILURE (Status))
                {
                    goto Cleanup;
                }

                *TablePointer = TableInfo.Pointer;
                goto Cleanup;
            }
        }
    }

    /* Did not find the table */

    Status = AE_NOT_EXIST;


Cleanup:
    AcpiOsUnmapMemory (RsdtInfo.Pointer, (ACPI_SIZE) RsdtInfo.Pointer->Length);
    return_ACPI_STATUS (Status);
}
Esempio n. 23
0
static ACPI_STATUS
AcpiDbReadTable (
    FILE                    *fp,
    ACPI_TABLE_HEADER       **Table,
    UINT32                  *TableLength)
{
    ACPI_TABLE_HEADER       TableHeader;
    UINT32                  Actual;
    ACPI_STATUS             Status;
    UINT32                  FileSize;
    BOOLEAN                 StandardHeader = TRUE;


    /* Get the file size */

    fseek (fp, 0, SEEK_END);
    FileSize = (UINT32) ftell (fp);
    fseek (fp, 0, SEEK_SET);

    if (FileSize < 4)
    {
        return (AE_BAD_HEADER);
    }

    /* Read the signature */

    if (fread (&TableHeader, 1, 4, fp) != 4)
    {
        AcpiOsPrintf ("Could not read the table signature\n");
        return (AE_BAD_HEADER);
    }

    fseek (fp, 0, SEEK_SET);

    /* The RSDT, FACS and S3PT tables do not have standard ACPI headers */

    if (ACPI_COMPARE_NAME (TableHeader.Signature, "RSD ") ||
        ACPI_COMPARE_NAME (TableHeader.Signature, "FACS") ||
        ACPI_COMPARE_NAME (TableHeader.Signature, "S3PT"))
    {
        *TableLength = FileSize;
        StandardHeader = FALSE;
    }
    else
    {
        /* Read the table header */

        if (fread (&TableHeader, 1, sizeof (TableHeader), fp) !=
                sizeof (ACPI_TABLE_HEADER))
        {
            AcpiOsPrintf ("Could not read the table header\n");
            return (AE_BAD_HEADER);
        }

#if 0
        /* Validate the table header/length */

        Status = AcpiTbValidateTableHeader (&TableHeader);
        if (ACPI_FAILURE (Status))
        {
            AcpiOsPrintf ("Table header is invalid!\n");
            return (Status);
        }
#endif

        /* File size must be at least as long as the Header-specified length */

        if (TableHeader.Length > FileSize)
        {
            AcpiOsPrintf (
                "TableHeader length [0x%X] greater than the input file size [0x%X]\n",
                TableHeader.Length, FileSize);
            return (AE_BAD_HEADER);
        }

#ifdef ACPI_OBSOLETE_CODE
        /* We only support a limited number of table types */

        if (ACPI_STRNCMP ((char *) TableHeader.Signature, DSDT_SIG, 4) &&
            ACPI_STRNCMP ((char *) TableHeader.Signature, PSDT_SIG, 4) &&
            ACPI_STRNCMP ((char *) TableHeader.Signature, SSDT_SIG, 4))
        {
            AcpiOsPrintf ("Table signature [%4.4s] is invalid or not supported\n",
                (char *) TableHeader.Signature);
            ACPI_DUMP_BUFFER (&TableHeader, sizeof (ACPI_TABLE_HEADER));
            return (AE_ERROR);
        }
#endif

        *TableLength = TableHeader.Length;
    }

    /* Allocate a buffer for the table */

    *Table = AcpiOsAllocate ((size_t) FileSize);
    if (!*Table)
    {
        AcpiOsPrintf (
            "Could not allocate memory for ACPI table %4.4s (size=0x%X)\n",
            TableHeader.Signature, *TableLength);
        return (AE_NO_MEMORY);
    }

    /* Get the rest of the table */

    fseek (fp, 0, SEEK_SET);
    Actual = fread (*Table, 1, (size_t) FileSize, fp);
    if (Actual == FileSize)
    {
        if (StandardHeader)
        {
            /* Now validate the checksum */

            Status = AcpiTbVerifyChecksum ((void *) *Table,
                        ACPI_CAST_PTR (ACPI_TABLE_HEADER, *Table)->Length);

            if (Status == AE_BAD_CHECKSUM)
            {
                Status = AcpiDbCheckTextModeCorruption ((UINT8 *) *Table,
                            FileSize, (*Table)->Length);
                return (Status);
            }
        }
        return (AE_OK);
    }

    if (Actual > 0)
    {
        AcpiOsPrintf ("Warning - reading table, asked for %X got %X\n",
            FileSize, Actual);
        return (AE_OK);
    }

    AcpiOsPrintf ("Error - could not read the table file\n");
    AcpiOsFree (*Table);
    *Table = NULL;
    *TableLength = 0;

    return (AE_ERROR);
}
Esempio n. 24
0
static ACPI_STATUS
OptBuildShortestPath (
    ACPI_PARSE_OBJECT       *Op,
    ACPI_WALK_STATE         *WalkState,
    ACPI_NAMESPACE_NODE     *CurrentNode,
    ACPI_NAMESPACE_NODE     *TargetNode,
    ACPI_BUFFER             *CurrentPath,
    ACPI_BUFFER             *TargetPath,
    ACPI_SIZE               AmlNameStringLength,
    UINT8                   IsDeclaration,
    char                    **ReturnNewPath)
{
    UINT32                  NumCommonSegments;
    UINT32                  MaxCommonSegments;
    ACPI_NATIVE_UINT        Index;
    UINT32                  NumCarats;
    ACPI_NATIVE_UINT        i;
    char                    *NewPath;
    char                    *NewPathExternal;
    ACPI_NAMESPACE_NODE     *Node;
    ACPI_GENERIC_STATE      ScopeInfo;
    ACPI_STATUS             Status;
    BOOLEAN                 SubPath = FALSE;


    ACPI_FUNCTION_NAME (OptBuildShortestPath);


    ScopeInfo.Scope.Node = CurrentNode;

    /*
     * Determine the maximum number of NameSegs that the Target and Current paths
     * can possibly have in common.  (To optimize, we have to have at least 1)
     *
     * Note: The external NamePath string lengths are always a multiple of 5
     * (ACPI_NAME_SIZE + separator)
     */
    MaxCommonSegments = TargetPath->Length / ACPI_PATH_SEGMENT_LENGTH;
    if (CurrentPath->Length < TargetPath->Length)
    {
        MaxCommonSegments = CurrentPath->Length / ACPI_PATH_SEGMENT_LENGTH;
    }

    /*
     * Determine how many NameSegs the two paths have in common.
     * (Starting from the root)
     */
    for (NumCommonSegments = 0;
         NumCommonSegments < MaxCommonSegments;
         NumCommonSegments++)
    {
        /* Compare two single NameSegs */

        if (ACPI_STRNCMP (
            &((char *) TargetPath->Pointer)[(NumCommonSegments *
                                             ACPI_PATH_SEGMENT_LENGTH) + 1],
            &((char *) CurrentPath->Pointer)[(NumCommonSegments *
                                              ACPI_PATH_SEGMENT_LENGTH) + 1],
            ACPI_NAME_SIZE))
        {
            /* Mismatch */

            break;
        }
    }

    ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS, " COMMON: %d",
        NumCommonSegments));

    /* There must be at least 1 common NameSeg in order to optimize */

    if (NumCommonSegments == 0)
    {
        return (AE_NOT_FOUND);
    }

    if (NumCommonSegments == MaxCommonSegments)
    {
        if (CurrentPath->Length == TargetPath->Length)
        {
            ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS, " SAME PATH"));
            return (AE_NOT_FOUND);
        }
        else
        {
            ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS, " SUBPATH"));
            SubPath = TRUE;
        }
    }

    /* Determine how many prefix Carats are required */

    NumCarats = (CurrentPath->Length / ACPI_PATH_SEGMENT_LENGTH) -
                NumCommonSegments;

    /*
     * Construct a new target string
     */
    NewPathExternal = ACPI_ALLOCATE_ZEROED (
        TargetPath->Length + NumCarats + 1);

    /* Insert the Carats into the Target string */

    for (i = 0; i < NumCarats; i++)
    {
        NewPathExternal[i] = '^';
    }

    /*
     * Copy only the necessary (optimal) segments from the original
     * target string
     */
    Index = (NumCommonSegments * ACPI_PATH_SEGMENT_LENGTH) + 1;

    /* Special handling for exact subpath in a name declaration */

    if (IsDeclaration && SubPath && (CurrentPath->Length > TargetPath->Length))
    {
        /*
         * The current path is longer than the target, and the target is a
         * subpath of the current path. We must include one more NameSeg of
         * the target path
         */
        Index -= ACPI_PATH_SEGMENT_LENGTH;

        /* Special handling for Scope() operator */

        if (Op->Asl.AmlOpcode == AML_SCOPE_OP)
        {
            NewPathExternal[i] = '^';
            i++;
            ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS, "(EXTRA ^)"));
        }
    }

    /* Make sure we haven't gone off the end of the target path */

    if (Index > TargetPath->Length)
    {
        Index = TargetPath->Length;
    }

    ACPI_STRCPY (&NewPathExternal[i], &((char *) TargetPath->Pointer)[Index]);
    ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS, " %-24s", NewPathExternal));

    /*
     * Internalize the new target string and check it against the original
     * string to make sure that this is in fact an optimization. If the
     * original string is already optimal, there is no point in continuing.
     */
    Status = AcpiNsInternalizeName (NewPathExternal, &NewPath);
    if (ACPI_FAILURE (Status))
    {
        AslCoreSubsystemError (Op, Status, "Internalizing new NamePath",
            ASL_NO_ABORT);
        ACPI_FREE (NewPathExternal);
        return (Status);
    }

    if (ACPI_STRLEN (NewPath) >= AmlNameStringLength)
    {
        ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS,
            " NOT SHORTER (New %u old %u)",
            ACPI_STRLEN (NewPath), AmlNameStringLength));
        ACPI_FREE (NewPathExternal);
        return (AE_NOT_FOUND);
    }

    /*
     * Check to make sure that the optimization finds the node we are
     * looking for.  This is simply a sanity check on the new
     * path that has been created.
     */
    Status = AcpiNsLookup (&ScopeInfo,  NewPath,
                    ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE,
                    ACPI_NS_DONT_OPEN_SCOPE, WalkState, &(Node));
    if (ACPI_SUCCESS (Status))
    {
        /* Found the namepath, but make sure the node is correct */

        if (Node == TargetNode)
        {
            /* The lookup matched the node, accept this optimization */

            AslError (ASL_OPTIMIZATION, ASL_MSG_NAME_OPTIMIZATION,
                Op, NewPathExternal);
            *ReturnNewPath = NewPath;
        }
        else
        {
            /* Node is not correct, do not use this optimization */

            Status = AE_NOT_FOUND;
            ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS, " ***** WRONG NODE"));
            AslError (ASL_WARNING, ASL_MSG_COMPILER_INTERNAL, Op,
                "Not using optimized name - found wrong node");
        }
    }
    else
    {
        /* The lookup failed, we obviously cannot use this optimization */

        ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS, " ***** NOT FOUND"));
        AslError (ASL_WARNING, ASL_MSG_COMPILER_INTERNAL, Op,
            "Not using optimized name - did not find node");
    }

    ACPI_FREE (NewPathExternal);
    return (Status);
}
Esempio n. 25
0
static ACPI_STATUS
OptSearchToRoot (
    ACPI_PARSE_OBJECT       *Op,
    ACPI_WALK_STATE         *WalkState,
    ACPI_NAMESPACE_NODE     *CurrentNode,
    ACPI_NAMESPACE_NODE     *TargetNode,
    ACPI_BUFFER             *TargetPath,
    char                    **NewPath)
{
    ACPI_NAMESPACE_NODE     *Node;
    ACPI_GENERIC_STATE      ScopeInfo;
    ACPI_STATUS             Status;
    char                    *Path;


    ACPI_FUNCTION_NAME (OptSearchToRoot);


    /*
     * Check if search-to-root can be utilized. Use the last NameSeg of
     * the NamePath and 1) See if can be found and 2) If found, make
     * sure that it is the same node that we want. If there is another
     * name in the search path before the one we want, the nodes will
     * not match, and we cannot use this optimization.
     */
    Path = &(((char *) TargetPath->Pointer)[TargetPath->Length -
                                            ACPI_NAME_SIZE]),
    ScopeInfo.Scope.Node = CurrentNode;

    /* Lookup the NameSeg using SEARCH_PARENT (search-to-root) */

    Status = AcpiNsLookup (&ScopeInfo, Path, ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE,
                    ACPI_NS_SEARCH_PARENT | ACPI_NS_DONT_OPEN_SCOPE,
                    WalkState, &(Node));
    if (ACPI_FAILURE (Status))
    {
        return (Status);
    }

    /*
     * We found the name, but we must check to make sure that the node
     * matches. Otherwise, there is another identical name in the search
     * path that precludes the use of this optimization.
     */
    if (Node != TargetNode)
    {
        /*
         * This means that another object with the same name was found first,
         * and we cannot use this optimization.
         */
        return (AE_NOT_FOUND);
    }

    /* Found the node, we can use this optimization */

    ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS,
        "NAMESEG:   %-24s", Path));

    /* We must allocate a new string for the name (TargetPath gets deleted) */

    *NewPath = UtStringCacheCalloc (ACPI_NAME_SIZE + 1);
    ACPI_STRCPY (*NewPath, Path);

    if (ACPI_STRNCMP (*NewPath, "_T_", 3))
    {
        AslError (ASL_OPTIMIZATION, ASL_MSG_SINGLE_NAME_OPTIMIZATION, Op,
                *NewPath);
    }

    return (AE_OK);
}
Esempio n. 26
0
ACPI_STATUS
DtCreateTemplates (
    char                    *Signature)
{
    ACPI_DMTABLE_DATA       *TableData;
    ACPI_STATUS             Status;


    AslInitializeGlobals ();
    AcpiUtStrupr (Signature);

    /* Create all known templates if requested */

    if (!ACPI_STRNCMP (Signature, "ALL", 3) ||
        !ACPI_STRCMP (Signature, "*"))
    {
        Status = DtCreateAllTemplates ();
        return (Status);
    }

    /*
     * Validate signature and get the template data:
     *  1) Signature must be 4 characters
     *  2) Signature must be a recognized ACPI table
     *  3) There must be a template associated with the signature
     */
    if (strlen (Signature) != ACPI_NAME_SIZE)
    {
        fprintf (stderr, "%s, Invalid ACPI table signature\n", Signature);
        return (AE_ERROR);
    }

    /*
     * Some slack for the two strange tables whose name is different than
     * their signatures: MADT->APIC and FADT->FACP.
     */
    if (!strcmp (Signature, "MADT"))
    {
        Signature = "APIC";
    }
    else if (!strcmp (Signature, "FADT"))
    {
        Signature = "FACP";
    }

    TableData = AcpiDmGetTableData (Signature);
    if (TableData)
    {
        if (!TableData->Template)
        {
            fprintf (stderr, "%4.4s, No template available\n", Signature);
            return (AE_ERROR);
        }
    }
    else if (!AcpiUtIsSpecialTable (Signature))
    {
        fprintf (stderr,
            "%4.4s, Unrecognized ACPI table signature\n", Signature);
        return (AE_ERROR);
    }

    Status = AdInitialize ();
    if (ACPI_FAILURE (Status))
    {
        return (Status);
    }

    Status = DtCreateOneTemplate (Signature, TableData);
    return (Status);
}
Esempio n. 27
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. 28
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. 29
0
ACPI_STATUS
AcpiTbAddTable (
    ACPI_TABLE_DESC         *TableDesc,
    UINT32                  *TableIndex)
{
    UINT32                  i;
    ACPI_STATUS             Status = AE_OK;


    ACPI_FUNCTION_TRACE (TbAddTable);


    if (!TableDesc->Pointer)
    {
        Status = AcpiTbVerifyTable (TableDesc);
        if (ACPI_FAILURE (Status) || !TableDesc->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 ((TableDesc->Pointer->Signature[0] != 0x00) &&
       (!ACPI_COMPARE_NAME (TableDesc->Pointer->Signature, ACPI_SIG_SSDT)) &&
       (ACPI_STRNCMP (TableDesc->Pointer->Signature, "OEM", 3)))
    {
        ACPI_BIOS_ERROR ((AE_INFO,
            "Table has invalid signature [%4.4s] (0x%8.8X), "
            "must be SSDT or OEMx",
            AcpiUtValidAcpiName (TableDesc->Pointer->Signature) ?
                TableDesc->Pointer->Signature : "????",
            *(UINT32 *) TableDesc->Pointer->Signature));

        return_ACPI_STATUS (AE_BAD_SIGNATURE);
    }

    (void) AcpiUtAcquireMutex (ACPI_MTX_TABLES);

    /* Check if table is already registered */

    for (i = 0; i < AcpiGbl_RootTableList.CurrentTableCount; ++i)
    {
        if (!AcpiGbl_RootTableList.Tables[i].Pointer)
        {
            Status = AcpiTbVerifyTable (&AcpiGbl_RootTableList.Tables[i]);
            if (ACPI_FAILURE (Status) ||
                !AcpiGbl_RootTableList.Tables[i].Pointer)
            {
                continue;
            }
        }

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

        if (ACPI_MEMCMP (TableDesc->Pointer,
                AcpiGbl_RootTableList.Tables[i].Pointer,
                AcpiGbl_RootTableList.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.
         */
        AcpiTbDeleteTable (TableDesc);
        *TableIndex = i;

        if (AcpiGbl_RootTableList.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 */

            TableDesc->Pointer = AcpiGbl_RootTableList.Tables[i].Pointer;
            TableDesc->Address = AcpiGbl_RootTableList.Tables[i].Address;
            Status = AE_OK;
            goto PrintHeader;
        }
    }

    /*
     * 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 TbTableOverride if the table is actually overridden.
     */
    (void) AcpiTbTableOverride (TableDesc->Pointer, TableDesc);

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

    Status = AcpiTbStoreTable (TableDesc->Address, TableDesc->Pointer,
                TableDesc->Length, TableDesc->Flags, TableIndex);
    if (ACPI_FAILURE (Status))
    {
        goto Release;
    }

PrintHeader:
    AcpiTbPrintTableHeader (TableDesc->Address, TableDesc->Pointer);

Release:
    (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES);
    return_ACPI_STATUS (Status);
}
Esempio n. 30
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);
}