xref: /illumos-gate/usr/src/common/acpica/utilities/utmisc.c (revision 45ede40b2394db7967e59f19288fae9b62efd4aa)
1 /*******************************************************************************
2  *
3  * Module Name: utmisc - common utility procedures
4  *
5  ******************************************************************************/
6 
7 /******************************************************************************
8  *
9  * 1. Copyright Notice
10  *
11  * Some or all of this work - Copyright (c) 1999 - 2018, Intel Corp.
12  * All rights reserved.
13  *
14  * 2. License
15  *
16  * 2.1. This is your license from Intel Corp. under its intellectual property
17  * rights. You may have additional license terms from the party that provided
18  * you this software, covering your right to use that party's intellectual
19  * property rights.
20  *
21  * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
22  * copy of the source code appearing in this file ("Covered Code") an
23  * irrevocable, perpetual, worldwide license under Intel's copyrights in the
24  * base code distributed originally by Intel ("Original Intel Code") to copy,
25  * make derivatives, distribute, use and display any portion of the Covered
26  * Code in any form, with the right to sublicense such rights; and
27  *
28  * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
29  * license (with the right to sublicense), under only those claims of Intel
30  * patents that are infringed by the Original Intel Code, to make, use, sell,
31  * offer to sell, and import the Covered Code and derivative works thereof
32  * solely to the minimum extent necessary to exercise the above copyright
33  * license, and in no event shall the patent license extend to any additions
34  * to or modifications of the Original Intel Code. No other license or right
35  * is granted directly or by implication, estoppel or otherwise;
36  *
37  * The above copyright and patent license is granted only if the following
38  * conditions are met:
39  *
40  * 3. Conditions
41  *
42  * 3.1. Redistribution of Source with Rights to Further Distribute Source.
43  * Redistribution of source code of any substantial portion of the Covered
44  * Code or modification with rights to further distribute source must include
45  * the above Copyright Notice, the above License, this list of Conditions,
46  * and the following Disclaimer and Export Compliance provision. In addition,
47  * Licensee must cause all Covered Code to which Licensee contributes to
48  * contain a file documenting the changes Licensee made to create that Covered
49  * Code and the date of any change. Licensee must include in that file the
50  * documentation of any changes made by any predecessor Licensee. Licensee
51  * must include a prominent statement that the modification is derived,
52  * directly or indirectly, from Original Intel Code.
53  *
54  * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
55  * Redistribution of source code of any substantial portion of the Covered
56  * Code or modification without rights to further distribute source must
57  * include the following Disclaimer and Export Compliance provision in the
58  * documentation and/or other materials provided with distribution. In
59  * addition, Licensee may not authorize further sublicense of source of any
60  * portion of the Covered Code, and must include terms to the effect that the
61  * license from Licensee to its licensee is limited to the intellectual
62  * property embodied in the software Licensee provides to its licensee, and
63  * not to intellectual property embodied in modifications its licensee may
64  * make.
65  *
66  * 3.3. Redistribution of Executable. Redistribution in executable form of any
67  * substantial portion of the Covered Code or modification must reproduce the
68  * above Copyright Notice, and the following Disclaimer and Export Compliance
69  * provision in the documentation and/or other materials provided with the
70  * distribution.
71  *
72  * 3.4. Intel retains all right, title, and interest in and to the Original
73  * Intel Code.
74  *
75  * 3.5. Neither the name Intel nor any other trademark owned or controlled by
76  * Intel shall be used in advertising or otherwise to promote the sale, use or
77  * other dealings in products derived from or relating to the Covered Code
78  * without prior written authorization from Intel.
79  *
80  * 4. Disclaimer and Export Compliance
81  *
82  * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
83  * HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
84  * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE,
85  * INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY
86  * UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY
87  * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
88  * PARTICULAR PURPOSE.
89  *
90  * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
91  * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
92  * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
93  * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
94  * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
95  * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS
96  * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
97  * LIMITED REMEDY.
98  *
99  * 4.3. Licensee shall not export, either directly or indirectly, any of this
100  * software or system incorporating such software without first obtaining any
101  * required license or other approval from the U. S. Department of Commerce or
102  * any other agency or department of the United States Government. In the
103  * event Licensee exports any such software from the United States or
104  * re-exports any such software from a foreign destination, Licensee shall
105  * ensure that the distribution and export/re-export of the software is in
106  * compliance with all laws, regulations, orders, or other restrictions of the
107  * U.S. Export Administration Regulations. Licensee agrees that neither it nor
108  * any of its subsidiaries will export/re-export any technical data, process,
109  * software, or service, directly or indirectly, to any country for which the
110  * United States government or any agency thereof requires an export license,
111  * other governmental approval, or letter of assurance, without first obtaining
112  * such license, approval or letter.
113  *
114  *****************************************************************************
115  *
116  * Alternatively, you may choose to be licensed under the terms of the
117  * following license:
118  *
119  * Redistribution and use in source and binary forms, with or without
120  * modification, are permitted provided that the following conditions
121  * are met:
122  * 1. Redistributions of source code must retain the above copyright
123  *    notice, this list of conditions, and the following disclaimer,
124  *    without modification.
125  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
126  *    substantially similar to the "NO WARRANTY" disclaimer below
127  *    ("Disclaimer") and any redistribution must be conditioned upon
128  *    including a substantially similar Disclaimer requirement for further
129  *    binary redistribution.
130  * 3. Neither the names of the above-listed copyright holders nor the names
131  *    of any contributors may be used to endorse or promote products derived
132  *    from this software without specific prior written permission.
133  *
134  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
135  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
136  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
137  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
138  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
139  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
140  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
141  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
142  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
143  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
144  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
145  *
146  * Alternatively, you may choose to be licensed under the terms of the
147  * GNU General Public License ("GPL") version 2 as published by the Free
148  * Software Foundation.
149  *
150  *****************************************************************************/
151 
152 #include "acpi.h"
153 #include "accommon.h"
154 #include "acnamesp.h"
155 
156 
157 #define _COMPONENT          ACPI_UTILITIES
158         ACPI_MODULE_NAME    ("utmisc")
159 
160 
161 /*******************************************************************************
162  *
163  * FUNCTION:    AcpiUtIsPciRootBridge
164  *
165  * PARAMETERS:  Id              - The HID/CID in string format
166  *
167  * RETURN:      TRUE if the Id is a match for a PCI/PCI-Express Root Bridge
168  *
169  * DESCRIPTION: Determine if the input ID is a PCI Root Bridge ID.
170  *
171  ******************************************************************************/
172 
173 BOOLEAN
174 AcpiUtIsPciRootBridge (
175     char                    *Id)
176 {
177 
178     /*
179      * Check if this is a PCI root bridge.
180      * ACPI 3.0+: check for a PCI Express root also.
181      */
182     if (!(strcmp (Id,
183         PCI_ROOT_HID_STRING)) ||
184 
185         !(strcmp (Id,
186         PCI_EXPRESS_ROOT_HID_STRING)))
187     {
188         return (TRUE);
189     }
190 
191     return (FALSE);
192 }
193 
194 
195 #if (defined ACPI_ASL_COMPILER || defined ACPI_EXEC_APP || defined ACPI_NAMES_APP)
196 /*******************************************************************************
197  *
198  * FUNCTION:    AcpiUtIsAmlTable
199  *
200  * PARAMETERS:  Table               - An ACPI table
201  *
202  * RETURN:      TRUE if table contains executable AML; FALSE otherwise
203  *
204  * DESCRIPTION: Check ACPI Signature for a table that contains AML code.
205  *              Currently, these are DSDT,SSDT,PSDT. All other table types are
206  *              data tables that do not contain AML code.
207  *
208  ******************************************************************************/
209 
210 BOOLEAN
211 AcpiUtIsAmlTable (
212     ACPI_TABLE_HEADER       *Table)
213 {
214 
215     /* These are the only tables that contain executable AML */
216 
217     if (ACPI_COMPARE_NAME (Table->Signature, ACPI_SIG_DSDT) ||
218         ACPI_COMPARE_NAME (Table->Signature, ACPI_SIG_PSDT) ||
219         ACPI_COMPARE_NAME (Table->Signature, ACPI_SIG_SSDT) ||
220         ACPI_COMPARE_NAME (Table->Signature, ACPI_SIG_OSDT))
221     {
222         return (TRUE);
223     }
224 
225     return (FALSE);
226 }
227 #endif
228 
229 
230 /*******************************************************************************
231  *
232  * FUNCTION:    AcpiUtDwordByteSwap
233  *
234  * PARAMETERS:  Value           - Value to be converted
235  *
236  * RETURN:      UINT32 integer with bytes swapped
237  *
238  * DESCRIPTION: Convert a 32-bit value to big-endian (swap the bytes)
239  *
240  ******************************************************************************/
241 
242 UINT32
243 AcpiUtDwordByteSwap (
244     UINT32                  Value)
245 {
246     union
247     {
248         UINT32              Value;
249         UINT8               Bytes[4];
250     } Out;
251     union
252     {
253         UINT32              Value;
254         UINT8               Bytes[4];
255     } In;
256 
257 
258     ACPI_FUNCTION_ENTRY ();
259 
260 
261     In.Value = Value;
262 
263     Out.Bytes[0] = In.Bytes[3];
264     Out.Bytes[1] = In.Bytes[2];
265     Out.Bytes[2] = In.Bytes[1];
266     Out.Bytes[3] = In.Bytes[0];
267 
268     return (Out.Value);
269 }
270 
271 
272 /*******************************************************************************
273  *
274  * FUNCTION:    AcpiUtSetIntegerWidth
275  *
276  * PARAMETERS:  Revision            From DSDT header
277  *
278  * RETURN:      None
279  *
280  * DESCRIPTION: Set the global integer bit width based upon the revision
281  *              of the DSDT. For Revision 1 and 0, Integers are 32 bits.
282  *              For Revision 2 and above, Integers are 64 bits. Yes, this
283  *              makes a difference.
284  *
285  ******************************************************************************/
286 
287 void
288 AcpiUtSetIntegerWidth (
289     UINT8                   Revision)
290 {
291 
292     if (Revision < 2)
293     {
294         /* 32-bit case */
295 
296         AcpiGbl_IntegerBitWidth = 32;
297         AcpiGbl_IntegerNybbleWidth = 8;
298         AcpiGbl_IntegerByteWidth = 4;
299     }
300     else
301     {
302         /* 64-bit case (ACPI 2.0+) */
303 
304         AcpiGbl_IntegerBitWidth = 64;
305         AcpiGbl_IntegerNybbleWidth = 16;
306         AcpiGbl_IntegerByteWidth = 8;
307     }
308 }
309 
310 
311 /*******************************************************************************
312  *
313  * FUNCTION:    AcpiUtCreateUpdateStateAndPush
314  *
315  * PARAMETERS:  Object          - Object to be added to the new state
316  *              Action          - Increment/Decrement
317  *              StateList       - List the state will be added to
318  *
319  * RETURN:      Status
320  *
321  * DESCRIPTION: Create a new state and push it
322  *
323  ******************************************************************************/
324 
325 ACPI_STATUS
326 AcpiUtCreateUpdateStateAndPush (
327     ACPI_OPERAND_OBJECT     *Object,
328     UINT16                  Action,
329     ACPI_GENERIC_STATE      **StateList)
330 {
331     ACPI_GENERIC_STATE       *State;
332 
333 
334     ACPI_FUNCTION_ENTRY ();
335 
336 
337     /* Ignore null objects; these are expected */
338 
339     if (!Object)
340     {
341         return (AE_OK);
342     }
343 
344     State = AcpiUtCreateUpdateState (Object, Action);
345     if (!State)
346     {
347         return (AE_NO_MEMORY);
348     }
349 
350     AcpiUtPushGenericState (StateList, State);
351     return (AE_OK);
352 }
353 
354 
355 /*******************************************************************************
356  *
357  * FUNCTION:    AcpiUtWalkPackageTree
358  *
359  * PARAMETERS:  SourceObject        - The package to walk
360  *              TargetObject        - Target object (if package is being copied)
361  *              WalkCallback        - Called once for each package element
362  *              Context             - Passed to the callback function
363  *
364  * RETURN:      Status
365  *
366  * DESCRIPTION: Walk through a package, including subpackages
367  *
368  ******************************************************************************/
369 
370 ACPI_STATUS
371 AcpiUtWalkPackageTree (
372     ACPI_OPERAND_OBJECT     *SourceObject,
373     void                    *TargetObject,
374     ACPI_PKG_CALLBACK       WalkCallback,
375     void                    *Context)
376 {
377     ACPI_STATUS             Status = AE_OK;
378     ACPI_GENERIC_STATE      *StateList = NULL;
379     ACPI_GENERIC_STATE      *State;
380     ACPI_OPERAND_OBJECT     *ThisSourceObj;
381     UINT32                  ThisIndex;
382 
383 
384     ACPI_FUNCTION_TRACE (UtWalkPackageTree);
385 
386 
387     State = AcpiUtCreatePkgState (SourceObject, TargetObject, 0);
388     if (!State)
389     {
390         return_ACPI_STATUS (AE_NO_MEMORY);
391     }
392 
393     while (State)
394     {
395         /* Get one element of the package */
396 
397         ThisIndex = State->Pkg.Index;
398         ThisSourceObj =
399             State->Pkg.SourceObject->Package.Elements[ThisIndex];
400         State->Pkg.ThisTargetObj =
401             &State->Pkg.SourceObject->Package.Elements[ThisIndex];
402 
403         /*
404          * Check for:
405          * 1) An uninitialized package element. It is completely
406          *    legal to declare a package and leave it uninitialized
407          * 2) Not an internal object - can be a namespace node instead
408          * 3) Any type other than a package. Packages are handled in else
409          *    case below.
410          */
411         if ((!ThisSourceObj) ||
412             (ACPI_GET_DESCRIPTOR_TYPE (ThisSourceObj) !=
413                 ACPI_DESC_TYPE_OPERAND) ||
414             (ThisSourceObj->Common.Type != ACPI_TYPE_PACKAGE))
415         {
416             Status = WalkCallback (ACPI_COPY_TYPE_SIMPLE, ThisSourceObj,
417                 State, Context);
418             if (ACPI_FAILURE (Status))
419             {
420                 return_ACPI_STATUS (Status);
421             }
422 
423             State->Pkg.Index++;
424             while (State->Pkg.Index >=
425                 State->Pkg.SourceObject->Package.Count)
426             {
427                 /*
428                  * We've handled all of the objects at this level,  This means
429                  * that we have just completed a package. That package may
430                  * have contained one or more packages itself.
431                  *
432                  * Delete this state and pop the previous state (package).
433                  */
434                 AcpiUtDeleteGenericState (State);
435                 State = AcpiUtPopGenericState (&StateList);
436 
437                 /* Finished when there are no more states */
438 
439                 if (!State)
440                 {
441                     /*
442                      * We have handled all of the objects in the top level
443                      * package just add the length of the package objects
444                      * and exit
445                      */
446                     return_ACPI_STATUS (AE_OK);
447                 }
448 
449                 /*
450                  * Go back up a level and move the index past the just
451                  * completed package object.
452                  */
453                 State->Pkg.Index++;
454             }
455         }
456         else
457         {
458             /* This is a subobject of type package */
459 
460             Status = WalkCallback (
461                 ACPI_COPY_TYPE_PACKAGE, ThisSourceObj, State, Context);
462             if (ACPI_FAILURE (Status))
463             {
464                 return_ACPI_STATUS (Status);
465             }
466 
467             /*
468              * Push the current state and create a new one
469              * The callback above returned a new target package object.
470              */
471             AcpiUtPushGenericState (&StateList, State);
472             State = AcpiUtCreatePkgState (
473                 ThisSourceObj, State->Pkg.ThisTargetObj, 0);
474             if (!State)
475             {
476                 /* Free any stacked Update State objects */
477 
478                 while (StateList)
479                 {
480                     State = AcpiUtPopGenericState (&StateList);
481                     AcpiUtDeleteGenericState (State);
482                 }
483                 return_ACPI_STATUS (AE_NO_MEMORY);
484             }
485         }
486     }
487 
488     /* We should never get here */
489 
490     ACPI_ERROR ((AE_INFO,
491         "State list did not terminate correctly"));
492 
493     return_ACPI_STATUS (AE_AML_INTERNAL);
494 }
495 
496 
497 #ifdef ACPI_DEBUG_OUTPUT
498 /*******************************************************************************
499  *
500  * FUNCTION:    AcpiUtDisplayInitPathname
501  *
502  * PARAMETERS:  Type                - Object type of the node
503  *              ObjHandle           - Handle whose pathname will be displayed
504  *              Path                - Additional path string to be appended.
505  *                                      (NULL if no extra path)
506  *
507  * RETURN:      ACPI_STATUS
508  *
509  * DESCRIPTION: Display full pathname of an object, DEBUG ONLY
510  *
511  ******************************************************************************/
512 
513 void
514 AcpiUtDisplayInitPathname (
515     UINT8                   Type,
516     ACPI_NAMESPACE_NODE     *ObjHandle,
517     const char              *Path)
518 {
519     ACPI_STATUS             Status;
520     ACPI_BUFFER             Buffer;
521 
522 
523     ACPI_FUNCTION_ENTRY ();
524 
525 
526     /* Only print the path if the appropriate debug level is enabled */
527 
528     if (!(AcpiDbgLevel & ACPI_LV_INIT_NAMES))
529     {
530         return;
531     }
532 
533     /* Get the full pathname to the node */
534 
535     Buffer.Length = ACPI_ALLOCATE_LOCAL_BUFFER;
536     Status = AcpiNsHandleToPathname (ObjHandle, &Buffer, TRUE);
537     if (ACPI_FAILURE (Status))
538     {
539         return;
540     }
541 
542     /* Print what we're doing */
543 
544     switch (Type)
545     {
546     case ACPI_TYPE_METHOD:
547 
548         AcpiOsPrintf ("Executing    ");
549         break;
550 
551     default:
552 
553         AcpiOsPrintf ("Initializing ");
554         break;
555     }
556 
557     /* Print the object type and pathname */
558 
559     AcpiOsPrintf ("%-12s  %s",
560         AcpiUtGetTypeName (Type), (char *) Buffer.Pointer);
561 
562     /* Extra path is used to append names like _STA, _INI, etc. */
563 
564     if (Path)
565     {
566         AcpiOsPrintf (".%s", Path);
567     }
568     AcpiOsPrintf ("\n");
569 
570     ACPI_FREE (Buffer.Pointer);
571 }
572 #endif
573