Fedora kernel-2.6.17-1.2142_FC4 patched with stable patch-2.6.17.4-vs2.0.2-rc26.diff
[linux-2.6.git] / drivers / acpi / tables / tbxfroot.c
1 /******************************************************************************
2  *
3  * Module Name: tbxfroot - Find the root ACPI table (RSDT)
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 <linux/module.h>
45
46 #include <acpi/acpi.h>
47 #include <acpi/actables.h>
48
49 #define _COMPONENT          ACPI_TABLES
50 ACPI_MODULE_NAME("tbxfroot")
51
52 /* Local prototypes */
53 static acpi_status
54 acpi_tb_find_rsdp(struct acpi_table_desc *table_info, u32 flags);
55
56 static u8 *acpi_tb_scan_memory_for_rsdp(u8 * start_address, u32 length);
57
58 /*******************************************************************************
59  *
60  * FUNCTION:    acpi_tb_validate_rsdp
61  *
62  * PARAMETERS:  Rsdp        - Pointer to unvalidated RSDP
63  *
64  * RETURN:      Status
65  *
66  * DESCRIPTION: Validate the RSDP (ptr)
67  *
68  ******************************************************************************/
69
70 acpi_status acpi_tb_validate_rsdp(struct rsdp_descriptor *rsdp)
71 {
72         ACPI_FUNCTION_ENTRY();
73
74         /*
75          *  The signature and checksum must both be correct
76          */
77         if (ACPI_STRNCMP((char *)rsdp, RSDP_SIG, sizeof(RSDP_SIG) - 1) != 0) {
78                 /* Nope, BAD Signature */
79
80                 return (AE_BAD_SIGNATURE);
81         }
82
83         /* Check the standard checksum */
84
85         if (acpi_tb_generate_checksum(rsdp, ACPI_RSDP_CHECKSUM_LENGTH) != 0) {
86                 return (AE_BAD_CHECKSUM);
87         }
88
89         /* Check extended checksum if table version >= 2 */
90
91         if ((rsdp->revision >= 2) &&
92             (acpi_tb_generate_checksum(rsdp, ACPI_RSDP_XCHECKSUM_LENGTH) !=
93              0)) {
94                 return (AE_BAD_CHECKSUM);
95         }
96
97         return (AE_OK);
98 }
99
100 /*******************************************************************************
101  *
102  * FUNCTION:    acpi_tb_find_table
103  *
104  * PARAMETERS:  Signature           - String with ACPI table signature
105  *              oem_id              - String with the table OEM ID
106  *              oem_table_id        - String with the OEM Table ID
107  *              table_ptr           - Where the table pointer is returned
108  *
109  * RETURN:      Status
110  *
111  * DESCRIPTION: Find an ACPI table (in the RSDT/XSDT) that matches the
112  *              Signature, OEM ID and OEM Table ID.
113  *
114  ******************************************************************************/
115
116 acpi_status
117 acpi_tb_find_table(char *signature,
118                    char *oem_id,
119                    char *oem_table_id, struct acpi_table_header ** table_ptr)
120 {
121         acpi_status status;
122         struct acpi_table_header *table;
123
124         ACPI_FUNCTION_TRACE("tb_find_table");
125
126         /* Validate string lengths */
127
128         if ((ACPI_STRLEN(signature) > ACPI_NAME_SIZE) ||
129             (ACPI_STRLEN(oem_id) > sizeof(table->oem_id)) ||
130             (ACPI_STRLEN(oem_table_id) > sizeof(table->oem_table_id))) {
131                 return_ACPI_STATUS(AE_AML_STRING_LIMIT);
132         }
133
134         if (!ACPI_STRNCMP(signature, DSDT_SIG, ACPI_NAME_SIZE)) {
135                 /*
136                  * The DSDT pointer is contained in the FADT, not the RSDT.
137                  * This code should suffice, because the only code that would perform
138                  * a "find" on the DSDT is the data_table_region() AML opcode -- in
139                  * which case, the DSDT is guaranteed to be already loaded.
140                  * If this becomes insufficient, the FADT will have to be found first.
141                  */
142                 if (!acpi_gbl_DSDT) {
143                         return_ACPI_STATUS(AE_NO_ACPI_TABLES);
144                 }
145                 table = acpi_gbl_DSDT;
146         } else {
147                 /* Find the table */
148
149                 status = acpi_get_firmware_table(signature, 1,
150                                                  ACPI_LOGICAL_ADDRESSING,
151                                                  &table);
152                 if (ACPI_FAILURE(status)) {
153                         return_ACPI_STATUS(status);
154                 }
155         }
156
157         /* Check oem_id and oem_table_id */
158
159         if ((oem_id[0] && ACPI_STRNCMP(oem_id, table->oem_id,
160                                        sizeof(table->oem_id))) ||
161             (oem_table_id[0] && ACPI_STRNCMP(oem_table_id, table->oem_table_id,
162                                              sizeof(table->oem_table_id)))) {
163                 return_ACPI_STATUS(AE_AML_NAME_NOT_FOUND);
164         }
165
166         ACPI_DEBUG_PRINT((ACPI_DB_TABLES, "Found table [%4.4s]\n",
167                           table->signature));
168
169         *table_ptr = table;
170         return_ACPI_STATUS(AE_OK);
171 }
172
173 /*******************************************************************************
174  *
175  * FUNCTION:    acpi_get_firmware_table
176  *
177  * PARAMETERS:  Signature       - Any ACPI table signature
178  *              Instance        - the non zero instance of the table, allows
179  *                                support for multiple tables of the same type
180  *              Flags           - Physical/Virtual support
181  *              table_pointer   - Where a buffer containing the table is
182  *                                returned
183  *
184  * RETURN:      Status
185  *
186  * DESCRIPTION: This function is called to get an ACPI table. A buffer is
187  *              allocated for the table and returned in table_pointer.
188  *              This table will be a complete table including the header.
189  *
190  ******************************************************************************/
191
192 acpi_status
193 acpi_get_firmware_table(acpi_string signature,
194                         u32 instance,
195                         u32 flags, struct acpi_table_header **table_pointer)
196 {
197         acpi_status status;
198         struct acpi_pointer address;
199         struct acpi_table_header *header = NULL;
200         struct acpi_table_desc *table_info = NULL;
201         struct acpi_table_desc *rsdt_info;
202         u32 table_count;
203         u32 i;
204         u32 j;
205
206         ACPI_FUNCTION_TRACE("acpi_get_firmware_table");
207
208         /*
209          * Ensure that at least the table manager is initialized.  We don't
210          * require that the entire ACPI subsystem is up for this interface.
211          * If we have a buffer, we must have a length too
212          */
213         if ((instance == 0) || (!signature) || (!table_pointer)) {
214                 return_ACPI_STATUS(AE_BAD_PARAMETER);
215         }
216
217         /* Ensure that we have a RSDP */
218
219         if (!acpi_gbl_RSDP) {
220                 /* Get the RSDP */
221
222                 status = acpi_os_get_root_pointer(flags, &address);
223                 if (ACPI_FAILURE(status)) {
224                         ACPI_DEBUG_PRINT((ACPI_DB_INFO, "RSDP not found\n"));
225                         return_ACPI_STATUS(AE_NO_ACPI_TABLES);
226                 }
227
228                 /* Map and validate the RSDP */
229
230                 if ((flags & ACPI_MEMORY_MODE) == ACPI_LOGICAL_ADDRESSING) {
231                         status = acpi_os_map_memory(address.pointer.physical,
232                                                     sizeof(struct
233                                                            rsdp_descriptor),
234                                                     (void *)&acpi_gbl_RSDP);
235                         if (ACPI_FAILURE(status)) {
236                                 return_ACPI_STATUS(status);
237                         }
238                 } else {
239                         acpi_gbl_RSDP = address.pointer.logical;
240                 }
241
242                 /* The RDSP signature and checksum must both be correct */
243
244                 status = acpi_tb_validate_rsdp(acpi_gbl_RSDP);
245                 if (ACPI_FAILURE(status)) {
246                         return_ACPI_STATUS(status);
247                 }
248         }
249
250         /* Get the RSDT address via the RSDP */
251
252         acpi_tb_get_rsdt_address(&address);
253         ACPI_DEBUG_PRINT((ACPI_DB_INFO,
254                           "RSDP located at %p, RSDT physical=%8.8X%8.8X\n",
255                           acpi_gbl_RSDP,
256                           ACPI_FORMAT_UINT64(address.pointer.value)));
257
258         /* Insert processor_mode flags */
259
260         address.pointer_type |= flags;
261
262         /* Get and validate the RSDT */
263
264         rsdt_info = ACPI_MEM_CALLOCATE(sizeof(struct acpi_table_desc));
265         if (!rsdt_info) {
266                 return_ACPI_STATUS(AE_NO_MEMORY);
267         }
268
269         status = acpi_tb_get_table(&address, rsdt_info);
270         if (ACPI_FAILURE(status)) {
271                 goto cleanup;
272         }
273
274         status = acpi_tb_validate_rsdt(rsdt_info->pointer);
275         if (ACPI_FAILURE(status)) {
276                 goto cleanup;
277         }
278
279         /* Allocate a scratch table header and table descriptor */
280
281         header = ACPI_MEM_ALLOCATE(sizeof(struct acpi_table_header));
282         if (!header) {
283                 status = AE_NO_MEMORY;
284                 goto cleanup;
285         }
286
287         table_info = ACPI_MEM_ALLOCATE(sizeof(struct acpi_table_desc));
288         if (!table_info) {
289                 status = AE_NO_MEMORY;
290                 goto cleanup;
291         }
292
293         /* Get the number of table pointers within the RSDT */
294
295         table_count =
296             acpi_tb_get_table_count(acpi_gbl_RSDP, rsdt_info->pointer);
297         address.pointer_type = acpi_gbl_table_flags | flags;
298
299         /*
300          * Search the RSDT/XSDT for the correct instance of the
301          * requested table
302          */
303         for (i = 0, j = 0; i < table_count; i++) {
304                 /*
305                  * Get the next table pointer, handle RSDT vs. XSDT
306                  * RSDT pointers are 32 bits, XSDT pointers are 64 bits
307                  */
308                 if (acpi_gbl_root_table_type == ACPI_TABLE_TYPE_RSDT) {
309                         address.pointer.value =
310                             (ACPI_CAST_PTR
311                              (RSDT_DESCRIPTOR,
312                               rsdt_info->pointer))->table_offset_entry[i];
313                 } else {
314                         address.pointer.value =
315                             (ACPI_CAST_PTR
316                              (XSDT_DESCRIPTOR,
317                               rsdt_info->pointer))->table_offset_entry[i];
318                 }
319
320                 /* Get the table header */
321
322                 status = acpi_tb_get_table_header(&address, header);
323                 if (ACPI_FAILURE(status)) {
324                         goto cleanup;
325                 }
326
327                 /* Compare table signatures and table instance */
328
329                 if (!ACPI_STRNCMP(header->signature, signature, ACPI_NAME_SIZE)) {
330                         /* An instance of the table was found */
331
332                         j++;
333                         if (j >= instance) {
334                                 /* Found the correct instance, get the entire table */
335
336                                 status =
337                                     acpi_tb_get_table_body(&address, header,
338                                                            table_info);
339                                 if (ACPI_FAILURE(status)) {
340                                         goto cleanup;
341                                 }
342
343                                 *table_pointer = table_info->pointer;
344                                 goto cleanup;
345                         }
346                 }
347         }
348
349         /* Did not find the table */
350
351         status = AE_NOT_EXIST;
352
353       cleanup:
354         if (rsdt_info->pointer) {
355                 acpi_os_unmap_memory(rsdt_info->pointer,
356                                      (acpi_size) rsdt_info->pointer->length);
357         }
358         ACPI_MEM_FREE(rsdt_info);
359
360         if (header) {
361                 ACPI_MEM_FREE(header);
362         }
363         if (table_info) {
364                 ACPI_MEM_FREE(table_info);
365         }
366         return_ACPI_STATUS(status);
367 }
368
369 EXPORT_SYMBOL(acpi_get_firmware_table);
370
371 /* TBD: Move to a new file */
372
373 #if ACPI_MACHINE_WIDTH != 16
374
375 /*******************************************************************************
376  *
377  * FUNCTION:    acpi_find_root_pointer
378  *
379  * PARAMETERS:  Flags                   - Logical/Physical addressing
380  *              rsdp_address            - Where to place the RSDP address
381  *
382  * RETURN:      Status, Physical address of the RSDP
383  *
384  * DESCRIPTION: Find the RSDP
385  *
386  ******************************************************************************/
387
388 acpi_status acpi_find_root_pointer(u32 flags, struct acpi_pointer *rsdp_address)
389 {
390         struct acpi_table_desc table_info;
391         acpi_status status;
392
393         ACPI_FUNCTION_TRACE("acpi_find_root_pointer");
394
395         /* Get the RSDP */
396
397         status = acpi_tb_find_rsdp(&table_info, flags);
398         if (ACPI_FAILURE(status)) {
399                 ACPI_EXCEPTION((AE_INFO, status,
400                                 "RSDP structure not found - Flags=%X", flags));
401
402                 return_ACPI_STATUS(AE_NO_ACPI_TABLES);
403         }
404
405         rsdp_address->pointer_type = ACPI_PHYSICAL_POINTER;
406         rsdp_address->pointer.physical = table_info.physical_address;
407         return_ACPI_STATUS(AE_OK);
408 }
409
410 /*******************************************************************************
411  *
412  * FUNCTION:    acpi_tb_scan_memory_for_rsdp
413  *
414  * PARAMETERS:  start_address       - Starting pointer for search
415  *              Length              - Maximum length to search
416  *
417  * RETURN:      Pointer to the RSDP if found, otherwise NULL.
418  *
419  * DESCRIPTION: Search a block of memory for the RSDP signature
420  *
421  ******************************************************************************/
422
423 static u8 *acpi_tb_scan_memory_for_rsdp(u8 * start_address, u32 length)
424 {
425         acpi_status status;
426         u8 *mem_rover;
427         u8 *end_address;
428
429         ACPI_FUNCTION_TRACE("tb_scan_memory_for_rsdp");
430
431         end_address = start_address + length;
432
433         /* Search from given start address for the requested length */
434
435         for (mem_rover = start_address; mem_rover < end_address;
436              mem_rover += ACPI_RSDP_SCAN_STEP) {
437                 /* The RSDP signature and checksum must both be correct */
438
439                 status =
440                     acpi_tb_validate_rsdp(ACPI_CAST_PTR
441                                           (struct rsdp_descriptor, mem_rover));
442                 if (ACPI_SUCCESS(status)) {
443                         /* Sig and checksum valid, we have found a real RSDP */
444
445                         ACPI_DEBUG_PRINT((ACPI_DB_INFO,
446                                           "RSDP located at physical address %p\n",
447                                           mem_rover));
448                         return_PTR(mem_rover);
449                 }
450
451                 /* No sig match or bad checksum, keep searching */
452         }
453
454         /* Searched entire block, no RSDP was found */
455
456         ACPI_DEBUG_PRINT((ACPI_DB_INFO,
457                           "Searched entire block from %p, valid RSDP was not found\n",
458                           start_address));
459         return_PTR(NULL);
460 }
461
462 /*******************************************************************************
463  *
464  * FUNCTION:    acpi_tb_find_rsdp
465  *
466  * PARAMETERS:  table_info              - Where the table info is returned
467  *              Flags                   - Current memory mode (logical vs.
468  *                                        physical addressing)
469  *
470  * RETURN:      Status, RSDP physical address
471  *
472  * DESCRIPTION: search lower 1_mbyte of memory for the root system descriptor
473  *              pointer structure.  If it is found, set *RSDP to point to it.
474  *
475  *              NOTE1: The RSDp must be either in the first 1_k of the Extended
476  *              BIOS Data Area or between E0000 and FFFFF (From ACPI Spec.)
477  *              Only a 32-bit physical address is necessary.
478  *
479  *              NOTE2: This function is always available, regardless of the
480  *              initialization state of the rest of ACPI.
481  *
482  ******************************************************************************/
483
484 static acpi_status
485 acpi_tb_find_rsdp(struct acpi_table_desc *table_info, u32 flags)
486 {
487         u8 *table_ptr;
488         u8 *mem_rover;
489         u32 physical_address;
490         acpi_status status;
491
492         ACPI_FUNCTION_TRACE("tb_find_rsdp");
493
494         /*
495          * Scan supports either logical addressing or physical addressing
496          */
497         if ((flags & ACPI_MEMORY_MODE) == ACPI_LOGICAL_ADDRESSING) {
498                 /* 1a) Get the location of the Extended BIOS Data Area (EBDA) */
499
500                 status = acpi_os_map_memory((acpi_physical_address)
501                                             ACPI_EBDA_PTR_LOCATION,
502                                             ACPI_EBDA_PTR_LENGTH,
503                                             (void *)&table_ptr);
504                 if (ACPI_FAILURE(status)) {
505                         ACPI_ERROR((AE_INFO,
506                                     "Could not map memory at %8.8X for length %X",
507                                     ACPI_EBDA_PTR_LOCATION,
508                                     ACPI_EBDA_PTR_LENGTH));
509
510                         return_ACPI_STATUS(status);
511                 }
512
513                 ACPI_MOVE_16_TO_32(&physical_address, table_ptr);
514
515                 /* Convert segment part to physical address */
516
517                 physical_address <<= 4;
518                 acpi_os_unmap_memory(table_ptr, ACPI_EBDA_PTR_LENGTH);
519
520                 /* EBDA present? */
521
522                 if (physical_address > 0x400) {
523                         /*
524                          * 1b) Search EBDA paragraphs (EBDa is required to be a
525                          *     minimum of 1_k length)
526                          */
527                         status = acpi_os_map_memory((acpi_physical_address)
528                                                     physical_address,
529                                                     ACPI_EBDA_WINDOW_SIZE,
530                                                     (void *)&table_ptr);
531                         if (ACPI_FAILURE(status)) {
532                                 ACPI_ERROR((AE_INFO,
533                                             "Could not map memory at %8.8X for length %X",
534                                             physical_address,
535                                             ACPI_EBDA_WINDOW_SIZE));
536
537                                 return_ACPI_STATUS(status);
538                         }
539
540                         mem_rover = acpi_tb_scan_memory_for_rsdp(table_ptr,
541                                                                  ACPI_EBDA_WINDOW_SIZE);
542                         acpi_os_unmap_memory(table_ptr, ACPI_EBDA_WINDOW_SIZE);
543
544                         if (mem_rover) {
545                                 /* Return the physical address */
546
547                                 physical_address +=
548                                     ACPI_PTR_DIFF(mem_rover, table_ptr);
549
550                                 table_info->physical_address =
551                                     (acpi_physical_address) physical_address;
552                                 return_ACPI_STATUS(AE_OK);
553                         }
554                 }
555
556                 /*
557                  * 2) Search upper memory: 16-byte boundaries in E0000h-FFFFFh
558                  */
559                 status = acpi_os_map_memory((acpi_physical_address)
560                                             ACPI_HI_RSDP_WINDOW_BASE,
561                                             ACPI_HI_RSDP_WINDOW_SIZE,
562                                             (void *)&table_ptr);
563
564                 if (ACPI_FAILURE(status)) {
565                         ACPI_ERROR((AE_INFO,
566                                     "Could not map memory at %8.8X for length %X",
567                                     ACPI_HI_RSDP_WINDOW_BASE,
568                                     ACPI_HI_RSDP_WINDOW_SIZE));
569
570                         return_ACPI_STATUS(status);
571                 }
572
573                 mem_rover =
574                     acpi_tb_scan_memory_for_rsdp(table_ptr,
575                                                  ACPI_HI_RSDP_WINDOW_SIZE);
576                 acpi_os_unmap_memory(table_ptr, ACPI_HI_RSDP_WINDOW_SIZE);
577
578                 if (mem_rover) {
579                         /* Return the physical address */
580
581                         physical_address =
582                             ACPI_HI_RSDP_WINDOW_BASE + ACPI_PTR_DIFF(mem_rover,
583                                                                      table_ptr);
584
585                         table_info->physical_address =
586                             (acpi_physical_address) physical_address;
587                         return_ACPI_STATUS(AE_OK);
588                 }
589         }
590
591         /*
592          * Physical addressing
593          */
594         else {
595                 /* 1a) Get the location of the EBDA */
596
597                 ACPI_MOVE_16_TO_32(&physical_address, ACPI_EBDA_PTR_LOCATION);
598                 physical_address <<= 4; /* Convert segment to physical address */
599
600                 /* EBDA present? */
601
602                 if (physical_address > 0x400) {
603                         /*
604                          * 1b) Search EBDA paragraphs (EBDa is required to be a minimum of
605                          *     1_k length)
606                          */
607                         mem_rover =
608                             acpi_tb_scan_memory_for_rsdp(ACPI_PHYSADDR_TO_PTR
609                                                          (physical_address),
610                                                          ACPI_EBDA_WINDOW_SIZE);
611                         if (mem_rover) {
612                                 /* Return the physical address */
613
614                                 table_info->physical_address =
615                                     ACPI_TO_INTEGER(mem_rover);
616                                 return_ACPI_STATUS(AE_OK);
617                         }
618                 }
619
620                 /* 2) Search upper memory: 16-byte boundaries in E0000h-FFFFFh */
621
622                 mem_rover =
623                     acpi_tb_scan_memory_for_rsdp(ACPI_PHYSADDR_TO_PTR
624                                                  (ACPI_HI_RSDP_WINDOW_BASE),
625                                                  ACPI_HI_RSDP_WINDOW_SIZE);
626                 if (mem_rover) {
627                         /* Found it, return the physical address */
628
629                         table_info->physical_address =
630                             ACPI_TO_INTEGER(mem_rover);
631                         return_ACPI_STATUS(AE_OK);
632                 }
633         }
634
635         /* A valid RSDP was not found */
636
637         ACPI_ERROR((AE_INFO, "No valid RSDP was found"));
638         return_ACPI_STATUS(AE_NOT_FOUND);
639 }
640
641 #endif