X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=drivers%2Facpi%2Fexecuter%2Fexmisc.c;h=bd98aab017cf577768ad09f41b0634a3f8d3dc7f;hb=refs%2Fheads%2Fvserver;hp=74fd68491ba85a7cb681302713419e6e48a8f8ab;hpb=5273a3df6485dc2ad6aa7ddd441b9a21970f003b;p=linux-2.6.git diff --git a/drivers/acpi/executer/exmisc.c b/drivers/acpi/executer/exmisc.c index 74fd68491..bd98aab01 100644 --- a/drivers/acpi/executer/exmisc.c +++ b/drivers/acpi/executer/exmisc.c @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2004, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -42,15 +42,13 @@ * POSSIBILITY OF SUCH DAMAGES. */ - #include #include #include - +#include #define _COMPONENT ACPI_EXECUTER - ACPI_MODULE_NAME ("exmisc") - +ACPI_MODULE_NAME("exmisc") /******************************************************************************* * @@ -66,27 +64,23 @@ * Common code for the ref_of_op and the cond_ref_of_op. * ******************************************************************************/ - acpi_status -acpi_ex_get_object_reference ( - union acpi_operand_object *obj_desc, - union acpi_operand_object **return_desc, - struct acpi_walk_state *walk_state) +acpi_ex_get_object_reference(union acpi_operand_object *obj_desc, + union acpi_operand_object **return_desc, + struct acpi_walk_state *walk_state) { - union acpi_operand_object *reference_obj; - union acpi_operand_object *referenced_obj; - - - ACPI_FUNCTION_TRACE_PTR ("ex_get_object_reference", obj_desc); + union acpi_operand_object *reference_obj; + union acpi_operand_object *referenced_obj; + ACPI_FUNCTION_TRACE_PTR(ex_get_object_reference, obj_desc); *return_desc = NULL; - switch (ACPI_GET_DESCRIPTOR_TYPE (obj_desc)) { + switch (ACPI_GET_DESCRIPTOR_TYPE(obj_desc)) { case ACPI_DESC_TYPE_OPERAND: - if (ACPI_GET_OBJECT_TYPE (obj_desc) != ACPI_TYPE_LOCAL_REFERENCE) { - return_ACPI_STATUS (AE_AML_OPERAND_TYPE); + if (ACPI_GET_OBJECT_TYPE(obj_desc) != ACPI_TYPE_LOCAL_REFERENCE) { + return_ACPI_STATUS(AE_AML_OPERAND_TYPE); } /* @@ -95,6 +89,7 @@ acpi_ex_get_object_reference ( switch (obj_desc->reference.opcode) { case AML_LOCAL_OP: case AML_ARG_OP: + case AML_DEBUG_OP: /* The referenced object is the pseudo-node for the local/arg */ @@ -103,13 +98,12 @@ acpi_ex_get_object_reference ( default: - ACPI_REPORT_ERROR (("Unknown Reference subtype in get ref %X\n", - obj_desc->reference.opcode)); - return_ACPI_STATUS (AE_AML_INTERNAL); + ACPI_ERROR((AE_INFO, "Unknown Reference opcode %X", + obj_desc->reference.opcode)); + return_ACPI_STATUS(AE_AML_INTERNAL); } break; - case ACPI_DESC_TYPE_NAMED: /* @@ -118,39 +112,40 @@ acpi_ex_get_object_reference ( referenced_obj = obj_desc; break; - default: - ACPI_REPORT_ERROR (("Invalid descriptor type in get ref: %X\n", - ACPI_GET_DESCRIPTOR_TYPE (obj_desc))); - return_ACPI_STATUS (AE_TYPE); + ACPI_ERROR((AE_INFO, "Invalid descriptor type %X", + ACPI_GET_DESCRIPTOR_TYPE(obj_desc))); + return_ACPI_STATUS(AE_TYPE); } - /* Create a new reference object */ - reference_obj = acpi_ut_create_internal_object (ACPI_TYPE_LOCAL_REFERENCE); + reference_obj = + acpi_ut_create_internal_object(ACPI_TYPE_LOCAL_REFERENCE); if (!reference_obj) { - return_ACPI_STATUS (AE_NO_MEMORY); + return_ACPI_STATUS(AE_NO_MEMORY); } reference_obj->reference.opcode = AML_REF_OF_OP; reference_obj->reference.object = referenced_obj; *return_desc = reference_obj; - ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Object %p Type [%s], returning Reference %p\n", - obj_desc, acpi_ut_get_object_type_name (obj_desc), *return_desc)); + ACPI_DEBUG_PRINT((ACPI_DB_EXEC, + "Object %p Type [%s], returning Reference %p\n", + obj_desc, acpi_ut_get_object_type_name(obj_desc), + *return_desc)); - return_ACPI_STATUS (AE_OK); + return_ACPI_STATUS(AE_OK); } - /******************************************************************************* * * FUNCTION: acpi_ex_concat_template * - * PARAMETERS: *obj_desc - Object to be converted. Must be an - * Integer, Buffer, or String + * PARAMETERS: Operand0 - First source object + * Operand1 - Second source object + * actual_return_desc - Where to place the return object * walk_state - Current walk state * * RETURN: Status @@ -160,69 +155,81 @@ acpi_ex_get_object_reference ( ******************************************************************************/ acpi_status -acpi_ex_concat_template ( - union acpi_operand_object *obj_desc1, - union acpi_operand_object *obj_desc2, - union acpi_operand_object **actual_return_desc, - struct acpi_walk_state *walk_state) +acpi_ex_concat_template(union acpi_operand_object *operand0, + union acpi_operand_object *operand1, + union acpi_operand_object **actual_return_desc, + struct acpi_walk_state *walk_state) { - union acpi_operand_object *return_desc; - u8 *new_buf; - u8 *end_tag1; - u8 *end_tag2; - acpi_size length1; - acpi_size length2; + acpi_status status; + union acpi_operand_object *return_desc; + u8 *new_buf; + u8 *end_tag; + acpi_size length0; + acpi_size length1; + acpi_size new_length; + + ACPI_FUNCTION_TRACE(ex_concat_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 + */ + /* Get the length of the first resource template */ - ACPI_FUNCTION_TRACE ("ex_concat_template"); + status = acpi_ut_get_resource_end_tag(operand0, &end_tag); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + length0 = ACPI_PTR_DIFF(end_tag, operand0->buffer.pointer); - /* Find the end_tags in each resource template */ + /* Get the length of the second resource template */ - end_tag1 = acpi_ut_get_resource_end_tag (obj_desc1); - end_tag2 = acpi_ut_get_resource_end_tag (obj_desc2); - if (!end_tag1 || !end_tag2) { - return_ACPI_STATUS (AE_AML_OPERAND_TYPE); + status = acpi_ut_get_resource_end_tag(operand1, &end_tag); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); } - /* Compute the length of each part */ + length1 = ACPI_PTR_DIFF(end_tag, operand1->buffer.pointer); + + /* Combine both lengths, minimum size will be 2 for end_tag */ - length1 = ACPI_PTR_DIFF (end_tag1, obj_desc1->buffer.pointer); - length2 = ACPI_PTR_DIFF (end_tag2, obj_desc2->buffer.pointer) + - 2; /* Size of END_TAG */ + new_length = length0 + length1 + sizeof(struct aml_resource_end_tag); - /* Create a new buffer object for the result */ + /* Create a new buffer object for the result (with one end_tag) */ - return_desc = acpi_ut_create_buffer_object (length1 + length2); + return_desc = acpi_ut_create_buffer_object(new_length); if (!return_desc) { - return_ACPI_STATUS (AE_NO_MEMORY); + 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, obj_desc1->buffer.pointer, length1); - ACPI_MEMCPY (new_buf + length1, obj_desc2->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); + return_ACPI_STATUS(AE_OK); } - /******************************************************************************* * * FUNCTION: acpi_ex_do_concatenate * - * PARAMETERS: obj_desc1 - First source object - * obj_desc2 - Second source object + * PARAMETERS: Operand0 - First source object + * Operand1 - Second source object * actual_return_desc - Where to place the return object * walk_state - Current walk state * @@ -233,21 +240,55 @@ acpi_ex_concat_template ( ******************************************************************************/ acpi_status -acpi_ex_do_concatenate ( - union acpi_operand_object *obj_desc1, - union acpi_operand_object *obj_desc2, - union acpi_operand_object **actual_return_desc, - struct acpi_walk_state *walk_state) +acpi_ex_do_concatenate(union acpi_operand_object *operand0, + union acpi_operand_object *operand1, + union acpi_operand_object **actual_return_desc, + struct acpi_walk_state *walk_state) { - acpi_status status; - u32 i; - acpi_integer this_integer; - union acpi_operand_object *return_desc; - char *new_buf; + union acpi_operand_object *local_operand1 = operand1; + union acpi_operand_object *return_desc; + char *new_buf; + acpi_status status; + + ACPI_FUNCTION_TRACE(ex_do_concatenate); + /* + * Convert the second operand if necessary. The first operand + * determines the type of the second operand, (See the Data Types + * section of the ACPI specification.) Both object types are + * guaranteed to be either Integer/String/Buffer by the operand + * resolution mechanism. + */ + switch (ACPI_GET_OBJECT_TYPE(operand0)) { + case ACPI_TYPE_INTEGER: + status = + acpi_ex_convert_to_integer(operand1, &local_operand1, 16); + break; - ACPI_FUNCTION_ENTRY (); + case ACPI_TYPE_STRING: + status = acpi_ex_convert_to_string(operand1, &local_operand1, + ACPI_IMPLICIT_CONVERT_HEX); + break; + case ACPI_TYPE_BUFFER: + status = acpi_ex_convert_to_buffer(operand1, &local_operand1); + break; + + default: + ACPI_ERROR((AE_INFO, "Invalid object type: %X", + ACPI_GET_OBJECT_TYPE(operand0))); + status = AE_AML_INTERNAL; + } + + if (ACPI_FAILURE(status)) { + goto cleanup; + } + + /* + * Both operands are now known to be the same object type + * (Both are Integer, String, or Buffer), and we can now perform the + * concatenation. + */ /* * There are three cases to handle: @@ -256,123 +297,108 @@ acpi_ex_do_concatenate ( * 2) Two Strings concatenated to produce a new String * 3) Two Buffers concatenated to produce a new Buffer */ - switch (ACPI_GET_OBJECT_TYPE (obj_desc1)) { + switch (ACPI_GET_OBJECT_TYPE(operand0)) { case ACPI_TYPE_INTEGER: /* Result of two Integers is a Buffer */ /* Need enough buffer space for two integers */ - return_desc = acpi_ut_create_buffer_object (acpi_gbl_integer_byte_width * 2); + return_desc = acpi_ut_create_buffer_object((acpi_size) + ACPI_MUL_2 + (acpi_gbl_integer_byte_width)); if (!return_desc) { - return (AE_NO_MEMORY); + status = AE_NO_MEMORY; + goto cleanup; } - new_buf = (char *) return_desc->buffer.pointer; + new_buf = (char *)return_desc->buffer.pointer; - /* Convert the first integer */ + /* Copy the first integer, LSB first */ - this_integer = obj_desc1->integer.value; - for (i = 0; i < acpi_gbl_integer_byte_width; i++) { - new_buf[i] = (char) this_integer; - this_integer >>= 8; - } + ACPI_MEMCPY(new_buf, &operand0->integer.value, + acpi_gbl_integer_byte_width); - /* Convert the second integer */ - - this_integer = obj_desc2->integer.value; - for (; i < (ACPI_MUL_2 (acpi_gbl_integer_byte_width)); i++) { - new_buf[i] = (char) this_integer; - this_integer >>= 8; - } + /* Copy the second integer (LSB first) after the first */ + ACPI_MEMCPY(new_buf + acpi_gbl_integer_byte_width, + &local_operand1->integer.value, + acpi_gbl_integer_byte_width); break; - case ACPI_TYPE_STRING: /* Result of two Strings is a String */ - return_desc = acpi_ut_create_internal_object (ACPI_TYPE_STRING); + return_desc = acpi_ut_create_string_object((acpi_size) + (operand0->string. + length + + local_operand1-> + string.length)); if (!return_desc) { - return (AE_NO_MEMORY); - } - - /* Operand0 is string */ - - new_buf = ACPI_MEM_CALLOCATE ((acpi_size) obj_desc1->string.length + - (acpi_size) obj_desc2->string.length + 1); - if (!new_buf) { - ACPI_REPORT_ERROR - (("ex_do_concatenate: String allocation failure\n")); status = AE_NO_MEMORY; goto cleanup; } - /* Concatenate the strings */ - - ACPI_STRCPY (new_buf, obj_desc1->string.pointer); - ACPI_STRCPY (new_buf + obj_desc1->string.length, - obj_desc2->string.pointer); + new_buf = return_desc->string.pointer; - /* Complete the String object initialization */ + /* Concatenate the strings */ - return_desc->string.pointer = new_buf; - return_desc->string.length = obj_desc1->string.length + - obj_desc2->string.length; + ACPI_STRCPY(new_buf, operand0->string.pointer); + ACPI_STRCPY(new_buf + operand0->string.length, + local_operand1->string.pointer); break; - case ACPI_TYPE_BUFFER: /* Result of two Buffers is a Buffer */ - return_desc = acpi_ut_create_buffer_object ( - (acpi_size) obj_desc1->buffer.length + - (acpi_size) obj_desc2->buffer.length); + return_desc = acpi_ut_create_buffer_object((acpi_size) + (operand0->buffer. + length + + local_operand1-> + buffer.length)); if (!return_desc) { - return (AE_NO_MEMORY); + status = AE_NO_MEMORY; + goto cleanup; } - new_buf = (char *) return_desc->buffer.pointer; + new_buf = (char *)return_desc->buffer.pointer; /* Concatenate the buffers */ - ACPI_MEMCPY (new_buf, obj_desc1->buffer.pointer, - obj_desc1->buffer.length); - ACPI_MEMCPY (new_buf + obj_desc1->buffer.length, obj_desc2->buffer.pointer, - obj_desc2->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); break; - default: /* Invalid object type, should not happen here */ - ACPI_REPORT_ERROR (("Concat - invalid obj type: %X\n", - ACPI_GET_OBJECT_TYPE (obj_desc1))); + ACPI_ERROR((AE_INFO, "Invalid object type: %X", + ACPI_GET_OBJECT_TYPE(operand0))); status = AE_AML_INTERNAL; - return_desc = NULL; + goto cleanup; } *actual_return_desc = return_desc; - return (AE_OK); - -cleanup: - - acpi_ut_remove_reference (return_desc); - return (status); + cleanup: + if (local_operand1 != operand1) { + acpi_ut_remove_reference(local_operand1); + } + return_ACPI_STATUS(status); } - /******************************************************************************* * * FUNCTION: acpi_ex_do_math_op * * PARAMETERS: Opcode - AML opcode - * Operand0 - Integer operand #0 - * Operand1 - Integer operand #1 + * Integer0 - Integer operand #0 + * Integer1 - Integer operand #1 * * RETURN: Integer result of the operation * @@ -383,84 +409,147 @@ cleanup: ******************************************************************************/ acpi_integer -acpi_ex_do_math_op ( - u16 opcode, - acpi_integer operand0, - acpi_integer operand1) +acpi_ex_do_math_op(u16 opcode, acpi_integer integer0, acpi_integer integer1) { + ACPI_FUNCTION_ENTRY(); switch (opcode) { - case AML_ADD_OP: /* Add (Operand0, Operand1, Result) */ + case AML_ADD_OP: /* Add (Integer0, Integer1, Result) */ - return (operand0 + operand1); + return (integer0 + integer1); + case AML_BIT_AND_OP: /* And (Integer0, Integer1, Result) */ - case AML_BIT_AND_OP: /* And (Operand0, Operand1, Result) */ + return (integer0 & integer1); - return (operand0 & operand1); + case AML_BIT_NAND_OP: /* NAnd (Integer0, Integer1, Result) */ + return (~(integer0 & integer1)); - case AML_BIT_NAND_OP: /* NAnd (Operand0, Operand1, Result) */ + case AML_BIT_OR_OP: /* Or (Integer0, Integer1, Result) */ - return (~(operand0 & operand1)); + return (integer0 | integer1); + case AML_BIT_NOR_OP: /* NOr (Integer0, Integer1, Result) */ - case AML_BIT_OR_OP: /* Or (Operand0, Operand1, Result) */ + return (~(integer0 | integer1)); - return (operand0 | operand1); + case AML_BIT_XOR_OP: /* XOr (Integer0, Integer1, Result) */ + return (integer0 ^ integer1); - case AML_BIT_NOR_OP: /* NOr (Operand0, Operand1, Result) */ + case AML_MULTIPLY_OP: /* Multiply (Integer0, Integer1, Result) */ - return (~(operand0 | operand1)); + return (integer0 * integer1); + case AML_SHIFT_LEFT_OP: /* shift_left (Operand, shift_count, Result) */ - case AML_BIT_XOR_OP: /* XOr (Operand0, Operand1, 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); - return (operand0 ^ operand1); + 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_MULTIPLY_OP: /* Multiply (Operand0, Operand1, Result) */ + case AML_SUBTRACT_OP: /* Subtract (Integer0, Integer1, Result) */ - return (operand0 * operand1); + return (integer0 - integer1); + default: - case AML_SHIFT_LEFT_OP: /* shift_left (Operand, shift_count, Result) */ + return (0); + } +} - return (operand0 << operand1); +/******************************************************************************* + * + * FUNCTION: acpi_ex_do_logical_numeric_op + * + * PARAMETERS: Opcode - AML opcode + * Integer0 - Integer operand #0 + * Integer1 - Integer operand #1 + * logical_result - TRUE/FALSE result of the operation + * + * RETURN: Status + * + * DESCRIPTION: Execute a logical "Numeric" AML opcode. For these Numeric + * operators (LAnd and LOr), both operands must be integers. + * + * Note: cleanest machine code seems to be produced by the code + * below, rather than using statements of the form: + * Result = (Integer0 && Integer1); + * + ******************************************************************************/ +acpi_status +acpi_ex_do_logical_numeric_op(u16 opcode, + acpi_integer integer0, + acpi_integer integer1, u8 * logical_result) +{ + acpi_status status = AE_OK; + u8 local_result = FALSE; - case AML_SHIFT_RIGHT_OP: /* shift_right (Operand, shift_count, Result) */ + ACPI_FUNCTION_TRACE(ex_do_logical_numeric_op); - return (operand0 >> operand1); + switch (opcode) { + case AML_LAND_OP: /* LAnd (Integer0, Integer1) */ + if (integer0 && integer1) { + local_result = TRUE; + } + break; - case AML_SUBTRACT_OP: /* Subtract (Operand0, Operand1, Result) */ + case AML_LOR_OP: /* LOr (Integer0, Integer1) */ - return (operand0 - operand1); + if (integer0 || integer1) { + local_result = TRUE; + } + break; default: - - return (0); + status = AE_AML_INTERNAL; + break; } -} + /* Return the logical result and status */ + + *logical_result = local_result; + return_ACPI_STATUS(status); +} /******************************************************************************* * * FUNCTION: acpi_ex_do_logical_op * * PARAMETERS: Opcode - AML opcode - * Operand0 - Integer operand #0 - * Operand1 - Integer operand #1 + * Operand0 - operand #0 + * Operand1 - operand #1 + * logical_result - TRUE/FALSE result of the operation * - * RETURN: TRUE/FALSE result of the operation + * RETURN: Status * * DESCRIPTION: Execute a logical AML opcode. The purpose of having all of the * functions here is to prevent a lot of pointer dereferencing * to obtain the operands and to simplify the generation of the - * logical value. + * logical value. For the Numeric operators (LAnd and LOr), both + * operands must be integers. For the other logical operators, + * operands can be any combination of Integer/String/Buffer. The + * first operand determines the type to which the second operand + * will be converted. * * Note: cleanest machine code seems to be produced by the code * below, rather than using statements of the form: @@ -468,60 +557,169 @@ acpi_ex_do_math_op ( * ******************************************************************************/ -u8 -acpi_ex_do_logical_op ( - u16 opcode, - acpi_integer operand0, - acpi_integer operand1) +acpi_status +acpi_ex_do_logical_op(u16 opcode, + union acpi_operand_object *operand0, + union acpi_operand_object *operand1, u8 * logical_result) { + union acpi_operand_object *local_operand1 = operand1; + acpi_integer integer0; + acpi_integer integer1; + u32 length0; + u32 length1; + acpi_status status = AE_OK; + u8 local_result = FALSE; + int compare; + ACPI_FUNCTION_TRACE(ex_do_logical_op); - switch (opcode) { + /* + * Convert the second operand if necessary. The first operand + * determines the type of the second operand, (See the Data Types + * section of the ACPI 3.0+ specification.) Both object types are + * guaranteed to be either Integer/String/Buffer by the operand + * resolution mechanism. + */ + switch (ACPI_GET_OBJECT_TYPE(operand0)) { + case ACPI_TYPE_INTEGER: + status = + acpi_ex_convert_to_integer(operand1, &local_operand1, 16); + break; - case AML_LAND_OP: /* LAnd (Operand0, Operand1) */ + case ACPI_TYPE_STRING: + status = acpi_ex_convert_to_string(operand1, &local_operand1, + ACPI_IMPLICIT_CONVERT_HEX); + break; - if (operand0 && operand1) { - return (TRUE); - } + case ACPI_TYPE_BUFFER: + status = acpi_ex_convert_to_buffer(operand1, &local_operand1); break; + default: + status = AE_AML_INTERNAL; + break; + } - case AML_LEQUAL_OP: /* LEqual (Operand0, Operand1) */ + if (ACPI_FAILURE(status)) { + goto cleanup; + } - if (operand0 == operand1) { - return (TRUE); - } - break; + /* + * Two cases: 1) Both Integers, 2) Both Strings or Buffers + */ + if (ACPI_GET_OBJECT_TYPE(operand0) == ACPI_TYPE_INTEGER) { + /* + * 1) Both operands are of type integer + * Note: local_operand1 may have changed above + */ + integer0 = operand0->integer.value; + integer1 = local_operand1->integer.value; + switch (opcode) { + case AML_LEQUAL_OP: /* LEqual (Operand0, Operand1) */ - case AML_LGREATER_OP: /* LGreater (Operand0, Operand1) */ + if (integer0 == integer1) { + local_result = TRUE; + } + break; - if (operand0 > operand1) { - return (TRUE); - } - break; + case AML_LGREATER_OP: /* LGreater (Operand0, Operand1) */ + + if (integer0 > integer1) { + local_result = TRUE; + } + break; + case AML_LLESS_OP: /* LLess (Operand0, Operand1) */ - case AML_LLESS_OP: /* LLess (Operand0, Operand1) */ + if (integer0 < integer1) { + local_result = TRUE; + } + break; - if (operand0 < operand1) { - return (TRUE); + default: + status = AE_AML_INTERNAL; + break; } - break; + } else { + /* + * 2) Both operands are Strings or both are Buffers + * Note: Code below takes advantage of common Buffer/String + * object fields. local_operand1 may have changed above. Use + * memcmp to handle nulls in buffers. + */ + length0 = operand0->buffer.length; + length1 = local_operand1->buffer.length; + /* Lexicographic compare: compare the data bytes */ - case AML_LOR_OP: /* LOr (Operand0, Operand1) */ + compare = ACPI_MEMCMP(operand0->buffer.pointer, + local_operand1->buffer.pointer, + (length0 > length1) ? length1 : length0); - if (operand0 || operand1) { - return (TRUE); - } - break; + switch (opcode) { + case AML_LEQUAL_OP: /* LEqual (Operand0, Operand1) */ - default: - break; + /* Length and all bytes must be equal */ + + if ((length0 == length1) && (compare == 0)) { + + /* Length and all bytes match ==> TRUE */ + + local_result = TRUE; + } + break; + + case AML_LGREATER_OP: /* LGreater (Operand0, Operand1) */ + + if (compare > 0) { + local_result = TRUE; + goto cleanup; /* TRUE */ + } + if (compare < 0) { + goto cleanup; /* FALSE */ + } + + /* Bytes match (to shortest length), compare lengths */ + + if (length0 > length1) { + local_result = TRUE; + } + break; + + case AML_LLESS_OP: /* LLess (Operand0, Operand1) */ + + if (compare > 0) { + goto cleanup; /* FALSE */ + } + if (compare < 0) { + local_result = TRUE; + goto cleanup; /* TRUE */ + } + + /* Bytes match (to shortest length), compare lengths */ + + if (length0 < length1) { + local_result = TRUE; + } + break; + + default: + status = AE_AML_INTERNAL; + break; + } } - return (FALSE); -} + cleanup: + /* New object was created if implicit conversion performed - delete */ + if (local_operand1 != operand1) { + acpi_ut_remove_reference(local_operand1); + } + + /* Return the logical result and status */ + + *logical_result = local_result; + return_ACPI_STATUS(status); +}