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