patch-2.4.0-test3 linux/drivers/acpi/parser/psargs.c
Next file: linux/drivers/acpi/parser/psopcode.c
Previous file: linux/drivers/acpi/osd.c
Back to the patch index
Back to the overall index
- Lines: 736
- Date:
Wed Jul 5 11:23:12 2000
- Orig file:
v2.4.0-test2/linux/drivers/acpi/parser/psargs.c
- Orig date:
Wed Dec 31 16:00:00 1969
diff -u --recursive --new-file v2.4.0-test2/linux/drivers/acpi/parser/psargs.c linux/drivers/acpi/parser/psargs.c
@@ -0,0 +1,735 @@
+/******************************************************************************
+ *
+ * Module Name: psargs - Parse AML opcode arguments
+ *
+ *****************************************************************************/
+
+/*
+ * Copyright (C) 2000 R. Byron Moore
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#include "acpi.h"
+#include "parser.h"
+#include "amlcode.h"
+#include "namesp.h"
+
+#define _COMPONENT PARSER
+ MODULE_NAME ("psargs");
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: Acpi_ps_get_next_package_length
+ *
+ * PARAMETERS: Parser_state - Current parser state object
+ *
+ * RETURN: Decoded package length. On completion, the AML pointer points
+ * past the length byte or bytes.
+ *
+ * DESCRIPTION: Decode and return a package length field
+ *
+ ******************************************************************************/
+
+u32
+acpi_ps_get_next_package_length (
+ ACPI_PARSE_STATE *parser_state)
+{
+ s32 encoded_length;
+ s32 length = 0;
+
+
+ encoded_length = (s32) 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 = (GET8 (parser_state->aml) << 4) | (encoded_length & 0xf);
+ parser_state->aml++;
+ break;
+
+
+ case 2: /* 3-byte encoding (next 2 bytes + bits 0-3) */
+
+ length = ( (GET8 (parser_state->aml + 1) << 12)
+ | (GET8 (parser_state->aml) << 4)
+ | (encoded_length & 0xf));
+ parser_state->aml += 2;
+ break;
+
+
+ case 3: /* 4-byte encoding (next 3 bytes + bits 0-3) */
+
+ length = ( (GET8 (parser_state->aml + 2) << 20)
+ | (GET8 (parser_state->aml + 1) << 12)
+ | (GET8 (parser_state->aml) << 4)
+ | (encoded_length & 0xf));
+ parser_state->aml += 3;
+ break;
+ }
+
+ return (length);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: Acpi_ps_get_next_package_end
+ *
+ * PARAMETERS: Parser_state - Current parser state object
+ *
+ * RETURN: Pointer to end-of-package +1
+ *
+ * DESCRIPTION: Get next package length and return a pointer past the end of
+ * the package. Consumes the package length field
+ *
+ ******************************************************************************/
+
+u8 *
+acpi_ps_get_next_package_end (
+ ACPI_PARSE_STATE *parser_state)
+{
+ u8 *start = parser_state->aml;
+ NATIVE_UINT length;
+
+
+ length = (NATIVE_UINT) acpi_ps_get_next_package_length (parser_state);
+
+ return (start + length); /* end of package */
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: Acpi_ps_get_next_namestring
+ *
+ * PARAMETERS: Parser_state - Current parser state object
+ *
+ * RETURN: Pointer to the start of the name string (pointer points into
+ * the AML.
+ *
+ * DESCRIPTION: Get next raw namestring within the AML stream. Handles all name
+ * prefix characters. Set parser state to point past the string.
+ * (Name is consumed from the AML.)
+ *
+ ******************************************************************************/
+
+char *
+acpi_ps_get_next_namestring (
+ ACPI_PARSE_STATE *parser_state)
+{
+ char *start = (char *) parser_state->aml;
+ char *end = (char *) parser_state->aml;
+ s32 length;
+
+
+ /* Handle multiple prefix characters */
+
+ while (acpi_ps_is_prefix_char (GET8 (end))) {
+ /* include prefix '\\' or '^' */
+
+ end++;
+ }
+
+ /* Decode the path */
+
+ switch (GET8 (end))
+ {
+ case 0:
+
+ /* Null_name */
+
+ if (end == start) {
+ start = NULL;
+ }
+ end++;
+ break;
+
+
+ case AML_DUAL_NAME_PREFIX:
+
+ /* two name segments */
+
+ end += 9;
+ break;
+
+
+ case AML_MULTI_NAME_PREFIX_OP:
+
+ /* multiple name segments */
+
+ length = (s32) GET8 (end + 1) * 4;
+ end += 2 + length;
+ break;
+
+
+ default:
+
+ /* single name segment */
+ /* assert (Acpi_ps_is_lead (GET8 (End))); */
+
+ end += 4;
+ break;
+ }
+
+ parser_state->aml = (u8*) end;
+
+ return (start);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: Acpi_ps_get_next_namepath
+ *
+ * PARAMETERS: Parser_state - Current parser state object
+ * Arg - Where the namepath will be stored
+ * Arg_count - If the namepath points to a control method
+ * the method's argument is returned here.
+ * Method_call - Whether the namepath can be the start
+ * of a method call
+ *
+ * RETURN: None
+ *
+ * DESCRIPTION: Get next name (if method call, push appropriate # args). Names
+ * are looked up in either the parsed or internal namespace to
+ * determine if the name represents a control method. If a method
+ * is found, the number of arguments to the method is returned.
+ * This information is critical for parsing to continue correctly.
+ *
+ ******************************************************************************/
+
+
+#ifdef PARSER_ONLY
+
+void
+acpi_ps_get_next_namepath (
+ ACPI_PARSE_STATE *parser_state,
+ ACPI_GENERIC_OP *arg,
+ u32 *arg_count,
+ u8 method_call)
+{
+ char *path;
+ ACPI_GENERIC_OP *name;
+ ACPI_GENERIC_OP *op;
+ ACPI_GENERIC_OP *count;
+
+
+ path = acpi_ps_get_next_namestring (parser_state);
+ if (!path || !method_call) {
+ /* Null name case, create a null namepath object */
+
+ acpi_ps_init_op (arg, AML_NAMEPATH_OP);
+ arg->value.name = path;
+ return;
+ }
+
+
+ if (acpi_gbl_parsed_namespace_root) {
+ /*
+ * Lookup the name in the parsed namespace
+ */
+
+ op = NULL;
+ if (method_call) {
+ op = acpi_ps_find (acpi_ps_get_parent_scope (parser_state),
+ path, AML_METHOD_OP, 0);
+ }
+
+ if (op) {
+ if (op->opcode == AML_METHOD_OP) {
+ /*
+ * The name refers to a control method, so this namepath is a
+ * method invocation. We need to 1) Get the number of arguments
+ * associated with this method, and 2) Change the NAMEPATH
+ * object into a METHODCALL object.
+ */
+
+ count = acpi_ps_get_arg (op, 0);
+ if (count && count->opcode == AML_BYTE_OP) {
+ name = acpi_ps_alloc_op (AML_NAMEPATH_OP);
+ if (name) {
+ /* Change arg into a METHOD CALL and attach the name */
+
+ acpi_ps_init_op (arg, AML_METHODCALL_OP);
+
+ name->value.name = path;
+
+ /* Point METHODCALL/NAME to the METHOD NTE */
+
+ name->acpi_named_object = op;
+ acpi_ps_append_arg (arg, name);
+
+ *arg_count = count->value.integer &
+ METHOD_FLAGS_ARG_COUNT;
+ }
+ }
+
+ return;
+ }
+
+ /*
+ * Else this is normal named object reference.
+ * Just init the NAMEPATH object with the pathname.
+ * (See code below)
+ */
+ }
+ }
+
+
+ /*
+ * Either we didn't find the object in the namespace, or the object is
+ * something other than a control method. Just initialize the Op with the
+ * pathname
+ */
+
+ acpi_ps_init_op (arg, AML_NAMEPATH_OP);
+ arg->value.name = path;
+
+
+ return;
+}
+
+
+#else
+
+
+void
+acpi_ps_get_next_namepath (
+ ACPI_PARSE_STATE *parser_state,
+ ACPI_GENERIC_OP *arg,
+ u32 *arg_count,
+ u8 method_call)
+{
+ char *path;
+ ACPI_GENERIC_OP *name;
+ ACPI_STATUS status;
+ ACPI_NAMED_OBJECT *method = NULL;
+ ACPI_NAMED_OBJECT *entry;
+ ACPI_GENERIC_STATE scope_info;
+
+
+ path = acpi_ps_get_next_namestring (parser_state);
+ if (!path || !method_call) {
+ /* Null name case, create a null namepath object */
+
+ acpi_ps_init_op (arg, AML_NAMEPATH_OP);
+ arg->value.name = path;
+ return;
+ }
+
+
+ if (method_call) {
+ /*
+ * Lookup the name in the internal namespace
+ */
+ scope_info.scope.name_table = NULL;
+ entry = parser_state->start_op->acpi_named_object;
+ if (entry) {
+ scope_info.scope.name_table = entry->child_table;
+ }
+
+ /*
+ * Lookup object. We don't want to add anything new to the namespace
+ * here, however. So we use MODE_EXECUTE. Allow searching of the
+ * parent tree, but don't open a new scope -- we just want to lookup the
+ * object (MUST BE mode EXECUTE to perform upsearch)
+ */
+
+ status = acpi_ns_lookup (&scope_info, path, ACPI_TYPE_ANY, IMODE_EXECUTE,
+ NS_SEARCH_PARENT | NS_DONT_OPEN_SCOPE, NULL,
+ &entry);
+ if (ACPI_SUCCESS (status)) {
+ if (entry->type == ACPI_TYPE_METHOD) {
+ method = entry;
+ name = acpi_ps_alloc_op (AML_NAMEPATH_OP);
+ if (name) {
+ /* Change arg into a METHOD CALL and attach name to it */
+
+ acpi_ps_init_op (arg, AML_METHODCALL_OP);
+
+ name->value.name = path;
+
+ /* Point METHODCALL/NAME to the METHOD NTE */
+
+ name->acpi_named_object = method;
+ acpi_ps_append_arg (arg, name);
+
+ *arg_count = ((ACPI_OBJECT_INTERNAL *) method->object)->method.param_count;
+ }
+
+ return;
+ }
+
+ /*
+ * Else this is normal named object reference.
+ * Just init the NAMEPATH object with the pathname.
+ * (See code below)
+ */
+ }
+ }
+
+ /*
+ * Either we didn't find the object in the namespace, or the object is
+ * something other than a control method. Just initialize the Op with the
+ * pathname
+ */
+
+ acpi_ps_init_op (arg, AML_NAMEPATH_OP);
+ arg->value.name = path;
+
+
+ return;
+}
+
+#endif
+
+/*******************************************************************************
+ *
+ * FUNCTION: Acpi_ps_get_next_simple_arg
+ *
+ * PARAMETERS: Parser_state - Current parser state object
+ * Arg_type - The argument type (AML_*_ARG)
+ * Arg - Where the argument is returned
+ *
+ * RETURN: None
+ *
+ * DESCRIPTION: Get the next simple argument (constant, string, or namestring)
+ *
+ ******************************************************************************/
+
+void
+acpi_ps_get_next_simple_arg (
+ ACPI_PARSE_STATE *parser_state,
+ s32 arg_type,
+ ACPI_GENERIC_OP *arg)
+{
+
+
+ switch (arg_type)
+ {
+
+ case ARGP_BYTEDATA:
+
+ acpi_ps_init_op (arg, AML_BYTE_OP);
+ arg->value.integer = (u32) GET8 (parser_state->aml);
+ parser_state->aml++;
+ break;
+
+
+ case ARGP_WORDDATA:
+
+ acpi_ps_init_op (arg, AML_WORD_OP);
+
+ /* Get 2 bytes from the AML stream */
+
+ MOVE_UNALIGNED16_TO_32 (&arg->value.integer, parser_state->aml);
+ parser_state->aml += 2;
+ break;
+
+
+ case ARGP_DWORDDATA:
+
+ acpi_ps_init_op (arg, AML_DWORD_OP);
+
+ /* Get 4 bytes from the AML stream */
+
+ MOVE_UNALIGNED32_TO_32 (&arg->value.integer, parser_state->aml);
+ parser_state->aml += 4;
+ break;
+
+
+ case ARGP_CHARLIST:
+
+ acpi_ps_init_op (arg, AML_STRING_OP);
+ arg->value.string = (char*) parser_state->aml;
+
+ while (GET8 (parser_state->aml) != '\0') {
+ parser_state->aml++;
+ }
+ parser_state->aml++;
+ break;
+
+
+ case ARGP_NAME:
+ case ARGP_NAMESTRING:
+
+ acpi_ps_init_op (arg, AML_NAMEPATH_OP);
+ arg->value.name = acpi_ps_get_next_namestring (parser_state);
+ break;
+ }
+
+ return;
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: Acpi_ps_get_next_field
+ *
+ * PARAMETERS: Parser_state - Current parser state object
+ *
+ * RETURN: A newly allocated FIELD op
+ *
+ * DESCRIPTION: Get next field (Named_field, Reserved_field, or Access_field)
+ *
+ ******************************************************************************/
+
+ACPI_GENERIC_OP *
+acpi_ps_get_next_field (
+ ACPI_PARSE_STATE *parser_state)
+{
+ ACPI_PTRDIFF aml_offset = parser_state->aml -
+ parser_state->aml_start;
+ ACPI_GENERIC_OP *field;
+ u16 opcode;
+ u32 name;
+
+
+ /* determine field type */
+
+ switch (GET8 (parser_state->aml))
+ {
+
+ default:
+
+ opcode = AML_NAMEDFIELD_OP;
+ break;
+
+
+ case 0x00:
+
+ opcode = AML_RESERVEDFIELD_OP;
+ parser_state->aml++;
+ break;
+
+
+ case 0x01:
+
+ opcode = AML_ACCESSFIELD_OP;
+ parser_state->aml++;
+ break;
+ }
+
+
+ /* Allocate a new field op */
+
+ field = acpi_ps_alloc_op (opcode);
+ if (field) {
+ field->aml_offset = aml_offset;
+
+ /* Decode the field type */
+
+ switch (opcode)
+ {
+ case AML_NAMEDFIELD_OP:
+
+ /* Get the 4-character name */
+
+ MOVE_UNALIGNED32_TO_32 (&name, parser_state->aml);
+ acpi_ps_set_name (field, name);
+ parser_state->aml += 4;
+
+ /* Get the length which is encoded as a package length */
+
+ field->value.size = acpi_ps_get_next_package_length (parser_state);
+ break;
+
+
+ case AML_RESERVEDFIELD_OP:
+
+ /* Get the length which is encoded as a package length */
+
+ field->value.size = acpi_ps_get_next_package_length (parser_state);
+ break;
+
+
+ case AML_ACCESSFIELD_OP:
+
+ /* Get Access_type and Access_atrib and merge into the field Op */
+
+ field->value.integer = ((GET8 (parser_state->aml) << 8) |
+ GET8 (parser_state->aml));
+ parser_state->aml += 2;
+ break;
+ }
+ }
+
+ return (field);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: Acpi_ps_get_next_arg
+ *
+ * PARAMETERS: Parser_state - Current parser state object
+ * Arg_type - The argument type (AML_*_ARG)
+ * Arg_count - If the argument points to a control method
+ * the method's argument is returned here.
+ *
+ * RETURN: An op object containing the next argument.
+ *
+ * DESCRIPTION: Get next argument (including complex list arguments that require
+ * pushing the parser stack)
+ *
+ ******************************************************************************/
+
+ACPI_GENERIC_OP *
+acpi_ps_get_next_arg (
+ ACPI_PARSE_STATE *parser_state,
+ s32 arg_type,
+ u32 *arg_count)
+{
+ ACPI_GENERIC_OP *arg = NULL;
+ ACPI_GENERIC_OP *prev = NULL;
+ ACPI_GENERIC_OP *field;
+ s32 subop;
+
+
+ switch (arg_type)
+ {
+ case ARGP_BYTEDATA:
+ case ARGP_WORDDATA:
+ case ARGP_DWORDDATA:
+ case ARGP_CHARLIST:
+ case ARGP_NAME:
+ case ARGP_NAMESTRING:
+
+ /* constants, strings, and namestrings are all the same size */
+
+ arg = acpi_ps_alloc_op (AML_BYTE_OP);
+ if (arg) {
+ acpi_ps_get_next_simple_arg (parser_state, arg_type, arg);
+ }
+ break;
+
+
+ case ARGP_PKGLENGTH:
+
+ /* package length, nothing returned */
+
+ parser_state->pkg_end = acpi_ps_get_next_package_end (parser_state);
+ break;
+
+
+ case ARGP_FIELDLIST:
+
+ if (parser_state->aml < parser_state->pkg_end) {
+ /* non-empty list */
+
+ while (parser_state->aml < parser_state->pkg_end) {
+ field = acpi_ps_get_next_field (parser_state);
+ if (!field) {
+ break;
+ }
+
+ if (prev) {
+ prev->next = field;
+ }
+
+ else {
+ arg = field;
+ }
+
+ prev = field;
+ }
+
+ /* skip to End of byte data */
+
+ parser_state->aml = parser_state->pkg_end;
+ }
+ break;
+
+
+ case ARGP_BYTELIST:
+
+ if (parser_state->aml < parser_state->pkg_end) {
+ /* non-empty list */
+
+ arg = acpi_ps_alloc_op (AML_BYTELIST_OP);
+ if (arg) {
+ /* fill in bytelist data */
+
+ arg->value.size = (parser_state->pkg_end - parser_state->aml);
+ acpi_ps_to_bytelist_op (arg)->data = parser_state->aml;
+ }
+
+ /* skip to End of byte data */
+
+ parser_state->aml = parser_state->pkg_end;
+ }
+ break;
+
+
+ case ARGP_TARGET:
+ case ARGP_SUPERNAME:
+ {
+ subop = acpi_ps_peek_opcode (parser_state);
+ if (subop == 0 ||
+ acpi_ps_is_leading_char (subop) ||
+ acpi_ps_is_prefix_char (subop))
+ {
+ /* Null_name or Name_string */
+
+ arg = acpi_ps_alloc_op (AML_NAMEPATH_OP);
+ if (arg) {
+ acpi_ps_get_next_namepath (parser_state, arg, arg_count, 0);
+ }
+ }
+
+ else {
+ /* single complex argument, nothing returned */
+
+ *arg_count = 1;
+ }
+ }
+ break;
+
+
+ case ARGP_DATAOBJ:
+ case ARGP_TERMARG:
+
+ /* single complex argument, nothing returned */
+
+ *arg_count = 1;
+ break;
+
+
+ case ARGP_DATAOBJLIST:
+ case ARGP_TERMLIST:
+ case ARGP_OBJLIST:
+
+ if (parser_state->aml < parser_state->pkg_end) {
+ /* non-empty list of variable arguments, nothing returned */
+
+ *arg_count = ACPI_VAR_ARGS;
+ }
+ break;
+ }
+
+ return (arg);
+}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)