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