/** @file Source code file for Platform Init Pre-Memory PEI module. Copyright (c) 2015 - 2017, Intel Corporation. All rights reserved.
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. **/ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "Smip.h" #include "Stall.h" #include "FvCallback.h" #include "MemoryCallback.h" #include "BoardGpiosPreMem.h" #include "PlatformInitPreMem.h" #include #include #include #include #include #include #include #include // // GUID used in FCE. FCE generate ffs file with this GUID. // EFI_GUID gDefaultDataOptSizeFileGuid = { 0x003e7b41, 0x98a2, 0x4be2, { 0xb2, 0x7a, 0x6c, 0x30, 0xc7, 0x65, 0x52, 0x25 }}; #if (ENBDT_PF_ENABLE == 1) // //SSC // #include #include #include #endif extern EFI_GUID gEfiBootMediaHobGuid; // // The global indicator, the FvFileLoader callback will modify it to TRUE after loading PEIM into memory // BOOLEAN ImageInMemory = FALSE; CHAR8 mGdtTable[0x40]; // //Memory Test Manufacturing mode // #define DATA_PATTERN_ARRAY_SIZE (sizeof(DataPatternForMemoryTest) / sizeof(UINT32)) UINT32 DataPatternForMemoryTest[] = { 0x55555555, 0xAAAAAAAA, 0x55555510, 0x555555EF, 0x55555510, 0x555555EF, 0x55555510, 0x555555EF, 0x55555555, 0xAAAAAAAA, 0x55551055, 0x5555EF55, 0x55551055, 0x5555EF55, 0x55551055, 0x5555EF55, 0x55555555, 0xAAAAAAAA, 0x55105555, 0x55EF5555, 0x55105555, 0x55EF5555, 0x55105555, 0x55EF5555, 0x55555555, 0xAAAAAAAA, 0x10555555, 0xEF555555, 0x10555555, 0xEF555555, 0x10555555, 0xEF555555 }; extern EFI_PEI_PPI_DESCRIPTOR mCseUfsSelectPpiList[]; extern EFI_PEI_PPI_DESCRIPTOR mCseEmmcSelectPpiList[]; extern EFI_PEI_PPI_DESCRIPTOR mCseSpiSelectPpiList[]; #define PEI_STALL_RESOLUTION 1 static EFI_PEI_STALL_PPI mStallPpi = { PEI_STALL_RESOLUTION, Stall }; #if defined(PRAM_SUPPORT) static PEI_BIOS_RESERVED_MEMORY_POLICY_PPI mPeiBiosReservedMemoryPolicyPpi = { GetBiosReservedMemoryPolicy }; static EFI_PEI_PPI_DESCRIPTOR mBiosReservedMemoryPolicyPpi = { EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST, &gBiosReservedMemoryPolicyPpiGuid, &mPeiBiosReservedMemoryPolicyPpi }; #endif static EFI_PEI_PPI_DESCRIPTOR mInstallStallPpi = { EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST, &gEfiPeiStallPpiGuid, &mStallPpi }; static PEI_MFG_MEMORY_TEST_PPI mPeiMfgMemoryTestPpi = { MfgMemoryTest }; static EFI_PEI_PPI_DESCRIPTOR mMfgMemTestPpi = { EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST, &gPeiMfgMemoryTestPpiGuid, &mPeiMfgMemoryTestPpi }; static EFI_PEI_PPI_DESCRIPTOR mPeiTemporaryRamSupportPpiPpi[] = { { (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST), &gEfiTemporaryRamSupportPpiGuid, NULL } }; // // Notify Callbacks for SPI and non-SPI boot devices. // These are installed by MemoryDiscovered Callback, since they require main memory. // EFI_PEI_NOTIFY_DESCRIPTOR mFvNotifyList[] = { { EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK, &gEfiPeiVirtualBlockIoPpiGuid, //non-SPI boot - installed after MemInit GetFvNotifyCallback }, { (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST), &gCseSpiSelectPpiGuid, //SPI boot - installed by PeiSecUma GetFvNotifyCallback } }; EFI_STATUS EFIAPI FspTempRamExitCallback ( IN EFI_PEI_SERVICES **PeiServices, IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor, IN VOID *Ppi ) { EFI_STATUS Status = EFI_SUCCESS; DEBUG ((DEBUG_INFO, "FspTempRamExitCallback\n")); Status = PeiServicesNotifyPpi (&mFvNotifyList[0]); return Status; } EFI_PEI_NOTIFY_DESCRIPTOR mFspTempRamExitList[] = { { (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST), &gFspTempRamExitGuid, FspTempRamExitCallback } }; EFI_STATUS EFIAPI GetBiosReservedMemoryPolicy ( IN CONST EFI_PEI_SERVICES **PeiServices, IN PEI_BIOS_RESERVED_MEMORY_POLICY_PPI *This, IN OUT BIOS_RESERVED_MEMORY_CONFIG *BiosReservedMemoryPolicy ); VOID CopyMemSse4 ( IN VOID* Dst, IN VOID* Src, IN UINTN SizeInBytes ) { #ifdef __GNUC__ CopyMem (Dst, Src, SizeInBytes); #else _asm { // // Initialize pointers to start of the USWC memory // mov esi, Src mov edx, Src // // Initialize pointer to end of the USWC memory // add edx, SizeInBytes // // Initialize pointer to start of the cacheable WB buffer // mov edi, Dst // // save xmm0 ~ xmm3 to stack // sub esp, 040h movdqu [esp], xmm0 movdqu [esp + 16], xmm1 movdqu [esp + 32], xmm2 movdqu [esp + 48], xmm3 // // Start of Bulk Load loop // inner_start: // // Load data from USWC Memory using Streaming Load // MOVNTDQA xmm0, xmmword ptr [esi] MOVNTDQA xmm1, xmmword ptr [esi + 16] MOVNTDQA xmm2, xmmword ptr [esi + 32] MOVNTDQA xmm3, xmmword ptr [esi + 48] // // Copy data to buffer // MOVDQA xmmword ptr [edi], xmm0 MOVDQA xmmword ptr [edi + 16], xmm1 MOVDQA xmmword ptr [edi + 32], xmm2 MOVDQA xmmword ptr [edi + 48], xmm3 // // Increment pointers by cache line size and test for end of loop // add esi, 040h add edi, 040h cmp esi, edx jne inner_start // // restore xmm0 ~ xmm3 // mfence movdqu xmm0, [esp] movdqu xmm1, [esp + 16] movdqu xmm2, [esp + 32] movdqu xmm3, [esp + 48] add esp, 040h // stack cleanup } #endif // End of Bulk Load loop } #if defined(PRAM_SUPPORT) /** This function is to get Bios Reserved Memory in PEI. @param[in] PeiServices Pointer to PEI Services. @param[in] This Pei memory test PPI pointer. @param[in, out] BiosReservedMemoryPolicy Pointer to BiosReservedMemorypolicy. @retval EFI_SUCCESS The operation completed successfully. **/ EFI_STATUS EFIAPI GetBiosReservedMemoryPolicy ( IN CONST EFI_PEI_SERVICES **PeiServices, IN PEI_BIOS_RESERVED_MEMORY_POLICY_PPI *This, IN OUT BIOS_RESERVED_MEMORY_CONFIG *BiosReservedMemoryPolicy ) { EFI_STATUS Status; UINTN VariableSize; EFI_PEI_READ_ONLY_VARIABLE2_PPI *VariableServices; SYSTEM_CONFIGURATION SystemConfiguration; Status = PeiServicesLocatePpi (&gEfiPeiReadOnlyVariable2PpiGuid, 0, NULL, (VOID **) &VariableServices); if (EFI_ERROR (Status)) { ASSERT_EFI_ERROR (Status); return Status; } VariableSize = sizeof (SYSTEM_CONFIGURATION); Status = VariableServices->GetVariable ( VariableServices, PLATFORM_SETUP_VARIABLE_NAME, &gEfiSetupVariableGuid, NULL, &VariableSize, &SystemConfiguration ); if (Status == EFI_SUCCESS) { #ifdef PRAM_SUPPORT BiosReservedMemoryPolicy->Pram = SystemConfiguration.Pram; #endif } else { #ifdef PRAM_SUPPORT BiosReservedMemoryPolicy->Pram = 0x30; #endif } Status = EFI_SUCCESS; #ifdef PRAM_SUPPORT DEBUG ((DEBUG_INFO, "SystemConfiguration.Pram = %x \n", SystemConfiguration.Pram)); #endif return Status; } #endif /** This function checks the memory range in PEI. @param[in] PeiServices Pointer to PEI Services. @param[in] This Pei memory test PPI pointer. @param[in] BeginAddress Beginning of the memory address to be checked. @param[in] MemoryLength Bytes of memory range to be checked. @retval EFI_SUCCESS The operation completed successfully. @retval EFI_DEVICE_ERROR Memory test failed. It's not safe to use this range of memory. **/ EFI_STATUS EFIAPI MfgMemoryTest ( IN CONST EFI_PEI_SERVICES **PeiServices, IN PEI_MFG_MEMORY_TEST_PPI *This, IN UINT32 BeginAddress, IN UINT32 MemoryLength ) { UINT32 i; UINT32 memAddr; UINT32 readData; UINT32 xorData; UINT32 TestFlag = 0; memAddr = BeginAddress; // // Output Message for MFG // DEBUG ((DEBUG_INFO, "MFGMODE SET\n")); // // Writing the pattern in defined location. // while (memAddr < (BeginAddress+MemoryLength)) { for (i = 0; i < DATA_PATTERN_ARRAY_SIZE; i++) { if (memAddr > (BeginAddress + MemoryLength - 4)) { memAddr = memAddr + 4; break; } *((volatile UINT32*) memAddr) = DataPatternForMemoryTest[i]; memAddr = memAddr + 4; } } // // Verify the pattern // memAddr = BeginAddress; while (memAddr < (BeginAddress + MemoryLength)) { for (i = 0; i < DATA_PATTERN_ARRAY_SIZE; i++) { if (memAddr > (BeginAddress + MemoryLength - 4)) { memAddr = memAddr + 4; break; } readData = *((volatile UINT32*) memAddr); xorData = readData ^ DataPatternForMemoryTest[i]; // // If xorData is non-zero, this particular memAddr has a failure. // if (xorData != 0x00000000) { DEBUG ((DEBUG_ERROR, "Expected value....: %x\n", DataPatternForMemoryTest[i])); DEBUG ((DEBUG_ERROR, "ReadData value....: %x\n", readData)); DEBUG ((DEBUG_ERROR, "Pattern failure at....: %x\n", memAddr)); TestFlag = 1; } memAddr = memAddr + 4; } } if (TestFlag) { return EFI_DEVICE_ERROR; } // //Output Message for MFG // DEBUG ((DEBUG_INFO, "MFGMODE MEMORY TEST PASSED\n")); return EFI_SUCCESS; } BOOLEAN IsRtcUipAlwaysSet ( IN CONST EFI_PEI_SERVICES **PeiServices ) { EFI_PEI_STALL_PPI *StallPpi; UINTN Count; PeiServicesLocatePpi (&gEfiPeiStallPpiGuid, 0, NULL, (VOID **) &StallPpi); for (Count = 0; Count < 500; Count++) { // Maximum waiting approximates to 1.5 seconds (= 3 msec * 500) IoWrite8 (R_RTC_INDEX2, R_RTC_REGISTERA); if ((IoRead8 (R_RTC_TARGET2) & B_RTC_REGISTERA_UIP) == 0) { return FALSE; } StallPpi->Stall (PeiServices, StallPpi, 3000); } return TRUE; } VOID RtcPowerFailureHandler ( VOID ) { UINT16 Data16; UINT8 Data8; // When the RTC_PWR_STS bit is set, it indicates that the RTCRST# signal went low. // Software should clear this bit. For example, changing the RTC battery sets this bit. // System BIOS should reset CMOS to default values if the RTC_PWR_STS bit is set. // The System BIOS should execute the sequence below if the RTC_PWR_STS bit is set // before memory initialization. This will ensure that the RTC state machine has been // initialized. // 1. If the RTC_PWR_STS bit is set which indicates a new coin-cell battery insertion or a // battery failure, steps 2 through 5 should be executed. // 2. Set RTC Register 0x0A[6:4] to 110b or 111b. // 3. Set RTC Register 0x0B[7]. // 4. Set RTC Register 0x0A[6:4] to 010b. // 5. Clear RTC Register 0x0B[7]. // Data16 = MmioRead16 (PMC_BASE_ADDRESS + R_PMC_GEN_PMCON_1); if ((Data16 & B_PMC_GEN_PMCON_RTC_PWR_STS) != 0) { // // 2. Set RTC Register 0Ah[6:4] to 110b or 111b // IoWrite8 (R_RTC_INDEX2, (UINT8) R_RTC_REGISTERA); Data8 = IoRead8 (R_RTC_TARGET2) & (UINT8) ~(B_RTC_REGISTERA_DV); Data8 |= (UINT8) (V_RTC_REGISTERA_DV_DIV_RST1); IoWrite8 (R_RTC_TARGET2, Data8); // // 3. Set RTC Register 0Bh[7]. // IoWrite8 (R_RTC_INDEX2, (UINT8) R_RTC_REGISTERB); IoOr8 (R_RTC_TARGET2, (UINT8) B_RTC_REGISTERB_SET); // // 4. Set RTC Register 0Ah[6:4] to 010b // IoWrite8 (R_RTC_INDEX2, (UINT8) R_RTC_REGISTERA); Data8 = IoRead8 (R_RTC_TARGET2) & (UINT8) ~(B_RTC_REGISTERA_DV); Data8 |= (UINT8) (V_RTC_REGISTERA_DV_NORM_OP); IoWrite8 (R_RTC_TARGET2, Data8); // // 5. Clear RTC Register 0Bh[7]. // IoWrite8 (R_RTC_INDEX2, (UINT8) R_RTC_REGISTERB); IoAnd8 (R_RTC_TARGET2, (UINT8) ~B_RTC_REGISTERB_SET); } return; } VOID ScBaseInit ( VOID ) { // // Set BARs for PMC SSRAM (0/13/3) // Allocation for these regions is done in PlatformInitFinalConfig() via call to BuildResourceDescriptorHob() // MmioWrite32 ( MmPciAddress (0, 0, PCI_DEVICE_NUMBER_PMC, PCI_FUNCTION_NUMBER_PMC_SSRAM, 0x10), //Write BAR0-lower PcdGet32 (PcdPmcSsramBaseAddress0) ); MmioWrite32 ( MmPciAddress (0, 0, PCI_DEVICE_NUMBER_PMC, PCI_FUNCTION_NUMBER_PMC_SSRAM, 0x18), //Write BAR1-lower PcdGet32 (PcdPmcSsramBaseAddress1) ); MmioWrite16 ( MmPciAddress (0, 0, PCI_DEVICE_NUMBER_PMC, PCI_FUNCTION_NUMBER_PMC_SSRAM, 0x4), //Set BME and MSE 0x6 ); // // Set SPI Base Address // MmioWrite32 ( MmPciAddress (0,DEFAULT_PCI_BUS_NUMBER_SC, PCI_DEVICE_NUMBER_SPI, PCI_FUNCTION_NUMBER_SPI, R_SPI_BASE), (UINT32) ((SPI_BASE_ADDRESS & B_SPI_BASE_BAR)) ); // // Enable SPI Memory decode // MmioWrite16 ( MmPciAddress (0, DEFAULT_PCI_BUS_NUMBER_SC, PCI_DEVICE_NUMBER_SPI, PCI_FUNCTION_NUMBER_SPI, R_SPI_COMMAND), EFI_PCI_COMMAND_MEMORY_SPACE ); // // Set P2SB Base Address // MmioWrite32 ( MmPciAddress (0, DEFAULT_PCI_BUS_NUMBER_SC, PCI_DEVICE_NUMBER_P2SB, PCI_FUNCTION_NUMBER_P2SB, R_P2SB_BASE), (UINT32) ((PcdGet32 (PcdP2SBBaseAddress))) ); // // Enable P2SB Memory decode // MmioWrite16 ( MmPciAddress (0, DEFAULT_PCI_BUS_NUMBER_SC, PCI_DEVICE_NUMBER_P2SB, PCI_FUNCTION_NUMBER_P2SB, R_P2SB_STSCMD), B_P2SB_STSCMD_BME | B_P2SB_STSCMD_MSE ); PchLpcIoDecodeRangesSet ( (V_PCH_LPC_IOD_LPT_378 << N_PCH_LPC_IOD_LPT) | (V_PCH_LPC_IOD_COMB_3E8 << N_PCH_LPC_IOD_COMB) | (V_PCH_LPC_IOD_COMA_3F8 << N_PCH_LPC_IOD_COMA) ); PchLpcIoEnableDecodingSet ( B_PCH_LPC_IOE_ME2 | B_PCH_LPC_IOE_SE | B_PCH_LPC_IOE_ME1 | B_PCH_LPC_IOE_KE | B_PCH_LPC_IOE_HGE | B_PCH_LPC_IOE_LGE | B_PCH_LPC_IOE_FDE | B_PCH_LPC_IOE_PPE | B_PCH_LPC_IOE_CBE | B_PCH_LPC_IOE_CAE ); } /** This function performs SC PreMem Policy initialization. @param[in] StartTimerTicker The Start Timer Ticker for PFET# enabled @retval EFI_SUCCESS The PPI is installed and initialized. @retval EFI ERRORS The PPI is not successfully installed. @retval EFI_OUT_OF_RESOURCES Do not have enough resources to initialize the driver **/ EFI_STATUS EFIAPI PeiScPreMemPolicyInit ( IN UINT64 *StartTimerTicker ) { EFI_STATUS Status; SC_PREMEM_POLICY_PPI *ScPreMemPolicy; SC_PCIE_PREMEM_CONFIG *PciePreMemConfig; // // Call ScCreatePreMemConfigBlocks to initialize SC Policy structure // and get all Intel default policy settings. // Status = ScCreatePreMemConfigBlocks (&ScPreMemPolicy); ASSERT_EFI_ERROR (Status); // // Update and override all platform related and customized settings below. // Status = GetConfigBlock ((VOID *) ScPreMemPolicy, &gPcieRpPreMemConfigGuid, (VOID *) &PciePreMemConfig); ASSERT_EFI_ERROR (Status); // // Update PCIe PERST# and CLK# policies // PciePreMemConfig->StartTimerTickerOfPfetAssert = (UINTN) *StartTimerTicker; PciePreMemConfig->RootPort[0].Perst = N_GPIO_13; // Slot2 PciePreMemConfig->RootPort[1].Perst = N_GPIO_15; // NGFF PciePreMemConfig->RootPort[2].Perst = W_GPIO_152; // Slot1 PciePreMemConfig->RootPort[3].Perst = 0; PciePreMemConfig->RootPort[4].Perst = N_GPIO_37; // LOM PciePreMemConfig->RootPort[5].Perst = 0; PciePreMemConfig->RootPort[0].Clock = W_GPIO_211; // Slot2 PciePreMemConfig->RootPort[1].Clock = W_GPIO_212; // NGFF PciePreMemConfig->RootPort[2].Clock = W_GPIO_209; // Slot1 PciePreMemConfig->RootPort[3].Clock = 0; PciePreMemConfig->RootPort[4].Clock = 0; PciePreMemConfig->RootPort[5].Clock = 0; // // Install ScPreMemPolicyPpi. // While installed, RC assumes the Policy is ready and finalized. So please // update and override any setting before calling this function. // Status = ScInstallPreMemPolicyPpi (ScPreMemPolicy); ASSERT_EFI_ERROR (Status); return Status; } #if (ENBDT_PF_ENABLE == 1) // // DDR SSC // EFI_STATUS EFIAPI PeiDDRSSCInit ( VOID ) { EFI_STATUS Status; EFI_PEI_READ_ONLY_VARIABLE2_PPI *VariableServices; SSC_IPC_BUFFER WBuf; UINT32 BufferSize = 0; SYSTEM_CONFIGURATION SystemConfiguration; UINTN VariableSize; // // static table for the SSC settings (corresponding with the SSC settings 0~-0.5%, 0.1% stepping) // Modulation Freq = 32KHz // SSC_SETTING SSC_Select_Table[] = {{No_SSC, 0x12B, 0}, {M01_SSC, 0x12B, 0x1062}, {M02_SSC, 0x12B, 0x2BB0}, {M03_SSC, 0x12B, 0x46FF}, {M04_SSC, 0x12B, 0x624D}, {M05_SSC, 0x12B, 0x7D9C}}; // //static table for the clock bending settings (corresponding with the clock bending settings 1.3%, 0.6%, 0, -0.9%) // CLOCK_BENDING_SETTING CLK_Bending_Table[] = {{Clk_Bending_13, 0xA00000, 0x7E}, {Clk_Bending_06, 0xC00000, 0x7D}, {No_Clk_Bending, 0x0, 0x7D}, {Clk_Bending_M09, 0xDB6C20, 0x7B}}; // // default value of the 4 SSC setting registers // WBuf.LJ1PLL_CTRL_1.Data = 0x00; WBuf.LJ1PLL_CTRL_2.Data = 0x0888812B; WBuf.LJ1PLL_CTRL_3 = 0x7D000000; WBuf.LJ1PLL_CTRL_5.Data = 0x7D000000; BufferSize = sizeof (UINT32) * 4; Status = PeiServicesLocatePpi (&gEfiPeiReadOnlyVariable2PpiGuid, 0, NULL, (VOID **) &VariableServices); if (EFI_ERROR (Status)) { ASSERT_EFI_ERROR (Status); return Status; } VariableSize = sizeof (SYSTEM_CONFIGURATION); Status = VariableServices->GetVariable ( VariableServices, PLATFORM_SETUP_VARIABLE_NAME, &gEfiSetupVariableGuid, NULL, &VariableSize, &SystemConfiguration ); if (EFI_ERROR (Status)) { DEBUG ((DEBUG_ERROR, "Setup Variable is not ready for SSC setting! Used default value!!\n\r")); // // Set default value of SSC // WBuf.LJ1PLL_CTRL_2.Fields.ssc_cyc_to_peak_m1 = SSC_Select_Table[SSC_DEFAULT_SETTING].Ssc_Cyc_To_Peak; WBuf.LJ1PLL_CTRL_2.Fields.ssc_frac_step = SSC_Select_Table[SSC_DEFAULT_SETTING].Ffs_Frac_Step; // // Set default value of Clock bending // WBuf.LJ1PLL_CTRL_5.Fields.pll_ratio_frac = CLK_Bending_Table[CLK_BENDING_DEFAULT_SETTING].Pll_Ratio_Frac; WBuf.LJ1PLL_CTRL_5.Fields.pll_ratio_int = CLK_Bending_Table[CLK_BENDING_DEFAULT_SETTING].Pll_Ratio_Int; // // send the IPC command for SSC // Status = IpcSendCommandEx (IPC_CMD_ID_EMI_RFI_SUPPORT, IPC_SUBCMD_ID_SSC_APPLY_NOW, &WBuf, BufferSize); // // Delay for 1ms to avoid the SSC doesn't set correctly sometimes // MicroSecondDelay (1000); // // set the ssc_en to Disable! // WBuf.LJ1PLL_CTRL_1.Fields.ssc_en = SSC_DISABLE; WBuf.LJ1PLL_CTRL_1.Fields.ssc_en_ovr = SSC_DISABLE; Status = IpcSendCommandEx (IPC_CMD_ID_EMI_RFI_SUPPORT, IPC_SUBCMD_ID_SSC_APPLY_NOW, &WBuf, BufferSize); return Status; } if (SystemConfiguration.DDRSSCEnable) { // // get the correct register values of the SSC setting // WBuf.LJ1PLL_CTRL_2.Fields.ssc_cyc_to_peak_m1 = SSC_Select_Table[SystemConfiguration.DDRSSCSelection].Ssc_Cyc_To_Peak; WBuf.LJ1PLL_CTRL_2.Fields.ssc_frac_step = SSC_Select_Table[SystemConfiguration.DDRSSCSelection].Ffs_Frac_Step; // // get the correct register values of the clock bending setting WBuf.LJ1PLL_CTRL_5.Fields.pll_ratio_frac = CLK_Bending_Table[SystemConfiguration.DDRCLKBending].Pll_Ratio_Frac; WBuf.LJ1PLL_CTRL_5.Fields.pll_ratio_int = CLK_Bending_Table[SystemConfiguration.DDRCLKBending].Pll_Ratio_Int; // // send the IPC command for SSC settings // Status = IpcSendCommandEx (IPC_CMD_ID_EMI_RFI_SUPPORT, IPC_SUBCMD_ID_SSC_APPLY_NOW, &WBuf, BufferSize); // // Delay for 1ms to avoid the SSC doesn't set correctly sometimes // MicroSecondDelay (1000); // // set the ssc_en and ssc_en_ovr to Enable! // WBuf.LJ1PLL_CTRL_1.Fields.ssc_en = SSC_ENABLE; WBuf.LJ1PLL_CTRL_1.Fields.ssc_en_ovr = SSC_ENABLE; // // send the IPC command for SSC EN // Status = IpcSendCommandEx (IPC_CMD_ID_EMI_RFI_SUPPORT, IPC_SUBCMD_ID_SSC_APPLY_NOW, &WBuf, BufferSize); } else { // get the correct register values of the clock bending setting WBuf.LJ1PLL_CTRL_5.Fields.pll_ratio_frac = CLK_Bending_Table[SystemConfiguration.DDRCLKBending].Pll_Ratio_Frac; WBuf.LJ1PLL_CTRL_5.Fields.pll_ratio_int = CLK_Bending_Table[SystemConfiguration.DDRCLKBending].Pll_Ratio_Int; Status = IpcSendCommandEx (IPC_CMD_ID_EMI_RFI_SUPPORT, IPC_SUBCMD_ID_SSC_APPLY_NOW, &WBuf, BufferSize); return Status; } return Status; } // // USB3, PCie, SATA, eDP, DP, eMMC, SD and SDIO SSC // EFI_STATUS EFIAPI PeiHighSpeedSerialInterfaceSSCInit ( VOID ) { EFI_STATUS Status; LCPLL_CR_RW_CONTROL_1 LCPLL_CTRL_1; LCPLL_CR_RW_CONTROL_2 LCPLL_CTRL_2; EFI_PEI_READ_ONLY_VARIABLE2_PPI *VariableServices; SYSTEM_CONFIGURATION SystemConfiguration; UINTN VariableSize; // // static table for the SSC settings (corresponding with the SSC settings 0~-0.5%, 0.1% stepping) // Modulation Freq = 32KHz // SSC_SETTING HSSIO_SSC_Select_Table[] = {{ No_SSC, 0x12B, 0 }, { M01_SSC, 0x12B, 0x1062 }, { M02_SSC, 0x12B, 0x2BB0 }, { M03_SSC, 0x12B, 0x46FF }, { M04_SSC, 0x12B, 0x624D }, { M05_SSC, 0x12B, 0x7D9C }}; LCPLL_CTRL_1.Data = SideBandRead32 (0x99, 0x9910); LCPLL_CTRL_2.Data = SideBandRead32 (0x99, 0x9914); VariableSize = sizeof (SYSTEM_CONFIGURATION); Status = PeiServicesLocatePpi (&gEfiPeiReadOnlyVariable2PpiGuid, 0, NULL, (VOID **) &VariableServices); if (EFI_ERROR (Status)) { ASSERT_EFI_ERROR (Status); return Status; } VariableSize = sizeof (SYSTEM_CONFIGURATION); Status = VariableServices->GetVariable ( VariableServices, PLATFORM_SETUP_VARIABLE_NAME, &gEfiSetupVariableGuid, NULL, &VariableSize, &SystemConfiguration ); if (EFI_ERROR (Status)) { DEBUG ((DEBUG_ERROR, "\nSetup Variable is not ready for SSC setting! Leave the default system HSSIO SSC settings!!\n\r")); return EFI_SUCCESS; } if (SystemConfiguration.HSSIOSSCEnable) { LCPLL_CTRL_2.Fields.ssc_cyc_to_peak_m1 = HSSIO_SSC_Select_Table[SystemConfiguration.HSSIOSSCSelection].Ssc_Cyc_To_Peak; LCPLL_CTRL_2.Fields.ssc_frac_step = HSSIO_SSC_Select_Table[SystemConfiguration.HSSIOSSCSelection].Ffs_Frac_Step; SideBandWrite32 (0x99, 0x9914, LCPLL_CTRL_2.Data); SideBandWrite32 (0x99, 0x9910, 0); } else { LCPLL_CTRL_1.Fields.ssc_en = SSC_DISABLE; LCPLL_CTRL_1.Fields.ssc_en_ovr = SSC_ENABLE; SideBandWrite32 (0x99, 0x9910, LCPLL_CTRL_1.Data); } return EFI_SUCCESS; } #endif /** This is the entry point of PEIM @param[in] FileHandle Handle of the file being invoked. @param[in] PeiServices Describes the list of possible PEI Services. @retval EFI_SUCCESS if it completed successfully. **/ EFI_STATUS EFIAPI PlatformInitPreMemEntryPoint ( IN EFI_PEI_FILE_HANDLE FileHandle, IN CONST EFI_PEI_SERVICES **PeiServices ) { EFI_PLATFORM_INFO_HOB PlatformInfo; EFI_STATUS Status = EFI_SUCCESS; EFI_PEI_PPI_DESCRIPTOR *PeiPpiDescriptor; FIRMWARE_SEC_PERFORMANCE Performance; EFI_PEI_READ_ONLY_VARIABLE2_PPI *VariableServices; VOID *Memory; IA32_DESCRIPTOR GdtDscriptor; UINT32 Temp32; UINT32 IfwiVerAddr; DRAM_POLICY_PPI *DramPolicy; EFI_PEI_PPI_DESCRIPTOR *NewPeiPpiDescriptor; EFI_BOOT_MODE BootMode; CarMapStruc *CarMap = NULL; SYSTEM_CONFIGURATION SystemConfiguration; UINTN VariableSize; EFI_PEI_HOB_POINTERS Hob; EFI_PLATFORM_INFO_HOB *PlatformInfoPtr; EFI_HOB_GUID_TYPE *FdoEnabledGuidHob = NULL; UINT64 StartTimerTicker = 0; UINT64 Tick; UINTN AcpiVarHobSize; #if (ENBDT_PF_ENABLE == 1) MBP_CURRENT_BOOT_MEDIA BootMediaData; #endif PEI_BOARD_PRE_MEM_INIT_PPI *BoardPreMemInitPpi; UINTN Instance; UINT64 AcpiVariableSetCompatibility; UINTN VarSize; Status = (*PeiServices)->RegisterForShadow (FileHandle); if (Status == EFI_ALREADY_STARTED) { ImageInMemory = TRUE; } else if (Status == EFI_NOT_FOUND) { ASSERT_EFI_ERROR (Status); } if (!ImageInMemory) { // // Since PEI has no PCI enumerator, set the BAR & I/O space enable ourselves // ScBaseInit (); MultiPlatformGpioProgramPreMem (&StartTimerTicker); } Status = InstallMonoStatusCode (FileHandle, PeiServices); if (!ImageInMemory) { // // Locate all Board Pre Mem Init PPI instances and call them one by one // Instance = 0; do { Status = PeiServicesLocatePpi ( &gBoardPreMemInitPpiGuid, Instance, &PeiPpiDescriptor, (VOID **)&BoardPreMemInitPpi ); if (Status == EFI_NOT_FOUND) { break; } ASSERT_EFI_ERROR (Status); DEBUG ((EFI_D_INFO, "Call Board Pre Mem Init PPI\n")); Status = BoardPreMemInitPpi->PreMemInit (PeiServices, BoardPreMemInitPpi); ASSERT_EFI_ERROR (Status); Instance ++; } while (TRUE); } AsmReadGdtr (&GdtDscriptor); DEBUG ((DEBUG_INFO, "GdtDscriptor Base Address:0x%X\n", (UINT32) GdtDscriptor.Base)); PERF_START_EX (NULL, NULL, NULL, 0, 0x9100); SeCUmaEntry (FileHandle, PeiServices); PERF_END_EX (NULL, NULL, NULL, 0, 0x9101); Status = PeiScPreMemPolicyInit (&StartTimerTicker); ASSERT_EFI_ERROR (Status); if (!ImageInMemory) { if (GdtDscriptor.Base >= 0xFE000000) { IfwiVerAddr = GdtDscriptor.Base; IfwiVerAddr &= 0xfffff000; // 4K alignment to get IBBL base address. IfwiVerAddr +=0x1000; // the address of IBBL end for (Temp32 = 0; Temp32 < 0x8000; Temp32 += 0x10) { CarMap = (CarMapStruc *) (IfwiVerAddr-Temp32); if (CarMap->Sign == SIGNATURE_32 ('$','S','I','G')) { DEBUG ((DEBUG_INFO, "CarMap Address:0x%X\n", (UINT32) CarMap)); break; } } } // // Set PcdIafwPlatformInfo = Real_Silicon + Max_RevId // PcdSet32S (PcdIafwPlatformInfo, 0x0000FF00); // // Initialize PlatformInfo HOB // ZeroMem (&PlatformInfo, sizeof (PlatformInfo)); PlatformInfo.SsidSvid = (UINT32) CarMap; Status = ReadBxtIPlatformIds (PeiServices, &PlatformInfo); ASSERT_EFI_ERROR (Status); // // Build HOB for PlatformInfo // BuildGuidDataHob ( &gEfiPlatformInfoGuid, &PlatformInfo, sizeof (EFI_PLATFORM_INFO_HOB) ); // // Attempt to locate SMIP and publish its data to PPI's and PCDs. // Currently no reason to check Status, but could add in future. // // This currently installs gDramPolicyPpiGuid, but may move in future // Status = SmipInit ((VOID *)CarMap->FITBase, PlatformInfo.BoardId); MultiPlatformGpioUpdatePreMem (); // // Print out Patch version string (BXT) // AsmWriteMsr64 (0x8B, 0); AsmCpuid (0x1, NULL, NULL, NULL, NULL); Temp32 = (UINT32) (AsmReadMsr64 (0x8B) >> 32); DEBUG ((DEBUG_INFO, "PatchInfo: 0x%08x ", Temp32 )); DEBUG ((DEBUG_INFO, "%08x \n", (UINT32) (AsmReadMsr64 (0x8B)))); // // Set the new boot mode for MRC // Status = UpdateBootMode (PeiServices, &PlatformInfo); ASSERT_EFI_ERROR (Status); // // Initialize MfgMemoryTest PPIs // Status = PeiServicesInstallPpi (&mMfgMemTestPpi); ASSERT_EFI_ERROR (Status); // // Setting 8254 // Program timer 1 as refresh timer // IoWrite8 (0x43, 0x54); IoWrite8 (0x41, 0x12); // // RTC power failure handling // RtcPowerFailureHandler (); #if (ENBDT_PF_ENABLE == 1) if (GetBxtSeries() == BxtP) { // // DDR SSC // PeiDDRSSCInit (); // // USB3, PCie, SATA, eDP, DP, eMMC, SD and SDIO SSC // PeiHighSpeedSerialInterfaceSSCInit (); } #endif #if defined(PRAM_SUPPORT) // // Install Ppi for BIOS reserved memory // Status = PeiServicesInstallPpi (&mBiosReservedMemoryPolicyPpi); #endif Status = PeiServicesLocatePpi (&gEfiPeiReadOnlyVariable2PpiGuid, 0, NULL, (VOID **) &VariableServices); if (EFI_ERROR (Status)) { ASSERT_EFI_ERROR (Status); return Status; } VariableSize = sizeof (AcpiVariableSetCompatibility); Status = VariableServices->GetVariable ( VariableServices, ACPI_GLOBAL_VARIABLE, &gEfiAcpiVariableCompatiblityGuid, NULL, &VariableSize, &AcpiVariableSetCompatibility ); AcpiVarHobSize = sizeof (UINT64); BuildGuidDataHob ( &gEfiAcpiVariableCompatiblityGuid, &AcpiVariableSetCompatibility, sizeof (AcpiVarHobSize) ); DEBUG ((DEBUG_INFO, "AcpiVariableAddr : 0x%08x\n", AcpiVariableSetCompatibility)); PERF_START_EX (NULL, "RstVctr", "IBBL", 1, 0x1000); Tick = CarMap->IbblPerfRecord0; PERF_END_EX (NULL, "RstVctr", "IBBL", Tick, 0x1001); PERF_START_EX (NULL, "InitNEM", "IBBL", Tick, 0x1010); Tick = CarMap->IbblPerfRecord1; PERF_END_EX (NULL, "InitNEM", "IBBL", Tick, 0x1011); PERF_START_EX (NULL, "IBBLSdw", "IBBL", Tick, 0x1020); Tick = CarMap->IbblPerfRecord2; PERF_END_EX (NULL, "IBBLSdw", "IBBL", Tick, 0x1021); PERF_START_EX (NULL, "IBBMLod", "IBBL", Tick, 0x1030); Tick = CarMap->IbblPerfRecord3; PERF_END_EX (NULL, "IBBMLod", "IBBL", Tick, 0x1031); PERF_START_EX (NULL, "IBBMVer", "IBBL", Tick, 0x1040); Tick = CarMap->IbblPerfRecord4; PERF_END_EX (NULL, "IBBMVer", "IBBL", Tick, 0x1041); VarSize = sizeof (SYSTEM_CONFIGURATION); Status = VariableServices->GetVariable ( VariableServices, L"Setup", &gEfiSetupVariableGuid, NULL, &VarSize, &SystemConfiguration ); if (EFI_ERROR (Status) || VarSize != sizeof(SYSTEM_CONFIGURATION)) { Status = PlatformCreateDefaultVariableHob (EFI_HII_DEFAULT_CLASS_STANDARD); ASSERT_EFI_ERROR (Status); } Status = VariableServices->GetVariable ( VariableServices, L"Setup", &gEfiSetupVariableGuid, NULL, &VarSize, &SystemConfiguration ); ASSERT_EFI_ERROR (Status); // // Normal boot - build Hob for SEC performance data. // Performance.ResetEnd = GetTimeInNanoSecond (CarMap->IbblPerfRecord0); if (!EFI_ERROR (Status)) { BuildGuidDataHob ( &gEfiFirmwarePerformanceGuid, &Performance, sizeof (FIRMWARE_SEC_PERFORMANCE) ); DEBUG ((EFI_D_INFO, "FPDT: SEC Performance Hob ResetEnd = %ld\n", Performance.ResetEnd)); } } else { //PostMem Hob.Raw = GetFirstGuidHob (&gEfiPlatformInfoGuid); ASSERT (Hob.Raw != NULL); PlatformInfoPtr = GET_GUID_HOB_DATA (Hob.Raw); CarMap = (CarMapStruc *) (UINT32) PlatformInfoPtr->SsidSvid; // // Locate and Reinstall necessary PPI's before MemoryCallback is run // Status = PeiServicesLocatePpi ( &gDramPolicyPpiGuid, 0, &PeiPpiDescriptor, NULL // PPI ); if (EFI_ERROR (Status)) { DEBUG ((DEBUG_ERROR, "Couldn't locate DRAM Policy PPI, LocatePpi returned %r.\n", Status)); } else { DramPolicy = (DRAM_POLICY_PPI *) AllocateZeroPool (sizeof (DRAM_POLICY_PPI)); NewPeiPpiDescriptor = (EFI_PEI_PPI_DESCRIPTOR *) AllocateZeroPool (sizeof (EFI_PEI_PPI_DESCRIPTOR)); if ((DramPolicy == NULL) || (NewPeiPpiDescriptor == NULL)) { DEBUG ((DEBUG_ERROR, "Couldn't allocate memory for DRAM Policy PPI.\n")); } else { (*PeiServices)->CopyMem ( (VOID *) DramPolicy, (VOID *) PeiPpiDescriptor->Ppi, sizeof (DRAM_POLICY_PPI) ); NewPeiPpiDescriptor->Ppi = DramPolicy; NewPeiPpiDescriptor->Guid = &gDramPolicyPpiGuid; NewPeiPpiDescriptor->Flags = EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST; Status = (**PeiServices).ReInstallPpi ( PeiServices, PeiPpiDescriptor, NewPeiPpiDescriptor ); } } if (GdtDscriptor.Base >= 0xFE000000) { (*PeiServices)->CopyMem ( (VOID *) mGdtTable, (VOID *) GdtDscriptor.Base, GdtDscriptor.Limit + 1 ); GdtDscriptor.Base = (UINT32) mGdtTable; AsmWriteGdtr (&GdtDscriptor); } // // Set "Force Volatile Mode" in the variable driver // If Firmware Descriptor Override (FDO) boot is enabled // FdoEnabledGuidHob = GetFirstGuidHob (&gFdoModeEnabledHobGuid); if (FdoEnabledGuidHob != NULL) { PcdSetBoolS (PcdForceVolatileVariable, TRUE); } // // locate the MfgMemoryTest PPI // Status = PeiServicesLocatePpi ( &gPeiMfgMemoryTestPpiGuid, // GUID 0, // INSTANCE &PeiPpiDescriptor, // EFI_PEI_PPI_DESCRIPTOR NULL // PPI ); if (Status == EFI_SUCCESS) { // // Reinstall the MfgMemoryTest PPI // Status = PeiServicesReInstallPpi ( PeiPpiDescriptor, &mMfgMemTestPpi ); } // // locate the TemporaryRamSupport PPI // Status = PeiServicesLocatePpi ( &gEfiTemporaryRamSupportPpiGuid, // GUID 0, // INSTANCE &PeiPpiDescriptor, // EFI_PEI_PPI_DESCRIPTOR NULL // PPI ); if (Status == EFI_SUCCESS) { // // Reinstall the Variable PPI // Status = PeiServicesReInstallPpi ( PeiPpiDescriptor, mPeiTemporaryRamSupportPpiPpi ); } #if defined(PRAM_SUPPORT) // // locate the BiosReservedMemory PPI // Status = PeiServicesLocatePpi ( &gBiosReservedMemoryPolicyPpiGuid, 0, &PeiPpiDescriptor, NULL // PPI ); if (Status == EFI_SUCCESS) { Status = PeiServicesReInstallPpi ( PeiPpiDescriptor, &mBiosReservedMemoryPolicyPpi ); } #endif // // Initialize Stall PPIs // Status = PeiServicesInstallPpi (&mInstallStallPpi); ASSERT_EFI_ERROR (Status); Status = PeiServicesGetBootMode (&BootMode); #if (ENBDT_PF_ENABLE == 1) if (BootMode == BOOT_ON_S3_RESUME) { Status = PeiServicesLocatePpi (&gEfiPeiReadOnlyVariable2PpiGuid, 0, NULL, (VOID **) &VariableServices); if (EFI_ERROR (Status)) { ASSERT_EFI_ERROR (Status); return Status; } VariableSize = sizeof (SYSTEM_CONFIGURATION); Status = VariableServices->GetVariable ( VariableServices, PLATFORM_SETUP_VARIABLE_NAME, &gEfiSetupVariableGuid, NULL, &VariableSize, &SystemConfiguration ); if (!EFI_ERROR (Status)) { SetMem (&BootMediaData, sizeof (MBP_CURRENT_BOOT_MEDIA), 0x0); switch (SystemConfiguration.CseBootDevice) { case 0: DEBUG ((DEBUG_INFO, "CSE Boot Device is EMMC.\n")); Status = (*PeiServices)->InstallPpi (PeiServices, mCseEmmcSelectPpiList); break; case 1: DEBUG ((DEBUG_INFO, "CSE Boot Device is UFS.\n")); Status = (*PeiServices)->InstallPpi (PeiServices, mCseUfsSelectPpiList); break; case 2: DEBUG ((DEBUG_INFO, "CSE Boot Device is SPI.\n")); Status = (*PeiServices)->InstallPpi (PeiServices, mCseSpiSelectPpiList); break; default: DEBUG ((EFI_D_ERROR, "\nCSE Boot device is unknown. Cannot continue!\n")); CpuDeadLoop(); break; } BootMediaData.PhysicalData = SystemConfiguration.CseBootDevice; // // Build HOB for BootMediaData // BuildGuidDataHob ( &gEfiBootMediaHobGuid, &BootMediaData, sizeof (MBP_CURRENT_BOOT_MEDIA) ); } } #endif // // copy IBBM from Cache to DRAM. the hardcoded address need to be changed // to use the parameter in IBBL. // Memory = AllocatePages (EFI_SIZE_TO_PAGES (PcdGet32 (PcdFlashFvIBBMSize))); if (Memory != NULL) { CopyMem (Memory , (VOID *) CarMap->IBBBase, PcdGet32 (PcdFlashFvIBBMSize)); DEBUG ((DEBUG_INFO, "IBBM address: %x\n", Memory)); PeiServicesInstallFvInfoPpi ( NULL, (VOID *) Memory, PcdGet32 (PcdFlashFvIBBMSize), NULL, NULL ); } else { ASSERT (FALSE); } DEBUG ((DEBUG_INFO, "PreMem Policy Init - Start\n")); // // Initialize Pre-Mem PEI Platform Policy // Status = PeiPolicyInitPreMem (); ASSERT_EFI_ERROR (Status); DEBUG ((DEBUG_INFO, "PreMem Policy Init - End\n\n")); // // Register Notify Callback to process OBB loading. // In FSP+Wrapper, the MTRRs are set after TempRamExit, not gEfiPeiMemoryDiscoveredPpiGuid. // Status = PeiServicesNotifyPpi (&mFspTempRamExitList[0]); ASSERT_EFI_ERROR (Status); } //end PostMem DEBUG ((DEBUG_INFO, "PeiInitPlatform end\n")); return Status; } // // Read Platform ID for IOTG Platforms // EFI_STATUS ReadBxtIPlatformIds ( IN CONST EFI_PEI_SERVICES **PeiServices, IN OUT EFI_PLATFORM_INFO_HOB *PlatformInfoHob ) { UINT8 BoardId = 0; UINT8 FabId = 0; DEBUG ((DEBUG_INFO, "Port(0x62) = %02X\n", IoRead8 (0x62))); PlatformInfoHob->ECPresent = 0; BoardId = (UINT8) PcdGet8 (PcdBoardId); FabId = (UINT8) PcdGet8 (PcdFabId); PlatformInfoHob->BoardId = BoardId; PlatformInfoHob->BoardRev = FabId; DEBUG ((DEBUG_INFO, "BoardId: [0x%08x]\n", PlatformInfoHob->BoardId)); DEBUG ((DEBUG_INFO, "FabId: [0x%08x]\n", PlatformInfoHob->BoardRev)); return EFI_SUCCESS; } /** Description: This function finds the matched default data and create GUID hob for it. Arguments: DefaultId - Specifies the type of defaults to retrieve. Returns: EFI_SUCCESS - The matched default data is found. EFI_NOT_FOUND - The matched default data is not found. EFI_OUT_OF_RESOURCES - No enough resource to create HOB. **/ EFI_STATUS PlatformCreateDefaultVariableHob ( IN UINT16 DefaultId ) { UINTN FvInstance; EFI_FIRMWARE_VOLUME_HEADER *FvHeader; EFI_FFS_FILE_HEADER *FfsHeader; UINT32 FileSize; EFI_COMMON_SECTION_HEADER *Section; UINT32 SectionLength; BOOLEAN DefaultSettingIsFound; DEFAULT_DATA *DefaultData; DEFAULT_INFO *DefaultInfo; VARIABLE_STORE_HEADER *VarStoreHeader; VARIABLE_STORE_HEADER *VarStoreHeaderHob; UINT8 *VarHobPtr; UINT8 *VarPtr; UINT32 VarDataOffset; UINT32 VarHobDataOffset; BOOLEAN IsFirstSection; DATA_DELTA *DataDelta; UINTN DataDeltaSize; UINTN Index; CONST EFI_PEI_SERVICES **PeiServices; // // Get PeiService pointer // PeiServices = GetPeiServicesTablePointer (); // // Find the FFS file that stores all default data. // DefaultSettingIsFound = FALSE; FvInstance = 0; FfsHeader = NULL; while (((*PeiServices)->FfsFindNextVolume (PeiServices, FvInstance, (VOID **) &FvHeader) == EFI_SUCCESS) && (!DefaultSettingIsFound)) { FfsHeader = NULL; while ((*PeiServices)->FfsFindNextFile (PeiServices, EFI_FV_FILETYPE_FREEFORM, FvHeader, (VOID **) &FfsHeader) == EFI_SUCCESS) { if (CompareGuid ((EFI_GUID *) FfsHeader, &gDefaultDataOptSizeFileGuid)) { DefaultSettingIsFound = TRUE; break; } } FvInstance ++; } // // FFS file is not found. // if (!DefaultSettingIsFound) { return EFI_NOT_FOUND; } // // Find the matched default data for the input default ID and plat ID. // DefaultSettingIsFound = FALSE; VarStoreHeaderHob = NULL; VarHobPtr = NULL; DataDelta = NULL; DataDeltaSize = 0; IsFirstSection = TRUE; VarStoreHeader = NULL; Section = (EFI_COMMON_SECTION_HEADER *)(FfsHeader + 1); FileSize = *(UINT32 *)(FfsHeader->Size) & 0x00FFFFFF; while (((UINTN) Section < (UINTN) FfsHeader + FileSize) && !DefaultSettingIsFound) { DefaultData = (DEFAULT_DATA *) (Section + 1); DefaultInfo = &(DefaultData->DefaultInfo[0]); SectionLength = *(UINT32 *)Section->Size & 0x00FFFFFF; if (IsFirstSection) { // // Create HOB to store default data so that Variable driver can use it. // Allocate more data for header alignment. // VarStoreHeader = (VARIABLE_STORE_HEADER *) ((UINT8 *) DefaultData + DefaultData->HeaderSize); VarStoreHeaderHob = (VARIABLE_STORE_HEADER *) BuildGuidHob (&VarStoreHeader->Signature, VarStoreHeader->Size + HEADER_ALIGNMENT - 1); if (VarStoreHeaderHob == NULL) { // // No enough hob resource. // return EFI_OUT_OF_RESOURCES; } // // Copy variable storage header. // CopyMem (VarStoreHeaderHob, VarStoreHeader, sizeof (VARIABLE_STORE_HEADER)); // // Copy variable data. // VarPtr = (UINT8 *) HEADER_ALIGN ((UINTN) (VarStoreHeader + 1)); VarDataOffset = (UINT32) ((UINTN) VarPtr - (UINTN) VarStoreHeader); VarHobPtr = (UINT8 *) HEADER_ALIGN ((UINTN) (VarStoreHeaderHob + 1)); VarHobDataOffset = (UINT32) ((UINTN) VarHobPtr - (UINTN) VarStoreHeaderHob); CopyMem (VarHobPtr, VarPtr, VarStoreHeader->Size - VarDataOffset); // // Update variable size. // VarStoreHeaderHob->Size = VarStoreHeader->Size - VarDataOffset + VarHobDataOffset; // // Update Delta Data // VarHobPtr = (UINT8 *) VarStoreHeaderHob - VarDataOffset + VarHobDataOffset; } else { // // Apply delta setting // DataDelta = (DATA_DELTA *) ((UINT8 *) DefaultData + DefaultData->HeaderSize); DataDeltaSize = SectionLength - sizeof (EFI_COMMON_SECTION_HEADER) - DefaultData->HeaderSize; for (Index = 0; Index < DataDeltaSize / sizeof (DATA_DELTA); Index ++) { *((UINT8 *) VarHobPtr + DataDelta[Index].Offset) = DataDelta[Index].Value; } } // // Find the matched DefaultId // while ((UINTN) DefaultInfo < (UINTN) DefaultData + DefaultData->HeaderSize) { if (DefaultInfo->DefaultId == DefaultId) { DefaultSettingIsFound = TRUE; break; } DefaultInfo ++; } // // Size is 24 bits wide so mask upper 8 bits. // SectionLength is adjusted it is 4 byte aligned. // Go to the next section // SectionLength = (SectionLength + 3) & (~3); ASSERT (SectionLength != 0); Section = (EFI_COMMON_SECTION_HEADER *)((UINT8 *)Section + SectionLength); IsFirstSection = FALSE; } // // Matched default data is not found. // if (!DefaultSettingIsFound) { // // Change created HOB type to be unused. // if (VarStoreHeaderHob != NULL) { ((EFI_HOB_GUID_TYPE *)((UINT8 *) VarStoreHeaderHob - sizeof (EFI_HOB_GUID_TYPE)))->Header.HobType = EFI_HOB_TYPE_UNUSED; } return EFI_NOT_FOUND; } return EFI_SUCCESS; }