05ad32adf2e67ab1ff0d7d47304afff848dac7b7
[reactos.git] / drivers / bus / acpi / acpica / utilities / utmisc.c
1 /*******************************************************************************
2 *
3 * Module Name: utmisc - common utility procedures
4 *
5 ******************************************************************************/
6
7 /*
8 * Copyright (C) 2000 - 2018, 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 #include "acpi.h"
45 #include "accommon.h"
46 #include "acnamesp.h"
47
48
49 #define _COMPONENT ACPI_UTILITIES
50 ACPI_MODULE_NAME ("utmisc")
51
52
53 /*******************************************************************************
54 *
55 * FUNCTION: AcpiUtIsPciRootBridge
56 *
57 * PARAMETERS: Id - The HID/CID in string format
58 *
59 * RETURN: TRUE if the Id is a match for a PCI/PCI-Express Root Bridge
60 *
61 * DESCRIPTION: Determine if the input ID is a PCI Root Bridge ID.
62 *
63 ******************************************************************************/
64
65 BOOLEAN
66 AcpiUtIsPciRootBridge (
67 char *Id)
68 {
69
70 /*
71 * Check if this is a PCI root bridge.
72 * ACPI 3.0+: check for a PCI Express root also.
73 */
74 if (!(strcmp (Id,
75 PCI_ROOT_HID_STRING)) ||
76
77 !(strcmp (Id,
78 PCI_EXPRESS_ROOT_HID_STRING)))
79 {
80 return (TRUE);
81 }
82
83 return (FALSE);
84 }
85
86
87 #if (defined ACPI_ASL_COMPILER || defined ACPI_EXEC_APP || defined ACPI_NAMES_APP)
88 /*******************************************************************************
89 *
90 * FUNCTION: AcpiUtIsAmlTable
91 *
92 * PARAMETERS: Table - An ACPI table
93 *
94 * RETURN: TRUE if table contains executable AML; FALSE otherwise
95 *
96 * DESCRIPTION: Check ACPI Signature for a table that contains AML code.
97 * Currently, these are DSDT,SSDT,PSDT. All other table types are
98 * data tables that do not contain AML code.
99 *
100 ******************************************************************************/
101
102 BOOLEAN
103 AcpiUtIsAmlTable (
104 ACPI_TABLE_HEADER *Table)
105 {
106
107 /* These are the only tables that contain executable AML */
108
109 if (ACPI_COMPARE_NAME (Table->Signature, ACPI_SIG_DSDT) ||
110 ACPI_COMPARE_NAME (Table->Signature, ACPI_SIG_PSDT) ||
111 ACPI_COMPARE_NAME (Table->Signature, ACPI_SIG_SSDT) ||
112 ACPI_COMPARE_NAME (Table->Signature, ACPI_SIG_OSDT) ||
113 ACPI_IS_OEM_SIG (Table->Signature))
114 {
115 return (TRUE);
116 }
117
118 return (FALSE);
119 }
120 #endif
121
122
123 /*******************************************************************************
124 *
125 * FUNCTION: AcpiUtDwordByteSwap
126 *
127 * PARAMETERS: Value - Value to be converted
128 *
129 * RETURN: UINT32 integer with bytes swapped
130 *
131 * DESCRIPTION: Convert a 32-bit value to big-endian (swap the bytes)
132 *
133 ******************************************************************************/
134
135 UINT32
136 AcpiUtDwordByteSwap (
137 UINT32 Value)
138 {
139 union
140 {
141 UINT32 Value;
142 UINT8 Bytes[4];
143 } Out;
144 union
145 {
146 UINT32 Value;
147 UINT8 Bytes[4];
148 } In;
149
150
151 ACPI_FUNCTION_ENTRY ();
152
153
154 In.Value = Value;
155
156 Out.Bytes[0] = In.Bytes[3];
157 Out.Bytes[1] = In.Bytes[2];
158 Out.Bytes[2] = In.Bytes[1];
159 Out.Bytes[3] = In.Bytes[0];
160
161 return (Out.Value);
162 }
163
164
165 /*******************************************************************************
166 *
167 * FUNCTION: AcpiUtSetIntegerWidth
168 *
169 * PARAMETERS: Revision From DSDT header
170 *
171 * RETURN: None
172 *
173 * DESCRIPTION: Set the global integer bit width based upon the revision
174 * of the DSDT. For Revision 1 and 0, Integers are 32 bits.
175 * For Revision 2 and above, Integers are 64 bits. Yes, this
176 * makes a difference.
177 *
178 ******************************************************************************/
179
180 void
181 AcpiUtSetIntegerWidth (
182 UINT8 Revision)
183 {
184
185 if (Revision < 2)
186 {
187 /* 32-bit case */
188
189 AcpiGbl_IntegerBitWidth = 32;
190 AcpiGbl_IntegerNybbleWidth = 8;
191 AcpiGbl_IntegerByteWidth = 4;
192 }
193 else
194 {
195 /* 64-bit case (ACPI 2.0+) */
196
197 AcpiGbl_IntegerBitWidth = 64;
198 AcpiGbl_IntegerNybbleWidth = 16;
199 AcpiGbl_IntegerByteWidth = 8;
200 }
201 }
202
203
204 /*******************************************************************************
205 *
206 * FUNCTION: AcpiUtCreateUpdateStateAndPush
207 *
208 * PARAMETERS: Object - Object to be added to the new state
209 * Action - Increment/Decrement
210 * StateList - List the state will be added to
211 *
212 * RETURN: Status
213 *
214 * DESCRIPTION: Create a new state and push it
215 *
216 ******************************************************************************/
217
218 ACPI_STATUS
219 AcpiUtCreateUpdateStateAndPush (
220 ACPI_OPERAND_OBJECT *Object,
221 UINT16 Action,
222 ACPI_GENERIC_STATE **StateList)
223 {
224 ACPI_GENERIC_STATE *State;
225
226
227 ACPI_FUNCTION_ENTRY ();
228
229
230 /* Ignore null objects; these are expected */
231
232 if (!Object)
233 {
234 return (AE_OK);
235 }
236
237 State = AcpiUtCreateUpdateState (Object, Action);
238 if (!State)
239 {
240 return (AE_NO_MEMORY);
241 }
242
243 AcpiUtPushGenericState (StateList, State);
244 return (AE_OK);
245 }
246
247
248 /*******************************************************************************
249 *
250 * FUNCTION: AcpiUtWalkPackageTree
251 *
252 * PARAMETERS: SourceObject - The package to walk
253 * TargetObject - Target object (if package is being copied)
254 * WalkCallback - Called once for each package element
255 * Context - Passed to the callback function
256 *
257 * RETURN: Status
258 *
259 * DESCRIPTION: Walk through a package, including subpackages
260 *
261 ******************************************************************************/
262
263 ACPI_STATUS
264 AcpiUtWalkPackageTree (
265 ACPI_OPERAND_OBJECT *SourceObject,
266 void *TargetObject,
267 ACPI_PKG_CALLBACK WalkCallback,
268 void *Context)
269 {
270 ACPI_STATUS Status = AE_OK;
271 ACPI_GENERIC_STATE *StateList = NULL;
272 ACPI_GENERIC_STATE *State;
273 ACPI_OPERAND_OBJECT *ThisSourceObj;
274 UINT32 ThisIndex;
275
276
277 ACPI_FUNCTION_TRACE (UtWalkPackageTree);
278
279
280 State = AcpiUtCreatePkgState (SourceObject, TargetObject, 0);
281 if (!State)
282 {
283 return_ACPI_STATUS (AE_NO_MEMORY);
284 }
285
286 while (State)
287 {
288 /* Get one element of the package */
289
290 ThisIndex = State->Pkg.Index;
291 ThisSourceObj =
292 State->Pkg.SourceObject->Package.Elements[ThisIndex];
293 State->Pkg.ThisTargetObj =
294 &State->Pkg.SourceObject->Package.Elements[ThisIndex];
295
296 /*
297 * Check for:
298 * 1) An uninitialized package element. It is completely
299 * legal to declare a package and leave it uninitialized
300 * 2) Not an internal object - can be a namespace node instead
301 * 3) Any type other than a package. Packages are handled in else
302 * case below.
303 */
304 if ((!ThisSourceObj) ||
305 (ACPI_GET_DESCRIPTOR_TYPE (ThisSourceObj) !=
306 ACPI_DESC_TYPE_OPERAND) ||
307 (ThisSourceObj->Common.Type != ACPI_TYPE_PACKAGE))
308 {
309 Status = WalkCallback (ACPI_COPY_TYPE_SIMPLE, ThisSourceObj,
310 State, Context);
311 if (ACPI_FAILURE (Status))
312 {
313 return_ACPI_STATUS (Status);
314 }
315
316 State->Pkg.Index++;
317 while (State->Pkg.Index >=
318 State->Pkg.SourceObject->Package.Count)
319 {
320 /*
321 * We've handled all of the objects at this level, This means
322 * that we have just completed a package. That package may
323 * have contained one or more packages itself.
324 *
325 * Delete this state and pop the previous state (package).
326 */
327 AcpiUtDeleteGenericState (State);
328 State = AcpiUtPopGenericState (&StateList);
329
330 /* Finished when there are no more states */
331
332 if (!State)
333 {
334 /*
335 * We have handled all of the objects in the top level
336 * package just add the length of the package objects
337 * and exit
338 */
339 return_ACPI_STATUS (AE_OK);
340 }
341
342 /*
343 * Go back up a level and move the index past the just
344 * completed package object.
345 */
346 State->Pkg.Index++;
347 }
348 }
349 else
350 {
351 /* This is a subobject of type package */
352
353 Status = WalkCallback (
354 ACPI_COPY_TYPE_PACKAGE, ThisSourceObj, State, Context);
355 if (ACPI_FAILURE (Status))
356 {
357 return_ACPI_STATUS (Status);
358 }
359
360 /*
361 * Push the current state and create a new one
362 * The callback above returned a new target package object.
363 */
364 AcpiUtPushGenericState (&StateList, State);
365 State = AcpiUtCreatePkgState (
366 ThisSourceObj, State->Pkg.ThisTargetObj, 0);
367 if (!State)
368 {
369 /* Free any stacked Update State objects */
370
371 while (StateList)
372 {
373 State = AcpiUtPopGenericState (&StateList);
374 AcpiUtDeleteGenericState (State);
375 }
376 return_ACPI_STATUS (AE_NO_MEMORY);
377 }
378 }
379 }
380
381 /* We should never get here */
382
383 ACPI_ERROR ((AE_INFO,
384 "State list did not terminate correctly"));
385
386 return_ACPI_STATUS (AE_AML_INTERNAL);
387 }
388
389
390 #ifdef ACPI_DEBUG_OUTPUT
391 /*******************************************************************************
392 *
393 * FUNCTION: AcpiUtDisplayInitPathname
394 *
395 * PARAMETERS: Type - Object type of the node
396 * ObjHandle - Handle whose pathname will be displayed
397 * Path - Additional path string to be appended.
398 * (NULL if no extra path)
399 *
400 * RETURN: ACPI_STATUS
401 *
402 * DESCRIPTION: Display full pathname of an object, DEBUG ONLY
403 *
404 ******************************************************************************/
405
406 void
407 AcpiUtDisplayInitPathname (
408 UINT8 Type,
409 ACPI_NAMESPACE_NODE *ObjHandle,
410 const char *Path)
411 {
412 ACPI_STATUS Status;
413 ACPI_BUFFER Buffer;
414
415
416 ACPI_FUNCTION_ENTRY ();
417
418
419 /* Only print the path if the appropriate debug level is enabled */
420
421 if (!(AcpiDbgLevel & ACPI_LV_INIT_NAMES))
422 {
423 return;
424 }
425
426 /* Get the full pathname to the node */
427
428 Buffer.Length = ACPI_ALLOCATE_LOCAL_BUFFER;
429 Status = AcpiNsHandleToPathname (ObjHandle, &Buffer, TRUE);
430 if (ACPI_FAILURE (Status))
431 {
432 return;
433 }
434
435 /* Print what we're doing */
436
437 switch (Type)
438 {
439 case ACPI_TYPE_METHOD:
440
441 AcpiOsPrintf ("Executing ");
442 break;
443
444 default:
445
446 AcpiOsPrintf ("Initializing ");
447 break;
448 }
449
450 /* Print the object type and pathname */
451
452 AcpiOsPrintf ("%-12s %s",
453 AcpiUtGetTypeName (Type), (char *) Buffer.Pointer);
454
455 /* Extra path is used to append names like _STA, _INI, etc. */
456
457 if (Path)
458 {
459 AcpiOsPrintf (".%s", Path);
460 }
461 AcpiOsPrintf ("\n");
462
463 ACPI_FREE (Buffer.Pointer);
464 }
465 #endif