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