xref: /netbsd-src/sys/external/bsd/acpica/dist/os_specific/service_layers/oslinuxtbl.c (revision 2c7d7e3ca2e4f0b675c6c58e614f6aede66c678e)
1 /******************************************************************************
2  *
3  * Module Name: oslinuxtbl - Linux OSL for obtaining ACPI tables
4  *
5  *****************************************************************************/
6 
7 /*
8  * Copyright (C) 2000 - 2023, Intel Corp.
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 MERCHANTABILITY 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 "acpidump.h"
45 
46 
47 #define _COMPONENT          ACPI_OS_SERVICES
48         ACPI_MODULE_NAME    ("oslinuxtbl")
49 
50 
51 #ifndef PATH_MAX
52 #define PATH_MAX 256
53 #endif
54 
55 
56 /* List of information about obtained ACPI tables */
57 
58 typedef struct osl_table_info
59 {
60     struct osl_table_info   *Next;
61     UINT32                  Instance;
62     char                    Signature[ACPI_NAMESEG_SIZE];
63 
64 } OSL_TABLE_INFO;
65 
66 /* Local prototypes */
67 
68 static ACPI_STATUS
69 OslTableInitialize (
70     void);
71 
72 static ACPI_STATUS
73 OslTableNameFromFile (
74     char                    *Filename,
75     char                    *Signature,
76     UINT32                  *Instance);
77 
78 static ACPI_STATUS
79 OslAddTableToList (
80     char                    *Signature,
81     UINT32                  Instance);
82 
83 static ACPI_STATUS
84 OslReadTableFromFile (
85     char                    *Filename,
86     ACPI_SIZE               FileOffset,
87     ACPI_TABLE_HEADER       **Table);
88 
89 static ACPI_STATUS
90 OslMapTable (
91     ACPI_SIZE               Address,
92     char                    *Signature,
93     ACPI_TABLE_HEADER       **Table);
94 
95 static void
96 OslUnmapTable (
97     ACPI_TABLE_HEADER       *Table);
98 
99 static ACPI_PHYSICAL_ADDRESS
100 OslFindRsdpViaEfiByKeyword (
101     FILE                    *File,
102     const char              *Keyword);
103 
104 static ACPI_PHYSICAL_ADDRESS
105 OslFindRsdpViaEfi (
106     void);
107 
108 static ACPI_STATUS
109 OslLoadRsdp (
110     void);
111 
112 static ACPI_STATUS
113 OslListCustomizedTables (
114     char                    *Directory);
115 
116 static ACPI_STATUS
117 OslGetCustomizedTable (
118     char                    *Pathname,
119     char                    *Signature,
120     UINT32                  Instance,
121     ACPI_TABLE_HEADER       **Table,
122     ACPI_PHYSICAL_ADDRESS   *Address);
123 
124 static ACPI_STATUS
125 OslListBiosTables (
126     void);
127 
128 static ACPI_STATUS
129 OslGetBiosTable (
130     char                    *Signature,
131     UINT32                  Instance,
132     ACPI_TABLE_HEADER       **Table,
133     ACPI_PHYSICAL_ADDRESS   *Address);
134 
135 static ACPI_STATUS
136 OslGetLastStatus (
137     ACPI_STATUS             DefaultStatus);
138 
139 
140 /* File locations */
141 
142 #define DYNAMIC_TABLE_DIR   "/sys/firmware/acpi/tables/dynamic"
143 #define STATIC_TABLE_DIR    "/sys/firmware/acpi/tables"
144 #define EFI_SYSTAB          "/sys/firmware/efi/systab"
145 
146 /* Should we get dynamically loaded SSDTs from DYNAMIC_TABLE_DIR? */
147 
148 UINT8                   Gbl_DumpDynamicTables = TRUE;
149 
150 /* Initialization flags */
151 
152 UINT8                   Gbl_TableListInitialized = FALSE;
153 
154 /* Local copies of main ACPI tables */
155 
156 ACPI_TABLE_RSDP         Gbl_Rsdp;
157 ACPI_TABLE_FADT         *Gbl_Fadt = NULL;
158 ACPI_TABLE_RSDT         *Gbl_Rsdt = NULL;
159 ACPI_TABLE_XSDT         *Gbl_Xsdt = NULL;
160 
161 /* Table addresses */
162 
163 ACPI_PHYSICAL_ADDRESS   Gbl_FadtAddress = 0;
164 ACPI_PHYSICAL_ADDRESS   Gbl_RsdpAddress = 0;
165 
166 /* Revision of RSD PTR */
167 
168 UINT8                   Gbl_Revision = 0;
169 
170 OSL_TABLE_INFO          *Gbl_TableListHead = NULL;
171 UINT32                  Gbl_TableCount = 0;
172 
173 
174 /******************************************************************************
175  *
176  * FUNCTION:    OslGetLastStatus
177  *
178  * PARAMETERS:  DefaultStatus   - Default error status to return
179  *
180  * RETURN:      Status; Converted from errno.
181  *
182  * DESCRIPTION: Get last errno and convert it to ACPI_STATUS.
183  *
184  *****************************************************************************/
185 
186 static ACPI_STATUS
OslGetLastStatus(ACPI_STATUS DefaultStatus)187 OslGetLastStatus (
188     ACPI_STATUS             DefaultStatus)
189 {
190 
191     switch (errno)
192     {
193     case EACCES:
194     case EPERM:
195 
196         return (AE_ACCESS);
197 
198     case ENOENT:
199 
200         return (AE_NOT_FOUND);
201 
202     case ENOMEM:
203 
204         return (AE_NO_MEMORY);
205 
206     default:
207 
208         return (DefaultStatus);
209     }
210 }
211 
212 
213 /******************************************************************************
214  *
215  * FUNCTION:    AcpiOsGetTableByAddress
216  *
217  * PARAMETERS:  Address         - Physical address of the ACPI table
218  *              Table           - Where a pointer to the table is returned
219  *
220  * RETURN:      Status; Table buffer is returned if AE_OK.
221  *              AE_NOT_FOUND: A valid table was not found at the address
222  *
223  * DESCRIPTION: Get an ACPI table via a physical memory address.
224  *
225  *****************************************************************************/
226 
227 ACPI_STATUS
AcpiOsGetTableByAddress(ACPI_PHYSICAL_ADDRESS Address,ACPI_TABLE_HEADER ** Table)228 AcpiOsGetTableByAddress (
229     ACPI_PHYSICAL_ADDRESS   Address,
230     ACPI_TABLE_HEADER       **Table)
231 {
232     UINT32                  TableLength;
233     ACPI_TABLE_HEADER       *MappedTable;
234     ACPI_TABLE_HEADER       *LocalTable = NULL;
235     ACPI_STATUS             Status = AE_OK;
236 
237 
238     /* Get main ACPI tables from memory on first invocation of this function */
239 
240     Status = OslTableInitialize ();
241     if (ACPI_FAILURE (Status))
242     {
243         return (Status);
244     }
245 
246     /* Map the table and validate it */
247 
248     Status = OslMapTable (Address, NULL, &MappedTable);
249     if (ACPI_FAILURE (Status))
250     {
251         return (Status);
252     }
253 
254     /* Copy table to local buffer and return it */
255 
256     TableLength = ApGetTableLength (MappedTable);
257     if (TableLength == 0)
258     {
259         Status = AE_BAD_HEADER;
260         goto Exit;
261     }
262 
263     LocalTable = calloc (1, TableLength);
264     if (!LocalTable)
265     {
266         Status = AE_NO_MEMORY;
267         goto Exit;
268     }
269 
270     memcpy (LocalTable, MappedTable, TableLength);
271 
272 Exit:
273     OslUnmapTable (MappedTable);
274     *Table = LocalTable;
275     return (Status);
276 }
277 
278 
279 /******************************************************************************
280  *
281  * FUNCTION:    AcpiOsGetTableByName
282  *
283  * PARAMETERS:  Signature       - ACPI Signature for desired table. Must be
284  *                                a null terminated 4-character string.
285  *              Instance        - Multiple table support for SSDT/UEFI (0...n)
286  *                                Must be 0 for other tables.
287  *              Table           - Where a pointer to the table is returned
288  *              Address         - Where the table physical address is returned
289  *
290  * RETURN:      Status; Table buffer and physical address returned if AE_OK.
291  *              AE_LIMIT: Instance is beyond valid limit
292  *              AE_NOT_FOUND: A table with the signature was not found
293  *
294  * NOTE:        Assumes the input signature is uppercase.
295  *
296  *****************************************************************************/
297 
298 ACPI_STATUS
AcpiOsGetTableByName(char * Signature,UINT32 Instance,ACPI_TABLE_HEADER ** Table,ACPI_PHYSICAL_ADDRESS * Address)299 AcpiOsGetTableByName (
300     char                    *Signature,
301     UINT32                  Instance,
302     ACPI_TABLE_HEADER       **Table,
303     ACPI_PHYSICAL_ADDRESS   *Address)
304 {
305     ACPI_STATUS             Status;
306 
307 
308     /* Get main ACPI tables from memory on first invocation of this function */
309 
310     Status = OslTableInitialize ();
311     if (ACPI_FAILURE (Status))
312     {
313         return (Status);
314     }
315 
316     /* Not a main ACPI table, attempt to extract it from the RSDT/XSDT */
317 
318     if (!Gbl_DumpCustomizedTables)
319     {
320         /* Attempt to get the table from the memory */
321 
322         Status = OslGetBiosTable (Signature, Instance, Table, Address);
323     }
324     else
325     {
326         /* Attempt to get the table from the static directory */
327 
328         Status = OslGetCustomizedTable (STATIC_TABLE_DIR, Signature,
329             Instance, Table, Address);
330     }
331 
332     if (ACPI_FAILURE (Status) && Status == AE_LIMIT)
333     {
334         if (Gbl_DumpDynamicTables)
335         {
336             /* Attempt to get a dynamic table */
337 
338             Status = OslGetCustomizedTable (DYNAMIC_TABLE_DIR, Signature,
339                 Instance, Table, Address);
340         }
341     }
342 
343     return (Status);
344 }
345 
346 
347 /******************************************************************************
348  *
349  * FUNCTION:    OslAddTableToList
350  *
351  * PARAMETERS:  Signature       - Table signature
352  *              Instance        - Table instance
353  *
354  * RETURN:      Status; Successfully added if AE_OK.
355  *              AE_NO_MEMORY: Memory allocation error
356  *
357  * DESCRIPTION: Insert a table structure into OSL table list.
358  *
359  *****************************************************************************/
360 
361 static ACPI_STATUS
OslAddTableToList(char * Signature,UINT32 Instance)362 OslAddTableToList (
363     char                    *Signature,
364     UINT32                  Instance)
365 {
366     OSL_TABLE_INFO          *NewInfo;
367     OSL_TABLE_INFO          *Next;
368     UINT32                  NextInstance = 0;
369     BOOLEAN                 Found = FALSE;
370 
371 
372     NewInfo = calloc (1, sizeof (OSL_TABLE_INFO));
373     if (!NewInfo)
374     {
375         return (AE_NO_MEMORY);
376     }
377 
378     ACPI_COPY_NAMESEG (NewInfo->Signature, Signature);
379 
380     if (!Gbl_TableListHead)
381     {
382         Gbl_TableListHead = NewInfo;
383     }
384     else
385     {
386         Next = Gbl_TableListHead;
387         while (1)
388         {
389             if (ACPI_COMPARE_NAMESEG (Next->Signature, Signature))
390             {
391                 if (Next->Instance == Instance)
392                 {
393                     Found = TRUE;
394                 }
395                 if (Next->Instance >= NextInstance)
396                 {
397                     NextInstance = Next->Instance + 1;
398                 }
399             }
400 
401             if (!Next->Next)
402             {
403                 break;
404             }
405             Next = Next->Next;
406         }
407         Next->Next = NewInfo;
408     }
409 
410     if (Found)
411     {
412         if (Instance)
413         {
414             fprintf (stderr,
415                 "%4.4s: Warning unmatched table instance %d, expected %d\n",
416                 Signature, Instance, NextInstance);
417         }
418         Instance = NextInstance;
419     }
420 
421     NewInfo->Instance = Instance;
422     Gbl_TableCount++;
423 
424     return (AE_OK);
425 }
426 
427 
428 /******************************************************************************
429  *
430  * FUNCTION:    AcpiOsGetTableByIndex
431  *
432  * PARAMETERS:  Index           - Which table to get
433  *              Table           - Where a pointer to the table is returned
434  *              Instance        - Where a pointer to the table instance no. is
435  *                                returned
436  *              Address         - Where the table physical address is returned
437  *
438  * RETURN:      Status; Table buffer and physical address returned if AE_OK.
439  *              AE_LIMIT: Index is beyond valid limit
440  *
441  * DESCRIPTION: Get an ACPI table via an index value (0 through n). Returns
442  *              AE_LIMIT when an invalid index is reached. Index is not
443  *              necessarily an index into the RSDT/XSDT.
444  *
445  *****************************************************************************/
446 
447 ACPI_STATUS
AcpiOsGetTableByIndex(UINT32 Index,ACPI_TABLE_HEADER ** Table,UINT32 * Instance,ACPI_PHYSICAL_ADDRESS * Address)448 AcpiOsGetTableByIndex (
449     UINT32                  Index,
450     ACPI_TABLE_HEADER       **Table,
451     UINT32                  *Instance,
452     ACPI_PHYSICAL_ADDRESS   *Address)
453 {
454     OSL_TABLE_INFO          *Info;
455     ACPI_STATUS             Status;
456     UINT32                  i;
457 
458 
459     /* Get main ACPI tables from memory on first invocation of this function */
460 
461     Status = OslTableInitialize ();
462     if (ACPI_FAILURE (Status))
463     {
464         return (Status);
465     }
466 
467     /* Validate Index */
468 
469     if (Index >= Gbl_TableCount)
470     {
471         return (AE_LIMIT);
472     }
473 
474     /* Point to the table list entry specified by the Index argument */
475 
476     Info = Gbl_TableListHead;
477     for (i = 0; i < Index; i++)
478     {
479         Info = Info->Next;
480     }
481 
482     /* Now we can just get the table via the signature */
483 
484     Status = AcpiOsGetTableByName (Info->Signature, Info->Instance,
485         Table, Address);
486 
487     if (ACPI_SUCCESS (Status))
488     {
489         *Instance = Info->Instance;
490     }
491     return (Status);
492 }
493 
494 
495 /******************************************************************************
496  *
497  * FUNCTION:    OslFindRsdpViaEfiByKeyword
498  *
499  * PARAMETERS:  Keyword         - Character string indicating ACPI GUID version
500  *                                in the EFI table
501  *
502  * RETURN:      RSDP address if found
503  *
504  * DESCRIPTION: Find RSDP address via EFI using keyword indicating the ACPI
505  *              GUID version.
506  *
507  *****************************************************************************/
508 
509 static ACPI_PHYSICAL_ADDRESS
OslFindRsdpViaEfiByKeyword(FILE * File,const char * Keyword)510 OslFindRsdpViaEfiByKeyword (
511     FILE                    *File,
512     const char              *Keyword)
513 {
514     char                    Buffer[80];
515     unsigned long long      Address = 0;
516     char                    Format[32];
517 
518 
519     snprintf (Format, 32, "%s=%s", Keyword, "%llx");
520     fseek (File, 0, SEEK_SET);
521     while (fgets (Buffer, 80, File))
522     {
523         if (sscanf (Buffer, Format, &Address) == 1)
524         {
525             break;
526         }
527     }
528 
529     return ((ACPI_PHYSICAL_ADDRESS) (Address));
530 }
531 
532 
533 /******************************************************************************
534  *
535  * FUNCTION:    OslFindRsdpViaEfi
536  *
537  * PARAMETERS:  None
538  *
539  * RETURN:      RSDP address if found
540  *
541  * DESCRIPTION: Find RSDP address via EFI.
542  *
543  *****************************************************************************/
544 
545 static ACPI_PHYSICAL_ADDRESS
OslFindRsdpViaEfi(void)546 OslFindRsdpViaEfi (
547     void)
548 {
549     FILE                    *File;
550     ACPI_PHYSICAL_ADDRESS   Address = 0;
551 
552 
553     File = fopen (EFI_SYSTAB, "r");
554     if (File)
555     {
556         Address = OslFindRsdpViaEfiByKeyword (File, "ACPI20");
557         if (!Address)
558         {
559             Address = OslFindRsdpViaEfiByKeyword (File, "ACPI");
560         }
561         fclose (File);
562     }
563 
564     return (Address);
565 }
566 
567 
568 /******************************************************************************
569  *
570  * FUNCTION:    OslLoadRsdp
571  *
572  * PARAMETERS:  None
573  *
574  * RETURN:      Status
575  *
576  * DESCRIPTION: Scan and load RSDP.
577  *
578  *****************************************************************************/
579 
580 static ACPI_STATUS
OslLoadRsdp(void)581 OslLoadRsdp (
582     void)
583 {
584     ACPI_TABLE_HEADER       *MappedTable;
585     UINT8                   *RsdpAddress;
586     ACPI_PHYSICAL_ADDRESS   RsdpBase;
587     ACPI_SIZE               RsdpSize;
588 
589 
590     /* Get RSDP from memory */
591 
592     RsdpSize = sizeof (ACPI_TABLE_RSDP);
593     if (Gbl_RsdpBase)
594     {
595         RsdpBase = Gbl_RsdpBase;
596     }
597     else
598     {
599         RsdpBase = OslFindRsdpViaEfi ();
600     }
601 
602     if (!RsdpBase)
603     {
604         RsdpBase = ACPI_HI_RSDP_WINDOW_BASE;
605         RsdpSize = ACPI_HI_RSDP_WINDOW_SIZE;
606     }
607 
608     RsdpAddress = AcpiOsMapMemory (RsdpBase, RsdpSize);
609     if (!RsdpAddress)
610     {
611         return (OslGetLastStatus (AE_BAD_ADDRESS));
612     }
613 
614     /* Search low memory for the RSDP */
615 
616     MappedTable = ACPI_CAST_PTR (ACPI_TABLE_HEADER,
617         AcpiTbScanMemoryForRsdp (RsdpAddress, RsdpSize));
618     if (!MappedTable)
619     {
620         AcpiOsUnmapMemory (RsdpAddress, RsdpSize);
621         return (AE_NOT_FOUND);
622     }
623 
624     Gbl_RsdpAddress = RsdpBase + (ACPI_CAST8 (MappedTable) - RsdpAddress);
625 
626     memcpy (&Gbl_Rsdp, MappedTable, sizeof (ACPI_TABLE_RSDP));
627     AcpiOsUnmapMemory (RsdpAddress, RsdpSize);
628 
629     return (AE_OK);
630 }
631 
632 
633 /******************************************************************************
634  *
635  * FUNCTION:    OslCanUseXsdt
636  *
637  * PARAMETERS:  None
638  *
639  * RETURN:      TRUE if XSDT is allowed to be used.
640  *
641  * DESCRIPTION: This function collects logic that can be used to determine if
642  *              XSDT should be used instead of RSDT.
643  *
644  *****************************************************************************/
645 
646 static BOOLEAN
OslCanUseXsdt(void)647 OslCanUseXsdt (
648     void)
649 {
650     if (Gbl_Revision && !AcpiGbl_DoNotUseXsdt)
651     {
652         return (TRUE);
653     }
654     else
655     {
656         return (FALSE);
657     }
658 }
659 
660 
661 /******************************************************************************
662  *
663  * FUNCTION:    OslTableInitialize
664  *
665  * PARAMETERS:  None
666  *
667  * RETURN:      Status
668  *
669  * DESCRIPTION: Initialize ACPI table data. Get and store main ACPI tables to
670  *              local variables. Main ACPI tables include RSDT, FADT, RSDT,
671  *              and/or XSDT.
672  *
673  *****************************************************************************/
674 
675 static ACPI_STATUS
OslTableInitialize(void)676 OslTableInitialize (
677     void)
678 {
679     ACPI_STATUS             Status;
680     ACPI_PHYSICAL_ADDRESS   Address;
681 
682 
683     if (Gbl_TableListInitialized)
684     {
685         return (AE_OK);
686     }
687 
688     if (!Gbl_DumpCustomizedTables)
689     {
690         /* Get RSDP from memory */
691 
692         Status = OslLoadRsdp ();
693         if (ACPI_FAILURE (Status))
694         {
695             return (Status);
696         }
697 
698         /* Get XSDT from memory */
699 
700         if (Gbl_Rsdp.Revision && !Gbl_DoNotDumpXsdt)
701         {
702             if (Gbl_Xsdt)
703             {
704                 free (Gbl_Xsdt);
705                 Gbl_Xsdt = NULL;
706             }
707 
708             Gbl_Revision = 2;
709             Status = OslGetBiosTable (ACPI_SIG_XSDT, 0,
710                 ACPI_CAST_PTR (ACPI_TABLE_HEADER *, &Gbl_Xsdt), &Address);
711             if (ACPI_FAILURE (Status))
712             {
713                 return (Status);
714             }
715         }
716 
717         /* Get RSDT from memory */
718 
719         if (Gbl_Rsdp.RsdtPhysicalAddress)
720         {
721             if (Gbl_Rsdt)
722             {
723                 free (Gbl_Rsdt);
724                 Gbl_Rsdt = NULL;
725             }
726 
727             Status = OslGetBiosTable (ACPI_SIG_RSDT, 0,
728                 ACPI_CAST_PTR (ACPI_TABLE_HEADER *, &Gbl_Rsdt), &Address);
729             if (ACPI_FAILURE (Status))
730             {
731                 return (Status);
732             }
733         }
734 
735         /* Get FADT from memory */
736 
737         if (Gbl_Fadt)
738         {
739             free (Gbl_Fadt);
740             Gbl_Fadt = NULL;
741         }
742 
743         Status = OslGetBiosTable (ACPI_SIG_FADT, 0,
744             ACPI_CAST_PTR (ACPI_TABLE_HEADER *, &Gbl_Fadt), &Gbl_FadtAddress);
745         if (ACPI_FAILURE (Status))
746         {
747             return (Status);
748         }
749 
750         /* Add mandatory tables to global table list first */
751 
752         Status = OslAddTableToList (ACPI_RSDP_NAME, 0);
753         if (ACPI_FAILURE (Status))
754         {
755             return (Status);
756         }
757 
758         Status = OslAddTableToList (ACPI_SIG_RSDT, 0);
759         if (ACPI_FAILURE (Status))
760         {
761             return (Status);
762         }
763 
764         if (Gbl_Revision == 2)
765         {
766             Status = OslAddTableToList (ACPI_SIG_XSDT, 0);
767             if (ACPI_FAILURE (Status))
768             {
769                 return (Status);
770             }
771         }
772 
773         Status = OslAddTableToList (ACPI_SIG_DSDT, 0);
774         if (ACPI_FAILURE (Status))
775         {
776             return (Status);
777         }
778 
779         Status = OslAddTableToList (ACPI_SIG_FACS, 0);
780         if (ACPI_FAILURE (Status))
781         {
782             return (Status);
783         }
784 
785         /* Add all tables found in the memory */
786 
787         Status = OslListBiosTables ();
788         if (ACPI_FAILURE (Status))
789         {
790             return (Status);
791         }
792     }
793     else
794     {
795         /* Add all tables found in the static directory */
796 
797         Status = OslListCustomizedTables (STATIC_TABLE_DIR);
798         if (ACPI_FAILURE (Status))
799         {
800             return (Status);
801         }
802     }
803 
804     if (Gbl_DumpDynamicTables)
805     {
806         /* Add all dynamically loaded tables in the dynamic directory */
807 
808         Status = OslListCustomizedTables (DYNAMIC_TABLE_DIR);
809         if (ACPI_FAILURE (Status))
810         {
811             return (Status);
812         }
813     }
814 
815     Gbl_TableListInitialized = TRUE;
816     return (AE_OK);
817 }
818 
819 
820 /******************************************************************************
821  *
822  * FUNCTION:    OslListBiosTables
823  *
824  * PARAMETERS:  None
825  *
826  * RETURN:      Status; Table list is initialized if AE_OK.
827  *
828  * DESCRIPTION: Add ACPI tables to the table list from memory.
829  *
830  * NOTE:        This works on Linux as table customization does not modify the
831  *              addresses stored in RSDP/RSDT/XSDT/FADT.
832  *
833  *****************************************************************************/
834 
835 static ACPI_STATUS
OslListBiosTables(void)836 OslListBiosTables (
837     void)
838 {
839     ACPI_TABLE_HEADER       *MappedTable = NULL;
840     UINT8                   *TableData;
841     UINT8                   NumberOfTables;
842     UINT8                   ItemSize;
843     ACPI_PHYSICAL_ADDRESS   TableAddress = 0;
844     ACPI_STATUS             Status = AE_OK;
845     UINT32                  i;
846 
847 
848     if (OslCanUseXsdt ())
849     {
850         ItemSize = sizeof (UINT64);
851         TableData = ACPI_CAST8 (Gbl_Xsdt) + sizeof (ACPI_TABLE_HEADER);
852         NumberOfTables =
853             (UINT8) ((Gbl_Xsdt->Header.Length - sizeof (ACPI_TABLE_HEADER))
854             / ItemSize);
855     }
856     else /* Use RSDT if XSDT is not available */
857     {
858         ItemSize = sizeof (UINT32);
859         TableData = ACPI_CAST8 (Gbl_Rsdt) + sizeof (ACPI_TABLE_HEADER);
860         NumberOfTables =
861             (UINT8) ((Gbl_Rsdt->Header.Length - sizeof (ACPI_TABLE_HEADER))
862             / ItemSize);
863     }
864 
865     /* Search RSDT/XSDT for the requested table */
866 
867     for (i = 0; i < NumberOfTables; ++i, TableData += ItemSize)
868     {
869         if (OslCanUseXsdt ())
870         {
871             TableAddress =
872                 (ACPI_PHYSICAL_ADDRESS) (*ACPI_CAST64 (TableData));
873         }
874         else
875         {
876             TableAddress =
877                 (ACPI_PHYSICAL_ADDRESS) (*ACPI_CAST32 (TableData));
878         }
879 
880         /* Skip NULL entries in RSDT/XSDT */
881 
882         if (TableAddress == 0)
883         {
884             continue;
885         }
886 
887         Status = OslMapTable (TableAddress, NULL, &MappedTable);
888         if (ACPI_FAILURE (Status))
889         {
890             return (Status);
891         }
892 
893         OslAddTableToList (MappedTable->Signature, 0);
894         OslUnmapTable (MappedTable);
895     }
896 
897     return (AE_OK);
898 }
899 
900 
901 /******************************************************************************
902  *
903  * FUNCTION:    OslGetBiosTable
904  *
905  * PARAMETERS:  Signature       - ACPI Signature for common table. Must be
906  *                                a null terminated 4-character string.
907  *              Instance        - Multiple table support for SSDT/UEFI (0...n)
908  *                                Must be 0 for other tables.
909  *              Table           - Where a pointer to the table is returned
910  *              Address         - Where the table physical address is returned
911  *
912  * RETURN:      Status; Table buffer and physical address returned if AE_OK.
913  *              AE_LIMIT: Instance is beyond valid limit
914  *              AE_NOT_FOUND: A table with the signature was not found
915  *
916  * DESCRIPTION: Get a BIOS provided ACPI table
917  *
918  * NOTE:        Assumes the input signature is uppercase.
919  *
920  *****************************************************************************/
921 
922 static ACPI_STATUS
OslGetBiosTable(char * Signature,UINT32 Instance,ACPI_TABLE_HEADER ** Table,ACPI_PHYSICAL_ADDRESS * Address)923 OslGetBiosTable (
924     char                    *Signature,
925     UINT32                  Instance,
926     ACPI_TABLE_HEADER       **Table,
927     ACPI_PHYSICAL_ADDRESS   *Address)
928 {
929     ACPI_TABLE_HEADER       *LocalTable = NULL;
930     ACPI_TABLE_HEADER       *MappedTable = NULL;
931     UINT8                   *TableData;
932     UINT8                   NumberOfTables;
933     UINT8                   ItemSize;
934     UINT32                  CurrentInstance = 0;
935     ACPI_PHYSICAL_ADDRESS   TableAddress;
936     ACPI_PHYSICAL_ADDRESS   FirstTableAddress = 0;
937     UINT32                  TableLength = 0;
938     ACPI_STATUS             Status = AE_OK;
939     UINT32                  i;
940 
941 
942     /* Handle special tables whose addresses are not in RSDT/XSDT */
943 
944     if (ACPI_COMPARE_NAMESEG (Signature, ACPI_RSDP_NAME) ||
945         ACPI_COMPARE_NAMESEG (Signature, ACPI_SIG_RSDT) ||
946         ACPI_COMPARE_NAMESEG (Signature, ACPI_SIG_XSDT) ||
947         ACPI_COMPARE_NAMESEG (Signature, ACPI_SIG_DSDT) ||
948         ACPI_COMPARE_NAMESEG (Signature, ACPI_SIG_FACS))
949     {
950 
951 FindNextInstance:
952 
953         TableAddress = 0;
954 
955         /*
956          * Get the appropriate address, either 32-bit or 64-bit. Be very
957          * careful about the FADT length and validate table addresses.
958          * Note: The 64-bit addresses have priority.
959          */
960         if (ACPI_COMPARE_NAMESEG (Signature, ACPI_SIG_DSDT))
961         {
962             if (CurrentInstance < 2)
963             {
964                 if ((Gbl_Fadt->Header.Length >= MIN_FADT_FOR_XDSDT) &&
965                     Gbl_Fadt->XDsdt && CurrentInstance == 0)
966                 {
967                     TableAddress = (ACPI_PHYSICAL_ADDRESS) Gbl_Fadt->XDsdt;
968                 }
969                 else if ((Gbl_Fadt->Header.Length >= MIN_FADT_FOR_DSDT) &&
970                     Gbl_Fadt->Dsdt != FirstTableAddress)
971                 {
972                     TableAddress = (ACPI_PHYSICAL_ADDRESS) Gbl_Fadt->Dsdt;
973                 }
974             }
975         }
976         else if (ACPI_COMPARE_NAMESEG (Signature, ACPI_SIG_FACS))
977         {
978             if (CurrentInstance < 2)
979             {
980                 if ((Gbl_Fadt->Header.Length >= MIN_FADT_FOR_XFACS) &&
981                     Gbl_Fadt->XFacs && CurrentInstance == 0)
982                 {
983                     TableAddress = (ACPI_PHYSICAL_ADDRESS) Gbl_Fadt->XFacs;
984                 }
985                 else if ((Gbl_Fadt->Header.Length >= MIN_FADT_FOR_FACS) &&
986                     Gbl_Fadt->Facs != FirstTableAddress)
987                 {
988                     TableAddress = (ACPI_PHYSICAL_ADDRESS) Gbl_Fadt->Facs;
989                 }
990             }
991         }
992         else if (ACPI_COMPARE_NAMESEG (Signature, ACPI_SIG_XSDT))
993         {
994             if (!Gbl_Revision)
995             {
996                 return (AE_BAD_SIGNATURE);
997             }
998             if (CurrentInstance == 0)
999             {
1000                 TableAddress =
1001                     (ACPI_PHYSICAL_ADDRESS) Gbl_Rsdp.XsdtPhysicalAddress;
1002             }
1003         }
1004         else if (ACPI_COMPARE_NAMESEG (Signature, ACPI_SIG_RSDT))
1005         {
1006             if (CurrentInstance == 0)
1007             {
1008                 TableAddress =
1009                     (ACPI_PHYSICAL_ADDRESS) Gbl_Rsdp.RsdtPhysicalAddress;
1010             }
1011         }
1012         else
1013         {
1014             if (CurrentInstance == 0)
1015             {
1016                 TableAddress = (ACPI_PHYSICAL_ADDRESS) Gbl_RsdpAddress;
1017                 Signature = ACPI_SIG_RSDP;
1018             }
1019         }
1020 
1021         if (TableAddress == 0)
1022         {
1023             goto ExitFindTable;
1024         }
1025 
1026         /* Now we can get the requested special table */
1027 
1028         Status = OslMapTable (TableAddress, Signature, &MappedTable);
1029         if (ACPI_FAILURE (Status))
1030         {
1031             return (Status);
1032         }
1033 
1034         TableLength = ApGetTableLength (MappedTable);
1035         if (FirstTableAddress == 0)
1036         {
1037             FirstTableAddress = TableAddress;
1038         }
1039 
1040         /* Match table instance */
1041 
1042         if (CurrentInstance != Instance)
1043         {
1044             OslUnmapTable (MappedTable);
1045             MappedTable = NULL;
1046             CurrentInstance++;
1047             goto FindNextInstance;
1048         }
1049     }
1050     else /* Case for a normal ACPI table */
1051     {
1052         if (OslCanUseXsdt ())
1053         {
1054             ItemSize = sizeof (UINT64);
1055             TableData = ACPI_CAST8 (Gbl_Xsdt) + sizeof (ACPI_TABLE_HEADER);
1056             NumberOfTables =
1057                 (UINT8) ((Gbl_Xsdt->Header.Length - sizeof (ACPI_TABLE_HEADER))
1058                 / ItemSize);
1059         }
1060         else /* Use RSDT if XSDT is not available */
1061         {
1062             ItemSize = sizeof (UINT32);
1063             TableData = ACPI_CAST8 (Gbl_Rsdt) + sizeof (ACPI_TABLE_HEADER);
1064             NumberOfTables =
1065                 (UINT8) ((Gbl_Rsdt->Header.Length - sizeof (ACPI_TABLE_HEADER))
1066                 / ItemSize);
1067         }
1068 
1069         /* Search RSDT/XSDT for the requested table */
1070 
1071         for (i = 0; i < NumberOfTables; ++i, TableData += ItemSize)
1072         {
1073             if (OslCanUseXsdt ())
1074             {
1075                 TableAddress =
1076                     (ACPI_PHYSICAL_ADDRESS) (*ACPI_CAST64 (TableData));
1077             }
1078             else
1079             {
1080                 TableAddress =
1081                     (ACPI_PHYSICAL_ADDRESS) (*ACPI_CAST32 (TableData));
1082             }
1083 
1084             /* Skip NULL entries in RSDT/XSDT */
1085 
1086             if (TableAddress == 0)
1087             {
1088                 continue;
1089             }
1090 
1091             Status = OslMapTable (TableAddress, NULL, &MappedTable);
1092             if (ACPI_FAILURE (Status))
1093             {
1094                 return (Status);
1095             }
1096             TableLength = MappedTable->Length;
1097 
1098             /* Does this table match the requested signature? */
1099 
1100             if (!ACPI_COMPARE_NAMESEG (MappedTable->Signature, Signature))
1101             {
1102                 OslUnmapTable (MappedTable);
1103                 MappedTable = NULL;
1104                 continue;
1105             }
1106 
1107             /* Match table instance (for SSDT/UEFI tables) */
1108 
1109             if (CurrentInstance != Instance)
1110             {
1111                 OslUnmapTable (MappedTable);
1112                 MappedTable = NULL;
1113                 CurrentInstance++;
1114                 continue;
1115             }
1116 
1117             break;
1118         }
1119     }
1120 
1121 ExitFindTable:
1122 
1123     if (!MappedTable)
1124     {
1125         return (AE_LIMIT);
1126     }
1127 
1128     if (TableLength == 0)
1129     {
1130         Status = AE_BAD_HEADER;
1131         goto Exit;
1132     }
1133 
1134     /* Copy table to local buffer and return it */
1135 
1136     LocalTable = calloc (1, TableLength);
1137     if (!LocalTable)
1138     {
1139         Status = AE_NO_MEMORY;
1140         goto Exit;
1141     }
1142 
1143     memcpy (LocalTable, MappedTable, TableLength);
1144     *Address = TableAddress;
1145     *Table = LocalTable;
1146 
1147 Exit:
1148     OslUnmapTable (MappedTable);
1149     return (Status);
1150 }
1151 
1152 
1153 /******************************************************************************
1154  *
1155  * FUNCTION:    OslListCustomizedTables
1156  *
1157  * PARAMETERS:  Directory           - Directory that contains the tables
1158  *
1159  * RETURN:      Status; Table list is initialized if AE_OK.
1160  *
1161  * DESCRIPTION: Add ACPI tables to the table list from a directory.
1162  *
1163  *****************************************************************************/
1164 
1165 static ACPI_STATUS
OslListCustomizedTables(char * Directory)1166 OslListCustomizedTables (
1167     char                    *Directory)
1168 {
1169     void                    *TableDir;
1170     UINT32                  Instance;
1171     char                    TempName[ACPI_NAMESEG_SIZE];
1172     char                    *Filename;
1173     ACPI_STATUS             Status = AE_OK;
1174 
1175 
1176     /* Open the requested directory */
1177 
1178     TableDir = AcpiOsOpenDirectory (Directory, "*", REQUEST_FILE_ONLY);
1179     if (!TableDir)
1180     {
1181         return (OslGetLastStatus (AE_NOT_FOUND));
1182     }
1183 
1184     /* Examine all entries in this directory */
1185 
1186     while ((Filename = AcpiOsGetNextFilename (TableDir)))
1187     {
1188         /* Extract table name and instance number */
1189 
1190         Status = OslTableNameFromFile (Filename, TempName, &Instance);
1191 
1192         /* Ignore meaningless files */
1193 
1194         if (ACPI_FAILURE (Status))
1195         {
1196             continue;
1197         }
1198 
1199         /* Add new info node to global table list */
1200 
1201         Status = OslAddTableToList (TempName, Instance);
1202         if (ACPI_FAILURE (Status))
1203         {
1204             break;
1205         }
1206     }
1207 
1208     AcpiOsCloseDirectory (TableDir);
1209     return (Status);
1210 }
1211 
1212 
1213 /******************************************************************************
1214  *
1215  * FUNCTION:    OslMapTable
1216  *
1217  * PARAMETERS:  Address             - Address of the table in memory
1218  *              Signature           - Optional ACPI Signature for desired table.
1219  *                                    Null terminated 4-character string.
1220  *              Table               - Where a pointer to the mapped table is
1221  *                                    returned
1222  *
1223  * RETURN:      Status; Mapped table is returned if AE_OK.
1224  *              AE_NOT_FOUND: A valid table was not found at the address
1225  *
1226  * DESCRIPTION: Map entire ACPI table into caller's address space.
1227  *
1228  *****************************************************************************/
1229 
1230 static ACPI_STATUS
OslMapTable(ACPI_SIZE Address,char * Signature,ACPI_TABLE_HEADER ** Table)1231 OslMapTable (
1232     ACPI_SIZE               Address,
1233     char                    *Signature,
1234     ACPI_TABLE_HEADER       **Table)
1235 {
1236     ACPI_TABLE_HEADER       *MappedTable;
1237     UINT32                  Length;
1238 
1239 
1240     if (!Address)
1241     {
1242         return (AE_BAD_ADDRESS);
1243     }
1244 
1245     /*
1246      * Map the header so we can get the table length.
1247      * Use sizeof (ACPI_TABLE_HEADER) as:
1248      * 1. it is bigger than 24 to include RSDP->Length
1249      * 2. it is smaller than sizeof (ACPI_TABLE_RSDP)
1250      */
1251     MappedTable = AcpiOsMapMemory (Address, sizeof (ACPI_TABLE_HEADER));
1252     if (!MappedTable)
1253     {
1254         fprintf (stderr, "Could not map table header at 0x%8.8X%8.8X\n",
1255             ACPI_FORMAT_UINT64 (Address));
1256         return (OslGetLastStatus (AE_BAD_ADDRESS));
1257     }
1258 
1259     /* If specified, signature must match */
1260 
1261     if (Signature)
1262     {
1263         if (ACPI_VALIDATE_RSDP_SIG (Signature))
1264         {
1265             if (!ACPI_VALIDATE_RSDP_SIG (MappedTable->Signature))
1266             {
1267                 AcpiOsUnmapMemory (MappedTable, sizeof (ACPI_TABLE_HEADER));
1268                 return (AE_BAD_SIGNATURE);
1269             }
1270         }
1271         else if (!ACPI_COMPARE_NAMESEG (Signature, MappedTable->Signature))
1272         {
1273             AcpiOsUnmapMemory (MappedTable, sizeof (ACPI_TABLE_HEADER));
1274             return (AE_BAD_SIGNATURE);
1275         }
1276     }
1277 
1278     /* Map the entire table */
1279 
1280     Length = ApGetTableLength (MappedTable);
1281     AcpiOsUnmapMemory (MappedTable, sizeof (ACPI_TABLE_HEADER));
1282     if (Length == 0)
1283     {
1284         return (AE_BAD_HEADER);
1285     }
1286 
1287     MappedTable = AcpiOsMapMemory (Address, Length);
1288     if (!MappedTable)
1289     {
1290         fprintf (stderr, "Could not map table at 0x%8.8X%8.8X length %8.8X\n",
1291             ACPI_FORMAT_UINT64 (Address), Length);
1292         return (OslGetLastStatus (AE_INVALID_TABLE_LENGTH));
1293     }
1294 
1295     (void) ApIsValidChecksum (MappedTable);
1296 
1297     *Table = MappedTable;
1298     return (AE_OK);
1299 }
1300 
1301 
1302 /******************************************************************************
1303  *
1304  * FUNCTION:    OslUnmapTable
1305  *
1306  * PARAMETERS:  Table               - A pointer to the mapped table
1307  *
1308  * RETURN:      None
1309  *
1310  * DESCRIPTION: Unmap entire ACPI table.
1311  *
1312  *****************************************************************************/
1313 
1314 static void
OslUnmapTable(ACPI_TABLE_HEADER * Table)1315 OslUnmapTable (
1316     ACPI_TABLE_HEADER       *Table)
1317 {
1318     if (Table)
1319     {
1320         AcpiOsUnmapMemory (Table, ApGetTableLength (Table));
1321     }
1322 }
1323 
1324 
1325 /******************************************************************************
1326  *
1327  * FUNCTION:    OslTableNameFromFile
1328  *
1329  * PARAMETERS:  Filename            - File that contains the desired table
1330  *              Signature           - Pointer to 4-character buffer to store
1331  *                                    extracted table signature.
1332  *              Instance            - Pointer to integer to store extracted
1333  *                                    table instance number.
1334  *
1335  * RETURN:      Status; Table name is extracted if AE_OK.
1336  *
1337  * DESCRIPTION: Extract table signature and instance number from a table file
1338  *              name.
1339  *
1340  *****************************************************************************/
1341 
1342 static ACPI_STATUS
OslTableNameFromFile(char * Filename,char * Signature,UINT32 * Instance)1343 OslTableNameFromFile (
1344     char                    *Filename,
1345     char                    *Signature,
1346     UINT32                  *Instance)
1347 {
1348 
1349     /* Ignore meaningless files */
1350 
1351     if (strlen (Filename) < ACPI_NAMESEG_SIZE)
1352     {
1353         return (AE_BAD_SIGNATURE);
1354     }
1355 
1356     /* Extract instance number */
1357 
1358     if (isdigit ((int) Filename[ACPI_NAMESEG_SIZE]))
1359     {
1360         sscanf (&Filename[ACPI_NAMESEG_SIZE], "%u", Instance);
1361     }
1362     else if (strlen (Filename) != ACPI_NAMESEG_SIZE)
1363     {
1364         return (AE_BAD_SIGNATURE);
1365     }
1366     else
1367     {
1368         *Instance = 0;
1369     }
1370 
1371     /* Extract signature */
1372 
1373     ACPI_COPY_NAMESEG (Signature, Filename);
1374     return (AE_OK);
1375 }
1376 
1377 
1378 /******************************************************************************
1379  *
1380  * FUNCTION:    OslReadTableFromFile
1381  *
1382  * PARAMETERS:  Filename            - File that contains the desired table
1383  *              FileOffset          - Offset of the table in file
1384  *              Table               - Where a pointer to the table is returned
1385  *
1386  * RETURN:      Status; Table buffer is returned if AE_OK.
1387  *
1388  * DESCRIPTION: Read a ACPI table from a file.
1389  *
1390  *****************************************************************************/
1391 
1392 static ACPI_STATUS
OslReadTableFromFile(char * Filename,ACPI_SIZE FileOffset,ACPI_TABLE_HEADER ** Table)1393 OslReadTableFromFile (
1394     char                    *Filename,
1395     ACPI_SIZE               FileOffset,
1396     ACPI_TABLE_HEADER       **Table)
1397 {
1398     FILE                    *TableFile;
1399     ACPI_TABLE_HEADER       Header;
1400     ACPI_TABLE_HEADER       *LocalTable = NULL;
1401     UINT32                  TableLength;
1402     INT32                   Count;
1403     ACPI_STATUS             Status = AE_OK;
1404 
1405 
1406     /* Open the file */
1407 
1408     TableFile = fopen (Filename, "rb");
1409     if (TableFile == NULL)
1410     {
1411         fprintf (stderr, "Could not open table file: %s\n", Filename);
1412         return (OslGetLastStatus (AE_NOT_FOUND));
1413     }
1414 
1415     fseek (TableFile, FileOffset, SEEK_SET);
1416 
1417     /* Read the Table header to get the table length */
1418 
1419     Count = fread (&Header, 1, sizeof (ACPI_TABLE_HEADER), TableFile);
1420     if (Count != sizeof (ACPI_TABLE_HEADER))
1421     {
1422         fprintf (stderr, "Could not read table header: %s\n", Filename);
1423         Status = AE_BAD_HEADER;
1424         goto Exit;
1425     }
1426 
1427 #ifdef ACPI_OBSOLETE_FUNCTIONS
1428 
1429     /* If signature is specified, it must match the table */
1430 
1431     if (Signature)
1432     {
1433         if (ACPI_VALIDATE_RSDP_SIG (Signature))
1434         {
1435             if (!ACPI_VALIDATE_RSDP_SIG (Header.Signature)) {
1436                 fprintf (stderr, "Incorrect RSDP signature: found %8.8s\n",
1437                     Header.Signature);
1438                 Status = AE_BAD_SIGNATURE;
1439                 goto Exit;
1440             }
1441         }
1442         else if (!ACPI_COMPARE_NAMESEG (Signature, Header.Signature))
1443         {
1444             fprintf (stderr, "Incorrect signature: Expecting %4.4s, found %4.4s\n",
1445                 Signature, Header.Signature);
1446             Status = AE_BAD_SIGNATURE;
1447             goto Exit;
1448         }
1449     }
1450 #endif
1451 
1452     TableLength = ApGetTableLength (&Header);
1453     if (TableLength == 0)
1454     {
1455         Status = AE_BAD_HEADER;
1456         goto Exit;
1457     }
1458 
1459     /* Read the entire table into a local buffer */
1460 
1461     LocalTable = calloc (1, TableLength);
1462     if (!LocalTable)
1463     {
1464         fprintf (stderr,
1465             "%4.4s: Could not allocate buffer for table of length %X\n",
1466             Header.Signature, TableLength);
1467         Status = AE_NO_MEMORY;
1468         goto Exit;
1469     }
1470 
1471     fseek (TableFile, FileOffset, SEEK_SET);
1472 
1473     Count = fread (LocalTable, 1, TableLength, TableFile);
1474     if (Count != TableLength)
1475     {
1476         fprintf (stderr, "%4.4s: Could not read table content\n",
1477             Header.Signature);
1478         Status = AE_INVALID_TABLE_LENGTH;
1479         goto Exit;
1480     }
1481 
1482     /* Validate checksum */
1483 
1484     (void) ApIsValidChecksum (LocalTable);
1485 
1486 Exit:
1487     fclose (TableFile);
1488     *Table = LocalTable;
1489     return (Status);
1490 }
1491 
1492 
1493 /******************************************************************************
1494  *
1495  * FUNCTION:    OslGetCustomizedTable
1496  *
1497  * PARAMETERS:  Pathname        - Directory to find Linux customized table
1498  *              Signature       - ACPI Signature for desired table. Must be
1499  *                                a null terminated 4-character string.
1500  *              Instance        - Multiple table support for SSDT/UEFI (0...n)
1501  *                                Must be 0 for other tables.
1502  *              Table           - Where a pointer to the table is returned
1503  *              Address         - Where the table physical address is returned
1504  *
1505  * RETURN:      Status; Table buffer is returned if AE_OK.
1506  *              AE_LIMIT: Instance is beyond valid limit
1507  *              AE_NOT_FOUND: A table with the signature was not found
1508  *
1509  * DESCRIPTION: Get an OS customized table.
1510  *
1511  *****************************************************************************/
1512 
1513 static ACPI_STATUS
OslGetCustomizedTable(char * Pathname,char * Signature,UINT32 Instance,ACPI_TABLE_HEADER ** Table,ACPI_PHYSICAL_ADDRESS * Address)1514 OslGetCustomizedTable (
1515     char                    *Pathname,
1516     char                    *Signature,
1517     UINT32                  Instance,
1518     ACPI_TABLE_HEADER       **Table,
1519     ACPI_PHYSICAL_ADDRESS   *Address)
1520 {
1521     void                    *TableDir;
1522     UINT32                  CurrentInstance = 0;
1523     char                    TempName[ACPI_NAMESEG_SIZE];
1524     char                    TableFilename[PATH_MAX];
1525     char                    *Filename;
1526     ACPI_STATUS             Status;
1527 
1528 
1529     /* Open the directory for customized tables */
1530 
1531     TableDir = AcpiOsOpenDirectory (Pathname, "*", REQUEST_FILE_ONLY);
1532     if (!TableDir)
1533     {
1534         return (OslGetLastStatus (AE_NOT_FOUND));
1535     }
1536 
1537     /* Attempt to find the table in the directory */
1538 
1539     while ((Filename = AcpiOsGetNextFilename (TableDir)))
1540     {
1541         /* Ignore meaningless files */
1542 
1543         if (!ACPI_COMPARE_NAMESEG (Filename, Signature))
1544         {
1545             continue;
1546         }
1547 
1548         /* Extract table name and instance number */
1549 
1550         Status = OslTableNameFromFile (Filename, TempName, &CurrentInstance);
1551 
1552         /* Ignore meaningless files */
1553 
1554         if (ACPI_FAILURE (Status) || CurrentInstance != Instance)
1555         {
1556             continue;
1557         }
1558 
1559         /* Create the table pathname */
1560 
1561         if (Instance != 0)
1562         {
1563             snprintf (TableFilename, sizeof(TableFilename), "%s/%4.4s%d",
1564 		Pathname, TempName, Instance);
1565         }
1566         else
1567         {
1568             snprintf (TableFilename, sizeof(TableFilename), "%s/%4.4s",
1569 		Pathname, TempName);
1570         }
1571         break;
1572     }
1573 
1574     AcpiOsCloseDirectory (TableDir);
1575 
1576     if (!Filename)
1577     {
1578         return (AE_LIMIT);
1579     }
1580 
1581     /* There is no physical address saved for customized tables, use zero */
1582 
1583     *Address = 0;
1584     Status = OslReadTableFromFile (TableFilename, 0, Table);
1585 
1586     return (Status);
1587 }
1588