xref: /illumos-gate/usr/src/common/acpica/dispatcher/dsfield.c (revision aa693e996c2928c92cccd8a3efe91373e85a6967)
1 /******************************************************************************
2  *
3  * Module Name: dsfield - Dispatcher field routines
4  *
5  *****************************************************************************/
6 
7 /******************************************************************************
8  *
9  * 1. Copyright Notice
10  *
11  * Some or all of this work - Copyright (c) 1999 - 2018, Intel Corp.
12  * All rights reserved.
13  *
14  * 2. License
15  *
16  * 2.1. This is your license from Intel Corp. under its intellectual property
17  * rights. You may have additional license terms from the party that provided
18  * you this software, covering your right to use that party's intellectual
19  * property rights.
20  *
21  * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
22  * copy of the source code appearing in this file ("Covered Code") an
23  * irrevocable, perpetual, worldwide license under Intel's copyrights in the
24  * base code distributed originally by Intel ("Original Intel Code") to copy,
25  * make derivatives, distribute, use and display any portion of the Covered
26  * Code in any form, with the right to sublicense such rights; and
27  *
28  * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
29  * license (with the right to sublicense), under only those claims of Intel
30  * patents that are infringed by the Original Intel Code, to make, use, sell,
31  * offer to sell, and import the Covered Code and derivative works thereof
32  * solely to the minimum extent necessary to exercise the above copyright
33  * license, and in no event shall the patent license extend to any additions
34  * to or modifications of the Original Intel Code. No other license or right
35  * is granted directly or by implication, estoppel or otherwise;
36  *
37  * The above copyright and patent license is granted only if the following
38  * conditions are met:
39  *
40  * 3. Conditions
41  *
42  * 3.1. Redistribution of Source with Rights to Further Distribute Source.
43  * Redistribution of source code of any substantial portion of the Covered
44  * Code or modification with rights to further distribute source must include
45  * the above Copyright Notice, the above License, this list of Conditions,
46  * and the following Disclaimer and Export Compliance provision. In addition,
47  * Licensee must cause all Covered Code to which Licensee contributes to
48  * contain a file documenting the changes Licensee made to create that Covered
49  * Code and the date of any change. Licensee must include in that file the
50  * documentation of any changes made by any predecessor Licensee. Licensee
51  * must include a prominent statement that the modification is derived,
52  * directly or indirectly, from Original Intel Code.
53  *
54  * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
55  * Redistribution of source code of any substantial portion of the Covered
56  * Code or modification without rights to further distribute source must
57  * include the following Disclaimer and Export Compliance provision in the
58  * documentation and/or other materials provided with distribution. In
59  * addition, Licensee may not authorize further sublicense of source of any
60  * portion of the Covered Code, and must include terms to the effect that the
61  * license from Licensee to its licensee is limited to the intellectual
62  * property embodied in the software Licensee provides to its licensee, and
63  * not to intellectual property embodied in modifications its licensee may
64  * make.
65  *
66  * 3.3. Redistribution of Executable. Redistribution in executable form of any
67  * substantial portion of the Covered Code or modification must reproduce the
68  * above Copyright Notice, and the following Disclaimer and Export Compliance
69  * provision in the documentation and/or other materials provided with the
70  * distribution.
71  *
72  * 3.4. Intel retains all right, title, and interest in and to the Original
73  * Intel Code.
74  *
75  * 3.5. Neither the name Intel nor any other trademark owned or controlled by
76  * Intel shall be used in advertising or otherwise to promote the sale, use or
77  * other dealings in products derived from or relating to the Covered Code
78  * without prior written authorization from Intel.
79  *
80  * 4. Disclaimer and Export Compliance
81  *
82  * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
83  * HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
84  * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE,
85  * INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY
86  * UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY
87  * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
88  * PARTICULAR PURPOSE.
89  *
90  * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
91  * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
92  * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
93  * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
94  * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
95  * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS
96  * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
97  * LIMITED REMEDY.
98  *
99  * 4.3. Licensee shall not export, either directly or indirectly, any of this
100  * software or system incorporating such software without first obtaining any
101  * required license or other approval from the U. S. Department of Commerce or
102  * any other agency or department of the United States Government. In the
103  * event Licensee exports any such software from the United States or
104  * re-exports any such software from a foreign destination, Licensee shall
105  * ensure that the distribution and export/re-export of the software is in
106  * compliance with all laws, regulations, orders, or other restrictions of the
107  * U.S. Export Administration Regulations. Licensee agrees that neither it nor
108  * any of its subsidiaries will export/re-export any technical data, process,
109  * software, or service, directly or indirectly, to any country for which the
110  * United States government or any agency thereof requires an export license,
111  * other governmental approval, or letter of assurance, without first obtaining
112  * such license, approval or letter.
113  *
114  *****************************************************************************
115  *
116  * Alternatively, you may choose to be licensed under the terms of the
117  * following license:
118  *
119  * Redistribution and use in source and binary forms, with or without
120  * modification, are permitted provided that the following conditions
121  * are met:
122  * 1. Redistributions of source code must retain the above copyright
123  *    notice, this list of conditions, and the following disclaimer,
124  *    without modification.
125  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
126  *    substantially similar to the "NO WARRANTY" disclaimer below
127  *    ("Disclaimer") and any redistribution must be conditioned upon
128  *    including a substantially similar Disclaimer requirement for further
129  *    binary redistribution.
130  * 3. Neither the names of the above-listed copyright holders nor the names
131  *    of any contributors may be used to endorse or promote products derived
132  *    from this software without specific prior written permission.
133  *
134  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
135  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
136  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
137  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
138  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
139  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
140  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
141  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
142  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
143  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
144  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
145  *
146  * Alternatively, you may choose to be licensed under the terms of the
147  * GNU General Public License ("GPL") version 2 as published by the Free
148  * Software Foundation.
149  *
150  *****************************************************************************/
151 
152 #include "acpi.h"
153 #include "accommon.h"
154 #include "amlcode.h"
155 #include "acdispat.h"
156 #include "acinterp.h"
157 #include "acnamesp.h"
158 #include "acparser.h"
159 
160 
161 #define _COMPONENT          ACPI_DISPATCHER
162         ACPI_MODULE_NAME    ("dsfield")
163 
164 /* Local prototypes */
165 
166 #ifdef ACPI_ASL_COMPILER
167 #include "acdisasm.h"
168 
169 static ACPI_STATUS
170 AcpiDsCreateExternalRegion (
171     ACPI_STATUS             LookupStatus,
172     ACPI_PARSE_OBJECT       *Op,
173     char                    *Path,
174     ACPI_WALK_STATE         *WalkState,
175     ACPI_NAMESPACE_NODE     **Node);
176 #endif
177 
178 static ACPI_STATUS
179 AcpiDsGetFieldNames (
180     ACPI_CREATE_FIELD_INFO  *Info,
181     ACPI_WALK_STATE         *WalkState,
182     ACPI_PARSE_OBJECT       *Arg);
183 
184 
185 #ifdef ACPI_ASL_COMPILER
186 /*******************************************************************************
187  *
188  * FUNCTION:    AcpiDsCreateExternalRegion (iASL Disassembler only)
189  *
190  * PARAMETERS:  LookupStatus    - Status from NsLookup operation
191  *              Op              - Op containing the Field definition and args
192  *              Path            - Pathname of the region
193  *  `           WalkState       - Current method state
194  *              Node            - Where the new region node is returned
195  *
196  * RETURN:      Status
197  *
198  * DESCRIPTION: Add region to the external list if NOT_FOUND. Create a new
199  *              region node/object.
200  *
201  ******************************************************************************/
202 
203 static ACPI_STATUS
204 AcpiDsCreateExternalRegion (
205     ACPI_STATUS             LookupStatus,
206     ACPI_PARSE_OBJECT       *Op,
207     char                    *Path,
208     ACPI_WALK_STATE         *WalkState,
209     ACPI_NAMESPACE_NODE     **Node)
210 {
211     ACPI_STATUS             Status;
212     ACPI_OPERAND_OBJECT     *ObjDesc;
213 
214 
215     if (LookupStatus != AE_NOT_FOUND)
216     {
217         return (LookupStatus);
218     }
219 
220     /*
221      * Table disassembly:
222      * OperationRegion not found. Generate an External for it, and
223      * insert the name into the namespace.
224      */
225     AcpiDmAddOpToExternalList (Op, Path, ACPI_TYPE_REGION, 0, 0);
226 
227     Status = AcpiNsLookup (WalkState->ScopeInfo, Path, ACPI_TYPE_REGION,
228        ACPI_IMODE_LOAD_PASS1, ACPI_NS_SEARCH_PARENT, WalkState, Node);
229     if (ACPI_FAILURE (Status))
230     {
231         return (Status);
232     }
233 
234     /* Must create and install a region object for the new node */
235 
236     ObjDesc = AcpiUtCreateInternalObject (ACPI_TYPE_REGION);
237     if (!ObjDesc)
238     {
239         return (AE_NO_MEMORY);
240     }
241 
242     ObjDesc->Region.Node = *Node;
243     Status = AcpiNsAttachObject (*Node, ObjDesc, ACPI_TYPE_REGION);
244     return (Status);
245 }
246 #endif
247 
248 
249 /*******************************************************************************
250  *
251  * FUNCTION:    AcpiDsCreateBufferField
252  *
253  * PARAMETERS:  Op                  - Current parse op (CreateXXField)
254  *              WalkState           - Current state
255  *
256  * RETURN:      Status
257  *
258  * DESCRIPTION: Execute the CreateField operators:
259  *              CreateBitFieldOp,
260  *              CreateByteFieldOp,
261  *              CreateWordFieldOp,
262  *              CreateDwordFieldOp,
263  *              CreateQwordFieldOp,
264  *              CreateFieldOp       (all of which define a field in a buffer)
265  *
266  ******************************************************************************/
267 
268 ACPI_STATUS
269 AcpiDsCreateBufferField (
270     ACPI_PARSE_OBJECT       *Op,
271     ACPI_WALK_STATE         *WalkState)
272 {
273     ACPI_PARSE_OBJECT       *Arg;
274     ACPI_NAMESPACE_NODE     *Node;
275     ACPI_STATUS             Status;
276     ACPI_OPERAND_OBJECT     *ObjDesc;
277     ACPI_OPERAND_OBJECT     *SecondDesc = NULL;
278     UINT32                  Flags;
279 
280 
281     ACPI_FUNCTION_TRACE (DsCreateBufferField);
282 
283 
284     /*
285      * Get the NameString argument (name of the new BufferField)
286      */
287     if (Op->Common.AmlOpcode == AML_CREATE_FIELD_OP)
288     {
289         /* For CreateField, name is the 4th argument */
290 
291         Arg = AcpiPsGetArg (Op, 3);
292     }
293     else
294     {
295         /* For all other CreateXXXField operators, name is the 3rd argument */
296 
297         Arg = AcpiPsGetArg (Op, 2);
298     }
299 
300     if (!Arg)
301     {
302         return_ACPI_STATUS (AE_AML_NO_OPERAND);
303     }
304 
305     if (WalkState->DeferredNode)
306     {
307         Node = WalkState->DeferredNode;
308         Status = AE_OK;
309     }
310     else
311     {
312         /* Execute flag should always be set when this function is entered */
313 
314         if (!(WalkState->ParseFlags & ACPI_PARSE_EXECUTE))
315         {
316             ACPI_ERROR ((AE_INFO,
317                 "Parse execute mode is not set"));
318             return_ACPI_STATUS (AE_AML_INTERNAL);
319         }
320 
321         /* Creating new namespace node, should not already exist */
322 
323         Flags = ACPI_NS_NO_UPSEARCH | ACPI_NS_DONT_OPEN_SCOPE |
324             ACPI_NS_ERROR_IF_FOUND;
325 
326         /*
327          * Mark node temporary if we are executing a normal control
328          * method. (Don't mark if this is a module-level code method)
329          */
330         if (WalkState->MethodNode &&
331             !(WalkState->ParseFlags & ACPI_PARSE_MODULE_LEVEL))
332         {
333             Flags |= ACPI_NS_TEMPORARY;
334         }
335 
336         /* Enter the NameString into the namespace */
337 
338         Status = AcpiNsLookup (WalkState->ScopeInfo,
339             Arg->Common.Value.String, ACPI_TYPE_ANY,
340             ACPI_IMODE_LOAD_PASS1, Flags, WalkState, &Node);
341         if (ACPI_FAILURE (Status))
342         {
343             ACPI_ERROR_NAMESPACE (WalkState->ScopeInfo,
344                 Arg->Common.Value.String, Status);
345             return_ACPI_STATUS (Status);
346         }
347     }
348 
349     /*
350      * We could put the returned object (Node) on the object stack for later,
351      * but for now, we will put it in the "op" object that the parser uses,
352      * so we can get it again at the end of this scope.
353      */
354     Op->Common.Node = Node;
355 
356     /*
357      * If there is no object attached to the node, this node was just created
358      * and we need to create the field object. Otherwise, this was a lookup
359      * of an existing node and we don't want to create the field object again.
360      */
361     ObjDesc = AcpiNsGetAttachedObject (Node);
362     if (ObjDesc)
363     {
364         return_ACPI_STATUS (AE_OK);
365     }
366 
367     /*
368      * The Field definition is not fully parsed at this time.
369      * (We must save the address of the AML for the buffer and index operands)
370      */
371 
372     /* Create the buffer field object */
373 
374     ObjDesc = AcpiUtCreateInternalObject (ACPI_TYPE_BUFFER_FIELD);
375     if (!ObjDesc)
376     {
377         Status = AE_NO_MEMORY;
378         goto Cleanup;
379     }
380 
381     /*
382      * Remember location in AML stream of the field unit opcode and operands
383      * -- since the buffer and index operands must be evaluated.
384      */
385     SecondDesc = ObjDesc->Common.NextObject;
386     SecondDesc->Extra.AmlStart = Op->Named.Data;
387     SecondDesc->Extra.AmlLength = Op->Named.Length;
388     ObjDesc->BufferField.Node = Node;
389 
390     /* Attach constructed field descriptors to parent node */
391 
392     Status = AcpiNsAttachObject (Node, ObjDesc, ACPI_TYPE_BUFFER_FIELD);
393     if (ACPI_FAILURE (Status))
394     {
395         goto Cleanup;
396     }
397 
398 
399 Cleanup:
400 
401     /* Remove local reference to the object */
402 
403     AcpiUtRemoveReference (ObjDesc);
404     return_ACPI_STATUS (Status);
405 }
406 
407 
408 /*******************************************************************************
409  *
410  * FUNCTION:    AcpiDsGetFieldNames
411  *
412  * PARAMETERS:  Info            - CreateField info structure
413  *  `           WalkState       - Current method state
414  *              Arg             - First parser arg for the field name list
415  *
416  * RETURN:      Status
417  *
418  * DESCRIPTION: Process all named fields in a field declaration. Names are
419  *              entered into the namespace.
420  *
421  ******************************************************************************/
422 
423 static ACPI_STATUS
424 AcpiDsGetFieldNames (
425     ACPI_CREATE_FIELD_INFO  *Info,
426     ACPI_WALK_STATE         *WalkState,
427     ACPI_PARSE_OBJECT       *Arg)
428 {
429     ACPI_STATUS             Status;
430     UINT64                  Position;
431     ACPI_PARSE_OBJECT       *Child;
432 
433 
434     ACPI_FUNCTION_TRACE_PTR (DsGetFieldNames, Info);
435 
436 
437     /* First field starts at bit zero */
438 
439     Info->FieldBitPosition = 0;
440 
441     /* Process all elements in the field list (of parse nodes) */
442 
443     while (Arg)
444     {
445         /*
446          * Four types of field elements are handled:
447          * 1) Name - Enters a new named field into the namespace
448          * 2) Offset - specifies a bit offset
449          * 3) AccessAs - changes the access mode/attributes
450          * 4) Connection - Associate a resource template with the field
451          */
452         switch (Arg->Common.AmlOpcode)
453         {
454         case AML_INT_RESERVEDFIELD_OP:
455 
456             Position = (UINT64) Info->FieldBitPosition +
457                 (UINT64) Arg->Common.Value.Size;
458 
459             if (Position > ACPI_UINT32_MAX)
460             {
461                 ACPI_ERROR ((AE_INFO,
462                     "Bit offset within field too large (> 0xFFFFFFFF)"));
463                 return_ACPI_STATUS (AE_SUPPORT);
464             }
465 
466             Info->FieldBitPosition = (UINT32) Position;
467             break;
468 
469         case AML_INT_ACCESSFIELD_OP:
470         case AML_INT_EXTACCESSFIELD_OP:
471             /*
472              * Get new AccessType, AccessAttribute, and AccessLength fields
473              * -- to be used for all field units that follow, until the
474              * end-of-field or another AccessAs keyword is encountered.
475              * NOTE. These three bytes are encoded in the integer value
476              * of the parseop for convenience.
477              *
478              * In FieldFlags, preserve the flag bits other than the
479              * ACCESS_TYPE bits.
480              */
481 
482             /* AccessType (ByteAcc, WordAcc, etc.) */
483 
484             Info->FieldFlags = (UINT8)
485                 ((Info->FieldFlags & ~(AML_FIELD_ACCESS_TYPE_MASK)) |
486                 ((UINT8) ((UINT32) (Arg->Common.Value.Integer & 0x07))));
487 
488             /* AccessAttribute (AttribQuick, AttribByte, etc.) */
489 
490             Info->Attribute = (UINT8)
491                 ((Arg->Common.Value.Integer >> 8) & 0xFF);
492 
493             /* AccessLength (for serial/buffer protocols) */
494 
495             Info->AccessLength = (UINT8)
496                 ((Arg->Common.Value.Integer >> 16) & 0xFF);
497             break;
498 
499         case AML_INT_CONNECTION_OP:
500             /*
501              * Clear any previous connection. New connection is used for all
502              * fields that follow, similar to AccessAs
503              */
504             Info->ResourceBuffer = NULL;
505             Info->ConnectionNode = NULL;
506             Info->PinNumberIndex = 0;
507 
508             /*
509              * A Connection() is either an actual resource descriptor (buffer)
510              * or a named reference to a resource template
511              */
512             Child = Arg->Common.Value.Arg;
513             if (Child->Common.AmlOpcode == AML_INT_BYTELIST_OP)
514             {
515                 Info->ResourceBuffer = Child->Named.Data;
516                 Info->ResourceLength = (UINT16) Child->Named.Value.Integer;
517             }
518             else
519             {
520                 /* Lookup the Connection() namepath, it should already exist */
521 
522                 Status = AcpiNsLookup (WalkState->ScopeInfo,
523                     Child->Common.Value.Name, ACPI_TYPE_ANY,
524                     ACPI_IMODE_EXECUTE, ACPI_NS_DONT_OPEN_SCOPE,
525                     WalkState, &Info->ConnectionNode);
526                 if (ACPI_FAILURE (Status))
527                 {
528                     ACPI_ERROR_NAMESPACE (WalkState->ScopeInfo,
529                         Child->Common.Value.Name, Status);
530                     return_ACPI_STATUS (Status);
531                 }
532             }
533             break;
534 
535         case AML_INT_NAMEDFIELD_OP:
536 
537             /* Lookup the name, it should already exist */
538 
539             Status = AcpiNsLookup (WalkState->ScopeInfo,
540                 (char *) &Arg->Named.Name, Info->FieldType,
541                 ACPI_IMODE_EXECUTE, ACPI_NS_DONT_OPEN_SCOPE,
542                 WalkState, &Info->FieldNode);
543             if (ACPI_FAILURE (Status))
544             {
545                 ACPI_ERROR_NAMESPACE (WalkState->ScopeInfo,
546                     (char *) &Arg->Named.Name, Status);
547                 return_ACPI_STATUS (Status);
548             }
549             else
550             {
551                 Arg->Common.Node = Info->FieldNode;
552                 Info->FieldBitLength = Arg->Common.Value.Size;
553 
554                 /*
555                  * If there is no object attached to the node, this node was
556                  * just created and we need to create the field object.
557                  * Otherwise, this was a lookup of an existing node and we
558                  * don't want to create the field object again.
559                  */
560                 if (!AcpiNsGetAttachedObject (Info->FieldNode))
561                 {
562                     Status = AcpiExPrepFieldValue (Info);
563                     if (ACPI_FAILURE (Status))
564                     {
565                         return_ACPI_STATUS (Status);
566                     }
567                 }
568             }
569 
570             /* Keep track of bit position for the next field */
571 
572             Position = (UINT64) Info->FieldBitPosition +
573                 (UINT64) Arg->Common.Value.Size;
574 
575             if (Position > ACPI_UINT32_MAX)
576             {
577                 ACPI_ERROR ((AE_INFO,
578                     "Field [%4.4s] bit offset too large (> 0xFFFFFFFF)",
579                     ACPI_CAST_PTR (char, &Info->FieldNode->Name)));
580                 return_ACPI_STATUS (AE_SUPPORT);
581             }
582 
583             Info->FieldBitPosition += Info->FieldBitLength;
584             Info->PinNumberIndex++; /* Index relative to previous Connection() */
585             break;
586 
587         default:
588 
589             ACPI_ERROR ((AE_INFO,
590                 "Invalid opcode in field list: 0x%X",
591                 Arg->Common.AmlOpcode));
592             return_ACPI_STATUS (AE_AML_BAD_OPCODE);
593         }
594 
595         Arg = Arg->Common.Next;
596     }
597 
598     return_ACPI_STATUS (AE_OK);
599 }
600 
601 
602 /*******************************************************************************
603  *
604  * FUNCTION:    AcpiDsCreateField
605  *
606  * PARAMETERS:  Op              - Op containing the Field definition and args
607  *              RegionNode      - Object for the containing Operation Region
608  *  `           WalkState       - Current method state
609  *
610  * RETURN:      Status
611  *
612  * DESCRIPTION: Create a new field in the specified operation region
613  *
614  ******************************************************************************/
615 
616 ACPI_STATUS
617 AcpiDsCreateField (
618     ACPI_PARSE_OBJECT       *Op,
619     ACPI_NAMESPACE_NODE     *RegionNode,
620     ACPI_WALK_STATE         *WalkState)
621 {
622     ACPI_STATUS             Status;
623     ACPI_PARSE_OBJECT       *Arg;
624     ACPI_CREATE_FIELD_INFO  Info;
625 
626 
627     ACPI_FUNCTION_TRACE_PTR (DsCreateField, Op);
628 
629 
630     /* First arg is the name of the parent OpRegion (must already exist) */
631 
632     Arg = Op->Common.Value.Arg;
633 
634     if (!RegionNode)
635     {
636         Status = AcpiNsLookup (WalkState->ScopeInfo, Arg->Common.Value.Name,
637             ACPI_TYPE_REGION, ACPI_IMODE_EXECUTE,
638             ACPI_NS_SEARCH_PARENT, WalkState, &RegionNode);
639 #ifdef ACPI_ASL_COMPILER
640         Status = AcpiDsCreateExternalRegion (Status, Arg,
641             Arg->Common.Value.Name, WalkState, &RegionNode);
642 #endif
643         if (ACPI_FAILURE (Status))
644         {
645             ACPI_ERROR_NAMESPACE (WalkState->ScopeInfo,
646                 Arg->Common.Value.Name, Status);
647             return_ACPI_STATUS (Status);
648         }
649     }
650 
651     memset (&Info, 0, sizeof (ACPI_CREATE_FIELD_INFO));
652 
653     /* Second arg is the field flags */
654 
655     Arg = Arg->Common.Next;
656     Info.FieldFlags = (UINT8) Arg->Common.Value.Integer;
657     Info.Attribute = 0;
658 
659     /* Each remaining arg is a Named Field */
660 
661     Info.FieldType = ACPI_TYPE_LOCAL_REGION_FIELD;
662     Info.RegionNode = RegionNode;
663 
664     Status = AcpiDsGetFieldNames (&Info, WalkState, Arg->Common.Next);
665     return_ACPI_STATUS (Status);
666 }
667 
668 
669 /*******************************************************************************
670  *
671  * FUNCTION:    AcpiDsInitFieldObjects
672  *
673  * PARAMETERS:  Op              - Op containing the Field definition and args
674  *  `           WalkState       - Current method state
675  *
676  * RETURN:      Status
677  *
678  * DESCRIPTION: For each "Field Unit" name in the argument list that is
679  *              part of the field declaration, enter the name into the
680  *              namespace.
681  *
682  ******************************************************************************/
683 
684 ACPI_STATUS
685 AcpiDsInitFieldObjects (
686     ACPI_PARSE_OBJECT       *Op,
687     ACPI_WALK_STATE         *WalkState)
688 {
689     ACPI_STATUS             Status;
690     ACPI_PARSE_OBJECT       *Arg = NULL;
691     ACPI_NAMESPACE_NODE     *Node;
692     UINT8                   Type = 0;
693     UINT32                  Flags;
694 
695 
696     ACPI_FUNCTION_TRACE_PTR (DsInitFieldObjects, Op);
697 
698 
699     /* Execute flag should always be set when this function is entered */
700 
701     if (!(WalkState->ParseFlags & ACPI_PARSE_EXECUTE))
702     {
703         if (WalkState->ParseFlags & ACPI_PARSE_DEFERRED_OP)
704         {
705             /* BankField Op is deferred, just return OK */
706 
707             return_ACPI_STATUS (AE_OK);
708         }
709 
710         ACPI_ERROR ((AE_INFO,
711             "Parse deferred mode is not set"));
712         return_ACPI_STATUS (AE_AML_INTERNAL);
713     }
714 
715     /*
716      * Get the FieldList argument for this opcode. This is the start of the
717      * list of field elements.
718      */
719     switch (WalkState->Opcode)
720     {
721     case AML_FIELD_OP:
722 
723         Arg = AcpiPsGetArg (Op, 2);
724         Type = ACPI_TYPE_LOCAL_REGION_FIELD;
725         break;
726 
727     case AML_BANK_FIELD_OP:
728 
729         Arg = AcpiPsGetArg (Op, 4);
730         Type = ACPI_TYPE_LOCAL_BANK_FIELD;
731         break;
732 
733     case AML_INDEX_FIELD_OP:
734 
735         Arg = AcpiPsGetArg (Op, 3);
736         Type = ACPI_TYPE_LOCAL_INDEX_FIELD;
737         break;
738 
739     default:
740 
741         return_ACPI_STATUS (AE_BAD_PARAMETER);
742     }
743 
744     /* Creating new namespace node(s), should not already exist */
745 
746     Flags = ACPI_NS_NO_UPSEARCH | ACPI_NS_DONT_OPEN_SCOPE |
747         ACPI_NS_ERROR_IF_FOUND;
748 
749     /*
750      * Mark node(s) temporary if we are executing a normal control
751      * method. (Don't mark if this is a module-level code method)
752      */
753     if (WalkState->MethodNode &&
754         !(WalkState->ParseFlags & ACPI_PARSE_MODULE_LEVEL))
755     {
756         Flags |= ACPI_NS_TEMPORARY;
757     }
758 
759     /*
760      * Walk the list of entries in the FieldList
761      * Note: FieldList can be of zero length. In this case, Arg will be NULL.
762      */
763     while (Arg)
764     {
765         /*
766          * Ignore OFFSET/ACCESSAS/CONNECTION terms here; we are only interested
767          * in the field names in order to enter them into the namespace.
768          */
769         if (Arg->Common.AmlOpcode == AML_INT_NAMEDFIELD_OP)
770         {
771             Status = AcpiNsLookup (WalkState->ScopeInfo,
772                 (char *) &Arg->Named.Name, Type, ACPI_IMODE_LOAD_PASS1,
773                 Flags, WalkState, &Node);
774             if (ACPI_FAILURE (Status))
775             {
776                 ACPI_ERROR_NAMESPACE (WalkState->ScopeInfo,
777                     (char *) &Arg->Named.Name, Status);
778                 if (Status != AE_ALREADY_EXISTS)
779                 {
780                     return_ACPI_STATUS (Status);
781                 }
782 
783                 /* Name already exists, just ignore this error */
784 
785                 Status = AE_OK;
786             }
787 
788             Arg->Common.Node = Node;
789         }
790 
791         /* Get the next field element in the list */
792 
793         Arg = Arg->Common.Next;
794     }
795 
796     return_ACPI_STATUS (AE_OK);
797 }
798 
799 
800 /*******************************************************************************
801  *
802  * FUNCTION:    AcpiDsCreateBankField
803  *
804  * PARAMETERS:  Op              - Op containing the Field definition and args
805  *              RegionNode      - Object for the containing Operation Region
806  *              WalkState       - Current method state
807  *
808  * RETURN:      Status
809  *
810  * DESCRIPTION: Create a new bank field in the specified operation region
811  *
812  ******************************************************************************/
813 
814 ACPI_STATUS
815 AcpiDsCreateBankField (
816     ACPI_PARSE_OBJECT       *Op,
817     ACPI_NAMESPACE_NODE     *RegionNode,
818     ACPI_WALK_STATE         *WalkState)
819 {
820     ACPI_STATUS             Status;
821     ACPI_PARSE_OBJECT       *Arg;
822     ACPI_CREATE_FIELD_INFO  Info;
823 
824 
825     ACPI_FUNCTION_TRACE_PTR (DsCreateBankField, Op);
826 
827 
828     /* First arg is the name of the parent OpRegion (must already exist) */
829 
830     Arg = Op->Common.Value.Arg;
831     if (!RegionNode)
832     {
833         Status = AcpiNsLookup (WalkState->ScopeInfo, Arg->Common.Value.Name,
834             ACPI_TYPE_REGION, ACPI_IMODE_EXECUTE,
835             ACPI_NS_SEARCH_PARENT, WalkState, &RegionNode);
836 #ifdef ACPI_ASL_COMPILER
837         Status = AcpiDsCreateExternalRegion (Status, Arg,
838             Arg->Common.Value.Name, WalkState, &RegionNode);
839 #endif
840         if (ACPI_FAILURE (Status))
841         {
842             ACPI_ERROR_NAMESPACE (WalkState->ScopeInfo,
843                 Arg->Common.Value.Name, Status);
844             return_ACPI_STATUS (Status);
845         }
846     }
847 
848     /* Second arg is the Bank Register (Field) (must already exist) */
849 
850     Arg = Arg->Common.Next;
851     Status = AcpiNsLookup (WalkState->ScopeInfo, Arg->Common.Value.String,
852         ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE,
853         ACPI_NS_SEARCH_PARENT, WalkState, &Info.RegisterNode);
854     if (ACPI_FAILURE (Status))
855     {
856         ACPI_ERROR_NAMESPACE (WalkState->ScopeInfo,
857             Arg->Common.Value.String, Status);
858         return_ACPI_STATUS (Status);
859     }
860 
861     /*
862      * Third arg is the BankValue
863      * This arg is a TermArg, not a constant
864      * It will be evaluated later, by AcpiDsEvalBankFieldOperands
865      */
866     Arg = Arg->Common.Next;
867 
868     /* Fourth arg is the field flags */
869 
870     Arg = Arg->Common.Next;
871     Info.FieldFlags = (UINT8) Arg->Common.Value.Integer;
872 
873     /* Each remaining arg is a Named Field */
874 
875     Info.FieldType = ACPI_TYPE_LOCAL_BANK_FIELD;
876     Info.RegionNode = RegionNode;
877 
878     /*
879      * Use Info.DataRegisterNode to store BankField Op
880      * It's safe because DataRegisterNode will never be used when create
881      * bank field \we store AmlStart and AmlLength in the BankField Op for
882      * late evaluation. Used in AcpiExPrepFieldValue(Info)
883      *
884      * TBD: Or, should we add a field in ACPI_CREATE_FIELD_INFO, like
885      * "void *ParentOp"?
886      */
887     Info.DataRegisterNode = (ACPI_NAMESPACE_NODE*) Op;
888 
889     Status = AcpiDsGetFieldNames (&Info, WalkState, Arg->Common.Next);
890     return_ACPI_STATUS (Status);
891 }
892 
893 
894 /*******************************************************************************
895  *
896  * FUNCTION:    AcpiDsCreateIndexField
897  *
898  * PARAMETERS:  Op              - Op containing the Field definition and args
899  *              RegionNode      - Object for the containing Operation Region
900  *  `           WalkState       - Current method state
901  *
902  * RETURN:      Status
903  *
904  * DESCRIPTION: Create a new index field in the specified operation region
905  *
906  ******************************************************************************/
907 
908 ACPI_STATUS
909 AcpiDsCreateIndexField (
910     ACPI_PARSE_OBJECT       *Op,
911     ACPI_NAMESPACE_NODE     *RegionNode,
912     ACPI_WALK_STATE         *WalkState)
913 {
914     ACPI_STATUS             Status;
915     ACPI_PARSE_OBJECT       *Arg;
916     ACPI_CREATE_FIELD_INFO  Info;
917 
918 
919     ACPI_FUNCTION_TRACE_PTR (DsCreateIndexField, Op);
920 
921 
922     /* First arg is the name of the Index register (must already exist) */
923 
924     Arg = Op->Common.Value.Arg;
925     Status = AcpiNsLookup (WalkState->ScopeInfo, Arg->Common.Value.String,
926         ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE,
927         ACPI_NS_SEARCH_PARENT, WalkState, &Info.RegisterNode);
928     if (ACPI_FAILURE (Status))
929     {
930         ACPI_ERROR_NAMESPACE (WalkState->ScopeInfo,
931             Arg->Common.Value.String, Status);
932         return_ACPI_STATUS (Status);
933     }
934 
935     /* Second arg is the data register (must already exist) */
936 
937     Arg = Arg->Common.Next;
938     Status = AcpiNsLookup (WalkState->ScopeInfo, Arg->Common.Value.String,
939         ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE,
940         ACPI_NS_SEARCH_PARENT, WalkState, &Info.DataRegisterNode);
941     if (ACPI_FAILURE (Status))
942     {
943         ACPI_ERROR_NAMESPACE (WalkState->ScopeInfo,
944             Arg->Common.Value.String, Status);
945         return_ACPI_STATUS (Status);
946     }
947 
948     /* Next arg is the field flags */
949 
950     Arg = Arg->Common.Next;
951     Info.FieldFlags = (UINT8) Arg->Common.Value.Integer;
952 
953     /* Each remaining arg is a Named Field */
954 
955     Info.FieldType = ACPI_TYPE_LOCAL_INDEX_FIELD;
956     Info.RegionNode = RegionNode;
957 
958     Status = AcpiDsGetFieldNames (&Info, WalkState, Arg->Common.Next);
959     return_ACPI_STATUS (Status);
960 }
961