1*4882a593Smuzhiyun // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
2*4882a593Smuzhiyun /******************************************************************************
3*4882a593Smuzhiyun *
4*4882a593Smuzhiyun * Module Name: nsrepair - Repair for objects returned by predefined methods
5*4882a593Smuzhiyun *
6*4882a593Smuzhiyun * Copyright (C) 2000 - 2020, Intel Corp.
7*4882a593Smuzhiyun *
8*4882a593Smuzhiyun *****************************************************************************/
9*4882a593Smuzhiyun
10*4882a593Smuzhiyun #include <acpi/acpi.h>
11*4882a593Smuzhiyun #include "accommon.h"
12*4882a593Smuzhiyun #include "acnamesp.h"
13*4882a593Smuzhiyun #include "acinterp.h"
14*4882a593Smuzhiyun #include "acpredef.h"
15*4882a593Smuzhiyun #include "amlresrc.h"
16*4882a593Smuzhiyun
17*4882a593Smuzhiyun #define _COMPONENT ACPI_NAMESPACE
18*4882a593Smuzhiyun ACPI_MODULE_NAME("nsrepair")
19*4882a593Smuzhiyun
20*4882a593Smuzhiyun /*******************************************************************************
21*4882a593Smuzhiyun *
22*4882a593Smuzhiyun * This module attempts to repair or convert objects returned by the
23*4882a593Smuzhiyun * predefined methods to an object type that is expected, as per the ACPI
24*4882a593Smuzhiyun * specification. The need for this code is dictated by the many machines that
25*4882a593Smuzhiyun * return incorrect types for the standard predefined methods. Performing these
26*4882a593Smuzhiyun * conversions here, in one place, eliminates the need for individual ACPI
27*4882a593Smuzhiyun * device drivers to do the same. Note: Most of these conversions are different
28*4882a593Smuzhiyun * than the internal object conversion routines used for implicit object
29*4882a593Smuzhiyun * conversion.
30*4882a593Smuzhiyun *
31*4882a593Smuzhiyun * The following conversions can be performed as necessary:
32*4882a593Smuzhiyun *
33*4882a593Smuzhiyun * Integer -> String
34*4882a593Smuzhiyun * Integer -> Buffer
35*4882a593Smuzhiyun * String -> Integer
36*4882a593Smuzhiyun * String -> Buffer
37*4882a593Smuzhiyun * Buffer -> Integer
38*4882a593Smuzhiyun * Buffer -> String
39*4882a593Smuzhiyun * Buffer -> Package of Integers
40*4882a593Smuzhiyun * Package -> Package of one Package
41*4882a593Smuzhiyun *
42*4882a593Smuzhiyun * Additional conversions that are available:
43*4882a593Smuzhiyun * Convert a null return or zero return value to an end_tag descriptor
44*4882a593Smuzhiyun * Convert an ASCII string to a Unicode buffer
45*4882a593Smuzhiyun *
46*4882a593Smuzhiyun * An incorrect standalone object is wrapped with required outer package
47*4882a593Smuzhiyun *
48*4882a593Smuzhiyun * Additional possible repairs:
49*4882a593Smuzhiyun * Required package elements that are NULL replaced by Integer/String/Buffer
50*4882a593Smuzhiyun *
51*4882a593Smuzhiyun ******************************************************************************/
52*4882a593Smuzhiyun /* Local prototypes */
53*4882a593Smuzhiyun static const struct acpi_simple_repair_info *acpi_ns_match_simple_repair(struct
54*4882a593Smuzhiyun acpi_namespace_node
55*4882a593Smuzhiyun *node,
56*4882a593Smuzhiyun u32
57*4882a593Smuzhiyun return_btype,
58*4882a593Smuzhiyun u32
59*4882a593Smuzhiyun package_index);
60*4882a593Smuzhiyun
61*4882a593Smuzhiyun /*
62*4882a593Smuzhiyun * Special but simple repairs for some names.
63*4882a593Smuzhiyun *
64*4882a593Smuzhiyun * 2nd argument: Unexpected types that can be repaired
65*4882a593Smuzhiyun */
66*4882a593Smuzhiyun static const struct acpi_simple_repair_info acpi_object_repair_info[] = {
67*4882a593Smuzhiyun /* Resource descriptor conversions */
68*4882a593Smuzhiyun
69*4882a593Smuzhiyun {"_CRS",
70*4882a593Smuzhiyun ACPI_RTYPE_INTEGER | ACPI_RTYPE_STRING | ACPI_RTYPE_BUFFER |
71*4882a593Smuzhiyun ACPI_RTYPE_NONE,
72*4882a593Smuzhiyun ACPI_NOT_PACKAGE_ELEMENT,
73*4882a593Smuzhiyun acpi_ns_convert_to_resource},
74*4882a593Smuzhiyun {"_DMA",
75*4882a593Smuzhiyun ACPI_RTYPE_INTEGER | ACPI_RTYPE_STRING | ACPI_RTYPE_BUFFER |
76*4882a593Smuzhiyun ACPI_RTYPE_NONE,
77*4882a593Smuzhiyun ACPI_NOT_PACKAGE_ELEMENT,
78*4882a593Smuzhiyun acpi_ns_convert_to_resource},
79*4882a593Smuzhiyun {"_PRS",
80*4882a593Smuzhiyun ACPI_RTYPE_INTEGER | ACPI_RTYPE_STRING | ACPI_RTYPE_BUFFER |
81*4882a593Smuzhiyun ACPI_RTYPE_NONE,
82*4882a593Smuzhiyun ACPI_NOT_PACKAGE_ELEMENT,
83*4882a593Smuzhiyun acpi_ns_convert_to_resource},
84*4882a593Smuzhiyun
85*4882a593Smuzhiyun /* Object reference conversions */
86*4882a593Smuzhiyun
87*4882a593Smuzhiyun {"_DEP", ACPI_RTYPE_STRING, ACPI_ALL_PACKAGE_ELEMENTS,
88*4882a593Smuzhiyun acpi_ns_convert_to_reference},
89*4882a593Smuzhiyun
90*4882a593Smuzhiyun /* Unicode conversions */
91*4882a593Smuzhiyun
92*4882a593Smuzhiyun {"_MLS", ACPI_RTYPE_STRING, 1,
93*4882a593Smuzhiyun acpi_ns_convert_to_unicode},
94*4882a593Smuzhiyun {"_STR", ACPI_RTYPE_STRING | ACPI_RTYPE_BUFFER,
95*4882a593Smuzhiyun ACPI_NOT_PACKAGE_ELEMENT,
96*4882a593Smuzhiyun acpi_ns_convert_to_unicode},
97*4882a593Smuzhiyun {{0, 0, 0, 0}, 0, 0, NULL} /* Table terminator */
98*4882a593Smuzhiyun };
99*4882a593Smuzhiyun
100*4882a593Smuzhiyun /*******************************************************************************
101*4882a593Smuzhiyun *
102*4882a593Smuzhiyun * FUNCTION: acpi_ns_simple_repair
103*4882a593Smuzhiyun *
104*4882a593Smuzhiyun * PARAMETERS: info - Method execution information block
105*4882a593Smuzhiyun * expected_btypes - Object types expected
106*4882a593Smuzhiyun * package_index - Index of object within parent package (if
107*4882a593Smuzhiyun * applicable - ACPI_NOT_PACKAGE_ELEMENT
108*4882a593Smuzhiyun * otherwise)
109*4882a593Smuzhiyun * return_object_ptr - Pointer to the object returned from the
110*4882a593Smuzhiyun * evaluation of a method or object
111*4882a593Smuzhiyun *
112*4882a593Smuzhiyun * RETURN: Status. AE_OK if repair was successful.
113*4882a593Smuzhiyun *
114*4882a593Smuzhiyun * DESCRIPTION: Attempt to repair/convert a return object of a type that was
115*4882a593Smuzhiyun * not expected.
116*4882a593Smuzhiyun *
117*4882a593Smuzhiyun ******************************************************************************/
118*4882a593Smuzhiyun
119*4882a593Smuzhiyun acpi_status
acpi_ns_simple_repair(struct acpi_evaluate_info * info,u32 expected_btypes,u32 package_index,union acpi_operand_object ** return_object_ptr)120*4882a593Smuzhiyun acpi_ns_simple_repair(struct acpi_evaluate_info *info,
121*4882a593Smuzhiyun u32 expected_btypes,
122*4882a593Smuzhiyun u32 package_index,
123*4882a593Smuzhiyun union acpi_operand_object **return_object_ptr)
124*4882a593Smuzhiyun {
125*4882a593Smuzhiyun union acpi_operand_object *return_object = *return_object_ptr;
126*4882a593Smuzhiyun union acpi_operand_object *new_object = NULL;
127*4882a593Smuzhiyun acpi_status status;
128*4882a593Smuzhiyun const struct acpi_simple_repair_info *predefined;
129*4882a593Smuzhiyun
130*4882a593Smuzhiyun ACPI_FUNCTION_NAME(ns_simple_repair);
131*4882a593Smuzhiyun
132*4882a593Smuzhiyun /*
133*4882a593Smuzhiyun * Special repairs for certain names that are in the repair table.
134*4882a593Smuzhiyun * Check if this name is in the list of repairable names.
135*4882a593Smuzhiyun */
136*4882a593Smuzhiyun predefined = acpi_ns_match_simple_repair(info->node,
137*4882a593Smuzhiyun info->return_btype,
138*4882a593Smuzhiyun package_index);
139*4882a593Smuzhiyun if (predefined) {
140*4882a593Smuzhiyun if (!return_object) {
141*4882a593Smuzhiyun ACPI_WARN_PREDEFINED((AE_INFO, info->full_pathname,
142*4882a593Smuzhiyun ACPI_WARN_ALWAYS,
143*4882a593Smuzhiyun "Missing expected return value"));
144*4882a593Smuzhiyun }
145*4882a593Smuzhiyun
146*4882a593Smuzhiyun status = predefined->object_converter(info->node, return_object,
147*4882a593Smuzhiyun &new_object);
148*4882a593Smuzhiyun if (ACPI_FAILURE(status)) {
149*4882a593Smuzhiyun
150*4882a593Smuzhiyun /* A fatal error occurred during a conversion */
151*4882a593Smuzhiyun
152*4882a593Smuzhiyun ACPI_EXCEPTION((AE_INFO, status,
153*4882a593Smuzhiyun "During return object analysis"));
154*4882a593Smuzhiyun return (status);
155*4882a593Smuzhiyun }
156*4882a593Smuzhiyun if (new_object) {
157*4882a593Smuzhiyun goto object_repaired;
158*4882a593Smuzhiyun }
159*4882a593Smuzhiyun }
160*4882a593Smuzhiyun
161*4882a593Smuzhiyun /*
162*4882a593Smuzhiyun * Do not perform simple object repair unless the return type is not
163*4882a593Smuzhiyun * expected.
164*4882a593Smuzhiyun */
165*4882a593Smuzhiyun if (info->return_btype & expected_btypes) {
166*4882a593Smuzhiyun return (AE_OK);
167*4882a593Smuzhiyun }
168*4882a593Smuzhiyun
169*4882a593Smuzhiyun /*
170*4882a593Smuzhiyun * At this point, we know that the type of the returned object was not
171*4882a593Smuzhiyun * one of the expected types for this predefined name. Attempt to
172*4882a593Smuzhiyun * repair the object by converting it to one of the expected object
173*4882a593Smuzhiyun * types for this predefined name.
174*4882a593Smuzhiyun */
175*4882a593Smuzhiyun
176*4882a593Smuzhiyun /*
177*4882a593Smuzhiyun * If there is no return value, check if we require a return value for
178*4882a593Smuzhiyun * this predefined name. Either one return value is expected, or none,
179*4882a593Smuzhiyun * for both methods and other objects.
180*4882a593Smuzhiyun *
181*4882a593Smuzhiyun * Try to fix if there was no return object. Warning if failed to fix.
182*4882a593Smuzhiyun */
183*4882a593Smuzhiyun if (!return_object) {
184*4882a593Smuzhiyun if (expected_btypes && (!(expected_btypes & ACPI_RTYPE_NONE))) {
185*4882a593Smuzhiyun if (package_index != ACPI_NOT_PACKAGE_ELEMENT) {
186*4882a593Smuzhiyun ACPI_WARN_PREDEFINED((AE_INFO,
187*4882a593Smuzhiyun info->full_pathname,
188*4882a593Smuzhiyun ACPI_WARN_ALWAYS,
189*4882a593Smuzhiyun "Found unexpected NULL package element"));
190*4882a593Smuzhiyun
191*4882a593Smuzhiyun status =
192*4882a593Smuzhiyun acpi_ns_repair_null_element(info,
193*4882a593Smuzhiyun expected_btypes,
194*4882a593Smuzhiyun package_index,
195*4882a593Smuzhiyun return_object_ptr);
196*4882a593Smuzhiyun if (ACPI_SUCCESS(status)) {
197*4882a593Smuzhiyun return (AE_OK); /* Repair was successful */
198*4882a593Smuzhiyun }
199*4882a593Smuzhiyun } else {
200*4882a593Smuzhiyun ACPI_WARN_PREDEFINED((AE_INFO,
201*4882a593Smuzhiyun info->full_pathname,
202*4882a593Smuzhiyun ACPI_WARN_ALWAYS,
203*4882a593Smuzhiyun "Missing expected return value"));
204*4882a593Smuzhiyun }
205*4882a593Smuzhiyun
206*4882a593Smuzhiyun return (AE_AML_NO_RETURN_VALUE);
207*4882a593Smuzhiyun }
208*4882a593Smuzhiyun }
209*4882a593Smuzhiyun
210*4882a593Smuzhiyun if (expected_btypes & ACPI_RTYPE_INTEGER) {
211*4882a593Smuzhiyun status = acpi_ns_convert_to_integer(return_object, &new_object);
212*4882a593Smuzhiyun if (ACPI_SUCCESS(status)) {
213*4882a593Smuzhiyun goto object_repaired;
214*4882a593Smuzhiyun }
215*4882a593Smuzhiyun }
216*4882a593Smuzhiyun if (expected_btypes & ACPI_RTYPE_STRING) {
217*4882a593Smuzhiyun status = acpi_ns_convert_to_string(return_object, &new_object);
218*4882a593Smuzhiyun if (ACPI_SUCCESS(status)) {
219*4882a593Smuzhiyun goto object_repaired;
220*4882a593Smuzhiyun }
221*4882a593Smuzhiyun }
222*4882a593Smuzhiyun if (expected_btypes & ACPI_RTYPE_BUFFER) {
223*4882a593Smuzhiyun status = acpi_ns_convert_to_buffer(return_object, &new_object);
224*4882a593Smuzhiyun if (ACPI_SUCCESS(status)) {
225*4882a593Smuzhiyun goto object_repaired;
226*4882a593Smuzhiyun }
227*4882a593Smuzhiyun }
228*4882a593Smuzhiyun if (expected_btypes & ACPI_RTYPE_PACKAGE) {
229*4882a593Smuzhiyun /*
230*4882a593Smuzhiyun * A package is expected. We will wrap the existing object with a
231*4882a593Smuzhiyun * new package object. It is often the case that if a variable-length
232*4882a593Smuzhiyun * package is required, but there is only a single object needed, the
233*4882a593Smuzhiyun * BIOS will return that object instead of wrapping it with a Package
234*4882a593Smuzhiyun * object. Note: after the wrapping, the package will be validated
235*4882a593Smuzhiyun * for correct contents (expected object type or types).
236*4882a593Smuzhiyun */
237*4882a593Smuzhiyun status =
238*4882a593Smuzhiyun acpi_ns_wrap_with_package(info, return_object, &new_object);
239*4882a593Smuzhiyun if (ACPI_SUCCESS(status)) {
240*4882a593Smuzhiyun /*
241*4882a593Smuzhiyun * The original object just had its reference count
242*4882a593Smuzhiyun * incremented for being inserted into the new package.
243*4882a593Smuzhiyun */
244*4882a593Smuzhiyun *return_object_ptr = new_object; /* New Package object */
245*4882a593Smuzhiyun info->return_flags |= ACPI_OBJECT_REPAIRED;
246*4882a593Smuzhiyun return (AE_OK);
247*4882a593Smuzhiyun }
248*4882a593Smuzhiyun }
249*4882a593Smuzhiyun
250*4882a593Smuzhiyun /* We cannot repair this object */
251*4882a593Smuzhiyun
252*4882a593Smuzhiyun return (AE_AML_OPERAND_TYPE);
253*4882a593Smuzhiyun
254*4882a593Smuzhiyun object_repaired:
255*4882a593Smuzhiyun
256*4882a593Smuzhiyun /* Object was successfully repaired */
257*4882a593Smuzhiyun
258*4882a593Smuzhiyun if (package_index != ACPI_NOT_PACKAGE_ELEMENT) {
259*4882a593Smuzhiyun
260*4882a593Smuzhiyun /* Update reference count of new object */
261*4882a593Smuzhiyun
262*4882a593Smuzhiyun if (!(info->return_flags & ACPI_OBJECT_WRAPPED)) {
263*4882a593Smuzhiyun new_object->common.reference_count =
264*4882a593Smuzhiyun return_object->common.reference_count;
265*4882a593Smuzhiyun }
266*4882a593Smuzhiyun
267*4882a593Smuzhiyun ACPI_DEBUG_PRINT((ACPI_DB_REPAIR,
268*4882a593Smuzhiyun "%s: Converted %s to expected %s at Package index %u\n",
269*4882a593Smuzhiyun info->full_pathname,
270*4882a593Smuzhiyun acpi_ut_get_object_type_name(return_object),
271*4882a593Smuzhiyun acpi_ut_get_object_type_name(new_object),
272*4882a593Smuzhiyun package_index));
273*4882a593Smuzhiyun } else {
274*4882a593Smuzhiyun ACPI_DEBUG_PRINT((ACPI_DB_REPAIR,
275*4882a593Smuzhiyun "%s: Converted %s to expected %s\n",
276*4882a593Smuzhiyun info->full_pathname,
277*4882a593Smuzhiyun acpi_ut_get_object_type_name(return_object),
278*4882a593Smuzhiyun acpi_ut_get_object_type_name(new_object)));
279*4882a593Smuzhiyun }
280*4882a593Smuzhiyun
281*4882a593Smuzhiyun /* Delete old object, install the new return object */
282*4882a593Smuzhiyun
283*4882a593Smuzhiyun acpi_ut_remove_reference(return_object);
284*4882a593Smuzhiyun *return_object_ptr = new_object;
285*4882a593Smuzhiyun info->return_flags |= ACPI_OBJECT_REPAIRED;
286*4882a593Smuzhiyun return (AE_OK);
287*4882a593Smuzhiyun }
288*4882a593Smuzhiyun
289*4882a593Smuzhiyun /******************************************************************************
290*4882a593Smuzhiyun *
291*4882a593Smuzhiyun * FUNCTION: acpi_ns_match_simple_repair
292*4882a593Smuzhiyun *
293*4882a593Smuzhiyun * PARAMETERS: node - Namespace node for the method/object
294*4882a593Smuzhiyun * return_btype - Object type that was returned
295*4882a593Smuzhiyun * package_index - Index of object within parent package (if
296*4882a593Smuzhiyun * applicable - ACPI_NOT_PACKAGE_ELEMENT
297*4882a593Smuzhiyun * otherwise)
298*4882a593Smuzhiyun *
299*4882a593Smuzhiyun * RETURN: Pointer to entry in repair table. NULL indicates not found.
300*4882a593Smuzhiyun *
301*4882a593Smuzhiyun * DESCRIPTION: Check an object name against the repairable object list.
302*4882a593Smuzhiyun *
303*4882a593Smuzhiyun *****************************************************************************/
304*4882a593Smuzhiyun
acpi_ns_match_simple_repair(struct acpi_namespace_node * node,u32 return_btype,u32 package_index)305*4882a593Smuzhiyun static const struct acpi_simple_repair_info *acpi_ns_match_simple_repair(struct
306*4882a593Smuzhiyun acpi_namespace_node
307*4882a593Smuzhiyun *node,
308*4882a593Smuzhiyun u32
309*4882a593Smuzhiyun return_btype,
310*4882a593Smuzhiyun u32
311*4882a593Smuzhiyun package_index)
312*4882a593Smuzhiyun {
313*4882a593Smuzhiyun const struct acpi_simple_repair_info *this_name;
314*4882a593Smuzhiyun
315*4882a593Smuzhiyun /* Search info table for a repairable predefined method/object name */
316*4882a593Smuzhiyun
317*4882a593Smuzhiyun this_name = acpi_object_repair_info;
318*4882a593Smuzhiyun while (this_name->object_converter) {
319*4882a593Smuzhiyun if (ACPI_COMPARE_NAMESEG(node->name.ascii, this_name->name)) {
320*4882a593Smuzhiyun
321*4882a593Smuzhiyun /* Check if we can actually repair this name/type combination */
322*4882a593Smuzhiyun
323*4882a593Smuzhiyun if ((return_btype & this_name->unexpected_btypes) &&
324*4882a593Smuzhiyun (this_name->package_index ==
325*4882a593Smuzhiyun ACPI_ALL_PACKAGE_ELEMENTS
326*4882a593Smuzhiyun || package_index == this_name->package_index)) {
327*4882a593Smuzhiyun return (this_name);
328*4882a593Smuzhiyun }
329*4882a593Smuzhiyun
330*4882a593Smuzhiyun return (NULL);
331*4882a593Smuzhiyun }
332*4882a593Smuzhiyun
333*4882a593Smuzhiyun this_name++;
334*4882a593Smuzhiyun }
335*4882a593Smuzhiyun
336*4882a593Smuzhiyun return (NULL); /* Name was not found in the repair table */
337*4882a593Smuzhiyun }
338*4882a593Smuzhiyun
339*4882a593Smuzhiyun /*******************************************************************************
340*4882a593Smuzhiyun *
341*4882a593Smuzhiyun * FUNCTION: acpi_ns_repair_null_element
342*4882a593Smuzhiyun *
343*4882a593Smuzhiyun * PARAMETERS: info - Method execution information block
344*4882a593Smuzhiyun * expected_btypes - Object types expected
345*4882a593Smuzhiyun * package_index - Index of object within parent package (if
346*4882a593Smuzhiyun * applicable - ACPI_NOT_PACKAGE_ELEMENT
347*4882a593Smuzhiyun * otherwise)
348*4882a593Smuzhiyun * return_object_ptr - Pointer to the object returned from the
349*4882a593Smuzhiyun * evaluation of a method or object
350*4882a593Smuzhiyun *
351*4882a593Smuzhiyun * RETURN: Status. AE_OK if repair was successful.
352*4882a593Smuzhiyun *
353*4882a593Smuzhiyun * DESCRIPTION: Attempt to repair a NULL element of a returned Package object.
354*4882a593Smuzhiyun *
355*4882a593Smuzhiyun ******************************************************************************/
356*4882a593Smuzhiyun
357*4882a593Smuzhiyun acpi_status
acpi_ns_repair_null_element(struct acpi_evaluate_info * info,u32 expected_btypes,u32 package_index,union acpi_operand_object ** return_object_ptr)358*4882a593Smuzhiyun acpi_ns_repair_null_element(struct acpi_evaluate_info *info,
359*4882a593Smuzhiyun u32 expected_btypes,
360*4882a593Smuzhiyun u32 package_index,
361*4882a593Smuzhiyun union acpi_operand_object **return_object_ptr)
362*4882a593Smuzhiyun {
363*4882a593Smuzhiyun union acpi_operand_object *return_object = *return_object_ptr;
364*4882a593Smuzhiyun union acpi_operand_object *new_object;
365*4882a593Smuzhiyun
366*4882a593Smuzhiyun ACPI_FUNCTION_NAME(ns_repair_null_element);
367*4882a593Smuzhiyun
368*4882a593Smuzhiyun /* No repair needed if return object is non-NULL */
369*4882a593Smuzhiyun
370*4882a593Smuzhiyun if (return_object) {
371*4882a593Smuzhiyun return (AE_OK);
372*4882a593Smuzhiyun }
373*4882a593Smuzhiyun
374*4882a593Smuzhiyun /*
375*4882a593Smuzhiyun * Attempt to repair a NULL element of a Package object. This applies to
376*4882a593Smuzhiyun * predefined names that return a fixed-length package and each element
377*4882a593Smuzhiyun * is required. It does not apply to variable-length packages where NULL
378*4882a593Smuzhiyun * elements are allowed, especially at the end of the package.
379*4882a593Smuzhiyun */
380*4882a593Smuzhiyun if (expected_btypes & ACPI_RTYPE_INTEGER) {
381*4882a593Smuzhiyun
382*4882a593Smuzhiyun /* Need an integer - create a zero-value integer */
383*4882a593Smuzhiyun
384*4882a593Smuzhiyun new_object = acpi_ut_create_integer_object((u64)0);
385*4882a593Smuzhiyun } else if (expected_btypes & ACPI_RTYPE_STRING) {
386*4882a593Smuzhiyun
387*4882a593Smuzhiyun /* Need a string - create a NULL string */
388*4882a593Smuzhiyun
389*4882a593Smuzhiyun new_object = acpi_ut_create_string_object(0);
390*4882a593Smuzhiyun } else if (expected_btypes & ACPI_RTYPE_BUFFER) {
391*4882a593Smuzhiyun
392*4882a593Smuzhiyun /* Need a buffer - create a zero-length buffer */
393*4882a593Smuzhiyun
394*4882a593Smuzhiyun new_object = acpi_ut_create_buffer_object(0);
395*4882a593Smuzhiyun } else {
396*4882a593Smuzhiyun /* Error for all other expected types */
397*4882a593Smuzhiyun
398*4882a593Smuzhiyun return (AE_AML_OPERAND_TYPE);
399*4882a593Smuzhiyun }
400*4882a593Smuzhiyun
401*4882a593Smuzhiyun if (!new_object) {
402*4882a593Smuzhiyun return (AE_NO_MEMORY);
403*4882a593Smuzhiyun }
404*4882a593Smuzhiyun
405*4882a593Smuzhiyun /* Set the reference count according to the parent Package object */
406*4882a593Smuzhiyun
407*4882a593Smuzhiyun new_object->common.reference_count =
408*4882a593Smuzhiyun info->parent_package->common.reference_count;
409*4882a593Smuzhiyun
410*4882a593Smuzhiyun ACPI_DEBUG_PRINT((ACPI_DB_REPAIR,
411*4882a593Smuzhiyun "%s: Converted NULL package element to expected %s at index %u\n",
412*4882a593Smuzhiyun info->full_pathname,
413*4882a593Smuzhiyun acpi_ut_get_object_type_name(new_object),
414*4882a593Smuzhiyun package_index));
415*4882a593Smuzhiyun
416*4882a593Smuzhiyun *return_object_ptr = new_object;
417*4882a593Smuzhiyun info->return_flags |= ACPI_OBJECT_REPAIRED;
418*4882a593Smuzhiyun return (AE_OK);
419*4882a593Smuzhiyun }
420*4882a593Smuzhiyun
421*4882a593Smuzhiyun /******************************************************************************
422*4882a593Smuzhiyun *
423*4882a593Smuzhiyun * FUNCTION: acpi_ns_remove_null_elements
424*4882a593Smuzhiyun *
425*4882a593Smuzhiyun * PARAMETERS: info - Method execution information block
426*4882a593Smuzhiyun * package_type - An acpi_return_package_types value
427*4882a593Smuzhiyun * obj_desc - A Package object
428*4882a593Smuzhiyun *
429*4882a593Smuzhiyun * RETURN: None.
430*4882a593Smuzhiyun *
431*4882a593Smuzhiyun * DESCRIPTION: Remove all NULL package elements from packages that contain
432*4882a593Smuzhiyun * a variable number of subpackages. For these types of
433*4882a593Smuzhiyun * packages, NULL elements can be safely removed.
434*4882a593Smuzhiyun *
435*4882a593Smuzhiyun *****************************************************************************/
436*4882a593Smuzhiyun
437*4882a593Smuzhiyun void
acpi_ns_remove_null_elements(struct acpi_evaluate_info * info,u8 package_type,union acpi_operand_object * obj_desc)438*4882a593Smuzhiyun acpi_ns_remove_null_elements(struct acpi_evaluate_info *info,
439*4882a593Smuzhiyun u8 package_type,
440*4882a593Smuzhiyun union acpi_operand_object *obj_desc)
441*4882a593Smuzhiyun {
442*4882a593Smuzhiyun union acpi_operand_object **source;
443*4882a593Smuzhiyun union acpi_operand_object **dest;
444*4882a593Smuzhiyun u32 count;
445*4882a593Smuzhiyun u32 new_count;
446*4882a593Smuzhiyun u32 i;
447*4882a593Smuzhiyun
448*4882a593Smuzhiyun ACPI_FUNCTION_NAME(ns_remove_null_elements);
449*4882a593Smuzhiyun
450*4882a593Smuzhiyun /*
451*4882a593Smuzhiyun * We can safely remove all NULL elements from these package types:
452*4882a593Smuzhiyun * PTYPE1_VAR packages contain a variable number of simple data types.
453*4882a593Smuzhiyun * PTYPE2 packages contain a variable number of subpackages.
454*4882a593Smuzhiyun */
455*4882a593Smuzhiyun switch (package_type) {
456*4882a593Smuzhiyun case ACPI_PTYPE1_VAR:
457*4882a593Smuzhiyun case ACPI_PTYPE2:
458*4882a593Smuzhiyun case ACPI_PTYPE2_COUNT:
459*4882a593Smuzhiyun case ACPI_PTYPE2_PKG_COUNT:
460*4882a593Smuzhiyun case ACPI_PTYPE2_FIXED:
461*4882a593Smuzhiyun case ACPI_PTYPE2_MIN:
462*4882a593Smuzhiyun case ACPI_PTYPE2_REV_FIXED:
463*4882a593Smuzhiyun case ACPI_PTYPE2_FIX_VAR:
464*4882a593Smuzhiyun break;
465*4882a593Smuzhiyun
466*4882a593Smuzhiyun default:
467*4882a593Smuzhiyun case ACPI_PTYPE2_VAR_VAR:
468*4882a593Smuzhiyun case ACPI_PTYPE1_FIXED:
469*4882a593Smuzhiyun case ACPI_PTYPE1_OPTION:
470*4882a593Smuzhiyun return;
471*4882a593Smuzhiyun }
472*4882a593Smuzhiyun
473*4882a593Smuzhiyun count = obj_desc->package.count;
474*4882a593Smuzhiyun new_count = count;
475*4882a593Smuzhiyun
476*4882a593Smuzhiyun source = obj_desc->package.elements;
477*4882a593Smuzhiyun dest = source;
478*4882a593Smuzhiyun
479*4882a593Smuzhiyun /* Examine all elements of the package object, remove nulls */
480*4882a593Smuzhiyun
481*4882a593Smuzhiyun for (i = 0; i < count; i++) {
482*4882a593Smuzhiyun if (!*source) {
483*4882a593Smuzhiyun new_count--;
484*4882a593Smuzhiyun } else {
485*4882a593Smuzhiyun *dest = *source;
486*4882a593Smuzhiyun dest++;
487*4882a593Smuzhiyun }
488*4882a593Smuzhiyun
489*4882a593Smuzhiyun source++;
490*4882a593Smuzhiyun }
491*4882a593Smuzhiyun
492*4882a593Smuzhiyun /* Update parent package if any null elements were removed */
493*4882a593Smuzhiyun
494*4882a593Smuzhiyun if (new_count < count) {
495*4882a593Smuzhiyun ACPI_DEBUG_PRINT((ACPI_DB_REPAIR,
496*4882a593Smuzhiyun "%s: Found and removed %u NULL elements\n",
497*4882a593Smuzhiyun info->full_pathname, (count - new_count)));
498*4882a593Smuzhiyun
499*4882a593Smuzhiyun /* NULL terminate list and update the package count */
500*4882a593Smuzhiyun
501*4882a593Smuzhiyun *dest = NULL;
502*4882a593Smuzhiyun obj_desc->package.count = new_count;
503*4882a593Smuzhiyun }
504*4882a593Smuzhiyun }
505*4882a593Smuzhiyun
506*4882a593Smuzhiyun /*******************************************************************************
507*4882a593Smuzhiyun *
508*4882a593Smuzhiyun * FUNCTION: acpi_ns_wrap_with_package
509*4882a593Smuzhiyun *
510*4882a593Smuzhiyun * PARAMETERS: info - Method execution information block
511*4882a593Smuzhiyun * original_object - Pointer to the object to repair.
512*4882a593Smuzhiyun * obj_desc_ptr - The new package object is returned here
513*4882a593Smuzhiyun *
514*4882a593Smuzhiyun * RETURN: Status, new object in *obj_desc_ptr
515*4882a593Smuzhiyun *
516*4882a593Smuzhiyun * DESCRIPTION: Repair a common problem with objects that are defined to
517*4882a593Smuzhiyun * return a variable-length Package of sub-objects. If there is
518*4882a593Smuzhiyun * only one sub-object, some BIOS code mistakenly simply declares
519*4882a593Smuzhiyun * the single object instead of a Package with one sub-object.
520*4882a593Smuzhiyun * This function attempts to repair this error by wrapping a
521*4882a593Smuzhiyun * Package object around the original object, creating the
522*4882a593Smuzhiyun * correct and expected Package with one sub-object.
523*4882a593Smuzhiyun *
524*4882a593Smuzhiyun * Names that can be repaired in this manner include:
525*4882a593Smuzhiyun * _ALR, _CSD, _HPX, _MLS, _PLD, _PRT, _PSS, _TRT, _TSS,
526*4882a593Smuzhiyun * _BCL, _DOD, _FIX, _Sx
527*4882a593Smuzhiyun *
528*4882a593Smuzhiyun ******************************************************************************/
529*4882a593Smuzhiyun
530*4882a593Smuzhiyun acpi_status
acpi_ns_wrap_with_package(struct acpi_evaluate_info * info,union acpi_operand_object * original_object,union acpi_operand_object ** obj_desc_ptr)531*4882a593Smuzhiyun acpi_ns_wrap_with_package(struct acpi_evaluate_info *info,
532*4882a593Smuzhiyun union acpi_operand_object *original_object,
533*4882a593Smuzhiyun union acpi_operand_object **obj_desc_ptr)
534*4882a593Smuzhiyun {
535*4882a593Smuzhiyun union acpi_operand_object *pkg_obj_desc;
536*4882a593Smuzhiyun
537*4882a593Smuzhiyun ACPI_FUNCTION_NAME(ns_wrap_with_package);
538*4882a593Smuzhiyun
539*4882a593Smuzhiyun /*
540*4882a593Smuzhiyun * Create the new outer package and populate it. The new
541*4882a593Smuzhiyun * package will have a single element, the lone sub-object.
542*4882a593Smuzhiyun */
543*4882a593Smuzhiyun pkg_obj_desc = acpi_ut_create_package_object(1);
544*4882a593Smuzhiyun if (!pkg_obj_desc) {
545*4882a593Smuzhiyun return (AE_NO_MEMORY);
546*4882a593Smuzhiyun }
547*4882a593Smuzhiyun
548*4882a593Smuzhiyun pkg_obj_desc->package.elements[0] = original_object;
549*4882a593Smuzhiyun
550*4882a593Smuzhiyun ACPI_DEBUG_PRINT((ACPI_DB_REPAIR,
551*4882a593Smuzhiyun "%s: Wrapped %s with expected Package object\n",
552*4882a593Smuzhiyun info->full_pathname,
553*4882a593Smuzhiyun acpi_ut_get_object_type_name(original_object)));
554*4882a593Smuzhiyun
555*4882a593Smuzhiyun /* Return the new object in the object pointer */
556*4882a593Smuzhiyun
557*4882a593Smuzhiyun *obj_desc_ptr = pkg_obj_desc;
558*4882a593Smuzhiyun info->return_flags |= ACPI_OBJECT_REPAIRED | ACPI_OBJECT_WRAPPED;
559*4882a593Smuzhiyun return (AE_OK);
560*4882a593Smuzhiyun }
561