ACPICA: Implement simplified Table Manager
[pandora-kernel.git] / drivers / acpi / tables / tbutils.c
1 /******************************************************************************
2  *
3  * Module Name: tbutils   - table utilities
4  *
5  *****************************************************************************/
6
7 /*
8  * Copyright (C) 2000 - 2006, 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/actables.h>
46
47 #define _COMPONENT          ACPI_TABLES
48 ACPI_MODULE_NAME("tbutils")
49
50 /* Local prototypes */
51 static void acpi_tb_parse_fadt(struct acpi_table_fadt *fadt, u8 flags);
52
53 static void inline
54 acpi_tb_init_generic_address(struct acpi_generic_address *new_gas_struct,
55                              u8 bit_width, acpi_physical_address address);
56
57 /*******************************************************************************
58  *
59  * FUNCTION:    acpi_tb_print_table_header
60  *
61  * PARAMETERS:  Address             - Table physical address
62  *              Header              - Table header
63  *
64  * RETURN:      None
65  *
66  * DESCRIPTION: Print an ACPI table header
67  *
68  ******************************************************************************/
69
70 void
71 acpi_tb_print_table_header(acpi_physical_address address,
72                            struct acpi_table_header *header)
73 {
74
75         ACPI_INFO((AE_INFO,
76                    "%4.4s @ 0x%p Length 0x%04X (v%3.3d %6.6s %8.8s 0x%08X %4.4s 0x%08X)",
77                    header->signature, ACPI_CAST_PTR(void, address),
78                    header->length, header->revision, header->oem_id,
79                    header->oem_table_id, header->oem_revision,
80                    header->asl_compiler_id, header->asl_compiler_revision));
81 }
82
83 /*******************************************************************************
84  *
85  * FUNCTION:    acpi_tb_init_generic_address
86  *
87  * PARAMETERS:  new_gas_struct      - GAS struct to be initialized
88  *              bit_width           - Width of this register
89  *              Address             - Address of the register
90  *
91  * RETURN:      None
92  *
93  * DESCRIPTION: Initialize a GAS structure.
94  *
95  ******************************************************************************/
96
97 static void inline
98 acpi_tb_init_generic_address(struct acpi_generic_address *new_gas_struct,
99                              u8 bit_width, acpi_physical_address address)
100 {
101
102         ACPI_STORE_ADDRESS(new_gas_struct->address, address);
103         new_gas_struct->space_id = ACPI_ADR_SPACE_SYSTEM_IO;
104         new_gas_struct->bit_width = bit_width;
105         new_gas_struct->bit_offset = 0;
106         new_gas_struct->access_width = 0;
107 }
108
109 /*******************************************************************************
110  *
111  * FUNCTION:    acpi_tb_checksum
112  *
113  * PARAMETERS:  Buffer          - Pointer to memory region to be checked
114  *              Length          - Length of this memory region
115  *
116  * RETURN:      Checksum (u8)
117  *
118  * DESCRIPTION: Calculates circular checksum of memory region.
119  *
120  ******************************************************************************/
121
122 u8 acpi_tb_checksum(u8 * buffer, acpi_native_uint length)
123 {
124         u8 sum = 0;
125         u8 *end = buffer + length;
126
127         while (buffer < end) {
128                 sum = (u8) (sum + *(buffer++));
129         }
130
131         return sum;
132 }
133
134 /*******************************************************************************
135  *
136  * FUNCTION:    acpi_tb_convert_fadt
137  *
138  * PARAMETERS:  Fadt                - FADT table to be converted
139  *
140  * RETURN:      None
141  *
142  * DESCRIPTION: Converts a BIOS supplied ACPI 1.0 FADT to a local
143  *              ACPI 2.0 FADT. If the BIOS supplied a 2.0 FADT then it is simply
144  *              copied to the local FADT.  The ACPI CA software uses this
145  *              local FADT. Thus a significant amount of special #ifdef
146  *              type codeing is saved.
147  *
148  ******************************************************************************/
149
150 void acpi_tb_convert_fadt(struct acpi_table_fadt *fadt)
151 {
152
153         /*
154          * Convert table pointers to 64-bit fields
155          */
156         if (!acpi_gbl_FADT.Xfacs) {
157                 acpi_gbl_FADT.Xfacs = (u64) acpi_gbl_FADT.facs;
158         }
159
160         if (!acpi_gbl_FADT.Xdsdt) {
161                 acpi_gbl_FADT.Xdsdt = (u64) acpi_gbl_FADT.dsdt;
162         }
163
164         /*
165          * Convert the V1.0 block addresses to V2.0 GAS structures
166          */
167         acpi_tb_init_generic_address(&acpi_gbl_FADT.xpm1a_event_block,
168                                      acpi_gbl_FADT.pm1_event_length,
169                                      (acpi_physical_address) acpi_gbl_FADT.
170                                      pm1a_event_block);
171         acpi_tb_init_generic_address(&acpi_gbl_FADT.xpm1b_event_block,
172                                      acpi_gbl_FADT.pm1_event_length,
173                                      (acpi_physical_address) acpi_gbl_FADT.
174                                      pm1b_event_block);
175         acpi_tb_init_generic_address(&acpi_gbl_FADT.xpm1a_control_block,
176                                      acpi_gbl_FADT.pm1_control_length,
177                                      (acpi_physical_address) acpi_gbl_FADT.
178                                      pm1a_control_block);
179         acpi_tb_init_generic_address(&acpi_gbl_FADT.xpm1b_control_block,
180                                      acpi_gbl_FADT.pm1_control_length,
181                                      (acpi_physical_address) acpi_gbl_FADT.
182                                      pm1b_control_block);
183         acpi_tb_init_generic_address(&acpi_gbl_FADT.xpm2_control_block,
184                                      acpi_gbl_FADT.pm2_control_length,
185                                      (acpi_physical_address) acpi_gbl_FADT.
186                                      pm2_control_block);
187         acpi_tb_init_generic_address(&acpi_gbl_FADT.xpm_timer_block,
188                                      acpi_gbl_FADT.pm_timer_length,
189                                      (acpi_physical_address) acpi_gbl_FADT.
190                                      pm_timer_block);
191         acpi_tb_init_generic_address(&acpi_gbl_FADT.xgpe0_block, 0,
192                                      (acpi_physical_address) acpi_gbl_FADT.
193                                      gpe0_block);
194         acpi_tb_init_generic_address(&acpi_gbl_FADT.xgpe1_block, 0,
195                                      (acpi_physical_address) acpi_gbl_FADT.
196                                      gpe1_block);
197
198         /*
199          * Create separate GAS structs for the PM1 Enable registers
200          */
201         acpi_tb_init_generic_address(&acpi_gbl_xpm1a_enable,
202                                      (u8) ACPI_DIV_2(acpi_gbl_FADT.
203                                                      pm1_event_length),
204                                      (acpi_physical_address)
205                                      (acpi_gbl_FADT.xpm1a_event_block.address +
206                                       ACPI_DIV_2(acpi_gbl_FADT.
207                                                  pm1_event_length)));
208
209         /*
210          * PM1B is optional; leave null if not present
211          */
212         if (acpi_gbl_FADT.xpm1b_event_block.address) {
213                 acpi_tb_init_generic_address(&acpi_gbl_xpm1b_enable,
214                                              (u8) ACPI_DIV_2(acpi_gbl_FADT.
215                                                              pm1_event_length),
216                                              (acpi_physical_address)
217                                              (acpi_gbl_FADT.xpm1b_event_block.
218                                               address +
219                                               ACPI_DIV_2(acpi_gbl_FADT.
220                                                          pm1_event_length)));
221         }
222
223         /* Global FADT is the new common V2.0 FADT  */
224
225         acpi_gbl_FADT.header.length = sizeof(struct acpi_table_fadt);
226 }
227
228 /*******************************************************************************
229  *
230  * FUNCTION:    acpi_tb_parse_fadt
231  *
232  * PARAMETERS:  Fadt                - Pointer to FADT table
233  *              Flags               - Flags
234  *
235  * RETURN:      none
236  *
237  * DESCRIPTION: This function is called to initialise the FADT, DSDT and FACS
238  *              tables (FADT contains the addresses of the DSDT and FACS)
239  *
240  ******************************************************************************/
241
242 static void acpi_tb_parse_fadt(struct acpi_table_fadt *fadt, u8 flags)
243 {
244         acpi_physical_address dsdt_address =
245             (acpi_physical_address) fadt->Xdsdt;
246         acpi_physical_address facs_address =
247             (acpi_physical_address) fadt->Xfacs;
248         struct acpi_table_header *table;
249
250         if (!dsdt_address) {
251                 goto no_dsdt;
252         }
253
254         table =
255             acpi_os_map_memory(dsdt_address, sizeof(struct acpi_table_header));
256         if (!table) {
257                 goto no_dsdt;
258         }
259
260         /* Initialize the DSDT table */
261
262         ACPI_MOVE_32_TO_32(&
263                            (acpi_gbl_root_table_list.
264                             tables[ACPI_TABLE_INDEX_DSDT].signature),
265                            ACPI_SIG_DSDT);
266
267         acpi_gbl_root_table_list.tables[ACPI_TABLE_INDEX_DSDT].address =
268             dsdt_address;
269         acpi_gbl_root_table_list.tables[ACPI_TABLE_INDEX_DSDT].length =
270             table->length;
271         acpi_gbl_root_table_list.tables[ACPI_TABLE_INDEX_DSDT].flags = flags;
272
273         acpi_tb_print_table_header(dsdt_address, table);
274
275         /* Global integer width is based upon revision of the DSDT */
276
277         acpi_ut_set_integer_width(table->revision);
278         acpi_os_unmap_memory(table, sizeof(struct acpi_table_header));
279
280       no_dsdt:
281         if (!facs_address) {
282                 return;
283         }
284
285         table =
286             acpi_os_map_memory(facs_address, sizeof(struct acpi_table_header));
287         if (!table) {
288                 return;
289         }
290
291         /* Initialize the FACS table */
292
293         ACPI_MOVE_32_TO_32(&
294                            (acpi_gbl_root_table_list.
295                             tables[ACPI_TABLE_INDEX_FACS].signature),
296                            ACPI_SIG_FACS);
297
298         acpi_gbl_root_table_list.tables[ACPI_TABLE_INDEX_FACS].address =
299             facs_address;
300         acpi_gbl_root_table_list.tables[ACPI_TABLE_INDEX_FACS].length =
301             table->length;
302         acpi_gbl_root_table_list.tables[ACPI_TABLE_INDEX_FACS].flags = flags;
303
304         ACPI_INFO((AE_INFO, "%4.4s @ 0x%p",
305                    table->signature, ACPI_CAST_PTR(void, facs_address)));
306
307         acpi_os_unmap_memory(table, sizeof(struct acpi_table_header));
308 }
309
310 /*******************************************************************************
311  *
312  * FUNCTION:    acpi_tb_parse_root_table
313  *
314  * PARAMETERS:  Rsdp                    - Pointer to the RSDP
315  *              Flags                   - Flags
316  *
317  * RETURN:      Status
318  *
319  * DESCRIPTION: This function is called to parse the Root System Description
320  *              Table (RSDT or XSDT)
321  *
322  * NOTE:        Tables are mapped (not copied) for efficiency. The FACS must
323  *              be mapped and cannot be copied because it contains the actual
324  *              memory location of the ACPI Global Lock.
325  *
326  ******************************************************************************/
327
328 acpi_status acpi_tb_parse_root_table(struct acpi_table_rsdp *rsdp, u8 flags)
329 {
330         struct acpi_table_header *table;
331         acpi_physical_address address;
332         u32 length;
333         u8 *table_entry;
334         acpi_native_uint i;
335         acpi_native_uint pointer_size;
336         u32 table_count;
337         u8 checksum;
338         acpi_status status;
339
340         ACPI_FUNCTION_TRACE(tb_parse_root_table);
341
342         /* Differentiate between RSDT and XSDT root tables */
343
344         if (rsdp->revision > 1 && rsdp->xsdt_physical_address) {
345                 /*
346                  * Root table is an XSDT (64-bit physical addresses). We must use the
347                  * XSDT if the revision is > 1 and the XSDT pointer is present, as per
348                  * the ACPI specification.
349                  */
350                 address = (acpi_native_uint) rsdp->xsdt_physical_address;
351                 pointer_size = sizeof(u64);
352         } else {
353                 /* Root table is an RSDT (32-bit physical addresses) */
354
355                 address = (acpi_native_uint) rsdp->rsdt_physical_address;
356                 pointer_size = sizeof(u32);
357         }
358
359         /* Map the table header to get the full table length */
360
361         table = acpi_os_map_memory(address, sizeof(struct acpi_table_header));
362         if (!table) {
363                 return (AE_NO_MEMORY);
364         }
365
366         /* Get the length of the full table, verify length and map entire table */
367
368         length = table->length;
369         acpi_os_unmap_memory(table, sizeof(struct acpi_table_header));
370
371         if (length < sizeof(struct acpi_table_header)) {
372                 ACPI_ERROR((AE_INFO, "Invalid length 0x%X in RSDT/XSDT",
373                             length));
374                 return (AE_INVALID_TABLE_LENGTH);
375         }
376
377         table = acpi_os_map_memory(address, length);
378         if (!table) {
379                 return (AE_NO_MEMORY);
380         }
381
382         /* Validate the root table checksum */
383
384         checksum = acpi_tb_checksum(ACPI_CAST_PTR(u8, table), length);
385 #if (ACPI_CHECKSUM_ABORT)
386
387         if (checksum) {
388                 acpi_os_unmap_memory(table, length);
389                 return (AE_BAD_CHECKSUM);
390         }
391 #endif
392
393         acpi_tb_print_table_header(address, table);
394
395         /* Calculate the number of tables described in the root table */
396
397         table_count =
398             (table->length - sizeof(struct acpi_table_header)) / pointer_size;
399
400         /* Setup loop */
401
402         table_entry =
403             ACPI_CAST_PTR(u8, table) + sizeof(struct acpi_table_header);
404         acpi_gbl_root_table_list.count = 2;
405
406         /*
407          * Initialize the ACPI table entries
408          * First two entries in the table array are reserved for the DSDT and FACS
409          */
410         for (i = 0; i < table_count; ++i, table_entry += pointer_size) {
411
412                 /* Ensure there is room for another table entry */
413
414                 if (acpi_gbl_root_table_list.count >=
415                     acpi_gbl_root_table_list.size) {
416                         status = acpi_tb_resize_root_table_list();
417                         if (ACPI_FAILURE(status)) {
418                                 ACPI_WARNING((AE_INFO,
419                                               "Truncating %u table entries!",
420                                               (unsigned)
421                                               (acpi_gbl_root_table_list.size -
422                                                acpi_gbl_root_table_list.
423                                                count)));
424                                 break;
425                         }
426                 }
427
428                 /* Get the physical address (32-bit for RSDT, 64-bit for XSDT) */
429
430                 if (pointer_size == sizeof(u32)) {
431                         acpi_gbl_root_table_list.
432                             tables[acpi_gbl_root_table_list.count].address =
433                             (acpi_physical_address) (*ACPI_CAST_PTR
434                                                      (u32, table_entry));
435                 } else {
436                         acpi_gbl_root_table_list.
437                             tables[acpi_gbl_root_table_list.count].address =
438                             (acpi_physical_address) (*ACPI_CAST_PTR
439                                                      (u64, table_entry));
440                 }
441
442                 acpi_gbl_root_table_list.count++;
443         }
444
445         /*
446          * It is not possible to map more than one entry in some environments,
447          * so unmap the root table here before mapping other tables
448          */
449         acpi_os_unmap_memory(table, length);
450
451         /* Initialize all tables other than the DSDT and FACS */
452
453         for (i = 2; i < acpi_gbl_root_table_list.count; i++) {
454                 address = acpi_gbl_root_table_list.tables[i].address;
455                 length = sizeof(struct acpi_table_header);
456
457                 table = acpi_os_map_memory(address, length);
458                 if (!table) {
459                         continue;
460                 }
461
462                 acpi_gbl_root_table_list.tables[i].length = table->length;
463                 acpi_gbl_root_table_list.tables[i].flags = flags;
464
465                 ACPI_MOVE_32_TO_32(&
466                                    (acpi_gbl_root_table_list.tables[i].
467                                     signature), table->signature);
468
469                 acpi_tb_print_table_header(address, table);
470
471                 /*
472                  * Special case for the FADT because of multiple versions -
473                  * get a local copy and convert to common format
474                  */
475                 if (ACPI_COMPARE_NAME(table->signature, ACPI_SIG_FADT)) {
476                         acpi_os_unmap_memory(table, length);
477                         length = table->length;
478
479                         table = acpi_os_map_memory(address, length);
480                         if (!table) {
481                                 continue;
482                         }
483
484                         /* Copy the entire FADT locally */
485
486                         ACPI_MEMCPY(&acpi_gbl_FADT, table,
487                                     ACPI_MIN(table->length,
488                                              sizeof(struct acpi_table_fadt)));
489
490                         /* Small table means old revision, convert to new */
491
492                         if (table->length < sizeof(struct acpi_table_fadt)) {
493                                 acpi_tb_convert_fadt(ACPI_CAST_PTR
494                                                      (struct acpi_table_fadt,
495                                                       table));
496                         }
497
498                         /* Unmap original FADT */
499
500                         acpi_os_unmap_memory(table, length);
501                         acpi_tb_parse_fadt(&acpi_gbl_FADT, flags);
502                 } else {
503                         acpi_os_unmap_memory(table, length);
504                 }
505         }
506
507         return_ACPI_STATUS(AE_OK);
508 }
509
510 /******************************************************************************
511  *
512  * FUNCTION:    acpi_tb_map
513  *
514  * PARAMETERS:  Address             - Address to be mapped
515  *              Length              - Length to be mapped
516  *              Flags               - Logical or physical addressing mode
517  *
518  * RETURN:      Pointer to mapped region
519  *
520  * DESCRIPTION: Maps memory according to flag
521  *
522  *****************************************************************************/
523
524 void *acpi_tb_map(acpi_physical_address address, u32 length, u32 flags)
525 {
526
527         if (flags == ACPI_TABLE_ORIGIN_MAPPED) {
528                 return (acpi_os_map_memory(address, length));
529         } else {
530                 return (ACPI_CAST_PTR(void, address));
531         }
532 }
533
534 /******************************************************************************
535  *
536  * FUNCTION:    acpi_tb_unmap
537  *
538  * PARAMETERS:  Pointer             - To mapped region
539  *              Length              - Length to be unmapped
540  *              Flags               - Logical or physical addressing mode
541  *
542  * RETURN:      None
543  *
544  * DESCRIPTION: Unmaps memory according to flag
545  *
546  *****************************************************************************/
547
548 void acpi_tb_unmap(void *pointer, u32 length, u32 flags)
549 {
550
551         if (flags == ACPI_TABLE_ORIGIN_MAPPED) {
552                 acpi_os_unmap_memory(pointer, length);
553         }
554 }