Merge master.kernel.org:/pub/scm/linux/kernel/git/wim/linux-2.6-watchdog
[pandora-kernel.git] / drivers / acpi / tables / tbutils.c
1 /******************************************************************************
2  *
3  * Module Name: tbutils   - table utilities
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/actables.h>
46
47 #define _COMPONENT          ACPI_TABLES
48 ACPI_MODULE_NAME("tbutils")
49
50 /* Local prototypes */
51 static acpi_physical_address
52 acpi_tb_get_root_table_entry(u8 * table_entry,
53                              acpi_native_uint table_entry_size);
54
55 /*******************************************************************************
56  *
57  * FUNCTION:    acpi_tb_tables_loaded
58  *
59  * PARAMETERS:  None
60  *
61  * RETURN:      TRUE if required ACPI tables are loaded
62  *
63  * DESCRIPTION: Determine if the minimum required ACPI tables are present
64  *              (FADT, FACS, DSDT)
65  *
66  ******************************************************************************/
67
68 u8 acpi_tb_tables_loaded(void)
69 {
70
71         if (acpi_gbl_root_table_list.count >= 3) {
72                 return (TRUE);
73         }
74
75         return (FALSE);
76 }
77
78 /*******************************************************************************
79  *
80  * FUNCTION:    acpi_tb_print_table_header
81  *
82  * PARAMETERS:  Address             - Table physical address
83  *              Header              - Table header
84  *
85  * RETURN:      None
86  *
87  * DESCRIPTION: Print an ACPI table header. Special cases for FACS and RSDP.
88  *
89  ******************************************************************************/
90
91 void
92 acpi_tb_print_table_header(acpi_physical_address address,
93                            struct acpi_table_header *header)
94 {
95
96         if (ACPI_COMPARE_NAME(header->signature, ACPI_SIG_FACS)) {
97
98                 /* FACS only has signature and length fields of common table header */
99
100                 ACPI_INFO((AE_INFO, "%4.4s %08lX, %04X",
101                            header->signature, (unsigned long)address,
102                            header->length));
103         } else if (ACPI_COMPARE_NAME(header->signature, ACPI_SIG_RSDP)) {
104
105                 /* RSDP has no common fields */
106
107                 ACPI_INFO((AE_INFO, "RSDP %08lX, %04X (r%d %6.6s)",
108                            (unsigned long)address,
109                            (ACPI_CAST_PTR(struct acpi_table_rsdp, header)->
110                             revision >
111                             0) ? ACPI_CAST_PTR(struct acpi_table_rsdp,
112                                                header)->length : 20,
113                            ACPI_CAST_PTR(struct acpi_table_rsdp,
114                                          header)->revision,
115                            ACPI_CAST_PTR(struct acpi_table_rsdp,
116                                          header)->oem_id));
117         } else {
118                 /* Standard ACPI table with full common header */
119
120                 ACPI_INFO((AE_INFO,
121                            "%4.4s %08lX, %04X (r%d %6.6s %8.8s %8X %4.4s %8X)",
122                            header->signature, (unsigned long)address,
123                            header->length, header->revision, header->oem_id,
124                            header->oem_table_id, header->oem_revision,
125                            header->asl_compiler_id,
126                            header->asl_compiler_revision));
127         }
128 }
129
130 /*******************************************************************************
131  *
132  * FUNCTION:    acpi_tb_validate_checksum
133  *
134  * PARAMETERS:  Table               - ACPI table to verify
135  *              Length              - Length of entire table
136  *
137  * RETURN:      Status
138  *
139  * DESCRIPTION: Verifies that the table checksums to zero. Optionally returns
140  *              exception on bad checksum.
141  *
142  ******************************************************************************/
143
144 acpi_status acpi_tb_verify_checksum(struct acpi_table_header *table, u32 length)
145 {
146         u8 checksum;
147
148         /* Compute the checksum on the table */
149
150         checksum = acpi_tb_checksum(ACPI_CAST_PTR(u8, table), length);
151
152         /* Checksum ok? (should be zero) */
153
154         if (checksum) {
155                 ACPI_WARNING((AE_INFO,
156                               "Incorrect checksum in table [%4.4s] -  %2.2X, should be %2.2X",
157                               table->signature, table->checksum,
158                               (u8) (table->checksum - checksum)));
159
160 #if (ACPI_CHECKSUM_ABORT)
161
162                 return (AE_BAD_CHECKSUM);
163 #endif
164         }
165
166         return (AE_OK);
167 }
168
169 /*******************************************************************************
170  *
171  * FUNCTION:    acpi_tb_checksum
172  *
173  * PARAMETERS:  Buffer          - Pointer to memory region to be checked
174  *              Length          - Length of this memory region
175  *
176  * RETURN:      Checksum (u8)
177  *
178  * DESCRIPTION: Calculates circular checksum of memory region.
179  *
180  ******************************************************************************/
181
182 u8 acpi_tb_checksum(u8 * buffer, acpi_native_uint length)
183 {
184         u8 sum = 0;
185         u8 *end = buffer + length;
186
187         while (buffer < end) {
188                 sum = (u8) (sum + *(buffer++));
189         }
190
191         return sum;
192 }
193
194 /*******************************************************************************
195  *
196  * FUNCTION:    acpi_tb_install_table
197  *
198  * PARAMETERS:  Address                 - Physical address of DSDT or FACS
199  *              Flags                   - Flags
200  *              Signature               - Table signature, NULL if no need to
201  *                                        match
202  *              table_index             - Index into root table array
203  *
204  * RETURN:      None
205  *
206  * DESCRIPTION: Install an ACPI table into the global data structure.
207  *
208  ******************************************************************************/
209
210 void
211 acpi_tb_install_table(acpi_physical_address address,
212                       u8 flags, char *signature, acpi_native_uint table_index)
213 {
214         struct acpi_table_header *table;
215
216         if (!address) {
217                 ACPI_ERROR((AE_INFO,
218                             "Null physical address for ACPI table [%s]",
219                             signature));
220                 return;
221         }
222
223         /* Map just the table header */
224
225         table = acpi_os_map_memory(address, sizeof(struct acpi_table_header));
226         if (!table) {
227                 return;
228         }
229
230         /* If a particular signature is expected, signature must match */
231
232         if (signature && !ACPI_COMPARE_NAME(table->signature, signature)) {
233                 ACPI_ERROR((AE_INFO,
234                             "Invalid signature 0x%X for ACPI table [%s]",
235                             *ACPI_CAST_PTR(u32, table->signature), signature));
236                 goto unmap_and_exit;
237         }
238
239         /* Initialize the table entry */
240
241         acpi_gbl_root_table_list.tables[table_index].address = address;
242         acpi_gbl_root_table_list.tables[table_index].length = table->length;
243         acpi_gbl_root_table_list.tables[table_index].flags = flags;
244
245         ACPI_MOVE_32_TO_32(&
246                            (acpi_gbl_root_table_list.tables[table_index].
247                             signature), table->signature);
248
249         acpi_tb_print_table_header(address, table);
250
251         if (table_index == ACPI_TABLE_INDEX_DSDT) {
252
253                 /* Global integer width is based upon revision of the DSDT */
254
255                 acpi_ut_set_integer_width(table->revision);
256         }
257
258       unmap_and_exit:
259         acpi_os_unmap_memory(table, sizeof(struct acpi_table_header));
260 }
261
262 /*******************************************************************************
263  *
264  * FUNCTION:    acpi_tb_get_root_table_entry
265  *
266  * PARAMETERS:  table_entry         - Pointer to the RSDT/XSDT table entry
267  *              table_entry_size    - sizeof 32 or 64 (RSDT or XSDT)
268  *
269  * RETURN:      Physical address extracted from the root table
270  *
271  * DESCRIPTION: Get one root table entry. Handles 32-bit and 64-bit cases on
272  *              both 32-bit and 64-bit platforms
273  *
274  * NOTE:        acpi_physical_address is 32-bit on 32-bit platforms, 64-bit on
275  *              64-bit platforms.
276  *
277  ******************************************************************************/
278
279 static acpi_physical_address
280 acpi_tb_get_root_table_entry(u8 * table_entry,
281                              acpi_native_uint table_entry_size)
282 {
283         u64 address64;
284
285         /*
286          * Get the table physical address (32-bit for RSDT, 64-bit for XSDT):
287          * Note: Addresses are 32-bit aligned (not 64) in both RSDT and XSDT
288          */
289         if (table_entry_size == sizeof(u32)) {
290                 /*
291                  * 32-bit platform, RSDT: Return 32-bit table entry
292                  * 64-bit platform, RSDT: Expand 32-bit to 64-bit and return
293                  */
294                 return ((acpi_physical_address)
295                         (*ACPI_CAST_PTR(u32, table_entry)));
296         } else {
297                 /*
298                  * 32-bit platform, XSDT: Truncate 64-bit to 32-bit and return
299                  * 64-bit platform, XSDT: Move (unaligned) 64-bit to local, return 64-bit
300                  */
301                 ACPI_MOVE_64_TO_64(&address64, table_entry);
302
303 #if ACPI_MACHINE_WIDTH == 32
304                 if (address64 > ACPI_UINT32_MAX) {
305
306                         /* Will truncate 64-bit address to 32 bits, issue warning */
307
308                         ACPI_WARNING((AE_INFO,
309                                       "64-bit Physical Address in XSDT is too large (%8.8X%8.8X), truncating",
310                                       ACPI_FORMAT_UINT64(address64)));
311                 }
312 #endif
313                 return ((acpi_physical_address) (address64));
314         }
315 }
316
317 /*******************************************************************************
318  *
319  * FUNCTION:    acpi_tb_parse_root_table
320  *
321  * PARAMETERS:  Rsdp                    - Pointer to the RSDP
322  *              Flags                   - Flags
323  *
324  * RETURN:      Status
325  *
326  * DESCRIPTION: This function is called to parse the Root System Description
327  *              Table (RSDT or XSDT)
328  *
329  * NOTE:        Tables are mapped (not copied) for efficiency. The FACS must
330  *              be mapped and cannot be copied because it contains the actual
331  *              memory location of the ACPI Global Lock.
332  *
333  ******************************************************************************/
334
335 acpi_status __init
336 acpi_tb_parse_root_table(acpi_physical_address rsdp_address, u8 flags)
337 {
338         struct acpi_table_rsdp *rsdp;
339         acpi_native_uint table_entry_size;
340         acpi_native_uint i;
341         u32 table_count;
342         struct acpi_table_header *table;
343         acpi_physical_address address;
344         u32 length;
345         u8 *table_entry;
346         acpi_status status;
347
348         ACPI_FUNCTION_TRACE(tb_parse_root_table);
349
350         /*
351          * Map the entire RSDP and extract the address of the RSDT or XSDT
352          */
353         rsdp = acpi_os_map_memory(rsdp_address, sizeof(struct acpi_table_rsdp));
354         if (!rsdp) {
355                 return_ACPI_STATUS(AE_NO_MEMORY);
356         }
357
358         acpi_tb_print_table_header(rsdp_address,
359                                    ACPI_CAST_PTR(struct acpi_table_header,
360                                                  rsdp));
361
362         /* Differentiate between RSDT and XSDT root tables */
363
364         if (rsdp->revision > 1 && rsdp->xsdt_physical_address) {
365                 /*
366                  * Root table is an XSDT (64-bit physical addresses). We must use the
367                  * XSDT if the revision is > 1 and the XSDT pointer is present, as per
368                  * the ACPI specification.
369                  */
370                 address = (acpi_physical_address) rsdp->xsdt_physical_address;
371                 table_entry_size = sizeof(u64);
372         } else {
373                 /* Root table is an RSDT (32-bit physical addresses) */
374
375                 address = (acpi_physical_address) rsdp->rsdt_physical_address;
376                 table_entry_size = sizeof(u32);
377         }
378
379         /*
380          * It is not possible to map more than one entry in some environments,
381          * so unmap the RSDP here before mapping other tables
382          */
383         acpi_os_unmap_memory(rsdp, sizeof(struct acpi_table_rsdp));
384
385         /* Map the RSDT/XSDT table header to get the full table length */
386
387         table = acpi_os_map_memory(address, sizeof(struct acpi_table_header));
388         if (!table) {
389                 return_ACPI_STATUS(AE_NO_MEMORY);
390         }
391
392         acpi_tb_print_table_header(address, table);
393
394         /* Get the length of the full table, verify length and map entire table */
395
396         length = table->length;
397         acpi_os_unmap_memory(table, sizeof(struct acpi_table_header));
398
399         if (length < sizeof(struct acpi_table_header)) {
400                 ACPI_ERROR((AE_INFO, "Invalid length 0x%X in RSDT/XSDT",
401                             length));
402                 return_ACPI_STATUS(AE_INVALID_TABLE_LENGTH);
403         }
404
405         table = acpi_os_map_memory(address, length);
406         if (!table) {
407                 return_ACPI_STATUS(AE_NO_MEMORY);
408         }
409
410         /* Validate the root table checksum */
411
412         status = acpi_tb_verify_checksum(table, length);
413         if (ACPI_FAILURE(status)) {
414                 acpi_os_unmap_memory(table, length);
415                 return_ACPI_STATUS(status);
416         }
417
418         /* Calculate the number of tables described in the root table */
419
420         table_count =
421             (u32) ((table->length -
422                     sizeof(struct acpi_table_header)) / table_entry_size);
423
424         /*
425          * First two entries in the table array are reserved for the DSDT and FACS,
426          * which are not actually present in the RSDT/XSDT - they come from the FADT
427          */
428         table_entry =
429             ACPI_CAST_PTR(u8, table) + sizeof(struct acpi_table_header);
430         acpi_gbl_root_table_list.count = 2;
431
432         /*
433          * Initialize the root table array from the RSDT/XSDT
434          */
435         for (i = 0; i < table_count; i++) {
436                 if (acpi_gbl_root_table_list.count >=
437                     acpi_gbl_root_table_list.size) {
438
439                         /* There is no more room in the root table array, attempt resize */
440
441                         status = acpi_tb_resize_root_table_list();
442                         if (ACPI_FAILURE(status)) {
443                                 ACPI_WARNING((AE_INFO,
444                                               "Truncating %u table entries!",
445                                               (unsigned)
446                                               (acpi_gbl_root_table_list.size -
447                                                acpi_gbl_root_table_list.
448                                                count)));
449                                 break;
450                         }
451                 }
452
453                 /* Get the table physical address (32-bit for RSDT, 64-bit for XSDT) */
454
455                 acpi_gbl_root_table_list.tables[acpi_gbl_root_table_list.count].
456                     address =
457                     acpi_tb_get_root_table_entry(table_entry, table_entry_size);
458
459                 table_entry += table_entry_size;
460                 acpi_gbl_root_table_list.count++;
461         }
462
463         /*
464          * It is not possible to map more than one entry in some environments,
465          * so unmap the root table here before mapping other tables
466          */
467         acpi_os_unmap_memory(table, length);
468
469         /*
470          * Complete the initialization of the root table array by examining
471          * the header of each table
472          */
473         for (i = 2; i < acpi_gbl_root_table_list.count; i++) {
474                 acpi_tb_install_table(acpi_gbl_root_table_list.tables[i].
475                                       address, flags, NULL, i);
476
477                 /* Special case for FADT - get the DSDT and FACS */
478
479                 if (ACPI_COMPARE_NAME
480                     (&acpi_gbl_root_table_list.tables[i].signature,
481                      ACPI_SIG_FADT)) {
482                         acpi_tb_parse_fadt(i, flags);
483                 }
484         }
485
486         return_ACPI_STATUS(AE_OK);
487 }