aboutsummaryrefslogtreecommitdiff
path: root/drivers/acpi/parser/psargs.c
diff options
context:
space:
mode:
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 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++;