Merge git://git.kernel.org/pub/scm/linux/kernel/git/herbert/crypto-2.6
[linux-2.6] / drivers / acpi / tables / tbinstal.c
1 /******************************************************************************
2  *
3  * Module Name: tbinstal - ACPI table installation and removal
4  *
5  *****************************************************************************/
6
7 /*
8  * Copyright (C) 2000 - 2007, R. Byron Moore
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 #include <acpi/acpi.h>
45 #include <acpi/acnamesp.h>
46 #include <acpi/actables.h>
47
48 #define _COMPONENT          ACPI_TABLES
49 ACPI_MODULE_NAME("tbinstal")
50
51 /******************************************************************************
52  *
53  * FUNCTION:    acpi_tb_verify_table
54  *
55  * PARAMETERS:  table_desc          - table
56  *
57  * RETURN:      Status
58  *
59  * DESCRIPTION: this function is called to verify and map table
60  *
61  *****************************************************************************/
62 acpi_status acpi_tb_verify_table(struct acpi_table_desc *table_desc)
63 {
64         acpi_status status = AE_OK;
65
66         ACPI_FUNCTION_TRACE(tb_verify_table);
67
68         /* Map the table if necessary */
69
70         if (!table_desc->pointer) {
71                 if ((table_desc->flags & ACPI_TABLE_ORIGIN_MASK) ==
72                     ACPI_TABLE_ORIGIN_MAPPED) {
73                         table_desc->pointer =
74                             acpi_os_map_memory(table_desc->address,
75                                                table_desc->length);
76                 }
77                 if (!table_desc->pointer) {
78                         return_ACPI_STATUS(AE_NO_MEMORY);
79                 }
80         }
81
82         /* FACS is the odd table, has no standard ACPI header and no checksum */
83
84         if (!ACPI_COMPARE_NAME(&table_desc->signature, ACPI_SIG_FACS)) {
85
86                 /* Always calculate checksum, ignore bad checksum if requested */
87
88                 status =
89                     acpi_tb_verify_checksum(table_desc->pointer,
90                                             table_desc->length);
91         }
92
93         return_ACPI_STATUS(status);
94 }
95
96 /*******************************************************************************
97  *
98  * FUNCTION:    acpi_tb_add_table
99  *
100  * PARAMETERS:  table_desc          - Table descriptor
101  *              table_index         - Where the table index is returned
102  *
103  * RETURN:      Status
104  *
105  * DESCRIPTION: This function is called to add the ACPI table
106  *
107  ******************************************************************************/
108
109 acpi_status
110 acpi_tb_add_table(struct acpi_table_desc *table_desc,
111                   acpi_native_uint * table_index)
112 {
113         acpi_native_uint i;
114         acpi_native_uint length;
115         acpi_status status = AE_OK;
116
117         ACPI_FUNCTION_TRACE(tb_add_table);
118
119         if (!table_desc->pointer) {
120                 status = acpi_tb_verify_table(table_desc);
121                 if (ACPI_FAILURE(status) || !table_desc->pointer) {
122                         return_ACPI_STATUS(status);
123                 }
124         }
125
126         /* The table must be either an SSDT or a PSDT or an OEMx */
127
128         if ((!ACPI_COMPARE_NAME(table_desc->pointer->signature, ACPI_SIG_PSDT))
129             &&
130             (!ACPI_COMPARE_NAME(table_desc->pointer->signature, ACPI_SIG_SSDT))
131             && (strncmp(table_desc->pointer->signature, "OEM", 3))) {
132                 ACPI_ERROR((AE_INFO,
133                             "Table has invalid signature [%4.4s], must be SSDT, PSDT or OEMx",
134                             table_desc->pointer->signature));
135                 return_ACPI_STATUS(AE_BAD_SIGNATURE);
136         }
137
138         (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
139
140         /* Check if table is already registered */
141
142         for (i = 0; i < acpi_gbl_root_table_list.count; ++i) {
143                 if (!acpi_gbl_root_table_list.tables[i].pointer) {
144                         status =
145                             acpi_tb_verify_table(&acpi_gbl_root_table_list.
146                                                  tables[i]);
147                         if (ACPI_FAILURE(status)
148                             || !acpi_gbl_root_table_list.tables[i].pointer) {
149                                 continue;
150                         }
151                 }
152
153                 length = ACPI_MIN(table_desc->length,
154                                   acpi_gbl_root_table_list.tables[i].length);
155                 if (ACPI_MEMCMP(table_desc->pointer,
156                                 acpi_gbl_root_table_list.tables[i].pointer,
157                                 length)) {
158                         continue;
159                 }
160
161                 /* Table is already registered */
162
163                 acpi_tb_delete_table(table_desc);
164                 *table_index = i;
165                 goto release;
166         }
167
168         /*
169          * Add the table to the global table list
170          */
171         status = acpi_tb_store_table(table_desc->address, table_desc->pointer,
172                                      table_desc->length, table_desc->flags,
173                                      table_index);
174         if (ACPI_FAILURE(status)) {
175                 goto release;
176         }
177
178         acpi_tb_print_table_header(table_desc->address, table_desc->pointer);
179
180       release:
181         (void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
182         return_ACPI_STATUS(status);
183 }
184
185 /*******************************************************************************
186  *
187  * FUNCTION:    acpi_tb_resize_root_table_list
188  *
189  * PARAMETERS:  None
190  *
191  * RETURN:      Status
192  *
193  * DESCRIPTION: Expand the size of global table array
194  *
195  ******************************************************************************/
196
197 acpi_status acpi_tb_resize_root_table_list(void)
198 {
199         struct acpi_table_desc *tables;
200
201         ACPI_FUNCTION_TRACE(tb_resize_root_table_list);
202
203         /* allow_resize flag is a parameter to acpi_initialize_tables */
204
205         if (!(acpi_gbl_root_table_list.flags & ACPI_ROOT_ALLOW_RESIZE)) {
206                 ACPI_ERROR((AE_INFO,
207                             "Resize of Root Table Array is not allowed"));
208                 return_ACPI_STATUS(AE_SUPPORT);
209         }
210
211         /* Increase the Table Array size */
212
213         tables = ACPI_ALLOCATE_ZEROED((acpi_gbl_root_table_list.size +
214                                        ACPI_ROOT_TABLE_SIZE_INCREMENT)
215                                       * sizeof(struct acpi_table_desc));
216         if (!tables) {
217                 ACPI_ERROR((AE_INFO,
218                             "Could not allocate new root table array"));
219                 return_ACPI_STATUS(AE_NO_MEMORY);
220         }
221
222         /* Copy and free the previous table array */
223
224         if (acpi_gbl_root_table_list.tables) {
225                 ACPI_MEMCPY(tables, acpi_gbl_root_table_list.tables,
226                             acpi_gbl_root_table_list.size *
227                             sizeof(struct acpi_table_desc));
228
229                 if (acpi_gbl_root_table_list.flags & ACPI_ROOT_ORIGIN_ALLOCATED) {
230                         ACPI_FREE(acpi_gbl_root_table_list.tables);
231                 }
232         }
233
234         acpi_gbl_root_table_list.tables = tables;
235         acpi_gbl_root_table_list.size += ACPI_ROOT_TABLE_SIZE_INCREMENT;
236         acpi_gbl_root_table_list.flags |= (u8) ACPI_ROOT_ORIGIN_ALLOCATED;
237
238         return_ACPI_STATUS(AE_OK);
239 }
240
241 /*******************************************************************************
242  *
243  * FUNCTION:    acpi_tb_store_table
244  *
245  * PARAMETERS:  Address             - Table address
246  *              Table               - Table header
247  *              Length              - Table length
248  *              Flags               - flags
249  *
250  * RETURN:      Status and table index.
251  *
252  * DESCRIPTION: Add an ACPI table to the global table list
253  *
254  ******************************************************************************/
255
256 acpi_status
257 acpi_tb_store_table(acpi_physical_address address,
258                     struct acpi_table_header *table,
259                     u32 length, u8 flags, acpi_native_uint * table_index)
260 {
261         acpi_status status = AE_OK;
262
263         /* Ensure that there is room for the table in the Root Table List */
264
265         if (acpi_gbl_root_table_list.count >= acpi_gbl_root_table_list.size) {
266                 status = acpi_tb_resize_root_table_list();
267                 if (ACPI_FAILURE(status)) {
268                         return (status);
269                 }
270         }
271
272         /* Initialize added table */
273
274         acpi_gbl_root_table_list.tables[acpi_gbl_root_table_list.count].
275             address = address;
276         acpi_gbl_root_table_list.tables[acpi_gbl_root_table_list.count].
277             pointer = table;
278         acpi_gbl_root_table_list.tables[acpi_gbl_root_table_list.count].length =
279             length;
280         acpi_gbl_root_table_list.tables[acpi_gbl_root_table_list.count].
281             owner_id = 0;
282         acpi_gbl_root_table_list.tables[acpi_gbl_root_table_list.count].flags =
283             flags;
284
285         ACPI_MOVE_32_TO_32(&
286                            (acpi_gbl_root_table_list.
287                             tables[acpi_gbl_root_table_list.count].signature),
288                            table->signature);
289
290         *table_index = acpi_gbl_root_table_list.count;
291         acpi_gbl_root_table_list.count++;
292         return (status);
293 }
294
295 /*******************************************************************************
296  *
297  * FUNCTION:    acpi_tb_delete_table
298  *
299  * PARAMETERS:  table_index         - Table index
300  *
301  * RETURN:      None
302  *
303  * DESCRIPTION: Delete one internal ACPI table
304  *
305  ******************************************************************************/
306
307 void acpi_tb_delete_table(struct acpi_table_desc *table_desc)
308 {
309         /* Table must be mapped or allocated */
310         if (!table_desc->pointer) {
311                 return;
312         }
313         switch (table_desc->flags & ACPI_TABLE_ORIGIN_MASK) {
314         case ACPI_TABLE_ORIGIN_MAPPED:
315                 acpi_os_unmap_memory(table_desc->pointer, table_desc->length);
316                 break;
317         case ACPI_TABLE_ORIGIN_ALLOCATED:
318                 ACPI_FREE(table_desc->pointer);
319                 break;
320         default:;
321         }
322
323         table_desc->pointer = NULL;
324 }
325
326 /*******************************************************************************
327  *
328  * FUNCTION:    acpi_tb_terminate
329  *
330  * PARAMETERS:  None
331  *
332  * RETURN:      None
333  *
334  * DESCRIPTION: Delete all internal ACPI tables
335  *
336  ******************************************************************************/
337
338 void acpi_tb_terminate(void)
339 {
340         acpi_native_uint i;
341
342         ACPI_FUNCTION_TRACE(tb_terminate);
343
344         (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
345
346         /* Delete the individual tables */
347
348         for (i = 0; i < acpi_gbl_root_table_list.count; ++i) {
349                 acpi_tb_delete_table(&acpi_gbl_root_table_list.tables[i]);
350         }
351
352         /*
353          * Delete the root table array if allocated locally. Array cannot be
354          * mapped, so we don't need to check for that flag.
355          */
356         if (acpi_gbl_root_table_list.flags & ACPI_ROOT_ORIGIN_ALLOCATED) {
357                 ACPI_FREE(acpi_gbl_root_table_list.tables);
358         }
359
360         acpi_gbl_root_table_list.tables = NULL;
361         acpi_gbl_root_table_list.flags = 0;
362         acpi_gbl_root_table_list.count = 0;
363
364         ACPI_DEBUG_PRINT((ACPI_DB_INFO, "ACPI Tables freed\n"));
365         (void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
366 }
367
368 /*******************************************************************************
369  *
370  * FUNCTION:    acpi_tb_delete_namespace_by_owner
371  *
372  * PARAMETERS:  table_index         - Table index
373  *
374  * RETURN:      None
375  *
376  * DESCRIPTION: Delete all namespace objects created when this table was loaded.
377  *
378  ******************************************************************************/
379
380 void acpi_tb_delete_namespace_by_owner(acpi_native_uint table_index)
381 {
382         acpi_owner_id owner_id;
383
384         (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
385         if (table_index < acpi_gbl_root_table_list.count) {
386                 owner_id =
387                     acpi_gbl_root_table_list.tables[table_index].owner_id;
388         } else {
389                 (void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
390                 return;
391         }
392
393         (void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
394         acpi_ns_delete_namespace_by_owner(owner_id);
395 }
396
397 /*******************************************************************************
398  *
399  * FUNCTION:    acpi_tb_allocate_owner_id
400  *
401  * PARAMETERS:  table_index         - Table index
402  *
403  * RETURN:      Status
404  *
405  * DESCRIPTION: Allocates owner_id in table_desc
406  *
407  ******************************************************************************/
408
409 acpi_status acpi_tb_allocate_owner_id(acpi_native_uint table_index)
410 {
411         acpi_status status = AE_BAD_PARAMETER;
412
413         ACPI_FUNCTION_TRACE(tb_allocate_owner_id);
414
415         (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
416         if (table_index < acpi_gbl_root_table_list.count) {
417                 status = acpi_ut_allocate_owner_id
418                     (&(acpi_gbl_root_table_list.tables[table_index].owner_id));
419         }
420
421         (void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
422         return_ACPI_STATUS(status);
423 }
424
425 /*******************************************************************************
426  *
427  * FUNCTION:    acpi_tb_release_owner_id
428  *
429  * PARAMETERS:  table_index         - Table index
430  *
431  * RETURN:      Status
432  *
433  * DESCRIPTION: Releases owner_id in table_desc
434  *
435  ******************************************************************************/
436
437 acpi_status acpi_tb_release_owner_id(acpi_native_uint table_index)
438 {
439         acpi_status status = AE_BAD_PARAMETER;
440
441         ACPI_FUNCTION_TRACE(tb_release_owner_id);
442
443         (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
444         if (table_index < acpi_gbl_root_table_list.count) {
445                 acpi_ut_release_owner_id(&
446                                          (acpi_gbl_root_table_list.
447                                           tables[table_index].owner_id));
448                 status = AE_OK;
449         }
450
451         (void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
452         return_ACPI_STATUS(status);
453 }
454
455 /*******************************************************************************
456  *
457  * FUNCTION:    acpi_tb_get_owner_id
458  *
459  * PARAMETERS:  table_index         - Table index
460  *              owner_id            - Where the table owner_id is returned
461  *
462  * RETURN:      Status
463  *
464  * DESCRIPTION: returns owner_id for the ACPI table
465  *
466  ******************************************************************************/
467
468 acpi_status
469 acpi_tb_get_owner_id(acpi_native_uint table_index, acpi_owner_id * owner_id)
470 {
471         acpi_status status = AE_BAD_PARAMETER;
472
473         ACPI_FUNCTION_TRACE(tb_get_owner_id);
474
475         (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
476         if (table_index < acpi_gbl_root_table_list.count) {
477                 *owner_id =
478                     acpi_gbl_root_table_list.tables[table_index].owner_id;
479                 status = AE_OK;
480         }
481
482         (void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
483         return_ACPI_STATUS(status);
484 }
485
486 /*******************************************************************************
487  *
488  * FUNCTION:    acpi_tb_is_table_loaded
489  *
490  * PARAMETERS:  table_index         - Table index
491  *
492  * RETURN:      Table Loaded Flag
493  *
494  ******************************************************************************/
495
496 u8 acpi_tb_is_table_loaded(acpi_native_uint table_index)
497 {
498         u8 is_loaded = FALSE;
499
500         (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
501         if (table_index < acpi_gbl_root_table_list.count) {
502                 is_loaded = (u8)
503                     (acpi_gbl_root_table_list.tables[table_index].
504                      flags & ACPI_TABLE_IS_LOADED);
505         }
506
507         (void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
508         return (is_loaded);
509 }
510
511 /*******************************************************************************
512  *
513  * FUNCTION:    acpi_tb_set_table_loaded_flag
514  *
515  * PARAMETERS:  table_index         - Table index
516  *              is_loaded           - TRUE if table is loaded, FALSE otherwise
517  *
518  * RETURN:      None
519  *
520  * DESCRIPTION: Sets the table loaded flag to either TRUE or FALSE.
521  *
522  ******************************************************************************/
523
524 void acpi_tb_set_table_loaded_flag(acpi_native_uint table_index, u8 is_loaded)
525 {
526
527         (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
528         if (table_index < acpi_gbl_root_table_list.count) {
529                 if (is_loaded) {
530                         acpi_gbl_root_table_list.tables[table_index].flags |=
531                             ACPI_TABLE_IS_LOADED;
532                 } else {
533                         acpi_gbl_root_table_list.tables[table_index].flags &=
534                             ~ACPI_TABLE_IS_LOADED;
535                 }
536         }
537
538         (void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
539 }