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 | |
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 | |
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 | |
207 | ACPI_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 | |
224 | ACPI_STATUS |
225 | ( |
226 | ACPI_CONST_STRING Signature, |
227 | UINT32 Instance, |
228 | ACPI_TABLE_HEADER *) |
229 | { |
230 | UINT32 i; |
231 | UINT32 j; |
232 | ACPI_TABLE_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 | |
291 | ACPI_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 | |
309 | ACPI_STATUS |
310 | AcpiGetTable ( |
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 | |
353 | ACPI_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 | |
370 | ACPI_STATUS |
371 | AcpiGetTableByIndex ( |
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 | |
416 | ACPI_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 | |
432 | ACPI_STATUS |
433 | AcpiInstallTableHandler ( |
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 | |
467 | Cleanup: |
468 | (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS); |
469 | return_ACPI_STATUS (Status); |
470 | } |
471 | |
472 | ACPI_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 | |
488 | ACPI_STATUS |
489 | AcpiRemoveTableHandler ( |
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 | |
517 | Cleanup: |
518 | (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS); |
519 | return_ACPI_STATUS (Status); |
520 | } |
521 | |
522 | ACPI_EXPORT_SYMBOL (AcpiRemoveTableHandler) |
523 | |