MemoryPeim.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397
  1. /** @file
  2. Copyright (c) 2004 - 2019, Intel Corporation. All rights reserved.<BR>
  3. SPDX-License-Identifier: BSD-2-Clause-Patent
  4. Module Name:
  5. MemoryPeim.c
  6. Abstract:
  7. Tiano PEIM to provide the platform support functionality.
  8. This file implements the Platform Memory Range PPI
  9. --*/
  10. #include "PlatformEarlyInit.h"
  11. //
  12. // Need min. of 48MB PEI phase
  13. //
  14. #define PEI_MIN_MEMORY_SIZE (6 * 0x800000)
  15. #define PEI_RECOVERY_MIN_MEMORY_SIZE (6 * 0x800000)
  16. //
  17. // This is the memory needed for PEI to start up DXE.
  18. //
  19. // Over-estimating this size will lead to higher fragmentation
  20. // of main memory. Under-estimation of this will cause catastrophic
  21. // failure of PEI to load DXE. Generally, the failure may only be
  22. // realized during capsule updates.
  23. //
  24. #define PRERESERVED_PEI_MEMORY ( \
  25. EFI_SIZE_TO_PAGES (3 * 0x800000) /* PEI Core memory based stack */ \
  26. )
  27. EFI_MEMORY_TYPE_INFORMATION mDefaultMemoryTypeInformation[] = {
  28. { EfiACPIReclaimMemory, 0x40 }, // 0x40 pages = 256k for ASL
  29. { EfiACPIMemoryNVS, 0x40 }, // 0x40 pages = 256k MB for S3, SMM, HII, etc
  30. { EfiReservedMemoryType, 0x80 }, // 512k for BIOS Reserved
  31. { EfiRuntimeServicesCode, 0x100 },
  32. { EfiRuntimeServicesData, 0x100 },
  33. { EfiMaxMemoryType, 0 }
  34. };
  35. STATIC
  36. EFI_STATUS
  37. GetMemorySize (
  38. IN CONST EFI_PEI_SERVICES **PeiServices,
  39. OUT UINT64 *LowMemoryLength,
  40. OUT UINT64 *HighMemoryLength
  41. );
  42. /**
  43. Initializes the valid address mask for MTRRs.
  44. This function initializes the valid bits mask and valid address mask for MTRRs.
  45. **/
  46. UINT64
  47. InitializeAddressMtrrMask (
  48. VOID
  49. )
  50. {
  51. UINT32 RegEax;
  52. UINT8 PhysicalAddressBits;
  53. UINT64 ValidMtrrBitsMask;
  54. AsmCpuid (0x80000000, &RegEax, NULL, NULL, NULL);
  55. if (RegEax >= 0x80000008) {
  56. AsmCpuid (0x80000008, &RegEax, NULL, NULL, NULL);
  57. PhysicalAddressBits = (UINT8) RegEax;
  58. } else {
  59. PhysicalAddressBits = 36;
  60. }
  61. ValidMtrrBitsMask = LShiftU64 (1, PhysicalAddressBits) - 1;
  62. return (ValidMtrrBitsMask & 0xfffffffffffff000ULL);
  63. }
  64. EFI_STATUS
  65. EFIAPI
  66. SetPeiCacheMode (
  67. IN CONST EFI_PEI_SERVICES **PeiServices
  68. )
  69. {
  70. EFI_STATUS Status;
  71. PEI_CACHE_PPI *CachePpi;
  72. EFI_BOOT_MODE BootMode;
  73. UINT64 MemoryLength;
  74. UINT64 MemOverflow;
  75. UINT64 MemoryLengthUc;
  76. UINT64 MaxMemoryLength;
  77. UINT64 LowMemoryLength;
  78. UINT64 HighMemoryLength;
  79. UINT8 Index;
  80. MTRR_SETTINGS MtrrSetting;
  81. UINT64 ValidMtrrAddressMask;
  82. //
  83. // Load Cache PPI
  84. //
  85. Status = (**PeiServices).LocatePpi (
  86. PeiServices,
  87. &gPeiCachePpiGuid, // GUID
  88. 0, // Instance
  89. NULL, // EFI_PEI_PPI_DESCRIPTOR
  90. (void **)&CachePpi // PPI
  91. );
  92. if (!EFI_ERROR(Status)) {
  93. //
  94. // Clear the CAR Settings (Default Cache Type => UC)
  95. //
  96. DEBUG ((EFI_D_INFO, "Reset cache attribute and disable CAR. \n"));
  97. CachePpi->ResetCache(
  98. (EFI_PEI_SERVICES**)PeiServices,
  99. CachePpi
  100. );
  101. }
  102. //
  103. // Variable initialization
  104. //
  105. LowMemoryLength = 0;
  106. HighMemoryLength = 0;
  107. MemoryLengthUc = 0;
  108. Status = (*PeiServices)->GetBootMode (
  109. PeiServices,
  110. &BootMode
  111. );
  112. ValidMtrrAddressMask = InitializeAddressMtrrMask ();
  113. //
  114. // Determine memory usage
  115. //
  116. GetMemorySize (
  117. PeiServices,
  118. &LowMemoryLength,
  119. &HighMemoryLength
  120. );
  121. LowMemoryLength = (EFI_PHYSICAL_ADDRESS)MmPci32( 0, 0, 2, 0, 0x70);
  122. LowMemoryLength &= 0xFFF00000ULL;
  123. MaxMemoryLength = LowMemoryLength;
  124. //
  125. // Round up to nearest 256MB with high memory and 64MB w/o high memory
  126. //
  127. if (HighMemoryLength != 0 ) {
  128. MemOverflow = (LowMemoryLength & 0x0fffffff);
  129. if (MemOverflow != 0) {
  130. MaxMemoryLength = LowMemoryLength + (0x10000000 - MemOverflow);
  131. }
  132. } else {
  133. MemOverflow = (LowMemoryLength & 0x03ffffff);
  134. if (MemOverflow != 0) {
  135. MaxMemoryLength = LowMemoryLength + (0x4000000 - MemOverflow);
  136. }
  137. }
  138. ZeroMem (&MtrrSetting, sizeof(MTRR_SETTINGS));
  139. for (Index = 0; Index < 2; Index++) {
  140. MtrrSetting.Fixed.Mtrr[Index]=0x0606060606060606;
  141. }
  142. for (Index = 2; Index < 11; Index++) {
  143. MtrrSetting.Fixed.Mtrr[Index]=0x0505050505050505;
  144. }
  145. //
  146. // Cache the flash area to improve the boot performance in PEI phase
  147. //
  148. Index = 0;
  149. ((MSR_IA32_MTRR_PHYSBASE_REGISTER *) &MtrrSetting.Variables.Mtrr[0].Base)->Uint64 = FixedPcdGet32 (PcdFlashAreaBaseAddress);
  150. ((MSR_IA32_MTRR_PHYSBASE_REGISTER *) &MtrrSetting.Variables.Mtrr[0].Base)->Bits.Type = CacheWriteProtected;
  151. ((MSR_IA32_MTRR_PHYSMASK_REGISTER *) &MtrrSetting.Variables.Mtrr[0].Mask)->Uint64 = (~((UINT64)(FixedPcdGet32 (PcdFlashAreaSize) - 1))) & ValidMtrrAddressMask;
  152. ((MSR_IA32_MTRR_PHYSMASK_REGISTER *) &MtrrSetting.Variables.Mtrr[0].Mask)->Bits.V = 1;
  153. Index ++;
  154. MemOverflow =0;
  155. while (MaxMemoryLength > MemOverflow){
  156. MemoryLength = MaxMemoryLength - MemOverflow;
  157. MemoryLength = GetPowerOfTwo64 (MemoryLength);
  158. ((MSR_IA32_MTRR_PHYSBASE_REGISTER *) &MtrrSetting.Variables.Mtrr[Index].Base)->Uint64 = MemOverflow & ValidMtrrAddressMask;
  159. ((MSR_IA32_MTRR_PHYSBASE_REGISTER *) &MtrrSetting.Variables.Mtrr[Index].Base)->Bits.Type = CacheWriteBack;
  160. ((MSR_IA32_MTRR_PHYSMASK_REGISTER *) &MtrrSetting.Variables.Mtrr[Index].Mask)->Uint64 = (~(MemoryLength - 1)) & ValidMtrrAddressMask;
  161. ((MSR_IA32_MTRR_PHYSMASK_REGISTER *) &MtrrSetting.Variables.Mtrr[Index].Mask)->Bits.V = 1;
  162. MemOverflow += MemoryLength;
  163. Index++;
  164. }
  165. MemoryLength = LowMemoryLength;
  166. while (MaxMemoryLength != MemoryLength) {
  167. MemoryLengthUc = GetPowerOfTwo64 (MaxMemoryLength - MemoryLength);
  168. ((MSR_IA32_MTRR_PHYSBASE_REGISTER *) &MtrrSetting.Variables.Mtrr[Index].Base)->Uint64 = (MaxMemoryLength - MemoryLengthUc) & ValidMtrrAddressMask;
  169. ((MSR_IA32_MTRR_PHYSBASE_REGISTER *) &MtrrSetting.Variables.Mtrr[Index].Base)->Bits.Type = CacheUncacheable;
  170. ((MSR_IA32_MTRR_PHYSMASK_REGISTER *) &MtrrSetting.Variables.Mtrr[Index].Mask)->Uint64 = (~(MemoryLengthUc - 1)) & ValidMtrrAddressMask;
  171. ((MSR_IA32_MTRR_PHYSMASK_REGISTER *) &MtrrSetting.Variables.Mtrr[Index].Mask)->Bits.V = 1;
  172. MaxMemoryLength -= MemoryLengthUc;
  173. Index++;
  174. }
  175. MemOverflow =0x100000000;
  176. while (HighMemoryLength > 0) {
  177. MemoryLength = HighMemoryLength;
  178. MemoryLength = GetPowerOfTwo64 (MemoryLength);
  179. if (MemoryLength > MemOverflow){
  180. MemoryLength = MemOverflow;
  181. }
  182. ((MSR_IA32_MTRR_PHYSBASE_REGISTER *) &MtrrSetting.Variables.Mtrr[Index].Base)->Uint64 = MemOverflow & ValidMtrrAddressMask;
  183. ((MSR_IA32_MTRR_PHYSBASE_REGISTER *) &MtrrSetting.Variables.Mtrr[Index].Base)->Bits.Type = CacheWriteBack;
  184. ((MSR_IA32_MTRR_PHYSMASK_REGISTER *) &MtrrSetting.Variables.Mtrr[Index].Mask)->Uint64 = (~(MemoryLength - 1)) & ValidMtrrAddressMask;
  185. ((MSR_IA32_MTRR_PHYSMASK_REGISTER *) &MtrrSetting.Variables.Mtrr[Index].Mask)->Bits.V = 1;
  186. MemOverflow += MemoryLength;
  187. HighMemoryLength -= MemoryLength;
  188. Index++;
  189. }
  190. for (Index = 0; Index < MTRR_NUMBER_OF_VARIABLE_MTRR; Index++) {
  191. if (MtrrSetting.Variables.Mtrr[Index].Base == 0){
  192. break;
  193. }
  194. DEBUG ((EFI_D_INFO, "Base=%lx, Mask=%lx\n",MtrrSetting.Variables.Mtrr[Index].Base ,MtrrSetting.Variables.Mtrr[Index].Mask));
  195. }
  196. //
  197. // set FE/E bits for IA32_MTRR_DEF_TYPE
  198. //
  199. MtrrSetting.MtrrDefType |= 3 <<10;
  200. MtrrSetAllMtrrs(&MtrrSetting);
  201. //
  202. // Dump MTRR Setting
  203. //
  204. MtrrDebugPrintAllMtrrs ();
  205. return EFI_SUCCESS;
  206. }
  207. EFI_STATUS
  208. EFIAPI
  209. SetDxeCacheMode (
  210. IN CONST EFI_PEI_SERVICES **PeiServices
  211. )
  212. {
  213. //
  214. // This is not needed for now.
  215. //
  216. return EFI_SUCCESS;
  217. }
  218. STATIC
  219. EFI_STATUS
  220. GetMemorySize (
  221. IN CONST EFI_PEI_SERVICES **PeiServices,
  222. OUT UINT64 *LowMemoryLength,
  223. OUT UINT64 *HighMemoryLength
  224. )
  225. {
  226. EFI_STATUS Status;
  227. EFI_PEI_HOB_POINTERS Hob;
  228. *HighMemoryLength = 0;
  229. *LowMemoryLength = 0x100000;
  230. //
  231. // Get the HOB list for processing
  232. //
  233. Status = (*PeiServices)->GetHobList (PeiServices, (void **)&Hob.Raw);
  234. if (EFI_ERROR(Status)) {
  235. return Status;
  236. }
  237. //
  238. // Collect memory ranges
  239. //
  240. while (!END_OF_HOB_LIST (Hob)) {
  241. if (Hob.Header->HobType == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) {
  242. if (Hob.ResourceDescriptor->ResourceType == EFI_RESOURCE_SYSTEM_MEMORY) {
  243. //
  244. // Need memory above 1MB to be collected here
  245. //
  246. if (Hob.ResourceDescriptor->PhysicalStart >= 0x100000 &&
  247. Hob.ResourceDescriptor->PhysicalStart < (EFI_PHYSICAL_ADDRESS) 0x100000000) {
  248. *LowMemoryLength += (UINT64) (Hob.ResourceDescriptor->ResourceLength);
  249. } else if (Hob.ResourceDescriptor->PhysicalStart >= (EFI_PHYSICAL_ADDRESS) 0x100000000) {
  250. *HighMemoryLength += (UINT64) (Hob.ResourceDescriptor->ResourceLength);
  251. }
  252. }
  253. }
  254. Hob.Raw = GET_NEXT_HOB (Hob);
  255. }
  256. return EFI_SUCCESS;
  257. }
  258. /**
  259. Publish Memory Type Information.
  260. @param NULL
  261. @retval EFI_SUCCESS Success.
  262. @retval Others Errors have occurred.
  263. **/
  264. EFI_STATUS
  265. EFIAPI
  266. PublishMemoryTypeInfo (
  267. void
  268. )
  269. {
  270. EFI_STATUS Status;
  271. EFI_PEI_READ_ONLY_VARIABLE2_PPI *Variable;
  272. UINTN DataSize;
  273. EFI_MEMORY_TYPE_INFORMATION MemoryData[EfiMaxMemoryType + 1];
  274. Status = PeiServicesLocatePpi (
  275. &gEfiPeiReadOnlyVariable2PpiGuid,
  276. 0,
  277. NULL,
  278. (void **)&Variable
  279. );
  280. if (EFI_ERROR(Status)) {
  281. DEBUG((EFI_D_ERROR, "WARNING: Locating Pei variable failed 0x%x \n", Status));
  282. DEBUG((EFI_D_ERROR, "Build Hob from default\n"));
  283. //
  284. // Build the default GUID'd HOB for DXE
  285. //
  286. BuildGuidDataHob (
  287. &gEfiMemoryTypeInformationGuid,
  288. mDefaultMemoryTypeInformation,
  289. sizeof (mDefaultMemoryTypeInformation)
  290. );
  291. return Status;
  292. }
  293. DataSize = sizeof (MemoryData);
  294. //
  295. // This variable is saved in BDS stage. Now read it back
  296. //
  297. Status = Variable->GetVariable (
  298. Variable,
  299. EFI_MEMORY_TYPE_INFORMATION_VARIABLE_NAME,
  300. &gEfiMemoryTypeInformationGuid,
  301. NULL,
  302. &DataSize,
  303. &MemoryData
  304. );
  305. if (EFI_ERROR (Status)) {
  306. //
  307. //build default
  308. //
  309. DEBUG((EFI_D_ERROR, "Build Hob from default\n"));
  310. BuildGuidDataHob (
  311. &gEfiMemoryTypeInformationGuid,
  312. mDefaultMemoryTypeInformation,
  313. sizeof (mDefaultMemoryTypeInformation)
  314. );
  315. } else {
  316. //
  317. // Build the GUID'd HOB for DXE from variable
  318. //
  319. DEBUG((EFI_D_ERROR, "Build Hob from variable \n"));
  320. BuildGuidDataHob (
  321. &gEfiMemoryTypeInformationGuid,
  322. MemoryData,
  323. DataSize
  324. );
  325. }
  326. return Status;
  327. }