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