Indentation fix, cleanup.
[AROS.git] / arch / all-pc / acpica / source / os_specific / service_layers / oslinuxtbl.c
blob1d27b0cc7fc84cf01a688fe44242d5fe25b93993
1 /******************************************************************************
3 * Module Name: oslinuxtbl - Linux OSL for obtaining ACPI tables
5 *****************************************************************************/
7 /*
8 * Copyright (C) 2000 - 2013, Intel Corp.
9 * All rights reserved.
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions, and the following disclaimer,
16 * without modification.
17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18 * substantially similar to the "NO WARRANTY" disclaimer below
19 * ("Disclaimer") and any redistribution must be conditioned upon
20 * including a substantially similar Disclaimer requirement for further
21 * binary redistribution.
22 * 3. Neither the names of the above-listed copyright holders nor the names
23 * of any contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
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.
30 * NO WARRANTY
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33 * LIMITED TO, THE IMPLIED WARRANTIES OF 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.
44 #include "acpidump.h"
47 #define _COMPONENT ACPI_OS_SERVICES
48 ACPI_MODULE_NAME ("oslinuxtbl")
51 #ifndef PATH_MAX
52 #define PATH_MAX 256
53 #endif
56 /* List of information about obtained ACPI tables */
58 typedef struct table_info
60 struct table_info *Next;
61 UINT32 Instance;
62 char Signature[ACPI_NAME_SIZE];
64 } OSL_TABLE_INFO;
66 /* Local prototypes */
68 static ACPI_STATUS
69 OslTableInitialize (
70 void);
72 static ACPI_STATUS
73 OslTableNameFromFile (
74 char *Filename,
75 char *Signature,
76 UINT32 *Instance);
78 static ACPI_STATUS
79 OslAddTableToList (
80 char *Signature,
81 UINT32 Instance);
83 static ACPI_STATUS
84 OslReadTableFromFile (
85 char *Filename,
86 ACPI_SIZE FileOffset,
87 char *Signature,
88 ACPI_TABLE_HEADER **Table);
90 static ACPI_STATUS
91 OslMapTable (
92 ACPI_SIZE Address,
93 char *Signature,
94 ACPI_TABLE_HEADER **Table);
96 static void
97 OslUnmapTable (
98 ACPI_TABLE_HEADER *Table);
100 static ACPI_PHYSICAL_ADDRESS
101 OslFindRsdpViaEfi (
102 void);
104 static ACPI_STATUS
105 OslLoadRsdp (
106 void);
108 static ACPI_STATUS
109 OslListCustomizedTables (
110 char *Directory);
112 static ACPI_STATUS
113 OslGetCustomizedTable (
114 char *Pathname,
115 char *Signature,
116 UINT32 Instance,
117 ACPI_TABLE_HEADER **Table,
118 ACPI_PHYSICAL_ADDRESS *Address);
120 static ACPI_STATUS
121 OslListBiosTables (
122 void);
124 static ACPI_STATUS
125 OslGetBiosTable (
126 char *Signature,
127 UINT32 Instance,
128 ACPI_TABLE_HEADER **Table,
129 ACPI_PHYSICAL_ADDRESS *Address);
131 static ACPI_STATUS
132 OslGetLastStatus (
133 ACPI_STATUS DefaultStatus);
136 /* File locations */
138 #define DYNAMIC_TABLE_DIR "/sys/firmware/acpi/tables/dynamic"
139 #define STATIC_TABLE_DIR "/sys/firmware/acpi/tables"
140 #define EFI_SYSTAB "/sys/firmware/efi/systab"
142 /* Should we get dynamically loaded SSDTs from DYNAMIC_TABLE_DIR? */
144 UINT8 Gbl_DumpDynamicTables = TRUE;
146 /* Initialization flags */
148 UINT8 Gbl_TableListInitialized = FALSE;
150 /* Local copies of main ACPI tables */
152 ACPI_TABLE_RSDP Gbl_Rsdp;
153 ACPI_TABLE_FADT *Gbl_Fadt = NULL;
154 ACPI_TABLE_RSDT *Gbl_Rsdt = NULL;
155 ACPI_TABLE_XSDT *Gbl_Xsdt = NULL;
157 /* Table addresses */
159 ACPI_PHYSICAL_ADDRESS Gbl_FadtAddress = 0;
160 ACPI_PHYSICAL_ADDRESS Gbl_RsdpAddress = 0;
162 /* Revision of RSD PTR */
164 UINT8 Gbl_Revision = 0;
166 OSL_TABLE_INFO *Gbl_TableListHead = NULL;
167 UINT32 Gbl_TableCount = 0;
170 /******************************************************************************
172 * FUNCTION: OslGetLastStatus
174 * PARAMETERS: DefaultStatus - Default error status to return
176 * RETURN: Status; Converted from errno.
178 * DESCRIPTION: Get last errno and conver it to ACPI_STATUS.
180 *****************************************************************************/
182 static ACPI_STATUS
183 OslGetLastStatus (
184 ACPI_STATUS DefaultStatus)
187 switch (errno)
189 case EACCES:
190 case EPERM:
192 return (AE_ACCESS);
194 case ENOENT:
196 return (AE_NOT_FOUND);
198 case ENOMEM:
200 return (AE_NO_MEMORY);
202 default:
204 return (DefaultStatus);
209 /******************************************************************************
211 * FUNCTION: AcpiOsGetTableByAddress
213 * PARAMETERS: Address - Physical address of the ACPI table
214 * Table - Where a pointer to the table is returned
216 * RETURN: Status; Table buffer is returned if AE_OK.
217 * AE_NOT_FOUND: A valid table was not found at the address
219 * DESCRIPTION: Get an ACPI table via a physical memory address.
221 *****************************************************************************/
223 ACPI_STATUS
224 AcpiOsGetTableByAddress (
225 ACPI_PHYSICAL_ADDRESS Address,
226 ACPI_TABLE_HEADER **Table)
228 UINT32 TableLength;
229 ACPI_TABLE_HEADER *MappedTable;
230 ACPI_TABLE_HEADER *LocalTable = NULL;
231 ACPI_STATUS Status = AE_OK;
234 /* Get main ACPI tables from memory on first invocation of this function */
236 Status = OslTableInitialize ();
237 if (ACPI_FAILURE (Status))
239 return (Status);
242 /* Map the table and validate it */
244 Status = OslMapTable (Address, NULL, &MappedTable);
245 if (ACPI_FAILURE (Status))
247 return (Status);
250 /* Copy table to local buffer and return it */
252 TableLength = ApGetTableLength (MappedTable);
253 if (TableLength == 0)
255 Status = AE_BAD_HEADER;
256 goto ErrorExit;
259 LocalTable = calloc (1, TableLength);
260 if (!LocalTable)
262 Status = AE_NO_MEMORY;
263 goto ErrorExit;
266 ACPI_MEMCPY (LocalTable, MappedTable, TableLength);
268 ErrorExit:
269 OslUnmapTable (MappedTable);
270 *Table = LocalTable;
271 return (AE_OK);
275 /******************************************************************************
277 * FUNCTION: AcpiOsGetTableByName
279 * PARAMETERS: Signature - ACPI Signature for desired table. Must be
280 * a null terminated 4-character string.
281 * Instance - Multiple table support for SSDT/UEFI (0...n)
282 * Must be 0 for other tables.
283 * Table - Where a pointer to the table is returned
284 * Address - Where the table physical address is returned
286 * RETURN: Status; Table buffer and physical address returned if AE_OK.
287 * AE_LIMIT: Instance is beyond valid limit
288 * AE_NOT_FOUND: A table with the signature was not found
290 * NOTE: Assumes the input signature is uppercase.
292 *****************************************************************************/
294 ACPI_STATUS
295 AcpiOsGetTableByName (
296 char *Signature,
297 UINT32 Instance,
298 ACPI_TABLE_HEADER **Table,
299 ACPI_PHYSICAL_ADDRESS *Address)
301 ACPI_STATUS Status;
304 /* Get main ACPI tables from memory on first invocation of this function */
306 Status = OslTableInitialize ();
307 if (ACPI_FAILURE (Status))
309 return (Status);
312 /* Not a main ACPI table, attempt to extract it from the RSDT/XSDT */
314 if (!Gbl_DumpCustomizedTables)
316 /* Attempt to get the table from the memory */
318 Status = OslGetBiosTable (Signature, Instance, Table, Address);
320 else
322 /* Attempt to get the table from the static directory */
324 Status = OslGetCustomizedTable (STATIC_TABLE_DIR, Signature,
325 Instance, Table, Address);
328 if (ACPI_FAILURE (Status) && Status == AE_LIMIT)
330 if (Gbl_DumpDynamicTables)
332 /* Attempt to get a dynamic table */
334 Status = OslGetCustomizedTable (DYNAMIC_TABLE_DIR, Signature,
335 Instance, Table, Address);
339 return (Status);
343 /******************************************************************************
345 * FUNCTION: OslAddTableToList
347 * PARAMETERS: Signature - Table signature
348 * Instance - Table instance
350 * RETURN: Status; Successfully added if AE_OK.
351 * AE_NO_MEMORY: Memory allocation error
353 * DESCRIPTION: Insert a table structure into OSL table list.
355 *****************************************************************************/
357 static ACPI_STATUS
358 OslAddTableToList (
359 char *Signature,
360 UINT32 Instance)
362 OSL_TABLE_INFO *NewInfo;
363 OSL_TABLE_INFO *Next;
364 UINT32 NextInstance = 0;
365 BOOLEAN Found = FALSE;
368 NewInfo = calloc (1, sizeof (OSL_TABLE_INFO));
369 if (!NewInfo)
371 return (AE_NO_MEMORY);
374 ACPI_MOVE_NAME (NewInfo->Signature, Signature);
376 if (!Gbl_TableListHead)
378 Gbl_TableListHead = NewInfo;
380 else
382 Next = Gbl_TableListHead;
383 while (1)
385 if (ACPI_COMPARE_NAME (Next->Signature, Signature))
387 if (Next->Instance == Instance)
389 Found = TRUE;
391 if (Next->Instance >= NextInstance)
393 NextInstance = Next->Instance + 1;
397 if (!Next->Next)
399 break;
401 Next = Next->Next;
403 Next->Next = NewInfo;
406 if (Found)
408 if (Instance)
410 fprintf (stderr,
411 "%4.4s: Warning unmatched table instance %d, expected %d\n",
412 Signature, Instance, NextInstance);
414 Instance = NextInstance;
417 NewInfo->Instance = Instance;
418 Gbl_TableCount++;
420 return (AE_OK);
424 /******************************************************************************
426 * FUNCTION: AcpiOsGetTableByIndex
428 * PARAMETERS: Index - Which table to get
429 * Table - Where a pointer to the table is returned
430 * Instance - Where a pointer to the table instance no. is
431 * returned
432 * Address - Where the table physical address is returned
434 * RETURN: Status; Table buffer and physical address returned if AE_OK.
435 * AE_LIMIT: Index is beyond valid limit
437 * DESCRIPTION: Get an ACPI table via an index value (0 through n). Returns
438 * AE_LIMIT when an invalid index is reached. Index is not
439 * necessarily an index into the RSDT/XSDT.
441 *****************************************************************************/
443 ACPI_STATUS
444 AcpiOsGetTableByIndex (
445 UINT32 Index,
446 ACPI_TABLE_HEADER **Table,
447 UINT32 *Instance,
448 ACPI_PHYSICAL_ADDRESS *Address)
450 OSL_TABLE_INFO *Info;
451 ACPI_STATUS Status;
452 UINT32 i;
455 /* Get main ACPI tables from memory on first invocation of this function */
457 Status = OslTableInitialize ();
458 if (ACPI_FAILURE (Status))
460 return (Status);
463 /* Validate Index */
465 if (Index >= Gbl_TableCount)
467 return (AE_LIMIT);
470 /* Point to the table list entry specified by the Index argument */
472 Info = Gbl_TableListHead;
473 for (i = 0; i < Index; i++)
475 Info = Info->Next;
478 /* Now we can just get the table via the signature */
480 Status = AcpiOsGetTableByName (Info->Signature, Info->Instance,
481 Table, Address);
483 if (ACPI_SUCCESS (Status))
485 *Instance = Info->Instance;
487 return (Status);
491 /******************************************************************************
493 * FUNCTION: OslFindRsdpViaEfi
495 * PARAMETERS: None
497 * RETURN: RSDP address if found
499 * DESCRIPTION: Find RSDP address via EFI.
501 *****************************************************************************/
503 static ACPI_PHYSICAL_ADDRESS
504 OslFindRsdpViaEfi (
505 void)
507 FILE *File;
508 char Buffer[80];
509 unsigned long Address = 0;
512 File = fopen (EFI_SYSTAB, "r");
513 if (File)
515 while (fgets (Buffer, 80, File))
517 if (sscanf (Buffer, "ACPI20=0x%lx", &Address) == 1)
519 break;
522 fclose (File);
525 return ((ACPI_PHYSICAL_ADDRESS) (Address));
529 /******************************************************************************
531 * FUNCTION: OslLoadRsdp
533 * PARAMETERS: None
535 * RETURN: Status
537 * DESCRIPTION: Scan and load RSDP.
539 *****************************************************************************/
541 static ACPI_STATUS
542 OslLoadRsdp (
543 void)
545 ACPI_TABLE_HEADER *MappedTable;
546 UINT8 *RsdpAddress;
547 ACPI_PHYSICAL_ADDRESS RsdpBase;
548 ACPI_SIZE RsdpSize;
551 /* Get RSDP from memory */
553 RsdpSize = sizeof (ACPI_TABLE_RSDP);
554 if (Gbl_RsdpBase)
556 RsdpBase = Gbl_RsdpBase;
558 else
560 RsdpBase = OslFindRsdpViaEfi ();
563 if (!RsdpBase)
565 RsdpBase = ACPI_HI_RSDP_WINDOW_BASE;
566 RsdpSize = ACPI_HI_RSDP_WINDOW_SIZE;
569 RsdpAddress = AcpiOsMapMemory (RsdpBase, RsdpSize);
570 if (!RsdpAddress)
572 return (OslGetLastStatus (AE_BAD_ADDRESS));
575 /* Search low memory for the RSDP */
577 MappedTable = ACPI_CAST_PTR (ACPI_TABLE_HEADER,
578 AcpiTbScanMemoryForRsdp (RsdpAddress, RsdpSize));
579 if (!MappedTable)
581 AcpiOsUnmapMemory (RsdpAddress, RsdpSize);
582 return (AE_NOT_FOUND);
585 Gbl_RsdpAddress = RsdpBase + (ACPI_CAST8 (MappedTable) - RsdpAddress);
587 ACPI_MEMCPY (&Gbl_Rsdp, MappedTable, sizeof (ACPI_TABLE_RSDP));
588 AcpiOsUnmapMemory (RsdpAddress, RsdpSize);
590 return (AE_OK);
594 /******************************************************************************
596 * FUNCTION: OslTableInitialize
598 * PARAMETERS: None
600 * RETURN: Status
602 * DESCRIPTION: Initialize ACPI table data. Get and store main ACPI tables to
603 * local variables. Main ACPI tables include RSDT, FADT, RSDT,
604 * and/or XSDT.
606 *****************************************************************************/
608 static ACPI_STATUS
609 OslTableInitialize (
610 void)
612 ACPI_STATUS Status;
613 ACPI_PHYSICAL_ADDRESS Address;
616 if (Gbl_TableListInitialized)
618 return (AE_OK);
621 /* Get RSDP from memory */
623 Status = OslLoadRsdp ();
624 if (ACPI_FAILURE (Status))
626 return (Status);
629 /* Get XSDT from memory */
631 if (Gbl_Rsdp.Revision)
633 if (Gbl_Xsdt)
635 free (Gbl_Xsdt);
636 Gbl_Xsdt = NULL;
639 Gbl_Revision = 2;
640 Status = OslGetBiosTable (ACPI_SIG_XSDT, 0,
641 ACPI_CAST_PTR (ACPI_TABLE_HEADER *, &Gbl_Xsdt), &Address);
642 if (ACPI_FAILURE (Status))
644 return (Status);
648 /* Get RSDT from memory */
650 if (Gbl_Rsdp.RsdtPhysicalAddress)
652 if (Gbl_Rsdt)
654 free (Gbl_Rsdt);
655 Gbl_Rsdt = NULL;
658 Status = OslGetBiosTable (ACPI_SIG_RSDT, 0,
659 ACPI_CAST_PTR (ACPI_TABLE_HEADER *, &Gbl_Rsdt), &Address);
660 if (ACPI_FAILURE (Status))
662 return (Status);
666 /* Get FADT from memory */
668 if (Gbl_Fadt)
670 free (Gbl_Fadt);
671 Gbl_Fadt = NULL;
674 Status = OslGetBiosTable (ACPI_SIG_FADT, 0,
675 ACPI_CAST_PTR (ACPI_TABLE_HEADER *, &Gbl_Fadt), &Gbl_FadtAddress);
676 if (ACPI_FAILURE (Status))
678 return (Status);
681 if (!Gbl_DumpCustomizedTables)
683 /* Add mandatory tables to global table list first */
685 Status = OslAddTableToList (AP_DUMP_SIG_RSDP, 0);
686 if (ACPI_FAILURE (Status))
688 return (Status);
691 Status = OslAddTableToList (ACPI_SIG_RSDT, 0);
692 if (ACPI_FAILURE (Status))
694 return (Status);
697 if (Gbl_Revision == 2)
699 Status = OslAddTableToList (ACPI_SIG_XSDT, 0);
700 if (ACPI_FAILURE (Status))
702 return (Status);
706 Status = OslAddTableToList (ACPI_SIG_DSDT, 0);
707 if (ACPI_FAILURE (Status))
709 return (Status);
712 Status = OslAddTableToList (ACPI_SIG_FACS, 0);
713 if (ACPI_FAILURE (Status))
715 return (Status);
718 /* Add all tables found in the memory */
720 Status = OslListBiosTables ();
721 if (ACPI_FAILURE (Status))
723 return (Status);
726 else
728 /* Add all tables found in the static directory */
730 Status = OslListCustomizedTables (STATIC_TABLE_DIR);
731 if (ACPI_FAILURE (Status))
733 return (Status);
737 if (Gbl_DumpDynamicTables)
739 /* Add all dynamically loaded tables in the dynamic directory */
741 Status = OslListCustomizedTables (DYNAMIC_TABLE_DIR);
742 if (ACPI_FAILURE (Status))
744 return (Status);
748 Gbl_TableListInitialized = TRUE;
749 return (AE_OK);
753 /******************************************************************************
755 * FUNCTION: OslListBiosTables
757 * PARAMETERS: None
759 * RETURN: Status; Table list is initialized if AE_OK.
761 * DESCRIPTION: Add ACPI tables to the table list from memory.
763 * NOTE: This works on Linux as table customization does not modify the
764 * addresses stored in RSDP/RSDT/XSDT/FADT.
766 *****************************************************************************/
768 static ACPI_STATUS
769 OslListBiosTables (
770 void)
772 ACPI_TABLE_HEADER *MappedTable = NULL;
773 UINT8 *TableData;
774 UINT8 NumberOfTables;
775 UINT8 ItemSize;
776 ACPI_PHYSICAL_ADDRESS TableAddress = 0;
777 ACPI_STATUS Status = AE_OK;
778 UINT32 i;
781 if (Gbl_Revision)
783 ItemSize = sizeof (UINT64);
784 TableData = ACPI_CAST8 (Gbl_Xsdt) + sizeof (ACPI_TABLE_HEADER);
785 NumberOfTables =
786 (UINT8) ((Gbl_Xsdt->Header.Length - sizeof (ACPI_TABLE_HEADER))
787 / ItemSize);
789 else /* Use RSDT if XSDT is not available */
791 ItemSize = sizeof (UINT32);
792 TableData = ACPI_CAST8 (Gbl_Rsdt) + sizeof (ACPI_TABLE_HEADER);
793 NumberOfTables =
794 (UINT8) ((Gbl_Rsdt->Header.Length - sizeof (ACPI_TABLE_HEADER))
795 / ItemSize);
798 /* Search RSDT/XSDT for the requested table */
800 for (i = 0; i < NumberOfTables; ++i, TableData += ItemSize)
802 if (Gbl_Revision)
804 TableAddress =
805 (ACPI_PHYSICAL_ADDRESS) (*ACPI_CAST64 (TableData));
807 else
809 TableAddress =
810 (ACPI_PHYSICAL_ADDRESS) (*ACPI_CAST32 (TableData));
813 Status = OslMapTable (TableAddress, NULL, &MappedTable);
814 if (ACPI_FAILURE (Status))
816 return (Status);
819 OslAddTableToList (MappedTable->Signature, 0);
820 OslUnmapTable (MappedTable);
823 return (AE_OK);
827 /******************************************************************************
829 * FUNCTION: OslGetBiosTable
831 * PARAMETERS: Signature - ACPI Signature for common table. Must be
832 * a null terminated 4-character string.
833 * Instance - Multiple table support for SSDT/UEFI (0...n)
834 * Must be 0 for other tables.
835 * Table - Where a pointer to the table is returned
836 * Address - Where the table physical address is returned
838 * RETURN: Status; Table buffer and physical address returned if AE_OK.
839 * AE_LIMIT: Instance is beyond valid limit
840 * AE_NOT_FOUND: A table with the signature was not found
842 * DESCRIPTION: Get a BIOS provided ACPI table
844 * NOTE: Assumes the input signature is uppercase.
846 *****************************************************************************/
848 static ACPI_STATUS
849 OslGetBiosTable (
850 char *Signature,
851 UINT32 Instance,
852 ACPI_TABLE_HEADER **Table,
853 ACPI_PHYSICAL_ADDRESS *Address)
855 ACPI_TABLE_HEADER *LocalTable = NULL;
856 ACPI_TABLE_HEADER *MappedTable = NULL;
857 UINT8 *TableData;
858 UINT8 NumberOfTables;
859 UINT8 ItemSize;
860 UINT32 CurrentInstance = 0;
861 ACPI_PHYSICAL_ADDRESS TableAddress = 0;
862 UINT32 TableLength = 0;
863 ACPI_STATUS Status = AE_OK;
864 UINT32 i;
867 /* Handle special tables whose addresses are not in RSDT/XSDT */
869 if (ACPI_COMPARE_NAME (Signature, AP_DUMP_SIG_RSDP) ||
870 ACPI_COMPARE_NAME (Signature, ACPI_SIG_RSDT) ||
871 ACPI_COMPARE_NAME (Signature, ACPI_SIG_XSDT) ||
872 ACPI_COMPARE_NAME (Signature, ACPI_SIG_DSDT) ||
873 ACPI_COMPARE_NAME (Signature, ACPI_SIG_FACS))
876 * Get the appropriate address, either 32-bit or 64-bit. Be very
877 * careful about the FADT length and validate table addresses.
878 * Note: The 64-bit addresses have priority.
880 if (ACPI_COMPARE_NAME (Signature, ACPI_SIG_DSDT))
882 if ((Gbl_Fadt->Header.Length >= MIN_FADT_FOR_XDSDT) &&
883 Gbl_Fadt->XDsdt)
885 TableAddress = (ACPI_PHYSICAL_ADDRESS) Gbl_Fadt->XDsdt;
887 else if ((Gbl_Fadt->Header.Length >= MIN_FADT_FOR_DSDT) &&
888 Gbl_Fadt->Dsdt)
890 TableAddress = (ACPI_PHYSICAL_ADDRESS) Gbl_Fadt->Dsdt;
893 else if (ACPI_COMPARE_NAME (Signature, ACPI_SIG_FACS))
895 if ((Gbl_Fadt->Header.Length >= MIN_FADT_FOR_XFACS) &&
896 Gbl_Fadt->XFacs)
898 TableAddress = (ACPI_PHYSICAL_ADDRESS) Gbl_Fadt->XFacs;
900 else if ((Gbl_Fadt->Header.Length >= MIN_FADT_FOR_FACS) &&
901 Gbl_Fadt->Facs)
903 TableAddress = (ACPI_PHYSICAL_ADDRESS) Gbl_Fadt->Facs;
906 else if (ACPI_COMPARE_NAME (Signature, ACPI_SIG_XSDT))
908 if (!Gbl_Revision)
910 return (AE_BAD_SIGNATURE);
912 TableAddress = (ACPI_PHYSICAL_ADDRESS) Gbl_Rsdp.XsdtPhysicalAddress;
914 else if (ACPI_COMPARE_NAME (Signature, ACPI_SIG_RSDT))
916 TableAddress = (ACPI_PHYSICAL_ADDRESS) Gbl_Rsdp.RsdtPhysicalAddress;
918 else
920 TableAddress = (ACPI_PHYSICAL_ADDRESS) Gbl_RsdpAddress;
921 Signature = ACPI_SIG_RSDP;
924 /* Now we can get the requested special table */
926 Status = OslMapTable (TableAddress, Signature, &MappedTable);
927 if (ACPI_FAILURE (Status))
929 return (Status);
932 TableLength = ApGetTableLength (MappedTable);
934 else /* Case for a normal ACPI table */
936 if (Gbl_Revision)
938 ItemSize = sizeof (UINT64);
939 TableData = ACPI_CAST8 (Gbl_Xsdt) + sizeof (ACPI_TABLE_HEADER);
940 NumberOfTables =
941 (UINT8) ((Gbl_Xsdt->Header.Length - sizeof (ACPI_TABLE_HEADER))
942 / ItemSize);
944 else /* Use RSDT if XSDT is not available */
946 ItemSize = sizeof (UINT32);
947 TableData = ACPI_CAST8 (Gbl_Rsdt) + sizeof (ACPI_TABLE_HEADER);
948 NumberOfTables =
949 (UINT8) ((Gbl_Rsdt->Header.Length - sizeof (ACPI_TABLE_HEADER))
950 / ItemSize);
953 /* Search RSDT/XSDT for the requested table */
955 for (i = 0; i < NumberOfTables; ++i, TableData += ItemSize)
957 if (Gbl_Revision)
959 TableAddress =
960 (ACPI_PHYSICAL_ADDRESS) (*ACPI_CAST64 (TableData));
962 else
964 TableAddress =
965 (ACPI_PHYSICAL_ADDRESS) (*ACPI_CAST32 (TableData));
968 Status = OslMapTable (TableAddress, NULL, &MappedTable);
969 if (ACPI_FAILURE (Status))
971 return (Status);
973 TableLength = MappedTable->Length;
975 /* Does this table match the requested signature? */
977 if (!ACPI_COMPARE_NAME (MappedTable->Signature, Signature))
979 OslUnmapTable (MappedTable);
980 MappedTable = NULL;
981 continue;
984 /* Match table instance (for SSDT/UEFI tables) */
986 if (CurrentInstance != Instance)
988 OslUnmapTable (MappedTable);
989 MappedTable = NULL;
990 CurrentInstance++;
991 continue;
994 break;
998 if (!MappedTable)
1000 return (AE_LIMIT);
1003 if (TableLength == 0)
1005 Status = AE_BAD_HEADER;
1006 goto ErrorExit;
1009 /* Copy table to local buffer and return it */
1011 LocalTable = calloc (1, TableLength);
1012 if (!LocalTable)
1014 Status = AE_NO_MEMORY;
1015 goto ErrorExit;
1018 ACPI_MEMCPY (LocalTable, MappedTable, TableLength);
1019 *Address = TableAddress;
1020 *Table = LocalTable;
1022 ErrorExit:
1023 OslUnmapTable (MappedTable);
1024 return (AE_OK);
1028 /******************************************************************************
1030 * FUNCTION: OslListCustomizedTables
1032 * PARAMETERS: Directory - Directory that contains the tables
1034 * RETURN: Status; Table list is initialized if AE_OK.
1036 * DESCRIPTION: Add ACPI tables to the table list from a directory.
1038 *****************************************************************************/
1040 static ACPI_STATUS
1041 OslListCustomizedTables (
1042 char *Directory)
1044 void *TableDir;
1045 UINT32 Instance;
1046 char TempName[ACPI_NAME_SIZE];
1047 char *Filename;
1048 ACPI_STATUS Status = AE_OK;
1051 /* Open the requested directory */
1053 TableDir = AcpiOsOpenDirectory (Directory, "*", REQUEST_FILE_ONLY);
1054 if (!TableDir)
1056 return (OslGetLastStatus (AE_NOT_FOUND));
1059 /* Examine all entries in this directory */
1061 while ((Filename = AcpiOsGetNextFilename (TableDir)))
1063 /* Extract table name and instance number */
1065 Status = OslTableNameFromFile (Filename, TempName, &Instance);
1067 /* Ignore meaningless files */
1069 if (ACPI_FAILURE (Status))
1071 continue;
1074 /* Add new info node to global table list */
1076 Status = OslAddTableToList (TempName, Instance);
1077 if (ACPI_FAILURE (Status))
1079 break;
1083 AcpiOsCloseDirectory (TableDir);
1084 return (Status);
1088 /******************************************************************************
1090 * FUNCTION: OslMapTable
1092 * PARAMETERS: Address - Address of the table in memory
1093 * Signature - Optional ACPI Signature for desired table.
1094 * Null terminated 4-character string.
1095 * Table - Where a pointer to the mapped table is
1096 * returned
1098 * RETURN: Status; Mapped table is returned if AE_OK.
1099 * AE_NOT_FOUND: A valid table was not found at the address
1101 * DESCRIPTION: Map entire ACPI table into caller's address space.
1103 *****************************************************************************/
1105 static ACPI_STATUS
1106 OslMapTable (
1107 ACPI_SIZE Address,
1108 char *Signature,
1109 ACPI_TABLE_HEADER **Table)
1111 ACPI_TABLE_HEADER *MappedTable;
1112 UINT32 Length;
1115 if (!Address)
1117 return (AE_BAD_ADDRESS);
1121 * Map the header so we can get the table length.
1122 * Use sizeof (ACPI_TABLE_HEADER) as:
1123 * 1. it is bigger than 24 to include RSDP->Length
1124 * 2. it is smaller than sizeof (ACPI_TABLE_RSDP)
1126 MappedTable = AcpiOsMapMemory (Address, sizeof (ACPI_TABLE_HEADER));
1127 if (!MappedTable)
1129 fprintf (stderr, "Could not map table header at 0x%8.8X%8.8X\n",
1130 ACPI_FORMAT_UINT64 (Address));
1131 return (OslGetLastStatus (AE_BAD_ADDRESS));
1134 /* If specified, signature must match */
1136 if (Signature &&
1137 !ACPI_COMPARE_NAME (Signature, MappedTable->Signature))
1139 AcpiOsUnmapMemory (MappedTable, sizeof (ACPI_TABLE_HEADER));
1140 return (AE_BAD_SIGNATURE);
1143 /* Map the entire table */
1145 Length = ApGetTableLength (MappedTable);
1146 AcpiOsUnmapMemory (MappedTable, sizeof (ACPI_TABLE_HEADER));
1147 if (Length == 0)
1149 return (AE_BAD_HEADER);
1152 MappedTable = AcpiOsMapMemory (Address, Length);
1153 if (!MappedTable)
1155 fprintf (stderr, "Could not map table at 0x%8.8X%8.8X length %8.8X\n",
1156 ACPI_FORMAT_UINT64 (Address), Length);
1157 return (OslGetLastStatus (AE_INVALID_TABLE_LENGTH));
1160 (void) ApIsValidChecksum (MappedTable);
1162 *Table = MappedTable;
1163 return (AE_OK);
1167 /******************************************************************************
1169 * FUNCTION: OslUnmapTable
1171 * PARAMETERS: Table - A pointer to the mapped table
1173 * RETURN: None
1175 * DESCRIPTION: Unmap entire ACPI table.
1177 *****************************************************************************/
1179 static void
1180 OslUnmapTable (
1181 ACPI_TABLE_HEADER *Table)
1183 if (Table)
1185 AcpiOsUnmapMemory (Table, ApGetTableLength (Table));
1190 /******************************************************************************
1192 * FUNCTION: OslTableNameFromFile
1194 * PARAMETERS: Filename - File that contains the desired table
1195 * Signature - Pointer to 4-character buffer to store
1196 * extracted table signature.
1197 * Instance - Pointer to integer to store extracted
1198 * table instance number.
1200 * RETURN: Status; Table name is extracted if AE_OK.
1202 * DESCRIPTION: Extract table signature and instance number from a table file
1203 * name.
1205 *****************************************************************************/
1207 static ACPI_STATUS
1208 OslTableNameFromFile (
1209 char *Filename,
1210 char *Signature,
1211 UINT32 *Instance)
1214 /* Ignore meaningless files */
1216 if (strlen (Filename) < ACPI_NAME_SIZE)
1218 return (AE_BAD_SIGNATURE);
1221 /* Extract instance number */
1223 if (isdigit ((int) Filename[ACPI_NAME_SIZE]))
1225 sscanf (&Filename[ACPI_NAME_SIZE], "%d", Instance);
1227 else if (strlen (Filename) != ACPI_NAME_SIZE)
1229 return (AE_BAD_SIGNATURE);
1231 else
1233 *Instance = 0;
1236 /* Extract signature */
1238 ACPI_MOVE_NAME (Signature, Filename);
1239 return (AE_OK);
1243 /******************************************************************************
1245 * FUNCTION: OslReadTableFromFile
1247 * PARAMETERS: Filename - File that contains the desired table
1248 * FileOffset - Offset of the table in file
1249 * Signature - Optional ACPI Signature for desired table.
1250 * A null terminated 4-character string.
1251 * Table - Where a pointer to the table is returned
1253 * RETURN: Status; Table buffer is returned if AE_OK.
1255 * DESCRIPTION: Read a ACPI table from a file.
1257 *****************************************************************************/
1259 static ACPI_STATUS
1260 OslReadTableFromFile (
1261 char *Filename,
1262 ACPI_SIZE FileOffset,
1263 char *Signature,
1264 ACPI_TABLE_HEADER **Table)
1266 FILE *TableFile;
1267 ACPI_TABLE_HEADER Header;
1268 ACPI_TABLE_HEADER *LocalTable = NULL;
1269 UINT32 TableLength;
1270 INT32 Count;
1271 UINT32 Total = 0;
1272 ACPI_STATUS Status = AE_OK;
1275 /* Open the file */
1277 TableFile = fopen (Filename, "rb");
1278 if (TableFile == NULL)
1280 fprintf (stderr, "Could not open table file: %s\n", Filename);
1281 return (OslGetLastStatus (AE_NOT_FOUND));
1284 fseek (TableFile, FileOffset, SEEK_SET);
1286 /* Read the Table header to get the table length */
1288 Count = fread (&Header, 1, sizeof (ACPI_TABLE_HEADER), TableFile);
1289 if (Count != sizeof (ACPI_TABLE_HEADER))
1291 fprintf (stderr, "Could not read table header: %s\n", Filename);
1292 Status = AE_BAD_HEADER;
1293 goto ErrorExit;
1296 /* If signature is specified, it must match the table */
1298 if (Signature &&
1299 !ACPI_COMPARE_NAME (Signature, Header.Signature))
1301 fprintf (stderr, "Incorrect signature: Expecting %4.4s, found %4.4s\n",
1302 Signature, Header.Signature);
1303 Status = AE_BAD_SIGNATURE;
1304 goto ErrorExit;
1307 TableLength = ApGetTableLength (&Header);
1308 if (TableLength == 0)
1310 Status = AE_BAD_HEADER;
1311 goto ErrorExit;
1314 /* Read the entire table into a local buffer */
1316 LocalTable = calloc (1, TableLength);
1317 if (!LocalTable)
1319 fprintf (stderr,
1320 "%4.4s: Could not allocate buffer for table of length %X\n",
1321 Header.Signature, TableLength);
1322 Status = AE_NO_MEMORY;
1323 goto ErrorExit;
1326 fseek (TableFile, FileOffset, SEEK_SET);
1328 while (!feof (TableFile) && Total < TableLength)
1330 Count = fread (LocalTable, 1, TableLength-Total, TableFile);
1331 if (Count < 0)
1333 fprintf (stderr, "%4.4s: Could not read table content\n",
1334 Header.Signature);
1335 Status = AE_INVALID_TABLE_LENGTH;
1336 goto ErrorExit;
1339 Total += Count;
1342 /* Validate checksum */
1344 (void) ApIsValidChecksum (LocalTable);
1346 ErrorExit:
1347 fclose (TableFile);
1348 *Table = LocalTable;
1349 return (Status);
1353 /******************************************************************************
1355 * FUNCTION: OslGetCustomizedTable
1357 * PARAMETERS: Pathname - Directory to find Linux customized table
1358 * Signature - ACPI Signature for desired table. Must be
1359 * a null terminated 4-character string.
1360 * Instance - Multiple table support for SSDT/UEFI (0...n)
1361 * Must be 0 for other tables.
1362 * Table - Where a pointer to the table is returned
1363 * Address - Where the table physical address is returned
1365 * RETURN: Status; Table buffer is returned if AE_OK.
1366 * AE_LIMIT: Instance is beyond valid limit
1367 * AE_NOT_FOUND: A table with the signature was not found
1369 * DESCRIPTION: Get an OS customized table.
1371 *****************************************************************************/
1373 static ACPI_STATUS
1374 OslGetCustomizedTable (
1375 char *Pathname,
1376 char *Signature,
1377 UINT32 Instance,
1378 ACPI_TABLE_HEADER **Table,
1379 ACPI_PHYSICAL_ADDRESS *Address)
1381 void *TableDir;
1382 UINT32 CurrentInstance = 0;
1383 char TempName[ACPI_NAME_SIZE];
1384 char TableFilename[PATH_MAX];
1385 char *Filename;
1386 ACPI_STATUS Status;
1389 /* Open the directory for customized tables */
1391 TableDir = AcpiOsOpenDirectory (Pathname, "*", REQUEST_FILE_ONLY);
1392 if (!TableDir)
1394 return (OslGetLastStatus (AE_NOT_FOUND));
1397 /* Attempt to find the table in the directory */
1399 while ((Filename = AcpiOsGetNextFilename (TableDir)))
1401 /* Ignore meaningless files */
1403 if (!ACPI_COMPARE_NAME (Filename, Signature))
1405 continue;
1408 /* Extract table name and instance number */
1410 Status = OslTableNameFromFile (Filename, TempName, &CurrentInstance);
1412 /* Ignore meaningless files */
1414 if (ACPI_FAILURE (Status) || CurrentInstance != Instance)
1416 continue;
1419 /* Create the table pathname */
1421 if (Instance != 0)
1423 sprintf (TableFilename, "%s/%4.4s%d", Pathname, TempName, Instance);
1425 else
1427 sprintf (TableFilename, "%s/%4.4s", Pathname, TempName);
1429 break;
1432 AcpiOsCloseDirectory (TableDir);
1434 if (!Filename)
1436 return (AE_LIMIT);
1439 /* There is no physical address saved for customized tables, use zero */
1441 *Address = 0;
1442 Status = OslReadTableFromFile (TableFilename, 0, NULL, Table);
1444 return (Status);