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