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#if 0
284
285
286
287
288
289
290 switch (acpi_ns_get_type(info->node)) {
291 case ACPI_TYPE_METHOD:
292
293
294
295 if (info->obj_desc->method.param_count > info->param_count) {
296 ACPI_ERROR((AE_INFO,
297 "Insufficient arguments (%u) - %u are required",
298 info->param_count,
299 info->obj_desc->method.param_count));
300
301 status = AE_MISSING_ARGUMENTS;
302 goto cleanup;
303 }
304
305 else if (info->obj_desc->method.param_count < info->param_count) {
306 ACPI_WARNING((AE_INFO,
307 "Excess arguments (%u) - only %u are required",
308 info->param_count,
309 info->obj_desc->method.param_count));
310
311
312
313 info->param_count = info->obj_desc->method.param_count;
314 }
315
316
317
318
319
320 if (info->param_count) {
321
322
323
324
325 info->parameters = ACPI_ALLOCATE_ZEROED(((acpi_size)
326 info->
327 param_count +
328 1) *
329 sizeof(void *));
330 if (!info->parameters) {
331 status = AE_NO_MEMORY;
332 goto cleanup;
333 }
334
335
336
337 for (i = 0; i < info->param_count; i++) {
338 status =
339 acpi_ut_copy_eobject_to_iobject
340 (&external_params->pointer[i],
341 &info->parameters[i]);
342 if (ACPI_FAILURE(status)) {
343 goto cleanup;
344 }
345 }
346
347 info->parameters[info->param_count] = NULL;
348 }
349 break;
350
351 default:
352
353
354
355 if (info->param_count) {
356 ACPI_WARNING((AE_INFO,
357 "%u arguments were passed to a non-method ACPI object",
358 info->param_count));
359 }
360 break;
361 }
362
363#endif
364
365
366
367 status = acpi_ns_evaluate(info);
368
369
370
371
372
373 if (return_buffer) {
374 if (!info->return_object) {
375 return_buffer->length = 0;
376 } else {
377 if (ACPI_GET_DESCRIPTOR_TYPE(info->return_object) ==
378 ACPI_DESC_TYPE_NAMED) {
379
380
381
382
383
384
385
386
387 status = AE_TYPE;
388 info->return_object = NULL;
389 return_buffer->length = 0;
390 }
391
392 if (ACPI_SUCCESS(status)) {
393
394
395
396 acpi_ns_resolve_references(info);
397
398
399
400 status =
401 acpi_ut_get_object_size(info->return_object,
402 &buffer_space_needed);
403 if (ACPI_SUCCESS(status)) {
404
405
406
407 status =
408 acpi_ut_initialize_buffer
409 (return_buffer,
410 buffer_space_needed);
411 if (ACPI_FAILURE(status)) {
412
413
414
415
416 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
417 "Needed buffer size %X, %s\n",
418 (u32)
419 buffer_space_needed,
420 acpi_format_exception
421 (status)));
422 } else {
423
424
425 status =
426 acpi_ut_copy_iobject_to_eobject
427 (info->return_object,
428 return_buffer);
429 }
430 }
431 }
432 }
433 }
434
435 if (info->return_object) {
436
437
438
439
440 acpi_ex_enter_interpreter();
441
442
443
444 acpi_ut_remove_reference(info->return_object);
445 acpi_ex_exit_interpreter();
446 }
447
448cleanup:
449
450
451
452 if (info->parameters) {
453
454
455
456 acpi_ut_delete_internal_object_list(info->parameters);
457 }
458
459 ACPI_FREE(info);
460 return_ACPI_STATUS(status);
461}
462
463ACPI_EXPORT_SYMBOL(acpi_evaluate_object)
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485static void acpi_ns_resolve_references(struct acpi_evaluate_info *info)
486{
487 union acpi_operand_object *obj_desc = NULL;
488 struct acpi_namespace_node *node;
489
490
491
492 if ((info->return_object)->common.type != ACPI_TYPE_LOCAL_REFERENCE) {
493 return;
494 }
495
496
497
498
499
500
501
502
503 switch (info->return_object->reference.class) {
504 case ACPI_REFCLASS_INDEX:
505
506 obj_desc = *(info->return_object->reference.where);
507 break;
508
509 case ACPI_REFCLASS_REFOF:
510
511 node = info->return_object->reference.object;
512 if (node) {
513 obj_desc = node->object;
514 }
515 break;
516
517 default:
518
519 return;
520 }
521
522
523
524 if (obj_desc) {
525 acpi_ut_add_reference(obj_desc);
526 acpi_ut_remove_reference(info->return_object);
527 info->return_object = obj_desc;
528 }
529
530 return;
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
565
566acpi_status
567acpi_walk_namespace(acpi_object_type type,
568 acpi_handle start_object,
569 u32 max_depth,
570 acpi_walk_callback descending_callback,
571 acpi_walk_callback ascending_callback,
572 void *context, void **return_value)
573{
574 acpi_status status;
575
576 ACPI_FUNCTION_TRACE(acpi_walk_namespace);
577
578
579
580 if ((type > ACPI_TYPE_LOCAL_MAX) ||
581 (!max_depth) || (!descending_callback && !ascending_callback)) {
582 return_ACPI_STATUS(AE_BAD_PARAMETER);
583 }
584
585
586
587
588
589
590
591
592
593
594
595
596 status = acpi_ut_acquire_read_lock(&acpi_gbl_namespace_rw_lock);
597 if (ACPI_FAILURE(status)) {
598 return_ACPI_STATUS(status);
599 }
600
601
602
603
604
605
606
607 status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
608 if (ACPI_FAILURE(status)) {
609 goto unlock_and_exit;
610 }
611
612
613
614 if (!acpi_ns_validate_handle(start_object)) {
615 status = AE_BAD_PARAMETER;
616 goto unlock_and_exit2;
617 }
618
619 status = acpi_ns_walk_namespace(type, start_object, max_depth,
620 ACPI_NS_WALK_UNLOCK,
621 descending_callback, ascending_callback,
622 context, return_value);
623
624unlock_and_exit2:
625 (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
626
627unlock_and_exit:
628 (void)acpi_ut_release_read_lock(&acpi_gbl_namespace_rw_lock);
629 return_ACPI_STATUS(status);
630}
631
632ACPI_EXPORT_SYMBOL(acpi_walk_namespace)
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647static acpi_status
648acpi_ns_get_device_callback(acpi_handle obj_handle,
649 u32 nesting_level,
650 void *context, void **return_value)
651{
652 struct acpi_get_devices_info *info = context;
653 acpi_status status;
654 struct acpi_namespace_node *node;
655 u32 flags;
656 struct acpi_pnp_device_id *hid;
657 struct acpi_pnp_device_id_list *cid;
658 u32 i;
659 u8 found;
660 int no_match;
661
662 status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
663 if (ACPI_FAILURE(status)) {
664 return (status);
665 }
666
667 node = acpi_ns_validate_handle(obj_handle);
668 status = acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
669 if (ACPI_FAILURE(status)) {
670 return (status);
671 }
672
673 if (!node) {
674 return (AE_BAD_PARAMETER);
675 }
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691 if (info->hid != NULL) {
692 status = acpi_ut_execute_HID(node, &hid);
693 if (status == AE_NOT_FOUND) {
694 return (AE_OK);
695 } else if (ACPI_FAILURE(status)) {
696 return (AE_CTRL_DEPTH);
697 }
698
699 no_match = ACPI_STRCMP(hid->string, info->hid);
700 ACPI_FREE(hid);
701
702 if (no_match) {
703
704
705
706
707 status = acpi_ut_execute_CID(node, &cid);
708 if (status == AE_NOT_FOUND) {
709 return (AE_OK);
710 } else if (ACPI_FAILURE(status)) {
711 return (AE_CTRL_DEPTH);
712 }
713
714
715
716 found = FALSE;
717 for (i = 0; i < cid->count; i++) {
718 if (ACPI_STRCMP(cid->ids[i].string, info->hid)
719 == 0) {
720
721
722
723 found = TRUE;
724 break;
725 }
726 }
727
728 ACPI_FREE(cid);
729 if (!found) {
730 return (AE_OK);
731 }
732 }
733 }
734
735
736
737 status = acpi_ut_execute_STA(node, &flags);
738 if (ACPI_FAILURE(status)) {
739 return (AE_CTRL_DEPTH);
740 }
741
742 if (!(flags & ACPI_STA_DEVICE_PRESENT) &&
743 !(flags & ACPI_STA_DEVICE_FUNCTIONING)) {
744
745
746
747
748
749 return (AE_CTRL_DEPTH);
750 }
751
752
753
754 status = info->user_function(obj_handle, nesting_level, info->context,
755 return_value);
756 return (status);
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
782
783
784acpi_status
785acpi_get_devices(const char *HID,
786 acpi_walk_callback user_function,
787 void *context, void **return_value)
788{
789 acpi_status status;
790 struct acpi_get_devices_info info;
791
792 ACPI_FUNCTION_TRACE(acpi_get_devices);
793
794
795
796 if (!user_function) {
797 return_ACPI_STATUS(AE_BAD_PARAMETER);
798 }
799
800
801
802
803
804 info.hid = HID;
805 info.context = context;
806 info.user_function = user_function;
807
808
809
810
811
812
813
814 status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
815 if (ACPI_FAILURE(status)) {
816 return_ACPI_STATUS(status);
817 }
818
819 status = acpi_ns_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
820 ACPI_UINT32_MAX, ACPI_NS_WALK_UNLOCK,
821 acpi_ns_get_device_callback, NULL,
822 &info, return_value);
823
824 (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
825 return_ACPI_STATUS(status);
826}
827
828ACPI_EXPORT_SYMBOL(acpi_get_devices)
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843acpi_status
844acpi_attach_data(acpi_handle obj_handle,
845 acpi_object_handler handler, void *data)
846{
847 struct acpi_namespace_node *node;
848 acpi_status status;
849
850
851
852 if (!obj_handle || !handler || !data) {
853 return (AE_BAD_PARAMETER);
854 }
855
856 status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
857 if (ACPI_FAILURE(status)) {
858 return (status);
859 }
860
861
862
863 node = acpi_ns_validate_handle(obj_handle);
864 if (!node) {
865 status = AE_BAD_PARAMETER;
866 goto unlock_and_exit;
867 }
868
869 status = acpi_ns_attach_data(node, handler, data);
870
871unlock_and_exit:
872 (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
873 return (status);
874}
875
876ACPI_EXPORT_SYMBOL(acpi_attach_data)
877
878
879
880
881
882
883
884
885
886
887
888
889
890acpi_status
891acpi_detach_data(acpi_handle obj_handle, acpi_object_handler handler)
892{
893 struct acpi_namespace_node *node;
894 acpi_status status;
895
896
897
898 if (!obj_handle || !handler) {
899 return (AE_BAD_PARAMETER);
900 }
901
902 status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
903 if (ACPI_FAILURE(status)) {
904 return (status);
905 }
906
907
908
909 node = acpi_ns_validate_handle(obj_handle);
910 if (!node) {
911 status = AE_BAD_PARAMETER;
912 goto unlock_and_exit;
913 }
914
915 status = acpi_ns_detach_data(node, handler);
916
917unlock_and_exit:
918 (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
919 return (status);
920}
921
922ACPI_EXPORT_SYMBOL(acpi_detach_data)
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937acpi_status
938acpi_get_data(acpi_handle obj_handle, acpi_object_handler handler, void **data)
939{
940 struct acpi_namespace_node *node;
941 acpi_status status;
942
943
944
945 if (!obj_handle || !handler || !data) {
946 return (AE_BAD_PARAMETER);
947 }
948
949 status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
950 if (ACPI_FAILURE(status)) {
951 return (status);
952 }
953
954
955
956 node = acpi_ns_validate_handle(obj_handle);
957 if (!node) {
958 status = AE_BAD_PARAMETER;
959 goto unlock_and_exit;
960 }
961
962 status = acpi_ns_get_attached_data(node, handler, data);
963
964unlock_and_exit:
965 (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
966 return (status);
967}
968
969ACPI_EXPORT_SYMBOL(acpi_get_data)
970