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