/** @file This file contains Madt Talbe initialized work. Copyright (c) 2013-2015 Intel Corporation. This program and the accompanying materials are licensed and made available under the terms and conditions of the BSD License which accompanies this distribution. The full text of the license may be found at http://opensource.org/licenses/bsd-license.php THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. **/ // // Statements that include other files // #include "AcpiPlatform.h" VOID InitMadtConfigData (MADT_CONFIG_DATA *mConfigData) { mConfigData->MadtInterruptSetting[0].Enable = PcdGet8 (PcdInterruptOverrideSettingTable0Enable); mConfigData->MadtInterruptSetting[0].SourceIrq = PcdGet8 (PcdInterruptOverrideSettingTable0SourceIrq); mConfigData->MadtInterruptSetting[0].Polarity = PcdGet8 (PcdInterruptOverrideSettingTable0Polarity); mConfigData->MadtInterruptSetting[0].TrigerMode = PcdGet8 (PcdInterruptOverrideSettingTable0TrigerMode); mConfigData->MadtInterruptSetting[0].GlobalIrq = PcdGet32 (PcdInterruptOverrideSettingTable0GlobalIrq); mConfigData->MadtInterruptSetting[1].Enable = PcdGet8 (PcdInterruptOverrideSettingTable1Enable); mConfigData->MadtInterruptSetting[1].SourceIrq = PcdGet8 (PcdInterruptOverrideSettingTable1SourceIrq); mConfigData->MadtInterruptSetting[1].Polarity = PcdGet8 (PcdInterruptOverrideSettingTable1Polarity); mConfigData->MadtInterruptSetting[1].TrigerMode = PcdGet8 (PcdInterruptOverrideSettingTable1TrigerMode); mConfigData->MadtInterruptSetting[1].GlobalIrq = PcdGet32 (PcdInterruptOverrideSettingTable1GlobalIrq); mConfigData->MadtInterruptSetting[2].Enable = PcdGet8 (PcdInterruptOverrideSettingTable2Enable); mConfigData->MadtInterruptSetting[2].SourceIrq = PcdGet8 (PcdInterruptOverrideSettingTable2SourceIrq); mConfigData->MadtInterruptSetting[2].Polarity = PcdGet8 (PcdInterruptOverrideSettingTable2Polarity); mConfigData->MadtInterruptSetting[2].TrigerMode = PcdGet8 (PcdInterruptOverrideSettingTable2TrigerMode); mConfigData->MadtInterruptSetting[2].GlobalIrq = PcdGet32 (PcdInterruptOverrideSettingTable2GlobalIrq); mConfigData->MadtInterruptSetting[3].Enable = PcdGet8 (PcdInterruptOverrideSettingTable3Enable); mConfigData->MadtInterruptSetting[3].SourceIrq = PcdGet8 (PcdInterruptOverrideSettingTable3SourceIrq); mConfigData->MadtInterruptSetting[3].Polarity = PcdGet8 (PcdInterruptOverrideSettingTable3Polarity); mConfigData->MadtInterruptSetting[3].TrigerMode = PcdGet8 (PcdInterruptOverrideSettingTable3TrigerMode); mConfigData->MadtInterruptSetting[3].GlobalIrq = PcdGet32 (PcdInterruptOverrideSettingTable3GlobalIrq); mConfigData->MadtInterruptSetting[4].Enable = PcdGet8 (PcdInterruptOverrideSettingTable4Enable); mConfigData->MadtInterruptSetting[4].SourceIrq = PcdGet8 (PcdInterruptOverrideSettingTable4SourceIrq); mConfigData->MadtInterruptSetting[4].Polarity = PcdGet8 (PcdInterruptOverrideSettingTable4Polarity); mConfigData->MadtInterruptSetting[4].TrigerMode = PcdGet8 (PcdInterruptOverrideSettingTable4TrigerMode); mConfigData->MadtInterruptSetting[4].GlobalIrq = PcdGet32 (PcdInterruptOverrideSettingTable4GlobalIrq); mConfigData->MadtInterruptSetting[5].Enable = PcdGet8 (PcdInterruptOverrideSettingTable5Enable); mConfigData->MadtInterruptSetting[5].SourceIrq = PcdGet8 (PcdInterruptOverrideSettingTable5SourceIrq); mConfigData->MadtInterruptSetting[5].Polarity = PcdGet8 (PcdInterruptOverrideSettingTable5Polarity); mConfigData->MadtInterruptSetting[5].TrigerMode = PcdGet8 (PcdInterruptOverrideSettingTable5TrigerMode); mConfigData->MadtInterruptSetting[5].GlobalIrq = PcdGet32 (PcdInterruptOverrideSettingTable5GlobalIrq); mConfigData->MadtInterruptSetting[6].Enable = PcdGet8 (PcdInterruptOverrideSettingTable6Enable); mConfigData->MadtInterruptSetting[6].SourceIrq = PcdGet8 (PcdInterruptOverrideSettingTable6SourceIrq); mConfigData->MadtInterruptSetting[6].Polarity = PcdGet8 (PcdInterruptOverrideSettingTable6Polarity); mConfigData->MadtInterruptSetting[6].TrigerMode = PcdGet8 (PcdInterruptOverrideSettingTable6TrigerMode); mConfigData->MadtInterruptSetting[6].GlobalIrq = PcdGet32 (PcdInterruptOverrideSettingTable6GlobalIrq); mConfigData->MadtInterruptSetting[7].Enable = PcdGet8 (PcdInterruptOverrideSettingTable7Enable); mConfigData->MadtInterruptSetting[7].SourceIrq = PcdGet8 (PcdInterruptOverrideSettingTable7SourceIrq); mConfigData->MadtInterruptSetting[7].Polarity = PcdGet8 (PcdInterruptOverrideSettingTable7Polarity); mConfigData->MadtInterruptSetting[7].TrigerMode = PcdGet8 (PcdInterruptOverrideSettingTable7TrigerMode); mConfigData->MadtInterruptSetting[7].GlobalIrq = PcdGet32 (PcdInterruptOverrideSettingTable7GlobalIrq); mConfigData->MadtInterruptSetting[8].Enable = PcdGet8 (PcdInterruptOverrideSettingTable8Enable); mConfigData->MadtInterruptSetting[8].SourceIrq = PcdGet8 (PcdInterruptOverrideSettingTable8SourceIrq); mConfigData->MadtInterruptSetting[8].Polarity = PcdGet8 (PcdInterruptOverrideSettingTable8Polarity); mConfigData->MadtInterruptSetting[8].TrigerMode = PcdGet8 (PcdInterruptOverrideSettingTable8TrigerMode); mConfigData->MadtInterruptSetting[8].GlobalIrq = PcdGet32 (PcdInterruptOverrideSettingTable8GlobalIrq); mConfigData->MadtInterruptSetting[9].Enable = PcdGet8 (PcdInterruptOverrideSettingTable9Enable); mConfigData->MadtInterruptSetting[9].SourceIrq = PcdGet8 (PcdInterruptOverrideSettingTable9SourceIrq); mConfigData->MadtInterruptSetting[9].Polarity = PcdGet8 (PcdInterruptOverrideSettingTable9Polarity); mConfigData->MadtInterruptSetting[9].TrigerMode = PcdGet8 (PcdInterruptOverrideSettingTable9TrigerMode); mConfigData->MadtInterruptSetting[9].GlobalIrq = PcdGet32 (PcdInterruptOverrideSettingTable9GlobalIrq); mConfigData->MadtInterruptSetting[10].Enable = PcdGet8 (PcdInterruptOverrideSettingTable10Enable); mConfigData->MadtInterruptSetting[10].SourceIrq = PcdGet8 (PcdInterruptOverrideSettingTable10SourceIrq); mConfigData->MadtInterruptSetting[10].Polarity = PcdGet8 (PcdInterruptOverrideSettingTable10Polarity); mConfigData->MadtInterruptSetting[10].TrigerMode = PcdGet8 (PcdInterruptOverrideSettingTable10TrigerMode); mConfigData->MadtInterruptSetting[10].GlobalIrq = PcdGet32 (PcdInterruptOverrideSettingTable10GlobalIrq); mConfigData->MadtInterruptSetting[11].Enable = PcdGet8 (PcdInterruptOverrideSettingTable11Enable); mConfigData->MadtInterruptSetting[11].SourceIrq = PcdGet8 (PcdInterruptOverrideSettingTable11SourceIrq); mConfigData->MadtInterruptSetting[11].Polarity = PcdGet8 (PcdInterruptOverrideSettingTable11Polarity); mConfigData->MadtInterruptSetting[11].TrigerMode = PcdGet8 (PcdInterruptOverrideSettingTable11TrigerMode); mConfigData->MadtInterruptSetting[11].GlobalIrq = PcdGet32 (PcdInterruptOverrideSettingTable11GlobalIrq); mConfigData->MadtInterruptSetting[12].Enable = PcdGet8 (PcdInterruptOverrideSettingTable12Enable); mConfigData->MadtInterruptSetting[12].SourceIrq = PcdGet8 (PcdInterruptOverrideSettingTable12SourceIrq); mConfigData->MadtInterruptSetting[12].Polarity = PcdGet8 (PcdInterruptOverrideSettingTable12Polarity); mConfigData->MadtInterruptSetting[12].TrigerMode = PcdGet8 (PcdInterruptOverrideSettingTable12TrigerMode); mConfigData->MadtInterruptSetting[12].GlobalIrq = PcdGet32 (PcdInterruptOverrideSettingTable12GlobalIrq); mConfigData->MadtInterruptSetting[13].Enable = PcdGet8 (PcdInterruptOverrideSettingTable13Enable); mConfigData->MadtInterruptSetting[13].SourceIrq = PcdGet8 (PcdInterruptOverrideSettingTable13SourceIrq); mConfigData->MadtInterruptSetting[13].Polarity = PcdGet8 (PcdInterruptOverrideSettingTable13Polarity); mConfigData->MadtInterruptSetting[13].TrigerMode = PcdGet8 (PcdInterruptOverrideSettingTable13TrigerMode); mConfigData->MadtInterruptSetting[13].GlobalIrq = PcdGet32 (PcdInterruptOverrideSettingTable13GlobalIrq); mConfigData->MadtInterruptSetting[14].Enable = PcdGet8 (PcdInterruptOverrideSettingTable14Enable); mConfigData->MadtInterruptSetting[14].SourceIrq = PcdGet8 (PcdInterruptOverrideSettingTable14SourceIrq); mConfigData->MadtInterruptSetting[14].Polarity = PcdGet8 (PcdInterruptOverrideSettingTable14Polarity); mConfigData->MadtInterruptSetting[14].TrigerMode = PcdGet8 (PcdInterruptOverrideSettingTable14TrigerMode); mConfigData->MadtInterruptSetting[14].GlobalIrq = PcdGet32 (PcdInterruptOverrideSettingTable14GlobalIrq); mConfigData->MadtInterruptSetting[15].Enable = PcdGet8 (PcdInterruptOverrideSettingTable15Enable); mConfigData->MadtInterruptSetting[15].SourceIrq = PcdGet8 (PcdInterruptOverrideSettingTable15SourceIrq); mConfigData->MadtInterruptSetting[15].Polarity = PcdGet8 (PcdInterruptOverrideSettingTable15Polarity); mConfigData->MadtInterruptSetting[15].TrigerMode = PcdGet8 (PcdInterruptOverrideSettingTable15TrigerMode); mConfigData->MadtInterruptSetting[15].GlobalIrq = PcdGet32 (PcdInterruptOverrideSettingTable15GlobalIrq); mConfigData->MadtIoApicSetting.IoApicAddress = (UINT32)PcdGet64(PcdIoApicBaseAddress); mConfigData->MadtIoApicSetting.GlobalInterruptBase = PcdGet32 (PcdIoApicSettingGlobalInterruptBase); mConfigData->MadtIoApicSetting.IoApicId = PcdGet8 (PcdIoApicSettingIoApicId); mConfigData->MadtIoApicSetting.NmiEnable = PcdGet8 (PcdIoApicSettingNmiEnable); mConfigData->MadtIoApicSetting.NmiSource = PcdGet8 (PcdIoApicSettingNmiSource); mConfigData->MadtIoApicSetting.Polarity = PcdGet8 (PcdIoApicSettingPolarity); mConfigData->MadtIoApicSetting.TrigerMode = PcdGet8 (PcdIoApicSettingTrigerMode); mConfigData->MadtLocalApicSetting.NmiEnabelApicIdMask = PcdGet8 (PcdLocalApicSettingNmiEnabelApicIdMask); mConfigData->MadtLocalApicSetting.AddressOverrideEnable = PcdGet8 (PcdLocalApicSettingAddressOverrideEnable); mConfigData->MadtLocalApicSetting.Polarity = PcdGet8 (PcdLocalApicSettingPolarity); mConfigData->MadtLocalApicSetting.TrigerMode = PcdGet8 (PcdLocalApicSettingTrigerMode); mConfigData->MadtLocalApicSetting.LocalApicLint = PcdGet8 (PcdLocalApicSettingLocalApicLint); mConfigData->MadtLocalApicSetting.LocalApicAddressOverride = PcdGet64 (PcdLocalApicAddressOverride); mConfigData->MadtLocalApicSetting.LocalApicAddress = PcdGet32 (PcdCpuLocalApicBaseAddress); } UINT32 GetAcutalMadtTableSize ( IN MADT_CONFIG_DATA * MadtConfigData, IN INTN NumberOfCPUs ) { UINT32 MadtSize; UINT8 Index; MadtSize = (UINT32)(sizeof (EFI_ACPI_2_0_MULTIPLE_APIC_DESCRIPTION_TABLE_HEADER) + sizeof (EFI_ACPI_2_0_PROCESSOR_LOCAL_APIC_STRUCTURE) * NumberOfCPUs + sizeof (EFI_ACPI_2_0_IO_APIC_STRUCTURE) + sizeof (EFI_ACPI_2_0_LOCAL_APIC_ADDRESS_OVERRIDE_STRUCTURE) * (MadtConfigData->MadtLocalApicSetting.AddressOverrideEnable != 0?1:0) ); for (Index = 0; Index < EFI_ACPI_INTERRUPT_SOURCE_OVERRIDE_COUNT_MAX; Index ++ ) { if (MadtConfigData->MadtInterruptSetting[Index].Enable != 0) { MadtSize += sizeof (EFI_ACPI_2_0_INTERRUPT_SOURCE_OVERRIDE_STRUCTURE); } } for (Index = 0; Index < NumberOfCPUs; Index ++ ) { if (0 != (MadtConfigData->MadtLocalApicSetting.NmiEnabelApicIdMask & (1 << Index))) { MadtSize += sizeof (EFI_ACPI_2_0_LOCAL_APIC_NMI_STRUCTURE); } } if (0 != MadtConfigData->MadtIoApicSetting.NmiEnable) { MadtSize += sizeof (EFI_ACPI_2_0_NON_MASKABLE_INTERRUPT_SOURCE_STRUCTURE); } return MadtSize; } // // Init Multiple APIC Description Table // EFI_STATUS MadtTableInitialize ( OUT EFI_ACPI_COMMON_HEADER **MadtTable, OUT UINTN *Size ) { EFI_ACPI_2_0_MULTIPLE_APIC_DESCRIPTION_TABLE_HEADER *Madt; EFI_ACPI_2_0_PROCESSOR_LOCAL_APIC_STRUCTURE *ProcLocalApic; EFI_ACPI_2_0_IO_APIC_STRUCTURE *IoApic; EFI_ACPI_2_0_INTERRUPT_SOURCE_OVERRIDE_STRUCTURE *InterruptSourceOverride; EFI_ACPI_2_0_NON_MASKABLE_INTERRUPT_SOURCE_STRUCTURE *IoApicNmiSource; EFI_ACPI_2_0_LOCAL_APIC_NMI_STRUCTURE *LocalApicNmiSource; EFI_ACPI_2_0_LOCAL_APIC_ADDRESS_OVERRIDE_STRUCTURE *LocalApicAddressOverride; EFI_MP_SERVICES_PROTOCOL *MpService; UINTN NumberOfCPUs; UINTN NumberOfEnabledCPUs; MADT_CONFIG_DATA MadtConfigData; UINT32 MadtSize; UINTN Index; EFI_STATUS Status; ASSERT (NULL != MadtTable); ASSERT (NULL != Size); // // Init Madt table data // InitMadtConfigData (&MadtConfigData); // // Find the MP Protocol. This is an MP platform, so MP protocol must be // there. // Status = gBS->LocateProtocol ( &gEfiMpServiceProtocolGuid, NULL, (VOID **)&MpService ); ASSERT_EFI_ERROR (Status); // // Determine the number of processors // MpService->GetNumberOfProcessors ( MpService, &NumberOfCPUs, &NumberOfEnabledCPUs ); //ASSERT (NumberOfCPUs <= 2 && NumberOfCPUs > 0); MadtSize = GetAcutalMadtTableSize (&MadtConfigData, NumberOfCPUs); Madt = (EFI_ACPI_2_0_MULTIPLE_APIC_DESCRIPTION_TABLE_HEADER *)AllocateZeroPool (MadtSize); ASSERT (Madt != NULL); // // Initialize MADT Header information // Madt->Header.Signature = EFI_ACPI_2_0_MULTIPLE_SAPIC_DESCRIPTION_TABLE_SIGNATURE; Madt->Header.Length = MadtSize; Madt->Header.Revision = EFI_ACPI_2_0_MULTIPLE_APIC_DESCRIPTION_TABLE_REVISION; Madt->Header.OemTableId = EFI_ACPI_OEM_TABLE_ID; Madt->Header.OemRevision = EFI_ACPI_OEM_MADT_REVISION; Madt->Header.CreatorId = EFI_ACPI_CREATOR_ID; Madt->LocalApicAddress = MadtConfigData.MadtLocalApicSetting.LocalApicAddress; Madt->Flags = EFI_ACPI_2_0_MULTIPLE_APIC_FLAGS; CopyMem (Madt->Header.OemId, EFI_ACPI_OEM_ID, 6); ProcLocalApic = (EFI_ACPI_2_0_PROCESSOR_LOCAL_APIC_STRUCTURE *) (Madt + 1); // // Initialization of Processor's local APICs // for (Index = 0;Index < NumberOfCPUs; Index++) { ProcLocalApic[Index].Type = EFI_ACPI_2_0_PROCESSOR_LOCAL_APIC; ProcLocalApic[Index].Length = sizeof (EFI_ACPI_2_0_PROCESSOR_LOCAL_APIC_STRUCTURE); ProcLocalApic[Index].AcpiProcessorId = (UINT8)(Index + 1); ProcLocalApic[Index].ApicId = 0xff; ProcLocalApic[Index].Flags = 0; } // // Initialization of IO APIC. // Note: Here assumes that there must be one and only one IO APIC in platform. // IoApic = (EFI_ACPI_2_0_IO_APIC_STRUCTURE *) (&ProcLocalApic[Index]); IoApic->Type = EFI_ACPI_2_0_IO_APIC; IoApic->Length = sizeof (EFI_ACPI_2_0_IO_APIC_STRUCTURE); IoApic->IoApicId = MadtConfigData.MadtIoApicSetting.IoApicId; IoApic->IoApicAddress = MadtConfigData.MadtIoApicSetting.IoApicAddress; IoApic->GlobalSystemInterruptBase = MadtConfigData.MadtIoApicSetting.GlobalInterruptBase; InterruptSourceOverride = (EFI_ACPI_2_0_INTERRUPT_SOURCE_OVERRIDE_STRUCTURE *) (IoApic + 1); for (Index = 0;Index < EFI_ACPI_INTERRUPT_SOURCE_OVERRIDE_COUNT_MAX; Index++ ){ if (MadtConfigData.MadtInterruptSetting[Index].Enable) { InterruptSourceOverride->Type = EFI_ACPI_2_0_INTERRUPT_SOURCE_OVERRIDE; InterruptSourceOverride->Length = sizeof (EFI_ACPI_2_0_INTERRUPT_SOURCE_OVERRIDE_STRUCTURE); InterruptSourceOverride->Bus = 0; InterruptSourceOverride->Source = MadtConfigData.MadtInterruptSetting[Index].SourceIrq; InterruptSourceOverride->Flags = ((MadtConfigData.MadtInterruptSetting[Index].TrigerMode & 0x03) << 2) | (MadtConfigData.MadtInterruptSetting[Index].Polarity & 0x03); InterruptSourceOverride->GlobalSystemInterrupt = MadtConfigData.MadtInterruptSetting[Index].GlobalIrq; InterruptSourceOverride++; } } // // support NMI source configuration. // IoApicNmiSource = (EFI_ACPI_2_0_NON_MASKABLE_INTERRUPT_SOURCE_STRUCTURE *) InterruptSourceOverride; if ((BOOLEAN) MadtConfigData.MadtIoApicSetting.NmiEnable) { IoApicNmiSource->Type = EFI_ACPI_2_0_NON_MASKABLE_INTERRUPT_SOURCE; IoApicNmiSource->Length = sizeof (EFI_ACPI_2_0_NON_MASKABLE_INTERRUPT_SOURCE_STRUCTURE); IoApicNmiSource->Flags = ((MadtConfigData.MadtIoApicSetting.TrigerMode & 0x03) << 2) | (MadtConfigData.MadtIoApicSetting.Polarity & 0x03); IoApicNmiSource->GlobalSystemInterrupt = MadtConfigData.MadtIoApicSetting.NmiSource; IoApicNmiSource ++; } // // Assume each processor has same NMI interrupt source. // LocalApicNmiSource = (EFI_ACPI_2_0_LOCAL_APIC_NMI_STRUCTURE *) IoApicNmiSource; for (Index = 0;Index < NumberOfCPUs; Index++) { if (0 != (MadtConfigData.MadtLocalApicSetting.NmiEnabelApicIdMask & (1 << Index))){ LocalApicNmiSource->Type = EFI_ACPI_2_0_LOCAL_APIC_NMI; LocalApicNmiSource->Length = sizeof (EFI_ACPI_2_0_LOCAL_APIC_NMI_STRUCTURE); LocalApicNmiSource->LocalApicLint = MadtConfigData.MadtLocalApicSetting.LocalApicLint; LocalApicNmiSource->Flags = ((MadtConfigData.MadtLocalApicSetting.TrigerMode & 0x03) << 2) | (MadtConfigData.MadtLocalApicSetting.Polarity & 0x03); LocalApicNmiSource->AcpiProcessorId = (UINT8)(Index + 1); LocalApicNmiSource++; } } LocalApicAddressOverride = (EFI_ACPI_2_0_LOCAL_APIC_ADDRESS_OVERRIDE_STRUCTURE *) LocalApicNmiSource; if ((BOOLEAN) MadtConfigData.MadtLocalApicSetting.AddressOverrideEnable) { LocalApicAddressOverride->Type = EFI_ACPI_2_0_LOCAL_APIC_ADDRESS_OVERRIDE; LocalApicAddressOverride->Length = sizeof (EFI_ACPI_2_0_LOCAL_APIC_ADDRESS_OVERRIDE_STRUCTURE); LocalApicAddressOverride->LocalApicAddress = MadtConfigData.MadtLocalApicSetting.LocalApicAddressOverride; LocalApicAddressOverride++; } *Size = MadtSize; *MadtTable = (EFI_ACPI_COMMON_HEADER *) Madt; return EFI_SUCCESS; }