1
2
3
4
5
6
7
8
9#define EXPORT_ACPI_INTERFACES
10
11#include <acpi/acpi.h>
12#include "accommon.h"
13#include "acnamesp.h"
14#include "acinterp.h"
15
16#define _COMPONENT ACPI_NAMESPACE
17ACPI_MODULE_NAME("nsxfeval")
18
19
20static void acpi_ns_resolve_references(struct acpi_evaluate_info *info);
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43acpi_status
44acpi_evaluate_object_typed(acpi_handle handle,
45 acpi_string pathname,
46 struct acpi_object_list *external_params,
47 struct acpi_buffer *return_buffer,
48 acpi_object_type return_type)
49{
50 acpi_status status;
51 u8 free_buffer_on_error = FALSE;
52 acpi_handle target_handle;
53 char *full_pathname;
54
55 ACPI_FUNCTION_TRACE(acpi_evaluate_object_typed);
56
57
58
59 if (!return_buffer) {
60 return_ACPI_STATUS(AE_BAD_PARAMETER);
61 }
62
63 if (return_buffer->length == ACPI_ALLOCATE_BUFFER) {
64 free_buffer_on_error = TRUE;
65 }
66
67
68
69 target_handle = handle;
70 if (pathname) {
71 status = acpi_get_handle(handle, pathname, &target_handle);
72 if (ACPI_FAILURE(status)) {
73 return_ACPI_STATUS(status);
74 }
75 }
76
77 full_pathname = acpi_ns_get_external_pathname(target_handle);
78 if (!full_pathname) {
79 return_ACPI_STATUS(AE_NO_MEMORY);
80 }
81
82
83
84 status = acpi_evaluate_object(target_handle, NULL, external_params,
85 return_buffer);
86 if (ACPI_FAILURE(status)) {
87 goto exit;
88 }
89
90
91
92 if (return_type == ACPI_TYPE_ANY) {
93 goto exit;
94 }
95
96 if (return_buffer->length == 0) {
97
98
99
100 ACPI_ERROR((AE_INFO, "%s did not return any object",
101 full_pathname));
102 status = AE_NULL_OBJECT;
103 goto exit;
104 }
105
106
107
108 if (((union acpi_object *)return_buffer->pointer)->type == return_type) {
109 goto exit;
110 }
111
112
113
114 ACPI_ERROR((AE_INFO,
115 "Incorrect return type from %s - received [%s], requested [%s]",
116 full_pathname,
117 acpi_ut_get_type_name(((union acpi_object *)return_buffer->
118 pointer)->type),
119 acpi_ut_get_type_name(return_type)));
120
121 if (free_buffer_on_error) {
122
123
124
125
126
127
128
129 acpi_os_free(return_buffer->pointer);
130 return_buffer->pointer = NULL;
131 }
132
133 return_buffer->length = 0;
134 status = AE_TYPE;
135
136exit:
137 ACPI_FREE(full_pathname);
138 return_ACPI_STATUS(status);
139}
140
141ACPI_EXPORT_SYMBOL(acpi_evaluate_object_typed)
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162acpi_status
163acpi_evaluate_object(acpi_handle handle,
164 acpi_string pathname,
165 struct acpi_object_list *external_params,
166 struct acpi_buffer *return_buffer)
167{
168 acpi_status status;
169 struct acpi_evaluate_info *info;
170 acpi_size buffer_space_needed;
171 u32 i;
172
173 ACPI_FUNCTION_TRACE(acpi_evaluate_object);
174
175
176
177 info = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_evaluate_info));
178 if (!info) {
179 return_ACPI_STATUS(AE_NO_MEMORY);
180 }
181
182
183
184 info->prefix_node = acpi_ns_validate_handle(handle);
185 if (!info->prefix_node) {
186 status = AE_BAD_PARAMETER;
187 goto cleanup;
188 }
189
190
191
192
193
194
195
196
197
198 if ((pathname) && (ACPI_IS_ROOT_PREFIX(pathname[0]))) {
199
200
201
202 info->prefix_node = NULL;
203 } else if (!handle) {
204
205
206
207
208
209 if (!pathname) {
210 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
211 "Both Handle and Pathname are NULL"));
212 } else {
213 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
214 "Null Handle with relative pathname [%s]",
215 pathname));
216 }
217
218 status = AE_BAD_PARAMETER;
219 goto cleanup;
220 }
221
222 info->relative_pathname = pathname;
223
224
225
226
227
228 if (external_params && external_params->count) {
229 info->param_count = (u16)external_params->count;
230
231
232
233 if (info->param_count > ACPI_METHOD_NUM_ARGS) {
234 ACPI_WARN_PREDEFINED((AE_INFO, pathname,
235 ACPI_WARN_ALWAYS,
236 "Excess arguments (%u) - using only %u",
237 info->param_count,
238 ACPI_METHOD_NUM_ARGS));
239
240 info->param_count = ACPI_METHOD_NUM_ARGS;
241 }
242
243
244
245
246
247 info->parameters = ACPI_ALLOCATE_ZEROED(((acpi_size)info->
248 param_count +
249 1) * sizeof(void *));
250 if (!info->parameters) {
251 status = AE_NO_MEMORY;
252 goto cleanup;
253 }
254
255
256
257 for (i = 0; i < info->param_count; i++) {
258 status =
259 acpi_ut_copy_eobject_to_iobject(&external_params->
260 pointer[i],
261 &info->
262 parameters[i]);
263 if (ACPI_FAILURE(status)) {
264 goto cleanup;
265 }
266 }
267
268 info->parameters[info->param_count] = NULL;
269 }
270
271#ifdef _FUTURE_FEATURE
272
273
274
275
276
277 switch (acpi_ns_get_type(info->node)) {
278 case ACPI_TYPE_METHOD:
279
280
281
282 if (info->obj_desc->method.param_count > info->param_count) {
283 ACPI_ERROR((AE_INFO,
284 "Insufficient arguments (%u) - %u are required",
285 info->param_count,
286 info->obj_desc->method.param_count));
287
288 status = AE_MISSING_ARGUMENTS;
289 goto cleanup;
290 }
291
292 else if (info->obj_desc->method.param_count < info->param_count) {
293 ACPI_WARNING((AE_INFO,
294 "Excess arguments (%u) - only %u are required",
295 info->param_count,
296 info->obj_desc->method.param_count));
297
298
299
300 info->param_count = info->obj_desc->method.param_count;
301 }
302
303
304
305
306
307 if (info->param_count) {
308
309
310
311
312 info->parameters = ACPI_ALLOCATE_ZEROED(((acpi_size)
313 info->
314 param_count +
315 1) *
316 sizeof(void *));
317 if (!info->parameters) {
318 status = AE_NO_MEMORY;
319 goto cleanup;
320 }
321
322
323
324 for (i = 0; i < info->param_count; i++) {
325 status =
326 acpi_ut_copy_eobject_to_iobject
327 (&external_params->pointer[i],
328 &info->parameters[i]);
329 if (ACPI_FAILURE(status)) {
330 goto cleanup;
331 }
332 }
333
334 info->parameters[info->param_count] = NULL;
335 }
336 break;
337
338 default:
339
340
341
342 if (info->param_count) {
343 ACPI_WARNING((AE_INFO,
344 "%u arguments were passed to a non-method ACPI object",
345 info->param_count));
346 }
347 break;
348 }
349
350#endif
351
352
353
354 status = acpi_ns_evaluate(info);
355
356
357
358
359
360 if (!return_buffer) {
361 goto cleanup_return_object;
362 }
363
364 if (!info->return_object) {
365 return_buffer->length = 0;
366 goto cleanup;
367 }
368
369 if (ACPI_GET_DESCRIPTOR_TYPE(info->return_object) ==
370 ACPI_DESC_TYPE_NAMED) {
371
372
373
374
375
376
377
378
379 status = AE_TYPE;
380 info->return_object = NULL;
381 return_buffer->length = 0;
382 }
383
384 if (ACPI_FAILURE(status)) {
385 goto cleanup_return_object;
386 }
387
388
389
390 acpi_ns_resolve_references(info);
391
392
393
394 status = acpi_ut_get_object_size(info->return_object,
395 &buffer_space_needed);
396 if (ACPI_SUCCESS(status)) {
397
398
399
400 status = acpi_ut_initialize_buffer(return_buffer,
401 buffer_space_needed);
402 if (ACPI_FAILURE(status)) {
403
404
405
406
407 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
408 "Needed buffer size %X, %s\n",
409 (u32)buffer_space_needed,
410 acpi_format_exception(status)));
411 } else {
412
413
414 status =
415 acpi_ut_copy_iobject_to_eobject(info->return_object,
416 return_buffer);
417 }
418 }
419
420cleanup_return_object:
421
422 if (info->return_object) {
423
424
425
426
427 acpi_ex_enter_interpreter();
428
429
430
431 acpi_ut_remove_reference(info->return_object);
432 acpi_ex_exit_interpreter();
433 }
434
435cleanup:
436
437
438
439 if (info->parameters) {
440
441
442
443 acpi_ut_delete_internal_object_list(info->parameters);
444 }
445
446 ACPI_FREE(info);
447 return_ACPI_STATUS(status);
448}
449
450ACPI_EXPORT_SYMBOL(acpi_evaluate_object)
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472static void acpi_ns_resolve_references(struct acpi_evaluate_info *info)
473{
474 union acpi_operand_object *obj_desc = NULL;
475 struct acpi_namespace_node *node;
476
477
478
479 if ((info->return_object)->common.type != ACPI_TYPE_LOCAL_REFERENCE) {
480 return;
481 }
482
483
484
485
486
487
488
489
490 switch (info->return_object->reference.class) {
491 case ACPI_REFCLASS_INDEX:
492
493 obj_desc = *(info->return_object->reference.where);
494 break;
495
496 case ACPI_REFCLASS_REFOF:
497
498 node = info->return_object->reference.object;
499 if (node) {
500 obj_desc = node->object;
501 }
502 break;
503
504 default:
505
506 return;
507 }
508
509
510
511 if (obj_desc) {
512 acpi_ut_add_reference(obj_desc);
513 acpi_ut_remove_reference(info->return_object);
514 info->return_object = obj_desc;
515 }
516
517 return;
518}
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553acpi_status
554acpi_walk_namespace(acpi_object_type type,
555 acpi_handle start_object,
556 u32 max_depth,
557 acpi_walk_callback descending_callback,
558 acpi_walk_callback ascending_callback,
559 void *context, void **return_value)
560{
561 acpi_status status;
562
563 ACPI_FUNCTION_TRACE(acpi_walk_namespace);
564
565
566
567 if ((type > ACPI_TYPE_LOCAL_MAX) ||
568 (!max_depth) || (!descending_callback && !ascending_callback)) {
569 return_ACPI_STATUS(AE_BAD_PARAMETER);
570 }
571
572
573
574
575
576
577
578
579
580
581
582
583 status = acpi_ut_acquire_read_lock(&acpi_gbl_namespace_rw_lock);
584 if (ACPI_FAILURE(status)) {
585 return_ACPI_STATUS(status);
586 }
587
588
589
590
591
592
593
594 status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
595 if (ACPI_FAILURE(status)) {
596 goto unlock_and_exit;
597 }
598
599
600
601 if (!acpi_ns_validate_handle(start_object)) {
602 status = AE_BAD_PARAMETER;
603 goto unlock_and_exit2;
604 }
605
606 status = acpi_ns_walk_namespace(type, start_object, max_depth,
607 ACPI_NS_WALK_UNLOCK,
608 descending_callback, ascending_callback,
609 context, return_value);
610
611unlock_and_exit2:
612 (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
613
614unlock_and_exit:
615 (void)acpi_ut_release_read_lock(&acpi_gbl_namespace_rw_lock);
616 return_ACPI_STATUS(status);
617}
618
619ACPI_EXPORT_SYMBOL(acpi_walk_namespace)
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634static acpi_status
635acpi_ns_get_device_callback(acpi_handle obj_handle,
636 u32 nesting_level,
637 void *context, void **return_value)
638{
639 struct acpi_get_devices_info *info = context;
640 acpi_status status;
641 struct acpi_namespace_node *node;
642 u32 flags;
643 struct acpi_pnp_device_id *hid;
644 struct acpi_pnp_device_id_list *cid;
645 u32 i;
646 u8 found;
647 int no_match;
648
649 status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
650 if (ACPI_FAILURE(status)) {
651 return (status);
652 }
653
654 node = acpi_ns_validate_handle(obj_handle);
655 status = acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
656 if (ACPI_FAILURE(status)) {
657 return (status);
658 }
659
660 if (!node) {
661 return (AE_BAD_PARAMETER);
662 }
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678 if (info->hid != NULL) {
679 status = acpi_ut_execute_HID(node, &hid);
680 if (status == AE_NOT_FOUND) {
681 return (AE_OK);
682 } else if (ACPI_FAILURE(status)) {
683 return (AE_CTRL_DEPTH);
684 }
685
686 no_match = strcmp(hid->string, info->hid);
687 ACPI_FREE(hid);
688
689 if (no_match) {
690
691
692
693
694 status = acpi_ut_execute_CID(node, &cid);
695 if (status == AE_NOT_FOUND) {
696 return (AE_OK);
697 } else if (ACPI_FAILURE(status)) {
698 return (AE_CTRL_DEPTH);
699 }
700
701
702
703 found = FALSE;
704 for (i = 0; i < cid->count; i++) {
705 if (strcmp(cid->ids[i].string, info->hid) == 0) {
706
707
708
709 found = TRUE;
710 break;
711 }
712 }
713
714 ACPI_FREE(cid);
715 if (!found) {
716 return (AE_OK);
717 }
718 }
719 }
720
721
722
723 status = acpi_ut_execute_STA(node, &flags);
724 if (ACPI_FAILURE(status)) {
725 return (AE_CTRL_DEPTH);
726 }
727
728 if (!(flags & ACPI_STA_DEVICE_PRESENT) &&
729 !(flags & ACPI_STA_DEVICE_FUNCTIONING)) {
730
731
732
733
734
735 return (AE_CTRL_DEPTH);
736 }
737
738
739
740 status = info->user_function(obj_handle, nesting_level,
741 info->context, return_value);
742 return (status);
743}
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770acpi_status
771acpi_get_devices(const char *HID,
772 acpi_walk_callback user_function,
773 void *context, void **return_value)
774{
775 acpi_status status;
776 struct acpi_get_devices_info info;
777
778 ACPI_FUNCTION_TRACE(acpi_get_devices);
779
780
781
782 if (!user_function) {
783 return_ACPI_STATUS(AE_BAD_PARAMETER);
784 }
785
786
787
788
789
790 info.hid = HID;
791 info.context = context;
792 info.user_function = user_function;
793
794
795
796
797
798
799
800 status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
801 if (ACPI_FAILURE(status)) {
802 return_ACPI_STATUS(status);
803 }
804
805 status = acpi_ns_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
806 ACPI_UINT32_MAX, ACPI_NS_WALK_UNLOCK,
807 acpi_ns_get_device_callback, NULL,
808 &info, return_value);
809
810 (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
811 return_ACPI_STATUS(status);
812}
813
814ACPI_EXPORT_SYMBOL(acpi_get_devices)
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829acpi_status
830acpi_attach_data(acpi_handle obj_handle,
831 acpi_object_handler handler, void *data)
832{
833 struct acpi_namespace_node *node;
834 acpi_status status;
835
836
837
838 if (!obj_handle || !handler || !data) {
839 return (AE_BAD_PARAMETER);
840 }
841
842 status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
843 if (ACPI_FAILURE(status)) {
844 return (status);
845 }
846
847
848
849 node = acpi_ns_validate_handle(obj_handle);
850 if (!node) {
851 status = AE_BAD_PARAMETER;
852 goto unlock_and_exit;
853 }
854
855 status = acpi_ns_attach_data(node, handler, data);
856
857unlock_and_exit:
858 (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
859 return (status);
860}
861
862ACPI_EXPORT_SYMBOL(acpi_attach_data)
863
864
865
866
867
868
869
870
871
872
873
874
875
876acpi_status
877acpi_detach_data(acpi_handle obj_handle, acpi_object_handler handler)
878{
879 struct acpi_namespace_node *node;
880 acpi_status status;
881
882
883
884 if (!obj_handle || !handler) {
885 return (AE_BAD_PARAMETER);
886 }
887
888 status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
889 if (ACPI_FAILURE(status)) {
890 return (status);
891 }
892
893
894
895 node = acpi_ns_validate_handle(obj_handle);
896 if (!node) {
897 status = AE_BAD_PARAMETER;
898 goto unlock_and_exit;
899 }
900
901 status = acpi_ns_detach_data(node, handler);
902
903unlock_and_exit:
904 (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
905 return (status);
906}
907
908ACPI_EXPORT_SYMBOL(acpi_detach_data)
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925acpi_status
926acpi_get_data_full(acpi_handle obj_handle, acpi_object_handler handler,
927 void **data, void (*callback)(void *))
928{
929 struct acpi_namespace_node *node;
930 acpi_status status;
931
932
933
934 if (!obj_handle || !handler || !data) {
935 return (AE_BAD_PARAMETER);
936 }
937
938 status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
939 if (ACPI_FAILURE(status)) {
940 return (status);
941 }
942
943
944
945 node = acpi_ns_validate_handle(obj_handle);
946 if (!node) {
947 status = AE_BAD_PARAMETER;
948 goto unlock_and_exit;
949 }
950
951 status = acpi_ns_get_attached_data(node, handler, data);
952 if (ACPI_SUCCESS(status) && callback) {
953 callback(*data);
954 }
955
956unlock_and_exit:
957 (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
958 return (status);
959}
960
961ACPI_EXPORT_SYMBOL(acpi_get_data_full)
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976acpi_status
977acpi_get_data(acpi_handle obj_handle, acpi_object_handler handler, void **data)
978{
979 return acpi_get_data_full(obj_handle, handler, data, NULL);
980}
981
982ACPI_EXPORT_SYMBOL(acpi_get_data)
983