1 | /****************************************************************************** |
2 | * |
3 | * Module Name: dsfield - Dispatcher field routines |
4 | * |
5 | *****************************************************************************/ |
6 | |
7 | /* |
8 | * Copyright (C) 2000 - 2016, Intel Corp. |
9 | * All rights reserved. |
10 | * |
11 | * Redistribution and use in source and binary forms, with or without |
12 | * modification, are permitted provided that the following conditions |
13 | * are met: |
14 | * 1. Redistributions of source code must retain the above copyright |
15 | * notice, this list of conditions, and the following disclaimer, |
16 | * without modification. |
17 | * 2. Redistributions in binary form must reproduce at minimum a disclaimer |
18 | * substantially similar to the "NO WARRANTY" disclaimer below |
19 | * ("Disclaimer") and any redistribution must be conditioned upon |
20 | * including a substantially similar Disclaimer requirement for further |
21 | * binary redistribution. |
22 | * 3. Neither the names of the above-listed copyright holders nor the names |
23 | * of any contributors may be used to endorse or promote products derived |
24 | * from this software without specific prior written permission. |
25 | * |
26 | * Alternatively, this software may be distributed under the terms of the |
27 | * GNU General Public License ("GPL") version 2 as published by the Free |
28 | * Software Foundation. |
29 | * |
30 | * NO WARRANTY |
31 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
32 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
33 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR |
34 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
35 | * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
36 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
37 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
38 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, |
39 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING |
40 | * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
41 | * POSSIBILITY OF SUCH DAMAGES. |
42 | */ |
43 | |
44 | #include "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 | |
53 | #define _COMPONENT ACPI_DISPATCHER |
54 | ACPI_MODULE_NAME ("dsfield" ) |
55 | |
56 | /* Local prototypes */ |
57 | |
58 | #ifdef ACPI_ASL_COMPILER |
59 | #include "acdisasm.h" |
60 | |
61 | static ACPI_STATUS |
62 | AcpiDsCreateExternalRegion ( |
63 | ACPI_STATUS LookupStatus, |
64 | ACPI_PARSE_OBJECT *Op, |
65 | char *Path, |
66 | ACPI_WALK_STATE *WalkState, |
67 | ACPI_NAMESPACE_NODE **Node); |
68 | #endif |
69 | |
70 | static ACPI_STATUS |
71 | AcpiDsGetFieldNames ( |
72 | ACPI_CREATE_FIELD_INFO *Info, |
73 | ACPI_WALK_STATE *WalkState, |
74 | ACPI_PARSE_OBJECT *Arg); |
75 | |
76 | |
77 | #ifdef ACPI_ASL_COMPILER |
78 | /******************************************************************************* |
79 | * |
80 | * FUNCTION: AcpiDsCreateExternalRegion (iASL Disassembler only) |
81 | * |
82 | * PARAMETERS: LookupStatus - Status from NsLookup operation |
83 | * Op - Op containing the Field definition and args |
84 | * Path - Pathname of the region |
85 | * ` WalkState - Current method state |
86 | * Node - Where the new region node is returned |
87 | * |
88 | * RETURN: Status |
89 | * |
90 | * DESCRIPTION: Add region to the external list if NOT_FOUND. Create a new |
91 | * region node/object. |
92 | * |
93 | ******************************************************************************/ |
94 | |
95 | static ACPI_STATUS |
96 | AcpiDsCreateExternalRegion ( |
97 | ACPI_STATUS LookupStatus, |
98 | ACPI_PARSE_OBJECT *Op, |
99 | char *Path, |
100 | ACPI_WALK_STATE *WalkState, |
101 | ACPI_NAMESPACE_NODE **Node) |
102 | { |
103 | ACPI_STATUS Status; |
104 | ACPI_OPERAND_OBJECT *ObjDesc; |
105 | |
106 | |
107 | if (LookupStatus != AE_NOT_FOUND) |
108 | { |
109 | return (LookupStatus); |
110 | } |
111 | |
112 | /* |
113 | * Table disassembly: |
114 | * OperationRegion not found. Generate an External for it, and |
115 | * insert the name into the namespace. |
116 | */ |
117 | AcpiDmAddOpToExternalList (Op, Path, ACPI_TYPE_REGION, 0, 0); |
118 | |
119 | Status = AcpiNsLookup (WalkState->ScopeInfo, Path, ACPI_TYPE_REGION, |
120 | ACPI_IMODE_LOAD_PASS1, ACPI_NS_SEARCH_PARENT, WalkState, Node); |
121 | if (ACPI_FAILURE (Status)) |
122 | { |
123 | return (Status); |
124 | } |
125 | |
126 | /* Must create and install a region object for the new node */ |
127 | |
128 | ObjDesc = AcpiUtCreateInternalObject (ACPI_TYPE_REGION); |
129 | if (!ObjDesc) |
130 | { |
131 | return (AE_NO_MEMORY); |
132 | } |
133 | |
134 | ObjDesc->Region.Node = *Node; |
135 | Status = AcpiNsAttachObject (*Node, ObjDesc, ACPI_TYPE_REGION); |
136 | return (Status); |
137 | } |
138 | #endif |
139 | |
140 | |
141 | /******************************************************************************* |
142 | * |
143 | * FUNCTION: AcpiDsCreateBufferField |
144 | * |
145 | * PARAMETERS: Op - Current parse op (CreateXXField) |
146 | * WalkState - Current state |
147 | * |
148 | * RETURN: Status |
149 | * |
150 | * DESCRIPTION: Execute the CreateField operators: |
151 | * CreateBitFieldOp, |
152 | * CreateByteFieldOp, |
153 | * CreateWordFieldOp, |
154 | * CreateDwordFieldOp, |
155 | * CreateQwordFieldOp, |
156 | * CreateFieldOp (all of which define a field in a buffer) |
157 | * |
158 | ******************************************************************************/ |
159 | |
160 | ACPI_STATUS |
161 | AcpiDsCreateBufferField ( |
162 | ACPI_PARSE_OBJECT *Op, |
163 | ACPI_WALK_STATE *WalkState) |
164 | { |
165 | ACPI_PARSE_OBJECT *Arg; |
166 | ACPI_NAMESPACE_NODE *Node; |
167 | ACPI_STATUS Status; |
168 | ACPI_OPERAND_OBJECT *ObjDesc; |
169 | ACPI_OPERAND_OBJECT *SecondDesc = NULL; |
170 | UINT32 Flags; |
171 | |
172 | |
173 | ACPI_FUNCTION_TRACE (DsCreateBufferField); |
174 | |
175 | |
176 | /* |
177 | * Get the NameString argument (name of the new BufferField) |
178 | */ |
179 | if (Op->Common.AmlOpcode == AML_CREATE_FIELD_OP) |
180 | { |
181 | /* For CreateField, name is the 4th argument */ |
182 | |
183 | Arg = AcpiPsGetArg (Op, 3); |
184 | } |
185 | else |
186 | { |
187 | /* For all other CreateXXXField operators, name is the 3rd argument */ |
188 | |
189 | Arg = AcpiPsGetArg (Op, 2); |
190 | } |
191 | |
192 | if (!Arg) |
193 | { |
194 | return_ACPI_STATUS (AE_AML_NO_OPERAND); |
195 | } |
196 | |
197 | if (WalkState->DeferredNode) |
198 | { |
199 | Node = WalkState->DeferredNode; |
200 | Status = AE_OK; |
201 | } |
202 | else |
203 | { |
204 | /* Execute flag should always be set when this function is entered */ |
205 | |
206 | if (!(WalkState->ParseFlags & ACPI_PARSE_EXECUTE)) |
207 | { |
208 | return_ACPI_STATUS (AE_AML_INTERNAL); |
209 | } |
210 | |
211 | /* Creating new namespace node, should not already exist */ |
212 | |
213 | Flags = ACPI_NS_NO_UPSEARCH | ACPI_NS_DONT_OPEN_SCOPE | |
214 | ACPI_NS_ERROR_IF_FOUND; |
215 | |
216 | /* |
217 | * Mark node temporary if we are executing a normal control |
218 | * method. (Don't mark if this is a module-level code method) |
219 | */ |
220 | if (WalkState->MethodNode && |
221 | !(WalkState->ParseFlags & ACPI_PARSE_MODULE_LEVEL)) |
222 | { |
223 | Flags |= ACPI_NS_TEMPORARY; |
224 | } |
225 | |
226 | /* Enter the NameString into the namespace */ |
227 | |
228 | Status = AcpiNsLookup (WalkState->ScopeInfo, |
229 | Arg->Common.Value.String, ACPI_TYPE_ANY, |
230 | ACPI_IMODE_LOAD_PASS1, Flags, WalkState, &Node); |
231 | if (ACPI_FAILURE (Status)) |
232 | { |
233 | ACPI_ERROR_NAMESPACE (Arg->Common.Value.String, Status); |
234 | return_ACPI_STATUS (Status); |
235 | } |
236 | } |
237 | |
238 | /* |
239 | * We could put the returned object (Node) on the object stack for later, |
240 | * but for now, we will put it in the "op" object that the parser uses, |
241 | * so we can get it again at the end of this scope. |
242 | */ |
243 | Op->Common.Node = Node; |
244 | |
245 | /* |
246 | * If there is no object attached to the node, this node was just created |
247 | * and we need to create the field object. Otherwise, this was a lookup |
248 | * of an existing node and we don't want to create the field object again. |
249 | */ |
250 | ObjDesc = AcpiNsGetAttachedObject (Node); |
251 | if (ObjDesc) |
252 | { |
253 | return_ACPI_STATUS (AE_OK); |
254 | } |
255 | |
256 | /* |
257 | * The Field definition is not fully parsed at this time. |
258 | * (We must save the address of the AML for the buffer and index operands) |
259 | */ |
260 | |
261 | /* Create the buffer field object */ |
262 | |
263 | ObjDesc = AcpiUtCreateInternalObject (ACPI_TYPE_BUFFER_FIELD); |
264 | if (!ObjDesc) |
265 | { |
266 | Status = AE_NO_MEMORY; |
267 | goto Cleanup; |
268 | } |
269 | |
270 | /* |
271 | * Remember location in AML stream of the field unit opcode and operands |
272 | * -- since the buffer and index operands must be evaluated. |
273 | */ |
274 | SecondDesc = ObjDesc->Common.NextObject; |
275 | SecondDesc->Extra.AmlStart = Op->Named.Data; |
276 | SecondDesc->Extra.AmlLength = Op->Named.Length; |
277 | ObjDesc->BufferField.Node = Node; |
278 | |
279 | /* Attach constructed field descriptors to parent node */ |
280 | |
281 | Status = AcpiNsAttachObject (Node, ObjDesc, ACPI_TYPE_BUFFER_FIELD); |
282 | if (ACPI_FAILURE (Status)) |
283 | { |
284 | goto Cleanup; |
285 | } |
286 | |
287 | |
288 | Cleanup: |
289 | |
290 | /* Remove local reference to the object */ |
291 | |
292 | AcpiUtRemoveReference (ObjDesc); |
293 | return_ACPI_STATUS (Status); |
294 | } |
295 | |
296 | |
297 | /******************************************************************************* |
298 | * |
299 | * FUNCTION: AcpiDsGetFieldNames |
300 | * |
301 | * PARAMETERS: Info - CreateField info structure |
302 | * ` WalkState - Current method state |
303 | * Arg - First parser arg for the field name list |
304 | * |
305 | * RETURN: Status |
306 | * |
307 | * DESCRIPTION: Process all named fields in a field declaration. Names are |
308 | * entered into the namespace. |
309 | * |
310 | ******************************************************************************/ |
311 | |
312 | static ACPI_STATUS |
313 | AcpiDsGetFieldNames ( |
314 | ACPI_CREATE_FIELD_INFO *Info, |
315 | ACPI_WALK_STATE *WalkState, |
316 | ACPI_PARSE_OBJECT *Arg) |
317 | { |
318 | ACPI_STATUS Status; |
319 | UINT64 Position; |
320 | ACPI_PARSE_OBJECT *Child; |
321 | |
322 | |
323 | ACPI_FUNCTION_TRACE_PTR (DsGetFieldNames, Info); |
324 | |
325 | |
326 | /* First field starts at bit zero */ |
327 | |
328 | Info->FieldBitPosition = 0; |
329 | |
330 | /* Process all elements in the field list (of parse nodes) */ |
331 | |
332 | while (Arg) |
333 | { |
334 | /* |
335 | * Four types of field elements are handled: |
336 | * 1) Name - Enters a new named field into the namespace |
337 | * 2) Offset - specifies a bit offset |
338 | * 3) AccessAs - changes the access mode/attributes |
339 | * 4) Connection - Associate a resource template with the field |
340 | */ |
341 | switch (Arg->Common.AmlOpcode) |
342 | { |
343 | case AML_INT_RESERVEDFIELD_OP: |
344 | |
345 | Position = (UINT64) Info->FieldBitPosition + |
346 | (UINT64) Arg->Common.Value.Size; |
347 | |
348 | if (Position > ACPI_UINT32_MAX) |
349 | { |
350 | ACPI_ERROR ((AE_INFO, |
351 | "Bit offset within field too large (> 0xFFFFFFFF)" )); |
352 | return_ACPI_STATUS (AE_SUPPORT); |
353 | } |
354 | |
355 | Info->FieldBitPosition = (UINT32) Position; |
356 | break; |
357 | |
358 | case AML_INT_ACCESSFIELD_OP: |
359 | case AML_INT_EXTACCESSFIELD_OP: |
360 | /* |
361 | * Get new AccessType, AccessAttribute, and AccessLength fields |
362 | * -- to be used for all field units that follow, until the |
363 | * end-of-field or another AccessAs keyword is encountered. |
364 | * NOTE. These three bytes are encoded in the integer value |
365 | * of the parseop for convenience. |
366 | * |
367 | * In FieldFlags, preserve the flag bits other than the |
368 | * ACCESS_TYPE bits. |
369 | */ |
370 | |
371 | /* AccessType (ByteAcc, WordAcc, etc.) */ |
372 | |
373 | Info->FieldFlags = (UINT8) |
374 | ((Info->FieldFlags & ~(AML_FIELD_ACCESS_TYPE_MASK)) | |
375 | ((UINT8) ((UINT32) (Arg->Common.Value.Integer & 0x07)))); |
376 | |
377 | /* AccessAttribute (AttribQuick, AttribByte, etc.) */ |
378 | |
379 | Info->Attribute = (UINT8) |
380 | ((Arg->Common.Value.Integer >> 8) & 0xFF); |
381 | |
382 | /* AccessLength (for serial/buffer protocols) */ |
383 | |
384 | Info->AccessLength = (UINT8) |
385 | ((Arg->Common.Value.Integer >> 16) & 0xFF); |
386 | break; |
387 | |
388 | case AML_INT_CONNECTION_OP: |
389 | /* |
390 | * Clear any previous connection. New connection is used for all |
391 | * fields that follow, similar to AccessAs |
392 | */ |
393 | Info->ResourceBuffer = NULL; |
394 | Info->ConnectionNode = NULL; |
395 | Info->PinNumberIndex = 0; |
396 | |
397 | /* |
398 | * A Connection() is either an actual resource descriptor (buffer) |
399 | * or a named reference to a resource template |
400 | */ |
401 | Child = Arg->Common.Value.Arg; |
402 | if (Child->Common.AmlOpcode == AML_INT_BYTELIST_OP) |
403 | { |
404 | Info->ResourceBuffer = Child->Named.Data; |
405 | Info->ResourceLength = (UINT16) Child->Named.Value.Integer; |
406 | } |
407 | else |
408 | { |
409 | /* Lookup the Connection() namepath, it should already exist */ |
410 | |
411 | Status = AcpiNsLookup (WalkState->ScopeInfo, |
412 | Child->Common.Value.Name, ACPI_TYPE_ANY, |
413 | ACPI_IMODE_EXECUTE, ACPI_NS_DONT_OPEN_SCOPE, |
414 | WalkState, &Info->ConnectionNode); |
415 | if (ACPI_FAILURE (Status)) |
416 | { |
417 | ACPI_ERROR_NAMESPACE (Child->Common.Value.Name, Status); |
418 | return_ACPI_STATUS (Status); |
419 | } |
420 | } |
421 | break; |
422 | |
423 | case AML_INT_NAMEDFIELD_OP: |
424 | |
425 | /* Lookup the name, it should already exist */ |
426 | |
427 | Status = AcpiNsLookup (WalkState->ScopeInfo, |
428 | (char *) &Arg->Named.Name, Info->FieldType, |
429 | ACPI_IMODE_EXECUTE, ACPI_NS_DONT_OPEN_SCOPE, |
430 | WalkState, &Info->FieldNode); |
431 | if (ACPI_FAILURE (Status)) |
432 | { |
433 | ACPI_ERROR_NAMESPACE ((char *) &Arg->Named.Name, Status); |
434 | return_ACPI_STATUS (Status); |
435 | } |
436 | else |
437 | { |
438 | Arg->Common.Node = Info->FieldNode; |
439 | Info->FieldBitLength = Arg->Common.Value.Size; |
440 | |
441 | /* |
442 | * If there is no object attached to the node, this node was |
443 | * just created and we need to create the field object. |
444 | * Otherwise, this was a lookup of an existing node and we |
445 | * don't want to create the field object again. |
446 | */ |
447 | if (!AcpiNsGetAttachedObject (Info->FieldNode)) |
448 | { |
449 | Status = AcpiExPrepFieldValue (Info); |
450 | if (ACPI_FAILURE (Status)) |
451 | { |
452 | return_ACPI_STATUS (Status); |
453 | } |
454 | } |
455 | } |
456 | |
457 | /* Keep track of bit position for the next field */ |
458 | |
459 | Position = (UINT64) Info->FieldBitPosition + |
460 | (UINT64) Arg->Common.Value.Size; |
461 | |
462 | if (Position > ACPI_UINT32_MAX) |
463 | { |
464 | ACPI_ERROR ((AE_INFO, |
465 | "Field [%4.4s] bit offset too large (> 0xFFFFFFFF)" , |
466 | ACPI_CAST_PTR (char, &Info->FieldNode->Name))); |
467 | return_ACPI_STATUS (AE_SUPPORT); |
468 | } |
469 | |
470 | Info->FieldBitPosition += Info->FieldBitLength; |
471 | Info->PinNumberIndex++; /* Index relative to previous Connection() */ |
472 | break; |
473 | |
474 | default: |
475 | |
476 | ACPI_ERROR ((AE_INFO, |
477 | "Invalid opcode in field list: 0x%X" , |
478 | Arg->Common.AmlOpcode)); |
479 | return_ACPI_STATUS (AE_AML_BAD_OPCODE); |
480 | } |
481 | |
482 | Arg = Arg->Common.Next; |
483 | } |
484 | |
485 | return_ACPI_STATUS (AE_OK); |
486 | } |
487 | |
488 | |
489 | /******************************************************************************* |
490 | * |
491 | * FUNCTION: AcpiDsCreateField |
492 | * |
493 | * PARAMETERS: Op - Op containing the Field definition and args |
494 | * RegionNode - Object for the containing Operation Region |
495 | * ` WalkState - Current method state |
496 | * |
497 | * RETURN: Status |
498 | * |
499 | * DESCRIPTION: Create a new field in the specified operation region |
500 | * |
501 | ******************************************************************************/ |
502 | |
503 | ACPI_STATUS |
504 | AcpiDsCreateField ( |
505 | ACPI_PARSE_OBJECT *Op, |
506 | ACPI_NAMESPACE_NODE *RegionNode, |
507 | ACPI_WALK_STATE *WalkState) |
508 | { |
509 | ACPI_STATUS Status; |
510 | ACPI_PARSE_OBJECT *Arg; |
511 | ACPI_CREATE_FIELD_INFO Info; |
512 | |
513 | |
514 | ACPI_FUNCTION_TRACE_PTR (DsCreateField, Op); |
515 | |
516 | |
517 | /* First arg is the name of the parent OpRegion (must already exist) */ |
518 | |
519 | Arg = Op->Common.Value.Arg; |
520 | |
521 | if (!RegionNode) |
522 | { |
523 | Status = AcpiNsLookup (WalkState->ScopeInfo, Arg->Common.Value.Name, |
524 | ACPI_TYPE_REGION, ACPI_IMODE_EXECUTE, |
525 | ACPI_NS_SEARCH_PARENT, WalkState, &RegionNode); |
526 | #ifdef ACPI_ASL_COMPILER |
527 | Status = AcpiDsCreateExternalRegion (Status, Arg, |
528 | Arg->Common.Value.Name, WalkState, &RegionNode); |
529 | #endif |
530 | if (ACPI_FAILURE (Status)) |
531 | { |
532 | ACPI_ERROR_NAMESPACE (Arg->Common.Value.Name, Status); |
533 | return_ACPI_STATUS (Status); |
534 | } |
535 | } |
536 | |
537 | memset (&Info, 0, sizeof (ACPI_CREATE_FIELD_INFO)); |
538 | |
539 | /* Second arg is the field flags */ |
540 | |
541 | Arg = Arg->Common.Next; |
542 | Info.FieldFlags = (UINT8) Arg->Common.Value.Integer; |
543 | Info.Attribute = 0; |
544 | |
545 | /* Each remaining arg is a Named Field */ |
546 | |
547 | Info.FieldType = ACPI_TYPE_LOCAL_REGION_FIELD; |
548 | Info.RegionNode = RegionNode; |
549 | |
550 | Status = AcpiDsGetFieldNames (&Info, WalkState, Arg->Common.Next); |
551 | return_ACPI_STATUS (Status); |
552 | } |
553 | |
554 | |
555 | /******************************************************************************* |
556 | * |
557 | * FUNCTION: AcpiDsInitFieldObjects |
558 | * |
559 | * PARAMETERS: Op - Op containing the Field definition and args |
560 | * ` WalkState - Current method state |
561 | * |
562 | * RETURN: Status |
563 | * |
564 | * DESCRIPTION: For each "Field Unit" name in the argument list that is |
565 | * part of the field declaration, enter the name into the |
566 | * namespace. |
567 | * |
568 | ******************************************************************************/ |
569 | |
570 | ACPI_STATUS |
571 | AcpiDsInitFieldObjects ( |
572 | ACPI_PARSE_OBJECT *Op, |
573 | ACPI_WALK_STATE *WalkState) |
574 | { |
575 | ACPI_STATUS Status; |
576 | ACPI_PARSE_OBJECT *Arg = NULL; |
577 | ACPI_NAMESPACE_NODE *Node; |
578 | UINT8 Type = 0; |
579 | UINT32 Flags; |
580 | |
581 | |
582 | ACPI_FUNCTION_TRACE_PTR (DsInitFieldObjects, Op); |
583 | |
584 | |
585 | /* Execute flag should always be set when this function is entered */ |
586 | |
587 | if (!(WalkState->ParseFlags & ACPI_PARSE_EXECUTE)) |
588 | { |
589 | if (WalkState->ParseFlags & ACPI_PARSE_DEFERRED_OP) |
590 | { |
591 | /* BankField Op is deferred, just return OK */ |
592 | |
593 | return_ACPI_STATUS (AE_OK); |
594 | } |
595 | |
596 | return_ACPI_STATUS (AE_AML_INTERNAL); |
597 | } |
598 | |
599 | /* |
600 | * Get the FieldList argument for this opcode. This is the start of the |
601 | * list of field elements. |
602 | */ |
603 | switch (WalkState->Opcode) |
604 | { |
605 | case AML_FIELD_OP: |
606 | |
607 | Arg = AcpiPsGetArg (Op, 2); |
608 | Type = ACPI_TYPE_LOCAL_REGION_FIELD; |
609 | break; |
610 | |
611 | case AML_BANK_FIELD_OP: |
612 | |
613 | Arg = AcpiPsGetArg (Op, 4); |
614 | Type = ACPI_TYPE_LOCAL_BANK_FIELD; |
615 | break; |
616 | |
617 | case AML_INDEX_FIELD_OP: |
618 | |
619 | Arg = AcpiPsGetArg (Op, 3); |
620 | Type = ACPI_TYPE_LOCAL_INDEX_FIELD; |
621 | break; |
622 | |
623 | default: |
624 | |
625 | return_ACPI_STATUS (AE_BAD_PARAMETER); |
626 | } |
627 | |
628 | /* Creating new namespace node(s), should not already exist */ |
629 | |
630 | Flags = ACPI_NS_NO_UPSEARCH | ACPI_NS_DONT_OPEN_SCOPE | |
631 | ACPI_NS_ERROR_IF_FOUND; |
632 | |
633 | /* |
634 | * Mark node(s) temporary if we are executing a normal control |
635 | * method. (Don't mark if this is a module-level code method) |
636 | */ |
637 | if (WalkState->MethodNode && |
638 | !(WalkState->ParseFlags & ACPI_PARSE_MODULE_LEVEL)) |
639 | { |
640 | Flags |= ACPI_NS_TEMPORARY; |
641 | } |
642 | |
643 | /* |
644 | * Walk the list of entries in the FieldList |
645 | * Note: FieldList can be of zero length. In this case, Arg will be NULL. |
646 | */ |
647 | while (Arg) |
648 | { |
649 | /* |
650 | * Ignore OFFSET/ACCESSAS/CONNECTION terms here; we are only interested |
651 | * in the field names in order to enter them into the namespace. |
652 | */ |
653 | if (Arg->Common.AmlOpcode == AML_INT_NAMEDFIELD_OP) |
654 | { |
655 | Status = AcpiNsLookup (WalkState->ScopeInfo, |
656 | (char *) &Arg->Named.Name, Type, ACPI_IMODE_LOAD_PASS1, |
657 | Flags, WalkState, &Node); |
658 | if (ACPI_FAILURE (Status)) |
659 | { |
660 | ACPI_ERROR_NAMESPACE ((char *) &Arg->Named.Name, Status); |
661 | if (Status != AE_ALREADY_EXISTS) |
662 | { |
663 | return_ACPI_STATUS (Status); |
664 | } |
665 | |
666 | /* Name already exists, just ignore this error */ |
667 | |
668 | Status = AE_OK; |
669 | } |
670 | |
671 | Arg->Common.Node = Node; |
672 | } |
673 | |
674 | /* Get the next field element in the list */ |
675 | |
676 | Arg = Arg->Common.Next; |
677 | } |
678 | |
679 | return_ACPI_STATUS (AE_OK); |
680 | } |
681 | |
682 | |
683 | /******************************************************************************* |
684 | * |
685 | * FUNCTION: AcpiDsCreateBankField |
686 | * |
687 | * PARAMETERS: Op - Op containing the Field definition and args |
688 | * RegionNode - Object for the containing Operation Region |
689 | * WalkState - Current method state |
690 | * |
691 | * RETURN: Status |
692 | * |
693 | * DESCRIPTION: Create a new bank field in the specified operation region |
694 | * |
695 | ******************************************************************************/ |
696 | |
697 | ACPI_STATUS |
698 | AcpiDsCreateBankField ( |
699 | ACPI_PARSE_OBJECT *Op, |
700 | ACPI_NAMESPACE_NODE *RegionNode, |
701 | ACPI_WALK_STATE *WalkState) |
702 | { |
703 | ACPI_STATUS Status; |
704 | ACPI_PARSE_OBJECT *Arg; |
705 | ACPI_CREATE_FIELD_INFO Info; |
706 | |
707 | |
708 | ACPI_FUNCTION_TRACE_PTR (DsCreateBankField, Op); |
709 | |
710 | |
711 | /* First arg is the name of the parent OpRegion (must already exist) */ |
712 | |
713 | Arg = Op->Common.Value.Arg; |
714 | if (!RegionNode) |
715 | { |
716 | Status = AcpiNsLookup (WalkState->ScopeInfo, Arg->Common.Value.Name, |
717 | ACPI_TYPE_REGION, ACPI_IMODE_EXECUTE, |
718 | ACPI_NS_SEARCH_PARENT, WalkState, &RegionNode); |
719 | #ifdef ACPI_ASL_COMPILER |
720 | Status = AcpiDsCreateExternalRegion (Status, Arg, |
721 | Arg->Common.Value.Name, WalkState, &RegionNode); |
722 | #endif |
723 | if (ACPI_FAILURE (Status)) |
724 | { |
725 | ACPI_ERROR_NAMESPACE (Arg->Common.Value.Name, Status); |
726 | return_ACPI_STATUS (Status); |
727 | } |
728 | } |
729 | |
730 | /* Second arg is the Bank Register (Field) (must already exist) */ |
731 | |
732 | Arg = Arg->Common.Next; |
733 | Status = AcpiNsLookup (WalkState->ScopeInfo, Arg->Common.Value.String, |
734 | ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE, |
735 | ACPI_NS_SEARCH_PARENT, WalkState, &Info.RegisterNode); |
736 | if (ACPI_FAILURE (Status)) |
737 | { |
738 | ACPI_ERROR_NAMESPACE (Arg->Common.Value.String, Status); |
739 | return_ACPI_STATUS (Status); |
740 | } |
741 | |
742 | /* |
743 | * Third arg is the BankValue |
744 | * This arg is a TermArg, not a constant |
745 | * It will be evaluated later, by AcpiDsEvalBankFieldOperands |
746 | */ |
747 | Arg = Arg->Common.Next; |
748 | |
749 | /* Fourth arg is the field flags */ |
750 | |
751 | Arg = Arg->Common.Next; |
752 | Info.FieldFlags = (UINT8) Arg->Common.Value.Integer; |
753 | |
754 | /* Each remaining arg is a Named Field */ |
755 | |
756 | Info.FieldType = ACPI_TYPE_LOCAL_BANK_FIELD; |
757 | Info.RegionNode = RegionNode; |
758 | |
759 | /* |
760 | * Use Info.DataRegisterNode to store BankField Op |
761 | * It's safe because DataRegisterNode will never be used when create |
762 | * bank field \we store AmlStart and AmlLength in the BankField Op for |
763 | * late evaluation. Used in AcpiExPrepFieldValue(Info) |
764 | * |
765 | * TBD: Or, should we add a field in ACPI_CREATE_FIELD_INFO, like |
766 | * "void *ParentOp"? |
767 | */ |
768 | Info.DataRegisterNode = (ACPI_NAMESPACE_NODE*) Op; |
769 | |
770 | Status = AcpiDsGetFieldNames (&Info, WalkState, Arg->Common.Next); |
771 | return_ACPI_STATUS (Status); |
772 | } |
773 | |
774 | |
775 | /******************************************************************************* |
776 | * |
777 | * FUNCTION: AcpiDsCreateIndexField |
778 | * |
779 | * PARAMETERS: Op - Op containing the Field definition and args |
780 | * RegionNode - Object for the containing Operation Region |
781 | * ` WalkState - Current method state |
782 | * |
783 | * RETURN: Status |
784 | * |
785 | * DESCRIPTION: Create a new index field in the specified operation region |
786 | * |
787 | ******************************************************************************/ |
788 | |
789 | ACPI_STATUS |
790 | AcpiDsCreateIndexField ( |
791 | ACPI_PARSE_OBJECT *Op, |
792 | ACPI_NAMESPACE_NODE *RegionNode, |
793 | ACPI_WALK_STATE *WalkState) |
794 | { |
795 | ACPI_STATUS Status; |
796 | ACPI_PARSE_OBJECT *Arg; |
797 | ACPI_CREATE_FIELD_INFO Info; |
798 | |
799 | |
800 | ACPI_FUNCTION_TRACE_PTR (DsCreateIndexField, Op); |
801 | |
802 | |
803 | /* First arg is the name of the Index register (must already exist) */ |
804 | |
805 | Arg = Op->Common.Value.Arg; |
806 | Status = AcpiNsLookup (WalkState->ScopeInfo, Arg->Common.Value.String, |
807 | ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE, |
808 | ACPI_NS_SEARCH_PARENT, WalkState, &Info.RegisterNode); |
809 | if (ACPI_FAILURE (Status)) |
810 | { |
811 | ACPI_ERROR_NAMESPACE (Arg->Common.Value.String, Status); |
812 | return_ACPI_STATUS (Status); |
813 | } |
814 | |
815 | /* Second arg is the data register (must already exist) */ |
816 | |
817 | Arg = Arg->Common.Next; |
818 | Status = AcpiNsLookup (WalkState->ScopeInfo, Arg->Common.Value.String, |
819 | ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE, |
820 | ACPI_NS_SEARCH_PARENT, WalkState, &Info.DataRegisterNode); |
821 | if (ACPI_FAILURE (Status)) |
822 | { |
823 | ACPI_ERROR_NAMESPACE (Arg->Common.Value.String, Status); |
824 | return_ACPI_STATUS (Status); |
825 | } |
826 | |
827 | /* Next arg is the field flags */ |
828 | |
829 | Arg = Arg->Common.Next; |
830 | Info.FieldFlags = (UINT8) Arg->Common.Value.Integer; |
831 | |
832 | /* Each remaining arg is a Named Field */ |
833 | |
834 | Info.FieldType = ACPI_TYPE_LOCAL_INDEX_FIELD; |
835 | Info.RegionNode = RegionNode; |
836 | |
837 | Status = AcpiDsGetFieldNames (&Info, WalkState, Arg->Common.Next); |
838 | return_ACPI_STATUS (Status); |
839 | } |
840 | |