1 /******************************************************************************
3 * Module Name: oslinuxtbl - Linux OSL for obtaining ACPI tables
5 *****************************************************************************/
8 * Copyright (C) 2000 - 2014, Intel Corp.
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
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.
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.
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41 * POSSIBILITY OF SUCH DAMAGES.
47 #define _COMPONENT ACPI_OS_SERVICES
48 ACPI_MODULE_NAME ("oslinuxtbl")
56 /* List of information about obtained ACPI tables */
58 typedef struct osl_table_info
60 struct osl_table_info *Next;
62 char Signature[ACPI_NAME_SIZE];
66 /* Local prototypes */
73 OslTableNameFromFile (
84 OslReadTableFromFile (
88 ACPI_TABLE_HEADER **Table);
94 ACPI_TABLE_HEADER **Table);
98 ACPI_TABLE_HEADER *Table);
100 static ACPI_PHYSICAL_ADDRESS
101 OslFindRsdpViaEfiByKeyword (
103 const char *Keyword);
105 static ACPI_PHYSICAL_ADDRESS
114 OslListCustomizedTables (
118 OslGetCustomizedTable (
122 ACPI_TABLE_HEADER **Table,
123 ACPI_PHYSICAL_ADDRESS *Address);
133 ACPI_TABLE_HEADER **Table,
134 ACPI_PHYSICAL_ADDRESS *Address);
138 ACPI_STATUS DefaultStatus);
143 #define DYNAMIC_TABLE_DIR "/sys/firmware/acpi/tables/dynamic"
144 #define STATIC_TABLE_DIR "/sys/firmware/acpi/tables"
145 #define EFI_SYSTAB "/sys/firmware/efi/systab"
147 /* Should we get dynamically loaded SSDTs from DYNAMIC_TABLE_DIR? */
149 UINT8 Gbl_DumpDynamicTables = TRUE;
151 /* Initialization flags */
153 UINT8 Gbl_TableListInitialized = FALSE;
155 /* Local copies of main ACPI tables */
157 ACPI_TABLE_RSDP Gbl_Rsdp;
158 ACPI_TABLE_FADT *Gbl_Fadt = NULL;
159 ACPI_TABLE_RSDT *Gbl_Rsdt = NULL;
160 ACPI_TABLE_XSDT *Gbl_Xsdt = NULL;
162 /* Table addresses */
164 ACPI_PHYSICAL_ADDRESS Gbl_FadtAddress = 0;
165 ACPI_PHYSICAL_ADDRESS Gbl_RsdpAddress = 0;
167 /* Revision of RSD PTR */
169 UINT8 Gbl_Revision = 0;
171 OSL_TABLE_INFO *Gbl_TableListHead = NULL;
172 UINT32 Gbl_TableCount = 0;
175 /******************************************************************************
177 * FUNCTION: OslGetLastStatus
179 * PARAMETERS: DefaultStatus - Default error status to return
181 * RETURN: Status; Converted from errno.
183 * DESCRIPTION: Get last errno and conver it to ACPI_STATUS.
185 *****************************************************************************/
189 ACPI_STATUS DefaultStatus)
201 return (AE_NOT_FOUND);
205 return (AE_NO_MEMORY);
209 return (DefaultStatus);
214 /******************************************************************************
216 * FUNCTION: AcpiOsGetTableByAddress
218 * PARAMETERS: Address - Physical address of the ACPI table
219 * Table - Where a pointer to the table is returned
221 * RETURN: Status; Table buffer is returned if AE_OK.
222 * AE_NOT_FOUND: A valid table was not found at the address
224 * DESCRIPTION: Get an ACPI table via a physical memory address.
226 *****************************************************************************/
229 AcpiOsGetTableByAddress (
230 ACPI_PHYSICAL_ADDRESS Address,
231 ACPI_TABLE_HEADER **Table)
234 ACPI_TABLE_HEADER *MappedTable;
235 ACPI_TABLE_HEADER *LocalTable = NULL;
236 ACPI_STATUS Status = AE_OK;
239 /* Get main ACPI tables from memory on first invocation of this function */
241 Status = OslTableInitialize ();
242 if (ACPI_FAILURE (Status))
247 /* Map the table and validate it */
249 Status = OslMapTable (Address, NULL, &MappedTable);
250 if (ACPI_FAILURE (Status))
255 /* Copy table to local buffer and return it */
257 TableLength = ApGetTableLength (MappedTable);
258 if (TableLength == 0)
260 Status = AE_BAD_HEADER;
264 LocalTable = calloc (1, TableLength);
267 Status = AE_NO_MEMORY;
271 ACPI_MEMCPY (LocalTable, MappedTable, TableLength);
274 OslUnmapTable (MappedTable);
280 /******************************************************************************
282 * FUNCTION: AcpiOsGetTableByName
284 * PARAMETERS: Signature - ACPI Signature for desired table. Must be
285 * a null terminated 4-character string.
286 * Instance - Multiple table support for SSDT/UEFI (0...n)
287 * Must be 0 for other tables.
288 * Table - Where a pointer to the table is returned
289 * Address - Where the table physical address is returned
291 * RETURN: Status; Table buffer and physical address returned if AE_OK.
292 * AE_LIMIT: Instance is beyond valid limit
293 * AE_NOT_FOUND: A table with the signature was not found
295 * NOTE: Assumes the input signature is uppercase.
297 *****************************************************************************/
300 AcpiOsGetTableByName (
303 ACPI_TABLE_HEADER **Table,
304 ACPI_PHYSICAL_ADDRESS *Address)
309 /* Get main ACPI tables from memory on first invocation of this function */
311 Status = OslTableInitialize ();
312 if (ACPI_FAILURE (Status))
317 /* Not a main ACPI table, attempt to extract it from the RSDT/XSDT */
319 if (!Gbl_DumpCustomizedTables)
321 /* Attempt to get the table from the memory */
323 Status = OslGetBiosTable (Signature, Instance, Table, Address);
327 /* Attempt to get the table from the static directory */
329 Status = OslGetCustomizedTable (STATIC_TABLE_DIR, Signature,
330 Instance, Table, Address);
333 if (ACPI_FAILURE (Status) && Status == AE_LIMIT)
335 if (Gbl_DumpDynamicTables)
337 /* Attempt to get a dynamic table */
339 Status = OslGetCustomizedTable (DYNAMIC_TABLE_DIR, Signature,
340 Instance, Table, Address);
348 /******************************************************************************
350 * FUNCTION: OslAddTableToList
352 * PARAMETERS: Signature - Table signature
353 * Instance - Table instance
355 * RETURN: Status; Successfully added if AE_OK.
356 * AE_NO_MEMORY: Memory allocation error
358 * DESCRIPTION: Insert a table structure into OSL table list.
360 *****************************************************************************/
367 OSL_TABLE_INFO *NewInfo;
368 OSL_TABLE_INFO *Next;
369 UINT32 NextInstance = 0;
370 BOOLEAN Found = FALSE;
373 NewInfo = calloc (1, sizeof (OSL_TABLE_INFO));
376 return (AE_NO_MEMORY);
379 ACPI_MOVE_NAME (NewInfo->Signature, Signature);
381 if (!Gbl_TableListHead)
383 Gbl_TableListHead = NewInfo;
387 Next = Gbl_TableListHead;
390 if (ACPI_COMPARE_NAME (Next->Signature, Signature))
392 if (Next->Instance == Instance)
396 if (Next->Instance >= NextInstance)
398 NextInstance = Next->Instance + 1;
408 Next->Next = NewInfo;
416 "%4.4s: Warning unmatched table instance %d, expected %d\n",
417 Signature, Instance, NextInstance);
419 Instance = NextInstance;
422 NewInfo->Instance = Instance;
429 /******************************************************************************
431 * FUNCTION: AcpiOsGetTableByIndex
433 * PARAMETERS: Index - Which table to get
434 * Table - Where a pointer to the table is returned
435 * Instance - Where a pointer to the table instance no. is
437 * Address - Where the table physical address is returned
439 * RETURN: Status; Table buffer and physical address returned if AE_OK.
440 * AE_LIMIT: Index is beyond valid limit
442 * DESCRIPTION: Get an ACPI table via an index value (0 through n). Returns
443 * AE_LIMIT when an invalid index is reached. Index is not
444 * necessarily an index into the RSDT/XSDT.
446 *****************************************************************************/
449 AcpiOsGetTableByIndex (
451 ACPI_TABLE_HEADER **Table,
453 ACPI_PHYSICAL_ADDRESS *Address)
455 OSL_TABLE_INFO *Info;
460 /* Get main ACPI tables from memory on first invocation of this function */
462 Status = OslTableInitialize ();
463 if (ACPI_FAILURE (Status))
470 if (Index >= Gbl_TableCount)
475 /* Point to the table list entry specified by the Index argument */
477 Info = Gbl_TableListHead;
478 for (i = 0; i < Index; i++)
483 /* Now we can just get the table via the signature */
485 Status = AcpiOsGetTableByName (Info->Signature, Info->Instance,
488 if (ACPI_SUCCESS (Status))
490 *Instance = Info->Instance;
496 /******************************************************************************
498 * FUNCTION: OslFindRsdpViaEfiByKeyword
500 * PARAMETERS: Keyword - Character string indicating ACPI GUID version
503 * RETURN: RSDP address if found
505 * DESCRIPTION: Find RSDP address via EFI using keyword indicating the ACPI
508 *****************************************************************************/
510 static ACPI_PHYSICAL_ADDRESS
511 OslFindRsdpViaEfiByKeyword (
516 unsigned long long Address = 0;
520 snprintf (Format, 32, "%s=%s", Keyword, "%llx");
521 fseek (File, 0, SEEK_SET);
522 while (fgets (Buffer, 80, File))
524 if (sscanf (Buffer, Format, &Address) == 1)
530 return ((ACPI_PHYSICAL_ADDRESS) (Address));
534 /******************************************************************************
536 * FUNCTION: OslFindRsdpViaEfi
540 * RETURN: RSDP address if found
542 * DESCRIPTION: Find RSDP address via EFI.
544 *****************************************************************************/
546 static ACPI_PHYSICAL_ADDRESS
551 ACPI_PHYSICAL_ADDRESS Address = 0;
554 File = fopen (EFI_SYSTAB, "r");
557 Address = OslFindRsdpViaEfiByKeyword (File, "ACPI20");
560 Address = OslFindRsdpViaEfiByKeyword (File, "ACPI");
569 /******************************************************************************
571 * FUNCTION: OslLoadRsdp
577 * DESCRIPTION: Scan and load RSDP.
579 *****************************************************************************/
585 ACPI_TABLE_HEADER *MappedTable;
587 ACPI_PHYSICAL_ADDRESS RsdpBase;
591 /* Get RSDP from memory */
593 RsdpSize = sizeof (ACPI_TABLE_RSDP);
596 RsdpBase = Gbl_RsdpBase;
600 RsdpBase = OslFindRsdpViaEfi ();
605 RsdpBase = ACPI_HI_RSDP_WINDOW_BASE;
606 RsdpSize = ACPI_HI_RSDP_WINDOW_SIZE;
609 RsdpAddress = AcpiOsMapMemory (RsdpBase, RsdpSize);
612 return (OslGetLastStatus (AE_BAD_ADDRESS));
615 /* Search low memory for the RSDP */
617 MappedTable = ACPI_CAST_PTR (ACPI_TABLE_HEADER,
618 AcpiTbScanMemoryForRsdp (RsdpAddress, RsdpSize));
621 AcpiOsUnmapMemory (RsdpAddress, RsdpSize);
622 return (AE_NOT_FOUND);
625 Gbl_RsdpAddress = RsdpBase + (ACPI_CAST8 (MappedTable) - RsdpAddress);
627 ACPI_MEMCPY (&Gbl_Rsdp, MappedTable, sizeof (ACPI_TABLE_RSDP));
628 AcpiOsUnmapMemory (RsdpAddress, RsdpSize);
634 /******************************************************************************
636 * FUNCTION: OslCanUseXsdt
640 * RETURN: TRUE if XSDT is allowed to be used.
642 * DESCRIPTION: This function collects logic that can be used to determine if
643 * XSDT should be used instead of RSDT.
645 *****************************************************************************/
651 if (Gbl_Revision && !AcpiGbl_DoNotUseXsdt)
662 /******************************************************************************
664 * FUNCTION: OslTableInitialize
670 * DESCRIPTION: Initialize ACPI table data. Get and store main ACPI tables to
671 * local variables. Main ACPI tables include RSDT, FADT, RSDT,
674 *****************************************************************************/
681 ACPI_PHYSICAL_ADDRESS Address;
684 if (Gbl_TableListInitialized)
689 /* Get RSDP from memory */
691 Status = OslLoadRsdp ();
692 if (ACPI_FAILURE (Status))
697 /* Get XSDT from memory */
699 if (Gbl_Rsdp.Revision && !Gbl_DoNotDumpXsdt)
708 Status = OslGetBiosTable (ACPI_SIG_XSDT, 0,
709 ACPI_CAST_PTR (ACPI_TABLE_HEADER *, &Gbl_Xsdt), &Address);
710 if (ACPI_FAILURE (Status))
716 /* Get RSDT from memory */
718 if (Gbl_Rsdp.RsdtPhysicalAddress)
726 Status = OslGetBiosTable (ACPI_SIG_RSDT, 0,
727 ACPI_CAST_PTR (ACPI_TABLE_HEADER *, &Gbl_Rsdt), &Address);
728 if (ACPI_FAILURE (Status))
734 /* Get FADT from memory */
742 Status = OslGetBiosTable (ACPI_SIG_FADT, 0,
743 ACPI_CAST_PTR (ACPI_TABLE_HEADER *, &Gbl_Fadt), &Gbl_FadtAddress);
744 if (ACPI_FAILURE (Status))
749 if (!Gbl_DumpCustomizedTables)
751 /* Add mandatory tables to global table list first */
753 Status = OslAddTableToList (ACPI_RSDP_NAME, 0);
754 if (ACPI_FAILURE (Status))
759 Status = OslAddTableToList (ACPI_SIG_RSDT, 0);
760 if (ACPI_FAILURE (Status))
765 if (Gbl_Revision == 2)
767 Status = OslAddTableToList (ACPI_SIG_XSDT, 0);
768 if (ACPI_FAILURE (Status))
774 Status = OslAddTableToList (ACPI_SIG_DSDT, 0);
775 if (ACPI_FAILURE (Status))
780 Status = OslAddTableToList (ACPI_SIG_FACS, 0);
781 if (ACPI_FAILURE (Status))
786 /* Add all tables found in the memory */
788 Status = OslListBiosTables ();
789 if (ACPI_FAILURE (Status))
796 /* Add all tables found in the static directory */
798 Status = OslListCustomizedTables (STATIC_TABLE_DIR);
799 if (ACPI_FAILURE (Status))
805 if (Gbl_DumpDynamicTables)
807 /* Add all dynamically loaded tables in the dynamic directory */
809 Status = OslListCustomizedTables (DYNAMIC_TABLE_DIR);
810 if (ACPI_FAILURE (Status))
816 Gbl_TableListInitialized = TRUE;
821 /******************************************************************************
823 * FUNCTION: OslListBiosTables
827 * RETURN: Status; Table list is initialized if AE_OK.
829 * DESCRIPTION: Add ACPI tables to the table list from memory.
831 * NOTE: This works on Linux as table customization does not modify the
832 * addresses stored in RSDP/RSDT/XSDT/FADT.
834 *****************************************************************************/
840 ACPI_TABLE_HEADER *MappedTable = NULL;
842 UINT8 NumberOfTables;
844 ACPI_PHYSICAL_ADDRESS TableAddress = 0;
845 ACPI_STATUS Status = AE_OK;
849 if (OslCanUseXsdt ())
851 ItemSize = sizeof (UINT64);
852 TableData = ACPI_CAST8 (Gbl_Xsdt) + sizeof (ACPI_TABLE_HEADER);
854 (UINT8) ((Gbl_Xsdt->Header.Length - sizeof (ACPI_TABLE_HEADER))
857 else /* Use RSDT if XSDT is not available */
859 ItemSize = sizeof (UINT32);
860 TableData = ACPI_CAST8 (Gbl_Rsdt) + sizeof (ACPI_TABLE_HEADER);
862 (UINT8) ((Gbl_Rsdt->Header.Length - sizeof (ACPI_TABLE_HEADER))
866 /* Search RSDT/XSDT for the requested table */
868 for (i = 0; i < NumberOfTables; ++i, TableData += ItemSize)
870 if (OslCanUseXsdt ())
873 (ACPI_PHYSICAL_ADDRESS) (*ACPI_CAST64 (TableData));
878 (ACPI_PHYSICAL_ADDRESS) (*ACPI_CAST32 (TableData));
881 /* Skip NULL entries in RSDT/XSDT */
888 Status = OslMapTable (TableAddress, NULL, &MappedTable);
889 if (ACPI_FAILURE (Status))
894 OslAddTableToList (MappedTable->Signature, 0);
895 OslUnmapTable (MappedTable);
902 /******************************************************************************
904 * FUNCTION: OslGetBiosTable
906 * PARAMETERS: Signature - ACPI Signature for common table. Must be
907 * a null terminated 4-character string.
908 * Instance - Multiple table support for SSDT/UEFI (0...n)
909 * Must be 0 for other tables.
910 * Table - Where a pointer to the table is returned
911 * Address - Where the table physical address is returned
913 * RETURN: Status; Table buffer and physical address returned if AE_OK.
914 * AE_LIMIT: Instance is beyond valid limit
915 * AE_NOT_FOUND: A table with the signature was not found
917 * DESCRIPTION: Get a BIOS provided ACPI table
919 * NOTE: Assumes the input signature is uppercase.
921 *****************************************************************************/
927 ACPI_TABLE_HEADER **Table,
928 ACPI_PHYSICAL_ADDRESS *Address)
930 ACPI_TABLE_HEADER *LocalTable = NULL;
931 ACPI_TABLE_HEADER *MappedTable = NULL;
933 UINT8 NumberOfTables;
935 UINT32 CurrentInstance = 0;
936 ACPI_PHYSICAL_ADDRESS TableAddress = 0;
937 UINT32 TableLength = 0;
938 ACPI_STATUS Status = AE_OK;
942 /* Handle special tables whose addresses are not in RSDT/XSDT */
944 if (ACPI_COMPARE_NAME (Signature, ACPI_RSDP_NAME) ||
945 ACPI_COMPARE_NAME (Signature, ACPI_SIG_RSDT) ||
946 ACPI_COMPARE_NAME (Signature, ACPI_SIG_XSDT) ||
947 ACPI_COMPARE_NAME (Signature, ACPI_SIG_DSDT) ||
948 ACPI_COMPARE_NAME (Signature, ACPI_SIG_FACS))
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.
960 if (ACPI_COMPARE_NAME (Signature, ACPI_SIG_DSDT))
962 if ((Gbl_Fadt->Header.Length >= MIN_FADT_FOR_XDSDT) &&
965 TableAddress = (ACPI_PHYSICAL_ADDRESS) Gbl_Fadt->XDsdt;
967 else if ((Gbl_Fadt->Header.Length >= MIN_FADT_FOR_DSDT) &&
970 TableAddress = (ACPI_PHYSICAL_ADDRESS) Gbl_Fadt->Dsdt;
973 else if (ACPI_COMPARE_NAME (Signature, ACPI_SIG_FACS))
975 if ((Gbl_Fadt->Header.Length >= MIN_FADT_FOR_XFACS) &&
978 TableAddress = (ACPI_PHYSICAL_ADDRESS) Gbl_Fadt->XFacs;
980 else if ((Gbl_Fadt->Header.Length >= MIN_FADT_FOR_FACS) &&
983 TableAddress = (ACPI_PHYSICAL_ADDRESS) Gbl_Fadt->Facs;
986 else if (ACPI_COMPARE_NAME (Signature, ACPI_SIG_XSDT))
990 return (AE_BAD_SIGNATURE);
992 TableAddress = (ACPI_PHYSICAL_ADDRESS) Gbl_Rsdp.XsdtPhysicalAddress;
994 else if (ACPI_COMPARE_NAME (Signature, ACPI_SIG_RSDT))
996 TableAddress = (ACPI_PHYSICAL_ADDRESS) Gbl_Rsdp.RsdtPhysicalAddress;
1000 TableAddress = (ACPI_PHYSICAL_ADDRESS) Gbl_RsdpAddress;
1001 Signature = ACPI_SIG_RSDP;
1004 /* Now we can get the requested special table */
1006 Status = OslMapTable (TableAddress, Signature, &MappedTable);
1007 if (ACPI_FAILURE (Status))
1012 TableLength = ApGetTableLength (MappedTable);
1014 else /* Case for a normal ACPI table */
1016 if (OslCanUseXsdt ())
1018 ItemSize = sizeof (UINT64);
1019 TableData = ACPI_CAST8 (Gbl_Xsdt) + sizeof (ACPI_TABLE_HEADER);
1021 (UINT8) ((Gbl_Xsdt->Header.Length - sizeof (ACPI_TABLE_HEADER))
1024 else /* Use RSDT if XSDT is not available */
1026 ItemSize = sizeof (UINT32);
1027 TableData = ACPI_CAST8 (Gbl_Rsdt) + sizeof (ACPI_TABLE_HEADER);
1029 (UINT8) ((Gbl_Rsdt->Header.Length - sizeof (ACPI_TABLE_HEADER))
1033 /* Search RSDT/XSDT for the requested table */
1035 for (i = 0; i < NumberOfTables; ++i, TableData += ItemSize)
1037 if (OslCanUseXsdt ())
1040 (ACPI_PHYSICAL_ADDRESS) (*ACPI_CAST64 (TableData));
1045 (ACPI_PHYSICAL_ADDRESS) (*ACPI_CAST32 (TableData));
1048 /* Skip NULL entries in RSDT/XSDT */
1055 Status = OslMapTable (TableAddress, NULL, &MappedTable);
1056 if (ACPI_FAILURE (Status))
1060 TableLength = MappedTable->Length;
1062 /* Does this table match the requested signature? */
1064 if (!ACPI_COMPARE_NAME (MappedTable->Signature, Signature))
1066 OslUnmapTable (MappedTable);
1071 /* Match table instance (for SSDT/UEFI tables) */
1073 if (CurrentInstance != Instance)
1075 OslUnmapTable (MappedTable);
1090 if (TableLength == 0)
1092 Status = AE_BAD_HEADER;
1096 /* Copy table to local buffer and return it */
1098 LocalTable = calloc (1, TableLength);
1101 Status = AE_NO_MEMORY;
1105 ACPI_MEMCPY (LocalTable, MappedTable, TableLength);
1106 *Address = TableAddress;
1107 *Table = LocalTable;
1110 OslUnmapTable (MappedTable);
1115 /******************************************************************************
1117 * FUNCTION: OslListCustomizedTables
1119 * PARAMETERS: Directory - Directory that contains the tables
1121 * RETURN: Status; Table list is initialized if AE_OK.
1123 * DESCRIPTION: Add ACPI tables to the table list from a directory.
1125 *****************************************************************************/
1128 OslListCustomizedTables (
1133 char TempName[ACPI_NAME_SIZE];
1135 ACPI_STATUS Status = AE_OK;
1138 /* Open the requested directory */
1140 TableDir = AcpiOsOpenDirectory (Directory, "*", REQUEST_FILE_ONLY);
1143 return (OslGetLastStatus (AE_NOT_FOUND));
1146 /* Examine all entries in this directory */
1148 while ((Filename = AcpiOsGetNextFilename (TableDir)))
1150 /* Extract table name and instance number */
1152 Status = OslTableNameFromFile (Filename, TempName, &Instance);
1154 /* Ignore meaningless files */
1156 if (ACPI_FAILURE (Status))
1161 /* Add new info node to global table list */
1163 Status = OslAddTableToList (TempName, Instance);
1164 if (ACPI_FAILURE (Status))
1170 AcpiOsCloseDirectory (TableDir);
1175 /******************************************************************************
1177 * FUNCTION: OslMapTable
1179 * PARAMETERS: Address - Address of the table in memory
1180 * Signature - Optional ACPI Signature for desired table.
1181 * Null terminated 4-character string.
1182 * Table - Where a pointer to the mapped table is
1185 * RETURN: Status; Mapped table is returned if AE_OK.
1186 * AE_NOT_FOUND: A valid table was not found at the address
1188 * DESCRIPTION: Map entire ACPI table into caller's address space.
1190 *****************************************************************************/
1196 ACPI_TABLE_HEADER **Table)
1198 ACPI_TABLE_HEADER *MappedTable;
1204 return (AE_BAD_ADDRESS);
1208 * Map the header so we can get the table length.
1209 * Use sizeof (ACPI_TABLE_HEADER) as:
1210 * 1. it is bigger than 24 to include RSDP->Length
1211 * 2. it is smaller than sizeof (ACPI_TABLE_RSDP)
1213 MappedTable = AcpiOsMapMemory (Address, sizeof (ACPI_TABLE_HEADER));
1216 fprintf (stderr, "Could not map table header at 0x%8.8X%8.8X\n",
1217 ACPI_FORMAT_UINT64 (Address));
1218 return (OslGetLastStatus (AE_BAD_ADDRESS));
1221 /* If specified, signature must match */
1225 if (ACPI_VALIDATE_RSDP_SIG (Signature))
1227 if (!ACPI_VALIDATE_RSDP_SIG (MappedTable->Signature))
1229 AcpiOsUnmapMemory (MappedTable, sizeof (ACPI_TABLE_HEADER));
1230 return (AE_BAD_SIGNATURE);
1233 else if (!ACPI_COMPARE_NAME (Signature, MappedTable->Signature))
1235 AcpiOsUnmapMemory (MappedTable, sizeof (ACPI_TABLE_HEADER));
1236 return (AE_BAD_SIGNATURE);
1240 /* Map the entire table */
1242 Length = ApGetTableLength (MappedTable);
1243 AcpiOsUnmapMemory (MappedTable, sizeof (ACPI_TABLE_HEADER));
1246 return (AE_BAD_HEADER);
1249 MappedTable = AcpiOsMapMemory (Address, Length);
1252 fprintf (stderr, "Could not map table at 0x%8.8X%8.8X length %8.8X\n",
1253 ACPI_FORMAT_UINT64 (Address), Length);
1254 return (OslGetLastStatus (AE_INVALID_TABLE_LENGTH));
1257 (void) ApIsValidChecksum (MappedTable);
1259 *Table = MappedTable;
1264 /******************************************************************************
1266 * FUNCTION: OslUnmapTable
1268 * PARAMETERS: Table - A pointer to the mapped table
1272 * DESCRIPTION: Unmap entire ACPI table.
1274 *****************************************************************************/
1278 ACPI_TABLE_HEADER *Table)
1282 AcpiOsUnmapMemory (Table, ApGetTableLength (Table));
1287 /******************************************************************************
1289 * FUNCTION: OslTableNameFromFile
1291 * PARAMETERS: Filename - File that contains the desired table
1292 * Signature - Pointer to 4-character buffer to store
1293 * extracted table signature.
1294 * Instance - Pointer to integer to store extracted
1295 * table instance number.
1297 * RETURN: Status; Table name is extracted if AE_OK.
1299 * DESCRIPTION: Extract table signature and instance number from a table file
1302 *****************************************************************************/
1305 OslTableNameFromFile (
1311 /* Ignore meaningless files */
1313 if (strlen (Filename) < ACPI_NAME_SIZE)
1315 return (AE_BAD_SIGNATURE);
1318 /* Extract instance number */
1320 if (isdigit ((int) Filename[ACPI_NAME_SIZE]))
1322 sscanf (&Filename[ACPI_NAME_SIZE], "%d", Instance);
1324 else if (strlen (Filename) != ACPI_NAME_SIZE)
1326 return (AE_BAD_SIGNATURE);
1333 /* Extract signature */
1335 ACPI_MOVE_NAME (Signature, Filename);
1340 /******************************************************************************
1342 * FUNCTION: OslReadTableFromFile
1344 * PARAMETERS: Filename - File that contains the desired table
1345 * FileOffset - Offset of the table in file
1346 * Signature - Optional ACPI Signature for desired table.
1347 * A null terminated 4-character string.
1348 * Table - Where a pointer to the table is returned
1350 * RETURN: Status; Table buffer is returned if AE_OK.
1352 * DESCRIPTION: Read a ACPI table from a file.
1354 *****************************************************************************/
1357 OslReadTableFromFile (
1359 ACPI_SIZE FileOffset,
1361 ACPI_TABLE_HEADER **Table)
1364 ACPI_TABLE_HEADER Header;
1365 ACPI_TABLE_HEADER *LocalTable = NULL;
1368 ACPI_STATUS Status = AE_OK;
1373 TableFile = fopen (Filename, "rb");
1374 if (TableFile == NULL)
1376 fprintf (stderr, "Could not open table file: %s\n", Filename);
1377 return (OslGetLastStatus (AE_NOT_FOUND));
1380 fseek (TableFile, FileOffset, SEEK_SET);
1382 /* Read the Table header to get the table length */
1384 Count = fread (&Header, 1, sizeof (ACPI_TABLE_HEADER), TableFile);
1385 if (Count != sizeof (ACPI_TABLE_HEADER))
1387 fprintf (stderr, "Could not read table header: %s\n", Filename);
1388 Status = AE_BAD_HEADER;
1392 /* If signature is specified, it must match the table */
1396 if (ACPI_VALIDATE_RSDP_SIG (Signature))
1398 if (!ACPI_VALIDATE_RSDP_SIG (Header.Signature)) {
1399 fprintf (stderr, "Incorrect RSDP signature: found %8.8s\n",
1401 Status = AE_BAD_SIGNATURE;
1405 else if (!ACPI_COMPARE_NAME (Signature, Header.Signature))
1407 fprintf (stderr, "Incorrect signature: Expecting %4.4s, found %4.4s\n",
1408 Signature, Header.Signature);
1409 Status = AE_BAD_SIGNATURE;
1414 TableLength = ApGetTableLength (&Header);
1415 if (TableLength == 0)
1417 Status = AE_BAD_HEADER;
1421 /* Read the entire table into a local buffer */
1423 LocalTable = calloc (1, TableLength);
1427 "%4.4s: Could not allocate buffer for table of length %X\n",
1428 Header.Signature, TableLength);
1429 Status = AE_NO_MEMORY;
1433 fseek (TableFile, FileOffset, SEEK_SET);
1435 Count = fread (LocalTable, 1, TableLength, TableFile);
1436 if (Count != TableLength)
1438 fprintf (stderr, "%4.4s: Could not read table content\n",
1440 Status = AE_INVALID_TABLE_LENGTH;
1444 /* Validate checksum */
1446 (void) ApIsValidChecksum (LocalTable);
1450 *Table = LocalTable;
1455 /******************************************************************************
1457 * FUNCTION: OslGetCustomizedTable
1459 * PARAMETERS: Pathname - Directory to find Linux customized table
1460 * Signature - ACPI Signature for desired table. Must be
1461 * a null terminated 4-character string.
1462 * Instance - Multiple table support for SSDT/UEFI (0...n)
1463 * Must be 0 for other tables.
1464 * Table - Where a pointer to the table is returned
1465 * Address - Where the table physical address is returned
1467 * RETURN: Status; Table buffer is returned if AE_OK.
1468 * AE_LIMIT: Instance is beyond valid limit
1469 * AE_NOT_FOUND: A table with the signature was not found
1471 * DESCRIPTION: Get an OS customized table.
1473 *****************************************************************************/
1476 OslGetCustomizedTable (
1480 ACPI_TABLE_HEADER **Table,
1481 ACPI_PHYSICAL_ADDRESS *Address)
1484 UINT32 CurrentInstance = 0;
1485 char TempName[ACPI_NAME_SIZE];
1486 char TableFilename[PATH_MAX];
1491 /* Open the directory for customized tables */
1493 TableDir = AcpiOsOpenDirectory (Pathname, "*", REQUEST_FILE_ONLY);
1496 return (OslGetLastStatus (AE_NOT_FOUND));
1499 /* Attempt to find the table in the directory */
1501 while ((Filename = AcpiOsGetNextFilename (TableDir)))
1503 /* Ignore meaningless files */
1505 if (!ACPI_COMPARE_NAME (Filename, Signature))
1510 /* Extract table name and instance number */
1512 Status = OslTableNameFromFile (Filename, TempName, &CurrentInstance);
1514 /* Ignore meaningless files */
1516 if (ACPI_FAILURE (Status) || CurrentInstance != Instance)
1521 /* Create the table pathname */
1525 sprintf (TableFilename, "%s/%4.4s%d", Pathname, TempName, Instance);
1529 sprintf (TableFilename, "%s/%4.4s", Pathname, TempName);
1534 AcpiOsCloseDirectory (TableDir);
1541 /* There is no physical address saved for customized tables, use zero */
1544 Status = OslReadTableFromFile (TableFilename, 0, NULL, Table);