xref: /netbsd-src/sys/external/bsd/acpica/dist/os_specific/service_layers/oslinuxtbl.c (revision 2c7d7e3ca2e4f0b675c6c58e614f6aede66c678e)
1ff4a156dSchristos /******************************************************************************
2ff4a156dSchristos  *
3ff4a156dSchristos  * Module Name: oslinuxtbl - Linux OSL for obtaining ACPI tables
4ff4a156dSchristos  *
5ff4a156dSchristos  *****************************************************************************/
6ff4a156dSchristos 
7ff4a156dSchristos /*
8*2c7d7e3cSchristos  * Copyright (C) 2000 - 2023, Intel Corp.
9ff4a156dSchristos  * All rights reserved.
10ff4a156dSchristos  *
11ff4a156dSchristos  * Redistribution and use in source and binary forms, with or without
12ff4a156dSchristos  * modification, are permitted provided that the following conditions
13ff4a156dSchristos  * are met:
14ff4a156dSchristos  * 1. Redistributions of source code must retain the above copyright
15ff4a156dSchristos  *    notice, this list of conditions, and the following disclaimer,
16ff4a156dSchristos  *    without modification.
17ff4a156dSchristos  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18ff4a156dSchristos  *    substantially similar to the "NO WARRANTY" disclaimer below
19ff4a156dSchristos  *    ("Disclaimer") and any redistribution must be conditioned upon
20ff4a156dSchristos  *    including a substantially similar Disclaimer requirement for further
21ff4a156dSchristos  *    binary redistribution.
22ff4a156dSchristos  * 3. Neither the names of the above-listed copyright holders nor the names
23ff4a156dSchristos  *    of any contributors may be used to endorse or promote products derived
24ff4a156dSchristos  *    from this software without specific prior written permission.
25ff4a156dSchristos  *
26ff4a156dSchristos  * Alternatively, this software may be distributed under the terms of the
27ff4a156dSchristos  * GNU General Public License ("GPL") version 2 as published by the Free
28ff4a156dSchristos  * Software Foundation.
29ff4a156dSchristos  *
30ff4a156dSchristos  * NO WARRANTY
31ff4a156dSchristos  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32ff4a156dSchristos  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
3398244dcfSchristos  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
34ff4a156dSchristos  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35ff4a156dSchristos  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36ff4a156dSchristos  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37ff4a156dSchristos  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38ff4a156dSchristos  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39ff4a156dSchristos  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40ff4a156dSchristos  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41ff4a156dSchristos  * POSSIBILITY OF SUCH DAMAGES.
42ff4a156dSchristos  */
43ff4a156dSchristos 
44ff4a156dSchristos #include "acpidump.h"
45ff4a156dSchristos 
46ff4a156dSchristos 
47ff4a156dSchristos #define _COMPONENT          ACPI_OS_SERVICES
48ff4a156dSchristos         ACPI_MODULE_NAME    ("oslinuxtbl")
49ff4a156dSchristos 
50ff4a156dSchristos 
51ff4a156dSchristos #ifndef PATH_MAX
52ff4a156dSchristos #define PATH_MAX 256
53ff4a156dSchristos #endif
54ff4a156dSchristos 
55ff4a156dSchristos 
56ff4a156dSchristos /* List of information about obtained ACPI tables */
57ff4a156dSchristos 
58414ef032Schristos typedef struct osl_table_info
59ff4a156dSchristos {
60414ef032Schristos     struct osl_table_info   *Next;
61ff4a156dSchristos     UINT32                  Instance;
625b948c02Schristos     char                    Signature[ACPI_NAMESEG_SIZE];
63ff4a156dSchristos 
64ff4a156dSchristos } OSL_TABLE_INFO;
65ff4a156dSchristos 
66ff4a156dSchristos /* Local prototypes */
67ff4a156dSchristos 
68ff4a156dSchristos static ACPI_STATUS
69ff4a156dSchristos OslTableInitialize (
70ff4a156dSchristos     void);
71ff4a156dSchristos 
72ff4a156dSchristos static ACPI_STATUS
73ff4a156dSchristos OslTableNameFromFile (
74ff4a156dSchristos     char                    *Filename,
75ff4a156dSchristos     char                    *Signature,
76ff4a156dSchristos     UINT32                  *Instance);
77ff4a156dSchristos 
78ff4a156dSchristos static ACPI_STATUS
79ff4a156dSchristos OslAddTableToList (
80ff4a156dSchristos     char                    *Signature,
81ff4a156dSchristos     UINT32                  Instance);
82ff4a156dSchristos 
83ff4a156dSchristos static ACPI_STATUS
84ff4a156dSchristos OslReadTableFromFile (
85ff4a156dSchristos     char                    *Filename,
86ff4a156dSchristos     ACPI_SIZE               FileOffset,
87ff4a156dSchristos     ACPI_TABLE_HEADER       **Table);
88ff4a156dSchristos 
89ff4a156dSchristos static ACPI_STATUS
90ff4a156dSchristos OslMapTable (
91ff4a156dSchristos     ACPI_SIZE               Address,
92ff4a156dSchristos     char                    *Signature,
93ff4a156dSchristos     ACPI_TABLE_HEADER       **Table);
94ff4a156dSchristos 
95ff4a156dSchristos static void
96ff4a156dSchristos OslUnmapTable (
97ff4a156dSchristos     ACPI_TABLE_HEADER       *Table);
98ff4a156dSchristos 
99ff4a156dSchristos static ACPI_PHYSICAL_ADDRESS
100414ef032Schristos OslFindRsdpViaEfiByKeyword (
101414ef032Schristos     FILE                    *File,
102414ef032Schristos     const char              *Keyword);
103414ef032Schristos 
104414ef032Schristos static ACPI_PHYSICAL_ADDRESS
105ff4a156dSchristos OslFindRsdpViaEfi (
106ff4a156dSchristos     void);
107ff4a156dSchristos 
108ff4a156dSchristos static ACPI_STATUS
109ff4a156dSchristos OslLoadRsdp (
110ff4a156dSchristos     void);
111ff4a156dSchristos 
112ff4a156dSchristos static ACPI_STATUS
113ff4a156dSchristos OslListCustomizedTables (
114ff4a156dSchristos     char                    *Directory);
115ff4a156dSchristos 
116ff4a156dSchristos static ACPI_STATUS
117ff4a156dSchristos OslGetCustomizedTable (
118ff4a156dSchristos     char                    *Pathname,
119ff4a156dSchristos     char                    *Signature,
120ff4a156dSchristos     UINT32                  Instance,
121ff4a156dSchristos     ACPI_TABLE_HEADER       **Table,
122ff4a156dSchristos     ACPI_PHYSICAL_ADDRESS   *Address);
123ff4a156dSchristos 
124ff4a156dSchristos static ACPI_STATUS
125ff4a156dSchristos OslListBiosTables (
126ff4a156dSchristos     void);
127ff4a156dSchristos 
128ff4a156dSchristos static ACPI_STATUS
129ff4a156dSchristos OslGetBiosTable (
130ff4a156dSchristos     char                    *Signature,
131ff4a156dSchristos     UINT32                  Instance,
132ff4a156dSchristos     ACPI_TABLE_HEADER       **Table,
133ff4a156dSchristos     ACPI_PHYSICAL_ADDRESS   *Address);
134ff4a156dSchristos 
135ff4a156dSchristos static ACPI_STATUS
136ff4a156dSchristos OslGetLastStatus (
137ff4a156dSchristos     ACPI_STATUS             DefaultStatus);
138ff4a156dSchristos 
139ff4a156dSchristos 
140ff4a156dSchristos /* File locations */
141ff4a156dSchristos 
142ff4a156dSchristos #define DYNAMIC_TABLE_DIR   "/sys/firmware/acpi/tables/dynamic"
143ff4a156dSchristos #define STATIC_TABLE_DIR    "/sys/firmware/acpi/tables"
144ff4a156dSchristos #define EFI_SYSTAB          "/sys/firmware/efi/systab"
145ff4a156dSchristos 
146ff4a156dSchristos /* Should we get dynamically loaded SSDTs from DYNAMIC_TABLE_DIR? */
147ff4a156dSchristos 
148ff4a156dSchristos UINT8                   Gbl_DumpDynamicTables = TRUE;
149ff4a156dSchristos 
150ff4a156dSchristos /* Initialization flags */
151ff4a156dSchristos 
152ff4a156dSchristos UINT8                   Gbl_TableListInitialized = FALSE;
153ff4a156dSchristos 
154ff4a156dSchristos /* Local copies of main ACPI tables */
155ff4a156dSchristos 
156ff4a156dSchristos ACPI_TABLE_RSDP         Gbl_Rsdp;
157ff4a156dSchristos ACPI_TABLE_FADT         *Gbl_Fadt = NULL;
158ff4a156dSchristos ACPI_TABLE_RSDT         *Gbl_Rsdt = NULL;
159ff4a156dSchristos ACPI_TABLE_XSDT         *Gbl_Xsdt = NULL;
160ff4a156dSchristos 
161ff4a156dSchristos /* Table addresses */
162ff4a156dSchristos 
163ff4a156dSchristos ACPI_PHYSICAL_ADDRESS   Gbl_FadtAddress = 0;
164ff4a156dSchristos ACPI_PHYSICAL_ADDRESS   Gbl_RsdpAddress = 0;
165ff4a156dSchristos 
166ff4a156dSchristos /* Revision of RSD PTR */
167ff4a156dSchristos 
168ff4a156dSchristos UINT8                   Gbl_Revision = 0;
169ff4a156dSchristos 
170ff4a156dSchristos OSL_TABLE_INFO          *Gbl_TableListHead = NULL;
171ff4a156dSchristos UINT32                  Gbl_TableCount = 0;
172ff4a156dSchristos 
173ff4a156dSchristos 
174ff4a156dSchristos /******************************************************************************
175ff4a156dSchristos  *
176ff4a156dSchristos  * FUNCTION:    OslGetLastStatus
177ff4a156dSchristos  *
178ff4a156dSchristos  * PARAMETERS:  DefaultStatus   - Default error status to return
179ff4a156dSchristos  *
180ff4a156dSchristos  * RETURN:      Status; Converted from errno.
181ff4a156dSchristos  *
182b558e860Schristos  * DESCRIPTION: Get last errno and convert it to ACPI_STATUS.
183ff4a156dSchristos  *
184ff4a156dSchristos  *****************************************************************************/
185ff4a156dSchristos 
186ff4a156dSchristos static ACPI_STATUS
OslGetLastStatus(ACPI_STATUS DefaultStatus)187ff4a156dSchristos OslGetLastStatus (
188ff4a156dSchristos     ACPI_STATUS             DefaultStatus)
189ff4a156dSchristos {
190ff4a156dSchristos 
191ff4a156dSchristos     switch (errno)
192ff4a156dSchristos     {
193ff4a156dSchristos     case EACCES:
194ff4a156dSchristos     case EPERM:
195ff4a156dSchristos 
196ff4a156dSchristos         return (AE_ACCESS);
197ff4a156dSchristos 
198ff4a156dSchristos     case ENOENT:
199ff4a156dSchristos 
200ff4a156dSchristos         return (AE_NOT_FOUND);
201ff4a156dSchristos 
202ff4a156dSchristos     case ENOMEM:
203ff4a156dSchristos 
204ff4a156dSchristos         return (AE_NO_MEMORY);
205ff4a156dSchristos 
206ff4a156dSchristos     default:
207ff4a156dSchristos 
208ff4a156dSchristos         return (DefaultStatus);
209ff4a156dSchristos     }
210ff4a156dSchristos }
211ff4a156dSchristos 
212ff4a156dSchristos 
213ff4a156dSchristos /******************************************************************************
214ff4a156dSchristos  *
215ff4a156dSchristos  * FUNCTION:    AcpiOsGetTableByAddress
216ff4a156dSchristos  *
217ff4a156dSchristos  * PARAMETERS:  Address         - Physical address of the ACPI table
218ff4a156dSchristos  *              Table           - Where a pointer to the table is returned
219ff4a156dSchristos  *
220ff4a156dSchristos  * RETURN:      Status; Table buffer is returned if AE_OK.
221ff4a156dSchristos  *              AE_NOT_FOUND: A valid table was not found at the address
222ff4a156dSchristos  *
223ff4a156dSchristos  * DESCRIPTION: Get an ACPI table via a physical memory address.
224ff4a156dSchristos  *
225ff4a156dSchristos  *****************************************************************************/
226ff4a156dSchristos 
227ff4a156dSchristos ACPI_STATUS
AcpiOsGetTableByAddress(ACPI_PHYSICAL_ADDRESS Address,ACPI_TABLE_HEADER ** Table)228ff4a156dSchristos AcpiOsGetTableByAddress (
229ff4a156dSchristos     ACPI_PHYSICAL_ADDRESS   Address,
230ff4a156dSchristos     ACPI_TABLE_HEADER       **Table)
231ff4a156dSchristos {
232ff4a156dSchristos     UINT32                  TableLength;
233ff4a156dSchristos     ACPI_TABLE_HEADER       *MappedTable;
234ff4a156dSchristos     ACPI_TABLE_HEADER       *LocalTable = NULL;
235ff4a156dSchristos     ACPI_STATUS             Status = AE_OK;
236ff4a156dSchristos 
237ff4a156dSchristos 
238ff4a156dSchristos     /* Get main ACPI tables from memory on first invocation of this function */
239ff4a156dSchristos 
240ff4a156dSchristos     Status = OslTableInitialize ();
241ff4a156dSchristos     if (ACPI_FAILURE (Status))
242ff4a156dSchristos     {
243ff4a156dSchristos         return (Status);
244ff4a156dSchristos     }
245ff4a156dSchristos 
246ff4a156dSchristos     /* Map the table and validate it */
247ff4a156dSchristos 
248ff4a156dSchristos     Status = OslMapTable (Address, NULL, &MappedTable);
249ff4a156dSchristos     if (ACPI_FAILURE (Status))
250ff4a156dSchristos     {
251ff4a156dSchristos         return (Status);
252ff4a156dSchristos     }
253ff4a156dSchristos 
254ff4a156dSchristos     /* Copy table to local buffer and return it */
255ff4a156dSchristos 
256ff4a156dSchristos     TableLength = ApGetTableLength (MappedTable);
257ff4a156dSchristos     if (TableLength == 0)
258ff4a156dSchristos     {
259ff4a156dSchristos         Status = AE_BAD_HEADER;
260414ef032Schristos         goto Exit;
261ff4a156dSchristos     }
262ff4a156dSchristos 
263ff4a156dSchristos     LocalTable = calloc (1, TableLength);
264ff4a156dSchristos     if (!LocalTable)
265ff4a156dSchristos     {
266ff4a156dSchristos         Status = AE_NO_MEMORY;
267414ef032Schristos         goto Exit;
268ff4a156dSchristos     }
269ff4a156dSchristos 
2709b9ee194Schristos     memcpy (LocalTable, MappedTable, TableLength);
271ff4a156dSchristos 
272414ef032Schristos Exit:
273ff4a156dSchristos     OslUnmapTable (MappedTable);
274ff4a156dSchristos     *Table = LocalTable;
275414ef032Schristos     return (Status);
276ff4a156dSchristos }
277ff4a156dSchristos 
278ff4a156dSchristos 
279ff4a156dSchristos /******************************************************************************
280ff4a156dSchristos  *
281ff4a156dSchristos  * FUNCTION:    AcpiOsGetTableByName
282ff4a156dSchristos  *
283ff4a156dSchristos  * PARAMETERS:  Signature       - ACPI Signature for desired table. Must be
284ff4a156dSchristos  *                                a null terminated 4-character string.
285ff4a156dSchristos  *              Instance        - Multiple table support for SSDT/UEFI (0...n)
286ff4a156dSchristos  *                                Must be 0 for other tables.
287ff4a156dSchristos  *              Table           - Where a pointer to the table is returned
288ff4a156dSchristos  *              Address         - Where the table physical address is returned
289ff4a156dSchristos  *
290ff4a156dSchristos  * RETURN:      Status; Table buffer and physical address returned if AE_OK.
291ff4a156dSchristos  *              AE_LIMIT: Instance is beyond valid limit
292ff4a156dSchristos  *              AE_NOT_FOUND: A table with the signature was not found
293ff4a156dSchristos  *
294ff4a156dSchristos  * NOTE:        Assumes the input signature is uppercase.
295ff4a156dSchristos  *
296ff4a156dSchristos  *****************************************************************************/
297ff4a156dSchristos 
298ff4a156dSchristos ACPI_STATUS
AcpiOsGetTableByName(char * Signature,UINT32 Instance,ACPI_TABLE_HEADER ** Table,ACPI_PHYSICAL_ADDRESS * Address)299ff4a156dSchristos AcpiOsGetTableByName (
300ff4a156dSchristos     char                    *Signature,
301ff4a156dSchristos     UINT32                  Instance,
302ff4a156dSchristos     ACPI_TABLE_HEADER       **Table,
303ff4a156dSchristos     ACPI_PHYSICAL_ADDRESS   *Address)
304ff4a156dSchristos {
305ff4a156dSchristos     ACPI_STATUS             Status;
306ff4a156dSchristos 
307ff4a156dSchristos 
308ff4a156dSchristos     /* Get main ACPI tables from memory on first invocation of this function */
309ff4a156dSchristos 
310ff4a156dSchristos     Status = OslTableInitialize ();
311ff4a156dSchristos     if (ACPI_FAILURE (Status))
312ff4a156dSchristos     {
313ff4a156dSchristos         return (Status);
314ff4a156dSchristos     }
315ff4a156dSchristos 
316ff4a156dSchristos     /* Not a main ACPI table, attempt to extract it from the RSDT/XSDT */
317ff4a156dSchristos 
318ff4a156dSchristos     if (!Gbl_DumpCustomizedTables)
319ff4a156dSchristos     {
320ff4a156dSchristos         /* Attempt to get the table from the memory */
321ff4a156dSchristos 
322ff4a156dSchristos         Status = OslGetBiosTable (Signature, Instance, Table, Address);
323ff4a156dSchristos     }
324ff4a156dSchristos     else
325ff4a156dSchristos     {
326ff4a156dSchristos         /* Attempt to get the table from the static directory */
327ff4a156dSchristos 
328ff4a156dSchristos         Status = OslGetCustomizedTable (STATIC_TABLE_DIR, Signature,
329ff4a156dSchristos             Instance, Table, Address);
330ff4a156dSchristos     }
331ff4a156dSchristos 
332ff4a156dSchristos     if (ACPI_FAILURE (Status) && Status == AE_LIMIT)
333ff4a156dSchristos     {
334ff4a156dSchristos         if (Gbl_DumpDynamicTables)
335ff4a156dSchristos         {
336ff4a156dSchristos             /* Attempt to get a dynamic table */
337ff4a156dSchristos 
338ff4a156dSchristos             Status = OslGetCustomizedTable (DYNAMIC_TABLE_DIR, Signature,
339ff4a156dSchristos                 Instance, Table, Address);
340ff4a156dSchristos         }
341ff4a156dSchristos     }
342ff4a156dSchristos 
343ff4a156dSchristos     return (Status);
344ff4a156dSchristos }
345ff4a156dSchristos 
346ff4a156dSchristos 
347ff4a156dSchristos /******************************************************************************
348ff4a156dSchristos  *
349ff4a156dSchristos  * FUNCTION:    OslAddTableToList
350ff4a156dSchristos  *
351ff4a156dSchristos  * PARAMETERS:  Signature       - Table signature
352ff4a156dSchristos  *              Instance        - Table instance
353ff4a156dSchristos  *
354ff4a156dSchristos  * RETURN:      Status; Successfully added if AE_OK.
355ff4a156dSchristos  *              AE_NO_MEMORY: Memory allocation error
356ff4a156dSchristos  *
357ff4a156dSchristos  * DESCRIPTION: Insert a table structure into OSL table list.
358ff4a156dSchristos  *
359ff4a156dSchristos  *****************************************************************************/
360ff4a156dSchristos 
361ff4a156dSchristos static ACPI_STATUS
OslAddTableToList(char * Signature,UINT32 Instance)362ff4a156dSchristos OslAddTableToList (
363ff4a156dSchristos     char                    *Signature,
364ff4a156dSchristos     UINT32                  Instance)
365ff4a156dSchristos {
366ff4a156dSchristos     OSL_TABLE_INFO          *NewInfo;
367ff4a156dSchristos     OSL_TABLE_INFO          *Next;
368ff4a156dSchristos     UINT32                  NextInstance = 0;
369ff4a156dSchristos     BOOLEAN                 Found = FALSE;
370ff4a156dSchristos 
371ff4a156dSchristos 
372ff4a156dSchristos     NewInfo = calloc (1, sizeof (OSL_TABLE_INFO));
373ff4a156dSchristos     if (!NewInfo)
374ff4a156dSchristos     {
375ff4a156dSchristos         return (AE_NO_MEMORY);
376ff4a156dSchristos     }
377ff4a156dSchristos 
3785b948c02Schristos     ACPI_COPY_NAMESEG (NewInfo->Signature, Signature);
379ff4a156dSchristos 
380ff4a156dSchristos     if (!Gbl_TableListHead)
381ff4a156dSchristos     {
382ff4a156dSchristos         Gbl_TableListHead = NewInfo;
383ff4a156dSchristos     }
384ff4a156dSchristos     else
385ff4a156dSchristos     {
386ff4a156dSchristos         Next = Gbl_TableListHead;
387ff4a156dSchristos         while (1)
388ff4a156dSchristos         {
3895b948c02Schristos             if (ACPI_COMPARE_NAMESEG (Next->Signature, Signature))
390ff4a156dSchristos             {
391ff4a156dSchristos                 if (Next->Instance == Instance)
392ff4a156dSchristos                 {
393ff4a156dSchristos                     Found = TRUE;
394ff4a156dSchristos                 }
395ff4a156dSchristos                 if (Next->Instance >= NextInstance)
396ff4a156dSchristos                 {
397ff4a156dSchristos                     NextInstance = Next->Instance + 1;
398ff4a156dSchristos                 }
399ff4a156dSchristos             }
400ff4a156dSchristos 
401ff4a156dSchristos             if (!Next->Next)
402ff4a156dSchristos             {
403ff4a156dSchristos                 break;
404ff4a156dSchristos             }
405ff4a156dSchristos             Next = Next->Next;
406ff4a156dSchristos         }
407ff4a156dSchristos         Next->Next = NewInfo;
408ff4a156dSchristos     }
409ff4a156dSchristos 
410ff4a156dSchristos     if (Found)
411ff4a156dSchristos     {
412ff4a156dSchristos         if (Instance)
413ff4a156dSchristos         {
414ff4a156dSchristos             fprintf (stderr,
415ff4a156dSchristos                 "%4.4s: Warning unmatched table instance %d, expected %d\n",
416ff4a156dSchristos                 Signature, Instance, NextInstance);
417ff4a156dSchristos         }
418ff4a156dSchristos         Instance = NextInstance;
419ff4a156dSchristos     }
420ff4a156dSchristos 
421ff4a156dSchristos     NewInfo->Instance = Instance;
422ff4a156dSchristos     Gbl_TableCount++;
423ff4a156dSchristos 
424ff4a156dSchristos     return (AE_OK);
425ff4a156dSchristos }
426ff4a156dSchristos 
427ff4a156dSchristos 
428ff4a156dSchristos /******************************************************************************
429ff4a156dSchristos  *
430ff4a156dSchristos  * FUNCTION:    AcpiOsGetTableByIndex
431ff4a156dSchristos  *
432ff4a156dSchristos  * PARAMETERS:  Index           - Which table to get
433ff4a156dSchristos  *              Table           - Where a pointer to the table is returned
434ff4a156dSchristos  *              Instance        - Where a pointer to the table instance no. is
435ff4a156dSchristos  *                                returned
436ff4a156dSchristos  *              Address         - Where the table physical address is returned
437ff4a156dSchristos  *
438ff4a156dSchristos  * RETURN:      Status; Table buffer and physical address returned if AE_OK.
439ff4a156dSchristos  *              AE_LIMIT: Index is beyond valid limit
440ff4a156dSchristos  *
441ff4a156dSchristos  * DESCRIPTION: Get an ACPI table via an index value (0 through n). Returns
442ff4a156dSchristos  *              AE_LIMIT when an invalid index is reached. Index is not
443ff4a156dSchristos  *              necessarily an index into the RSDT/XSDT.
444ff4a156dSchristos  *
445ff4a156dSchristos  *****************************************************************************/
446ff4a156dSchristos 
447ff4a156dSchristos ACPI_STATUS
AcpiOsGetTableByIndex(UINT32 Index,ACPI_TABLE_HEADER ** Table,UINT32 * Instance,ACPI_PHYSICAL_ADDRESS * Address)448ff4a156dSchristos AcpiOsGetTableByIndex (
449ff4a156dSchristos     UINT32                  Index,
450ff4a156dSchristos     ACPI_TABLE_HEADER       **Table,
451ff4a156dSchristos     UINT32                  *Instance,
452ff4a156dSchristos     ACPI_PHYSICAL_ADDRESS   *Address)
453ff4a156dSchristos {
454ff4a156dSchristos     OSL_TABLE_INFO          *Info;
455ff4a156dSchristos     ACPI_STATUS             Status;
456ff4a156dSchristos     UINT32                  i;
457ff4a156dSchristos 
458ff4a156dSchristos 
459ff4a156dSchristos     /* Get main ACPI tables from memory on first invocation of this function */
460ff4a156dSchristos 
461ff4a156dSchristos     Status = OslTableInitialize ();
462ff4a156dSchristos     if (ACPI_FAILURE (Status))
463ff4a156dSchristos     {
464ff4a156dSchristos         return (Status);
465ff4a156dSchristos     }
466ff4a156dSchristos 
467ff4a156dSchristos     /* Validate Index */
468ff4a156dSchristos 
469ff4a156dSchristos     if (Index >= Gbl_TableCount)
470ff4a156dSchristos     {
471ff4a156dSchristos         return (AE_LIMIT);
472ff4a156dSchristos     }
473ff4a156dSchristos 
474ff4a156dSchristos     /* Point to the table list entry specified by the Index argument */
475ff4a156dSchristos 
476ff4a156dSchristos     Info = Gbl_TableListHead;
477ff4a156dSchristos     for (i = 0; i < Index; i++)
478ff4a156dSchristos     {
479ff4a156dSchristos         Info = Info->Next;
480ff4a156dSchristos     }
481ff4a156dSchristos 
482ff4a156dSchristos     /* Now we can just get the table via the signature */
483ff4a156dSchristos 
484ff4a156dSchristos     Status = AcpiOsGetTableByName (Info->Signature, Info->Instance,
485ff4a156dSchristos         Table, Address);
486ff4a156dSchristos 
487ff4a156dSchristos     if (ACPI_SUCCESS (Status))
488ff4a156dSchristos     {
489ff4a156dSchristos         *Instance = Info->Instance;
490ff4a156dSchristos     }
491ff4a156dSchristos     return (Status);
492ff4a156dSchristos }
493ff4a156dSchristos 
494ff4a156dSchristos 
495ff4a156dSchristos /******************************************************************************
496ff4a156dSchristos  *
497414ef032Schristos  * FUNCTION:    OslFindRsdpViaEfiByKeyword
498414ef032Schristos  *
499414ef032Schristos  * PARAMETERS:  Keyword         - Character string indicating ACPI GUID version
500414ef032Schristos  *                                in the EFI table
501414ef032Schristos  *
502414ef032Schristos  * RETURN:      RSDP address if found
503414ef032Schristos  *
504414ef032Schristos  * DESCRIPTION: Find RSDP address via EFI using keyword indicating the ACPI
505414ef032Schristos  *              GUID version.
506414ef032Schristos  *
507414ef032Schristos  *****************************************************************************/
508414ef032Schristos 
509414ef032Schristos static ACPI_PHYSICAL_ADDRESS
OslFindRsdpViaEfiByKeyword(FILE * File,const char * Keyword)510414ef032Schristos OslFindRsdpViaEfiByKeyword (
511414ef032Schristos     FILE                    *File,
512414ef032Schristos     const char              *Keyword)
513414ef032Schristos {
514414ef032Schristos     char                    Buffer[80];
515414ef032Schristos     unsigned long long      Address = 0;
516414ef032Schristos     char                    Format[32];
517414ef032Schristos 
518414ef032Schristos 
519414ef032Schristos     snprintf (Format, 32, "%s=%s", Keyword, "%llx");
520414ef032Schristos     fseek (File, 0, SEEK_SET);
521414ef032Schristos     while (fgets (Buffer, 80, File))
522414ef032Schristos     {
523414ef032Schristos         if (sscanf (Buffer, Format, &Address) == 1)
524414ef032Schristos         {
525414ef032Schristos             break;
526414ef032Schristos         }
527414ef032Schristos     }
528414ef032Schristos 
529414ef032Schristos     return ((ACPI_PHYSICAL_ADDRESS) (Address));
530414ef032Schristos }
531414ef032Schristos 
532414ef032Schristos 
533414ef032Schristos /******************************************************************************
534414ef032Schristos  *
535ff4a156dSchristos  * FUNCTION:    OslFindRsdpViaEfi
536ff4a156dSchristos  *
537ff4a156dSchristos  * PARAMETERS:  None
538ff4a156dSchristos  *
539ff4a156dSchristos  * RETURN:      RSDP address if found
540ff4a156dSchristos  *
541ff4a156dSchristos  * DESCRIPTION: Find RSDP address via EFI.
542ff4a156dSchristos  *
543ff4a156dSchristos  *****************************************************************************/
544ff4a156dSchristos 
545ff4a156dSchristos static ACPI_PHYSICAL_ADDRESS
OslFindRsdpViaEfi(void)546ff4a156dSchristos OslFindRsdpViaEfi (
547ff4a156dSchristos     void)
548ff4a156dSchristos {
549ff4a156dSchristos     FILE                    *File;
550414ef032Schristos     ACPI_PHYSICAL_ADDRESS   Address = 0;
551ff4a156dSchristos 
552ff4a156dSchristos 
553ff4a156dSchristos     File = fopen (EFI_SYSTAB, "r");
554ff4a156dSchristos     if (File)
555ff4a156dSchristos     {
556414ef032Schristos         Address = OslFindRsdpViaEfiByKeyword (File, "ACPI20");
557414ef032Schristos         if (!Address)
558ff4a156dSchristos         {
559414ef032Schristos             Address = OslFindRsdpViaEfiByKeyword (File, "ACPI");
560ff4a156dSchristos         }
561ff4a156dSchristos         fclose (File);
562ff4a156dSchristos     }
563ff4a156dSchristos 
564414ef032Schristos     return (Address);
565ff4a156dSchristos }
566ff4a156dSchristos 
567ff4a156dSchristos 
568ff4a156dSchristos /******************************************************************************
569ff4a156dSchristos  *
570ff4a156dSchristos  * FUNCTION:    OslLoadRsdp
571ff4a156dSchristos  *
572ff4a156dSchristos  * PARAMETERS:  None
573ff4a156dSchristos  *
574ff4a156dSchristos  * RETURN:      Status
575ff4a156dSchristos  *
576ff4a156dSchristos  * DESCRIPTION: Scan and load RSDP.
577ff4a156dSchristos  *
578ff4a156dSchristos  *****************************************************************************/
579ff4a156dSchristos 
580ff4a156dSchristos static ACPI_STATUS
OslLoadRsdp(void)581ff4a156dSchristos OslLoadRsdp (
582ff4a156dSchristos     void)
583ff4a156dSchristos {
584ff4a156dSchristos     ACPI_TABLE_HEADER       *MappedTable;
585ff4a156dSchristos     UINT8                   *RsdpAddress;
586ff4a156dSchristos     ACPI_PHYSICAL_ADDRESS   RsdpBase;
587ff4a156dSchristos     ACPI_SIZE               RsdpSize;
588ff4a156dSchristos 
589ff4a156dSchristos 
590ff4a156dSchristos     /* Get RSDP from memory */
591ff4a156dSchristos 
592ff4a156dSchristos     RsdpSize = sizeof (ACPI_TABLE_RSDP);
593ff4a156dSchristos     if (Gbl_RsdpBase)
594ff4a156dSchristos     {
595ff4a156dSchristos         RsdpBase = Gbl_RsdpBase;
596ff4a156dSchristos     }
597ff4a156dSchristos     else
598ff4a156dSchristos     {
599ff4a156dSchristos         RsdpBase = OslFindRsdpViaEfi ();
600ff4a156dSchristos     }
601ff4a156dSchristos 
602ff4a156dSchristos     if (!RsdpBase)
603ff4a156dSchristos     {
604ff4a156dSchristos         RsdpBase = ACPI_HI_RSDP_WINDOW_BASE;
605ff4a156dSchristos         RsdpSize = ACPI_HI_RSDP_WINDOW_SIZE;
606ff4a156dSchristos     }
607ff4a156dSchristos 
608ff4a156dSchristos     RsdpAddress = AcpiOsMapMemory (RsdpBase, RsdpSize);
609ff4a156dSchristos     if (!RsdpAddress)
610ff4a156dSchristos     {
611ff4a156dSchristos         return (OslGetLastStatus (AE_BAD_ADDRESS));
612ff4a156dSchristos     }
613ff4a156dSchristos 
614ff4a156dSchristos     /* Search low memory for the RSDP */
615ff4a156dSchristos 
616ff4a156dSchristos     MappedTable = ACPI_CAST_PTR (ACPI_TABLE_HEADER,
617ff4a156dSchristos         AcpiTbScanMemoryForRsdp (RsdpAddress, RsdpSize));
618ff4a156dSchristos     if (!MappedTable)
619ff4a156dSchristos     {
620ff4a156dSchristos         AcpiOsUnmapMemory (RsdpAddress, RsdpSize);
621ff4a156dSchristos         return (AE_NOT_FOUND);
622ff4a156dSchristos     }
623ff4a156dSchristos 
624ff4a156dSchristos     Gbl_RsdpAddress = RsdpBase + (ACPI_CAST8 (MappedTable) - RsdpAddress);
625ff4a156dSchristos 
6269b9ee194Schristos     memcpy (&Gbl_Rsdp, MappedTable, sizeof (ACPI_TABLE_RSDP));
627ff4a156dSchristos     AcpiOsUnmapMemory (RsdpAddress, RsdpSize);
628ff4a156dSchristos 
629ff4a156dSchristos     return (AE_OK);
630ff4a156dSchristos }
631ff4a156dSchristos 
632ff4a156dSchristos 
633ff4a156dSchristos /******************************************************************************
634ff4a156dSchristos  *
635414ef032Schristos  * FUNCTION:    OslCanUseXsdt
636414ef032Schristos  *
637414ef032Schristos  * PARAMETERS:  None
638414ef032Schristos  *
639414ef032Schristos  * RETURN:      TRUE if XSDT is allowed to be used.
640414ef032Schristos  *
641414ef032Schristos  * DESCRIPTION: This function collects logic that can be used to determine if
642414ef032Schristos  *              XSDT should be used instead of RSDT.
643414ef032Schristos  *
644414ef032Schristos  *****************************************************************************/
645414ef032Schristos 
646414ef032Schristos static BOOLEAN
OslCanUseXsdt(void)647414ef032Schristos OslCanUseXsdt (
648414ef032Schristos     void)
649414ef032Schristos {
650414ef032Schristos     if (Gbl_Revision && !AcpiGbl_DoNotUseXsdt)
651414ef032Schristos     {
652414ef032Schristos         return (TRUE);
653414ef032Schristos     }
654414ef032Schristos     else
655414ef032Schristos     {
656414ef032Schristos         return (FALSE);
657414ef032Schristos     }
658414ef032Schristos }
659414ef032Schristos 
660414ef032Schristos 
661414ef032Schristos /******************************************************************************
662414ef032Schristos  *
663ff4a156dSchristos  * FUNCTION:    OslTableInitialize
664ff4a156dSchristos  *
665ff4a156dSchristos  * PARAMETERS:  None
666ff4a156dSchristos  *
667ff4a156dSchristos  * RETURN:      Status
668ff4a156dSchristos  *
669ff4a156dSchristos  * DESCRIPTION: Initialize ACPI table data. Get and store main ACPI tables to
670ff4a156dSchristos  *              local variables. Main ACPI tables include RSDT, FADT, RSDT,
671ff4a156dSchristos  *              and/or XSDT.
672ff4a156dSchristos  *
673ff4a156dSchristos  *****************************************************************************/
674ff4a156dSchristos 
675ff4a156dSchristos static ACPI_STATUS
OslTableInitialize(void)676ff4a156dSchristos OslTableInitialize (
677ff4a156dSchristos     void)
678ff4a156dSchristos {
679ff4a156dSchristos     ACPI_STATUS             Status;
680ff4a156dSchristos     ACPI_PHYSICAL_ADDRESS   Address;
681ff4a156dSchristos 
682ff4a156dSchristos 
683ff4a156dSchristos     if (Gbl_TableListInitialized)
684ff4a156dSchristos     {
685ff4a156dSchristos         return (AE_OK);
686ff4a156dSchristos     }
687ff4a156dSchristos 
6889b9ee194Schristos     if (!Gbl_DumpCustomizedTables)
6899b9ee194Schristos     {
690ff4a156dSchristos         /* Get RSDP from memory */
691ff4a156dSchristos 
692ff4a156dSchristos         Status = OslLoadRsdp ();
693ff4a156dSchristos         if (ACPI_FAILURE (Status))
694ff4a156dSchristos         {
695ff4a156dSchristos             return (Status);
696ff4a156dSchristos         }
697ff4a156dSchristos 
698ff4a156dSchristos         /* Get XSDT from memory */
699ff4a156dSchristos 
700414ef032Schristos         if (Gbl_Rsdp.Revision && !Gbl_DoNotDumpXsdt)
701ff4a156dSchristos         {
702ff4a156dSchristos             if (Gbl_Xsdt)
703ff4a156dSchristos             {
704ff4a156dSchristos                 free (Gbl_Xsdt);
705ff4a156dSchristos                 Gbl_Xsdt = NULL;
706ff4a156dSchristos             }
707ff4a156dSchristos 
708ff4a156dSchristos             Gbl_Revision = 2;
709ff4a156dSchristos             Status = OslGetBiosTable (ACPI_SIG_XSDT, 0,
710ff4a156dSchristos                 ACPI_CAST_PTR (ACPI_TABLE_HEADER *, &Gbl_Xsdt), &Address);
711ff4a156dSchristos             if (ACPI_FAILURE (Status))
712ff4a156dSchristos             {
713ff4a156dSchristos                 return (Status);
714ff4a156dSchristos             }
715ff4a156dSchristos         }
716ff4a156dSchristos 
717ff4a156dSchristos         /* Get RSDT from memory */
718ff4a156dSchristos 
719ff4a156dSchristos         if (Gbl_Rsdp.RsdtPhysicalAddress)
720ff4a156dSchristos         {
721ff4a156dSchristos             if (Gbl_Rsdt)
722ff4a156dSchristos             {
723ff4a156dSchristos                 free (Gbl_Rsdt);
724ff4a156dSchristos                 Gbl_Rsdt = NULL;
725ff4a156dSchristos             }
726ff4a156dSchristos 
727ff4a156dSchristos             Status = OslGetBiosTable (ACPI_SIG_RSDT, 0,
728ff4a156dSchristos                 ACPI_CAST_PTR (ACPI_TABLE_HEADER *, &Gbl_Rsdt), &Address);
729ff4a156dSchristos             if (ACPI_FAILURE (Status))
730ff4a156dSchristos             {
731ff4a156dSchristos                 return (Status);
732ff4a156dSchristos             }
733ff4a156dSchristos         }
734ff4a156dSchristos 
735ff4a156dSchristos         /* Get FADT from memory */
736ff4a156dSchristos 
737ff4a156dSchristos         if (Gbl_Fadt)
738ff4a156dSchristos         {
739ff4a156dSchristos             free (Gbl_Fadt);
740ff4a156dSchristos             Gbl_Fadt = NULL;
741ff4a156dSchristos         }
742ff4a156dSchristos 
743ff4a156dSchristos         Status = OslGetBiosTable (ACPI_SIG_FADT, 0,
744ff4a156dSchristos             ACPI_CAST_PTR (ACPI_TABLE_HEADER *, &Gbl_Fadt), &Gbl_FadtAddress);
745ff4a156dSchristos         if (ACPI_FAILURE (Status))
746ff4a156dSchristos         {
747ff4a156dSchristos             return (Status);
748ff4a156dSchristos         }
749ff4a156dSchristos 
750ff4a156dSchristos         /* Add mandatory tables to global table list first */
751ff4a156dSchristos 
752414ef032Schristos         Status = OslAddTableToList (ACPI_RSDP_NAME, 0);
753ff4a156dSchristos         if (ACPI_FAILURE (Status))
754ff4a156dSchristos         {
755ff4a156dSchristos             return (Status);
756ff4a156dSchristos         }
757ff4a156dSchristos 
758ff4a156dSchristos         Status = OslAddTableToList (ACPI_SIG_RSDT, 0);
759ff4a156dSchristos         if (ACPI_FAILURE (Status))
760ff4a156dSchristos         {
761ff4a156dSchristos             return (Status);
762ff4a156dSchristos         }
763ff4a156dSchristos 
764ff4a156dSchristos         if (Gbl_Revision == 2)
765ff4a156dSchristos         {
766ff4a156dSchristos             Status = OslAddTableToList (ACPI_SIG_XSDT, 0);
767ff4a156dSchristos             if (ACPI_FAILURE (Status))
768ff4a156dSchristos             {
769ff4a156dSchristos                 return (Status);
770ff4a156dSchristos             }
771ff4a156dSchristos         }
772ff4a156dSchristos 
773ff4a156dSchristos         Status = OslAddTableToList (ACPI_SIG_DSDT, 0);
774ff4a156dSchristos         if (ACPI_FAILURE (Status))
775ff4a156dSchristos         {
776ff4a156dSchristos             return (Status);
777ff4a156dSchristos         }
778ff4a156dSchristos 
779ff4a156dSchristos         Status = OslAddTableToList (ACPI_SIG_FACS, 0);
780ff4a156dSchristos         if (ACPI_FAILURE (Status))
781ff4a156dSchristos         {
782ff4a156dSchristos             return (Status);
783ff4a156dSchristos         }
784ff4a156dSchristos 
785ff4a156dSchristos         /* Add all tables found in the memory */
786ff4a156dSchristos 
787ff4a156dSchristos         Status = OslListBiosTables ();
788ff4a156dSchristos         if (ACPI_FAILURE (Status))
789ff4a156dSchristos         {
790ff4a156dSchristos             return (Status);
791ff4a156dSchristos         }
792ff4a156dSchristos     }
793ff4a156dSchristos     else
794ff4a156dSchristos     {
795ff4a156dSchristos         /* Add all tables found in the static directory */
796ff4a156dSchristos 
797ff4a156dSchristos         Status = OslListCustomizedTables (STATIC_TABLE_DIR);
798ff4a156dSchristos         if (ACPI_FAILURE (Status))
799ff4a156dSchristos         {
800ff4a156dSchristos             return (Status);
801ff4a156dSchristos         }
802ff4a156dSchristos     }
803ff4a156dSchristos 
804ff4a156dSchristos     if (Gbl_DumpDynamicTables)
805ff4a156dSchristos     {
806ff4a156dSchristos         /* Add all dynamically loaded tables in the dynamic directory */
807ff4a156dSchristos 
808ff4a156dSchristos         Status = OslListCustomizedTables (DYNAMIC_TABLE_DIR);
809ff4a156dSchristos         if (ACPI_FAILURE (Status))
810ff4a156dSchristos         {
811ff4a156dSchristos             return (Status);
812ff4a156dSchristos         }
813ff4a156dSchristos     }
814ff4a156dSchristos 
815ff4a156dSchristos     Gbl_TableListInitialized = TRUE;
816ff4a156dSchristos     return (AE_OK);
817ff4a156dSchristos }
818ff4a156dSchristos 
819ff4a156dSchristos 
820ff4a156dSchristos /******************************************************************************
821ff4a156dSchristos  *
822ff4a156dSchristos  * FUNCTION:    OslListBiosTables
823ff4a156dSchristos  *
824ff4a156dSchristos  * PARAMETERS:  None
825ff4a156dSchristos  *
826ff4a156dSchristos  * RETURN:      Status; Table list is initialized if AE_OK.
827ff4a156dSchristos  *
828ff4a156dSchristos  * DESCRIPTION: Add ACPI tables to the table list from memory.
829ff4a156dSchristos  *
830ff4a156dSchristos  * NOTE:        This works on Linux as table customization does not modify the
831ff4a156dSchristos  *              addresses stored in RSDP/RSDT/XSDT/FADT.
832ff4a156dSchristos  *
833ff4a156dSchristos  *****************************************************************************/
834ff4a156dSchristos 
835ff4a156dSchristos static ACPI_STATUS
OslListBiosTables(void)836ff4a156dSchristos OslListBiosTables (
837ff4a156dSchristos     void)
838ff4a156dSchristos {
839ff4a156dSchristos     ACPI_TABLE_HEADER       *MappedTable = NULL;
840ff4a156dSchristos     UINT8                   *TableData;
841ff4a156dSchristos     UINT8                   NumberOfTables;
842ff4a156dSchristos     UINT8                   ItemSize;
843ff4a156dSchristos     ACPI_PHYSICAL_ADDRESS   TableAddress = 0;
844ff4a156dSchristos     ACPI_STATUS             Status = AE_OK;
845ff4a156dSchristos     UINT32                  i;
846ff4a156dSchristos 
847ff4a156dSchristos 
848414ef032Schristos     if (OslCanUseXsdt ())
849ff4a156dSchristos     {
850ff4a156dSchristos         ItemSize = sizeof (UINT64);
851ff4a156dSchristos         TableData = ACPI_CAST8 (Gbl_Xsdt) + sizeof (ACPI_TABLE_HEADER);
852ff4a156dSchristos         NumberOfTables =
853ff4a156dSchristos             (UINT8) ((Gbl_Xsdt->Header.Length - sizeof (ACPI_TABLE_HEADER))
854ff4a156dSchristos             / ItemSize);
855ff4a156dSchristos     }
856ff4a156dSchristos     else /* Use RSDT if XSDT is not available */
857ff4a156dSchristos     {
858ff4a156dSchristos         ItemSize = sizeof (UINT32);
859ff4a156dSchristos         TableData = ACPI_CAST8 (Gbl_Rsdt) + sizeof (ACPI_TABLE_HEADER);
860ff4a156dSchristos         NumberOfTables =
861ff4a156dSchristos             (UINT8) ((Gbl_Rsdt->Header.Length - sizeof (ACPI_TABLE_HEADER))
862ff4a156dSchristos             / ItemSize);
863ff4a156dSchristos     }
864ff4a156dSchristos 
865ff4a156dSchristos     /* Search RSDT/XSDT for the requested table */
866ff4a156dSchristos 
867ff4a156dSchristos     for (i = 0; i < NumberOfTables; ++i, TableData += ItemSize)
868ff4a156dSchristos     {
869414ef032Schristos         if (OslCanUseXsdt ())
870ff4a156dSchristos         {
871ff4a156dSchristos             TableAddress =
872ff4a156dSchristos                 (ACPI_PHYSICAL_ADDRESS) (*ACPI_CAST64 (TableData));
873ff4a156dSchristos         }
874ff4a156dSchristos         else
875ff4a156dSchristos         {
876ff4a156dSchristos             TableAddress =
877ff4a156dSchristos                 (ACPI_PHYSICAL_ADDRESS) (*ACPI_CAST32 (TableData));
878ff4a156dSchristos         }
879ff4a156dSchristos 
880414ef032Schristos         /* Skip NULL entries in RSDT/XSDT */
881414ef032Schristos 
882ae01dbf5Schristos         if (TableAddress == 0)
883414ef032Schristos         {
884414ef032Schristos             continue;
885414ef032Schristos         }
886414ef032Schristos 
887ff4a156dSchristos         Status = OslMapTable (TableAddress, NULL, &MappedTable);
888ff4a156dSchristos         if (ACPI_FAILURE (Status))
889ff4a156dSchristos         {
890ff4a156dSchristos             return (Status);
891ff4a156dSchristos         }
892ff4a156dSchristos 
893ff4a156dSchristos         OslAddTableToList (MappedTable->Signature, 0);
894ff4a156dSchristos         OslUnmapTable (MappedTable);
895ff4a156dSchristos     }
896ff4a156dSchristos 
897ff4a156dSchristos     return (AE_OK);
898ff4a156dSchristos }
899ff4a156dSchristos 
900ff4a156dSchristos 
901ff4a156dSchristos /******************************************************************************
902ff4a156dSchristos  *
903ff4a156dSchristos  * FUNCTION:    OslGetBiosTable
904ff4a156dSchristos  *
905ff4a156dSchristos  * PARAMETERS:  Signature       - ACPI Signature for common table. Must be
906ff4a156dSchristos  *                                a null terminated 4-character string.
907ff4a156dSchristos  *              Instance        - Multiple table support for SSDT/UEFI (0...n)
908ff4a156dSchristos  *                                Must be 0 for other tables.
909ff4a156dSchristos  *              Table           - Where a pointer to the table is returned
910ff4a156dSchristos  *              Address         - Where the table physical address is returned
911ff4a156dSchristos  *
912ff4a156dSchristos  * RETURN:      Status; Table buffer and physical address returned if AE_OK.
913ff4a156dSchristos  *              AE_LIMIT: Instance is beyond valid limit
914ff4a156dSchristos  *              AE_NOT_FOUND: A table with the signature was not found
915ff4a156dSchristos  *
916ff4a156dSchristos  * DESCRIPTION: Get a BIOS provided ACPI table
917ff4a156dSchristos  *
918ff4a156dSchristos  * NOTE:        Assumes the input signature is uppercase.
919ff4a156dSchristos  *
920ff4a156dSchristos  *****************************************************************************/
921ff4a156dSchristos 
922ff4a156dSchristos static ACPI_STATUS
OslGetBiosTable(char * Signature,UINT32 Instance,ACPI_TABLE_HEADER ** Table,ACPI_PHYSICAL_ADDRESS * Address)923ff4a156dSchristos OslGetBiosTable (
924ff4a156dSchristos     char                    *Signature,
925ff4a156dSchristos     UINT32                  Instance,
926ff4a156dSchristos     ACPI_TABLE_HEADER       **Table,
927ff4a156dSchristos     ACPI_PHYSICAL_ADDRESS   *Address)
928ff4a156dSchristos {
929ff4a156dSchristos     ACPI_TABLE_HEADER       *LocalTable = NULL;
930ff4a156dSchristos     ACPI_TABLE_HEADER       *MappedTable = NULL;
931ff4a156dSchristos     UINT8                   *TableData;
932ff4a156dSchristos     UINT8                   NumberOfTables;
933ff4a156dSchristos     UINT8                   ItemSize;
934ff4a156dSchristos     UINT32                  CurrentInstance = 0;
935ae01dbf5Schristos     ACPI_PHYSICAL_ADDRESS   TableAddress;
936ae01dbf5Schristos     ACPI_PHYSICAL_ADDRESS   FirstTableAddress = 0;
937ff4a156dSchristos     UINT32                  TableLength = 0;
938ff4a156dSchristos     ACPI_STATUS             Status = AE_OK;
939ff4a156dSchristos     UINT32                  i;
940ff4a156dSchristos 
941ff4a156dSchristos 
942ff4a156dSchristos     /* Handle special tables whose addresses are not in RSDT/XSDT */
943ff4a156dSchristos 
9445b948c02Schristos     if (ACPI_COMPARE_NAMESEG (Signature, ACPI_RSDP_NAME) ||
9455b948c02Schristos         ACPI_COMPARE_NAMESEG (Signature, ACPI_SIG_RSDT) ||
9465b948c02Schristos         ACPI_COMPARE_NAMESEG (Signature, ACPI_SIG_XSDT) ||
9475b948c02Schristos         ACPI_COMPARE_NAMESEG (Signature, ACPI_SIG_DSDT) ||
9485b948c02Schristos         ACPI_COMPARE_NAMESEG (Signature, ACPI_SIG_FACS))
949ff4a156dSchristos     {
950ae01dbf5Schristos 
951ae01dbf5Schristos FindNextInstance:
952ae01dbf5Schristos 
953ae01dbf5Schristos         TableAddress = 0;
954414ef032Schristos 
955ff4a156dSchristos         /*
956ff4a156dSchristos          * Get the appropriate address, either 32-bit or 64-bit. Be very
957ff4a156dSchristos          * careful about the FADT length and validate table addresses.
958ff4a156dSchristos          * Note: The 64-bit addresses have priority.
959ff4a156dSchristos          */
9605b948c02Schristos         if (ACPI_COMPARE_NAMESEG (Signature, ACPI_SIG_DSDT))
961ff4a156dSchristos         {
962ae01dbf5Schristos             if (CurrentInstance < 2)
963ae01dbf5Schristos             {
964ff4a156dSchristos                 if ((Gbl_Fadt->Header.Length >= MIN_FADT_FOR_XDSDT) &&
965ae01dbf5Schristos                     Gbl_Fadt->XDsdt && CurrentInstance == 0)
966ff4a156dSchristos                 {
967ff4a156dSchristos                     TableAddress = (ACPI_PHYSICAL_ADDRESS) Gbl_Fadt->XDsdt;
968ff4a156dSchristos                 }
969ff4a156dSchristos                 else if ((Gbl_Fadt->Header.Length >= MIN_FADT_FOR_DSDT) &&
970ae01dbf5Schristos                     Gbl_Fadt->Dsdt != FirstTableAddress)
971ff4a156dSchristos                 {
972ff4a156dSchristos                     TableAddress = (ACPI_PHYSICAL_ADDRESS) Gbl_Fadt->Dsdt;
973ff4a156dSchristos                 }
974ff4a156dSchristos             }
975ae01dbf5Schristos         }
9765b948c02Schristos         else if (ACPI_COMPARE_NAMESEG (Signature, ACPI_SIG_FACS))
977ff4a156dSchristos         {
978ae01dbf5Schristos             if (CurrentInstance < 2)
979ae01dbf5Schristos             {
980ff4a156dSchristos                 if ((Gbl_Fadt->Header.Length >= MIN_FADT_FOR_XFACS) &&
981ae01dbf5Schristos                     Gbl_Fadt->XFacs && CurrentInstance == 0)
982ff4a156dSchristos                 {
983ff4a156dSchristos                     TableAddress = (ACPI_PHYSICAL_ADDRESS) Gbl_Fadt->XFacs;
984ff4a156dSchristos                 }
985ff4a156dSchristos                 else if ((Gbl_Fadt->Header.Length >= MIN_FADT_FOR_FACS) &&
986ae01dbf5Schristos                     Gbl_Fadt->Facs != FirstTableAddress)
987ff4a156dSchristos                 {
988ff4a156dSchristos                     TableAddress = (ACPI_PHYSICAL_ADDRESS) Gbl_Fadt->Facs;
989ff4a156dSchristos                 }
990ff4a156dSchristos             }
991ae01dbf5Schristos         }
9925b948c02Schristos         else if (ACPI_COMPARE_NAMESEG (Signature, ACPI_SIG_XSDT))
993ff4a156dSchristos         {
994ff4a156dSchristos             if (!Gbl_Revision)
995ff4a156dSchristos             {
996ff4a156dSchristos                 return (AE_BAD_SIGNATURE);
997ff4a156dSchristos             }
998ae01dbf5Schristos             if (CurrentInstance == 0)
999ae01dbf5Schristos             {
1000ae01dbf5Schristos                 TableAddress =
1001ae01dbf5Schristos                     (ACPI_PHYSICAL_ADDRESS) Gbl_Rsdp.XsdtPhysicalAddress;
1002ae01dbf5Schristos             }
1003ff4a156dSchristos         }
10045b948c02Schristos         else if (ACPI_COMPARE_NAMESEG (Signature, ACPI_SIG_RSDT))
1005ff4a156dSchristos         {
1006ae01dbf5Schristos             if (CurrentInstance == 0)
1007ae01dbf5Schristos             {
1008ae01dbf5Schristos                 TableAddress =
1009ae01dbf5Schristos                     (ACPI_PHYSICAL_ADDRESS) Gbl_Rsdp.RsdtPhysicalAddress;
1010ae01dbf5Schristos             }
1011ff4a156dSchristos         }
1012ff4a156dSchristos         else
1013ff4a156dSchristos         {
1014ae01dbf5Schristos             if (CurrentInstance == 0)
1015ae01dbf5Schristos             {
1016ff4a156dSchristos                 TableAddress = (ACPI_PHYSICAL_ADDRESS) Gbl_RsdpAddress;
1017ff4a156dSchristos                 Signature = ACPI_SIG_RSDP;
1018ff4a156dSchristos             }
1019ae01dbf5Schristos         }
1020ae01dbf5Schristos 
1021ae01dbf5Schristos         if (TableAddress == 0)
1022ae01dbf5Schristos         {
1023ae01dbf5Schristos             goto ExitFindTable;
1024ae01dbf5Schristos         }
1025ff4a156dSchristos 
1026ff4a156dSchristos         /* Now we can get the requested special table */
1027ff4a156dSchristos 
1028ff4a156dSchristos         Status = OslMapTable (TableAddress, Signature, &MappedTable);
1029ff4a156dSchristos         if (ACPI_FAILURE (Status))
1030ff4a156dSchristos         {
1031ff4a156dSchristos             return (Status);
1032ff4a156dSchristos         }
1033ff4a156dSchristos 
1034ff4a156dSchristos         TableLength = ApGetTableLength (MappedTable);
1035ae01dbf5Schristos         if (FirstTableAddress == 0)
1036ae01dbf5Schristos         {
1037ae01dbf5Schristos             FirstTableAddress = TableAddress;
1038ae01dbf5Schristos         }
1039ae01dbf5Schristos 
1040ae01dbf5Schristos         /* Match table instance */
1041ae01dbf5Schristos 
1042ae01dbf5Schristos         if (CurrentInstance != Instance)
1043ae01dbf5Schristos         {
1044ae01dbf5Schristos             OslUnmapTable (MappedTable);
1045ae01dbf5Schristos             MappedTable = NULL;
1046ae01dbf5Schristos             CurrentInstance++;
1047ae01dbf5Schristos             goto FindNextInstance;
1048ae01dbf5Schristos         }
1049ff4a156dSchristos     }
1050ff4a156dSchristos     else /* Case for a normal ACPI table */
1051ff4a156dSchristos     {
1052414ef032Schristos         if (OslCanUseXsdt ())
1053ff4a156dSchristos         {
1054ff4a156dSchristos             ItemSize = sizeof (UINT64);
1055ff4a156dSchristos             TableData = ACPI_CAST8 (Gbl_Xsdt) + sizeof (ACPI_TABLE_HEADER);
1056ff4a156dSchristos             NumberOfTables =
1057ff4a156dSchristos                 (UINT8) ((Gbl_Xsdt->Header.Length - sizeof (ACPI_TABLE_HEADER))
1058ff4a156dSchristos                 / ItemSize);
1059ff4a156dSchristos         }
1060ff4a156dSchristos         else /* Use RSDT if XSDT is not available */
1061ff4a156dSchristos         {
1062ff4a156dSchristos             ItemSize = sizeof (UINT32);
1063ff4a156dSchristos             TableData = ACPI_CAST8 (Gbl_Rsdt) + sizeof (ACPI_TABLE_HEADER);
1064ff4a156dSchristos             NumberOfTables =
1065ff4a156dSchristos                 (UINT8) ((Gbl_Rsdt->Header.Length - sizeof (ACPI_TABLE_HEADER))
1066ff4a156dSchristos                 / ItemSize);
1067ff4a156dSchristos         }
1068ff4a156dSchristos 
1069ff4a156dSchristos         /* Search RSDT/XSDT for the requested table */
1070ff4a156dSchristos 
1071ff4a156dSchristos         for (i = 0; i < NumberOfTables; ++i, TableData += ItemSize)
1072ff4a156dSchristos         {
1073414ef032Schristos             if (OslCanUseXsdt ())
1074ff4a156dSchristos             {
1075ff4a156dSchristos                 TableAddress =
1076ff4a156dSchristos                     (ACPI_PHYSICAL_ADDRESS) (*ACPI_CAST64 (TableData));
1077ff4a156dSchristos             }
1078ff4a156dSchristos             else
1079ff4a156dSchristos             {
1080ff4a156dSchristos                 TableAddress =
1081ff4a156dSchristos                     (ACPI_PHYSICAL_ADDRESS) (*ACPI_CAST32 (TableData));
1082ff4a156dSchristos             }
1083ff4a156dSchristos 
1084414ef032Schristos             /* Skip NULL entries in RSDT/XSDT */
1085414ef032Schristos 
1086ae01dbf5Schristos             if (TableAddress == 0)
1087414ef032Schristos             {
1088414ef032Schristos                 continue;
1089414ef032Schristos             }
1090414ef032Schristos 
1091ff4a156dSchristos             Status = OslMapTable (TableAddress, NULL, &MappedTable);
1092ff4a156dSchristos             if (ACPI_FAILURE (Status))
1093ff4a156dSchristos             {
1094ff4a156dSchristos                 return (Status);
1095ff4a156dSchristos             }
1096ff4a156dSchristos             TableLength = MappedTable->Length;
1097ff4a156dSchristos 
1098ff4a156dSchristos             /* Does this table match the requested signature? */
1099ff4a156dSchristos 
11005b948c02Schristos             if (!ACPI_COMPARE_NAMESEG (MappedTable->Signature, Signature))
1101ff4a156dSchristos             {
1102ff4a156dSchristos                 OslUnmapTable (MappedTable);
1103ff4a156dSchristos                 MappedTable = NULL;
1104ff4a156dSchristos                 continue;
1105ff4a156dSchristos             }
1106ff4a156dSchristos 
1107ff4a156dSchristos             /* Match table instance (for SSDT/UEFI tables) */
1108ff4a156dSchristos 
1109ff4a156dSchristos             if (CurrentInstance != Instance)
1110ff4a156dSchristos             {
1111ff4a156dSchristos                 OslUnmapTable (MappedTable);
1112ff4a156dSchristos                 MappedTable = NULL;
1113ff4a156dSchristos                 CurrentInstance++;
1114ff4a156dSchristos                 continue;
1115ff4a156dSchristos             }
1116ff4a156dSchristos 
1117ff4a156dSchristos             break;
1118ff4a156dSchristos         }
1119ff4a156dSchristos     }
1120ff4a156dSchristos 
1121ae01dbf5Schristos ExitFindTable:
1122ae01dbf5Schristos 
1123ff4a156dSchristos     if (!MappedTable)
1124ff4a156dSchristos     {
1125ff4a156dSchristos         return (AE_LIMIT);
1126ff4a156dSchristos     }
1127ff4a156dSchristos 
1128ff4a156dSchristos     if (TableLength == 0)
1129ff4a156dSchristos     {
1130ff4a156dSchristos         Status = AE_BAD_HEADER;
1131414ef032Schristos         goto Exit;
1132ff4a156dSchristos     }
1133ff4a156dSchristos 
1134ff4a156dSchristos     /* Copy table to local buffer and return it */
1135ff4a156dSchristos 
1136ff4a156dSchristos     LocalTable = calloc (1, TableLength);
1137ff4a156dSchristos     if (!LocalTable)
1138ff4a156dSchristos     {
1139ff4a156dSchristos         Status = AE_NO_MEMORY;
1140414ef032Schristos         goto Exit;
1141ff4a156dSchristos     }
1142ff4a156dSchristos 
11439b9ee194Schristos     memcpy (LocalTable, MappedTable, TableLength);
1144ff4a156dSchristos     *Address = TableAddress;
1145ff4a156dSchristos     *Table = LocalTable;
1146ff4a156dSchristos 
1147414ef032Schristos Exit:
1148ff4a156dSchristos     OslUnmapTable (MappedTable);
1149414ef032Schristos     return (Status);
1150ff4a156dSchristos }
1151ff4a156dSchristos 
1152ff4a156dSchristos 
1153ff4a156dSchristos /******************************************************************************
1154ff4a156dSchristos  *
1155ff4a156dSchristos  * FUNCTION:    OslListCustomizedTables
1156ff4a156dSchristos  *
1157ff4a156dSchristos  * PARAMETERS:  Directory           - Directory that contains the tables
1158ff4a156dSchristos  *
1159ff4a156dSchristos  * RETURN:      Status; Table list is initialized if AE_OK.
1160ff4a156dSchristos  *
1161ff4a156dSchristos  * DESCRIPTION: Add ACPI tables to the table list from a directory.
1162ff4a156dSchristos  *
1163ff4a156dSchristos  *****************************************************************************/
1164ff4a156dSchristos 
1165ff4a156dSchristos static ACPI_STATUS
OslListCustomizedTables(char * Directory)1166ff4a156dSchristos OslListCustomizedTables (
1167ff4a156dSchristos     char                    *Directory)
1168ff4a156dSchristos {
1169ff4a156dSchristos     void                    *TableDir;
1170ff4a156dSchristos     UINT32                  Instance;
11715b948c02Schristos     char                    TempName[ACPI_NAMESEG_SIZE];
1172ff4a156dSchristos     char                    *Filename;
1173ff4a156dSchristos     ACPI_STATUS             Status = AE_OK;
1174ff4a156dSchristos 
1175ff4a156dSchristos 
1176ff4a156dSchristos     /* Open the requested directory */
1177ff4a156dSchristos 
1178ff4a156dSchristos     TableDir = AcpiOsOpenDirectory (Directory, "*", REQUEST_FILE_ONLY);
1179ff4a156dSchristos     if (!TableDir)
1180ff4a156dSchristos     {
1181ff4a156dSchristos         return (OslGetLastStatus (AE_NOT_FOUND));
1182ff4a156dSchristos     }
1183ff4a156dSchristos 
1184ff4a156dSchristos     /* Examine all entries in this directory */
1185ff4a156dSchristos 
1186ff4a156dSchristos     while ((Filename = AcpiOsGetNextFilename (TableDir)))
1187ff4a156dSchristos     {
1188ff4a156dSchristos         /* Extract table name and instance number */
1189ff4a156dSchristos 
1190ff4a156dSchristos         Status = OslTableNameFromFile (Filename, TempName, &Instance);
1191ff4a156dSchristos 
1192ff4a156dSchristos         /* Ignore meaningless files */
1193ff4a156dSchristos 
1194ff4a156dSchristos         if (ACPI_FAILURE (Status))
1195ff4a156dSchristos         {
1196ff4a156dSchristos             continue;
1197ff4a156dSchristos         }
1198ff4a156dSchristos 
1199ff4a156dSchristos         /* Add new info node to global table list */
1200ff4a156dSchristos 
1201ff4a156dSchristos         Status = OslAddTableToList (TempName, Instance);
1202ff4a156dSchristos         if (ACPI_FAILURE (Status))
1203ff4a156dSchristos         {
1204ff4a156dSchristos             break;
1205ff4a156dSchristos         }
1206ff4a156dSchristos     }
1207ff4a156dSchristos 
1208ff4a156dSchristos     AcpiOsCloseDirectory (TableDir);
1209ff4a156dSchristos     return (Status);
1210ff4a156dSchristos }
1211ff4a156dSchristos 
1212ff4a156dSchristos 
1213ff4a156dSchristos /******************************************************************************
1214ff4a156dSchristos  *
1215ff4a156dSchristos  * FUNCTION:    OslMapTable
1216ff4a156dSchristos  *
1217ff4a156dSchristos  * PARAMETERS:  Address             - Address of the table in memory
1218ff4a156dSchristos  *              Signature           - Optional ACPI Signature for desired table.
1219ff4a156dSchristos  *                                    Null terminated 4-character string.
1220ff4a156dSchristos  *              Table               - Where a pointer to the mapped table is
1221ff4a156dSchristos  *                                    returned
1222ff4a156dSchristos  *
1223ff4a156dSchristos  * RETURN:      Status; Mapped table is returned if AE_OK.
1224ff4a156dSchristos  *              AE_NOT_FOUND: A valid table was not found at the address
1225ff4a156dSchristos  *
1226ff4a156dSchristos  * DESCRIPTION: Map entire ACPI table into caller's address space.
1227ff4a156dSchristos  *
1228ff4a156dSchristos  *****************************************************************************/
1229ff4a156dSchristos 
1230ff4a156dSchristos static ACPI_STATUS
OslMapTable(ACPI_SIZE Address,char * Signature,ACPI_TABLE_HEADER ** Table)1231ff4a156dSchristos OslMapTable (
1232ff4a156dSchristos     ACPI_SIZE               Address,
1233ff4a156dSchristos     char                    *Signature,
1234ff4a156dSchristos     ACPI_TABLE_HEADER       **Table)
1235ff4a156dSchristos {
1236ff4a156dSchristos     ACPI_TABLE_HEADER       *MappedTable;
1237ff4a156dSchristos     UINT32                  Length;
1238ff4a156dSchristos 
1239ff4a156dSchristos 
1240ff4a156dSchristos     if (!Address)
1241ff4a156dSchristos     {
1242ff4a156dSchristos         return (AE_BAD_ADDRESS);
1243ff4a156dSchristos     }
1244ff4a156dSchristos 
1245ff4a156dSchristos     /*
1246ff4a156dSchristos      * Map the header so we can get the table length.
1247ff4a156dSchristos      * Use sizeof (ACPI_TABLE_HEADER) as:
1248ff4a156dSchristos      * 1. it is bigger than 24 to include RSDP->Length
1249ff4a156dSchristos      * 2. it is smaller than sizeof (ACPI_TABLE_RSDP)
1250ff4a156dSchristos      */
1251ff4a156dSchristos     MappedTable = AcpiOsMapMemory (Address, sizeof (ACPI_TABLE_HEADER));
1252ff4a156dSchristos     if (!MappedTable)
1253ff4a156dSchristos     {
1254ff4a156dSchristos         fprintf (stderr, "Could not map table header at 0x%8.8X%8.8X\n",
1255ff4a156dSchristos             ACPI_FORMAT_UINT64 (Address));
1256ff4a156dSchristos         return (OslGetLastStatus (AE_BAD_ADDRESS));
1257ff4a156dSchristos     }
1258ff4a156dSchristos 
1259ff4a156dSchristos     /* If specified, signature must match */
1260ff4a156dSchristos 
1261414ef032Schristos     if (Signature)
1262414ef032Schristos     {
1263414ef032Schristos         if (ACPI_VALIDATE_RSDP_SIG (Signature))
1264414ef032Schristos         {
1265414ef032Schristos             if (!ACPI_VALIDATE_RSDP_SIG (MappedTable->Signature))
1266ff4a156dSchristos             {
1267ff4a156dSchristos                 AcpiOsUnmapMemory (MappedTable, sizeof (ACPI_TABLE_HEADER));
1268ff4a156dSchristos                 return (AE_BAD_SIGNATURE);
1269ff4a156dSchristos             }
1270414ef032Schristos         }
12715b948c02Schristos         else if (!ACPI_COMPARE_NAMESEG (Signature, MappedTable->Signature))
1272414ef032Schristos         {
1273414ef032Schristos             AcpiOsUnmapMemory (MappedTable, sizeof (ACPI_TABLE_HEADER));
1274414ef032Schristos             return (AE_BAD_SIGNATURE);
1275414ef032Schristos         }
1276414ef032Schristos     }
1277ff4a156dSchristos 
1278ff4a156dSchristos     /* Map the entire table */
1279ff4a156dSchristos 
1280ff4a156dSchristos     Length = ApGetTableLength (MappedTable);
1281ff4a156dSchristos     AcpiOsUnmapMemory (MappedTable, sizeof (ACPI_TABLE_HEADER));
1282ff4a156dSchristos     if (Length == 0)
1283ff4a156dSchristos     {
1284ff4a156dSchristos         return (AE_BAD_HEADER);
1285ff4a156dSchristos     }
1286ff4a156dSchristos 
1287ff4a156dSchristos     MappedTable = AcpiOsMapMemory (Address, Length);
1288ff4a156dSchristos     if (!MappedTable)
1289ff4a156dSchristos     {
1290ff4a156dSchristos         fprintf (stderr, "Could not map table at 0x%8.8X%8.8X length %8.8X\n",
1291ff4a156dSchristos             ACPI_FORMAT_UINT64 (Address), Length);
1292ff4a156dSchristos         return (OslGetLastStatus (AE_INVALID_TABLE_LENGTH));
1293ff4a156dSchristos     }
1294ff4a156dSchristos 
1295ff4a156dSchristos     (void) ApIsValidChecksum (MappedTable);
1296ff4a156dSchristos 
1297ff4a156dSchristos     *Table = MappedTable;
1298ff4a156dSchristos     return (AE_OK);
1299ff4a156dSchristos }
1300ff4a156dSchristos 
1301ff4a156dSchristos 
1302ff4a156dSchristos /******************************************************************************
1303ff4a156dSchristos  *
1304ff4a156dSchristos  * FUNCTION:    OslUnmapTable
1305ff4a156dSchristos  *
1306ff4a156dSchristos  * PARAMETERS:  Table               - A pointer to the mapped table
1307ff4a156dSchristos  *
1308ff4a156dSchristos  * RETURN:      None
1309ff4a156dSchristos  *
1310ff4a156dSchristos  * DESCRIPTION: Unmap entire ACPI table.
1311ff4a156dSchristos  *
1312ff4a156dSchristos  *****************************************************************************/
1313ff4a156dSchristos 
1314ff4a156dSchristos static void
OslUnmapTable(ACPI_TABLE_HEADER * Table)1315ff4a156dSchristos OslUnmapTable (
1316ff4a156dSchristos     ACPI_TABLE_HEADER       *Table)
1317ff4a156dSchristos {
1318ff4a156dSchristos     if (Table)
1319ff4a156dSchristos     {
1320ff4a156dSchristos         AcpiOsUnmapMemory (Table, ApGetTableLength (Table));
1321ff4a156dSchristos     }
1322ff4a156dSchristos }
1323ff4a156dSchristos 
1324ff4a156dSchristos 
1325ff4a156dSchristos /******************************************************************************
1326ff4a156dSchristos  *
1327ff4a156dSchristos  * FUNCTION:    OslTableNameFromFile
1328ff4a156dSchristos  *
1329ff4a156dSchristos  * PARAMETERS:  Filename            - File that contains the desired table
1330ff4a156dSchristos  *              Signature           - Pointer to 4-character buffer to store
1331ff4a156dSchristos  *                                    extracted table signature.
1332ff4a156dSchristos  *              Instance            - Pointer to integer to store extracted
1333ff4a156dSchristos  *                                    table instance number.
1334ff4a156dSchristos  *
1335ff4a156dSchristos  * RETURN:      Status; Table name is extracted if AE_OK.
1336ff4a156dSchristos  *
1337ff4a156dSchristos  * DESCRIPTION: Extract table signature and instance number from a table file
1338ff4a156dSchristos  *              name.
1339ff4a156dSchristos  *
1340ff4a156dSchristos  *****************************************************************************/
1341ff4a156dSchristos 
1342ff4a156dSchristos static ACPI_STATUS
OslTableNameFromFile(char * Filename,char * Signature,UINT32 * Instance)1343ff4a156dSchristos OslTableNameFromFile (
1344ff4a156dSchristos     char                    *Filename,
1345ff4a156dSchristos     char                    *Signature,
1346ff4a156dSchristos     UINT32                  *Instance)
1347ff4a156dSchristos {
1348ff4a156dSchristos 
1349ff4a156dSchristos     /* Ignore meaningless files */
1350ff4a156dSchristos 
13515b948c02Schristos     if (strlen (Filename) < ACPI_NAMESEG_SIZE)
1352ff4a156dSchristos     {
1353ff4a156dSchristos         return (AE_BAD_SIGNATURE);
1354ff4a156dSchristos     }
1355ff4a156dSchristos 
1356ff4a156dSchristos     /* Extract instance number */
1357ff4a156dSchristos 
13585b948c02Schristos     if (isdigit ((int) Filename[ACPI_NAMESEG_SIZE]))
1359ff4a156dSchristos     {
13605b948c02Schristos         sscanf (&Filename[ACPI_NAMESEG_SIZE], "%u", Instance);
1361ff4a156dSchristos     }
13625b948c02Schristos     else if (strlen (Filename) != ACPI_NAMESEG_SIZE)
1363ff4a156dSchristos     {
1364ff4a156dSchristos         return (AE_BAD_SIGNATURE);
1365ff4a156dSchristos     }
1366ff4a156dSchristos     else
1367ff4a156dSchristos     {
1368ff4a156dSchristos         *Instance = 0;
1369ff4a156dSchristos     }
1370ff4a156dSchristos 
1371ff4a156dSchristos     /* Extract signature */
1372ff4a156dSchristos 
13735b948c02Schristos     ACPI_COPY_NAMESEG (Signature, Filename);
1374ff4a156dSchristos     return (AE_OK);
1375ff4a156dSchristos }
1376ff4a156dSchristos 
1377ff4a156dSchristos 
1378ff4a156dSchristos /******************************************************************************
1379ff4a156dSchristos  *
1380ff4a156dSchristos  * FUNCTION:    OslReadTableFromFile
1381ff4a156dSchristos  *
1382ff4a156dSchristos  * PARAMETERS:  Filename            - File that contains the desired table
1383ff4a156dSchristos  *              FileOffset          - Offset of the table in file
1384ff4a156dSchristos  *              Table               - Where a pointer to the table is returned
1385ff4a156dSchristos  *
1386ff4a156dSchristos  * RETURN:      Status; Table buffer is returned if AE_OK.
1387ff4a156dSchristos  *
1388ff4a156dSchristos  * DESCRIPTION: Read a ACPI table from a file.
1389ff4a156dSchristos  *
1390ff4a156dSchristos  *****************************************************************************/
1391ff4a156dSchristos 
1392ff4a156dSchristos static ACPI_STATUS
OslReadTableFromFile(char * Filename,ACPI_SIZE FileOffset,ACPI_TABLE_HEADER ** Table)1393ff4a156dSchristos OslReadTableFromFile (
1394ff4a156dSchristos     char                    *Filename,
1395ff4a156dSchristos     ACPI_SIZE               FileOffset,
1396ff4a156dSchristos     ACPI_TABLE_HEADER       **Table)
1397ff4a156dSchristos {
1398ff4a156dSchristos     FILE                    *TableFile;
1399ff4a156dSchristos     ACPI_TABLE_HEADER       Header;
1400ff4a156dSchristos     ACPI_TABLE_HEADER       *LocalTable = NULL;
1401ff4a156dSchristos     UINT32                  TableLength;
1402ff4a156dSchristos     INT32                   Count;
1403ff4a156dSchristos     ACPI_STATUS             Status = AE_OK;
1404ff4a156dSchristos 
1405ff4a156dSchristos 
1406ff4a156dSchristos     /* Open the file */
1407ff4a156dSchristos 
1408ff4a156dSchristos     TableFile = fopen (Filename, "rb");
1409ff4a156dSchristos     if (TableFile == NULL)
1410ff4a156dSchristos     {
1411ff4a156dSchristos         fprintf (stderr, "Could not open table file: %s\n", Filename);
1412ff4a156dSchristos         return (OslGetLastStatus (AE_NOT_FOUND));
1413ff4a156dSchristos     }
1414ff4a156dSchristos 
1415ff4a156dSchristos     fseek (TableFile, FileOffset, SEEK_SET);
1416ff4a156dSchristos 
1417ff4a156dSchristos     /* Read the Table header to get the table length */
1418ff4a156dSchristos 
1419ff4a156dSchristos     Count = fread (&Header, 1, sizeof (ACPI_TABLE_HEADER), TableFile);
1420ff4a156dSchristos     if (Count != sizeof (ACPI_TABLE_HEADER))
1421ff4a156dSchristos     {
1422ff4a156dSchristos         fprintf (stderr, "Could not read table header: %s\n", Filename);
1423ff4a156dSchristos         Status = AE_BAD_HEADER;
1424414ef032Schristos         goto Exit;
1425ff4a156dSchristos     }
1426ff4a156dSchristos 
1427531a0538Schristos #ifdef ACPI_OBSOLETE_FUNCTIONS
1428531a0538Schristos 
1429ff4a156dSchristos     /* If signature is specified, it must match the table */
1430ff4a156dSchristos 
1431414ef032Schristos     if (Signature)
1432414ef032Schristos     {
1433414ef032Schristos         if (ACPI_VALIDATE_RSDP_SIG (Signature))
1434414ef032Schristos         {
1435414ef032Schristos             if (!ACPI_VALIDATE_RSDP_SIG (Header.Signature)) {
1436414ef032Schristos                 fprintf (stderr, "Incorrect RSDP signature: found %8.8s\n",
1437414ef032Schristos                     Header.Signature);
1438414ef032Schristos                 Status = AE_BAD_SIGNATURE;
1439414ef032Schristos                 goto Exit;
1440414ef032Schristos             }
1441414ef032Schristos         }
14425b948c02Schristos         else if (!ACPI_COMPARE_NAMESEG (Signature, Header.Signature))
1443ff4a156dSchristos         {
1444ff4a156dSchristos             fprintf (stderr, "Incorrect signature: Expecting %4.4s, found %4.4s\n",
1445ff4a156dSchristos                 Signature, Header.Signature);
1446ff4a156dSchristos             Status = AE_BAD_SIGNATURE;
1447414ef032Schristos             goto Exit;
1448414ef032Schristos         }
1449ff4a156dSchristos     }
1450531a0538Schristos #endif
1451ff4a156dSchristos 
1452ff4a156dSchristos     TableLength = ApGetTableLength (&Header);
1453ff4a156dSchristos     if (TableLength == 0)
1454ff4a156dSchristos     {
1455ff4a156dSchristos         Status = AE_BAD_HEADER;
1456414ef032Schristos         goto Exit;
1457ff4a156dSchristos     }
1458ff4a156dSchristos 
1459ff4a156dSchristos     /* Read the entire table into a local buffer */
1460ff4a156dSchristos 
1461ff4a156dSchristos     LocalTable = calloc (1, TableLength);
1462ff4a156dSchristos     if (!LocalTable)
1463ff4a156dSchristos     {
1464ff4a156dSchristos         fprintf (stderr,
1465ff4a156dSchristos             "%4.4s: Could not allocate buffer for table of length %X\n",
1466ff4a156dSchristos             Header.Signature, TableLength);
1467ff4a156dSchristos         Status = AE_NO_MEMORY;
1468414ef032Schristos         goto Exit;
1469ff4a156dSchristos     }
1470ff4a156dSchristos 
1471ff4a156dSchristos     fseek (TableFile, FileOffset, SEEK_SET);
1472ff4a156dSchristos 
1473414ef032Schristos     Count = fread (LocalTable, 1, TableLength, TableFile);
1474414ef032Schristos     if (Count != TableLength)
1475ff4a156dSchristos     {
1476ff4a156dSchristos         fprintf (stderr, "%4.4s: Could not read table content\n",
1477ff4a156dSchristos             Header.Signature);
1478ff4a156dSchristos         Status = AE_INVALID_TABLE_LENGTH;
1479414ef032Schristos         goto Exit;
1480ff4a156dSchristos     }
1481ff4a156dSchristos 
1482ff4a156dSchristos     /* Validate checksum */
1483ff4a156dSchristos 
1484ff4a156dSchristos     (void) ApIsValidChecksum (LocalTable);
1485ff4a156dSchristos 
1486414ef032Schristos Exit:
1487ff4a156dSchristos     fclose (TableFile);
1488ff4a156dSchristos     *Table = LocalTable;
1489ff4a156dSchristos     return (Status);
1490ff4a156dSchristos }
1491ff4a156dSchristos 
1492ff4a156dSchristos 
1493ff4a156dSchristos /******************************************************************************
1494ff4a156dSchristos  *
1495ff4a156dSchristos  * FUNCTION:    OslGetCustomizedTable
1496ff4a156dSchristos  *
1497ff4a156dSchristos  * PARAMETERS:  Pathname        - Directory to find Linux customized table
1498ff4a156dSchristos  *              Signature       - ACPI Signature for desired table. Must be
1499ff4a156dSchristos  *                                a null terminated 4-character string.
1500ff4a156dSchristos  *              Instance        - Multiple table support for SSDT/UEFI (0...n)
1501ff4a156dSchristos  *                                Must be 0 for other tables.
1502ff4a156dSchristos  *              Table           - Where a pointer to the table is returned
1503ff4a156dSchristos  *              Address         - Where the table physical address is returned
1504ff4a156dSchristos  *
1505ff4a156dSchristos  * RETURN:      Status; Table buffer is returned if AE_OK.
1506ff4a156dSchristos  *              AE_LIMIT: Instance is beyond valid limit
1507ff4a156dSchristos  *              AE_NOT_FOUND: A table with the signature was not found
1508ff4a156dSchristos  *
1509ff4a156dSchristos  * DESCRIPTION: Get an OS customized table.
1510ff4a156dSchristos  *
1511ff4a156dSchristos  *****************************************************************************/
1512ff4a156dSchristos 
1513ff4a156dSchristos static ACPI_STATUS
OslGetCustomizedTable(char * Pathname,char * Signature,UINT32 Instance,ACPI_TABLE_HEADER ** Table,ACPI_PHYSICAL_ADDRESS * Address)1514ff4a156dSchristos OslGetCustomizedTable (
1515ff4a156dSchristos     char                    *Pathname,
1516ff4a156dSchristos     char                    *Signature,
1517ff4a156dSchristos     UINT32                  Instance,
1518ff4a156dSchristos     ACPI_TABLE_HEADER       **Table,
1519ff4a156dSchristos     ACPI_PHYSICAL_ADDRESS   *Address)
1520ff4a156dSchristos {
1521ff4a156dSchristos     void                    *TableDir;
1522ff4a156dSchristos     UINT32                  CurrentInstance = 0;
15235b948c02Schristos     char                    TempName[ACPI_NAMESEG_SIZE];
1524ff4a156dSchristos     char                    TableFilename[PATH_MAX];
1525ff4a156dSchristos     char                    *Filename;
1526ff4a156dSchristos     ACPI_STATUS             Status;
1527ff4a156dSchristos 
1528ff4a156dSchristos 
1529ff4a156dSchristos     /* Open the directory for customized tables */
1530ff4a156dSchristos 
1531ff4a156dSchristos     TableDir = AcpiOsOpenDirectory (Pathname, "*", REQUEST_FILE_ONLY);
1532ff4a156dSchristos     if (!TableDir)
1533ff4a156dSchristos     {
1534ff4a156dSchristos         return (OslGetLastStatus (AE_NOT_FOUND));
1535ff4a156dSchristos     }
1536ff4a156dSchristos 
1537ff4a156dSchristos     /* Attempt to find the table in the directory */
1538ff4a156dSchristos 
1539ff4a156dSchristos     while ((Filename = AcpiOsGetNextFilename (TableDir)))
1540ff4a156dSchristos     {
1541ff4a156dSchristos         /* Ignore meaningless files */
1542ff4a156dSchristos 
15435b948c02Schristos         if (!ACPI_COMPARE_NAMESEG (Filename, Signature))
1544ff4a156dSchristos         {
1545ff4a156dSchristos             continue;
1546ff4a156dSchristos         }
1547ff4a156dSchristos 
1548ff4a156dSchristos         /* Extract table name and instance number */
1549ff4a156dSchristos 
1550ff4a156dSchristos         Status = OslTableNameFromFile (Filename, TempName, &CurrentInstance);
1551ff4a156dSchristos 
1552ff4a156dSchristos         /* Ignore meaningless files */
1553ff4a156dSchristos 
1554ff4a156dSchristos         if (ACPI_FAILURE (Status) || CurrentInstance != Instance)
1555ff4a156dSchristos         {
1556ff4a156dSchristos             continue;
1557ff4a156dSchristos         }
1558ff4a156dSchristos 
1559ff4a156dSchristos         /* Create the table pathname */
1560ff4a156dSchristos 
1561ff4a156dSchristos         if (Instance != 0)
1562ff4a156dSchristos         {
156352afc2f5Schristos             snprintf (TableFilename, sizeof(TableFilename), "%s/%4.4s%d",
156452afc2f5Schristos 		Pathname, TempName, Instance);
1565ff4a156dSchristos         }
1566ff4a156dSchristos         else
1567ff4a156dSchristos         {
156852afc2f5Schristos             snprintf (TableFilename, sizeof(TableFilename), "%s/%4.4s",
156952afc2f5Schristos 		Pathname, TempName);
1570ff4a156dSchristos         }
1571ff4a156dSchristos         break;
1572ff4a156dSchristos     }
1573ff4a156dSchristos 
1574ff4a156dSchristos     AcpiOsCloseDirectory (TableDir);
1575ff4a156dSchristos 
1576ff4a156dSchristos     if (!Filename)
1577ff4a156dSchristos     {
1578ff4a156dSchristos         return (AE_LIMIT);
1579ff4a156dSchristos     }
1580ff4a156dSchristos 
1581ff4a156dSchristos     /* There is no physical address saved for customized tables, use zero */
1582ff4a156dSchristos 
1583ff4a156dSchristos     *Address = 0;
1584531a0538Schristos     Status = OslReadTableFromFile (TableFilename, 0, Table);
1585ff4a156dSchristos 
1586ff4a156dSchristos     return (Status);
1587ff4a156dSchristos }
1588