diff options
Diffstat (limited to 'drivers/acpi/acpica/tbxface.c')
-rw-r--r-- | drivers/acpi/acpica/tbxface.c | 735 |
1 files changed, 735 insertions, 0 deletions
diff --git a/drivers/acpi/acpica/tbxface.c b/drivers/acpi/acpica/tbxface.c new file mode 100644 index 000000000000..115796694a2f --- /dev/null +++ b/drivers/acpi/acpica/tbxface.c | |||
@@ -0,0 +1,735 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * Module Name: tbxface - Public interfaces to the ACPI subsystem | ||
4 | * ACPI table oriented interfaces | ||
5 | * | ||
6 | *****************************************************************************/ | ||
7 | |||
8 | /* | ||
9 | * Copyright (C) 2000 - 2008, Intel Corp. | ||
10 | * All rights reserved. | ||
11 | * | ||
12 | * Redistribution and use in source and binary forms, with or without | ||
13 | * modification, are permitted provided that the following conditions | ||
14 | * are met: | ||
15 | * 1. Redistributions of source code must retain the above copyright | ||
16 | * notice, this list of conditions, and the following disclaimer, | ||
17 | * without modification. | ||
18 | * 2. Redistributions in binary form must reproduce at minimum a disclaimer | ||
19 | * substantially similar to the "NO WARRANTY" disclaimer below | ||
20 | * ("Disclaimer") and any redistribution must be conditioned upon | ||
21 | * including a substantially similar Disclaimer requirement for further | ||
22 | * binary redistribution. | ||
23 | * 3. Neither the names of the above-listed copyright holders nor the names | ||
24 | * of any contributors may be used to endorse or promote products derived | ||
25 | * from this software without specific prior written permission. | ||
26 | * | ||
27 | * Alternatively, this software may be distributed under the terms of the | ||
28 | * GNU General Public License ("GPL") version 2 as published by the Free | ||
29 | * Software Foundation. | ||
30 | * | ||
31 | * NO WARRANTY | ||
32 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
33 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
34 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR | ||
35 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
36 | * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | ||
37 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | ||
38 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | ||
39 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, | ||
40 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING | ||
41 | * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
42 | * POSSIBILITY OF SUCH DAMAGES. | ||
43 | */ | ||
44 | |||
45 | #include <acpi/acpi.h> | ||
46 | #include <acpi/accommon.h> | ||
47 | #include <acpi/acnamesp.h> | ||
48 | #include <acpi/actables.h> | ||
49 | |||
50 | #define _COMPONENT ACPI_TABLES | ||
51 | ACPI_MODULE_NAME("tbxface") | ||
52 | |||
53 | /* Local prototypes */ | ||
54 | static acpi_status acpi_tb_load_namespace(void); | ||
55 | |||
56 | static int no_auto_ssdt; | ||
57 | |||
58 | /******************************************************************************* | ||
59 | * | ||
60 | * FUNCTION: acpi_allocate_root_table | ||
61 | * | ||
62 | * PARAMETERS: initial_table_count - Size of initial_table_array, in number of | ||
63 | * struct acpi_table_desc structures | ||
64 | * | ||
65 | * RETURN: Status | ||
66 | * | ||
67 | * DESCRIPTION: Allocate a root table array. Used by i_aSL compiler and | ||
68 | * acpi_initialize_tables. | ||
69 | * | ||
70 | ******************************************************************************/ | ||
71 | |||
72 | acpi_status acpi_allocate_root_table(u32 initial_table_count) | ||
73 | { | ||
74 | |||
75 | acpi_gbl_root_table_list.size = initial_table_count; | ||
76 | acpi_gbl_root_table_list.flags = ACPI_ROOT_ALLOW_RESIZE; | ||
77 | |||
78 | return (acpi_tb_resize_root_table_list()); | ||
79 | } | ||
80 | |||
81 | /******************************************************************************* | ||
82 | * | ||
83 | * FUNCTION: acpi_initialize_tables | ||
84 | * | ||
85 | * PARAMETERS: initial_table_array - Pointer to an array of pre-allocated | ||
86 | * struct acpi_table_desc structures. If NULL, the | ||
87 | * array is dynamically allocated. | ||
88 | * initial_table_count - Size of initial_table_array, in number of | ||
89 | * struct acpi_table_desc structures | ||
90 | * allow_realloc - Flag to tell Table Manager if resize of | ||
91 | * pre-allocated array is allowed. Ignored | ||
92 | * if initial_table_array is NULL. | ||
93 | * | ||
94 | * RETURN: Status | ||
95 | * | ||
96 | * DESCRIPTION: Initialize the table manager, get the RSDP and RSDT/XSDT. | ||
97 | * | ||
98 | * NOTE: Allows static allocation of the initial table array in order | ||
99 | * to avoid the use of dynamic memory in confined environments | ||
100 | * such as the kernel boot sequence where it may not be available. | ||
101 | * | ||
102 | * If the host OS memory managers are initialized, use NULL for | ||
103 | * initial_table_array, and the table will be dynamically allocated. | ||
104 | * | ||
105 | ******************************************************************************/ | ||
106 | |||
107 | acpi_status __init | ||
108 | acpi_initialize_tables(struct acpi_table_desc * initial_table_array, | ||
109 | u32 initial_table_count, u8 allow_resize) | ||
110 | { | ||
111 | acpi_physical_address rsdp_address; | ||
112 | acpi_status status; | ||
113 | |||
114 | ACPI_FUNCTION_TRACE(acpi_initialize_tables); | ||
115 | |||
116 | /* | ||
117 | * Set up the Root Table Array | ||
118 | * Allocate the table array if requested | ||
119 | */ | ||
120 | if (!initial_table_array) { | ||
121 | status = acpi_allocate_root_table(initial_table_count); | ||
122 | if (ACPI_FAILURE(status)) { | ||
123 | return_ACPI_STATUS(status); | ||
124 | } | ||
125 | } else { | ||
126 | /* Root Table Array has been statically allocated by the host */ | ||
127 | |||
128 | ACPI_MEMSET(initial_table_array, 0, | ||
129 | (acpi_size) initial_table_count * | ||
130 | sizeof(struct acpi_table_desc)); | ||
131 | |||
132 | acpi_gbl_root_table_list.tables = initial_table_array; | ||
133 | acpi_gbl_root_table_list.size = initial_table_count; | ||
134 | acpi_gbl_root_table_list.flags = ACPI_ROOT_ORIGIN_UNKNOWN; | ||
135 | if (allow_resize) { | ||
136 | acpi_gbl_root_table_list.flags |= | ||
137 | ACPI_ROOT_ALLOW_RESIZE; | ||
138 | } | ||
139 | } | ||
140 | |||
141 | /* Get the address of the RSDP */ | ||
142 | |||
143 | rsdp_address = acpi_os_get_root_pointer(); | ||
144 | if (!rsdp_address) { | ||
145 | return_ACPI_STATUS(AE_NOT_FOUND); | ||
146 | } | ||
147 | |||
148 | /* | ||
149 | * Get the root table (RSDT or XSDT) and extract all entries to the local | ||
150 | * Root Table Array. This array contains the information of the RSDT/XSDT | ||
151 | * in a common, more useable format. | ||
152 | */ | ||
153 | status = | ||
154 | acpi_tb_parse_root_table(rsdp_address, ACPI_TABLE_ORIGIN_MAPPED); | ||
155 | return_ACPI_STATUS(status); | ||
156 | } | ||
157 | |||
158 | /******************************************************************************* | ||
159 | * | ||
160 | * FUNCTION: acpi_reallocate_root_table | ||
161 | * | ||
162 | * PARAMETERS: None | ||
163 | * | ||
164 | * RETURN: Status | ||
165 | * | ||
166 | * DESCRIPTION: Reallocate Root Table List into dynamic memory. Copies the | ||
167 | * root list from the previously provided scratch area. Should | ||
168 | * be called once dynamic memory allocation is available in the | ||
169 | * kernel | ||
170 | * | ||
171 | ******************************************************************************/ | ||
172 | acpi_status acpi_reallocate_root_table(void) | ||
173 | { | ||
174 | struct acpi_table_desc *tables; | ||
175 | acpi_size new_size; | ||
176 | |||
177 | ACPI_FUNCTION_TRACE(acpi_reallocate_root_table); | ||
178 | |||
179 | /* | ||
180 | * Only reallocate the root table if the host provided a static buffer | ||
181 | * for the table array in the call to acpi_initialize_tables. | ||
182 | */ | ||
183 | if (acpi_gbl_root_table_list.flags & ACPI_ROOT_ORIGIN_ALLOCATED) { | ||
184 | return_ACPI_STATUS(AE_SUPPORT); | ||
185 | } | ||
186 | |||
187 | new_size = ((acpi_size) acpi_gbl_root_table_list.count + | ||
188 | ACPI_ROOT_TABLE_SIZE_INCREMENT) * | ||
189 | sizeof(struct acpi_table_desc); | ||
190 | |||
191 | /* Create new array and copy the old array */ | ||
192 | |||
193 | tables = ACPI_ALLOCATE_ZEROED(new_size); | ||
194 | if (!tables) { | ||
195 | return_ACPI_STATUS(AE_NO_MEMORY); | ||
196 | } | ||
197 | |||
198 | ACPI_MEMCPY(tables, acpi_gbl_root_table_list.tables, new_size); | ||
199 | |||
200 | acpi_gbl_root_table_list.size = acpi_gbl_root_table_list.count; | ||
201 | acpi_gbl_root_table_list.tables = tables; | ||
202 | acpi_gbl_root_table_list.flags = | ||
203 | ACPI_ROOT_ORIGIN_ALLOCATED | ACPI_ROOT_ALLOW_RESIZE; | ||
204 | |||
205 | return_ACPI_STATUS(AE_OK); | ||
206 | } | ||
207 | |||
208 | /******************************************************************************* | ||
209 | * | ||
210 | * FUNCTION: acpi_load_table | ||
211 | * | ||
212 | * PARAMETERS: table_ptr - pointer to a buffer containing the entire | ||
213 | * table to be loaded | ||
214 | * | ||
215 | * RETURN: Status | ||
216 | * | ||
217 | * DESCRIPTION: This function is called to load a table from the caller's | ||
218 | * buffer. The buffer must contain an entire ACPI Table including | ||
219 | * a valid header. The header fields will be verified, and if it | ||
220 | * is determined that the table is invalid, the call will fail. | ||
221 | * | ||
222 | ******************************************************************************/ | ||
223 | acpi_status acpi_load_table(struct acpi_table_header *table_ptr) | ||
224 | { | ||
225 | acpi_status status; | ||
226 | u32 table_index; | ||
227 | struct acpi_table_desc table_desc; | ||
228 | |||
229 | if (!table_ptr) | ||
230 | return AE_BAD_PARAMETER; | ||
231 | |||
232 | ACPI_MEMSET(&table_desc, 0, sizeof(struct acpi_table_desc)); | ||
233 | table_desc.pointer = table_ptr; | ||
234 | table_desc.length = table_ptr->length; | ||
235 | table_desc.flags = ACPI_TABLE_ORIGIN_UNKNOWN; | ||
236 | |||
237 | /* | ||
238 | * Install the new table into the local data structures | ||
239 | */ | ||
240 | status = acpi_tb_add_table(&table_desc, &table_index); | ||
241 | if (ACPI_FAILURE(status)) { | ||
242 | return status; | ||
243 | } | ||
244 | status = acpi_ns_load_table(table_index, acpi_gbl_root_node); | ||
245 | return status; | ||
246 | } | ||
247 | |||
248 | ACPI_EXPORT_SYMBOL(acpi_load_table) | ||
249 | |||
250 | /****************************************************************************** | ||
251 | * | ||
252 | * FUNCTION: acpi_get_table_header | ||
253 | * | ||
254 | * PARAMETERS: Signature - ACPI signature of needed table | ||
255 | * Instance - Which instance (for SSDTs) | ||
256 | * out_table_header - The pointer to the table header to fill | ||
257 | * | ||
258 | * RETURN: Status and pointer to mapped table header | ||
259 | * | ||
260 | * DESCRIPTION: Finds an ACPI table header. | ||
261 | * | ||
262 | * NOTE: Caller is responsible in unmapping the header with | ||
263 | * acpi_os_unmap_memory | ||
264 | * | ||
265 | *****************************************************************************/ | ||
266 | acpi_status | ||
267 | acpi_get_table_header(char *signature, | ||
268 | u32 instance, struct acpi_table_header *out_table_header) | ||
269 | { | ||
270 | u32 i; | ||
271 | u32 j; | ||
272 | struct acpi_table_header *header; | ||
273 | |||
274 | /* Parameter validation */ | ||
275 | |||
276 | if (!signature || !out_table_header) { | ||
277 | return (AE_BAD_PARAMETER); | ||
278 | } | ||
279 | |||
280 | /* | ||
281 | * Walk the root table list | ||
282 | */ | ||
283 | for (i = 0, j = 0; i < acpi_gbl_root_table_list.count; i++) { | ||
284 | if (!ACPI_COMPARE_NAME | ||
285 | (&(acpi_gbl_root_table_list.tables[i].signature), | ||
286 | signature)) { | ||
287 | continue; | ||
288 | } | ||
289 | |||
290 | if (++j < instance) { | ||
291 | continue; | ||
292 | } | ||
293 | |||
294 | if (!acpi_gbl_root_table_list.tables[i].pointer) { | ||
295 | if ((acpi_gbl_root_table_list.tables[i]. | ||
296 | flags & ACPI_TABLE_ORIGIN_MASK) == | ||
297 | ACPI_TABLE_ORIGIN_MAPPED) { | ||
298 | header = | ||
299 | acpi_os_map_memory(acpi_gbl_root_table_list. | ||
300 | tables[i].address, | ||
301 | sizeof(struct | ||
302 | acpi_table_header)); | ||
303 | if (!header) { | ||
304 | return AE_NO_MEMORY; | ||
305 | } | ||
306 | ACPI_MEMCPY(out_table_header, header, | ||
307 | sizeof(struct acpi_table_header)); | ||
308 | acpi_os_unmap_memory(header, | ||
309 | sizeof(struct | ||
310 | acpi_table_header)); | ||
311 | } else { | ||
312 | return AE_NOT_FOUND; | ||
313 | } | ||
314 | } else { | ||
315 | ACPI_MEMCPY(out_table_header, | ||
316 | acpi_gbl_root_table_list.tables[i].pointer, | ||
317 | sizeof(struct acpi_table_header)); | ||
318 | } | ||
319 | return (AE_OK); | ||
320 | } | ||
321 | |||
322 | return (AE_NOT_FOUND); | ||
323 | } | ||
324 | |||
325 | ACPI_EXPORT_SYMBOL(acpi_get_table_header) | ||
326 | |||
327 | /****************************************************************************** | ||
328 | * | ||
329 | * FUNCTION: acpi_unload_table_id | ||
330 | * | ||
331 | * PARAMETERS: id - Owner ID of the table to be removed. | ||
332 | * | ||
333 | * RETURN: Status | ||
334 | * | ||
335 | * DESCRIPTION: This routine is used to force the unload of a table (by id) | ||
336 | * | ||
337 | ******************************************************************************/ | ||
338 | acpi_status acpi_unload_table_id(acpi_owner_id id) | ||
339 | { | ||
340 | int i; | ||
341 | acpi_status status = AE_NOT_EXIST; | ||
342 | |||
343 | ACPI_FUNCTION_TRACE(acpi_unload_table_id); | ||
344 | |||
345 | /* Find table in the global table list */ | ||
346 | for (i = 0; i < acpi_gbl_root_table_list.count; ++i) { | ||
347 | if (id != acpi_gbl_root_table_list.tables[i].owner_id) { | ||
348 | continue; | ||
349 | } | ||
350 | /* | ||
351 | * Delete all namespace objects owned by this table. Note that these | ||
352 | * objects can appear anywhere in the namespace by virtue of the AML | ||
353 | * "Scope" operator. Thus, we need to track ownership by an ID, not | ||
354 | * simply a position within the hierarchy | ||
355 | */ | ||
356 | acpi_tb_delete_namespace_by_owner(i); | ||
357 | status = acpi_tb_release_owner_id(i); | ||
358 | acpi_tb_set_table_loaded_flag(i, FALSE); | ||
359 | break; | ||
360 | } | ||
361 | return_ACPI_STATUS(status); | ||
362 | } | ||
363 | |||
364 | ACPI_EXPORT_SYMBOL(acpi_unload_table_id) | ||
365 | |||
366 | /******************************************************************************* | ||
367 | * | ||
368 | * FUNCTION: acpi_get_table | ||
369 | * | ||
370 | * PARAMETERS: Signature - ACPI signature of needed table | ||
371 | * Instance - Which instance (for SSDTs) | ||
372 | * out_table - Where the pointer to the table is returned | ||
373 | * | ||
374 | * RETURN: Status and pointer to table | ||
375 | * | ||
376 | * DESCRIPTION: Finds and verifies an ACPI table. | ||
377 | * | ||
378 | *****************************************************************************/ | ||
379 | acpi_status | ||
380 | acpi_get_table(char *signature, | ||
381 | u32 instance, struct acpi_table_header **out_table) | ||
382 | { | ||
383 | u32 i; | ||
384 | u32 j; | ||
385 | acpi_status status; | ||
386 | |||
387 | /* Parameter validation */ | ||
388 | |||
389 | if (!signature || !out_table) { | ||
390 | return (AE_BAD_PARAMETER); | ||
391 | } | ||
392 | |||
393 | /* | ||
394 | * Walk the root table list | ||
395 | */ | ||
396 | for (i = 0, j = 0; i < acpi_gbl_root_table_list.count; i++) { | ||
397 | if (!ACPI_COMPARE_NAME | ||
398 | (&(acpi_gbl_root_table_list.tables[i].signature), | ||
399 | signature)) { | ||
400 | continue; | ||
401 | } | ||
402 | |||
403 | if (++j < instance) { | ||
404 | continue; | ||
405 | } | ||
406 | |||
407 | status = | ||
408 | acpi_tb_verify_table(&acpi_gbl_root_table_list.tables[i]); | ||
409 | if (ACPI_SUCCESS(status)) { | ||
410 | *out_table = acpi_gbl_root_table_list.tables[i].pointer; | ||
411 | } | ||
412 | |||
413 | if (!acpi_gbl_permanent_mmap) { | ||
414 | acpi_gbl_root_table_list.tables[i].pointer = NULL; | ||
415 | } | ||
416 | |||
417 | return (status); | ||
418 | } | ||
419 | |||
420 | return (AE_NOT_FOUND); | ||
421 | } | ||
422 | |||
423 | ACPI_EXPORT_SYMBOL(acpi_get_table) | ||
424 | |||
425 | /******************************************************************************* | ||
426 | * | ||
427 | * FUNCTION: acpi_get_table_by_index | ||
428 | * | ||
429 | * PARAMETERS: table_index - Table index | ||
430 | * Table - Where the pointer to the table is returned | ||
431 | * | ||
432 | * RETURN: Status and pointer to the table | ||
433 | * | ||
434 | * DESCRIPTION: Obtain a table by an index into the global table list. | ||
435 | * | ||
436 | ******************************************************************************/ | ||
437 | acpi_status | ||
438 | acpi_get_table_by_index(u32 table_index, struct acpi_table_header **table) | ||
439 | { | ||
440 | acpi_status status; | ||
441 | |||
442 | ACPI_FUNCTION_TRACE(acpi_get_table_by_index); | ||
443 | |||
444 | /* Parameter validation */ | ||
445 | |||
446 | if (!table) { | ||
447 | return_ACPI_STATUS(AE_BAD_PARAMETER); | ||
448 | } | ||
449 | |||
450 | (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES); | ||
451 | |||
452 | /* Validate index */ | ||
453 | |||
454 | if (table_index >= acpi_gbl_root_table_list.count) { | ||
455 | (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); | ||
456 | return_ACPI_STATUS(AE_BAD_PARAMETER); | ||
457 | } | ||
458 | |||
459 | if (!acpi_gbl_root_table_list.tables[table_index].pointer) { | ||
460 | |||
461 | /* Table is not mapped, map it */ | ||
462 | |||
463 | status = | ||
464 | acpi_tb_verify_table(&acpi_gbl_root_table_list. | ||
465 | tables[table_index]); | ||
466 | if (ACPI_FAILURE(status)) { | ||
467 | (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); | ||
468 | return_ACPI_STATUS(status); | ||
469 | } | ||
470 | } | ||
471 | |||
472 | *table = acpi_gbl_root_table_list.tables[table_index].pointer; | ||
473 | (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); | ||
474 | return_ACPI_STATUS(AE_OK); | ||
475 | } | ||
476 | |||
477 | ACPI_EXPORT_SYMBOL(acpi_get_table_by_index) | ||
478 | |||
479 | /******************************************************************************* | ||
480 | * | ||
481 | * FUNCTION: acpi_tb_load_namespace | ||
482 | * | ||
483 | * PARAMETERS: None | ||
484 | * | ||
485 | * RETURN: Status | ||
486 | * | ||
487 | * DESCRIPTION: Load the namespace from the DSDT and all SSDTs/PSDTs found in | ||
488 | * the RSDT/XSDT. | ||
489 | * | ||
490 | ******************************************************************************/ | ||
491 | static acpi_status acpi_tb_load_namespace(void) | ||
492 | { | ||
493 | acpi_status status; | ||
494 | struct acpi_table_header *table; | ||
495 | u32 i; | ||
496 | |||
497 | ACPI_FUNCTION_TRACE(tb_load_namespace); | ||
498 | |||
499 | (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES); | ||
500 | |||
501 | /* | ||
502 | * Load the namespace. The DSDT is required, but any SSDT and PSDT tables | ||
503 | * are optional. | ||
504 | */ | ||
505 | if (!acpi_gbl_root_table_list.count || | ||
506 | !ACPI_COMPARE_NAME(& | ||
507 | (acpi_gbl_root_table_list. | ||
508 | tables[ACPI_TABLE_INDEX_DSDT].signature), | ||
509 | ACPI_SIG_DSDT) | ||
510 | || | ||
511 | ACPI_FAILURE(acpi_tb_verify_table | ||
512 | (&acpi_gbl_root_table_list. | ||
513 | tables[ACPI_TABLE_INDEX_DSDT]))) { | ||
514 | status = AE_NO_ACPI_TABLES; | ||
515 | goto unlock_and_exit; | ||
516 | } | ||
517 | |||
518 | /* | ||
519 | * Find DSDT table | ||
520 | */ | ||
521 | status = | ||
522 | acpi_os_table_override(acpi_gbl_root_table_list. | ||
523 | tables[ACPI_TABLE_INDEX_DSDT].pointer, | ||
524 | &table); | ||
525 | if (ACPI_SUCCESS(status) && table) { | ||
526 | /* | ||
527 | * DSDT table has been found | ||
528 | */ | ||
529 | acpi_tb_delete_table(&acpi_gbl_root_table_list. | ||
530 | tables[ACPI_TABLE_INDEX_DSDT]); | ||
531 | acpi_gbl_root_table_list.tables[ACPI_TABLE_INDEX_DSDT].pointer = | ||
532 | table; | ||
533 | acpi_gbl_root_table_list.tables[ACPI_TABLE_INDEX_DSDT].length = | ||
534 | table->length; | ||
535 | acpi_gbl_root_table_list.tables[ACPI_TABLE_INDEX_DSDT].flags = | ||
536 | ACPI_TABLE_ORIGIN_UNKNOWN; | ||
537 | |||
538 | ACPI_INFO((AE_INFO, "Table DSDT replaced by host OS")); | ||
539 | acpi_tb_print_table_header(0, table); | ||
540 | |||
541 | if (no_auto_ssdt == 0) { | ||
542 | printk(KERN_WARNING "ACPI: DSDT override uses original SSDTs unless \"acpi_no_auto_ssdt\"\n"); | ||
543 | } | ||
544 | } | ||
545 | |||
546 | status = | ||
547 | acpi_tb_verify_table(&acpi_gbl_root_table_list. | ||
548 | tables[ACPI_TABLE_INDEX_DSDT]); | ||
549 | if (ACPI_FAILURE(status)) { | ||
550 | |||
551 | /* A valid DSDT is required */ | ||
552 | |||
553 | status = AE_NO_ACPI_TABLES; | ||
554 | goto unlock_and_exit; | ||
555 | } | ||
556 | |||
557 | (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); | ||
558 | |||
559 | /* | ||
560 | * Load and parse tables. | ||
561 | */ | ||
562 | status = acpi_ns_load_table(ACPI_TABLE_INDEX_DSDT, acpi_gbl_root_node); | ||
563 | if (ACPI_FAILURE(status)) { | ||
564 | return_ACPI_STATUS(status); | ||
565 | } | ||
566 | |||
567 | /* | ||
568 | * Load any SSDT or PSDT tables. Note: Loop leaves tables locked | ||
569 | */ | ||
570 | (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES); | ||
571 | for (i = 0; i < acpi_gbl_root_table_list.count; ++i) { | ||
572 | if ((!ACPI_COMPARE_NAME | ||
573 | (&(acpi_gbl_root_table_list.tables[i].signature), | ||
574 | ACPI_SIG_SSDT) | ||
575 | && | ||
576 | !ACPI_COMPARE_NAME(& | ||
577 | (acpi_gbl_root_table_list.tables[i]. | ||
578 | signature), ACPI_SIG_PSDT)) | ||
579 | || | ||
580 | ACPI_FAILURE(acpi_tb_verify_table | ||
581 | (&acpi_gbl_root_table_list.tables[i]))) { | ||
582 | continue; | ||
583 | } | ||
584 | |||
585 | if (no_auto_ssdt) { | ||
586 | printk(KERN_WARNING "ACPI: SSDT ignored due to \"acpi_no_auto_ssdt\"\n"); | ||
587 | continue; | ||
588 | } | ||
589 | |||
590 | /* Ignore errors while loading tables, get as many as possible */ | ||
591 | |||
592 | (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); | ||
593 | (void)acpi_ns_load_table(i, acpi_gbl_root_node); | ||
594 | (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES); | ||
595 | } | ||
596 | |||
597 | ACPI_DEBUG_PRINT((ACPI_DB_INIT, "ACPI Tables successfully acquired\n")); | ||
598 | |||
599 | unlock_and_exit: | ||
600 | (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); | ||
601 | return_ACPI_STATUS(status); | ||
602 | } | ||
603 | |||
604 | /******************************************************************************* | ||
605 | * | ||
606 | * FUNCTION: acpi_load_tables | ||
607 | * | ||
608 | * PARAMETERS: None | ||
609 | * | ||
610 | * RETURN: Status | ||
611 | * | ||
612 | * DESCRIPTION: Load the ACPI tables from the RSDT/XSDT | ||
613 | * | ||
614 | ******************************************************************************/ | ||
615 | |||
616 | acpi_status acpi_load_tables(void) | ||
617 | { | ||
618 | acpi_status status; | ||
619 | |||
620 | ACPI_FUNCTION_TRACE(acpi_load_tables); | ||
621 | |||
622 | /* | ||
623 | * Load the namespace from the tables | ||
624 | */ | ||
625 | status = acpi_tb_load_namespace(); | ||
626 | if (ACPI_FAILURE(status)) { | ||
627 | ACPI_EXCEPTION((AE_INFO, status, | ||
628 | "While loading namespace from ACPI tables")); | ||
629 | } | ||
630 | |||
631 | return_ACPI_STATUS(status); | ||
632 | } | ||
633 | |||
634 | ACPI_EXPORT_SYMBOL(acpi_load_tables) | ||
635 | |||
636 | |||
637 | /******************************************************************************* | ||
638 | * | ||
639 | * FUNCTION: acpi_install_table_handler | ||
640 | * | ||
641 | * PARAMETERS: Handler - Table event handler | ||
642 | * Context - Value passed to the handler on each event | ||
643 | * | ||
644 | * RETURN: Status | ||
645 | * | ||
646 | * DESCRIPTION: Install table event handler | ||
647 | * | ||
648 | ******************************************************************************/ | ||
649 | acpi_status | ||
650 | acpi_install_table_handler(acpi_tbl_handler handler, void *context) | ||
651 | { | ||
652 | acpi_status status; | ||
653 | |||
654 | ACPI_FUNCTION_TRACE(acpi_install_table_handler); | ||
655 | |||
656 | if (!handler) { | ||
657 | return_ACPI_STATUS(AE_BAD_PARAMETER); | ||
658 | } | ||
659 | |||
660 | status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS); | ||
661 | if (ACPI_FAILURE(status)) { | ||
662 | return_ACPI_STATUS(status); | ||
663 | } | ||
664 | |||
665 | /* Don't allow more than one handler */ | ||
666 | |||
667 | if (acpi_gbl_table_handler) { | ||
668 | status = AE_ALREADY_EXISTS; | ||
669 | goto cleanup; | ||
670 | } | ||
671 | |||
672 | /* Install the handler */ | ||
673 | |||
674 | acpi_gbl_table_handler = handler; | ||
675 | acpi_gbl_table_handler_context = context; | ||
676 | |||
677 | cleanup: | ||
678 | (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS); | ||
679 | return_ACPI_STATUS(status); | ||
680 | } | ||
681 | |||
682 | ACPI_EXPORT_SYMBOL(acpi_install_table_handler) | ||
683 | |||
684 | /******************************************************************************* | ||
685 | * | ||
686 | * FUNCTION: acpi_remove_table_handler | ||
687 | * | ||
688 | * PARAMETERS: Handler - Table event handler that was installed | ||
689 | * previously. | ||
690 | * | ||
691 | * RETURN: Status | ||
692 | * | ||
693 | * DESCRIPTION: Remove table event handler | ||
694 | * | ||
695 | ******************************************************************************/ | ||
696 | acpi_status acpi_remove_table_handler(acpi_tbl_handler handler) | ||
697 | { | ||
698 | acpi_status status; | ||
699 | |||
700 | ACPI_FUNCTION_TRACE(acpi_remove_table_handler); | ||
701 | |||
702 | status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS); | ||
703 | if (ACPI_FAILURE(status)) { | ||
704 | return_ACPI_STATUS(status); | ||
705 | } | ||
706 | |||
707 | /* Make sure that the installed handler is the same */ | ||
708 | |||
709 | if (!handler || handler != acpi_gbl_table_handler) { | ||
710 | status = AE_BAD_PARAMETER; | ||
711 | goto cleanup; | ||
712 | } | ||
713 | |||
714 | /* Remove the handler */ | ||
715 | |||
716 | acpi_gbl_table_handler = NULL; | ||
717 | |||
718 | cleanup: | ||
719 | (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS); | ||
720 | return_ACPI_STATUS(status); | ||
721 | } | ||
722 | |||
723 | ACPI_EXPORT_SYMBOL(acpi_remove_table_handler) | ||
724 | |||
725 | |||
726 | static int __init acpi_no_auto_ssdt_setup(char *s) { | ||
727 | |||
728 | printk(KERN_NOTICE "ACPI: SSDT auto-load disabled\n"); | ||
729 | |||
730 | no_auto_ssdt = 1; | ||
731 | |||
732 | return 1; | ||
733 | } | ||
734 | |||
735 | __setup("acpi_no_auto_ssdt", acpi_no_auto_ssdt_setup); | ||