1 | // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 |
2 | /****************************************************************************** |
3 | * |
4 | * Module Name: dsfield - Dispatcher field routines |
5 | * |
6 | * Copyright (C) 2000 - 2023, Intel Corp. |
7 | * |
8 | *****************************************************************************/ |
9 | |
10 | #include <acpi/acpi.h> |
11 | #include "accommon.h" |
12 | #include "amlcode.h" |
13 | #include "acdispat.h" |
14 | #include "acinterp.h" |
15 | #include "acnamesp.h" |
16 | #include "acparser.h" |
17 | |
18 | #ifdef ACPI_EXEC_APP |
19 | #include "aecommon.h" |
20 | #endif |
21 | |
22 | #define _COMPONENT ACPI_DISPATCHER |
23 | ACPI_MODULE_NAME("dsfield" ) |
24 | |
25 | /* Local prototypes */ |
26 | #ifdef ACPI_ASL_COMPILER |
27 | #include "acdisasm.h" |
28 | static acpi_status |
29 | acpi_ds_create_external_region(acpi_status lookup_status, |
30 | union acpi_parse_object *op, |
31 | char *path, |
32 | struct acpi_walk_state *walk_state, |
33 | struct acpi_namespace_node **node); |
34 | #endif |
35 | |
36 | static acpi_status |
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); |
40 | |
41 | #ifdef ACPI_ASL_COMPILER |
42 | /******************************************************************************* |
43 | * |
44 | * FUNCTION: acpi_ds_create_external_region (iASL Disassembler only) |
45 | * |
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 |
51 | * |
52 | * RETURN: Status |
53 | * |
54 | * DESCRIPTION: Add region to the external list if NOT_FOUND. Create a new |
55 | * region node/object. |
56 | * |
57 | ******************************************************************************/ |
58 | |
59 | static acpi_status |
60 | acpi_ds_create_external_region(acpi_status lookup_status, |
61 | union acpi_parse_object *op, |
62 | char *path, |
63 | struct acpi_walk_state *walk_state, |
64 | struct acpi_namespace_node **node) |
65 | { |
66 | acpi_status status; |
67 | union acpi_operand_object *obj_desc; |
68 | |
69 | if (lookup_status != AE_NOT_FOUND) { |
70 | return (lookup_status); |
71 | } |
72 | |
73 | /* |
74 | * Table disassembly: |
75 | * operation_region not found. Generate an External for it, and |
76 | * insert the name into the namespace. |
77 | */ |
78 | acpi_dm_add_op_to_external_list(op, path, ACPI_TYPE_REGION, 0, 0); |
79 | |
80 | status = acpi_ns_lookup(walk_state->scope_info, path, ACPI_TYPE_REGION, |
81 | ACPI_IMODE_LOAD_PASS1, ACPI_NS_SEARCH_PARENT, |
82 | walk_state, node); |
83 | if (ACPI_FAILURE(status)) { |
84 | return (status); |
85 | } |
86 | |
87 | /* Must create and install a region object for the new node */ |
88 | |
89 | obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_REGION); |
90 | if (!obj_desc) { |
91 | return (AE_NO_MEMORY); |
92 | } |
93 | |
94 | obj_desc->region.node = *node; |
95 | status = acpi_ns_attach_object(*node, obj_desc, ACPI_TYPE_REGION); |
96 | return (status); |
97 | } |
98 | #endif |
99 | |
100 | /******************************************************************************* |
101 | * |
102 | * FUNCTION: acpi_ds_create_buffer_field |
103 | * |
104 | * PARAMETERS: op - Current parse op (create_XXField) |
105 | * walk_state - Current state |
106 | * |
107 | * RETURN: Status |
108 | * |
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) |
116 | * |
117 | ******************************************************************************/ |
118 | |
119 | acpi_status |
120 | acpi_ds_create_buffer_field(union acpi_parse_object *op, |
121 | struct acpi_walk_state *walk_state) |
122 | { |
123 | union acpi_parse_object *arg; |
124 | struct acpi_namespace_node *node; |
125 | acpi_status status; |
126 | union acpi_operand_object *obj_desc; |
127 | union acpi_operand_object *second_desc = NULL; |
128 | u32 flags; |
129 | |
130 | ACPI_FUNCTION_TRACE(ds_create_buffer_field); |
131 | |
132 | /* |
133 | * Get the name_string argument (name of the new buffer_field) |
134 | */ |
135 | if (op->common.aml_opcode == AML_CREATE_FIELD_OP) { |
136 | |
137 | /* For create_field, name is the 4th argument */ |
138 | |
139 | arg = acpi_ps_get_arg(op, argn: 3); |
140 | } else { |
141 | /* For all other create_XXXField operators, name is the 3rd argument */ |
142 | |
143 | arg = acpi_ps_get_arg(op, argn: 2); |
144 | } |
145 | |
146 | if (!arg) { |
147 | return_ACPI_STATUS(AE_AML_NO_OPERAND); |
148 | } |
149 | |
150 | if (walk_state->deferred_node) { |
151 | node = walk_state->deferred_node; |
152 | } else { |
153 | /* Execute flag should always be set when this function is entered */ |
154 | |
155 | if (!(walk_state->parse_flags & ACPI_PARSE_EXECUTE)) { |
156 | ACPI_ERROR((AE_INFO, "Parse execute mode is not set" )); |
157 | return_ACPI_STATUS(AE_AML_INTERNAL); |
158 | } |
159 | |
160 | /* Creating new namespace node, should not already exist */ |
161 | |
162 | flags = ACPI_NS_NO_UPSEARCH | ACPI_NS_DONT_OPEN_SCOPE | |
163 | ACPI_NS_ERROR_IF_FOUND; |
164 | |
165 | /* |
166 | * Mark node temporary if we are executing a normal control |
167 | * method. (Don't mark if this is a module-level code method) |
168 | */ |
169 | if (walk_state->method_node && |
170 | !(walk_state->parse_flags & ACPI_PARSE_MODULE_LEVEL)) { |
171 | flags |= ACPI_NS_TEMPORARY; |
172 | } |
173 | |
174 | /* Enter the name_string into the namespace */ |
175 | |
176 | status = acpi_ns_lookup(scope_info: walk_state->scope_info, |
177 | name: arg->common.value.string, ACPI_TYPE_ANY, |
178 | interpreter_mode: ACPI_IMODE_LOAD_PASS1, flags, |
179 | walk_state, ret_node: &node); |
180 | if ((walk_state->parse_flags & ACPI_PARSE_DISASSEMBLE) |
181 | && status == AE_ALREADY_EXISTS) { |
182 | status = AE_OK; |
183 | } else if (ACPI_FAILURE(status)) { |
184 | ACPI_ERROR_NAMESPACE(walk_state->scope_info, |
185 | arg->common.value.string, status); |
186 | return_ACPI_STATUS(status); |
187 | } |
188 | } |
189 | |
190 | /* |
191 | * We could put the returned object (Node) on the object stack for later, |
192 | * but for now, we will put it in the "op" object that the parser uses, |
193 | * so we can get it again at the end of this scope. |
194 | */ |
195 | op->common.node = node; |
196 | |
197 | /* |
198 | * If there is no object attached to the node, this node was just created |
199 | * and we need to create the field object. Otherwise, this was a lookup |
200 | * of an existing node and we don't want to create the field object again. |
201 | */ |
202 | obj_desc = acpi_ns_get_attached_object(node); |
203 | if (obj_desc) { |
204 | return_ACPI_STATUS(AE_OK); |
205 | } |
206 | |
207 | /* |
208 | * The Field definition is not fully parsed at this time. |
209 | * (We must save the address of the AML for the buffer and index operands) |
210 | */ |
211 | |
212 | /* Create the buffer field object */ |
213 | |
214 | obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_BUFFER_FIELD); |
215 | if (!obj_desc) { |
216 | status = AE_NO_MEMORY; |
217 | goto cleanup; |
218 | } |
219 | |
220 | /* |
221 | * Remember location in AML stream of the field unit opcode and operands |
222 | * -- since the buffer and index operands must be evaluated. |
223 | */ |
224 | second_desc = obj_desc->common.next_object; |
225 | second_desc->extra.aml_start = op->named.data; |
226 | second_desc->extra.aml_length = op->named.length; |
227 | obj_desc->buffer_field.node = node; |
228 | |
229 | /* Attach constructed field descriptors to parent node */ |
230 | |
231 | status = acpi_ns_attach_object(node, object: obj_desc, ACPI_TYPE_BUFFER_FIELD); |
232 | if (ACPI_FAILURE(status)) { |
233 | goto cleanup; |
234 | } |
235 | |
236 | cleanup: |
237 | |
238 | /* Remove local reference to the object */ |
239 | |
240 | acpi_ut_remove_reference(object: obj_desc); |
241 | return_ACPI_STATUS(status); |
242 | } |
243 | |
244 | /******************************************************************************* |
245 | * |
246 | * FUNCTION: acpi_ds_get_field_names |
247 | * |
248 | * PARAMETERS: info - create_field info structure |
249 | * walk_state - Current method state |
250 | * arg - First parser arg for the field name list |
251 | * |
252 | * RETURN: Status |
253 | * |
254 | * DESCRIPTION: Process all named fields in a field declaration. Names are |
255 | * entered into the namespace. |
256 | * |
257 | ******************************************************************************/ |
258 | |
259 | static acpi_status |
260 | acpi_ds_get_field_names(struct acpi_create_field_info *info, |
261 | struct acpi_walk_state *walk_state, |
262 | union acpi_parse_object *arg) |
263 | { |
264 | acpi_status status; |
265 | u64 position; |
266 | union acpi_parse_object *child; |
267 | |
268 | #ifdef ACPI_EXEC_APP |
269 | union acpi_operand_object *result_desc; |
270 | union acpi_operand_object *obj_desc; |
271 | char *name_path; |
272 | #endif |
273 | |
274 | ACPI_FUNCTION_TRACE_PTR(ds_get_field_names, info); |
275 | |
276 | /* First field starts at bit zero */ |
277 | |
278 | info->field_bit_position = 0; |
279 | |
280 | /* Process all elements in the field list (of parse nodes) */ |
281 | |
282 | while (arg) { |
283 | /* |
284 | * Four types of field elements are handled: |
285 | * 1) name - Enters a new named field into the namespace |
286 | * 2) offset - specifies a bit offset |
287 | * 3) access_as - changes the access mode/attributes |
288 | * 4) connection - Associate a resource template with the field |
289 | */ |
290 | switch (arg->common.aml_opcode) { |
291 | case AML_INT_RESERVEDFIELD_OP: |
292 | |
293 | position = (u64)info->field_bit_position + |
294 | (u64)arg->common.value.size; |
295 | |
296 | if (position > ACPI_UINT32_MAX) { |
297 | ACPI_ERROR((AE_INFO, |
298 | "Bit offset within field too large (> 0xFFFFFFFF)" )); |
299 | return_ACPI_STATUS(AE_SUPPORT); |
300 | } |
301 | |
302 | info->field_bit_position = (u32) position; |
303 | break; |
304 | |
305 | case AML_INT_ACCESSFIELD_OP: |
306 | case AML_INT_EXTACCESSFIELD_OP: |
307 | /* |
308 | * Get new access_type, access_attribute, and access_length fields |
309 | * -- to be used for all field units that follow, until the |
310 | * end-of-field or another access_as keyword is encountered. |
311 | * NOTE. These three bytes are encoded in the integer value |
312 | * of the parseop for convenience. |
313 | * |
314 | * In field_flags, preserve the flag bits other than the |
315 | * ACCESS_TYPE bits. |
316 | */ |
317 | |
318 | /* access_type (byte_acc, word_acc, etc.) */ |
319 | |
320 | info->field_flags = (u8) |
321 | ((info-> |
322 | field_flags & ~(AML_FIELD_ACCESS_TYPE_MASK)) | |
323 | ((u8)((u32)(arg->common.value.integer & 0x07)))); |
324 | |
325 | /* access_attribute (attrib_quick, attrib_byte, etc.) */ |
326 | |
327 | info->attribute = (u8) |
328 | ((arg->common.value.integer >> 8) & 0xFF); |
329 | |
330 | /* access_length (for serial/buffer protocols) */ |
331 | |
332 | info->access_length = (u8) |
333 | ((arg->common.value.integer >> 16) & 0xFF); |
334 | break; |
335 | |
336 | case AML_INT_CONNECTION_OP: |
337 | /* |
338 | * Clear any previous connection. New connection is used for all |
339 | * fields that follow, similar to access_as |
340 | */ |
341 | info->resource_buffer = NULL; |
342 | info->connection_node = NULL; |
343 | info->pin_number_index = 0; |
344 | |
345 | /* |
346 | * A Connection() is either an actual resource descriptor (buffer) |
347 | * or a named reference to a resource template |
348 | */ |
349 | child = arg->common.value.arg; |
350 | if (child->common.aml_opcode == AML_INT_BYTELIST_OP) { |
351 | info->resource_buffer = child->named.data; |
352 | info->resource_length = |
353 | (u16)child->named.value.integer; |
354 | } else { |
355 | /* Lookup the Connection() namepath, it should already exist */ |
356 | |
357 | status = acpi_ns_lookup(scope_info: walk_state->scope_info, |
358 | name: child->common.value. |
359 | name, ACPI_TYPE_ANY, |
360 | interpreter_mode: ACPI_IMODE_EXECUTE, |
361 | ACPI_NS_DONT_OPEN_SCOPE, |
362 | walk_state, |
363 | ret_node: &info->connection_node); |
364 | if (ACPI_FAILURE(status)) { |
365 | ACPI_ERROR_NAMESPACE(walk_state-> |
366 | scope_info, |
367 | child->common. |
368 | value.name, |
369 | status); |
370 | return_ACPI_STATUS(status); |
371 | } |
372 | } |
373 | break; |
374 | |
375 | case AML_INT_NAMEDFIELD_OP: |
376 | |
377 | /* Lookup the name, it should already exist */ |
378 | |
379 | status = acpi_ns_lookup(scope_info: walk_state->scope_info, |
380 | name: (char *)&arg->named.name, |
381 | type: info->field_type, |
382 | interpreter_mode: ACPI_IMODE_EXECUTE, |
383 | ACPI_NS_DONT_OPEN_SCOPE, |
384 | walk_state, ret_node: &info->field_node); |
385 | if (ACPI_FAILURE(status)) { |
386 | ACPI_ERROR_NAMESPACE(walk_state->scope_info, |
387 | (char *)&arg->named.name, |
388 | status); |
389 | return_ACPI_STATUS(status); |
390 | } else { |
391 | arg->common.node = info->field_node; |
392 | info->field_bit_length = arg->common.value.size; |
393 | |
394 | /* |
395 | * If there is no object attached to the node, this node was |
396 | * just created and we need to create the field object. |
397 | * Otherwise, this was a lookup of an existing node and we |
398 | * don't want to create the field object again. |
399 | */ |
400 | if (!acpi_ns_get_attached_object |
401 | (node: info->field_node)) { |
402 | status = acpi_ex_prep_field_value(info); |
403 | if (ACPI_FAILURE(status)) { |
404 | return_ACPI_STATUS(status); |
405 | } |
406 | #ifdef ACPI_EXEC_APP |
407 | name_path = |
408 | acpi_ns_get_external_pathname(info-> |
409 | field_node); |
410 | if (ACPI_SUCCESS |
411 | (ae_lookup_init_file_entry |
412 | (name_path, &obj_desc))) { |
413 | acpi_ex_write_data_to_field |
414 | (obj_desc, |
415 | acpi_ns_get_attached_object |
416 | (info->field_node), |
417 | &result_desc); |
418 | acpi_ut_remove_reference |
419 | (obj_desc); |
420 | } |
421 | ACPI_FREE(name_path); |
422 | #endif |
423 | } |
424 | } |
425 | |
426 | /* Keep track of bit position for the next field */ |
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++; /* Index relative to previous Connection() */ |
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 | * FUNCTION: acpi_ds_create_field |
461 | * |
462 | * PARAMETERS: op - Op containing the Field definition and args |
463 | * region_node - Object for the containing Operation Region |
464 | * ` walk_state - Current method state |
465 | * |
466 | * RETURN: Status |
467 | * |
468 | * DESCRIPTION: Create a new field in the specified operation region |
469 | * |
470 | ******************************************************************************/ |
471 | |
472 | acpi_status |
473 | acpi_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 | /* First arg is the name of the parent op_region (must already exist) */ |
484 | |
485 | arg = op->common.value.arg; |
486 | |
487 | if (!region_node) { |
488 | status = |
489 | acpi_ns_lookup(scope_info: walk_state->scope_info, |
490 | name: arg->common.value.name, ACPI_TYPE_REGION, |
491 | interpreter_mode: ACPI_IMODE_EXECUTE, ACPI_NS_SEARCH_PARENT, |
492 | walk_state, ret_node: ®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(walk_state->scope_info, |
501 | arg->common.value.name, status); |
502 | return_ACPI_STATUS(status); |
503 | } |
504 | } |
505 | |
506 | memset(&info, 0, sizeof(struct acpi_create_field_info)); |
507 | |
508 | /* Second arg is the field flags */ |
509 | |
510 | arg = arg->common.next; |
511 | info.field_flags = (u8) arg->common.value.integer; |
512 | info.attribute = 0; |
513 | |
514 | /* Each remaining arg is a Named Field */ |
515 | |
516 | info.field_type = ACPI_TYPE_LOCAL_REGION_FIELD; |
517 | info.region_node = region_node; |
518 | |
519 | status = acpi_ds_get_field_names(info: &info, walk_state, arg: arg->common.next); |
520 | if (ACPI_FAILURE(status)) { |
521 | return_ACPI_STATUS(status); |
522 | } |
523 | |
524 | if (info.region_node->object->region.space_id == |
525 | ACPI_ADR_SPACE_PLATFORM_COMM) { |
526 | region_node->object->field.internal_pcc_buffer = |
527 | ACPI_ALLOCATE_ZEROED(info.region_node->object->region. |
528 | length); |
529 | if (!region_node->object->field.internal_pcc_buffer) { |
530 | return_ACPI_STATUS(AE_NO_MEMORY); |
531 | } |
532 | } |
533 | |
534 | return_ACPI_STATUS(status); |
535 | } |
536 | |
537 | /******************************************************************************* |
538 | * |
539 | * FUNCTION: acpi_ds_init_field_objects |
540 | * |
541 | * PARAMETERS: op - Op containing the Field definition and args |
542 | * ` walk_state - Current method state |
543 | * |
544 | * RETURN: Status |
545 | * |
546 | * DESCRIPTION: For each "Field Unit" name in the argument list that is |
547 | * part of the field declaration, enter the name into the |
548 | * namespace. |
549 | * |
550 | ******************************************************************************/ |
551 | |
552 | acpi_status |
553 | acpi_ds_init_field_objects(union acpi_parse_object *op, |
554 | struct acpi_walk_state *walk_state) |
555 | { |
556 | acpi_status status; |
557 | union acpi_parse_object *arg = NULL; |
558 | struct acpi_namespace_node *node; |
559 | u8 type = 0; |
560 | u32 flags; |
561 | |
562 | ACPI_FUNCTION_TRACE_PTR(ds_init_field_objects, op); |
563 | |
564 | /* Execute flag should always be set when this function is entered */ |
565 | |
566 | if (!(walk_state->parse_flags & ACPI_PARSE_EXECUTE)) { |
567 | if (walk_state->parse_flags & ACPI_PARSE_DEFERRED_OP) { |
568 | |
569 | /* bank_field Op is deferred, just return OK */ |
570 | |
571 | return_ACPI_STATUS(AE_OK); |
572 | } |
573 | |
574 | ACPI_ERROR((AE_INFO, "Parse deferred mode is not set" )); |
575 | return_ACPI_STATUS(AE_AML_INTERNAL); |
576 | } |
577 | |
578 | /* |
579 | * Get the field_list argument for this opcode. This is the start of the |
580 | * list of field elements. |
581 | */ |
582 | switch (walk_state->opcode) { |
583 | case AML_FIELD_OP: |
584 | |
585 | arg = acpi_ps_get_arg(op, argn: 2); |
586 | type = ACPI_TYPE_LOCAL_REGION_FIELD; |
587 | break; |
588 | |
589 | case AML_BANK_FIELD_OP: |
590 | |
591 | arg = acpi_ps_get_arg(op, argn: 4); |
592 | type = ACPI_TYPE_LOCAL_BANK_FIELD; |
593 | break; |
594 | |
595 | case AML_INDEX_FIELD_OP: |
596 | |
597 | arg = acpi_ps_get_arg(op, argn: 3); |
598 | type = ACPI_TYPE_LOCAL_INDEX_FIELD; |
599 | break; |
600 | |
601 | default: |
602 | |
603 | return_ACPI_STATUS(AE_BAD_PARAMETER); |
604 | } |
605 | |
606 | /* Creating new namespace node(s), should not already exist */ |
607 | |
608 | flags = ACPI_NS_NO_UPSEARCH | ACPI_NS_DONT_OPEN_SCOPE | |
609 | ACPI_NS_ERROR_IF_FOUND; |
610 | |
611 | /* |
612 | * Mark node(s) temporary if we are executing a normal control |
613 | * method. (Don't mark if this is a module-level code method) |
614 | */ |
615 | if (walk_state->method_node && |
616 | !(walk_state->parse_flags & ACPI_PARSE_MODULE_LEVEL)) { |
617 | flags |= ACPI_NS_TEMPORARY; |
618 | } |
619 | #ifdef ACPI_EXEC_APP |
620 | flags |= ACPI_NS_OVERRIDE_IF_FOUND; |
621 | #endif |
622 | /* |
623 | * Walk the list of entries in the field_list |
624 | * Note: field_list can be of zero length. In this case, Arg will be NULL. |
625 | */ |
626 | while (arg) { |
627 | /* |
628 | * Ignore OFFSET/ACCESSAS/CONNECTION terms here; we are only interested |
629 | * in the field names in order to enter them into the namespace. |
630 | */ |
631 | if (arg->common.aml_opcode == AML_INT_NAMEDFIELD_OP) { |
632 | status = acpi_ns_lookup(scope_info: walk_state->scope_info, |
633 | name: (char *)&arg->named.name, type, |
634 | interpreter_mode: ACPI_IMODE_LOAD_PASS1, flags, |
635 | walk_state, ret_node: &node); |
636 | if (ACPI_FAILURE(status)) { |
637 | ACPI_ERROR_NAMESPACE(walk_state->scope_info, |
638 | (char *)&arg->named.name, |
639 | status); |
640 | if (status != AE_ALREADY_EXISTS) { |
641 | return_ACPI_STATUS(status); |
642 | } |
643 | |
644 | /* Name already exists, just ignore this error */ |
645 | } |
646 | |
647 | arg->common.node = node; |
648 | } |
649 | |
650 | /* Get the next field element in the list */ |
651 | |
652 | arg = arg->common.next; |
653 | } |
654 | |
655 | return_ACPI_STATUS(AE_OK); |
656 | } |
657 | |
658 | /******************************************************************************* |
659 | * |
660 | * FUNCTION: acpi_ds_create_bank_field |
661 | * |
662 | * PARAMETERS: op - Op containing the Field definition and args |
663 | * region_node - Object for the containing Operation Region |
664 | * walk_state - Current method state |
665 | * |
666 | * RETURN: Status |
667 | * |
668 | * DESCRIPTION: Create a new bank field in the specified operation region |
669 | * |
670 | ******************************************************************************/ |
671 | |
672 | acpi_status |
673 | acpi_ds_create_bank_field(union acpi_parse_object *op, |
674 | struct acpi_namespace_node *region_node, |
675 | struct acpi_walk_state *walk_state) |
676 | { |
677 | acpi_status status; |
678 | union acpi_parse_object *arg; |
679 | struct acpi_create_field_info info; |
680 | |
681 | ACPI_FUNCTION_TRACE_PTR(ds_create_bank_field, op); |
682 | |
683 | /* First arg is the name of the parent op_region (must already exist) */ |
684 | |
685 | arg = op->common.value.arg; |
686 | if (!region_node) { |
687 | status = |
688 | acpi_ns_lookup(scope_info: walk_state->scope_info, |
689 | name: arg->common.value.name, ACPI_TYPE_REGION, |
690 | interpreter_mode: ACPI_IMODE_EXECUTE, ACPI_NS_SEARCH_PARENT, |
691 | walk_state, ret_node: ®ion_node); |
692 | #ifdef ACPI_ASL_COMPILER |
693 | status = acpi_ds_create_external_region(status, arg, |
694 | arg->common.value.name, |
695 | walk_state, |
696 | ®ion_node); |
697 | #endif |
698 | if (ACPI_FAILURE(status)) { |
699 | ACPI_ERROR_NAMESPACE(walk_state->scope_info, |
700 | arg->common.value.name, status); |
701 | return_ACPI_STATUS(status); |
702 | } |
703 | } |
704 | |
705 | /* Second arg is the Bank Register (Field) (must already exist) */ |
706 | |
707 | arg = arg->common.next; |
708 | status = |
709 | acpi_ns_lookup(scope_info: walk_state->scope_info, name: arg->common.value.string, |
710 | ACPI_TYPE_ANY, interpreter_mode: ACPI_IMODE_EXECUTE, |
711 | ACPI_NS_SEARCH_PARENT, walk_state, |
712 | ret_node: &info.register_node); |
713 | if (ACPI_FAILURE(status)) { |
714 | ACPI_ERROR_NAMESPACE(walk_state->scope_info, |
715 | arg->common.value.string, status); |
716 | return_ACPI_STATUS(status); |
717 | } |
718 | |
719 | /* |
720 | * Third arg is the bank_value |
721 | * This arg is a term_arg, not a constant |
722 | * It will be evaluated later, by acpi_ds_eval_bank_field_operands |
723 | */ |
724 | arg = arg->common.next; |
725 | |
726 | /* Fourth arg is the field flags */ |
727 | |
728 | arg = arg->common.next; |
729 | info.field_flags = (u8) arg->common.value.integer; |
730 | |
731 | /* Each remaining arg is a Named Field */ |
732 | |
733 | info.field_type = ACPI_TYPE_LOCAL_BANK_FIELD; |
734 | info.region_node = region_node; |
735 | |
736 | /* |
737 | * Use Info.data_register_node to store bank_field Op |
738 | * It's safe because data_register_node will never be used when create |
739 | * bank field \we store aml_start and aml_length in the bank_field Op for |
740 | * late evaluation. Used in acpi_ex_prep_field_value(Info) |
741 | * |
742 | * TBD: Or, should we add a field in struct acpi_create_field_info, like |
743 | * "void *ParentOp"? |
744 | */ |
745 | info.data_register_node = (struct acpi_namespace_node *)op; |
746 | |
747 | status = acpi_ds_get_field_names(info: &info, walk_state, arg: arg->common.next); |
748 | return_ACPI_STATUS(status); |
749 | } |
750 | |
751 | /******************************************************************************* |
752 | * |
753 | * FUNCTION: acpi_ds_create_index_field |
754 | * |
755 | * PARAMETERS: op - Op containing the Field definition and args |
756 | * region_node - Object for the containing Operation Region |
757 | * ` walk_state - Current method state |
758 | * |
759 | * RETURN: Status |
760 | * |
761 | * DESCRIPTION: Create a new index field in the specified operation region |
762 | * |
763 | ******************************************************************************/ |
764 | |
765 | acpi_status |
766 | acpi_ds_create_index_field(union acpi_parse_object *op, |
767 | struct acpi_namespace_node *region_node, |
768 | struct acpi_walk_state *walk_state) |
769 | { |
770 | acpi_status status; |
771 | union acpi_parse_object *arg; |
772 | struct acpi_create_field_info info; |
773 | |
774 | ACPI_FUNCTION_TRACE_PTR(ds_create_index_field, op); |
775 | |
776 | /* First arg is the name of the Index register (must already exist) */ |
777 | |
778 | arg = op->common.value.arg; |
779 | status = |
780 | acpi_ns_lookup(scope_info: walk_state->scope_info, name: arg->common.value.string, |
781 | ACPI_TYPE_ANY, interpreter_mode: ACPI_IMODE_EXECUTE, |
782 | ACPI_NS_SEARCH_PARENT, walk_state, |
783 | ret_node: &info.register_node); |
784 | if (ACPI_FAILURE(status)) { |
785 | ACPI_ERROR_NAMESPACE(walk_state->scope_info, |
786 | arg->common.value.string, status); |
787 | return_ACPI_STATUS(status); |
788 | } |
789 | |
790 | /* Second arg is the data register (must already exist) */ |
791 | |
792 | arg = arg->common.next; |
793 | status = |
794 | acpi_ns_lookup(scope_info: walk_state->scope_info, name: arg->common.value.string, |
795 | ACPI_TYPE_ANY, interpreter_mode: ACPI_IMODE_EXECUTE, |
796 | ACPI_NS_SEARCH_PARENT, walk_state, |
797 | ret_node: &info.data_register_node); |
798 | if (ACPI_FAILURE(status)) { |
799 | ACPI_ERROR_NAMESPACE(walk_state->scope_info, |
800 | arg->common.value.string, status); |
801 | return_ACPI_STATUS(status); |
802 | } |
803 | |
804 | /* Next arg is the field flags */ |
805 | |
806 | arg = arg->common.next; |
807 | info.field_flags = (u8) arg->common.value.integer; |
808 | |
809 | /* Each remaining arg is a Named Field */ |
810 | |
811 | info.field_type = ACPI_TYPE_LOCAL_INDEX_FIELD; |
812 | info.region_node = region_node; |
813 | |
814 | status = acpi_ds_get_field_names(info: &info, walk_state, arg: arg->common.next); |
815 | return_ACPI_STATUS(status); |
816 | } |
817 | |