Root/
| |
---|---|
Source at commit 2920 created 5 years 9 months ago. By ifabio, typo | |
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.h"␊ |
34 | ␊ |
35 | static U32 GetRsdtPointer(void *mem_addr, U32 mem_size, ACPI_TABLES * acpi_tables);␊ |
36 | static U32 GetXsdtPointer(ACPI_TABLES * acpi_tables);␊ |
37 | static ACPI_TABLE_HEADER *GetTablePtr(ACPI_TABLE_RSDT * rsdt, U32 signature);␊ |
38 | static 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 | //-------------------------------------------------------------------------------␊ |
60 | U32 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;␊ |
75 | ␉␉acpi_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␊ |
133 | ␉␉ACPI_TABLE_DSDT *DsdtPointer64 = (ACPI_TABLE_DSDT *)((U32)acpi_tables->FacpPointer64->XDsdt);␊ |
134 | ␊ |
135 | if (DsdtPointer64 == 0ul)␊ |
136 | break;␊ |
137 | ␊ |
138 | ␉␉if ((*(U32*) (DsdtPointer64->Header.Signature) == NAMESEG("DSDT")) &&␊ |
139 | ␉␉␉(GetChecksum(DsdtPointer64, DsdtPointer64->Header.Length) == 0))␊ |
140 | ␉␉␉acpi_tables->DsdtPointer64 = (ACPI_TABLE_DSDT *) DsdtPointer64;␊ |
141 | ␊ |
142 | // Find the XFACS which is included in the FACP(64) table␊ |
143 | ␉␉ACPI_TABLE_FACS *FacsPointer64 = (ACPI_TABLE_FACS *)((U32)acpi_tables->FacpPointer64->XFacs);␊ |
144 | ␊ |
145 | if (FacsPointer64 == 0ul)␊ |
146 | break;␊ |
147 | ␊ |
148 | ␉␉if (*(U32*) (FacsPointer64->Signature) == NAMESEG("FACS"))␊ |
149 | ␉␉␉acpi_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 | //-----------------------------------------------------------------------------␊ |
162 | U32 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 | //-----------------------------------------------------------------------------␊ |
170 | U32 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 | //-------------------------------------------------------------------------------␊ |
188 | static 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 | if ((*(U32 *) (table_array[index]->Signature) == signature) &&␊ |
199 | (GetChecksum(table_array[index], table_array[index]->Length) == 0)) {␊ |
200 | return (table_array[index]);␊ |
201 | }␊ |
202 | }␊ |
203 | return (0);␊ |
204 | }␊ |
205 | ␊ |
206 | //-------------------------------------------------------------------------------␊ |
207 | //␊ |
208 | // Procedure: GetTablePtr64 - Find ACPI table in XSDT with input signature.␊ |
209 | //␊ |
210 | //-------------------------------------------------------------------------------␊ |
211 | static ACPI_TABLE_HEADER *GetTablePtr64(ACPI_TABLE_XSDT * xsdt, U32 signature)␊ |
212 | {␊ |
213 | U32 index;␊ |
214 | U32 num_tables;␊ |
215 | ␉␊ |
216 | ␉int method;␊ |
217 | ␉␊ |
218 | ␉// Compute number of table pointers included in XSDT␊ |
219 | num_tables = get_num_tables64(xsdt);␊ |
220 | ␉␊ |
221 | ␉getIntForKey(kAcpiMethod, &method, &bootInfo->chameleonConfig);␊ |
222 | ␉switch (method) {␊ |
223 | ␉␉case 0x2:␊ |
224 | ␉␉{␊ |
225 | ␉␉␉for (index = 0; index < num_tables; index++) {␊ |
226 | ␉␉␉␉U64 ptr = xsdt->TableOffsetEntry[index];␊ |
227 | ␉␉␉␉␊ |
228 | ␉␉␉␉if ((*(U32 *) ((ACPI_TABLE_HEADER *) (unsigned long)ptr)->Signature == signature) &&␊ |
229 | ␉␉␉␉␉(GetChecksum(((ACPI_TABLE_HEADER *) (unsigned long)ptr), ((ACPI_TABLE_HEADER *) (unsigned long)ptr)->Length) == 0)) {␊ |
230 | ␉␉␉␉␉return (((ACPI_TABLE_HEADER *) (unsigned long)ptr));␊ |
231 | ␉␉␉␉} ␊ |
232 | ␉␉␉}␊ |
233 | ␉␉␉break;␊ |
234 | ␉␉}␊ |
235 | ␉␉case 0x1:␉␉␉␊ |
236 | ␉␉default:␊ |
237 | ␉␉{␊ |
238 | ␉␉␉ACPI_TABLE_HEADER *table = (ACPI_TABLE_HEADER *) xsdt->TableOffsetEntry;␉␉␊ |
239 | ␉␉␉␊ |
240 | ␉␉␉for (index = 0; index < num_tables; index++) {␊ |
241 | ␉␉␉␉if (((U32) (table->Signature) == signature) &&␊ |
242 | ␉␉␉␉␉(GetChecksum(table, table->Length) == 0)) {␊ |
243 | ␉␉␉␉␉return (table);␊ |
244 | ␉␉␉␉}␊ |
245 | ␉␉␉␉// Move array pointer to next 64-bit pointer␊ |
246 | ␉␉␉␉table = (ACPI_TABLE_HEADER *) ((U32) table + sizeof(U64));␊ |
247 | ␉␉␉}␊ |
248 | ␉␉␉break;␊ |
249 | ␉␉}␊ |
250 | ␉}␉␉␊ |
251 | ␊ |
252 | return (0);␊ |
253 | }␊ |
254 | ␊ |
255 | //-------------------------------------------------------------------------------␊ |
256 | //␊ |
257 | // Procedure: GetChecksum - Performs byte checksum␊ |
258 | //␊ |
259 | //-------------------------------------------------------------------------------␊ |
260 | U8 GetChecksum(void *mem_addr, U32 mem_size)␊ |
261 | {␊ |
262 | U8 *current = mem_addr;␊ |
263 | U8 *end = current + mem_size;␊ |
264 | U8 checksum = 0;␊ |
265 | ␊ |
266 | for (; current < end; current++)␊ |
267 | checksum = checksum + *current;␊ |
268 | ␊ |
269 | return (checksum);␊ |
270 | }␊ |
271 | ␊ |
272 | /*==========================================================================␊ |
273 | * Function to map 32 bit physical address to 64 bit virtual address␊ |
274 | */␊ |
275 | ␊ |
276 | ␊ |
277 | //-------------------------------------------------------------------------------␊ |
278 | //␊ |
279 | // Procedure: GetRsdtPointer - Scans given segment for RSDT pointer␊ |
280 | //␊ |
281 | // Description: Scans for root system description table pointer signature␊ |
282 | // ('RSD PTR ') , verifies checksum, and returns pointer to␊ |
283 | // RSDT table if found.␊ |
284 | //␊ |
285 | //-------------------------------------------------------------------------------␊ |
286 | static U32 GetRsdtPointer(void *mem_addr, U32 mem_size, ACPI_TABLES * acpi_tables)␊ |
287 | {␊ |
288 | U8 *current = mem_addr;␊ |
289 | U8 *end = current + mem_size;␊ |
290 | ␊ |
291 | // Quick sanity check for a valid start address␊ |
292 | if (current == 0ul)␊ |
293 | return (0ul);␊ |
294 | ␊ |
295 | for (; current < end; current += 16) {␊ |
296 | if (*(volatile U64 *)current == NAMESEG64("RSD PTR ")) {␊ |
297 | if (GetChecksum(current, ACPI_RSDP_REV0_SIZE) == 0) {␊ |
298 | // RSD pointer structure checksum okay, lookup the RSDT pointer. ␊ |
299 | acpi_tables->RsdPointer = (ACPI_TABLE_RSDP *)current;␊ |
300 | acpi_tables->RsdtPointer = (ACPI_TABLE_RSDT *) acpi_tables->RsdPointer->RsdtPhysicalAddress;␊ |
301 | if ((acpi_tables->RsdPointer != (void*)0ul) && (acpi_tables->RsdtPointer != (void*)0ul))␊ |
302 | return (1ul);␊ |
303 | else␊ |
304 | return (0ul);␊ |
305 | }␊ |
306 | }␊ |
307 | }␊ |
308 | ␊ |
309 | return (0);␊ |
310 | }␊ |
311 | ␊ |
312 | //-------------------------------------------------------------------------------␊ |
313 | //␊ |
314 | // Procedure: GetXsdtPointer␊ |
315 | //␊ |
316 | //-------------------------------------------------------------------------------␊ |
317 | static U32 GetXsdtPointer(ACPI_TABLES * acpi_tables)␊ |
318 | {␊ |
319 | if ((GetChecksum(acpi_tables->RsdPointer, sizeof(ACPI_TABLE_RSDP)) == 0) &&␊ |
320 | (acpi_tables->RsdPointer->Revision == 2) &&␊ |
321 | (acpi_tables->RsdPointer->Length == sizeof(ACPI_TABLE_RSDP))) {␊ |
322 | // RSD pointer structure checksum okay, lookup the XSDT pointer.␊ |
323 | acpi_tables->XsdtPointer = (ACPI_TABLE_XSDT *) (U32) acpi_tables->RsdPointer->XsdtPhysicalAddress;␊ |
324 | return (1ul);␊ |
325 | }␊ |
326 | ␊ |
327 | return (0ul);␊ |
328 | }␊ |
329 |