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