tbxface.c revision 1.13.2.2 1 /******************************************************************************
2 *
3 * Module Name: tbxface - ACPI table-oriented external interfaces
4 *
5 *****************************************************************************/
6
7 /*
8 * Copyright (C) 2000 - 2020, 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 where the table header
264 * is returned
265 *
266 * RETURN: Status and a copy of the table header
267 *
268 * DESCRIPTION: Finds and returns an ACPI table header. Caller provides the
269 * memory where a copy of the header is to be returned
270 * (fixed length).
271 *
272 ******************************************************************************/
273
274 ACPI_STATUS
275 AcpiGetTableHeader (
276 ACPI_CONST_STRING Signature,
277 UINT32 Instance,
278 ACPI_TABLE_HEADER *OutTableHeader)
279 {
280 UINT32 i;
281 UINT32 j;
282 ACPI_TABLE_HEADER *Header;
283
284 /* Parameter validation */
285
286 if (!Signature || !OutTableHeader)
287 {
288 return (AE_BAD_PARAMETER);
289 }
290
291 /* Walk the root table list */
292
293 for (i = 0, j = 0; i < AcpiGbl_RootTableList.CurrentTableCount; i++)
294 {
295 if (!ACPI_COMPARE_NAMESEG (
296 &(AcpiGbl_RootTableList.Tables[i].Signature), Signature))
297 {
298 continue;
299 }
300
301 if (++j < Instance)
302 {
303 continue;
304 }
305
306 if (!AcpiGbl_RootTableList.Tables[i].Pointer)
307 {
308 if ((AcpiGbl_RootTableList.Tables[i].Flags &
309 ACPI_TABLE_ORIGIN_MASK) ==
310 ACPI_TABLE_ORIGIN_INTERNAL_PHYSICAL)
311 {
312 Header = AcpiOsMapMemory (
313 AcpiGbl_RootTableList.Tables[i].Address,
314 sizeof (ACPI_TABLE_HEADER));
315 if (!Header)
316 {
317 return (AE_NO_MEMORY);
318 }
319
320 memcpy (OutTableHeader, Header, sizeof (ACPI_TABLE_HEADER));
321 AcpiOsUnmapMemory (Header, sizeof (ACPI_TABLE_HEADER));
322 }
323 else
324 {
325 return (AE_NOT_FOUND);
326 }
327 }
328 else
329 {
330 memcpy (OutTableHeader,
331 AcpiGbl_RootTableList.Tables[i].Pointer,
332 sizeof (ACPI_TABLE_HEADER));
333 }
334
335 return (AE_OK);
336 }
337
338 return (AE_NOT_FOUND);
339 }
340
341 ACPI_EXPORT_SYMBOL (AcpiGetTableHeader)
342
343
344 /*******************************************************************************
345 *
346 * FUNCTION: AcpiGetTable
347 *
348 * PARAMETERS: Signature - ACPI signature of needed table
349 * Instance - Which instance (for SSDTs)
350 * OutTable - Where the pointer to the table is returned
351 *
352 * RETURN: Status and pointer to the requested table
353 *
354 * DESCRIPTION: Finds and verifies an ACPI table. Table must be in the
355 * RSDT/XSDT.
356 * Note that an early stage AcpiGetTable() call must be paired
357 * with an early stage AcpiPutTable() call. otherwise the table
358 * pointer mapped by the early stage mapping implementation may be
359 * erroneously unmapped by the late stage unmapping implementation
360 * in an AcpiPutTable() invoked during the late stage.
361 *
362 ******************************************************************************/
363
364 ACPI_STATUS
365 AcpiGetTable (
366 ACPI_CONST_STRING Signature,
367 UINT32 Instance,
368 ACPI_TABLE_HEADER **OutTable)
369 {
370 UINT32 i;
371 UINT32 j;
372 ACPI_STATUS Status = AE_NOT_FOUND;
373 ACPI_TABLE_DESC *TableDesc;
374
375 /* Parameter validation */
376
377 if (!Signature || !OutTable)
378 {
379 return (AE_BAD_PARAMETER);
380 }
381
382 /*
383 * Note that the following line is required by some OSPMs, they only
384 * check if the returned table is NULL instead of the returned status
385 * to determined if this function is succeeded.
386 */
387 *OutTable = NULL;
388
389 (void) AcpiUtAcquireMutex (ACPI_MTX_TABLES);
390
391 /* Walk the root table list */
392
393 for (i = 0, j = 0; i < AcpiGbl_RootTableList.CurrentTableCount; i++)
394 {
395 TableDesc = &AcpiGbl_RootTableList.Tables[i];
396
397 if (!ACPI_COMPARE_NAMESEG (&TableDesc->Signature, Signature))
398 {
399 continue;
400 }
401
402 if (++j < Instance)
403 {
404 continue;
405 }
406
407 Status = AcpiTbGetTable (TableDesc, OutTable);
408 break;
409 }
410
411 (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES);
412 return (Status);
413 }
414
415 ACPI_EXPORT_SYMBOL (AcpiGetTable)
416
417
418 /*******************************************************************************
419 *
420 * FUNCTION: AcpiPutTable
421 *
422 * PARAMETERS: Table - The pointer to the table
423 *
424 * RETURN: None
425 *
426 * DESCRIPTION: Release a table returned by AcpiGetTable() and its clones.
427 * Note that it is not safe if this function was invoked after an
428 * uninstallation happened to the original table descriptor.
429 * Currently there is no OSPMs' requirement to handle such
430 * situations.
431 *
432 ******************************************************************************/
433
434 void
435 AcpiPutTable (
436 ACPI_TABLE_HEADER *Table)
437 {
438 UINT32 i;
439 ACPI_TABLE_DESC *TableDesc;
440
441
442 ACPI_FUNCTION_TRACE (AcpiPutTable);
443
444
445 if (!Table)
446 {
447 return_VOID;
448 }
449
450 (void) AcpiUtAcquireMutex (ACPI_MTX_TABLES);
451
452 /* Walk the root table list */
453
454 for (i = 0; i < AcpiGbl_RootTableList.CurrentTableCount; i++)
455 {
456 TableDesc = &AcpiGbl_RootTableList.Tables[i];
457
458 if (TableDesc->Pointer != Table)
459 {
460 continue;
461 }
462
463 AcpiTbPutTable (TableDesc);
464 break;
465 }
466
467 (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES);
468 return_VOID;
469 }
470
471 ACPI_EXPORT_SYMBOL (AcpiPutTable)
472
473
474 /*******************************************************************************
475 *
476 * FUNCTION: AcpiGetTableByIndex
477 *
478 * PARAMETERS: TableIndex - Table index
479 * OutTable - Where the pointer to the table is returned
480 *
481 * RETURN: Status and pointer to the requested table
482 *
483 * DESCRIPTION: Obtain a table by an index into the global table list. Used
484 * internally also.
485 *
486 ******************************************************************************/
487
488 ACPI_STATUS
489 AcpiGetTableByIndex (
490 UINT32 TableIndex,
491 ACPI_TABLE_HEADER **OutTable)
492 {
493 ACPI_STATUS Status;
494
495
496 ACPI_FUNCTION_TRACE (AcpiGetTableByIndex);
497
498
499 /* Parameter validation */
500
501 if (!OutTable)
502 {
503 return_ACPI_STATUS (AE_BAD_PARAMETER);
504 }
505
506 /*
507 * Note that the following line is required by some OSPMs, they only
508 * check if the returned table is NULL instead of the returned status
509 * to determined if this function is succeeded.
510 */
511 *OutTable = NULL;
512
513 (void) AcpiUtAcquireMutex (ACPI_MTX_TABLES);
514
515 /* Validate index */
516
517 if (TableIndex >= AcpiGbl_RootTableList.CurrentTableCount)
518 {
519 Status = AE_BAD_PARAMETER;
520 goto UnlockAndExit;
521 }
522
523 Status = AcpiTbGetTable (
524 &AcpiGbl_RootTableList.Tables[TableIndex], OutTable);
525
526 UnlockAndExit:
527 (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES);
528 return_ACPI_STATUS (Status);
529 }
530
531 ACPI_EXPORT_SYMBOL (AcpiGetTableByIndex)
532
533
534 /*******************************************************************************
535 *
536 * FUNCTION: AcpiInstallTableHandler
537 *
538 * PARAMETERS: Handler - Table event handler
539 * Context - Value passed to the handler on each event
540 *
541 * RETURN: Status
542 *
543 * DESCRIPTION: Install a global table event handler.
544 *
545 ******************************************************************************/
546
547 ACPI_STATUS
548 AcpiInstallTableHandler (
549 ACPI_TABLE_HANDLER Handler,
550 void *Context)
551 {
552 ACPI_STATUS Status;
553
554
555 ACPI_FUNCTION_TRACE (AcpiInstallTableHandler);
556
557
558 if (!Handler)
559 {
560 return_ACPI_STATUS (AE_BAD_PARAMETER);
561 }
562
563 Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
564 if (ACPI_FAILURE (Status))
565 {
566 return_ACPI_STATUS (Status);
567 }
568
569 /* Don't allow more than one handler */
570
571 if (AcpiGbl_TableHandler)
572 {
573 Status = AE_ALREADY_EXISTS;
574 goto Cleanup;
575 }
576
577 /* Install the handler */
578
579 AcpiGbl_TableHandler = Handler;
580 AcpiGbl_TableHandlerContext = Context;
581
582 Cleanup:
583 (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
584 return_ACPI_STATUS (Status);
585 }
586
587 ACPI_EXPORT_SYMBOL (AcpiInstallTableHandler)
588
589
590 /*******************************************************************************
591 *
592 * FUNCTION: AcpiRemoveTableHandler
593 *
594 * PARAMETERS: Handler - Table event handler that was installed
595 * previously.
596 *
597 * RETURN: Status
598 *
599 * DESCRIPTION: Remove a table event handler
600 *
601 ******************************************************************************/
602
603 ACPI_STATUS
604 AcpiRemoveTableHandler (
605 ACPI_TABLE_HANDLER Handler)
606 {
607 ACPI_STATUS Status;
608
609
610 ACPI_FUNCTION_TRACE (AcpiRemoveTableHandler);
611
612
613 Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
614 if (ACPI_FAILURE (Status))
615 {
616 return_ACPI_STATUS (Status);
617 }
618
619 /* Make sure that the installed handler is the same */
620
621 if (!Handler ||
622 Handler != AcpiGbl_TableHandler)
623 {
624 Status = AE_BAD_PARAMETER;
625 goto Cleanup;
626 }
627
628 /* Remove the handler */
629
630 AcpiGbl_TableHandler = NULL;
631
632 Cleanup:
633 (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
634 return_ACPI_STATUS (Status);
635 }
636
637 ACPI_EXPORT_SYMBOL (AcpiRemoveTableHandler)
638