GNU Linux-libre 4.19.264-gnu1
[releases.git] / tools / power / acpi / os_specific / service_layers / oslinuxtbl.c
1 // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
2 /******************************************************************************
3  *
4  * Module Name: oslinuxtbl - Linux OSL for obtaining ACPI tables
5  *
6  * Copyright (C) 2000 - 2018, Intel Corp.
7  *
8  *****************************************************************************/
9
10 #include "acpidump.h"
11
12 #define _COMPONENT          ACPI_OS_SERVICES
13 ACPI_MODULE_NAME("oslinuxtbl")
14
15 #ifndef PATH_MAX
16 #define PATH_MAX 256
17 #endif
18 /* List of information about obtained ACPI tables */
19 typedef struct osl_table_info {
20         struct osl_table_info *next;
21         u32 instance;
22         char signature[ACPI_NAME_SIZE];
23
24 } osl_table_info;
25
26 /* Local prototypes */
27
28 static acpi_status osl_table_initialize(void);
29
30 static acpi_status
31 osl_table_name_from_file(char *filename, char *signature, u32 *instance);
32
33 static acpi_status osl_add_table_to_list(char *signature, u32 instance);
34
35 static acpi_status
36 osl_read_table_from_file(char *filename,
37                          acpi_size file_offset,
38                          char *signature, struct acpi_table_header **table);
39
40 static acpi_status
41 osl_map_table(acpi_size address,
42               char *signature, struct acpi_table_header **table);
43
44 static void osl_unmap_table(struct acpi_table_header *table);
45
46 static acpi_physical_address
47 osl_find_rsdp_via_efi_by_keyword(FILE * file, const char *keyword);
48
49 static acpi_physical_address osl_find_rsdp_via_efi(void);
50
51 static acpi_status osl_load_rsdp(void);
52
53 static acpi_status osl_list_customized_tables(char *directory);
54
55 static acpi_status
56 osl_get_customized_table(char *pathname,
57                          char *signature,
58                          u32 instance,
59                          struct acpi_table_header **table,
60                          acpi_physical_address *address);
61
62 static acpi_status osl_list_bios_tables(void);
63
64 static acpi_status
65 osl_get_bios_table(char *signature,
66                    u32 instance,
67                    struct acpi_table_header **table,
68                    acpi_physical_address *address);
69
70 static acpi_status osl_get_last_status(acpi_status default_status);
71
72 /* File locations */
73
74 #define DYNAMIC_TABLE_DIR   "/sys/firmware/acpi/tables/dynamic"
75 #define STATIC_TABLE_DIR    "/sys/firmware/acpi/tables"
76 #define EFI_SYSTAB          "/sys/firmware/efi/systab"
77
78 /* Should we get dynamically loaded SSDTs from DYNAMIC_TABLE_DIR? */
79
80 u8 gbl_dump_dynamic_tables = TRUE;
81
82 /* Initialization flags */
83
84 u8 gbl_table_list_initialized = FALSE;
85
86 /* Local copies of main ACPI tables */
87
88 struct acpi_table_rsdp gbl_rsdp;
89 struct acpi_table_fadt *gbl_fadt = NULL;
90 struct acpi_table_rsdt *gbl_rsdt = NULL;
91 struct acpi_table_xsdt *gbl_xsdt = NULL;
92
93 /* Table addresses */
94
95 acpi_physical_address gbl_fadt_address = 0;
96 acpi_physical_address gbl_rsdp_address = 0;
97
98 /* Revision of RSD PTR */
99
100 u8 gbl_revision = 0;
101
102 struct osl_table_info *gbl_table_list_head = NULL;
103 u32 gbl_table_count = 0;
104
105 /******************************************************************************
106  *
107  * FUNCTION:    osl_get_last_status
108  *
109  * PARAMETERS:  default_status  - Default error status to return
110  *
111  * RETURN:      Status; Converted from errno.
112  *
113  * DESCRIPTION: Get last errno and conver it to acpi_status.
114  *
115  *****************************************************************************/
116
117 static acpi_status osl_get_last_status(acpi_status default_status)
118 {
119
120         switch (errno) {
121         case EACCES:
122         case EPERM:
123
124                 return (AE_ACCESS);
125
126         case ENOENT:
127
128                 return (AE_NOT_FOUND);
129
130         case ENOMEM:
131
132                 return (AE_NO_MEMORY);
133
134         default:
135
136                 return (default_status);
137         }
138 }
139
140 /******************************************************************************
141  *
142  * FUNCTION:    acpi_os_get_table_by_address
143  *
144  * PARAMETERS:  address         - Physical address of the ACPI table
145  *              table           - Where a pointer to the table is returned
146  *
147  * RETURN:      Status; Table buffer is returned if AE_OK.
148  *              AE_NOT_FOUND: A valid table was not found at the address
149  *
150  * DESCRIPTION: Get an ACPI table via a physical memory address.
151  *
152  *****************************************************************************/
153
154 acpi_status
155 acpi_os_get_table_by_address(acpi_physical_address address,
156                              struct acpi_table_header **table)
157 {
158         u32 table_length;
159         struct acpi_table_header *mapped_table;
160         struct acpi_table_header *local_table = NULL;
161         acpi_status status = AE_OK;
162
163         /* Get main ACPI tables from memory on first invocation of this function */
164
165         status = osl_table_initialize();
166         if (ACPI_FAILURE(status)) {
167                 return (status);
168         }
169
170         /* Map the table and validate it */
171
172         status = osl_map_table(address, NULL, &mapped_table);
173         if (ACPI_FAILURE(status)) {
174                 return (status);
175         }
176
177         /* Copy table to local buffer and return it */
178
179         table_length = ap_get_table_length(mapped_table);
180         if (table_length == 0) {
181                 status = AE_BAD_HEADER;
182                 goto exit;
183         }
184
185         local_table = calloc(1, table_length);
186         if (!local_table) {
187                 status = AE_NO_MEMORY;
188                 goto exit;
189         }
190
191         memcpy(local_table, mapped_table, table_length);
192
193 exit:
194         osl_unmap_table(mapped_table);
195         *table = local_table;
196         return (status);
197 }
198
199 /******************************************************************************
200  *
201  * FUNCTION:    acpi_os_get_table_by_name
202  *
203  * PARAMETERS:  signature       - ACPI Signature for desired table. Must be
204  *                                a null terminated 4-character string.
205  *              instance        - Multiple table support for SSDT/UEFI (0...n)
206  *                                Must be 0 for other tables.
207  *              table           - Where a pointer to the table is returned
208  *              address         - Where the table physical address is returned
209  *
210  * RETURN:      Status; Table buffer and physical address returned if AE_OK.
211  *              AE_LIMIT: Instance is beyond valid limit
212  *              AE_NOT_FOUND: A table with the signature was not found
213  *
214  * NOTE:        Assumes the input signature is uppercase.
215  *
216  *****************************************************************************/
217
218 acpi_status
219 acpi_os_get_table_by_name(char *signature,
220                           u32 instance,
221                           struct acpi_table_header **table,
222                           acpi_physical_address *address)
223 {
224         acpi_status status;
225
226         /* Get main ACPI tables from memory on first invocation of this function */
227
228         status = osl_table_initialize();
229         if (ACPI_FAILURE(status)) {
230                 return (status);
231         }
232
233         /* Not a main ACPI table, attempt to extract it from the RSDT/XSDT */
234
235         if (!gbl_dump_customized_tables) {
236
237                 /* Attempt to get the table from the memory */
238
239                 status =
240                     osl_get_bios_table(signature, instance, table, address);
241         } else {
242                 /* Attempt to get the table from the static directory */
243
244                 status = osl_get_customized_table(STATIC_TABLE_DIR, signature,
245                                                   instance, table, address);
246         }
247
248         if (ACPI_FAILURE(status) && status == AE_LIMIT) {
249                 if (gbl_dump_dynamic_tables) {
250
251                         /* Attempt to get a dynamic table */
252
253                         status =
254                             osl_get_customized_table(DYNAMIC_TABLE_DIR,
255                                                      signature, instance, table,
256                                                      address);
257                 }
258         }
259
260         return (status);
261 }
262
263 /******************************************************************************
264  *
265  * FUNCTION:    osl_add_table_to_list
266  *
267  * PARAMETERS:  signature       - Table signature
268  *              instance        - Table instance
269  *
270  * RETURN:      Status; Successfully added if AE_OK.
271  *              AE_NO_MEMORY: Memory allocation error
272  *
273  * DESCRIPTION: Insert a table structure into OSL table list.
274  *
275  *****************************************************************************/
276
277 static acpi_status osl_add_table_to_list(char *signature, u32 instance)
278 {
279         struct osl_table_info *new_info;
280         struct osl_table_info *next;
281         u32 next_instance = 0;
282         u8 found = FALSE;
283
284         new_info = calloc(1, sizeof(struct osl_table_info));
285         if (!new_info) {
286                 return (AE_NO_MEMORY);
287         }
288
289         ACPI_MOVE_NAME(new_info->signature, signature);
290
291         if (!gbl_table_list_head) {
292                 gbl_table_list_head = new_info;
293         } else {
294                 next = gbl_table_list_head;
295                 while (1) {
296                         if (ACPI_COMPARE_NAME(next->signature, signature)) {
297                                 if (next->instance == instance) {
298                                         found = TRUE;
299                                 }
300                                 if (next->instance >= next_instance) {
301                                         next_instance = next->instance + 1;
302                                 }
303                         }
304
305                         if (!next->next) {
306                                 break;
307                         }
308                         next = next->next;
309                 }
310                 next->next = new_info;
311         }
312
313         if (found) {
314                 if (instance) {
315                         fprintf(stderr,
316                                 "%4.4s: Warning unmatched table instance %d, expected %d\n",
317                                 signature, instance, next_instance);
318                 }
319                 instance = next_instance;
320         }
321
322         new_info->instance = instance;
323         gbl_table_count++;
324
325         return (AE_OK);
326 }
327
328 /******************************************************************************
329  *
330  * FUNCTION:    acpi_os_get_table_by_index
331  *
332  * PARAMETERS:  index           - Which table to get
333  *              table           - Where a pointer to the table is returned
334  *              instance        - Where a pointer to the table instance no. is
335  *                                returned
336  *              address         - Where the table physical address is returned
337  *
338  * RETURN:      Status; Table buffer and physical address returned if AE_OK.
339  *              AE_LIMIT: Index is beyond valid limit
340  *
341  * DESCRIPTION: Get an ACPI table via an index value (0 through n). Returns
342  *              AE_LIMIT when an invalid index is reached. Index is not
343  *              necessarily an index into the RSDT/XSDT.
344  *
345  *****************************************************************************/
346
347 acpi_status
348 acpi_os_get_table_by_index(u32 index,
349                            struct acpi_table_header **table,
350                            u32 *instance, acpi_physical_address *address)
351 {
352         struct osl_table_info *info;
353         acpi_status status;
354         u32 i;
355
356         /* Get main ACPI tables from memory on first invocation of this function */
357
358         status = osl_table_initialize();
359         if (ACPI_FAILURE(status)) {
360                 return (status);
361         }
362
363         /* Validate Index */
364
365         if (index >= gbl_table_count) {
366                 return (AE_LIMIT);
367         }
368
369         /* Point to the table list entry specified by the Index argument */
370
371         info = gbl_table_list_head;
372         for (i = 0; i < index; i++) {
373                 info = info->next;
374         }
375
376         /* Now we can just get the table via the signature */
377
378         status = acpi_os_get_table_by_name(info->signature, info->instance,
379                                            table, address);
380
381         if (ACPI_SUCCESS(status)) {
382                 *instance = info->instance;
383         }
384         return (status);
385 }
386
387 /******************************************************************************
388  *
389  * FUNCTION:    osl_find_rsdp_via_efi_by_keyword
390  *
391  * PARAMETERS:  keyword         - Character string indicating ACPI GUID version
392  *                                in the EFI table
393  *
394  * RETURN:      RSDP address if found
395  *
396  * DESCRIPTION: Find RSDP address via EFI using keyword indicating the ACPI
397  *              GUID version.
398  *
399  *****************************************************************************/
400
401 static acpi_physical_address
402 osl_find_rsdp_via_efi_by_keyword(FILE * file, const char *keyword)
403 {
404         char buffer[80];
405         unsigned long long address = 0;
406         char format[32];
407
408         snprintf(format, 32, "%s=%s", keyword, "%llx");
409         fseek(file, 0, SEEK_SET);
410         while (fgets(buffer, 80, file)) {
411                 if (sscanf(buffer, format, &address) == 1) {
412                         break;
413                 }
414         }
415
416         return ((acpi_physical_address)(address));
417 }
418
419 /******************************************************************************
420  *
421  * FUNCTION:    osl_find_rsdp_via_efi
422  *
423  * PARAMETERS:  None
424  *
425  * RETURN:      RSDP address if found
426  *
427  * DESCRIPTION: Find RSDP address via EFI.
428  *
429  *****************************************************************************/
430
431 static acpi_physical_address osl_find_rsdp_via_efi(void)
432 {
433         FILE *file;
434         acpi_physical_address address = 0;
435
436         file = fopen(EFI_SYSTAB, "r");
437         if (file) {
438                 address = osl_find_rsdp_via_efi_by_keyword(file, "ACPI20");
439                 if (!address) {
440                         address =
441                             osl_find_rsdp_via_efi_by_keyword(file, "ACPI");
442                 }
443                 fclose(file);
444         }
445
446         return (address);
447 }
448
449 /******************************************************************************
450  *
451  * FUNCTION:    osl_load_rsdp
452  *
453  * PARAMETERS:  None
454  *
455  * RETURN:      Status
456  *
457  * DESCRIPTION: Scan and load RSDP.
458  *
459  *****************************************************************************/
460
461 static acpi_status osl_load_rsdp(void)
462 {
463         struct acpi_table_header *mapped_table;
464         u8 *rsdp_address;
465         acpi_physical_address rsdp_base;
466         acpi_size rsdp_size;
467
468         /* Get RSDP from memory */
469
470         rsdp_size = sizeof(struct acpi_table_rsdp);
471         if (gbl_rsdp_base) {
472                 rsdp_base = gbl_rsdp_base;
473         } else {
474                 rsdp_base = osl_find_rsdp_via_efi();
475         }
476
477         if (!rsdp_base) {
478                 rsdp_base = ACPI_HI_RSDP_WINDOW_BASE;
479                 rsdp_size = ACPI_HI_RSDP_WINDOW_SIZE;
480         }
481
482         rsdp_address = acpi_os_map_memory(rsdp_base, rsdp_size);
483         if (!rsdp_address) {
484                 return (osl_get_last_status(AE_BAD_ADDRESS));
485         }
486
487         /* Search low memory for the RSDP */
488
489         mapped_table = ACPI_CAST_PTR(struct acpi_table_header,
490                                      acpi_tb_scan_memory_for_rsdp(rsdp_address,
491                                                                   rsdp_size));
492         if (!mapped_table) {
493                 acpi_os_unmap_memory(rsdp_address, rsdp_size);
494                 return (AE_NOT_FOUND);
495         }
496
497         gbl_rsdp_address =
498             rsdp_base + (ACPI_CAST8(mapped_table) - rsdp_address);
499
500         memcpy(&gbl_rsdp, mapped_table, sizeof(struct acpi_table_rsdp));
501         acpi_os_unmap_memory(rsdp_address, rsdp_size);
502
503         return (AE_OK);
504 }
505
506 /******************************************************************************
507  *
508  * FUNCTION:    osl_can_use_xsdt
509  *
510  * PARAMETERS:  None
511  *
512  * RETURN:      TRUE if XSDT is allowed to be used.
513  *
514  * DESCRIPTION: This function collects logic that can be used to determine if
515  *              XSDT should be used instead of RSDT.
516  *
517  *****************************************************************************/
518
519 static u8 osl_can_use_xsdt(void)
520 {
521         if (gbl_revision && !acpi_gbl_do_not_use_xsdt) {
522                 return (TRUE);
523         } else {
524                 return (FALSE);
525         }
526 }
527
528 /******************************************************************************
529  *
530  * FUNCTION:    osl_table_initialize
531  *
532  * PARAMETERS:  None
533  *
534  * RETURN:      Status
535  *
536  * DESCRIPTION: Initialize ACPI table data. Get and store main ACPI tables to
537  *              local variables. Main ACPI tables include RSDT, FADT, RSDT,
538  *              and/or XSDT.
539  *
540  *****************************************************************************/
541
542 static acpi_status osl_table_initialize(void)
543 {
544         acpi_status status;
545         acpi_physical_address address;
546
547         if (gbl_table_list_initialized) {
548                 return (AE_OK);
549         }
550
551         if (!gbl_dump_customized_tables) {
552
553                 /* Get RSDP from memory */
554
555                 status = osl_load_rsdp();
556                 if (ACPI_FAILURE(status)) {
557                         return (status);
558                 }
559
560                 /* Get XSDT from memory */
561
562                 if (gbl_rsdp.revision && !gbl_do_not_dump_xsdt) {
563                         if (gbl_xsdt) {
564                                 free(gbl_xsdt);
565                                 gbl_xsdt = NULL;
566                         }
567
568                         gbl_revision = 2;
569                         status = osl_get_bios_table(ACPI_SIG_XSDT, 0,
570                                                     ACPI_CAST_PTR(struct
571                                                                   acpi_table_header
572                                                                   *, &gbl_xsdt),
573                                                     &address);
574                         if (ACPI_FAILURE(status)) {
575                                 return (status);
576                         }
577                 }
578
579                 /* Get RSDT from memory */
580
581                 if (gbl_rsdp.rsdt_physical_address) {
582                         if (gbl_rsdt) {
583                                 free(gbl_rsdt);
584                                 gbl_rsdt = NULL;
585                         }
586
587                         status = osl_get_bios_table(ACPI_SIG_RSDT, 0,
588                                                     ACPI_CAST_PTR(struct
589                                                                   acpi_table_header
590                                                                   *, &gbl_rsdt),
591                                                     &address);
592                         if (ACPI_FAILURE(status)) {
593                                 return (status);
594                         }
595                 }
596
597                 /* Get FADT from memory */
598
599                 if (gbl_fadt) {
600                         free(gbl_fadt);
601                         gbl_fadt = NULL;
602                 }
603
604                 status = osl_get_bios_table(ACPI_SIG_FADT, 0,
605                                             ACPI_CAST_PTR(struct
606                                                           acpi_table_header *,
607                                                           &gbl_fadt),
608                                             &gbl_fadt_address);
609                 if (ACPI_FAILURE(status)) {
610                         return (status);
611                 }
612
613                 /* Add mandatory tables to global table list first */
614
615                 status = osl_add_table_to_list(ACPI_RSDP_NAME, 0);
616                 if (ACPI_FAILURE(status)) {
617                         return (status);
618                 }
619
620                 status = osl_add_table_to_list(ACPI_SIG_RSDT, 0);
621                 if (ACPI_FAILURE(status)) {
622                         return (status);
623                 }
624
625                 if (gbl_revision == 2) {
626                         status = osl_add_table_to_list(ACPI_SIG_XSDT, 0);
627                         if (ACPI_FAILURE(status)) {
628                                 return (status);
629                         }
630                 }
631
632                 status = osl_add_table_to_list(ACPI_SIG_DSDT, 0);
633                 if (ACPI_FAILURE(status)) {
634                         return (status);
635                 }
636
637                 status = osl_add_table_to_list(ACPI_SIG_FACS, 0);
638                 if (ACPI_FAILURE(status)) {
639                         return (status);
640                 }
641
642                 /* Add all tables found in the memory */
643
644                 status = osl_list_bios_tables();
645                 if (ACPI_FAILURE(status)) {
646                         return (status);
647                 }
648         } else {
649                 /* Add all tables found in the static directory */
650
651                 status = osl_list_customized_tables(STATIC_TABLE_DIR);
652                 if (ACPI_FAILURE(status)) {
653                         return (status);
654                 }
655         }
656
657         if (gbl_dump_dynamic_tables) {
658
659                 /* Add all dynamically loaded tables in the dynamic directory */
660
661                 status = osl_list_customized_tables(DYNAMIC_TABLE_DIR);
662                 if (ACPI_FAILURE(status)) {
663                         return (status);
664                 }
665         }
666
667         gbl_table_list_initialized = TRUE;
668         return (AE_OK);
669 }
670
671 /******************************************************************************
672  *
673  * FUNCTION:    osl_list_bios_tables
674  *
675  * PARAMETERS:  None
676  *
677  * RETURN:      Status; Table list is initialized if AE_OK.
678  *
679  * DESCRIPTION: Add ACPI tables to the table list from memory.
680  *
681  * NOTE:        This works on Linux as table customization does not modify the
682  *              addresses stored in RSDP/RSDT/XSDT/FADT.
683  *
684  *****************************************************************************/
685
686 static acpi_status osl_list_bios_tables(void)
687 {
688         struct acpi_table_header *mapped_table = NULL;
689         u8 *table_data;
690         u8 number_of_tables;
691         u8 item_size;
692         acpi_physical_address table_address = 0;
693         acpi_status status = AE_OK;
694         u32 i;
695
696         if (osl_can_use_xsdt()) {
697                 item_size = sizeof(u64);
698                 table_data =
699                     ACPI_CAST8(gbl_xsdt) + sizeof(struct acpi_table_header);
700                 number_of_tables =
701                     (u8)((gbl_xsdt->header.length -
702                           sizeof(struct acpi_table_header))
703                          / item_size);
704         } else {                /* Use RSDT if XSDT is not available */
705
706                 item_size = sizeof(u32);
707                 table_data =
708                     ACPI_CAST8(gbl_rsdt) + sizeof(struct acpi_table_header);
709                 number_of_tables =
710                     (u8)((gbl_rsdt->header.length -
711                           sizeof(struct acpi_table_header))
712                          / item_size);
713         }
714
715         /* Search RSDT/XSDT for the requested table */
716
717         for (i = 0; i < number_of_tables; ++i, table_data += item_size) {
718                 if (osl_can_use_xsdt()) {
719                         table_address =
720                             (acpi_physical_address)(*ACPI_CAST64(table_data));
721                 } else {
722                         table_address =
723                             (acpi_physical_address)(*ACPI_CAST32(table_data));
724                 }
725
726                 /* Skip NULL entries in RSDT/XSDT */
727
728                 if (table_address == 0) {
729                         continue;
730                 }
731
732                 status = osl_map_table(table_address, NULL, &mapped_table);
733                 if (ACPI_FAILURE(status)) {
734                         return (status);
735                 }
736
737                 osl_add_table_to_list(mapped_table->signature, 0);
738                 osl_unmap_table(mapped_table);
739         }
740
741         return (AE_OK);
742 }
743
744 /******************************************************************************
745  *
746  * FUNCTION:    osl_get_bios_table
747  *
748  * PARAMETERS:  signature       - ACPI Signature for common table. Must be
749  *                                a null terminated 4-character string.
750  *              instance        - Multiple table support for SSDT/UEFI (0...n)
751  *                                Must be 0 for other tables.
752  *              table           - Where a pointer to the table is returned
753  *              address         - Where the table physical address is returned
754  *
755  * RETURN:      Status; Table buffer and physical address returned if AE_OK.
756  *              AE_LIMIT: Instance is beyond valid limit
757  *              AE_NOT_FOUND: A table with the signature was not found
758  *
759  * DESCRIPTION: Get a BIOS provided ACPI table
760  *
761  * NOTE:        Assumes the input signature is uppercase.
762  *
763  *****************************************************************************/
764
765 static acpi_status
766 osl_get_bios_table(char *signature,
767                    u32 instance,
768                    struct acpi_table_header **table,
769                    acpi_physical_address *address)
770 {
771         struct acpi_table_header *local_table = NULL;
772         struct acpi_table_header *mapped_table = NULL;
773         u8 *table_data;
774         u8 number_of_tables;
775         u8 item_size;
776         u32 current_instance = 0;
777         acpi_physical_address table_address;
778         acpi_physical_address first_table_address = 0;
779         u32 table_length = 0;
780         acpi_status status = AE_OK;
781         u32 i;
782
783         /* Handle special tables whose addresses are not in RSDT/XSDT */
784
785         if (ACPI_COMPARE_NAME(signature, ACPI_RSDP_NAME) ||
786             ACPI_COMPARE_NAME(signature, ACPI_SIG_RSDT) ||
787             ACPI_COMPARE_NAME(signature, ACPI_SIG_XSDT) ||
788             ACPI_COMPARE_NAME(signature, ACPI_SIG_DSDT) ||
789             ACPI_COMPARE_NAME(signature, ACPI_SIG_FACS)) {
790
791 find_next_instance:
792
793                 table_address = 0;
794
795                 /*
796                  * Get the appropriate address, either 32-bit or 64-bit. Be very
797                  * careful about the FADT length and validate table addresses.
798                  * Note: The 64-bit addresses have priority.
799                  */
800                 if (ACPI_COMPARE_NAME(signature, ACPI_SIG_DSDT)) {
801                         if (current_instance < 2) {
802                                 if ((gbl_fadt->header.length >=
803                                      MIN_FADT_FOR_XDSDT) && gbl_fadt->Xdsdt
804                                     && current_instance == 0) {
805                                         table_address =
806                                             (acpi_physical_address)gbl_fadt->
807                                             Xdsdt;
808                                 } else
809                                     if ((gbl_fadt->header.length >=
810                                          MIN_FADT_FOR_DSDT)
811                                         && gbl_fadt->dsdt !=
812                                         first_table_address) {
813                                         table_address =
814                                             (acpi_physical_address)gbl_fadt->
815                                             dsdt;
816                                 }
817                         }
818                 } else if (ACPI_COMPARE_NAME(signature, ACPI_SIG_FACS)) {
819                         if (current_instance < 2) {
820                                 if ((gbl_fadt->header.length >=
821                                      MIN_FADT_FOR_XFACS) && gbl_fadt->Xfacs
822                                     && current_instance == 0) {
823                                         table_address =
824                                             (acpi_physical_address)gbl_fadt->
825                                             Xfacs;
826                                 } else
827                                     if ((gbl_fadt->header.length >=
828                                          MIN_FADT_FOR_FACS)
829                                         && gbl_fadt->facs !=
830                                         first_table_address) {
831                                         table_address =
832                                             (acpi_physical_address)gbl_fadt->
833                                             facs;
834                                 }
835                         }
836                 } else if (ACPI_COMPARE_NAME(signature, ACPI_SIG_XSDT)) {
837                         if (!gbl_revision) {
838                                 return (AE_BAD_SIGNATURE);
839                         }
840                         if (current_instance == 0) {
841                                 table_address =
842                                     (acpi_physical_address)gbl_rsdp.
843                                     xsdt_physical_address;
844                         }
845                 } else if (ACPI_COMPARE_NAME(signature, ACPI_SIG_RSDT)) {
846                         if (current_instance == 0) {
847                                 table_address =
848                                     (acpi_physical_address)gbl_rsdp.
849                                     rsdt_physical_address;
850                         }
851                 } else {
852                         if (current_instance == 0) {
853                                 table_address =
854                                     (acpi_physical_address)gbl_rsdp_address;
855                                 signature = ACPI_SIG_RSDP;
856                         }
857                 }
858
859                 if (table_address == 0) {
860                         goto exit_find_table;
861                 }
862
863                 /* Now we can get the requested special table */
864
865                 status = osl_map_table(table_address, signature, &mapped_table);
866                 if (ACPI_FAILURE(status)) {
867                         return (status);
868                 }
869
870                 table_length = ap_get_table_length(mapped_table);
871                 if (first_table_address == 0) {
872                         first_table_address = table_address;
873                 }
874
875                 /* Match table instance */
876
877                 if (current_instance != instance) {
878                         osl_unmap_table(mapped_table);
879                         mapped_table = NULL;
880                         current_instance++;
881                         goto find_next_instance;
882                 }
883         } else {                /* Case for a normal ACPI table */
884
885                 if (osl_can_use_xsdt()) {
886                         item_size = sizeof(u64);
887                         table_data =
888                             ACPI_CAST8(gbl_xsdt) +
889                             sizeof(struct acpi_table_header);
890                         number_of_tables =
891                             (u8)((gbl_xsdt->header.length -
892                                   sizeof(struct acpi_table_header))
893                                  / item_size);
894                 } else {        /* Use RSDT if XSDT is not available */
895
896                         item_size = sizeof(u32);
897                         table_data =
898                             ACPI_CAST8(gbl_rsdt) +
899                             sizeof(struct acpi_table_header);
900                         number_of_tables =
901                             (u8)((gbl_rsdt->header.length -
902                                   sizeof(struct acpi_table_header))
903                                  / item_size);
904                 }
905
906                 /* Search RSDT/XSDT for the requested table */
907
908                 for (i = 0; i < number_of_tables; ++i, table_data += item_size) {
909                         if (osl_can_use_xsdt()) {
910                                 table_address =
911                                     (acpi_physical_address)(*ACPI_CAST64
912                                                             (table_data));
913                         } else {
914                                 table_address =
915                                     (acpi_physical_address)(*ACPI_CAST32
916                                                             (table_data));
917                         }
918
919                         /* Skip NULL entries in RSDT/XSDT */
920
921                         if (table_address == 0) {
922                                 continue;
923                         }
924
925                         status =
926                             osl_map_table(table_address, NULL, &mapped_table);
927                         if (ACPI_FAILURE(status)) {
928                                 return (status);
929                         }
930                         table_length = mapped_table->length;
931
932                         /* Does this table match the requested signature? */
933
934                         if (!ACPI_COMPARE_NAME
935                             (mapped_table->signature, signature)) {
936                                 osl_unmap_table(mapped_table);
937                                 mapped_table = NULL;
938                                 continue;
939                         }
940
941                         /* Match table instance (for SSDT/UEFI tables) */
942
943                         if (current_instance != instance) {
944                                 osl_unmap_table(mapped_table);
945                                 mapped_table = NULL;
946                                 current_instance++;
947                                 continue;
948                         }
949
950                         break;
951                 }
952         }
953
954 exit_find_table:
955
956         if (!mapped_table) {
957                 return (AE_LIMIT);
958         }
959
960         if (table_length == 0) {
961                 status = AE_BAD_HEADER;
962                 goto exit;
963         }
964
965         /* Copy table to local buffer and return it */
966
967         local_table = calloc(1, table_length);
968         if (!local_table) {
969                 status = AE_NO_MEMORY;
970                 goto exit;
971         }
972
973         memcpy(local_table, mapped_table, table_length);
974         *address = table_address;
975         *table = local_table;
976
977 exit:
978         osl_unmap_table(mapped_table);
979         return (status);
980 }
981
982 /******************************************************************************
983  *
984  * FUNCTION:    osl_list_customized_tables
985  *
986  * PARAMETERS:  directory           - Directory that contains the tables
987  *
988  * RETURN:      Status; Table list is initialized if AE_OK.
989  *
990  * DESCRIPTION: Add ACPI tables to the table list from a directory.
991  *
992  *****************************************************************************/
993
994 static acpi_status osl_list_customized_tables(char *directory)
995 {
996         void *table_dir;
997         u32 instance;
998         char temp_name[ACPI_NAME_SIZE];
999         char *filename;
1000         acpi_status status = AE_OK;
1001
1002         /* Open the requested directory */
1003
1004         table_dir = acpi_os_open_directory(directory, "*", REQUEST_FILE_ONLY);
1005         if (!table_dir) {
1006                 return (osl_get_last_status(AE_NOT_FOUND));
1007         }
1008
1009         /* Examine all entries in this directory */
1010
1011         while ((filename = acpi_os_get_next_filename(table_dir))) {
1012
1013                 /* Extract table name and instance number */
1014
1015                 status =
1016                     osl_table_name_from_file(filename, temp_name, &instance);
1017
1018                 /* Ignore meaningless files */
1019
1020                 if (ACPI_FAILURE(status)) {
1021                         continue;
1022                 }
1023
1024                 /* Add new info node to global table list */
1025
1026                 status = osl_add_table_to_list(temp_name, instance);
1027                 if (ACPI_FAILURE(status)) {
1028                         break;
1029                 }
1030         }
1031
1032         acpi_os_close_directory(table_dir);
1033         return (status);
1034 }
1035
1036 /******************************************************************************
1037  *
1038  * FUNCTION:    osl_map_table
1039  *
1040  * PARAMETERS:  address             - Address of the table in memory
1041  *              signature           - Optional ACPI Signature for desired table.
1042  *                                    Null terminated 4-character string.
1043  *              table               - Where a pointer to the mapped table is
1044  *                                    returned
1045  *
1046  * RETURN:      Status; Mapped table is returned if AE_OK.
1047  *              AE_NOT_FOUND: A valid table was not found at the address
1048  *
1049  * DESCRIPTION: Map entire ACPI table into caller's address space.
1050  *
1051  *****************************************************************************/
1052
1053 static acpi_status
1054 osl_map_table(acpi_size address,
1055               char *signature, struct acpi_table_header **table)
1056 {
1057         struct acpi_table_header *mapped_table;
1058         u32 length;
1059
1060         if (!address) {
1061                 return (AE_BAD_ADDRESS);
1062         }
1063
1064         /*
1065          * Map the header so we can get the table length.
1066          * Use sizeof (struct acpi_table_header) as:
1067          * 1. it is bigger than 24 to include RSDP->Length
1068          * 2. it is smaller than sizeof (struct acpi_table_rsdp)
1069          */
1070         mapped_table =
1071             acpi_os_map_memory(address, sizeof(struct acpi_table_header));
1072         if (!mapped_table) {
1073                 fprintf(stderr, "Could not map table header at 0x%8.8X%8.8X\n",
1074                         ACPI_FORMAT_UINT64(address));
1075                 return (osl_get_last_status(AE_BAD_ADDRESS));
1076         }
1077
1078         /* If specified, signature must match */
1079
1080         if (signature) {
1081                 if (ACPI_VALIDATE_RSDP_SIG(signature)) {
1082                         if (!ACPI_VALIDATE_RSDP_SIG(mapped_table->signature)) {
1083                                 acpi_os_unmap_memory(mapped_table,
1084                                                      sizeof(struct
1085                                                             acpi_table_header));
1086                                 return (AE_BAD_SIGNATURE);
1087                         }
1088                 } else
1089                     if (!ACPI_COMPARE_NAME(signature, mapped_table->signature))
1090                 {
1091                         acpi_os_unmap_memory(mapped_table,
1092                                              sizeof(struct acpi_table_header));
1093                         return (AE_BAD_SIGNATURE);
1094                 }
1095         }
1096
1097         /* Map the entire table */
1098
1099         length = ap_get_table_length(mapped_table);
1100         acpi_os_unmap_memory(mapped_table, sizeof(struct acpi_table_header));
1101         if (length == 0) {
1102                 return (AE_BAD_HEADER);
1103         }
1104
1105         mapped_table = acpi_os_map_memory(address, length);
1106         if (!mapped_table) {
1107                 fprintf(stderr,
1108                         "Could not map table at 0x%8.8X%8.8X length %8.8X\n",
1109                         ACPI_FORMAT_UINT64(address), length);
1110                 return (osl_get_last_status(AE_INVALID_TABLE_LENGTH));
1111         }
1112
1113         (void)ap_is_valid_checksum(mapped_table);
1114
1115         *table = mapped_table;
1116         return (AE_OK);
1117 }
1118
1119 /******************************************************************************
1120  *
1121  * FUNCTION:    osl_unmap_table
1122  *
1123  * PARAMETERS:  table               - A pointer to the mapped table
1124  *
1125  * RETURN:      None
1126  *
1127  * DESCRIPTION: Unmap entire ACPI table.
1128  *
1129  *****************************************************************************/
1130
1131 static void osl_unmap_table(struct acpi_table_header *table)
1132 {
1133         if (table) {
1134                 acpi_os_unmap_memory(table, ap_get_table_length(table));
1135         }
1136 }
1137
1138 /******************************************************************************
1139  *
1140  * FUNCTION:    osl_table_name_from_file
1141  *
1142  * PARAMETERS:  filename            - File that contains the desired table
1143  *              signature           - Pointer to 4-character buffer to store
1144  *                                    extracted table signature.
1145  *              instance            - Pointer to integer to store extracted
1146  *                                    table instance number.
1147  *
1148  * RETURN:      Status; Table name is extracted if AE_OK.
1149  *
1150  * DESCRIPTION: Extract table signature and instance number from a table file
1151  *              name.
1152  *
1153  *****************************************************************************/
1154
1155 static acpi_status
1156 osl_table_name_from_file(char *filename, char *signature, u32 *instance)
1157 {
1158
1159         /* Ignore meaningless files */
1160
1161         if (strlen(filename) < ACPI_NAME_SIZE) {
1162                 return (AE_BAD_SIGNATURE);
1163         }
1164
1165         /* Extract instance number */
1166
1167         if (isdigit((int)filename[ACPI_NAME_SIZE])) {
1168                 sscanf(&filename[ACPI_NAME_SIZE], "%u", instance);
1169         } else if (strlen(filename) != ACPI_NAME_SIZE) {
1170                 return (AE_BAD_SIGNATURE);
1171         } else {
1172                 *instance = 0;
1173         }
1174
1175         /* Extract signature */
1176
1177         ACPI_MOVE_NAME(signature, filename);
1178         return (AE_OK);
1179 }
1180
1181 /******************************************************************************
1182  *
1183  * FUNCTION:    osl_read_table_from_file
1184  *
1185  * PARAMETERS:  filename            - File that contains the desired table
1186  *              file_offset         - Offset of the table in file
1187  *              signature           - Optional ACPI Signature for desired table.
1188  *                                    A null terminated 4-character string.
1189  *              table               - Where a pointer to the table is returned
1190  *
1191  * RETURN:      Status; Table buffer is returned if AE_OK.
1192  *
1193  * DESCRIPTION: Read a ACPI table from a file.
1194  *
1195  *****************************************************************************/
1196
1197 static acpi_status
1198 osl_read_table_from_file(char *filename,
1199                          acpi_size file_offset,
1200                          char *signature, struct acpi_table_header **table)
1201 {
1202         FILE *table_file;
1203         struct acpi_table_header header;
1204         struct acpi_table_header *local_table = NULL;
1205         u32 table_length;
1206         s32 count;
1207         acpi_status status = AE_OK;
1208
1209         /* Open the file */
1210
1211         table_file = fopen(filename, "rb");
1212         if (table_file == NULL) {
1213                 fprintf(stderr, "Could not open table file: %s\n", filename);
1214                 return (osl_get_last_status(AE_NOT_FOUND));
1215         }
1216
1217         fseek(table_file, file_offset, SEEK_SET);
1218
1219         /* Read the Table header to get the table length */
1220
1221         count = fread(&header, 1, sizeof(struct acpi_table_header), table_file);
1222         if (count != sizeof(struct acpi_table_header)) {
1223                 fprintf(stderr, "Could not read table header: %s\n", filename);
1224                 status = AE_BAD_HEADER;
1225                 goto exit;
1226         }
1227
1228         /* If signature is specified, it must match the table */
1229
1230         if (signature) {
1231                 if (ACPI_VALIDATE_RSDP_SIG(signature)) {
1232                         if (!ACPI_VALIDATE_RSDP_SIG(header.signature)) {
1233                                 fprintf(stderr,
1234                                         "Incorrect RSDP signature: found %8.8s\n",
1235                                         header.signature);
1236                                 status = AE_BAD_SIGNATURE;
1237                                 goto exit;
1238                         }
1239                 } else if (!ACPI_COMPARE_NAME(signature, header.signature)) {
1240                         fprintf(stderr,
1241                                 "Incorrect signature: Expecting %4.4s, found %4.4s\n",
1242                                 signature, header.signature);
1243                         status = AE_BAD_SIGNATURE;
1244                         goto exit;
1245                 }
1246         }
1247
1248         table_length = ap_get_table_length(&header);
1249         if (table_length == 0) {
1250                 status = AE_BAD_HEADER;
1251                 goto exit;
1252         }
1253
1254         /* Read the entire table into a local buffer */
1255
1256         local_table = calloc(1, table_length);
1257         if (!local_table) {
1258                 fprintf(stderr,
1259                         "%4.4s: Could not allocate buffer for table of length %X\n",
1260                         header.signature, table_length);
1261                 status = AE_NO_MEMORY;
1262                 goto exit;
1263         }
1264
1265         fseek(table_file, file_offset, SEEK_SET);
1266
1267         count = fread(local_table, 1, table_length, table_file);
1268         if (count != table_length) {
1269                 fprintf(stderr, "%4.4s: Could not read table content\n",
1270                         header.signature);
1271                 status = AE_INVALID_TABLE_LENGTH;
1272                 goto exit;
1273         }
1274
1275         /* Validate checksum */
1276
1277         (void)ap_is_valid_checksum(local_table);
1278
1279 exit:
1280         fclose(table_file);
1281         *table = local_table;
1282         return (status);
1283 }
1284
1285 /******************************************************************************
1286  *
1287  * FUNCTION:    osl_get_customized_table
1288  *
1289  * PARAMETERS:  pathname        - Directory to find Linux customized table
1290  *              signature       - ACPI Signature for desired table. Must be
1291  *                                a null terminated 4-character string.
1292  *              instance        - Multiple table support for SSDT/UEFI (0...n)
1293  *                                Must be 0 for other tables.
1294  *              table           - Where a pointer to the table is returned
1295  *              address         - Where the table physical address is returned
1296  *
1297  * RETURN:      Status; Table buffer is returned if AE_OK.
1298  *              AE_LIMIT: Instance is beyond valid limit
1299  *              AE_NOT_FOUND: A table with the signature was not found
1300  *
1301  * DESCRIPTION: Get an OS customized table.
1302  *
1303  *****************************************************************************/
1304
1305 static acpi_status
1306 osl_get_customized_table(char *pathname,
1307                          char *signature,
1308                          u32 instance,
1309                          struct acpi_table_header **table,
1310                          acpi_physical_address *address)
1311 {
1312         void *table_dir;
1313         u32 current_instance = 0;
1314         char temp_name[ACPI_NAME_SIZE];
1315         char table_filename[PATH_MAX];
1316         char *filename;
1317         acpi_status status;
1318
1319         /* Open the directory for customized tables */
1320
1321         table_dir = acpi_os_open_directory(pathname, "*", REQUEST_FILE_ONLY);
1322         if (!table_dir) {
1323                 return (osl_get_last_status(AE_NOT_FOUND));
1324         }
1325
1326         /* Attempt to find the table in the directory */
1327
1328         while ((filename = acpi_os_get_next_filename(table_dir))) {
1329
1330                 /* Ignore meaningless files */
1331
1332                 if (!ACPI_COMPARE_NAME(filename, signature)) {
1333                         continue;
1334                 }
1335
1336                 /* Extract table name and instance number */
1337
1338                 status =
1339                     osl_table_name_from_file(filename, temp_name,
1340                                              &current_instance);
1341
1342                 /* Ignore meaningless files */
1343
1344                 if (ACPI_FAILURE(status) || current_instance != instance) {
1345                         continue;
1346                 }
1347
1348                 /* Create the table pathname */
1349
1350                 if (instance != 0) {
1351                         sprintf(table_filename, "%s/%4.4s%d", pathname,
1352                                 temp_name, instance);
1353                 } else {
1354                         sprintf(table_filename, "%s/%4.4s", pathname,
1355                                 temp_name);
1356                 }
1357                 break;
1358         }
1359
1360         acpi_os_close_directory(table_dir);
1361
1362         if (!filename) {
1363                 return (AE_LIMIT);
1364         }
1365
1366         /* There is no physical address saved for customized tables, use zero */
1367
1368         *address = 0;
1369         status = osl_read_table_from_file(table_filename, 0, NULL, table);
1370
1371         return (status);
1372 }