]> err.no Git - linux-2.6/blob - drivers/acpi/tables/tbxfroot.c
ACPI: ACPICA 20060310
[linux-2.6] / 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 <acpi/acpi.h>
45 #include <acpi/actables.h>
46
47 #define _COMPONENT          ACPI_TABLES
48 ACPI_MODULE_NAME("tbxfroot")
49
50 /* Local prototypes */
51 static acpi_status
52 acpi_tb_find_rsdp(struct acpi_table_desc *table_info, u32 flags);
53
54 static u8 *acpi_tb_scan_memory_for_rsdp(u8 * start_address, u32 length);
55
56 /*******************************************************************************
57  *
58  * FUNCTION:    acpi_tb_validate_rsdp
59  *
60  * PARAMETERS:  Rsdp        - Pointer to unvalidated RSDP
61  *
62  * RETURN:      Status
63  *
64  * DESCRIPTION: Validate the RSDP (ptr)
65  *
66  ******************************************************************************/
67
68 acpi_status acpi_tb_validate_rsdp(struct rsdp_descriptor *rsdp)
69 {
70         ACPI_FUNCTION_ENTRY();
71
72         /*
73          *  The signature and checksum must both be correct
74          */
75         if (ACPI_STRNCMP((char *)rsdp, RSDP_SIG, sizeof(RSDP_SIG) - 1) != 0) {
76
77                 /* Nope, BAD Signature */
78
79                 return (AE_BAD_SIGNATURE);
80         }
81
82         /* Check the standard checksum */
83
84         if (acpi_tb_generate_checksum(rsdp, ACPI_RSDP_CHECKSUM_LENGTH) != 0) {
85                 return (AE_BAD_CHECKSUM);
86         }
87
88         /* Check extended checksum if table version >= 2 */
89
90         if ((rsdp->revision >= 2) &&
91             (acpi_tb_generate_checksum(rsdp, ACPI_RSDP_XCHECKSUM_LENGTH) !=
92              0)) {
93                 return (AE_BAD_CHECKSUM);
94         }
95
96         return (AE_OK);
97 }
98
99 /*******************************************************************************
100  *
101  * FUNCTION:    acpi_tb_find_table
102  *
103  * PARAMETERS:  Signature           - String with ACPI table signature
104  *              oem_id              - String with the table OEM ID
105  *              oem_table_id        - String with the OEM Table ID
106  *              table_ptr           - Where the table pointer is returned
107  *
108  * RETURN:      Status
109  *
110  * DESCRIPTION: Find an ACPI table (in the RSDT/XSDT) that matches the
111  *              Signature, OEM ID and OEM Table ID.
112  *
113  ******************************************************************************/
114
115 acpi_status
116 acpi_tb_find_table(char *signature,
117                    char *oem_id,
118                    char *oem_table_id, struct acpi_table_header ** table_ptr)
119 {
120         acpi_status status;
121         struct acpi_table_header *table;
122
123         ACPI_FUNCTION_TRACE("tb_find_table");
124
125         /* Validate string lengths */
126
127         if ((ACPI_STRLEN(signature) > ACPI_NAME_SIZE) ||
128             (ACPI_STRLEN(oem_id) > sizeof(table->oem_id)) ||
129             (ACPI_STRLEN(oem_table_id) > sizeof(table->oem_table_id))) {
130                 return_ACPI_STATUS(AE_AML_STRING_LIMIT);
131         }
132
133         if (!ACPI_STRNCMP(signature, DSDT_SIG, ACPI_NAME_SIZE)) {
134                 /*
135                  * The DSDT pointer is contained in the FADT, not the RSDT.
136                  * This code should suffice, because the only code that would perform
137                  * a "find" on the DSDT is the data_table_region() AML opcode -- in
138                  * which case, the DSDT is guaranteed to be already loaded.
139                  * If this becomes insufficient, the FADT will have to be found first.
140                  */
141                 if (!acpi_gbl_DSDT) {
142                         return_ACPI_STATUS(AE_NO_ACPI_TABLES);
143                 }
144                 table = acpi_gbl_DSDT;
145         } else {
146                 /* Find the table */
147
148                 status = acpi_get_firmware_table(signature, 1,
149                                                  ACPI_LOGICAL_ADDRESSING,
150                                                  &table);
151                 if (ACPI_FAILURE(status)) {
152                         return_ACPI_STATUS(status);
153                 }
154         }
155
156         /* Check oem_id and oem_table_id */
157
158         if ((oem_id[0] && ACPI_STRNCMP(oem_id, table->oem_id,
159                                        sizeof(table->oem_id))) ||
160             (oem_table_id[0] && ACPI_STRNCMP(oem_table_id, table->oem_table_id,
161                                              sizeof(table->oem_table_id)))) {
162                 return_ACPI_STATUS(AE_AML_NAME_NOT_FOUND);
163         }
164
165         ACPI_DEBUG_PRINT((ACPI_DB_TABLES, "Found table [%4.4s]\n",
166                           table->signature));
167
168         *table_ptr = table;
169         return_ACPI_STATUS(AE_OK);
170 }
171
172 /*******************************************************************************
173  *
174  * FUNCTION:    acpi_get_firmware_table
175  *
176  * PARAMETERS:  Signature       - Any ACPI table signature
177  *              Instance        - the non zero instance of the table, allows
178  *                                support for multiple tables of the same type
179  *              Flags           - Physical/Virtual support
180  *              table_pointer   - Where a buffer containing the table is
181  *                                returned
182  *
183  * RETURN:      Status
184  *
185  * DESCRIPTION: This function is called to get an ACPI table. A buffer is
186  *              allocated for the table and returned in table_pointer.
187  *              This table will be a complete table including the header.
188  *
189  ******************************************************************************/
190
191 acpi_status
192 acpi_get_firmware_table(acpi_string signature,
193                         u32 instance,
194                         u32 flags, struct acpi_table_header **table_pointer)
195 {
196         acpi_status status;
197         struct acpi_pointer address;
198         struct acpi_table_header *header = NULL;
199         struct acpi_table_desc *table_info = NULL;
200         struct acpi_table_desc *rsdt_info;
201         u32 table_count;
202         u32 i;
203         u32 j;
204
205         ACPI_FUNCTION_TRACE("acpi_get_firmware_table");
206
207         /*
208          * Ensure that at least the table manager is initialized.  We don't
209          * require that the entire ACPI subsystem is up for this interface.
210          * If we have a buffer, we must have a length too
211          */
212         if ((instance == 0) || (!signature) || (!table_pointer)) {
213                 return_ACPI_STATUS(AE_BAD_PARAMETER);
214         }
215
216         /* Ensure that we have a RSDP */
217
218         if (!acpi_gbl_RSDP) {
219
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_ALLOCATE_ZEROED(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_ALLOCATE(sizeof(struct acpi_table_header));
282         if (!header) {
283                 status = AE_NO_MEMORY;
284                 goto cleanup;
285         }
286
287         table_info = ACPI_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
331                         /* An instance of the table was found */
332
333                         j++;
334                         if (j >= instance) {
335
336                                 /* Found the correct instance, get the entire table */
337
338                                 status =
339                                     acpi_tb_get_table_body(&address, header,
340                                                            table_info);
341                                 if (ACPI_FAILURE(status)) {
342                                         goto cleanup;
343                                 }
344
345                                 *table_pointer = table_info->pointer;
346                                 goto cleanup;
347                         }
348                 }
349         }
350
351         /* Did not find the table */
352
353         status = AE_NOT_EXIST;
354
355       cleanup:
356         if (rsdt_info->pointer) {
357                 acpi_os_unmap_memory(rsdt_info->pointer,
358                                      (acpi_size) rsdt_info->pointer->length);
359         }
360         ACPI_FREE(rsdt_info);
361
362         if (header) {
363                 ACPI_FREE(header);
364         }
365         if (table_info) {
366                 ACPI_FREE(table_info);
367         }
368         return_ACPI_STATUS(status);
369 }
370
371 ACPI_EXPORT_SYMBOL(acpi_get_firmware_table)
372
373 /* TBD: Move to a new file */
374 #if ACPI_MACHINE_WIDTH != 16
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 acpi_status acpi_find_root_pointer(u32 flags, struct acpi_pointer *rsdp_address)
388 {
389         struct acpi_table_desc table_info;
390         acpi_status status;
391
392         ACPI_FUNCTION_TRACE("acpi_find_root_pointer");
393
394         /* Get the RSDP */
395
396         status = acpi_tb_find_rsdp(&table_info, flags);
397         if (ACPI_FAILURE(status)) {
398                 ACPI_EXCEPTION((AE_INFO, status,
399                                 "RSDP structure not found - Flags=%X", flags));
400
401                 return_ACPI_STATUS(AE_NO_ACPI_TABLES);
402         }
403
404         rsdp_address->pointer_type = ACPI_PHYSICAL_POINTER;
405         rsdp_address->pointer.physical = table_info.physical_address;
406         return_ACPI_STATUS(AE_OK);
407 }
408
409 ACPI_EXPORT_SYMBOL(acpi_find_root_pointer)
410
411 /*******************************************************************************
412  *
413  * FUNCTION:    acpi_tb_scan_memory_for_rsdp
414  *
415  * PARAMETERS:  start_address       - Starting pointer for search
416  *              Length              - Maximum length to search
417  *
418  * RETURN:      Pointer to the RSDP if found, otherwise NULL.
419  *
420  * DESCRIPTION: Search a block of memory for the RSDP signature
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
438                 /* The RSDP signature and checksum must both be correct */
439
440                 status =
441                     acpi_tb_validate_rsdp(ACPI_CAST_PTR
442                                           (struct rsdp_descriptor, mem_rover));
443                 if (ACPI_SUCCESS(status)) {
444
445                         /* Sig and checksum valid, we have found a real RSDP */
446
447                         ACPI_DEBUG_PRINT((ACPI_DB_INFO,
448                                           "RSDP located at physical address %p\n",
449                                           mem_rover));
450                         return_PTR(mem_rover);
451                 }
452
453                 /* No sig match or bad checksum, keep searching */
454         }
455
456         /* Searched entire block, no RSDP was found */
457
458         ACPI_DEBUG_PRINT((ACPI_DB_INFO,
459                           "Searched entire block from %p, valid RSDP was not found\n",
460                           start_address));
461         return_PTR(NULL);
462 }
463
464 /*******************************************************************************
465  *
466  * FUNCTION:    acpi_tb_find_rsdp
467  *
468  * PARAMETERS:  table_info              - Where the table info is returned
469  *              Flags                   - Current memory mode (logical vs.
470  *                                        physical addressing)
471  *
472  * RETURN:      Status, RSDP physical address
473  *
474  * DESCRIPTION: search lower 1_mbyte of memory for the root system descriptor
475  *              pointer structure.  If it is found, set *RSDP to point to it.
476  *
477  *              NOTE1: The RSDp must be either in the first 1_k of the Extended
478  *              BIOS Data Area or between E0000 and FFFFF (From ACPI Spec.)
479  *              Only a 32-bit physical address is necessary.
480  *
481  *              NOTE2: This function is always available, regardless of the
482  *              initialization state of the rest of ACPI.
483  *
484  ******************************************************************************/
485
486 static acpi_status
487 acpi_tb_find_rsdp(struct acpi_table_desc *table_info, u32 flags)
488 {
489         u8 *table_ptr;
490         u8 *mem_rover;
491         u32 physical_address;
492         acpi_status status;
493
494         ACPI_FUNCTION_TRACE("tb_find_rsdp");
495
496         /*
497          * Scan supports either logical addressing or physical addressing
498          */
499         if ((flags & ACPI_MEMORY_MODE) == ACPI_LOGICAL_ADDRESSING) {
500
501                 /* 1a) Get the location of the Extended BIOS Data Area (EBDA) */
502
503                 status = acpi_os_map_memory((acpi_physical_address)
504                                             ACPI_EBDA_PTR_LOCATION,
505                                             ACPI_EBDA_PTR_LENGTH,
506                                             (void *)&table_ptr);
507                 if (ACPI_FAILURE(status)) {
508                         ACPI_ERROR((AE_INFO,
509                                     "Could not map memory at %8.8X for length %X",
510                                     ACPI_EBDA_PTR_LOCATION,
511                                     ACPI_EBDA_PTR_LENGTH));
512
513                         return_ACPI_STATUS(status);
514                 }
515
516                 ACPI_MOVE_16_TO_32(&physical_address, table_ptr);
517
518                 /* Convert segment part to physical address */
519
520                 physical_address <<= 4;
521                 acpi_os_unmap_memory(table_ptr, ACPI_EBDA_PTR_LENGTH);
522
523                 /* EBDA present? */
524
525                 if (physical_address > 0x400) {
526                         /*
527                          * 1b) Search EBDA paragraphs (EBDa is required to be a
528                          *     minimum of 1_k length)
529                          */
530                         status = acpi_os_map_memory((acpi_physical_address)
531                                                     physical_address,
532                                                     ACPI_EBDA_WINDOW_SIZE,
533                                                     (void *)&table_ptr);
534                         if (ACPI_FAILURE(status)) {
535                                 ACPI_ERROR((AE_INFO,
536                                             "Could not map memory at %8.8X for length %X",
537                                             physical_address,
538                                             ACPI_EBDA_WINDOW_SIZE));
539
540                                 return_ACPI_STATUS(status);
541                         }
542
543                         mem_rover = acpi_tb_scan_memory_for_rsdp(table_ptr,
544                                                                  ACPI_EBDA_WINDOW_SIZE);
545                         acpi_os_unmap_memory(table_ptr, ACPI_EBDA_WINDOW_SIZE);
546
547                         if (mem_rover) {
548
549                                 /* Return the physical address */
550
551                                 physical_address +=
552                                     ACPI_PTR_DIFF(mem_rover, table_ptr);
553
554                                 table_info->physical_address =
555                                     (acpi_physical_address) physical_address;
556                                 return_ACPI_STATUS(AE_OK);
557                         }
558                 }
559
560                 /*
561                  * 2) Search upper memory: 16-byte boundaries in E0000h-FFFFFh
562                  */
563                 status = acpi_os_map_memory((acpi_physical_address)
564                                             ACPI_HI_RSDP_WINDOW_BASE,
565                                             ACPI_HI_RSDP_WINDOW_SIZE,
566                                             (void *)&table_ptr);
567
568                 if (ACPI_FAILURE(status)) {
569                         ACPI_ERROR((AE_INFO,
570                                     "Could not map memory at %8.8X for length %X",
571                                     ACPI_HI_RSDP_WINDOW_BASE,
572                                     ACPI_HI_RSDP_WINDOW_SIZE));
573
574                         return_ACPI_STATUS(status);
575                 }
576
577                 mem_rover =
578                     acpi_tb_scan_memory_for_rsdp(table_ptr,
579                                                  ACPI_HI_RSDP_WINDOW_SIZE);
580                 acpi_os_unmap_memory(table_ptr, ACPI_HI_RSDP_WINDOW_SIZE);
581
582                 if (mem_rover) {
583
584                         /* Return the physical address */
585
586                         physical_address =
587                             ACPI_HI_RSDP_WINDOW_BASE + ACPI_PTR_DIFF(mem_rover,
588                                                                      table_ptr);
589
590                         table_info->physical_address =
591                             (acpi_physical_address) physical_address;
592                         return_ACPI_STATUS(AE_OK);
593                 }
594         }
595
596         /*
597          * Physical addressing
598          */
599         else {
600                 /* 1a) Get the location of the EBDA */
601
602                 ACPI_MOVE_16_TO_32(&physical_address, ACPI_EBDA_PTR_LOCATION);
603                 physical_address <<= 4; /* Convert segment to physical address */
604
605                 /* EBDA present? */
606
607                 if (physical_address > 0x400) {
608                         /*
609                          * 1b) Search EBDA paragraphs (EBDa is required to be a minimum of
610                          *     1_k length)
611                          */
612                         mem_rover =
613                             acpi_tb_scan_memory_for_rsdp(ACPI_PHYSADDR_TO_PTR
614                                                          (physical_address),
615                                                          ACPI_EBDA_WINDOW_SIZE);
616                         if (mem_rover) {
617
618                                 /* Return the physical address */
619
620                                 table_info->physical_address =
621                                     ACPI_TO_INTEGER(mem_rover);
622                                 return_ACPI_STATUS(AE_OK);
623                         }
624                 }
625
626                 /* 2) Search upper memory: 16-byte boundaries in E0000h-FFFFFh */
627
628                 mem_rover =
629                     acpi_tb_scan_memory_for_rsdp(ACPI_PHYSADDR_TO_PTR
630                                                  (ACPI_HI_RSDP_WINDOW_BASE),
631                                                  ACPI_HI_RSDP_WINDOW_SIZE);
632                 if (mem_rover) {
633
634                         /* Found it, return the physical address */
635
636                         table_info->physical_address =
637                             ACPI_TO_INTEGER(mem_rover);
638                         return_ACPI_STATUS(AE_OK);
639                 }
640         }
641
642         /* A valid RSDP was not found */
643
644         ACPI_ERROR((AE_INFO, "No valid RSDP was found"));
645         return_ACPI_STATUS(AE_NOT_FOUND);
646 }
647
648 #endif