Linux Audio

Check our new training course

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