0001
0002
0003
0004
0005
0006
0007
0008 #include <acpi/acpi.h>
0009 #include "accommon.h"
0010 #include "acdispat.h"
0011 #include "acnamesp.h"
0012 #include "acinterp.h"
0013
0014 #define _COMPONENT ACPI_DISPATCHER
0015 ACPI_MODULE_NAME("dsmthdat")
0016
0017
0018 static void
0019 acpi_ds_method_data_delete_value(u8 type,
0020 u32 index, struct acpi_walk_state *walk_state);
0021
0022 static acpi_status
0023 acpi_ds_method_data_set_value(u8 type,
0024 u32 index,
0025 union acpi_operand_object *object,
0026 struct acpi_walk_state *walk_state);
0027
0028 #ifdef ACPI_OBSOLETE_FUNCTIONS
0029 acpi_object_type
0030 acpi_ds_method_data_get_type(u16 opcode,
0031 u32 index, struct acpi_walk_state *walk_state);
0032 #endif
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055 void acpi_ds_method_data_init(struct acpi_walk_state *walk_state)
0056 {
0057 u32 i;
0058
0059 ACPI_FUNCTION_TRACE(ds_method_data_init);
0060
0061
0062
0063 for (i = 0; i < ACPI_METHOD_NUM_ARGS; i++) {
0064 ACPI_MOVE_32_TO_32(&walk_state->arguments[i].name,
0065 NAMEOF_ARG_NTE);
0066
0067 walk_state->arguments[i].name.integer |= (i << 24);
0068 walk_state->arguments[i].descriptor_type = ACPI_DESC_TYPE_NAMED;
0069 walk_state->arguments[i].type = ACPI_TYPE_ANY;
0070 walk_state->arguments[i].flags = ANOBJ_METHOD_ARG;
0071 }
0072
0073
0074
0075 for (i = 0; i < ACPI_METHOD_NUM_LOCALS; i++) {
0076 ACPI_MOVE_32_TO_32(&walk_state->local_variables[i].name,
0077 NAMEOF_LOCAL_NTE);
0078
0079 walk_state->local_variables[i].name.integer |= (i << 24);
0080 walk_state->local_variables[i].descriptor_type =
0081 ACPI_DESC_TYPE_NAMED;
0082 walk_state->local_variables[i].type = ACPI_TYPE_ANY;
0083 walk_state->local_variables[i].flags = ANOBJ_METHOD_LOCAL;
0084 }
0085
0086 return_VOID;
0087 }
0088
0089
0090
0091
0092
0093
0094
0095
0096
0097
0098
0099
0100
0101
0102 void acpi_ds_method_data_delete_all(struct acpi_walk_state *walk_state)
0103 {
0104 u32 index;
0105
0106 ACPI_FUNCTION_TRACE(ds_method_data_delete_all);
0107
0108
0109
0110 for (index = 0; index < ACPI_METHOD_NUM_LOCALS; index++) {
0111 if (walk_state->local_variables[index].object) {
0112 ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Deleting Local%u=%p\n",
0113 index,
0114 walk_state->local_variables[index].
0115 object));
0116
0117
0118
0119 acpi_ns_detach_object(&walk_state->
0120 local_variables[index]);
0121 }
0122 }
0123
0124
0125
0126 for (index = 0; index < ACPI_METHOD_NUM_ARGS; index++) {
0127 if (walk_state->arguments[index].object) {
0128 ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Deleting Arg%u=%p\n",
0129 index,
0130 walk_state->arguments[index].object));
0131
0132
0133
0134 acpi_ns_detach_object(&walk_state->arguments[index]);
0135 }
0136 }
0137
0138 return_VOID;
0139 }
0140
0141
0142
0143
0144
0145
0146
0147
0148
0149
0150
0151
0152
0153
0154
0155
0156
0157 acpi_status
0158 acpi_ds_method_data_init_args(union acpi_operand_object **params,
0159 u32 max_param_count,
0160 struct acpi_walk_state *walk_state)
0161 {
0162 acpi_status status;
0163 u32 index = 0;
0164
0165 ACPI_FUNCTION_TRACE_PTR(ds_method_data_init_args, params);
0166
0167 if (!params) {
0168 ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
0169 "No parameter list passed to method\n"));
0170 return_ACPI_STATUS(AE_OK);
0171 }
0172
0173
0174
0175 while ((index < ACPI_METHOD_NUM_ARGS) &&
0176 (index < max_param_count) && params[index]) {
0177
0178
0179
0180
0181
0182 status =
0183 acpi_ds_method_data_set_value(ACPI_REFCLASS_ARG, index,
0184 params[index], walk_state);
0185 if (ACPI_FAILURE(status)) {
0186 return_ACPI_STATUS(status);
0187 }
0188
0189 index++;
0190 }
0191
0192 ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "%u args passed to method\n", index));
0193 return_ACPI_STATUS(AE_OK);
0194 }
0195
0196
0197
0198
0199
0200
0201
0202
0203
0204
0205
0206
0207
0208
0209
0210
0211
0212 acpi_status
0213 acpi_ds_method_data_get_node(u8 type,
0214 u32 index,
0215 struct acpi_walk_state *walk_state,
0216 struct acpi_namespace_node **node)
0217 {
0218 ACPI_FUNCTION_TRACE(ds_method_data_get_node);
0219
0220
0221
0222
0223 switch (type) {
0224 case ACPI_REFCLASS_LOCAL:
0225
0226 if (index > ACPI_METHOD_MAX_LOCAL) {
0227 ACPI_ERROR((AE_INFO,
0228 "Local index %u is invalid (max %u)",
0229 index, ACPI_METHOD_MAX_LOCAL));
0230 return_ACPI_STATUS(AE_AML_INVALID_INDEX);
0231 }
0232
0233
0234
0235 *node = &walk_state->local_variables[index];
0236 break;
0237
0238 case ACPI_REFCLASS_ARG:
0239
0240 if (index > ACPI_METHOD_MAX_ARG) {
0241 ACPI_ERROR((AE_INFO,
0242 "Arg index %u is invalid (max %u)",
0243 index, ACPI_METHOD_MAX_ARG));
0244 return_ACPI_STATUS(AE_AML_INVALID_INDEX);
0245 }
0246
0247
0248
0249 *node = &walk_state->arguments[index];
0250 break;
0251
0252 default:
0253
0254 ACPI_ERROR((AE_INFO, "Type %u is invalid", type));
0255 return_ACPI_STATUS(AE_TYPE);
0256 }
0257
0258 return_ACPI_STATUS(AE_OK);
0259 }
0260
0261
0262
0263
0264
0265
0266
0267
0268
0269
0270
0271
0272
0273
0274
0275
0276
0277
0278 static acpi_status
0279 acpi_ds_method_data_set_value(u8 type,
0280 u32 index,
0281 union acpi_operand_object *object,
0282 struct acpi_walk_state *walk_state)
0283 {
0284 acpi_status status;
0285 struct acpi_namespace_node *node;
0286
0287 ACPI_FUNCTION_TRACE(ds_method_data_set_value);
0288
0289 ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
0290 "NewObj %p Type %2.2X, Refs=%u [%s]\n", object,
0291 type, object->common.reference_count,
0292 acpi_ut_get_type_name(object->common.type)));
0293
0294
0295
0296 status = acpi_ds_method_data_get_node(type, index, walk_state, &node);
0297 if (ACPI_FAILURE(status)) {
0298 return_ACPI_STATUS(status);
0299 }
0300
0301
0302
0303
0304
0305
0306
0307 acpi_ut_add_reference(object);
0308
0309
0310
0311 node->object = object;
0312 return_ACPI_STATUS(status);
0313 }
0314
0315
0316
0317
0318
0319
0320
0321
0322
0323
0324
0325
0326
0327
0328
0329
0330
0331
0332 acpi_status
0333 acpi_ds_method_data_get_value(u8 type,
0334 u32 index,
0335 struct acpi_walk_state *walk_state,
0336 union acpi_operand_object **dest_desc)
0337 {
0338 acpi_status status;
0339 struct acpi_namespace_node *node;
0340 union acpi_operand_object *object;
0341
0342 ACPI_FUNCTION_TRACE(ds_method_data_get_value);
0343
0344
0345
0346 if (!dest_desc) {
0347 ACPI_ERROR((AE_INFO, "Null object descriptor pointer"));
0348 return_ACPI_STATUS(AE_BAD_PARAMETER);
0349 }
0350
0351
0352
0353 status = acpi_ds_method_data_get_node(type, index, walk_state, &node);
0354 if (ACPI_FAILURE(status)) {
0355 return_ACPI_STATUS(status);
0356 }
0357
0358
0359
0360 object = node->object;
0361
0362
0363
0364 if (!object) {
0365
0366
0367
0368
0369
0370
0371
0372
0373
0374
0375 if (acpi_gbl_enable_interpreter_slack) {
0376 object = acpi_ut_create_integer_object((u64) 0);
0377 if (!object) {
0378 return_ACPI_STATUS(AE_NO_MEMORY);
0379 }
0380
0381 node->object = object;
0382 }
0383
0384
0385
0386 else
0387 switch (type) {
0388 case ACPI_REFCLASS_ARG:
0389
0390 ACPI_ERROR((AE_INFO,
0391 "Uninitialized Arg[%u] at node %p",
0392 index, node));
0393
0394 return_ACPI_STATUS(AE_AML_UNINITIALIZED_ARG);
0395
0396 case ACPI_REFCLASS_LOCAL:
0397
0398
0399
0400
0401 return_ACPI_STATUS(AE_AML_UNINITIALIZED_LOCAL);
0402
0403 default:
0404
0405 ACPI_ERROR((AE_INFO,
0406 "Not a Arg/Local opcode: 0x%X",
0407 type));
0408 return_ACPI_STATUS(AE_AML_INTERNAL);
0409 }
0410 }
0411
0412
0413
0414
0415
0416 *dest_desc = object;
0417 acpi_ut_add_reference(object);
0418
0419 return_ACPI_STATUS(AE_OK);
0420 }
0421
0422
0423
0424
0425
0426
0427
0428
0429
0430
0431
0432
0433
0434
0435
0436
0437
0438 static void
0439 acpi_ds_method_data_delete_value(u8 type,
0440 u32 index, struct acpi_walk_state *walk_state)
0441 {
0442 acpi_status status;
0443 struct acpi_namespace_node *node;
0444 union acpi_operand_object *object;
0445
0446 ACPI_FUNCTION_TRACE(ds_method_data_delete_value);
0447
0448
0449
0450 status = acpi_ds_method_data_get_node(type, index, walk_state, &node);
0451 if (ACPI_FAILURE(status)) {
0452 return_VOID;
0453 }
0454
0455
0456
0457 object = acpi_ns_get_attached_object(node);
0458
0459
0460
0461
0462
0463
0464 node->object = NULL;
0465
0466 if ((object) &&
0467 (ACPI_GET_DESCRIPTOR_TYPE(object) == ACPI_DESC_TYPE_OPERAND)) {
0468
0469
0470
0471
0472
0473 acpi_ut_remove_reference(object);
0474 }
0475
0476 return_VOID;
0477 }
0478
0479
0480
0481
0482
0483
0484
0485
0486
0487
0488
0489
0490
0491
0492
0493
0494
0495
0496
0497 acpi_status
0498 acpi_ds_store_object_to_local(u8 type,
0499 u32 index,
0500 union acpi_operand_object *obj_desc,
0501 struct acpi_walk_state *walk_state)
0502 {
0503 acpi_status status;
0504 struct acpi_namespace_node *node;
0505 union acpi_operand_object *current_obj_desc;
0506 union acpi_operand_object *new_obj_desc;
0507
0508 ACPI_FUNCTION_TRACE(ds_store_object_to_local);
0509 ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Type=%2.2X Index=%u Obj=%p\n",
0510 type, index, obj_desc));
0511
0512
0513
0514 if (!obj_desc) {
0515 return_ACPI_STATUS(AE_BAD_PARAMETER);
0516 }
0517
0518
0519
0520 status = acpi_ds_method_data_get_node(type, index, walk_state, &node);
0521 if (ACPI_FAILURE(status)) {
0522 return_ACPI_STATUS(status);
0523 }
0524
0525 current_obj_desc = acpi_ns_get_attached_object(node);
0526 if (current_obj_desc == obj_desc) {
0527 ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Obj=%p already installed!\n",
0528 obj_desc));
0529 return_ACPI_STATUS(status);
0530 }
0531
0532
0533
0534
0535
0536
0537
0538
0539 new_obj_desc = obj_desc;
0540 if (obj_desc->common.reference_count > 1) {
0541 status =
0542 acpi_ut_copy_iobject_to_iobject(obj_desc, &new_obj_desc,
0543 walk_state);
0544 if (ACPI_FAILURE(status)) {
0545 return_ACPI_STATUS(status);
0546 }
0547 }
0548
0549
0550
0551
0552
0553
0554
0555 if (current_obj_desc) {
0556
0557
0558
0559
0560
0561
0562
0563
0564
0565
0566
0567
0568
0569
0570
0571
0572 if (type == ACPI_REFCLASS_ARG) {
0573
0574
0575
0576
0577 if ((ACPI_GET_DESCRIPTOR_TYPE(current_obj_desc) ==
0578 ACPI_DESC_TYPE_OPERAND) &&
0579 (current_obj_desc->common.type ==
0580 ACPI_TYPE_LOCAL_REFERENCE) &&
0581 (current_obj_desc->reference.class ==
0582 ACPI_REFCLASS_REFOF)) {
0583 ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
0584 "Arg (%p) is an ObjRef(Node), storing in node %p\n",
0585 new_obj_desc,
0586 current_obj_desc));
0587
0588
0589
0590
0591
0592
0593 status =
0594 acpi_ex_store_object_to_node(new_obj_desc,
0595 current_obj_desc->
0596 reference.
0597 object,
0598 walk_state,
0599 ACPI_NO_IMPLICIT_CONVERSION);
0600
0601
0602
0603 if (new_obj_desc != obj_desc) {
0604 acpi_ut_remove_reference(new_obj_desc);
0605 }
0606
0607 return_ACPI_STATUS(status);
0608 }
0609 }
0610
0611
0612
0613 acpi_ds_method_data_delete_value(type, index, walk_state);
0614 }
0615
0616
0617
0618
0619
0620
0621 status =
0622 acpi_ds_method_data_set_value(type, index, new_obj_desc,
0623 walk_state);
0624
0625
0626
0627 if (new_obj_desc != obj_desc) {
0628 acpi_ut_remove_reference(new_obj_desc);
0629 }
0630
0631 return_ACPI_STATUS(status);
0632 }
0633
0634 #ifdef ACPI_OBSOLETE_FUNCTIONS
0635
0636
0637
0638
0639
0640
0641
0642
0643
0644
0645
0646
0647
0648
0649
0650 acpi_object_type
0651 acpi_ds_method_data_get_type(u16 opcode,
0652 u32 index, struct acpi_walk_state *walk_state)
0653 {
0654 acpi_status status;
0655 struct acpi_namespace_node *node;
0656 union acpi_operand_object *object;
0657
0658 ACPI_FUNCTION_TRACE(ds_method_data_get_type);
0659
0660
0661
0662 status = acpi_ds_method_data_get_node(opcode, index, walk_state, &node);
0663 if (ACPI_FAILURE(status)) {
0664 return_VALUE((ACPI_TYPE_NOT_FOUND));
0665 }
0666
0667
0668
0669 object = acpi_ns_get_attached_object(node);
0670 if (!object) {
0671
0672
0673
0674 return_VALUE(ACPI_TYPE_ANY);
0675 }
0676
0677
0678
0679 return_VALUE(object->type);
0680 }
0681 #endif