/** This function will be called when MRC is done. @param PeiServices General purpose services available to every PEIM. @param NotifyDescriptor Information about the notify event.. @param Ppi The notify context. @retval EFI_SUCCESS If the function completed successfully. **/ EFI_STATUS EFIAPI MemoryDiscoveredPpiNotifyCallback ( IN EFI_PEI_SERVICES **PeiServices, IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor, IN VOID *Ppi ) { EFI_STATUS Status; EFI_BOOT_MODE BootMode; UINT64 MemoryLength; UINT64 MemoryLengthUc; UINT64 MaxMemoryLength; UINT64 MemOverflow; EFI_SMRAM_DESCRIPTOR *SmramDescriptor; UINTN NumSmramRegions; UINT64 EnlargedMemoryLength; UINT32 RmuMainBaseAddress; UINTN Index; MTRR_SETTINGS MtrrSetting; UINT32 RegData32; EFI_PHYSICAL_ADDRESS NewBuffer; UINT8 CpuAddressWidth; EFI_CPUID_REGISTER FeatureInfo; DEBUG ((EFI_D_INFO, "Platform PEIM Memory Callback\n")); NumSmramRegions = 0; SmramDescriptor = NULL; RmuMainBaseAddress = 0; PERF_START (NULL, "SetCache", NULL, 0); InfoPostInstallMemory (&RmuMainBaseAddress, &SmramDescriptor, &NumSmramRegions); ASSERT (SmramDescriptor != NULL); ASSERT (RmuMainBaseAddress != 0); MemoryLength = ((UINT64) RmuMainBaseAddress) + 0x10000; EnlargedMemoryLength = MemoryLength; if (NumSmramRegions > 0) { // // Find the TSEG // for (Index = 0; Index < NumSmramRegions; Index ++) { if ((SmramDescriptor[Index].PhysicalStart) == EnlargedMemoryLength) { if (SmramDescriptor[Index].RegionState & EFI_CACHEABLE) { // // Enlarge memory length to include TSEG size // EnlargedMemoryLength += (SmramDescriptor[Index].PhysicalSize); } } } } // // Check if a UC region is present // MaxMemoryLength = EnlargedMemoryLength; // Round up to nearest 256MB MemOverflow = (MemoryLength & 0x0fffffff); if (MemOverflow != 0) { MaxMemoryLength = MemoryLength + (0x10000000 - MemOverflow); } Status = PeiServicesGetBootMode (&BootMode); ASSERT_EFI_ERROR (Status); ZeroMem (&MtrrSetting, sizeof(MTRR_SETTINGS)); (**PeiServices).CopyMem ((VOID *)&MtrrSetting.Fixed,(VOID *)&mFixedMtrrTable, sizeof(MTRR_FIXED_SETTINGS) ); // // Cache the flash area to improve the boot performance in PEI phase // MtrrSetting.Variables.Mtrr[0].Base = (QUARK_BOOTROM_BASE_ADDRESS | CacheWriteBack); MtrrSetting.Variables.Mtrr[0].Mask = (((~(QUARK_BOOTROM_SIZE_BYTES - 1)) & MTRR_LIB_CACHE_VALID_ADDRESS) | MTRR_LIB_CACHE_MTRR_ENABLED); MtrrSetting.Variables.Mtrr[1].Base = CacheWriteBack; MtrrSetting.Variables.Mtrr[1].Mask = ((~(MaxMemoryLength - 1)) & MTRR_LIB_CACHE_VALID_ADDRESS) | MTRR_LIB_CACHE_MTRR_ENABLED; Index = 2; while (MaxMemoryLength != MemoryLength) { MemoryLengthUc = GetPowerOfTwo64 (MaxMemoryLength - MemoryLength); //Status = MtrrSetMemoryAttribute (MaxMemoryLength - MemoryLengthUc, MemoryLengthUc, CacheUncacheable); //ASSERT_EFI_ERROR (Status); MtrrSetting.Variables.Mtrr[Index].Base = ((MaxMemoryLength - MemoryLengthUc) & MTRR_LIB_CACHE_VALID_ADDRESS) | CacheUncacheable; MtrrSetting.Variables.Mtrr[Index].Mask= ((~(MemoryLengthUc - 1)) & MTRR_LIB_CACHE_VALID_ADDRESS) | MTRR_LIB_CACHE_MTRR_ENABLED; MaxMemoryLength -= MemoryLengthUc; Index++; } AsmInvd (); MtrrSetting.MtrrDefType = MTRR_LIB_CACHE_MTRR_ENABLED | MTRR_LIB_CACHE_FIXED_MTRR_ENABLED; MtrrSetAllMtrrs(&MtrrSetting); PERF_END (NULL, "SetCache", NULL, 0); // // Install PeiReset for PeiResetSystem service // Status = PeiServicesInstallPpi (&mPpiList[0]); ASSERT_EFI_ERROR (Status); // // Do QNC initialization after MRC // PeiQNCPostMemInit (); Status = PeiServicesInstallPpi (&mPpiStall[0]); ASSERT_EFI_ERROR (Status); // // Set E000/F000 Routing // RegData32 = QNCPortRead (QUARK_NC_HOST_BRIDGE_SB_PORT_ID, QNC_MSG_FSBIC_REG_HMISC); RegData32 |= (BIT2|BIT1); QNCPortWrite (QUARK_NC_HOST_BRIDGE_SB_PORT_ID, QNC_MSG_FSBIC_REG_HMISC, RegData32); if (BootMode == BOOT_IN_RECOVERY_MODE) { PeiServicesInstallFvInfoPpi ( NULL, (VOID *) (UINTN) PcdGet32 (PcdFlashFvRecovery2Base), PcdGet32 (PcdFlashFvRecovery2Size), NULL, NULL ); Status = PeimInitializeRecovery (PeiServices); ASSERT_EFI_ERROR (Status); } else if (BootMode == BOOT_ON_S3_RESUME) { return EFI_SUCCESS; } else { // // Allocate the memory so that it gets preserved into DXE // Status = PeiServicesAllocatePages ( EfiBootServicesData, EFI_SIZE_TO_PAGES (PcdGet32 (PcdFvSecurityHeaderSize) + PcdGet32 (PcdFlashFvMainSize)), &NewBuffer ); // // Copy the compressed main Firmware Volume to memory for faster processing later // CopyMem ((VOID *) (UINTN) NewBuffer, (VOID *) (UINTN) (PcdGet32 (PcdFlashFvMainBase) - PcdGet32 (PcdFvSecurityHeaderSize)), (PcdGet32 (PcdFvSecurityHeaderSize) +PcdGet32 (PcdFlashFvMainSize))); PeiServicesInstallFvInfoPpi ( NULL, (VOID *) (UINTN) (NewBuffer + PcdGet32 (PcdFvSecurityHeaderSize)), PcdGet32 (PcdFlashFvMainSize), NULL, NULL ); } // // Build flash HOB, it's going to be used by GCD and E820 building // Map full SPI flash decode range (regardless of smaller SPI flash parts installed) // BuildResourceDescriptorHob ( EFI_RESOURCE_FIRMWARE_DEVICE, (EFI_RESOURCE_ATTRIBUTE_PRESENT | EFI_RESOURCE_ATTRIBUTE_INITIALIZED | EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE), (SIZE_4GB - SIZE_8MB), SIZE_8MB ); // // Create a CPU hand-off information // CpuAddressWidth = 32; AsmCpuid (EFI_CPUID_EXTENDED_FUNCTION, &FeatureInfo.RegEax, NULL, NULL, NULL); if (FeatureInfo.RegEax >= EFI_CPUID_VIR_PHY_ADDRESS_SIZE) { AsmCpuid (EFI_CPUID_VIR_PHY_ADDRESS_SIZE, &FeatureInfo.RegEax, NULL, NULL, NULL); CpuAddressWidth = (UINT8) (FeatureInfo.RegEax & 0xFF); } DEBUG ((EFI_D_INFO, "CpuAddressWidth: %d\n", CpuAddressWidth)); BuildCpuHob (CpuAddressWidth, 16); ASSERT_EFI_ERROR (Status); return Status; }
/** This function will be called when MRC is done. @param PeiServices General purpose services available to every PEIM. @param NotifyDescriptor Information about the notify event.. @param Ppi The notify context. @retval EFI_SUCCESS If the function completed successfully. **/ EFI_STATUS EFIAPI MemoryDiscoveredPpiNotifyCallback ( IN EFI_PEI_SERVICES **PeiServices, IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor, IN VOID *Ppi ) { EFI_STATUS Status; EFI_BOOT_MODE BootMode; UINT64 MemoryLength; EFI_SMRAM_DESCRIPTOR *SmramDescriptor; UINTN NumSmramRegions; UINT32 RmuMainBaseAddress; UINT32 RegData32; UINT8 CpuAddressWidth; UINT32 RegEax; MTRR_SETTINGS MtrrSettings; EFI_PEI_READ_ONLY_VARIABLE2_PPI *VariableServices; UINT8 MorControl; UINTN DataSize; DEBUG ((EFI_D_INFO, "Platform PEIM Memory Callback\n")); NumSmramRegions = 0; SmramDescriptor = NULL; RmuMainBaseAddress = 0; PERF_START (NULL, "SetCache", NULL, 0); InfoPostInstallMemory (&RmuMainBaseAddress, &SmramDescriptor, &NumSmramRegions); ASSERT (SmramDescriptor != NULL); ASSERT (RmuMainBaseAddress != 0); MemoryLength = ((UINT64) RmuMainBaseAddress) + 0x10000; Status = PeiServicesGetBootMode (&BootMode); ASSERT_EFI_ERROR (Status); // // Get current MTRR settings // MtrrGetAllMtrrs (&MtrrSettings); // // Set all DRAM cachability to CacheWriteBack // Status = MtrrSetMemoryAttributeInMtrrSettings (&MtrrSettings, 0, MemoryLength, CacheWriteBack); ASSERT_EFI_ERROR (Status); // // RTC:28208 - System hang/crash when entering probe mode(ITP) when relocating SMBASE // Workaround to make default SMRAM UnCachable // Status = MtrrSetMemoryAttributeInMtrrSettings (&MtrrSettings, 0x30000, SIZE_64KB, CacheUncacheable); ASSERT_EFI_ERROR (Status); // // Set new MTRR settings // MtrrSetAllMtrrs (&MtrrSettings); PERF_END (NULL, "SetCache", NULL, 0); // // Get necessary PPI // Status = PeiServicesLocatePpi ( &gEfiPeiReadOnlyVariable2PpiGuid, // GUID 0, // INSTANCE NULL, // EFI_PEI_PPI_DESCRIPTOR (VOID **)&VariableServices // PPI ); ASSERT_EFI_ERROR (Status); // // Detect MOR request by the OS. // MorControl = 0; DataSize = sizeof (MorControl); Status = VariableServices->GetVariable ( VariableServices, MEMORY_OVERWRITE_REQUEST_VARIABLE_NAME, &gEfiMemoryOverwriteControlDataGuid, NULL, &DataSize, &MorControl ); // // If OS requested a memory overwrite perform it now for Embedded SRAM // if (MOR_CLEAR_MEMORY_VALUE (MorControl)) { DEBUG ((EFI_D_INFO, "Clear Embedded SRAM per MOR request.\n")); if (PcdGet32 (PcdESramMemorySize) > 0) { if (PcdGet32 (PcdEsramStage1Base) == 0) { // // ZeroMem() generates an ASSERT() if Buffer parameter is NULL. // Clear byte at 0 and start clear operation at address 1. // *(UINT8 *)(0) = 0; ZeroMem ((VOID *)1, (UINTN)PcdGet32 (PcdESramMemorySize) - 1); } else { ZeroMem ( (VOID *)(UINTN)PcdGet32 (PcdEsramStage1Base), (UINTN)PcdGet32 (PcdESramMemorySize) ); } } } // // Install PeiReset for PeiResetSystem service // Status = PeiServicesInstallPpi (&mPpiList[0]); ASSERT_EFI_ERROR (Status); // // Do QNC initialization after MRC // PeiQNCPostMemInit (); Status = PeiServicesInstallPpi (&mPpiStall[0]); ASSERT_EFI_ERROR (Status); // // Set E000/F000 Routing // RegData32 = QNCPortRead (QUARK_NC_HOST_BRIDGE_SB_PORT_ID, QNC_MSG_FSBIC_REG_HMISC); RegData32 |= (BIT2|BIT1); QNCPortWrite (QUARK_NC_HOST_BRIDGE_SB_PORT_ID, QNC_MSG_FSBIC_REG_HMISC, RegData32); if (BootMode == BOOT_IN_RECOVERY_MODE) { // Do nothing here. A generic RecoveryModule will handle it. } else if (BootMode == BOOT_ON_S3_RESUME) { return EFI_SUCCESS; } else { PeiServicesInstallFvInfoPpi ( NULL, (VOID *) (UINTN) PcdGet32 (PcdFlashFvMainBase), PcdGet32 (PcdFlashFvMainSize), NULL, NULL ); // // Publish the FVMAIN FV so the DXE Phase can dispatch drivers from this FV // and produce Load File Protocols for UEFI Applications in this FV. // BuildFvHob ( PcdGet32 (PcdFlashFvMainBase), PcdGet32 (PcdFlashFvMainSize) ); // // Publish the Payload FV so the DXE Phase can dispatch drivers from this FV // and produce Load File Protocols for UEFI Applications in this FV. // BuildFvHob ( PcdGet32 (PcdFlashFvPayloadBase), PcdGet32 (PcdFlashFvPayloadSize) ); } // // Build flash HOB, it's going to be used by GCD and E820 building // Map full SPI flash decode range (regardless of smaller SPI flash parts installed) // BuildResourceDescriptorHob ( EFI_RESOURCE_FIRMWARE_DEVICE, (EFI_RESOURCE_ATTRIBUTE_PRESENT | EFI_RESOURCE_ATTRIBUTE_INITIALIZED | EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE), (SIZE_4GB - SIZE_8MB), SIZE_8MB ); // // Create a CPU hand-off information // CpuAddressWidth = 32; AsmCpuid (CPUID_EXTENDED_FUNCTION, &RegEax, NULL, NULL, NULL); if (RegEax >= CPUID_VIR_PHY_ADDRESS_SIZE) { AsmCpuid (CPUID_VIR_PHY_ADDRESS_SIZE, &RegEax, NULL, NULL, NULL); CpuAddressWidth = (UINT8) (RegEax & 0xFF); } DEBUG ((EFI_D_INFO, "CpuAddressWidth: %d\n", CpuAddressWidth)); BuildCpuHob (CpuAddressWidth, 16); ASSERT_EFI_ERROR (Status); return Status; }