aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi/parser
diff options
context:
space:
mode:
authorBob Moore <robert.moore@intel.com>2005-11-17 13:07:00 -0500
committerLen Brown <len.brown@intel.com>2005-12-10 00:27:56 -0500
commitc51a4de85de720670f2fbc592a6f8040af72ad87 (patch)
treeccaa60c483fcc904abd63d936ff7dc380bf28e7b /drivers/acpi/parser
parent96db255c8f014ae3497507104e8df809785a619f (diff)
[ACPI] ACPICA 20051117
Fixed a problem in the AML parser where the method thread count could be decremented below zero if any errors occurred during the method parse phase. This should eliminate AE_AML_METHOD_LIMIT exceptions seen on some machines. This also fixed a related regression with the mechanism that detects and corrects methods that cannot properly handle reentrancy (related to the deployment of the new OwnerId mechanism.) Eliminated the pre-parsing of control methods (to detect errors) during table load. Related to the problem above, this was causing unwind issues if any errors occurred during the parse, and it seemed to be overkill. A table load should not be aborted if there are problems with any single control method, thus rendering this feature rather pointless. Fixed a problem with the new table-driven resource manager where an internal buffer overflow could occur for small resource templates. Implemented a new external interface, acpi_get_vendor_resource() This interface will find and return a vendor-defined resource descriptor within a _CRS or _PRS method via an ACPI 3.0 UUID match. (from Bjorn Helgaas) Removed the length limit (200) on string objects as per the upcoming ACPI 3.0A specification. This affects the following areas of the interpreter: 1) any implicit conversion of a Buffer to a String, 2) a String object result of the ASL Concatentate operator, 3) the String object result of the ASL ToString operator. 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.c152
-rw-r--r--drivers/acpi/parser/psparse.c35
-rw-r--r--drivers/acpi/parser/psxface.c2
3 files changed, 94 insertions, 95 deletions
diff --git a/drivers/acpi/parser/psargs.c b/drivers/acpi/parser/psargs.c
index 562d0f822ab1..6eae35febccd 100644
--- a/drivers/acpi/parser/psargs.c
+++ b/drivers/acpi/parser/psargs.c
@@ -62,61 +62,51 @@ static union acpi_parse_object *acpi_ps_get_next_field(struct acpi_parse_state
62 * 62 *
63 * PARAMETERS: parser_state - Current parser state object 63 * PARAMETERS: parser_state - Current parser state object
64 * 64 *
65 * RETURN: Decoded package length. On completion, the AML pointer points 65 * RETURN: Decoded package length. On completion, the AML pointer points
66 * past the length byte or bytes. 66 * past the length byte or bytes.
67 * 67 *
68 * DESCRIPTION: Decode and return a package length field 68 * DESCRIPTION: Decode and return a package length field.
69 * Note: Largest package length is 28 bits, from ACPI specification
69 * 70 *
70 ******************************************************************************/ 71 ******************************************************************************/
71 72
72static u32 73static u32
73acpi_ps_get_next_package_length(struct acpi_parse_state *parser_state) 74acpi_ps_get_next_package_length(struct acpi_parse_state *parser_state)
74{ 75{
75 u32 encoded_length; 76 u8 *aml = parser_state->aml;
76 u32 length = 0; 77 u32 package_length = 0;
78 acpi_native_uint byte_count;
79 u8 byte_zero_mask = 0x3F; /* Default [0:5] */
77 80
78 ACPI_FUNCTION_TRACE("ps_get_next_package_length"); 81 ACPI_FUNCTION_TRACE("ps_get_next_package_length");
79 82
80 encoded_length = (u32) ACPI_GET8(parser_state->aml); 83 /*
81 parser_state->aml++; 84 * Byte 0 bits [6:7] contain the number of additional bytes
82 85 * used to encode the package length, either 0,1,2, or 3
83 switch (encoded_length >> 6) { /* bits 6-7 contain encoding scheme */ 86 */
84 case 0: /* 1-byte encoding (bits 0-5) */ 87 byte_count = (aml[0] >> 6);
85 88 parser_state->aml += (byte_count + 1);
86 length = (encoded_length & 0x3F);
87 break;
88
89 case 1: /* 2-byte encoding (next byte + bits 0-3) */
90
91 length = ((ACPI_GET8(parser_state->aml) << 04) |
92 (encoded_length & 0x0F));
93 parser_state->aml++;
94 break;
95
96 case 2: /* 3-byte encoding (next 2 bytes + bits 0-3) */
97
98 length = ((ACPI_GET8(parser_state->aml + 1) << 12) |
99 (ACPI_GET8(parser_state->aml) << 04) |
100 (encoded_length & 0x0F));
101 parser_state->aml += 2;
102 break;
103
104 case 3: /* 4-byte encoding (next 3 bytes + bits 0-3) */
105 89
106 length = ((ACPI_GET8(parser_state->aml + 2) << 20) | 90 /* Get bytes 3, 2, 1 as needed */
107 (ACPI_GET8(parser_state->aml + 1) << 12) |
108 (ACPI_GET8(parser_state->aml) << 04) |
109 (encoded_length & 0x0F));
110 parser_state->aml += 3;
111 break;
112 91
113 default: 92 while (byte_count) {
93 /*
94 * Final bit positions for the package length bytes:
95 * Byte3->[20:27]
96 * Byte2->[12:19]
97 * Byte1->[04:11]
98 * Byte0->[00:03]
99 */
100 package_length |= (aml[byte_count] << ((byte_count << 3) - 4));
114 101
115 /* Can't get here, only 2 bits / 4 cases */ 102 byte_zero_mask = 0x0F; /* Use bits [0:3] of byte 0 */
116 break; 103 byte_count--;
117 } 104 }
118 105
119 return_UINT32(length); 106 /* Byte 0 is a special case, either bits [0:3] or [0:5] are used */
107
108 package_length |= (aml[0] & byte_zero_mask);
109 return_UINT32(package_length);
120} 110}
121 111
122/******************************************************************************* 112/*******************************************************************************
@@ -135,16 +125,15 @@ acpi_ps_get_next_package_length(struct acpi_parse_state *parser_state)
135u8 *acpi_ps_get_next_package_end(struct acpi_parse_state *parser_state) 125u8 *acpi_ps_get_next_package_end(struct acpi_parse_state *parser_state)
136{ 126{
137 u8 *start = parser_state->aml; 127 u8 *start = parser_state->aml;
138 acpi_native_uint length; 128 u32 package_length;
139 129
140 ACPI_FUNCTION_TRACE("ps_get_next_package_end"); 130 ACPI_FUNCTION_TRACE("ps_get_next_package_end");
141 131
142 /* Function below changes parser_state->Aml */ 132 /* Function below updates parser_state->Aml */
143 133
144 length = 134 package_length = acpi_ps_get_next_package_length(parser_state);
145 (acpi_native_uint) acpi_ps_get_next_package_length(parser_state);
146 135
147 return_PTR(start + length); /* end of package */ 136 return_PTR(start + package_length); /* end of package */
148} 137}
149 138
150/******************************************************************************* 139/*******************************************************************************
@@ -169,17 +158,15 @@ char *acpi_ps_get_next_namestring(struct acpi_parse_state *parser_state)
169 158
170 ACPI_FUNCTION_TRACE("ps_get_next_namestring"); 159 ACPI_FUNCTION_TRACE("ps_get_next_namestring");
171 160
172 /* Handle multiple prefix characters */ 161 /* Point past any namestring prefix characters (backslash or carat) */
173
174 while (acpi_ps_is_prefix_char(ACPI_GET8(end))) {
175 /* Include prefix '\\' or '^' */
176 162
163 while (acpi_ps_is_prefix_char(*end)) {
177 end++; 164 end++;
178 } 165 }
179 166
180 /* Decode the path */ 167 /* Decode the path prefix character */
181 168
182 switch (ACPI_GET8(end)) { 169 switch (*end) {
183 case 0: 170 case 0:
184 171
185 /* null_name */ 172 /* null_name */
@@ -199,9 +186,9 @@ char *acpi_ps_get_next_namestring(struct acpi_parse_state *parser_state)
199 186
200 case AML_MULTI_NAME_PREFIX_OP: 187 case AML_MULTI_NAME_PREFIX_OP:
201 188
202 /* Multiple name segments, 4 chars each */ 189 /* Multiple name segments, 4 chars each, count in next byte */
203 190
204 end += 2 + ((acpi_size) ACPI_GET8(end + 1) * ACPI_NAME_SIZE); 191 end += 2 + (*(end + 1) * ACPI_NAME_SIZE);
205 break; 192 break;
206 193
207 default: 194 default:
@@ -212,7 +199,7 @@ char *acpi_ps_get_next_namestring(struct acpi_parse_state *parser_state)
212 break; 199 break;
213 } 200 }
214 201
215 parser_state->aml = (u8 *) end; 202 parser_state->aml = end;
216 return_PTR((char *)start); 203 return_PTR((char *)start);
217} 204}
218 205
@@ -342,7 +329,6 @@ acpi_ps_get_next_namepath(struct acpi_walk_state *walk_state,
342 ("search_node %p start_node %p return_node %p\n", 329 ("search_node %p start_node %p return_node %p\n",
343 scope_info.scope.node, 330 scope_info.scope.node,
344 parser_state->start_node, node); 331 parser_state->start_node, node);
345
346 } else { 332 } else {
347 /* 333 /*
348 * We got a NOT_FOUND during table load or we encountered 334 * We got a NOT_FOUND during table load or we encountered
@@ -382,59 +368,63 @@ void
382acpi_ps_get_next_simple_arg(struct acpi_parse_state *parser_state, 368acpi_ps_get_next_simple_arg(struct acpi_parse_state *parser_state,
383 u32 arg_type, union acpi_parse_object *arg) 369 u32 arg_type, union acpi_parse_object *arg)
384{ 370{
371 u32 length;
372 u16 opcode;
373 u8 *aml = parser_state->aml;
385 374
386 ACPI_FUNCTION_TRACE_U32("ps_get_next_simple_arg", arg_type); 375 ACPI_FUNCTION_TRACE_U32("ps_get_next_simple_arg", arg_type);
387 376
388 switch (arg_type) { 377 switch (arg_type) {
389 case ARGP_BYTEDATA: 378 case ARGP_BYTEDATA:
390 379
391 acpi_ps_init_op(arg, AML_BYTE_OP); 380 /* Get 1 byte from the AML stream */
392 arg->common.value.integer = (u32) ACPI_GET8(parser_state->aml); 381
393 parser_state->aml++; 382 opcode = AML_BYTE_OP;
383 arg->common.value.integer = (acpi_integer) * aml;
384 length = 1;
394 break; 385 break;
395 386
396 case ARGP_WORDDATA: 387 case ARGP_WORDDATA:
397 388
398 acpi_ps_init_op(arg, AML_WORD_OP);
399
400 /* Get 2 bytes from the AML stream */ 389 /* Get 2 bytes from the AML stream */
401 390
402 ACPI_MOVE_16_TO_32(&arg->common.value.integer, 391 opcode = AML_WORD_OP;
403 parser_state->aml); 392 ACPI_MOVE_16_TO_64(&arg->common.value.integer, aml);
404 parser_state->aml += 2; 393 length = 2;
405 break; 394 break;
406 395
407 case ARGP_DWORDDATA: 396 case ARGP_DWORDDATA:
408 397
409 acpi_ps_init_op(arg, AML_DWORD_OP);
410
411 /* Get 4 bytes from the AML stream */ 398 /* Get 4 bytes from the AML stream */
412 399
413 ACPI_MOVE_32_TO_32(&arg->common.value.integer, 400 opcode = AML_DWORD_OP;
414 parser_state->aml); 401 ACPI_MOVE_32_TO_64(&arg->common.value.integer, aml);
415 parser_state->aml += 4; 402 length = 4;
416 break; 403 break;
417 404
418 case ARGP_QWORDDATA: 405 case ARGP_QWORDDATA:
419 406
420 acpi_ps_init_op(arg, AML_QWORD_OP);
421
422 /* Get 8 bytes from the AML stream */ 407 /* Get 8 bytes from the AML stream */
423 408
424 ACPI_MOVE_64_TO_64(&arg->common.value.integer, 409 opcode = AML_QWORD_OP;
425 parser_state->aml); 410 ACPI_MOVE_64_TO_64(&arg->common.value.integer, aml);
426 parser_state->aml += 8; 411 length = 8;
427 break; 412 break;
428 413
429 case ARGP_CHARLIST: 414 case ARGP_CHARLIST:
430 415
431 acpi_ps_init_op(arg, AML_STRING_OP); 416 /* Get a pointer to the string, point past the string */
432 arg->common.value.string = (char *)parser_state->aml; 417
418 opcode = AML_STRING_OP;
419 arg->common.value.string = ACPI_CAST_PTR(char, aml);
433 420
434 while (ACPI_GET8(parser_state->aml) != '\0') { 421 /* Find the null terminator */
435 parser_state->aml++; 422
423 length = 0;
424 while (aml[length]) {
425 length++;
436 } 426 }
437 parser_state->aml++; 427 length++;
438 break; 428 break;
439 429
440 case ARGP_NAME: 430 case ARGP_NAME:
@@ -443,14 +433,16 @@ acpi_ps_get_next_simple_arg(struct acpi_parse_state *parser_state,
443 acpi_ps_init_op(arg, AML_INT_NAMEPATH_OP); 433 acpi_ps_init_op(arg, AML_INT_NAMEPATH_OP);
444 arg->common.value.name = 434 arg->common.value.name =
445 acpi_ps_get_next_namestring(parser_state); 435 acpi_ps_get_next_namestring(parser_state);
446 break; 436 return_VOID;
447 437
448 default: 438 default:
449 439
450 ACPI_REPORT_ERROR(("Invalid arg_type %X\n", arg_type)); 440 ACPI_REPORT_ERROR(("Invalid arg_type %X\n", arg_type));
451 break; 441 return_VOID;
452 } 442 }
453 443
444 acpi_ps_init_op(arg, opcode);
445 parser_state->aml += length;
454 return_VOID; 446 return_VOID;
455} 447}
456 448
@@ -540,7 +532,7 @@ static union acpi_parse_object *acpi_ps_get_next_field(struct acpi_parse_state
540 * access_type is first operand, access_attribute is second 532 * access_type is first operand, access_attribute is second
541 */ 533 */
542 field->common.value.integer = 534 field->common.value.integer =
543 (ACPI_GET8(parser_state->aml) << 8); 535 (((u32) ACPI_GET8(parser_state->aml) << 8));
544 parser_state->aml++; 536 parser_state->aml++;
545 field->common.value.integer |= ACPI_GET8(parser_state->aml); 537 field->common.value.integer |= ACPI_GET8(parser_state->aml);
546 parser_state->aml++; 538 parser_state->aml++;
diff --git a/drivers/acpi/parser/psparse.c b/drivers/acpi/parser/psparse.c
index 76d4d640d83c..7cfa7eb0dfc7 100644
--- a/drivers/acpi/parser/psparse.c
+++ b/drivers/acpi/parser/psparse.c
@@ -503,22 +503,23 @@ acpi_status acpi_ps_parse_aml(struct acpi_walk_state *walk_state)
503 } else if (status == AE_CTRL_TERMINATE) { 503 } else if (status == AE_CTRL_TERMINATE) {
504 status = AE_OK; 504 status = AE_OK;
505 } else if ((status != AE_OK) && (walk_state->method_desc)) { 505 } else if ((status != AE_OK) && (walk_state->method_desc)) {
506 ACPI_REPORT_METHOD_ERROR("Method execution failed", 506 /* Either the method parse or actual execution failed */
507 walk_state->method_node, NULL,
508 status);
509 507
510 /* Ensure proper cleanup */ 508 ACPI_REPORT_METHOD_ERROR
511 509 ("Method parse/execution failed",
512 walk_state->parse_flags |= ACPI_PARSE_EXECUTE; 510 walk_state->method_node, NULL, status);
513 511
514 /* Check for possible multi-thread reentrancy problem */ 512 /* Check for possible multi-thread reentrancy problem */
515 513
516 if ((status == AE_ALREADY_EXISTS) && 514 if ((status == AE_ALREADY_EXISTS) &&
517 (!walk_state->method_desc->method.semaphore)) { 515 (!walk_state->method_desc->method.semaphore)) {
518 /* 516 /*
519 * This method is marked not_serialized, but it tried to create 517 * Method tried to create an object twice. The probable cause is
518 * that the method cannot handle reentrancy.
519 *
520 * The method is marked not_serialized, but it tried to create
520 * a named object, causing the second thread entrance to fail. 521 * a named object, causing the second thread entrance to fail.
521 * We will workaround this by marking the method permanently 522 * Workaround this problem by marking the method permanently
522 * as Serialized. 523 * as Serialized.
523 */ 524 */
524 walk_state->method_desc->method.method_flags |= 525 walk_state->method_desc->method.method_flags |=
@@ -536,15 +537,22 @@ acpi_status acpi_ps_parse_aml(struct acpi_walk_state *walk_state)
536 acpi_ds_scope_stack_clear(walk_state); 537 acpi_ds_scope_stack_clear(walk_state);
537 538
538 /* 539 /*
539 * If we just returned from the execution of a control method, 540 * If we just returned from the execution of a control method or if we
540 * there's lots of cleanup to do 541 * encountered an error during the method parse phase, there's lots of
542 * cleanup to do
541 */ 543 */
542 if ((walk_state->parse_flags & ACPI_PARSE_MODE_MASK) == 544 if (((walk_state->parse_flags & ACPI_PARSE_MODE_MASK) ==
543 ACPI_PARSE_EXECUTE) { 545 ACPI_PARSE_EXECUTE) || (ACPI_FAILURE(status))) {
544 if (walk_state->method_desc) { 546 if (walk_state->method_desc) {
545 /* Decrement the thread count on the method parse tree */ 547 /* Decrement the thread count on the method parse tree */
546 548
547 walk_state->method_desc->method.thread_count--; 549 if (walk_state->method_desc->method.
550 thread_count) {
551 walk_state->method_desc->method.
552 thread_count--;
553 } else {
554 ACPI_REPORT_ERROR(("Invalid zero thread count in method\n"));
555 }
548 } 556 }
549 557
550 acpi_ds_terminate_control_method(walk_state); 558 acpi_ds_terminate_control_method(walk_state);
@@ -553,7 +561,6 @@ acpi_status acpi_ps_parse_aml(struct acpi_walk_state *walk_state)
553 /* Delete this walk state and all linked control states */ 561 /* Delete this walk state and all linked control states */
554 562
555 acpi_ps_cleanup_scope(&walk_state->parser_state); 563 acpi_ps_cleanup_scope(&walk_state->parser_state);
556
557 previous_walk_state = walk_state; 564 previous_walk_state = walk_state;
558 565
559 ACPI_DEBUG_PRINT((ACPI_DB_PARSE, 566 ACPI_DEBUG_PRINT((ACPI_DB_PARSE,
diff --git a/drivers/acpi/parser/psxface.c b/drivers/acpi/parser/psxface.c
index 4c426f4c6af6..14d544d60867 100644
--- a/drivers/acpi/parser/psxface.c
+++ b/drivers/acpi/parser/psxface.c
@@ -87,7 +87,7 @@ acpi_debug_trace(char *name, u32 debug_level, u32 debug_layer, u32 flags)
87 87
88 /* TBDs: Validate name, allow full path or just nameseg */ 88 /* TBDs: Validate name, allow full path or just nameseg */
89 89
90 acpi_gbl_trace_method_name = *(u32 *) name; 90 acpi_gbl_trace_method_name = *ACPI_CAST_PTR(u32, name);
91 acpi_gbl_trace_flags = flags; 91 acpi_gbl_trace_flags = flags;
92 92
93 if (debug_level) { 93 if (debug_level) {