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