summaryrefslogtreecommitdiff
path: root/drivers/acpi/parser/psargs.c
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/psargs.c
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/psargs.c')
-rw-r--r--drivers/acpi/parser/psargs.c152
1 files changed, 72 insertions, 80 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
*
* 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++;