xref: /freebsd/sys/contrib/dev/acpica/components/namespace/nspredef.c (revision 11c5cac53f6cc9a2d94cb6f58728b2655e92d3a5)
1 /******************************************************************************
2  *
3  * Module Name: nspredef - Validation of ACPI predefined methods and objects
4  *
5  *****************************************************************************/
6 
7 /*
8  * Copyright (C) 2000 - 2013, 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 <contrib/dev/acpica/include/acpi.h>
47 #include <contrib/dev/acpica/include/accommon.h>
48 #include <contrib/dev/acpica/include/acnamesp.h>
49 #include <contrib/dev/acpica/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 AcpiNsCheckReference (
82     ACPI_PREDEFINED_DATA        *Data,
83     ACPI_OPERAND_OBJECT         *ReturnObject);
84 
85 static void
86 AcpiNsGetExpectedTypes (
87     char                        *Buffer,
88     UINT32                      ExpectedBtypes);
89 
90 static UINT32
91 AcpiNsGetBitmappedType (
92     ACPI_OPERAND_OBJECT         *ReturnObject);
93 
94 
95 /*
96  * Names for the types that can be returned by the predefined objects.
97  * Used for warning messages. Must be in the same order as the ACPI_RTYPEs
98  */
99 static const char   *AcpiRtypeNames[] =
100 {
101     "/Integer",
102     "/String",
103     "/Buffer",
104     "/Package",
105     "/Reference",
106 };
107 
108 
109 /*******************************************************************************
110  *
111  * FUNCTION:    AcpiNsCheckPredefinedNames
112  *
113  * PARAMETERS:  Node            - Namespace node for the method/object
114  *              UserParamCount  - Number of parameters actually passed
115  *              ReturnStatus    - Status from the object evaluation
116  *              ReturnObjectPtr - Pointer to the object returned from the
117  *                                evaluation of a method or object
118  *
119  * RETURN:      Status
120  *
121  * DESCRIPTION: Check an ACPI name for a match in the predefined name list.
122  *
123  ******************************************************************************/
124 
125 ACPI_STATUS
126 AcpiNsCheckPredefinedNames (
127     ACPI_NAMESPACE_NODE         *Node,
128     UINT32                      UserParamCount,
129     ACPI_STATUS                 ReturnStatus,
130     ACPI_OPERAND_OBJECT         **ReturnObjectPtr)
131 {
132     ACPI_STATUS                 Status = AE_OK;
133     const ACPI_PREDEFINED_INFO  *Predefined;
134     char                        *Pathname;
135     ACPI_PREDEFINED_DATA        *Data;
136 
137 
138     /* Match the name for this method/object against the predefined list */
139 
140     Predefined = AcpiNsCheckForPredefinedName (Node);
141 
142     /* Get the full pathname to the object, for use in warning messages */
143 
144     Pathname = AcpiNsGetExternalPathname (Node);
145     if (!Pathname)
146     {
147         return (AE_OK); /* Could not get pathname, ignore */
148     }
149 
150     /*
151      * Check that the parameter count for this method matches the ASL
152      * definition. For predefined names, ensure that both the caller and
153      * the method itself are in accordance with the ACPI specification.
154      */
155     AcpiNsCheckParameterCount (Pathname, Node, UserParamCount, Predefined);
156 
157     /* If not a predefined name, we cannot validate the return object */
158 
159     if (!Predefined)
160     {
161         goto Cleanup;
162     }
163 
164     /*
165      * If the method failed or did not actually return an object, we cannot
166      * validate the return object
167      */
168     if ((ReturnStatus != AE_OK) && (ReturnStatus != AE_CTRL_RETURN_VALUE))
169     {
170         goto Cleanup;
171     }
172 
173     /*
174      * Return value validation and possible repair.
175      *
176      * 1) Don't perform return value validation/repair if this feature
177      * has been disabled via a global option.
178      *
179      * 2) We have a return value, but if one wasn't expected, just exit,
180      * this is not a problem. For example, if the "Implicit Return"
181      * feature is enabled, methods will always return a value.
182      *
183      * 3) If the return value can be of any type, then we cannot perform
184      * any validation, just exit.
185      */
186     if (AcpiGbl_DisableAutoRepair ||
187         (!Predefined->Info.ExpectedBtypes) ||
188         (Predefined->Info.ExpectedBtypes == ACPI_RTYPE_ALL))
189     {
190         goto Cleanup;
191     }
192 
193     /* Create the parameter data block for object validation */
194 
195     Data = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_PREDEFINED_DATA));
196     if (!Data)
197     {
198         goto Cleanup;
199     }
200     Data->Predefined = Predefined;
201     Data->Node = Node;
202     Data->NodeFlags = Node->Flags;
203     Data->Pathname = Pathname;
204 
205     /*
206      * Check that the type of the main return object is what is expected
207      * for this predefined name
208      */
209     Status = AcpiNsCheckObjectType (Data, ReturnObjectPtr,
210                 Predefined->Info.ExpectedBtypes, ACPI_NOT_PACKAGE_ELEMENT);
211     if (ACPI_FAILURE (Status))
212     {
213         goto Exit;
214     }
215 
216     /*
217      * For returned Package objects, check the type of all sub-objects.
218      * Note: Package may have been newly created by call above.
219      */
220     if ((*ReturnObjectPtr)->Common.Type == ACPI_TYPE_PACKAGE)
221     {
222         Data->ParentPackage = *ReturnObjectPtr;
223         Status = AcpiNsCheckPackage (Data, ReturnObjectPtr);
224         if (ACPI_FAILURE (Status))
225         {
226             goto Exit;
227         }
228     }
229 
230     /*
231      * The return object was OK, or it was successfully repaired above.
232      * Now make some additional checks such as verifying that package
233      * objects are sorted correctly (if required) or buffer objects have
234      * the correct data width (bytes vs. dwords). These repairs are
235      * performed on a per-name basis, i.e., the code is specific to
236      * particular predefined names.
237      */
238     Status = AcpiNsComplexRepairs (Data, Node, Status, ReturnObjectPtr);
239 
240 Exit:
241     /*
242      * If the object validation failed or if we successfully repaired one
243      * or more objects, mark the parent node to suppress further warning
244      * messages during the next evaluation of the same method/object.
245      */
246     if (ACPI_FAILURE (Status) || (Data->Flags & ACPI_OBJECT_REPAIRED))
247     {
248         Node->Flags |= ANOBJ_EVALUATED;
249     }
250     ACPI_FREE (Data);
251 
252 Cleanup:
253     ACPI_FREE (Pathname);
254     return (Status);
255 }
256 
257 
258 /*******************************************************************************
259  *
260  * FUNCTION:    AcpiNsCheckParameterCount
261  *
262  * PARAMETERS:  Pathname        - Full pathname to the node (for error msgs)
263  *              Node            - Namespace node for the method/object
264  *              UserParamCount  - Number of args passed in by the caller
265  *              Predefined      - Pointer to entry in predefined name table
266  *
267  * RETURN:      None
268  *
269  * DESCRIPTION: Check that the declared (in ASL/AML) parameter count for a
270  *              predefined name is what is expected (i.e., what is defined in
271  *              the ACPI specification for this predefined name.)
272  *
273  ******************************************************************************/
274 
275 void
276 AcpiNsCheckParameterCount (
277     char                        *Pathname,
278     ACPI_NAMESPACE_NODE         *Node,
279     UINT32                      UserParamCount,
280     const ACPI_PREDEFINED_INFO  *Predefined)
281 {
282     UINT32                      ParamCount;
283     UINT32                      RequiredParamsCurrent;
284     UINT32                      RequiredParamsOld;
285 
286 
287     /* Methods have 0-7 parameters. All other types have zero. */
288 
289     ParamCount = 0;
290     if (Node->Type == ACPI_TYPE_METHOD)
291     {
292         ParamCount = Node->Object->Method.ParamCount;
293     }
294 
295     if (!Predefined)
296     {
297         /*
298          * Check the parameter count for non-predefined methods/objects.
299          *
300          * Warning if too few or too many arguments have been passed by the
301          * caller. An incorrect number of arguments may not cause the method
302          * to fail. However, the method will fail if there are too few
303          * arguments and the method attempts to use one of the missing ones.
304          */
305         if (UserParamCount < ParamCount)
306         {
307             ACPI_WARN_PREDEFINED ((AE_INFO, Pathname, ACPI_WARN_ALWAYS,
308                 "Insufficient arguments - needs %u, found %u",
309                 ParamCount, UserParamCount));
310         }
311         else if (UserParamCount > ParamCount)
312         {
313             ACPI_WARN_PREDEFINED ((AE_INFO, Pathname, ACPI_WARN_ALWAYS,
314                 "Excess arguments - needs %u, found %u",
315                 ParamCount, UserParamCount));
316         }
317         return;
318     }
319 
320     /*
321      * Validate the user-supplied parameter count.
322      * Allow two different legal argument counts (_SCP, etc.)
323      */
324     RequiredParamsCurrent = Predefined->Info.ParamCount & 0x0F;
325     RequiredParamsOld = Predefined->Info.ParamCount >> 4;
326 
327     if (UserParamCount != ACPI_UINT32_MAX)
328     {
329         if ((UserParamCount != RequiredParamsCurrent) &&
330             (UserParamCount != RequiredParamsOld))
331         {
332             ACPI_WARN_PREDEFINED ((AE_INFO, Pathname, ACPI_WARN_ALWAYS,
333                 "Parameter count mismatch - "
334                 "caller passed %u, ACPI requires %u",
335                 UserParamCount, RequiredParamsCurrent));
336         }
337     }
338 
339     /*
340      * Check that the ASL-defined parameter count is what is expected for
341      * this predefined name (parameter count as defined by the ACPI
342      * specification)
343      */
344     if ((ParamCount != RequiredParamsCurrent) &&
345         (ParamCount != RequiredParamsOld))
346     {
347         ACPI_WARN_PREDEFINED ((AE_INFO, Pathname, Node->Flags,
348             "Parameter count mismatch - ASL declared %u, ACPI requires %u",
349             ParamCount, RequiredParamsCurrent));
350     }
351 }
352 
353 
354 /*******************************************************************************
355  *
356  * FUNCTION:    AcpiNsCheckForPredefinedName
357  *
358  * PARAMETERS:  Node            - Namespace node for the method/object
359  *
360  * RETURN:      Pointer to entry in predefined table. NULL indicates not found.
361  *
362  * DESCRIPTION: Check an object name against the predefined object list.
363  *
364  ******************************************************************************/
365 
366 const ACPI_PREDEFINED_INFO *
367 AcpiNsCheckForPredefinedName (
368     ACPI_NAMESPACE_NODE         *Node)
369 {
370     const ACPI_PREDEFINED_INFO  *ThisName;
371 
372 
373     /* Quick check for a predefined name, first character must be underscore */
374 
375     if (Node->Name.Ascii[0] != '_')
376     {
377         return (NULL);
378     }
379 
380     /* Search info table for a predefined method/object name */
381 
382     ThisName = PredefinedNames;
383     while (ThisName->Info.Name[0])
384     {
385         if (ACPI_COMPARE_NAME (Node->Name.Ascii, ThisName->Info.Name))
386         {
387             return (ThisName);
388         }
389 
390         /*
391          * Skip next entry in the table if this name returns a Package
392          * (next entry contains the package info)
393          */
394         if (ThisName->Info.ExpectedBtypes & ACPI_RTYPE_PACKAGE)
395         {
396             ThisName++;
397         }
398 
399         ThisName++;
400     }
401 
402     return (NULL); /* Not found */
403 }
404 
405 
406 /*******************************************************************************
407  *
408  * FUNCTION:    AcpiNsCheckObjectType
409  *
410  * PARAMETERS:  Data            - Pointer to validation data structure
411  *              ReturnObjectPtr - Pointer to the object returned from the
412  *                                evaluation of a method or object
413  *              ExpectedBtypes  - Bitmap of expected return type(s)
414  *              PackageIndex    - Index of object within parent package (if
415  *                                applicable - ACPI_NOT_PACKAGE_ELEMENT
416  *                                otherwise)
417  *
418  * RETURN:      Status
419  *
420  * DESCRIPTION: Check the type of the return object against the expected object
421  *              type(s). Use of Btype allows multiple expected object types.
422  *
423  ******************************************************************************/
424 
425 ACPI_STATUS
426 AcpiNsCheckObjectType (
427     ACPI_PREDEFINED_DATA        *Data,
428     ACPI_OPERAND_OBJECT         **ReturnObjectPtr,
429     UINT32                      ExpectedBtypes,
430     UINT32                      PackageIndex)
431 {
432     ACPI_OPERAND_OBJECT         *ReturnObject = *ReturnObjectPtr;
433     ACPI_STATUS                 Status = AE_OK;
434     char                        TypeBuffer[48]; /* Room for 5 types */
435 
436 
437     /* A Namespace node should not get here, but make sure */
438 
439     if (ReturnObject &&
440         ACPI_GET_DESCRIPTOR_TYPE (ReturnObject) == ACPI_DESC_TYPE_NAMED)
441     {
442         ACPI_WARN_PREDEFINED ((AE_INFO, Data->Pathname, Data->NodeFlags,
443             "Invalid return type - Found a Namespace node [%4.4s] type %s",
444             ReturnObject->Node.Name.Ascii,
445             AcpiUtGetTypeName (ReturnObject->Node.Type)));
446         return (AE_AML_OPERAND_TYPE);
447     }
448 
449     /*
450      * Convert the object type (ACPI_TYPE_xxx) to a bitmapped object type.
451      * The bitmapped type allows multiple possible return types.
452      *
453      * Note, the cases below must handle all of the possible types returned
454      * from all of the predefined names (including elements of returned
455      * packages)
456      */
457     Data->ReturnBtype = AcpiNsGetBitmappedType (ReturnObject);
458     if (Data->ReturnBtype == ACPI_RTYPE_ANY)
459     {
460         /* Not one of the supported objects, must be incorrect */
461         goto TypeErrorExit;
462     }
463 
464     /* For reference objects, check that the reference type is correct */
465 
466     if ((Data->ReturnBtype & ExpectedBtypes) == ACPI_RTYPE_REFERENCE)
467     {
468         Status = AcpiNsCheckReference (Data, ReturnObject);
469         return (Status);
470     }
471 
472     /* Attempt simple repair of the returned object if necessary */
473 
474     Status = AcpiNsSimpleRepair (Data, ExpectedBtypes,
475                 PackageIndex, ReturnObjectPtr);
476     return (Status);
477 
478 
479 TypeErrorExit:
480 
481     /* Create a string with all expected types for this predefined object */
482 
483     AcpiNsGetExpectedTypes (TypeBuffer, ExpectedBtypes);
484 
485     if (PackageIndex == ACPI_NOT_PACKAGE_ELEMENT)
486     {
487         ACPI_WARN_PREDEFINED ((AE_INFO, Data->Pathname, Data->NodeFlags,
488             "Return type mismatch - found %s, expected %s",
489             AcpiUtGetObjectTypeName (ReturnObject), TypeBuffer));
490     }
491     else
492     {
493         ACPI_WARN_PREDEFINED ((AE_INFO, Data->Pathname, Data->NodeFlags,
494             "Return Package type mismatch at index %u - "
495             "found %s, expected %s", PackageIndex,
496             AcpiUtGetObjectTypeName (ReturnObject), TypeBuffer));
497     }
498 
499     return (AE_AML_OPERAND_TYPE);
500 }
501 
502 
503 /*******************************************************************************
504  *
505  * FUNCTION:    AcpiNsCheckReference
506  *
507  * PARAMETERS:  Data            - Pointer to validation data structure
508  *              ReturnObject    - Object returned from the evaluation of a
509  *                                method or object
510  *
511  * RETURN:      Status
512  *
513  * DESCRIPTION: Check a returned reference object for the correct reference
514  *              type. The only reference type that can be returned from a
515  *              predefined method is a named reference. All others are invalid.
516  *
517  ******************************************************************************/
518 
519 static ACPI_STATUS
520 AcpiNsCheckReference (
521     ACPI_PREDEFINED_DATA        *Data,
522     ACPI_OPERAND_OBJECT         *ReturnObject)
523 {
524 
525     /*
526      * Check the reference object for the correct reference type (opcode).
527      * The only type of reference that can be converted to an ACPI_OBJECT is
528      * a reference to a named object (reference class: NAME)
529      */
530     if (ReturnObject->Reference.Class == ACPI_REFCLASS_NAME)
531     {
532         return (AE_OK);
533     }
534 
535     ACPI_WARN_PREDEFINED ((AE_INFO, Data->Pathname, Data->NodeFlags,
536         "Return type mismatch - unexpected reference object type [%s] %2.2X",
537         AcpiUtGetReferenceName (ReturnObject),
538         ReturnObject->Reference.Class));
539 
540     return (AE_AML_OPERAND_TYPE);
541 }
542 
543 
544 /*******************************************************************************
545  *
546  * FUNCTION:    AcpiNsGetBitmappedType
547  *
548  * PARAMETERS:  ReturnObject    - Object returned from method/obj evaluation
549  *
550  * RETURN:      Object return type. ACPI_RTYPE_ANY indicates that the object
551  *              type is not supported. ACPI_RTYPE_NONE indicates that no
552  *              object was returned (ReturnObject is NULL).
553  *
554  * DESCRIPTION: Convert object type into a bitmapped object return type.
555  *
556  ******************************************************************************/
557 
558 static UINT32
559 AcpiNsGetBitmappedType (
560     ACPI_OPERAND_OBJECT         *ReturnObject)
561 {
562     UINT32                      ReturnBtype;
563 
564 
565     if (!ReturnObject)
566     {
567         return (ACPI_RTYPE_NONE);
568     }
569 
570     /* Map ACPI_OBJECT_TYPE to internal bitmapped type */
571 
572     switch (ReturnObject->Common.Type)
573     {
574     case ACPI_TYPE_INTEGER:
575         ReturnBtype = ACPI_RTYPE_INTEGER;
576         break;
577 
578     case ACPI_TYPE_BUFFER:
579         ReturnBtype = ACPI_RTYPE_BUFFER;
580         break;
581 
582     case ACPI_TYPE_STRING:
583         ReturnBtype = ACPI_RTYPE_STRING;
584         break;
585 
586     case ACPI_TYPE_PACKAGE:
587         ReturnBtype = ACPI_RTYPE_PACKAGE;
588         break;
589 
590     case ACPI_TYPE_LOCAL_REFERENCE:
591         ReturnBtype = ACPI_RTYPE_REFERENCE;
592         break;
593 
594     default:
595         /* Not one of the supported objects, must be incorrect */
596 
597         ReturnBtype = ACPI_RTYPE_ANY;
598         break;
599     }
600 
601     return (ReturnBtype);
602 }
603 
604 
605 /*******************************************************************************
606  *
607  * FUNCTION:    AcpiNsGetExpectedTypes
608  *
609  * PARAMETERS:  Buffer          - Pointer to where the string is returned
610  *              ExpectedBtypes  - Bitmap of expected return type(s)
611  *
612  * RETURN:      Buffer is populated with type names.
613  *
614  * DESCRIPTION: Translate the expected types bitmap into a string of ascii
615  *              names of expected types, for use in warning messages.
616  *
617  ******************************************************************************/
618 
619 static void
620 AcpiNsGetExpectedTypes (
621     char                        *Buffer,
622     UINT32                      ExpectedBtypes)
623 {
624     UINT32                      ThisRtype;
625     UINT32                      i;
626     UINT32                      j;
627 
628 
629     j = 1;
630     Buffer[0] = 0;
631     ThisRtype = ACPI_RTYPE_INTEGER;
632 
633     for (i = 0; i < ACPI_NUM_RTYPES; i++)
634     {
635         /* If one of the expected types, concatenate the name of this type */
636 
637         if (ExpectedBtypes & ThisRtype)
638         {
639             ACPI_STRCAT (Buffer, &AcpiRtypeNames[i][j]);
640             j = 0;              /* Use name separator from now on */
641         }
642         ThisRtype <<= 1;    /* Next Rtype */
643     }
644 }
645