4 Copyright (c) 2008 - 2012, Intel Corporation. All rights reserved.<BR>
6 Copyright (C) 2012-2014, Red Hat, Inc.
8 This program and the accompanying materials
9 are licensed and made available under the terms and conditions of the BSD License
10 which accompanies this distribution. The full text of the license may be found at
11 http://opensource.org/licenses/bsd-license.php
13 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
14 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
18 #include "AcpiPlatform.h"
19 #include <Library/BaseMemoryLib.h>
20 #include <Library/MemoryAllocationLib.h>
21 #include <Library/QemuFwCfgLib.h>
22 #include <Library/DxeServicesTableLib.h>
23 #include <Library/PcdLib.h>
24 #include <IndustryStandard/Acpi.h>
31 if (!QemuFwCfgIsAvailable ()) {
46 // For all N >= 1, N bits are enough to represent the number of bits set
47 // among N bits. It's true for N == 1. When adding a new bit (N := N+1),
48 // the maximum number of possibly set bits increases by one, while the
49 // representable maximum doubles.
51 Mask
= ((Mask
& 0xAAAA) >> 1) + (Mask
& 0x5555);
52 Mask
= ((Mask
& 0xCCCC) >> 2) + (Mask
& 0x3333);
53 Mask
= ((Mask
& 0xF0F0) >> 4) + (Mask
& 0x0F0F);
54 Mask
= ((Mask
& 0xFF00) >> 8) + (Mask
& 0x00FF);
63 QemuInstallAcpiMadtTable (
64 IN EFI_ACPI_TABLE_PROTOCOL
*AcpiProtocol
,
65 IN VOID
*AcpiTableBuffer
,
66 IN UINTN AcpiTableBufferSize
,
71 UINTN PciLinkIsoCount
;
73 EFI_ACPI_1_0_MULTIPLE_APIC_DESCRIPTION_TABLE_HEADER
*Madt
;
74 EFI_ACPI_1_0_PROCESSOR_LOCAL_APIC_STRUCTURE
*LocalApic
;
75 EFI_ACPI_1_0_IO_APIC_STRUCTURE
*IoApic
;
76 EFI_ACPI_1_0_INTERRUPT_SOURCE_OVERRIDE_STRUCTURE
*Iso
;
77 EFI_ACPI_1_0_LOCAL_APIC_NMI_STRUCTURE
*LocalApicNmi
;
82 ASSERT (AcpiTableBufferSize
>= sizeof (EFI_ACPI_DESCRIPTION_HEADER
));
84 QemuFwCfgSelectItem (QemuFwCfgItemSmpCpuCount
);
85 CpuCount
= QemuFwCfgRead16 ();
86 ASSERT (CpuCount
>= 1);
89 // Set Level-tiggered, Active High for these identity mapped IRQs. The bitset
90 // corresponds to the union of all possible interrupt assignments for the LNKA,
91 // LNKB, LNKC, LNKD PCI interrupt lines. See the DSDT.
93 PciLinkIsoCount
= CountBits16 (PcdGet16 (Pcd8259LegacyModeEdgeLevel
));
95 NewBufferSize
= 1 * sizeof (*Madt
) +
96 CpuCount
* sizeof (*LocalApic
) +
97 1 * sizeof (*IoApic
) +
98 (1 + PciLinkIsoCount
) * sizeof (*Iso
) +
99 1 * sizeof (*LocalApicNmi
);
101 Madt
= AllocatePool (NewBufferSize
);
103 return EFI_OUT_OF_RESOURCES
;
106 CopyMem (&(Madt
->Header
), AcpiTableBuffer
, sizeof (EFI_ACPI_DESCRIPTION_HEADER
));
107 Madt
->Header
.Length
= (UINT32
) NewBufferSize
;
108 Madt
->LocalApicAddress
= PcdGet32 (PcdCpuLocalApicBaseAddress
);
109 Madt
->Flags
= EFI_ACPI_1_0_PCAT_COMPAT
;
113 for (Loop
= 0; Loop
< CpuCount
; ++Loop
) {
114 LocalApic
->Type
= EFI_ACPI_1_0_PROCESSOR_LOCAL_APIC
;
115 LocalApic
->Length
= sizeof (*LocalApic
);
116 LocalApic
->AcpiProcessorId
= (UINT8
) Loop
;
117 LocalApic
->ApicId
= (UINT8
) Loop
;
118 LocalApic
->Flags
= 1; // enabled
124 IoApic
->Type
= EFI_ACPI_1_0_IO_APIC
;
125 IoApic
->Length
= sizeof (*IoApic
);
126 IoApic
->IoApicId
= (UINT8
) CpuCount
;
127 IoApic
->Reserved
= EFI_ACPI_RESERVED_BYTE
;
128 IoApic
->IoApicAddress
= 0xFEC00000;
129 IoApic
->SystemVectorBase
= 0x00000000;
133 // IRQ0 (8254 Timer) => IRQ2 (PIC) Interrupt Source Override Structure
136 Iso
->Type
= EFI_ACPI_1_0_INTERRUPT_SOURCE_OVERRIDE
;
137 Iso
->Length
= sizeof (*Iso
);
138 Iso
->Bus
= 0x00; // ISA
139 Iso
->Source
= 0x00; // IRQ0
140 Iso
->GlobalSystemInterruptVector
= 0x00000002;
141 Iso
->Flags
= 0x0000; // Conforms to specs of the bus
145 // Set Level-tiggered, Active High for all possible PCI link targets.
147 for (Loop
= 0; Loop
< 16; ++Loop
) {
148 if ((PcdGet16 (Pcd8259LegacyModeEdgeLevel
) & (1 << Loop
)) == 0) {
151 Iso
->Type
= EFI_ACPI_1_0_INTERRUPT_SOURCE_OVERRIDE
;
152 Iso
->Length
= sizeof (*Iso
);
153 Iso
->Bus
= 0x00; // ISA
154 Iso
->Source
= (UINT8
) Loop
;
155 Iso
->GlobalSystemInterruptVector
= (UINT32
) Loop
;
156 Iso
->Flags
= 0x000D; // Level-tiggered, Active High
160 (UINTN
) (Iso
- (EFI_ACPI_1_0_INTERRUPT_SOURCE_OVERRIDE_STRUCTURE
*)Ptr
) ==
166 LocalApicNmi
->Type
= EFI_ACPI_1_0_LOCAL_APIC_NMI
;
167 LocalApicNmi
->Length
= sizeof (*LocalApicNmi
);
168 LocalApicNmi
->AcpiProcessorId
= 0xFF; // applies to all processors
170 // polarity and trigger mode of the APIC I/O input signals conform to the
171 // specifications of the bus
173 LocalApicNmi
->Flags
= 0x0000;
175 // Local APIC interrupt input LINTn to which NMI is connected.
177 LocalApicNmi
->LocalApicInti
= 0x01;
178 Ptr
= LocalApicNmi
+ 1;
180 ASSERT ((UINTN
) ((UINT8
*)Ptr
- (UINT8
*)Madt
) == NewBufferSize
);
181 Status
= InstallAcpiTable (AcpiProtocol
, Madt
, NewBufferSize
, TableKey
);
198 PCI_WINDOW PciWindow32
;
199 PCI_WINDOW PciWindow64
;
214 AML_BYTE Pm1aCntSlpTyp
;
215 AML_BYTE Pm1bCntSlpTyp
;
216 AML_BYTE Reserved
[2];
217 } SYSTEM_STATE_PACKAGE
;
226 OUT FIRMWARE_DATA
*FwData
231 EFI_GCD_MEMORY_SPACE_DESCRIPTOR
*AllDesc
;
233 Status
= gDS
->GetMemorySpaceMap (&NumDesc
, &AllDesc
);
234 if (Status
== EFI_SUCCESS
) {
235 UINT64 NonMmio32MaxExclTop
;
236 UINT64 Mmio32MinBase
;
237 UINT64 Mmio32MaxExclTop
;
240 Status
= EFI_UNSUPPORTED
;
242 NonMmio32MaxExclTop
= 0;
243 Mmio32MinBase
= BASE_4GB
;
244 Mmio32MaxExclTop
= 0;
246 for (CurDesc
= 0; CurDesc
< NumDesc
; ++CurDesc
) {
247 CONST EFI_GCD_MEMORY_SPACE_DESCRIPTOR
*Desc
;
250 Desc
= &AllDesc
[CurDesc
];
251 ExclTop
= Desc
->BaseAddress
+ Desc
->Length
;
253 if (ExclTop
<= (UINT64
) PcdGet32 (PcdOvmfFdBaseAddress
)) {
254 switch (Desc
->GcdMemoryType
) {
255 case EfiGcdMemoryTypeNonExistent
:
258 case EfiGcdMemoryTypeReserved
:
259 case EfiGcdMemoryTypeSystemMemory
:
260 if (NonMmio32MaxExclTop
< ExclTop
) {
261 NonMmio32MaxExclTop
= ExclTop
;
265 case EfiGcdMemoryTypeMemoryMappedIo
:
266 if (Mmio32MinBase
> Desc
->BaseAddress
) {
267 Mmio32MinBase
= Desc
->BaseAddress
;
269 if (Mmio32MaxExclTop
< ExclTop
) {
270 Mmio32MaxExclTop
= ExclTop
;
280 if (Mmio32MinBase
< NonMmio32MaxExclTop
) {
281 Mmio32MinBase
= NonMmio32MaxExclTop
;
284 if (Mmio32MinBase
< Mmio32MaxExclTop
) {
285 FwData
->PciWindow32
.Base
= Mmio32MinBase
;
286 FwData
->PciWindow32
.End
= Mmio32MaxExclTop
- 1;
287 FwData
->PciWindow32
.Length
= Mmio32MaxExclTop
- Mmio32MinBase
;
289 FwData
->PciWindow64
.Base
= 0;
290 FwData
->PciWindow64
.End
= 0;
291 FwData
->PciWindow64
.Length
= 0;
293 Status
= EFI_SUCCESS
;
301 "ACPI PciWindow32: Base=0x%08lx End=0x%08lx Length=0x%08lx\n",
302 FwData
->PciWindow32
.Base
,
303 FwData
->PciWindow32
.End
,
304 FwData
->PciWindow32
.Length
308 "ACPI PciWindow64: Base=0x%08lx End=0x%08lx Length=0x%08lx\n",
309 FwData
->PciWindow64
.Base
,
310 FwData
->PciWindow64
.End
,
311 FwData
->PciWindow64
.Length
322 UINTN
*SuspendToRamSize
,
323 SYSTEM_STATE_PACKAGE
*SuspendToRam
,
324 UINTN
*SuspendToDiskSize
,
325 SYSTEM_STATE_PACKAGE
*SuspendToDisk
328 STATIC CONST SYSTEM_STATE_PACKAGE Template
= {
331 { '_', 'S', 'x', '_' }, // NameChar[4]
335 { 0x0A, 0x00 }, // Pm1aCntSlpTyp
336 { 0x0A, 0x00 }, // Pm1bCntSlpTyp -- we don't support it
342 RETURN_STATUS Status
;
343 FIRMWARE_CONFIG_ITEM FwCfgItem
;
345 UINT8 SystemStates
[6];
348 // configure defaults
350 *SuspendToRamSize
= sizeof Template
;
351 CopyMem (SuspendToRam
, &Template
, sizeof Template
);
352 SuspendToRam
->NameChar
[2] = '3'; // S3
353 SuspendToRam
->Pm1aCntSlpTyp
.ByteValue
= 1; // PIIX4: STR
355 *SuspendToDiskSize
= sizeof Template
;
356 CopyMem (SuspendToDisk
, &Template
, sizeof Template
);
357 SuspendToDisk
->NameChar
[2] = '4'; // S4
358 SuspendToDisk
->Pm1aCntSlpTyp
.ByteValue
= 2; // PIIX4: POSCL
361 // check for overrides
363 Status
= QemuFwCfgFindFile ("etc/system-states", &FwCfgItem
, &FwCfgSize
);
364 if (Status
!= RETURN_SUCCESS
|| FwCfgSize
!= sizeof SystemStates
) {
365 DEBUG ((DEBUG_INFO
, "ACPI using S3/S4 defaults\n"));
368 QemuFwCfgSelectItem (FwCfgItem
);
369 QemuFwCfgReadBytes (sizeof SystemStates
, SystemStates
);
372 // Each byte corresponds to a system state. In each byte, the MSB tells us
373 // whether the given state is enabled. If so, the three LSBs specify the
374 // value to be written to the PM control register's SUS_TYP bits.
376 if (SystemStates
[3] & BIT7
) {
377 SuspendToRam
->Pm1aCntSlpTyp
.ByteValue
=
378 SystemStates
[3] & (BIT2
| BIT1
| BIT0
);
379 DEBUG ((DEBUG_INFO
, "ACPI S3 value: %d\n",
380 SuspendToRam
->Pm1aCntSlpTyp
.ByteValue
));
382 *SuspendToRamSize
= 0;
383 DEBUG ((DEBUG_INFO
, "ACPI S3 disabled\n"));
386 if (SystemStates
[4] & BIT7
) {
387 SuspendToDisk
->Pm1aCntSlpTyp
.ByteValue
=
388 SystemStates
[4] & (BIT2
| BIT1
| BIT0
);
389 DEBUG ((DEBUG_INFO
, "ACPI S4 value: %d\n",
390 SuspendToDisk
->Pm1aCntSlpTyp
.ByteValue
));
392 *SuspendToDiskSize
= 0;
393 DEBUG ((DEBUG_INFO
, "ACPI S4 disabled\n"));
401 QemuInstallAcpiSsdtTable (
402 IN EFI_ACPI_TABLE_PROTOCOL
*AcpiProtocol
,
403 IN VOID
*AcpiTableBuffer
,
404 IN UINTN AcpiTableBufferSize
,
409 FIRMWARE_DATA
*FwData
;
411 Status
= EFI_OUT_OF_RESOURCES
;
413 FwData
= AllocateReservedPool (sizeof (*FwData
));
414 if (FwData
!= NULL
) {
415 UINTN SuspendToRamSize
;
416 SYSTEM_STATE_PACKAGE SuspendToRam
;
417 UINTN SuspendToDiskSize
;
418 SYSTEM_STATE_PACKAGE SuspendToDisk
;
422 GetSuspendStates (&SuspendToRamSize
, &SuspendToRam
,
423 &SuspendToDiskSize
, &SuspendToDisk
);
424 SsdtSize
= AcpiTableBufferSize
+ 17 + SuspendToRamSize
+ SuspendToDiskSize
;
425 Ssdt
= AllocatePool (SsdtSize
);
428 Status
= PopulateFwData (FwData
);
430 if (Status
== EFI_SUCCESS
) {
435 CopyMem (SsdtPtr
, AcpiTableBuffer
, AcpiTableBufferSize
);
436 SsdtPtr
+= AcpiTableBufferSize
;
439 // build "OperationRegion(FWDT, SystemMemory, 0x12345678, 0x87654321)"
441 *(SsdtPtr
++) = 0x5B; // ExtOpPrefix
442 *(SsdtPtr
++) = 0x80; // OpRegionOp
447 *(SsdtPtr
++) = 0x00; // SystemMemory
448 *(SsdtPtr
++) = 0x0C; // DWordPrefix
451 // no virtual addressing yet, take the four least significant bytes
453 CopyMem(SsdtPtr
, &FwData
, 4);
456 *(SsdtPtr
++) = 0x0C; // DWordPrefix
458 *(UINT32
*) SsdtPtr
= sizeof (*FwData
);
462 // add suspend system states
464 CopyMem (SsdtPtr
, &SuspendToRam
, SuspendToRamSize
);
465 SsdtPtr
+= SuspendToRamSize
;
466 CopyMem (SsdtPtr
, &SuspendToDisk
, SuspendToDiskSize
);
467 SsdtPtr
+= SuspendToDiskSize
;
469 ASSERT((UINTN
) (SsdtPtr
- Ssdt
) == SsdtSize
);
470 ((EFI_ACPI_DESCRIPTION_HEADER
*) Ssdt
)->Length
= (UINT32
) SsdtSize
;
471 Status
= InstallAcpiTable (AcpiProtocol
, Ssdt
, SsdtSize
, TableKey
);
477 if (Status
!= EFI_SUCCESS
) {
488 QemuInstallAcpiTable (
489 IN EFI_ACPI_TABLE_PROTOCOL
*AcpiProtocol
,
490 IN VOID
*AcpiTableBuffer
,
491 IN UINTN AcpiTableBufferSize
,
495 EFI_ACPI_DESCRIPTION_HEADER
*Hdr
;
496 EFI_ACPI_TABLE_INSTALL_ACPI_TABLE TableInstallFunction
;
498 Hdr
= (EFI_ACPI_DESCRIPTION_HEADER
*) AcpiTableBuffer
;
499 switch (Hdr
->Signature
) {
500 case EFI_ACPI_1_0_APIC_SIGNATURE
:
501 TableInstallFunction
= QemuInstallAcpiMadtTable
;
503 case EFI_ACPI_1_0_SECONDARY_SYSTEM_DESCRIPTION_TABLE_SIGNATURE
:
504 TableInstallFunction
= QemuInstallAcpiSsdtTable
;
507 TableInstallFunction
= InstallAcpiTable
;
510 return TableInstallFunction (
520 // We'll be saving the keys of installed tables so that we can roll them back
521 // in case of failure. 128 tables should be enough for anyone (TM).
523 #define INSTALLED_TABLES_MAX 128
526 Download one ACPI table data file from QEMU and interpret it.
528 @param[in] FwCfgFile The NUL-terminated name of the fw_cfg file to
529 download and interpret.
531 @param[in] AcpiProtocol The ACPI table protocol used to install tables.
533 @param[in,out] InstalledKey On input, an array of INSTALLED_TABLES_MAX UINTN
534 elements, allocated by the caller. On output,
535 the function will have stored (appended) the
536 AcpiProtocol-internal keys of the ACPI tables
537 that the function has installed from the fw_cfg
538 file. The array reflects installed tables even
539 if the function returns with an error.
541 @param[in,out] NumInstalled On input, the number of entries already used in
542 InstalledKey; it must be in [0,
543 INSTALLED_TABLES_MAX] inclusive. On output, the
544 parameter is updated to the new cumulative count
545 of the keys stored in InstalledKey; the value
546 reflects installed tables even if the function
547 returns with an error.
549 @retval EFI_INVALID_PARAMETER NumInstalled is outside the allowed range on
552 @retval EFI_UNSUPPORTED Firmware configuration is unavailable.
554 @retval EFI_NOT_FOUND The host doesn't export the requested fw_cfg
557 @retval EFI_OUT_OF_RESOURCES Memory allocation failed, or no more room in
560 @retval EFI_PROTOCOL_ERROR Found truncated or invalid ACPI table header
561 in the fw_cfg contents.
563 @return Status codes returned by
564 AcpiProtocol->InstallAcpiTable().
570 InstallQemuLinkedTables (
571 IN CONST CHAR8
*FwCfgFile
,
572 IN EFI_ACPI_TABLE_PROTOCOL
*AcpiProtocol
,
573 IN OUT UINTN InstalledKey
[INSTALLED_TABLES_MAX
],
574 IN OUT INT32
*NumInstalled
578 FIRMWARE_CONFIG_ITEM TablesFile
;
579 UINTN TablesFileSize
;
583 if (*NumInstalled
< 0 || *NumInstalled
> INSTALLED_TABLES_MAX
) {
584 return EFI_INVALID_PARAMETER
;
587 Status
= QemuFwCfgFindFile (FwCfgFile
, &TablesFile
, &TablesFileSize
);
588 if (EFI_ERROR (Status
)) {
589 DEBUG ((EFI_D_ERROR
, "%a: \"%a\" unavailable: %r\n", __FUNCTION__
,
594 Tables
= AllocatePool (TablesFileSize
);
595 if (Tables
== NULL
) {
596 return EFI_OUT_OF_RESOURCES
;
599 QemuFwCfgSelectItem (TablesFile
);
600 QemuFwCfgReadBytes (TablesFileSize
, Tables
);
603 while (Processed
< TablesFileSize
) {
605 EFI_ACPI_DESCRIPTION_HEADER
*Probe
;
607 Remaining
= TablesFileSize
- Processed
;
608 if (Remaining
< sizeof *Probe
) {
609 Status
= EFI_PROTOCOL_ERROR
;
613 Probe
= (EFI_ACPI_DESCRIPTION_HEADER
*) (Tables
+ Processed
);
614 if (Remaining
< Probe
->Length
|| Probe
->Length
< sizeof *Probe
) {
615 Status
= EFI_PROTOCOL_ERROR
;
619 DEBUG ((EFI_D_VERBOSE
, "%a: \"%a\" offset 0x%016Lx:"
620 " Signature=\"%-4.4a\" Length=0x%08x\n",
621 __FUNCTION__
, FwCfgFile
, (UINT64
) Processed
,
622 (CONST CHAR8
*) &Probe
->Signature
, Probe
->Length
));
625 // skip automatically handled "root" tables: RSDT, XSDT
627 if (Probe
->Signature
!=
628 EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_TABLE_SIGNATURE
&&
630 EFI_ACPI_2_0_EXTENDED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE
) {
631 if (*NumInstalled
== INSTALLED_TABLES_MAX
) {
632 DEBUG ((EFI_D_ERROR
, "%a: can't install more than %d tables\n",
633 __FUNCTION__
, INSTALLED_TABLES_MAX
));
634 Status
= EFI_OUT_OF_RESOURCES
;
638 Status
= AcpiProtocol
->InstallAcpiTable (AcpiProtocol
, Probe
,
639 Probe
->Length
, &InstalledKey
[*NumInstalled
]);
640 if (EFI_ERROR (Status
)) {
642 "%a: failed to install table \"%-4.4a\" at \"%a\" offset 0x%Lx: "
643 "%r\n", __FUNCTION__
, (CONST CHAR8
*)&Probe
->Signature
, FwCfgFile
,
644 (UINT64
) Processed
, Status
));
651 Processed
+= Probe
->Length
;
655 // NUL-padding at the end is accepted
657 if (Status
== EFI_PROTOCOL_ERROR
) {
660 ErrorLocation
= Processed
;
661 while (Processed
< TablesFileSize
&& Tables
[Processed
] == '\0') {
664 if (Processed
< TablesFileSize
) {
665 DEBUG ((EFI_D_ERROR
, "%a: truncated or invalid ACPI table header at "
666 "\"%a\" offset 0x%Lx\n", __FUNCTION__
, FwCfgFile
,
667 (UINT64
)ErrorLocation
));
671 if (Processed
== TablesFileSize
) {
672 Status
= EFI_SUCCESS
;
674 ASSERT (EFI_ERROR (Status
));
682 Download all ACPI table data files from QEMU and interpret them.
684 @param[in] AcpiProtocol The ACPI table protocol used to install tables.
686 @retval EFI_UNSUPPORTED Firmware configuration is unavailable.
688 @retval EFI_NOT_FOUND The host doesn't export the required fw_cfg
691 @retval EFI_OUT_OF_RESOURCES Memory allocation failed, or more than
692 INSTALLED_TABLES_MAX tables found.
694 @retval EFI_PROTOCOL_ERROR Found truncated or invalid ACPI table header
695 in the fw_cfg contents.
697 @return Status codes returned by
698 AcpiProtocol->InstallAcpiTable().
704 InstallAllQemuLinkedTables (
705 IN EFI_ACPI_TABLE_PROTOCOL
*AcpiProtocol
712 InstalledKey
= AllocatePool (INSTALLED_TABLES_MAX
* sizeof *InstalledKey
);
713 if (InstalledKey
== NULL
) {
714 return EFI_OUT_OF_RESOURCES
;
718 Status
= InstallQemuLinkedTables ("etc/acpi/tables", AcpiProtocol
,
719 InstalledKey
, &Installed
);
720 if (EFI_ERROR (Status
)) {
721 ASSERT (Status
!= EFI_INVALID_PARAMETER
);
723 // Roll back partial installation.
725 while (Installed
> 0) {
727 AcpiProtocol
->UninstallAcpiTable (AcpiProtocol
, InstalledKey
[Installed
]);
730 DEBUG ((EFI_D_INFO
, "%a: installed %d tables\n", __FUNCTION__
, Installed
));
733 FreePool (InstalledKey
);