0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #include <acpi/acpi.h>
0011 #include "accommon.h"
0012 #include "acinterp.h"
0013 #include "acparser.h"
0014 #include "amlcode.h"
0015
0016 #define _COMPONENT ACPI_EXECUTER
0017 ACPI_MODULE_NAME("exoparg3")
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051 acpi_status acpi_ex_opcode_3A_0T_0R(struct acpi_walk_state *walk_state)
0052 {
0053 union acpi_operand_object **operand = &walk_state->operands[0];
0054 struct acpi_signal_fatal_info *fatal;
0055 acpi_status status = AE_OK;
0056
0057 ACPI_FUNCTION_TRACE_STR(ex_opcode_3A_0T_0R,
0058 acpi_ps_get_opcode_name(walk_state->opcode));
0059
0060 switch (walk_state->opcode) {
0061 case AML_FATAL_OP:
0062
0063 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
0064 "FatalOp: Type %X Code %X Arg %X "
0065 "<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n",
0066 (u32)operand[0]->integer.value,
0067 (u32)operand[1]->integer.value,
0068 (u32)operand[2]->integer.value));
0069
0070 fatal = ACPI_ALLOCATE(sizeof(struct acpi_signal_fatal_info));
0071 if (fatal) {
0072 fatal->type = (u32) operand[0]->integer.value;
0073 fatal->code = (u32) operand[1]->integer.value;
0074 fatal->argument = (u32) operand[2]->integer.value;
0075 }
0076
0077
0078
0079 status = acpi_os_signal(ACPI_SIGNAL_FATAL, fatal);
0080
0081
0082
0083 ACPI_FREE(fatal);
0084 goto cleanup;
0085
0086 case AML_EXTERNAL_OP:
0087
0088
0089
0090
0091
0092
0093
0094
0095 ACPI_ERROR((AE_INFO, "Executed External Op"));
0096 status = AE_OK;
0097 goto cleanup;
0098
0099 default:
0100
0101 ACPI_ERROR((AE_INFO, "Unknown AML opcode 0x%X",
0102 walk_state->opcode));
0103
0104 status = AE_AML_BAD_OPCODE;
0105 goto cleanup;
0106 }
0107
0108 cleanup:
0109
0110 return_ACPI_STATUS(status);
0111 }
0112
0113
0114
0115
0116
0117
0118
0119
0120
0121
0122
0123
0124
0125 acpi_status acpi_ex_opcode_3A_1T_1R(struct acpi_walk_state *walk_state)
0126 {
0127 union acpi_operand_object **operand = &walk_state->operands[0];
0128 union acpi_operand_object *return_desc = NULL;
0129 char *buffer = NULL;
0130 acpi_status status = AE_OK;
0131 u64 index;
0132 acpi_size length;
0133
0134 ACPI_FUNCTION_TRACE_STR(ex_opcode_3A_1T_1R,
0135 acpi_ps_get_opcode_name(walk_state->opcode));
0136
0137 switch (walk_state->opcode) {
0138 case AML_MID_OP:
0139
0140
0141
0142
0143 return_desc = acpi_ut_create_internal_object((operand[0])->
0144 common.type);
0145 if (!return_desc) {
0146 status = AE_NO_MEMORY;
0147 goto cleanup;
0148 }
0149
0150
0151
0152 index = operand[1]->integer.value;
0153 length = (acpi_size)operand[2]->integer.value;
0154
0155
0156
0157
0158
0159 if (index >= operand[0]->string.length) {
0160 length = 0;
0161 }
0162
0163
0164
0165 else if ((index + length) > operand[0]->string.length) {
0166 length =
0167 (acpi_size)operand[0]->string.length -
0168 (acpi_size)index;
0169 }
0170
0171
0172
0173 switch ((operand[0])->common.type) {
0174 case ACPI_TYPE_STRING:
0175
0176
0177
0178 buffer = ACPI_ALLOCATE_ZEROED((acpi_size)length + 1);
0179 if (!buffer) {
0180 status = AE_NO_MEMORY;
0181 goto cleanup;
0182 }
0183 break;
0184
0185 case ACPI_TYPE_BUFFER:
0186
0187
0188
0189 if (length > 0) {
0190
0191
0192
0193 buffer = ACPI_ALLOCATE_ZEROED(length);
0194 if (!buffer) {
0195 status = AE_NO_MEMORY;
0196 goto cleanup;
0197 }
0198 }
0199 break;
0200
0201 default:
0202
0203 status = AE_AML_OPERAND_TYPE;
0204 goto cleanup;
0205 }
0206
0207 if (buffer) {
0208
0209
0210
0211 memcpy(buffer,
0212 operand[0]->string.pointer + index, length);
0213 }
0214
0215
0216
0217 return_desc->string.pointer = buffer;
0218 return_desc->string.length = (u32) length;
0219
0220
0221
0222 return_desc->buffer.flags |= AOPOBJ_DATA_VALID;
0223 break;
0224
0225 default:
0226
0227 ACPI_ERROR((AE_INFO, "Unknown AML opcode 0x%X",
0228 walk_state->opcode));
0229
0230 status = AE_AML_BAD_OPCODE;
0231 goto cleanup;
0232 }
0233
0234
0235
0236 status = acpi_ex_store(return_desc, operand[3], walk_state);
0237
0238 cleanup:
0239
0240
0241
0242 if (ACPI_FAILURE(status) || walk_state->result_obj) {
0243 acpi_ut_remove_reference(return_desc);
0244 walk_state->result_obj = NULL;
0245 } else {
0246
0247
0248 walk_state->result_obj = return_desc;
0249 }
0250
0251 return_ACPI_STATUS(status);
0252 }