xref: /netbsd-src/sys/external/bsd/acpica/dist/tables/tbxface.c (revision 413d532bcc3f62d122e56d92e13ac64825a40baf)
1 /******************************************************************************
2  *
3  * Module Name: tbxface - ACPI table-oriented external interfaces
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 __TBXFACE_C__
45 #define EXPORT_ACPI_INTERFACES
46 
47 #include "acpi.h"
48 #include "accommon.h"
49 #include "actables.h"
50 
51 #define _COMPONENT          ACPI_TABLES
52         ACPI_MODULE_NAME    ("tbxface")
53 
54 
55 /*******************************************************************************
56  *
57  * FUNCTION:    AcpiAllocateRootTable
58  *
59  * PARAMETERS:  InitialTableCount   - Size of InitialTableArray, in number of
60  *                                    ACPI_TABLE_DESC structures
61  *
62  * RETURN:      Status
63  *
64  * DESCRIPTION: Allocate a root table array. Used by iASL compiler and
65  *              AcpiInitializeTables.
66  *
67  ******************************************************************************/
68 
69 ACPI_STATUS
70 AcpiAllocateRootTable (
71     UINT32                  InitialTableCount)
72 {
73 
74     AcpiGbl_RootTableList.MaxTableCount = InitialTableCount;
75     AcpiGbl_RootTableList.Flags = ACPI_ROOT_ALLOW_RESIZE;
76 
77     return (AcpiTbResizeRootTableList ());
78 }
79 
80 
81 /*******************************************************************************
82  *
83  * FUNCTION:    AcpiInitializeTables
84  *
85  * PARAMETERS:  InitialTableArray   - Pointer to an array of pre-allocated
86  *                                    ACPI_TABLE_DESC structures. If NULL, the
87  *                                    array is dynamically allocated.
88  *              InitialTableCount   - Size of InitialTableArray, in number of
89  *                                    ACPI_TABLE_DESC structures
90  *              AllowResize         - Flag to tell Table Manager if resize of
91  *                                    pre-allocated array is allowed. Ignored
92  *                                    if InitialTableArray is NULL.
93  *
94  * RETURN:      Status
95  *
96  * DESCRIPTION: Initialize the table manager, get the RSDP and RSDT/XSDT.
97  *
98  * NOTE:        Allows static allocation of the initial table array in order
99  *              to avoid the use of dynamic memory in confined environments
100  *              such as the kernel boot sequence where it may not be available.
101  *
102  *              If the host OS memory managers are initialized, use NULL for
103  *              InitialTableArray, and the table will be dynamically allocated.
104  *
105  ******************************************************************************/
106 
107 ACPI_STATUS
108 AcpiInitializeTables (
109     ACPI_TABLE_DESC         *InitialTableArray,
110     UINT32                  InitialTableCount,
111     BOOLEAN                 AllowResize)
112 {
113     ACPI_PHYSICAL_ADDRESS   RsdpAddress;
114     ACPI_STATUS             Status;
115 
116 
117     ACPI_FUNCTION_TRACE (AcpiInitializeTables);
118 
119 
120     /*
121      * Setup the Root Table Array and allocate the table array
122      * if requested
123      */
124     if (!InitialTableArray)
125     {
126         Status = AcpiAllocateRootTable (InitialTableCount);
127         if (ACPI_FAILURE (Status))
128         {
129             return_ACPI_STATUS (Status);
130         }
131     }
132     else
133     {
134         /* Root Table Array has been statically allocated by the host */
135 
136         ACPI_MEMSET (InitialTableArray, 0,
137             (ACPI_SIZE) InitialTableCount * sizeof (ACPI_TABLE_DESC));
138 
139         AcpiGbl_RootTableList.Tables = InitialTableArray;
140         AcpiGbl_RootTableList.MaxTableCount = InitialTableCount;
141         AcpiGbl_RootTableList.Flags = ACPI_ROOT_ORIGIN_UNKNOWN;
142         if (AllowResize)
143         {
144             AcpiGbl_RootTableList.Flags |= ACPI_ROOT_ALLOW_RESIZE;
145         }
146     }
147 
148     /* Get the address of the RSDP */
149 
150     RsdpAddress = AcpiOsGetRootPointer ();
151     if (!RsdpAddress)
152     {
153         return_ACPI_STATUS (AE_NOT_FOUND);
154     }
155 
156     /*
157      * Get the root table (RSDT or XSDT) and extract all entries to the local
158      * Root Table Array. This array contains the information of the RSDT/XSDT
159      * in a common, more useable format.
160      */
161     Status = AcpiTbParseRootTable (RsdpAddress);
162     return_ACPI_STATUS (Status);
163 }
164 
165 ACPI_EXPORT_SYMBOL_INIT (AcpiInitializeTables)
166 
167 
168 /*******************************************************************************
169  *
170  * FUNCTION:    AcpiReallocateRootTable
171  *
172  * PARAMETERS:  None
173  *
174  * RETURN:      Status
175  *
176  * DESCRIPTION: Reallocate Root Table List into dynamic memory. Copies the
177  *              root list from the previously provided scratch area. Should
178  *              be called once dynamic memory allocation is available in the
179  *              kernel.
180  *
181  ******************************************************************************/
182 
183 ACPI_STATUS
184 AcpiReallocateRootTable (
185     void)
186 {
187     ACPI_STATUS             Status;
188 
189 
190     ACPI_FUNCTION_TRACE (AcpiReallocateRootTable);
191 
192 
193     /*
194      * Only reallocate the root table if the host provided a static buffer
195      * for the table array in the call to AcpiInitializeTables.
196      */
197     if (AcpiGbl_RootTableList.Flags & ACPI_ROOT_ORIGIN_ALLOCATED)
198     {
199         return_ACPI_STATUS (AE_SUPPORT);
200     }
201 
202     AcpiGbl_RootTableList.Flags |= ACPI_ROOT_ALLOW_RESIZE;
203 
204     Status = AcpiTbResizeRootTableList ();
205     return_ACPI_STATUS (Status);
206 }
207 
208 ACPI_EXPORT_SYMBOL_INIT (AcpiReallocateRootTable)
209 
210 
211 /*******************************************************************************
212  *
213  * FUNCTION:    AcpiGetTableHeader
214  *
215  * PARAMETERS:  Signature           - ACPI signature of needed table
216  *              Instance            - Which instance (for SSDTs)
217  *              OutTableHeader      - The pointer to the table header to fill
218  *
219  * RETURN:      Status and pointer to mapped table header
220  *
221  * DESCRIPTION: Finds an ACPI table header.
222  *
223  ******************************************************************************/
224 
225 ACPI_STATUS
226 AcpiGetTableHeader (
227     ACPI_CONST_STRING       Signature,
228     UINT32                  Instance,
229     ACPI_TABLE_HEADER       *OutTableHeader)
230 {
231     UINT32                  i;
232     UINT32                  j;
233     ACPI_TABLE_HEADER       *Header;
234     ACPI_STRING             USignature = __UNCONST(Signature);
235 
236     /* Parameter validation */
237 
238     if (!Signature || !OutTableHeader)
239     {
240         return (AE_BAD_PARAMETER);
241     }
242 
243     /* Walk the root table list */
244 
245     for (i = 0, j = 0; i < AcpiGbl_RootTableList.CurrentTableCount; i++)
246     {
247         if (!ACPI_COMPARE_NAME (&(AcpiGbl_RootTableList.Tables[i].Signature),
248                     USignature))
249         {
250             continue;
251         }
252 
253         if (++j < Instance)
254         {
255             continue;
256         }
257 
258         if (!AcpiGbl_RootTableList.Tables[i].Pointer)
259         {
260             if ((AcpiGbl_RootTableList.Tables[i].Flags &
261                     ACPI_TABLE_ORIGIN_MASK) ==
262                 ACPI_TABLE_ORIGIN_MAPPED)
263             {
264                 Header = AcpiOsMapMemory (
265                             AcpiGbl_RootTableList.Tables[i].Address,
266                             sizeof (ACPI_TABLE_HEADER));
267                 if (!Header)
268                 {
269                     return (AE_NO_MEMORY);
270                 }
271 
272                 ACPI_MEMCPY (OutTableHeader, Header,
273                     sizeof (ACPI_TABLE_HEADER));
274                 AcpiOsUnmapMemory (Header, sizeof (ACPI_TABLE_HEADER));
275             }
276             else
277             {
278                 return (AE_NOT_FOUND);
279             }
280         }
281         else
282         {
283             ACPI_MEMCPY (OutTableHeader,
284                 AcpiGbl_RootTableList.Tables[i].Pointer,
285                 sizeof (ACPI_TABLE_HEADER));
286         }
287 
288         return (AE_OK);
289     }
290 
291     return (AE_NOT_FOUND);
292 }
293 
294 ACPI_EXPORT_SYMBOL (AcpiGetTableHeader)
295 
296 
297 /*******************************************************************************
298  *
299  * FUNCTION:    AcpiGetTable
300  *
301  * PARAMETERS:  Signature           - ACPI signature of needed table
302  *              Instance            - Which instance (for SSDTs)
303  *              OutTable            - Where the pointer to the table is returned
304  *
305  * RETURN:      Status and pointer to the requested table
306  *
307  * DESCRIPTION: Finds and verifies an ACPI table. Table must be in the
308  *              RSDT/XSDT.
309  *
310  ******************************************************************************/
311 
312 ACPI_STATUS
313 AcpiGetTable (
314     ACPI_CONST_STRING       Signature,
315     UINT32                  Instance,
316     ACPI_TABLE_HEADER       **OutTable)
317 {
318     UINT32                  i;
319     UINT32                  j;
320     ACPI_STATUS             Status;
321     ACPI_STRING             USignature = __UNCONST(Signature);
322 
323     /* Parameter validation */
324 
325     if (!Signature || !OutTable)
326     {
327         return (AE_BAD_PARAMETER);
328     }
329 
330     /* Walk the root table list */
331 
332     for (i = 0, j = 0; i < AcpiGbl_RootTableList.CurrentTableCount; i++)
333     {
334         if (!ACPI_COMPARE_NAME (&(AcpiGbl_RootTableList.Tables[i].Signature),
335                 USignature))
336         {
337             continue;
338         }
339 
340         if (++j < Instance)
341         {
342             continue;
343         }
344 
345         Status = AcpiTbVerifyTable (&AcpiGbl_RootTableList.Tables[i]);
346         if (ACPI_SUCCESS (Status))
347         {
348             *OutTable = AcpiGbl_RootTableList.Tables[i].Pointer;
349         }
350 
351         return (Status);
352     }
353 
354     return (AE_NOT_FOUND);
355 }
356 
357 ACPI_EXPORT_SYMBOL (AcpiGetTable)
358 
359 
360 /*******************************************************************************
361  *
362  * FUNCTION:    AcpiGetTableByIndex
363  *
364  * PARAMETERS:  TableIndex          - Table index
365  *              Table               - Where the pointer to the table is returned
366  *
367  * RETURN:      Status and pointer to the requested table
368  *
369  * DESCRIPTION: Obtain a table by an index into the global table list. Used
370  *              internally also.
371  *
372  ******************************************************************************/
373 
374 ACPI_STATUS
375 AcpiGetTableByIndex (
376     UINT32                  TableIndex,
377     ACPI_TABLE_HEADER       **Table)
378 {
379     ACPI_STATUS             Status;
380 
381 
382     ACPI_FUNCTION_TRACE (AcpiGetTableByIndex);
383 
384 
385     /* Parameter validation */
386 
387     if (!Table)
388     {
389         return_ACPI_STATUS (AE_BAD_PARAMETER);
390     }
391 
392     (void) AcpiUtAcquireMutex (ACPI_MTX_TABLES);
393 
394     /* Validate index */
395 
396     if (TableIndex >= AcpiGbl_RootTableList.CurrentTableCount)
397     {
398         (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES);
399         return_ACPI_STATUS (AE_BAD_PARAMETER);
400     }
401 
402     if (!AcpiGbl_RootTableList.Tables[TableIndex].Pointer)
403     {
404         /* Table is not mapped, map it */
405 
406         Status = AcpiTbVerifyTable (&AcpiGbl_RootTableList.Tables[TableIndex]);
407         if (ACPI_FAILURE (Status))
408         {
409             (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES);
410             return_ACPI_STATUS (Status);
411         }
412     }
413 
414     *Table = AcpiGbl_RootTableList.Tables[TableIndex].Pointer;
415     (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES);
416     return_ACPI_STATUS (AE_OK);
417 }
418 
419 ACPI_EXPORT_SYMBOL (AcpiGetTableByIndex)
420 
421 
422 /*******************************************************************************
423  *
424  * FUNCTION:    AcpiInstallTableHandler
425  *
426  * PARAMETERS:  Handler         - Table event handler
427  *              Context         - Value passed to the handler on each event
428  *
429  * RETURN:      Status
430  *
431  * DESCRIPTION: Install a global table event handler.
432  *
433  ******************************************************************************/
434 
435 ACPI_STATUS
436 AcpiInstallTableHandler (
437     ACPI_TABLE_HANDLER      Handler,
438     void                    *Context)
439 {
440     ACPI_STATUS             Status;
441 
442 
443     ACPI_FUNCTION_TRACE (AcpiInstallTableHandler);
444 
445 
446     if (!Handler)
447     {
448         return_ACPI_STATUS (AE_BAD_PARAMETER);
449     }
450 
451     Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
452     if (ACPI_FAILURE (Status))
453     {
454         return_ACPI_STATUS (Status);
455     }
456 
457     /* Don't allow more than one handler */
458 
459     if (AcpiGbl_TableHandler)
460     {
461         Status = AE_ALREADY_EXISTS;
462         goto Cleanup;
463     }
464 
465     /* Install the handler */
466 
467     AcpiGbl_TableHandler = Handler;
468     AcpiGbl_TableHandlerContext = Context;
469 
470 Cleanup:
471     (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
472     return_ACPI_STATUS (Status);
473 }
474 
475 ACPI_EXPORT_SYMBOL (AcpiInstallTableHandler)
476 
477 
478 /*******************************************************************************
479  *
480  * FUNCTION:    AcpiRemoveTableHandler
481  *
482  * PARAMETERS:  Handler         - Table event handler that was installed
483  *                                previously.
484  *
485  * RETURN:      Status
486  *
487  * DESCRIPTION: Remove a table event handler
488  *
489  ******************************************************************************/
490 
491 ACPI_STATUS
492 AcpiRemoveTableHandler (
493     ACPI_TABLE_HANDLER      Handler)
494 {
495     ACPI_STATUS             Status;
496 
497 
498     ACPI_FUNCTION_TRACE (AcpiRemoveTableHandler);
499 
500 
501     Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
502     if (ACPI_FAILURE (Status))
503     {
504         return_ACPI_STATUS (Status);
505     }
506 
507     /* Make sure that the installed handler is the same */
508 
509     if (!Handler ||
510         Handler != AcpiGbl_TableHandler)
511     {
512         Status = AE_BAD_PARAMETER;
513         goto Cleanup;
514     }
515 
516     /* Remove the handler */
517 
518     AcpiGbl_TableHandler = NULL;
519 
520 Cleanup:
521     (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
522     return_ACPI_STATUS (Status);
523 }
524 
525 ACPI_EXPORT_SYMBOL (AcpiRemoveTableHandler)
526