1 /******************************************************************************
3 * Module Name: osefitbl - EFI 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 ("osefitbl")
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 */
81 ACPI_TABLE_HEADER **Table);
85 ACPI_TABLE_HEADER *Table);
99 ACPI_TABLE_HEADER **Table,
100 ACPI_PHYSICAL_ADDRESS *Address);
105 #define EFI_SYSTAB "/sys/firmware/efi/systab"
107 /* Initialization flags */
109 UINT8 Gbl_TableListInitialized = FALSE;
111 /* Local copies of main ACPI tables */
113 ACPI_TABLE_RSDP Gbl_Rsdp;
114 ACPI_TABLE_FADT *Gbl_Fadt = NULL;
115 ACPI_TABLE_RSDT *Gbl_Rsdt = NULL;
116 ACPI_TABLE_XSDT *Gbl_Xsdt = NULL;
118 /* Table addresses */
120 ACPI_PHYSICAL_ADDRESS Gbl_FadtAddress = 0;
121 ACPI_PHYSICAL_ADDRESS Gbl_RsdpAddress = 0;
123 /* Revision of RSD PTR */
125 UINT8 Gbl_Revision = 0;
127 OSL_TABLE_INFO *Gbl_TableListHead = NULL;
128 UINT32 Gbl_TableCount = 0;
131 /******************************************************************************
133 * FUNCTION: AcpiOsGetTableByAddress
135 * PARAMETERS: Address - Physical address of the ACPI table
136 * Table - Where a pointer to the table is returned
138 * RETURN: Status; Table buffer is returned if AE_OK.
139 * AE_NOT_FOUND: A valid table was not found at the address
141 * DESCRIPTION: Get an ACPI table via a physical memory address.
143 *****************************************************************************/
146 AcpiOsGetTableByAddress (
147 ACPI_PHYSICAL_ADDRESS Address,
148 ACPI_TABLE_HEADER **Table)
151 ACPI_TABLE_HEADER *MappedTable;
152 ACPI_TABLE_HEADER *LocalTable = NULL;
153 ACPI_STATUS Status = AE_OK;
156 /* Get main ACPI tables from memory on first invocation of this function */
158 Status = OslTableInitialize ();
159 if (ACPI_FAILURE (Status))
164 /* Map the table and validate it */
166 Status = OslMapTable (Address, NULL, &MappedTable);
167 if (ACPI_FAILURE (Status))
172 /* Copy table to local buffer and return it */
174 TableLength = ApGetTableLength (MappedTable);
175 if (TableLength == 0)
177 Status = AE_BAD_HEADER;
181 LocalTable = ACPI_ALLOCATE_ZEROED (TableLength);
184 Status = AE_NO_MEMORY;
188 ACPI_MEMCPY (LocalTable, MappedTable, TableLength);
191 OslUnmapTable (MappedTable);
197 /******************************************************************************
199 * FUNCTION: AcpiOsGetTableByName
201 * PARAMETERS: Signature - ACPI Signature for desired table. Must be
202 * a null terminated 4-character string.
203 * Instance - Multiple table support for SSDT/UEFI (0...n)
204 * Must be 0 for other tables.
205 * Table - Where a pointer to the table is returned
206 * Address - Where the table physical address is returned
208 * RETURN: Status; Table buffer and physical address returned if AE_OK.
209 * AE_LIMIT: Instance is beyond valid limit
210 * AE_NOT_FOUND: A table with the signature was not found
212 * NOTE: Assumes the input signature is uppercase.
214 *****************************************************************************/
217 AcpiOsGetTableByName (
220 ACPI_TABLE_HEADER **Table,
221 ACPI_PHYSICAL_ADDRESS *Address)
226 /* Get main ACPI tables from memory on first invocation of this function */
228 Status = OslTableInitialize ();
229 if (ACPI_FAILURE (Status))
234 /* Not a main ACPI table, attempt to extract it from the RSDT/XSDT */
236 if (!Gbl_DumpCustomizedTables)
238 /* Attempt to get the table from the memory */
240 Status = OslGetTable (Signature, Instance, Table, Address);
244 /* Attempt to get the table from the static directory */
253 /******************************************************************************
255 * FUNCTION: OslAddTableToList
257 * PARAMETERS: Signature - Table signature
258 * Instance - Table instance
260 * RETURN: Status; Successfully added if AE_OK.
261 * AE_NO_MEMORY: Memory allocation error
263 * DESCRIPTION: Insert a table structure into OSL table list.
265 *****************************************************************************/
272 OSL_TABLE_INFO *NewInfo;
273 OSL_TABLE_INFO *Next;
274 UINT32 NextInstance = 0;
275 BOOLEAN Found = FALSE;
278 NewInfo = ACPI_ALLOCATE_ZEROED (sizeof (OSL_TABLE_INFO));
281 return (AE_NO_MEMORY);
284 ACPI_MOVE_NAME (NewInfo->Signature, Signature);
286 if (!Gbl_TableListHead)
288 Gbl_TableListHead = NewInfo;
292 Next = Gbl_TableListHead;
295 if (ACPI_COMPARE_NAME (Next->Signature, Signature))
297 if (Next->Instance == Instance)
301 if (Next->Instance >= NextInstance)
303 NextInstance = Next->Instance + 1;
313 Next->Next = NewInfo;
321 "%4.4s: Warning unmatched table instance %d, expected %d\n",
322 Signature, Instance, NextInstance);
324 Instance = NextInstance;
327 NewInfo->Instance = Instance;
334 /******************************************************************************
336 * FUNCTION: AcpiOsGetTableByIndex
338 * PARAMETERS: Index - Which table to get
339 * Table - Where a pointer to the table is returned
340 * Instance - Where a pointer to the table instance no. is
342 * Address - Where the table physical address is returned
344 * RETURN: Status; Table buffer and physical address returned if AE_OK.
345 * AE_LIMIT: Index is beyond valid limit
347 * DESCRIPTION: Get an ACPI table via an index value (0 through n). Returns
348 * AE_LIMIT when an invalid index is reached. Index is not
349 * necessarily an index into the RSDT/XSDT.
351 *****************************************************************************/
354 AcpiOsGetTableByIndex (
356 ACPI_TABLE_HEADER **Table,
358 ACPI_PHYSICAL_ADDRESS *Address)
360 OSL_TABLE_INFO *Info;
365 /* Get main ACPI tables from memory on first invocation of this function */
367 Status = OslTableInitialize ();
368 if (ACPI_FAILURE (Status))
375 if (Index >= Gbl_TableCount)
380 /* Point to the table list entry specified by the Index argument */
382 Info = Gbl_TableListHead;
383 for (i = 0; i < Index; i++)
388 /* Now we can just get the table via the signature */
390 Status = AcpiOsGetTableByName (Info->Signature, Info->Instance,
393 if (ACPI_SUCCESS (Status))
395 *Instance = Info->Instance;
401 /******************************************************************************
403 * FUNCTION: OslLoadRsdp
409 * DESCRIPTION: Scan and load RSDP.
411 *****************************************************************************/
417 ACPI_TABLE_HEADER *MappedTable;
419 ACPI_PHYSICAL_ADDRESS RsdpBase;
423 /* Get RSDP from memory */
425 RsdpSize = sizeof (ACPI_TABLE_RSDP);
428 RsdpBase = Gbl_RsdpBase;
432 RsdpBase = AcpiOsGetRootPointer ();
437 RsdpBase = ACPI_HI_RSDP_WINDOW_BASE;
438 RsdpSize = ACPI_HI_RSDP_WINDOW_SIZE;
441 RsdpAddress = AcpiOsMapMemory (RsdpBase, RsdpSize);
444 return (AE_BAD_ADDRESS);
447 /* Search low memory for the RSDP */
449 MappedTable = ACPI_CAST_PTR (ACPI_TABLE_HEADER,
450 AcpiTbScanMemoryForRsdp (RsdpAddress, RsdpSize));
453 AcpiOsUnmapMemory (RsdpAddress, RsdpSize);
454 return (AE_NOT_FOUND);
457 Gbl_RsdpAddress = RsdpBase + (ACPI_CAST8 (MappedTable) - RsdpAddress);
459 ACPI_MEMCPY (&Gbl_Rsdp, MappedTable, sizeof (ACPI_TABLE_RSDP));
460 AcpiOsUnmapMemory (RsdpAddress, RsdpSize);
466 /******************************************************************************
468 * FUNCTION: OslCanUseXsdt
472 * RETURN: TRUE if XSDT is allowed to be used.
474 * DESCRIPTION: This function collects logic that can be used to determine if
475 * XSDT should be used instead of RSDT.
477 *****************************************************************************/
483 if (Gbl_Revision && !AcpiGbl_DoNotUseXsdt)
494 /******************************************************************************
496 * FUNCTION: OslTableInitialize
502 * DESCRIPTION: Initialize ACPI table data. Get and store main ACPI tables to
503 * local variables. Main ACPI tables include RSDT, FADT, RSDT,
506 *****************************************************************************/
513 ACPI_PHYSICAL_ADDRESS Address;
516 if (Gbl_TableListInitialized)
521 /* Get RSDP from memory */
523 Status = OslLoadRsdp ();
524 if (ACPI_FAILURE (Status))
529 /* Get XSDT from memory */
531 if (Gbl_Rsdp.Revision && !Gbl_DoNotDumpXsdt)
535 ACPI_FREE (Gbl_Xsdt);
540 Status = OslGetTable (ACPI_SIG_XSDT, 0,
541 ACPI_CAST_PTR (ACPI_TABLE_HEADER *, &Gbl_Xsdt), &Address);
542 if (ACPI_FAILURE (Status))
548 /* Get RSDT from memory */
550 if (Gbl_Rsdp.RsdtPhysicalAddress)
554 ACPI_FREE (Gbl_Rsdt);
558 Status = OslGetTable (ACPI_SIG_RSDT, 0,
559 ACPI_CAST_PTR (ACPI_TABLE_HEADER *, &Gbl_Rsdt), &Address);
560 if (ACPI_FAILURE (Status))
566 /* Get FADT from memory */
570 ACPI_FREE (Gbl_Fadt);
574 Status = OslGetTable (ACPI_SIG_FADT, 0,
575 ACPI_CAST_PTR (ACPI_TABLE_HEADER *, &Gbl_Fadt), &Gbl_FadtAddress);
576 if (ACPI_FAILURE (Status))
581 if (!Gbl_DumpCustomizedTables)
583 /* Add mandatory tables to global table list first */
585 Status = OslAddTableToList (ACPI_RSDP_NAME, 0);
586 if (ACPI_FAILURE (Status))
591 Status = OslAddTableToList (ACPI_SIG_RSDT, 0);
592 if (ACPI_FAILURE (Status))
597 if (Gbl_Revision == 2)
599 Status = OslAddTableToList (ACPI_SIG_XSDT, 0);
600 if (ACPI_FAILURE (Status))
606 Status = OslAddTableToList (ACPI_SIG_DSDT, 0);
607 if (ACPI_FAILURE (Status))
612 Status = OslAddTableToList (ACPI_SIG_FACS, 0);
613 if (ACPI_FAILURE (Status))
618 /* Add all tables found in the memory */
620 Status = OslListTables ();
621 if (ACPI_FAILURE (Status))
628 /* Add all tables found in the static directory */
633 Gbl_TableListInitialized = TRUE;
638 /******************************************************************************
640 * FUNCTION: OslListTables
644 * RETURN: Status; Table list is initialized if AE_OK.
646 * DESCRIPTION: Add ACPI tables to the table list from memory.
648 *****************************************************************************/
654 ACPI_TABLE_HEADER *MappedTable = NULL;
656 UINT8 NumberOfTables;
658 ACPI_PHYSICAL_ADDRESS TableAddress = 0;
659 ACPI_STATUS Status = AE_OK;
663 if (OslCanUseXsdt ())
665 ItemSize = sizeof (UINT64);
666 TableData = ACPI_CAST8 (Gbl_Xsdt) + sizeof (ACPI_TABLE_HEADER);
668 (UINT8) ((Gbl_Xsdt->Header.Length - sizeof (ACPI_TABLE_HEADER))
671 else /* Use RSDT if XSDT is not available */
673 ItemSize = sizeof (UINT32);
674 TableData = ACPI_CAST8 (Gbl_Rsdt) + sizeof (ACPI_TABLE_HEADER);
676 (UINT8) ((Gbl_Rsdt->Header.Length - sizeof (ACPI_TABLE_HEADER))
680 /* Search RSDT/XSDT for the requested table */
682 for (i = 0; i < NumberOfTables; ++i, TableData += ItemSize)
684 if (OslCanUseXsdt ())
687 (ACPI_PHYSICAL_ADDRESS) (*ACPI_CAST64 (TableData));
692 (ACPI_PHYSICAL_ADDRESS) (*ACPI_CAST32 (TableData));
695 /* Skip NULL entries in RSDT/XSDT */
702 Status = OslMapTable (TableAddress, NULL, &MappedTable);
703 if (ACPI_FAILURE (Status))
708 OslAddTableToList (MappedTable->Signature, 0);
709 OslUnmapTable (MappedTable);
716 /******************************************************************************
718 * FUNCTION: OslGetTable
720 * PARAMETERS: Signature - ACPI Signature for common table. Must be
721 * a null terminated 4-character string.
722 * Instance - Multiple table support for SSDT/UEFI (0...n)
723 * Must be 0 for other tables.
724 * Table - Where a pointer to the table is returned
725 * Address - Where the table physical address is returned
727 * RETURN: Status; Table buffer and physical address returned if AE_OK.
728 * AE_LIMIT: Instance is beyond valid limit
729 * AE_NOT_FOUND: A table with the signature was not found
731 * DESCRIPTION: Get a BIOS provided ACPI table
733 * NOTE: Assumes the input signature is uppercase.
735 *****************************************************************************/
741 ACPI_TABLE_HEADER **Table,
742 ACPI_PHYSICAL_ADDRESS *Address)
744 ACPI_TABLE_HEADER *LocalTable = NULL;
745 ACPI_TABLE_HEADER *MappedTable = NULL;
747 UINT8 NumberOfTables;
749 UINT32 CurrentInstance = 0;
750 ACPI_PHYSICAL_ADDRESS TableAddress = 0;
751 UINT32 TableLength = 0;
752 ACPI_STATUS Status = AE_OK;
756 /* Handle special tables whose addresses are not in RSDT/XSDT */
758 if (ACPI_COMPARE_NAME (Signature, ACPI_RSDP_NAME) ||
759 ACPI_COMPARE_NAME (Signature, ACPI_SIG_RSDT) ||
760 ACPI_COMPARE_NAME (Signature, ACPI_SIG_XSDT) ||
761 ACPI_COMPARE_NAME (Signature, ACPI_SIG_DSDT) ||
762 ACPI_COMPARE_NAME (Signature, ACPI_SIG_FACS))
765 * Get the appropriate address, either 32-bit or 64-bit. Be very
766 * careful about the FADT length and validate table addresses.
767 * Note: The 64-bit addresses have priority.
769 if (ACPI_COMPARE_NAME (Signature, ACPI_SIG_DSDT))
771 if ((Gbl_Fadt->Header.Length >= MIN_FADT_FOR_XDSDT) &&
774 TableAddress = (ACPI_PHYSICAL_ADDRESS) Gbl_Fadt->XDsdt;
776 else if ((Gbl_Fadt->Header.Length >= MIN_FADT_FOR_DSDT) &&
779 TableAddress = (ACPI_PHYSICAL_ADDRESS) Gbl_Fadt->Dsdt;
782 else if (ACPI_COMPARE_NAME (Signature, ACPI_SIG_FACS))
784 if ((Gbl_Fadt->Header.Length >= MIN_FADT_FOR_XFACS) &&
787 TableAddress = (ACPI_PHYSICAL_ADDRESS) Gbl_Fadt->XFacs;
789 else if ((Gbl_Fadt->Header.Length >= MIN_FADT_FOR_FACS) &&
792 TableAddress = (ACPI_PHYSICAL_ADDRESS) Gbl_Fadt->Facs;
795 else if (ACPI_COMPARE_NAME (Signature, ACPI_SIG_XSDT))
799 return (AE_BAD_SIGNATURE);
801 TableAddress = (ACPI_PHYSICAL_ADDRESS) Gbl_Rsdp.XsdtPhysicalAddress;
803 else if (ACPI_COMPARE_NAME (Signature, ACPI_SIG_RSDT))
805 TableAddress = (ACPI_PHYSICAL_ADDRESS) Gbl_Rsdp.RsdtPhysicalAddress;
809 TableAddress = (ACPI_PHYSICAL_ADDRESS) Gbl_RsdpAddress;
810 Signature = ACPI_SIG_RSDP;
813 /* Now we can get the requested special table */
815 Status = OslMapTable (TableAddress, Signature, &MappedTable);
816 if (ACPI_FAILURE (Status))
821 TableLength = ApGetTableLength (MappedTable);
823 else /* Case for a normal ACPI table */
825 if (OslCanUseXsdt ())
827 ItemSize = sizeof (UINT64);
828 TableData = ACPI_CAST8 (Gbl_Xsdt) + sizeof (ACPI_TABLE_HEADER);
830 (UINT8) ((Gbl_Xsdt->Header.Length - sizeof (ACPI_TABLE_HEADER))
833 else /* Use RSDT if XSDT is not available */
835 ItemSize = sizeof (UINT32);
836 TableData = ACPI_CAST8 (Gbl_Rsdt) + sizeof (ACPI_TABLE_HEADER);
838 (UINT8) ((Gbl_Rsdt->Header.Length - sizeof (ACPI_TABLE_HEADER))
842 /* Search RSDT/XSDT for the requested table */
844 for (i = 0; i < NumberOfTables; ++i, TableData += ItemSize)
846 if (OslCanUseXsdt ())
849 (ACPI_PHYSICAL_ADDRESS) (*ACPI_CAST64 (TableData));
854 (ACPI_PHYSICAL_ADDRESS) (*ACPI_CAST32 (TableData));
857 /* Skip NULL entries in RSDT/XSDT */
864 Status = OslMapTable (TableAddress, NULL, &MappedTable);
865 if (ACPI_FAILURE (Status))
869 TableLength = MappedTable->Length;
871 /* Does this table match the requested signature? */
873 if (!ACPI_COMPARE_NAME (MappedTable->Signature, Signature))
875 OslUnmapTable (MappedTable);
880 /* Match table instance (for SSDT/UEFI tables) */
882 if (CurrentInstance != Instance)
884 OslUnmapTable (MappedTable);
899 if (TableLength == 0)
901 Status = AE_BAD_HEADER;
905 /* Copy table to local buffer and return it */
907 LocalTable = ACPI_ALLOCATE_ZEROED (TableLength);
910 Status = AE_NO_MEMORY;
914 ACPI_MEMCPY (LocalTable, MappedTable, TableLength);
915 *Address = TableAddress;
919 OslUnmapTable (MappedTable);
924 /******************************************************************************
926 * FUNCTION: OslMapTable
928 * PARAMETERS: Address - Address of the table in memory
929 * Signature - Optional ACPI Signature for desired table.
930 * Null terminated 4-character string.
931 * Table - Where a pointer to the mapped table is
934 * RETURN: Status; Mapped table is returned if AE_OK.
935 * AE_NOT_FOUND: A valid table was not found at the address
937 * DESCRIPTION: Map entire ACPI table into caller's address space.
939 *****************************************************************************/
945 ACPI_TABLE_HEADER **Table)
947 ACPI_TABLE_HEADER *MappedTable;
953 return (AE_BAD_ADDRESS);
957 * Map the header so we can get the table length.
958 * Use sizeof (ACPI_TABLE_HEADER) as:
959 * 1. it is bigger than 24 to include RSDP->Length
960 * 2. it is smaller than sizeof (ACPI_TABLE_RSDP)
962 MappedTable = AcpiOsMapMemory (Address, sizeof (ACPI_TABLE_HEADER));
965 AcpiLogError ("Could not map table header at 0x%8.8X%8.8X\n",
966 ACPI_FORMAT_UINT64 (Address));
967 return (AE_BAD_ADDRESS);
970 /* If specified, signature must match */
974 if (ACPI_VALIDATE_RSDP_SIG (Signature))
976 if (!ACPI_VALIDATE_RSDP_SIG (MappedTable->Signature))
978 AcpiOsUnmapMemory (MappedTable, sizeof (ACPI_TABLE_HEADER));
979 return (AE_BAD_SIGNATURE);
982 else if (!ACPI_COMPARE_NAME (Signature, MappedTable->Signature))
984 AcpiOsUnmapMemory (MappedTable, sizeof (ACPI_TABLE_HEADER));
985 return (AE_BAD_SIGNATURE);
989 /* Map the entire table */
991 Length = ApGetTableLength (MappedTable);
992 AcpiOsUnmapMemory (MappedTable, sizeof (ACPI_TABLE_HEADER));
995 return (AE_BAD_HEADER);
998 MappedTable = AcpiOsMapMemory (Address, Length);
1001 AcpiLogError ("Could not map table at 0x%8.8X%8.8X length %8.8X\n",
1002 ACPI_FORMAT_UINT64 (Address), Length);
1003 return (AE_INVALID_TABLE_LENGTH);
1006 (void) ApIsValidChecksum (MappedTable);
1008 *Table = MappedTable;
1013 /******************************************************************************
1015 * FUNCTION: OslUnmapTable
1017 * PARAMETERS: Table - A pointer to the mapped table
1021 * DESCRIPTION: Unmap entire ACPI table.
1023 *****************************************************************************/
1027 ACPI_TABLE_HEADER *Table)
1031 AcpiOsUnmapMemory (Table, ApGetTableLength (Table));