1 /** @file 2 This file includes a memory call back function notified when MRC is done, 3 following action is performed in this file, 4 1. ICH initialization after MRC. 5 2. SIO initialization. 6 3. Install ResetSystem and FinvFv PPI. 7 4. Set MTRR for PEI 8 5. Create FV HOB and Flash HOB 9 10 Copyright (c) 2013 - 2016, Intel Corporation. 11 12 This program and the accompanying materials 13 are licensed and made available under the terms and conditions of the BSD License 14 which accompanies this distribution. The full text of the license may be found at 15 http://opensource.org/licenses/bsd-license.php 16 17 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 18 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. 19 20 **/ 21 22 23 #include "CommonHeader.h" 24 25 #include "PlatformEarlyInit.h" 26 27 extern EFI_PEI_PPI_DESCRIPTOR mPpiStall[]; 28 29 EFI_PEI_RESET_PPI mResetPpi = { ResetSystem }; 30 31 EFI_PEI_PPI_DESCRIPTOR mPpiList[1] = { 32 { 33 (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST), 34 &gEfiPeiResetPpiGuid, 35 &mResetPpi 36 } 37 }; 38 39 /** 40 This function reset the entire platform, including all processor and devices, and 41 reboots the system. 42 43 @param PeiServices General purpose services available to every PEIM. 44 45 @retval EFI_SUCCESS if it completed successfully. 46 **/ 47 EFI_STATUS 48 EFIAPI 49 ResetSystem ( 50 IN CONST EFI_PEI_SERVICES **PeiServices 51 ) 52 { 53 ResetCold(); 54 return EFI_SUCCESS; 55 } 56 57 /** 58 This function provides a blocking stall for reset at least the given number of microseconds 59 stipulated in the final argument. 60 61 @param PeiServices General purpose services available to every PEIM. 62 63 @param this Pointer to the local data for the interface. 64 65 @param Microseconds number of microseconds for which to stall. 66 67 @retval EFI_SUCCESS the function provided at least the required stall. 68 **/ 69 EFI_STATUS 70 EFIAPI 71 Stall ( 72 IN CONST EFI_PEI_SERVICES **PeiServices, 73 IN CONST EFI_PEI_STALL_PPI *This, 74 IN UINTN Microseconds 75 ) 76 { 77 MicroSecondDelay (Microseconds); 78 return EFI_SUCCESS; 79 } 80 81 82 /** 83 This function will be called when MRC is done. 84 85 @param PeiServices General purpose services available to every PEIM. 86 87 @param NotifyDescriptor Information about the notify event.. 88 89 @param Ppi The notify context. 90 91 @retval EFI_SUCCESS If the function completed successfully. 92 **/ 93 EFI_STATUS 94 EFIAPI 95 MemoryDiscoveredPpiNotifyCallback ( 96 IN EFI_PEI_SERVICES **PeiServices, 97 IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor, 98 IN VOID *Ppi 99 ) 100 { 101 EFI_STATUS Status; 102 EFI_BOOT_MODE BootMode; 103 UINT64 MemoryLength; 104 EFI_SMRAM_DESCRIPTOR *SmramDescriptor; 105 UINTN NumSmramRegions; 106 UINT32 RmuMainBaseAddress; 107 UINT32 RegData32; 108 UINT8 CpuAddressWidth; 109 UINT32 RegEax; 110 MTRR_SETTINGS MtrrSettings; 111 EFI_PEI_READ_ONLY_VARIABLE2_PPI *VariableServices; 112 UINT8 MorControl; 113 UINTN DataSize; 114 115 DEBUG ((EFI_D_INFO, "Platform PEIM Memory Callback\n")); 116 117 NumSmramRegions = 0; 118 SmramDescriptor = NULL; 119 RmuMainBaseAddress = 0; 120 121 PERF_START (NULL, "SetCache", NULL, 0); 122 123 InfoPostInstallMemory (&RmuMainBaseAddress, &SmramDescriptor, &NumSmramRegions); 124 ASSERT (SmramDescriptor != NULL); 125 ASSERT (RmuMainBaseAddress != 0); 126 127 MemoryLength = ((UINT64) RmuMainBaseAddress) + 0x10000; 128 129 Status = PeiServicesGetBootMode (&BootMode); 130 ASSERT_EFI_ERROR (Status); 131 132 // 133 // Get current MTRR settings 134 // 135 MtrrGetAllMtrrs (&MtrrSettings); 136 137 // 138 // Set all DRAM cachability to CacheWriteBack 139 // 140 Status = MtrrSetMemoryAttributeInMtrrSettings (&MtrrSettings, 0, MemoryLength, CacheWriteBack); 141 ASSERT_EFI_ERROR (Status); 142 143 // 144 // RTC:28208 - System hang/crash when entering probe mode(ITP) when relocating SMBASE 145 // Workaround to make default SMRAM UnCachable 146 // 147 Status = MtrrSetMemoryAttributeInMtrrSettings (&MtrrSettings, 0x30000, SIZE_64KB, CacheUncacheable); 148 ASSERT_EFI_ERROR (Status); 149 150 // 151 // Set new MTRR settings 152 // 153 MtrrSetAllMtrrs (&MtrrSettings); 154 155 PERF_END (NULL, "SetCache", NULL, 0); 156 157 // 158 // Get necessary PPI 159 // 160 Status = PeiServicesLocatePpi ( 161 &gEfiPeiReadOnlyVariable2PpiGuid, // GUID 162 0, // INSTANCE 163 NULL, // EFI_PEI_PPI_DESCRIPTOR 164 (VOID **)&VariableServices // PPI 165 ); 166 ASSERT_EFI_ERROR (Status); 167 168 // 169 // Detect MOR request by the OS. 170 // 171 MorControl = 0; 172 DataSize = sizeof (MorControl); 173 Status = VariableServices->GetVariable ( 174 VariableServices, 175 MEMORY_OVERWRITE_REQUEST_VARIABLE_NAME, 176 &gEfiMemoryOverwriteControlDataGuid, 177 NULL, 178 &DataSize, 179 &MorControl 180 ); 181 // 182 // If OS requested a memory overwrite perform it now for Embedded SRAM 183 // 184 if (MOR_CLEAR_MEMORY_VALUE (MorControl)) { 185 DEBUG ((EFI_D_INFO, "Clear Embedded SRAM per MOR request.\n")); 186 if (PcdGet32 (PcdESramMemorySize) > 0) { 187 if (PcdGet32 (PcdEsramStage1Base) == 0) { 188 // 189 // ZeroMem() generates an ASSERT() if Buffer parameter is NULL. 190 // Clear byte at 0 and start clear operation at address 1. 191 // 192 *(UINT8 *)(0) = 0; 193 ZeroMem ((VOID *)1, (UINTN)PcdGet32 (PcdESramMemorySize) - 1); 194 } else { 195 ZeroMem ( 196 (VOID *)(UINTN)PcdGet32 (PcdEsramStage1Base), 197 (UINTN)PcdGet32 (PcdESramMemorySize) 198 ); 199 } 200 } 201 } 202 203 // 204 // Install PeiReset for PeiResetSystem service 205 // 206 Status = PeiServicesInstallPpi (&mPpiList[0]); 207 ASSERT_EFI_ERROR (Status); 208 209 // 210 // Do QNC initialization after MRC 211 // 212 PeiQNCPostMemInit (); 213 214 Status = PeiServicesInstallPpi (&mPpiStall[0]); 215 ASSERT_EFI_ERROR (Status); 216 217 // 218 // Set E000/F000 Routing 219 // 220 RegData32 = QNCPortRead (QUARK_NC_HOST_BRIDGE_SB_PORT_ID, QNC_MSG_FSBIC_REG_HMISC); 221 RegData32 |= (BIT2|BIT1); 222 QNCPortWrite (QUARK_NC_HOST_BRIDGE_SB_PORT_ID, QNC_MSG_FSBIC_REG_HMISC, RegData32); 223 224 if (BootMode == BOOT_IN_RECOVERY_MODE) { 225 // Do nothing here. A generic RecoveryModule will handle it. 226 } else if (BootMode == BOOT_ON_S3_RESUME) { 227 return EFI_SUCCESS; 228 } else { 229 PeiServicesInstallFvInfoPpi ( 230 NULL, 231 (VOID *) (UINTN) PcdGet32 (PcdFlashFvMainBase), 232 PcdGet32 (PcdFlashFvMainSize), 233 NULL, 234 NULL 235 ); 236 237 // 238 // Publish the FVMAIN FV so the DXE Phase can dispatch drivers from this FV 239 // and produce Load File Protocols for UEFI Applications in this FV. 240 // 241 BuildFvHob ( 242 PcdGet32 (PcdFlashFvMainBase), 243 PcdGet32 (PcdFlashFvMainSize) 244 ); 245 246 // 247 // Publish the Payload FV so the DXE Phase can dispatch drivers from this FV 248 // and produce Load File Protocols for UEFI Applications in this FV. 249 // 250 BuildFvHob ( 251 PcdGet32 (PcdFlashFvPayloadBase), 252 PcdGet32 (PcdFlashFvPayloadSize) 253 ); 254 } 255 256 // 257 // Build flash HOB, it's going to be used by GCD and E820 building 258 // Map full SPI flash decode range (regardless of smaller SPI flash parts installed) 259 // 260 BuildResourceDescriptorHob ( 261 EFI_RESOURCE_FIRMWARE_DEVICE, 262 (EFI_RESOURCE_ATTRIBUTE_PRESENT | 263 EFI_RESOURCE_ATTRIBUTE_INITIALIZED | 264 EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE), 265 (SIZE_4GB - SIZE_8MB), 266 SIZE_8MB 267 ); 268 269 // 270 // Create a CPU hand-off information 271 // 272 CpuAddressWidth = 32; 273 AsmCpuid (CPUID_EXTENDED_FUNCTION, &RegEax, NULL, NULL, NULL); 274 if (RegEax >= CPUID_VIR_PHY_ADDRESS_SIZE) { 275 AsmCpuid (CPUID_VIR_PHY_ADDRESS_SIZE, &RegEax, NULL, NULL, NULL); 276 CpuAddressWidth = (UINT8) (RegEax & 0xFF); 277 } 278 DEBUG ((EFI_D_INFO, "CpuAddressWidth: %d\n", CpuAddressWidth)); 279 280 BuildCpuHob (CpuAddressWidth, 16); 281 282 ASSERT_EFI_ERROR (Status); 283 284 return Status; 285 } 286