1 // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
2 /******************************************************************************
4 * Module Name: dsfield - Dispatcher field routines
6 * Copyright (C) 2000 - 2019, Intel Corp.
8 *****************************************************************************/
10 #include <acpi/acpi.h>
22 #define _COMPONENT ACPI_DISPATCHER
23 ACPI_MODULE_NAME("dsfield")
25 /* Local prototypes */
26 #ifdef ACPI_ASL_COMPILER
29 acpi_ds_create_external_region(acpi_status lookup_status
,
30 union acpi_parse_object
*op
,
32 struct acpi_walk_state
*walk_state
,
33 struct acpi_namespace_node
**node
);
37 acpi_ds_get_field_names(struct acpi_create_field_info
*info
,
38 struct acpi_walk_state
*walk_state
,
39 union acpi_parse_object
*arg
);
41 #ifdef ACPI_ASL_COMPILER
42 /*******************************************************************************
44 * FUNCTION: acpi_ds_create_external_region (iASL Disassembler only)
46 * PARAMETERS: lookup_status - Status from ns_lookup operation
47 * op - Op containing the Field definition and args
48 * path - Pathname of the region
49 * ` walk_state - Current method state
50 * node - Where the new region node is returned
54 * DESCRIPTION: Add region to the external list if NOT_FOUND. Create a new
57 ******************************************************************************/
60 acpi_ds_create_external_region(acpi_status lookup_status
,
61 union acpi_parse_object
*op
,
63 struct acpi_walk_state
*walk_state
,
64 struct acpi_namespace_node
**node
)
67 union acpi_operand_object
*obj_desc
;
69 if (lookup_status
!= AE_NOT_FOUND
) {
70 return (lookup_status
);
75 * operation_region not found. Generate an External for it, and
76 * insert the name into the namespace.
78 acpi_dm_add_op_to_external_list(op
, path
, ACPI_TYPE_REGION
, 0, 0);
80 status
= acpi_ns_lookup(walk_state
->scope_info
, path
, ACPI_TYPE_REGION
,
81 ACPI_IMODE_LOAD_PASS1
, ACPI_NS_SEARCH_PARENT
,
83 if (ACPI_FAILURE(status
)) {
87 /* Must create and install a region object for the new node */
89 obj_desc
= acpi_ut_create_internal_object(ACPI_TYPE_REGION
);
91 return (AE_NO_MEMORY
);
94 obj_desc
->region
.node
= *node
;
95 status
= acpi_ns_attach_object(*node
, obj_desc
, ACPI_TYPE_REGION
);
100 /*******************************************************************************
102 * FUNCTION: acpi_ds_create_buffer_field
104 * PARAMETERS: op - Current parse op (create_XXField)
105 * walk_state - Current state
109 * DESCRIPTION: Execute the create_field operators:
110 * create_bit_field_op,
111 * create_byte_field_op,
112 * create_word_field_op,
113 * create_dword_field_op,
114 * create_qword_field_op,
115 * create_field_op (all of which define a field in a buffer)
117 ******************************************************************************/
120 acpi_ds_create_buffer_field(union acpi_parse_object
*op
,
121 struct acpi_walk_state
*walk_state
)
123 union acpi_parse_object
*arg
;
124 struct acpi_namespace_node
*node
;
126 union acpi_operand_object
*obj_desc
;
127 union acpi_operand_object
*second_desc
= NULL
;
130 ACPI_FUNCTION_TRACE(ds_create_buffer_field
);
133 * Get the name_string argument (name of the new buffer_field)
135 if (op
->common
.aml_opcode
== AML_CREATE_FIELD_OP
) {
137 /* For create_field, name is the 4th argument */
139 arg
= acpi_ps_get_arg(op
, 3);
141 /* For all other create_XXXField operators, name is the 3rd argument */
143 arg
= acpi_ps_get_arg(op
, 2);
147 return_ACPI_STATUS(AE_AML_NO_OPERAND
);
150 if (walk_state
->deferred_node
) {
151 node
= walk_state
->deferred_node
;
154 /* Execute flag should always be set when this function is entered */
156 if (!(walk_state
->parse_flags
& ACPI_PARSE_EXECUTE
)) {
157 ACPI_ERROR((AE_INFO
, "Parse execute mode is not set"));
158 return_ACPI_STATUS(AE_AML_INTERNAL
);
161 /* Creating new namespace node, should not already exist */
163 flags
= ACPI_NS_NO_UPSEARCH
| ACPI_NS_DONT_OPEN_SCOPE
|
164 ACPI_NS_ERROR_IF_FOUND
;
167 * Mark node temporary if we are executing a normal control
168 * method. (Don't mark if this is a module-level code method)
170 if (walk_state
->method_node
&&
171 !(walk_state
->parse_flags
& ACPI_PARSE_MODULE_LEVEL
)) {
172 flags
|= ACPI_NS_TEMPORARY
;
175 /* Enter the name_string into the namespace */
177 status
= acpi_ns_lookup(walk_state
->scope_info
,
178 arg
->common
.value
.string
, ACPI_TYPE_ANY
,
179 ACPI_IMODE_LOAD_PASS1
, flags
,
181 if (ACPI_FAILURE(status
)) {
182 ACPI_ERROR_NAMESPACE(walk_state
->scope_info
,
183 arg
->common
.value
.string
, status
);
184 return_ACPI_STATUS(status
);
189 * We could put the returned object (Node) on the object stack for later,
190 * but for now, we will put it in the "op" object that the parser uses,
191 * so we can get it again at the end of this scope.
193 op
->common
.node
= node
;
196 * If there is no object attached to the node, this node was just created
197 * and we need to create the field object. Otherwise, this was a lookup
198 * of an existing node and we don't want to create the field object again.
200 obj_desc
= acpi_ns_get_attached_object(node
);
202 return_ACPI_STATUS(AE_OK
);
206 * The Field definition is not fully parsed at this time.
207 * (We must save the address of the AML for the buffer and index operands)
210 /* Create the buffer field object */
212 obj_desc
= acpi_ut_create_internal_object(ACPI_TYPE_BUFFER_FIELD
);
214 status
= AE_NO_MEMORY
;
219 * Remember location in AML stream of the field unit opcode and operands
220 * -- since the buffer and index operands must be evaluated.
222 second_desc
= obj_desc
->common
.next_object
;
223 second_desc
->extra
.aml_start
= op
->named
.data
;
224 second_desc
->extra
.aml_length
= op
->named
.length
;
225 obj_desc
->buffer_field
.node
= node
;
227 /* Attach constructed field descriptors to parent node */
229 status
= acpi_ns_attach_object(node
, obj_desc
, ACPI_TYPE_BUFFER_FIELD
);
230 if (ACPI_FAILURE(status
)) {
236 /* Remove local reference to the object */
238 acpi_ut_remove_reference(obj_desc
);
239 return_ACPI_STATUS(status
);
242 /*******************************************************************************
244 * FUNCTION: acpi_ds_get_field_names
246 * PARAMETERS: info - create_field info structure
247 * ` walk_state - Current method state
248 * arg - First parser arg for the field name list
252 * DESCRIPTION: Process all named fields in a field declaration. Names are
253 * entered into the namespace.
255 ******************************************************************************/
258 acpi_ds_get_field_names(struct acpi_create_field_info
*info
,
259 struct acpi_walk_state
*walk_state
,
260 union acpi_parse_object
*arg
)
264 union acpi_parse_object
*child
;
268 union acpi_operand_object
*result_desc
;
269 union acpi_operand_object
*obj_desc
;
273 ACPI_FUNCTION_TRACE_PTR(ds_get_field_names
, info
);
275 /* First field starts at bit zero */
277 info
->field_bit_position
= 0;
279 /* Process all elements in the field list (of parse nodes) */
283 * Four types of field elements are handled:
284 * 1) name - Enters a new named field into the namespace
285 * 2) offset - specifies a bit offset
286 * 3) access_as - changes the access mode/attributes
287 * 4) connection - Associate a resource template with the field
289 switch (arg
->common
.aml_opcode
) {
290 case AML_INT_RESERVEDFIELD_OP
:
292 position
= (u64
)info
->field_bit_position
+
293 (u64
)arg
->common
.value
.size
;
295 if (position
> ACPI_UINT32_MAX
) {
297 "Bit offset within field too large (> 0xFFFFFFFF)"));
298 return_ACPI_STATUS(AE_SUPPORT
);
301 info
->field_bit_position
= (u32
) position
;
304 case AML_INT_ACCESSFIELD_OP
:
305 case AML_INT_EXTACCESSFIELD_OP
:
307 * Get new access_type, access_attribute, and access_length fields
308 * -- to be used for all field units that follow, until the
309 * end-of-field or another access_as keyword is encountered.
310 * NOTE. These three bytes are encoded in the integer value
311 * of the parseop for convenience.
313 * In field_flags, preserve the flag bits other than the
317 /* access_type (byte_acc, word_acc, etc.) */
319 info
->field_flags
= (u8
)
321 field_flags
& ~(AML_FIELD_ACCESS_TYPE_MASK
)) |
322 ((u8
)((u32
)(arg
->common
.value
.integer
& 0x07))));
324 /* access_attribute (attrib_quick, attrib_byte, etc.) */
326 info
->attribute
= (u8
)
327 ((arg
->common
.value
.integer
>> 8) & 0xFF);
329 /* access_length (for serial/buffer protocols) */
331 info
->access_length
= (u8
)
332 ((arg
->common
.value
.integer
>> 16) & 0xFF);
335 case AML_INT_CONNECTION_OP
:
337 * Clear any previous connection. New connection is used for all
338 * fields that follow, similar to access_as
340 info
->resource_buffer
= NULL
;
341 info
->connection_node
= NULL
;
342 info
->pin_number_index
= 0;
345 * A Connection() is either an actual resource descriptor (buffer)
346 * or a named reference to a resource template
348 child
= arg
->common
.value
.arg
;
349 if (child
->common
.aml_opcode
== AML_INT_BYTELIST_OP
) {
350 info
->resource_buffer
= child
->named
.data
;
351 info
->resource_length
=
352 (u16
)child
->named
.value
.integer
;
354 /* Lookup the Connection() namepath, it should already exist */
356 status
= acpi_ns_lookup(walk_state
->scope_info
,
360 ACPI_NS_DONT_OPEN_SCOPE
,
362 &info
->connection_node
);
363 if (ACPI_FAILURE(status
)) {
364 ACPI_ERROR_NAMESPACE(walk_state
->
369 return_ACPI_STATUS(status
);
374 case AML_INT_NAMEDFIELD_OP
:
376 /* Lookup the name, it should already exist */
378 status
= acpi_ns_lookup(walk_state
->scope_info
,
379 (char *)&arg
->named
.name
,
382 ACPI_NS_DONT_OPEN_SCOPE
,
383 walk_state
, &info
->field_node
);
384 if (ACPI_FAILURE(status
)) {
385 ACPI_ERROR_NAMESPACE(walk_state
->scope_info
,
386 (char *)&arg
->named
.name
,
388 return_ACPI_STATUS(status
);
390 arg
->common
.node
= info
->field_node
;
391 info
->field_bit_length
= arg
->common
.value
.size
;
394 * If there is no object attached to the node, this node was
395 * just created and we need to create the field object.
396 * Otherwise, this was a lookup of an existing node and we
397 * don't want to create the field object again.
399 if (!acpi_ns_get_attached_object
400 (info
->field_node
)) {
401 status
= acpi_ex_prep_field_value(info
);
402 if (ACPI_FAILURE(status
)) {
403 return_ACPI_STATUS(status
);
407 acpi_ns_get_external_pathname(info
->
410 acpi_ut_create_integer_object
413 (ae_lookup_init_file_entry
414 (name_path
, &value
))) {
415 acpi_ex_write_data_to_field
417 acpi_ns_get_attached_object
421 acpi_ut_remove_reference(obj_desc
);
422 ACPI_FREE(name_path
);
427 /* Keep track of bit position for the next field */
429 position
= (u64
)info
->field_bit_position
+
430 (u64
)arg
->common
.value
.size
;
432 if (position
> ACPI_UINT32_MAX
) {
434 "Field [%4.4s] bit offset too large (> 0xFFFFFFFF)",
438 return_ACPI_STATUS(AE_SUPPORT
);
441 info
->field_bit_position
+= info
->field_bit_length
;
442 info
->pin_number_index
++; /* Index relative to previous Connection() */
448 "Invalid opcode in field list: 0x%X",
449 arg
->common
.aml_opcode
));
450 return_ACPI_STATUS(AE_AML_BAD_OPCODE
);
453 arg
= arg
->common
.next
;
456 return_ACPI_STATUS(AE_OK
);
459 /*******************************************************************************
461 * FUNCTION: acpi_ds_create_field
463 * PARAMETERS: op - Op containing the Field definition and args
464 * region_node - Object for the containing Operation Region
465 * ` walk_state - Current method state
469 * DESCRIPTION: Create a new field in the specified operation region
471 ******************************************************************************/
474 acpi_ds_create_field(union acpi_parse_object
*op
,
475 struct acpi_namespace_node
*region_node
,
476 struct acpi_walk_state
*walk_state
)
479 union acpi_parse_object
*arg
;
480 struct acpi_create_field_info info
;
482 ACPI_FUNCTION_TRACE_PTR(ds_create_field
, op
);
484 /* First arg is the name of the parent op_region (must already exist) */
486 arg
= op
->common
.value
.arg
;
490 acpi_ns_lookup(walk_state
->scope_info
,
491 arg
->common
.value
.name
, ACPI_TYPE_REGION
,
492 ACPI_IMODE_EXECUTE
, ACPI_NS_SEARCH_PARENT
,
493 walk_state
, ®ion_node
);
494 #ifdef ACPI_ASL_COMPILER
495 status
= acpi_ds_create_external_region(status
, arg
,
496 arg
->common
.value
.name
,
500 if (ACPI_FAILURE(status
)) {
501 ACPI_ERROR_NAMESPACE(walk_state
->scope_info
,
502 arg
->common
.value
.name
, status
);
503 return_ACPI_STATUS(status
);
507 memset(&info
, 0, sizeof(struct acpi_create_field_info
));
509 /* Second arg is the field flags */
511 arg
= arg
->common
.next
;
512 info
.field_flags
= (u8
) arg
->common
.value
.integer
;
515 /* Each remaining arg is a Named Field */
517 info
.field_type
= ACPI_TYPE_LOCAL_REGION_FIELD
;
518 info
.region_node
= region_node
;
520 status
= acpi_ds_get_field_names(&info
, walk_state
, arg
->common
.next
);
521 if (info
.region_node
->object
->region
.space_id
==
522 ACPI_ADR_SPACE_PLATFORM_COMM
523 && !(region_node
->object
->field
.internal_pcc_buffer
=
524 ACPI_ALLOCATE_ZEROED(info
.region_node
->object
->region
.
526 return_ACPI_STATUS(AE_NO_MEMORY
);
528 return_ACPI_STATUS(status
);
531 /*******************************************************************************
533 * FUNCTION: acpi_ds_init_field_objects
535 * PARAMETERS: op - Op containing the Field definition and args
536 * ` walk_state - Current method state
540 * DESCRIPTION: For each "Field Unit" name in the argument list that is
541 * part of the field declaration, enter the name into the
544 ******************************************************************************/
547 acpi_ds_init_field_objects(union acpi_parse_object
*op
,
548 struct acpi_walk_state
*walk_state
)
551 union acpi_parse_object
*arg
= NULL
;
552 struct acpi_namespace_node
*node
;
556 ACPI_FUNCTION_TRACE_PTR(ds_init_field_objects
, op
);
558 /* Execute flag should always be set when this function is entered */
560 if (!(walk_state
->parse_flags
& ACPI_PARSE_EXECUTE
)) {
561 if (walk_state
->parse_flags
& ACPI_PARSE_DEFERRED_OP
) {
563 /* bank_field Op is deferred, just return OK */
565 return_ACPI_STATUS(AE_OK
);
568 ACPI_ERROR((AE_INFO
, "Parse deferred mode is not set"));
569 return_ACPI_STATUS(AE_AML_INTERNAL
);
573 * Get the field_list argument for this opcode. This is the start of the
574 * list of field elements.
576 switch (walk_state
->opcode
) {
579 arg
= acpi_ps_get_arg(op
, 2);
580 type
= ACPI_TYPE_LOCAL_REGION_FIELD
;
583 case AML_BANK_FIELD_OP
:
585 arg
= acpi_ps_get_arg(op
, 4);
586 type
= ACPI_TYPE_LOCAL_BANK_FIELD
;
589 case AML_INDEX_FIELD_OP
:
591 arg
= acpi_ps_get_arg(op
, 3);
592 type
= ACPI_TYPE_LOCAL_INDEX_FIELD
;
597 return_ACPI_STATUS(AE_BAD_PARAMETER
);
600 /* Creating new namespace node(s), should not already exist */
602 flags
= ACPI_NS_NO_UPSEARCH
| ACPI_NS_DONT_OPEN_SCOPE
|
603 ACPI_NS_ERROR_IF_FOUND
;
606 * Mark node(s) temporary if we are executing a normal control
607 * method. (Don't mark if this is a module-level code method)
609 if (walk_state
->method_node
&&
610 !(walk_state
->parse_flags
& ACPI_PARSE_MODULE_LEVEL
)) {
611 flags
|= ACPI_NS_TEMPORARY
;
614 flags
|= ACPI_NS_OVERRIDE_IF_FOUND
;
617 * Walk the list of entries in the field_list
618 * Note: field_list can be of zero length. In this case, Arg will be NULL.
622 * Ignore OFFSET/ACCESSAS/CONNECTION terms here; we are only interested
623 * in the field names in order to enter them into the namespace.
625 if (arg
->common
.aml_opcode
== AML_INT_NAMEDFIELD_OP
) {
626 status
= acpi_ns_lookup(walk_state
->scope_info
,
627 (char *)&arg
->named
.name
, type
,
628 ACPI_IMODE_LOAD_PASS1
, flags
,
630 if (ACPI_FAILURE(status
)) {
631 ACPI_ERROR_NAMESPACE(walk_state
->scope_info
,
632 (char *)&arg
->named
.name
,
634 if (status
!= AE_ALREADY_EXISTS
) {
635 return_ACPI_STATUS(status
);
638 /* Name already exists, just ignore this error */
643 arg
->common
.node
= node
;
646 /* Get the next field element in the list */
648 arg
= arg
->common
.next
;
651 return_ACPI_STATUS(AE_OK
);
654 /*******************************************************************************
656 * FUNCTION: acpi_ds_create_bank_field
658 * PARAMETERS: op - Op containing the Field definition and args
659 * region_node - Object for the containing Operation Region
660 * walk_state - Current method state
664 * DESCRIPTION: Create a new bank field in the specified operation region
666 ******************************************************************************/
669 acpi_ds_create_bank_field(union acpi_parse_object
*op
,
670 struct acpi_namespace_node
*region_node
,
671 struct acpi_walk_state
*walk_state
)
674 union acpi_parse_object
*arg
;
675 struct acpi_create_field_info info
;
677 ACPI_FUNCTION_TRACE_PTR(ds_create_bank_field
, op
);
679 /* First arg is the name of the parent op_region (must already exist) */
681 arg
= op
->common
.value
.arg
;
684 acpi_ns_lookup(walk_state
->scope_info
,
685 arg
->common
.value
.name
, ACPI_TYPE_REGION
,
686 ACPI_IMODE_EXECUTE
, ACPI_NS_SEARCH_PARENT
,
687 walk_state
, ®ion_node
);
688 #ifdef ACPI_ASL_COMPILER
689 status
= acpi_ds_create_external_region(status
, arg
,
690 arg
->common
.value
.name
,
694 if (ACPI_FAILURE(status
)) {
695 ACPI_ERROR_NAMESPACE(walk_state
->scope_info
,
696 arg
->common
.value
.name
, status
);
697 return_ACPI_STATUS(status
);
701 /* Second arg is the Bank Register (Field) (must already exist) */
703 arg
= arg
->common
.next
;
705 acpi_ns_lookup(walk_state
->scope_info
, arg
->common
.value
.string
,
706 ACPI_TYPE_ANY
, ACPI_IMODE_EXECUTE
,
707 ACPI_NS_SEARCH_PARENT
, walk_state
,
708 &info
.register_node
);
709 if (ACPI_FAILURE(status
)) {
710 ACPI_ERROR_NAMESPACE(walk_state
->scope_info
,
711 arg
->common
.value
.string
, status
);
712 return_ACPI_STATUS(status
);
716 * Third arg is the bank_value
717 * This arg is a term_arg, not a constant
718 * It will be evaluated later, by acpi_ds_eval_bank_field_operands
720 arg
= arg
->common
.next
;
722 /* Fourth arg is the field flags */
724 arg
= arg
->common
.next
;
725 info
.field_flags
= (u8
) arg
->common
.value
.integer
;
727 /* Each remaining arg is a Named Field */
729 info
.field_type
= ACPI_TYPE_LOCAL_BANK_FIELD
;
730 info
.region_node
= region_node
;
733 * Use Info.data_register_node to store bank_field Op
734 * It's safe because data_register_node will never be used when create
735 * bank field \we store aml_start and aml_length in the bank_field Op for
736 * late evaluation. Used in acpi_ex_prep_field_value(Info)
738 * TBD: Or, should we add a field in struct acpi_create_field_info, like
741 info
.data_register_node
= (struct acpi_namespace_node
*)op
;
743 status
= acpi_ds_get_field_names(&info
, walk_state
, arg
->common
.next
);
744 return_ACPI_STATUS(status
);
747 /*******************************************************************************
749 * FUNCTION: acpi_ds_create_index_field
751 * PARAMETERS: op - Op containing the Field definition and args
752 * region_node - Object for the containing Operation Region
753 * ` walk_state - Current method state
757 * DESCRIPTION: Create a new index field in the specified operation region
759 ******************************************************************************/
762 acpi_ds_create_index_field(union acpi_parse_object
*op
,
763 struct acpi_namespace_node
*region_node
,
764 struct acpi_walk_state
*walk_state
)
767 union acpi_parse_object
*arg
;
768 struct acpi_create_field_info info
;
770 ACPI_FUNCTION_TRACE_PTR(ds_create_index_field
, op
);
772 /* First arg is the name of the Index register (must already exist) */
774 arg
= op
->common
.value
.arg
;
776 acpi_ns_lookup(walk_state
->scope_info
, arg
->common
.value
.string
,
777 ACPI_TYPE_ANY
, ACPI_IMODE_EXECUTE
,
778 ACPI_NS_SEARCH_PARENT
, walk_state
,
779 &info
.register_node
);
780 if (ACPI_FAILURE(status
)) {
781 ACPI_ERROR_NAMESPACE(walk_state
->scope_info
,
782 arg
->common
.value
.string
, status
);
783 return_ACPI_STATUS(status
);
786 /* Second arg is the data register (must already exist) */
788 arg
= arg
->common
.next
;
790 acpi_ns_lookup(walk_state
->scope_info
, arg
->common
.value
.string
,
791 ACPI_TYPE_ANY
, ACPI_IMODE_EXECUTE
,
792 ACPI_NS_SEARCH_PARENT
, walk_state
,
793 &info
.data_register_node
);
794 if (ACPI_FAILURE(status
)) {
795 ACPI_ERROR_NAMESPACE(walk_state
->scope_info
,
796 arg
->common
.value
.string
, status
);
797 return_ACPI_STATUS(status
);
800 /* Next arg is the field flags */
802 arg
= arg
->common
.next
;
803 info
.field_flags
= (u8
) arg
->common
.value
.integer
;
805 /* Each remaining arg is a Named Field */
807 info
.field_type
= ACPI_TYPE_LOCAL_INDEX_FIELD
;
808 info
.region_node
= region_node
;
810 status
= acpi_ds_get_field_names(&info
, walk_state
, arg
->common
.next
);
811 return_ACPI_STATUS(status
);