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