Pull Kconfig into release branch
[pandora-kernel.git] / drivers / acpi / executer / exmisc.c
index a3f4d72..bd98aab 100644 (file)
@@ -6,7 +6,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2005, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -45,6 +45,7 @@
 #include <acpi/acpi.h>
 #include <acpi/acinterp.h>
 #include <acpi/amlcode.h>
+#include <acpi/amlresrc.h>
 
 #define _COMPONENT          ACPI_EXECUTER
 ACPI_MODULE_NAME("exmisc")
@@ -71,7 +72,7 @@ acpi_ex_get_object_reference(union acpi_operand_object *obj_desc,
        union acpi_operand_object *reference_obj;
        union acpi_operand_object *referenced_obj;
 
-       ACPI_FUNCTION_TRACE_PTR("ex_get_object_reference", obj_desc);
+       ACPI_FUNCTION_TRACE_PTR(ex_get_object_reference, obj_desc);
 
        *return_desc = NULL;
 
@@ -97,7 +98,8 @@ acpi_ex_get_object_reference(union acpi_operand_object *obj_desc,
 
                default:
 
-                       ACPI_REPORT_ERROR(("Unknown Reference opcode in get_reference %X\n", obj_desc->reference.opcode));
+                       ACPI_ERROR((AE_INFO, "Unknown Reference opcode %X",
+                                   obj_desc->reference.opcode));
                        return_ACPI_STATUS(AE_AML_INTERNAL);
                }
                break;
@@ -112,7 +114,8 @@ acpi_ex_get_object_reference(union acpi_operand_object *obj_desc,
 
        default:
 
-               ACPI_REPORT_ERROR(("Invalid descriptor type in get_reference: %X\n", ACPI_GET_DESCRIPTOR_TYPE(obj_desc)));
+               ACPI_ERROR((AE_INFO, "Invalid descriptor type %X",
+                           ACPI_GET_DESCRIPTOR_TYPE(obj_desc)));
                return_ACPI_STATUS(AE_TYPE);
        }
 
@@ -157,48 +160,65 @@ acpi_ex_concat_template(union acpi_operand_object *operand0,
                        union acpi_operand_object **actual_return_desc,
                        struct acpi_walk_state *walk_state)
 {
+       acpi_status status;
        union acpi_operand_object *return_desc;
        u8 *new_buf;
-       u8 *end_tag1;
-       u8 *end_tag2;
+       u8 *end_tag;
+       acpi_size length0;
        acpi_size length1;
-       acpi_size length2;
+       acpi_size new_length;
 
-       ACPI_FUNCTION_TRACE("ex_concat_template");
+       ACPI_FUNCTION_TRACE(ex_concat_template);
 
-       /* Find the end_tags in each resource template */
+       /*
+        * Find the end_tag descriptor in each resource template.
+        * Note1: returned pointers point TO the end_tag, not past it.
+        * Note2: zero-length buffers are allowed; treated like one end_tag
+        */
 
-       end_tag1 = acpi_ut_get_resource_end_tag(operand0);
-       end_tag2 = acpi_ut_get_resource_end_tag(operand1);
-       if (!end_tag1 || !end_tag2) {
-               return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
+       /* Get the length of the first resource template */
+
+       status = acpi_ut_get_resource_end_tag(operand0, &end_tag);
+       if (ACPI_FAILURE(status)) {
+               return_ACPI_STATUS(status);
        }
 
-       /* Compute the length of each part */
+       length0 = ACPI_PTR_DIFF(end_tag, operand0->buffer.pointer);
 
-       length1 = ACPI_PTR_DIFF(end_tag1, operand0->buffer.pointer);
-       length2 = ACPI_PTR_DIFF(end_tag2, operand1->buffer.pointer) + 2;        /* Size of END_TAG */
+       /* Get the length of the second resource template */
 
-       /* Create a new buffer object for the result */
+       status = acpi_ut_get_resource_end_tag(operand1, &end_tag);
+       if (ACPI_FAILURE(status)) {
+               return_ACPI_STATUS(status);
+       }
+
+       length1 = ACPI_PTR_DIFF(end_tag, operand1->buffer.pointer);
+
+       /* Combine both lengths, minimum size will be 2 for end_tag */
 
-       return_desc = acpi_ut_create_buffer_object(length1 + length2);
+       new_length = length0 + length1 + sizeof(struct aml_resource_end_tag);
+
+       /* Create a new buffer object for the result (with one end_tag) */
+
+       return_desc = acpi_ut_create_buffer_object(new_length);
        if (!return_desc) {
                return_ACPI_STATUS(AE_NO_MEMORY);
        }
 
-       /* Copy the templates to the new descriptor */
-
+       /*
+        * Copy the templates to the new buffer, 0 first, then 1 follows. One
+        * end_tag descriptor is copied from Operand1.
+        */
        new_buf = return_desc->buffer.pointer;
-       ACPI_MEMCPY(new_buf, operand0->buffer.pointer, length1);
-       ACPI_MEMCPY(new_buf + length1, operand1->buffer.pointer, length2);
+       ACPI_MEMCPY(new_buf, operand0->buffer.pointer, length0);
+       ACPI_MEMCPY(new_buf + length0, operand1->buffer.pointer, length1);
 
-       /* Compute the new checksum */
+       /* Insert end_tag and set the checksum to zero, means "ignore checksum" */
 
-       new_buf[return_desc->buffer.length - 1] =
-           acpi_ut_generate_checksum(return_desc->buffer.pointer,
-                                     (return_desc->buffer.length - 1));
+       new_buf[new_length - 1] = 0;
+       new_buf[new_length - 2] = ACPI_RESOURCE_NAME_END_TAG | 1;
 
-       /* Return the completed template descriptor */
+       /* Return the completed resource template */
 
        *actual_return_desc = return_desc;
        return_ACPI_STATUS(AE_OK);
@@ -229,9 +249,8 @@ acpi_ex_do_concatenate(union acpi_operand_object *operand0,
        union acpi_operand_object *return_desc;
        char *new_buf;
        acpi_status status;
-       acpi_size new_length;
 
-       ACPI_FUNCTION_TRACE("ex_do_concatenate");
+       ACPI_FUNCTION_TRACE(ex_do_concatenate);
 
        /*
         * Convert the second operand if necessary.  The first operand
@@ -256,8 +275,8 @@ acpi_ex_do_concatenate(union acpi_operand_object *operand0,
                break;
 
        default:
-               ACPI_REPORT_ERROR(("Concat - invalid obj type: %X\n",
-                                  ACPI_GET_OBJECT_TYPE(operand0)));
+               ACPI_ERROR((AE_INFO, "Invalid object type: %X",
+                           ACPI_GET_OBJECT_TYPE(operand0)));
                status = AE_AML_INTERNAL;
        }
 
@@ -296,8 +315,7 @@ acpi_ex_do_concatenate(union acpi_operand_object *operand0,
 
                /* Copy the first integer, LSB first */
 
-               ACPI_MEMCPY(new_buf,
-                           &operand0->integer.value,
+               ACPI_MEMCPY(new_buf, &operand0->integer.value,
                            acpi_gbl_integer_byte_width);
 
                /* Copy the second integer (LSB first) after the first */
@@ -311,14 +329,11 @@ acpi_ex_do_concatenate(union acpi_operand_object *operand0,
 
                /* Result of two Strings is a String */
 
-               new_length = (acpi_size) operand0->string.length +
-                   (acpi_size) local_operand1->string.length;
-               if (new_length > ACPI_MAX_STRING_CONVERSION) {
-                       status = AE_AML_STRING_LIMIT;
-                       goto cleanup;
-               }
-
-               return_desc = acpi_ut_create_string_object(new_length);
+               return_desc = acpi_ut_create_string_object((acpi_size)
+                                                          (operand0->string.
+                                                           length +
+                                                           local_operand1->
+                                                           string.length));
                if (!return_desc) {
                        status = AE_NO_MEMORY;
                        goto cleanup;
@@ -338,11 +353,10 @@ acpi_ex_do_concatenate(union acpi_operand_object *operand0,
                /* Result of two Buffers is a Buffer */
 
                return_desc = acpi_ut_create_buffer_object((acpi_size)
-                                                          operand0->buffer.
-                                                          length +
-                                                          (acpi_size)
-                                                          local_operand1->
-                                                          buffer.length);
+                                                          (operand0->buffer.
+                                                           length +
+                                                           local_operand1->
+                                                           buffer.length));
                if (!return_desc) {
                        status = AE_NO_MEMORY;
                        goto cleanup;
@@ -352,8 +366,8 @@ acpi_ex_do_concatenate(union acpi_operand_object *operand0,
 
                /* Concatenate the buffers */
 
-               ACPI_MEMCPY(new_buf,
-                           operand0->buffer.pointer, operand0->buffer.length);
+               ACPI_MEMCPY(new_buf, operand0->buffer.pointer,
+                           operand0->buffer.length);
                ACPI_MEMCPY(new_buf + operand0->buffer.length,
                            local_operand1->buffer.pointer,
                            local_operand1->buffer.length);
@@ -363,8 +377,8 @@ acpi_ex_do_concatenate(union acpi_operand_object *operand0,
 
                /* Invalid object type, should not happen here */
 
-               ACPI_REPORT_ERROR(("Concatenate - Invalid object type: %X\n",
-                                  ACPI_GET_OBJECT_TYPE(operand0)));
+               ACPI_ERROR((AE_INFO, "Invalid object type: %X",
+                           ACPI_GET_OBJECT_TYPE(operand0)));
                status = AE_AML_INTERNAL;
                goto cleanup;
        }
@@ -431,10 +445,24 @@ acpi_ex_do_math_op(u16 opcode, acpi_integer integer0, acpi_integer integer1)
 
        case AML_SHIFT_LEFT_OP: /* shift_left (Operand, shift_count, Result) */
 
+               /*
+                * We need to check if the shiftcount is larger than the integer bit
+                * width since the behavior of this is not well-defined in the C language.
+                */
+               if (integer1 >= acpi_gbl_integer_bit_width) {
+                       return (0);
+               }
                return (integer0 << integer1);
 
        case AML_SHIFT_RIGHT_OP:        /* shift_right (Operand, shift_count, Result) */
 
+               /*
+                * We need to check if the shiftcount is larger than the integer bit
+                * width since the behavior of this is not well-defined in the C language.
+                */
+               if (integer1 >= acpi_gbl_integer_bit_width) {
+                       return (0);
+               }
                return (integer0 >> integer1);
 
        case AML_SUBTRACT_OP:   /* Subtract (Integer0, Integer1, Result) */
@@ -475,7 +503,7 @@ acpi_ex_do_logical_numeric_op(u16 opcode,
        acpi_status status = AE_OK;
        u8 local_result = FALSE;
 
-       ACPI_FUNCTION_TRACE("ex_do_logical_numeric_op");
+       ACPI_FUNCTION_TRACE(ex_do_logical_numeric_op);
 
        switch (opcode) {
        case AML_LAND_OP:       /* LAnd (Integer0, Integer1) */
@@ -543,7 +571,7 @@ acpi_ex_do_logical_op(u16 opcode,
        u8 local_result = FALSE;
        int compare;
 
-       ACPI_FUNCTION_TRACE("ex_do_logical_op");
+       ACPI_FUNCTION_TRACE(ex_do_logical_op);
 
        /*
         * Convert the second operand if necessary.  The first operand
@@ -625,9 +653,8 @@ acpi_ex_do_logical_op(u16 opcode,
 
                /* Lexicographic compare: compare the data bytes */
 
-               compare = ACPI_MEMCMP((const char *)operand0->buffer.pointer,
-                                     (const char *)local_operand1->buffer.
-                                     pointer,
+               compare = ACPI_MEMCMP(operand0->buffer.pointer,
+                                     local_operand1->buffer.pointer,
                                      (length0 > length1) ? length1 : length0);
 
                switch (opcode) {
@@ -636,6 +663,7 @@ acpi_ex_do_logical_op(u16 opcode,
                        /* Length and all bytes must be equal */
 
                        if ((length0 == length1) && (compare == 0)) {
+
                                /* Length and all bytes match ==> TRUE */
 
                                local_result = TRUE;