diff options
Diffstat (limited to 'drivers/acpi/namespace')
-rw-r--r-- | drivers/acpi/namespace/Makefile | 2 | ||||
-rw-r--r-- | drivers/acpi/namespace/nsdump.c | 5 | ||||
-rw-r--r-- | drivers/acpi/namespace/nseval.c | 73 | ||||
-rw-r--r-- | drivers/acpi/namespace/nsnames.c | 7 | ||||
-rw-r--r-- | drivers/acpi/namespace/nspredef.c | 900 | ||||
-rw-r--r-- | drivers/acpi/namespace/nssearch.c | 2 | ||||
-rw-r--r-- | drivers/acpi/namespace/nsxfeval.c | 78 | ||||
-rw-r--r-- | drivers/acpi/namespace/nsxfname.c | 5 |
8 files changed, 1051 insertions, 21 deletions
diff --git a/drivers/acpi/namespace/Makefile b/drivers/acpi/namespace/Makefile index 3f63d3640696..371a2daf837f 100644 --- a/drivers/acpi/namespace/Makefile +++ b/drivers/acpi/namespace/Makefile | |||
@@ -5,7 +5,7 @@ | |||
5 | obj-y := nsaccess.o nsload.o nssearch.o nsxfeval.o \ | 5 | obj-y := nsaccess.o nsload.o nssearch.o nsxfeval.o \ |
6 | nsalloc.o nseval.o nsnames.o nsutils.o nsxfname.o \ | 6 | nsalloc.o nseval.o nsnames.o nsutils.o nsxfname.o \ |
7 | nsdump.o nsinit.o nsobject.o nswalk.o nsxfobj.o \ | 7 | nsdump.o nsinit.o nsobject.o nswalk.o nsxfobj.o \ |
8 | nsparse.o | 8 | nsparse.o nspredef.o |
9 | 9 | ||
10 | obj-$(ACPI_FUTURE_USAGE) += nsdumpdv.o | 10 | obj-$(ACPI_FUTURE_USAGE) += nsdumpdv.o |
11 | 11 | ||
diff --git a/drivers/acpi/namespace/nsdump.c b/drivers/acpi/namespace/nsdump.c index 0ab22004728a..cc0ae39440e4 100644 --- a/drivers/acpi/namespace/nsdump.c +++ b/drivers/acpi/namespace/nsdump.c | |||
@@ -43,7 +43,6 @@ | |||
43 | 43 | ||
44 | #include <acpi/acpi.h> | 44 | #include <acpi/acpi.h> |
45 | #include <acpi/acnamesp.h> | 45 | #include <acpi/acnamesp.h> |
46 | #include <acpi/acparser.h> | ||
47 | 46 | ||
48 | #define _COMPONENT ACPI_NAMESPACE | 47 | #define _COMPONENT ACPI_NAMESPACE |
49 | ACPI_MODULE_NAME("nsdump") | 48 | ACPI_MODULE_NAME("nsdump") |
@@ -334,9 +333,7 @@ acpi_ns_dump_one_object(acpi_handle obj_handle, | |||
334 | case ACPI_TYPE_LOCAL_REFERENCE: | 333 | case ACPI_TYPE_LOCAL_REFERENCE: |
335 | 334 | ||
336 | acpi_os_printf("[%s]\n", | 335 | acpi_os_printf("[%s]\n", |
337 | acpi_ps_get_opcode_name(obj_desc-> | 336 | acpi_ut_get_reference_name(obj_desc)); |
338 | reference. | ||
339 | opcode)); | ||
340 | break; | 337 | break; |
341 | 338 | ||
342 | case ACPI_TYPE_BUFFER_FIELD: | 339 | case ACPI_TYPE_BUFFER_FIELD: |
diff --git a/drivers/acpi/namespace/nseval.c b/drivers/acpi/namespace/nseval.c index d369164e00b0..4cdf03ac2b46 100644 --- a/drivers/acpi/namespace/nseval.c +++ b/drivers/acpi/namespace/nseval.c | |||
@@ -78,6 +78,7 @@ ACPI_MODULE_NAME("nseval") | |||
78 | acpi_status acpi_ns_evaluate(struct acpi_evaluate_info * info) | 78 | acpi_status acpi_ns_evaluate(struct acpi_evaluate_info * info) |
79 | { | 79 | { |
80 | acpi_status status; | 80 | acpi_status status; |
81 | struct acpi_namespace_node *node; | ||
81 | 82 | ||
82 | ACPI_FUNCTION_TRACE(ns_evaluate); | 83 | ACPI_FUNCTION_TRACE(ns_evaluate); |
83 | 84 | ||
@@ -117,6 +118,8 @@ acpi_status acpi_ns_evaluate(struct acpi_evaluate_info * info) | |||
117 | info->resolved_node, | 118 | info->resolved_node, |
118 | acpi_ns_get_attached_object(info->resolved_node))); | 119 | acpi_ns_get_attached_object(info->resolved_node))); |
119 | 120 | ||
121 | node = info->resolved_node; | ||
122 | |||
120 | /* | 123 | /* |
121 | * Two major cases here: | 124 | * Two major cases here: |
122 | * | 125 | * |
@@ -148,21 +151,22 @@ acpi_status acpi_ns_evaluate(struct acpi_evaluate_info * info) | |||
148 | info->param_count++; | 151 | info->param_count++; |
149 | } | 152 | } |
150 | 153 | ||
151 | /* Error if too few arguments were passed in */ | 154 | /* |
155 | * Warning if too few or too many arguments have been passed by the | ||
156 | * caller. We don't want to abort here with an error because an | ||
157 | * incorrect number of arguments may not cause the method to fail. | ||
158 | * However, the method will fail if there are too few arguments passed | ||
159 | * and the method attempts to use one of the missing ones. | ||
160 | */ | ||
152 | 161 | ||
153 | if (info->param_count < info->obj_desc->method.param_count) { | 162 | if (info->param_count < info->obj_desc->method.param_count) { |
154 | ACPI_ERROR((AE_INFO, | 163 | ACPI_WARNING((AE_INFO, |
155 | "Insufficient arguments - " | 164 | "Insufficient arguments - " |
156 | "method [%4.4s] needs %d, found %d", | 165 | "method [%4.4s] needs %d, found %d", |
157 | acpi_ut_get_node_name(info->resolved_node), | 166 | acpi_ut_get_node_name(info->resolved_node), |
158 | info->obj_desc->method.param_count, | 167 | info->obj_desc->method.param_count, |
159 | info->param_count)); | 168 | info->param_count)); |
160 | return_ACPI_STATUS(AE_MISSING_ARGUMENTS); | 169 | } else if (info->param_count > |
161 | } | ||
162 | |||
163 | /* Just a warning if too many arguments */ | ||
164 | |||
165 | else if (info->param_count > | ||
166 | info->obj_desc->method.param_count) { | 170 | info->obj_desc->method.param_count) { |
167 | ACPI_WARNING((AE_INFO, | 171 | ACPI_WARNING((AE_INFO, |
168 | "Excess arguments - " | 172 | "Excess arguments - " |
@@ -195,7 +199,28 @@ acpi_status acpi_ns_evaluate(struct acpi_evaluate_info * info) | |||
195 | } else { | 199 | } else { |
196 | /* | 200 | /* |
197 | * 2) Object is not a method, return its current value | 201 | * 2) Object is not a method, return its current value |
202 | * | ||
203 | * Disallow certain object types. For these, "evaluation" is undefined. | ||
198 | */ | 204 | */ |
205 | switch (info->resolved_node->type) { | ||
206 | case ACPI_TYPE_DEVICE: | ||
207 | case ACPI_TYPE_EVENT: | ||
208 | case ACPI_TYPE_MUTEX: | ||
209 | case ACPI_TYPE_REGION: | ||
210 | case ACPI_TYPE_THERMAL: | ||
211 | case ACPI_TYPE_LOCAL_SCOPE: | ||
212 | |||
213 | ACPI_ERROR((AE_INFO, | ||
214 | "[%4.4s] Evaluation of object type [%s] is not supported", | ||
215 | info->resolved_node->name.ascii, | ||
216 | acpi_ut_get_type_name(info->resolved_node-> | ||
217 | type))); | ||
218 | |||
219 | return_ACPI_STATUS(AE_TYPE); | ||
220 | |||
221 | default: | ||
222 | break; | ||
223 | } | ||
199 | 224 | ||
200 | /* | 225 | /* |
201 | * Objects require additional resolution steps (e.g., the Node may be | 226 | * Objects require additional resolution steps (e.g., the Node may be |
@@ -239,9 +264,35 @@ acpi_status acpi_ns_evaluate(struct acpi_evaluate_info * info) | |||
239 | } | 264 | } |
240 | } | 265 | } |
241 | 266 | ||
242 | /* | 267 | /* Validation of return values for ACPI-predefined methods and objects */ |
243 | * Check if there is a return value that must be dealt with | 268 | |
244 | */ | 269 | if ((status == AE_OK) || (status == AE_CTRL_RETURN_VALUE)) { |
270 | /* | ||
271 | * If this is the first evaluation, check the return value. This | ||
272 | * ensures that any warnings will only be emitted during the very | ||
273 | * first evaluation of the object. | ||
274 | */ | ||
275 | if (!(node->flags & ANOBJ_EVALUATED)) { | ||
276 | /* | ||
277 | * Check for a predefined ACPI name. If found, validate the | ||
278 | * returned object. | ||
279 | * | ||
280 | * Note: Ignore return status for now, emit warnings if there are | ||
281 | * problems with the returned object. May change later to abort | ||
282 | * the method on invalid return object. | ||
283 | */ | ||
284 | (void)acpi_ns_check_predefined_names(node, | ||
285 | info-> | ||
286 | return_object); | ||
287 | } | ||
288 | |||
289 | /* Mark the node as having been evaluated */ | ||
290 | |||
291 | node->flags |= ANOBJ_EVALUATED; | ||
292 | } | ||
293 | |||
294 | /* Check if there is a return value that must be dealt with */ | ||
295 | |||
245 | if (status == AE_CTRL_RETURN_VALUE) { | 296 | if (status == AE_CTRL_RETURN_VALUE) { |
246 | 297 | ||
247 | /* If caller does not want the return value, delete it */ | 298 | /* If caller does not want the return value, delete it */ |
diff --git a/drivers/acpi/namespace/nsnames.c b/drivers/acpi/namespace/nsnames.c index bd5773878009..42a39a7c96e9 100644 --- a/drivers/acpi/namespace/nsnames.c +++ b/drivers/acpi/namespace/nsnames.c | |||
@@ -115,7 +115,6 @@ acpi_ns_build_external_path(struct acpi_namespace_node *node, | |||
115 | return (AE_OK); | 115 | return (AE_OK); |
116 | } | 116 | } |
117 | 117 | ||
118 | #ifdef ACPI_DEBUG_OUTPUT | ||
119 | /******************************************************************************* | 118 | /******************************************************************************* |
120 | * | 119 | * |
121 | * FUNCTION: acpi_ns_get_external_pathname | 120 | * FUNCTION: acpi_ns_get_external_pathname |
@@ -142,7 +141,7 @@ char *acpi_ns_get_external_pathname(struct acpi_namespace_node *node) | |||
142 | 141 | ||
143 | size = acpi_ns_get_pathname_length(node); | 142 | size = acpi_ns_get_pathname_length(node); |
144 | if (!size) { | 143 | if (!size) { |
145 | return (NULL); | 144 | return_PTR(NULL); |
146 | } | 145 | } |
147 | 146 | ||
148 | /* Allocate a buffer to be returned to caller */ | 147 | /* Allocate a buffer to be returned to caller */ |
@@ -157,12 +156,12 @@ char *acpi_ns_get_external_pathname(struct acpi_namespace_node *node) | |||
157 | 156 | ||
158 | status = acpi_ns_build_external_path(node, size, name_buffer); | 157 | status = acpi_ns_build_external_path(node, size, name_buffer); |
159 | if (ACPI_FAILURE(status)) { | 158 | if (ACPI_FAILURE(status)) { |
160 | return (NULL); | 159 | ACPI_FREE(name_buffer); |
160 | return_PTR(NULL); | ||
161 | } | 161 | } |
162 | 162 | ||
163 | return_PTR(name_buffer); | 163 | return_PTR(name_buffer); |
164 | } | 164 | } |
165 | #endif | ||
166 | 165 | ||
167 | /******************************************************************************* | 166 | /******************************************************************************* |
168 | * | 167 | * |
diff --git a/drivers/acpi/namespace/nspredef.c b/drivers/acpi/namespace/nspredef.c new file mode 100644 index 000000000000..0f17cf0898c9 --- /dev/null +++ b/drivers/acpi/namespace/nspredef.c | |||
@@ -0,0 +1,900 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * Module Name: nspredef - Validation of ACPI predefined methods and objects | ||
4 | * $Revision: 1.1 $ | ||
5 | * | ||
6 | *****************************************************************************/ | ||
7 | |||
8 | /* | ||
9 | * Copyright (C) 2000 - 2008, Intel Corp. | ||
10 | * All rights reserved. | ||
11 | * | ||
12 | * Redistribution and use in source and binary forms, with or without | ||
13 | * modification, are permitted provided that the following conditions | ||
14 | * are met: | ||
15 | * 1. Redistributions of source code must retain the above copyright | ||
16 | * notice, this list of conditions, and the following disclaimer, | ||
17 | * without modification. | ||
18 | * 2. Redistributions in binary form must reproduce at minimum a disclaimer | ||
19 | * substantially similar to the "NO WARRANTY" disclaimer below | ||
20 | * ("Disclaimer") and any redistribution must be conditioned upon | ||
21 | * including a substantially similar Disclaimer requirement for further | ||
22 | * binary redistribution. | ||
23 | * 3. Neither the names of the above-listed copyright holders nor the names | ||
24 | * of any contributors may be used to endorse or promote products derived | ||
25 | * from this software without specific prior written permission. | ||
26 | * | ||
27 | * Alternatively, this software may be distributed under the terms of the | ||
28 | * GNU General Public License ("GPL") version 2 as published by the Free | ||
29 | * Software Foundation. | ||
30 | * | ||
31 | * NO WARRANTY | ||
32 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
33 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
34 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR | ||
35 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
36 | * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | ||
37 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | ||
38 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | ||
39 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, | ||
40 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING | ||
41 | * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
42 | * POSSIBILITY OF SUCH DAMAGES. | ||
43 | */ | ||
44 | |||
45 | #include <acpi/acpi.h> | ||
46 | #include <acpi/acnamesp.h> | ||
47 | #include <acpi/acpredef.h> | ||
48 | |||
49 | #define _COMPONENT ACPI_NAMESPACE | ||
50 | ACPI_MODULE_NAME("nspredef") | ||
51 | |||
52 | /******************************************************************************* | ||
53 | * | ||
54 | * This module validates predefined ACPI objects that appear in the namespace, | ||
55 | * at the time they are evaluated (via acpi_evaluate_object). The purpose of this | ||
56 | * validation is to detect problems with BIOS-exposed predefined ACPI objects | ||
57 | * before the results are returned to the ACPI-related drivers. | ||
58 | * | ||
59 | * There are several areas that are validated: | ||
60 | * | ||
61 | * 1) The number of input arguments as defined by the method/object in the | ||
62 | * ASL is validated against the ACPI specification. | ||
63 | * 2) The type of the return object (if any) is validated against the ACPI | ||
64 | * specification. | ||
65 | * 3) For returned package objects, the count of package elements is | ||
66 | * validated, as well as the type of each package element. Nested | ||
67 | * packages are supported. | ||
68 | * | ||
69 | * For any problems found, a warning message is issued. | ||
70 | * | ||
71 | ******************************************************************************/ | ||
72 | /* Local prototypes */ | ||
73 | static acpi_status | ||
74 | acpi_ns_check_package(char *pathname, | ||
75 | union acpi_operand_object *return_object, | ||
76 | const union acpi_predefined_info *predefined); | ||
77 | |||
78 | static acpi_status | ||
79 | acpi_ns_check_package_elements(char *pathname, | ||
80 | union acpi_operand_object **elements, | ||
81 | u8 type1, u32 count1, u8 type2, u32 count2); | ||
82 | |||
83 | static acpi_status | ||
84 | acpi_ns_check_object_type(char *pathname, | ||
85 | union acpi_operand_object *return_object, | ||
86 | u32 expected_btypes, u32 package_index); | ||
87 | |||
88 | static acpi_status | ||
89 | acpi_ns_check_reference(char *pathname, | ||
90 | union acpi_operand_object *return_object); | ||
91 | |||
92 | /* | ||
93 | * Names for the types that can be returned by the predefined objects. | ||
94 | * Used for warning messages. Must be in the same order as the ACPI_RTYPEs | ||
95 | */ | ||
96 | static const char *acpi_rtype_names[] = { | ||
97 | "/Integer", | ||
98 | "/String", | ||
99 | "/Buffer", | ||
100 | "/Package", | ||
101 | "/Reference", | ||
102 | }; | ||
103 | |||
104 | #define ACPI_NOT_PACKAGE ACPI_UINT32_MAX | ||
105 | |||
106 | /******************************************************************************* | ||
107 | * | ||
108 | * FUNCTION: acpi_ns_check_predefined_names | ||
109 | * | ||
110 | * PARAMETERS: Node - Namespace node for the method/object | ||
111 | * return_object - Object returned from the evaluation of this | ||
112 | * method/object | ||
113 | * | ||
114 | * RETURN: Status | ||
115 | * | ||
116 | * DESCRIPTION: Check an ACPI name for a match in the predefined name list. | ||
117 | * | ||
118 | ******************************************************************************/ | ||
119 | |||
120 | acpi_status | ||
121 | acpi_ns_check_predefined_names(struct acpi_namespace_node *node, | ||
122 | union acpi_operand_object *return_object) | ||
123 | { | ||
124 | acpi_status status = AE_OK; | ||
125 | const union acpi_predefined_info *predefined; | ||
126 | char *pathname; | ||
127 | |||
128 | /* Match the name for this method/object against the predefined list */ | ||
129 | |||
130 | predefined = acpi_ns_check_for_predefined_name(node); | ||
131 | if (!predefined) { | ||
132 | |||
133 | /* Name was not one of the predefined names */ | ||
134 | |||
135 | return (AE_OK); | ||
136 | } | ||
137 | |||
138 | /* Get the full pathname to the object, for use in error messages */ | ||
139 | |||
140 | pathname = acpi_ns_get_external_pathname(node); | ||
141 | if (!pathname) { | ||
142 | pathname = ACPI_CAST_PTR(char, predefined->info.name); | ||
143 | } | ||
144 | |||
145 | /* | ||
146 | * Check that the parameter count for this method is in accordance | ||
147 | * with the ACPI specification. | ||
148 | */ | ||
149 | acpi_ns_check_parameter_count(pathname, node, predefined); | ||
150 | |||
151 | /* | ||
152 | * If there is no return value, check if we require a return value for | ||
153 | * this predefined name. Either one return value is expected, or none, | ||
154 | * for both methods and other objects. | ||
155 | * | ||
156 | * Exit now if there is no return object. Warning if one was expected. | ||
157 | */ | ||
158 | if (!return_object) { | ||
159 | if ((predefined->info.expected_btypes) && | ||
160 | (!(predefined->info.expected_btypes & ACPI_RTYPE_NONE))) { | ||
161 | ACPI_ERROR((AE_INFO, | ||
162 | "%s: Missing expected return value", | ||
163 | pathname)); | ||
164 | |||
165 | status = AE_AML_NO_RETURN_VALUE; | ||
166 | } | ||
167 | goto exit; | ||
168 | } | ||
169 | |||
170 | /* | ||
171 | * We have a return value, but if one wasn't expected, just exit, this is | ||
172 | * not a problem | ||
173 | * | ||
174 | * For example, if "Implicit return value" is enabled, methods will | ||
175 | * always return a value | ||
176 | */ | ||
177 | if (!predefined->info.expected_btypes) { | ||
178 | goto exit; | ||
179 | } | ||
180 | |||
181 | /* | ||
182 | * Check that the type of the return object is what is expected for | ||
183 | * this predefined name | ||
184 | */ | ||
185 | status = acpi_ns_check_object_type(pathname, return_object, | ||
186 | predefined->info.expected_btypes, | ||
187 | ACPI_NOT_PACKAGE); | ||
188 | if (ACPI_FAILURE(status)) { | ||
189 | goto exit; | ||
190 | } | ||
191 | |||
192 | /* For returned Package objects, check the type of all sub-objects */ | ||
193 | |||
194 | if (ACPI_GET_OBJECT_TYPE(return_object) == ACPI_TYPE_PACKAGE) { | ||
195 | status = | ||
196 | acpi_ns_check_package(pathname, return_object, predefined); | ||
197 | } | ||
198 | |||
199 | exit: | ||
200 | if (pathname) { | ||
201 | ACPI_FREE(pathname); | ||
202 | } | ||
203 | |||
204 | return (status); | ||
205 | } | ||
206 | |||
207 | /******************************************************************************* | ||
208 | * | ||
209 | * FUNCTION: acpi_ns_check_parameter_count | ||
210 | * | ||
211 | * PARAMETERS: Pathname - Full pathname to the node (for error msgs) | ||
212 | * Node - Namespace node for the method/object | ||
213 | * Predefined - Pointer to entry in predefined name table | ||
214 | * | ||
215 | * RETURN: None | ||
216 | * | ||
217 | * DESCRIPTION: Check that the declared (in ASL/AML) parameter count for a | ||
218 | * predefined name is what is expected (i.e., what is defined in | ||
219 | * the ACPI specification for this predefined name.) | ||
220 | * | ||
221 | ******************************************************************************/ | ||
222 | |||
223 | void | ||
224 | acpi_ns_check_parameter_count(char *pathname, | ||
225 | struct acpi_namespace_node *node, | ||
226 | const union acpi_predefined_info *predefined) | ||
227 | { | ||
228 | u32 param_count; | ||
229 | u32 required_params_current; | ||
230 | u32 required_params_old; | ||
231 | |||
232 | /* | ||
233 | * Check that the ASL-defined parameter count is what is expected for | ||
234 | * this predefined name. | ||
235 | * | ||
236 | * Methods have 0-7 parameters. All other types have zero. | ||
237 | */ | ||
238 | param_count = 0; | ||
239 | if (node->type == ACPI_TYPE_METHOD) { | ||
240 | param_count = node->object->method.param_count; | ||
241 | } | ||
242 | |||
243 | /* Validate parameter count - allow two different legal counts (_SCP) */ | ||
244 | |||
245 | required_params_current = predefined->info.param_count & 0x0F; | ||
246 | required_params_old = predefined->info.param_count >> 4; | ||
247 | |||
248 | if ((param_count != required_params_current) && | ||
249 | (param_count != required_params_old)) { | ||
250 | ACPI_WARNING((AE_INFO, | ||
251 | "%s: Parameter count mismatch - ASL declared %d, expected %d", | ||
252 | pathname, param_count, required_params_current)); | ||
253 | } | ||
254 | } | ||
255 | |||
256 | /******************************************************************************* | ||
257 | * | ||
258 | * FUNCTION: acpi_ns_check_for_predefined_name | ||
259 | * | ||
260 | * PARAMETERS: Node - Namespace node for the method/object | ||
261 | * | ||
262 | * RETURN: Pointer to entry in predefined table. NULL indicates not found. | ||
263 | * | ||
264 | * DESCRIPTION: Check an object name against the predefined object list. | ||
265 | * | ||
266 | ******************************************************************************/ | ||
267 | |||
268 | const union acpi_predefined_info *acpi_ns_check_for_predefined_name(struct | ||
269 | acpi_namespace_node | ||
270 | *node) | ||
271 | { | ||
272 | const union acpi_predefined_info *this_name; | ||
273 | |||
274 | /* Quick check for a predefined name, first character must be underscore */ | ||
275 | |||
276 | if (node->name.ascii[0] != '_') { | ||
277 | return (NULL); | ||
278 | } | ||
279 | |||
280 | /* Search info table for a predefined method/object name */ | ||
281 | |||
282 | this_name = predefined_names; | ||
283 | while (this_name->info.name[0]) { | ||
284 | if (ACPI_COMPARE_NAME(node->name.ascii, this_name->info.name)) { | ||
285 | |||
286 | /* Return pointer to this table entry */ | ||
287 | |||
288 | return (this_name); | ||
289 | } | ||
290 | |||
291 | /* | ||
292 | * Skip next entry in the table if this name returns a Package | ||
293 | * (next entry contains the package info) | ||
294 | */ | ||
295 | if (this_name->info.expected_btypes & ACPI_RTYPE_PACKAGE) { | ||
296 | this_name++; | ||
297 | } | ||
298 | |||
299 | this_name++; | ||
300 | } | ||
301 | |||
302 | return (NULL); | ||
303 | } | ||
304 | |||
305 | /******************************************************************************* | ||
306 | * | ||
307 | * FUNCTION: acpi_ns_check_package | ||
308 | * | ||
309 | * PARAMETERS: Pathname - Full pathname to the node (for error msgs) | ||
310 | * return_object - Object returned from the evaluation of a | ||
311 | * method or object | ||
312 | * Predefined - Pointer to entry in predefined name table | ||
313 | * | ||
314 | * RETURN: Status | ||
315 | * | ||
316 | * DESCRIPTION: Check a returned package object for the correct count and | ||
317 | * correct type of all sub-objects. | ||
318 | * | ||
319 | ******************************************************************************/ | ||
320 | |||
321 | static acpi_status | ||
322 | acpi_ns_check_package(char *pathname, | ||
323 | union acpi_operand_object *return_object, | ||
324 | const union acpi_predefined_info *predefined) | ||
325 | { | ||
326 | const union acpi_predefined_info *package; | ||
327 | union acpi_operand_object *sub_package; | ||
328 | union acpi_operand_object **elements; | ||
329 | union acpi_operand_object **sub_elements; | ||
330 | acpi_status status; | ||
331 | u32 expected_count; | ||
332 | u32 count; | ||
333 | u32 i; | ||
334 | u32 j; | ||
335 | |||
336 | ACPI_FUNCTION_NAME(ns_check_package); | ||
337 | |||
338 | /* The package info for this name is in the next table entry */ | ||
339 | |||
340 | package = predefined + 1; | ||
341 | |||
342 | ACPI_DEBUG_PRINT((ACPI_DB_NAMES, | ||
343 | "%s Validating return Package of Type %X, Count %X\n", | ||
344 | pathname, package->ret_info.type, | ||
345 | return_object->package.count)); | ||
346 | |||
347 | /* Extract package count and elements array */ | ||
348 | |||
349 | elements = return_object->package.elements; | ||
350 | count = return_object->package.count; | ||
351 | |||
352 | /* The package must have at least one element, else invalid */ | ||
353 | |||
354 | if (!count) { | ||
355 | ACPI_WARNING((AE_INFO, | ||
356 | "%s: Return Package has no elements (empty)", | ||
357 | pathname)); | ||
358 | |||
359 | return (AE_AML_OPERAND_VALUE); | ||
360 | } | ||
361 | |||
362 | /* | ||
363 | * Decode the type of the expected package contents | ||
364 | * | ||
365 | * PTYPE1 packages contain no subpackages | ||
366 | * PTYPE2 packages contain sub-packages | ||
367 | */ | ||
368 | switch (package->ret_info.type) { | ||
369 | case ACPI_PTYPE1_FIXED: | ||
370 | |||
371 | /* | ||
372 | * The package count is fixed and there are no sub-packages | ||
373 | * | ||
374 | * If package is too small, exit. | ||
375 | * If package is larger than expected, issue warning but continue | ||
376 | */ | ||
377 | expected_count = | ||
378 | package->ret_info.count1 + package->ret_info.count2; | ||
379 | if (count < expected_count) { | ||
380 | goto package_too_small; | ||
381 | } else if (count > expected_count) { | ||
382 | ACPI_WARNING((AE_INFO, | ||
383 | "%s: Return Package is larger than needed - " | ||
384 | "found %u, expected %u", pathname, count, | ||
385 | expected_count)); | ||
386 | } | ||
387 | |||
388 | /* Validate all elements of the returned package */ | ||
389 | |||
390 | status = acpi_ns_check_package_elements(pathname, elements, | ||
391 | package->ret_info. | ||
392 | object_type1, | ||
393 | package->ret_info. | ||
394 | count1, | ||
395 | package->ret_info. | ||
396 | object_type2, | ||
397 | package->ret_info. | ||
398 | count2); | ||
399 | if (ACPI_FAILURE(status)) { | ||
400 | return (status); | ||
401 | } | ||
402 | break; | ||
403 | |||
404 | case ACPI_PTYPE1_VAR: | ||
405 | |||
406 | /* | ||
407 | * The package count is variable, there are no sub-packages, and all | ||
408 | * elements must be of the same type | ||
409 | */ | ||
410 | for (i = 0; i < count; i++) { | ||
411 | status = acpi_ns_check_object_type(pathname, *elements, | ||
412 | package->ret_info. | ||
413 | object_type1, i); | ||
414 | if (ACPI_FAILURE(status)) { | ||
415 | return (status); | ||
416 | } | ||
417 | elements++; | ||
418 | } | ||
419 | break; | ||
420 | |||
421 | case ACPI_PTYPE1_OPTION: | ||
422 | |||
423 | /* | ||
424 | * The package count is variable, there are no sub-packages. There are | ||
425 | * a fixed number of required elements, and a variable number of | ||
426 | * optional elements. | ||
427 | * | ||
428 | * Check if package is at least as large as the minimum required | ||
429 | */ | ||
430 | expected_count = package->ret_info3.count; | ||
431 | if (count < expected_count) { | ||
432 | goto package_too_small; | ||
433 | } | ||
434 | |||
435 | /* Variable number of sub-objects */ | ||
436 | |||
437 | for (i = 0; i < count; i++) { | ||
438 | if (i < package->ret_info3.count) { | ||
439 | |||
440 | /* These are the required package elements (0, 1, or 2) */ | ||
441 | |||
442 | status = | ||
443 | acpi_ns_check_object_type(pathname, | ||
444 | *elements, | ||
445 | package-> | ||
446 | ret_info3. | ||
447 | object_type[i], | ||
448 | i); | ||
449 | if (ACPI_FAILURE(status)) { | ||
450 | return (status); | ||
451 | } | ||
452 | } else { | ||
453 | /* These are the optional package elements */ | ||
454 | |||
455 | status = | ||
456 | acpi_ns_check_object_type(pathname, | ||
457 | *elements, | ||
458 | package-> | ||
459 | ret_info3. | ||
460 | tail_object_type, | ||
461 | i); | ||
462 | if (ACPI_FAILURE(status)) { | ||
463 | return (status); | ||
464 | } | ||
465 | } | ||
466 | elements++; | ||
467 | } | ||
468 | break; | ||
469 | |||
470 | case ACPI_PTYPE2_PKG_COUNT: | ||
471 | |||
472 | /* First element is the (Integer) count of sub-packages to follow */ | ||
473 | |||
474 | status = acpi_ns_check_object_type(pathname, *elements, | ||
475 | ACPI_RTYPE_INTEGER, 0); | ||
476 | if (ACPI_FAILURE(status)) { | ||
477 | return (status); | ||
478 | } | ||
479 | |||
480 | /* | ||
481 | * Count cannot be larger than the parent package length, but allow it | ||
482 | * to be smaller. The >= accounts for the Integer above. | ||
483 | */ | ||
484 | expected_count = (u32) (*elements)->integer.value; | ||
485 | if (expected_count >= count) { | ||
486 | goto package_too_small; | ||
487 | } | ||
488 | |||
489 | count = expected_count; | ||
490 | elements++; | ||
491 | |||
492 | /* Now we can walk the sub-packages */ | ||
493 | |||
494 | /*lint -fallthrough */ | ||
495 | |||
496 | case ACPI_PTYPE2: | ||
497 | case ACPI_PTYPE2_FIXED: | ||
498 | case ACPI_PTYPE2_MIN: | ||
499 | case ACPI_PTYPE2_COUNT: | ||
500 | |||
501 | /* | ||
502 | * These types all return a single package that consists of a variable | ||
503 | * number of sub-packages | ||
504 | */ | ||
505 | for (i = 0; i < count; i++) { | ||
506 | sub_package = *elements; | ||
507 | sub_elements = sub_package->package.elements; | ||
508 | |||
509 | /* Each sub-object must be of type Package */ | ||
510 | |||
511 | status = | ||
512 | acpi_ns_check_object_type(pathname, sub_package, | ||
513 | ACPI_RTYPE_PACKAGE, i); | ||
514 | if (ACPI_FAILURE(status)) { | ||
515 | return (status); | ||
516 | } | ||
517 | |||
518 | /* Examine the different types of sub-packages */ | ||
519 | |||
520 | switch (package->ret_info.type) { | ||
521 | case ACPI_PTYPE2: | ||
522 | case ACPI_PTYPE2_PKG_COUNT: | ||
523 | |||
524 | /* Each subpackage has a fixed number of elements */ | ||
525 | |||
526 | expected_count = | ||
527 | package->ret_info.count1 + | ||
528 | package->ret_info.count2; | ||
529 | if (sub_package->package.count != | ||
530 | expected_count) { | ||
531 | count = sub_package->package.count; | ||
532 | goto package_too_small; | ||
533 | } | ||
534 | |||
535 | status = | ||
536 | acpi_ns_check_package_elements(pathname, | ||
537 | sub_elements, | ||
538 | package-> | ||
539 | ret_info. | ||
540 | object_type1, | ||
541 | package-> | ||
542 | ret_info. | ||
543 | count1, | ||
544 | package-> | ||
545 | ret_info. | ||
546 | object_type2, | ||
547 | package-> | ||
548 | ret_info. | ||
549 | count2); | ||
550 | if (ACPI_FAILURE(status)) { | ||
551 | return (status); | ||
552 | } | ||
553 | break; | ||
554 | |||
555 | case ACPI_PTYPE2_FIXED: | ||
556 | |||
557 | /* Each sub-package has a fixed length */ | ||
558 | |||
559 | expected_count = package->ret_info2.count; | ||
560 | if (sub_package->package.count < expected_count) { | ||
561 | count = sub_package->package.count; | ||
562 | goto package_too_small; | ||
563 | } | ||
564 | |||
565 | /* Check the type of each sub-package element */ | ||
566 | |||
567 | for (j = 0; j < expected_count; j++) { | ||
568 | status = | ||
569 | acpi_ns_check_object_type(pathname, | ||
570 | sub_elements | ||
571 | [j], | ||
572 | package-> | ||
573 | ret_info2. | ||
574 | object_type | ||
575 | [j], j); | ||
576 | if (ACPI_FAILURE(status)) { | ||
577 | return (status); | ||
578 | } | ||
579 | } | ||
580 | break; | ||
581 | |||
582 | case ACPI_PTYPE2_MIN: | ||
583 | |||
584 | /* Each sub-package has a variable but minimum length */ | ||
585 | |||
586 | expected_count = package->ret_info.count1; | ||
587 | if (sub_package->package.count < expected_count) { | ||
588 | count = sub_package->package.count; | ||
589 | goto package_too_small; | ||
590 | } | ||
591 | |||
592 | /* Check the type of each sub-package element */ | ||
593 | |||
594 | status = | ||
595 | acpi_ns_check_package_elements(pathname, | ||
596 | sub_elements, | ||
597 | package-> | ||
598 | ret_info. | ||
599 | object_type1, | ||
600 | sub_package-> | ||
601 | package. | ||
602 | count, 0, 0); | ||
603 | if (ACPI_FAILURE(status)) { | ||
604 | return (status); | ||
605 | } | ||
606 | break; | ||
607 | |||
608 | case ACPI_PTYPE2_COUNT: | ||
609 | |||
610 | /* First element is the (Integer) count of elements to follow */ | ||
611 | |||
612 | status = | ||
613 | acpi_ns_check_object_type(pathname, | ||
614 | *sub_elements, | ||
615 | ACPI_RTYPE_INTEGER, | ||
616 | 0); | ||
617 | if (ACPI_FAILURE(status)) { | ||
618 | return (status); | ||
619 | } | ||
620 | |||
621 | /* Make sure package is large enough for the Count */ | ||
622 | |||
623 | expected_count = | ||
624 | (u32) (*sub_elements)->integer.value; | ||
625 | if (sub_package->package.count < expected_count) { | ||
626 | count = sub_package->package.count; | ||
627 | goto package_too_small; | ||
628 | } | ||
629 | |||
630 | /* Check the type of each sub-package element */ | ||
631 | |||
632 | status = | ||
633 | acpi_ns_check_package_elements(pathname, | ||
634 | (sub_elements | ||
635 | + 1), | ||
636 | package-> | ||
637 | ret_info. | ||
638 | object_type1, | ||
639 | (expected_count | ||
640 | - 1), 0, 0); | ||
641 | if (ACPI_FAILURE(status)) { | ||
642 | return (status); | ||
643 | } | ||
644 | break; | ||
645 | |||
646 | default: | ||
647 | break; | ||
648 | } | ||
649 | |||
650 | elements++; | ||
651 | } | ||
652 | break; | ||
653 | |||
654 | default: | ||
655 | |||
656 | /* Should not get here if predefined info table is correct */ | ||
657 | |||
658 | ACPI_WARNING((AE_INFO, | ||
659 | "%s: Invalid internal return type in table entry: %X", | ||
660 | pathname, package->ret_info.type)); | ||
661 | |||
662 | return (AE_AML_INTERNAL); | ||
663 | } | ||
664 | |||
665 | return (AE_OK); | ||
666 | |||
667 | package_too_small: | ||
668 | |||
669 | /* Error exit for the case with an incorrect package count */ | ||
670 | |||
671 | ACPI_WARNING((AE_INFO, "%s: Return Package is too small - " | ||
672 | "found %u, expected %u", pathname, count, | ||
673 | expected_count)); | ||
674 | |||
675 | return (AE_AML_OPERAND_VALUE); | ||
676 | } | ||
677 | |||
678 | /******************************************************************************* | ||
679 | * | ||
680 | * FUNCTION: acpi_ns_check_package_elements | ||
681 | * | ||
682 | * PARAMETERS: Pathname - Full pathname to the node (for error msgs) | ||
683 | * Elements - Pointer to the package elements array | ||
684 | * Type1 - Object type for first group | ||
685 | * Count1 - Count for first group | ||
686 | * Type2 - Object type for second group | ||
687 | * Count2 - Count for second group | ||
688 | * | ||
689 | * RETURN: Status | ||
690 | * | ||
691 | * DESCRIPTION: Check that all elements of a package are of the correct object | ||
692 | * type. Supports up to two groups of different object types. | ||
693 | * | ||
694 | ******************************************************************************/ | ||
695 | |||
696 | static acpi_status | ||
697 | acpi_ns_check_package_elements(char *pathname, | ||
698 | union acpi_operand_object **elements, | ||
699 | u8 type1, u32 count1, u8 type2, u32 count2) | ||
700 | { | ||
701 | union acpi_operand_object **this_element = elements; | ||
702 | acpi_status status; | ||
703 | u32 i; | ||
704 | |||
705 | /* | ||
706 | * Up to two groups of package elements are supported by the data | ||
707 | * structure. All elements in each group must be of the same type. | ||
708 | * The second group can have a count of zero. | ||
709 | */ | ||
710 | for (i = 0; i < count1; i++) { | ||
711 | status = acpi_ns_check_object_type(pathname, *this_element, | ||
712 | type1, i); | ||
713 | if (ACPI_FAILURE(status)) { | ||
714 | return (status); | ||
715 | } | ||
716 | this_element++; | ||
717 | } | ||
718 | |||
719 | for (i = 0; i < count2; i++) { | ||
720 | status = acpi_ns_check_object_type(pathname, *this_element, | ||
721 | type2, (i + count1)); | ||
722 | if (ACPI_FAILURE(status)) { | ||
723 | return (status); | ||
724 | } | ||
725 | this_element++; | ||
726 | } | ||
727 | |||
728 | return (AE_OK); | ||
729 | } | ||
730 | |||
731 | /******************************************************************************* | ||
732 | * | ||
733 | * FUNCTION: acpi_ns_check_object_type | ||
734 | * | ||
735 | * PARAMETERS: Pathname - Full pathname to the node (for error msgs) | ||
736 | * return_object - Object return from the execution of this | ||
737 | * method/object | ||
738 | * expected_btypes - Bitmap of expected return type(s) | ||
739 | * package_index - Index of object within parent package (if | ||
740 | * applicable - ACPI_NOT_PACKAGE otherwise) | ||
741 | * | ||
742 | * RETURN: Status | ||
743 | * | ||
744 | * DESCRIPTION: Check the type of the return object against the expected object | ||
745 | * type(s). Use of Btype allows multiple expected object types. | ||
746 | * | ||
747 | ******************************************************************************/ | ||
748 | |||
749 | static acpi_status | ||
750 | acpi_ns_check_object_type(char *pathname, | ||
751 | union acpi_operand_object *return_object, | ||
752 | u32 expected_btypes, u32 package_index) | ||
753 | { | ||
754 | acpi_status status = AE_OK; | ||
755 | u32 return_btype; | ||
756 | char type_buffer[48]; /* Room for 5 types */ | ||
757 | u32 this_rtype; | ||
758 | u32 i; | ||
759 | u32 j; | ||
760 | |||
761 | /* | ||
762 | * If we get a NULL return_object here, it is a NULL package element, | ||
763 | * and this is always an error. | ||
764 | */ | ||
765 | if (!return_object) { | ||
766 | goto type_error_exit; | ||
767 | } | ||
768 | |||
769 | /* A Namespace node should not get here, but make sure */ | ||
770 | |||
771 | if (ACPI_GET_DESCRIPTOR_TYPE(return_object) == ACPI_DESC_TYPE_NAMED) { | ||
772 | ACPI_WARNING((AE_INFO, | ||
773 | "%s: Invalid return type - Found a Namespace node [%4.4s] type %s", | ||
774 | pathname, return_object->node.name.ascii, | ||
775 | acpi_ut_get_type_name(return_object->node.type))); | ||
776 | return (AE_AML_OPERAND_TYPE); | ||
777 | } | ||
778 | |||
779 | /* | ||
780 | * Convert the object type (ACPI_TYPE_xxx) to a bitmapped object type. | ||
781 | * The bitmapped type allows multiple possible return types. | ||
782 | * | ||
783 | * Note, the cases below must handle all of the possible types returned | ||
784 | * from all of the predefined names (including elements of returned | ||
785 | * packages) | ||
786 | */ | ||
787 | switch (ACPI_GET_OBJECT_TYPE(return_object)) { | ||
788 | case ACPI_TYPE_INTEGER: | ||
789 | return_btype = ACPI_RTYPE_INTEGER; | ||
790 | break; | ||
791 | |||
792 | case ACPI_TYPE_BUFFER: | ||
793 | return_btype = ACPI_RTYPE_BUFFER; | ||
794 | break; | ||
795 | |||
796 | case ACPI_TYPE_STRING: | ||
797 | return_btype = ACPI_RTYPE_STRING; | ||
798 | break; | ||
799 | |||
800 | case ACPI_TYPE_PACKAGE: | ||
801 | return_btype = ACPI_RTYPE_PACKAGE; | ||
802 | break; | ||
803 | |||
804 | case ACPI_TYPE_LOCAL_REFERENCE: | ||
805 | return_btype = ACPI_RTYPE_REFERENCE; | ||
806 | break; | ||
807 | |||
808 | default: | ||
809 | /* Not one of the supported objects, must be incorrect */ | ||
810 | |||
811 | goto type_error_exit; | ||
812 | } | ||
813 | |||
814 | /* Is the object one of the expected types? */ | ||
815 | |||
816 | if (!(return_btype & expected_btypes)) { | ||
817 | goto type_error_exit; | ||
818 | } | ||
819 | |||
820 | /* For reference objects, check that the reference type is correct */ | ||
821 | |||
822 | if (ACPI_GET_OBJECT_TYPE(return_object) == ACPI_TYPE_LOCAL_REFERENCE) { | ||
823 | status = acpi_ns_check_reference(pathname, return_object); | ||
824 | } | ||
825 | |||
826 | return (status); | ||
827 | |||
828 | type_error_exit: | ||
829 | |||
830 | /* Create a string with all expected types for this predefined object */ | ||
831 | |||
832 | j = 1; | ||
833 | type_buffer[0] = 0; | ||
834 | this_rtype = ACPI_RTYPE_INTEGER; | ||
835 | |||
836 | for (i = 0; i < ACPI_NUM_RTYPES; i++) { | ||
837 | |||
838 | /* If one of the expected types, concatenate the name of this type */ | ||
839 | |||
840 | if (expected_btypes & this_rtype) { | ||
841 | ACPI_STRCAT(type_buffer, &acpi_rtype_names[i][j]); | ||
842 | j = 0; /* Use name separator from now on */ | ||
843 | } | ||
844 | this_rtype <<= 1; /* Next Rtype */ | ||
845 | } | ||
846 | |||
847 | if (package_index == ACPI_NOT_PACKAGE) { | ||
848 | ACPI_WARNING((AE_INFO, | ||
849 | "%s: Return type mismatch - found %s, expected %s", | ||
850 | pathname, | ||
851 | acpi_ut_get_object_type_name(return_object), | ||
852 | type_buffer)); | ||
853 | } else { | ||
854 | ACPI_WARNING((AE_INFO, | ||
855 | "%s: Return Package type mismatch at index %u - " | ||
856 | "found %s, expected %s", pathname, package_index, | ||
857 | acpi_ut_get_object_type_name(return_object), | ||
858 | type_buffer)); | ||
859 | } | ||
860 | |||
861 | return (AE_AML_OPERAND_TYPE); | ||
862 | } | ||
863 | |||
864 | /******************************************************************************* | ||
865 | * | ||
866 | * FUNCTION: acpi_ns_check_reference | ||
867 | * | ||
868 | * PARAMETERS: Pathname - Full pathname to the node (for error msgs) | ||
869 | * return_object - Object returned from the evaluation of a | ||
870 | * method or object | ||
871 | * | ||
872 | * RETURN: Status | ||
873 | * | ||
874 | * DESCRIPTION: Check a returned reference object for the correct reference | ||
875 | * type. The only reference type that can be returned from a | ||
876 | * predefined method is a named reference. All others are invalid. | ||
877 | * | ||
878 | ******************************************************************************/ | ||
879 | |||
880 | static acpi_status | ||
881 | acpi_ns_check_reference(char *pathname, | ||
882 | union acpi_operand_object *return_object) | ||
883 | { | ||
884 | |||
885 | /* | ||
886 | * Check the reference object for the correct reference type (opcode). | ||
887 | * The only type of reference that can be converted to an union acpi_object is | ||
888 | * a reference to a named object (reference class: NAME) | ||
889 | */ | ||
890 | if (return_object->reference.class == ACPI_REFCLASS_NAME) { | ||
891 | return (AE_OK); | ||
892 | } | ||
893 | |||
894 | ACPI_WARNING((AE_INFO, | ||
895 | "%s: Return type mismatch - unexpected reference object type [%s] %2.2X", | ||
896 | pathname, acpi_ut_get_reference_name(return_object), | ||
897 | return_object->reference.class)); | ||
898 | |||
899 | return (AE_AML_OPERAND_TYPE); | ||
900 | } | ||
diff --git a/drivers/acpi/namespace/nssearch.c b/drivers/acpi/namespace/nssearch.c index 8399276cba1e..a9a80bf811b3 100644 --- a/drivers/acpi/namespace/nssearch.c +++ b/drivers/acpi/namespace/nssearch.c | |||
@@ -331,7 +331,7 @@ acpi_ns_search_and_enter(u32 target_name, | |||
331 | "Found bad character(s) in name, repaired: [%4.4s]\n", | 331 | "Found bad character(s) in name, repaired: [%4.4s]\n", |
332 | ACPI_CAST_PTR(char, &target_name))); | 332 | ACPI_CAST_PTR(char, &target_name))); |
333 | } else { | 333 | } else { |
334 | ACPI_DEBUG_PRINT((ACPI_DB_WARN, | 334 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, |
335 | "Found bad character(s) in name, repaired: [%4.4s]\n", | 335 | "Found bad character(s) in name, repaired: [%4.4s]\n", |
336 | ACPI_CAST_PTR(char, &target_name))); | 336 | ACPI_CAST_PTR(char, &target_name))); |
337 | } | 337 | } |
diff --git a/drivers/acpi/namespace/nsxfeval.c b/drivers/acpi/namespace/nsxfeval.c index 38be5865d95d..a085cc39c055 100644 --- a/drivers/acpi/namespace/nsxfeval.c +++ b/drivers/acpi/namespace/nsxfeval.c | |||
@@ -48,6 +48,10 @@ | |||
48 | 48 | ||
49 | #define _COMPONENT ACPI_NAMESPACE | 49 | #define _COMPONENT ACPI_NAMESPACE |
50 | ACPI_MODULE_NAME("nsxfeval") | 50 | ACPI_MODULE_NAME("nsxfeval") |
51 | |||
52 | /* Local prototypes */ | ||
53 | static void acpi_ns_resolve_references(struct acpi_evaluate_info *info); | ||
54 | |||
51 | #ifdef ACPI_FUTURE_USAGE | 55 | #ifdef ACPI_FUTURE_USAGE |
52 | /******************************************************************************* | 56 | /******************************************************************************* |
53 | * | 57 | * |
@@ -69,6 +73,7 @@ ACPI_MODULE_NAME("nsxfeval") | |||
69 | * be valid (non-null) | 73 | * be valid (non-null) |
70 | * | 74 | * |
71 | ******************************************************************************/ | 75 | ******************************************************************************/ |
76 | |||
72 | acpi_status | 77 | acpi_status |
73 | acpi_evaluate_object_typed(acpi_handle handle, | 78 | acpi_evaluate_object_typed(acpi_handle handle, |
74 | acpi_string pathname, | 79 | acpi_string pathname, |
@@ -283,6 +288,10 @@ acpi_evaluate_object(acpi_handle handle, | |||
283 | 288 | ||
284 | if (ACPI_SUCCESS(status)) { | 289 | if (ACPI_SUCCESS(status)) { |
285 | 290 | ||
291 | /* Dereference Index and ref_of references */ | ||
292 | |||
293 | acpi_ns_resolve_references(info); | ||
294 | |||
286 | /* Get the size of the returned object */ | 295 | /* Get the size of the returned object */ |
287 | 296 | ||
288 | status = | 297 | status = |
@@ -352,6 +361,74 @@ ACPI_EXPORT_SYMBOL(acpi_evaluate_object) | |||
352 | 361 | ||
353 | /******************************************************************************* | 362 | /******************************************************************************* |
354 | * | 363 | * |
364 | * FUNCTION: acpi_ns_resolve_references | ||
365 | * | ||
366 | * PARAMETERS: Info - Evaluation info block | ||
367 | * | ||
368 | * RETURN: Info->return_object is replaced with the dereferenced object | ||
369 | * | ||
370 | * DESCRIPTION: Dereference certain reference objects. Called before an | ||
371 | * internal return object is converted to an external union acpi_object. | ||
372 | * | ||
373 | * Performs an automatic dereference of Index and ref_of reference objects. | ||
374 | * These reference objects are not supported by the union acpi_object, so this is a | ||
375 | * last resort effort to return something useful. Also, provides compatibility | ||
376 | * with other ACPI implementations. | ||
377 | * | ||
378 | * NOTE: does not handle references within returned package objects or nested | ||
379 | * references, but this support could be added later if found to be necessary. | ||
380 | * | ||
381 | ******************************************************************************/ | ||
382 | static void acpi_ns_resolve_references(struct acpi_evaluate_info *info) | ||
383 | { | ||
384 | union acpi_operand_object *obj_desc = NULL; | ||
385 | struct acpi_namespace_node *node; | ||
386 | |||
387 | /* We are interested in reference objects only */ | ||
388 | |||
389 | if (ACPI_GET_OBJECT_TYPE(info->return_object) != | ||
390 | ACPI_TYPE_LOCAL_REFERENCE) { | ||
391 | return; | ||
392 | } | ||
393 | |||
394 | /* | ||
395 | * Two types of references are supported - those created by Index and | ||
396 | * ref_of operators. A name reference (AML_NAMEPATH_OP) can be converted | ||
397 | * to an union acpi_object, so it is not dereferenced here. A ddb_handle | ||
398 | * (AML_LOAD_OP) cannot be dereferenced, nor can it be converted to | ||
399 | * an union acpi_object. | ||
400 | */ | ||
401 | switch (info->return_object->reference.class) { | ||
402 | case ACPI_REFCLASS_INDEX: | ||
403 | |||
404 | obj_desc = *(info->return_object->reference.where); | ||
405 | break; | ||
406 | |||
407 | case ACPI_REFCLASS_REFOF: | ||
408 | |||
409 | node = info->return_object->reference.object; | ||
410 | if (node) { | ||
411 | obj_desc = node->object; | ||
412 | } | ||
413 | break; | ||
414 | |||
415 | default: | ||
416 | return; | ||
417 | } | ||
418 | |||
419 | /* Replace the existing reference object */ | ||
420 | |||
421 | if (obj_desc) { | ||
422 | acpi_ut_add_reference(obj_desc); | ||
423 | acpi_ut_remove_reference(info->return_object); | ||
424 | info->return_object = obj_desc; | ||
425 | } | ||
426 | |||
427 | return; | ||
428 | } | ||
429 | |||
430 | /******************************************************************************* | ||
431 | * | ||
355 | * FUNCTION: acpi_walk_namespace | 432 | * FUNCTION: acpi_walk_namespace |
356 | * | 433 | * |
357 | * PARAMETERS: Type - acpi_object_type to search for | 434 | * PARAMETERS: Type - acpi_object_type to search for |
@@ -379,6 +456,7 @@ ACPI_EXPORT_SYMBOL(acpi_evaluate_object) | |||
379 | * function, etc. | 456 | * function, etc. |
380 | * | 457 | * |
381 | ******************************************************************************/ | 458 | ******************************************************************************/ |
459 | |||
382 | acpi_status | 460 | acpi_status |
383 | acpi_walk_namespace(acpi_object_type type, | 461 | acpi_walk_namespace(acpi_object_type type, |
384 | acpi_handle start_object, | 462 | acpi_handle start_object, |
diff --git a/drivers/acpi/namespace/nsxfname.c b/drivers/acpi/namespace/nsxfname.c index a287ed550f54..5efa4e7ddb0b 100644 --- a/drivers/acpi/namespace/nsxfname.c +++ b/drivers/acpi/namespace/nsxfname.c | |||
@@ -253,6 +253,7 @@ acpi_get_object_info(acpi_handle handle, struct acpi_buffer * buffer) | |||
253 | node = acpi_ns_map_handle_to_node(handle); | 253 | node = acpi_ns_map_handle_to_node(handle); |
254 | if (!node) { | 254 | if (!node) { |
255 | (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); | 255 | (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); |
256 | status = AE_BAD_PARAMETER; | ||
256 | goto cleanup; | 257 | goto cleanup; |
257 | } | 258 | } |
258 | 259 | ||
@@ -264,6 +265,10 @@ acpi_get_object_info(acpi_handle handle, struct acpi_buffer * buffer) | |||
264 | info->name = node->name.integer; | 265 | info->name = node->name.integer; |
265 | info->valid = 0; | 266 | info->valid = 0; |
266 | 267 | ||
268 | if (node->type == ACPI_TYPE_METHOD) { | ||
269 | info->param_count = node->object->method.param_count; | ||
270 | } | ||
271 | |||
267 | status = acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); | 272 | status = acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); |
268 | if (ACPI_FAILURE(status)) { | 273 | if (ACPI_FAILURE(status)) { |
269 | goto cleanup; | 274 | goto cleanup; |