xref: /titanic_52/usr/src/uts/intel/io/acpica/namespace/nspredef.c (revision c0e7977a434048a8bc7386ea0e8befaa77a646cf)
1 /******************************************************************************
2  *
3  * Module Name: nspredef - Validation of ACPI predefined methods and objects
4  *
5  *****************************************************************************/
6 
7 /*
8  * Copyright (C) 2000 - 2011, 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 #define ACPI_CREATE_PREDEFINED_TABLE
45 
46 #include "acpi.h"
47 #include "accommon.h"
48 #include "acnamesp.h"
49 #include "acpredef.h"
50 
51 
52 #define _COMPONENT          ACPI_NAMESPACE
53         ACPI_MODULE_NAME    ("nspredef")
54 
55 
56 /*******************************************************************************
57  *
58  * This module validates predefined ACPI objects that appear in the namespace,
59  * at the time they are evaluated (via AcpiEvaluateObject). The purpose of this
60  * validation is to detect problems with BIOS-exposed predefined ACPI objects
61  * before the results are returned to the ACPI-related drivers.
62  *
63  * There are several areas that are validated:
64  *
65  *  1) The number of input arguments as defined by the method/object in the
66  *      ASL is validated against the ACPI specification.
67  *  2) The type of the return object (if any) is validated against the ACPI
68  *      specification.
69  *  3) For returned package objects, the count of package elements is
70  *      validated, as well as the type of each package element. Nested
71  *      packages are supported.
72  *
73  * For any problems found, a warning message is issued.
74  *
75  ******************************************************************************/
76 
77 
78 /* Local prototypes */
79 
80 static ACPI_STATUS
81 AcpiNsCheckPackage (
82     ACPI_PREDEFINED_DATA        *Data,
83     ACPI_OPERAND_OBJECT         **ReturnObjectPtr);
84 
85 static ACPI_STATUS
86 AcpiNsCheckPackageList (
87     ACPI_PREDEFINED_DATA        *Data,
88     const ACPI_PREDEFINED_INFO  *Package,
89     ACPI_OPERAND_OBJECT         **Elements,
90     UINT32                      Count);
91 
92 static ACPI_STATUS
93 AcpiNsCheckPackageElements (
94     ACPI_PREDEFINED_DATA        *Data,
95     ACPI_OPERAND_OBJECT         **Elements,
96     UINT8                       Type1,
97     UINT32                      Count1,
98     UINT8                       Type2,
99     UINT32                      Count2,
100     UINT32                      StartIndex);
101 
102 static ACPI_STATUS
103 AcpiNsCheckObjectType (
104     ACPI_PREDEFINED_DATA        *Data,
105     ACPI_OPERAND_OBJECT         **ReturnObjectPtr,
106     UINT32                      ExpectedBtypes,
107     UINT32                      PackageIndex);
108 
109 static ACPI_STATUS
110 AcpiNsCheckReference (
111     ACPI_PREDEFINED_DATA        *Data,
112     ACPI_OPERAND_OBJECT         *ReturnObject);
113 
114 static void
115 AcpiNsGetExpectedTypes (
116     char                        *Buffer,
117     UINT32                      ExpectedBtypes);
118 
119 /*
120  * Names for the types that can be returned by the predefined objects.
121  * Used for warning messages. Must be in the same order as the ACPI_RTYPEs
122  */
123 static const char   *AcpiRtypeNames[] =
124 {
125     "/Integer",
126     "/String",
127     "/Buffer",
128     "/Package",
129     "/Reference",
130 };
131 
132 
133 /*******************************************************************************
134  *
135  * FUNCTION:    AcpiNsCheckPredefinedNames
136  *
137  * PARAMETERS:  Node            - Namespace node for the method/object
138  *              UserParamCount  - Number of parameters actually passed
139  *              ReturnStatus    - Status from the object evaluation
140  *              ReturnObjectPtr - Pointer to the object returned from the
141  *                                evaluation of a method or object
142  *
143  * RETURN:      Status
144  *
145  * DESCRIPTION: Check an ACPI name for a match in the predefined name list.
146  *
147  ******************************************************************************/
148 
149 ACPI_STATUS
150 AcpiNsCheckPredefinedNames (
151     ACPI_NAMESPACE_NODE         *Node,
152     UINT32                      UserParamCount,
153     ACPI_STATUS                 ReturnStatus,
154     ACPI_OPERAND_OBJECT         **ReturnObjectPtr)
155 {
156     ACPI_OPERAND_OBJECT         *ReturnObject = *ReturnObjectPtr;
157     ACPI_STATUS                 Status = AE_OK;
158     const ACPI_PREDEFINED_INFO  *Predefined;
159     char                        *Pathname;
160     ACPI_PREDEFINED_DATA        *Data;
161 
162 
163     /* Match the name for this method/object against the predefined list */
164 
165     Predefined = AcpiNsCheckForPredefinedName (Node);
166 
167     /* Get the full pathname to the object, for use in warning messages */
168 
169     Pathname = AcpiNsGetExternalPathname (Node);
170     if (!Pathname)
171     {
172         return (AE_OK); /* Could not get pathname, ignore */
173     }
174 
175     /*
176      * Check that the parameter count for this method matches the ASL
177      * definition. For predefined names, ensure that both the caller and
178      * the method itself are in accordance with the ACPI specification.
179      */
180     AcpiNsCheckParameterCount (Pathname, Node, UserParamCount, Predefined);
181 
182     /* If not a predefined name, we cannot validate the return object */
183 
184     if (!Predefined)
185     {
186         goto Cleanup;
187     }
188 
189     /*
190      * If the method failed or did not actually return an object, we cannot
191      * validate the return object
192      */
193     if ((ReturnStatus != AE_OK) && (ReturnStatus != AE_CTRL_RETURN_VALUE))
194     {
195         goto Cleanup;
196     }
197 
198     /*
199      * If there is no return value, check if we require a return value for
200      * this predefined name. Either one return value is expected, or none,
201      * for both methods and other objects.
202      *
203      * Exit now if there is no return object. Warning if one was expected.
204      */
205     if (!ReturnObject)
206     {
207         if ((Predefined->Info.ExpectedBtypes) &&
208             (!(Predefined->Info.ExpectedBtypes & ACPI_RTYPE_NONE)))
209         {
210             ACPI_WARN_PREDEFINED ((AE_INFO, Pathname, ACPI_WARN_ALWAYS,
211                 "Missing expected return value"));
212 
213             Status = AE_AML_NO_RETURN_VALUE;
214         }
215         goto Cleanup;
216     }
217 
218     /*
219      * 1) We have a return value, but if one wasn't expected, just exit, this is
220      * not a problem. For example, if the "Implicit Return" feature is
221      * enabled, methods will always return a value.
222      *
223      * 2) If the return value can be of any type, then we cannot perform any
224      * validation, exit.
225      */
226     if ((!Predefined->Info.ExpectedBtypes) ||
227         (Predefined->Info.ExpectedBtypes == ACPI_RTYPE_ALL))
228     {
229         goto Cleanup;
230     }
231 
232     /* Create the parameter data block for object validation */
233 
234     Data = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_PREDEFINED_DATA));
235     if (!Data)
236     {
237         goto Cleanup;
238     }
239     Data->Predefined = Predefined;
240     Data->NodeFlags = Node->Flags;
241     Data->Pathname = Pathname;
242 
243     /*
244      * Check that the type of the main return object is what is expected
245      * for this predefined name
246      */
247     Status = AcpiNsCheckObjectType (Data, ReturnObjectPtr,
248                 Predefined->Info.ExpectedBtypes, ACPI_NOT_PACKAGE_ELEMENT);
249     if (ACPI_FAILURE (Status))
250     {
251         goto Exit;
252     }
253 
254     /*
255      * For returned Package objects, check the type of all sub-objects.
256      * Note: Package may have been newly created by call above.
257      */
258     if ((*ReturnObjectPtr)->Common.Type == ACPI_TYPE_PACKAGE)
259     {
260         Data->ParentPackage = *ReturnObjectPtr;
261         Status = AcpiNsCheckPackage (Data, ReturnObjectPtr);
262         if (ACPI_FAILURE (Status))
263         {
264             goto Exit;
265         }
266     }
267 
268     /*
269      * The return object was OK, or it was successfully repaired above.
270      * Now make some additional checks such as verifying that package
271      * objects are sorted correctly (if required) or buffer objects have
272      * the correct data width (bytes vs. dwords). These repairs are
273      * performed on a per-name basis, i.e., the code is specific to
274      * particular predefined names.
275      */
276     Status = AcpiNsComplexRepairs (Data, Node, Status, ReturnObjectPtr);
277 
278 Exit:
279     /*
280      * If the object validation failed or if we successfully repaired one
281      * or more objects, mark the parent node to suppress further warning
282      * messages during the next evaluation of the same method/object.
283      */
284     if (ACPI_FAILURE (Status) || (Data->Flags & ACPI_OBJECT_REPAIRED))
285     {
286         Node->Flags |= ANOBJ_EVALUATED;
287     }
288     ACPI_FREE (Data);
289 
290 Cleanup:
291     ACPI_FREE (Pathname);
292     return (Status);
293 }
294 
295 
296 /*******************************************************************************
297  *
298  * FUNCTION:    AcpiNsCheckParameterCount
299  *
300  * PARAMETERS:  Pathname        - Full pathname to the node (for error msgs)
301  *              Node            - Namespace node for the method/object
302  *              UserParamCount  - Number of args passed in by the caller
303  *              Predefined      - Pointer to entry in predefined name table
304  *
305  * RETURN:      None
306  *
307  * DESCRIPTION: Check that the declared (in ASL/AML) parameter count for a
308  *              predefined name is what is expected (i.e., what is defined in
309  *              the ACPI specification for this predefined name.)
310  *
311  ******************************************************************************/
312 
313 void
314 AcpiNsCheckParameterCount (
315     char                        *Pathname,
316     ACPI_NAMESPACE_NODE         *Node,
317     UINT32                      UserParamCount,
318     const ACPI_PREDEFINED_INFO  *Predefined)
319 {
320     UINT32                      ParamCount;
321     UINT32                      RequiredParamsCurrent;
322     UINT32                      RequiredParamsOld;
323 
324 
325     /* Methods have 0-7 parameters. All other types have zero. */
326 
327     ParamCount = 0;
328     if (Node->Type == ACPI_TYPE_METHOD)
329     {
330         ParamCount = Node->Object->Method.ParamCount;
331     }
332 
333     if (!Predefined)
334     {
335         /*
336          * Check the parameter count for non-predefined methods/objects.
337          *
338          * Warning if too few or too many arguments have been passed by the
339          * caller. An incorrect number of arguments may not cause the method
340          * to fail. However, the method will fail if there are too few
341          * arguments and the method attempts to use one of the missing ones.
342          */
343         if (UserParamCount < ParamCount)
344         {
345             ACPI_WARN_PREDEFINED ((AE_INFO, Pathname, ACPI_WARN_ALWAYS,
346                 "Insufficient arguments - needs %u, found %u",
347                 ParamCount, UserParamCount));
348         }
349         else if (UserParamCount > ParamCount)
350         {
351             ACPI_WARN_PREDEFINED ((AE_INFO, Pathname, ACPI_WARN_ALWAYS,
352                 "Excess arguments - needs %u, found %u",
353                 ParamCount, UserParamCount));
354         }
355         return;
356     }
357 
358     /*
359      * Validate the user-supplied parameter count.
360      * Allow two different legal argument counts (_SCP, etc.)
361      */
362     RequiredParamsCurrent = Predefined->Info.ParamCount & 0x0F;
363     RequiredParamsOld = Predefined->Info.ParamCount >> 4;
364 
365     if (UserParamCount != ACPI_UINT32_MAX)
366     {
367         if ((UserParamCount != RequiredParamsCurrent) &&
368             (UserParamCount != RequiredParamsOld))
369         {
370             ACPI_WARN_PREDEFINED ((AE_INFO, Pathname, ACPI_WARN_ALWAYS,
371                 "Parameter count mismatch - "
372                 "caller passed %u, ACPI requires %u",
373                 UserParamCount, RequiredParamsCurrent));
374         }
375     }
376 
377     /*
378      * Check that the ASL-defined parameter count is what is expected for
379      * this predefined name (parameter count as defined by the ACPI
380      * specification)
381      */
382     if ((ParamCount != RequiredParamsCurrent) &&
383         (ParamCount != RequiredParamsOld))
384     {
385         ACPI_WARN_PREDEFINED ((AE_INFO, Pathname, Node->Flags,
386             "Parameter count mismatch - ASL declared %u, ACPI requires %u",
387             ParamCount, RequiredParamsCurrent));
388     }
389 }
390 
391 
392 /*******************************************************************************
393  *
394  * FUNCTION:    AcpiNsCheckForPredefinedName
395  *
396  * PARAMETERS:  Node            - Namespace node for the method/object
397  *
398  * RETURN:      Pointer to entry in predefined table. NULL indicates not found.
399  *
400  * DESCRIPTION: Check an object name against the predefined object list.
401  *
402  ******************************************************************************/
403 
404 const ACPI_PREDEFINED_INFO *
405 AcpiNsCheckForPredefinedName (
406     ACPI_NAMESPACE_NODE         *Node)
407 {
408     const ACPI_PREDEFINED_INFO  *ThisName;
409 
410 
411     /* Quick check for a predefined name, first character must be underscore */
412 
413     if (Node->Name.Ascii[0] != '_')
414     {
415         return (NULL);
416     }
417 
418     /* Search info table for a predefined method/object name */
419 
420     ThisName = PredefinedNames;
421     while (ThisName->Info.Name[0])
422     {
423         if (ACPI_COMPARE_NAME (Node->Name.Ascii, ThisName->Info.Name))
424         {
425             return (ThisName);
426         }
427 
428         /*
429          * Skip next entry in the table if this name returns a Package
430          * (next entry contains the package info)
431          */
432         if (ThisName->Info.ExpectedBtypes & ACPI_RTYPE_PACKAGE)
433         {
434             ThisName++;
435         }
436 
437         ThisName++;
438     }
439 
440     return (NULL); /* Not found */
441 }
442 
443 
444 /*******************************************************************************
445  *
446  * FUNCTION:    AcpiNsCheckPackage
447  *
448  * PARAMETERS:  Data            - Pointer to validation data structure
449  *              ReturnObjectPtr - Pointer to the object returned from the
450  *                                evaluation of a method or object
451  *
452  * RETURN:      Status
453  *
454  * DESCRIPTION: Check a returned package object for the correct count and
455  *              correct type of all sub-objects.
456  *
457  ******************************************************************************/
458 
459 static ACPI_STATUS
460 AcpiNsCheckPackage (
461     ACPI_PREDEFINED_DATA        *Data,
462     ACPI_OPERAND_OBJECT         **ReturnObjectPtr)
463 {
464     ACPI_OPERAND_OBJECT         *ReturnObject = *ReturnObjectPtr;
465     const ACPI_PREDEFINED_INFO  *Package;
466     ACPI_OPERAND_OBJECT         **Elements;
467     ACPI_STATUS                 Status = AE_OK;
468     UINT32                      ExpectedCount;
469     UINT32                      Count;
470     UINT32                      i;
471 
472 
473     ACPI_FUNCTION_NAME (NsCheckPackage);
474 
475 
476     /* The package info for this name is in the next table entry */
477 
478     Package = Data->Predefined + 1;
479 
480     ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
481         "%s Validating return Package of Type %X, Count %X\n",
482         Data->Pathname, Package->RetInfo.Type, ReturnObject->Package.Count));
483 
484     /*
485      * For variable-length Packages, we can safely remove all embedded
486      * and trailing NULL package elements
487      */
488     AcpiNsRemoveNullElements (Data, Package->RetInfo.Type, ReturnObject);
489 
490     /* Extract package count and elements array */
491 
492     Elements = ReturnObject->Package.Elements;
493     Count = ReturnObject->Package.Count;
494 
495     /* The package must have at least one element, else invalid */
496 
497     if (!Count)
498     {
499         ACPI_WARN_PREDEFINED ((AE_INFO, Data->Pathname, Data->NodeFlags,
500             "Return Package has no elements (empty)"));
501 
502         return (AE_AML_OPERAND_VALUE);
503     }
504 
505     /*
506      * Decode the type of the expected package contents
507      *
508      * PTYPE1 packages contain no subpackages
509      * PTYPE2 packages contain sub-packages
510      */
511     switch (Package->RetInfo.Type)
512     {
513     case ACPI_PTYPE1_FIXED:
514 
515         /*
516          * The package count is fixed and there are no sub-packages
517          *
518          * If package is too small, exit.
519          * If package is larger than expected, issue warning but continue
520          */
521         ExpectedCount = Package->RetInfo.Count1 + Package->RetInfo.Count2;
522         if (Count < ExpectedCount)
523         {
524             goto PackageTooSmall;
525         }
526         else if (Count > ExpectedCount)
527         {
528             ACPI_DEBUG_PRINT ((ACPI_DB_REPAIR,
529                 "%s: Return Package is larger than needed - "
530                 "found %u, expected %u\n",
531                 Data->Pathname, Count, ExpectedCount));
532         }
533 
534         /* Validate all elements of the returned package */
535 
536         Status = AcpiNsCheckPackageElements (Data, Elements,
537                     Package->RetInfo.ObjectType1, Package->RetInfo.Count1,
538                     Package->RetInfo.ObjectType2, Package->RetInfo.Count2, 0);
539         break;
540 
541 
542     case ACPI_PTYPE1_VAR:
543 
544         /*
545          * The package count is variable, there are no sub-packages, and all
546          * elements must be of the same type
547          */
548         for (i = 0; i < Count; i++)
549         {
550             Status = AcpiNsCheckObjectType (Data, Elements,
551                         Package->RetInfo.ObjectType1, i);
552             if (ACPI_FAILURE (Status))
553             {
554                 return (Status);
555             }
556             Elements++;
557         }
558         break;
559 
560 
561     case ACPI_PTYPE1_OPTION:
562 
563         /*
564          * The package count is variable, there are no sub-packages. There are
565          * a fixed number of required elements, and a variable number of
566          * optional elements.
567          *
568          * Check if package is at least as large as the minimum required
569          */
570         ExpectedCount = Package->RetInfo3.Count;
571         if (Count < ExpectedCount)
572         {
573             goto PackageTooSmall;
574         }
575 
576         /* Variable number of sub-objects */
577 
578         for (i = 0; i < Count; i++)
579         {
580             if (i < Package->RetInfo3.Count)
581             {
582                 /* These are the required package elements (0, 1, or 2) */
583 
584                 Status = AcpiNsCheckObjectType (Data, Elements,
585                             Package->RetInfo3.ObjectType[i], i);
586                 if (ACPI_FAILURE (Status))
587                 {
588                     return (Status);
589                 }
590             }
591             else
592             {
593                 /* These are the optional package elements */
594 
595                 Status = AcpiNsCheckObjectType (Data, Elements,
596                             Package->RetInfo3.TailObjectType, i);
597                 if (ACPI_FAILURE (Status))
598                 {
599                     return (Status);
600                 }
601             }
602             Elements++;
603         }
604         break;
605 
606 
607     case ACPI_PTYPE2_REV_FIXED:
608 
609         /* First element is the (Integer) revision */
610 
611         Status = AcpiNsCheckObjectType (Data, Elements,
612                     ACPI_RTYPE_INTEGER, 0);
613         if (ACPI_FAILURE (Status))
614         {
615             return (Status);
616         }
617 
618         Elements++;
619         Count--;
620 
621         /* Examine the sub-packages */
622 
623         Status = AcpiNsCheckPackageList (Data, Package, Elements, Count);
624         break;
625 
626 
627     case ACPI_PTYPE2_PKG_COUNT:
628 
629         /* First element is the (Integer) count of sub-packages to follow */
630 
631         Status = AcpiNsCheckObjectType (Data, Elements,
632                     ACPI_RTYPE_INTEGER, 0);
633         if (ACPI_FAILURE (Status))
634         {
635             return (Status);
636         }
637 
638         /*
639          * Count cannot be larger than the parent package length, but allow it
640          * to be smaller. The >= accounts for the Integer above.
641          */
642         ExpectedCount = (UINT32) (*Elements)->Integer.Value;
643         if (ExpectedCount >= Count)
644         {
645             goto PackageTooSmall;
646         }
647 
648         Count = ExpectedCount;
649         Elements++;
650 
651         /* Examine the sub-packages */
652 
653         Status = AcpiNsCheckPackageList (Data, Package, Elements, Count);
654         break;
655 
656 
657     case ACPI_PTYPE2:
658     case ACPI_PTYPE2_FIXED:
659     case ACPI_PTYPE2_MIN:
660     case ACPI_PTYPE2_COUNT:
661 
662         /*
663          * These types all return a single Package that consists of a
664          * variable number of sub-Packages.
665          *
666          * First, ensure that the first element is a sub-Package. If not,
667          * the BIOS may have incorrectly returned the object as a single
668          * package instead of a Package of Packages (a common error if
669          * there is only one entry). We may be able to repair this by
670          * wrapping the returned Package with a new outer Package.
671          */
672         if (*Elements && ((*Elements)->Common.Type != ACPI_TYPE_PACKAGE))
673         {
674             /* Create the new outer package and populate it */
675 
676             Status = AcpiNsRepairPackageList (Data, ReturnObjectPtr);
677             if (ACPI_FAILURE (Status))
678             {
679                 return (Status);
680             }
681 
682             /* Update locals to point to the new package (of 1 element) */
683 
684             ReturnObject = *ReturnObjectPtr;
685             Elements = ReturnObject->Package.Elements;
686             Count = 1;
687         }
688 
689         /* Examine the sub-packages */
690 
691         Status = AcpiNsCheckPackageList (Data, Package, Elements, Count);
692         break;
693 
694 
695     default:
696 
697         /* Should not get here if predefined info table is correct */
698 
699         ACPI_WARN_PREDEFINED ((AE_INFO, Data->Pathname, Data->NodeFlags,
700             "Invalid internal return type in table entry: %X",
701             Package->RetInfo.Type));
702 
703         return (AE_AML_INTERNAL);
704     }
705 
706     return (Status);
707 
708 
709 PackageTooSmall:
710 
711     /* Error exit for the case with an incorrect package count */
712 
713     ACPI_WARN_PREDEFINED ((AE_INFO, Data->Pathname, Data->NodeFlags,
714         "Return Package is too small - found %u elements, expected %u",
715         Count, ExpectedCount));
716 
717     return (AE_AML_OPERAND_VALUE);
718 }
719 
720 
721 /*******************************************************************************
722  *
723  * FUNCTION:    AcpiNsCheckPackageList
724  *
725  * PARAMETERS:  Data            - Pointer to validation data structure
726  *              Package         - Pointer to package-specific info for method
727  *              Elements        - Element list of parent package. All elements
728  *                                of this list should be of type Package.
729  *              Count           - Count of subpackages
730  *
731  * RETURN:      Status
732  *
733  * DESCRIPTION: Examine a list of subpackages
734  *
735  ******************************************************************************/
736 
737 static ACPI_STATUS
738 AcpiNsCheckPackageList (
739     ACPI_PREDEFINED_DATA        *Data,
740     const ACPI_PREDEFINED_INFO  *Package,
741     ACPI_OPERAND_OBJECT         **Elements,
742     UINT32                      Count)
743 {
744     ACPI_OPERAND_OBJECT         *SubPackage;
745     ACPI_OPERAND_OBJECT         **SubElements;
746     ACPI_STATUS                 Status;
747     UINT32                      ExpectedCount;
748     UINT32                      i;
749     UINT32                      j;
750 
751 
752     /*
753      * Validate each sub-Package in the parent Package
754      *
755      * NOTE: assumes list of sub-packages contains no NULL elements.
756      * Any NULL elements should have been removed by earlier call
757      * to AcpiNsRemoveNullElements.
758      */
759     for (i = 0; i < Count; i++)
760     {
761         SubPackage = *Elements;
762         SubElements = SubPackage->Package.Elements;
763         Data->ParentPackage = SubPackage;
764 
765         /* Each sub-object must be of type Package */
766 
767         Status = AcpiNsCheckObjectType (Data, &SubPackage,
768                     ACPI_RTYPE_PACKAGE, i);
769         if (ACPI_FAILURE (Status))
770         {
771             return (Status);
772         }
773 
774         /* Examine the different types of expected sub-packages */
775 
776         Data->ParentPackage = SubPackage;
777         switch (Package->RetInfo.Type)
778         {
779         case ACPI_PTYPE2:
780         case ACPI_PTYPE2_PKG_COUNT:
781         case ACPI_PTYPE2_REV_FIXED:
782 
783             /* Each subpackage has a fixed number of elements */
784 
785             ExpectedCount = Package->RetInfo.Count1 + Package->RetInfo.Count2;
786             if (SubPackage->Package.Count < ExpectedCount)
787             {
788                 goto PackageTooSmall;
789             }
790 
791             Status = AcpiNsCheckPackageElements (Data, SubElements,
792                         Package->RetInfo.ObjectType1,
793                         Package->RetInfo.Count1,
794                         Package->RetInfo.ObjectType2,
795                         Package->RetInfo.Count2, 0);
796             if (ACPI_FAILURE (Status))
797             {
798                 return (Status);
799             }
800             break;
801 
802 
803         case ACPI_PTYPE2_FIXED:
804 
805             /* Each sub-package has a fixed length */
806 
807             ExpectedCount = Package->RetInfo2.Count;
808             if (SubPackage->Package.Count < ExpectedCount)
809             {
810                 goto PackageTooSmall;
811             }
812 
813             /* Check the type of each sub-package element */
814 
815             for (j = 0; j < ExpectedCount; j++)
816             {
817                 Status = AcpiNsCheckObjectType (Data, &SubElements[j],
818                             Package->RetInfo2.ObjectType[j], j);
819                 if (ACPI_FAILURE (Status))
820                 {
821                     return (Status);
822                 }
823             }
824             break;
825 
826 
827         case ACPI_PTYPE2_MIN:
828 
829             /* Each sub-package has a variable but minimum length */
830 
831             ExpectedCount = Package->RetInfo.Count1;
832             if (SubPackage->Package.Count < ExpectedCount)
833             {
834                 goto PackageTooSmall;
835             }
836 
837             /* Check the type of each sub-package element */
838 
839             Status = AcpiNsCheckPackageElements (Data, SubElements,
840                         Package->RetInfo.ObjectType1,
841                         SubPackage->Package.Count, 0, 0, 0);
842             if (ACPI_FAILURE (Status))
843             {
844                 return (Status);
845             }
846             break;
847 
848 
849         case ACPI_PTYPE2_COUNT:
850 
851             /*
852              * First element is the (Integer) count of elements, including
853              * the count field (the ACPI name is NumElements)
854              */
855             Status = AcpiNsCheckObjectType (Data, SubElements,
856                         ACPI_RTYPE_INTEGER, 0);
857             if (ACPI_FAILURE (Status))
858             {
859                 return (Status);
860             }
861 
862             /*
863              * Make sure package is large enough for the Count and is
864              * is as large as the minimum size
865              */
866             ExpectedCount = (UINT32) (*SubElements)->Integer.Value;
867             if (SubPackage->Package.Count < ExpectedCount)
868             {
869                 goto PackageTooSmall;
870             }
871             if (SubPackage->Package.Count < Package->RetInfo.Count1)
872             {
873                 ExpectedCount = Package->RetInfo.Count1;
874                 goto PackageTooSmall;
875             }
876             if (ExpectedCount == 0)
877             {
878                 /*
879                  * Either the NumEntries element was originally zero or it was
880                  * a NULL element and repaired to an Integer of value zero.
881                  * In either case, repair it by setting NumEntries to be the
882                  * actual size of the subpackage.
883                  */
884                 ExpectedCount = SubPackage->Package.Count;
885                 (*SubElements)->Integer.Value = ExpectedCount;
886             }
887 
888             /* Check the type of each sub-package element */
889 
890             Status = AcpiNsCheckPackageElements (Data, (SubElements + 1),
891                         Package->RetInfo.ObjectType1,
892                         (ExpectedCount - 1), 0, 0, 1);
893             if (ACPI_FAILURE (Status))
894             {
895                 return (Status);
896             }
897             break;
898 
899 
900         default: /* Should not get here, type was validated by caller */
901 
902             return (AE_AML_INTERNAL);
903         }
904 
905         Elements++;
906     }
907 
908     return (AE_OK);
909 
910 
911 PackageTooSmall:
912 
913     /* The sub-package count was smaller than required */
914 
915     ACPI_WARN_PREDEFINED ((AE_INFO, Data->Pathname, Data->NodeFlags,
916         "Return Sub-Package[%u] is too small - found %u elements, expected %u",
917         i, SubPackage->Package.Count, ExpectedCount));
918 
919     return (AE_AML_OPERAND_VALUE);
920 }
921 
922 
923 /*******************************************************************************
924  *
925  * FUNCTION:    AcpiNsCheckPackageElements
926  *
927  * PARAMETERS:  Data            - Pointer to validation data structure
928  *              Elements        - Pointer to the package elements array
929  *              Type1           - Object type for first group
930  *              Count1          - Count for first group
931  *              Type2           - Object type for second group
932  *              Count2          - Count for second group
933  *              StartIndex      - Start of the first group of elements
934  *
935  * RETURN:      Status
936  *
937  * DESCRIPTION: Check that all elements of a package are of the correct object
938  *              type. Supports up to two groups of different object types.
939  *
940  ******************************************************************************/
941 
942 static ACPI_STATUS
943 AcpiNsCheckPackageElements (
944     ACPI_PREDEFINED_DATA        *Data,
945     ACPI_OPERAND_OBJECT         **Elements,
946     UINT8                       Type1,
947     UINT32                      Count1,
948     UINT8                       Type2,
949     UINT32                      Count2,
950     UINT32                      StartIndex)
951 {
952     ACPI_OPERAND_OBJECT         **ThisElement = Elements;
953     ACPI_STATUS                 Status;
954     UINT32                      i;
955 
956 
957     /*
958      * Up to two groups of package elements are supported by the data
959      * structure. All elements in each group must be of the same type.
960      * The second group can have a count of zero.
961      */
962     for (i = 0; i < Count1; i++)
963     {
964         Status = AcpiNsCheckObjectType (Data, ThisElement,
965                     Type1, i + StartIndex);
966         if (ACPI_FAILURE (Status))
967         {
968             return (Status);
969         }
970         ThisElement++;
971     }
972 
973     for (i = 0; i < Count2; i++)
974     {
975         Status = AcpiNsCheckObjectType (Data, ThisElement,
976                     Type2, (i + Count1 + StartIndex));
977         if (ACPI_FAILURE (Status))
978         {
979             return (Status);
980         }
981         ThisElement++;
982     }
983 
984     return (AE_OK);
985 }
986 
987 
988 /*******************************************************************************
989  *
990  * FUNCTION:    AcpiNsCheckObjectType
991  *
992  * PARAMETERS:  Data            - Pointer to validation data structure
993  *              ReturnObjectPtr - Pointer to the object returned from the
994  *                                evaluation of a method or object
995  *              ExpectedBtypes  - Bitmap of expected return type(s)
996  *              PackageIndex    - Index of object within parent package (if
997  *                                applicable - ACPI_NOT_PACKAGE_ELEMENT
998  *                                otherwise)
999  *
1000  * RETURN:      Status
1001  *
1002  * DESCRIPTION: Check the type of the return object against the expected object
1003  *              type(s). Use of Btype allows multiple expected object types.
1004  *
1005  ******************************************************************************/
1006 
1007 static ACPI_STATUS
1008 AcpiNsCheckObjectType (
1009     ACPI_PREDEFINED_DATA        *Data,
1010     ACPI_OPERAND_OBJECT         **ReturnObjectPtr,
1011     UINT32                      ExpectedBtypes,
1012     UINT32                      PackageIndex)
1013 {
1014     ACPI_OPERAND_OBJECT         *ReturnObject = *ReturnObjectPtr;
1015     ACPI_STATUS                 Status = AE_OK;
1016     UINT32                      ReturnBtype;
1017     char                        TypeBuffer[48]; /* Room for 5 types */
1018 
1019 
1020     /*
1021      * If we get a NULL ReturnObject here, it is a NULL package element.
1022      * Since all extraneous NULL package elements were removed earlier by a
1023      * call to AcpiNsRemoveNullElements, this is an unexpected NULL element.
1024      * We will attempt to repair it.
1025      */
1026     if (!ReturnObject)
1027     {
1028         Status = AcpiNsRepairNullElement (Data, ExpectedBtypes,
1029                     PackageIndex, ReturnObjectPtr);
1030         if (ACPI_SUCCESS (Status))
1031         {
1032             return (AE_OK); /* Repair was successful */
1033         }
1034         goto TypeErrorExit;
1035     }
1036 
1037     /* A Namespace node should not get here, but make sure */
1038 
1039     if (ACPI_GET_DESCRIPTOR_TYPE (ReturnObject) == ACPI_DESC_TYPE_NAMED)
1040     {
1041         ACPI_WARN_PREDEFINED ((AE_INFO, Data->Pathname, Data->NodeFlags,
1042             "Invalid return type - Found a Namespace node [%4.4s] type %s",
1043             ReturnObject->Node.Name.Ascii,
1044             AcpiUtGetTypeName (ReturnObject->Node.Type)));
1045         return (AE_AML_OPERAND_TYPE);
1046     }
1047 
1048     /*
1049      * Convert the object type (ACPI_TYPE_xxx) to a bitmapped object type.
1050      * The bitmapped type allows multiple possible return types.
1051      *
1052      * Note, the cases below must handle all of the possible types returned
1053      * from all of the predefined names (including elements of returned
1054      * packages)
1055      */
1056     switch (ReturnObject->Common.Type)
1057     {
1058     case ACPI_TYPE_INTEGER:
1059         ReturnBtype = ACPI_RTYPE_INTEGER;
1060         break;
1061 
1062     case ACPI_TYPE_BUFFER:
1063         ReturnBtype = ACPI_RTYPE_BUFFER;
1064         break;
1065 
1066     case ACPI_TYPE_STRING:
1067         ReturnBtype = ACPI_RTYPE_STRING;
1068         break;
1069 
1070     case ACPI_TYPE_PACKAGE:
1071         ReturnBtype = ACPI_RTYPE_PACKAGE;
1072         break;
1073 
1074     case ACPI_TYPE_LOCAL_REFERENCE:
1075         ReturnBtype = ACPI_RTYPE_REFERENCE;
1076         break;
1077 
1078     default:
1079         /* Not one of the supported objects, must be incorrect */
1080 
1081         goto TypeErrorExit;
1082     }
1083 
1084     /* Is the object one of the expected types? */
1085 
1086     if (ReturnBtype & ExpectedBtypes)
1087     {
1088         /* For reference objects, check that the reference type is correct */
1089 
1090         if (ReturnObject->Common.Type == ACPI_TYPE_LOCAL_REFERENCE)
1091         {
1092             Status = AcpiNsCheckReference (Data, ReturnObject);
1093         }
1094 
1095         return (Status);
1096     }
1097 
1098     /* Type mismatch -- attempt repair of the returned object */
1099 
1100     Status = AcpiNsRepairObject (Data, ExpectedBtypes,
1101                 PackageIndex, ReturnObjectPtr);
1102     if (ACPI_SUCCESS (Status))
1103     {
1104         return (AE_OK); /* Repair was successful */
1105     }
1106 
1107 
1108 TypeErrorExit:
1109 
1110     /* Create a string with all expected types for this predefined object */
1111 
1112     AcpiNsGetExpectedTypes (TypeBuffer, ExpectedBtypes);
1113 
1114     if (PackageIndex == ACPI_NOT_PACKAGE_ELEMENT)
1115     {
1116         ACPI_WARN_PREDEFINED ((AE_INFO, Data->Pathname, Data->NodeFlags,
1117             "Return type mismatch - found %s, expected %s",
1118             AcpiUtGetObjectTypeName (ReturnObject), TypeBuffer));
1119     }
1120     else
1121     {
1122         ACPI_WARN_PREDEFINED ((AE_INFO, Data->Pathname, Data->NodeFlags,
1123             "Return Package type mismatch at index %u - "
1124             "found %s, expected %s", PackageIndex,
1125             AcpiUtGetObjectTypeName (ReturnObject), TypeBuffer));
1126     }
1127 
1128     return (AE_AML_OPERAND_TYPE);
1129 }
1130 
1131 
1132 /*******************************************************************************
1133  *
1134  * FUNCTION:    AcpiNsCheckReference
1135  *
1136  * PARAMETERS:  Data            - Pointer to validation data structure
1137  *              ReturnObject    - Object returned from the evaluation of a
1138  *                                method or object
1139  *
1140  * RETURN:      Status
1141  *
1142  * DESCRIPTION: Check a returned reference object for the correct reference
1143  *              type. The only reference type that can be returned from a
1144  *              predefined method is a named reference. All others are invalid.
1145  *
1146  ******************************************************************************/
1147 
1148 static ACPI_STATUS
1149 AcpiNsCheckReference (
1150     ACPI_PREDEFINED_DATA        *Data,
1151     ACPI_OPERAND_OBJECT         *ReturnObject)
1152 {
1153 
1154     /*
1155      * Check the reference object for the correct reference type (opcode).
1156      * The only type of reference that can be converted to an ACPI_OBJECT is
1157      * a reference to a named object (reference class: NAME)
1158      */
1159     if (ReturnObject->Reference.Class == ACPI_REFCLASS_NAME)
1160     {
1161         return (AE_OK);
1162     }
1163 
1164     ACPI_WARN_PREDEFINED ((AE_INFO, Data->Pathname, Data->NodeFlags,
1165         "Return type mismatch - unexpected reference object type [%s] %2.2X",
1166         AcpiUtGetReferenceName (ReturnObject),
1167         ReturnObject->Reference.Class));
1168 
1169     return (AE_AML_OPERAND_TYPE);
1170 }
1171 
1172 
1173 /*******************************************************************************
1174  *
1175  * FUNCTION:    AcpiNsGetExpectedTypes
1176  *
1177  * PARAMETERS:  Buffer          - Pointer to where the string is returned
1178  *              ExpectedBtypes  - Bitmap of expected return type(s)
1179  *
1180  * RETURN:      Buffer is populated with type names.
1181  *
1182  * DESCRIPTION: Translate the expected types bitmap into a string of ascii
1183  *              names of expected types, for use in warning messages.
1184  *
1185  ******************************************************************************/
1186 
1187 static void
1188 AcpiNsGetExpectedTypes (
1189     char                        *Buffer,
1190     UINT32                      ExpectedBtypes)
1191 {
1192     UINT32                      ThisRtype;
1193     UINT32                      i;
1194     UINT32                      j;
1195 
1196 
1197     j = 1;
1198     Buffer[0] = 0;
1199     ThisRtype = ACPI_RTYPE_INTEGER;
1200 
1201     for (i = 0; i < ACPI_NUM_RTYPES; i++)
1202     {
1203         /* If one of the expected types, concatenate the name of this type */
1204 
1205         if (ExpectedBtypes & ThisRtype)
1206         {
1207             ACPI_STRCAT (Buffer, &AcpiRtypeNames[i][j]);
1208             j = 0;              /* Use name separator from now on */
1209         }
1210         ThisRtype <<= 1;    /* Next Rtype */
1211     }
1212 }
1213