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