Chameleon

Chameleon Svn Source Tree

Root/branches/cparm/i386/libsaio/acpi_tools.c

  • Property svn:executable set to *
1/*
2 Copyright (c) 2010, Intel Corporation
3 All rights reserved.
4
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions are met:
7
8 * Redistributions of source code must retain the above copyright notice,
9 this list of conditions and the following disclaimer.
10 * Redistributions in binary form must reproduce the above copyright notice,
11 this list of conditions and the following disclaimer in the documentation
12 and/or other materials provided with the distribution.
13 * Neither the name of Intel Corporation nor the names of its contributors
14 may be used to endorse or promote products derived from this software
15 without specific prior written permission.
16
17 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
18 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
21 ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
24 ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28#include "libsaio.h"
29#include "bootstruct.h"
30#include "datatype.h"
31#include "intel_acpi.h"
32#include "ppm.h"
33#include "acpi_tools.h"
34
35static U32 GetRsdtPointer(void *mem_addr, U32 mem_size, ACPI_TABLES * acpi_tables);
36static U32 GetXsdtPointer(ACPI_TABLES * acpi_tables);
37static ACPI_TABLE_HEADER *GetTablePtr(ACPI_TABLE_RSDT * rsdt, U32 signature);
38static ACPI_TABLE_HEADER *GetTablePtr64(ACPI_TABLE_XSDT * xsdt, U32 signature);
39
40//-------------------------------------------------------------------------------
41//
42// Procedure: FindAcpiTables - Collects addresses for RSDP, RSDT, FADT, & DSDT.
43//
44// Description: Finds the differentiated system description table pointer
45// by scanning and checking ACPI tables. This function will
46// get and store the following ACPI Table Pointers:
47// 1) RSD Pointer in RsdPointer Variable
48// 2) RSDT Pointer in RsdtPointer Variable(RSDP->RSDT)
49// 3) XSDT Pointer in XsdtPointer Variable(RSDP->XSDT)
50// 4) FACP Pointer in FacpPointer Variable(RSDP->RSDT->FACP)
51// 5) FACP(64) Pointer in FacpPointer64 Variable(RSDP->XSDT->FACP)
52// 6) DSDT Pointer in DsdtPointer Variable(RSDP->RSDT->FACP->DSDT)
53// 7) DSDT(64) Pointer in DsdtPointer64 Variable(RSDP->XSDT->FACP->XDSDT)
54// 8) FACS Pointer in FacsPointer Variable(RSDP->RSDT->FACP->FACS)
55// 9) FACS(64) Pointer in FacsPointer64 Variable(RSDP->XSDT->FACP->XFACS)
56// A) MADT Pointer in FacsPointer Variable(RSDP->RSDT->APIC)
57// B) MADT(64) Pointer in MadtPointer64 Variable(RSDP->XSDT->APIC)
58//
59//-------------------------------------------------------------------------------
60U32 FindAcpiTables(ACPI_TABLES * acpi_tables)
61{
62 U32 success = 0ul;
63
64 // Perform init of ACPI table pointers
65 {
66 void *null = 0ul;
67 acpi_tables->DsdtPointer = null;
68 acpi_tables->DsdtPointer64 = null;
69 acpi_tables->FacpPointer = null;
70 acpi_tables->FacsPointer = null;
71 acpi_tables->FacsPointer64 = null;
72 acpi_tables->RsdPointer = null;
73 acpi_tables->RsdtPointer = null;
74 acpi_tables->MadtPointer = null;
75acpi_tables->MadtPointer64 = null;
76 acpi_tables->XsdtPointer = null;
77 acpi_tables->FacpPointer64 = null;
78 }
79
80 // Find the RSDT pointer by scanning EBDA/E000/F000 segments.
81
82 // Init memory address as EBDA and scan 1KB region
83 success = GetRsdtPointer((void *)(((U32) * (U16 *) 0x40E) << 4), 0x400, acpi_tables);
84
85 // Init memory address as E000 segment and scan 64KB region
86 if (!success)
87 success = GetRsdtPointer((void *)0x0E0000, 0x10000, acpi_tables);
88
89 // Init memory address as F000 segment and scan 64KB region
90 if (!success)
91 success = GetRsdtPointer((void *)0x0F0000, 0x10000, acpi_tables);
92
93 if (!success || (acpi_tables->RsdtPointer == 0ul))
94 return (0ul);
95
96 success = GetXsdtPointer(acpi_tables);
97
98 // Find FACP table pointer which is one of table pointers in the RDST
99 acpi_tables->FacpPointer = (ACPI_TABLE_FADT *)
100 GetTablePtr(acpi_tables->RsdtPointer, NAMESEG("FACP"));
101 if (acpi_tables->FacpPointer == 0ul)
102 return (0ul);
103
104 // Find the DSDT which is included in the FACP table
105 acpi_tables->DsdtPointer = (ACPI_TABLE_DSDT *) acpi_tables->FacpPointer->Dsdt;
106 if ((acpi_tables->DsdtPointer == 0ul) || (*(U32 *) (acpi_tables->DsdtPointer->Header.Signature) != NAMESEG("DSDT")) ||
107 (GetChecksum(acpi_tables->DsdtPointer, acpi_tables->DsdtPointer->Header.Length) != 0))
108 return (0ul);
109
110 // Find the FACS which is included in the FACP table
111 acpi_tables->FacsPointer = (ACPI_TABLE_FACS *) acpi_tables->FacpPointer->Facs;
112 if ((acpi_tables->FacsPointer == 0ul) || (*(U32 *) (acpi_tables->FacsPointer->Signature) != NAMESEG("FACS")))
113 return (0ul);
114
115 // Find the MADT table which is one of the table pointers in the RSDT
116 acpi_tables->MadtPointer = (ACPI_TABLE_MADT *) GetTablePtr(acpi_tables->RsdtPointer, NAMESEG("APIC"));
117 if (acpi_tables->MadtPointer == 0ul)
118 return (0ul);
119
120 do {
121
122 if (!success || (acpi_tables->XsdtPointer == 0ul))
123 break;
124
125 // Find FACP(64) table pointer which is one of table pointers in the XDST
126 acpi_tables->FacpPointer64 = (ACPI_TABLE_FADT *)
127 GetTablePtr64(acpi_tables->XsdtPointer, NAMESEG("FACP"));
128
129 if (acpi_tables->FacpPointer64 == 0ul)
130 break;
131
132// Find the XDSDT which is included in the FACP(64) table
133ACPI_TABLE_DSDT *DsdtPointer64 = (ACPI_TABLE_DSDT *)((U32)acpi_tables->FacpPointer64->XDsdt);
134
135 if (DsdtPointer64 == 0ul)
136 break;
137
138if ((*(U32*) (DsdtPointer64->Header.Signature) == NAMESEG("DSDT")) &&
139(GetChecksum(DsdtPointer64, DsdtPointer64->Header.Length) == 0))
140acpi_tables->DsdtPointer64 = (ACPI_TABLE_DSDT *) DsdtPointer64;
141
142 // Find the XFACS which is included in the FACP(64) table
143ACPI_TABLE_FACS *FacsPointer64 = (ACPI_TABLE_FACS *)((U32)acpi_tables->FacpPointer64->XFacs);
144
145 if (FacsPointer64 == 0ul)
146 break;
147
148if (*(U32*) (FacsPointer64->Signature) == NAMESEG("FACS"))
149acpi_tables->FacsPointer64 = (ACPI_TABLE_FACS *) FacsPointer64;
150
151
152 // Find the MADT(64) table which is one of the table pointers in the XSDT
153 acpi_tables->MadtPointer64 = (ACPI_TABLE_MADT *) GetTablePtr64(acpi_tables->XsdtPointer, NAMESEG("APIC"));
154
155 } while (0);
156
157
158 return (1ul);
159}
160
161//-----------------------------------------------------------------------------
162U32 get_num_tables(ACPI_TABLE_RSDT * rsdt)
163{
164 // Compute number of table pointers included in RSDT
165 return ((rsdt->Header.Length - sizeof(ACPI_TABLE_HEADER))
166 / sizeof(ACPI_TABLE_HEADER *));
167}
168
169//-----------------------------------------------------------------------------
170U32 get_num_tables64(ACPI_TABLE_XSDT * xsdt)
171{
172 {
173 void *null = 0ul;
174 if (xsdt == null)
175 return 0ul;
176 }
177
178 // Compute number of table pointers included in XSDT
179 return ((xsdt->Header.Length - sizeof(ACPI_TABLE_HEADER))
180 / sizeof(U64));
181}
182
183//-------------------------------------------------------------------------------
184//
185// Procedure: GetTablePtr - Find ACPI table in RSDT with input signature.
186//
187//-------------------------------------------------------------------------------
188static ACPI_TABLE_HEADER *GetTablePtr(ACPI_TABLE_RSDT * rsdt, U32 signature)
189{
190 U32 index;
191 U32 num_tables;
192 ACPI_TABLE_HEADER **table_array = (ACPI_TABLE_HEADER **) rsdt->TableOffsetEntry;
193
194 // Compute number of table pointers included in RSDT
195 num_tables = get_num_tables(rsdt);
196
197 for (index = 0; index < num_tables; index++)
198{
199if (!table_array[index]) continue;
200
201 if ((*(U32 *) (table_array[index]->Signature) == signature) &&
202 (GetChecksum(table_array[index], table_array[index]->Length) == 0))
203{
204 return (table_array[index]);
205 }
206 }
207 return (0);
208}
209
210//-------------------------------------------------------------------------------
211//
212// Procedure: GetTablePtr64 - Find ACPI table in XSDT with input signature.
213//
214//-------------------------------------------------------------------------------
215static ACPI_TABLE_HEADER *GetTablePtr64(ACPI_TABLE_XSDT * xsdt, U32 signature)
216{
217 U32 index;
218 U32 num_tables;
219
220int method;
221
222// Compute number of table pointers included in XSDT
223 num_tables = get_num_tables64(xsdt);
224
225getIntForKey(kAcpiMethod, &method, DEFAULT_BOOT_CONFIG);
226switch (method) {
227case 0x2:
228{
229for (index = 0; index < num_tables; index++)
230{
231U64 ptr = xsdt->TableOffsetEntry[index];
232
233if (!ptr) continue;
234
235if ((*(U32 *) ((ACPI_TABLE_HEADER *) (unsigned long)ptr)->Signature == signature) &&
236(GetChecksum(((ACPI_TABLE_HEADER *) (unsigned long)ptr), ((ACPI_TABLE_HEADER *) (unsigned long)ptr)->Length) == 0))
237{
238return (((ACPI_TABLE_HEADER *) (unsigned long)ptr));
239}
240}
241break;
242}
243case 0x1:
244default:
245{
246ACPI_TABLE_HEADER *table = (ACPI_TABLE_HEADER *) xsdt->TableOffsetEntry;
247
248for (index = 0; index < num_tables; index++)
249{
250if (!table) continue;
251
252if (((U32) (table->Signature) == signature) &&
253(GetChecksum(table, table->Length) == 0))
254{
255return (table);
256}
257// Move array pointer to next 64-bit pointer
258table = (ACPI_TABLE_HEADER *) ((U32) table + sizeof(U64));
259}
260break;
261}
262}
263
264 return (0);
265}
266
267//-------------------------------------------------------------------------------
268//
269// Procedure: GetChecksum - Performs byte checksum
270//
271//-------------------------------------------------------------------------------
272U8 GetChecksum(void *mem_addr, U32 mem_size)
273{
274 U8 *current = mem_addr;
275 U8 *end = current + mem_size;
276 U8 checksum = 0;
277
278 for (; current < end; current++)
279 checksum = checksum + *current;
280
281 return (checksum);
282}
283
284/*==========================================================================
285 * Function to map 32 bit physical address to 64 bit virtual address
286 */
287
288
289//-------------------------------------------------------------------------------
290//
291// Procedure: GetRsdtPointer - Scans given segment for RSDT pointer
292//
293// Description: Scans for root system description table pointer signature
294// ('RSD PTR ') , verifies checksum, and returns pointer to
295// RSDT table if found.
296//
297//-------------------------------------------------------------------------------
298static U32 GetRsdtPointer(void *mem_addr, U32 mem_size, ACPI_TABLES * acpi_tables)
299{
300 U8 *current = mem_addr;
301 U8 *end = current + mem_size;
302
303 // Quick sanity check for a valid start address
304 if (current == 0ul)
305 return (0ul);
306
307 for (; current < end; current += 16)
308{
309if (!current) continue;
310
311 if (*(volatile U64 *)current == NAMESEG64("RSD PTR "))
312{
313 if (GetChecksum(current, ACPI_RSDP_REV0_SIZE) == 0)
314{
315 // RSD pointer structure checksum okay, lookup the RSDT pointer.
316 acpi_tables->RsdPointer = (ACPI_TABLE_RSDP *)current;
317 acpi_tables->RsdtPointer = (ACPI_TABLE_RSDT *) acpi_tables->RsdPointer->RsdtPhysicalAddress;
318 if ((acpi_tables->RsdPointer != (void*)0ul) && (acpi_tables->RsdtPointer != (void*)0ul))
319 return (1ul);
320 else
321 return (0ul);
322 }
323 }
324 }
325
326 return (0);
327}
328
329//-------------------------------------------------------------------------------
330//
331// Procedure: GetXsdtPointer
332//
333//-------------------------------------------------------------------------------
334static U32 GetXsdtPointer(ACPI_TABLES * acpi_tables)
335{
336 if ((GetChecksum(acpi_tables->RsdPointer, sizeof(ACPI_TABLE_RSDP)) == 0) &&
337 (acpi_tables->RsdPointer->Revision == 2) &&
338 (acpi_tables->RsdPointer->Length == sizeof(ACPI_TABLE_RSDP))) {
339 // RSD pointer structure checksum okay, lookup the XSDT pointer.
340 acpi_tables->XsdtPointer = (ACPI_TABLE_XSDT *) (U32) acpi_tables->RsdPointer->XsdtPhysicalAddress;
341 return (1ul);
342 }
343
344 return (0ul);
345}
346

Archive Download this file

Revision: 2121