diff options
Diffstat (limited to 'drivers/acpi/parser/psargs.c')
-rw-r--r-- | drivers/acpi/parser/psargs.c | 198 |
1 files changed, 106 insertions, 92 deletions
diff --git a/drivers/acpi/parser/psargs.c b/drivers/acpi/parser/psargs.c index 6eae35febccd..e6d4cb9fd303 100644 --- a/drivers/acpi/parser/psargs.c +++ b/drivers/acpi/parser/psargs.c | |||
@@ -45,6 +45,7 @@ | |||
45 | #include <acpi/acparser.h> | 45 | #include <acpi/acparser.h> |
46 | #include <acpi/amlcode.h> | 46 | #include <acpi/amlcode.h> |
47 | #include <acpi/acnamesp.h> | 47 | #include <acpi/acnamesp.h> |
48 | #include <acpi/acdispat.h> | ||
48 | 49 | ||
49 | #define _COMPONENT ACPI_PARSER | 50 | #define _COMPONENT ACPI_PARSER |
50 | ACPI_MODULE_NAME("psargs") | 51 | ACPI_MODULE_NAME("psargs") |
@@ -211,7 +212,7 @@ char *acpi_ps_get_next_namestring(struct acpi_parse_state *parser_state) | |||
211 | * Arg - Where the namepath will be stored | 212 | * Arg - Where the namepath will be stored |
212 | * arg_count - If the namepath points to a control method | 213 | * arg_count - If the namepath points to a control method |
213 | * the method's argument is returned here. | 214 | * the method's argument is returned here. |
214 | * method_call - Whether the namepath can possibly be the | 215 | * possible_method_call - Whether the namepath can possibly be the |
215 | * start of a method call | 216 | * start of a method call |
216 | * | 217 | * |
217 | * RETURN: Status | 218 | * RETURN: Status |
@@ -227,11 +228,11 @@ char *acpi_ps_get_next_namestring(struct acpi_parse_state *parser_state) | |||
227 | acpi_status | 228 | acpi_status |
228 | acpi_ps_get_next_namepath(struct acpi_walk_state *walk_state, | 229 | acpi_ps_get_next_namepath(struct acpi_walk_state *walk_state, |
229 | struct acpi_parse_state *parser_state, | 230 | struct acpi_parse_state *parser_state, |
230 | union acpi_parse_object *arg, u8 method_call) | 231 | union acpi_parse_object *arg, u8 possible_method_call) |
231 | { | 232 | { |
232 | char *path; | 233 | char *path; |
233 | union acpi_parse_object *name_op; | 234 | union acpi_parse_object *name_op; |
234 | acpi_status status = AE_OK; | 235 | acpi_status status; |
235 | union acpi_operand_object *method_desc; | 236 | union acpi_operand_object *method_desc; |
236 | struct acpi_namespace_node *node; | 237 | struct acpi_namespace_node *node; |
237 | union acpi_generic_state scope_info; | 238 | union acpi_generic_state scope_info; |
@@ -239,114 +240,127 @@ acpi_ps_get_next_namepath(struct acpi_walk_state *walk_state, | |||
239 | ACPI_FUNCTION_TRACE("ps_get_next_namepath"); | 240 | ACPI_FUNCTION_TRACE("ps_get_next_namepath"); |
240 | 241 | ||
241 | path = acpi_ps_get_next_namestring(parser_state); | 242 | path = acpi_ps_get_next_namestring(parser_state); |
243 | acpi_ps_init_op(arg, AML_INT_NAMEPATH_OP); | ||
242 | 244 | ||
243 | /* Null path case is allowed */ | 245 | /* Null path case is allowed, just exit */ |
244 | 246 | ||
245 | if (path) { | 247 | if (!path) { |
246 | /* | 248 | arg->common.value.name = path; |
247 | * Lookup the name in the internal namespace | 249 | return_ACPI_STATUS(AE_OK); |
248 | */ | 250 | } |
249 | scope_info.scope.node = NULL; | ||
250 | node = parser_state->start_node; | ||
251 | if (node) { | ||
252 | scope_info.scope.node = node; | ||
253 | } | ||
254 | 251 | ||
255 | /* | 252 | /* Setup search scope info */ |
256 | * Lookup object. We don't want to add anything new to the namespace | 253 | |
257 | * here, however. So we use MODE_EXECUTE. Allow searching of the | 254 | scope_info.scope.node = NULL; |
258 | * parent tree, but don't open a new scope -- we just want to lookup the | 255 | node = parser_state->start_node; |
259 | * object (MUST BE mode EXECUTE to perform upsearch) | 256 | if (node) { |
260 | */ | 257 | scope_info.scope.node = node; |
261 | status = acpi_ns_lookup(&scope_info, path, ACPI_TYPE_ANY, | 258 | } |
262 | ACPI_IMODE_EXECUTE, | ||
263 | ACPI_NS_SEARCH_PARENT | | ||
264 | ACPI_NS_DONT_OPEN_SCOPE, NULL, &node); | ||
265 | if (ACPI_SUCCESS(status) && method_call) { | ||
266 | if (node->type == ACPI_TYPE_METHOD) { | ||
267 | /* This name is actually a control method invocation */ | ||
268 | |||
269 | method_desc = acpi_ns_get_attached_object(node); | ||
270 | ACPI_DEBUG_PRINT((ACPI_DB_PARSE, | ||
271 | "Control Method - %p Desc %p Path=%p\n", | ||
272 | node, method_desc, path)); | ||
273 | |||
274 | name_op = acpi_ps_alloc_op(AML_INT_NAMEPATH_OP); | ||
275 | if (!name_op) { | ||
276 | return_ACPI_STATUS(AE_NO_MEMORY); | ||
277 | } | ||
278 | 259 | ||
279 | /* Change arg into a METHOD CALL and attach name to it */ | 260 | /* |
261 | * Lookup the name in the internal namespace. We don't want to add | ||
262 | * anything new to the namespace here, however, so we use MODE_EXECUTE. | ||
263 | * Allow searching of the parent tree, but don't open a new scope - | ||
264 | * we just want to lookup the object (must be mode EXECUTE to perform | ||
265 | * the upsearch) | ||
266 | */ | ||
267 | status = | ||
268 | acpi_ns_lookup(&scope_info, path, ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE, | ||
269 | ACPI_NS_SEARCH_PARENT | ACPI_NS_DONT_OPEN_SCOPE, | ||
270 | NULL, &node); | ||
280 | 271 | ||
281 | acpi_ps_init_op(arg, AML_INT_METHODCALL_OP); | 272 | /* |
282 | name_op->common.value.name = path; | 273 | * If this name is a control method invocation, we must |
274 | * setup the method call | ||
275 | */ | ||
276 | if (ACPI_SUCCESS(status) && | ||
277 | possible_method_call && (node->type == ACPI_TYPE_METHOD)) { | ||
278 | /* This name is actually a control method invocation */ | ||
283 | 279 | ||
284 | /* Point METHODCALL/NAME to the METHOD Node */ | 280 | method_desc = acpi_ns_get_attached_object(node); |
281 | ACPI_DEBUG_PRINT((ACPI_DB_PARSE, | ||
282 | "Control Method - %p Desc %p Path=%p\n", node, | ||
283 | method_desc, path)); | ||
285 | 284 | ||
286 | name_op->common.node = node; | 285 | name_op = acpi_ps_alloc_op(AML_INT_NAMEPATH_OP); |
287 | acpi_ps_append_arg(arg, name_op); | 286 | if (!name_op) { |
287 | return_ACPI_STATUS(AE_NO_MEMORY); | ||
288 | } | ||
288 | 289 | ||
289 | if (!method_desc) { | 290 | /* Change Arg into a METHOD CALL and attach name to it */ |
290 | ACPI_REPORT_ERROR(("ps_get_next_namepath: Control Method %p has no attached object\n", node)); | ||
291 | return_ACPI_STATUS(AE_AML_INTERNAL); | ||
292 | } | ||
293 | 291 | ||
294 | ACPI_DEBUG_PRINT((ACPI_DB_PARSE, | 292 | acpi_ps_init_op(arg, AML_INT_METHODCALL_OP); |
295 | "Control Method - %p Args %X\n", | 293 | name_op->common.value.name = path; |
296 | node, | ||
297 | method_desc->method. | ||
298 | param_count)); | ||
299 | 294 | ||
300 | /* Get the number of arguments to expect */ | 295 | /* Point METHODCALL/NAME to the METHOD Node */ |
301 | 296 | ||
302 | walk_state->arg_count = | 297 | name_op->common.node = node; |
303 | method_desc->method.param_count; | 298 | acpi_ps_append_arg(arg, name_op); |
304 | return_ACPI_STATUS(AE_OK); | ||
305 | } | ||
306 | 299 | ||
307 | /* | 300 | if (!method_desc) { |
308 | * Else this is normal named object reference. | 301 | ACPI_REPORT_ERROR(("ps_get_next_namepath: Control Method %p has no attached object\n", node)); |
309 | * Just init the NAMEPATH object with the pathname. | 302 | return_ACPI_STATUS(AE_AML_INTERNAL); |
310 | * (See code below) | ||
311 | */ | ||
312 | } | 303 | } |
313 | 304 | ||
314 | if (ACPI_FAILURE(status)) { | 305 | ACPI_DEBUG_PRINT((ACPI_DB_PARSE, |
315 | /* | 306 | "Control Method - %p Args %X\n", |
316 | * 1) Any error other than NOT_FOUND is always severe | 307 | node, method_desc->method.param_count)); |
317 | * 2) NOT_FOUND is only important if we are executing a method. | 308 | |
318 | * 3) If executing a cond_ref_of opcode, NOT_FOUND is ok. | 309 | /* Get the number of arguments to expect */ |
319 | */ | 310 | |
320 | if ((((walk_state-> | 311 | walk_state->arg_count = method_desc->method.param_count; |
321 | parse_flags & ACPI_PARSE_MODE_MASK) == | 312 | return_ACPI_STATUS(AE_OK); |
322 | ACPI_PARSE_EXECUTE) && (status == AE_NOT_FOUND) | ||
323 | && (walk_state->op->common.aml_opcode != | ||
324 | AML_COND_REF_OF_OP)) | ||
325 | || (status != AE_NOT_FOUND)) { | ||
326 | ACPI_REPORT_NSERROR(path, status); | ||
327 | |||
328 | acpi_os_printf | ||
329 | ("search_node %p start_node %p return_node %p\n", | ||
330 | scope_info.scope.node, | ||
331 | parser_state->start_node, node); | ||
332 | } else { | ||
333 | /* | ||
334 | * We got a NOT_FOUND during table load or we encountered | ||
335 | * a cond_ref_of(x) where the target does not exist. | ||
336 | * Either case is ok | ||
337 | */ | ||
338 | status = AE_OK; | ||
339 | } | ||
340 | } | ||
341 | } | 313 | } |
342 | 314 | ||
343 | /* | 315 | /* |
344 | * Regardless of success/failure above, | 316 | * Special handling if the name was not found during the lookup - |
345 | * Just initialize the Op with the pathname. | 317 | * some not_found cases are allowed |
346 | */ | 318 | */ |
347 | acpi_ps_init_op(arg, AML_INT_NAMEPATH_OP); | 319 | if (status == AE_NOT_FOUND) { |
348 | arg->common.value.name = path; | 320 | /* 1) not_found is ok during load pass 1/2 (allow forward references) */ |
321 | |||
322 | if ((walk_state->parse_flags & ACPI_PARSE_MODE_MASK) != | ||
323 | ACPI_PARSE_EXECUTE) { | ||
324 | status = AE_OK; | ||
325 | } | ||
326 | |||
327 | /* 2) not_found during a cond_ref_of(x) is ok by definition */ | ||
328 | |||
329 | else if (walk_state->op->common.aml_opcode == | ||
330 | AML_COND_REF_OF_OP) { | ||
331 | status = AE_OK; | ||
332 | } | ||
333 | |||
334 | /* | ||
335 | * 3) not_found while building a Package is ok at this point, we | ||
336 | * may flag as an error later if slack mode is not enabled. | ||
337 | * (Some ASL code depends on allowing this behavior) | ||
338 | */ | ||
339 | else if ((arg->common.parent) && | ||
340 | ((arg->common.parent->common.aml_opcode == | ||
341 | AML_PACKAGE_OP) | ||
342 | || (arg->common.parent->common.aml_opcode == | ||
343 | AML_VAR_PACKAGE_OP))) { | ||
344 | status = AE_OK; | ||
345 | } | ||
346 | } | ||
347 | |||
348 | /* Final exception check (may have been changed from code above) */ | ||
349 | |||
350 | if (ACPI_FAILURE(status)) { | ||
351 | ACPI_REPORT_NSERROR(path, status); | ||
352 | |||
353 | if ((walk_state->parse_flags & ACPI_PARSE_MODE_MASK) == | ||
354 | ACPI_PARSE_EXECUTE) { | ||
355 | /* Report a control method execution error */ | ||
349 | 356 | ||
357 | status = acpi_ds_method_error(status, walk_state); | ||
358 | } | ||
359 | } | ||
360 | |||
361 | /* Save the namepath */ | ||
362 | |||
363 | arg->common.value.name = path; | ||
350 | return_ACPI_STATUS(status); | 364 | return_ACPI_STATUS(status); |
351 | } | 365 | } |
352 | 366 | ||