0001
0002
0003
0004
0005
0006
0007
0008
0009 #define EXPORT_ACPI_INTERFACES
0010
0011 #include <acpi/acpi.h>
0012 #include "accommon.h"
0013 #include "acnamesp.h"
0014 #include "acinterp.h"
0015
0016 #define _COMPONENT ACPI_NAMESPACE
0017 ACPI_MODULE_NAME("nsxfeval")
0018
0019
0020 static void acpi_ns_resolve_references(struct acpi_evaluate_info *info);
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043 acpi_status
0044 acpi_evaluate_object_typed(acpi_handle handle,
0045 acpi_string pathname,
0046 struct acpi_object_list *external_params,
0047 struct acpi_buffer *return_buffer,
0048 acpi_object_type return_type)
0049 {
0050 acpi_status status;
0051 u8 free_buffer_on_error = FALSE;
0052 acpi_handle target_handle;
0053 char *full_pathname;
0054
0055 ACPI_FUNCTION_TRACE(acpi_evaluate_object_typed);
0056
0057
0058
0059 if (!return_buffer) {
0060 return_ACPI_STATUS(AE_BAD_PARAMETER);
0061 }
0062
0063 if (return_buffer->length == ACPI_ALLOCATE_BUFFER) {
0064 free_buffer_on_error = TRUE;
0065 }
0066
0067
0068
0069 target_handle = handle;
0070 if (pathname) {
0071 status = acpi_get_handle(handle, pathname, &target_handle);
0072 if (ACPI_FAILURE(status)) {
0073 return_ACPI_STATUS(status);
0074 }
0075 }
0076
0077 full_pathname = acpi_ns_get_external_pathname(target_handle);
0078 if (!full_pathname) {
0079 return_ACPI_STATUS(AE_NO_MEMORY);
0080 }
0081
0082
0083
0084 status = acpi_evaluate_object(target_handle, NULL, external_params,
0085 return_buffer);
0086 if (ACPI_FAILURE(status)) {
0087 goto exit;
0088 }
0089
0090
0091
0092 if (return_type == ACPI_TYPE_ANY) {
0093 goto exit;
0094 }
0095
0096 if (return_buffer->length == 0) {
0097
0098
0099
0100 ACPI_ERROR((AE_INFO, "%s did not return any object",
0101 full_pathname));
0102 status = AE_NULL_OBJECT;
0103 goto exit;
0104 }
0105
0106
0107
0108 if (((union acpi_object *)return_buffer->pointer)->type == return_type) {
0109 goto exit;
0110 }
0111
0112
0113
0114 ACPI_ERROR((AE_INFO,
0115 "Incorrect return type from %s - received [%s], requested [%s]",
0116 full_pathname,
0117 acpi_ut_get_type_name(((union acpi_object *)return_buffer->
0118 pointer)->type),
0119 acpi_ut_get_type_name(return_type)));
0120
0121 if (free_buffer_on_error) {
0122
0123
0124
0125
0126
0127
0128
0129 acpi_os_free(return_buffer->pointer);
0130 return_buffer->pointer = NULL;
0131 }
0132
0133 return_buffer->length = 0;
0134 status = AE_TYPE;
0135
0136 exit:
0137 ACPI_FREE(full_pathname);
0138 return_ACPI_STATUS(status);
0139 }
0140
0141 ACPI_EXPORT_SYMBOL(acpi_evaluate_object_typed)
0142
0143
0144
0145
0146
0147
0148
0149
0150
0151
0152
0153
0154
0155
0156
0157
0158
0159
0160
0161
0162 acpi_status
0163 acpi_evaluate_object(acpi_handle handle,
0164 acpi_string pathname,
0165 struct acpi_object_list *external_params,
0166 struct acpi_buffer *return_buffer)
0167 {
0168 acpi_status status;
0169 struct acpi_evaluate_info *info;
0170 acpi_size buffer_space_needed;
0171 u32 i;
0172
0173 ACPI_FUNCTION_TRACE(acpi_evaluate_object);
0174
0175
0176
0177 info = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_evaluate_info));
0178 if (!info) {
0179 return_ACPI_STATUS(AE_NO_MEMORY);
0180 }
0181
0182
0183
0184 info->prefix_node = acpi_ns_validate_handle(handle);
0185 if (!info->prefix_node) {
0186 status = AE_BAD_PARAMETER;
0187 goto cleanup;
0188 }
0189
0190
0191
0192
0193
0194
0195
0196
0197
0198 if ((pathname) && (ACPI_IS_ROOT_PREFIX(pathname[0]))) {
0199
0200
0201
0202 info->prefix_node = NULL;
0203 } else if (!handle) {
0204
0205
0206
0207
0208
0209 if (!pathname) {
0210 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
0211 "Both Handle and Pathname are NULL"));
0212 } else {
0213 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
0214 "Null Handle with relative pathname [%s]",
0215 pathname));
0216 }
0217
0218 status = AE_BAD_PARAMETER;
0219 goto cleanup;
0220 }
0221
0222 info->relative_pathname = pathname;
0223
0224
0225
0226
0227
0228 if (external_params && external_params->count) {
0229 info->param_count = (u16)external_params->count;
0230
0231
0232
0233 if (info->param_count > ACPI_METHOD_NUM_ARGS) {
0234 ACPI_WARN_PREDEFINED((AE_INFO, pathname,
0235 ACPI_WARN_ALWAYS,
0236 "Excess arguments (%u) - using only %u",
0237 info->param_count,
0238 ACPI_METHOD_NUM_ARGS));
0239
0240 info->param_count = ACPI_METHOD_NUM_ARGS;
0241 }
0242
0243
0244
0245
0246
0247 info->parameters = ACPI_ALLOCATE_ZEROED(((acpi_size)info->
0248 param_count +
0249 1) * sizeof(void *));
0250 if (!info->parameters) {
0251 status = AE_NO_MEMORY;
0252 goto cleanup;
0253 }
0254
0255
0256
0257 for (i = 0; i < info->param_count; i++) {
0258 status =
0259 acpi_ut_copy_eobject_to_iobject(&external_params->
0260 pointer[i],
0261 &info->
0262 parameters[i]);
0263 if (ACPI_FAILURE(status)) {
0264 goto cleanup;
0265 }
0266 }
0267
0268 info->parameters[info->param_count] = NULL;
0269 }
0270
0271 #ifdef _FUTURE_FEATURE
0272
0273
0274
0275
0276
0277 switch (acpi_ns_get_type(info->node)) {
0278 case ACPI_TYPE_METHOD:
0279
0280
0281
0282 if (info->obj_desc->method.param_count > info->param_count) {
0283 ACPI_ERROR((AE_INFO,
0284 "Insufficient arguments (%u) - %u are required",
0285 info->param_count,
0286 info->obj_desc->method.param_count));
0287
0288 status = AE_MISSING_ARGUMENTS;
0289 goto cleanup;
0290 }
0291
0292 else if (info->obj_desc->method.param_count < info->param_count) {
0293 ACPI_WARNING((AE_INFO,
0294 "Excess arguments (%u) - only %u are required",
0295 info->param_count,
0296 info->obj_desc->method.param_count));
0297
0298
0299
0300 info->param_count = info->obj_desc->method.param_count;
0301 }
0302
0303
0304
0305
0306
0307 if (info->param_count) {
0308
0309
0310
0311
0312 info->parameters = ACPI_ALLOCATE_ZEROED(((acpi_size)
0313 info->
0314 param_count +
0315 1) *
0316 sizeof(void *));
0317 if (!info->parameters) {
0318 status = AE_NO_MEMORY;
0319 goto cleanup;
0320 }
0321
0322
0323
0324 for (i = 0; i < info->param_count; i++) {
0325 status =
0326 acpi_ut_copy_eobject_to_iobject
0327 (&external_params->pointer[i],
0328 &info->parameters[i]);
0329 if (ACPI_FAILURE(status)) {
0330 goto cleanup;
0331 }
0332 }
0333
0334 info->parameters[info->param_count] = NULL;
0335 }
0336 break;
0337
0338 default:
0339
0340
0341
0342 if (info->param_count) {
0343 ACPI_WARNING((AE_INFO,
0344 "%u arguments were passed to a non-method ACPI object",
0345 info->param_count));
0346 }
0347 break;
0348 }
0349
0350 #endif
0351
0352
0353
0354 status = acpi_ns_evaluate(info);
0355
0356
0357
0358
0359
0360 if (!return_buffer) {
0361 goto cleanup_return_object;
0362 }
0363
0364 if (!info->return_object) {
0365 return_buffer->length = 0;
0366 goto cleanup;
0367 }
0368
0369 if (ACPI_GET_DESCRIPTOR_TYPE(info->return_object) ==
0370 ACPI_DESC_TYPE_NAMED) {
0371
0372
0373
0374
0375
0376
0377
0378
0379 status = AE_TYPE;
0380 info->return_object = NULL;
0381 return_buffer->length = 0;
0382 }
0383
0384 if (ACPI_FAILURE(status)) {
0385 goto cleanup_return_object;
0386 }
0387
0388
0389
0390 acpi_ns_resolve_references(info);
0391
0392
0393
0394 status = acpi_ut_get_object_size(info->return_object,
0395 &buffer_space_needed);
0396 if (ACPI_SUCCESS(status)) {
0397
0398
0399
0400 status = acpi_ut_initialize_buffer(return_buffer,
0401 buffer_space_needed);
0402 if (ACPI_FAILURE(status)) {
0403
0404
0405
0406
0407 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
0408 "Needed buffer size %X, %s\n",
0409 (u32)buffer_space_needed,
0410 acpi_format_exception(status)));
0411 } else {
0412
0413
0414 status =
0415 acpi_ut_copy_iobject_to_eobject(info->return_object,
0416 return_buffer);
0417 }
0418 }
0419
0420 cleanup_return_object:
0421
0422 if (info->return_object) {
0423
0424
0425
0426
0427 acpi_ex_enter_interpreter();
0428
0429
0430
0431 acpi_ut_remove_reference(info->return_object);
0432 acpi_ex_exit_interpreter();
0433 }
0434
0435 cleanup:
0436
0437
0438
0439 if (info->parameters) {
0440
0441
0442
0443 acpi_ut_delete_internal_object_list(info->parameters);
0444 }
0445
0446 ACPI_FREE(info);
0447 return_ACPI_STATUS(status);
0448 }
0449
0450 ACPI_EXPORT_SYMBOL(acpi_evaluate_object)
0451
0452
0453
0454
0455
0456
0457
0458
0459
0460
0461
0462
0463
0464
0465
0466
0467
0468
0469
0470
0471
0472 static void acpi_ns_resolve_references(struct acpi_evaluate_info *info)
0473 {
0474 union acpi_operand_object *obj_desc = NULL;
0475 struct acpi_namespace_node *node;
0476
0477
0478
0479 if ((info->return_object)->common.type != ACPI_TYPE_LOCAL_REFERENCE) {
0480 return;
0481 }
0482
0483
0484
0485
0486
0487
0488
0489
0490 switch (info->return_object->reference.class) {
0491 case ACPI_REFCLASS_INDEX:
0492
0493 obj_desc = *(info->return_object->reference.where);
0494 break;
0495
0496 case ACPI_REFCLASS_REFOF:
0497
0498 node = info->return_object->reference.object;
0499 if (node) {
0500 obj_desc = node->object;
0501 }
0502 break;
0503
0504 default:
0505
0506 return;
0507 }
0508
0509
0510
0511 if (obj_desc) {
0512 acpi_ut_add_reference(obj_desc);
0513 acpi_ut_remove_reference(info->return_object);
0514 info->return_object = obj_desc;
0515 }
0516
0517 return;
0518 }
0519
0520
0521
0522
0523
0524
0525
0526
0527
0528
0529
0530
0531
0532
0533
0534
0535
0536
0537
0538
0539
0540
0541
0542
0543
0544
0545
0546
0547
0548
0549
0550
0551
0552
0553 acpi_status
0554 acpi_walk_namespace(acpi_object_type type,
0555 acpi_handle start_object,
0556 u32 max_depth,
0557 acpi_walk_callback descending_callback,
0558 acpi_walk_callback ascending_callback,
0559 void *context, void **return_value)
0560 {
0561 acpi_status status;
0562
0563 ACPI_FUNCTION_TRACE(acpi_walk_namespace);
0564
0565
0566
0567 if ((type > ACPI_TYPE_LOCAL_MAX) ||
0568 (!max_depth) || (!descending_callback && !ascending_callback)) {
0569 return_ACPI_STATUS(AE_BAD_PARAMETER);
0570 }
0571
0572
0573
0574
0575
0576
0577
0578
0579
0580
0581
0582
0583 status = acpi_ut_acquire_read_lock(&acpi_gbl_namespace_rw_lock);
0584 if (ACPI_FAILURE(status)) {
0585 return_ACPI_STATUS(status);
0586 }
0587
0588
0589
0590
0591
0592
0593
0594 status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
0595 if (ACPI_FAILURE(status)) {
0596 goto unlock_and_exit;
0597 }
0598
0599
0600
0601 if (!acpi_ns_validate_handle(start_object)) {
0602 status = AE_BAD_PARAMETER;
0603 goto unlock_and_exit2;
0604 }
0605
0606 status = acpi_ns_walk_namespace(type, start_object, max_depth,
0607 ACPI_NS_WALK_UNLOCK,
0608 descending_callback, ascending_callback,
0609 context, return_value);
0610
0611 unlock_and_exit2:
0612 (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
0613
0614 unlock_and_exit:
0615 (void)acpi_ut_release_read_lock(&acpi_gbl_namespace_rw_lock);
0616 return_ACPI_STATUS(status);
0617 }
0618
0619 ACPI_EXPORT_SYMBOL(acpi_walk_namespace)
0620
0621
0622
0623
0624
0625
0626
0627
0628
0629
0630
0631
0632
0633
0634 static acpi_status
0635 acpi_ns_get_device_callback(acpi_handle obj_handle,
0636 u32 nesting_level,
0637 void *context, void **return_value)
0638 {
0639 struct acpi_get_devices_info *info = context;
0640 acpi_status status;
0641 struct acpi_namespace_node *node;
0642 u32 flags;
0643 struct acpi_pnp_device_id *hid;
0644 struct acpi_pnp_device_id_list *cid;
0645 u32 i;
0646 u8 found;
0647 int no_match;
0648
0649 status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
0650 if (ACPI_FAILURE(status)) {
0651 return (status);
0652 }
0653
0654 node = acpi_ns_validate_handle(obj_handle);
0655 status = acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
0656 if (ACPI_FAILURE(status)) {
0657 return (status);
0658 }
0659
0660 if (!node) {
0661 return (AE_BAD_PARAMETER);
0662 }
0663
0664
0665
0666
0667
0668
0669
0670
0671
0672
0673
0674
0675
0676
0677
0678 if (info->hid != NULL) {
0679 status = acpi_ut_execute_HID(node, &hid);
0680 if (status == AE_NOT_FOUND) {
0681 return (AE_OK);
0682 } else if (ACPI_FAILURE(status)) {
0683 return (AE_CTRL_DEPTH);
0684 }
0685
0686 no_match = strcmp(hid->string, info->hid);
0687 ACPI_FREE(hid);
0688
0689 if (no_match) {
0690
0691
0692
0693
0694 status = acpi_ut_execute_CID(node, &cid);
0695 if (status == AE_NOT_FOUND) {
0696 return (AE_OK);
0697 } else if (ACPI_FAILURE(status)) {
0698 return (AE_CTRL_DEPTH);
0699 }
0700
0701
0702
0703 found = FALSE;
0704 for (i = 0; i < cid->count; i++) {
0705 if (strcmp(cid->ids[i].string, info->hid) == 0) {
0706
0707
0708
0709 found = TRUE;
0710 break;
0711 }
0712 }
0713
0714 ACPI_FREE(cid);
0715 if (!found) {
0716 return (AE_OK);
0717 }
0718 }
0719 }
0720
0721
0722
0723 status = acpi_ut_execute_STA(node, &flags);
0724 if (ACPI_FAILURE(status)) {
0725 return (AE_CTRL_DEPTH);
0726 }
0727
0728 if (!(flags & ACPI_STA_DEVICE_PRESENT) &&
0729 !(flags & ACPI_STA_DEVICE_FUNCTIONING)) {
0730
0731
0732
0733
0734
0735 return (AE_CTRL_DEPTH);
0736 }
0737
0738
0739
0740 status = info->user_function(obj_handle, nesting_level,
0741 info->context, return_value);
0742 return (status);
0743 }
0744
0745
0746
0747
0748
0749
0750
0751
0752
0753
0754
0755
0756
0757
0758
0759
0760
0761
0762
0763
0764
0765
0766
0767
0768
0769
0770 acpi_status
0771 acpi_get_devices(const char *HID,
0772 acpi_walk_callback user_function,
0773 void *context, void **return_value)
0774 {
0775 acpi_status status;
0776 struct acpi_get_devices_info info;
0777
0778 ACPI_FUNCTION_TRACE(acpi_get_devices);
0779
0780
0781
0782 if (!user_function) {
0783 return_ACPI_STATUS(AE_BAD_PARAMETER);
0784 }
0785
0786
0787
0788
0789
0790 info.hid = HID;
0791 info.context = context;
0792 info.user_function = user_function;
0793
0794
0795
0796
0797
0798
0799
0800 status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
0801 if (ACPI_FAILURE(status)) {
0802 return_ACPI_STATUS(status);
0803 }
0804
0805 status = acpi_ns_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
0806 ACPI_UINT32_MAX, ACPI_NS_WALK_UNLOCK,
0807 acpi_ns_get_device_callback, NULL,
0808 &info, return_value);
0809
0810 (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
0811 return_ACPI_STATUS(status);
0812 }
0813
0814 ACPI_EXPORT_SYMBOL(acpi_get_devices)
0815
0816
0817
0818
0819
0820
0821
0822
0823
0824
0825
0826
0827
0828
0829 acpi_status
0830 acpi_attach_data(acpi_handle obj_handle,
0831 acpi_object_handler handler, void *data)
0832 {
0833 struct acpi_namespace_node *node;
0834 acpi_status status;
0835
0836
0837
0838 if (!obj_handle || !handler || !data) {
0839 return (AE_BAD_PARAMETER);
0840 }
0841
0842 status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
0843 if (ACPI_FAILURE(status)) {
0844 return (status);
0845 }
0846
0847
0848
0849 node = acpi_ns_validate_handle(obj_handle);
0850 if (!node) {
0851 status = AE_BAD_PARAMETER;
0852 goto unlock_and_exit;
0853 }
0854
0855 status = acpi_ns_attach_data(node, handler, data);
0856
0857 unlock_and_exit:
0858 (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
0859 return (status);
0860 }
0861
0862 ACPI_EXPORT_SYMBOL(acpi_attach_data)
0863
0864
0865
0866
0867
0868
0869
0870
0871
0872
0873
0874
0875
0876 acpi_status
0877 acpi_detach_data(acpi_handle obj_handle, acpi_object_handler handler)
0878 {
0879 struct acpi_namespace_node *node;
0880 acpi_status status;
0881
0882
0883
0884 if (!obj_handle || !handler) {
0885 return (AE_BAD_PARAMETER);
0886 }
0887
0888 status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
0889 if (ACPI_FAILURE(status)) {
0890 return (status);
0891 }
0892
0893
0894
0895 node = acpi_ns_validate_handle(obj_handle);
0896 if (!node) {
0897 status = AE_BAD_PARAMETER;
0898 goto unlock_and_exit;
0899 }
0900
0901 status = acpi_ns_detach_data(node, handler);
0902
0903 unlock_and_exit:
0904 (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
0905 return (status);
0906 }
0907
0908 ACPI_EXPORT_SYMBOL(acpi_detach_data)
0909
0910
0911
0912
0913
0914
0915
0916
0917
0918
0919
0920
0921
0922
0923
0924
0925 acpi_status
0926 acpi_get_data_full(acpi_handle obj_handle, acpi_object_handler handler,
0927 void **data, void (*callback)(void *))
0928 {
0929 struct acpi_namespace_node *node;
0930 acpi_status status;
0931
0932
0933
0934 if (!obj_handle || !handler || !data) {
0935 return (AE_BAD_PARAMETER);
0936 }
0937
0938 status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
0939 if (ACPI_FAILURE(status)) {
0940 return (status);
0941 }
0942
0943
0944
0945 node = acpi_ns_validate_handle(obj_handle);
0946 if (!node) {
0947 status = AE_BAD_PARAMETER;
0948 goto unlock_and_exit;
0949 }
0950
0951 status = acpi_ns_get_attached_data(node, handler, data);
0952 if (ACPI_SUCCESS(status) && callback) {
0953 callback(*data);
0954 }
0955
0956 unlock_and_exit:
0957 (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
0958 return (status);
0959 }
0960
0961 ACPI_EXPORT_SYMBOL(acpi_get_data_full)
0962
0963
0964
0965
0966
0967
0968
0969
0970
0971
0972
0973
0974
0975
0976 acpi_status
0977 acpi_get_data(acpi_handle obj_handle, acpi_object_handler handler, void **data)
0978 {
0979 return acpi_get_data_full(obj_handle, handler, data, NULL);
0980 }
0981
0982 ACPI_EXPORT_SYMBOL(acpi_get_data)