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