1249637Sjkim/******************************************************************************
2249637Sjkim *
3249637Sjkim * Module Name: nsarguments - Validation of args for ACPI predefined methods
4249637Sjkim *
5249637Sjkim *****************************************************************************/
6249637Sjkim
7249637Sjkim/*
8306536Sjkim * Copyright (C) 2000 - 2016, Intel Corp.
9249637Sjkim * All rights reserved.
10249637Sjkim *
11249637Sjkim * Redistribution and use in source and binary forms, with or without
12249637Sjkim * modification, are permitted provided that the following conditions
13249637Sjkim * are met:
14249637Sjkim * 1. Redistributions of source code must retain the above copyright
15249637Sjkim *    notice, this list of conditions, and the following disclaimer,
16249637Sjkim *    without modification.
17249637Sjkim * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18249637Sjkim *    substantially similar to the "NO WARRANTY" disclaimer below
19249637Sjkim *    ("Disclaimer") and any redistribution must be conditioned upon
20249637Sjkim *    including a substantially similar Disclaimer requirement for further
21249637Sjkim *    binary redistribution.
22249637Sjkim * 3. Neither the names of the above-listed copyright holders nor the names
23249637Sjkim *    of any contributors may be used to endorse or promote products derived
24249637Sjkim *    from this software without specific prior written permission.
25249637Sjkim *
26249637Sjkim * Alternatively, this software may be distributed under the terms of the
27249637Sjkim * GNU General Public License ("GPL") version 2 as published by the Free
28249637Sjkim * Software Foundation.
29249637Sjkim *
30249637Sjkim * NO WARRANTY
31249637Sjkim * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32249637Sjkim * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33249637Sjkim * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34249637Sjkim * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35249637Sjkim * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36249637Sjkim * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37249637Sjkim * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38249637Sjkim * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39249637Sjkim * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40249637Sjkim * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41249637Sjkim * POSSIBILITY OF SUCH DAMAGES.
42249637Sjkim */
43249637Sjkim
44249663Sjkim#include <contrib/dev/acpica/include/acpi.h>
45249663Sjkim#include <contrib/dev/acpica/include/accommon.h>
46249663Sjkim#include <contrib/dev/acpica/include/acnamesp.h>
47249663Sjkim#include <contrib/dev/acpica/include/acpredef.h>
48249637Sjkim
49249637Sjkim
50249637Sjkim#define _COMPONENT          ACPI_NAMESPACE
51249637Sjkim        ACPI_MODULE_NAME    ("nsarguments")
52249637Sjkim
53249637Sjkim
54249637Sjkim/*******************************************************************************
55249637Sjkim *
56249637Sjkim * FUNCTION:    AcpiNsCheckArgumentTypes
57249637Sjkim *
58249637Sjkim * PARAMETERS:  Info            - Method execution information block
59249637Sjkim *
60249637Sjkim * RETURN:      None
61249637Sjkim *
62249637Sjkim * DESCRIPTION: Check the incoming argument count and all argument types
63249637Sjkim *              against the argument type list for a predefined name.
64249637Sjkim *
65249637Sjkim ******************************************************************************/
66249637Sjkim
67249637Sjkimvoid
68249637SjkimAcpiNsCheckArgumentTypes (
69249637Sjkim    ACPI_EVALUATE_INFO          *Info)
70249637Sjkim{
71249637Sjkim    UINT16                      ArgTypeList;
72249637Sjkim    UINT8                       ArgCount;
73249637Sjkim    UINT8                       ArgType;
74249637Sjkim    UINT8                       UserArgType;
75249637Sjkim    UINT32                      i;
76249637Sjkim
77249637Sjkim
78249637Sjkim    /* If not a predefined name, cannot typecheck args */
79249637Sjkim
80249637Sjkim    if (!Info->Predefined)
81249637Sjkim    {
82249637Sjkim        return;
83249637Sjkim    }
84249637Sjkim
85249637Sjkim    ArgTypeList = Info->Predefined->Info.ArgumentList;
86249637Sjkim    ArgCount = METHOD_GET_ARG_COUNT (ArgTypeList);
87249637Sjkim
88249637Sjkim    /* Typecheck all arguments */
89249637Sjkim
90249637Sjkim    for (i = 0; ((i < ArgCount) && (i < Info->ParamCount)); i++)
91249637Sjkim    {
92249637Sjkim        ArgType = METHOD_GET_NEXT_TYPE (ArgTypeList);
93249637Sjkim        UserArgType = Info->Parameters[i]->Common.Type;
94249637Sjkim
95249637Sjkim        if (UserArgType != ArgType)
96249637Sjkim        {
97249637Sjkim            ACPI_WARN_PREDEFINED ((AE_INFO, Info->FullPathname, ACPI_WARN_ALWAYS,
98249637Sjkim                "Argument #%u type mismatch - "
99249637Sjkim                "Found [%s], ACPI requires [%s]", (i + 1),
100249637Sjkim                AcpiUtGetTypeName (UserArgType),
101249637Sjkim                AcpiUtGetTypeName (ArgType)));
102249637Sjkim        }
103249637Sjkim    }
104249637Sjkim}
105249637Sjkim
106249637Sjkim
107249637Sjkim/*******************************************************************************
108249637Sjkim *
109249637Sjkim * FUNCTION:    AcpiNsCheckAcpiCompliance
110249637Sjkim *
111249637Sjkim * PARAMETERS:  Pathname        - Full pathname to the node (for error msgs)
112249637Sjkim *              Node            - Namespace node for the method/object
113249637Sjkim *              Predefined      - Pointer to entry in predefined name table
114249637Sjkim *
115249637Sjkim * RETURN:      None
116249637Sjkim *
117249637Sjkim * DESCRIPTION: Check that the declared parameter count (in ASL/AML) for a
118249637Sjkim *              predefined name is what is expected (matches what is defined in
119249637Sjkim *              the ACPI specification for this predefined name.)
120249637Sjkim *
121249637Sjkim ******************************************************************************/
122249637Sjkim
123249637Sjkimvoid
124249637SjkimAcpiNsCheckAcpiCompliance (
125249637Sjkim    char                        *Pathname,
126249637Sjkim    ACPI_NAMESPACE_NODE         *Node,
127249637Sjkim    const ACPI_PREDEFINED_INFO  *Predefined)
128249637Sjkim{
129249637Sjkim    UINT32                      AmlParamCount;
130249637Sjkim    UINT32                      RequiredParamCount;
131249637Sjkim
132249637Sjkim
133249637Sjkim    if (!Predefined)
134249637Sjkim    {
135249637Sjkim        return;
136249637Sjkim    }
137249637Sjkim
138249637Sjkim    /* Get the ACPI-required arg count from the predefined info table */
139249637Sjkim
140306536Sjkim    RequiredParamCount =
141306536Sjkim        METHOD_GET_ARG_COUNT (Predefined->Info.ArgumentList);
142249637Sjkim
143249637Sjkim    /*
144249637Sjkim     * If this object is not a control method, we can check if the ACPI
145249637Sjkim     * spec requires that it be a method.
146249637Sjkim     */
147249637Sjkim    if (Node->Type != ACPI_TYPE_METHOD)
148249637Sjkim    {
149249637Sjkim        if (RequiredParamCount > 0)
150249637Sjkim        {
151249637Sjkim            /* Object requires args, must be implemented as a method */
152249637Sjkim
153249637Sjkim            ACPI_BIOS_ERROR_PREDEFINED ((AE_INFO, Pathname, ACPI_WARN_ALWAYS,
154249637Sjkim                "Object (%s) must be a control method with %u arguments",
155249637Sjkim                AcpiUtGetTypeName (Node->Type), RequiredParamCount));
156249637Sjkim        }
157249637Sjkim        else if (!RequiredParamCount && !Predefined->Info.ExpectedBtypes)
158249637Sjkim        {
159249637Sjkim            /* Object requires no args and no return value, must be a method */
160249637Sjkim
161249637Sjkim            ACPI_BIOS_ERROR_PREDEFINED ((AE_INFO, Pathname, ACPI_WARN_ALWAYS,
162249637Sjkim                "Object (%s) must be a control method "
163249637Sjkim                "with no arguments and no return value",
164249637Sjkim                AcpiUtGetTypeName (Node->Type)));
165249637Sjkim        }
166249637Sjkim
167249637Sjkim        return;
168249637Sjkim    }
169249637Sjkim
170249637Sjkim    /*
171249637Sjkim     * This is a control method.
172249637Sjkim     * Check that the ASL/AML-defined parameter count for this method
173249637Sjkim     * matches the ACPI-required parameter count
174249637Sjkim     *
175249637Sjkim     * Some methods are allowed to have a "minimum" number of args (_SCP)
176249637Sjkim     * because their definition in ACPI has changed over time.
177249637Sjkim     *
178249637Sjkim     * Note: These are BIOS errors in the declaration of the object
179249637Sjkim     */
180249637Sjkim    AmlParamCount = Node->Object->Method.ParamCount;
181249637Sjkim
182249637Sjkim    if (AmlParamCount < RequiredParamCount)
183249637Sjkim    {
184249637Sjkim        ACPI_BIOS_ERROR_PREDEFINED ((AE_INFO, Pathname, ACPI_WARN_ALWAYS,
185249637Sjkim            "Insufficient arguments - "
186249637Sjkim            "ASL declared %u, ACPI requires %u",
187249637Sjkim            AmlParamCount, RequiredParamCount));
188249637Sjkim    }
189249637Sjkim    else if ((AmlParamCount > RequiredParamCount) &&
190249637Sjkim        !(Predefined->Info.ArgumentList & ARG_COUNT_IS_MINIMUM))
191249637Sjkim    {
192249637Sjkim        ACPI_BIOS_ERROR_PREDEFINED ((AE_INFO, Pathname, ACPI_WARN_ALWAYS,
193249637Sjkim            "Excess arguments - "
194249637Sjkim            "ASL declared %u, ACPI requires %u",
195249637Sjkim            AmlParamCount, RequiredParamCount));
196249637Sjkim    }
197249637Sjkim}
198249637Sjkim
199249637Sjkim
200249637Sjkim/*******************************************************************************
201249637Sjkim *
202249637Sjkim * FUNCTION:    AcpiNsCheckArgumentCount
203249637Sjkim *
204249637Sjkim * PARAMETERS:  Pathname        - Full pathname to the node (for error msgs)
205249637Sjkim *              Node            - Namespace node for the method/object
206249637Sjkim *              UserParamCount  - Number of args passed in by the caller
207249637Sjkim *              Predefined      - Pointer to entry in predefined name table
208249637Sjkim *
209249637Sjkim * RETURN:      None
210249637Sjkim *
211249637Sjkim * DESCRIPTION: Check that incoming argument count matches the declared
212249637Sjkim *              parameter count (in the ASL/AML) for an object.
213249637Sjkim *
214249637Sjkim ******************************************************************************/
215249637Sjkim
216249637Sjkimvoid
217249637SjkimAcpiNsCheckArgumentCount (
218249637Sjkim    char                        *Pathname,
219249637Sjkim    ACPI_NAMESPACE_NODE         *Node,
220249637Sjkim    UINT32                      UserParamCount,
221249637Sjkim    const ACPI_PREDEFINED_INFO  *Predefined)
222249637Sjkim{
223249637Sjkim    UINT32                      AmlParamCount;
224249637Sjkim    UINT32                      RequiredParamCount;
225249637Sjkim
226249637Sjkim
227249637Sjkim    if (!Predefined)
228249637Sjkim    {
229249637Sjkim        /*
230249637Sjkim         * Not a predefined name. Check the incoming user argument count
231249637Sjkim         * against the count that is specified in the method/object.
232249637Sjkim         */
233249637Sjkim        if (Node->Type != ACPI_TYPE_METHOD)
234249637Sjkim        {
235249637Sjkim            if (UserParamCount)
236249637Sjkim            {
237249637Sjkim                ACPI_INFO_PREDEFINED ((AE_INFO, Pathname, ACPI_WARN_ALWAYS,
238249637Sjkim                    "%u arguments were passed to a non-method ACPI object (%s)",
239249637Sjkim                    UserParamCount, AcpiUtGetTypeName (Node->Type)));
240249637Sjkim            }
241249637Sjkim
242249637Sjkim            return;
243249637Sjkim        }
244249637Sjkim
245249637Sjkim        /*
246249637Sjkim         * This is a control method. Check the parameter count.
247249637Sjkim         * We can only check the incoming argument count against the
248249637Sjkim         * argument count declared for the method in the ASL/AML.
249249637Sjkim         *
250249637Sjkim         * Emit a message if too few or too many arguments have been passed
251249637Sjkim         * by the caller.
252249637Sjkim         *
253249637Sjkim         * Note: Too many arguments will not cause the method to
254249637Sjkim         * fail. However, the method will fail if there are too few
255249637Sjkim         * arguments and the method attempts to use one of the missing ones.
256249637Sjkim         */
257249637Sjkim        AmlParamCount = Node->Object->Method.ParamCount;
258249637Sjkim
259249637Sjkim        if (UserParamCount < AmlParamCount)
260249637Sjkim        {
261249637Sjkim            ACPI_WARN_PREDEFINED ((AE_INFO, Pathname, ACPI_WARN_ALWAYS,
262249637Sjkim                "Insufficient arguments - "
263249637Sjkim                "Caller passed %u, method requires %u",
264249637Sjkim                UserParamCount, AmlParamCount));
265249637Sjkim        }
266249637Sjkim        else if (UserParamCount > AmlParamCount)
267249637Sjkim        {
268249637Sjkim            ACPI_INFO_PREDEFINED ((AE_INFO, Pathname, ACPI_WARN_ALWAYS,
269249637Sjkim                "Excess arguments - "
270249637Sjkim                "Caller passed %u, method requires %u",
271249637Sjkim                UserParamCount, AmlParamCount));
272249637Sjkim        }
273249637Sjkim
274249637Sjkim        return;
275249637Sjkim    }
276249637Sjkim
277249637Sjkim    /*
278249637Sjkim     * This is a predefined name. Validate the user-supplied parameter
279249637Sjkim     * count against the ACPI specification. We don't validate against
280249637Sjkim     * the method itself because what is important here is that the
281249637Sjkim     * caller is in conformance with the spec. (The arg count for the
282249637Sjkim     * method was checked against the ACPI spec earlier.)
283249637Sjkim     *
284249637Sjkim     * Some methods are allowed to have a "minimum" number of args (_SCP)
285249637Sjkim     * because their definition in ACPI has changed over time.
286249637Sjkim     */
287306536Sjkim    RequiredParamCount =
288306536Sjkim        METHOD_GET_ARG_COUNT (Predefined->Info.ArgumentList);
289249637Sjkim
290249637Sjkim    if (UserParamCount < RequiredParamCount)
291249637Sjkim    {
292249637Sjkim        ACPI_WARN_PREDEFINED ((AE_INFO, Pathname, ACPI_WARN_ALWAYS,
293249637Sjkim            "Insufficient arguments - "
294249637Sjkim            "Caller passed %u, ACPI requires %u",
295249637Sjkim            UserParamCount, RequiredParamCount));
296249637Sjkim    }
297249637Sjkim    else if ((UserParamCount > RequiredParamCount) &&
298249637Sjkim        !(Predefined->Info.ArgumentList & ARG_COUNT_IS_MINIMUM))
299249637Sjkim    {
300249637Sjkim        ACPI_INFO_PREDEFINED ((AE_INFO, Pathname, ACPI_WARN_ALWAYS,
301249637Sjkim            "Excess arguments - "
302249637Sjkim            "Caller passed %u, ACPI requires %u",
303249637Sjkim            UserParamCount, RequiredParamCount));
304249637Sjkim    }
305249637Sjkim}
306