Chameleon

Chameleon Svn Source Tree

Root/branches/cparm/i386/modules/ACPICodec/acpicode.c

1/*
2Copyright (c) 2010, Intel Corporation
3All rights reserved.
4
5Redistribution and use in source and binary forms, with or without
6modification, 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
17THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
18ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
21ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
24ANY 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
26SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27*/
28
29#include "datatype.h"
30#include "acpi.h"
31#include "ppm.h"
32#include "acpicode.h"
33
34static void setPackage(ACPI_PACKAGE * package, U8 numElements);
35static void setNamePath(ACPI_NAME_PATH * namePath, U32 name);
36
37void SetChecksum(struct acpi_table_header *header)
38{
39 header->Checksum = 0;
40 header->Checksum = 0 - GetChecksum(header, header->Length);
41}
42
43void setRsdpchecksum(ACPI_TABLE_RSDP *rsdp)
44{
45 rsdp->Checksum = 0;
46 rsdp->Checksum = 0 - GetChecksum(rsdp, ACPI_RSDP_REV0_SIZE);
47}
48
49void setRsdpXchecksum(ACPI_TABLE_RSDP *rsdp)
50{
51 rsdp->ExtendedChecksum = 0;
52 rsdp->ExtendedChecksum = 0 - GetChecksum(rsdp, rsdp->Length);
53}
54
55void update_rsdp_with_xsdt(ACPI_TABLE_RSDP *rsdp, ACPI_TABLE_XSDT *xsdt)
56{
57 rsdp->XsdtPhysicalAddress = ((U64)((U32)xsdt));
58
59 setRsdpXchecksum(rsdp);
60}
61
62void update_rsdp_with_rsdt(ACPI_TABLE_RSDP *rsdp, ACPI_TABLE_RSDT *rsdt)
63{
64 rsdp->RsdtPhysicalAddress = (U32)rsdt;
65
66 setRsdpchecksum(rsdp);
67
68}
69
70//-----------------------------------------------------------------------------
71U32 ProcessMadt(ACPI_TABLE_MADT * madt, MADT_INFO * madt_info)
72{
73 void *current;
74 void *end;
75
76 // Quick sanity check for a valid MADT
77 if (madt == 0ul)
78 return (0ul);
79
80 madt_info->lapic_count = 0;
81
82 // Search MADT for Sub-tables with needed data
83 current = madt + 1;
84 end = (U8 *) madt + madt->Header.Length;
85
86 while (current < end) {
87 ACPI_SUBTABLE_HEADER *subtable = current;
88
89 switch (subtable->Type) {
90 case ACPI_MADT_TYPE_LOCAL_APIC:
91 {
92 // Process sub-tables with Type as 0: Processor Local APIC
93 ACPI_MADT_LOCAL_APIC *lapic = current;
94 current = lapic + 1;
95
96 if (!(lapic->LapicFlags & ACPI_MADT_ENABLED))
97 continue;
98
99 {
100 LAPIC_INFO *lapic_info = &madt_info->lapic[madt_info->lapic_count];
101
102 lapic_info->processorId = lapic->ProcessorId;
103 lapic_info->apicId = lapic->Id;
104 lapic_info->madt_type = ACPI_MADT_TYPE_LOCAL_APIC;
105 }
106
107 madt_info->lapic_count++;
108
109 // Sanity check to verify compile time limit for max logical CPU is not exceeded
110 if (madt_info->lapic_count > MAX_LOGICAL_CPU)
111 return (0);
112
113 break;
114 }
115 case ACPI_MADT_TYPE_X2APIC:
116 {
117 // Process sub-tables with Type as 9: Processor X2APIC
118 ACPI_MADT_X2APIC *x2apic = current;
119 current = x2apic + 1;
120
121 if (!(x2apic->x2apicFlags & ACPI_MADT_ENABLED))
122 continue;
123
124 {
125 LAPIC_INFO *lapic_info = &madt_info->lapic[madt_info->lapic_count];
126
127 lapic_info->uid = x2apic->UID;
128 lapic_info->apicId = x2apic->x2apicId;
129 lapic_info->madt_type = ACPI_MADT_TYPE_X2APIC;
130 }
131
132 madt_info->lapic_count++;
133
134 // Sanity check to verify compile time limit for max logical CPU is not exceeded
135 if (madt_info->lapic_count > MAX_LOGICAL_CPU)
136 return (0);
137
138 break;
139 }
140 default:
141 {
142 // Process all other sub-tables
143 current = (U8 *) subtable + subtable->Length;
144 break;
145 }
146 } // switch
147
148 } // while
149
150 return (1);
151}
152
153//-------------------------------------------------------------------------------
154U32 ProcessDsdt(ACPI_TABLE_DSDT * DsdtPointer, U8 * PCIUIDPointer, U8 uid)
155{
156 // 1. Sanity check
157// 2. Replace UID value with the new value
158 // 3. Update the checksum of the DSDT
159
160{
161 // 1. Sanity check
162 if ((memcmp(&uid, PCIUIDPointer, sizeof(U8)) == 0) || (PCIUIDPointer == (U8*)0) || (DsdtPointer == (void*)0ul))
163return (0);
164 }
165
166 {
167 // 2. Replace UID value with the new value
168buildOpCode((void*)PCIUIDPointer, uid);
169 }
170
171 {
172 // 3. Update the checksum of the DSDT
173SetChecksum(&DsdtPointer->Header);
174 }
175
176return (1);
177}
178
179//-------------------------------------------------------------------------------
180void MoveRsdtInsertSsdt(ACPI_TABLE_RSDP * RsdPointer, ACPI_TABLE_RSDT * OldRsdtPointer, ACPI_TABLE_RSDT * NewRsdtPointer, ACPI_TABLE_SSDT * SsdtPointer)
181{
182 // 1. Move the RSDT in memory to the new location
183 // 2. Add new pointer for the SSDT into the RSDT
184 // 3. Update the size of the RSDT
185 // 4. Update the checksum of the RSDT
186 // 5. Update the RSDT pointer in the RSDP
187 // 6. Update the checksum of the RSDP
188
189 {
190 // 1. Move the RSDT in memory to the new location
191 memcpy(NewRsdtPointer, OldRsdtPointer, OldRsdtPointer->Header.Length);
192 }
193
194 {
195 // 2. Add new pointer for the SSDT into the RSDT
196 // 3. Update the size of the RSDT
197 // 4. Update the checksum of the RSDT
198 InsertSsdt(NewRsdtPointer, SsdtPointer);
199 }
200
201 {
202 // 5. Update the RSDT pointer in the RSDP
203 RsdPointer->RsdtPhysicalAddress = (U32) NewRsdtPointer;
204 }
205
206 {
207 // 6. Update the checksum of the RSDP
208setRsdpchecksum(RsdPointer);
209 }
210}
211
212//-------------------------------------------------------------------------------
213void InsertSsdt(ACPI_TABLE_RSDT * RsdtPointer, ACPI_TABLE_SSDT * SsdtPointer)
214{
215 // 1. Add new pointer for the SSDT into the RSDT
216 // 2. Update the size of the RSDT
217 // 3. Update the checksum of the RSDT
218
219 {
220 // 1. Add new pointer for the SSDT into the RSDT
221 U32 index = get_num_tables(RsdtPointer);
222 RsdtPointer->TableOffsetEntry[index] = (U32) SsdtPointer;
223 }
224
225 {
226 // 2. Update the size of the RSDT
227 RsdtPointer->Header.Length = RsdtPointer->Header.Length + sizeof(ACPI_TABLE_SSDT *);
228 }
229
230 {
231 // 3. Update the checksum of the RSDT
232 SetChecksum(&RsdtPointer->Header);
233 }
234}
235
236//-------------------------------------------------------------------------------
237void InsertSsdt64(ACPI_TABLE_XSDT * XsdtPointer, ACPI_TABLE_SSDT * SsdtPointer)
238{
239 {
240 void *null = 0ul;
241 if (XsdtPointer == null)
242 return;
243 }
244
245 // 1. Add new pointer for the SSDT into the XSDT
246 // 2. Update the size of the XSDT
247 // 3. Update the checksum of the XSDT
248
249 {
250 // 1. Add new pointer for the SSDT into the XSDT
251 U32 index = get_num_tables64(XsdtPointer);
252 XsdtPointer->TableOffsetEntry[index] = (U64) ((U32) SsdtPointer);
253 }
254
255 {
256 // 2. Update the size of the XSDT
257 XsdtPointer->Header.Length = XsdtPointer->Header.Length + sizeof(U64);
258 }
259
260 {
261 // 3. Update the checksum of the XSDT
262 SetChecksum(&XsdtPointer->Header);
263 }
264}
265
266//-----------------------------------------------------------------------------
267void *buildNameSeg(void *current, U32 name)
268{
269 U32 *nameSeg = current;
270 current = nameSeg + 1;
271
272 *nameSeg = name;
273
274 return (current);
275}
276
277//-----------------------------------------------------------------------------
278void *buildOpCode(void *current, U8 opCode)
279{
280 U8 *op = current;
281 current = op + 1;
282
283 *op = opCode;
284
285 return (current);
286}
287
288//-----------------------------------------------------------------------------
289void *buildReturnPackage(void *current, U8 numElements)
290{
291 ACPI_RETURN_PACKAGE *returnPackage = current;
292 current = returnPackage + 1;
293
294 returnPackage->returnOpcode = AML_RETURN_OP;
295 setPackage(&returnPackage->package, numElements);
296
297 return (current);
298}
299
300//-----------------------------------------------------------------------------
301void *buildReturnZero(void *current)
302{
303 ACPI_RETURN_ZERO *returnZero = current;
304 current = returnZero + 1;
305
306 returnZero->returnOpcode = AML_RETURN_OP;
307 returnZero->zeroOpcode = AML_ZERO_OP;
308
309 return (current);
310}
311
312//-----------------------------------------------------------------------------
313void *buildReturnOpcode(void *current, U8 opcodeToReturn)
314{
315 ACPI_RETURN_OPCODE *returnOpcode = current;
316 current = returnOpcode + 1;
317
318 returnOpcode->returnOpcode = AML_RETURN_OP;
319 returnOpcode->opcodeToReturn = opcodeToReturn;
320
321 return (current);
322}
323
324//-----------------------------------------------------------------------------
325void *buildMethod(void *current, U32 name, U8 methodFlags)
326{
327 ACPI_METHOD *method = current;
328 current = method + 1;
329
330 method->methodOpcode = AML_METHOD_OP;
331 method->name = name;
332 method->methodFlags = methodFlags;
333
334 return (current);
335}
336
337//-----------------------------------------------------------------------------
338void *buildSmallMethod(void *current, U32 name, U8 methodFlags)
339{
340 ACPI_SMALL_METHOD *method = current;
341 current = method + 1;
342
343 method->methodOpcode = AML_METHOD_OP;
344 method->name = name;
345 method->methodFlags = methodFlags;
346
347 return (current);
348}
349
350//-----------------------------------------------------------------------------
351void *buildNamedDword(void *current, U32 name, U32 dword)
352{
353 ACPI_NAMED_DWORD *namedDword = current;
354 current = namedDword + 1;
355
356 setNamePath(&namedDword->namePath, name);
357 setDwordConst(&namedDword->dword, dword);
358
359 return (current);
360}
361
362//-----------------------------------------------------------------------------
363void *buildGenericRegister(void *current, const ACPI_GENERIC_ADDRESS * gas)
364{
365 ACPI_GENERIC_REGISTER *genReg = current;
366 current = genReg + 1;
367
368 genReg->genericRegisterField = AML_GEN_REG_FIELD;
369 genReg->pkgLength.packageLength0 = 0x0c;
370 genReg->pkgLength.packageLength1 = 0;
371
372 genReg->gas.SpaceId = gas->SpaceId;
373 genReg->gas.BitWidth = gas->BitWidth;
374 genReg->gas.BitOffset = gas->BitOffset;
375 genReg->gas.AccessWidth = gas->AccessWidth;
376 genReg->gas.Address = gas->Address;
377
378 return (current);
379}
380
381//-----------------------------------------------------------------------------
382void *buildSmallBuffer(void *current)
383{
384 ACPI_SMALL_BUFFER *buffer = current;
385 current = buffer + 1;
386
387 buffer->bufferOpcode = AML_BUFFER_OP;
388
389 return (current);
390}
391
392//-----------------------------------------------------------------------------
393void *buildEndTag(void *current)
394{
395 ACPI_END_TAG *endTag = current;
396 current = endTag + 1;
397
398 endTag->endTagField = AML_END_TAG_OP;
399 endTag->checksum = 0;
400
401 return (current);
402}
403
404//-----------------------------------------------------------------------------
405void setSmallPackage(ACPI_SMALL_PACKAGE * package, U8 numElements)
406{
407 package->packageOpcode = AML_PACKAGE_OP;
408 package->numElements = numElements;
409}
410
411//-----------------------------------------------------------------------------
412void *buildSmallPackage(void *current, U8 numElements)
413{
414 ACPI_SMALL_PACKAGE *package = current;
415 current = package + 1;
416 setSmallPackage(package, numElements);
417 return (current);
418}
419
420//-----------------------------------------------------------------------------
421static void setPackage(ACPI_PACKAGE * package, U8 numElements)
422{
423 package->packageOpcode = AML_PACKAGE_OP;
424 package->numElements = numElements;
425}
426
427//-----------------------------------------------------------------------------
428void setPackageLength(ACPI_PACKAGE_LENGTH * packageLength, U32 length)
429{
430 packageLength->packageLength0 = 0x40 + (U8) (length & 0xf);
431 packageLength->packageLength1 = (U8) (length >> 4);
432}
433
434//-----------------------------------------------------------------------------
435void *buildPackageLength(void *current, U32 length)
436{
437 ACPI_PACKAGE_LENGTH *packageLength = current;
438 current = packageLength + 1;
439 setPackageLength(packageLength, length);
440 return (current);
441}
442
443//-----------------------------------------------------------------------------
444static void setNamePath(ACPI_NAME_PATH * namePath, U32 name)
445{
446 namePath->nameOpcode = AML_NAME_OP;
447 namePath->name = name;
448}
449
450//-----------------------------------------------------------------------------
451void *buildNamePath(void *current, U32 name)
452{
453 ACPI_NAME_PATH *namePath = current;
454 current = namePath + 1;
455 setNamePath(namePath, name);
456 return (current);
457}
458
459//-----------------------------------------------------------------------------
460static void setTableHeader(ACPI_TABLE_HEADER * tableHeader, U32 signature, U64 oemTableId)
461{
462 *(U32 *) &tableHeader->Signature = signature;
463 tableHeader->Length = 0;
464 tableHeader->Revision = 1;
465 tableHeader->Checksum = 0;
466 memcpy(&tableHeader->OemId[0], "INTEL ", 6);
467 *(U64 *) (tableHeader->OemTableId) = oemTableId;
468 tableHeader->OemRevision = 0x80000001;
469 *(U32 *) tableHeader->AslCompilerId = NAMESEG("INTL"); // ASCII ASL compiler vendor ID
470 tableHeader->AslCompilerRevision = 0x20061109; // ASL compiler version
471}
472
473//-----------------------------------------------------------------------------
474void *buildTableHeader(void *current, U32 signature, U64 oemTableId)
475{
476 ACPI_TABLE_HEADER *tableHeader = current;
477 current = tableHeader + 1;
478 setTableHeader(tableHeader, signature, oemTableId);
479 return (current);
480}
481
482//-----------------------------------------------------------------------------
483void setByteConst(ACPI_BYTE_CONST * byteConst, U8 byteData)
484{
485 byteConst->byteOpcode = AML_BYTE_OP;
486 byteConst->byteData = byteData;
487}
488
489//-----------------------------------------------------------------------------
490void *buildByteConst(void *current, U8 byteData)
491{
492 ACPI_BYTE_CONST *byteConst = current;
493 current = byteConst + 1;
494 setByteConst(byteConst, byteData);
495 return (current);
496}
497
498//-----------------------------------------------------------------------------
499void setWordConst(ACPI_WORD_CONST * wordConst, U16 wordData)
500{
501 wordConst->wordOpcode = AML_WORD_OP;
502 wordConst->wordData = wordData;
503}
504
505//-----------------------------------------------------------------------------
506void *buildWordConst(void *current, U16 wordData)
507{
508 ACPI_WORD_CONST *wordConst = current;
509 current = wordConst + 1;
510 setWordConst(wordConst, wordData);
511 return (current);
512}
513
514//-----------------------------------------------------------------------------
515void setDwordConst(ACPI_DWORD_CONST * dwordConst, U32 dwordData)
516{
517 dwordConst->dwordOpcode = AML_DWORD_OP;
518 dwordConst->dwordData = dwordData;
519}
520
521//-----------------------------------------------------------------------------
522void *buildDwordConst(void *current, U32 dwordData)
523{
524 ACPI_DWORD_CONST *dwordConst = current;
525 current = dwordConst + 1;
526 setDwordConst(dwordConst, dwordData);
527 return (current);
528}
529
530//-------------------------------------------------------------------------------
531U32 ProcessFadt(ACPI_TABLE_FADT * FadtPointer, U32 pmbase)
532{
533 {
534 // Update fields in FADT
535
536 // Update ACPI 1.0 fields first
537
538 FadtPointer->Pm1aEventBlock = pmbase;
539 FadtPointer->Pm1aControlBlock = pmbase + 4;
540 FadtPointer->Pm2ControlBlock = pmbase + 0x50;
541 FadtPointer->PmTimerBlock = pmbase + 8;
542 FadtPointer->Pm1EventLength = 4;
543 FadtPointer->Pm1ControlLength = 2;
544 FadtPointer->Pm2ControlLength = 1;
545 FadtPointer->PmTimerLength = 4;
546
547 // No legacy C2
548 FadtPointer->C2Latency = 101;
549
550 // No legacy C3
551 FadtPointer->C3Latency = 1001;
552
553 // C1 power state is supported on all processors
554 FadtPointer->BootFlags |= 1UL << 2;
555
556 // No legacy C2 on MP systems
557 FadtPointer->BootFlags &= ~(1UL << 3);
558
559 // Update ACPI 2.0+ fields if supported
560 if (FadtPointer->Header.Revision >= 3) {
561 // Address space where struct or register exists - System IO
562 FadtPointer->XPm1aEventBlock.SpaceId = 1;
563 // Size in bits of given register
564 FadtPointer->XPm1aEventBlock.BitWidth = 0x20;
565 // Bit offset within the register
566 FadtPointer->XPm1aEventBlock.BitOffset = 0;
567 // Minimum Access size (ACPI 3.0)
568 FadtPointer->XPm1aEventBlock.AccessWidth = 0;
569 // 64-bit address of struct or register
570 FadtPointer->XPm1aEventBlock.Address = pmbase;
571
572 // Address space where struct or register exists - System IO
573 FadtPointer->XPm1aControlBlock.SpaceId = 1;
574 // Size in bits of given register
575 FadtPointer->XPm1aControlBlock.BitWidth = 0x10;
576 // Bit offset within the register
577 FadtPointer->XPm1aControlBlock.BitOffset = 0;
578 // Minimum Access size (ACPI 3.0)
579 FadtPointer->XPm1aControlBlock.AccessWidth = 0;
580 // 64-bit address of struct or register
581 FadtPointer->XPm1aControlBlock.Address = pmbase + 4;
582
583 // Address space where struct or register exists - System IO
584 FadtPointer->XPm2ControlBlock.SpaceId = 1;
585 // Size in bits of given register
586 FadtPointer->XPm2ControlBlock.BitWidth = 0x08;
587 // Bit offset within the register
588 FadtPointer->XPm2ControlBlock.BitOffset = 0;
589 // Minimum Access size (ACPI 3.0)
590 FadtPointer->XPm2ControlBlock.AccessWidth = 0;
591 // 64-bit address of struct or register
592 FadtPointer->XPm2ControlBlock.Address = pmbase + 0x50;
593
594 // Address space where struct or register exists - System IO
595 FadtPointer->XPmTimerBlock.SpaceId = 1;
596 // Size in bits of given register
597 FadtPointer->XPmTimerBlock.BitWidth = 0x20;
598 // Bit offset within the register
599 FadtPointer->XPmTimerBlock.BitOffset = 0;
600 // Minimum Access size (ACPI 3.0)
601 FadtPointer->XPmTimerBlock.AccessWidth = 0;
602 // 64-bit address of struct or register
603 FadtPointer->XPmTimerBlock.Address = pmbase + 8;
604 }
605 }
606
607 // Update checksum in FADT
608 SetChecksum(&FadtPointer->Header);
609
610 return (1);
611}
612

Archive Download this file

Revision: 1119