1193267Sjkim/******************************************************************************
2193267Sjkim *
3193267Sjkim * Module Name: nspredef - Validation of ACPI predefined methods and objects
4193267Sjkim *
5193267Sjkim *****************************************************************************/
6193267Sjkim
7217365Sjkim/*
8245582Sjkim * Copyright (C) 2000 - 2013, Intel Corp.
9193267Sjkim * All rights reserved.
10193267Sjkim *
11217365Sjkim * Redistribution and use in source and binary forms, with or without
12217365Sjkim * modification, are permitted provided that the following conditions
13217365Sjkim * are met:
14217365Sjkim * 1. Redistributions of source code must retain the above copyright
15217365Sjkim *    notice, this list of conditions, and the following disclaimer,
16217365Sjkim *    without modification.
17217365Sjkim * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18217365Sjkim *    substantially similar to the "NO WARRANTY" disclaimer below
19217365Sjkim *    ("Disclaimer") and any redistribution must be conditioned upon
20217365Sjkim *    including a substantially similar Disclaimer requirement for further
21217365Sjkim *    binary redistribution.
22217365Sjkim * 3. Neither the names of the above-listed copyright holders nor the names
23217365Sjkim *    of any contributors may be used to endorse or promote products derived
24217365Sjkim *    from this software without specific prior written permission.
25193267Sjkim *
26217365Sjkim * Alternatively, this software may be distributed under the terms of the
27217365Sjkim * GNU General Public License ("GPL") version 2 as published by the Free
28217365Sjkim * Software Foundation.
29193267Sjkim *
30217365Sjkim * NO WARRANTY
31217365Sjkim * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32217365Sjkim * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33217365Sjkim * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34217365Sjkim * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35217365Sjkim * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36217365Sjkim * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37217365Sjkim * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38217365Sjkim * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39217365Sjkim * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40217365Sjkim * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41217365Sjkim * POSSIBILITY OF SUCH DAMAGES.
42217365Sjkim */
43193267Sjkim
44197104Sjkim#define ACPI_CREATE_PREDEFINED_TABLE
45193267Sjkim
46193341Sjkim#include <contrib/dev/acpica/include/acpi.h>
47193341Sjkim#include <contrib/dev/acpica/include/accommon.h>
48193341Sjkim#include <contrib/dev/acpica/include/acnamesp.h>
49193341Sjkim#include <contrib/dev/acpica/include/acpredef.h>
50193267Sjkim
51193267Sjkim
52193267Sjkim#define _COMPONENT          ACPI_NAMESPACE
53193267Sjkim        ACPI_MODULE_NAME    ("nspredef")
54193267Sjkim
55193267Sjkim
56193267Sjkim/*******************************************************************************
57193267Sjkim *
58193267Sjkim * This module validates predefined ACPI objects that appear in the namespace,
59193267Sjkim * at the time they are evaluated (via AcpiEvaluateObject). The purpose of this
60193267Sjkim * validation is to detect problems with BIOS-exposed predefined ACPI objects
61193267Sjkim * before the results are returned to the ACPI-related drivers.
62193267Sjkim *
63193267Sjkim * There are several areas that are validated:
64193267Sjkim *
65193267Sjkim *  1) The number of input arguments as defined by the method/object in the
66249663Sjkim *     ASL is validated against the ACPI specification.
67193267Sjkim *  2) The type of the return object (if any) is validated against the ACPI
68249663Sjkim *     specification.
69193267Sjkim *  3) For returned package objects, the count of package elements is
70249663Sjkim *     validated, as well as the type of each package element. Nested
71249663Sjkim *     packages are supported.
72193267Sjkim *
73193267Sjkim * For any problems found, a warning message is issued.
74193267Sjkim *
75193267Sjkim ******************************************************************************/
76193267Sjkim
77197104Sjkim
78193267Sjkim/* Local prototypes */
79193267Sjkim
80193267Sjkimstatic ACPI_STATUS
81193267SjkimAcpiNsCheckReference (
82249663Sjkim    ACPI_EVALUATE_INFO          *Info,
83193267Sjkim    ACPI_OPERAND_OBJECT         *ReturnObject);
84193267Sjkim
85246849Sjkimstatic UINT32
86246849SjkimAcpiNsGetBitmappedType (
87246849Sjkim    ACPI_OPERAND_OBJECT         *ReturnObject);
88246849Sjkim
89246849Sjkim
90193267Sjkim/*******************************************************************************
91193267Sjkim *
92249663Sjkim * FUNCTION:    AcpiNsCheckReturnValue
93193267Sjkim *
94193267Sjkim * PARAMETERS:  Node            - Namespace node for the method/object
95249663Sjkim *              Info            - Method execution information block
96197104Sjkim *              UserParamCount  - Number of parameters actually passed
97197104Sjkim *              ReturnStatus    - Status from the object evaluation
98193267Sjkim *              ReturnObjectPtr - Pointer to the object returned from the
99193267Sjkim *                                evaluation of a method or object
100193267Sjkim *
101193267Sjkim * RETURN:      Status
102193267Sjkim *
103249663Sjkim * DESCRIPTION: Check the value returned from a predefined name.
104193267Sjkim *
105193267Sjkim ******************************************************************************/
106193267Sjkim
107193267SjkimACPI_STATUS
108249663SjkimAcpiNsCheckReturnValue (
109193267Sjkim    ACPI_NAMESPACE_NODE         *Node,
110249663Sjkim    ACPI_EVALUATE_INFO          *Info,
111193267Sjkim    UINT32                      UserParamCount,
112193267Sjkim    ACPI_STATUS                 ReturnStatus,
113193267Sjkim    ACPI_OPERAND_OBJECT         **ReturnObjectPtr)
114193267Sjkim{
115249663Sjkim    ACPI_STATUS                 Status;
116193267Sjkim    const ACPI_PREDEFINED_INFO  *Predefined;
117193267Sjkim
118193267Sjkim
119193267Sjkim    /* If not a predefined name, we cannot validate the return object */
120193267Sjkim
121249663Sjkim    Predefined = Info->Predefined;
122193267Sjkim    if (!Predefined)
123193267Sjkim    {
124249663Sjkim        return (AE_OK);
125193267Sjkim    }
126193267Sjkim
127193267Sjkim    /*
128197104Sjkim     * If the method failed or did not actually return an object, we cannot
129197104Sjkim     * validate the return object
130193267Sjkim     */
131249663Sjkim    if ((ReturnStatus != AE_OK) &&
132249663Sjkim        (ReturnStatus != AE_CTRL_RETURN_VALUE))
133193267Sjkim    {
134249663Sjkim        return (AE_OK);
135193267Sjkim    }
136193267Sjkim
137193267Sjkim    /*
138228110Sjkim     * Return value validation and possible repair.
139193267Sjkim     *
140228110Sjkim     * 1) Don't perform return value validation/repair if this feature
141228110Sjkim     * has been disabled via a global option.
142228110Sjkim     *
143228110Sjkim     * 2) We have a return value, but if one wasn't expected, just exit,
144228110Sjkim     * this is not a problem. For example, if the "Implicit Return"
145228110Sjkim     * feature is enabled, methods will always return a value.
146228110Sjkim     *
147228110Sjkim     * 3) If the return value can be of any type, then we cannot perform
148228110Sjkim     * any validation, just exit.
149193267Sjkim     */
150228110Sjkim    if (AcpiGbl_DisableAutoRepair ||
151228110Sjkim        (!Predefined->Info.ExpectedBtypes) ||
152197104Sjkim        (Predefined->Info.ExpectedBtypes == ACPI_RTYPE_ALL))
153193267Sjkim    {
154249663Sjkim        return (AE_OK);
155193267Sjkim    }
156193267Sjkim
157193267Sjkim    /*
158200553Sjkim     * Check that the type of the main return object is what is expected
159200553Sjkim     * for this predefined name
160193267Sjkim     */
161249663Sjkim    Status = AcpiNsCheckObjectType (Info, ReturnObjectPtr,
162249663Sjkim        Predefined->Info.ExpectedBtypes, ACPI_NOT_PACKAGE_ELEMENT);
163193267Sjkim    if (ACPI_FAILURE (Status))
164193267Sjkim    {
165200553Sjkim        goto Exit;
166193267Sjkim    }
167193267Sjkim
168200553Sjkim    /*
169253690Sjkim     *
170253690Sjkim     * 4) If there is no return value and it is optional, just return
171253690Sjkim     * AE_OK (_WAK).
172253690Sjkim     */
173253690Sjkim    if (!(*ReturnObjectPtr))
174253690Sjkim    {
175253690Sjkim        goto Exit;
176253690Sjkim    }
177253690Sjkim
178253690Sjkim    /*
179200553Sjkim     * For returned Package objects, check the type of all sub-objects.
180200553Sjkim     * Note: Package may have been newly created by call above.
181200553Sjkim     */
182200553Sjkim    if ((*ReturnObjectPtr)->Common.Type == ACPI_TYPE_PACKAGE)
183193267Sjkim    {
184249663Sjkim        Info->ParentPackage = *ReturnObjectPtr;
185249663Sjkim        Status = AcpiNsCheckPackage (Info, ReturnObjectPtr);
186200553Sjkim        if (ACPI_FAILURE (Status))
187200553Sjkim        {
188250838Sjkim            /* We might be able to fix some errors */
189250838Sjkim
190250838Sjkim            if ((Status != AE_AML_OPERAND_TYPE) &&
191250838Sjkim                (Status != AE_AML_OPERAND_VALUE))
192250838Sjkim            {
193250838Sjkim                goto Exit;
194250838Sjkim            }
195200553Sjkim        }
196193267Sjkim    }
197193267Sjkim
198199337Sjkim    /*
199200553Sjkim     * The return object was OK, or it was successfully repaired above.
200200553Sjkim     * Now make some additional checks such as verifying that package
201200553Sjkim     * objects are sorted correctly (if required) or buffer objects have
202200553Sjkim     * the correct data width (bytes vs. dwords). These repairs are
203200553Sjkim     * performed on a per-name basis, i.e., the code is specific to
204200553Sjkim     * particular predefined names.
205199337Sjkim     */
206249663Sjkim    Status = AcpiNsComplexRepairs (Info, Node, Status, ReturnObjectPtr);
207197104Sjkim
208200553SjkimExit:
209197104Sjkim    /*
210197104Sjkim     * If the object validation failed or if we successfully repaired one
211197104Sjkim     * or more objects, mark the parent node to suppress further warning
212197104Sjkim     * messages during the next evaluation of the same method/object.
213197104Sjkim     */
214249663Sjkim    if (ACPI_FAILURE (Status) ||
215249663Sjkim       (Info->ReturnFlags & ACPI_OBJECT_REPAIRED))
216197104Sjkim    {
217197104Sjkim        Node->Flags |= ANOBJ_EVALUATED;
218197104Sjkim    }
219197104Sjkim
220193267Sjkim    return (Status);
221193267Sjkim}
222193267Sjkim
223193267Sjkim
224193267Sjkim/*******************************************************************************
225193267Sjkim *
226193267Sjkim * FUNCTION:    AcpiNsCheckObjectType
227193267Sjkim *
228249663Sjkim * PARAMETERS:  Info            - Method execution information block
229193267Sjkim *              ReturnObjectPtr - Pointer to the object returned from the
230193267Sjkim *                                evaluation of a method or object
231193267Sjkim *              ExpectedBtypes  - Bitmap of expected return type(s)
232193267Sjkim *              PackageIndex    - Index of object within parent package (if
233197104Sjkim *                                applicable - ACPI_NOT_PACKAGE_ELEMENT
234197104Sjkim *                                otherwise)
235193267Sjkim *
236193267Sjkim * RETURN:      Status
237193267Sjkim *
238193267Sjkim * DESCRIPTION: Check the type of the return object against the expected object
239193267Sjkim *              type(s). Use of Btype allows multiple expected object types.
240193267Sjkim *
241193267Sjkim ******************************************************************************/
242193267Sjkim
243245582SjkimACPI_STATUS
244193267SjkimAcpiNsCheckObjectType (
245249663Sjkim    ACPI_EVALUATE_INFO          *Info,
246193267Sjkim    ACPI_OPERAND_OBJECT         **ReturnObjectPtr,
247193267Sjkim    UINT32                      ExpectedBtypes,
248193267Sjkim    UINT32                      PackageIndex)
249193267Sjkim{
250193267Sjkim    ACPI_OPERAND_OBJECT         *ReturnObject = *ReturnObjectPtr;
251193267Sjkim    ACPI_STATUS                 Status = AE_OK;
252193267Sjkim    char                        TypeBuffer[48]; /* Room for 5 types */
253193267Sjkim
254193267Sjkim
255193267Sjkim    /* A Namespace node should not get here, but make sure */
256193267Sjkim
257246849Sjkim    if (ReturnObject &&
258246849Sjkim        ACPI_GET_DESCRIPTOR_TYPE (ReturnObject) == ACPI_DESC_TYPE_NAMED)
259193267Sjkim    {
260249663Sjkim        ACPI_WARN_PREDEFINED ((AE_INFO, Info->FullPathname, Info->NodeFlags,
261197104Sjkim            "Invalid return type - Found a Namespace node [%4.4s] type %s",
262197104Sjkim            ReturnObject->Node.Name.Ascii,
263193267Sjkim            AcpiUtGetTypeName (ReturnObject->Node.Type)));
264193267Sjkim        return (AE_AML_OPERAND_TYPE);
265193267Sjkim    }
266193267Sjkim
267193267Sjkim    /*
268193267Sjkim     * Convert the object type (ACPI_TYPE_xxx) to a bitmapped object type.
269193267Sjkim     * The bitmapped type allows multiple possible return types.
270193267Sjkim     *
271193267Sjkim     * Note, the cases below must handle all of the possible types returned
272193267Sjkim     * from all of the predefined names (including elements of returned
273193267Sjkim     * packages)
274193267Sjkim     */
275249663Sjkim    Info->ReturnBtype = AcpiNsGetBitmappedType (ReturnObject);
276249663Sjkim    if (Info->ReturnBtype == ACPI_RTYPE_ANY)
277193267Sjkim    {
278193267Sjkim        /* Not one of the supported objects, must be incorrect */
279193267Sjkim        goto TypeErrorExit;
280193267Sjkim    }
281193267Sjkim
282246849Sjkim    /* For reference objects, check that the reference type is correct */
283193267Sjkim
284249663Sjkim    if ((Info->ReturnBtype & ExpectedBtypes) == ACPI_RTYPE_REFERENCE)
285193267Sjkim    {
286249663Sjkim        Status = AcpiNsCheckReference (Info, ReturnObject);
287202771Sjkim        return (Status);
288193267Sjkim    }
289193267Sjkim
290246849Sjkim    /* Attempt simple repair of the returned object if necessary */
291193267Sjkim
292249663Sjkim    Status = AcpiNsSimpleRepair (Info, ExpectedBtypes,
293249663Sjkim        PackageIndex, ReturnObjectPtr);
294249663Sjkim    if (ACPI_SUCCESS (Status))
295249663Sjkim    {
296249663Sjkim        return (AE_OK); /* Successful repair */
297249663Sjkim    }
298193267Sjkim
299193267Sjkim
300193267SjkimTypeErrorExit:
301193267Sjkim
302193267Sjkim    /* Create a string with all expected types for this predefined object */
303193267Sjkim
304249112Sjkim    AcpiUtGetExpectedReturnTypes (TypeBuffer, ExpectedBtypes);
305193267Sjkim
306253690Sjkim    if (!ReturnObject)
307193267Sjkim    {
308249663Sjkim        ACPI_WARN_PREDEFINED ((AE_INFO, Info->FullPathname, Info->NodeFlags,
309253690Sjkim            "Expected return object of type %s",
310253690Sjkim            TypeBuffer));
311253690Sjkim    }
312253690Sjkim    else if (PackageIndex == ACPI_NOT_PACKAGE_ELEMENT)
313253690Sjkim    {
314253690Sjkim        ACPI_WARN_PREDEFINED ((AE_INFO, Info->FullPathname, Info->NodeFlags,
315197104Sjkim            "Return type mismatch - found %s, expected %s",
316197104Sjkim            AcpiUtGetObjectTypeName (ReturnObject), TypeBuffer));
317193267Sjkim    }
318193267Sjkim    else
319193267Sjkim    {
320249663Sjkim        ACPI_WARN_PREDEFINED ((AE_INFO, Info->FullPathname, Info->NodeFlags,
321197104Sjkim            "Return Package type mismatch at index %u - "
322197104Sjkim            "found %s, expected %s", PackageIndex,
323193267Sjkim            AcpiUtGetObjectTypeName (ReturnObject), TypeBuffer));
324193267Sjkim    }
325193267Sjkim
326193267Sjkim    return (AE_AML_OPERAND_TYPE);
327193267Sjkim}
328193267Sjkim
329193267Sjkim
330193267Sjkim/*******************************************************************************
331193267Sjkim *
332193267Sjkim * FUNCTION:    AcpiNsCheckReference
333193267Sjkim *
334249663Sjkim * PARAMETERS:  Info            - Method execution information block
335193267Sjkim *              ReturnObject    - Object returned from the evaluation of a
336193267Sjkim *                                method or object
337193267Sjkim *
338193267Sjkim * RETURN:      Status
339193267Sjkim *
340193267Sjkim * DESCRIPTION: Check a returned reference object for the correct reference
341193267Sjkim *              type. The only reference type that can be returned from a
342193267Sjkim *              predefined method is a named reference. All others are invalid.
343193267Sjkim *
344193267Sjkim ******************************************************************************/
345193267Sjkim
346193267Sjkimstatic ACPI_STATUS
347193267SjkimAcpiNsCheckReference (
348249663Sjkim    ACPI_EVALUATE_INFO          *Info,
349193267Sjkim    ACPI_OPERAND_OBJECT         *ReturnObject)
350193267Sjkim{
351193267Sjkim
352193267Sjkim    /*
353193267Sjkim     * Check the reference object for the correct reference type (opcode).
354193267Sjkim     * The only type of reference that can be converted to an ACPI_OBJECT is
355193267Sjkim     * a reference to a named object (reference class: NAME)
356193267Sjkim     */
357193267Sjkim    if (ReturnObject->Reference.Class == ACPI_REFCLASS_NAME)
358193267Sjkim    {
359193267Sjkim        return (AE_OK);
360193267Sjkim    }
361193267Sjkim
362249663Sjkim    ACPI_WARN_PREDEFINED ((AE_INFO, Info->FullPathname, Info->NodeFlags,
363197104Sjkim        "Return type mismatch - unexpected reference object type [%s] %2.2X",
364197104Sjkim        AcpiUtGetReferenceName (ReturnObject),
365193267Sjkim        ReturnObject->Reference.Class));
366193267Sjkim
367193267Sjkim    return (AE_AML_OPERAND_TYPE);
368193267Sjkim}
369193267Sjkim
370193267Sjkim
371193267Sjkim/*******************************************************************************
372193267Sjkim *
373246849Sjkim * FUNCTION:    AcpiNsGetBitmappedType
374246849Sjkim *
375246849Sjkim * PARAMETERS:  ReturnObject    - Object returned from method/obj evaluation
376246849Sjkim *
377246849Sjkim * RETURN:      Object return type. ACPI_RTYPE_ANY indicates that the object
378246849Sjkim *              type is not supported. ACPI_RTYPE_NONE indicates that no
379246849Sjkim *              object was returned (ReturnObject is NULL).
380246849Sjkim *
381246849Sjkim * DESCRIPTION: Convert object type into a bitmapped object return type.
382246849Sjkim *
383246849Sjkim ******************************************************************************/
384246849Sjkim
385246849Sjkimstatic UINT32
386246849SjkimAcpiNsGetBitmappedType (
387246849Sjkim    ACPI_OPERAND_OBJECT         *ReturnObject)
388246849Sjkim{
389246849Sjkim    UINT32                      ReturnBtype;
390246849Sjkim
391246849Sjkim
392246849Sjkim    if (!ReturnObject)
393246849Sjkim    {
394246849Sjkim        return (ACPI_RTYPE_NONE);
395246849Sjkim    }
396246849Sjkim
397246849Sjkim    /* Map ACPI_OBJECT_TYPE to internal bitmapped type */
398246849Sjkim
399246849Sjkim    switch (ReturnObject->Common.Type)
400246849Sjkim    {
401246849Sjkim    case ACPI_TYPE_INTEGER:
402250838Sjkim
403246849Sjkim        ReturnBtype = ACPI_RTYPE_INTEGER;
404246849Sjkim        break;
405246849Sjkim
406246849Sjkim    case ACPI_TYPE_BUFFER:
407250838Sjkim
408246849Sjkim        ReturnBtype = ACPI_RTYPE_BUFFER;
409246849Sjkim        break;
410246849Sjkim
411246849Sjkim    case ACPI_TYPE_STRING:
412250838Sjkim
413246849Sjkim        ReturnBtype = ACPI_RTYPE_STRING;
414246849Sjkim        break;
415246849Sjkim
416246849Sjkim    case ACPI_TYPE_PACKAGE:
417250838Sjkim
418246849Sjkim        ReturnBtype = ACPI_RTYPE_PACKAGE;
419246849Sjkim        break;
420246849Sjkim
421246849Sjkim    case ACPI_TYPE_LOCAL_REFERENCE:
422250838Sjkim
423246849Sjkim        ReturnBtype = ACPI_RTYPE_REFERENCE;
424246849Sjkim        break;
425246849Sjkim
426246849Sjkim    default:
427250838Sjkim
428246849Sjkim        /* Not one of the supported objects, must be incorrect */
429246849Sjkim
430246849Sjkim        ReturnBtype = ACPI_RTYPE_ANY;
431246849Sjkim        break;
432246849Sjkim    }
433246849Sjkim
434246849Sjkim    return (ReturnBtype);
435246849Sjkim}
436