xref: /freebsd/sys/contrib/dev/acpica/compiler/aslwalks.c (revision e8e8c939350bdf3c228a411caa9660c607c27a11)
1 /******************************************************************************
2  *
3  * Module Name: aslwalks.c - Miscellaneous analytical parse tree walks
4  *
5  *****************************************************************************/
6 
7 /*
8  * Copyright (C) 2000 - 2015, 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 <contrib/dev/acpica/compiler/aslcompiler.h>
45 #include "aslcompiler.y.h"
46 #include <contrib/dev/acpica/include/acparser.h>
47 #include <contrib/dev/acpica/include/amlcode.h>
48 
49 
50 #define _COMPONENT          ACPI_COMPILER
51         ACPI_MODULE_NAME    ("aslwalks")
52 
53 
54 /*******************************************************************************
55  *
56  * FUNCTION:    AnMethodTypingWalkEnd
57  *
58  * PARAMETERS:  ASL_WALK_CALLBACK
59  *
60  * RETURN:      Status
61  *
62  * DESCRIPTION: Ascending callback for typing walk. Complete the method
63  *              return analysis. Check methods for:
64  *              1) Initialized local variables
65  *              2) Valid arguments
66  *              3) Return types
67  *
68  ******************************************************************************/
69 
70 ACPI_STATUS
71 AnMethodTypingWalkEnd (
72     ACPI_PARSE_OBJECT       *Op,
73     UINT32                  Level,
74     void                    *Context)
75 {
76     UINT32                  ThisNodeBtype;
77 
78 
79     switch (Op->Asl.ParseOpcode)
80     {
81     case PARSEOP_METHOD:
82 
83         Op->Asl.CompileFlags |= NODE_METHOD_TYPED;
84         break;
85 
86     case PARSEOP_RETURN:
87 
88         if ((Op->Asl.Child) &&
89             (Op->Asl.Child->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG))
90         {
91             ThisNodeBtype = AnGetBtype (Op->Asl.Child);
92 
93             if ((Op->Asl.Child->Asl.ParseOpcode == PARSEOP_METHODCALL) &&
94                 (ThisNodeBtype == (ACPI_UINT32_MAX -1)))
95             {
96                 /*
97                  * The called method is untyped at this time (typically a
98                  * forward reference).
99                  *
100                  * Check for a recursive method call first.
101                  */
102                 if (Op->Asl.ParentMethod != Op->Asl.Child->Asl.Node->Op)
103                 {
104                     /* We must type the method here */
105 
106                     TrWalkParseTree (Op->Asl.Child->Asl.Node->Op,
107                         ASL_WALK_VISIT_UPWARD, NULL,
108                         AnMethodTypingWalkEnd, NULL);
109 
110                     ThisNodeBtype = AnGetBtype (Op->Asl.Child);
111                 }
112             }
113 
114             /* Returns a value, save the value type */
115 
116             if (Op->Asl.ParentMethod)
117             {
118                 Op->Asl.ParentMethod->Asl.AcpiBtype |= ThisNodeBtype;
119             }
120         }
121         break;
122 
123     default:
124 
125         break;
126     }
127 
128     return (AE_OK);
129 }
130 
131 
132 /*******************************************************************************
133  *
134  * FUNCTION:    AnOperandTypecheckWalkEnd
135  *
136  * PARAMETERS:  ASL_WALK_CALLBACK
137  *
138  * RETURN:      Status
139  *
140  * DESCRIPTION: Ascending callback for analysis walk. Complete method
141  *              return analysis.
142  *
143  ******************************************************************************/
144 
145 ACPI_STATUS
146 AnOperandTypecheckWalkEnd (
147     ACPI_PARSE_OBJECT       *Op,
148     UINT32                  Level,
149     void                    *Context)
150 {
151     const ACPI_OPCODE_INFO  *OpInfo;
152     UINT32                  RuntimeArgTypes;
153     UINT32                  RuntimeArgTypes2;
154     UINT32                  RequiredBtypes;
155     UINT32                  ThisNodeBtype;
156     UINT32                  CommonBtypes;
157     UINT32                  OpcodeClass;
158     ACPI_PARSE_OBJECT       *ArgOp;
159     UINT32                  ArgType;
160 
161 
162     switch (Op->Asl.AmlOpcode)
163     {
164     case AML_RAW_DATA_BYTE:
165     case AML_RAW_DATA_WORD:
166     case AML_RAW_DATA_DWORD:
167     case AML_RAW_DATA_QWORD:
168     case AML_RAW_DATA_BUFFER:
169     case AML_RAW_DATA_CHAIN:
170     case AML_PACKAGE_LENGTH:
171     case AML_UNASSIGNED_OPCODE:
172     case AML_DEFAULT_ARG_OP:
173 
174         /* Ignore the internal (compiler-only) AML opcodes */
175 
176         return (AE_OK);
177 
178     default:
179 
180         break;
181     }
182 
183     OpInfo = AcpiPsGetOpcodeInfo (Op->Asl.AmlOpcode);
184     if (!OpInfo)
185     {
186         return (AE_OK);
187     }
188 
189     ArgOp           = Op->Asl.Child;
190     RuntimeArgTypes = OpInfo->RuntimeArgs;
191     OpcodeClass     = OpInfo->Class;
192 
193 #ifdef ASL_ERROR_NAMED_OBJECT_IN_WHILE
194     /*
195      * Update 11/2008: In practice, we can't perform this check. A simple
196      * analysis is not sufficient. Also, it can cause errors when compiling
197      * disassembled code because of the way Switch operators are implemented
198      * (a While(One) loop with a named temp variable created within.)
199      */
200 
201     /*
202      * If we are creating a named object, check if we are within a while loop
203      * by checking if the parent is a WHILE op. This is a simple analysis, but
204      * probably sufficient for many cases.
205      *
206      * Allow Scope(), Buffer(), and Package().
207      */
208     if (((OpcodeClass == AML_CLASS_NAMED_OBJECT) && (Op->Asl.AmlOpcode != AML_SCOPE_OP)) ||
209         ((OpcodeClass == AML_CLASS_CREATE) && (OpInfo->Flags & AML_NSNODE)))
210     {
211         if (Op->Asl.Parent->Asl.AmlOpcode == AML_WHILE_OP)
212         {
213             AslError (ASL_ERROR, ASL_MSG_NAMED_OBJECT_IN_WHILE, Op, NULL);
214         }
215     }
216 #endif
217 
218     /*
219      * Special case for control opcodes IF/RETURN/WHILE since they
220      * have no runtime arg list (at this time)
221      */
222     switch (Op->Asl.AmlOpcode)
223     {
224     case AML_IF_OP:
225     case AML_WHILE_OP:
226     case AML_RETURN_OP:
227 
228         if (ArgOp->Asl.ParseOpcode == PARSEOP_METHODCALL)
229         {
230             /* Check for an internal method */
231 
232             if (AnIsInternalMethod (ArgOp))
233             {
234                 return (AE_OK);
235             }
236 
237             /* The lone arg is a method call, check it */
238 
239             RequiredBtypes = AnMapArgTypeToBtype (ARGI_INTEGER);
240             if (Op->Asl.AmlOpcode == AML_RETURN_OP)
241             {
242                 RequiredBtypes = 0xFFFFFFFF;
243             }
244 
245             ThisNodeBtype = AnGetBtype (ArgOp);
246             if (ThisNodeBtype == ACPI_UINT32_MAX)
247             {
248                 return (AE_OK);
249             }
250             AnCheckMethodReturnValue (Op, OpInfo, ArgOp,
251                 RequiredBtypes, ThisNodeBtype);
252         }
253         return (AE_OK);
254 
255     case AML_EXTERNAL_OP:
256         /*
257          * Not really a "runtime" opcode since it used by disassembler only.
258          * The parser will find any issues with the operands.
259          */
260         return (AE_OK);
261 
262     default:
263 
264         break;
265     }
266 
267     /* Ignore the non-executable opcodes */
268 
269     if (RuntimeArgTypes == ARGI_INVALID_OPCODE)
270     {
271         return (AE_OK);
272     }
273 
274     switch (OpcodeClass)
275     {
276     case AML_CLASS_EXECUTE:
277     case AML_CLASS_CREATE:
278     case AML_CLASS_CONTROL:
279     case AML_CLASS_RETURN_VALUE:
280 
281         /* TBD: Change class or fix typechecking for these */
282 
283         if ((Op->Asl.AmlOpcode == AML_BUFFER_OP)        ||
284             (Op->Asl.AmlOpcode == AML_PACKAGE_OP)       ||
285             (Op->Asl.AmlOpcode == AML_VAR_PACKAGE_OP))
286         {
287             break;
288         }
289 
290         /* Reverse the runtime argument list */
291 
292         RuntimeArgTypes2 = 0;
293         while ((ArgType = GET_CURRENT_ARG_TYPE (RuntimeArgTypes)))
294         {
295             RuntimeArgTypes2 <<= ARG_TYPE_WIDTH;
296             RuntimeArgTypes2 |= ArgType;
297             INCREMENT_ARG_LIST (RuntimeArgTypes);
298         }
299 
300         while ((ArgType = GET_CURRENT_ARG_TYPE (RuntimeArgTypes2)))
301         {
302             RequiredBtypes = AnMapArgTypeToBtype (ArgType);
303 
304             if (!ArgOp)
305             {
306                 AslError (ASL_ERROR, ASL_MSG_COMPILER_INTERNAL, Op,
307                     "Null ArgOp in argument loop");
308                 AslAbort ();
309             }
310 
311             ThisNodeBtype = AnGetBtype (ArgOp);
312             if (ThisNodeBtype == ACPI_UINT32_MAX)
313             {
314                 goto NextArgument;
315             }
316 
317             /* Examine the arg based on the required type of the arg */
318 
319             switch (ArgType)
320             {
321             case ARGI_TARGETREF:
322 
323                 if (ArgOp->Asl.ParseOpcode == PARSEOP_ZERO)
324                 {
325                     /* ZERO is the placeholder for "don't store result" */
326 
327                     ThisNodeBtype = RequiredBtypes;
328                     break;
329                 }
330 
331                 if (ArgOp->Asl.ParseOpcode == PARSEOP_INTEGER)
332                 {
333                     /*
334                      * This is the case where an original reference to a resource
335                      * descriptor field has been replaced by an (Integer) offset.
336                      * These named fields are supported at compile-time only;
337                      * the names are not passed to the interpreter (via the AML).
338                      */
339                     if ((ArgOp->Asl.Node->Type == ACPI_TYPE_LOCAL_RESOURCE_FIELD) ||
340                         (ArgOp->Asl.Node->Type == ACPI_TYPE_LOCAL_RESOURCE))
341                     {
342                         AslError (ASL_ERROR, ASL_MSG_RESOURCE_FIELD, ArgOp, NULL);
343                     }
344                     else
345                     {
346                         AslError (ASL_ERROR, ASL_MSG_INVALID_TYPE, ArgOp, NULL);
347                     }
348                     break;
349                 }
350 
351                 if ((ArgOp->Asl.ParseOpcode == PARSEOP_METHODCALL) ||
352                     (ArgOp->Asl.ParseOpcode == PARSEOP_DEREFOF))
353                 {
354                     break;
355                 }
356 
357                 ThisNodeBtype = RequiredBtypes;
358                 break;
359 
360 
361             case ARGI_REFERENCE:            /* References */
362             case ARGI_INTEGER_REF:
363             case ARGI_OBJECT_REF:
364             case ARGI_DEVICE_REF:
365 
366                 switch (ArgOp->Asl.ParseOpcode)
367                 {
368                 case PARSEOP_LOCAL0:
369                 case PARSEOP_LOCAL1:
370                 case PARSEOP_LOCAL2:
371                 case PARSEOP_LOCAL3:
372                 case PARSEOP_LOCAL4:
373                 case PARSEOP_LOCAL5:
374                 case PARSEOP_LOCAL6:
375                 case PARSEOP_LOCAL7:
376 
377                     /* TBD: implement analysis of current value (type) of the local */
378                     /* For now, just treat any local as a typematch */
379 
380                     /*ThisNodeBtype = RequiredBtypes;*/
381                     break;
382 
383                 case PARSEOP_ARG0:
384                 case PARSEOP_ARG1:
385                 case PARSEOP_ARG2:
386                 case PARSEOP_ARG3:
387                 case PARSEOP_ARG4:
388                 case PARSEOP_ARG5:
389                 case PARSEOP_ARG6:
390 
391                     /* Hard to analyze argument types, sow we won't */
392                     /* For now, just treat any arg as a typematch */
393 
394                     /* ThisNodeBtype = RequiredBtypes; */
395                     break;
396 
397                 case PARSEOP_DEBUG:
398                 case PARSEOP_REFOF:
399                 case PARSEOP_INDEX:
400                 default:
401 
402                     break;
403 
404                 }
405                 break;
406 
407             case ARGI_INTEGER:
408             default:
409 
410                 break;
411             }
412 
413 
414             CommonBtypes = ThisNodeBtype & RequiredBtypes;
415 
416             if (ArgOp->Asl.ParseOpcode == PARSEOP_METHODCALL)
417             {
418                 if (AnIsInternalMethod (ArgOp))
419                 {
420                     return (AE_OK);
421                 }
422 
423                 /* Check a method call for a valid return value */
424 
425                 AnCheckMethodReturnValue (Op, OpInfo, ArgOp,
426                     RequiredBtypes, ThisNodeBtype);
427             }
428 
429             /*
430              * Now check if the actual type(s) match at least one
431              * bit to the required type
432              */
433             else if (!CommonBtypes)
434             {
435                 /* No match -- this is a type mismatch error */
436 
437                 AnFormatBtype (StringBuffer, ThisNodeBtype);
438                 AnFormatBtype (StringBuffer2, RequiredBtypes);
439 
440                 sprintf (MsgBuffer, "[%s] found, %s operator requires [%s]",
441                             StringBuffer, OpInfo->Name, StringBuffer2);
442 
443                 AslError (ASL_ERROR, ASL_MSG_INVALID_TYPE, ArgOp, MsgBuffer);
444             }
445 
446         NextArgument:
447             ArgOp = ArgOp->Asl.Next;
448             INCREMENT_ARG_LIST (RuntimeArgTypes2);
449         }
450         break;
451 
452     default:
453 
454         break;
455     }
456 
457     return (AE_OK);
458 }
459 
460 
461 /*******************************************************************************
462  *
463  * FUNCTION:    AnOtherSemanticAnalysisWalkBegin
464  *
465  * PARAMETERS:  ASL_WALK_CALLBACK
466  *
467  * RETURN:      Status
468  *
469  * DESCRIPTION: Descending callback for the analysis walk. Checks for
470  *              miscellaneous issues in the code.
471  *
472  ******************************************************************************/
473 
474 ACPI_STATUS
475 AnOtherSemanticAnalysisWalkBegin (
476     ACPI_PARSE_OBJECT       *Op,
477     UINT32                  Level,
478     void                    *Context)
479 {
480     ACPI_PARSE_OBJECT       *ArgNode;
481     ACPI_PARSE_OBJECT       *PrevArgNode = NULL;
482     const ACPI_OPCODE_INFO  *OpInfo;
483     ACPI_NAMESPACE_NODE     *Node;
484 
485 
486     OpInfo = AcpiPsGetOpcodeInfo (Op->Asl.AmlOpcode);
487 
488     /*
489      * Determine if an execution class operator actually does something by
490      * checking if it has a target and/or the function return value is used.
491      * (Target is optional, so a standalone statement can actually do nothing.)
492      */
493     if ((OpInfo->Class == AML_CLASS_EXECUTE) &&
494         (OpInfo->Flags & AML_HAS_RETVAL) &&
495         (!AnIsResultUsed (Op)))
496     {
497         if (OpInfo->Flags & AML_HAS_TARGET)
498         {
499             /*
500              * Find the target node, it is always the last child. If the traget
501              * is not specified in the ASL, a default node of type Zero was
502              * created by the parser.
503              */
504             ArgNode = Op->Asl.Child;
505             while (ArgNode->Asl.Next)
506             {
507                 PrevArgNode = ArgNode;
508                 ArgNode = ArgNode->Asl.Next;
509             }
510 
511             /* Divide() is the only weird case, it has two targets */
512 
513             if (Op->Asl.AmlOpcode == AML_DIVIDE_OP)
514             {
515                 if ((ArgNode->Asl.ParseOpcode == PARSEOP_ZERO) &&
516                     (PrevArgNode) &&
517                     (PrevArgNode->Asl.ParseOpcode == PARSEOP_ZERO))
518                 {
519                     AslError (ASL_ERROR, ASL_MSG_RESULT_NOT_USED,
520                         Op, Op->Asl.ExternalName);
521                 }
522             }
523             else if (ArgNode->Asl.ParseOpcode == PARSEOP_ZERO)
524             {
525                 AslError (ASL_ERROR, ASL_MSG_RESULT_NOT_USED,
526                     Op, Op->Asl.ExternalName);
527             }
528         }
529         else
530         {
531             /*
532              * Has no target and the result is not used. Only a couple opcodes
533              * can have this combination.
534              */
535             switch (Op->Asl.ParseOpcode)
536             {
537             case PARSEOP_ACQUIRE:
538             case PARSEOP_WAIT:
539             case PARSEOP_LOADTABLE:
540 
541                 break;
542 
543             default:
544 
545                 AslError (ASL_ERROR, ASL_MSG_RESULT_NOT_USED,
546                     Op, Op->Asl.ExternalName);
547                 break;
548             }
549         }
550     }
551 
552 
553     /*
554      * Semantic checks for individual ASL operators
555      */
556     switch (Op->Asl.ParseOpcode)
557     {
558     case PARSEOP_ACQUIRE:
559     case PARSEOP_WAIT:
560         /*
561          * Emit a warning if the timeout parameter for these operators is not
562          * ACPI_WAIT_FOREVER, and the result value from the operator is not
563          * checked, meaning that a timeout could happen, but the code
564          * would not know about it.
565          */
566 
567         /* First child is the namepath, 2nd child is timeout */
568 
569         ArgNode = Op->Asl.Child;
570         ArgNode = ArgNode->Asl.Next;
571 
572         /*
573          * Check for the WAIT_FOREVER case - defined by the ACPI spec to be
574          * 0xFFFF or greater
575          */
576         if (((ArgNode->Asl.ParseOpcode == PARSEOP_WORDCONST) ||
577              (ArgNode->Asl.ParseOpcode == PARSEOP_INTEGER))  &&
578              (ArgNode->Asl.Value.Integer >= (UINT64) ACPI_WAIT_FOREVER))
579         {
580             break;
581         }
582 
583         /*
584          * The operation could timeout. If the return value is not used
585          * (indicates timeout occurred), issue a warning
586          */
587         if (!AnIsResultUsed (Op))
588         {
589             AslError (ASL_WARNING, ASL_MSG_TIMEOUT, ArgNode,
590                 Op->Asl.ExternalName);
591         }
592         break;
593 
594     case PARSEOP_CREATEFIELD:
595         /*
596          * Check for a zero Length (NumBits) operand. NumBits is the 3rd operand
597          */
598         ArgNode = Op->Asl.Child;
599         ArgNode = ArgNode->Asl.Next;
600         ArgNode = ArgNode->Asl.Next;
601 
602         if ((ArgNode->Asl.ParseOpcode == PARSEOP_ZERO) ||
603            ((ArgNode->Asl.ParseOpcode == PARSEOP_INTEGER) &&
604             (ArgNode->Asl.Value.Integer == 0)))
605         {
606             AslError (ASL_ERROR, ASL_MSG_NON_ZERO, ArgNode, NULL);
607         }
608         break;
609 
610     case PARSEOP_CONNECTION:
611         /*
612          * Ensure that the referenced operation region has the correct SPACE_ID.
613          * From the grammar/parser, we know the parent is a FIELD definition.
614          */
615         ArgNode = Op->Asl.Parent;       /* Field definition */
616         ArgNode = ArgNode->Asl.Child;   /* First child is the OpRegion Name */
617         Node = ArgNode->Asl.Node;       /* OpRegion namespace node */
618         if (!Node)
619         {
620             break;
621         }
622 
623         ArgNode = Node->Op;             /* OpRegion definition */
624         ArgNode = ArgNode->Asl.Child;   /* First child is the OpRegion Name */
625         ArgNode = ArgNode->Asl.Next;    /* Next peer is the SPACE_ID (what we want) */
626 
627         /*
628          * The Connection() operator is only valid for the following operation
629          * region SpaceIds: GeneralPurposeIo and GenericSerialBus.
630          */
631         if ((ArgNode->Asl.Value.Integer != ACPI_ADR_SPACE_GPIO) &&
632             (ArgNode->Asl.Value.Integer != ACPI_ADR_SPACE_GSBUS))
633         {
634             AslError (ASL_ERROR, ASL_MSG_CONNECTION_INVALID, Op, NULL);
635         }
636         break;
637 
638     case PARSEOP_FIELD:
639         /*
640          * Ensure that fields for GeneralPurposeIo and GenericSerialBus
641          * contain at least one Connection() operator
642          */
643         ArgNode = Op->Asl.Child;        /* 1st child is the OpRegion Name */
644         Node = ArgNode->Asl.Node;       /* OpRegion namespace node */
645         if (!Node)
646         {
647             break;
648         }
649 
650         ArgNode = Node->Op;             /* OpRegion definition */
651         ArgNode = ArgNode->Asl.Child;   /* First child is the OpRegion Name */
652         ArgNode = ArgNode->Asl.Next;    /* Next peer is the SPACE_ID (what we want) */
653 
654         /* We are only interested in GeneralPurposeIo and GenericSerialBus */
655 
656         if ((ArgNode->Asl.Value.Integer != ACPI_ADR_SPACE_GPIO) &&
657             (ArgNode->Asl.Value.Integer != ACPI_ADR_SPACE_GSBUS))
658         {
659             break;
660         }
661 
662         ArgNode = Op->Asl.Child;        /* 1st child is the OpRegion Name */
663         ArgNode = ArgNode->Asl.Next;    /* AccessType */
664         ArgNode = ArgNode->Asl.Next;    /* LockRule */
665         ArgNode = ArgNode->Asl.Next;    /* UpdateRule */
666         ArgNode = ArgNode->Asl.Next;    /* Start of FieldUnitList */
667 
668         /* Walk the FieldUnitList */
669 
670         while (ArgNode)
671         {
672             if (ArgNode->Asl.ParseOpcode == PARSEOP_CONNECTION)
673             {
674                 break;
675             }
676             else if (ArgNode->Asl.ParseOpcode == PARSEOP_NAMESEG)
677             {
678                 AslError (ASL_ERROR, ASL_MSG_CONNECTION_MISSING, ArgNode, NULL);
679                 break;
680             }
681 
682             ArgNode = ArgNode->Asl.Next;
683         }
684         break;
685 
686     default:
687 
688         break;
689     }
690 
691     return (AE_OK);
692 }
693