OvmfPkg: generate full MADT dynamically, synchronize contents with qemu

Represent the set of possible PCI link target IRQs with
Pcd8259LegacyModeEdgeLevel. This ensures that the 8259 Interrupt
Controller code in PcAtChipsetPkg will treat them as level-triggered too.

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
Reviewed-by: Jordan Justen <jordan.l.justen@intel.com>

git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@13628 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
jljusten 2012-08-13 15:42:07 +00:00
parent 05c89c7f0c
commit 498f7d8ddd
7 changed files with 149 additions and 65 deletions

View File

@ -35,6 +35,8 @@
MdePkg/MdePkg.dec MdePkg/MdePkg.dec
MdeModulePkg/MdeModulePkg.dec MdeModulePkg/MdeModulePkg.dec
OvmfPkg/OvmfPkg.dec OvmfPkg/OvmfPkg.dec
UefiCpuPkg/UefiCpuPkg.dec
PcAtChipsetPkg/PcAtChipsetPkg.dec
[LibraryClasses] [LibraryClasses]
UefiLib UefiLib
@ -58,6 +60,8 @@
[Pcd] [Pcd]
gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiTableStorageFile gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiTableStorageFile
gUefiCpuPkgTokenSpaceGuid.PcdCpuLocalApicBaseAddress
gPcAtChipsetPkgTokenSpaceGuid.Pcd8259LegacyModeEdgeLevel
[Depex] [Depex]
gEfiAcpiTableProtocolGuid gEfiAcpiTableProtocolGuid

View File

@ -17,7 +17,8 @@
#include <Library/MemoryAllocationLib.h> #include <Library/MemoryAllocationLib.h>
#include <Library/QemuFwCfgLib.h> #include <Library/QemuFwCfgLib.h>
#include <Library/DxeServicesTableLib.h> #include <Library/DxeServicesTableLib.h>
#include <Library/PcdLib.h>
#include <IndustryStandard/Acpi.h>
BOOLEAN BOOLEAN
QemuDetected ( QemuDetected (
@ -32,6 +33,27 @@ QemuDetected (
} }
STATIC
UINTN
CountBits16 (
UINT16 Mask
)
{
//
// For all N >= 1, N bits are enough to represent the number of bits set
// among N bits. It's true for N == 1. When adding a new bit (N := N+1),
// the maximum number of possibly set bits increases by one, while the
// representable maximum doubles.
//
Mask = ((Mask & 0xAAAA) >> 1) + (Mask & 0x5555);
Mask = ((Mask & 0xCCCC) >> 2) + (Mask & 0x3333);
Mask = ((Mask & 0xF0F0) >> 4) + (Mask & 0x0F0F);
Mask = ((Mask & 0xFF00) >> 8) + (Mask & 0x00FF);
return Mask;
}
STATIC STATIC
EFI_STATUS EFI_STATUS
EFIAPI EFIAPI
@ -42,58 +64,120 @@ QemuInstallAcpiMadtTable (
OUT UINTN *TableKey OUT UINTN *TableKey
) )
{ {
EFI_STATUS Status; UINTN CpuCount;
UINTN Count; UINTN PciLinkIsoCount;
UINTN Loop; UINTN NewBufferSize;
EFI_ACPI_DESCRIPTION_HEADER *Hdr; EFI_ACPI_1_0_MULTIPLE_APIC_DESCRIPTION_TABLE_HEADER *Madt;
UINTN NewBufferSize; EFI_ACPI_1_0_PROCESSOR_LOCAL_APIC_STRUCTURE *LocalApic;
EFI_ACPI_1_0_PROCESSOR_LOCAL_APIC_STRUCTURE *LocalApic; EFI_ACPI_1_0_IO_APIC_STRUCTURE *IoApic;
EFI_ACPI_1_0_INTERRUPT_SOURCE_OVERRIDE_STRUCTURE *Iso;
EFI_ACPI_1_0_LOCAL_APIC_NMI_STRUCTURE *LocalApicNmi;
VOID *Ptr;
UINTN Loop;
EFI_STATUS Status;
ASSERT (AcpiTableBufferSize >= sizeof (EFI_ACPI_DESCRIPTION_HEADER));
QemuFwCfgSelectItem (QemuFwCfgItemSmpCpuCount); QemuFwCfgSelectItem (QemuFwCfgItemSmpCpuCount);
Count = (UINTN) QemuFwCfgRead16 (); CpuCount = QemuFwCfgRead16 ();
ASSERT (Count >= 1); ASSERT (CpuCount >= 1);
if (Count == 1) { //
// // Set Level-tiggered, Active High for these identity mapped IRQs. The bitset
// The pre-built MADT table covers the single CPU case // corresponds to the union of all possible interrupt assignments for the LNKA,
// // LNKB, LNKC, LNKD PCI interrupt lines. See the DSDT.
return InstallAcpiTable ( //
AcpiProtocol, PciLinkIsoCount = CountBits16 (PcdGet16 (Pcd8259LegacyModeEdgeLevel));
AcpiTableBuffer,
AcpiTableBufferSize, NewBufferSize = 1 * sizeof (*Madt) +
TableKey CpuCount * sizeof (*LocalApic) +
); 1 * sizeof (*IoApic) +
(1 + PciLinkIsoCount) * sizeof (*Iso) +
1 * sizeof (*LocalApicNmi);
Madt = AllocatePool (NewBufferSize);
if (Madt == NULL) {
return EFI_OUT_OF_RESOURCES;
} }
// Madt->Header = *(EFI_ACPI_DESCRIPTION_HEADER *) AcpiTableBuffer;
// We need to add additional Local APIC entries to the MADT Madt->Header.Length = NewBufferSize;
// Madt->LocalApicAddress = PcdGet32 (PcdCpuLocalApicBaseAddress);
NewBufferSize = AcpiTableBufferSize + ((Count - 1) * sizeof (*LocalApic)); Madt->Flags = EFI_ACPI_1_0_PCAT_COMPAT;
Hdr = (EFI_ACPI_DESCRIPTION_HEADER*) AllocatePool (NewBufferSize); Ptr = Madt + 1;
ASSERT (Hdr != NULL);
CopyMem (Hdr, AcpiTableBuffer, AcpiTableBufferSize); LocalApic = Ptr;
for (Loop = 0; Loop < CpuCount; ++Loop) {
LocalApic = (EFI_ACPI_1_0_PROCESSOR_LOCAL_APIC_STRUCTURE*) LocalApic->Type = EFI_ACPI_1_0_PROCESSOR_LOCAL_APIC;
(((UINT8*) Hdr) + AcpiTableBufferSize); LocalApic->Length = sizeof (*LocalApic);
LocalApic->AcpiProcessorId = Loop;
// LocalApic->ApicId = Loop;
// Add Local APIC entries for the APs to the MADT LocalApic->Flags = 1; // enabled
// ++LocalApic;
for (Loop = 1; Loop < Count; Loop++) {
LocalApic->Type = EFI_ACPI_1_0_PROCESSOR_LOCAL_APIC;
LocalApic->Length = sizeof (*LocalApic);
LocalApic->AcpiProcessorId = (UINT8) Loop;
LocalApic->ApicId = (UINT8) Loop;
LocalApic->Flags = 1;
LocalApic++;
} }
Ptr = LocalApic;
Hdr->Length = (UINT32) NewBufferSize; IoApic = Ptr;
IoApic->Type = EFI_ACPI_1_0_IO_APIC;
IoApic->Length = sizeof (*IoApic);
IoApic->IoApicId = CpuCount;
IoApic->Reserved = EFI_ACPI_RESERVED_BYTE;
IoApic->IoApicAddress = 0xFEC00000;
IoApic->SystemVectorBase = 0x00000000;
Ptr = IoApic + 1;
Status = InstallAcpiTable (AcpiProtocol, Hdr, NewBufferSize, TableKey); //
// IRQ0 (8254 Timer) => IRQ2 (PIC) Interrupt Source Override Structure
//
Iso = Ptr;
Iso->Type = EFI_ACPI_1_0_INTERRUPT_SOURCE_OVERRIDE;
Iso->Length = sizeof (*Iso);
Iso->Bus = 0x00; // ISA
Iso->Source = 0x00; // IRQ0
Iso->GlobalSystemInterruptVector = 0x00000002;
Iso->Flags = 0x0000; // Conforms to specs of the bus
++Iso;
FreePool (Hdr); //
// Set Level-tiggered, Active High for all possible PCI link targets.
//
for (Loop = 0; Loop < 16; ++Loop) {
if ((PcdGet16 (Pcd8259LegacyModeEdgeLevel) & (1 << Loop)) == 0) {
continue;
}
Iso->Type = EFI_ACPI_1_0_INTERRUPT_SOURCE_OVERRIDE;
Iso->Length = sizeof (*Iso);
Iso->Bus = 0x00; // ISA
Iso->Source = Loop;
Iso->GlobalSystemInterruptVector = Loop;
Iso->Flags = 0x000D; // Level-tiggered, Active High
++Iso;
}
ASSERT (
Iso - (EFI_ACPI_1_0_INTERRUPT_SOURCE_OVERRIDE_STRUCTURE *)Ptr ==
1 + PciLinkIsoCount
);
Ptr = Iso;
LocalApicNmi = Ptr;
LocalApicNmi->Type = EFI_ACPI_1_0_LOCAL_APIC_NMI;
LocalApicNmi->Length = sizeof (*LocalApicNmi);
LocalApicNmi->AcpiProcessorId = 0xFF; // applies to all processors
//
// polarity and trigger mode of the APIC I/O input signals conform to the
// specifications of the bus
//
LocalApicNmi->Flags = 0x0000;
//
// Local APIC interrupt input LINTn to which NMI is connected.
//
LocalApicNmi->LocalApicInti = 0x01;
Ptr = LocalApicNmi + 1;
ASSERT ((UINT8 *)Ptr - (UINT8 *)Madt == NewBufferSize);
Status = InstallAcpiTable (AcpiProtocol, Madt, NewBufferSize, TableKey);
FreePool (Madt);
return Status; return Status;
} }

View File

@ -16,11 +16,7 @@
**/ **/
#include <IndustryStandard/Acpi.h> #include <IndustryStandard/Acpi.h>
#include <Platform.h>
//
// MADT Definitions
//
#define EFI_ACPI_OEM_MADT_REVISION 0x00000000 // TBD
// //
// Local APIC address // Local APIC address
@ -74,21 +70,12 @@ EFI_ACPI_1_0_MULTIPLE_APIC_DESCRIPTION_TABLE Madt = {
EFI_ACPI_1_0_APIC_SIGNATURE, EFI_ACPI_1_0_APIC_SIGNATURE,
sizeof (EFI_ACPI_1_0_MULTIPLE_APIC_DESCRIPTION_TABLE), sizeof (EFI_ACPI_1_0_MULTIPLE_APIC_DESCRIPTION_TABLE),
EFI_ACPI_1_0_MULTIPLE_APIC_DESCRIPTION_TABLE_REVISION, EFI_ACPI_1_0_MULTIPLE_APIC_DESCRIPTION_TABLE_REVISION,
0x00, // Checksum will be updated at runtime
// EFI_ACPI_OEM_ID,
// Checksum will be updated at runtime EFI_ACPI_OEM_TABLE_ID,
// EFI_ACPI_OEM_REVISION,
0x00, EFI_ACPI_CREATOR_ID,
EFI_ACPI_CREATOR_REVISION,
//
// It is expected that these values will be programmed at runtime
//
' ', ' ', ' ', ' ', ' ', ' ',
0,
EFI_ACPI_OEM_MADT_REVISION,
0,
0,
// //
// MADT specific fields // MADT specific fields

View File

@ -23,9 +23,9 @@
// //
#define EFI_ACPI_OEM_ID 'O','V','M','F',' ',' ' // OEMID 6 bytes long #define EFI_ACPI_OEM_ID 'O','V','M','F',' ',' ' // OEMID 6 bytes long
#define EFI_ACPI_OEM_TABLE_ID SIGNATURE_64('O','V','M','F','E','D','K','2') // OEM table id 8 bytes long #define EFI_ACPI_OEM_TABLE_ID SIGNATURE_64('O','V','M','F','E','D','K','2') // OEM table id 8 bytes long
#define EFI_ACPI_OEM_REVISION 0x02000820 #define EFI_ACPI_OEM_REVISION 0x20120804
#define EFI_ACPI_CREATOR_ID SIGNATURE_32('O','V','M','F') #define EFI_ACPI_CREATOR_ID SIGNATURE_32('O','V','M','F')
#define EFI_ACPI_CREATOR_REVISION 0x00000097 #define EFI_ACPI_CREATOR_REVISION 0x00000098
#define INT_MODEL 0x01 #define INT_MODEL 0x01
#define SCI_INT_VECTOR 0x0009 #define SCI_INT_VECTOR 0x0009

View File

@ -302,6 +302,9 @@
!endif !endif
!endif !endif
# IRQs 5, 9, 10, 11 are level-triggered
gPcAtChipsetPkgTokenSpaceGuid.Pcd8259LegacyModeEdgeLevel|0x0E20
!if $(SECURE_BOOT_ENABLE) == TRUE !if $(SECURE_BOOT_ENABLE) == TRUE
# override the default values from SecurityPkg to ensure images from all sources are verified in secure boot # override the default values from SecurityPkg to ensure images from all sources are verified in secure boot
gEfiSecurityPkgTokenSpaceGuid.PcdOptionRomImageVerificationPolicy|0x05 gEfiSecurityPkgTokenSpaceGuid.PcdOptionRomImageVerificationPolicy|0x05

View File

@ -302,6 +302,9 @@
!endif !endif
!endif !endif
# IRQs 5, 9, 10, 11 are level-triggered
gPcAtChipsetPkgTokenSpaceGuid.Pcd8259LegacyModeEdgeLevel|0x0E20
[PcdsFixedAtBuild.X64] [PcdsFixedAtBuild.X64]
!if $(SECURE_BOOT_ENABLE) == TRUE !if $(SECURE_BOOT_ENABLE) == TRUE
# override the default values from SecurityPkg to ensure images from all sources are verified in secure boot # override the default values from SecurityPkg to ensure images from all sources are verified in secure boot

View File

@ -302,6 +302,9 @@
!endif !endif
!endif !endif
# IRQs 5, 9, 10, 11 are level-triggered
gPcAtChipsetPkgTokenSpaceGuid.Pcd8259LegacyModeEdgeLevel|0x0E20
!if $(SECURE_BOOT_ENABLE) == TRUE !if $(SECURE_BOOT_ENABLE) == TRUE
# override the default values from SecurityPkg to ensure images from all sources are verified in secure boot # override the default values from SecurityPkg to ensure images from all sources are verified in secure boot
gEfiSecurityPkgTokenSpaceGuid.PcdOptionRomImageVerificationPolicy|0x05 gEfiSecurityPkgTokenSpaceGuid.PcdOptionRomImageVerificationPolicy|0x05