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
29#include "datatype.h"
30#include "intel_acpi.h"
31#include "ppm.h"
32#include "acpi_tools.h"
33
34static U32 GetRsdtPointer(void *mem_addr, U32 mem_size, ACPI_TABLES * acpi_tables);
35static U32 GetXsdtPointer(ACPI_TABLES * acpi_tables);
36static ACPI_TABLE_HEADER *GetTablePtr(ACPI_TABLE_RSDT * rsdt, U32 signature);
37static ACPI_TABLE_HEADER *GetTablePtr64(ACPI_TABLE_XSDT * xsdt, U32 signature);
38
39//-------------------------------------------------------------------------------
40//
41// Procedure: FindAcpiTables - Collects addresses for RSDP, RSDT, FADT, & DSDT.
42//
43// Description: Finds the differentiated system description table pointer
44// by scanning and checking ACPI tables. This function will
45// get and store the following ACPI Table Pointers:
46// 1) RSD Pointer in RsdPointer Variable
47// 2) RSDT Pointer in RsdtPointer Variable (RSDP->RSDT)
48// 3) FACP Pointer in FacpPointer Variable (RSDP->RSDT->FACP)
49// 4) DSDT Pointer in DsdtPointer Variable (RSDP->RSDT->FACP->DSDT)
50// 5) FACS Pointer in FacsPointer Variable (RSDP->RSDT->FACP->FACS)
51// 6) FACP Pointer in Facp64Pointer Variable (RSDP->XSDT->FACP)
52//
53//-------------------------------------------------------------------------------
54U32 FindAcpiTables(ACPI_TABLES * acpi_tables)
55{
56 U32 success = 0ul;
57
58 // Perform init of ACPI table pointers
59 {
60 void *null = 0ul;
61 acpi_tables->DsdtPointer = null;
62 acpi_tables->DsdtPointer64 = null;
63 acpi_tables->FacpPointer = null;
64 acpi_tables->FacsPointer = null;
65 acpi_tables->FacsPointer64 = null;
66 acpi_tables->RsdPointer = null;
67 acpi_tables->RsdtPointer = null;
68 acpi_tables->MadtPointer = null;
69 acpi_tables->SsdtPointer = null;
70 acpi_tables->XsdtPointer = null;
71 acpi_tables->FacpPointer64 = null;
72 acpi_tables->RsdRevision = 0;
73 }
74
75 // Find the RSDT pointer by scanning EBDA/E000/F000 segments.
76
77 // Init memory address as EBDA and scan 1KB region
78 success = GetRsdtPointer((void *)(((U32) * (U16 *) 0x40E) << 4), 0x400, acpi_tables);
79
80 // Init memory address as E000 segment and scan 64KB region
81 if (!success)
82 success = GetRsdtPointer((void *)0x0E0000, 0x10000, acpi_tables);
83
84 // Init memory address as F000 segment and scan 64KB region
85 if (!success)
86 success = GetRsdtPointer((void *)0x0F0000, 0x10000, acpi_tables);
87
88 if (!success)
89 return (0ul);
90
91 GetXsdtPointer(acpi_tables);
92
93 // Find FACP table pointer which is one of table pointers in the RDST
94 acpi_tables->FacpPointer = (ACPI_TABLE_FADT *)
95 GetTablePtr(acpi_tables->RsdtPointer, NAMESEG("FACP"));
96 if (acpi_tables->FacpPointer == 0ul)
97 return (0ul);
98
99 // Find FACP(64) table pointer which is one of table pointers in the XDST
100 acpi_tables->FacpPointer64 = (ACPI_TABLE_FADT *)
101 GetTablePtr64(acpi_tables->XsdtPointer, NAMESEG("FACP"));
102
103 // Find the DSDT which is included in the FACP table
104 acpi_tables->DsdtPointer = (ACPI_TABLE_DSDT *) acpi_tables->FacpPointer->Dsdt;
105 if ((*(U32 *) (acpi_tables->DsdtPointer->Header.Signature) != NAMESEG("DSDT")) ||
106 (GetChecksum(acpi_tables->DsdtPointer, acpi_tables->DsdtPointer->Header.Length) != 0))
107 return (0ul);
108
109 // Find the XDSDT which is included in the FACP(64) table
110 ACPI_TABLE_DSDT *DsdtPointer64 = (ACPI_TABLE_DSDT *)((U32)acpi_tables->FacpPointer64->XDsdt);
111 if ((*(U32*) (DsdtPointer64->Header.Signature) == NAMESEG("DSDT")) &&
112 (GetChecksum(DsdtPointer64, DsdtPointer64->Header.Length) == 0))
113 acpi_tables->DsdtPointer64 = (ACPI_TABLE_DSDT *) DsdtPointer64;
114
115 // Find the FACS which is included in the FACP table
116 acpi_tables->FacsPointer = (ACPI_TABLE_FACS *) acpi_tables->FacpPointer->Facs;
117 if (*(U32 *) (acpi_tables->FacsPointer->Signature) != NAMESEG("FACS"))
118 return (0ul);
119
120 // Find the XFACS which is included in the FACP(64) table
121 ACPI_TABLE_FACS *FacsPointer64 = (ACPI_TABLE_FACS *)((U32)acpi_tables->FacpPointer64->XFacs);
122 if (*(U32*) (FacsPointer64->Signature) == NAMESEG("FACS"))
123 acpi_tables->FacsPointer64 = (ACPI_TABLE_FACS *) FacsPointer64;
124
125 // Find the MADT table which is one of the table pointers in the RSDT
126 acpi_tables->MadtPointer = (ACPI_TABLE_MADT *) GetTablePtr(acpi_tables->RsdtPointer, NAMESEG("APIC"));
127 if (acpi_tables->MadtPointer == 0ul)
128 return (0ul);
129
130 return (1ul);
131}
132
133//-----------------------------------------------------------------------------
134U32 get_num_tables(ACPI_TABLE_RSDT * rsdt)
135{
136 // Compute number of table pointers included in RSDT
137 return ((rsdt->Header.Length - sizeof(ACPI_TABLE_HEADER))
138 / sizeof(ACPI_TABLE_HEADER *));
139}
140
141//-----------------------------------------------------------------------------
142U32 get_num_tables64(ACPI_TABLE_XSDT * xsdt)
143{
144 {
145 void *null = 0ul;
146 if (xsdt == null)
147 return 0ul;
148 }
149
150 // Compute number of table pointers included in XSDT
151 return ((xsdt->Header.Length - sizeof(ACPI_TABLE_HEADER))
152 / sizeof(U64));
153}
154
155//-------------------------------------------------------------------------------
156//
157// Procedure: GetTablePtr - Find ACPI table with input signature.
158//
159//-------------------------------------------------------------------------------
160static ACPI_TABLE_HEADER *GetTablePtr(ACPI_TABLE_RSDT * rsdt, U32 signature)
161{
162 U32 index;
163 U32 num_tables;
164 ACPI_TABLE_HEADER **table_array = (ACPI_TABLE_HEADER **) rsdt->TableOffsetEntry;
165
166 // Compute number of table pointers included in RSDT
167 num_tables = get_num_tables(rsdt);
168
169 for (index = 0; index < num_tables; index++) {
170 if ((*(U32 *) (table_array[index]->Signature) == signature) &&
171 (GetChecksum(table_array[index], table_array[index]->Length) == 0)) {
172 return (table_array[index]);
173 }
174 }
175 return (0);
176}
177
178//-------------------------------------------------------------------------------
179//
180// Procedure: GetTablePtr - Find ACPI table with input signature.
181//
182//-------------------------------------------------------------------------------
183static ACPI_TABLE_HEADER *GetTablePtr64(ACPI_TABLE_XSDT * xsdt, U32 signature)
184{
185 U32 index;
186 U32 num_tables;
187 ACPI_TABLE_HEADER *table = (ACPI_TABLE_HEADER *) xsdt->TableOffsetEntry;
188
189 // Compute number of table pointers included in XSDT
190 num_tables = get_num_tables64(xsdt);
191
192 for (index = 0; index < num_tables; index++) {
193 if (((U32) (table->Signature) == signature) &&
194 (GetChecksum(table, table->Length) == 0)) {
195 return (table);
196 }
197 // Move array pointer to next 64-bit pointer
198 table = (ACPI_TABLE_HEADER *) ((U32) table + sizeof(U64));
199 }
200 return (0);
201}
202
203//-------------------------------------------------------------------------------
204//
205// Procedure: GetChecksum - Performs byte checksum
206//
207//-------------------------------------------------------------------------------
208U8 GetChecksum(void *mem_addr, U32 mem_size)
209{
210 U8 *current = mem_addr;
211 U8 *end = current + mem_size;
212 U8 checksum = 0;
213
214 for (; current < end; current++)
215 checksum = checksum + *current;
216
217 return (checksum);
218}
219
220/*==========================================================================
221 * Function to map 32 bit physical address to 64 bit virtual address
222 */
223
224
225//-------------------------------------------------------------------------------
226//
227// Procedure: GetRsdtPointer - Scans given segment for RSDT pointer
228//
229// Description: Scans for root system description table pointer signature
230// ('RSD PTR ') , verifies checksum, and returns pointer to
231// RSDT table if found.
232//
233//-------------------------------------------------------------------------------
234static U32 GetRsdtPointer(void *mem_addr, U32 mem_size, ACPI_TABLES * acpi_tables)
235{
236 U8 *current = mem_addr;
237 U8 *end = current + mem_size;
238
239 // Quick sanity check for a valid start address
240 if (current == 0ul)
241 return (0ul);
242
243 for (; current < end; current += 16) {
244 if (*(volatile U64 *)current == NAMESEG64("RSD PTR ")) {
245 if (GetChecksum(current, ACPI_RSDP_REV0_SIZE) == 0) {
246 // RSD pointer structure checksum okay, lookup the RSDT pointer.
247 acpi_tables->RsdRevision = ((ACPI_TABLE_RSDP *)current)->Revision;
248 acpi_tables->RsdPointer = (ACPI_TABLE_RSDP *)current;
249 acpi_tables->RsdtPointer = (ACPI_TABLE_RSDT *) acpi_tables->RsdPointer->RsdtPhysicalAddress;
250 if ((acpi_tables->RsdPointer != 0) && (acpi_tables->RsdtPointer != 0))
251 return (1ul);
252 else
253 return (0ul);
254 }
255 }
256 }
257
258 return (0);
259}
260
261//-------------------------------------------------------------------------------
262//
263// Procedure: GetXsdtPointer
264//
265//-------------------------------------------------------------------------------
266static U32 GetXsdtPointer(ACPI_TABLES * acpi_tables)
267{
268 if ((GetChecksum(acpi_tables->RsdPointer, sizeof(ACPI_TABLE_RSDP)) == 0) &&
269 (acpi_tables->RsdPointer->Revision == 2) &&
270 (acpi_tables->RsdPointer->Length == sizeof(ACPI_TABLE_RSDP))) {
271 // RSD pointer structure checksum okay, lookup the XSDT pointer.
272 acpi_tables->XsdtPointer = (ACPI_TABLE_XSDT *) (U32) acpi_tables->RsdPointer->XsdtPhysicalAddress;
273 return (1ul);
274 }
275
276 return (0ul);
277}
278

Archive Download this file

Revision: 1119