1*cb565728SJerry Jelinek /*
2*cb565728SJerry Jelinek *
3*cb565728SJerry Jelinek * Module Name: osillumostbl - illumos OSL for obtaining ACPI tables
4*cb565728SJerry Jelinek * This file is derived from the Intel oslinuxtbl source file.
5*cb565728SJerry Jelinek *
6*cb565728SJerry Jelinek */
7*cb565728SJerry Jelinek
8*cb565728SJerry Jelinek /*
9*cb565728SJerry Jelinek * Copyright (C) 2000 - 2016, Intel Corp.
10*cb565728SJerry Jelinek * All rights reserved.
11*cb565728SJerry Jelinek *
12*cb565728SJerry Jelinek * Redistribution and use in source and binary forms, with or without
13*cb565728SJerry Jelinek * modification, are permitted provided that the following conditions
14*cb565728SJerry Jelinek * are met:
15*cb565728SJerry Jelinek * 1. Redistributions of source code must retain the above copyright
16*cb565728SJerry Jelinek * notice, this list of conditions, and the following disclaimer,
17*cb565728SJerry Jelinek * without modification.
18*cb565728SJerry Jelinek * 2. Redistributions in binary form must reproduce at minimum a disclaimer
19*cb565728SJerry Jelinek * substantially similar to the "NO WARRANTY" disclaimer below
20*cb565728SJerry Jelinek * ("Disclaimer") and any redistribution must be conditioned upon
21*cb565728SJerry Jelinek * including a substantially similar Disclaimer requirement for further
22*cb565728SJerry Jelinek * binary redistribution.
23*cb565728SJerry Jelinek * 3. Neither the names of the above-listed copyright holders nor the names
24*cb565728SJerry Jelinek * of any contributors may be used to endorse or promote products derived
25*cb565728SJerry Jelinek * from this software without specific prior written permission.
26*cb565728SJerry Jelinek *
27*cb565728SJerry Jelinek * Alternatively, this software may be distributed under the terms of the
28*cb565728SJerry Jelinek * GNU General Public License ("GPL") version 2 as published by the Free
29*cb565728SJerry Jelinek * Software Foundation.
30*cb565728SJerry Jelinek *
31*cb565728SJerry Jelinek * NO WARRANTY
32*cb565728SJerry Jelinek * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
33*cb565728SJerry Jelinek * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
34*cb565728SJerry Jelinek * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
35*cb565728SJerry Jelinek * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
36*cb565728SJerry Jelinek * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
37*cb565728SJerry Jelinek * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
38*cb565728SJerry Jelinek * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
39*cb565728SJerry Jelinek * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
40*cb565728SJerry Jelinek * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
41*cb565728SJerry Jelinek * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
42*cb565728SJerry Jelinek * POSSIBILITY OF SUCH DAMAGES.
43*cb565728SJerry Jelinek */
44*cb565728SJerry Jelinek
45*cb565728SJerry Jelinek /*
46*cb565728SJerry Jelinek * Copyright 2016 Joyent, Inc.
47*cb565728SJerry Jelinek */
48*cb565728SJerry Jelinek
49*cb565728SJerry Jelinek #include <stdarg.h>
50*cb565728SJerry Jelinek #include <string.h>
51*cb565728SJerry Jelinek #include <stdlib.h>
52*cb565728SJerry Jelinek #include <unistd.h>
53*cb565728SJerry Jelinek #include "acpidump.h"
54*cb565728SJerry Jelinek
55*cb565728SJerry Jelinek #define _COMPONENT ACPI_OS_SERVICES
56*cb565728SJerry Jelinek ACPI_MODULE_NAME("osillumostbl")
57*cb565728SJerry Jelinek
58*cb565728SJerry Jelinek /* List of information about obtained ACPI tables */
59*cb565728SJerry Jelinek
60*cb565728SJerry Jelinek typedef struct osl_table_info
61*cb565728SJerry Jelinek {
62*cb565728SJerry Jelinek struct osl_table_info *Next;
63*cb565728SJerry Jelinek UINT32 Instance;
64*cb565728SJerry Jelinek char Signature[ACPI_NAME_SIZE];
65*cb565728SJerry Jelinek } OSL_TABLE_INFO;
66*cb565728SJerry Jelinek
67*cb565728SJerry Jelinek /* Local prototypes */
68*cb565728SJerry Jelinek static ACPI_STATUS
69*cb565728SJerry Jelinek OslTableInitialize(void);
70*cb565728SJerry Jelinek static ACPI_STATUS OslTableNameFromFile(char *, char *, UINT32 *);
71*cb565728SJerry Jelinek static ACPI_STATUS OslAddTableToList(char *);
72*cb565728SJerry Jelinek static ACPI_STATUS OslMapTable(ACPI_SIZE, char *, ACPI_TABLE_HEADER **);
73*cb565728SJerry Jelinek static void OslUnmapTable(ACPI_TABLE_HEADER *);
74*cb565728SJerry Jelinek static ACPI_STATUS OslLoadRsdp(void);
75*cb565728SJerry Jelinek static ACPI_STATUS OslListBiosTables(void);
76*cb565728SJerry Jelinek static ACPI_STATUS OslGetBiosTable(char *, UINT32, ACPI_TABLE_HEADER **,
77*cb565728SJerry Jelinek ACPI_PHYSICAL_ADDRESS *);
78*cb565728SJerry Jelinek static ACPI_STATUS OslGetLastStatus(ACPI_STATUS);
79*cb565728SJerry Jelinek
80*cb565728SJerry Jelinek static int pagesize;
81*cb565728SJerry Jelinek
82*cb565728SJerry Jelinek /* Initialization flags */
83*cb565728SJerry Jelinek UINT8 Gbl_TableListInitialized = FALSE;
84*cb565728SJerry Jelinek
85*cb565728SJerry Jelinek /* Local copies of main ACPI tables */
86*cb565728SJerry Jelinek ACPI_TABLE_RSDP Gbl_Rsdp;
87*cb565728SJerry Jelinek ACPI_TABLE_FADT *Gbl_Fadt = NULL;
88*cb565728SJerry Jelinek ACPI_TABLE_RSDT *Gbl_Rsdt = NULL;
89*cb565728SJerry Jelinek ACPI_TABLE_XSDT *Gbl_Xsdt = NULL;
90*cb565728SJerry Jelinek
91*cb565728SJerry Jelinek /* Table addresses */
92*cb565728SJerry Jelinek ACPI_PHYSICAL_ADDRESS Gbl_FadtAddress = 0;
93*cb565728SJerry Jelinek ACPI_PHYSICAL_ADDRESS Gbl_RsdpAddress = 0;
94*cb565728SJerry Jelinek
95*cb565728SJerry Jelinek /* Revision of RSD PTR */
96*cb565728SJerry Jelinek UINT8 Gbl_Revision = 0;
97*cb565728SJerry Jelinek
98*cb565728SJerry Jelinek OSL_TABLE_INFO *Gbl_TableListHead = NULL;
99*cb565728SJerry Jelinek UINT32 Gbl_TableCount = 0;
100*cb565728SJerry Jelinek
101*cb565728SJerry Jelinek /*
102*cb565728SJerry Jelinek *
103*cb565728SJerry Jelinek * FUNCTION: OslGetLastStatus
104*cb565728SJerry Jelinek *
105*cb565728SJerry Jelinek * PARAMETERS: DefaultStatus - Default error status to return
106*cb565728SJerry Jelinek *
107*cb565728SJerry Jelinek * RETURN: Status; Converted from errno.
108*cb565728SJerry Jelinek *
109*cb565728SJerry Jelinek * DESCRIPTION: Get last errno and conver it to ACPI_STATUS.
110*cb565728SJerry Jelinek *
111*cb565728SJerry Jelinek */
112*cb565728SJerry Jelinek static ACPI_STATUS
OslGetLastStatus(ACPI_STATUS DefaultStatus)113*cb565728SJerry Jelinek OslGetLastStatus(ACPI_STATUS DefaultStatus)
114*cb565728SJerry Jelinek {
115*cb565728SJerry Jelinek switch (errno) {
116*cb565728SJerry Jelinek case EACCES:
117*cb565728SJerry Jelinek case EPERM:
118*cb565728SJerry Jelinek return (AE_ACCESS);
119*cb565728SJerry Jelinek
120*cb565728SJerry Jelinek case ENOENT:
121*cb565728SJerry Jelinek return (AE_NOT_FOUND);
122*cb565728SJerry Jelinek
123*cb565728SJerry Jelinek case ENOMEM:
124*cb565728SJerry Jelinek return (AE_NO_MEMORY);
125*cb565728SJerry Jelinek
126*cb565728SJerry Jelinek default:
127*cb565728SJerry Jelinek return (DefaultStatus);
128*cb565728SJerry Jelinek }
129*cb565728SJerry Jelinek }
130*cb565728SJerry Jelinek
131*cb565728SJerry Jelinek /*
132*cb565728SJerry Jelinek *
133*cb565728SJerry Jelinek * FUNCTION: AcpiOsGetTableByAddress
134*cb565728SJerry Jelinek *
135*cb565728SJerry Jelinek * PARAMETERS: Address - Physical address of the ACPI table
136*cb565728SJerry Jelinek * Table - Where a pointer to the table is returned
137*cb565728SJerry Jelinek *
138*cb565728SJerry Jelinek * RETURN: Status; Table buffer is returned if AE_OK.
139*cb565728SJerry Jelinek * AE_NOT_FOUND: A valid table was not found at the address
140*cb565728SJerry Jelinek *
141*cb565728SJerry Jelinek * DESCRIPTION: Get an ACPI table via a physical memory address.
142*cb565728SJerry Jelinek *
143*cb565728SJerry Jelinek */
144*cb565728SJerry Jelinek ACPI_STATUS
AcpiOsGetTableByAddress(ACPI_PHYSICAL_ADDRESS Address,ACPI_TABLE_HEADER ** Table)145*cb565728SJerry Jelinek AcpiOsGetTableByAddress(ACPI_PHYSICAL_ADDRESS Address,
146*cb565728SJerry Jelinek ACPI_TABLE_HEADER **Table)
147*cb565728SJerry Jelinek {
148*cb565728SJerry Jelinek UINT32 TableLength;
149*cb565728SJerry Jelinek ACPI_TABLE_HEADER *MappedTable;
150*cb565728SJerry Jelinek ACPI_TABLE_HEADER *LocalTable = NULL;
151*cb565728SJerry Jelinek ACPI_STATUS Status = AE_OK;
152*cb565728SJerry Jelinek
153*cb565728SJerry Jelinek /*
154*cb565728SJerry Jelinek * Get main ACPI tables from memory on first invocation of this
155*cb565728SJerry Jelinek * function
156*cb565728SJerry Jelinek */
157*cb565728SJerry Jelinek Status = OslTableInitialize();
158*cb565728SJerry Jelinek if (ACPI_FAILURE(Status)) {
159*cb565728SJerry Jelinek return (Status);
160*cb565728SJerry Jelinek }
161*cb565728SJerry Jelinek
162*cb565728SJerry Jelinek /* Map the table and validate it */
163*cb565728SJerry Jelinek
164*cb565728SJerry Jelinek Status = OslMapTable(Address, NULL, &MappedTable);
165*cb565728SJerry Jelinek if (ACPI_FAILURE(Status)) {
166*cb565728SJerry Jelinek return (Status);
167*cb565728SJerry Jelinek }
168*cb565728SJerry Jelinek
169*cb565728SJerry Jelinek /* Copy table to local buffer and return it */
170*cb565728SJerry Jelinek
171*cb565728SJerry Jelinek TableLength = ApGetTableLength(MappedTable);
172*cb565728SJerry Jelinek if (TableLength == 0) {
173*cb565728SJerry Jelinek Status = AE_BAD_HEADER;
174*cb565728SJerry Jelinek goto Exit;
175*cb565728SJerry Jelinek }
176*cb565728SJerry Jelinek
177*cb565728SJerry Jelinek LocalTable = calloc(1, TableLength);
178*cb565728SJerry Jelinek if (!LocalTable) {
179*cb565728SJerry Jelinek Status = AE_NO_MEMORY;
180*cb565728SJerry Jelinek goto Exit;
181*cb565728SJerry Jelinek }
182*cb565728SJerry Jelinek
183*cb565728SJerry Jelinek memcpy(LocalTable, MappedTable, TableLength);
184*cb565728SJerry Jelinek
185*cb565728SJerry Jelinek Exit:
186*cb565728SJerry Jelinek OslUnmapTable(MappedTable);
187*cb565728SJerry Jelinek *Table = LocalTable;
188*cb565728SJerry Jelinek return (Status);
189*cb565728SJerry Jelinek }
190*cb565728SJerry Jelinek
191*cb565728SJerry Jelinek /*
192*cb565728SJerry Jelinek *
193*cb565728SJerry Jelinek * FUNCTION: AcpiOsGetTableByName
194*cb565728SJerry Jelinek *
195*cb565728SJerry Jelinek * PARAMETERS: Signature - ACPI Signature for desired table. Must be
196*cb565728SJerry Jelinek * a null terminated 4-character string.
197*cb565728SJerry Jelinek * Instance - Multiple table support for SSDT/UEFI (0...n)
198*cb565728SJerry Jelinek * Must be 0 for other tables.
199*cb565728SJerry Jelinek * Table - Where a pointer to the table is returned
200*cb565728SJerry Jelinek * Address - Where the table physical address is returned
201*cb565728SJerry Jelinek *
202*cb565728SJerry Jelinek * RETURN: Status; Table buffer and physical address returned if AE_OK.
203*cb565728SJerry Jelinek * AE_LIMIT: Instance is beyond valid limit
204*cb565728SJerry Jelinek * AE_NOT_FOUND: A table with the signature was not found
205*cb565728SJerry Jelinek *
206*cb565728SJerry Jelinek * NOTE: Assumes the input signature is uppercase.
207*cb565728SJerry Jelinek *
208*cb565728SJerry Jelinek */
209*cb565728SJerry Jelinek ACPI_STATUS
AcpiOsGetTableByName(char * Signature,UINT32 Instance,ACPI_TABLE_HEADER ** Table,ACPI_PHYSICAL_ADDRESS * Address)210*cb565728SJerry Jelinek AcpiOsGetTableByName(char *Signature, UINT32 Instance,
211*cb565728SJerry Jelinek ACPI_TABLE_HEADER **Table, ACPI_PHYSICAL_ADDRESS *Address)
212*cb565728SJerry Jelinek {
213*cb565728SJerry Jelinek ACPI_STATUS Status;
214*cb565728SJerry Jelinek
215*cb565728SJerry Jelinek /*
216*cb565728SJerry Jelinek * Get main ACPI tables from memory on first invocation of this
217*cb565728SJerry Jelinek * function
218*cb565728SJerry Jelinek */
219*cb565728SJerry Jelinek Status = OslTableInitialize();
220*cb565728SJerry Jelinek if (ACPI_FAILURE(Status)) {
221*cb565728SJerry Jelinek return (Status);
222*cb565728SJerry Jelinek }
223*cb565728SJerry Jelinek
224*cb565728SJerry Jelinek /* attempt to extract it from the RSDT/XSDT */
225*cb565728SJerry Jelinek Status = OslGetBiosTable(Signature, Instance, Table, Address);
226*cb565728SJerry Jelinek
227*cb565728SJerry Jelinek return (Status);
228*cb565728SJerry Jelinek }
229*cb565728SJerry Jelinek
230*cb565728SJerry Jelinek /*
231*cb565728SJerry Jelinek *
232*cb565728SJerry Jelinek * FUNCTION: OslAddTableToList
233*cb565728SJerry Jelinek *
234*cb565728SJerry Jelinek * PARAMETERS: Signature - Table signature
235*cb565728SJerry Jelinek *
236*cb565728SJerry Jelinek * RETURN: Status; Successfully added if AE_OK.
237*cb565728SJerry Jelinek * AE_NO_MEMORY: Memory allocation error
238*cb565728SJerry Jelinek *
239*cb565728SJerry Jelinek * DESCRIPTION: Insert a table structure into OSL table list.
240*cb565728SJerry Jelinek *
241*cb565728SJerry Jelinek */
242*cb565728SJerry Jelinek static ACPI_STATUS
OslAddTableToList(char * Signature)243*cb565728SJerry Jelinek OslAddTableToList(char *Signature)
244*cb565728SJerry Jelinek {
245*cb565728SJerry Jelinek OSL_TABLE_INFO *NewInfo;
246*cb565728SJerry Jelinek OSL_TABLE_INFO *Next;
247*cb565728SJerry Jelinek UINT32 NextInstance = 0;
248*cb565728SJerry Jelinek UINT32 Instance = 0;
249*cb565728SJerry Jelinek BOOLEAN Found = FALSE;
250*cb565728SJerry Jelinek
251*cb565728SJerry Jelinek NewInfo = calloc(1, sizeof (OSL_TABLE_INFO));
252*cb565728SJerry Jelinek if (NewInfo == NULL) {
253*cb565728SJerry Jelinek return (AE_NO_MEMORY);
254*cb565728SJerry Jelinek }
255*cb565728SJerry Jelinek
256*cb565728SJerry Jelinek ACPI_MOVE_NAME(NewInfo->Signature, Signature);
257*cb565728SJerry Jelinek
258*cb565728SJerry Jelinek if (!Gbl_TableListHead) {
259*cb565728SJerry Jelinek Gbl_TableListHead = NewInfo;
260*cb565728SJerry Jelinek } else {
261*cb565728SJerry Jelinek Next = Gbl_TableListHead;
262*cb565728SJerry Jelinek
263*cb565728SJerry Jelinek while (1) {
264*cb565728SJerry Jelinek if (ACPI_COMPARE_NAME(Next->Signature, Signature)) {
265*cb565728SJerry Jelinek if (Next->Instance == 0) {
266*cb565728SJerry Jelinek Found = TRUE;
267*cb565728SJerry Jelinek }
268*cb565728SJerry Jelinek if (Next->Instance >= NextInstance) {
269*cb565728SJerry Jelinek NextInstance = Next->Instance + 1;
270*cb565728SJerry Jelinek }
271*cb565728SJerry Jelinek }
272*cb565728SJerry Jelinek
273*cb565728SJerry Jelinek if (!Next->Next) {
274*cb565728SJerry Jelinek break;
275*cb565728SJerry Jelinek }
276*cb565728SJerry Jelinek Next = Next->Next;
277*cb565728SJerry Jelinek }
278*cb565728SJerry Jelinek Next->Next = NewInfo;
279*cb565728SJerry Jelinek }
280*cb565728SJerry Jelinek
281*cb565728SJerry Jelinek if (Found) {
282*cb565728SJerry Jelinek Instance = NextInstance;
283*cb565728SJerry Jelinek }
284*cb565728SJerry Jelinek
285*cb565728SJerry Jelinek NewInfo->Instance = Instance;
286*cb565728SJerry Jelinek Gbl_TableCount++;
287*cb565728SJerry Jelinek
288*cb565728SJerry Jelinek return (AE_OK);
289*cb565728SJerry Jelinek }
290*cb565728SJerry Jelinek
291*cb565728SJerry Jelinek /*
292*cb565728SJerry Jelinek *
293*cb565728SJerry Jelinek * FUNCTION: AcpiOsGetTableByIndex
294*cb565728SJerry Jelinek *
295*cb565728SJerry Jelinek * PARAMETERS: Index - Which table to get
296*cb565728SJerry Jelinek * Table - Where a pointer to the table is returned
297*cb565728SJerry Jelinek * Instance - Where a pointer to the table instance no. is
298*cb565728SJerry Jelinek * returned
299*cb565728SJerry Jelinek * Address - Where the table physical address is returned
300*cb565728SJerry Jelinek *
301*cb565728SJerry Jelinek * RETURN: Status; Table buffer and physical address returned if AE_OK.
302*cb565728SJerry Jelinek * AE_LIMIT: Index is beyond valid limit
303*cb565728SJerry Jelinek *
304*cb565728SJerry Jelinek * DESCRIPTION: Get an ACPI table via an index value (0 through n). Returns
305*cb565728SJerry Jelinek * AE_LIMIT when an invalid index is reached. Index is not
306*cb565728SJerry Jelinek * necessarily an index into the RSDT/XSDT.
307*cb565728SJerry Jelinek *
308*cb565728SJerry Jelinek */
309*cb565728SJerry Jelinek ACPI_STATUS
AcpiOsGetTableByIndex(UINT32 Index,ACPI_TABLE_HEADER ** Table,UINT32 * Instance,ACPI_PHYSICAL_ADDRESS * Address)310*cb565728SJerry Jelinek AcpiOsGetTableByIndex(UINT32 Index, ACPI_TABLE_HEADER **Table,
311*cb565728SJerry Jelinek UINT32 *Instance, ACPI_PHYSICAL_ADDRESS *Address)
312*cb565728SJerry Jelinek {
313*cb565728SJerry Jelinek OSL_TABLE_INFO *Info;
314*cb565728SJerry Jelinek ACPI_STATUS Status;
315*cb565728SJerry Jelinek UINT32 i;
316*cb565728SJerry Jelinek
317*cb565728SJerry Jelinek /*
318*cb565728SJerry Jelinek * Get main ACPI tables from memory on first invocation of this
319*cb565728SJerry Jelinek * function.
320*cb565728SJerry Jelinek */
321*cb565728SJerry Jelinek
322*cb565728SJerry Jelinek Status = OslTableInitialize();
323*cb565728SJerry Jelinek if (ACPI_FAILURE(Status)) {
324*cb565728SJerry Jelinek return (Status);
325*cb565728SJerry Jelinek }
326*cb565728SJerry Jelinek
327*cb565728SJerry Jelinek /* Validate Index */
328*cb565728SJerry Jelinek
329*cb565728SJerry Jelinek if (Index >= Gbl_TableCount) {
330*cb565728SJerry Jelinek return (AE_LIMIT);
331*cb565728SJerry Jelinek }
332*cb565728SJerry Jelinek
333*cb565728SJerry Jelinek /* Point to the table list entry specified by the Index argument */
334*cb565728SJerry Jelinek
335*cb565728SJerry Jelinek Info = Gbl_TableListHead;
336*cb565728SJerry Jelinek for (i = 0; i < Index; i++) {
337*cb565728SJerry Jelinek Info = Info->Next;
338*cb565728SJerry Jelinek }
339*cb565728SJerry Jelinek
340*cb565728SJerry Jelinek /* Now we can just get the table via the signature */
341*cb565728SJerry Jelinek
342*cb565728SJerry Jelinek Status = AcpiOsGetTableByName(Info->Signature, Info->Instance,
343*cb565728SJerry Jelinek Table, Address);
344*cb565728SJerry Jelinek
345*cb565728SJerry Jelinek if (ACPI_SUCCESS(Status)) {
346*cb565728SJerry Jelinek *Instance = Info->Instance;
347*cb565728SJerry Jelinek }
348*cb565728SJerry Jelinek return (Status);
349*cb565728SJerry Jelinek }
350*cb565728SJerry Jelinek
351*cb565728SJerry Jelinek /*
352*cb565728SJerry Jelinek *
353*cb565728SJerry Jelinek * FUNCTION: OslLoadRsdp
354*cb565728SJerry Jelinek *
355*cb565728SJerry Jelinek * PARAMETERS: None
356*cb565728SJerry Jelinek *
357*cb565728SJerry Jelinek * RETURN: Status
358*cb565728SJerry Jelinek *
359*cb565728SJerry Jelinek * DESCRIPTION: Scan and load RSDP.
360*cb565728SJerry Jelinek * See the find_rsdp() function in usr/src/uts/i86pc/os/fakebop.c, which is how
361*cb565728SJerry Jelinek * the kernel finds the RSDP. That algorithm matches AcpiFindRootPointer().
362*cb565728SJerry Jelinek * The code here is derived from AcpiFindRootPointer, except that we will try
363*cb565728SJerry Jelinek * the BIOS if the EBDA fails, and we will copy the table if found.
364*cb565728SJerry Jelinek */
365*cb565728SJerry Jelinek static ACPI_STATUS
OslLoadRsdp(void)366*cb565728SJerry Jelinek OslLoadRsdp(void)
367*cb565728SJerry Jelinek {
368*cb565728SJerry Jelinek UINT8 *mapp;
369*cb565728SJerry Jelinek ACPI_TABLE_HEADER *tblp;
370*cb565728SJerry Jelinek ACPI_SIZE mapsize;
371*cb565728SJerry Jelinek ACPI_PHYSICAL_ADDRESS physaddr;
372*cb565728SJerry Jelinek
373*cb565728SJerry Jelinek /* 1a) Get the location of the Extended BIOS Data Area (EBDA) */
374*cb565728SJerry Jelinek mapp = AcpiOsMapMemory((ACPI_PHYSICAL_ADDRESS)ACPI_EBDA_PTR_LOCATION,
375*cb565728SJerry Jelinek ACPI_EBDA_PTR_LENGTH);
376*cb565728SJerry Jelinek if (mapp == NULL)
377*cb565728SJerry Jelinek goto try_bios;
378*cb565728SJerry Jelinek
379*cb565728SJerry Jelinek ACPI_MOVE_16_TO_32(&physaddr, mapp);
380*cb565728SJerry Jelinek
381*cb565728SJerry Jelinek /* Convert segment part to physical address */
382*cb565728SJerry Jelinek physaddr <<= 4;
383*cb565728SJerry Jelinek AcpiOsUnmapMemory(mapp, ACPI_EBDA_PTR_LENGTH);
384*cb565728SJerry Jelinek
385*cb565728SJerry Jelinek /* EBDA present? */
386*cb565728SJerry Jelinek if (physaddr <= 0x400)
387*cb565728SJerry Jelinek goto try_bios;
388*cb565728SJerry Jelinek
389*cb565728SJerry Jelinek /*
390*cb565728SJerry Jelinek * 1b) Search EBDA paragraphs (EBDA is required to be a minimum of 1K
391*cb565728SJerry Jelinek * length)
392*cb565728SJerry Jelinek */
393*cb565728SJerry Jelinek mapp = AcpiOsMapMemory(physaddr, ACPI_EBDA_WINDOW_SIZE);
394*cb565728SJerry Jelinek if (mapp == NULL) {
395*cb565728SJerry Jelinek (void) fprintf(stderr, "EBDA (0x%p) found, but is not "
396*cb565728SJerry Jelinek "mappable\n", physaddr);
397*cb565728SJerry Jelinek goto try_bios;
398*cb565728SJerry Jelinek }
399*cb565728SJerry Jelinek
400*cb565728SJerry Jelinek tblp = ACPI_CAST_PTR(ACPI_TABLE_HEADER,
401*cb565728SJerry Jelinek AcpiTbScanMemoryForRsdp(mapp, ACPI_EBDA_WINDOW_SIZE));
402*cb565728SJerry Jelinek if (tblp != NULL) {
403*cb565728SJerry Jelinek physaddr += (ACPI_PHYSICAL_ADDRESS) ACPI_PTR_DIFF(tblp, mapp);
404*cb565728SJerry Jelinek Gbl_RsdpAddress = physaddr;
405*cb565728SJerry Jelinek memcpy(&Gbl_Rsdp, tblp, sizeof (ACPI_TABLE_RSDP));
406*cb565728SJerry Jelinek AcpiOsUnmapMemory(mapp, ACPI_EBDA_WINDOW_SIZE);
407*cb565728SJerry Jelinek
408*cb565728SJerry Jelinek return (AE_OK);
409*cb565728SJerry Jelinek }
410*cb565728SJerry Jelinek AcpiOsUnmapMemory(mapp, ACPI_EBDA_WINDOW_SIZE);
411*cb565728SJerry Jelinek
412*cb565728SJerry Jelinek try_bios:
413*cb565728SJerry Jelinek /* Try to get RSDP from BIOS memory */
414*cb565728SJerry Jelinek if (Gbl_RsdpBase != NULL) {
415*cb565728SJerry Jelinek physaddr = Gbl_RsdpBase;
416*cb565728SJerry Jelinek mapsize = sizeof (ACPI_TABLE_RSDP);
417*cb565728SJerry Jelinek } else {
418*cb565728SJerry Jelinek physaddr = ACPI_HI_RSDP_WINDOW_BASE;
419*cb565728SJerry Jelinek mapsize = ACPI_HI_RSDP_WINDOW_SIZE;
420*cb565728SJerry Jelinek }
421*cb565728SJerry Jelinek
422*cb565728SJerry Jelinek mapp = AcpiOsMapMemory(physaddr, mapsize);
423*cb565728SJerry Jelinek if (mapp == NULL)
424*cb565728SJerry Jelinek return (OslGetLastStatus(AE_BAD_ADDRESS));
425*cb565728SJerry Jelinek
426*cb565728SJerry Jelinek /* Search low memory for the RSDP */
427*cb565728SJerry Jelinek tblp = ACPI_CAST_PTR(ACPI_TABLE_HEADER,
428*cb565728SJerry Jelinek AcpiTbScanMemoryForRsdp(mapp, mapsize));
429*cb565728SJerry Jelinek if (tblp == NULL) {
430*cb565728SJerry Jelinek AcpiOsUnmapMemory(mapp, mapsize);
431*cb565728SJerry Jelinek return (AE_NOT_FOUND);
432*cb565728SJerry Jelinek }
433*cb565728SJerry Jelinek
434*cb565728SJerry Jelinek physaddr += (ACPI_PHYSICAL_ADDRESS) ACPI_PTR_DIFF(tblp, mapp);
435*cb565728SJerry Jelinek Gbl_RsdpAddress = physaddr;
436*cb565728SJerry Jelinek memcpy(&Gbl_Rsdp, tblp, sizeof (ACPI_TABLE_RSDP));
437*cb565728SJerry Jelinek AcpiOsUnmapMemory(mapp, mapsize);
438*cb565728SJerry Jelinek
439*cb565728SJerry Jelinek return (AE_OK);
440*cb565728SJerry Jelinek }
441*cb565728SJerry Jelinek
442*cb565728SJerry Jelinek /*
443*cb565728SJerry Jelinek *
444*cb565728SJerry Jelinek * FUNCTION: OslCanUseXsdt
445*cb565728SJerry Jelinek *
446*cb565728SJerry Jelinek * PARAMETERS: None
447*cb565728SJerry Jelinek *
448*cb565728SJerry Jelinek * RETURN: TRUE if XSDT is allowed to be used.
449*cb565728SJerry Jelinek *
450*cb565728SJerry Jelinek * DESCRIPTION: This function collects logic that can be used to determine if
451*cb565728SJerry Jelinek * XSDT should be used instead of RSDT.
452*cb565728SJerry Jelinek *
453*cb565728SJerry Jelinek */
454*cb565728SJerry Jelinek static BOOLEAN
OslCanUseXsdt(void)455*cb565728SJerry Jelinek OslCanUseXsdt(void)
456*cb565728SJerry Jelinek {
457*cb565728SJerry Jelinek if (Gbl_Revision && !AcpiGbl_DoNotUseXsdt) {
458*cb565728SJerry Jelinek return (TRUE);
459*cb565728SJerry Jelinek } else {
460*cb565728SJerry Jelinek return (FALSE);
461*cb565728SJerry Jelinek }
462*cb565728SJerry Jelinek }
463*cb565728SJerry Jelinek
464*cb565728SJerry Jelinek /*
465*cb565728SJerry Jelinek *
466*cb565728SJerry Jelinek * FUNCTION: OslTableInitialize
467*cb565728SJerry Jelinek *
468*cb565728SJerry Jelinek * PARAMETERS: None
469*cb565728SJerry Jelinek *
470*cb565728SJerry Jelinek * RETURN: Status
471*cb565728SJerry Jelinek *
472*cb565728SJerry Jelinek * DESCRIPTION: Initialize ACPI table data. Get and store main ACPI tables to
473*cb565728SJerry Jelinek * local variables. Main ACPI tables include RSDT, FADT, RSDT,
474*cb565728SJerry Jelinek * and/or XSDT.
475*cb565728SJerry Jelinek *
476*cb565728SJerry Jelinek */
477*cb565728SJerry Jelinek static ACPI_STATUS
OslTableInitialize(void)478*cb565728SJerry Jelinek OslTableInitialize(void)
479*cb565728SJerry Jelinek {
480*cb565728SJerry Jelinek ACPI_STATUS Status;
481*cb565728SJerry Jelinek ACPI_PHYSICAL_ADDRESS Address;
482*cb565728SJerry Jelinek
483*cb565728SJerry Jelinek if (Gbl_TableListInitialized) {
484*cb565728SJerry Jelinek return (AE_OK);
485*cb565728SJerry Jelinek }
486*cb565728SJerry Jelinek
487*cb565728SJerry Jelinek /* Get RSDP from memory */
488*cb565728SJerry Jelinek
489*cb565728SJerry Jelinek Status = OslLoadRsdp();
490*cb565728SJerry Jelinek if (ACPI_FAILURE(Status)) {
491*cb565728SJerry Jelinek return (Status);
492*cb565728SJerry Jelinek }
493*cb565728SJerry Jelinek
494*cb565728SJerry Jelinek /* Get XSDT from memory */
495*cb565728SJerry Jelinek
496*cb565728SJerry Jelinek if (Gbl_Rsdp.Revision && !Gbl_DoNotDumpXsdt) {
497*cb565728SJerry Jelinek if (Gbl_Xsdt) {
498*cb565728SJerry Jelinek free(Gbl_Xsdt);
499*cb565728SJerry Jelinek Gbl_Xsdt = NULL;
500*cb565728SJerry Jelinek }
501*cb565728SJerry Jelinek
502*cb565728SJerry Jelinek Gbl_Revision = 2;
503*cb565728SJerry Jelinek Status = OslGetBiosTable(ACPI_SIG_XSDT, 0,
504*cb565728SJerry Jelinek ACPI_CAST_PTR(ACPI_TABLE_HEADER *, &Gbl_Xsdt), &Address);
505*cb565728SJerry Jelinek if (ACPI_FAILURE(Status)) {
506*cb565728SJerry Jelinek return (Status);
507*cb565728SJerry Jelinek }
508*cb565728SJerry Jelinek }
509*cb565728SJerry Jelinek
510*cb565728SJerry Jelinek /* Get RSDT from memory */
511*cb565728SJerry Jelinek
512*cb565728SJerry Jelinek if (Gbl_Rsdp.RsdtPhysicalAddress) {
513*cb565728SJerry Jelinek if (Gbl_Rsdt) {
514*cb565728SJerry Jelinek free(Gbl_Rsdt);
515*cb565728SJerry Jelinek Gbl_Rsdt = NULL;
516*cb565728SJerry Jelinek }
517*cb565728SJerry Jelinek
518*cb565728SJerry Jelinek Status = OslGetBiosTable(ACPI_SIG_RSDT, 0,
519*cb565728SJerry Jelinek ACPI_CAST_PTR(ACPI_TABLE_HEADER *, &Gbl_Rsdt), &Address);
520*cb565728SJerry Jelinek if (ACPI_FAILURE(Status)) {
521*cb565728SJerry Jelinek return (Status);
522*cb565728SJerry Jelinek }
523*cb565728SJerry Jelinek }
524*cb565728SJerry Jelinek
525*cb565728SJerry Jelinek /* Get FADT from memory */
526*cb565728SJerry Jelinek
527*cb565728SJerry Jelinek if (Gbl_Fadt) {
528*cb565728SJerry Jelinek free(Gbl_Fadt);
529*cb565728SJerry Jelinek Gbl_Fadt = NULL;
530*cb565728SJerry Jelinek }
531*cb565728SJerry Jelinek
532*cb565728SJerry Jelinek Status = OslGetBiosTable(ACPI_SIG_FADT, 0,
533*cb565728SJerry Jelinek ACPI_CAST_PTR(ACPI_TABLE_HEADER *, &Gbl_Fadt), &Gbl_FadtAddress);
534*cb565728SJerry Jelinek if (ACPI_FAILURE(Status)) {
535*cb565728SJerry Jelinek return (Status);
536*cb565728SJerry Jelinek }
537*cb565728SJerry Jelinek
538*cb565728SJerry Jelinek /* Add mandatory tables to global table list first */
539*cb565728SJerry Jelinek
540*cb565728SJerry Jelinek Status = OslAddTableToList(ACPI_RSDP_NAME);
541*cb565728SJerry Jelinek if (ACPI_FAILURE(Status)) {
542*cb565728SJerry Jelinek return (Status);
543*cb565728SJerry Jelinek }
544*cb565728SJerry Jelinek
545*cb565728SJerry Jelinek Status = OslAddTableToList(ACPI_SIG_RSDT);
546*cb565728SJerry Jelinek if (ACPI_FAILURE(Status)) {
547*cb565728SJerry Jelinek return (Status);
548*cb565728SJerry Jelinek }
549*cb565728SJerry Jelinek
550*cb565728SJerry Jelinek if (Gbl_Revision == 2) {
551*cb565728SJerry Jelinek Status = OslAddTableToList(ACPI_SIG_XSDT);
552*cb565728SJerry Jelinek if (ACPI_FAILURE(Status)) {
553*cb565728SJerry Jelinek return (Status);
554*cb565728SJerry Jelinek }
555*cb565728SJerry Jelinek }
556*cb565728SJerry Jelinek
557*cb565728SJerry Jelinek Status = OslAddTableToList(ACPI_SIG_DSDT);
558*cb565728SJerry Jelinek if (ACPI_FAILURE(Status)) {
559*cb565728SJerry Jelinek return (Status);
560*cb565728SJerry Jelinek }
561*cb565728SJerry Jelinek
562*cb565728SJerry Jelinek Status = OslAddTableToList(ACPI_SIG_FACS);
563*cb565728SJerry Jelinek if (ACPI_FAILURE(Status)) {
564*cb565728SJerry Jelinek return (Status);
565*cb565728SJerry Jelinek }
566*cb565728SJerry Jelinek
567*cb565728SJerry Jelinek /* Add all tables found in the memory */
568*cb565728SJerry Jelinek
569*cb565728SJerry Jelinek Status = OslListBiosTables();
570*cb565728SJerry Jelinek if (ACPI_FAILURE(Status)) {
571*cb565728SJerry Jelinek return (Status);
572*cb565728SJerry Jelinek }
573*cb565728SJerry Jelinek
574*cb565728SJerry Jelinek Gbl_TableListInitialized = TRUE;
575*cb565728SJerry Jelinek return (AE_OK);
576*cb565728SJerry Jelinek }
577*cb565728SJerry Jelinek
578*cb565728SJerry Jelinek
579*cb565728SJerry Jelinek /*
580*cb565728SJerry Jelinek *
581*cb565728SJerry Jelinek * FUNCTION: OslListBiosTables
582*cb565728SJerry Jelinek *
583*cb565728SJerry Jelinek * PARAMETERS: None
584*cb565728SJerry Jelinek *
585*cb565728SJerry Jelinek * RETURN: Status; Table list is initialized if AE_OK.
586*cb565728SJerry Jelinek *
587*cb565728SJerry Jelinek * DESCRIPTION: Add ACPI tables to the table list from memory.
588*cb565728SJerry Jelinek */
589*cb565728SJerry Jelinek static ACPI_STATUS
OslListBiosTables(void)590*cb565728SJerry Jelinek OslListBiosTables(void)
591*cb565728SJerry Jelinek {
592*cb565728SJerry Jelinek ACPI_TABLE_HEADER *MappedTable = NULL;
593*cb565728SJerry Jelinek UINT8 *TableData;
594*cb565728SJerry Jelinek UINT32 NumberOfTables;
595*cb565728SJerry Jelinek UINT8 ItemSize;
596*cb565728SJerry Jelinek ACPI_PHYSICAL_ADDRESS TableAddress = 0;
597*cb565728SJerry Jelinek ACPI_STATUS Status = AE_OK;
598*cb565728SJerry Jelinek UINT32 i;
599*cb565728SJerry Jelinek
600*cb565728SJerry Jelinek if (OslCanUseXsdt()) {
601*cb565728SJerry Jelinek ItemSize = sizeof (UINT64);
602*cb565728SJerry Jelinek TableData = ACPI_CAST8(Gbl_Xsdt) + sizeof (ACPI_TABLE_HEADER);
603*cb565728SJerry Jelinek NumberOfTables = (UINT32)
604*cb565728SJerry Jelinek ((Gbl_Xsdt->Header.Length - sizeof (ACPI_TABLE_HEADER))
605*cb565728SJerry Jelinek / ItemSize);
606*cb565728SJerry Jelinek
607*cb565728SJerry Jelinek } else {
608*cb565728SJerry Jelinek /* Use RSDT if XSDT is not available */
609*cb565728SJerry Jelinek ItemSize = sizeof (UINT32);
610*cb565728SJerry Jelinek TableData = ACPI_CAST8(Gbl_Rsdt) + sizeof (ACPI_TABLE_HEADER);
611*cb565728SJerry Jelinek NumberOfTables = (UINT32)
612*cb565728SJerry Jelinek ((Gbl_Rsdt->Header.Length - sizeof (ACPI_TABLE_HEADER))
613*cb565728SJerry Jelinek / ItemSize);
614*cb565728SJerry Jelinek }
615*cb565728SJerry Jelinek
616*cb565728SJerry Jelinek /* Search RSDT/XSDT for the requested table */
617*cb565728SJerry Jelinek
618*cb565728SJerry Jelinek for (i = 0; i < NumberOfTables; ++i, TableData += ItemSize) {
619*cb565728SJerry Jelinek if (OslCanUseXsdt()) {
620*cb565728SJerry Jelinek TableAddress =
621*cb565728SJerry Jelinek (ACPI_PHYSICAL_ADDRESS) (*ACPI_CAST64(TableData));
622*cb565728SJerry Jelinek } else {
623*cb565728SJerry Jelinek TableAddress =
624*cb565728SJerry Jelinek (ACPI_PHYSICAL_ADDRESS) (*ACPI_CAST32(TableData));
625*cb565728SJerry Jelinek }
626*cb565728SJerry Jelinek
627*cb565728SJerry Jelinek /* Skip NULL entries in RSDT/XSDT */
628*cb565728SJerry Jelinek if (TableAddress == NULL) {
629*cb565728SJerry Jelinek continue;
630*cb565728SJerry Jelinek }
631*cb565728SJerry Jelinek
632*cb565728SJerry Jelinek Status = OslMapTable(TableAddress, NULL, &MappedTable);
633*cb565728SJerry Jelinek if (ACPI_FAILURE(Status)) {
634*cb565728SJerry Jelinek return (Status);
635*cb565728SJerry Jelinek }
636*cb565728SJerry Jelinek
637*cb565728SJerry Jelinek OslAddTableToList(MappedTable->Signature);
638*cb565728SJerry Jelinek OslUnmapTable(MappedTable);
639*cb565728SJerry Jelinek }
640*cb565728SJerry Jelinek
641*cb565728SJerry Jelinek return (AE_OK);
642*cb565728SJerry Jelinek }
643*cb565728SJerry Jelinek
644*cb565728SJerry Jelinek /*
645*cb565728SJerry Jelinek *
646*cb565728SJerry Jelinek * FUNCTION: OslGetBiosTable
647*cb565728SJerry Jelinek *
648*cb565728SJerry Jelinek * PARAMETERS: Signature - ACPI Signature for common table. Must be
649*cb565728SJerry Jelinek * a null terminated 4-character string.
650*cb565728SJerry Jelinek * Instance - Multiple table support for SSDT/UEFI (0...n)
651*cb565728SJerry Jelinek * Must be 0 for other tables.
652*cb565728SJerry Jelinek * Table - Where a pointer to the table is returned
653*cb565728SJerry Jelinek * Address - Where the table physical address is returned
654*cb565728SJerry Jelinek *
655*cb565728SJerry Jelinek * RETURN: Status; Table buffer and physical address returned if AE_OK.
656*cb565728SJerry Jelinek * AE_LIMIT: Instance is beyond valid limit
657*cb565728SJerry Jelinek * AE_NOT_FOUND: A table with the signature was not found
658*cb565728SJerry Jelinek *
659*cb565728SJerry Jelinek * DESCRIPTION: Get a BIOS provided ACPI table
660*cb565728SJerry Jelinek *
661*cb565728SJerry Jelinek * NOTE: Assumes the input signature is uppercase.
662*cb565728SJerry Jelinek *
663*cb565728SJerry Jelinek */
664*cb565728SJerry Jelinek static ACPI_STATUS
OslGetBiosTable(char * Signature,UINT32 Instance,ACPI_TABLE_HEADER ** Table,ACPI_PHYSICAL_ADDRESS * Address)665*cb565728SJerry Jelinek OslGetBiosTable(char *Signature, UINT32 Instance, ACPI_TABLE_HEADER **Table,
666*cb565728SJerry Jelinek ACPI_PHYSICAL_ADDRESS *Address)
667*cb565728SJerry Jelinek {
668*cb565728SJerry Jelinek ACPI_TABLE_HEADER *LocalTable = NULL;
669*cb565728SJerry Jelinek ACPI_TABLE_HEADER *MappedTable = NULL;
670*cb565728SJerry Jelinek UINT8 *TableData;
671*cb565728SJerry Jelinek UINT8 NumberOfTables;
672*cb565728SJerry Jelinek UINT8 ItemSize;
673*cb565728SJerry Jelinek UINT32 CurrentInstance = 0;
674*cb565728SJerry Jelinek ACPI_PHYSICAL_ADDRESS TableAddress = 0;
675*cb565728SJerry Jelinek UINT32 TableLength = 0;
676*cb565728SJerry Jelinek ACPI_STATUS Status = AE_OK;
677*cb565728SJerry Jelinek UINT32 i;
678*cb565728SJerry Jelinek
679*cb565728SJerry Jelinek /* Handle special tables whose addresses are not in RSDT/XSDT */
680*cb565728SJerry Jelinek
681*cb565728SJerry Jelinek if (ACPI_COMPARE_NAME(Signature, ACPI_RSDP_NAME) ||
682*cb565728SJerry Jelinek ACPI_COMPARE_NAME(Signature, ACPI_SIG_RSDT) ||
683*cb565728SJerry Jelinek ACPI_COMPARE_NAME(Signature, ACPI_SIG_XSDT) ||
684*cb565728SJerry Jelinek ACPI_COMPARE_NAME(Signature, ACPI_SIG_DSDT) ||
685*cb565728SJerry Jelinek ACPI_COMPARE_NAME(Signature, ACPI_SIG_FACS)) {
686*cb565728SJerry Jelinek if (Instance > 0) {
687*cb565728SJerry Jelinek return (AE_LIMIT);
688*cb565728SJerry Jelinek }
689*cb565728SJerry Jelinek
690*cb565728SJerry Jelinek /*
691*cb565728SJerry Jelinek * Get the appropriate address, either 32-bit or 64-bit. Be very
692*cb565728SJerry Jelinek * careful about the FADT length and validate table addresses.
693*cb565728SJerry Jelinek * Note: The 64-bit addresses have priority.
694*cb565728SJerry Jelinek */
695*cb565728SJerry Jelinek if (ACPI_COMPARE_NAME(Signature, ACPI_SIG_DSDT)) {
696*cb565728SJerry Jelinek if ((Gbl_Fadt->Header.Length >= MIN_FADT_FOR_XDSDT) &&
697*cb565728SJerry Jelinek Gbl_Fadt->XDsdt) {
698*cb565728SJerry Jelinek TableAddress =
699*cb565728SJerry Jelinek (ACPI_PHYSICAL_ADDRESS) Gbl_Fadt->XDsdt;
700*cb565728SJerry Jelinek
701*cb565728SJerry Jelinek } else if (Gbl_Fadt->Header.Length >=
702*cb565728SJerry Jelinek MIN_FADT_FOR_DSDT && Gbl_Fadt->Dsdt) {
703*cb565728SJerry Jelinek TableAddress =
704*cb565728SJerry Jelinek (ACPI_PHYSICAL_ADDRESS) Gbl_Fadt->Dsdt;
705*cb565728SJerry Jelinek }
706*cb565728SJerry Jelinek
707*cb565728SJerry Jelinek } else if (ACPI_COMPARE_NAME(Signature, ACPI_SIG_FACS)) {
708*cb565728SJerry Jelinek if ((Gbl_Fadt->Header.Length >= MIN_FADT_FOR_XFACS) &&
709*cb565728SJerry Jelinek Gbl_Fadt->XFacs) {
710*cb565728SJerry Jelinek TableAddress =
711*cb565728SJerry Jelinek (ACPI_PHYSICAL_ADDRESS) Gbl_Fadt->XFacs;
712*cb565728SJerry Jelinek
713*cb565728SJerry Jelinek } else if (Gbl_Fadt->Header.Length >=
714*cb565728SJerry Jelinek MIN_FADT_FOR_FACS && Gbl_Fadt->Facs) {
715*cb565728SJerry Jelinek TableAddress =
716*cb565728SJerry Jelinek (ACPI_PHYSICAL_ADDRESS) Gbl_Fadt->Facs;
717*cb565728SJerry Jelinek }
718*cb565728SJerry Jelinek
719*cb565728SJerry Jelinek } else if (ACPI_COMPARE_NAME(Signature, ACPI_SIG_XSDT)) {
720*cb565728SJerry Jelinek if (!Gbl_Revision) {
721*cb565728SJerry Jelinek return (AE_BAD_SIGNATURE);
722*cb565728SJerry Jelinek }
723*cb565728SJerry Jelinek TableAddress = (ACPI_PHYSICAL_ADDRESS)
724*cb565728SJerry Jelinek Gbl_Rsdp.XsdtPhysicalAddress;
725*cb565728SJerry Jelinek
726*cb565728SJerry Jelinek } else if (ACPI_COMPARE_NAME(Signature, ACPI_SIG_RSDT)) {
727*cb565728SJerry Jelinek TableAddress = (ACPI_PHYSICAL_ADDRESS)
728*cb565728SJerry Jelinek Gbl_Rsdp.RsdtPhysicalAddress;
729*cb565728SJerry Jelinek
730*cb565728SJerry Jelinek } else {
731*cb565728SJerry Jelinek TableAddress = (ACPI_PHYSICAL_ADDRESS) Gbl_RsdpAddress;
732*cb565728SJerry Jelinek Signature = ACPI_SIG_RSDP;
733*cb565728SJerry Jelinek }
734*cb565728SJerry Jelinek
735*cb565728SJerry Jelinek /* Now we can get the requested special table */
736*cb565728SJerry Jelinek
737*cb565728SJerry Jelinek Status = OslMapTable(TableAddress, Signature, &MappedTable);
738*cb565728SJerry Jelinek if (ACPI_FAILURE(Status)) {
739*cb565728SJerry Jelinek return (Status);
740*cb565728SJerry Jelinek }
741*cb565728SJerry Jelinek
742*cb565728SJerry Jelinek TableLength = ApGetTableLength(MappedTable);
743*cb565728SJerry Jelinek
744*cb565728SJerry Jelinek } else {
745*cb565728SJerry Jelinek /* Case for a normal ACPI table */
746*cb565728SJerry Jelinek if (OslCanUseXsdt()) {
747*cb565728SJerry Jelinek ItemSize = sizeof (UINT64);
748*cb565728SJerry Jelinek TableData = ACPI_CAST8(Gbl_Xsdt) +
749*cb565728SJerry Jelinek sizeof (ACPI_TABLE_HEADER);
750*cb565728SJerry Jelinek NumberOfTables = (UINT8) ((Gbl_Xsdt->Header.Length -
751*cb565728SJerry Jelinek sizeof (ACPI_TABLE_HEADER))
752*cb565728SJerry Jelinek / ItemSize);
753*cb565728SJerry Jelinek
754*cb565728SJerry Jelinek } else {
755*cb565728SJerry Jelinek /* Use RSDT if XSDT is not available */
756*cb565728SJerry Jelinek ItemSize = sizeof (UINT32);
757*cb565728SJerry Jelinek TableData = ACPI_CAST8(Gbl_Rsdt) +
758*cb565728SJerry Jelinek sizeof (ACPI_TABLE_HEADER);
759*cb565728SJerry Jelinek NumberOfTables = (UINT8) ((Gbl_Rsdt->Header.Length -
760*cb565728SJerry Jelinek sizeof (ACPI_TABLE_HEADER))
761*cb565728SJerry Jelinek / ItemSize);
762*cb565728SJerry Jelinek }
763*cb565728SJerry Jelinek
764*cb565728SJerry Jelinek /* Search RSDT/XSDT for the requested table */
765*cb565728SJerry Jelinek
766*cb565728SJerry Jelinek for (i = 0; i < NumberOfTables; ++i, TableData += ItemSize) {
767*cb565728SJerry Jelinek if (OslCanUseXsdt()) {
768*cb565728SJerry Jelinek TableAddress = (ACPI_PHYSICAL_ADDRESS)
769*cb565728SJerry Jelinek (*ACPI_CAST64(TableData));
770*cb565728SJerry Jelinek } else {
771*cb565728SJerry Jelinek TableAddress = (ACPI_PHYSICAL_ADDRESS)
772*cb565728SJerry Jelinek (*ACPI_CAST32(TableData));
773*cb565728SJerry Jelinek }
774*cb565728SJerry Jelinek
775*cb565728SJerry Jelinek /* Skip NULL entries in RSDT/XSDT */
776*cb565728SJerry Jelinek
777*cb565728SJerry Jelinek if (TableAddress == NULL) {
778*cb565728SJerry Jelinek continue;
779*cb565728SJerry Jelinek }
780*cb565728SJerry Jelinek
781*cb565728SJerry Jelinek Status = OslMapTable(TableAddress, NULL, &MappedTable);
782*cb565728SJerry Jelinek if (ACPI_FAILURE(Status)) {
783*cb565728SJerry Jelinek return (Status);
784*cb565728SJerry Jelinek }
785*cb565728SJerry Jelinek TableLength = MappedTable->Length;
786*cb565728SJerry Jelinek
787*cb565728SJerry Jelinek /* Does this table match the requested signature? */
788*cb565728SJerry Jelinek
789*cb565728SJerry Jelinek if (!ACPI_COMPARE_NAME(MappedTable->Signature,
790*cb565728SJerry Jelinek Signature)) {
791*cb565728SJerry Jelinek OslUnmapTable(MappedTable);
792*cb565728SJerry Jelinek MappedTable = NULL;
793*cb565728SJerry Jelinek continue;
794*cb565728SJerry Jelinek }
795*cb565728SJerry Jelinek
796*cb565728SJerry Jelinek /* Match table instance (for SSDT/UEFI tables) */
797*cb565728SJerry Jelinek
798*cb565728SJerry Jelinek if (CurrentInstance != Instance) {
799*cb565728SJerry Jelinek OslUnmapTable(MappedTable);
800*cb565728SJerry Jelinek MappedTable = NULL;
801*cb565728SJerry Jelinek CurrentInstance++;
802*cb565728SJerry Jelinek continue;
803*cb565728SJerry Jelinek }
804*cb565728SJerry Jelinek
805*cb565728SJerry Jelinek break;
806*cb565728SJerry Jelinek }
807*cb565728SJerry Jelinek }
808*cb565728SJerry Jelinek
809*cb565728SJerry Jelinek if (MappedTable == NULL) {
810*cb565728SJerry Jelinek return (AE_LIMIT);
811*cb565728SJerry Jelinek }
812*cb565728SJerry Jelinek
813*cb565728SJerry Jelinek if (TableLength == 0) {
814*cb565728SJerry Jelinek Status = AE_BAD_HEADER;
815*cb565728SJerry Jelinek goto Exit;
816*cb565728SJerry Jelinek }
817*cb565728SJerry Jelinek
818*cb565728SJerry Jelinek /* Copy table to local buffer and return it */
819*cb565728SJerry Jelinek
820*cb565728SJerry Jelinek LocalTable = calloc(1, TableLength);
821*cb565728SJerry Jelinek if (LocalTable == NULL) {
822*cb565728SJerry Jelinek Status = AE_NO_MEMORY;
823*cb565728SJerry Jelinek goto Exit;
824*cb565728SJerry Jelinek }
825*cb565728SJerry Jelinek
826*cb565728SJerry Jelinek memcpy(LocalTable, MappedTable, TableLength);
827*cb565728SJerry Jelinek *Address = TableAddress;
828*cb565728SJerry Jelinek *Table = LocalTable;
829*cb565728SJerry Jelinek
830*cb565728SJerry Jelinek Exit:
831*cb565728SJerry Jelinek OslUnmapTable(MappedTable);
832*cb565728SJerry Jelinek return (Status);
833*cb565728SJerry Jelinek }
834*cb565728SJerry Jelinek
835*cb565728SJerry Jelinek /*
836*cb565728SJerry Jelinek *
837*cb565728SJerry Jelinek * FUNCTION: OslMapTable
838*cb565728SJerry Jelinek *
839*cb565728SJerry Jelinek * PARAMETERS: Address - Address of the table in memory
840*cb565728SJerry Jelinek * Signature - Optional ACPI Signature for desired table.
841*cb565728SJerry Jelinek * Null terminated 4-character string.
842*cb565728SJerry Jelinek * Table - Where a pointer to the mapped table is
843*cb565728SJerry Jelinek * returned
844*cb565728SJerry Jelinek *
845*cb565728SJerry Jelinek * RETURN: Status; Mapped table is returned if AE_OK.
846*cb565728SJerry Jelinek * AE_NOT_FOUND: A valid table was not found at the address
847*cb565728SJerry Jelinek *
848*cb565728SJerry Jelinek * DESCRIPTION: Map entire ACPI table into caller's address space.
849*cb565728SJerry Jelinek *
850*cb565728SJerry Jelinek */
851*cb565728SJerry Jelinek static ACPI_STATUS
OslMapTable(ACPI_SIZE Address,char * Signature,ACPI_TABLE_HEADER ** Table)852*cb565728SJerry Jelinek OslMapTable(ACPI_SIZE Address, char *Signature, ACPI_TABLE_HEADER **Table)
853*cb565728SJerry Jelinek {
854*cb565728SJerry Jelinek ACPI_TABLE_HEADER *MappedTable;
855*cb565728SJerry Jelinek UINT32 Length;
856*cb565728SJerry Jelinek
857*cb565728SJerry Jelinek if (Address == NULL) {
858*cb565728SJerry Jelinek return (AE_BAD_ADDRESS);
859*cb565728SJerry Jelinek }
860*cb565728SJerry Jelinek
861*cb565728SJerry Jelinek /*
862*cb565728SJerry Jelinek * Map the header so we can get the table length.
863*cb565728SJerry Jelinek * Use sizeof (ACPI_TABLE_HEADER) as:
864*cb565728SJerry Jelinek * 1. it is bigger than 24 to include RSDP->Length
865*cb565728SJerry Jelinek * 2. it is smaller than sizeof (ACPI_TABLE_RSDP)
866*cb565728SJerry Jelinek */
867*cb565728SJerry Jelinek MappedTable = AcpiOsMapMemory(Address, sizeof (ACPI_TABLE_HEADER));
868*cb565728SJerry Jelinek if (MappedTable == NULL) {
869*cb565728SJerry Jelinek (void) fprintf(stderr, "Could not map table header at "
870*cb565728SJerry Jelinek "0x%8.8X%8.8X\n", ACPI_FORMAT_UINT64(Address));
871*cb565728SJerry Jelinek return (OslGetLastStatus(AE_BAD_ADDRESS));
872*cb565728SJerry Jelinek }
873*cb565728SJerry Jelinek
874*cb565728SJerry Jelinek /* If specified, signature must match */
875*cb565728SJerry Jelinek
876*cb565728SJerry Jelinek if (Signature != NULL) {
877*cb565728SJerry Jelinek if (ACPI_VALIDATE_RSDP_SIG(Signature)) {
878*cb565728SJerry Jelinek if (!ACPI_VALIDATE_RSDP_SIG(MappedTable->Signature)) {
879*cb565728SJerry Jelinek AcpiOsUnmapMemory(MappedTable,
880*cb565728SJerry Jelinek sizeof (ACPI_TABLE_HEADER));
881*cb565728SJerry Jelinek return (AE_BAD_SIGNATURE);
882*cb565728SJerry Jelinek }
883*cb565728SJerry Jelinek } else if (!ACPI_COMPARE_NAME(Signature,
884*cb565728SJerry Jelinek MappedTable->Signature)) {
885*cb565728SJerry Jelinek AcpiOsUnmapMemory(MappedTable,
886*cb565728SJerry Jelinek sizeof (ACPI_TABLE_HEADER));
887*cb565728SJerry Jelinek return (AE_BAD_SIGNATURE);
888*cb565728SJerry Jelinek }
889*cb565728SJerry Jelinek }
890*cb565728SJerry Jelinek
891*cb565728SJerry Jelinek /* Map the entire table */
892*cb565728SJerry Jelinek
893*cb565728SJerry Jelinek Length = ApGetTableLength(MappedTable);
894*cb565728SJerry Jelinek AcpiOsUnmapMemory(MappedTable, sizeof (ACPI_TABLE_HEADER));
895*cb565728SJerry Jelinek if (Length == 0) {
896*cb565728SJerry Jelinek return (AE_BAD_HEADER);
897*cb565728SJerry Jelinek }
898*cb565728SJerry Jelinek
899*cb565728SJerry Jelinek MappedTable = AcpiOsMapMemory(Address, Length);
900*cb565728SJerry Jelinek if (MappedTable == NULL) {
901*cb565728SJerry Jelinek (void) fprintf(stderr, "Could not map table at 0x%8.8X%8.8X "
902*cb565728SJerry Jelinek "length %8.8X\n", ACPI_FORMAT_UINT64(Address), Length);
903*cb565728SJerry Jelinek return (OslGetLastStatus(AE_INVALID_TABLE_LENGTH));
904*cb565728SJerry Jelinek }
905*cb565728SJerry Jelinek
906*cb565728SJerry Jelinek (void) ApIsValidChecksum(MappedTable);
907*cb565728SJerry Jelinek
908*cb565728SJerry Jelinek *Table = MappedTable;
909*cb565728SJerry Jelinek return (AE_OK);
910*cb565728SJerry Jelinek }
911*cb565728SJerry Jelinek
912*cb565728SJerry Jelinek
913*cb565728SJerry Jelinek /*
914*cb565728SJerry Jelinek *
915*cb565728SJerry Jelinek * FUNCTION: OslUnmapTable
916*cb565728SJerry Jelinek *
917*cb565728SJerry Jelinek * PARAMETERS: Table - A pointer to the mapped table
918*cb565728SJerry Jelinek *
919*cb565728SJerry Jelinek * RETURN: None
920*cb565728SJerry Jelinek *
921*cb565728SJerry Jelinek * DESCRIPTION: Unmap entire ACPI table.
922*cb565728SJerry Jelinek *
923*cb565728SJerry Jelinek */
924*cb565728SJerry Jelinek static void
OslUnmapTable(ACPI_TABLE_HEADER * Table)925*cb565728SJerry Jelinek OslUnmapTable(ACPI_TABLE_HEADER *Table)
926*cb565728SJerry Jelinek {
927*cb565728SJerry Jelinek if (Table != NULL) {
928*cb565728SJerry Jelinek AcpiOsUnmapMemory(Table, ApGetTableLength(Table));
929*cb565728SJerry Jelinek }
930*cb565728SJerry Jelinek }
931*cb565728SJerry Jelinek
932*cb565728SJerry Jelinek /*
933*cb565728SJerry Jelinek *
934*cb565728SJerry Jelinek * FUNCTION: OslTableNameFromFile
935*cb565728SJerry Jelinek *
936*cb565728SJerry Jelinek * PARAMETERS: Filename - File that contains the desired table
937*cb565728SJerry Jelinek * Signature - Pointer to 4-character buffer to store
938*cb565728SJerry Jelinek * extracted table signature.
939*cb565728SJerry Jelinek * Instance - Pointer to integer to store extracted
940*cb565728SJerry Jelinek * table instance number.
941*cb565728SJerry Jelinek *
942*cb565728SJerry Jelinek * RETURN: Status; Table name is extracted if AE_OK.
943*cb565728SJerry Jelinek *
944*cb565728SJerry Jelinek * DESCRIPTION: Extract table signature and instance number from a table file
945*cb565728SJerry Jelinek * name.
946*cb565728SJerry Jelinek *
947*cb565728SJerry Jelinek */
948*cb565728SJerry Jelinek static ACPI_STATUS
OslTableNameFromFile(char * Filename,char * Signature,UINT32 * Instance)949*cb565728SJerry Jelinek OslTableNameFromFile(char *Filename, char *Signature, UINT32 *Instance)
950*cb565728SJerry Jelinek {
951*cb565728SJerry Jelinek /* Ignore meaningless files */
952*cb565728SJerry Jelinek
953*cb565728SJerry Jelinek if (strlen(Filename) < ACPI_NAME_SIZE) {
954*cb565728SJerry Jelinek return (AE_BAD_SIGNATURE);
955*cb565728SJerry Jelinek }
956*cb565728SJerry Jelinek
957*cb565728SJerry Jelinek /* Extract instance number */
958*cb565728SJerry Jelinek
959*cb565728SJerry Jelinek if (isdigit((int)Filename[ACPI_NAME_SIZE])) {
960*cb565728SJerry Jelinek sscanf(&Filename[ACPI_NAME_SIZE], "%u", Instance);
961*cb565728SJerry Jelinek } else if (strlen(Filename) != ACPI_NAME_SIZE) {
962*cb565728SJerry Jelinek return (AE_BAD_SIGNATURE);
963*cb565728SJerry Jelinek } else {
964*cb565728SJerry Jelinek *Instance = 0;
965*cb565728SJerry Jelinek }
966*cb565728SJerry Jelinek
967*cb565728SJerry Jelinek /* Extract signature */
968*cb565728SJerry Jelinek
969*cb565728SJerry Jelinek ACPI_MOVE_NAME(Signature, Filename);
970*cb565728SJerry Jelinek return (AE_OK);
971*cb565728SJerry Jelinek }
972*cb565728SJerry Jelinek
973*cb565728SJerry Jelinek UINT32
CmGetFileSize(ACPI_FILE File)974*cb565728SJerry Jelinek CmGetFileSize(ACPI_FILE File)
975*cb565728SJerry Jelinek {
976*cb565728SJerry Jelinek int fd;
977*cb565728SJerry Jelinek struct stat sb;
978*cb565728SJerry Jelinek
979*cb565728SJerry Jelinek fd = fileno(File);
980*cb565728SJerry Jelinek if (fstat(fd, &sb) != 0)
981*cb565728SJerry Jelinek return (ACPI_UINT32_MAX);
982*cb565728SJerry Jelinek return ((UINT32)sb.st_size);
983*cb565728SJerry Jelinek }
984*cb565728SJerry Jelinek
985*cb565728SJerry Jelinek void *
AcpiOsAllocateZeroed(ACPI_SIZE Size)986*cb565728SJerry Jelinek AcpiOsAllocateZeroed(ACPI_SIZE Size)
987*cb565728SJerry Jelinek {
988*cb565728SJerry Jelinek return (calloc(1, Size));
989*cb565728SJerry Jelinek }
990*cb565728SJerry Jelinek
991*cb565728SJerry Jelinek void
AcpiOsFree(void * p)992*cb565728SJerry Jelinek AcpiOsFree(void *p)
993*cb565728SJerry Jelinek {
994*cb565728SJerry Jelinek free(p);
995*cb565728SJerry Jelinek }
996*cb565728SJerry Jelinek
997*cb565728SJerry Jelinek ACPI_FILE
AcpiOsOpenFile(const char * Path,UINT8 Modes)998*cb565728SJerry Jelinek AcpiOsOpenFile(const char *Path, UINT8 Modes)
999*cb565728SJerry Jelinek {
1000*cb565728SJerry Jelinek char mode[3];
1001*cb565728SJerry Jelinek
1002*cb565728SJerry Jelinek bzero(mode, sizeof (mode));
1003*cb565728SJerry Jelinek if ((Modes & ACPI_FILE_READING) != 0)
1004*cb565728SJerry Jelinek (void) strlcat(mode, "r", sizeof (mode));
1005*cb565728SJerry Jelinek
1006*cb565728SJerry Jelinek if ((Modes & ACPI_FILE_WRITING) != 0)
1007*cb565728SJerry Jelinek (void) strlcat(mode, "w", sizeof (mode));
1008*cb565728SJerry Jelinek
1009*cb565728SJerry Jelinek return (fopen(Path, mode));
1010*cb565728SJerry Jelinek }
1011*cb565728SJerry Jelinek
1012*cb565728SJerry Jelinek void
AcpiOsCloseFile(ACPI_FILE File)1013*cb565728SJerry Jelinek AcpiOsCloseFile(ACPI_FILE File)
1014*cb565728SJerry Jelinek {
1015*cb565728SJerry Jelinek fclose(File);
1016*cb565728SJerry Jelinek }
1017*cb565728SJerry Jelinek
1018*cb565728SJerry Jelinek int
AcpiOsReadFile(ACPI_FILE File,void * Buffer,ACPI_SIZE Size,ACPI_SIZE Count)1019*cb565728SJerry Jelinek AcpiOsReadFile(ACPI_FILE File, void *Buffer, ACPI_SIZE Size, ACPI_SIZE Count)
1020*cb565728SJerry Jelinek {
1021*cb565728SJerry Jelinek return (fread(Buffer, Size, Count, File));
1022*cb565728SJerry Jelinek }
1023*cb565728SJerry Jelinek
1024*cb565728SJerry Jelinek void *
AcpiOsMapMemory(ACPI_PHYSICAL_ADDRESS Where,ACPI_SIZE Length)1025*cb565728SJerry Jelinek AcpiOsMapMemory(ACPI_PHYSICAL_ADDRESS Where, ACPI_SIZE Length)
1026*cb565728SJerry Jelinek {
1027*cb565728SJerry Jelinek int fd;
1028*cb565728SJerry Jelinek void *p;
1029*cb565728SJerry Jelinek ulong_t offset;
1030*cb565728SJerry Jelinek
1031*cb565728SJerry Jelinek if ((fd = open("/dev/xsvc", O_RDONLY)) < 0)
1032*cb565728SJerry Jelinek return (NULL);
1033*cb565728SJerry Jelinek
1034*cb565728SJerry Jelinek if (pagesize == 0) {
1035*cb565728SJerry Jelinek pagesize = getpagesize();
1036*cb565728SJerry Jelinek }
1037*cb565728SJerry Jelinek
1038*cb565728SJerry Jelinek offset = Where % pagesize;
1039*cb565728SJerry Jelinek p = mmap(NULL, Length + offset, PROT_READ, MAP_SHARED | MAP_NORESERVE,
1040*cb565728SJerry Jelinek fd, Where - offset);
1041*cb565728SJerry Jelinek
1042*cb565728SJerry Jelinek (void) close(fd);
1043*cb565728SJerry Jelinek
1044*cb565728SJerry Jelinek if (p == MAP_FAILED)
1045*cb565728SJerry Jelinek return (NULL);
1046*cb565728SJerry Jelinek p = (char *)p + offset;
1047*cb565728SJerry Jelinek return (p);
1048*cb565728SJerry Jelinek }
1049*cb565728SJerry Jelinek
1050*cb565728SJerry Jelinek void
AcpiOsUnmapMemory(void * LogicalAddress,ACPI_SIZE Size)1051*cb565728SJerry Jelinek AcpiOsUnmapMemory(void *LogicalAddress, ACPI_SIZE Size)
1052*cb565728SJerry Jelinek {
1053*cb565728SJerry Jelinek ulong_t offset;
1054*cb565728SJerry Jelinek void *p;
1055*cb565728SJerry Jelinek
1056*cb565728SJerry Jelinek offset = (ulong_t)LogicalAddress % pagesize;
1057*cb565728SJerry Jelinek p = (void *)((char *)LogicalAddress - offset);
1058*cb565728SJerry Jelinek
1059*cb565728SJerry Jelinek (void) munmap(p, Size + offset);
1060*cb565728SJerry Jelinek }
1061