tbxface.c revision 1.14 1 /******************************************************************************
2 *
3 * Module Name: tbxface - ACPI table-oriented external interfaces
4 *
5 *****************************************************************************/
6
7 /*
8 * Copyright (C) 2000 - 2019, 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
68 ACPI_STATUS
69 AcpiAllocateRootTable (
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
106 ACPI_STATUS ACPI_INIT_FUNCTION
107 AcpiInitializeTables (
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 usable format.
159 */
160 Status = AcpiTbParseRootTable (RsdpAddress);
161 return_ACPI_STATUS (Status);
162 }
163
164 ACPI_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
182 ACPI_STATUS ACPI_INIT_FUNCTION
183 AcpiReallocateRootTable (
184 void)
185 {
186 ACPI_STATUS Status;
187 ACPI_TABLE_DESC *TableDesc;
188 UINT32 i, j;
189
190
191 ACPI_FUNCTION_TRACE (AcpiReallocateRootTable);
192
193
194 /*
195 * If there are tables unverified, it is required to reallocate the
196 * root table list to clean up invalid table entries. Otherwise only
197 * reallocate the root table list if the host provided a static buffer
198 * for the table array in the call to AcpiInitializeTables().
199 */
200 if ((AcpiGbl_RootTableList.Flags & ACPI_ROOT_ORIGIN_ALLOCATED) &&
201 AcpiGbl_EnableTableValidation)
202 {
203 return_ACPI_STATUS (AE_SUPPORT);
204 }
205
206 (void) AcpiUtAcquireMutex (ACPI_MTX_TABLES);
207
208 /*
209 * Ensure OS early boot logic, which is required by some hosts. If the
210 * table state is reported to be wrong, developers should fix the
211 * issue by invoking AcpiPutTable() for the reported table during the
212 * early stage.
213 */
214 for (i = 0; i < AcpiGbl_RootTableList.CurrentTableCount; ++i)
215 {
216 TableDesc = &AcpiGbl_RootTableList.Tables[i];
217 if (TableDesc->Pointer)
218 {
219 ACPI_ERROR ((AE_INFO,
220 "Table [%4.4s] is not invalidated during early boot stage",
221 TableDesc->Signature.Ascii));
222 }
223 }
224
225 if (!AcpiGbl_EnableTableValidation)
226 {
227 /*
228 * Now it's safe to do full table validation. We can do deferred
229 * table initialization here once the flag is set.
230 */
231 AcpiGbl_EnableTableValidation = TRUE;
232 for (i = 0; i < AcpiGbl_RootTableList.CurrentTableCount; ++i)
233 {
234 TableDesc = &AcpiGbl_RootTableList.Tables[i];
235 if (!(TableDesc->Flags & ACPI_TABLE_IS_VERIFIED))
236 {
237 Status = AcpiTbVerifyTempTable (TableDesc, NULL, &j);
238 if (ACPI_FAILURE (Status))
239 {
240 AcpiTbUninstallTable (TableDesc);
241 }
242 }
243 }
244 }
245
246 AcpiGbl_RootTableList.Flags |= ACPI_ROOT_ALLOW_RESIZE;
247 Status = AcpiTbResizeRootTableList ();
248 AcpiGbl_RootTableList.Flags |= ACPI_ROOT_ORIGIN_ALLOCATED;
249
250 (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES);
251 return_ACPI_STATUS (Status);
252 }
253
254 ACPI_EXPORT_SYMBOL_INIT (AcpiReallocateRootTable)
255
256
257 /*******************************************************************************
258 *
259 * FUNCTION: AcpiGetTableHeader
260 *
261 * PARAMETERS: Signature - ACPI signature of needed table
262 * Instance - Which instance (for SSDTs)
263 * OutTableHeader - The pointer to the table header to fill
264 *
265 * RETURN: Status and pointer to mapped table header
266 *
267 * DESCRIPTION: Finds an ACPI table header.
268 *
269 ******************************************************************************/
270
271 ACPI_STATUS
272 AcpiGetTableHeader (
273 ACPI_CONST_STRING Signature,
274 UINT32 Instance,
275 ACPI_TABLE_HEADER *OutTableHeader)
276 {
277 UINT32 i;
278 UINT32 j;
279 ACPI_TABLE_HEADER *Header;
280
281 /* Parameter validation */
282
283 if (!Signature || !OutTableHeader)
284 {
285 return (AE_BAD_PARAMETER);
286 }
287
288 /* Walk the root table list */
289
290 for (i = 0, j = 0; i < AcpiGbl_RootTableList.CurrentTableCount; i++)
291 {
292 if (!ACPI_COMPARE_NAMESEG (
293 &(AcpiGbl_RootTableList.Tables[i].Signature), Signature))
294 {
295 continue;
296 }
297
298 if (++j < Instance)
299 {
300 continue;
301 }
302
303 if (!AcpiGbl_RootTableList.Tables[i].Pointer)
304 {
305 if ((AcpiGbl_RootTableList.Tables[i].Flags &
306 ACPI_TABLE_ORIGIN_MASK) ==
307 ACPI_TABLE_ORIGIN_INTERNAL_PHYSICAL)
308 {
309 Header = AcpiOsMapMemory (
310 AcpiGbl_RootTableList.Tables[i].Address,
311 sizeof (ACPI_TABLE_HEADER));
312 if (!Header)
313 {
314 return (AE_NO_MEMORY);
315 }
316
317 memcpy (OutTableHeader, Header, sizeof (ACPI_TABLE_HEADER));
318 AcpiOsUnmapMemory (Header, sizeof (ACPI_TABLE_HEADER));
319 }
320 else
321 {
322 return (AE_NOT_FOUND);
323 }
324 }
325 else
326 {
327 memcpy (OutTableHeader,
328 AcpiGbl_RootTableList.Tables[i].Pointer,
329 sizeof (ACPI_TABLE_HEADER));
330 }
331
332 return (AE_OK);
333 }
334
335 return (AE_NOT_FOUND);
336 }
337
338 ACPI_EXPORT_SYMBOL (AcpiGetTableHeader)
339
340
341 /*******************************************************************************
342 *
343 * FUNCTION: AcpiGetTable
344 *
345 * PARAMETERS: Signature - ACPI signature of needed table
346 * Instance - Which instance (for SSDTs)
347 * OutTable - Where the pointer to the table is returned
348 *
349 * RETURN: Status and pointer to the requested table
350 *
351 * DESCRIPTION: Finds and verifies an ACPI table. Table must be in the
352 * RSDT/XSDT.
353 * Note that an early stage AcpiGetTable() call must be paired
354 * with an early stage AcpiPutTable() call. otherwise the table
355 * pointer mapped by the early stage mapping implementation may be
356 * erroneously unmapped by the late stage unmapping implementation
357 * in an AcpiPutTable() invoked during the late stage.
358 *
359 ******************************************************************************/
360
361 ACPI_STATUS
362 AcpiGetTable (
363 ACPI_CONST_STRING Signature,
364 UINT32 Instance,
365 ACPI_TABLE_HEADER **OutTable)
366 {
367 UINT32 i;
368 UINT32 j;
369 ACPI_STATUS Status = AE_NOT_FOUND;
370 ACPI_TABLE_DESC *TableDesc;
371
372 /* Parameter validation */
373
374 if (!Signature || !OutTable)
375 {
376 return (AE_BAD_PARAMETER);
377 }
378
379 /*
380 * Note that the following line is required by some OSPMs, they only
381 * check if the returned table is NULL instead of the returned status
382 * to determined if this function is succeeded.
383 */
384 *OutTable = NULL;
385
386 (void) AcpiUtAcquireMutex (ACPI_MTX_TABLES);
387
388 /* Walk the root table list */
389
390 for (i = 0, j = 0; i < AcpiGbl_RootTableList.CurrentTableCount; i++)
391 {
392 TableDesc = &AcpiGbl_RootTableList.Tables[i];
393
394 if (!ACPI_COMPARE_NAMESEG (&TableDesc->Signature, Signature))
395 {
396 continue;
397 }
398
399 if (++j < Instance)
400 {
401 continue;
402 }
403
404 Status = AcpiTbGetTable (TableDesc, OutTable);
405 break;
406 }
407
408 (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES);
409 return (Status);
410 }
411
412 ACPI_EXPORT_SYMBOL (AcpiGetTable)
413
414
415 /*******************************************************************************
416 *
417 * FUNCTION: AcpiPutTable
418 *
419 * PARAMETERS: Table - The pointer to the table
420 *
421 * RETURN: None
422 *
423 * DESCRIPTION: Release a table returned by AcpiGetTable() and its clones.
424 * Note that it is not safe if this function was invoked after an
425 * uninstallation happened to the original table descriptor.
426 * Currently there is no OSPMs' requirement to handle such
427 * situations.
428 *
429 ******************************************************************************/
430
431 void
432 AcpiPutTable (
433 ACPI_TABLE_HEADER *Table)
434 {
435 UINT32 i;
436 ACPI_TABLE_DESC *TableDesc;
437
438
439 ACPI_FUNCTION_TRACE (AcpiPutTable);
440
441
442 if (!Table)
443 {
444 return_VOID;
445 }
446
447 (void) AcpiUtAcquireMutex (ACPI_MTX_TABLES);
448
449 /* Walk the root table list */
450
451 for (i = 0; i < AcpiGbl_RootTableList.CurrentTableCount; i++)
452 {
453 TableDesc = &AcpiGbl_RootTableList.Tables[i];
454
455 if (TableDesc->Pointer != Table)
456 {
457 continue;
458 }
459
460 AcpiTbPutTable (TableDesc);
461 break;
462 }
463
464 (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES);
465 return_VOID;
466 }
467
468 ACPI_EXPORT_SYMBOL (AcpiPutTable)
469
470
471 /*******************************************************************************
472 *
473 * FUNCTION: AcpiGetTableByIndex
474 *
475 * PARAMETERS: TableIndex - Table index
476 * OutTable - Where the pointer to the table is returned
477 *
478 * RETURN: Status and pointer to the requested table
479 *
480 * DESCRIPTION: Obtain a table by an index into the global table list. Used
481 * internally also.
482 *
483 ******************************************************************************/
484
485 ACPI_STATUS
486 AcpiGetTableByIndex (
487 UINT32 TableIndex,
488 ACPI_TABLE_HEADER **OutTable)
489 {
490 ACPI_STATUS Status;
491
492
493 ACPI_FUNCTION_TRACE (AcpiGetTableByIndex);
494
495
496 /* Parameter validation */
497
498 if (!OutTable)
499 {
500 return_ACPI_STATUS (AE_BAD_PARAMETER);
501 }
502
503 /*
504 * Note that the following line is required by some OSPMs, they only
505 * check if the returned table is NULL instead of the returned status
506 * to determined if this function is succeeded.
507 */
508 *OutTable = NULL;
509
510 (void) AcpiUtAcquireMutex (ACPI_MTX_TABLES);
511
512 /* Validate index */
513
514 if (TableIndex >= AcpiGbl_RootTableList.CurrentTableCount)
515 {
516 Status = AE_BAD_PARAMETER;
517 goto UnlockAndExit;
518 }
519
520 Status = AcpiTbGetTable (
521 &AcpiGbl_RootTableList.Tables[TableIndex], OutTable);
522
523 UnlockAndExit:
524 (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES);
525 return_ACPI_STATUS (Status);
526 }
527
528 ACPI_EXPORT_SYMBOL (AcpiGetTableByIndex)
529
530
531 /*******************************************************************************
532 *
533 * FUNCTION: AcpiInstallTableHandler
534 *
535 * PARAMETERS: Handler - Table event handler
536 * Context - Value passed to the handler on each event
537 *
538 * RETURN: Status
539 *
540 * DESCRIPTION: Install a global table event handler.
541 *
542 ******************************************************************************/
543
544 ACPI_STATUS
545 AcpiInstallTableHandler (
546 ACPI_TABLE_HANDLER Handler,
547 void *Context)
548 {
549 ACPI_STATUS Status;
550
551
552 ACPI_FUNCTION_TRACE (AcpiInstallTableHandler);
553
554
555 if (!Handler)
556 {
557 return_ACPI_STATUS (AE_BAD_PARAMETER);
558 }
559
560 Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
561 if (ACPI_FAILURE (Status))
562 {
563 return_ACPI_STATUS (Status);
564 }
565
566 /* Don't allow more than one handler */
567
568 if (AcpiGbl_TableHandler)
569 {
570 Status = AE_ALREADY_EXISTS;
571 goto Cleanup;
572 }
573
574 /* Install the handler */
575
576 AcpiGbl_TableHandler = Handler;
577 AcpiGbl_TableHandlerContext = Context;
578
579 Cleanup:
580 (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
581 return_ACPI_STATUS (Status);
582 }
583
584 ACPI_EXPORT_SYMBOL (AcpiInstallTableHandler)
585
586
587 /*******************************************************************************
588 *
589 * FUNCTION: AcpiRemoveTableHandler
590 *
591 * PARAMETERS: Handler - Table event handler that was installed
592 * previously.
593 *
594 * RETURN: Status
595 *
596 * DESCRIPTION: Remove a table event handler
597 *
598 ******************************************************************************/
599
600 ACPI_STATUS
601 AcpiRemoveTableHandler (
602 ACPI_TABLE_HANDLER Handler)
603 {
604 ACPI_STATUS Status;
605
606
607 ACPI_FUNCTION_TRACE (AcpiRemoveTableHandler);
608
609
610 Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
611 if (ACPI_FAILURE (Status))
612 {
613 return_ACPI_STATUS (Status);
614 }
615
616 /* Make sure that the installed handler is the same */
617
618 if (!Handler ||
619 Handler != AcpiGbl_TableHandler)
620 {
621 Status = AE_BAD_PARAMETER;
622 goto Cleanup;
623 }
624
625 /* Remove the handler */
626
627 AcpiGbl_TableHandler = NULL;
628
629 Cleanup:
630 (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
631 return_ACPI_STATUS (Status);
632 }
633
634 ACPI_EXPORT_SYMBOL (AcpiRemoveTableHandler)
635