• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /netgear-R7000-V1.0.7.12_1.2.5/components/opensource/linux/linux-2.6.36/drivers/acpi/acpica/
1/******************************************************************************
2 *
3 * Module Name: nsrepair - Repair for objects returned by predefined methods
4 *
5 *****************************************************************************/
6
7/*
8 * Copyright (C) 2000 - 2010, Intel Corp.
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 *    notice, this list of conditions, and the following disclaimer,
16 *    without modification.
17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18 *    substantially similar to the "NO WARRANTY" disclaimer below
19 *    ("Disclaimer") and any redistribution must be conditioned upon
20 *    including a substantially similar Disclaimer requirement for further
21 *    binary redistribution.
22 * 3. Neither the names of the above-listed copyright holders nor the names
23 *    of any contributors may be used to endorse or promote products derived
24 *    from this software without specific prior written permission.
25 *
26 * Alternatively, this software may be distributed under the terms of the
27 * GNU General Public License ("GPL") version 2 as published by the Free
28 * Software Foundation.
29 *
30 * NO WARRANTY
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41 * POSSIBILITY OF SUCH DAMAGES.
42 */
43
44#include <acpi/acpi.h>
45#include "accommon.h"
46#include "acnamesp.h"
47#include "acinterp.h"
48#include "acpredef.h"
49
50#define _COMPONENT          ACPI_NAMESPACE
51ACPI_MODULE_NAME("nsrepair")
52
53/*******************************************************************************
54 *
55 * This module attempts to repair or convert objects returned by the
56 * predefined methods to an object type that is expected, as per the ACPI
57 * specification. The need for this code is dictated by the many machines that
58 * return incorrect types for the standard predefined methods. Performing these
59 * conversions here, in one place, eliminates the need for individual ACPI
60 * device drivers to do the same. Note: Most of these conversions are different
61 * than the internal object conversion routines used for implicit object
62 * conversion.
63 *
64 * The following conversions can be performed as necessary:
65 *
66 * Integer -> String
67 * Integer -> Buffer
68 * String  -> Integer
69 * String  -> Buffer
70 * Buffer  -> Integer
71 * Buffer  -> String
72 * Buffer  -> Package of Integers
73 * Package -> Package of one Package
74 *
75 * Additional possible repairs:
76 *
77 * Optional/unnecessary NULL package elements removed
78 * Required package elements that are NULL replaced by Integer/String/Buffer
79 * Incorrect standalone package wrapped with required outer package
80 *
81 ******************************************************************************/
82/* Local prototypes */
83static acpi_status
84acpi_ns_convert_to_integer(union acpi_operand_object *original_object,
85			   union acpi_operand_object **return_object);
86
87static acpi_status
88acpi_ns_convert_to_string(union acpi_operand_object *original_object,
89			  union acpi_operand_object **return_object);
90
91static acpi_status
92acpi_ns_convert_to_buffer(union acpi_operand_object *original_object,
93			  union acpi_operand_object **return_object);
94
95static acpi_status
96acpi_ns_convert_to_package(union acpi_operand_object *original_object,
97			   union acpi_operand_object **return_object);
98
99/*******************************************************************************
100 *
101 * FUNCTION:    acpi_ns_repair_object
102 *
103 * PARAMETERS:  Data                - Pointer to validation data structure
104 *              expected_btypes     - Object types expected
105 *              package_index       - Index of object within parent package (if
106 *                                    applicable - ACPI_NOT_PACKAGE_ELEMENT
107 *                                    otherwise)
108 *              return_object_ptr   - Pointer to the object returned from the
109 *                                    evaluation of a method or object
110 *
111 * RETURN:      Status. AE_OK if repair was successful.
112 *
113 * DESCRIPTION: Attempt to repair/convert a return object of a type that was
114 *              not expected.
115 *
116 ******************************************************************************/
117
118acpi_status
119acpi_ns_repair_object(struct acpi_predefined_data *data,
120		      u32 expected_btypes,
121		      u32 package_index,
122		      union acpi_operand_object **return_object_ptr)
123{
124	union acpi_operand_object *return_object = *return_object_ptr;
125	union acpi_operand_object *new_object;
126	acpi_status status;
127
128	ACPI_FUNCTION_NAME(ns_repair_object);
129
130	/*
131	 * At this point, we know that the type of the returned object was not
132	 * one of the expected types for this predefined name. Attempt to
133	 * repair the object by converting it to one of the expected object
134	 * types for this predefined name.
135	 */
136	if (expected_btypes & ACPI_RTYPE_INTEGER) {
137		status = acpi_ns_convert_to_integer(return_object, &new_object);
138		if (ACPI_SUCCESS(status)) {
139			goto object_repaired;
140		}
141	}
142	if (expected_btypes & ACPI_RTYPE_STRING) {
143		status = acpi_ns_convert_to_string(return_object, &new_object);
144		if (ACPI_SUCCESS(status)) {
145			goto object_repaired;
146		}
147	}
148	if (expected_btypes & ACPI_RTYPE_BUFFER) {
149		status = acpi_ns_convert_to_buffer(return_object, &new_object);
150		if (ACPI_SUCCESS(status)) {
151			goto object_repaired;
152		}
153	}
154	if (expected_btypes & ACPI_RTYPE_PACKAGE) {
155		status = acpi_ns_convert_to_package(return_object, &new_object);
156		if (ACPI_SUCCESS(status)) {
157			goto object_repaired;
158		}
159	}
160
161	/* We cannot repair this object */
162
163	return (AE_AML_OPERAND_TYPE);
164
165      object_repaired:
166
167	/* Object was successfully repaired */
168
169	/*
170	 * If the original object is a package element, we need to:
171	 * 1. Set the reference count of the new object to match the
172	 *    reference count of the old object.
173	 * 2. Decrement the reference count of the original object.
174	 */
175	if (package_index != ACPI_NOT_PACKAGE_ELEMENT) {
176		new_object->common.reference_count =
177		    return_object->common.reference_count;
178
179		if (return_object->common.reference_count > 1) {
180			return_object->common.reference_count--;
181		}
182
183		ACPI_DEBUG_PRINT((ACPI_DB_REPAIR,
184				  "%s: Converted %s to expected %s at index %u\n",
185				  data->pathname,
186				  acpi_ut_get_object_type_name(return_object),
187				  acpi_ut_get_object_type_name(new_object),
188				  package_index));
189	} else {
190		ACPI_DEBUG_PRINT((ACPI_DB_REPAIR,
191				  "%s: Converted %s to expected %s\n",
192				  data->pathname,
193				  acpi_ut_get_object_type_name(return_object),
194				  acpi_ut_get_object_type_name(new_object)));
195	}
196
197	/* Delete old object, install the new return object */
198
199	acpi_ut_remove_reference(return_object);
200	*return_object_ptr = new_object;
201	data->flags |= ACPI_OBJECT_REPAIRED;
202	return (AE_OK);
203}
204
205/*******************************************************************************
206 *
207 * FUNCTION:    acpi_ns_convert_to_integer
208 *
209 * PARAMETERS:  original_object     - Object to be converted
210 *              return_object       - Where the new converted object is returned
211 *
212 * RETURN:      Status. AE_OK if conversion was successful.
213 *
214 * DESCRIPTION: Attempt to convert a String/Buffer object to an Integer.
215 *
216 ******************************************************************************/
217
218static acpi_status
219acpi_ns_convert_to_integer(union acpi_operand_object *original_object,
220			   union acpi_operand_object **return_object)
221{
222	union acpi_operand_object *new_object;
223	acpi_status status;
224	u64 value = 0;
225	u32 i;
226
227	switch (original_object->common.type) {
228	case ACPI_TYPE_STRING:
229
230		/* String-to-Integer conversion */
231
232		status = acpi_ut_strtoul64(original_object->string.pointer,
233					   ACPI_ANY_BASE, &value);
234		if (ACPI_FAILURE(status)) {
235			return (status);
236		}
237		break;
238
239	case ACPI_TYPE_BUFFER:
240
241		/* Buffer-to-Integer conversion. Max buffer size is 64 bits. */
242
243		if (original_object->buffer.length > 8) {
244			return (AE_AML_OPERAND_TYPE);
245		}
246
247		/* Extract each buffer byte to create the integer */
248
249		for (i = 0; i < original_object->buffer.length; i++) {
250			value |=
251			    ((u64) original_object->buffer.
252			     pointer[i] << (i * 8));
253		}
254		break;
255
256	default:
257		return (AE_AML_OPERAND_TYPE);
258	}
259
260	new_object = acpi_ut_create_integer_object(value);
261	if (!new_object) {
262		return (AE_NO_MEMORY);
263	}
264
265	*return_object = new_object;
266	return (AE_OK);
267}
268
269/*******************************************************************************
270 *
271 * FUNCTION:    acpi_ns_convert_to_string
272 *
273 * PARAMETERS:  original_object     - Object to be converted
274 *              return_object       - Where the new converted object is returned
275 *
276 * RETURN:      Status. AE_OK if conversion was successful.
277 *
278 * DESCRIPTION: Attempt to convert a Integer/Buffer object to a String.
279 *
280 ******************************************************************************/
281
282static acpi_status
283acpi_ns_convert_to_string(union acpi_operand_object *original_object,
284			  union acpi_operand_object **return_object)
285{
286	union acpi_operand_object *new_object;
287	acpi_size length;
288	acpi_status status;
289
290	switch (original_object->common.type) {
291	case ACPI_TYPE_INTEGER:
292		/*
293		 * Integer-to-String conversion. Commonly, convert
294		 * an integer of value 0 to a NULL string. The last element of
295		 * _BIF and _BIX packages occasionally need this fix.
296		 */
297		if (original_object->integer.value == 0) {
298
299			/* Allocate a new NULL string object */
300
301			new_object = acpi_ut_create_string_object(0);
302			if (!new_object) {
303				return (AE_NO_MEMORY);
304			}
305		} else {
306			status =
307			    acpi_ex_convert_to_string(original_object,
308						      &new_object,
309						      ACPI_IMPLICIT_CONVERT_HEX);
310			if (ACPI_FAILURE(status)) {
311				return (status);
312			}
313		}
314		break;
315
316	case ACPI_TYPE_BUFFER:
317		/*
318		 * Buffer-to-String conversion. Use a to_string
319		 * conversion, no transform performed on the buffer data. The best
320		 * example of this is the _BIF method, where the string data from
321		 * the battery is often (incorrectly) returned as buffer object(s).
322		 */
323		length = 0;
324		while ((length < original_object->buffer.length) &&
325		       (original_object->buffer.pointer[length])) {
326			length++;
327		}
328
329		/* Allocate a new string object */
330
331		new_object = acpi_ut_create_string_object(length);
332		if (!new_object) {
333			return (AE_NO_MEMORY);
334		}
335
336		/*
337		 * Copy the raw buffer data with no transform. String is already NULL
338		 * terminated at Length+1.
339		 */
340		ACPI_MEMCPY(new_object->string.pointer,
341			    original_object->buffer.pointer, length);
342		break;
343
344	default:
345		return (AE_AML_OPERAND_TYPE);
346	}
347
348	*return_object = new_object;
349	return (AE_OK);
350}
351
352/*******************************************************************************
353 *
354 * FUNCTION:    acpi_ns_convert_to_buffer
355 *
356 * PARAMETERS:  original_object     - Object to be converted
357 *              return_object       - Where the new converted object is returned
358 *
359 * RETURN:      Status. AE_OK if conversion was successful.
360 *
361 * DESCRIPTION: Attempt to convert a Integer/String/Package object to a Buffer.
362 *
363 ******************************************************************************/
364
365static acpi_status
366acpi_ns_convert_to_buffer(union acpi_operand_object *original_object,
367			  union acpi_operand_object **return_object)
368{
369	union acpi_operand_object *new_object;
370	acpi_status status;
371	union acpi_operand_object **elements;
372	u32 *dword_buffer;
373	u32 count;
374	u32 i;
375
376	switch (original_object->common.type) {
377	case ACPI_TYPE_INTEGER:
378		/*
379		 * Integer-to-Buffer conversion.
380		 * Convert the Integer to a packed-byte buffer. _MAT and other
381		 * objects need this sometimes, if a read has been performed on a
382		 * Field object that is less than or equal to the global integer
383		 * size (32 or 64 bits).
384		 */
385		status =
386		    acpi_ex_convert_to_buffer(original_object, &new_object);
387		if (ACPI_FAILURE(status)) {
388			return (status);
389		}
390		break;
391
392	case ACPI_TYPE_STRING:
393
394		/* String-to-Buffer conversion. Simple data copy */
395
396		new_object =
397		    acpi_ut_create_buffer_object(original_object->string.
398						 length);
399		if (!new_object) {
400			return (AE_NO_MEMORY);
401		}
402
403		ACPI_MEMCPY(new_object->buffer.pointer,
404			    original_object->string.pointer,
405			    original_object->string.length);
406		break;
407
408	case ACPI_TYPE_PACKAGE:
409		/*
410		 * This case is often seen for predefined names that must return a
411		 * Buffer object with multiple DWORD integers within. For example,
412		 * _FDE and _GTM. The Package can be converted to a Buffer.
413		 */
414
415		/* All elements of the Package must be integers */
416
417		elements = original_object->package.elements;
418		count = original_object->package.count;
419
420		for (i = 0; i < count; i++) {
421			if ((!*elements) ||
422			    ((*elements)->common.type != ACPI_TYPE_INTEGER)) {
423				return (AE_AML_OPERAND_TYPE);
424			}
425			elements++;
426		}
427
428		/* Create the new buffer object to replace the Package */
429
430		new_object = acpi_ut_create_buffer_object(ACPI_MUL_4(count));
431		if (!new_object) {
432			return (AE_NO_MEMORY);
433		}
434
435		/* Copy the package elements (integers) to the buffer as DWORDs */
436
437		elements = original_object->package.elements;
438		dword_buffer = ACPI_CAST_PTR(u32, new_object->buffer.pointer);
439
440		for (i = 0; i < count; i++) {
441			*dword_buffer = (u32) (*elements)->integer.value;
442			dword_buffer++;
443			elements++;
444		}
445		break;
446
447	default:
448		return (AE_AML_OPERAND_TYPE);
449	}
450
451	*return_object = new_object;
452	return (AE_OK);
453}
454
455/*******************************************************************************
456 *
457 * FUNCTION:    acpi_ns_convert_to_package
458 *
459 * PARAMETERS:  original_object     - Object to be converted
460 *              return_object       - Where the new converted object is returned
461 *
462 * RETURN:      Status. AE_OK if conversion was successful.
463 *
464 * DESCRIPTION: Attempt to convert a Buffer object to a Package. Each byte of
465 *              the buffer is converted to a single integer package element.
466 *
467 ******************************************************************************/
468
469static acpi_status
470acpi_ns_convert_to_package(union acpi_operand_object *original_object,
471			   union acpi_operand_object **return_object)
472{
473	union acpi_operand_object *new_object;
474	union acpi_operand_object **elements;
475	u32 length;
476	u8 *buffer;
477
478	switch (original_object->common.type) {
479	case ACPI_TYPE_BUFFER:
480
481		/* Buffer-to-Package conversion */
482
483		length = original_object->buffer.length;
484		new_object = acpi_ut_create_package_object(length);
485		if (!new_object) {
486			return (AE_NO_MEMORY);
487		}
488
489		/* Convert each buffer byte to an integer package element */
490
491		elements = new_object->package.elements;
492		buffer = original_object->buffer.pointer;
493
494		while (length--) {
495			*elements =
496			    acpi_ut_create_integer_object((u64) *buffer);
497			if (!*elements) {
498				acpi_ut_remove_reference(new_object);
499				return (AE_NO_MEMORY);
500			}
501			elements++;
502			buffer++;
503		}
504		break;
505
506	default:
507		return (AE_AML_OPERAND_TYPE);
508	}
509
510	*return_object = new_object;
511	return (AE_OK);
512}
513
514/*******************************************************************************
515 *
516 * FUNCTION:    acpi_ns_repair_null_element
517 *
518 * PARAMETERS:  Data                - Pointer to validation data structure
519 *              expected_btypes     - Object types expected
520 *              package_index       - Index of object within parent package (if
521 *                                    applicable - ACPI_NOT_PACKAGE_ELEMENT
522 *                                    otherwise)
523 *              return_object_ptr   - Pointer to the object returned from the
524 *                                    evaluation of a method or object
525 *
526 * RETURN:      Status. AE_OK if repair was successful.
527 *
528 * DESCRIPTION: Attempt to repair a NULL element of a returned Package object.
529 *
530 ******************************************************************************/
531
532acpi_status
533acpi_ns_repair_null_element(struct acpi_predefined_data *data,
534			    u32 expected_btypes,
535			    u32 package_index,
536			    union acpi_operand_object **return_object_ptr)
537{
538	union acpi_operand_object *return_object = *return_object_ptr;
539	union acpi_operand_object *new_object;
540
541	ACPI_FUNCTION_NAME(ns_repair_null_element);
542
543	/* No repair needed if return object is non-NULL */
544
545	if (return_object) {
546		return (AE_OK);
547	}
548
549	/*
550	 * Attempt to repair a NULL element of a Package object. This applies to
551	 * predefined names that return a fixed-length package and each element
552	 * is required. It does not apply to variable-length packages where NULL
553	 * elements are allowed, especially at the end of the package.
554	 */
555	if (expected_btypes & ACPI_RTYPE_INTEGER) {
556
557		/* Need an Integer - create a zero-value integer */
558
559		new_object = acpi_ut_create_integer_object((u64)0);
560	} else if (expected_btypes & ACPI_RTYPE_STRING) {
561
562		/* Need a String - create a NULL string */
563
564		new_object = acpi_ut_create_string_object(0);
565	} else if (expected_btypes & ACPI_RTYPE_BUFFER) {
566
567		/* Need a Buffer - create a zero-length buffer */
568
569		new_object = acpi_ut_create_buffer_object(0);
570	} else {
571		/* Error for all other expected types */
572
573		return (AE_AML_OPERAND_TYPE);
574	}
575
576	if (!new_object) {
577		return (AE_NO_MEMORY);
578	}
579
580	/* Set the reference count according to the parent Package object */
581
582	new_object->common.reference_count =
583	    data->parent_package->common.reference_count;
584
585	ACPI_DEBUG_PRINT((ACPI_DB_REPAIR,
586			  "%s: Converted NULL package element to expected %s at index %u\n",
587			  data->pathname,
588			  acpi_ut_get_object_type_name(new_object),
589			  package_index));
590
591	*return_object_ptr = new_object;
592	data->flags |= ACPI_OBJECT_REPAIRED;
593	return (AE_OK);
594}
595
596/******************************************************************************
597 *
598 * FUNCTION:    acpi_ns_remove_null_elements
599 *
600 * PARAMETERS:  Data                - Pointer to validation data structure
601 *              package_type        - An acpi_return_package_types value
602 *              obj_desc            - A Package object
603 *
604 * RETURN:      None.
605 *
606 * DESCRIPTION: Remove all NULL package elements from packages that contain
607 *              a variable number of sub-packages. For these types of
608 *              packages, NULL elements can be safely removed.
609 *
610 *****************************************************************************/
611
612void
613acpi_ns_remove_null_elements(struct acpi_predefined_data *data,
614			     u8 package_type,
615			     union acpi_operand_object *obj_desc)
616{
617	union acpi_operand_object **source;
618	union acpi_operand_object **dest;
619	u32 count;
620	u32 new_count;
621	u32 i;
622
623	ACPI_FUNCTION_NAME(ns_remove_null_elements);
624
625	/*
626	 * PTYPE1 packages contain no subpackages.
627	 * PTYPE2 packages contain a variable number of sub-packages. We can
628	 * safely remove all NULL elements from the PTYPE2 packages.
629	 */
630	switch (package_type) {
631	case ACPI_PTYPE1_FIXED:
632	case ACPI_PTYPE1_VAR:
633	case ACPI_PTYPE1_OPTION:
634		return;
635
636	case ACPI_PTYPE2:
637	case ACPI_PTYPE2_COUNT:
638	case ACPI_PTYPE2_PKG_COUNT:
639	case ACPI_PTYPE2_FIXED:
640	case ACPI_PTYPE2_MIN:
641	case ACPI_PTYPE2_REV_FIXED:
642		break;
643
644	default:
645		return;
646	}
647
648	count = obj_desc->package.count;
649	new_count = count;
650
651	source = obj_desc->package.elements;
652	dest = source;
653
654	/* Examine all elements of the package object, remove nulls */
655
656	for (i = 0; i < count; i++) {
657		if (!*source) {
658			new_count--;
659		} else {
660			*dest = *source;
661			dest++;
662		}
663		source++;
664	}
665
666	/* Update parent package if any null elements were removed */
667
668	if (new_count < count) {
669		ACPI_DEBUG_PRINT((ACPI_DB_REPAIR,
670				  "%s: Found and removed %u NULL elements\n",
671				  data->pathname, (count - new_count)));
672
673		/* NULL terminate list and update the package count */
674
675		*dest = NULL;
676		obj_desc->package.count = new_count;
677	}
678}
679
680/*******************************************************************************
681 *
682 * FUNCTION:    acpi_ns_repair_package_list
683 *
684 * PARAMETERS:  Data                - Pointer to validation data structure
685 *              obj_desc_ptr        - Pointer to the object to repair. The new
686 *                                    package object is returned here,
687 *                                    overwriting the old object.
688 *
689 * RETURN:      Status, new object in *obj_desc_ptr
690 *
691 * DESCRIPTION: Repair a common problem with objects that are defined to return
692 *              a variable-length Package of Packages. If the variable-length
693 *              is one, some BIOS code mistakenly simply declares a single
694 *              Package instead of a Package with one sub-Package. This
695 *              function attempts to repair this error by wrapping a Package
696 *              object around the original Package, creating the correct
697 *              Package with one sub-Package.
698 *
699 *              Names that can be repaired in this manner include:
700 *              _ALR, _CSD, _HPX, _MLS, _PRT, _PSS, _TRT, TSS
701 *
702 ******************************************************************************/
703
704acpi_status
705acpi_ns_repair_package_list(struct acpi_predefined_data *data,
706			    union acpi_operand_object **obj_desc_ptr)
707{
708	union acpi_operand_object *pkg_obj_desc;
709
710	ACPI_FUNCTION_NAME(ns_repair_package_list);
711
712	/*
713	 * Create the new outer package and populate it. The new package will
714	 * have a single element, the lone subpackage.
715	 */
716	pkg_obj_desc = acpi_ut_create_package_object(1);
717	if (!pkg_obj_desc) {
718		return (AE_NO_MEMORY);
719	}
720
721	pkg_obj_desc->package.elements[0] = *obj_desc_ptr;
722
723	/* Return the new object in the object pointer */
724
725	*obj_desc_ptr = pkg_obj_desc;
726	data->flags |= ACPI_OBJECT_REPAIRED;
727
728	ACPI_DEBUG_PRINT((ACPI_DB_REPAIR,
729			  "%s: Repaired incorrectly formed Package\n",
730			  data->pathname));
731
732	return (AE_OK);
733}
734