/** Check if XD and BTS features are supported by all processors. **/ VOID CheckProcessorFeature ( VOID ) { EFI_STATUS Status; EFI_MP_SERVICES_PROTOCOL *MpServices; Status = gBS->LocateProtocol (&gEfiMpServiceProtocolGuid, NULL, (VOID **)&MpServices); ASSERT_EFI_ERROR (Status); // // First detect if XD and BTS are supported // mXdSupported = TRUE; mBtsSupported = TRUE; // // Check if XD and BTS are supported on all processors. // CheckFeatureSupported (); // //Check on other processors if BSP supports this // if (mXdSupported || mBtsSupported) { MpServices->StartupAllAPs ( MpServices, (EFI_AP_PROCEDURE) CheckFeatureSupported, TRUE, NULL, 0, NULL, NULL ); } }
/** The module Entry Point of the CPU SMM driver. @param ImageHandle The firmware allocated handle for the EFI image. @param SystemTable A pointer to the EFI System Table. @retval EFI_SUCCESS The entry point is executed successfully. @retval Other Some error occurs when executing this entry point. **/ EFI_STATUS EFIAPI PiCpuSmmEntry ( IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable ) { EFI_STATUS Status; EFI_MP_SERVICES_PROTOCOL *MpServices; UINTN NumberOfEnabledProcessors; UINTN Index; VOID *Buffer; UINTN BufferPages; UINTN TileCodeSize; UINTN TileDataSize; UINTN TileSize; UINT8 *Stacks; VOID *Registration; UINT32 RegEax; UINT32 RegEdx; UINTN FamilyId; UINTN ModelId; UINT32 Cr3; // // Initialize Debug Agent to support source level debug in SMM code // InitializeDebugAgent (DEBUG_AGENT_INIT_SMM, NULL, NULL); // // Report the start of CPU SMM initialization. // REPORT_STATUS_CODE ( EFI_PROGRESS_CODE, EFI_COMPUTING_UNIT_HOST_PROCESSOR | EFI_CU_HP_PC_SMM_INIT ); // // Fix segment address of the long-mode-switch jump // if (sizeof (UINTN) == sizeof (UINT64)) { gSmmJmpAddr.Segment = LONG_MODE_CODE_SEGMENT; } // // Find out SMRR Base and SMRR Size // FindSmramInfo (&mCpuHotPlugData.SmrrBase, &mCpuHotPlugData.SmrrSize); // // Get MP Services Protocol // Status = SystemTable->BootServices->LocateProtocol (&gEfiMpServiceProtocolGuid, NULL, (VOID **)&MpServices); ASSERT_EFI_ERROR (Status); // // Use MP Services Protocol to retrieve the number of processors and number of enabled processors // Status = MpServices->GetNumberOfProcessors (MpServices, &mNumberOfCpus, &NumberOfEnabledProcessors); ASSERT_EFI_ERROR (Status); ASSERT (mNumberOfCpus <= PcdGet32 (PcdCpuMaxLogicalProcessorNumber)); // // If support CPU hot plug, PcdCpuSmmEnableBspElection should be set to TRUE. // A constant BSP index makes no sense because it may be hot removed. // DEBUG_CODE ( if (FeaturePcdGet (PcdCpuHotPlugSupport)) { ASSERT (FeaturePcdGet (PcdCpuSmmEnableBspElection)); } );
/** Entry point for Acpi platform driver. @param[in] ImageHandle A handle for the image that is initializing this driver. @param[in] SystemTable A pointer to the EFI system table. @retval EFI_SUCCESS Driver initialized successfully. @retval EFI_LOAD_ERROR Failed to Initialize or has been loaded. @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources. **/ EFI_STATUS EFIAPI AcpiPlatformEntryPoint ( IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable ) { EFI_STATUS Status; EFI_STATUS AcpiStatus; EFI_ACPI_SUPPORT_PROTOCOL *AcpiSupport; EFI_FIRMWARE_VOLUME_PROTOCOL *FwVol; INTN Instance; EFI_ACPI_COMMON_HEADER *CurrentTable; UINTN TableHandle; UINT32 FvStatus; UINT32 Size; EFI_EVENT Event; EFI_ACPI_TABLE_VERSION TableVersion; UINTN VarSize; UINTN SysCfgSize; EFI_HANDLE Handle; EFI_PS2_POLICY_PROTOCOL *Ps2Policy; EFI_PEI_HOB_POINTERS GuidHob; UINT8 PortData; EFI_MP_SERVICES_PROTOCOL *MpService; UINTN MaximumNumberOfCPUs; UINTN NumberOfEnabledCPUs; UINT32 Data32; PCH_STEPPING pchStepping; mFirstNotify = FALSE; TableVersion = EFI_ACPI_TABLE_VERSION_2_0; Instance = 0; CurrentTable = NULL; TableHandle = 0; Data32 = 0; // // Update HOB variable for PCI resource information. // Get the HOB list. If it is not present, then ASSERT. // GuidHob.Raw = GetHobList (); if (GuidHob.Raw != NULL) { if ((GuidHob.Raw = GetNextGuidHob (&gEfiPlatformInfoGuid, GuidHob.Raw)) != NULL) { mPlatformInfo = GET_GUID_HOB_DATA (GuidHob.Guid); } } // // Search for the Memory Configuration GUID HOB. If it is not present, then // there's nothing we can do. It may not exist on the update path. // VarSize = sizeof(SYSTEM_CONFIGURATION); Status = gRT->GetVariable( L"Setup", &mSystemConfigurationGuid, NULL, &VarSize, &mSystemConfiguration ); ASSERT_EFI_ERROR (Status); // // Find the AcpiSupport protocol. // Status = LocateSupportProtocol (&gEfiAcpiSupportProtocolGuid, (VOID **) &AcpiSupport, 0); ASSERT_EFI_ERROR (Status); // // Locate the firmware volume protocol. // Status = LocateSupportProtocol (&gEfiFirmwareVolumeProtocolGuid, (VOID **) &FwVol, 1); ASSERT_EFI_ERROR (Status); // // Read the current system configuration variable store. // SysCfgSize = sizeof(SYSTEM_CONFIGURATION); Status = gRT->GetVariable ( L"Setup", &gEfiNormalSetupGuid, NULL, &SysCfgSize, &mSystemConfig ); Status = EFI_SUCCESS; Instance = 0; // // TBD: Need re-design based on the ValleyTrail platform. // Status = gBS->LocateProtocol ( &gEfiMpServiceProtocolGuid, NULL, (VOID **) &MpService ); if (EFI_ERROR (Status)) { return Status; } // // Determine the number of processors. // MpService->GetNumberOfProcessors ( MpService, &MaximumNumberOfCPUs, &NumberOfEnabledCPUs ); // // Allocate and initialize the NVS area for SMM and ASL communication. // Status = gBS->AllocatePool ( EfiACPIMemoryNVS, sizeof (EFI_GLOBAL_NVS_AREA), (void **)&mGlobalNvsArea.Area ); ASSERT_EFI_ERROR (Status); gBS->SetMem ( mGlobalNvsArea.Area, sizeof (EFI_GLOBAL_NVS_AREA), 0 ); DEBUG((EFI_D_ERROR, "mGlobalNvsArea.Area is at 0x%X\n", mGlobalNvsArea.Area)); // // Update global NVS area for ASL and SMM init code to use. // mGlobalNvsArea.Area->ApicEnable = 1; mGlobalNvsArea.Area->EmaEnable = 0; mGlobalNvsArea.Area->NumberOfBatteries = 1; mGlobalNvsArea.Area->BatteryCapacity0 = 100; mGlobalNvsArea.Area->BatteryStatus0 = 84; mGlobalNvsArea.Area->OnboardCom = 1; mGlobalNvsArea.Area->IdeMode = 0; mGlobalNvsArea.Area->PowerState = 0; mGlobalNvsArea.Area->LogicalProcessorCount = (UINT8)NumberOfEnabledCPUs; mGlobalNvsArea.Area->PassiveThermalTripPoint = mSystemConfiguration.PassiveThermalTripPoint; mGlobalNvsArea.Area->PassiveTc1Value = mSystemConfiguration.PassiveTc1Value; mGlobalNvsArea.Area->PassiveTc2Value = mSystemConfiguration.PassiveTc2Value; mGlobalNvsArea.Area->PassiveTspValue = mSystemConfiguration.PassiveTspValue; mGlobalNvsArea.Area->CriticalThermalTripPoint = mSystemConfiguration.CriticalThermalTripPoint; mGlobalNvsArea.Area->IgdPanelType = mSystemConfiguration.IgdFlatPanel; mGlobalNvsArea.Area->IgdPanelScaling = mSystemConfiguration.PanelScaling; mGlobalNvsArea.Area->IgdSciSmiMode = 0; mGlobalNvsArea.Area->IgdTvFormat = 0; mGlobalNvsArea.Area->IgdTvMinor = 0; mGlobalNvsArea.Area->IgdSscConfig = 1; mGlobalNvsArea.Area->IgdBiaConfig = mSystemConfiguration.IgdLcdIBia; mGlobalNvsArea.Area->IgdBlcConfig = mSystemConfiguration.IgdLcdIGmchBlc; mGlobalNvsArea.Area->IgdDvmtMemSize = mSystemConfiguration.IgdDvmt50TotalAlloc; mGlobalNvsArea.Area->IgdPAVP = mSystemConfiguration.PavpMode; mGlobalNvsArea.Area->AlsEnable = mSystemConfiguration.AlsEnable; mGlobalNvsArea.Area->BacklightControlSupport = 2; mGlobalNvsArea.Area->BrightnessPercentage = 100; mGlobalNvsArea.Area->IgdState = 1; mGlobalNvsArea.Area->LidState = 1; mGlobalNvsArea.Area->DeviceId1 = 0x80000100 ; mGlobalNvsArea.Area->DeviceId2 = 0x80000400 ; mGlobalNvsArea.Area->DeviceId3 = 0x80000200 ; mGlobalNvsArea.Area->DeviceId4 = 0x04; mGlobalNvsArea.Area->DeviceId5 = 0x05; mGlobalNvsArea.Area->NumberOfValidDeviceId = 4 ; mGlobalNvsArea.Area->CurrentDeviceList = 0x0F ; mGlobalNvsArea.Area->PreviousDeviceList = 0x0F ; mGlobalNvsArea.Area->UartSelection = mSystemConfiguration.UartInterface; mGlobalNvsArea.Area->PcuUart1Enable = mSystemConfiguration.PcuUart1; mGlobalNvsArea.Area->NativePCIESupport = 1; // // Update BootMode: 0:ACPI mode; 1:PCI mode // mGlobalNvsArea.Area->LpssSccMode = mSystemConfiguration.LpssPciModeEnabled; if (mSystemConfiguration.LpssMipiHsi == 0) { mGlobalNvsArea.Area->MipiHsiAddr = 0; mGlobalNvsArea.Area->MipiHsiLen = 0; mGlobalNvsArea.Area->MipiHsi1Addr = 0; mGlobalNvsArea.Area->MipiHsi1Len = 0; } // // Platform Flavor // mGlobalNvsArea.Area->PlatformFlavor = mPlatformInfo->PlatformFlavor; // // Update the Platform id // mGlobalNvsArea.Area->BoardID = mPlatformInfo->BoardId; // // Update the Board Revision // mGlobalNvsArea.Area->FabID = mPlatformInfo->BoardRev; // // Update SOC Stepping // mGlobalNvsArea.Area->SocStepping = (UINT8)(PchStepping()); mGlobalNvsArea.Area->OtgMode = mSystemConfiguration.PchUsbOtg; pchStepping = PchStepping(); if (mSystemConfiguration.UsbAutoMode == 1) { // // Auto mode is enabled. // if (PchA0 == pchStepping) { // // For A0, EHCI is enabled as default. // mSystemConfiguration.PchUsb20 = 1; mSystemConfiguration.PchUsb30Mode = 0; mSystemConfiguration.UsbXhciSupport = 0; DEBUG ((EFI_D_INFO, "EHCI is enabled as default. SOC 0x%x\n", pchStepping)); } else { // // For A1 and later, XHCI is enabled as default. // mSystemConfiguration.PchUsb20 = 0; mSystemConfiguration.PchUsb30Mode = 1; mSystemConfiguration.UsbXhciSupport = 1; DEBUG ((EFI_D_INFO, "XHCI is enabled as default. SOC 0x%x\n", pchStepping)); } } mGlobalNvsArea.Area->XhciMode = mSystemConfiguration.PchUsb30Mode; mGlobalNvsArea.Area->Stepping = mPlatformInfo->IchRevision; // // Override invalid Pre-Boot Driver and XhciMode combination. // if ((mSystemConfiguration.UsbXhciSupport == 0) && (mSystemConfiguration.PchUsb30Mode == 3)) { mGlobalNvsArea.Area->XhciMode = 2; } if ((mSystemConfiguration.UsbXhciSupport == 1) && (mSystemConfiguration.PchUsb30Mode == 2)) { mGlobalNvsArea.Area->XhciMode = 3; } DEBUG ((EFI_D_ERROR, "ACPI NVS XHCI:0x%x\n", mGlobalNvsArea.Area->XhciMode)); mGlobalNvsArea.Area->PmicEnable = GLOBAL_NVS_DEVICE_DISABLE; mGlobalNvsArea.Area->BatteryChargingSolution = GLOBAL_NVS_DEVICE_DISABLE; mGlobalNvsArea.Area->ISPDevSel = mSystemConfiguration.ISPDevSel; mGlobalNvsArea.Area->LpeEnable = mSystemConfiguration.Lpe; if (mSystemConfiguration.ISPEn == 0) { mGlobalNvsArea.Area->ISPDevSel = GLOBAL_NVS_DEVICE_DISABLE; } mGlobalNvsArea.Area->WittEnable = mSystemConfiguration.WittEnable; mGlobalNvsArea.Area->UtsEnable = mSystemConfiguration.UtsEnable; mGlobalNvsArea.Area->SarEnable = mSystemConfiguration.SAR1; mGlobalNvsArea.Area->ReservedO = 1; SettingI2CTouchAddress(); mGlobalNvsArea.Area->IdleReserve= mSystemConfiguration.IdleReserve; // // Read BMBOUND and store it in GlobalNVS to pass into ASL. // // BUGBUG: code was moved into silicon reference code. // if (mSystemConfiguration.eMMCBootMode== 1) { // // Auto detect mode. // DEBUG ((EFI_D_ERROR, "Auto detect mode------------start\n")); // // Silicon Steppings. // switch (PchStepping()) { case PchA0: // A0/A1 case PchA1: DEBUG ((EFI_D_ERROR, "SOC A0/A1: eMMC 4.41 Configuration\n")); mSystemConfiguration.LpsseMMCEnabled = 1; mSystemConfiguration.LpsseMMC45Enabled = 0; break; case PchB0: // B0 and later. default: DEBUG ((EFI_D_ERROR, "SOC B0 and later: eMMC 4.5 Configuration\n")); mSystemConfiguration.LpsseMMCEnabled = 0; mSystemConfiguration.LpsseMMC45Enabled = 1; break; } } else if (mSystemConfiguration.eMMCBootMode == 2) { // // eMMC 4.41 // DEBUG ((EFI_D_ERROR, "Force to eMMC 4.41 Configuration\n")); mSystemConfiguration.LpsseMMCEnabled = 1; mSystemConfiguration.LpsseMMC45Enabled = 0; } else if (mSystemConfiguration.eMMCBootMode == 3) { // // eMMC 4.5 // DEBUG ((EFI_D_ERROR, "Force to eMMC 4.5 Configuration\n")); mSystemConfiguration.LpsseMMCEnabled = 0; mSystemConfiguration.LpsseMMC45Enabled = 1; } else { // // Disable eMMC controllers. // DEBUG ((EFI_D_ERROR, "Disable eMMC controllers\n")); mSystemConfiguration.LpsseMMCEnabled = 0; mSystemConfiguration.LpsseMMC45Enabled = 0; } mGlobalNvsArea.Area->emmcVersion = 0; if (mSystemConfiguration.LpsseMMCEnabled) { DEBUG ((EFI_D_ERROR, "mGlobalNvsArea.Area->emmcVersion = 0\n")); mGlobalNvsArea.Area->emmcVersion = 0; } if (mSystemConfiguration.LpsseMMC45Enabled) { DEBUG ((EFI_D_ERROR, "mGlobalNvsArea.Area->emmcVersion = 1\n")); mGlobalNvsArea.Area->emmcVersion = 1; } mGlobalNvsArea.Area->SdCardRemovable = mSystemConfiguration.SdCardRemovable; // // Microsoft IOT // if ((mSystemConfiguration.LpssHsuart0FlowControlEnabled == 1) && \ (mSystemConfiguration.LpssPwm0Enabled == 0) && \ (mSystemConfiguration.LpssPwm1Enabled == 0)) { mGlobalNvsArea.Area->MicrosoftIoT = GLOBAL_NVS_DEVICE_ENABLE; DEBUG ((EFI_D_ERROR, "JP1 is set to be MSFT IOT configuration.\n")); } else { mGlobalNvsArea.Area->MicrosoftIoT = GLOBAL_NVS_DEVICE_DISABLE; DEBUG ((EFI_D_ERROR, "JP1 is not set to be MSFT IOT configuration.\n")); } // // SIO related option. // Status = gBS->LocateProtocol (&gEfiCpuIoProtocolGuid, NULL, (void **)&mCpuIo); ASSERT_EFI_ERROR (Status); mGlobalNvsArea.Area->WPCN381U = GLOBAL_NVS_DEVICE_DISABLE; mGlobalNvsArea.Area->DockedSioPresent = GLOBAL_NVS_DEVICE_DISABLE; if (mGlobalNvsArea.Area->DockedSioPresent != GLOBAL_NVS_DEVICE_ENABLE) { // // Check ID for SIO WPCN381U. // Status = mCpuIo->Io.Read ( mCpuIo, EfiCpuIoWidthUint8, WPCN381U_CONFIG_INDEX, 1, &PortData ); ASSERT_EFI_ERROR (Status); if (PortData != 0xFF) { PortData = 0x20; Status = mCpuIo->Io.Write ( mCpuIo, EfiCpuIoWidthUint8, WPCN381U_CONFIG_INDEX, 1, &PortData ); ASSERT_EFI_ERROR (Status); Status = mCpuIo->Io.Read ( mCpuIo, EfiCpuIoWidthUint8, WPCN381U_CONFIG_DATA, 1, &PortData ); ASSERT_EFI_ERROR (Status); if ((PortData == WPCN381U_CHIP_ID) || (PortData == WDCP376_CHIP_ID)) { mGlobalNvsArea.Area->WPCN381U = GLOBAL_NVS_DEVICE_ENABLE; mGlobalNvsArea.Area->OnboardCom = GLOBAL_NVS_DEVICE_ENABLE; mGlobalNvsArea.Area->OnboardComCir = GLOBAL_NVS_DEVICE_DISABLE; } } } // // Get Ps2 policy to set. Will be use if present. // Status = gBS->LocateProtocol ( &gEfiPs2PolicyProtocolGuid, NULL, (VOID **)&Ps2Policy ); if (!EFI_ERROR (Status)) { Status = Ps2Policy->Ps2InitHardware (ImageHandle); } mGlobalNvsArea.Area->SDIOMode = mSystemConfiguration.LpssSdioMode; Handle = NULL; Status = gBS->InstallMultipleProtocolInterfaces ( &Handle, &gEfiGlobalNvsAreaProtocolGuid, &mGlobalNvsArea, NULL ); // // Read tables from the storage file. // while (!EFI_ERROR (Status)) { CurrentTable = NULL; Status = FwVol->ReadSection ( FwVol, &gEfiAcpiTableStorageGuid, EFI_SECTION_RAW, Instance, (VOID **) &CurrentTable, (UINTN *) &Size, &FvStatus ); if (!EFI_ERROR (Status)) { // // Allow platform specific code to reject the table or update it. // AcpiStatus = AcpiPlatformHooksIsActiveTable (CurrentTable); if (!EFI_ERROR (AcpiStatus)) { // // Perform any table specific updates. // AcpiStatus = PlatformUpdateTables (CurrentTable); if (!EFI_ERROR (AcpiStatus)) { // // Add the table. // TableHandle = 0; AcpiStatus = AcpiSupport->SetAcpiTable ( AcpiSupport, CurrentTable, TRUE, TableVersion, &TableHandle ); ASSERT_EFI_ERROR (AcpiStatus); } } // // Increment the instance. // Instance++; } } Status = EfiCreateEventReadyToBootEx ( TPL_NOTIFY, OnReadyToBoot, NULL, &Event ); // // Finished. // return EFI_SUCCESS; }
/** This function will update any runtime platform specific information. This currently includes: Setting OEM table values, ID, table ID, creator ID and creator revision. Enabling the proper processor entries in the APIC tables. @param[in] Table The table to update. @retval EFI_SUCCESS The function completed successfully. **/ EFI_STATUS PlatformUpdateTables ( IN OUT EFI_ACPI_COMMON_HEADER *Table ) { EFI_ACPI_DESCRIPTION_HEADER *TableHeader; UINT8 *CurrPtr; UINT8 *EndPtr; ACPI_APIC_STRUCTURE_PTR *ApicPtr; UINT8 CurrProcessor; EFI_STATUS Status; EFI_MP_SERVICES_PROTOCOL *MpService; UINTN MaximumNumberOfCPUs; UINTN NumberOfEnabledCPUs; UINTN BufferSize; ACPI_APIC_STRUCTURE_PTR *ProcessorLocalApicEntry; UINTN BspIndex; EFI_ACPI_1_0_ASF_DESCRIPTION_TABLE *AsfEntry; EFI_ACPI_HIGH_PRECISION_EVENT_TIMER_TABLE_HEADER *HpetTbl; UINT64 OemIdValue; UINT8 Index; EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE *Facp; EFI_ACPI_OSFR_TABLE *OsfrTable; EFI_ACPI_OSFR_OCUR_OBJECT *pOcurObject; EFI_ACPI_OSFR_OCUR_OBJECT OcurObject = {{0xB46F133D, 0x235F, 0x4634, 0x9F, 0x03, 0xB1, 0xC0, 0x1C, 0x54, 0x78, 0x5B}, 0, 0, 0, 0, 0}; CHAR16 *OcurMfgStringBuffer = NULL; CHAR16 *OcurModelStringBuffer = NULL; UINT8 *OcurRefDataBlockBuffer = NULL; UINTN OcurMfgStringBufferSize; UINTN OcurModelStringBufferSize; UINTN OcurRefDataBlockBufferSize; #if defined (IDCC2_SUPPORTED) && IDCC2_SUPPORTED EFI_ACPI_ASPT_TABLE *pSpttTable; #endif UINT16 NumberOfHpets; UINT16 HpetCapIdValue; UINT32 HpetBlockID; UINTN LocalApicCounter; EFI_PROCESSOR_INFORMATION ProcessorInfoBuffer; UINT8 TempVal; EFI_ACPI_3_0_IO_APIC_STRUCTURE *IOApicType; EFI_ACPI_3_0_MULTIPLE_APIC_DESCRIPTION_TABLE_HEADER *APICTableHeader; CurrPtr = NULL; EndPtr = NULL; ApicPtr = NULL; LocalApicCounter = 0; CurrProcessor = 0; ProcessorLocalApicEntry = NULL; if (Table->Signature != EFI_ACPI_1_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_SIGNATURE) { TableHeader = (EFI_ACPI_DESCRIPTION_HEADER *) Table; // // Update the OEMID. // OemIdValue = mPlatformInfo->AcpiOemId; *(UINT32 *)(TableHeader->OemId) = (UINT32)OemIdValue; *(UINT16 *)(TableHeader->OemId + 4) = *(UINT16*)(((UINT8 *)&OemIdValue) + 4); if ((Table->Signature != EFI_ACPI_2_0_SECONDARY_SYSTEM_DESCRIPTION_TABLE_SIGNATURE)) { // // Update the OEM Table ID. // TableHeader->OemTableId = mPlatformInfo->AcpiOemTableId; } // // Update the OEM Table ID. // TableHeader->OemRevision = EFI_ACPI_OEM_REVISION; // // Update the creator ID. // TableHeader->CreatorId = EFI_ACPI_CREATOR_ID; // // Update the creator revision. // TableHeader->CreatorRevision = EFI_ACPI_CREATOR_REVISION; } // // Complete this function. // // // Locate the MP services protocol. // // // Find the MP Protocol. This is an MP platform, so MP protocol must be // there. // Status = gBS->LocateProtocol ( &gEfiMpServiceProtocolGuid, NULL, (VOID **) &MpService ); if (EFI_ERROR (Status)) { return Status; } // // Determine the number of processors. // MpService->GetNumberOfProcessors ( MpService, &MaximumNumberOfCPUs, &NumberOfEnabledCPUs ); ASSERT (MaximumNumberOfCPUs <= MAX_CPU_NUM && NumberOfEnabledCPUs >= 1); // // Assign a invalid intial value for update. // // // Update the processors in the APIC table. // switch (Table->Signature) { case EFI_ACPI_1_0_ASF_DESCRIPTION_TABLE_SIGNATURE: // // Update the table if ASF is enabled. Otherwise, return error so caller will not install. // if (mSystemConfig.Asf == 1) { return EFI_UNSUPPORTED; } AsfEntry = (EFI_ACPI_1_0_ASF_DESCRIPTION_TABLE *) Table; TempVal = (mNumberSmbusAddress < ASF_ADDR_DEVICE_ARRAY_LENGTH)? mNumberSmbusAddress : ASF_ADDR_DEVICE_ARRAY_LENGTH; for (Index = 0; Index < TempVal; Index++) { AsfEntry->AsfAddr.FixedSmbusAddresses[Index] = mSmbusRsvdAddresses[Index]; } break; case EFI_ACPI_3_0_MULTIPLE_APIC_DESCRIPTION_TABLE_SIGNATURE: Status = MpService->WhoAmI ( MpService, &BspIndex ); // // PCAT_COMPAT Set to 1 indicate 8259 vectors should be disabled. // APICTableHeader = (EFI_ACPI_3_0_MULTIPLE_APIC_DESCRIPTION_TABLE_HEADER *)Table; APICTableHeader->Flags |= EFI_ACPI_3_0_PCAT_COMPAT; CurrPtr = (UINT8 *) &((EFI_ACPI_DESCRIPTION_HEADER *) Table)[1]; CurrPtr = CurrPtr + 8; // // Size of Local APIC Address & Flag. // EndPtr = (UINT8 *) Table; EndPtr = EndPtr + Table->Length; while (CurrPtr < EndPtr) { ApicPtr = (ACPI_APIC_STRUCTURE_PTR *) CurrPtr; switch (ApicPtr->AcpiApicCommon.Type) { case EFI_ACPI_3_0_PROCESSOR_LOCAL_APIC: // // ESS override // Fix for Ordering of MADT to be maintained as it is in MADT table. // // Update processor enabled or disabled and keep the local APIC // order in MADT intact. // // Sanity check to make sure proc-id is not arbitrary. // DEBUG ((EFI_D_ERROR, "ApicPtr->AcpiLocalApic.AcpiProcessorId = %x, MaximumNumberOfCPUs = %x\n", \ ApicPtr->AcpiLocalApic.AcpiProcessorId, MaximumNumberOfCPUs)); if(ApicPtr->AcpiLocalApic.AcpiProcessorId > MaximumNumberOfCPUs) { ApicPtr->AcpiLocalApic.AcpiProcessorId = (UINT8)MaximumNumberOfCPUs; } BufferSize = 0; ApicPtr->AcpiLocalApic.Flags = 0; for (CurrProcessor = 0; CurrProcessor < MaximumNumberOfCPUs; CurrProcessor++) { Status = MpService->GetProcessorInfo ( MpService, CurrProcessor, &ProcessorInfoBuffer ); if (Status == EFI_SUCCESS && ProcessorInfoBuffer.ProcessorId == ApicPtr->AcpiLocalApic.ApicId) { // // Check to see whether or not a processor (or thread) is enabled. // if ((BspIndex == CurrProcessor) || ((ProcessorInfoBuffer.StatusFlag & PROCESSOR_ENABLED_BIT) != 0)) { // // Go on and check if Hyper Threading is enabled. If HT not enabled // hide this thread from OS by not setting the flag to 1. This is the // software way to disable Hyper Threading. Basically we just hide it // from the OS. // ApicPtr->AcpiLocalApic.Flags = EFI_ACPI_1_0_LOCAL_APIC_ENABLED; if(ProcessorInfoBuffer.Location.Thread != 0) { ApicPtr->AcpiLocalApic.Flags = 0; } AppendCpuMapTableEntry (&(ApicPtr->AcpiLocalApic)); } break; } } // // If no APIC-ID match, the cpu may not be populated. // break; case EFI_ACPI_3_0_IO_APIC: IOApicType = (EFI_ACPI_3_0_IO_APIC_STRUCTURE *)CurrPtr; IOApicType->IoApicId = 0x02; // // IO APIC entries can be patched here. // break; } CurrPtr = CurrPtr + ApicPtr->AcpiApicCommon.Length; } break; case EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE: Facp = (EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE *) Table; Facp->Flags &= (UINT32)(~(3<<2)); break; case EFI_ACPI_3_0_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE: // // Patch the memory resource. // PatchDsdtTable ((EFI_ACPI_DESCRIPTION_HEADER *) Table); break; case EFI_ACPI_3_0_SECONDARY_SYSTEM_DESCRIPTION_TABLE_SIGNATURE: // // Gv3 support // // TBD: Need re-design based on the ValleyTrail platform. // break; case EFI_ACPI_3_0_HIGH_PRECISION_EVENT_TIMER_TABLE_SIGNATURE: // // Adjust HPET Table to correct the Base Address. // // Enable HPET always as Hpet.asi always indicates that Hpet is enabled. // MmioOr8 (R_PCH_PCH_HPET + R_PCH_PCH_HPET_GCFG, B_PCH_PCH_HPET_GCFG_EN); HpetTbl = (EFI_ACPI_HIGH_PRECISION_EVENT_TIMER_TABLE_HEADER *) Table; HpetTbl->BaseAddressLower32Bit.Address = HPET_BASE_ADDRESS; HpetTbl->EventTimerBlockId = *((UINT32*)(UINTN)HPET_BASE_ADDRESS); HpetCapIdValue = *(UINT16 *)(UINTN)(HPET_BASE_ADDRESS); NumberOfHpets = HpetCapIdValue & B_PCH_PCH_HPET_GCID_NT; // Bits [8:12] contains the number of Hpets HpetBlockID = EFI_ACPI_EVENT_TIMER_BLOCK_ID; if((NumberOfHpets) && (NumberOfHpets & B_PCH_PCH_HPET_GCID_NT)) { HpetBlockID |= (NumberOfHpets); } HpetTbl->EventTimerBlockId = HpetBlockID; break; case EFI_ACPI_3_0_PCI_EXPRESS_MEMORY_MAPPED_CONFIGURATION_SPACE_BASE_ADDRESS_DESCRIPTION_TABLE_SIGNATURE: // // Update MCFG base and end bus number. // ((EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_BASE_ADDRESS_TABLE *) Table)->Segment[0].BaseAddress = mPlatformInfo->PciData.PciExpressBase; ((EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_BASE_ADDRESS_TABLE *) Table)->Segment[0].EndBusNumber = (UINT8)RShiftU64 (mPlatformInfo->PciData.PciExpressSize, 20) - 1; break; case EFI_ACPI_OSFR_TABLE_SIGNATURE: // // Get size of OSFR variable. // OcurMfgStringBufferSize = 0; Status = gRT->GetVariable ( gACPIOSFRMfgStringVariableName, &gACPIOSFRMfgStringVariableGuid, NULL, &OcurMfgStringBufferSize, NULL ); if (Status != EFI_BUFFER_TOO_SMALL) { // // Variable must not be present on the system. // return EFI_UNSUPPORTED; } // // Allocate memory for variable data. // OcurMfgStringBuffer = AllocatePool (OcurMfgStringBufferSize); Status = gRT->GetVariable ( gACPIOSFRMfgStringVariableName, &gACPIOSFRMfgStringVariableGuid, NULL, &OcurMfgStringBufferSize, OcurMfgStringBuffer ); if (!EFI_ERROR (Status)) { OcurModelStringBufferSize = 0; Status = gRT->GetVariable ( gACPIOSFRModelStringVariableName, &gACPIOSFRModelStringVariableGuid, NULL, &OcurModelStringBufferSize, NULL ); if (Status != EFI_BUFFER_TOO_SMALL) { // // Variable must not be present on the system. // return EFI_UNSUPPORTED; } // // Allocate memory for variable data. // OcurModelStringBuffer = AllocatePool (OcurModelStringBufferSize); Status = gRT->GetVariable ( gACPIOSFRModelStringVariableName, &gACPIOSFRModelStringVariableGuid, NULL, &OcurModelStringBufferSize, OcurModelStringBuffer ); if (!EFI_ERROR (Status)) { OcurRefDataBlockBufferSize = 0; Status = gRT->GetVariable ( gACPIOSFRRefDataBlockVariableName, &gACPIOSFRRefDataBlockVariableGuid, NULL, &OcurRefDataBlockBufferSize, NULL ); if (Status == EFI_BUFFER_TOO_SMALL) { // // Allocate memory for variable data. // OcurRefDataBlockBuffer = AllocatePool (OcurRefDataBlockBufferSize); Status = gRT->GetVariable ( gACPIOSFRRefDataBlockVariableName, &gACPIOSFRRefDataBlockVariableGuid, NULL, &OcurRefDataBlockBufferSize, OcurRefDataBlockBuffer ); } OsfrTable = (EFI_ACPI_OSFR_TABLE *) Table; // // Currently only one object is defined: OCUR_OSFR_TABLE. // OsfrTable->ObjectCount = 1; // // Initialize table length to fixed portion of the ACPI OSFR table. // OsfrTable->Header.Length = sizeof (EFI_ACPI_OSFR_TABLE_FIXED_PORTION); *(UINT32 *)((UINTN) OsfrTable + sizeof (EFI_ACPI_OSFR_TABLE_FIXED_PORTION)) = \ (UINT32) (sizeof (EFI_ACPI_OSFR_TABLE_FIXED_PORTION) + sizeof (UINT32)); pOcurObject = (EFI_ACPI_OSFR_OCUR_OBJECT *)((UINTN) OsfrTable + sizeof (EFI_ACPI_OSFR_TABLE_FIXED_PORTION) + \ sizeof (UINT32)); CopyMem (pOcurObject, &OcurObject, sizeof (EFI_ACPI_OSFR_OCUR_OBJECT)); pOcurObject->ManufacturerNameStringOffset = (UINT32)((UINTN) pOcurObject - (UINTN) OsfrTable + \ sizeof (EFI_ACPI_OSFR_OCUR_OBJECT)); pOcurObject->ModelNameStringOffset = (UINT32)((UINTN) pOcurObject - (UINTN) OsfrTable + \ sizeof (EFI_ACPI_OSFR_OCUR_OBJECT) + OcurMfgStringBufferSize); if (OcurRefDataBlockBufferSize > 0) { pOcurObject->MicrosoftReferenceOffset = (UINT32)((UINTN) pOcurObject - (UINTN) OsfrTable + \ sizeof (EFI_ACPI_OSFR_OCUR_OBJECT) + OcurMfgStringBufferSize + OcurModelStringBufferSize); } CopyMem ((UINTN *)((UINTN) pOcurObject + sizeof (EFI_ACPI_OSFR_OCUR_OBJECT)), OcurMfgStringBuffer, \ OcurMfgStringBufferSize); CopyMem ((UINTN *)((UINTN) pOcurObject + sizeof (EFI_ACPI_OSFR_OCUR_OBJECT) + OcurMfgStringBufferSize), \ OcurModelStringBuffer, OcurModelStringBufferSize); if (OcurRefDataBlockBufferSize > 0) { CopyMem ((UINTN *)((UINTN) pOcurObject + sizeof (EFI_ACPI_OSFR_OCUR_OBJECT) + OcurMfgStringBufferSize + \ OcurModelStringBufferSize),OcurRefDataBlockBuffer, OcurRefDataBlockBufferSize); } OsfrTable->Header.Length += (UINT32)(OcurMfgStringBufferSize + OcurModelStringBufferSize + OcurRefDataBlockBufferSize); OsfrTable->Header.Length += sizeof (EFI_ACPI_OSFR_OCUR_OBJECT) + sizeof (UINT32); } } gBS->FreePool (OcurMfgStringBuffer); gBS->FreePool (OcurModelStringBuffer); gBS->FreePool (OcurRefDataBlockBuffer); break; default: break; } // // // Update the hardware signature in the FACS structure. // // // Locate the SPCR table and update based on current settings. // The user may change CR settings via setup or other methods. // The SPCR table must match. // return EFI_SUCCESS; }
/** Get All processors EFI_CPU_LOCATION in system. LocationBuf is allocated inside the function Caller is responsible to free LocationBuf. @param[out] LocationBuf Returns Processor Location Buffer. @param[out] Num Returns processor number. @retval EFI_SUCCESS Operation completed successfully. @retval EFI_UNSUPPORTED MpService protocol not found. **/ EFI_STATUS GetProcessorsCpuLocation ( OUT EFI_CPU_PHYSICAL_LOCATION **LocationBuf, OUT UINTN *Num ) { EFI_STATUS Status; EFI_MP_SERVICES_PROTOCOL *MpProtocol; UINTN ProcessorNum; UINTN EnabledProcessorNum; EFI_PROCESSOR_INFORMATION ProcessorInfo; EFI_CPU_PHYSICAL_LOCATION *ProcessorLocBuf; UINTN Index; Status = gBS->LocateProtocol (&gEfiMpServiceProtocolGuid, NULL, (VOID **) &MpProtocol); if (EFI_ERROR (Status)) { // // MP protocol is not installed // return EFI_UNSUPPORTED; } Status = MpProtocol->GetNumberOfProcessors( MpProtocol, &ProcessorNum, &EnabledProcessorNum ); if (EFI_ERROR(Status)){ return Status; } Status = gBS->AllocatePool( EfiBootServicesData, sizeof(EFI_CPU_PHYSICAL_LOCATION) * ProcessorNum, (VOID **) &ProcessorLocBuf ); if (EFI_ERROR(Status)){ return Status; } // // Get each processor Location info // for (Index = 0; Index < ProcessorNum; Index++) { Status = MpProtocol->GetProcessorInfo( MpProtocol, Index, &ProcessorInfo ); if (EFI_ERROR(Status)){ FreePool(ProcessorLocBuf); return Status; } // // Get all Processor Location info & measure // CopyMem( &ProcessorLocBuf[Index], &ProcessorInfo.Location, sizeof(EFI_CPU_PHYSICAL_LOCATION) ); } *LocationBuf = ProcessorLocBuf; *Num = ProcessorNum; return Status; }
VOID ApicTableUpdate ( IN OUT EFI_ACPI_DESCRIPTION_HEADER *TableHeader, IN OUT EFI_ACPI_TABLE_VERSION *Version ) /*++ Routine Description: Update the processors information in the APIC table Arguments: Table - The table to be set Version - Version to publish Returns: None --*/ { EFI_STATUS Status; EFI_MP_SERVICES_PROTOCOL *MpService; UINT8 *CurrPtr; UINT8 *EndPtr; UINT8 CurrIoApic; UINT8 CurrProcessor; UINTN NumberOfCPUs; UINTN NumberOfEnabledCPUs; UINTN BufferSize; EFI_PROCESSOR_INFORMATION MpContext; ACPI_APIC_STRUCTURE_PTR *ApicPtr; CurrIoApic = 0; CurrProcessor = 0; // // Find the MP Protocol. This is an MP platform, so MP protocol must be // there. // Status = gBS->LocateProtocol ( &gEfiMpServiceProtocolGuid, NULL, (VOID**)&MpService ); if (EFI_ERROR (Status)) { // // Failed to get MP information, doesn't publish the invalid table // *Version = EFI_ACPI_TABLE_VERSION_NONE; return; } // // Determine the number of processors // MpService->GetNumberOfProcessors ( MpService, &NumberOfCPUs, &NumberOfEnabledCPUs ); CurrPtr = (UINT8*) &(TableHeader[1]); CurrPtr = CurrPtr + 8; // Size of Local APIC Address & Flag EndPtr = (UINT8*) TableHeader; EndPtr = EndPtr + TableHeader->Length; while (CurrPtr < EndPtr) { ApicPtr = (ACPI_APIC_STRUCTURE_PTR*) CurrPtr; switch (ApicPtr->AcpiApicCommon.Type) { case EFI_ACPI_1_0_PROCESSOR_LOCAL_APIC: BufferSize = sizeof (EFI_PROCESSOR_INFORMATION); ApicPtr->AcpiLocalApic.Flags = 0; ApicPtr->AcpiLocalApic.ApicId = 0; Status = MpService->GetProcessorInfo ( MpService, CurrProcessor, &MpContext ); if (!EFI_ERROR (Status)) { if (MpContext.StatusFlag & PROCESSOR_ENABLED_BIT) { ApicPtr->AcpiLocalApic.Flags = EFI_ACPI_3_0_LOCAL_APIC_ENABLED; } ApicPtr->AcpiLocalApic.ApicId = (UINT8)MpContext.ProcessorId; } CurrProcessor++; break; case EFI_ACPI_1_0_IO_APIC: // // IO APIC entries can be patched here // if (CurrIoApic == 0) { // // Update SOC internel IOAPIC base // ApicPtr->AcpiIoApic.IoApicId = PcdGet8 (PcdIoApicSettingIoApicId); ApicPtr->AcpiIoApic.IoApicAddress = (UINT32)FixedPcdGet64(PcdIoApicBaseAddress); ApicPtr->AcpiIoApic.GlobalSystemInterruptBase = 0; } else { // // Porting is required to update other IOAPIC entries if available // ASSERT (0); } CurrIoApic++; break; default: break; }; CurrPtr = CurrPtr + ApicPtr->AcpiApicCommon.Length; } }
EFI_STATUS EFIAPI PpmPolicyEntry( IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable ) { EFI_MP_SERVICES_PROTOCOL *MpService; EFI_CPUID_REGISTER Cpuid01 = { 0, 0, 0, 0}; EFI_HANDLE Handle; EFI_STATUS Status; UINTN CpuCount; UINT64 MaxRatio; UINT8 CPUMobileFeature; PCH_STEPPING Stepping; gBS = SystemTable->BootServices; pBS = SystemTable->BootServices; pRS = SystemTable->RuntimeServices; // // Set PPM policy structure to known value // gBS->SetMem (&mDxePlatformPpmPolicy, sizeof(PPM_PLATFORM_POLICY_PROTOCOL), 0); // // Find the MpService Protocol // Status = pBS->LocateProtocol (&gEfiMpServiceProtocolGuid, NULL, (void **)&MpService ); ASSERT_EFI_ERROR (Status); // // Get processor count from MP service. // Status = MpService->GetNumberOfProcessors (MpService, &CpuCount, NULL); ASSERT_EFI_ERROR (Status); // // Store the CPUID for use by SETUP items. // AsmCpuid (EFI_CPUID_VERSION_INFO, &Cpuid01.RegEax, &Cpuid01.RegEbx, &Cpuid01.RegEcx, &Cpuid01.RegEdx); MaxRatio = ((RShiftU64 (AsmReadMsr64(EFI_MSR_IA32_PLATFORM_ID), 8)) & 0x1F); mDxePlatformPpmPolicy.Revision = PPM_PLATFORM_POLICY_PROTOCOL_REVISION_4; //Read CPU Mobile feature from PLATFORM_ID_MSR MSR(0x17) NOTFB_I_AM_NOT_MOBILE_FUSE_CLIAMC00H Bit 28 //Bit Description: { Disables Mobile features 0 = I am NOT a mobile part 1 = I am a mobile part (default)"} CPUMobileFeature = ((RShiftU64 (AsmReadMsr64(EFI_MSR_IA32_PLATFORM_ID), 28)) & 0x1); if (!EFI_ERROR(Status)) { if (CPUMobileFeature == 1){//CPU mobile feature mDxePlatformPpmPolicy.FunctionEnables.EnableGv = ICH_DEVICE_ENABLE; mDxePlatformPpmPolicy.FunctionEnables.EnableCx = ICH_DEVICE_ENABLE; mDxePlatformPpmPolicy.FunctionEnables.EnableCxe = ICH_DEVICE_DISABLE; mDxePlatformPpmPolicy.FunctionEnables.EnableTm = ICH_DEVICE_ENABLE; //MaxC7 mDxePlatformPpmPolicy.FunctionEnables.EnableC7 = ICH_DEVICE_ENABLE; mDxePlatformPpmPolicy.FunctionEnables.EnableC6 = ICH_DEVICE_ENABLE; mDxePlatformPpmPolicy.FunctionEnables.EnableC4 = ICH_DEVICE_ENABLE; }else{//CPU desktop feature mDxePlatformPpmPolicy.FunctionEnables.EnableGv = ICH_DEVICE_DISABLE; mDxePlatformPpmPolicy.FunctionEnables.EnableCx = ICH_DEVICE_DISABLE; mDxePlatformPpmPolicy.FunctionEnables.EnableCxe = ICH_DEVICE_DISABLE; mDxePlatformPpmPolicy.FunctionEnables.EnableTm = ICH_DEVICE_DISABLE; mDxePlatformPpmPolicy.FunctionEnables.EnableC4 = ICH_DEVICE_DISABLE; mDxePlatformPpmPolicy.FunctionEnables.EnableC6 = ICH_DEVICE_DISABLE; mDxePlatformPpmPolicy.FunctionEnables.EnableC7 = ICH_DEVICE_DISABLE; } mDxePlatformPpmPolicy.FunctionEnables.EnableProcHot = ICH_DEVICE_ENABLE; mDxePlatformPpmPolicy.FunctionEnables.TStatesEnable = ICH_DEVICE_ENABLE; Stepping = PchStepping(); if (Stepping < PchB3) { // If SoC is B0~B2 Stepping, disable the Turbo mDxePlatformPpmPolicy.FunctionEnables.EnableTurboMode= ICH_DEVICE_DISABLE; } else { mDxePlatformPpmPolicy.FunctionEnables.EnableTurboMode= ICH_DEVICE_ENABLE; } mDxePlatformPpmPolicy.FunctionEnables.EnableTm = ICH_DEVICE_ENABLE; mDxePlatformPpmPolicy.FunctionEnables.EnableCMP = ICH_DEVICE_ENABLE; } else { mDxePlatformPpmPolicy.FunctionEnables.EnableGv = ICH_DEVICE_ENABLE; mDxePlatformPpmPolicy.FunctionEnables.EnableCx = ICH_DEVICE_ENABLE; mDxePlatformPpmPolicy.FunctionEnables.EnableCxe = ICH_DEVICE_ENABLE; mDxePlatformPpmPolicy.FunctionEnables.EnableTm = ICH_DEVICE_ENABLE; mDxePlatformPpmPolicy.FunctionEnables.EnableProcHot = ICH_DEVICE_ENABLE; mDxePlatformPpmPolicy.FunctionEnables.EnableCMP = ICH_DEVICE_DISABLE; mDxePlatformPpmPolicy.FunctionEnables.TStatesEnable = ICH_DEVICE_ENABLE; mDxePlatformPpmPolicy.FunctionEnables.EnableTurboMode= ICH_DEVICE_ENABLE; mDxePlatformPpmPolicy.FunctionEnables.EnableC4 = ICH_DEVICE_ENABLE; mDxePlatformPpmPolicy.FunctionEnables.EnableC6 = ICH_DEVICE_ENABLE; } mDxePlatformPpmPolicy.S3RestoreMsrSwSmiNumber = S3_RESTORE_MSR_SW_SMI; Handle = NULL; Status = gBS->InstallMultipleProtocolInterfaces ( &Handle, &gPpmPlatformPolicyProtocolGuid, &mDxePlatformPpmPolicy, NULL ); ASSERT_EFI_ERROR (Status); return EFI_SUCCESS; }
/** The entry function of the CpuS3Data driver. Allocate and initialize all fields of the ACPI_CPU_DATA structure except the MTRR settings. Register an event notification on gEfiEndOfDxeEventGroupGuid to capture the ACPI_CPU_DATA MTRR settings. The PcdCpuS3DataAddress is set to the address that ACPI_CPU_DATA is allocated at. @param[in] ImageHandle The firmware allocated handle for the EFI image. @param[in] SystemTable A pointer to the EFI System Table. @retval EFI_SUCCESS The entry point is executed successfully. @retval EFI_UNSUPPORTED Do not support ACPI S3. @retval other Some error occurs when executing this entry point. **/ EFI_STATUS EFIAPI CpuS3DataInitialize ( IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable ) { EFI_STATUS Status; ACPI_CPU_DATA_EX *AcpiCpuDataEx; ACPI_CPU_DATA *AcpiCpuData; EFI_MP_SERVICES_PROTOCOL *MpServices; UINTN NumberOfCpus; UINTN NumberOfEnabledProcessors; VOID *Stack; UINTN TableSize; CPU_REGISTER_TABLE *RegisterTable; UINTN Index; EFI_PROCESSOR_INFORMATION ProcessorInfoBuffer; UINTN GdtSize; UINTN IdtSize; VOID *Gdt; VOID *Idt; EFI_EVENT Event; ACPI_CPU_DATA *OldAcpiCpuData; if (!PcdGetBool (PcdAcpiS3Enable)) { return EFI_UNSUPPORTED; } // // Set PcdCpuS3DataAddress to the base address of the ACPI_CPU_DATA structure // OldAcpiCpuData = (ACPI_CPU_DATA *) (UINTN) PcdGet64 (PcdCpuS3DataAddress); AcpiCpuDataEx = AllocateZeroPages (sizeof (ACPI_CPU_DATA_EX)); ASSERT (AcpiCpuDataEx != NULL); AcpiCpuData = &AcpiCpuDataEx->AcpiCpuData; // // Get MP Services Protocol // Status = gBS->LocateProtocol ( &gEfiMpServiceProtocolGuid, NULL, (VOID **)&MpServices ); ASSERT_EFI_ERROR (Status); // // Get the number of CPUs // Status = MpServices->GetNumberOfProcessors ( MpServices, &NumberOfCpus, &NumberOfEnabledProcessors ); ASSERT_EFI_ERROR (Status); AcpiCpuData->NumberOfCpus = (UINT32)NumberOfCpus; // // Initialize ACPI_CPU_DATA fields // AcpiCpuData->StackSize = PcdGet32 (PcdCpuApStackSize); AcpiCpuData->ApMachineCheckHandlerBase = 0; AcpiCpuData->ApMachineCheckHandlerSize = 0; AcpiCpuData->GdtrProfile = (EFI_PHYSICAL_ADDRESS)(UINTN)&AcpiCpuDataEx->GdtrProfile; AcpiCpuData->IdtrProfile = (EFI_PHYSICAL_ADDRESS)(UINTN)&AcpiCpuDataEx->IdtrProfile; AcpiCpuData->MtrrTable = (EFI_PHYSICAL_ADDRESS)(UINTN)&AcpiCpuDataEx->MtrrTable; // // Allocate stack space for all CPUs. // Use ACPI NVS memory type because this data will be directly used by APs // in S3 resume phase in long mode. Also during S3 resume, the stack buffer // will only be used as scratch space. i.e. we won't read anything from it // before we write to it, in PiSmmCpuDxeSmm. // Stack = AllocateAcpiNvsMemory (NumberOfCpus * AcpiCpuData->StackSize); ASSERT (Stack != NULL); AcpiCpuData->StackAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)Stack; // // Get the boot processor's GDT and IDT // AsmReadGdtr (&AcpiCpuDataEx->GdtrProfile); AsmReadIdtr (&AcpiCpuDataEx->IdtrProfile); // // Allocate GDT and IDT and copy current GDT and IDT contents // GdtSize = AcpiCpuDataEx->GdtrProfile.Limit + 1; IdtSize = AcpiCpuDataEx->IdtrProfile.Limit + 1; Gdt = AllocateZeroPages (GdtSize + IdtSize); ASSERT (Gdt != NULL); Idt = (VOID *)((UINTN)Gdt + GdtSize); CopyMem (Gdt, (VOID *)AcpiCpuDataEx->GdtrProfile.Base, GdtSize); CopyMem (Idt, (VOID *)AcpiCpuDataEx->IdtrProfile.Base, IdtSize); AcpiCpuDataEx->GdtrProfile.Base = (UINTN)Gdt; AcpiCpuDataEx->IdtrProfile.Base = (UINTN)Idt; if (OldAcpiCpuData != NULL) { AcpiCpuData->RegisterTable = OldAcpiCpuData->RegisterTable; AcpiCpuData->PreSmmInitRegisterTable = OldAcpiCpuData->PreSmmInitRegisterTable; AcpiCpuData->ApLocation = OldAcpiCpuData->ApLocation; CopyMem (&AcpiCpuData->CpuStatus, &OldAcpiCpuData->CpuStatus, sizeof (CPU_STATUS_INFORMATION)); } else { // // Allocate buffer for empty RegisterTable and PreSmmInitRegisterTable for all CPUs // TableSize = 2 * NumberOfCpus * sizeof (CPU_REGISTER_TABLE); RegisterTable = (CPU_REGISTER_TABLE *)AllocateZeroPages (TableSize); ASSERT (RegisterTable != NULL); for (Index = 0; Index < NumberOfCpus; Index++) { Status = MpServices->GetProcessorInfo ( MpServices, Index, &ProcessorInfoBuffer ); ASSERT_EFI_ERROR (Status); RegisterTable[Index].InitialApicId = (UINT32)ProcessorInfoBuffer.ProcessorId; RegisterTable[Index].TableLength = 0; RegisterTable[Index].AllocatedSize = 0; RegisterTable[Index].RegisterTableEntry = 0; RegisterTable[NumberOfCpus + Index].InitialApicId = (UINT32)ProcessorInfoBuffer.ProcessorId; RegisterTable[NumberOfCpus + Index].TableLength = 0; RegisterTable[NumberOfCpus + Index].AllocatedSize = 0; RegisterTable[NumberOfCpus + Index].RegisterTableEntry = 0; } AcpiCpuData->RegisterTable = (EFI_PHYSICAL_ADDRESS)(UINTN)RegisterTable; AcpiCpuData->PreSmmInitRegisterTable = (EFI_PHYSICAL_ADDRESS)(UINTN)(RegisterTable + NumberOfCpus); } // // Set PcdCpuS3DataAddress to the base address of the ACPI_CPU_DATA structure // Status = PcdSet64S (PcdCpuS3DataAddress, (UINT64)(UINTN)AcpiCpuData); ASSERT_EFI_ERROR (Status); // // Register EFI_END_OF_DXE_EVENT_GROUP_GUID event. // The notification function allocates StartupVector and saves MTRRs for ACPI_CPU_DATA // Status = gBS->CreateEventEx ( EVT_NOTIFY_SIGNAL, TPL_CALLBACK, CpuS3DataOnEndOfDxe, AcpiCpuData, &gEfiEndOfDxeEventGroupGuid, &Event ); ASSERT_EFI_ERROR (Status); return EFI_SUCCESS; }
/** * AgesaRunFcnOnAp * * Description * Call the host environment interface to provide a user hook opportunity. * * @param[in] ApicIdOfCore * @param[in,out] LaunchApParams * * @return The AGESA Status returned from the callout. * */ AGESA_STATUS AgesaRunFcnOnAp ( IN UINTN ApicIdOfCore, IN AP_EXE_PARAMS *LaunchApParams ) { AGESA_STATUS AgesaStatus; EFI_STATUS Status; EFI_MP_SERVICES_PROTOCOL *MpServices; UINTN CpuData_Index; UINTN NumberOfEnabledCPUs; UINTN BufferSize; EFI_MP_PROC_CONTEXT ApCoreData; AgesaStatus = AGESA_ERROR; RelatedBlockLength = LaunchApParams->RelatedBlockLength; RelatedDataBlock = LaunchApParams->RelatedDataBlock; FunctionNumber = LaunchApParams->FunctionNumber; Status = gBS->LocateProtocol (&gEfiMpServiceProtocolGuid, NULL, &MpServices); if (EFI_ERROR (Status)) { return AgesaStatus; } Status = MpServices->GetGeneralMPInfo ( MpServices, 0, 0, &NumberOfEnabledCPUs, 0, 0 ); if (EFI_ERROR (Status)) { return AgesaStatus; } for (CpuData_Index = 0; CpuData_Index < NumberOfEnabledCPUs; CpuData_Index++) { Status = MpServices->GetProcessorContext ( MpServices, CpuData_Index, &BufferSize, &ApCoreData); if ( ApCoreData.ApicID == (UINT32) ApicIdOfCore ) { break; } } Status = MpServices->StartupThisAP ( MpServices, (EFI_AP_PROCEDURE) AgesaLaunchApForGivenTask, CpuData_Index, NULL, 0, NULL ); if (!EFI_ERROR (Status)) { AgesaStatus = AGESA_SUCCESS; } return AgesaStatus; }