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

Archive Download this file

Revision: 1468