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