0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #include <acpi/acpi.h>
0011 #include "accommon.h"
0012 #include "acinterp.h"
0013 #include "amlcode.h"
0014
0015 #define _COMPONENT ACPI_EXECUTER
0016 ACPI_MODULE_NAME("exmisc")
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032 acpi_status
0033 acpi_ex_get_object_reference(union acpi_operand_object *obj_desc,
0034 union acpi_operand_object **return_desc,
0035 struct acpi_walk_state *walk_state)
0036 {
0037 union acpi_operand_object *reference_obj;
0038 union acpi_operand_object *referenced_obj;
0039
0040 ACPI_FUNCTION_TRACE_PTR(ex_get_object_reference, obj_desc);
0041
0042 *return_desc = NULL;
0043
0044 switch (ACPI_GET_DESCRIPTOR_TYPE(obj_desc)) {
0045 case ACPI_DESC_TYPE_OPERAND:
0046
0047 if (obj_desc->common.type != ACPI_TYPE_LOCAL_REFERENCE) {
0048 return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
0049 }
0050
0051
0052
0053
0054 switch (obj_desc->reference.class) {
0055 case ACPI_REFCLASS_LOCAL:
0056 case ACPI_REFCLASS_ARG:
0057 case ACPI_REFCLASS_DEBUG:
0058
0059
0060
0061 referenced_obj = obj_desc->reference.object;
0062 break;
0063
0064 default:
0065
0066 ACPI_ERROR((AE_INFO, "Invalid Reference Class 0x%2.2X",
0067 obj_desc->reference.class));
0068 return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
0069 }
0070 break;
0071
0072 case ACPI_DESC_TYPE_NAMED:
0073
0074
0075
0076 referenced_obj = obj_desc;
0077 break;
0078
0079 default:
0080
0081 ACPI_ERROR((AE_INFO, "Invalid descriptor type 0x%X",
0082 ACPI_GET_DESCRIPTOR_TYPE(obj_desc)));
0083 return_ACPI_STATUS(AE_TYPE);
0084 }
0085
0086
0087
0088 reference_obj =
0089 acpi_ut_create_internal_object(ACPI_TYPE_LOCAL_REFERENCE);
0090 if (!reference_obj) {
0091 return_ACPI_STATUS(AE_NO_MEMORY);
0092 }
0093
0094 reference_obj->reference.class = ACPI_REFCLASS_REFOF;
0095 reference_obj->reference.object = referenced_obj;
0096 *return_desc = reference_obj;
0097
0098 ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
0099 "Object %p Type [%s], returning Reference %p\n",
0100 obj_desc, acpi_ut_get_object_type_name(obj_desc),
0101 *return_desc));
0102
0103 return_ACPI_STATUS(AE_OK);
0104 }
0105
0106
0107
0108
0109
0110
0111
0112
0113
0114
0115
0116
0117
0118
0119
0120
0121
0122 u64 acpi_ex_do_math_op(u16 opcode, u64 integer0, u64 integer1)
0123 {
0124
0125 ACPI_FUNCTION_ENTRY();
0126
0127 switch (opcode) {
0128 case AML_ADD_OP:
0129
0130 return (integer0 + integer1);
0131
0132 case AML_BIT_AND_OP:
0133
0134 return (integer0 & integer1);
0135
0136 case AML_BIT_NAND_OP:
0137
0138 return (~(integer0 & integer1));
0139
0140 case AML_BIT_OR_OP:
0141
0142 return (integer0 | integer1);
0143
0144 case AML_BIT_NOR_OP:
0145
0146 return (~(integer0 | integer1));
0147
0148 case AML_BIT_XOR_OP:
0149
0150 return (integer0 ^ integer1);
0151
0152 case AML_MULTIPLY_OP:
0153
0154 return (integer0 * integer1);
0155
0156 case AML_SHIFT_LEFT_OP:
0157
0158
0159
0160
0161
0162 if (integer1 >= acpi_gbl_integer_bit_width) {
0163 return (0);
0164 }
0165 return (integer0 << integer1);
0166
0167 case AML_SHIFT_RIGHT_OP:
0168
0169
0170
0171
0172
0173 if (integer1 >= acpi_gbl_integer_bit_width) {
0174 return (0);
0175 }
0176 return (integer0 >> integer1);
0177
0178 case AML_SUBTRACT_OP:
0179
0180 return (integer0 - integer1);
0181
0182 default:
0183
0184 return (0);
0185 }
0186 }
0187
0188
0189
0190
0191
0192
0193
0194
0195
0196
0197
0198
0199
0200
0201
0202
0203
0204
0205
0206
0207
0208 acpi_status
0209 acpi_ex_do_logical_numeric_op(u16 opcode,
0210 u64 integer0, u64 integer1, u8 *logical_result)
0211 {
0212 acpi_status status = AE_OK;
0213 u8 local_result = FALSE;
0214
0215 ACPI_FUNCTION_TRACE(ex_do_logical_numeric_op);
0216
0217 switch (opcode) {
0218 case AML_LOGICAL_AND_OP:
0219
0220 if (integer0 && integer1) {
0221 local_result = TRUE;
0222 }
0223 break;
0224
0225 case AML_LOGICAL_OR_OP:
0226
0227 if (integer0 || integer1) {
0228 local_result = TRUE;
0229 }
0230 break;
0231
0232 default:
0233
0234 ACPI_ERROR((AE_INFO,
0235 "Invalid numeric logical opcode: %X", opcode));
0236 status = AE_AML_INTERNAL;
0237 break;
0238 }
0239
0240
0241
0242 *logical_result = local_result;
0243 return_ACPI_STATUS(status);
0244 }
0245
0246
0247
0248
0249
0250
0251
0252
0253
0254
0255
0256
0257
0258
0259
0260
0261
0262
0263
0264
0265
0266
0267
0268
0269
0270
0271
0272 acpi_status
0273 acpi_ex_do_logical_op(u16 opcode,
0274 union acpi_operand_object *operand0,
0275 union acpi_operand_object *operand1, u8 * logical_result)
0276 {
0277 union acpi_operand_object *local_operand1 = operand1;
0278 u64 integer0;
0279 u64 integer1;
0280 u32 length0;
0281 u32 length1;
0282 acpi_status status = AE_OK;
0283 u8 local_result = FALSE;
0284 int compare;
0285
0286 ACPI_FUNCTION_TRACE(ex_do_logical_op);
0287
0288
0289
0290
0291
0292
0293
0294
0295 switch (operand0->common.type) {
0296 case ACPI_TYPE_INTEGER:
0297
0298 status = acpi_ex_convert_to_integer(operand1, &local_operand1,
0299 ACPI_IMPLICIT_CONVERSION);
0300 break;
0301
0302 case ACPI_TYPE_STRING:
0303
0304 status =
0305 acpi_ex_convert_to_string(operand1, &local_operand1,
0306 ACPI_IMPLICIT_CONVERT_HEX);
0307 break;
0308
0309 case ACPI_TYPE_BUFFER:
0310
0311 status = acpi_ex_convert_to_buffer(operand1, &local_operand1);
0312 break;
0313
0314 default:
0315
0316 ACPI_ERROR((AE_INFO,
0317 "Invalid object type for logical operator: %X",
0318 operand0->common.type));
0319 status = AE_AML_INTERNAL;
0320 break;
0321 }
0322
0323 if (ACPI_FAILURE(status)) {
0324 goto cleanup;
0325 }
0326
0327
0328
0329
0330 if (operand0->common.type == ACPI_TYPE_INTEGER) {
0331
0332
0333
0334
0335 integer0 = operand0->integer.value;
0336 integer1 = local_operand1->integer.value;
0337
0338 switch (opcode) {
0339 case AML_LOGICAL_EQUAL_OP:
0340
0341 if (integer0 == integer1) {
0342 local_result = TRUE;
0343 }
0344 break;
0345
0346 case AML_LOGICAL_GREATER_OP:
0347
0348 if (integer0 > integer1) {
0349 local_result = TRUE;
0350 }
0351 break;
0352
0353 case AML_LOGICAL_LESS_OP:
0354
0355 if (integer0 < integer1) {
0356 local_result = TRUE;
0357 }
0358 break;
0359
0360 default:
0361
0362 ACPI_ERROR((AE_INFO,
0363 "Invalid comparison opcode: %X", opcode));
0364 status = AE_AML_INTERNAL;
0365 break;
0366 }
0367 } else {
0368
0369
0370
0371
0372
0373
0374 length0 = operand0->buffer.length;
0375 length1 = local_operand1->buffer.length;
0376
0377
0378
0379 compare = memcmp(operand0->buffer.pointer,
0380 local_operand1->buffer.pointer,
0381 (length0 > length1) ? length1 : length0);
0382
0383 switch (opcode) {
0384 case AML_LOGICAL_EQUAL_OP:
0385
0386
0387
0388 if ((length0 == length1) && (compare == 0)) {
0389
0390
0391
0392 local_result = TRUE;
0393 }
0394 break;
0395
0396 case AML_LOGICAL_GREATER_OP:
0397
0398 if (compare > 0) {
0399 local_result = TRUE;
0400 goto cleanup;
0401 }
0402 if (compare < 0) {
0403 goto cleanup;
0404 }
0405
0406
0407
0408 if (length0 > length1) {
0409 local_result = TRUE;
0410 }
0411 break;
0412
0413 case AML_LOGICAL_LESS_OP:
0414
0415 if (compare > 0) {
0416 goto cleanup;
0417 }
0418 if (compare < 0) {
0419 local_result = TRUE;
0420 goto cleanup;
0421 }
0422
0423
0424
0425 if (length0 < length1) {
0426 local_result = TRUE;
0427 }
0428 break;
0429
0430 default:
0431
0432 ACPI_ERROR((AE_INFO,
0433 "Invalid comparison opcode: %X", opcode));
0434 status = AE_AML_INTERNAL;
0435 break;
0436 }
0437 }
0438
0439 cleanup:
0440
0441
0442
0443 if (local_operand1 != operand1) {
0444 acpi_ut_remove_reference(local_operand1);
0445 }
0446
0447
0448
0449 *logical_result = local_result;
0450 return_ACPI_STATUS(status);
0451 }