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