]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - sys/contrib/dev/acpica/components/executer/exutils.c
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.git] / sys / contrib / dev / acpica / components / executer / exutils.c
1 /******************************************************************************
2  *
3  * Module Name: exutils - interpreter/scanner utilities
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 __EXUTILS_C__
45
46 /*
47  * DEFINE_AML_GLOBALS is tested in amlcode.h
48  * to determine whether certain global names should be "defined" or only
49  * "declared" in the current compilation. This enhances maintainability
50  * by enabling a single header file to embody all knowledge of the names
51  * in question.
52  *
53  * Exactly one module of any executable should #define DEFINE_GLOBALS
54  * before #including the header files which use this convention. The
55  * names in question will be defined and initialized in that module,
56  * and declared as extern in all other modules which #include those
57  * header files.
58  */
59
60 #define DEFINE_AML_GLOBALS
61
62 #include <contrib/dev/acpica/include/acpi.h>
63 #include <contrib/dev/acpica/include/accommon.h>
64 #include <contrib/dev/acpica/include/acinterp.h>
65 #include <contrib/dev/acpica/include/amlcode.h>
66
67 #define _COMPONENT          ACPI_EXECUTER
68         ACPI_MODULE_NAME    ("exutils")
69
70 /* Local prototypes */
71
72 static UINT32
73 AcpiExDigitsNeeded (
74     UINT64                  Value,
75     UINT32                  Base);
76
77
78 #ifndef ACPI_NO_METHOD_EXECUTION
79 /*******************************************************************************
80  *
81  * FUNCTION:    AcpiExEnterInterpreter
82  *
83  * PARAMETERS:  None
84  *
85  * RETURN:      None
86  *
87  * DESCRIPTION: Enter the interpreter execution region. Failure to enter
88  *              the interpreter region is a fatal system error. Used in
89  *              conjunction with ExitInterpreter.
90  *
91  ******************************************************************************/
92
93 void
94 AcpiExEnterInterpreter (
95     void)
96 {
97     ACPI_STATUS             Status;
98
99
100     ACPI_FUNCTION_TRACE (ExEnterInterpreter);
101
102
103     Status = AcpiUtAcquireMutex (ACPI_MTX_INTERPRETER);
104     if (ACPI_FAILURE (Status))
105     {
106         ACPI_ERROR ((AE_INFO, "Could not acquire AML Interpreter mutex"));
107     }
108
109     return_VOID;
110 }
111
112
113 /*******************************************************************************
114  *
115  * FUNCTION:    AcpiExReacquireInterpreter
116  *
117  * PARAMETERS:  None
118  *
119  * RETURN:      None
120  *
121  * DESCRIPTION: Reacquire the interpreter execution region from within the
122  *              interpreter code. Failure to enter the interpreter region is a
123  *              fatal system error. Used in conjunction with
124  *              RelinquishInterpreter
125  *
126  ******************************************************************************/
127
128 void
129 AcpiExReacquireInterpreter (
130     void)
131 {
132     ACPI_FUNCTION_TRACE (ExReacquireInterpreter);
133
134
135     /*
136      * If the global serialized flag is set, do not release the interpreter,
137      * since it was not actually released by AcpiExRelinquishInterpreter.
138      * This forces the interpreter to be single threaded.
139      */
140     if (!AcpiGbl_AllMethodsSerialized)
141     {
142         AcpiExEnterInterpreter ();
143     }
144
145     return_VOID;
146 }
147
148
149 /*******************************************************************************
150  *
151  * FUNCTION:    AcpiExExitInterpreter
152  *
153  * PARAMETERS:  None
154  *
155  * RETURN:      None
156  *
157  * DESCRIPTION: Exit the interpreter execution region. This is the top level
158  *              routine used to exit the interpreter when all processing has
159  *              been completed.
160  *
161  ******************************************************************************/
162
163 void
164 AcpiExExitInterpreter (
165     void)
166 {
167     ACPI_STATUS             Status;
168
169
170     ACPI_FUNCTION_TRACE (ExExitInterpreter);
171
172
173     Status = AcpiUtReleaseMutex (ACPI_MTX_INTERPRETER);
174     if (ACPI_FAILURE (Status))
175     {
176         ACPI_ERROR ((AE_INFO, "Could not release AML Interpreter mutex"));
177     }
178
179     return_VOID;
180 }
181
182
183 /*******************************************************************************
184  *
185  * FUNCTION:    AcpiExRelinquishInterpreter
186  *
187  * PARAMETERS:  None
188  *
189  * RETURN:      None
190  *
191  * DESCRIPTION: Exit the interpreter execution region, from within the
192  *              interpreter - before attempting an operation that will possibly
193  *              block the running thread.
194  *
195  * Cases where the interpreter is unlocked internally
196  *      1) Method to be blocked on a Sleep() AML opcode
197  *      2) Method to be blocked on an Acquire() AML opcode
198  *      3) Method to be blocked on a Wait() AML opcode
199  *      4) Method to be blocked to acquire the global lock
200  *      5) Method to be blocked waiting to execute a serialized control method
201  *          that is currently executing
202  *      6) About to invoke a user-installed opregion handler
203  *
204  ******************************************************************************/
205
206 void
207 AcpiExRelinquishInterpreter (
208     void)
209 {
210     ACPI_FUNCTION_TRACE (ExRelinquishInterpreter);
211
212
213     /*
214      * If the global serialized flag is set, do not release the interpreter.
215      * This forces the interpreter to be single threaded.
216      */
217     if (!AcpiGbl_AllMethodsSerialized)
218     {
219         AcpiExExitInterpreter ();
220     }
221
222     return_VOID;
223 }
224
225
226 /*******************************************************************************
227  *
228  * FUNCTION:    AcpiExTruncateFor32bitTable
229  *
230  * PARAMETERS:  ObjDesc         - Object to be truncated
231  *
232  * RETURN:      TRUE if a truncation was performed, FALSE otherwise.
233  *
234  * DESCRIPTION: Truncate an ACPI Integer to 32 bits if the execution mode is
235  *              32-bit, as determined by the revision of the DSDT.
236  *
237  ******************************************************************************/
238
239 BOOLEAN
240 AcpiExTruncateFor32bitTable (
241     ACPI_OPERAND_OBJECT     *ObjDesc)
242 {
243
244     ACPI_FUNCTION_ENTRY ();
245
246
247     /*
248      * Object must be a valid number and we must be executing
249      * a control method. Object could be NS node for AML_INT_NAMEPATH_OP.
250      */
251     if ((!ObjDesc) ||
252         (ACPI_GET_DESCRIPTOR_TYPE (ObjDesc) != ACPI_DESC_TYPE_OPERAND) ||
253         (ObjDesc->Common.Type != ACPI_TYPE_INTEGER))
254     {
255         return (FALSE);
256     }
257
258     if ((AcpiGbl_IntegerByteWidth == 4) &&
259         (ObjDesc->Integer.Value > (UINT64) ACPI_UINT32_MAX))
260     {
261         /*
262          * We are executing in a 32-bit ACPI table.
263          * Truncate the value to 32 bits by zeroing out the upper 32-bit field
264          */
265         ObjDesc->Integer.Value &= (UINT64) ACPI_UINT32_MAX;
266         return (TRUE);
267     }
268
269     return (FALSE);
270 }
271
272
273 /*******************************************************************************
274  *
275  * FUNCTION:    AcpiExAcquireGlobalLock
276  *
277  * PARAMETERS:  FieldFlags            - Flags with Lock rule:
278  *                                      AlwaysLock or NeverLock
279  *
280  * RETURN:      None
281  *
282  * DESCRIPTION: Obtain the ACPI hardware Global Lock, only if the field
283  *              flags specifiy that it is to be obtained before field access.
284  *
285  ******************************************************************************/
286
287 void
288 AcpiExAcquireGlobalLock (
289     UINT32                  FieldFlags)
290 {
291     ACPI_STATUS             Status;
292
293
294     ACPI_FUNCTION_TRACE (ExAcquireGlobalLock);
295
296
297     /* Only use the lock if the AlwaysLock bit is set */
298
299     if (!(FieldFlags & AML_FIELD_LOCK_RULE_MASK))
300     {
301         return_VOID;
302     }
303
304     /* Attempt to get the global lock, wait forever */
305
306     Status = AcpiExAcquireMutexObject (ACPI_WAIT_FOREVER,
307                 AcpiGbl_GlobalLockMutex, AcpiOsGetThreadId ());
308
309     if (ACPI_FAILURE (Status))
310     {
311         ACPI_EXCEPTION ((AE_INFO, Status,
312             "Could not acquire Global Lock"));
313     }
314
315     return_VOID;
316 }
317
318
319 /*******************************************************************************
320  *
321  * FUNCTION:    AcpiExReleaseGlobalLock
322  *
323  * PARAMETERS:  FieldFlags            - Flags with Lock rule:
324  *                                      AlwaysLock or NeverLock
325  *
326  * RETURN:      None
327  *
328  * DESCRIPTION: Release the ACPI hardware Global Lock
329  *
330  ******************************************************************************/
331
332 void
333 AcpiExReleaseGlobalLock (
334     UINT32                  FieldFlags)
335 {
336     ACPI_STATUS             Status;
337
338
339     ACPI_FUNCTION_TRACE (ExReleaseGlobalLock);
340
341
342     /* Only use the lock if the AlwaysLock bit is set */
343
344     if (!(FieldFlags & AML_FIELD_LOCK_RULE_MASK))
345     {
346         return_VOID;
347     }
348
349     /* Release the global lock */
350
351     Status = AcpiExReleaseMutexObject (AcpiGbl_GlobalLockMutex);
352     if (ACPI_FAILURE (Status))
353     {
354         /* Report the error, but there isn't much else we can do */
355
356         ACPI_EXCEPTION ((AE_INFO, Status,
357             "Could not release Global Lock"));
358     }
359
360     return_VOID;
361 }
362
363
364 /*******************************************************************************
365  *
366  * FUNCTION:    AcpiExDigitsNeeded
367  *
368  * PARAMETERS:  Value           - Value to be represented
369  *              Base            - Base of representation
370  *
371  * RETURN:      The number of digits.
372  *
373  * DESCRIPTION: Calculate the number of digits needed to represent the Value
374  *              in the given Base (Radix)
375  *
376  ******************************************************************************/
377
378 static UINT32
379 AcpiExDigitsNeeded (
380     UINT64                  Value,
381     UINT32                  Base)
382 {
383     UINT32                  NumDigits;
384     UINT64                  CurrentValue;
385
386
387     ACPI_FUNCTION_TRACE (ExDigitsNeeded);
388
389
390     /* UINT64 is unsigned, so we don't worry about a '-' prefix */
391
392     if (Value == 0)
393     {
394         return_UINT32 (1);
395     }
396
397     CurrentValue = Value;
398     NumDigits = 0;
399
400     /* Count the digits in the requested base */
401
402     while (CurrentValue)
403     {
404         (void) AcpiUtShortDivide (CurrentValue, Base, &CurrentValue, NULL);
405         NumDigits++;
406     }
407
408     return_UINT32 (NumDigits);
409 }
410
411
412 /*******************************************************************************
413  *
414  * FUNCTION:    AcpiExEisaIdToString
415  *
416  * PARAMETERS:  CompressedId    - EISAID to be converted
417  *              OutString       - Where to put the converted string (8 bytes)
418  *
419  * RETURN:      None
420  *
421  * DESCRIPTION: Convert a numeric EISAID to string representation. Return
422  *              buffer must be large enough to hold the string. The string
423  *              returned is always exactly of length ACPI_EISAID_STRING_SIZE
424  *              (includes null terminator). The EISAID is always 32 bits.
425  *
426  ******************************************************************************/
427
428 void
429 AcpiExEisaIdToString (
430     char                    *OutString,
431     UINT64                  CompressedId)
432 {
433     UINT32                  SwappedId;
434
435
436     ACPI_FUNCTION_ENTRY ();
437
438
439     /* The EISAID should be a 32-bit integer */
440
441     if (CompressedId > ACPI_UINT32_MAX)
442     {
443         ACPI_WARNING ((AE_INFO,
444             "Expected EISAID is larger than 32 bits: 0x%8.8X%8.8X, truncating",
445             ACPI_FORMAT_UINT64 (CompressedId)));
446     }
447
448     /* Swap ID to big-endian to get contiguous bits */
449
450     SwappedId = AcpiUtDwordByteSwap ((UINT32) CompressedId);
451
452     /* First 3 bytes are uppercase letters. Next 4 bytes are hexadecimal */
453
454     OutString[0] = (char) (0x40 + (((unsigned long) SwappedId >> 26) & 0x1F));
455     OutString[1] = (char) (0x40 + ((SwappedId >> 21) & 0x1F));
456     OutString[2] = (char) (0x40 + ((SwappedId >> 16) & 0x1F));
457     OutString[3] = AcpiUtHexToAsciiChar ((UINT64) SwappedId, 12);
458     OutString[4] = AcpiUtHexToAsciiChar ((UINT64) SwappedId, 8);
459     OutString[5] = AcpiUtHexToAsciiChar ((UINT64) SwappedId, 4);
460     OutString[6] = AcpiUtHexToAsciiChar ((UINT64) SwappedId, 0);
461     OutString[7] = 0;
462 }
463
464
465 /*******************************************************************************
466  *
467  * FUNCTION:    AcpiExIntegerToString
468  *
469  * PARAMETERS:  OutString       - Where to put the converted string. At least
470  *                                21 bytes are needed to hold the largest
471  *                                possible 64-bit integer.
472  *              Value           - Value to be converted
473  *
474  * RETURN:      None, string
475  *
476  * DESCRIPTION: Convert a 64-bit integer to decimal string representation.
477  *              Assumes string buffer is large enough to hold the string. The
478  *              largest string is (ACPI_MAX64_DECIMAL_DIGITS + 1).
479  *
480  ******************************************************************************/
481
482 void
483 AcpiExIntegerToString (
484     char                    *OutString,
485     UINT64                  Value)
486 {
487     UINT32                  Count;
488     UINT32                  DigitsNeeded;
489     UINT32                  Remainder;
490
491
492     ACPI_FUNCTION_ENTRY ();
493
494
495     DigitsNeeded = AcpiExDigitsNeeded (Value, 10);
496     OutString[DigitsNeeded] = 0;
497
498     for (Count = DigitsNeeded; Count > 0; Count--)
499     {
500         (void) AcpiUtShortDivide (Value, 10, &Value, &Remainder);
501         OutString[Count-1] = (char) ('0' + Remainder);\
502     }
503 }
504
505
506 /*******************************************************************************
507  *
508  * FUNCTION:    AcpiIsValidSpaceId
509  *
510  * PARAMETERS:  SpaceId             - ID to be validated
511  *
512  * RETURN:      TRUE if valid/supported ID.
513  *
514  * DESCRIPTION: Validate an operation region SpaceID.
515  *
516  ******************************************************************************/
517
518 BOOLEAN
519 AcpiIsValidSpaceId (
520     UINT8                   SpaceId)
521 {
522
523     if ((SpaceId >= ACPI_NUM_PREDEFINED_REGIONS) &&
524         (SpaceId < ACPI_USER_REGION_BEGIN) &&
525         (SpaceId != ACPI_ADR_SPACE_DATA_TABLE) &&
526         (SpaceId != ACPI_ADR_SPACE_FIXED_HARDWARE))
527     {
528         return (FALSE);
529     }
530
531     return (TRUE);
532 }
533
534
535 #endif