xref: /openbmc/linux/drivers/acpi/acpica/uteval.c (revision e2f7a7772880458edff1b1cc5a988947229fac26)
195b482a8SLen Brown /******************************************************************************
295b482a8SLen Brown  *
395b482a8SLen Brown  * Module Name: uteval - Object evaluation
495b482a8SLen Brown  *
595b482a8SLen Brown  *****************************************************************************/
695b482a8SLen Brown 
795b482a8SLen Brown /*
895b482a8SLen Brown  * Copyright (C) 2000 - 2008, Intel Corp.
995b482a8SLen Brown  * All rights reserved.
1095b482a8SLen Brown  *
1195b482a8SLen Brown  * Redistribution and use in source and binary forms, with or without
1295b482a8SLen Brown  * modification, are permitted provided that the following conditions
1395b482a8SLen Brown  * are met:
1495b482a8SLen Brown  * 1. Redistributions of source code must retain the above copyright
1595b482a8SLen Brown  *    notice, this list of conditions, and the following disclaimer,
1695b482a8SLen Brown  *    without modification.
1795b482a8SLen Brown  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
1895b482a8SLen Brown  *    substantially similar to the "NO WARRANTY" disclaimer below
1995b482a8SLen Brown  *    ("Disclaimer") and any redistribution must be conditioned upon
2095b482a8SLen Brown  *    including a substantially similar Disclaimer requirement for further
2195b482a8SLen Brown  *    binary redistribution.
2295b482a8SLen Brown  * 3. Neither the names of the above-listed copyright holders nor the names
2395b482a8SLen Brown  *    of any contributors may be used to endorse or promote products derived
2495b482a8SLen Brown  *    from this software without specific prior written permission.
2595b482a8SLen Brown  *
2695b482a8SLen Brown  * Alternatively, this software may be distributed under the terms of the
2795b482a8SLen Brown  * GNU General Public License ("GPL") version 2 as published by the Free
2895b482a8SLen Brown  * Software Foundation.
2995b482a8SLen Brown  *
3095b482a8SLen Brown  * NO WARRANTY
3195b482a8SLen Brown  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
3295b482a8SLen Brown  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
3395b482a8SLen Brown  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
3495b482a8SLen Brown  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
3595b482a8SLen Brown  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
3695b482a8SLen Brown  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
3795b482a8SLen Brown  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
3895b482a8SLen Brown  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
3995b482a8SLen Brown  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
4095b482a8SLen Brown  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
4195b482a8SLen Brown  * POSSIBILITY OF SUCH DAMAGES.
4295b482a8SLen Brown  */
4395b482a8SLen Brown 
4495b482a8SLen Brown #include <acpi/acpi.h>
45*e2f7a777SLen Brown #include "accommon.h"
46*e2f7a777SLen Brown #include "acnamesp.h"
47*e2f7a777SLen Brown #include "acinterp.h"
4895b482a8SLen Brown 
4995b482a8SLen Brown #define _COMPONENT          ACPI_UTILITIES
5095b482a8SLen Brown ACPI_MODULE_NAME("uteval")
5195b482a8SLen Brown 
5295b482a8SLen Brown /* Local prototypes */
5395b482a8SLen Brown static void
5495b482a8SLen Brown acpi_ut_copy_id_string(char *destination, char *source, acpi_size max_length);
5595b482a8SLen Brown 
5695b482a8SLen Brown static acpi_status
5795b482a8SLen Brown acpi_ut_translate_one_cid(union acpi_operand_object *obj_desc,
5895b482a8SLen Brown 			  struct acpi_compatible_id *one_cid);
5995b482a8SLen Brown 
6095b482a8SLen Brown /*
6195b482a8SLen Brown  * Strings supported by the _OSI predefined (internal) method.
6295b482a8SLen Brown  */
6395b482a8SLen Brown static char *acpi_interfaces_supported[] = {
6495b482a8SLen Brown 	/* Operating System Vendor Strings */
6595b482a8SLen Brown 
6695b482a8SLen Brown 	"Windows 2000",		/* Windows 2000 */
6795b482a8SLen Brown 	"Windows 2001",		/* Windows XP */
6895b482a8SLen Brown 	"Windows 2001 SP1",	/* Windows XP SP1 */
6995b482a8SLen Brown 	"Windows 2001 SP2",	/* Windows XP SP2 */
7095b482a8SLen Brown 	"Windows 2001.1",	/* Windows Server 2003 */
7195b482a8SLen Brown 	"Windows 2001.1 SP1",	/* Windows Server 2003 SP1 - Added 03/2006 */
7295b482a8SLen Brown 	"Windows 2006",		/* Windows Vista - Added 03/2006 */
7395b482a8SLen Brown 
7495b482a8SLen Brown 	/* Feature Group Strings */
7595b482a8SLen Brown 
7695b482a8SLen Brown 	"Extended Address Space Descriptor"
7795b482a8SLen Brown 	    /*
7895b482a8SLen Brown 	     * All "optional" feature group strings (features that are implemented
7995b482a8SLen Brown 	     * by the host) should be implemented in the host version of
8095b482a8SLen Brown 	     * acpi_os_validate_interface and should not be added here.
8195b482a8SLen Brown 	     */
8295b482a8SLen Brown };
8395b482a8SLen Brown 
8495b482a8SLen Brown /*******************************************************************************
8595b482a8SLen Brown  *
8695b482a8SLen Brown  * FUNCTION:    acpi_ut_osi_implementation
8795b482a8SLen Brown  *
8895b482a8SLen Brown  * PARAMETERS:  walk_state          - Current walk state
8995b482a8SLen Brown  *
9095b482a8SLen Brown  * RETURN:      Status
9195b482a8SLen Brown  *
9295b482a8SLen Brown  * DESCRIPTION: Implementation of the _OSI predefined control method
9395b482a8SLen Brown  *
9495b482a8SLen Brown  ******************************************************************************/
9595b482a8SLen Brown 
9695b482a8SLen Brown acpi_status acpi_ut_osi_implementation(struct acpi_walk_state *walk_state)
9795b482a8SLen Brown {
9895b482a8SLen Brown 	acpi_status status;
9995b482a8SLen Brown 	union acpi_operand_object *string_desc;
10095b482a8SLen Brown 	union acpi_operand_object *return_desc;
10195b482a8SLen Brown 	u32 i;
10295b482a8SLen Brown 
10395b482a8SLen Brown 	ACPI_FUNCTION_TRACE(ut_osi_implementation);
10495b482a8SLen Brown 
10595b482a8SLen Brown 	/* Validate the string input argument */
10695b482a8SLen Brown 
10795b482a8SLen Brown 	string_desc = walk_state->arguments[0].object;
10895b482a8SLen Brown 	if (!string_desc || (string_desc->common.type != ACPI_TYPE_STRING)) {
10995b482a8SLen Brown 		return_ACPI_STATUS(AE_TYPE);
11095b482a8SLen Brown 	}
11195b482a8SLen Brown 
11295b482a8SLen Brown 	/* Create a return object */
11395b482a8SLen Brown 
11495b482a8SLen Brown 	return_desc = acpi_ut_create_internal_object(ACPI_TYPE_INTEGER);
11595b482a8SLen Brown 	if (!return_desc) {
11695b482a8SLen Brown 		return_ACPI_STATUS(AE_NO_MEMORY);
11795b482a8SLen Brown 	}
11895b482a8SLen Brown 
11995b482a8SLen Brown 	/* Default return value is SUPPORTED */
12095b482a8SLen Brown 
12195b482a8SLen Brown 	return_desc->integer.value = ACPI_UINT32_MAX;
12295b482a8SLen Brown 	walk_state->return_desc = return_desc;
12395b482a8SLen Brown 
12495b482a8SLen Brown 	/* Compare input string to static table of supported interfaces */
12595b482a8SLen Brown 
12695b482a8SLen Brown 	for (i = 0; i < ACPI_ARRAY_LENGTH(acpi_interfaces_supported); i++) {
12795b482a8SLen Brown 		if (!ACPI_STRCMP
12895b482a8SLen Brown 		    (string_desc->string.pointer,
12995b482a8SLen Brown 		     acpi_interfaces_supported[i])) {
13095b482a8SLen Brown 
13195b482a8SLen Brown 			/* The interface is supported */
13295b482a8SLen Brown 
13395b482a8SLen Brown 			return_ACPI_STATUS(AE_OK);
13495b482a8SLen Brown 		}
13595b482a8SLen Brown 	}
13695b482a8SLen Brown 
13795b482a8SLen Brown 	/*
13895b482a8SLen Brown 	 * Did not match the string in the static table, call the host OSL to
13995b482a8SLen Brown 	 * check for a match with one of the optional strings (such as
14095b482a8SLen Brown 	 * "Module Device", "3.0 Thermal Model", etc.)
14195b482a8SLen Brown 	 */
14295b482a8SLen Brown 	status = acpi_os_validate_interface(string_desc->string.pointer);
14395b482a8SLen Brown 	if (ACPI_SUCCESS(status)) {
14495b482a8SLen Brown 
14595b482a8SLen Brown 		/* The interface is supported */
14695b482a8SLen Brown 
14795b482a8SLen Brown 		return_ACPI_STATUS(AE_OK);
14895b482a8SLen Brown 	}
14995b482a8SLen Brown 
15095b482a8SLen Brown 	/* The interface is not supported */
15195b482a8SLen Brown 
15295b482a8SLen Brown 	return_desc->integer.value = 0;
15395b482a8SLen Brown 	return_ACPI_STATUS(AE_OK);
15495b482a8SLen Brown }
15595b482a8SLen Brown 
15695b482a8SLen Brown /*******************************************************************************
15795b482a8SLen Brown  *
15895b482a8SLen Brown  * FUNCTION:    acpi_osi_invalidate
15995b482a8SLen Brown  *
16095b482a8SLen Brown  * PARAMETERS:  interface_string
16195b482a8SLen Brown  *
16295b482a8SLen Brown  * RETURN:      Status
16395b482a8SLen Brown  *
16495b482a8SLen Brown  * DESCRIPTION: invalidate string in pre-defiend _OSI string list
16595b482a8SLen Brown  *
16695b482a8SLen Brown  ******************************************************************************/
16795b482a8SLen Brown 
16895b482a8SLen Brown acpi_status acpi_osi_invalidate(char *interface)
16995b482a8SLen Brown {
17095b482a8SLen Brown 	int i;
17195b482a8SLen Brown 
17295b482a8SLen Brown 	for (i = 0; i < ACPI_ARRAY_LENGTH(acpi_interfaces_supported); i++) {
17395b482a8SLen Brown 		if (!ACPI_STRCMP(interface, acpi_interfaces_supported[i])) {
17495b482a8SLen Brown 			*acpi_interfaces_supported[i] = '\0';
17595b482a8SLen Brown 			return AE_OK;
17695b482a8SLen Brown 		}
17795b482a8SLen Brown 	}
17895b482a8SLen Brown 	return AE_NOT_FOUND;
17995b482a8SLen Brown }
18095b482a8SLen Brown 
18195b482a8SLen Brown /*******************************************************************************
18295b482a8SLen Brown  *
18395b482a8SLen Brown  * FUNCTION:    acpi_ut_evaluate_object
18495b482a8SLen Brown  *
18595b482a8SLen Brown  * PARAMETERS:  prefix_node         - Starting node
18695b482a8SLen Brown  *              Path                - Path to object from starting node
18795b482a8SLen Brown  *              expected_return_types - Bitmap of allowed return types
18895b482a8SLen Brown  *              return_desc         - Where a return value is stored
18995b482a8SLen Brown  *
19095b482a8SLen Brown  * RETURN:      Status
19195b482a8SLen Brown  *
19295b482a8SLen Brown  * DESCRIPTION: Evaluates a namespace object and verifies the type of the
19395b482a8SLen Brown  *              return object.  Common code that simplifies accessing objects
19495b482a8SLen Brown  *              that have required return objects of fixed types.
19595b482a8SLen Brown  *
19695b482a8SLen Brown  *              NOTE: Internal function, no parameter validation
19795b482a8SLen Brown  *
19895b482a8SLen Brown  ******************************************************************************/
19995b482a8SLen Brown 
20095b482a8SLen Brown acpi_status
20195b482a8SLen Brown acpi_ut_evaluate_object(struct acpi_namespace_node *prefix_node,
20295b482a8SLen Brown 			char *path,
20395b482a8SLen Brown 			u32 expected_return_btypes,
20495b482a8SLen Brown 			union acpi_operand_object **return_desc)
20595b482a8SLen Brown {
20695b482a8SLen Brown 	struct acpi_evaluate_info *info;
20795b482a8SLen Brown 	acpi_status status;
20895b482a8SLen Brown 	u32 return_btype;
20995b482a8SLen Brown 
21095b482a8SLen Brown 	ACPI_FUNCTION_TRACE(ut_evaluate_object);
21195b482a8SLen Brown 
21295b482a8SLen Brown 	/* Allocate the evaluation information block */
21395b482a8SLen Brown 
21495b482a8SLen Brown 	info = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_evaluate_info));
21595b482a8SLen Brown 	if (!info) {
21695b482a8SLen Brown 		return_ACPI_STATUS(AE_NO_MEMORY);
21795b482a8SLen Brown 	}
21895b482a8SLen Brown 
21995b482a8SLen Brown 	info->prefix_node = prefix_node;
22095b482a8SLen Brown 	info->pathname = path;
22195b482a8SLen Brown 
22295b482a8SLen Brown 	/* Evaluate the object/method */
22395b482a8SLen Brown 
22495b482a8SLen Brown 	status = acpi_ns_evaluate(info);
22595b482a8SLen Brown 	if (ACPI_FAILURE(status)) {
22695b482a8SLen Brown 		if (status == AE_NOT_FOUND) {
22795b482a8SLen Brown 			ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
22895b482a8SLen Brown 					  "[%4.4s.%s] was not found\n",
22995b482a8SLen Brown 					  acpi_ut_get_node_name(prefix_node),
23095b482a8SLen Brown 					  path));
23195b482a8SLen Brown 		} else {
23295b482a8SLen Brown 			ACPI_ERROR_METHOD("Method execution failed",
23395b482a8SLen Brown 					  prefix_node, path, status);
23495b482a8SLen Brown 		}
23595b482a8SLen Brown 
23695b482a8SLen Brown 		goto cleanup;
23795b482a8SLen Brown 	}
23895b482a8SLen Brown 
23995b482a8SLen Brown 	/* Did we get a return object? */
24095b482a8SLen Brown 
24195b482a8SLen Brown 	if (!info->return_object) {
24295b482a8SLen Brown 		if (expected_return_btypes) {
24395b482a8SLen Brown 			ACPI_ERROR_METHOD("No object was returned from",
24495b482a8SLen Brown 					  prefix_node, path, AE_NOT_EXIST);
24595b482a8SLen Brown 
24695b482a8SLen Brown 			status = AE_NOT_EXIST;
24795b482a8SLen Brown 		}
24895b482a8SLen Brown 
24995b482a8SLen Brown 		goto cleanup;
25095b482a8SLen Brown 	}
25195b482a8SLen Brown 
25295b482a8SLen Brown 	/* Map the return object type to the bitmapped type */
25395b482a8SLen Brown 
25495b482a8SLen Brown 	switch (ACPI_GET_OBJECT_TYPE(info->return_object)) {
25595b482a8SLen Brown 	case ACPI_TYPE_INTEGER:
25695b482a8SLen Brown 		return_btype = ACPI_BTYPE_INTEGER;
25795b482a8SLen Brown 		break;
25895b482a8SLen Brown 
25995b482a8SLen Brown 	case ACPI_TYPE_BUFFER:
26095b482a8SLen Brown 		return_btype = ACPI_BTYPE_BUFFER;
26195b482a8SLen Brown 		break;
26295b482a8SLen Brown 
26395b482a8SLen Brown 	case ACPI_TYPE_STRING:
26495b482a8SLen Brown 		return_btype = ACPI_BTYPE_STRING;
26595b482a8SLen Brown 		break;
26695b482a8SLen Brown 
26795b482a8SLen Brown 	case ACPI_TYPE_PACKAGE:
26895b482a8SLen Brown 		return_btype = ACPI_BTYPE_PACKAGE;
26995b482a8SLen Brown 		break;
27095b482a8SLen Brown 
27195b482a8SLen Brown 	default:
27295b482a8SLen Brown 		return_btype = 0;
27395b482a8SLen Brown 		break;
27495b482a8SLen Brown 	}
27595b482a8SLen Brown 
27695b482a8SLen Brown 	if ((acpi_gbl_enable_interpreter_slack) && (!expected_return_btypes)) {
27795b482a8SLen Brown 		/*
27895b482a8SLen Brown 		 * We received a return object, but one was not expected.  This can
27995b482a8SLen Brown 		 * happen frequently if the "implicit return" feature is enabled.
28095b482a8SLen Brown 		 * Just delete the return object and return AE_OK.
28195b482a8SLen Brown 		 */
28295b482a8SLen Brown 		acpi_ut_remove_reference(info->return_object);
28395b482a8SLen Brown 		goto cleanup;
28495b482a8SLen Brown 	}
28595b482a8SLen Brown 
28695b482a8SLen Brown 	/* Is the return object one of the expected types? */
28795b482a8SLen Brown 
28895b482a8SLen Brown 	if (!(expected_return_btypes & return_btype)) {
28995b482a8SLen Brown 		ACPI_ERROR_METHOD("Return object type is incorrect",
29095b482a8SLen Brown 				  prefix_node, path, AE_TYPE);
29195b482a8SLen Brown 
29295b482a8SLen Brown 		ACPI_ERROR((AE_INFO,
29395b482a8SLen Brown 			    "Type returned from %s was incorrect: %s, expected Btypes: %X",
29495b482a8SLen Brown 			    path,
29595b482a8SLen Brown 			    acpi_ut_get_object_type_name(info->return_object),
29695b482a8SLen Brown 			    expected_return_btypes));
29795b482a8SLen Brown 
29895b482a8SLen Brown 		/* On error exit, we must delete the return object */
29995b482a8SLen Brown 
30095b482a8SLen Brown 		acpi_ut_remove_reference(info->return_object);
30195b482a8SLen Brown 		status = AE_TYPE;
30295b482a8SLen Brown 		goto cleanup;
30395b482a8SLen Brown 	}
30495b482a8SLen Brown 
30595b482a8SLen Brown 	/* Object type is OK, return it */
30695b482a8SLen Brown 
30795b482a8SLen Brown 	*return_desc = info->return_object;
30895b482a8SLen Brown 
30995b482a8SLen Brown       cleanup:
31095b482a8SLen Brown 	ACPI_FREE(info);
31195b482a8SLen Brown 	return_ACPI_STATUS(status);
31295b482a8SLen Brown }
31395b482a8SLen Brown 
31495b482a8SLen Brown /*******************************************************************************
31595b482a8SLen Brown  *
31695b482a8SLen Brown  * FUNCTION:    acpi_ut_evaluate_numeric_object
31795b482a8SLen Brown  *
31895b482a8SLen Brown  * PARAMETERS:  object_name         - Object name to be evaluated
31995b482a8SLen Brown  *              device_node         - Node for the device
32095b482a8SLen Brown  *              Address             - Where the value is returned
32195b482a8SLen Brown  *
32295b482a8SLen Brown  * RETURN:      Status
32395b482a8SLen Brown  *
32495b482a8SLen Brown  * DESCRIPTION: Evaluates a numeric namespace object for a selected device
32595b482a8SLen Brown  *              and stores result in *Address.
32695b482a8SLen Brown  *
32795b482a8SLen Brown  *              NOTE: Internal function, no parameter validation
32895b482a8SLen Brown  *
32995b482a8SLen Brown  ******************************************************************************/
33095b482a8SLen Brown 
33195b482a8SLen Brown acpi_status
33295b482a8SLen Brown acpi_ut_evaluate_numeric_object(char *object_name,
33395b482a8SLen Brown 				struct acpi_namespace_node *device_node,
33495b482a8SLen Brown 				acpi_integer * address)
33595b482a8SLen Brown {
33695b482a8SLen Brown 	union acpi_operand_object *obj_desc;
33795b482a8SLen Brown 	acpi_status status;
33895b482a8SLen Brown 
33995b482a8SLen Brown 	ACPI_FUNCTION_TRACE(ut_evaluate_numeric_object);
34095b482a8SLen Brown 
34195b482a8SLen Brown 	status = acpi_ut_evaluate_object(device_node, object_name,
34295b482a8SLen Brown 					 ACPI_BTYPE_INTEGER, &obj_desc);
34395b482a8SLen Brown 	if (ACPI_FAILURE(status)) {
34495b482a8SLen Brown 		return_ACPI_STATUS(status);
34595b482a8SLen Brown 	}
34695b482a8SLen Brown 
34795b482a8SLen Brown 	/* Get the returned Integer */
34895b482a8SLen Brown 
34995b482a8SLen Brown 	*address = obj_desc->integer.value;
35095b482a8SLen Brown 
35195b482a8SLen Brown 	/* On exit, we must delete the return object */
35295b482a8SLen Brown 
35395b482a8SLen Brown 	acpi_ut_remove_reference(obj_desc);
35495b482a8SLen Brown 	return_ACPI_STATUS(status);
35595b482a8SLen Brown }
35695b482a8SLen Brown 
35795b482a8SLen Brown /*******************************************************************************
35895b482a8SLen Brown  *
35995b482a8SLen Brown  * FUNCTION:    acpi_ut_copy_id_string
36095b482a8SLen Brown  *
36195b482a8SLen Brown  * PARAMETERS:  Destination         - Where to copy the string
36295b482a8SLen Brown  *              Source              - Source string
36395b482a8SLen Brown  *              max_length          - Length of the destination buffer
36495b482a8SLen Brown  *
36595b482a8SLen Brown  * RETURN:      None
36695b482a8SLen Brown  *
36795b482a8SLen Brown  * DESCRIPTION: Copies an ID string for the _HID, _CID, and _UID methods.
36895b482a8SLen Brown  *              Performs removal of a leading asterisk if present -- workaround
36995b482a8SLen Brown  *              for a known issue on a bunch of machines.
37095b482a8SLen Brown  *
37195b482a8SLen Brown  ******************************************************************************/
37295b482a8SLen Brown 
37395b482a8SLen Brown static void
37495b482a8SLen Brown acpi_ut_copy_id_string(char *destination, char *source, acpi_size max_length)
37595b482a8SLen Brown {
37695b482a8SLen Brown 
37795b482a8SLen Brown 	/*
37895b482a8SLen Brown 	 * Workaround for ID strings that have a leading asterisk. This construct
37995b482a8SLen Brown 	 * is not allowed by the ACPI specification  (ID strings must be
38095b482a8SLen Brown 	 * alphanumeric), but enough existing machines have this embedded in their
38195b482a8SLen Brown 	 * ID strings that the following code is useful.
38295b482a8SLen Brown 	 */
38395b482a8SLen Brown 	if (*source == '*') {
38495b482a8SLen Brown 		source++;
38595b482a8SLen Brown 	}
38695b482a8SLen Brown 
38795b482a8SLen Brown 	/* Do the actual copy */
38895b482a8SLen Brown 
38995b482a8SLen Brown 	ACPI_STRNCPY(destination, source, max_length);
39095b482a8SLen Brown }
39195b482a8SLen Brown 
39295b482a8SLen Brown /*******************************************************************************
39395b482a8SLen Brown  *
39495b482a8SLen Brown  * FUNCTION:    acpi_ut_execute_HID
39595b482a8SLen Brown  *
39695b482a8SLen Brown  * PARAMETERS:  device_node         - Node for the device
39795b482a8SLen Brown  *              Hid                 - Where the HID is returned
39895b482a8SLen Brown  *
39995b482a8SLen Brown  * RETURN:      Status
40095b482a8SLen Brown  *
40195b482a8SLen Brown  * DESCRIPTION: Executes the _HID control method that returns the hardware
40295b482a8SLen Brown  *              ID of the device.
40395b482a8SLen Brown  *
40495b482a8SLen Brown  *              NOTE: Internal function, no parameter validation
40595b482a8SLen Brown  *
40695b482a8SLen Brown  ******************************************************************************/
40795b482a8SLen Brown 
40895b482a8SLen Brown acpi_status
40995b482a8SLen Brown acpi_ut_execute_HID(struct acpi_namespace_node *device_node,
41095b482a8SLen Brown 		    struct acpica_device_id *hid)
41195b482a8SLen Brown {
41295b482a8SLen Brown 	union acpi_operand_object *obj_desc;
41395b482a8SLen Brown 	acpi_status status;
41495b482a8SLen Brown 
41595b482a8SLen Brown 	ACPI_FUNCTION_TRACE(ut_execute_HID);
41695b482a8SLen Brown 
41795b482a8SLen Brown 	status = acpi_ut_evaluate_object(device_node, METHOD_NAME__HID,
41895b482a8SLen Brown 					 ACPI_BTYPE_INTEGER | ACPI_BTYPE_STRING,
41995b482a8SLen Brown 					 &obj_desc);
42095b482a8SLen Brown 	if (ACPI_FAILURE(status)) {
42195b482a8SLen Brown 		return_ACPI_STATUS(status);
42295b482a8SLen Brown 	}
42395b482a8SLen Brown 
42495b482a8SLen Brown 	if (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_INTEGER) {
42595b482a8SLen Brown 
42695b482a8SLen Brown 		/* Convert the Numeric HID to string */
42795b482a8SLen Brown 
42895b482a8SLen Brown 		acpi_ex_eisa_id_to_string((u32) obj_desc->integer.value,
42995b482a8SLen Brown 					  hid->value);
43095b482a8SLen Brown 	} else {
43195b482a8SLen Brown 		/* Copy the String HID from the returned object */
43295b482a8SLen Brown 
43395b482a8SLen Brown 		acpi_ut_copy_id_string(hid->value, obj_desc->string.pointer,
43495b482a8SLen Brown 				       sizeof(hid->value));
43595b482a8SLen Brown 	}
43695b482a8SLen Brown 
43795b482a8SLen Brown 	/* On exit, we must delete the return object */
43895b482a8SLen Brown 
43995b482a8SLen Brown 	acpi_ut_remove_reference(obj_desc);
44095b482a8SLen Brown 	return_ACPI_STATUS(status);
44195b482a8SLen Brown }
44295b482a8SLen Brown 
44395b482a8SLen Brown /*******************************************************************************
44495b482a8SLen Brown  *
44595b482a8SLen Brown  * FUNCTION:    acpi_ut_translate_one_cid
44695b482a8SLen Brown  *
44795b482a8SLen Brown  * PARAMETERS:  obj_desc            - _CID object, must be integer or string
44895b482a8SLen Brown  *              one_cid             - Where the CID string is returned
44995b482a8SLen Brown  *
45095b482a8SLen Brown  * RETURN:      Status
45195b482a8SLen Brown  *
45295b482a8SLen Brown  * DESCRIPTION: Return a numeric or string _CID value as a string.
45395b482a8SLen Brown  *              (Compatible ID)
45495b482a8SLen Brown  *
45595b482a8SLen Brown  *              NOTE:  Assumes a maximum _CID string length of
45695b482a8SLen Brown  *                     ACPI_MAX_CID_LENGTH.
45795b482a8SLen Brown  *
45895b482a8SLen Brown  ******************************************************************************/
45995b482a8SLen Brown 
46095b482a8SLen Brown static acpi_status
46195b482a8SLen Brown acpi_ut_translate_one_cid(union acpi_operand_object *obj_desc,
46295b482a8SLen Brown 			  struct acpi_compatible_id *one_cid)
46395b482a8SLen Brown {
46495b482a8SLen Brown 
46595b482a8SLen Brown 	switch (ACPI_GET_OBJECT_TYPE(obj_desc)) {
46695b482a8SLen Brown 	case ACPI_TYPE_INTEGER:
46795b482a8SLen Brown 
46895b482a8SLen Brown 		/* Convert the Numeric CID to string */
46995b482a8SLen Brown 
47095b482a8SLen Brown 		acpi_ex_eisa_id_to_string((u32) obj_desc->integer.value,
47195b482a8SLen Brown 					  one_cid->value);
47295b482a8SLen Brown 		return (AE_OK);
47395b482a8SLen Brown 
47495b482a8SLen Brown 	case ACPI_TYPE_STRING:
47595b482a8SLen Brown 
47695b482a8SLen Brown 		if (obj_desc->string.length > ACPI_MAX_CID_LENGTH) {
47795b482a8SLen Brown 			return (AE_AML_STRING_LIMIT);
47895b482a8SLen Brown 		}
47995b482a8SLen Brown 
48095b482a8SLen Brown 		/* Copy the String CID from the returned object */
48195b482a8SLen Brown 
48295b482a8SLen Brown 		acpi_ut_copy_id_string(one_cid->value, obj_desc->string.pointer,
48395b482a8SLen Brown 				       ACPI_MAX_CID_LENGTH);
48495b482a8SLen Brown 		return (AE_OK);
48595b482a8SLen Brown 
48695b482a8SLen Brown 	default:
48795b482a8SLen Brown 
48895b482a8SLen Brown 		return (AE_TYPE);
48995b482a8SLen Brown 	}
49095b482a8SLen Brown }
49195b482a8SLen Brown 
49295b482a8SLen Brown /*******************************************************************************
49395b482a8SLen Brown  *
49495b482a8SLen Brown  * FUNCTION:    acpi_ut_execute_CID
49595b482a8SLen Brown  *
49695b482a8SLen Brown  * PARAMETERS:  device_node         - Node for the device
49795b482a8SLen Brown  *              return_cid_list     - Where the CID list is returned
49895b482a8SLen Brown  *
49995b482a8SLen Brown  * RETURN:      Status
50095b482a8SLen Brown  *
50195b482a8SLen Brown  * DESCRIPTION: Executes the _CID control method that returns one or more
50295b482a8SLen Brown  *              compatible hardware IDs for the device.
50395b482a8SLen Brown  *
50495b482a8SLen Brown  *              NOTE: Internal function, no parameter validation
50595b482a8SLen Brown  *
50695b482a8SLen Brown  ******************************************************************************/
50795b482a8SLen Brown 
50895b482a8SLen Brown acpi_status
50995b482a8SLen Brown acpi_ut_execute_CID(struct acpi_namespace_node * device_node,
51095b482a8SLen Brown 		    struct acpi_compatible_id_list ** return_cid_list)
51195b482a8SLen Brown {
51295b482a8SLen Brown 	union acpi_operand_object *obj_desc;
51395b482a8SLen Brown 	acpi_status status;
51495b482a8SLen Brown 	u32 count;
51595b482a8SLen Brown 	u32 size;
51695b482a8SLen Brown 	struct acpi_compatible_id_list *cid_list;
51795b482a8SLen Brown 	u32 i;
51895b482a8SLen Brown 
51995b482a8SLen Brown 	ACPI_FUNCTION_TRACE(ut_execute_CID);
52095b482a8SLen Brown 
52195b482a8SLen Brown 	/* Evaluate the _CID method for this device */
52295b482a8SLen Brown 
52395b482a8SLen Brown 	status = acpi_ut_evaluate_object(device_node, METHOD_NAME__CID,
52495b482a8SLen Brown 					 ACPI_BTYPE_INTEGER | ACPI_BTYPE_STRING
52595b482a8SLen Brown 					 | ACPI_BTYPE_PACKAGE, &obj_desc);
52695b482a8SLen Brown 	if (ACPI_FAILURE(status)) {
52795b482a8SLen Brown 		return_ACPI_STATUS(status);
52895b482a8SLen Brown 	}
52995b482a8SLen Brown 
53095b482a8SLen Brown 	/* Get the number of _CIDs returned */
53195b482a8SLen Brown 
53295b482a8SLen Brown 	count = 1;
53395b482a8SLen Brown 	if (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_PACKAGE) {
53495b482a8SLen Brown 		count = obj_desc->package.count;
53595b482a8SLen Brown 	}
53695b482a8SLen Brown 
53795b482a8SLen Brown 	/* Allocate a worst-case buffer for the _CIDs */
53895b482a8SLen Brown 
53995b482a8SLen Brown 	size = (((count - 1) * sizeof(struct acpi_compatible_id)) +
54095b482a8SLen Brown 		sizeof(struct acpi_compatible_id_list));
54195b482a8SLen Brown 
54295b482a8SLen Brown 	cid_list = ACPI_ALLOCATE_ZEROED((acpi_size) size);
54395b482a8SLen Brown 	if (!cid_list) {
54495b482a8SLen Brown 		return_ACPI_STATUS(AE_NO_MEMORY);
54595b482a8SLen Brown 	}
54695b482a8SLen Brown 
54795b482a8SLen Brown 	/* Init CID list */
54895b482a8SLen Brown 
54995b482a8SLen Brown 	cid_list->count = count;
55095b482a8SLen Brown 	cid_list->size = size;
55195b482a8SLen Brown 
55295b482a8SLen Brown 	/*
55395b482a8SLen Brown 	 *  A _CID can return either a single compatible ID or a package of
55495b482a8SLen Brown 	 *  compatible IDs.  Each compatible ID can be one of the following:
55595b482a8SLen Brown 	 *  1) Integer (32 bit compressed EISA ID) or
55695b482a8SLen Brown 	 *  2) String (PCI ID format, e.g. "PCI\VEN_vvvv&DEV_dddd&SUBSYS_ssssssss")
55795b482a8SLen Brown 	 */
55895b482a8SLen Brown 
55995b482a8SLen Brown 	/* The _CID object can be either a single CID or a package (list) of CIDs */
56095b482a8SLen Brown 
56195b482a8SLen Brown 	if (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_PACKAGE) {
56295b482a8SLen Brown 
56395b482a8SLen Brown 		/* Translate each package element */
56495b482a8SLen Brown 
56595b482a8SLen Brown 		for (i = 0; i < count; i++) {
56695b482a8SLen Brown 			status =
56795b482a8SLen Brown 			    acpi_ut_translate_one_cid(obj_desc->package.
56895b482a8SLen Brown 						      elements[i],
56995b482a8SLen Brown 						      &cid_list->id[i]);
57095b482a8SLen Brown 			if (ACPI_FAILURE(status)) {
57195b482a8SLen Brown 				break;
57295b482a8SLen Brown 			}
57395b482a8SLen Brown 		}
57495b482a8SLen Brown 	} else {
57595b482a8SLen Brown 		/* Only one CID, translate to a string */
57695b482a8SLen Brown 
57795b482a8SLen Brown 		status = acpi_ut_translate_one_cid(obj_desc, cid_list->id);
57895b482a8SLen Brown 	}
57995b482a8SLen Brown 
58095b482a8SLen Brown 	/* Cleanup on error */
58195b482a8SLen Brown 
58295b482a8SLen Brown 	if (ACPI_FAILURE(status)) {
58395b482a8SLen Brown 		ACPI_FREE(cid_list);
58495b482a8SLen Brown 	} else {
58595b482a8SLen Brown 		*return_cid_list = cid_list;
58695b482a8SLen Brown 	}
58795b482a8SLen Brown 
58895b482a8SLen Brown 	/* On exit, we must delete the _CID return object */
58995b482a8SLen Brown 
59095b482a8SLen Brown 	acpi_ut_remove_reference(obj_desc);
59195b482a8SLen Brown 	return_ACPI_STATUS(status);
59295b482a8SLen Brown }
59395b482a8SLen Brown 
59495b482a8SLen Brown /*******************************************************************************
59595b482a8SLen Brown  *
59695b482a8SLen Brown  * FUNCTION:    acpi_ut_execute_UID
59795b482a8SLen Brown  *
59895b482a8SLen Brown  * PARAMETERS:  device_node         - Node for the device
59995b482a8SLen Brown  *              Uid                 - Where the UID is returned
60095b482a8SLen Brown  *
60195b482a8SLen Brown  * RETURN:      Status
60295b482a8SLen Brown  *
60395b482a8SLen Brown  * DESCRIPTION: Executes the _UID control method that returns the hardware
60495b482a8SLen Brown  *              ID of the device.
60595b482a8SLen Brown  *
60695b482a8SLen Brown  *              NOTE: Internal function, no parameter validation
60795b482a8SLen Brown  *
60895b482a8SLen Brown  ******************************************************************************/
60995b482a8SLen Brown 
61095b482a8SLen Brown acpi_status
61195b482a8SLen Brown acpi_ut_execute_UID(struct acpi_namespace_node *device_node,
61295b482a8SLen Brown 		    struct acpica_device_id *uid)
61395b482a8SLen Brown {
61495b482a8SLen Brown 	union acpi_operand_object *obj_desc;
61595b482a8SLen Brown 	acpi_status status;
61695b482a8SLen Brown 
61795b482a8SLen Brown 	ACPI_FUNCTION_TRACE(ut_execute_UID);
61895b482a8SLen Brown 
61995b482a8SLen Brown 	status = acpi_ut_evaluate_object(device_node, METHOD_NAME__UID,
62095b482a8SLen Brown 					 ACPI_BTYPE_INTEGER | ACPI_BTYPE_STRING,
62195b482a8SLen Brown 					 &obj_desc);
62295b482a8SLen Brown 	if (ACPI_FAILURE(status)) {
62395b482a8SLen Brown 		return_ACPI_STATUS(status);
62495b482a8SLen Brown 	}
62595b482a8SLen Brown 
62695b482a8SLen Brown 	if (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_INTEGER) {
62795b482a8SLen Brown 
62895b482a8SLen Brown 		/* Convert the Numeric UID to string */
62995b482a8SLen Brown 
63095b482a8SLen Brown 		acpi_ex_unsigned_integer_to_string(obj_desc->integer.value,
63195b482a8SLen Brown 						   uid->value);
63295b482a8SLen Brown 	} else {
63395b482a8SLen Brown 		/* Copy the String UID from the returned object */
63495b482a8SLen Brown 
63595b482a8SLen Brown 		acpi_ut_copy_id_string(uid->value, obj_desc->string.pointer,
63695b482a8SLen Brown 				       sizeof(uid->value));
63795b482a8SLen Brown 	}
63895b482a8SLen Brown 
63995b482a8SLen Brown 	/* On exit, we must delete the return object */
64095b482a8SLen Brown 
64195b482a8SLen Brown 	acpi_ut_remove_reference(obj_desc);
64295b482a8SLen Brown 	return_ACPI_STATUS(status);
64395b482a8SLen Brown }
64495b482a8SLen Brown 
64595b482a8SLen Brown /*******************************************************************************
64695b482a8SLen Brown  *
64795b482a8SLen Brown  * FUNCTION:    acpi_ut_execute_STA
64895b482a8SLen Brown  *
64995b482a8SLen Brown  * PARAMETERS:  device_node         - Node for the device
65095b482a8SLen Brown  *              Flags               - Where the status flags are returned
65195b482a8SLen Brown  *
65295b482a8SLen Brown  * RETURN:      Status
65395b482a8SLen Brown  *
65495b482a8SLen Brown  * DESCRIPTION: Executes _STA for selected device and stores results in
65595b482a8SLen Brown  *              *Flags.
65695b482a8SLen Brown  *
65795b482a8SLen Brown  *              NOTE: Internal function, no parameter validation
65895b482a8SLen Brown  *
65995b482a8SLen Brown  ******************************************************************************/
66095b482a8SLen Brown 
66195b482a8SLen Brown acpi_status
66295b482a8SLen Brown acpi_ut_execute_STA(struct acpi_namespace_node *device_node, u32 * flags)
66395b482a8SLen Brown {
66495b482a8SLen Brown 	union acpi_operand_object *obj_desc;
66595b482a8SLen Brown 	acpi_status status;
66695b482a8SLen Brown 
66795b482a8SLen Brown 	ACPI_FUNCTION_TRACE(ut_execute_STA);
66895b482a8SLen Brown 
66995b482a8SLen Brown 	status = acpi_ut_evaluate_object(device_node, METHOD_NAME__STA,
67095b482a8SLen Brown 					 ACPI_BTYPE_INTEGER, &obj_desc);
67195b482a8SLen Brown 	if (ACPI_FAILURE(status)) {
67295b482a8SLen Brown 		if (AE_NOT_FOUND == status) {
67395b482a8SLen Brown 			ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
67495b482a8SLen Brown 					  "_STA on %4.4s was not found, assuming device is present\n",
67595b482a8SLen Brown 					  acpi_ut_get_node_name(device_node)));
67695b482a8SLen Brown 
67795b482a8SLen Brown 			*flags = ACPI_UINT32_MAX;
67895b482a8SLen Brown 			status = AE_OK;
67995b482a8SLen Brown 		}
68095b482a8SLen Brown 
68195b482a8SLen Brown 		return_ACPI_STATUS(status);
68295b482a8SLen Brown 	}
68395b482a8SLen Brown 
68495b482a8SLen Brown 	/* Extract the status flags */
68595b482a8SLen Brown 
68695b482a8SLen Brown 	*flags = (u32) obj_desc->integer.value;
68795b482a8SLen Brown 
68895b482a8SLen Brown 	/* On exit, we must delete the return object */
68995b482a8SLen Brown 
69095b482a8SLen Brown 	acpi_ut_remove_reference(obj_desc);
69195b482a8SLen Brown 	return_ACPI_STATUS(status);
69295b482a8SLen Brown }
69395b482a8SLen Brown 
69495b482a8SLen Brown /*******************************************************************************
69595b482a8SLen Brown  *
69695b482a8SLen Brown  * FUNCTION:    acpi_ut_execute_Sxds
69795b482a8SLen Brown  *
69895b482a8SLen Brown  * PARAMETERS:  device_node         - Node for the device
69995b482a8SLen Brown  *              Flags               - Where the status flags are returned
70095b482a8SLen Brown  *
70195b482a8SLen Brown  * RETURN:      Status
70295b482a8SLen Brown  *
70395b482a8SLen Brown  * DESCRIPTION: Executes _STA for selected device and stores results in
70495b482a8SLen Brown  *              *Flags.
70595b482a8SLen Brown  *
70695b482a8SLen Brown  *              NOTE: Internal function, no parameter validation
70795b482a8SLen Brown  *
70895b482a8SLen Brown  ******************************************************************************/
70995b482a8SLen Brown 
71095b482a8SLen Brown acpi_status
71195b482a8SLen Brown acpi_ut_execute_sxds(struct acpi_namespace_node *device_node, u8 * highest)
71295b482a8SLen Brown {
71395b482a8SLen Brown 	union acpi_operand_object *obj_desc;
71495b482a8SLen Brown 	acpi_status status;
71595b482a8SLen Brown 	u32 i;
71695b482a8SLen Brown 
71795b482a8SLen Brown 	ACPI_FUNCTION_TRACE(ut_execute_sxds);
71895b482a8SLen Brown 
71995b482a8SLen Brown 	for (i = 0; i < 4; i++) {
72095b482a8SLen Brown 		highest[i] = 0xFF;
72195b482a8SLen Brown 		status = acpi_ut_evaluate_object(device_node,
72295b482a8SLen Brown 						 ACPI_CAST_PTR(char,
72395b482a8SLen Brown 							       acpi_gbl_highest_dstate_names
72495b482a8SLen Brown 							       [i]),
72595b482a8SLen Brown 						 ACPI_BTYPE_INTEGER, &obj_desc);
72695b482a8SLen Brown 		if (ACPI_FAILURE(status)) {
72795b482a8SLen Brown 			if (status != AE_NOT_FOUND) {
72895b482a8SLen Brown 				ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
72995b482a8SLen Brown 						  "%s on Device %4.4s, %s\n",
73095b482a8SLen Brown 						  ACPI_CAST_PTR(char,
73195b482a8SLen Brown 								acpi_gbl_highest_dstate_names
73295b482a8SLen Brown 								[i]),
73395b482a8SLen Brown 						  acpi_ut_get_node_name
73495b482a8SLen Brown 						  (device_node),
73595b482a8SLen Brown 						  acpi_format_exception
73695b482a8SLen Brown 						  (status)));
73795b482a8SLen Brown 
73895b482a8SLen Brown 				return_ACPI_STATUS(status);
73995b482a8SLen Brown 			}
74095b482a8SLen Brown 		} else {
74195b482a8SLen Brown 			/* Extract the Dstate value */
74295b482a8SLen Brown 
74395b482a8SLen Brown 			highest[i] = (u8) obj_desc->integer.value;
74495b482a8SLen Brown 
74595b482a8SLen Brown 			/* Delete the return object */
74695b482a8SLen Brown 
74795b482a8SLen Brown 			acpi_ut_remove_reference(obj_desc);
74895b482a8SLen Brown 		}
74995b482a8SLen Brown 	}
75095b482a8SLen Brown 
75195b482a8SLen Brown 	return_ACPI_STATUS(AE_OK);
75295b482a8SLen Brown }
753