^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /******************************************************************************
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * Module Name: exmisc - ACPI AML (p-code) execution - specific opcodes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Copyright (C) 2000 - 2020, Intel Corp.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) *****************************************************************************/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <acpi/acpi.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include "accommon.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include "acinterp.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include "amlcode.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #define _COMPONENT ACPI_EXECUTER
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) ACPI_MODULE_NAME("exmisc")
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) /*******************************************************************************
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) * FUNCTION: acpi_ex_get_object_reference
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) * PARAMETERS: obj_desc - Create a reference to this object
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) * return_desc - Where to store the reference
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) * walk_state - Current state
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) * RETURN: Status
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) * DESCRIPTION: Obtain and return a "reference" to the target object
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) * Common code for the ref_of_op and the cond_ref_of_op.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) ******************************************************************************/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) acpi_status
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) acpi_ex_get_object_reference(union acpi_operand_object *obj_desc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) union acpi_operand_object **return_desc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) struct acpi_walk_state *walk_state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) union acpi_operand_object *reference_obj;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) union acpi_operand_object *referenced_obj;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) ACPI_FUNCTION_TRACE_PTR(ex_get_object_reference, obj_desc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) *return_desc = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) switch (ACPI_GET_DESCRIPTOR_TYPE(obj_desc)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) case ACPI_DESC_TYPE_OPERAND:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) if (obj_desc->common.type != ACPI_TYPE_LOCAL_REFERENCE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) * Must be a reference to a Local or Arg
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) switch (obj_desc->reference.class) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) case ACPI_REFCLASS_LOCAL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) case ACPI_REFCLASS_ARG:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) case ACPI_REFCLASS_DEBUG:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) /* The referenced object is the pseudo-node for the local/arg */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) referenced_obj = obj_desc->reference.object;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) ACPI_ERROR((AE_INFO, "Invalid Reference Class 0x%2.2X",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) obj_desc->reference.class));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) case ACPI_DESC_TYPE_NAMED:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) * A named reference that has already been resolved to a Node
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) referenced_obj = obj_desc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) ACPI_ERROR((AE_INFO, "Invalid descriptor type 0x%X",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) ACPI_GET_DESCRIPTOR_TYPE(obj_desc)));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) return_ACPI_STATUS(AE_TYPE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) /* Create a new reference object */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) reference_obj =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) acpi_ut_create_internal_object(ACPI_TYPE_LOCAL_REFERENCE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) if (!reference_obj) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) return_ACPI_STATUS(AE_NO_MEMORY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) reference_obj->reference.class = ACPI_REFCLASS_REFOF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) reference_obj->reference.object = referenced_obj;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) *return_desc = reference_obj;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) "Object %p Type [%s], returning Reference %p\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) obj_desc, acpi_ut_get_object_type_name(obj_desc),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) *return_desc));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) return_ACPI_STATUS(AE_OK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) /*******************************************************************************
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) * FUNCTION: acpi_ex_do_math_op
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) * PARAMETERS: opcode - AML opcode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) * integer0 - Integer operand #0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) * integer1 - Integer operand #1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) * RETURN: Integer result of the operation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) * DESCRIPTION: Execute a math AML opcode. The purpose of having all of the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) * math functions here is to prevent a lot of pointer dereferencing
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) * to obtain the operands.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) ******************************************************************************/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) u64 acpi_ex_do_math_op(u16 opcode, u64 integer0, u64 integer1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) ACPI_FUNCTION_ENTRY();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) switch (opcode) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) case AML_ADD_OP: /* Add (Integer0, Integer1, Result) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) return (integer0 + integer1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) case AML_BIT_AND_OP: /* And (Integer0, Integer1, Result) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) return (integer0 & integer1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) case AML_BIT_NAND_OP: /* NAnd (Integer0, Integer1, Result) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) return (~(integer0 & integer1));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) case AML_BIT_OR_OP: /* Or (Integer0, Integer1, Result) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) return (integer0 | integer1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) case AML_BIT_NOR_OP: /* NOr (Integer0, Integer1, Result) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) return (~(integer0 | integer1));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) case AML_BIT_XOR_OP: /* XOr (Integer0, Integer1, Result) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) return (integer0 ^ integer1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) case AML_MULTIPLY_OP: /* Multiply (Integer0, Integer1, Result) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) return (integer0 * integer1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) case AML_SHIFT_LEFT_OP: /* shift_left (Operand, shift_count, Result) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) * We need to check if the shiftcount is larger than the integer bit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) * width since the behavior of this is not well-defined in the C language.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) if (integer1 >= acpi_gbl_integer_bit_width) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) return (0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) return (integer0 << integer1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) case AML_SHIFT_RIGHT_OP: /* shift_right (Operand, shift_count, Result) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) * We need to check if the shiftcount is larger than the integer bit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) * width since the behavior of this is not well-defined in the C language.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) if (integer1 >= acpi_gbl_integer_bit_width) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) return (0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) return (integer0 >> integer1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) case AML_SUBTRACT_OP: /* Subtract (Integer0, Integer1, Result) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) return (integer0 - integer1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) return (0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) /*******************************************************************************
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) * FUNCTION: acpi_ex_do_logical_numeric_op
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) * PARAMETERS: opcode - AML opcode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) * integer0 - Integer operand #0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) * integer1 - Integer operand #1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) * logical_result - TRUE/FALSE result of the operation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) * RETURN: Status
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) * DESCRIPTION: Execute a logical "Numeric" AML opcode. For these Numeric
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) * operators (LAnd and LOr), both operands must be integers.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) * Note: cleanest machine code seems to be produced by the code
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) * below, rather than using statements of the form:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) * Result = (Integer0 && Integer1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) ******************************************************************************/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) acpi_status
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) acpi_ex_do_logical_numeric_op(u16 opcode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) u64 integer0, u64 integer1, u8 *logical_result)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) acpi_status status = AE_OK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) u8 local_result = FALSE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) ACPI_FUNCTION_TRACE(ex_do_logical_numeric_op);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) switch (opcode) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) case AML_LOGICAL_AND_OP: /* LAnd (Integer0, Integer1) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) if (integer0 && integer1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) local_result = TRUE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) case AML_LOGICAL_OR_OP: /* LOr (Integer0, Integer1) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) if (integer0 || integer1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) local_result = TRUE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) ACPI_ERROR((AE_INFO,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) "Invalid numeric logical opcode: %X", opcode));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) status = AE_AML_INTERNAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) /* Return the logical result and status */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) *logical_result = local_result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) return_ACPI_STATUS(status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) /*******************************************************************************
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) * FUNCTION: acpi_ex_do_logical_op
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) * PARAMETERS: opcode - AML opcode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) * operand0 - operand #0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) * operand1 - operand #1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) * logical_result - TRUE/FALSE result of the operation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) * RETURN: Status
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) * DESCRIPTION: Execute a logical AML opcode. The purpose of having all of the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) * functions here is to prevent a lot of pointer dereferencing
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) * to obtain the operands and to simplify the generation of the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) * logical value. For the Numeric operators (LAnd and LOr), both
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) * operands must be integers. For the other logical operators,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) * operands can be any combination of Integer/String/Buffer. The
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) * first operand determines the type to which the second operand
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) * will be converted.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) * Note: cleanest machine code seems to be produced by the code
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) * below, rather than using statements of the form:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) * Result = (Operand0 == Operand1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) ******************************************************************************/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) acpi_status
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) acpi_ex_do_logical_op(u16 opcode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) union acpi_operand_object *operand0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) union acpi_operand_object *operand1, u8 * logical_result)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) union acpi_operand_object *local_operand1 = operand1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) u64 integer0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) u64 integer1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) u32 length0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) u32 length1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) acpi_status status = AE_OK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) u8 local_result = FALSE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) int compare;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) ACPI_FUNCTION_TRACE(ex_do_logical_op);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) * Convert the second operand if necessary. The first operand
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) * determines the type of the second operand, (See the Data Types
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) * section of the ACPI 3.0+ specification.) Both object types are
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) * guaranteed to be either Integer/String/Buffer by the operand
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) * resolution mechanism.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) switch (operand0->common.type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) case ACPI_TYPE_INTEGER:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) status = acpi_ex_convert_to_integer(operand1, &local_operand1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) ACPI_IMPLICIT_CONVERSION);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) case ACPI_TYPE_STRING:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) status =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) acpi_ex_convert_to_string(operand1, &local_operand1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) ACPI_IMPLICIT_CONVERT_HEX);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) case ACPI_TYPE_BUFFER:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) status = acpi_ex_convert_to_buffer(operand1, &local_operand1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) ACPI_ERROR((AE_INFO,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) "Invalid object type for logical operator: %X",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) operand0->common.type));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) status = AE_AML_INTERNAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) if (ACPI_FAILURE(status)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) goto cleanup;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) * Two cases: 1) Both Integers, 2) Both Strings or Buffers
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) if (operand0->common.type == ACPI_TYPE_INTEGER) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) * 1) Both operands are of type integer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) * Note: local_operand1 may have changed above
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) integer0 = operand0->integer.value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) integer1 = local_operand1->integer.value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) switch (opcode) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) case AML_LOGICAL_EQUAL_OP: /* LEqual (Operand0, Operand1) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) if (integer0 == integer1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) local_result = TRUE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) case AML_LOGICAL_GREATER_OP: /* LGreater (Operand0, Operand1) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) if (integer0 > integer1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) local_result = TRUE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) case AML_LOGICAL_LESS_OP: /* LLess (Operand0, Operand1) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) if (integer0 < integer1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) local_result = TRUE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) ACPI_ERROR((AE_INFO,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) "Invalid comparison opcode: %X", opcode));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) status = AE_AML_INTERNAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) * 2) Both operands are Strings or both are Buffers
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) * Note: Code below takes advantage of common Buffer/String
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) * object fields. local_operand1 may have changed above. Use
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) * memcmp to handle nulls in buffers.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) length0 = operand0->buffer.length;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) length1 = local_operand1->buffer.length;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) /* Lexicographic compare: compare the data bytes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) compare = memcmp(operand0->buffer.pointer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) local_operand1->buffer.pointer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) (length0 > length1) ? length1 : length0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) switch (opcode) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) case AML_LOGICAL_EQUAL_OP: /* LEqual (Operand0, Operand1) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) /* Length and all bytes must be equal */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) if ((length0 == length1) && (compare == 0)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) /* Length and all bytes match ==> TRUE */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) local_result = TRUE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) case AML_LOGICAL_GREATER_OP: /* LGreater (Operand0, Operand1) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) if (compare > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) local_result = TRUE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) goto cleanup; /* TRUE */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) if (compare < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) goto cleanup; /* FALSE */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) /* Bytes match (to shortest length), compare lengths */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) if (length0 > length1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) local_result = TRUE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) case AML_LOGICAL_LESS_OP: /* LLess (Operand0, Operand1) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) if (compare > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) goto cleanup; /* FALSE */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) if (compare < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) local_result = TRUE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) goto cleanup; /* TRUE */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) /* Bytes match (to shortest length), compare lengths */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) if (length0 < length1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) local_result = TRUE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) ACPI_ERROR((AE_INFO,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) "Invalid comparison opcode: %X", opcode));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) status = AE_AML_INTERNAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) cleanup:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) /* New object was created if implicit conversion performed - delete */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) if (local_operand1 != operand1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) acpi_ut_remove_reference(local_operand1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) /* Return the logical result and status */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) *logical_result = local_result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) return_ACPI_STATUS(status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) }