diff options
author | Bob Moore <robert.moore@intel.com> | 2005-12-16 17:05:00 -0500 |
---|---|---|
committer | Len Brown <len.brown@intel.com> | 2005-12-28 02:54:59 -0500 |
commit | defba1d8f233c0d5cf3e1ea6aeb898eca7231860 (patch) | |
tree | cd8b1b84da8d8a52ad0d44107daaeeee0a0b65f4 /drivers/acpi/parser | |
parent | cb654695f6b912cef7cb3271665b6ee0d416124c (diff) |
[ACPI] ACPICA 20051216
Implemented optional support to allow unresolved names
within ASL Package objects. A null object is inserted in
the package when a named reference cannot be located in
the current namespace. Enabled via the interpreter slack
flag which Linux has enabled by default (acpi=strict
to disable slack). This should eliminate AE_NOT_FOUND
exceptions seen on machines that contain such code.
Implemented an optimization to the initialization
sequence that can improve boot time. During ACPI device
initialization, the _STA method is now run if and only
if the _INI method exists. The _STA method is used to
determine if the device is present; An _INI can only be
run if _STA returns present, but it is a waste of time to
run the _STA method if the _INI does not exist. (Prototype
and assistance from Dong Wei)
Implemented use of the C99 uintptr_t for the pointer
casting macros if it is available in the current
compiler. Otherwise, the default (void *) cast is used
as before.
Fixed some possible memory leaks found within the
execution path of the Break, Continue, If, and CreateField
operators. (Valery Podrezov)
Fixed a problem introduced in the 20051202 release where
an exception is generated during method execution if a
control method attempts to declare another method.
Signed-off-by: Bob Moore <robert.moore@intel.com>
Signed-off-by: Len Brown <len.brown@intel.com>
Diffstat (limited to 'drivers/acpi/parser')
-rw-r--r-- | drivers/acpi/parser/psargs.c | 198 | ||||
-rw-r--r-- | drivers/acpi/parser/psloop.c | 9 | ||||
-rw-r--r-- | drivers/acpi/parser/psparse.c | 17 |
3 files changed, 127 insertions, 97 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 | ||
diff --git a/drivers/acpi/parser/psloop.c b/drivers/acpi/parser/psloop.c index 088d33999d90..e81e51b8b3ae 100644 --- a/drivers/acpi/parser/psloop.c +++ b/drivers/acpi/parser/psloop.c | |||
@@ -704,6 +704,15 @@ acpi_status acpi_ps_parse_loop(struct acpi_walk_state *walk_state) | |||
704 | acpi_ps_pop_scope(parser_state, &op, | 704 | acpi_ps_pop_scope(parser_state, &op, |
705 | &walk_state->arg_types, | 705 | &walk_state->arg_types, |
706 | &walk_state->arg_count); | 706 | &walk_state->arg_count); |
707 | |||
708 | if (op->common.aml_opcode != AML_WHILE_OP) { | ||
709 | status2 = | ||
710 | acpi_ds_result_stack_pop | ||
711 | (walk_state); | ||
712 | if (ACPI_FAILURE(status2)) { | ||
713 | return_ACPI_STATUS(status2); | ||
714 | } | ||
715 | } | ||
707 | } | 716 | } |
708 | 717 | ||
709 | /* Close this iteration of the While loop */ | 718 | /* Close this iteration of the While loop */ |
diff --git a/drivers/acpi/parser/psparse.c b/drivers/acpi/parser/psparse.c index 7cfa7eb0dfc7..f0979b2956f2 100644 --- a/drivers/acpi/parser/psparse.c +++ b/drivers/acpi/parser/psparse.c | |||
@@ -333,7 +333,6 @@ acpi_ps_next_parse_state(struct acpi_walk_state *walk_state, | |||
333 | 333 | ||
334 | switch (callback_status) { | 334 | switch (callback_status) { |
335 | case AE_CTRL_TERMINATE: | 335 | case AE_CTRL_TERMINATE: |
336 | |||
337 | /* | 336 | /* |
338 | * A control method was terminated via a RETURN statement. | 337 | * A control method was terminated via a RETURN statement. |
339 | * The walk of this method is complete. | 338 | * The walk of this method is complete. |
@@ -346,13 +345,19 @@ acpi_ps_next_parse_state(struct acpi_walk_state *walk_state, | |||
346 | 345 | ||
347 | parser_state->aml = walk_state->aml_last_while; | 346 | parser_state->aml = walk_state->aml_last_while; |
348 | walk_state->control_state->common.value = FALSE; | 347 | walk_state->control_state->common.value = FALSE; |
349 | status = AE_CTRL_BREAK; | 348 | status = acpi_ds_result_stack_pop(walk_state); |
349 | if (ACPI_SUCCESS(status)) { | ||
350 | status = AE_CTRL_BREAK; | ||
351 | } | ||
350 | break; | 352 | break; |
351 | 353 | ||
352 | case AE_CTRL_CONTINUE: | 354 | case AE_CTRL_CONTINUE: |
353 | 355 | ||
354 | parser_state->aml = walk_state->aml_last_while; | 356 | parser_state->aml = walk_state->aml_last_while; |
355 | status = AE_CTRL_CONTINUE; | 357 | status = acpi_ds_result_stack_pop(walk_state); |
358 | if (ACPI_SUCCESS(status)) { | ||
359 | status = AE_CTRL_CONTINUE; | ||
360 | } | ||
356 | break; | 361 | break; |
357 | 362 | ||
358 | case AE_CTRL_PENDING: | 363 | case AE_CTRL_PENDING: |
@@ -369,16 +374,18 @@ acpi_ps_next_parse_state(struct acpi_walk_state *walk_state, | |||
369 | #endif | 374 | #endif |
370 | 375 | ||
371 | case AE_CTRL_TRUE: | 376 | case AE_CTRL_TRUE: |
372 | |||
373 | /* | 377 | /* |
374 | * Predicate of an IF was true, and we are at the matching ELSE. | 378 | * Predicate of an IF was true, and we are at the matching ELSE. |
375 | * Just close out this package | 379 | * Just close out this package |
376 | */ | 380 | */ |
377 | parser_state->aml = acpi_ps_get_next_package_end(parser_state); | 381 | parser_state->aml = acpi_ps_get_next_package_end(parser_state); |
382 | status = acpi_ds_result_stack_pop(walk_state); | ||
383 | if (ACPI_SUCCESS(status)) { | ||
384 | status = AE_CTRL_PENDING; | ||
385 | } | ||
378 | break; | 386 | break; |
379 | 387 | ||
380 | case AE_CTRL_FALSE: | 388 | case AE_CTRL_FALSE: |
381 | |||
382 | /* | 389 | /* |
383 | * Either an IF/WHILE Predicate was false or we encountered a BREAK | 390 | * Either an IF/WHILE Predicate was false or we encountered a BREAK |
384 | * opcode. In both cases, we do not execute the rest of the | 391 | * opcode. In both cases, we do not execute the rest of the |