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_to_external_list(op, path, ACPI_TYPE_REGION, 0);
109 status = acpi_ns_lookup(walk_state->scope_info, path, ACPI_TYPE_REGION,
110 ACPI_IMODE_LOAD_PASS1, ACPI_NS_SEARCH_PARENT,
111 walk_state, node);
112 if (ACPI_FAILURE(status)) {
113 return (status);
114 }
115
116
117
118 obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_REGION);
119 if (!obj_desc) {
120 return (AE_NO_MEMORY);
121 }
122
123 obj_desc->region.node = *node;
124 status = acpi_ns_attach_object(*node, obj_desc, ACPI_TYPE_REGION);
125 return (status);
126}
127#endif
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148acpi_status
149acpi_ds_create_buffer_field(union acpi_parse_object *op,
150 struct acpi_walk_state *walk_state)
151{
152 union acpi_parse_object *arg;
153 struct acpi_namespace_node *node;
154 acpi_status status;
155 union acpi_operand_object *obj_desc;
156 union acpi_operand_object *second_desc = NULL;
157 u32 flags;
158
159 ACPI_FUNCTION_TRACE(ds_create_buffer_field);
160
161
162
163
164 if (op->common.aml_opcode == AML_CREATE_FIELD_OP) {
165
166
167
168 arg = acpi_ps_get_arg(op, 3);
169 } else {
170
171
172 arg = acpi_ps_get_arg(op, 2);
173 }
174
175 if (!arg) {
176 return_ACPI_STATUS(AE_AML_NO_OPERAND);
177 }
178
179 if (walk_state->deferred_node) {
180 node = walk_state->deferred_node;
181 status = AE_OK;
182 } else {
183
184
185 if (!(walk_state->parse_flags & ACPI_PARSE_EXECUTE)) {
186 return_ACPI_STATUS(AE_AML_INTERNAL);
187 }
188
189
190
191 flags = ACPI_NS_NO_UPSEARCH | ACPI_NS_DONT_OPEN_SCOPE |
192 ACPI_NS_ERROR_IF_FOUND;
193
194
195
196
197
198 if (walk_state->method_node &&
199 !(walk_state->parse_flags & ACPI_PARSE_MODULE_LEVEL)) {
200 flags |= ACPI_NS_TEMPORARY;
201 }
202
203
204
205 status =
206 acpi_ns_lookup(walk_state->scope_info,
207 arg->common.value.string, ACPI_TYPE_ANY,
208 ACPI_IMODE_LOAD_PASS1, flags, walk_state,
209 &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
262 cleanup:
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 =
348 (u8)((arg->common.value.integer >> 8) & 0xFF);
349
350
351
352 info->access_length =
353 (u8)((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
364
365
366
367
368 child = arg->common.value.arg;
369 if (child->common.aml_opcode == AML_INT_BYTELIST_OP) {
370 info->resource_buffer = child->named.data;
371 info->resource_length =
372 (u16)child->named.value.integer;
373 } else {
374
375
376 status = acpi_ns_lookup(walk_state->scope_info,
377 child->common.value.
378 name, ACPI_TYPE_ANY,
379 ACPI_IMODE_EXECUTE,
380 ACPI_NS_DONT_OPEN_SCOPE,
381 walk_state,
382 &info->connection_node);
383 if (ACPI_FAILURE(status)) {
384 ACPI_ERROR_NAMESPACE(child->common.
385 value.name,
386 status);
387 return_ACPI_STATUS(status);
388 }
389 }
390 break;
391
392 case AML_INT_NAMEDFIELD_OP:
393
394
395
396 status = acpi_ns_lookup(walk_state->scope_info,
397 (char *)&arg->named.name,
398 info->field_type,
399 ACPI_IMODE_EXECUTE,
400 ACPI_NS_DONT_OPEN_SCOPE,
401 walk_state, &info->field_node);
402 if (ACPI_FAILURE(status)) {
403 ACPI_ERROR_NAMESPACE((char *)&arg->named.name,
404 status);
405 return_ACPI_STATUS(status);
406 } else {
407 arg->common.node = info->field_node;
408 info->field_bit_length = arg->common.value.size;
409
410
411
412
413
414
415
416 if (!acpi_ns_get_attached_object
417 (info->field_node)) {
418 status = acpi_ex_prep_field_value(info);
419 if (ACPI_FAILURE(status)) {
420 return_ACPI_STATUS(status);
421 }
422 }
423 }
424
425
426
427 position = (u64) info->field_bit_position
428 + (u64) arg->common.value.size;
429
430 if (position > ACPI_UINT32_MAX) {
431 ACPI_ERROR((AE_INFO,
432 "Field [%4.4s] bit offset too large (> 0xFFFFFFFF)",
433 ACPI_CAST_PTR(char,
434 &info->field_node->
435 name)));
436 return_ACPI_STATUS(AE_SUPPORT);
437 }
438
439 info->field_bit_position += info->field_bit_length;
440 break;
441
442 default:
443
444 ACPI_ERROR((AE_INFO,
445 "Invalid opcode in field list: 0x%X",
446 arg->common.aml_opcode));
447 return_ACPI_STATUS(AE_AML_BAD_OPCODE);
448 }
449
450 arg = arg->common.next;
451 }
452
453 return_ACPI_STATUS(AE_OK);
454}
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470acpi_status
471acpi_ds_create_field(union acpi_parse_object *op,
472 struct acpi_namespace_node *region_node,
473 struct acpi_walk_state *walk_state)
474{
475 acpi_status status;
476 union acpi_parse_object *arg;
477 struct acpi_create_field_info info;
478
479 ACPI_FUNCTION_TRACE_PTR(ds_create_field, op);
480
481
482
483 arg = op->common.value.arg;
484
485 if (!region_node) {
486 status =
487 acpi_ns_lookup(walk_state->scope_info,
488 arg->common.value.name, ACPI_TYPE_REGION,
489 ACPI_IMODE_EXECUTE, ACPI_NS_SEARCH_PARENT,
490 walk_state, ®ion_node);
491#ifdef ACPI_ASL_COMPILER
492 status = acpi_ds_create_external_region(status, arg,
493 arg->common.value.name,
494 walk_state,
495 ®ion_node);
496#endif
497 if (ACPI_FAILURE(status)) {
498 ACPI_ERROR_NAMESPACE(arg->common.value.name, status);
499 return_ACPI_STATUS(status);
500 }
501 }
502
503 ACPI_MEMSET(&info, 0, sizeof(struct acpi_create_field_info));
504
505
506
507 arg = arg->common.next;
508 info.field_flags = (u8) arg->common.value.integer;
509 info.attribute = 0;
510
511
512
513 info.field_type = ACPI_TYPE_LOCAL_REGION_FIELD;
514 info.region_node = region_node;
515
516 status = acpi_ds_get_field_names(&info, walk_state, arg->common.next);
517 return_ACPI_STATUS(status);
518}
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535acpi_status
536acpi_ds_init_field_objects(union acpi_parse_object *op,
537 struct acpi_walk_state *walk_state)
538{
539 acpi_status status;
540 union acpi_parse_object *arg = NULL;
541 struct acpi_namespace_node *node;
542 u8 type = 0;
543 u32 flags;
544
545 ACPI_FUNCTION_TRACE_PTR(ds_init_field_objects, op);
546
547
548
549 if (!(walk_state->parse_flags & ACPI_PARSE_EXECUTE)) {
550 if (walk_state->parse_flags & ACPI_PARSE_DEFERRED_OP) {
551
552
553
554 return_ACPI_STATUS(AE_OK);
555 }
556
557 return_ACPI_STATUS(AE_AML_INTERNAL);
558 }
559
560
561
562
563
564 switch (walk_state->opcode) {
565 case AML_FIELD_OP:
566 arg = acpi_ps_get_arg(op, 2);
567 type = ACPI_TYPE_LOCAL_REGION_FIELD;
568 break;
569
570 case AML_BANK_FIELD_OP:
571 arg = acpi_ps_get_arg(op, 4);
572 type = ACPI_TYPE_LOCAL_BANK_FIELD;
573 break;
574
575 case AML_INDEX_FIELD_OP:
576 arg = acpi_ps_get_arg(op, 3);
577 type = ACPI_TYPE_LOCAL_INDEX_FIELD;
578 break;
579
580 default:
581 return_ACPI_STATUS(AE_BAD_PARAMETER);
582 }
583
584
585
586 flags = ACPI_NS_NO_UPSEARCH | ACPI_NS_DONT_OPEN_SCOPE |
587 ACPI_NS_ERROR_IF_FOUND;
588
589
590
591
592
593 if (walk_state->method_node &&
594 !(walk_state->parse_flags & ACPI_PARSE_MODULE_LEVEL)) {
595 flags |= ACPI_NS_TEMPORARY;
596 }
597
598
599
600
601
602 while (arg) {
603
604
605
606
607 if (arg->common.aml_opcode == AML_INT_NAMEDFIELD_OP) {
608 status = acpi_ns_lookup(walk_state->scope_info,
609 (char *)&arg->named.name, type,
610 ACPI_IMODE_LOAD_PASS1, flags,
611 walk_state, &node);
612 if (ACPI_FAILURE(status)) {
613 ACPI_ERROR_NAMESPACE((char *)&arg->named.name,
614 status);
615 if (status != AE_ALREADY_EXISTS) {
616 return_ACPI_STATUS(status);
617 }
618
619
620
621 status = AE_OK;
622 }
623
624 arg->common.node = node;
625 }
626
627
628
629 arg = arg->common.next;
630 }
631
632 return_ACPI_STATUS(AE_OK);
633}
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649acpi_status
650acpi_ds_create_bank_field(union acpi_parse_object *op,
651 struct acpi_namespace_node *region_node,
652 struct acpi_walk_state *walk_state)
653{
654 acpi_status status;
655 union acpi_parse_object *arg;
656 struct acpi_create_field_info info;
657
658 ACPI_FUNCTION_TRACE_PTR(ds_create_bank_field, op);
659
660
661
662 arg = op->common.value.arg;
663 if (!region_node) {
664 status =
665 acpi_ns_lookup(walk_state->scope_info,
666 arg->common.value.name, ACPI_TYPE_REGION,
667 ACPI_IMODE_EXECUTE, ACPI_NS_SEARCH_PARENT,
668 walk_state, ®ion_node);
669#ifdef ACPI_ASL_COMPILER
670 status = acpi_ds_create_external_region(status, arg,
671 arg->common.value.name,
672 walk_state,
673 ®ion_node);
674#endif
675 if (ACPI_FAILURE(status)) {
676 ACPI_ERROR_NAMESPACE(arg->common.value.name, status);
677 return_ACPI_STATUS(status);
678 }
679 }
680
681
682
683 arg = arg->common.next;
684 status =
685 acpi_ns_lookup(walk_state->scope_info, arg->common.value.string,
686 ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE,
687 ACPI_NS_SEARCH_PARENT, walk_state,
688 &info.register_node);
689 if (ACPI_FAILURE(status)) {
690 ACPI_ERROR_NAMESPACE(arg->common.value.string, status);
691 return_ACPI_STATUS(status);
692 }
693
694
695
696
697
698
699 arg = arg->common.next;
700
701
702
703 arg = arg->common.next;
704 info.field_flags = (u8) arg->common.value.integer;
705
706
707
708 info.field_type = ACPI_TYPE_LOCAL_BANK_FIELD;
709 info.region_node = region_node;
710
711
712
713
714
715
716
717
718
719 info.data_register_node = (struct acpi_namespace_node *)op;
720
721 status = acpi_ds_get_field_names(&info, walk_state, arg->common.next);
722 return_ACPI_STATUS(status);
723}
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739acpi_status
740acpi_ds_create_index_field(union acpi_parse_object *op,
741 struct acpi_namespace_node *region_node,
742 struct acpi_walk_state *walk_state)
743{
744 acpi_status status;
745 union acpi_parse_object *arg;
746 struct acpi_create_field_info info;
747
748 ACPI_FUNCTION_TRACE_PTR(ds_create_index_field, op);
749
750
751
752 arg = op->common.value.arg;
753 status =
754 acpi_ns_lookup(walk_state->scope_info, arg->common.value.string,
755 ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE,
756 ACPI_NS_SEARCH_PARENT, walk_state,
757 &info.register_node);
758 if (ACPI_FAILURE(status)) {
759 ACPI_ERROR_NAMESPACE(arg->common.value.string, status);
760 return_ACPI_STATUS(status);
761 }
762
763
764
765 arg = arg->common.next;
766 status =
767 acpi_ns_lookup(walk_state->scope_info, arg->common.value.string,
768 ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE,
769 ACPI_NS_SEARCH_PARENT, walk_state,
770 &info.data_register_node);
771 if (ACPI_FAILURE(status)) {
772 ACPI_ERROR_NAMESPACE(arg->common.value.string, status);
773 return_ACPI_STATUS(status);
774 }
775
776
777
778 arg = arg->common.next;
779 info.field_flags = (u8) arg->common.value.integer;
780
781
782
783 info.field_type = ACPI_TYPE_LOCAL_INDEX_FIELD;
784 info.region_node = region_node;
785
786 status = acpi_ds_get_field_names(&info, walk_state, arg->common.next);
787 return_ACPI_STATUS(status);
788}
789