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