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#include <acpi/acpi.h>
45#include "accommon.h"
46#include "amlcode.h"
47#include "acdispat.h"
48#include "acinterp.h"
49#include "acnamesp.h"
50#include "acparser.h"
51
52#define _COMPONENT ACPI_DISPATCHER
53ACPI_MODULE_NAME("dsfield")
54
55
56#ifdef ACPI_ASL_COMPILER
57#include "acdisasm.h"
58static acpi_status
59acpi_ds_create_external_region(acpi_status lookup_status,
60 union acpi_parse_object *op,
61 char *path,
62 struct acpi_walk_state *walk_state,
63 struct acpi_namespace_node **node);
64#endif
65
66static acpi_status
67acpi_ds_get_field_names(struct acpi_create_field_info *info,
68 struct acpi_walk_state *walk_state,
69 union acpi_parse_object *arg);
70
71#ifdef ACPI_ASL_COMPILER
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89static acpi_status
90acpi_ds_create_external_region(acpi_status lookup_status,
91 union acpi_parse_object *op,
92 char *path,
93 struct acpi_walk_state *walk_state,
94 struct acpi_namespace_node **node)
95{
96 acpi_status status;
97 union acpi_operand_object *obj_desc;
98
99 if (lookup_status != AE_NOT_FOUND) {
100 return (lookup_status);
101 }
102
103
104
105
106
107
108 acpi_dm_add_op_to_external_list(op, path, ACPI_TYPE_REGION, 0, 0);
109
110 status = acpi_ns_lookup(walk_state->scope_info, path, ACPI_TYPE_REGION,
111 ACPI_IMODE_LOAD_PASS1, ACPI_NS_SEARCH_PARENT,
112 walk_state, node);
113 if (ACPI_FAILURE(status)) {
114 return (status);
115 }
116
117
118
119 obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_REGION);
120 if (!obj_desc) {
121 return (AE_NO_MEMORY);
122 }
123
124 obj_desc->region.node = *node;
125 status = acpi_ns_attach_object(*node, obj_desc, ACPI_TYPE_REGION);
126 return (status);
127}
128#endif
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149acpi_status
150acpi_ds_create_buffer_field(union acpi_parse_object *op,
151 struct acpi_walk_state *walk_state)
152{
153 union acpi_parse_object *arg;
154 struct acpi_namespace_node *node;
155 acpi_status status;
156 union acpi_operand_object *obj_desc;
157 union acpi_operand_object *second_desc = NULL;
158 u32 flags;
159
160 ACPI_FUNCTION_TRACE(ds_create_buffer_field);
161
162
163
164
165 if (op->common.aml_opcode == AML_CREATE_FIELD_OP) {
166
167
168
169 arg = acpi_ps_get_arg(op, 3);
170 } else {
171
172
173 arg = acpi_ps_get_arg(op, 2);
174 }
175
176 if (!arg) {
177 return_ACPI_STATUS(AE_AML_NO_OPERAND);
178 }
179
180 if (walk_state->deferred_node) {
181 node = walk_state->deferred_node;
182 status = AE_OK;
183 } else {
184
185
186 if (!(walk_state->parse_flags & ACPI_PARSE_EXECUTE)) {
187 return_ACPI_STATUS(AE_AML_INTERNAL);
188 }
189
190
191
192 flags = ACPI_NS_NO_UPSEARCH | ACPI_NS_DONT_OPEN_SCOPE |
193 ACPI_NS_ERROR_IF_FOUND;
194
195
196
197
198
199 if (walk_state->method_node &&
200 !(walk_state->parse_flags & ACPI_PARSE_MODULE_LEVEL)) {
201 flags |= ACPI_NS_TEMPORARY;
202 }
203
204
205
206 status = acpi_ns_lookup(walk_state->scope_info,
207 arg->common.value.string, ACPI_TYPE_ANY,
208 ACPI_IMODE_LOAD_PASS1, flags,
209 walk_state, &node);
210 if (ACPI_FAILURE(status)) {
211 ACPI_ERROR_NAMESPACE(arg->common.value.string, status);
212 return_ACPI_STATUS(status);
213 }
214 }
215
216
217
218
219
220
221 op->common.node = node;
222
223
224
225
226
227
228 obj_desc = acpi_ns_get_attached_object(node);
229 if (obj_desc) {
230 return_ACPI_STATUS(AE_OK);
231 }
232
233
234
235
236
237
238
239
240 obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_BUFFER_FIELD);
241 if (!obj_desc) {
242 status = AE_NO_MEMORY;
243 goto cleanup;
244 }
245
246
247
248
249
250 second_desc = obj_desc->common.next_object;
251 second_desc->extra.aml_start = op->named.data;
252 second_desc->extra.aml_length = op->named.length;
253 obj_desc->buffer_field.node = node;
254
255
256
257 status = acpi_ns_attach_object(node, obj_desc, ACPI_TYPE_BUFFER_FIELD);
258 if (ACPI_FAILURE(status)) {
259 goto cleanup;
260 }
261
262cleanup:
263
264
265
266 acpi_ut_remove_reference(obj_desc);
267 return_ACPI_STATUS(status);
268}
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285static acpi_status
286acpi_ds_get_field_names(struct acpi_create_field_info *info,
287 struct acpi_walk_state *walk_state,
288 union acpi_parse_object *arg)
289{
290 acpi_status status;
291 u64 position;
292 union acpi_parse_object *child;
293
294 ACPI_FUNCTION_TRACE_PTR(ds_get_field_names, info);
295
296
297
298 info->field_bit_position = 0;
299
300
301
302 while (arg) {
303
304
305
306
307
308
309
310 switch (arg->common.aml_opcode) {
311 case AML_INT_RESERVEDFIELD_OP:
312
313 position = (u64)info->field_bit_position +
314 (u64)arg->common.value.size;
315
316 if (position > ACPI_UINT32_MAX) {
317 ACPI_ERROR((AE_INFO,
318 "Bit offset within field too large (> 0xFFFFFFFF)"));
319 return_ACPI_STATUS(AE_SUPPORT);
320 }
321
322 info->field_bit_position = (u32) position;
323 break;
324
325 case AML_INT_ACCESSFIELD_OP:
326 case AML_INT_EXTACCESSFIELD_OP:
327
328
329
330
331
332
333
334
335
336
337
338
339
340 info->field_flags = (u8)
341 ((info->
342 field_flags & ~(AML_FIELD_ACCESS_TYPE_MASK)) |
343 ((u8)((u32)(arg->common.value.integer & 0x07))));
344
345
346
347 info->attribute = (u8)
348 ((arg->common.value.integer >> 8) & 0xFF);
349
350
351
352 info->access_length = (u8)
353 ((arg->common.value.integer >> 16) & 0xFF);
354 break;
355
356 case AML_INT_CONNECTION_OP:
357
358
359
360
361 info->resource_buffer = NULL;
362 info->connection_node = NULL;
363 info->pin_number_index = 0;
364
365
366
367
368
369 child = arg->common.value.arg;
370 if (child->common.aml_opcode == AML_INT_BYTELIST_OP) {
371 info->resource_buffer = child->named.data;
372 info->resource_length =
373 (u16)child->named.value.integer;
374 } else {
375
376
377 status = acpi_ns_lookup(walk_state->scope_info,
378 child->common.value.
379 name, ACPI_TYPE_ANY,
380 ACPI_IMODE_EXECUTE,
381 ACPI_NS_DONT_OPEN_SCOPE,
382 walk_state,
383 &info->connection_node);
384 if (ACPI_FAILURE(status)) {
385 ACPI_ERROR_NAMESPACE(child->common.
386 value.name,
387 status);
388 return_ACPI_STATUS(status);
389 }
390 }
391 break;
392
393 case AML_INT_NAMEDFIELD_OP:
394
395
396
397 status = acpi_ns_lookup(walk_state->scope_info,
398 (char *)&arg->named.name,
399 info->field_type,
400 ACPI_IMODE_EXECUTE,
401 ACPI_NS_DONT_OPEN_SCOPE,
402 walk_state, &info->field_node);
403 if (ACPI_FAILURE(status)) {
404 ACPI_ERROR_NAMESPACE((char *)&arg->named.name,
405 status);
406 return_ACPI_STATUS(status);
407 } else {
408 arg->common.node = info->field_node;
409 info->field_bit_length = arg->common.value.size;
410
411
412
413
414
415
416
417 if (!acpi_ns_get_attached_object
418 (info->field_node)) {
419 status = acpi_ex_prep_field_value(info);
420 if (ACPI_FAILURE(status)) {
421 return_ACPI_STATUS(status);
422 }
423 }
424 }
425
426
427
428 position = (u64)info->field_bit_position +
429 (u64)arg->common.value.size;
430
431 if (position > ACPI_UINT32_MAX) {
432 ACPI_ERROR((AE_INFO,
433 "Field [%4.4s] bit offset too large (> 0xFFFFFFFF)",
434 ACPI_CAST_PTR(char,
435 &info->field_node->
436 name)));
437 return_ACPI_STATUS(AE_SUPPORT);
438 }
439
440 info->field_bit_position += info->field_bit_length;
441 info->pin_number_index++;
442 break;
443
444 default:
445
446 ACPI_ERROR((AE_INFO,
447 "Invalid opcode in field list: 0x%X",
448 arg->common.aml_opcode));
449 return_ACPI_STATUS(AE_AML_BAD_OPCODE);
450 }
451
452 arg = arg->common.next;
453 }
454
455 return_ACPI_STATUS(AE_OK);
456}
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472acpi_status
473acpi_ds_create_field(union acpi_parse_object *op,
474 struct acpi_namespace_node *region_node,
475 struct acpi_walk_state *walk_state)
476{
477 acpi_status status;
478 union acpi_parse_object *arg;
479 struct acpi_create_field_info info;
480
481 ACPI_FUNCTION_TRACE_PTR(ds_create_field, op);
482
483
484
485 arg = op->common.value.arg;
486
487 if (!region_node) {
488 status =
489 acpi_ns_lookup(walk_state->scope_info,
490 arg->common.value.name, ACPI_TYPE_REGION,
491 ACPI_IMODE_EXECUTE, ACPI_NS_SEARCH_PARENT,
492 walk_state, ®ion_node);
493#ifdef ACPI_ASL_COMPILER
494 status = acpi_ds_create_external_region(status, arg,
495 arg->common.value.name,
496 walk_state,
497 ®ion_node);
498#endif
499 if (ACPI_FAILURE(status)) {
500 ACPI_ERROR_NAMESPACE(arg->common.value.name, status);
501 return_ACPI_STATUS(status);
502 }
503 }
504
505 memset(&info, 0, sizeof(struct acpi_create_field_info));
506
507
508
509 arg = arg->common.next;
510 info.field_flags = (u8) arg->common.value.integer;
511 info.attribute = 0;
512
513
514
515 info.field_type = ACPI_TYPE_LOCAL_REGION_FIELD;
516 info.region_node = region_node;
517
518 status = acpi_ds_get_field_names(&info, walk_state, arg->common.next);
519 return_ACPI_STATUS(status);
520}
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537acpi_status
538acpi_ds_init_field_objects(union acpi_parse_object *op,
539 struct acpi_walk_state *walk_state)
540{
541 acpi_status status;
542 union acpi_parse_object *arg = NULL;
543 struct acpi_namespace_node *node;
544 u8 type = 0;
545 u32 flags;
546
547 ACPI_FUNCTION_TRACE_PTR(ds_init_field_objects, op);
548
549
550
551 if (!(walk_state->parse_flags & ACPI_PARSE_EXECUTE)) {
552 if (walk_state->parse_flags & ACPI_PARSE_DEFERRED_OP) {
553
554
555
556 return_ACPI_STATUS(AE_OK);
557 }
558
559 return_ACPI_STATUS(AE_AML_INTERNAL);
560 }
561
562
563
564
565
566 switch (walk_state->opcode) {
567 case AML_FIELD_OP:
568
569 arg = acpi_ps_get_arg(op, 2);
570 type = ACPI_TYPE_LOCAL_REGION_FIELD;
571 break;
572
573 case AML_BANK_FIELD_OP:
574
575 arg = acpi_ps_get_arg(op, 4);
576 type = ACPI_TYPE_LOCAL_BANK_FIELD;
577 break;
578
579 case AML_INDEX_FIELD_OP:
580
581 arg = acpi_ps_get_arg(op, 3);
582 type = ACPI_TYPE_LOCAL_INDEX_FIELD;
583 break;
584
585 default:
586
587 return_ACPI_STATUS(AE_BAD_PARAMETER);
588 }
589
590
591
592 flags = ACPI_NS_NO_UPSEARCH | ACPI_NS_DONT_OPEN_SCOPE |
593 ACPI_NS_ERROR_IF_FOUND;
594
595
596
597
598
599 if (walk_state->method_node &&
600 !(walk_state->parse_flags & ACPI_PARSE_MODULE_LEVEL)) {
601 flags |= ACPI_NS_TEMPORARY;
602 }
603
604
605
606
607
608 while (arg) {
609
610
611
612
613 if (arg->common.aml_opcode == AML_INT_NAMEDFIELD_OP) {
614 status = acpi_ns_lookup(walk_state->scope_info,
615 (char *)&arg->named.name, type,
616 ACPI_IMODE_LOAD_PASS1, flags,
617 walk_state, &node);
618 if (ACPI_FAILURE(status)) {
619 ACPI_ERROR_NAMESPACE((char *)&arg->named.name,
620 status);
621 if (status != AE_ALREADY_EXISTS) {
622 return_ACPI_STATUS(status);
623 }
624
625
626
627 status = AE_OK;
628 }
629
630 arg->common.node = node;
631 }
632
633
634
635 arg = arg->common.next;
636 }
637
638 return_ACPI_STATUS(AE_OK);
639}
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655acpi_status
656acpi_ds_create_bank_field(union acpi_parse_object *op,
657 struct acpi_namespace_node *region_node,
658 struct acpi_walk_state *walk_state)
659{
660 acpi_status status;
661 union acpi_parse_object *arg;
662 struct acpi_create_field_info info;
663
664 ACPI_FUNCTION_TRACE_PTR(ds_create_bank_field, op);
665
666
667
668 arg = op->common.value.arg;
669 if (!region_node) {
670 status =
671 acpi_ns_lookup(walk_state->scope_info,
672 arg->common.value.name, ACPI_TYPE_REGION,
673 ACPI_IMODE_EXECUTE, ACPI_NS_SEARCH_PARENT,
674 walk_state, ®ion_node);
675#ifdef ACPI_ASL_COMPILER
676 status = acpi_ds_create_external_region(status, arg,
677 arg->common.value.name,
678 walk_state,
679 ®ion_node);
680#endif
681 if (ACPI_FAILURE(status)) {
682 ACPI_ERROR_NAMESPACE(arg->common.value.name, status);
683 return_ACPI_STATUS(status);
684 }
685 }
686
687
688
689 arg = arg->common.next;
690 status =
691 acpi_ns_lookup(walk_state->scope_info, arg->common.value.string,
692 ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE,
693 ACPI_NS_SEARCH_PARENT, walk_state,
694 &info.register_node);
695 if (ACPI_FAILURE(status)) {
696 ACPI_ERROR_NAMESPACE(arg->common.value.string, status);
697 return_ACPI_STATUS(status);
698 }
699
700
701
702
703
704
705 arg = arg->common.next;
706
707
708
709 arg = arg->common.next;
710 info.field_flags = (u8) arg->common.value.integer;
711
712
713
714 info.field_type = ACPI_TYPE_LOCAL_BANK_FIELD;
715 info.region_node = region_node;
716
717
718
719
720
721
722
723
724
725
726 info.data_register_node = (struct acpi_namespace_node *)op;
727
728 status = acpi_ds_get_field_names(&info, walk_state, arg->common.next);
729 return_ACPI_STATUS(status);
730}
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746acpi_status
747acpi_ds_create_index_field(union acpi_parse_object *op,
748 struct acpi_namespace_node *region_node,
749 struct acpi_walk_state *walk_state)
750{
751 acpi_status status;
752 union acpi_parse_object *arg;
753 struct acpi_create_field_info info;
754
755 ACPI_FUNCTION_TRACE_PTR(ds_create_index_field, op);
756
757
758
759 arg = op->common.value.arg;
760 status =
761 acpi_ns_lookup(walk_state->scope_info, arg->common.value.string,
762 ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE,
763 ACPI_NS_SEARCH_PARENT, walk_state,
764 &info.register_node);
765 if (ACPI_FAILURE(status)) {
766 ACPI_ERROR_NAMESPACE(arg->common.value.string, status);
767 return_ACPI_STATUS(status);
768 }
769
770
771
772 arg = arg->common.next;
773 status =
774 acpi_ns_lookup(walk_state->scope_info, arg->common.value.string,
775 ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE,
776 ACPI_NS_SEARCH_PARENT, walk_state,
777 &info.data_register_node);
778 if (ACPI_FAILURE(status)) {
779 ACPI_ERROR_NAMESPACE(arg->common.value.string, status);
780 return_ACPI_STATUS(status);
781 }
782
783
784
785 arg = arg->common.next;
786 info.field_flags = (u8) arg->common.value.integer;
787
788
789
790 info.field_type = ACPI_TYPE_LOCAL_INDEX_FIELD;
791 info.region_node = region_node;
792
793 status = acpi_ds_get_field_names(&info, walk_state, arg->common.next);
794 return_ACPI_STATUS(status);
795}
796