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