1 /******************************************************************************
2 *
3 * Module Name: tbxfload - Table load/unload 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 "acnamesp.h"
49 #include "actables.h"
50
51 #define _COMPONENT ACPI_TABLES
52 ACPI_MODULE_NAME ("tbxfload")
53
54
55 /*******************************************************************************
56 *
57 * FUNCTION: AcpiLoadTables
58 *
59 * PARAMETERS: None
60 *
61 * RETURN: Status
62 *
63 * DESCRIPTION: Load the ACPI tables from the RSDT/XSDT
64 *
65 ******************************************************************************/
66
67 ACPI_STATUS
AcpiLoadTables(void)68 AcpiLoadTables (
69 void)
70 {
71 ACPI_STATUS Status;
72
73
74 ACPI_FUNCTION_TRACE (AcpiLoadTables);
75
76
77 /* Load the namespace from the tables */
78
79 Status = AcpiTbLoadNamespace ();
80
81 /* Don't let single failures abort the load */
82
83 if (Status == AE_CTRL_TERMINATE)
84 {
85 Status = AE_OK;
86 }
87
88 if (ACPI_FAILURE (Status))
89 {
90 ACPI_EXCEPTION ((AE_INFO, Status,
91 "While loading namespace from ACPI tables"));
92 }
93
94 return_ACPI_STATUS (Status);
95 }
96
ACPI_EXPORT_SYMBOL_INIT(AcpiLoadTables)97 ACPI_EXPORT_SYMBOL_INIT (AcpiLoadTables)
98
99
100 /*******************************************************************************
101 *
102 * FUNCTION: AcpiTbLoadNamespace
103 *
104 * PARAMETERS: None
105 *
106 * RETURN: Status
107 *
108 * DESCRIPTION: Load the namespace from the DSDT and all SSDTs/PSDTs found in
109 * the RSDT/XSDT.
110 *
111 ******************************************************************************/
112
113 ACPI_STATUS
114 AcpiTbLoadNamespace (
115 void)
116 {
117 ACPI_STATUS Status;
118 UINT32 i;
119 ACPI_TABLE_HEADER *NewDsdt;
120 ACPI_TABLE_DESC *Table;
121 UINT32 TablesLoaded = 0;
122 UINT32 TablesFailed = 0;
123
124
125 ACPI_FUNCTION_TRACE (TbLoadNamespace);
126
127
128 (void) AcpiUtAcquireMutex (ACPI_MTX_TABLES);
129
130 if (AcpiGbl_DsdtIndex == ACPI_INVALID_TABLE_INDEX ||
131 !AcpiGbl_RootTableList.CurrentTableCount)
132 {
133 Status = AE_NO_ACPI_TABLES;
134 goto UnlockAndExit;
135 }
136
137 /*
138 * Load the namespace. The DSDT is required, but any SSDT and
139 * PSDT tables are optional. Verify the DSDT.
140 */
141 Table = &AcpiGbl_RootTableList.Tables[AcpiGbl_DsdtIndex];
142
143 if (!ACPI_COMPARE_NAME (Table->Signature.Ascii, ACPI_SIG_DSDT) ||
144 ACPI_FAILURE (AcpiTbValidateTable (Table)))
145 {
146 Status = AE_NO_ACPI_TABLES;
147 goto UnlockAndExit;
148 }
149
150 /*
151 * Save the DSDT pointer for simple access. This is the mapped memory
152 * address. We must take care here because the address of the .Tables
153 * array can change dynamically as tables are loaded at run-time. Note:
154 * .Pointer field is not validated until after call to AcpiTbValidateTable.
155 */
156 AcpiGbl_DSDT = Table->Pointer;
157
158 /*
159 * Optionally copy the entire DSDT to local memory (instead of simply
160 * mapping it.) There are some BIOSs that corrupt or replace the original
161 * DSDT, creating the need for this option. Default is FALSE, do not copy
162 * the DSDT.
163 */
164 if (AcpiGbl_CopyDsdtLocally)
165 {
166 NewDsdt = AcpiTbCopyDsdt (AcpiGbl_DsdtIndex);
167 if (NewDsdt)
168 {
169 AcpiGbl_DSDT = NewDsdt;
170 }
171 }
172
173 /*
174 * Save the original DSDT header for detection of table corruption
175 * and/or replacement of the DSDT from outside the OS.
176 */
177 memcpy (&AcpiGbl_OriginalDsdtHeader, AcpiGbl_DSDT,
178 sizeof (ACPI_TABLE_HEADER));
179
180 (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES);
181
182 /* Load and parse tables */
183
184 Status = AcpiNsLoadTable (AcpiGbl_DsdtIndex, AcpiGbl_RootNode);
185 if (ACPI_FAILURE (Status))
186 {
187 ACPI_EXCEPTION ((AE_INFO, Status, "[DSDT] table load failed"));
188 TablesFailed++;
189 }
190 else
191 {
192 TablesLoaded++;
193 }
194
195 /* Load any SSDT or PSDT tables. Note: Loop leaves tables locked */
196
197 (void) AcpiUtAcquireMutex (ACPI_MTX_TABLES);
198 for (i = 0; i < AcpiGbl_RootTableList.CurrentTableCount; ++i)
199 {
200 Table = &AcpiGbl_RootTableList.Tables[i];
201
202 if (!AcpiGbl_RootTableList.Tables[i].Address ||
203 (!ACPI_COMPARE_NAME (Table->Signature.Ascii, ACPI_SIG_SSDT) &&
204 !ACPI_COMPARE_NAME (Table->Signature.Ascii, ACPI_SIG_PSDT) &&
205 !ACPI_COMPARE_NAME (Table->Signature.Ascii, ACPI_SIG_OSDT)) ||
206 ACPI_FAILURE (AcpiTbValidateTable (Table)))
207 {
208 continue;
209 }
210
211 /* Ignore errors while loading tables, get as many as possible */
212
213 (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES);
214 Status = AcpiNsLoadTable (i, AcpiGbl_RootNode);
215 if (ACPI_FAILURE (Status))
216 {
217 ACPI_EXCEPTION ((AE_INFO, Status, "(%4.4s:%8.8s) while loading table",
218 Table->Signature.Ascii, Table->Pointer->OemTableId));
219
220 TablesFailed++;
221
222 ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INIT,
223 "Table [%4.4s:%8.8s] (id FF) - Table namespace load failed\n\n",
224 Table->Signature.Ascii, Table->Pointer->OemTableId));
225 }
226 else
227 {
228 TablesLoaded++;
229 }
230
231 (void) AcpiUtAcquireMutex (ACPI_MTX_TABLES);
232 }
233
234 if (!TablesFailed)
235 {
236 ACPI_INFO ((AE_INFO,
237 "%u ACPI AML tables successfully acquired and loaded\n",
238 TablesLoaded));
239 }
240 else
241 {
242 ACPI_ERROR ((AE_INFO,
243 "%u table load failures, %u successful",
244 TablesFailed, TablesLoaded));
245
246 /* Indicate at least one failure */
247
248 Status = AE_CTRL_TERMINATE;
249 }
250
251 UnlockAndExit:
252 (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES);
253 return_ACPI_STATUS (Status);
254 }
255
256
257 /*******************************************************************************
258 *
259 * FUNCTION: AcpiInstallTable
260 *
261 * PARAMETERS: Address - Address of the ACPI table to be installed.
262 * Physical - Whether the address is a physical table
263 * address or not
264 *
265 * RETURN: Status
266 *
267 * DESCRIPTION: Dynamically install an ACPI table.
268 * Note: This function should only be invoked after
269 * AcpiInitializeTables() and before AcpiLoadTables().
270 *
271 ******************************************************************************/
272
273 ACPI_STATUS
AcpiInstallTable(ACPI_PHYSICAL_ADDRESS Address,BOOLEAN Physical)274 AcpiInstallTable (
275 ACPI_PHYSICAL_ADDRESS Address,
276 BOOLEAN Physical)
277 {
278 ACPI_STATUS Status;
279 UINT8 Flags;
280 UINT32 TableIndex;
281
282
283 ACPI_FUNCTION_TRACE (AcpiInstallTable);
284
285
286 if (Physical)
287 {
288 Flags = ACPI_TABLE_ORIGIN_INTERNAL_PHYSICAL;
289 }
290 else
291 {
292 Flags = ACPI_TABLE_ORIGIN_EXTERNAL_VIRTUAL;
293 }
294
295 Status = AcpiTbInstallStandardTable (Address, Flags,
296 FALSE, FALSE, &TableIndex);
297
298 return_ACPI_STATUS (Status);
299 }
300
ACPI_EXPORT_SYMBOL_INIT(AcpiInstallTable)301 ACPI_EXPORT_SYMBOL_INIT (AcpiInstallTable)
302
303
304 /*******************************************************************************
305 *
306 * FUNCTION: AcpiLoadTable
307 *
308 * PARAMETERS: Table - Pointer to a buffer containing the ACPI
309 * table to be loaded.
310 *
311 * RETURN: Status
312 *
313 * DESCRIPTION: Dynamically load an ACPI table from the caller's buffer. Must
314 * be a valid ACPI table with a valid ACPI table header.
315 * Note1: Mainly intended to support hotplug addition of SSDTs.
316 * Note2: Does not copy the incoming table. User is responsible
317 * to ensure that the table is not deleted or unmapped.
318 *
319 ******************************************************************************/
320
321 ACPI_STATUS
322 AcpiLoadTable (
323 ACPI_TABLE_HEADER *Table)
324 {
325 ACPI_STATUS Status;
326 UINT32 TableIndex;
327
328
329 ACPI_FUNCTION_TRACE (AcpiLoadTable);
330
331
332 /* Parameter validation */
333
334 if (!Table)
335 {
336 return_ACPI_STATUS (AE_BAD_PARAMETER);
337 }
338
339 /* Must acquire the interpreter lock during this operation */
340
341 Status = AcpiUtAcquireMutex (ACPI_MTX_INTERPRETER);
342 if (ACPI_FAILURE (Status))
343 {
344 return_ACPI_STATUS (Status);
345 }
346
347 /* Install the table and load it into the namespace */
348
349 ACPI_INFO ((AE_INFO, "Host-directed Dynamic ACPI Table Load:"));
350 (void) AcpiUtAcquireMutex (ACPI_MTX_TABLES);
351
352 Status = AcpiTbInstallStandardTable (ACPI_PTR_TO_PHYSADDR (Table),
353 ACPI_TABLE_ORIGIN_EXTERNAL_VIRTUAL, TRUE, FALSE,
354 &TableIndex);
355
356 (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES);
357 if (ACPI_FAILURE (Status))
358 {
359 goto UnlockAndExit;
360 }
361
362 /*
363 * Note: Now table is "INSTALLED", it must be validated before
364 * using.
365 */
366 Status = AcpiTbValidateTable (
367 &AcpiGbl_RootTableList.Tables[TableIndex]);
368 if (ACPI_FAILURE (Status))
369 {
370 goto UnlockAndExit;
371 }
372
373 Status = AcpiNsLoadTable (TableIndex, AcpiGbl_RootNode);
374
375 /* Invoke table handler if present */
376
377 if (AcpiGbl_TableHandler)
378 {
379 (void) AcpiGbl_TableHandler (ACPI_TABLE_EVENT_LOAD, Table,
380 AcpiGbl_TableHandlerContext);
381 }
382
383 UnlockAndExit:
384 (void) AcpiUtReleaseMutex (ACPI_MTX_INTERPRETER);
385 return_ACPI_STATUS (Status);
386 }
387
ACPI_EXPORT_SYMBOL(AcpiLoadTable)388 ACPI_EXPORT_SYMBOL (AcpiLoadTable)
389
390
391 /*******************************************************************************
392 *
393 * FUNCTION: AcpiUnloadParentTable
394 *
395 * PARAMETERS: Object - Handle to any namespace object owned by
396 * the table to be unloaded
397 *
398 * RETURN: Status
399 *
400 * DESCRIPTION: Via any namespace object within an SSDT or OEMx table, unloads
401 * the table and deletes all namespace objects associated with
402 * that table. Unloading of the DSDT is not allowed.
403 * Note: Mainly intended to support hotplug removal of SSDTs.
404 *
405 ******************************************************************************/
406
407 ACPI_STATUS
408 AcpiUnloadParentTable (
409 ACPI_HANDLE Object)
410 {
411 ACPI_NAMESPACE_NODE *Node = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, Object);
412 ACPI_STATUS Status = AE_NOT_EXIST;
413 ACPI_OWNER_ID OwnerId;
414 UINT32 i;
415
416
417 ACPI_FUNCTION_TRACE (AcpiUnloadParentTable);
418
419
420 /* Parameter validation */
421
422 if (!Object)
423 {
424 return_ACPI_STATUS (AE_BAD_PARAMETER);
425 }
426
427 /*
428 * The node OwnerId is currently the same as the parent table ID.
429 * However, this could change in the future.
430 */
431 OwnerId = Node->OwnerId;
432 if (!OwnerId)
433 {
434 /* OwnerId==0 means DSDT is the owner. DSDT cannot be unloaded */
435
436 return_ACPI_STATUS (AE_TYPE);
437 }
438
439 /* Must acquire the interpreter lock during this operation */
440
441 Status = AcpiUtAcquireMutex (ACPI_MTX_INTERPRETER);
442 if (ACPI_FAILURE (Status))
443 {
444 return_ACPI_STATUS (Status);
445 }
446
447 /* Find the table in the global table list */
448
449 for (i = 0; i < AcpiGbl_RootTableList.CurrentTableCount; i++)
450 {
451 if (OwnerId != AcpiGbl_RootTableList.Tables[i].OwnerId)
452 {
453 continue;
454 }
455
456 /*
457 * Allow unload of SSDT and OEMx tables only. Do not allow unload
458 * of the DSDT. No other types of tables should get here, since
459 * only these types can contain AML and thus are the only types
460 * that can create namespace objects.
461 */
462 if (ACPI_COMPARE_NAME (
463 AcpiGbl_RootTableList.Tables[i].Signature.Ascii,
464 ACPI_SIG_DSDT))
465 {
466 Status = AE_TYPE;
467 break;
468 }
469
470 /* Ensure the table is actually loaded */
471
472 if (!AcpiTbIsTableLoaded (i))
473 {
474 Status = AE_NOT_EXIST;
475 break;
476 }
477
478 /* Invoke table handler if present */
479
480 if (AcpiGbl_TableHandler)
481 {
482 (void) AcpiGbl_TableHandler (ACPI_TABLE_EVENT_UNLOAD,
483 AcpiGbl_RootTableList.Tables[i].Pointer,
484 AcpiGbl_TableHandlerContext);
485 }
486
487 /*
488 * Delete all namespace objects owned by this table. Note that
489 * these objects can appear anywhere in the namespace by virtue
490 * of the AML "Scope" operator. Thus, we need to track ownership
491 * by an ID, not simply a position within the hierarchy.
492 */
493 Status = AcpiTbDeleteNamespaceByOwner (i);
494 if (ACPI_FAILURE (Status))
495 {
496 break;
497 }
498
499 Status = AcpiTbReleaseOwnerId (i);
500 AcpiTbSetTableLoadedFlag (i, FALSE);
501 break;
502 }
503
504 (void) AcpiUtReleaseMutex (ACPI_MTX_INTERPRETER);
505 return_ACPI_STATUS (Status);
506 }
507
508 ACPI_EXPORT_SYMBOL (AcpiUnloadParentTable)
509