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

Archive Download this file

Revision: 2006