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