diff options
Diffstat (limited to 'drivers/acpi/parser')
-rw-r--r-- | drivers/acpi/parser/psargs.c | 152 | ||||
-rw-r--r-- | drivers/acpi/parser/psparse.c | 35 | ||||
-rw-r--r-- | drivers/acpi/parser/psxface.c | 2 |
3 files changed, 94 insertions, 95 deletions
diff --git a/drivers/acpi/parser/psargs.c b/drivers/acpi/parser/psargs.c index 562d0f822ab..6eae35febcc 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 * * PARAMETERS: parser_state - Current parser state object * - * RETURN: Decoded package length. On completion, the AML pointer points + * RETURN: Decoded package length. On completion, the AML pointer points * past the length byte or bytes. * - * DESCRIPTION: Decode and return a package length field + * DESCRIPTION: Decode and return a package length field. + * Note: Largest package length is 28 bits, from ACPI specification * ******************************************************************************/ static u32 acpi_ps_get_next_package_length(struct acpi_parse_state *parser_state) { - u32 encoded_length; - u32 length = 0; + u8 *aml = parser_state->aml; + u32 package_length = 0; + acpi_native_uint byte_count; + u8 byte_zero_mask = 0x3F; /* Default [0:5] */ ACPI_FUNCTION_TRACE("ps_get_next_package_length"); - encoded_length = (u32) ACPI_GET8(parser_state->aml); - parser_state->aml++; - - switch (encoded_length >> 6) { /* bits 6-7 contain encoding scheme */ - case 0: /* 1-byte encoding (bits 0-5) */ - - length = (encoded_length & 0x3F); - break; - - case 1: /* 2-byte encoding (next byte + bits 0-3) */ - - length = ((ACPI_GET8(parser_state->aml) << 04) | - (encoded_length & 0x0F)); - parser_state->aml++; - break; - - case 2: /* 3-byte encoding (next 2 bytes + bits 0-3) */ - - length = ((ACPI_GET8(parser_state->aml + 1) << 12) | - (ACPI_GET8(parser_state->aml) << 04) | - (encoded_length & 0x0F)); - parser_state->aml += 2; - break; - - case 3: /* 4-byte encoding (next 3 bytes + bits 0-3) */ + /* + * Byte 0 bits [6:7] contain the number of additional bytes + * used to encode the package length, either 0,1,2, or 3 + */ + byte_count = (aml[0] >> 6); + parser_state->aml += (byte_count + 1); - length = ((ACPI_GET8(parser_state->aml + 2) << 20) | - (ACPI_GET8(parser_state->aml + 1) << 12) | - (ACPI_GET8(parser_state->aml) << 04) | - (encoded_length & 0x0F)); - parser_state->aml += 3; - break; + /* Get bytes 3, 2, 1 as needed */ - default: + while (byte_count) { + /* + * Final bit positions for the package length bytes: + * Byte3->[20:27] + * Byte2->[12:19] + * Byte1->[04:11] + * Byte0->[00:03] + */ + package_length |= (aml[byte_count] << ((byte_count << 3) - 4)); - /* Can't get here, only 2 bits / 4 cases */ - break; + byte_zero_mask = 0x0F; /* Use bits [0:3] of byte 0 */ + byte_count--; } - return_UINT32(length); + /* Byte 0 is a special case, either bits [0:3] or [0:5] are used */ + + package_length |= (aml[0] & byte_zero_mask); + return_UINT32(package_length); } /******************************************************************************* @@ -135,16 +125,15 @@ acpi_ps_get_next_package_length(struct acpi_parse_state *parser_state) u8 *acpi_ps_get_next_package_end(struct acpi_parse_state *parser_state) { u8 *start = parser_state->aml; - acpi_native_uint length; + u32 package_length; ACPI_FUNCTION_TRACE("ps_get_next_package_end"); - /* Function below changes parser_state->Aml */ + /* Function below updates parser_state->Aml */ - length = - (acpi_native_uint) acpi_ps_get_next_package_length(parser_state); + package_length = acpi_ps_get_next_package_length(parser_state); - return_PTR(start + length); /* end of package */ + return_PTR(start + package_length); /* end of package */ } /******************************************************************************* @@ -169,17 +158,15 @@ char *acpi_ps_get_next_namestring(struct acpi_parse_state *parser_state) ACPI_FUNCTION_TRACE("ps_get_next_namestring"); - /* Handle multiple prefix characters */ - - while (acpi_ps_is_prefix_char(ACPI_GET8(end))) { - /* Include prefix '\\' or '^' */ + /* Point past any namestring prefix characters (backslash or carat) */ + while (acpi_ps_is_prefix_char(*end)) { end++; } - /* Decode the path */ + /* Decode the path prefix character */ - switch (ACPI_GET8(end)) { + switch (*end) { case 0: /* null_name */ @@ -199,9 +186,9 @@ char *acpi_ps_get_next_namestring(struct acpi_parse_state *parser_state) case AML_MULTI_NAME_PREFIX_OP: - /* Multiple name segments, 4 chars each */ + /* Multiple name segments, 4 chars each, count in next byte */ - end += 2 + ((acpi_size) ACPI_GET8(end + 1) * ACPI_NAME_SIZE); + end += 2 + (*(end + 1) * ACPI_NAME_SIZE); break; default: @@ -212,7 +199,7 @@ char *acpi_ps_get_next_namestring(struct acpi_parse_state *parser_state) break; } - parser_state->aml = (u8 *) end; + parser_state->aml = end; return_PTR((char *)start); } @@ -342,7 +329,6 @@ acpi_ps_get_next_namepath(struct acpi_walk_state *walk_state, ("search_node %p start_node %p return_node %p\n", scope_info.scope.node, parser_state->start_node, node); - } else { /* * We got a NOT_FOUND during table load or we encountered @@ -382,59 +368,63 @@ void acpi_ps_get_next_simple_arg(struct acpi_parse_state *parser_state, u32 arg_type, union acpi_parse_object *arg) { + u32 length; + u16 opcode; + u8 *aml = parser_state->aml; ACPI_FUNCTION_TRACE_U32("ps_get_next_simple_arg", arg_type); switch (arg_type) { case ARGP_BYTEDATA: - acpi_ps_init_op(arg, AML_BYTE_OP); - arg->common.value.integer = (u32) ACPI_GET8(parser_state->aml); - parser_state->aml++; + /* Get 1 byte from the AML stream */ + + opcode = AML_BYTE_OP; + arg->common.value.integer = (acpi_integer) * aml; + length = 1; break; case ARGP_WORDDATA: - acpi_ps_init_op(arg, AML_WORD_OP); - /* Get 2 bytes from the AML stream */ - ACPI_MOVE_16_TO_32(&arg->common.value.integer, - parser_state->aml); - parser_state->aml += 2; + opcode = AML_WORD_OP; + ACPI_MOVE_16_TO_64(&arg->common.value.integer, aml); + length = 2; break; case ARGP_DWORDDATA: - acpi_ps_init_op(arg, AML_DWORD_OP); - /* Get 4 bytes from the AML stream */ - ACPI_MOVE_32_TO_32(&arg->common.value.integer, - parser_state->aml); - parser_state->aml += 4; + opcode = AML_DWORD_OP; + ACPI_MOVE_32_TO_64(&arg->common.value.integer, aml); + length = 4; break; case ARGP_QWORDDATA: - acpi_ps_init_op(arg, AML_QWORD_OP); - /* Get 8 bytes from the AML stream */ - ACPI_MOVE_64_TO_64(&arg->common.value.integer, - parser_state->aml); - parser_state->aml += 8; + opcode = AML_QWORD_OP; + ACPI_MOVE_64_TO_64(&arg->common.value.integer, aml); + length = 8; break; case ARGP_CHARLIST: - acpi_ps_init_op(arg, AML_STRING_OP); - arg->common.value.string = (char *)parser_state->aml; + /* Get a pointer to the string, point past the string */ + + opcode = AML_STRING_OP; + arg->common.value.string = ACPI_CAST_PTR(char, aml); - while (ACPI_GET8(parser_state->aml) != '\0') { - parser_state->aml++; + /* Find the null terminator */ + + length = 0; + while (aml[length]) { + length++; } - parser_state->aml++; + length++; break; case ARGP_NAME: @@ -443,14 +433,16 @@ acpi_ps_get_next_simple_arg(struct acpi_parse_state *parser_state, acpi_ps_init_op(arg, AML_INT_NAMEPATH_OP); arg->common.value.name = acpi_ps_get_next_namestring(parser_state); - break; + return_VOID; default: ACPI_REPORT_ERROR(("Invalid arg_type %X\n", arg_type)); - break; + return_VOID; } + acpi_ps_init_op(arg, opcode); + parser_state->aml += length; return_VOID; } @@ -540,7 +532,7 @@ static union acpi_parse_object *acpi_ps_get_next_field(struct acpi_parse_state * access_type is first operand, access_attribute is second */ field->common.value.integer = - (ACPI_GET8(parser_state->aml) << 8); + (((u32) ACPI_GET8(parser_state->aml) << 8)); parser_state->aml++; field->common.value.integer |= ACPI_GET8(parser_state->aml); parser_state->aml++; diff --git a/drivers/acpi/parser/psparse.c b/drivers/acpi/parser/psparse.c index 76d4d640d83..7cfa7eb0dfc 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) } else if (status == AE_CTRL_TERMINATE) { status = AE_OK; } else if ((status != AE_OK) && (walk_state->method_desc)) { - ACPI_REPORT_METHOD_ERROR("Method execution failed", - walk_state->method_node, NULL, - status); + /* Either the method parse or actual execution failed */ - /* Ensure proper cleanup */ - - walk_state->parse_flags |= ACPI_PARSE_EXECUTE; + ACPI_REPORT_METHOD_ERROR + ("Method parse/execution failed", + walk_state->method_node, NULL, status); /* Check for possible multi-thread reentrancy problem */ if ((status == AE_ALREADY_EXISTS) && (!walk_state->method_desc->method.semaphore)) { /* - * This method is marked not_serialized, but it tried to create + * Method tried to create an object twice. The probable cause is + * that the method cannot handle reentrancy. + * + * The method is marked not_serialized, but it tried to create * a named object, causing the second thread entrance to fail. - * We will workaround this by marking the method permanently + * Workaround this problem by marking the method permanently * as Serialized. */ walk_state->method_desc->method.method_flags |= @@ -536,15 +537,22 @@ acpi_status acpi_ps_parse_aml(struct acpi_walk_state *walk_state) acpi_ds_scope_stack_clear(walk_state); /* - * If we just returned from the execution of a control method, - * there's lots of cleanup to do + * If we just returned from the execution of a control method or if we + * encountered an error during the method parse phase, there's lots of + * cleanup to do */ - if ((walk_state->parse_flags & ACPI_PARSE_MODE_MASK) == - ACPI_PARSE_EXECUTE) { + if (((walk_state->parse_flags & ACPI_PARSE_MODE_MASK) == + ACPI_PARSE_EXECUTE) || (ACPI_FAILURE(status))) { if (walk_state->method_desc) { /* Decrement the thread count on the method parse tree */ - walk_state->method_desc->method.thread_count--; + if (walk_state->method_desc->method. + thread_count) { + walk_state->method_desc->method. + thread_count--; + } else { + ACPI_REPORT_ERROR(("Invalid zero thread count in method\n")); + } } acpi_ds_terminate_control_method(walk_state); @@ -553,7 +561,6 @@ acpi_status acpi_ps_parse_aml(struct acpi_walk_state *walk_state) /* Delete this walk state and all linked control states */ acpi_ps_cleanup_scope(&walk_state->parser_state); - previous_walk_state = walk_state; ACPI_DEBUG_PRINT((ACPI_DB_PARSE, diff --git a/drivers/acpi/parser/psxface.c b/drivers/acpi/parser/psxface.c index 4c426f4c6af..14d544d6086 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) /* TBDs: Validate name, allow full path or just nameseg */ - acpi_gbl_trace_method_name = *(u32 *) name; + acpi_gbl_trace_method_name = *ACPI_CAST_PTR(u32, name); acpi_gbl_trace_flags = flags; if (debug_level) { |