xref: /openbmc/linux/drivers/acpi/acpica/uteval.c (revision 95b482a8d31116f3f5c2a5089569393234d06385)
1*95b482a8SLen Brown /******************************************************************************
2*95b482a8SLen Brown  *
3*95b482a8SLen Brown  * Module Name: uteval - Object evaluation
4*95b482a8SLen Brown  *
5*95b482a8SLen Brown  *****************************************************************************/
6*95b482a8SLen Brown 
7*95b482a8SLen Brown /*
8*95b482a8SLen Brown  * Copyright (C) 2000 - 2008, Intel Corp.
9*95b482a8SLen Brown  * All rights reserved.
10*95b482a8SLen Brown  *
11*95b482a8SLen Brown  * Redistribution and use in source and binary forms, with or without
12*95b482a8SLen Brown  * modification, are permitted provided that the following conditions
13*95b482a8SLen Brown  * are met:
14*95b482a8SLen Brown  * 1. Redistributions of source code must retain the above copyright
15*95b482a8SLen Brown  *    notice, this list of conditions, and the following disclaimer,
16*95b482a8SLen Brown  *    without modification.
17*95b482a8SLen Brown  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18*95b482a8SLen Brown  *    substantially similar to the "NO WARRANTY" disclaimer below
19*95b482a8SLen Brown  *    ("Disclaimer") and any redistribution must be conditioned upon
20*95b482a8SLen Brown  *    including a substantially similar Disclaimer requirement for further
21*95b482a8SLen Brown  *    binary redistribution.
22*95b482a8SLen Brown  * 3. Neither the names of the above-listed copyright holders nor the names
23*95b482a8SLen Brown  *    of any contributors may be used to endorse or promote products derived
24*95b482a8SLen Brown  *    from this software without specific prior written permission.
25*95b482a8SLen Brown  *
26*95b482a8SLen Brown  * Alternatively, this software may be distributed under the terms of the
27*95b482a8SLen Brown  * GNU General Public License ("GPL") version 2 as published by the Free
28*95b482a8SLen Brown  * Software Foundation.
29*95b482a8SLen Brown  *
30*95b482a8SLen Brown  * NO WARRANTY
31*95b482a8SLen Brown  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32*95b482a8SLen Brown  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33*95b482a8SLen Brown  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34*95b482a8SLen Brown  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35*95b482a8SLen Brown  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36*95b482a8SLen Brown  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37*95b482a8SLen Brown  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38*95b482a8SLen Brown  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39*95b482a8SLen Brown  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40*95b482a8SLen Brown  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41*95b482a8SLen Brown  * POSSIBILITY OF SUCH DAMAGES.
42*95b482a8SLen Brown  */
43*95b482a8SLen Brown 
44*95b482a8SLen Brown #include <acpi/acpi.h>
45*95b482a8SLen Brown #include <acpi/accommon.h>
46*95b482a8SLen Brown #include <acpi/acnamesp.h>
47*95b482a8SLen Brown #include <acpi/acinterp.h>
48*95b482a8SLen Brown 
49*95b482a8SLen Brown #define _COMPONENT          ACPI_UTILITIES
50*95b482a8SLen Brown ACPI_MODULE_NAME("uteval")
51*95b482a8SLen Brown 
52*95b482a8SLen Brown /* Local prototypes */
53*95b482a8SLen Brown static void
54*95b482a8SLen Brown acpi_ut_copy_id_string(char *destination, char *source, acpi_size max_length);
55*95b482a8SLen Brown 
56*95b482a8SLen Brown static acpi_status
57*95b482a8SLen Brown acpi_ut_translate_one_cid(union acpi_operand_object *obj_desc,
58*95b482a8SLen Brown 			  struct acpi_compatible_id *one_cid);
59*95b482a8SLen Brown 
60*95b482a8SLen Brown /*
61*95b482a8SLen Brown  * Strings supported by the _OSI predefined (internal) method.
62*95b482a8SLen Brown  */
63*95b482a8SLen Brown static char *acpi_interfaces_supported[] = {
64*95b482a8SLen Brown 	/* Operating System Vendor Strings */
65*95b482a8SLen Brown 
66*95b482a8SLen Brown 	"Windows 2000",		/* Windows 2000 */
67*95b482a8SLen Brown 	"Windows 2001",		/* Windows XP */
68*95b482a8SLen Brown 	"Windows 2001 SP1",	/* Windows XP SP1 */
69*95b482a8SLen Brown 	"Windows 2001 SP2",	/* Windows XP SP2 */
70*95b482a8SLen Brown 	"Windows 2001.1",	/* Windows Server 2003 */
71*95b482a8SLen Brown 	"Windows 2001.1 SP1",	/* Windows Server 2003 SP1 - Added 03/2006 */
72*95b482a8SLen Brown 	"Windows 2006",		/* Windows Vista - Added 03/2006 */
73*95b482a8SLen Brown 
74*95b482a8SLen Brown 	/* Feature Group Strings */
75*95b482a8SLen Brown 
76*95b482a8SLen Brown 	"Extended Address Space Descriptor"
77*95b482a8SLen Brown 	    /*
78*95b482a8SLen Brown 	     * All "optional" feature group strings (features that are implemented
79*95b482a8SLen Brown 	     * by the host) should be implemented in the host version of
80*95b482a8SLen Brown 	     * acpi_os_validate_interface and should not be added here.
81*95b482a8SLen Brown 	     */
82*95b482a8SLen Brown };
83*95b482a8SLen Brown 
84*95b482a8SLen Brown /*******************************************************************************
85*95b482a8SLen Brown  *
86*95b482a8SLen Brown  * FUNCTION:    acpi_ut_osi_implementation
87*95b482a8SLen Brown  *
88*95b482a8SLen Brown  * PARAMETERS:  walk_state          - Current walk state
89*95b482a8SLen Brown  *
90*95b482a8SLen Brown  * RETURN:      Status
91*95b482a8SLen Brown  *
92*95b482a8SLen Brown  * DESCRIPTION: Implementation of the _OSI predefined control method
93*95b482a8SLen Brown  *
94*95b482a8SLen Brown  ******************************************************************************/
95*95b482a8SLen Brown 
96*95b482a8SLen Brown acpi_status acpi_ut_osi_implementation(struct acpi_walk_state *walk_state)
97*95b482a8SLen Brown {
98*95b482a8SLen Brown 	acpi_status status;
99*95b482a8SLen Brown 	union acpi_operand_object *string_desc;
100*95b482a8SLen Brown 	union acpi_operand_object *return_desc;
101*95b482a8SLen Brown 	u32 i;
102*95b482a8SLen Brown 
103*95b482a8SLen Brown 	ACPI_FUNCTION_TRACE(ut_osi_implementation);
104*95b482a8SLen Brown 
105*95b482a8SLen Brown 	/* Validate the string input argument */
106*95b482a8SLen Brown 
107*95b482a8SLen Brown 	string_desc = walk_state->arguments[0].object;
108*95b482a8SLen Brown 	if (!string_desc || (string_desc->common.type != ACPI_TYPE_STRING)) {
109*95b482a8SLen Brown 		return_ACPI_STATUS(AE_TYPE);
110*95b482a8SLen Brown 	}
111*95b482a8SLen Brown 
112*95b482a8SLen Brown 	/* Create a return object */
113*95b482a8SLen Brown 
114*95b482a8SLen Brown 	return_desc = acpi_ut_create_internal_object(ACPI_TYPE_INTEGER);
115*95b482a8SLen Brown 	if (!return_desc) {
116*95b482a8SLen Brown 		return_ACPI_STATUS(AE_NO_MEMORY);
117*95b482a8SLen Brown 	}
118*95b482a8SLen Brown 
119*95b482a8SLen Brown 	/* Default return value is SUPPORTED */
120*95b482a8SLen Brown 
121*95b482a8SLen Brown 	return_desc->integer.value = ACPI_UINT32_MAX;
122*95b482a8SLen Brown 	walk_state->return_desc = return_desc;
123*95b482a8SLen Brown 
124*95b482a8SLen Brown 	/* Compare input string to static table of supported interfaces */
125*95b482a8SLen Brown 
126*95b482a8SLen Brown 	for (i = 0; i < ACPI_ARRAY_LENGTH(acpi_interfaces_supported); i++) {
127*95b482a8SLen Brown 		if (!ACPI_STRCMP
128*95b482a8SLen Brown 		    (string_desc->string.pointer,
129*95b482a8SLen Brown 		     acpi_interfaces_supported[i])) {
130*95b482a8SLen Brown 
131*95b482a8SLen Brown 			/* The interface is supported */
132*95b482a8SLen Brown 
133*95b482a8SLen Brown 			return_ACPI_STATUS(AE_OK);
134*95b482a8SLen Brown 		}
135*95b482a8SLen Brown 	}
136*95b482a8SLen Brown 
137*95b482a8SLen Brown 	/*
138*95b482a8SLen Brown 	 * Did not match the string in the static table, call the host OSL to
139*95b482a8SLen Brown 	 * check for a match with one of the optional strings (such as
140*95b482a8SLen Brown 	 * "Module Device", "3.0 Thermal Model", etc.)
141*95b482a8SLen Brown 	 */
142*95b482a8SLen Brown 	status = acpi_os_validate_interface(string_desc->string.pointer);
143*95b482a8SLen Brown 	if (ACPI_SUCCESS(status)) {
144*95b482a8SLen Brown 
145*95b482a8SLen Brown 		/* The interface is supported */
146*95b482a8SLen Brown 
147*95b482a8SLen Brown 		return_ACPI_STATUS(AE_OK);
148*95b482a8SLen Brown 	}
149*95b482a8SLen Brown 
150*95b482a8SLen Brown 	/* The interface is not supported */
151*95b482a8SLen Brown 
152*95b482a8SLen Brown 	return_desc->integer.value = 0;
153*95b482a8SLen Brown 	return_ACPI_STATUS(AE_OK);
154*95b482a8SLen Brown }
155*95b482a8SLen Brown 
156*95b482a8SLen Brown /*******************************************************************************
157*95b482a8SLen Brown  *
158*95b482a8SLen Brown  * FUNCTION:    acpi_osi_invalidate
159*95b482a8SLen Brown  *
160*95b482a8SLen Brown  * PARAMETERS:  interface_string
161*95b482a8SLen Brown  *
162*95b482a8SLen Brown  * RETURN:      Status
163*95b482a8SLen Brown  *
164*95b482a8SLen Brown  * DESCRIPTION: invalidate string in pre-defiend _OSI string list
165*95b482a8SLen Brown  *
166*95b482a8SLen Brown  ******************************************************************************/
167*95b482a8SLen Brown 
168*95b482a8SLen Brown acpi_status acpi_osi_invalidate(char *interface)
169*95b482a8SLen Brown {
170*95b482a8SLen Brown 	int i;
171*95b482a8SLen Brown 
172*95b482a8SLen Brown 	for (i = 0; i < ACPI_ARRAY_LENGTH(acpi_interfaces_supported); i++) {
173*95b482a8SLen Brown 		if (!ACPI_STRCMP(interface, acpi_interfaces_supported[i])) {
174*95b482a8SLen Brown 			*acpi_interfaces_supported[i] = '\0';
175*95b482a8SLen Brown 			return AE_OK;
176*95b482a8SLen Brown 		}
177*95b482a8SLen Brown 	}
178*95b482a8SLen Brown 	return AE_NOT_FOUND;
179*95b482a8SLen Brown }
180*95b482a8SLen Brown 
181*95b482a8SLen Brown /*******************************************************************************
182*95b482a8SLen Brown  *
183*95b482a8SLen Brown  * FUNCTION:    acpi_ut_evaluate_object
184*95b482a8SLen Brown  *
185*95b482a8SLen Brown  * PARAMETERS:  prefix_node         - Starting node
186*95b482a8SLen Brown  *              Path                - Path to object from starting node
187*95b482a8SLen Brown  *              expected_return_types - Bitmap of allowed return types
188*95b482a8SLen Brown  *              return_desc         - Where a return value is stored
189*95b482a8SLen Brown  *
190*95b482a8SLen Brown  * RETURN:      Status
191*95b482a8SLen Brown  *
192*95b482a8SLen Brown  * DESCRIPTION: Evaluates a namespace object and verifies the type of the
193*95b482a8SLen Brown  *              return object.  Common code that simplifies accessing objects
194*95b482a8SLen Brown  *              that have required return objects of fixed types.
195*95b482a8SLen Brown  *
196*95b482a8SLen Brown  *              NOTE: Internal function, no parameter validation
197*95b482a8SLen Brown  *
198*95b482a8SLen Brown  ******************************************************************************/
199*95b482a8SLen Brown 
200*95b482a8SLen Brown acpi_status
201*95b482a8SLen Brown acpi_ut_evaluate_object(struct acpi_namespace_node *prefix_node,
202*95b482a8SLen Brown 			char *path,
203*95b482a8SLen Brown 			u32 expected_return_btypes,
204*95b482a8SLen Brown 			union acpi_operand_object **return_desc)
205*95b482a8SLen Brown {
206*95b482a8SLen Brown 	struct acpi_evaluate_info *info;
207*95b482a8SLen Brown 	acpi_status status;
208*95b482a8SLen Brown 	u32 return_btype;
209*95b482a8SLen Brown 
210*95b482a8SLen Brown 	ACPI_FUNCTION_TRACE(ut_evaluate_object);
211*95b482a8SLen Brown 
212*95b482a8SLen Brown 	/* Allocate the evaluation information block */
213*95b482a8SLen Brown 
214*95b482a8SLen Brown 	info = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_evaluate_info));
215*95b482a8SLen Brown 	if (!info) {
216*95b482a8SLen Brown 		return_ACPI_STATUS(AE_NO_MEMORY);
217*95b482a8SLen Brown 	}
218*95b482a8SLen Brown 
219*95b482a8SLen Brown 	info->prefix_node = prefix_node;
220*95b482a8SLen Brown 	info->pathname = path;
221*95b482a8SLen Brown 
222*95b482a8SLen Brown 	/* Evaluate the object/method */
223*95b482a8SLen Brown 
224*95b482a8SLen Brown 	status = acpi_ns_evaluate(info);
225*95b482a8SLen Brown 	if (ACPI_FAILURE(status)) {
226*95b482a8SLen Brown 		if (status == AE_NOT_FOUND) {
227*95b482a8SLen Brown 			ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
228*95b482a8SLen Brown 					  "[%4.4s.%s] was not found\n",
229*95b482a8SLen Brown 					  acpi_ut_get_node_name(prefix_node),
230*95b482a8SLen Brown 					  path));
231*95b482a8SLen Brown 		} else {
232*95b482a8SLen Brown 			ACPI_ERROR_METHOD("Method execution failed",
233*95b482a8SLen Brown 					  prefix_node, path, status);
234*95b482a8SLen Brown 		}
235*95b482a8SLen Brown 
236*95b482a8SLen Brown 		goto cleanup;
237*95b482a8SLen Brown 	}
238*95b482a8SLen Brown 
239*95b482a8SLen Brown 	/* Did we get a return object? */
240*95b482a8SLen Brown 
241*95b482a8SLen Brown 	if (!info->return_object) {
242*95b482a8SLen Brown 		if (expected_return_btypes) {
243*95b482a8SLen Brown 			ACPI_ERROR_METHOD("No object was returned from",
244*95b482a8SLen Brown 					  prefix_node, path, AE_NOT_EXIST);
245*95b482a8SLen Brown 
246*95b482a8SLen Brown 			status = AE_NOT_EXIST;
247*95b482a8SLen Brown 		}
248*95b482a8SLen Brown 
249*95b482a8SLen Brown 		goto cleanup;
250*95b482a8SLen Brown 	}
251*95b482a8SLen Brown 
252*95b482a8SLen Brown 	/* Map the return object type to the bitmapped type */
253*95b482a8SLen Brown 
254*95b482a8SLen Brown 	switch (ACPI_GET_OBJECT_TYPE(info->return_object)) {
255*95b482a8SLen Brown 	case ACPI_TYPE_INTEGER:
256*95b482a8SLen Brown 		return_btype = ACPI_BTYPE_INTEGER;
257*95b482a8SLen Brown 		break;
258*95b482a8SLen Brown 
259*95b482a8SLen Brown 	case ACPI_TYPE_BUFFER:
260*95b482a8SLen Brown 		return_btype = ACPI_BTYPE_BUFFER;
261*95b482a8SLen Brown 		break;
262*95b482a8SLen Brown 
263*95b482a8SLen Brown 	case ACPI_TYPE_STRING:
264*95b482a8SLen Brown 		return_btype = ACPI_BTYPE_STRING;
265*95b482a8SLen Brown 		break;
266*95b482a8SLen Brown 
267*95b482a8SLen Brown 	case ACPI_TYPE_PACKAGE:
268*95b482a8SLen Brown 		return_btype = ACPI_BTYPE_PACKAGE;
269*95b482a8SLen Brown 		break;
270*95b482a8SLen Brown 
271*95b482a8SLen Brown 	default:
272*95b482a8SLen Brown 		return_btype = 0;
273*95b482a8SLen Brown 		break;
274*95b482a8SLen Brown 	}
275*95b482a8SLen Brown 
276*95b482a8SLen Brown 	if ((acpi_gbl_enable_interpreter_slack) && (!expected_return_btypes)) {
277*95b482a8SLen Brown 		/*
278*95b482a8SLen Brown 		 * We received a return object, but one was not expected.  This can
279*95b482a8SLen Brown 		 * happen frequently if the "implicit return" feature is enabled.
280*95b482a8SLen Brown 		 * Just delete the return object and return AE_OK.
281*95b482a8SLen Brown 		 */
282*95b482a8SLen Brown 		acpi_ut_remove_reference(info->return_object);
283*95b482a8SLen Brown 		goto cleanup;
284*95b482a8SLen Brown 	}
285*95b482a8SLen Brown 
286*95b482a8SLen Brown 	/* Is the return object one of the expected types? */
287*95b482a8SLen Brown 
288*95b482a8SLen Brown 	if (!(expected_return_btypes & return_btype)) {
289*95b482a8SLen Brown 		ACPI_ERROR_METHOD("Return object type is incorrect",
290*95b482a8SLen Brown 				  prefix_node, path, AE_TYPE);
291*95b482a8SLen Brown 
292*95b482a8SLen Brown 		ACPI_ERROR((AE_INFO,
293*95b482a8SLen Brown 			    "Type returned from %s was incorrect: %s, expected Btypes: %X",
294*95b482a8SLen Brown 			    path,
295*95b482a8SLen Brown 			    acpi_ut_get_object_type_name(info->return_object),
296*95b482a8SLen Brown 			    expected_return_btypes));
297*95b482a8SLen Brown 
298*95b482a8SLen Brown 		/* On error exit, we must delete the return object */
299*95b482a8SLen Brown 
300*95b482a8SLen Brown 		acpi_ut_remove_reference(info->return_object);
301*95b482a8SLen Brown 		status = AE_TYPE;
302*95b482a8SLen Brown 		goto cleanup;
303*95b482a8SLen Brown 	}
304*95b482a8SLen Brown 
305*95b482a8SLen Brown 	/* Object type is OK, return it */
306*95b482a8SLen Brown 
307*95b482a8SLen Brown 	*return_desc = info->return_object;
308*95b482a8SLen Brown 
309*95b482a8SLen Brown       cleanup:
310*95b482a8SLen Brown 	ACPI_FREE(info);
311*95b482a8SLen Brown 	return_ACPI_STATUS(status);
312*95b482a8SLen Brown }
313*95b482a8SLen Brown 
314*95b482a8SLen Brown /*******************************************************************************
315*95b482a8SLen Brown  *
316*95b482a8SLen Brown  * FUNCTION:    acpi_ut_evaluate_numeric_object
317*95b482a8SLen Brown  *
318*95b482a8SLen Brown  * PARAMETERS:  object_name         - Object name to be evaluated
319*95b482a8SLen Brown  *              device_node         - Node for the device
320*95b482a8SLen Brown  *              Address             - Where the value is returned
321*95b482a8SLen Brown  *
322*95b482a8SLen Brown  * RETURN:      Status
323*95b482a8SLen Brown  *
324*95b482a8SLen Brown  * DESCRIPTION: Evaluates a numeric namespace object for a selected device
325*95b482a8SLen Brown  *              and stores result in *Address.
326*95b482a8SLen Brown  *
327*95b482a8SLen Brown  *              NOTE: Internal function, no parameter validation
328*95b482a8SLen Brown  *
329*95b482a8SLen Brown  ******************************************************************************/
330*95b482a8SLen Brown 
331*95b482a8SLen Brown acpi_status
332*95b482a8SLen Brown acpi_ut_evaluate_numeric_object(char *object_name,
333*95b482a8SLen Brown 				struct acpi_namespace_node *device_node,
334*95b482a8SLen Brown 				acpi_integer * address)
335*95b482a8SLen Brown {
336*95b482a8SLen Brown 	union acpi_operand_object *obj_desc;
337*95b482a8SLen Brown 	acpi_status status;
338*95b482a8SLen Brown 
339*95b482a8SLen Brown 	ACPI_FUNCTION_TRACE(ut_evaluate_numeric_object);
340*95b482a8SLen Brown 
341*95b482a8SLen Brown 	status = acpi_ut_evaluate_object(device_node, object_name,
342*95b482a8SLen Brown 					 ACPI_BTYPE_INTEGER, &obj_desc);
343*95b482a8SLen Brown 	if (ACPI_FAILURE(status)) {
344*95b482a8SLen Brown 		return_ACPI_STATUS(status);
345*95b482a8SLen Brown 	}
346*95b482a8SLen Brown 
347*95b482a8SLen Brown 	/* Get the returned Integer */
348*95b482a8SLen Brown 
349*95b482a8SLen Brown 	*address = obj_desc->integer.value;
350*95b482a8SLen Brown 
351*95b482a8SLen Brown 	/* On exit, we must delete the return object */
352*95b482a8SLen Brown 
353*95b482a8SLen Brown 	acpi_ut_remove_reference(obj_desc);
354*95b482a8SLen Brown 	return_ACPI_STATUS(status);
355*95b482a8SLen Brown }
356*95b482a8SLen Brown 
357*95b482a8SLen Brown /*******************************************************************************
358*95b482a8SLen Brown  *
359*95b482a8SLen Brown  * FUNCTION:    acpi_ut_copy_id_string
360*95b482a8SLen Brown  *
361*95b482a8SLen Brown  * PARAMETERS:  Destination         - Where to copy the string
362*95b482a8SLen Brown  *              Source              - Source string
363*95b482a8SLen Brown  *              max_length          - Length of the destination buffer
364*95b482a8SLen Brown  *
365*95b482a8SLen Brown  * RETURN:      None
366*95b482a8SLen Brown  *
367*95b482a8SLen Brown  * DESCRIPTION: Copies an ID string for the _HID, _CID, and _UID methods.
368*95b482a8SLen Brown  *              Performs removal of a leading asterisk if present -- workaround
369*95b482a8SLen Brown  *              for a known issue on a bunch of machines.
370*95b482a8SLen Brown  *
371*95b482a8SLen Brown  ******************************************************************************/
372*95b482a8SLen Brown 
373*95b482a8SLen Brown static void
374*95b482a8SLen Brown acpi_ut_copy_id_string(char *destination, char *source, acpi_size max_length)
375*95b482a8SLen Brown {
376*95b482a8SLen Brown 
377*95b482a8SLen Brown 	/*
378*95b482a8SLen Brown 	 * Workaround for ID strings that have a leading asterisk. This construct
379*95b482a8SLen Brown 	 * is not allowed by the ACPI specification  (ID strings must be
380*95b482a8SLen Brown 	 * alphanumeric), but enough existing machines have this embedded in their
381*95b482a8SLen Brown 	 * ID strings that the following code is useful.
382*95b482a8SLen Brown 	 */
383*95b482a8SLen Brown 	if (*source == '*') {
384*95b482a8SLen Brown 		source++;
385*95b482a8SLen Brown 	}
386*95b482a8SLen Brown 
387*95b482a8SLen Brown 	/* Do the actual copy */
388*95b482a8SLen Brown 
389*95b482a8SLen Brown 	ACPI_STRNCPY(destination, source, max_length);
390*95b482a8SLen Brown }
391*95b482a8SLen Brown 
392*95b482a8SLen Brown /*******************************************************************************
393*95b482a8SLen Brown  *
394*95b482a8SLen Brown  * FUNCTION:    acpi_ut_execute_HID
395*95b482a8SLen Brown  *
396*95b482a8SLen Brown  * PARAMETERS:  device_node         - Node for the device
397*95b482a8SLen Brown  *              Hid                 - Where the HID is returned
398*95b482a8SLen Brown  *
399*95b482a8SLen Brown  * RETURN:      Status
400*95b482a8SLen Brown  *
401*95b482a8SLen Brown  * DESCRIPTION: Executes the _HID control method that returns the hardware
402*95b482a8SLen Brown  *              ID of the device.
403*95b482a8SLen Brown  *
404*95b482a8SLen Brown  *              NOTE: Internal function, no parameter validation
405*95b482a8SLen Brown  *
406*95b482a8SLen Brown  ******************************************************************************/
407*95b482a8SLen Brown 
408*95b482a8SLen Brown acpi_status
409*95b482a8SLen Brown acpi_ut_execute_HID(struct acpi_namespace_node *device_node,
410*95b482a8SLen Brown 		    struct acpica_device_id *hid)
411*95b482a8SLen Brown {
412*95b482a8SLen Brown 	union acpi_operand_object *obj_desc;
413*95b482a8SLen Brown 	acpi_status status;
414*95b482a8SLen Brown 
415*95b482a8SLen Brown 	ACPI_FUNCTION_TRACE(ut_execute_HID);
416*95b482a8SLen Brown 
417*95b482a8SLen Brown 	status = acpi_ut_evaluate_object(device_node, METHOD_NAME__HID,
418*95b482a8SLen Brown 					 ACPI_BTYPE_INTEGER | ACPI_BTYPE_STRING,
419*95b482a8SLen Brown 					 &obj_desc);
420*95b482a8SLen Brown 	if (ACPI_FAILURE(status)) {
421*95b482a8SLen Brown 		return_ACPI_STATUS(status);
422*95b482a8SLen Brown 	}
423*95b482a8SLen Brown 
424*95b482a8SLen Brown 	if (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_INTEGER) {
425*95b482a8SLen Brown 
426*95b482a8SLen Brown 		/* Convert the Numeric HID to string */
427*95b482a8SLen Brown 
428*95b482a8SLen Brown 		acpi_ex_eisa_id_to_string((u32) obj_desc->integer.value,
429*95b482a8SLen Brown 					  hid->value);
430*95b482a8SLen Brown 	} else {
431*95b482a8SLen Brown 		/* Copy the String HID from the returned object */
432*95b482a8SLen Brown 
433*95b482a8SLen Brown 		acpi_ut_copy_id_string(hid->value, obj_desc->string.pointer,
434*95b482a8SLen Brown 				       sizeof(hid->value));
435*95b482a8SLen Brown 	}
436*95b482a8SLen Brown 
437*95b482a8SLen Brown 	/* On exit, we must delete the return object */
438*95b482a8SLen Brown 
439*95b482a8SLen Brown 	acpi_ut_remove_reference(obj_desc);
440*95b482a8SLen Brown 	return_ACPI_STATUS(status);
441*95b482a8SLen Brown }
442*95b482a8SLen Brown 
443*95b482a8SLen Brown /*******************************************************************************
444*95b482a8SLen Brown  *
445*95b482a8SLen Brown  * FUNCTION:    acpi_ut_translate_one_cid
446*95b482a8SLen Brown  *
447*95b482a8SLen Brown  * PARAMETERS:  obj_desc            - _CID object, must be integer or string
448*95b482a8SLen Brown  *              one_cid             - Where the CID string is returned
449*95b482a8SLen Brown  *
450*95b482a8SLen Brown  * RETURN:      Status
451*95b482a8SLen Brown  *
452*95b482a8SLen Brown  * DESCRIPTION: Return a numeric or string _CID value as a string.
453*95b482a8SLen Brown  *              (Compatible ID)
454*95b482a8SLen Brown  *
455*95b482a8SLen Brown  *              NOTE:  Assumes a maximum _CID string length of
456*95b482a8SLen Brown  *                     ACPI_MAX_CID_LENGTH.
457*95b482a8SLen Brown  *
458*95b482a8SLen Brown  ******************************************************************************/
459*95b482a8SLen Brown 
460*95b482a8SLen Brown static acpi_status
461*95b482a8SLen Brown acpi_ut_translate_one_cid(union acpi_operand_object *obj_desc,
462*95b482a8SLen Brown 			  struct acpi_compatible_id *one_cid)
463*95b482a8SLen Brown {
464*95b482a8SLen Brown 
465*95b482a8SLen Brown 	switch (ACPI_GET_OBJECT_TYPE(obj_desc)) {
466*95b482a8SLen Brown 	case ACPI_TYPE_INTEGER:
467*95b482a8SLen Brown 
468*95b482a8SLen Brown 		/* Convert the Numeric CID to string */
469*95b482a8SLen Brown 
470*95b482a8SLen Brown 		acpi_ex_eisa_id_to_string((u32) obj_desc->integer.value,
471*95b482a8SLen Brown 					  one_cid->value);
472*95b482a8SLen Brown 		return (AE_OK);
473*95b482a8SLen Brown 
474*95b482a8SLen Brown 	case ACPI_TYPE_STRING:
475*95b482a8SLen Brown 
476*95b482a8SLen Brown 		if (obj_desc->string.length > ACPI_MAX_CID_LENGTH) {
477*95b482a8SLen Brown 			return (AE_AML_STRING_LIMIT);
478*95b482a8SLen Brown 		}
479*95b482a8SLen Brown 
480*95b482a8SLen Brown 		/* Copy the String CID from the returned object */
481*95b482a8SLen Brown 
482*95b482a8SLen Brown 		acpi_ut_copy_id_string(one_cid->value, obj_desc->string.pointer,
483*95b482a8SLen Brown 				       ACPI_MAX_CID_LENGTH);
484*95b482a8SLen Brown 		return (AE_OK);
485*95b482a8SLen Brown 
486*95b482a8SLen Brown 	default:
487*95b482a8SLen Brown 
488*95b482a8SLen Brown 		return (AE_TYPE);
489*95b482a8SLen Brown 	}
490*95b482a8SLen Brown }
491*95b482a8SLen Brown 
492*95b482a8SLen Brown /*******************************************************************************
493*95b482a8SLen Brown  *
494*95b482a8SLen Brown  * FUNCTION:    acpi_ut_execute_CID
495*95b482a8SLen Brown  *
496*95b482a8SLen Brown  * PARAMETERS:  device_node         - Node for the device
497*95b482a8SLen Brown  *              return_cid_list     - Where the CID list is returned
498*95b482a8SLen Brown  *
499*95b482a8SLen Brown  * RETURN:      Status
500*95b482a8SLen Brown  *
501*95b482a8SLen Brown  * DESCRIPTION: Executes the _CID control method that returns one or more
502*95b482a8SLen Brown  *              compatible hardware IDs for the device.
503*95b482a8SLen Brown  *
504*95b482a8SLen Brown  *              NOTE: Internal function, no parameter validation
505*95b482a8SLen Brown  *
506*95b482a8SLen Brown  ******************************************************************************/
507*95b482a8SLen Brown 
508*95b482a8SLen Brown acpi_status
509*95b482a8SLen Brown acpi_ut_execute_CID(struct acpi_namespace_node * device_node,
510*95b482a8SLen Brown 		    struct acpi_compatible_id_list ** return_cid_list)
511*95b482a8SLen Brown {
512*95b482a8SLen Brown 	union acpi_operand_object *obj_desc;
513*95b482a8SLen Brown 	acpi_status status;
514*95b482a8SLen Brown 	u32 count;
515*95b482a8SLen Brown 	u32 size;
516*95b482a8SLen Brown 	struct acpi_compatible_id_list *cid_list;
517*95b482a8SLen Brown 	u32 i;
518*95b482a8SLen Brown 
519*95b482a8SLen Brown 	ACPI_FUNCTION_TRACE(ut_execute_CID);
520*95b482a8SLen Brown 
521*95b482a8SLen Brown 	/* Evaluate the _CID method for this device */
522*95b482a8SLen Brown 
523*95b482a8SLen Brown 	status = acpi_ut_evaluate_object(device_node, METHOD_NAME__CID,
524*95b482a8SLen Brown 					 ACPI_BTYPE_INTEGER | ACPI_BTYPE_STRING
525*95b482a8SLen Brown 					 | ACPI_BTYPE_PACKAGE, &obj_desc);
526*95b482a8SLen Brown 	if (ACPI_FAILURE(status)) {
527*95b482a8SLen Brown 		return_ACPI_STATUS(status);
528*95b482a8SLen Brown 	}
529*95b482a8SLen Brown 
530*95b482a8SLen Brown 	/* Get the number of _CIDs returned */
531*95b482a8SLen Brown 
532*95b482a8SLen Brown 	count = 1;
533*95b482a8SLen Brown 	if (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_PACKAGE) {
534*95b482a8SLen Brown 		count = obj_desc->package.count;
535*95b482a8SLen Brown 	}
536*95b482a8SLen Brown 
537*95b482a8SLen Brown 	/* Allocate a worst-case buffer for the _CIDs */
538*95b482a8SLen Brown 
539*95b482a8SLen Brown 	size = (((count - 1) * sizeof(struct acpi_compatible_id)) +
540*95b482a8SLen Brown 		sizeof(struct acpi_compatible_id_list));
541*95b482a8SLen Brown 
542*95b482a8SLen Brown 	cid_list = ACPI_ALLOCATE_ZEROED((acpi_size) size);
543*95b482a8SLen Brown 	if (!cid_list) {
544*95b482a8SLen Brown 		return_ACPI_STATUS(AE_NO_MEMORY);
545*95b482a8SLen Brown 	}
546*95b482a8SLen Brown 
547*95b482a8SLen Brown 	/* Init CID list */
548*95b482a8SLen Brown 
549*95b482a8SLen Brown 	cid_list->count = count;
550*95b482a8SLen Brown 	cid_list->size = size;
551*95b482a8SLen Brown 
552*95b482a8SLen Brown 	/*
553*95b482a8SLen Brown 	 *  A _CID can return either a single compatible ID or a package of
554*95b482a8SLen Brown 	 *  compatible IDs.  Each compatible ID can be one of the following:
555*95b482a8SLen Brown 	 *  1) Integer (32 bit compressed EISA ID) or
556*95b482a8SLen Brown 	 *  2) String (PCI ID format, e.g. "PCI\VEN_vvvv&DEV_dddd&SUBSYS_ssssssss")
557*95b482a8SLen Brown 	 */
558*95b482a8SLen Brown 
559*95b482a8SLen Brown 	/* The _CID object can be either a single CID or a package (list) of CIDs */
560*95b482a8SLen Brown 
561*95b482a8SLen Brown 	if (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_PACKAGE) {
562*95b482a8SLen Brown 
563*95b482a8SLen Brown 		/* Translate each package element */
564*95b482a8SLen Brown 
565*95b482a8SLen Brown 		for (i = 0; i < count; i++) {
566*95b482a8SLen Brown 			status =
567*95b482a8SLen Brown 			    acpi_ut_translate_one_cid(obj_desc->package.
568*95b482a8SLen Brown 						      elements[i],
569*95b482a8SLen Brown 						      &cid_list->id[i]);
570*95b482a8SLen Brown 			if (ACPI_FAILURE(status)) {
571*95b482a8SLen Brown 				break;
572*95b482a8SLen Brown 			}
573*95b482a8SLen Brown 		}
574*95b482a8SLen Brown 	} else {
575*95b482a8SLen Brown 		/* Only one CID, translate to a string */
576*95b482a8SLen Brown 
577*95b482a8SLen Brown 		status = acpi_ut_translate_one_cid(obj_desc, cid_list->id);
578*95b482a8SLen Brown 	}
579*95b482a8SLen Brown 
580*95b482a8SLen Brown 	/* Cleanup on error */
581*95b482a8SLen Brown 
582*95b482a8SLen Brown 	if (ACPI_FAILURE(status)) {
583*95b482a8SLen Brown 		ACPI_FREE(cid_list);
584*95b482a8SLen Brown 	} else {
585*95b482a8SLen Brown 		*return_cid_list = cid_list;
586*95b482a8SLen Brown 	}
587*95b482a8SLen Brown 
588*95b482a8SLen Brown 	/* On exit, we must delete the _CID return object */
589*95b482a8SLen Brown 
590*95b482a8SLen Brown 	acpi_ut_remove_reference(obj_desc);
591*95b482a8SLen Brown 	return_ACPI_STATUS(status);
592*95b482a8SLen Brown }
593*95b482a8SLen Brown 
594*95b482a8SLen Brown /*******************************************************************************
595*95b482a8SLen Brown  *
596*95b482a8SLen Brown  * FUNCTION:    acpi_ut_execute_UID
597*95b482a8SLen Brown  *
598*95b482a8SLen Brown  * PARAMETERS:  device_node         - Node for the device
599*95b482a8SLen Brown  *              Uid                 - Where the UID is returned
600*95b482a8SLen Brown  *
601*95b482a8SLen Brown  * RETURN:      Status
602*95b482a8SLen Brown  *
603*95b482a8SLen Brown  * DESCRIPTION: Executes the _UID control method that returns the hardware
604*95b482a8SLen Brown  *              ID of the device.
605*95b482a8SLen Brown  *
606*95b482a8SLen Brown  *              NOTE: Internal function, no parameter validation
607*95b482a8SLen Brown  *
608*95b482a8SLen Brown  ******************************************************************************/
609*95b482a8SLen Brown 
610*95b482a8SLen Brown acpi_status
611*95b482a8SLen Brown acpi_ut_execute_UID(struct acpi_namespace_node *device_node,
612*95b482a8SLen Brown 		    struct acpica_device_id *uid)
613*95b482a8SLen Brown {
614*95b482a8SLen Brown 	union acpi_operand_object *obj_desc;
615*95b482a8SLen Brown 	acpi_status status;
616*95b482a8SLen Brown 
617*95b482a8SLen Brown 	ACPI_FUNCTION_TRACE(ut_execute_UID);
618*95b482a8SLen Brown 
619*95b482a8SLen Brown 	status = acpi_ut_evaluate_object(device_node, METHOD_NAME__UID,
620*95b482a8SLen Brown 					 ACPI_BTYPE_INTEGER | ACPI_BTYPE_STRING,
621*95b482a8SLen Brown 					 &obj_desc);
622*95b482a8SLen Brown 	if (ACPI_FAILURE(status)) {
623*95b482a8SLen Brown 		return_ACPI_STATUS(status);
624*95b482a8SLen Brown 	}
625*95b482a8SLen Brown 
626*95b482a8SLen Brown 	if (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_INTEGER) {
627*95b482a8SLen Brown 
628*95b482a8SLen Brown 		/* Convert the Numeric UID to string */
629*95b482a8SLen Brown 
630*95b482a8SLen Brown 		acpi_ex_unsigned_integer_to_string(obj_desc->integer.value,
631*95b482a8SLen Brown 						   uid->value);
632*95b482a8SLen Brown 	} else {
633*95b482a8SLen Brown 		/* Copy the String UID from the returned object */
634*95b482a8SLen Brown 
635*95b482a8SLen Brown 		acpi_ut_copy_id_string(uid->value, obj_desc->string.pointer,
636*95b482a8SLen Brown 				       sizeof(uid->value));
637*95b482a8SLen Brown 	}
638*95b482a8SLen Brown 
639*95b482a8SLen Brown 	/* On exit, we must delete the return object */
640*95b482a8SLen Brown 
641*95b482a8SLen Brown 	acpi_ut_remove_reference(obj_desc);
642*95b482a8SLen Brown 	return_ACPI_STATUS(status);
643*95b482a8SLen Brown }
644*95b482a8SLen Brown 
645*95b482a8SLen Brown /*******************************************************************************
646*95b482a8SLen Brown  *
647*95b482a8SLen Brown  * FUNCTION:    acpi_ut_execute_STA
648*95b482a8SLen Brown  *
649*95b482a8SLen Brown  * PARAMETERS:  device_node         - Node for the device
650*95b482a8SLen Brown  *              Flags               - Where the status flags are returned
651*95b482a8SLen Brown  *
652*95b482a8SLen Brown  * RETURN:      Status
653*95b482a8SLen Brown  *
654*95b482a8SLen Brown  * DESCRIPTION: Executes _STA for selected device and stores results in
655*95b482a8SLen Brown  *              *Flags.
656*95b482a8SLen Brown  *
657*95b482a8SLen Brown  *              NOTE: Internal function, no parameter validation
658*95b482a8SLen Brown  *
659*95b482a8SLen Brown  ******************************************************************************/
660*95b482a8SLen Brown 
661*95b482a8SLen Brown acpi_status
662*95b482a8SLen Brown acpi_ut_execute_STA(struct acpi_namespace_node *device_node, u32 * flags)
663*95b482a8SLen Brown {
664*95b482a8SLen Brown 	union acpi_operand_object *obj_desc;
665*95b482a8SLen Brown 	acpi_status status;
666*95b482a8SLen Brown 
667*95b482a8SLen Brown 	ACPI_FUNCTION_TRACE(ut_execute_STA);
668*95b482a8SLen Brown 
669*95b482a8SLen Brown 	status = acpi_ut_evaluate_object(device_node, METHOD_NAME__STA,
670*95b482a8SLen Brown 					 ACPI_BTYPE_INTEGER, &obj_desc);
671*95b482a8SLen Brown 	if (ACPI_FAILURE(status)) {
672*95b482a8SLen Brown 		if (AE_NOT_FOUND == status) {
673*95b482a8SLen Brown 			ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
674*95b482a8SLen Brown 					  "_STA on %4.4s was not found, assuming device is present\n",
675*95b482a8SLen Brown 					  acpi_ut_get_node_name(device_node)));
676*95b482a8SLen Brown 
677*95b482a8SLen Brown 			*flags = ACPI_UINT32_MAX;
678*95b482a8SLen Brown 			status = AE_OK;
679*95b482a8SLen Brown 		}
680*95b482a8SLen Brown 
681*95b482a8SLen Brown 		return_ACPI_STATUS(status);
682*95b482a8SLen Brown 	}
683*95b482a8SLen Brown 
684*95b482a8SLen Brown 	/* Extract the status flags */
685*95b482a8SLen Brown 
686*95b482a8SLen Brown 	*flags = (u32) obj_desc->integer.value;
687*95b482a8SLen Brown 
688*95b482a8SLen Brown 	/* On exit, we must delete the return object */
689*95b482a8SLen Brown 
690*95b482a8SLen Brown 	acpi_ut_remove_reference(obj_desc);
691*95b482a8SLen Brown 	return_ACPI_STATUS(status);
692*95b482a8SLen Brown }
693*95b482a8SLen Brown 
694*95b482a8SLen Brown /*******************************************************************************
695*95b482a8SLen Brown  *
696*95b482a8SLen Brown  * FUNCTION:    acpi_ut_execute_Sxds
697*95b482a8SLen Brown  *
698*95b482a8SLen Brown  * PARAMETERS:  device_node         - Node for the device
699*95b482a8SLen Brown  *              Flags               - Where the status flags are returned
700*95b482a8SLen Brown  *
701*95b482a8SLen Brown  * RETURN:      Status
702*95b482a8SLen Brown  *
703*95b482a8SLen Brown  * DESCRIPTION: Executes _STA for selected device and stores results in
704*95b482a8SLen Brown  *              *Flags.
705*95b482a8SLen Brown  *
706*95b482a8SLen Brown  *              NOTE: Internal function, no parameter validation
707*95b482a8SLen Brown  *
708*95b482a8SLen Brown  ******************************************************************************/
709*95b482a8SLen Brown 
710*95b482a8SLen Brown acpi_status
711*95b482a8SLen Brown acpi_ut_execute_sxds(struct acpi_namespace_node *device_node, u8 * highest)
712*95b482a8SLen Brown {
713*95b482a8SLen Brown 	union acpi_operand_object *obj_desc;
714*95b482a8SLen Brown 	acpi_status status;
715*95b482a8SLen Brown 	u32 i;
716*95b482a8SLen Brown 
717*95b482a8SLen Brown 	ACPI_FUNCTION_TRACE(ut_execute_sxds);
718*95b482a8SLen Brown 
719*95b482a8SLen Brown 	for (i = 0; i < 4; i++) {
720*95b482a8SLen Brown 		highest[i] = 0xFF;
721*95b482a8SLen Brown 		status = acpi_ut_evaluate_object(device_node,
722*95b482a8SLen Brown 						 ACPI_CAST_PTR(char,
723*95b482a8SLen Brown 							       acpi_gbl_highest_dstate_names
724*95b482a8SLen Brown 							       [i]),
725*95b482a8SLen Brown 						 ACPI_BTYPE_INTEGER, &obj_desc);
726*95b482a8SLen Brown 		if (ACPI_FAILURE(status)) {
727*95b482a8SLen Brown 			if (status != AE_NOT_FOUND) {
728*95b482a8SLen Brown 				ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
729*95b482a8SLen Brown 						  "%s on Device %4.4s, %s\n",
730*95b482a8SLen Brown 						  ACPI_CAST_PTR(char,
731*95b482a8SLen Brown 								acpi_gbl_highest_dstate_names
732*95b482a8SLen Brown 								[i]),
733*95b482a8SLen Brown 						  acpi_ut_get_node_name
734*95b482a8SLen Brown 						  (device_node),
735*95b482a8SLen Brown 						  acpi_format_exception
736*95b482a8SLen Brown 						  (status)));
737*95b482a8SLen Brown 
738*95b482a8SLen Brown 				return_ACPI_STATUS(status);
739*95b482a8SLen Brown 			}
740*95b482a8SLen Brown 		} else {
741*95b482a8SLen Brown 			/* Extract the Dstate value */
742*95b482a8SLen Brown 
743*95b482a8SLen Brown 			highest[i] = (u8) obj_desc->integer.value;
744*95b482a8SLen Brown 
745*95b482a8SLen Brown 			/* Delete the return object */
746*95b482a8SLen Brown 
747*95b482a8SLen Brown 			acpi_ut_remove_reference(obj_desc);
748*95b482a8SLen Brown 		}
749*95b482a8SLen Brown 	}
750*95b482a8SLen Brown 
751*95b482a8SLen Brown 	return_ACPI_STATUS(AE_OK);
752*95b482a8SLen Brown }
753