Page.c 69 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190
  1. /** @file
  2. UEFI Memory page management functions.
  3. Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>
  4. SPDX-License-Identifier: BSD-2-Clause-Patent
  5. **/
  6. #include "DxeMain.h"
  7. #include "Imem.h"
  8. #include "HeapGuard.h"
  9. #include <Pi/PrePiDxeCis.h>
  10. //
  11. // Entry for tracking the memory regions for each memory type to coalesce similar memory types
  12. //
  13. typedef struct {
  14. EFI_PHYSICAL_ADDRESS BaseAddress;
  15. EFI_PHYSICAL_ADDRESS MaximumAddress;
  16. UINT64 CurrentNumberOfPages;
  17. UINT64 NumberOfPages;
  18. UINTN InformationIndex;
  19. BOOLEAN Special;
  20. BOOLEAN Runtime;
  21. } EFI_MEMORY_TYPE_STATISTICS;
  22. //
  23. // MemoryMap - The current memory map
  24. //
  25. UINTN mMemoryMapKey = 0;
  26. #define MAX_MAP_DEPTH 6
  27. ///
  28. /// mMapDepth - depth of new descriptor stack
  29. ///
  30. UINTN mMapDepth = 0;
  31. ///
  32. /// mMapStack - space to use as temp storage to build new map descriptors
  33. ///
  34. MEMORY_MAP mMapStack[MAX_MAP_DEPTH];
  35. UINTN mFreeMapStack = 0;
  36. ///
  37. /// This list maintain the free memory map list
  38. ///
  39. LIST_ENTRY mFreeMemoryMapEntryList = INITIALIZE_LIST_HEAD_VARIABLE (mFreeMemoryMapEntryList);
  40. BOOLEAN mMemoryTypeInformationInitialized = FALSE;
  41. EFI_MEMORY_TYPE_STATISTICS mMemoryTypeStatistics[EfiMaxMemoryType + 1] = {
  42. { 0, MAX_ALLOC_ADDRESS, 0, 0, EfiMaxMemoryType, TRUE, FALSE }, // EfiReservedMemoryType
  43. { 0, MAX_ALLOC_ADDRESS, 0, 0, EfiMaxMemoryType, FALSE, FALSE }, // EfiLoaderCode
  44. { 0, MAX_ALLOC_ADDRESS, 0, 0, EfiMaxMemoryType, FALSE, FALSE }, // EfiLoaderData
  45. { 0, MAX_ALLOC_ADDRESS, 0, 0, EfiMaxMemoryType, FALSE, FALSE }, // EfiBootServicesCode
  46. { 0, MAX_ALLOC_ADDRESS, 0, 0, EfiMaxMemoryType, FALSE, FALSE }, // EfiBootServicesData
  47. { 0, MAX_ALLOC_ADDRESS, 0, 0, EfiMaxMemoryType, TRUE, TRUE }, // EfiRuntimeServicesCode
  48. { 0, MAX_ALLOC_ADDRESS, 0, 0, EfiMaxMemoryType, TRUE, TRUE }, // EfiRuntimeServicesData
  49. { 0, MAX_ALLOC_ADDRESS, 0, 0, EfiMaxMemoryType, FALSE, FALSE }, // EfiConventionalMemory
  50. { 0, MAX_ALLOC_ADDRESS, 0, 0, EfiMaxMemoryType, FALSE, FALSE }, // EfiUnusableMemory
  51. { 0, MAX_ALLOC_ADDRESS, 0, 0, EfiMaxMemoryType, TRUE, FALSE }, // EfiACPIReclaimMemory
  52. { 0, MAX_ALLOC_ADDRESS, 0, 0, EfiMaxMemoryType, TRUE, FALSE }, // EfiACPIMemoryNVS
  53. { 0, MAX_ALLOC_ADDRESS, 0, 0, EfiMaxMemoryType, FALSE, FALSE }, // EfiMemoryMappedIO
  54. { 0, MAX_ALLOC_ADDRESS, 0, 0, EfiMaxMemoryType, FALSE, FALSE }, // EfiMemoryMappedIOPortSpace
  55. { 0, MAX_ALLOC_ADDRESS, 0, 0, EfiMaxMemoryType, TRUE, TRUE }, // EfiPalCode
  56. { 0, MAX_ALLOC_ADDRESS, 0, 0, EfiMaxMemoryType, FALSE, FALSE }, // EfiPersistentMemory
  57. { 0, MAX_ALLOC_ADDRESS, 0, 0, EfiMaxMemoryType, TRUE, FALSE }, // EfiUnacceptedMemoryType
  58. { 0, MAX_ALLOC_ADDRESS, 0, 0, EfiMaxMemoryType, FALSE, FALSE } // EfiMaxMemoryType
  59. };
  60. EFI_PHYSICAL_ADDRESS mDefaultMaximumAddress = MAX_ALLOC_ADDRESS;
  61. EFI_PHYSICAL_ADDRESS mDefaultBaseAddress = MAX_ALLOC_ADDRESS;
  62. EFI_MEMORY_TYPE_INFORMATION gMemoryTypeInformation[EfiMaxMemoryType + 1] = {
  63. { EfiReservedMemoryType, 0 },
  64. { EfiLoaderCode, 0 },
  65. { EfiLoaderData, 0 },
  66. { EfiBootServicesCode, 0 },
  67. { EfiBootServicesData, 0 },
  68. { EfiRuntimeServicesCode, 0 },
  69. { EfiRuntimeServicesData, 0 },
  70. { EfiConventionalMemory, 0 },
  71. { EfiUnusableMemory, 0 },
  72. { EfiACPIReclaimMemory, 0 },
  73. { EfiACPIMemoryNVS, 0 },
  74. { EfiMemoryMappedIO, 0 },
  75. { EfiMemoryMappedIOPortSpace, 0 },
  76. { EfiPalCode, 0 },
  77. { EfiPersistentMemory, 0 },
  78. { EFI_GCD_MEMORY_TYPE_UNACCEPTED, 0 },
  79. { EfiMaxMemoryType, 0 }
  80. };
  81. //
  82. // Only used when load module at fixed address feature is enabled. True means the memory is alreay successfully allocated
  83. // and ready to load the module in to specified address.or else, the memory is not ready and module will be loaded at a
  84. // address assigned by DXE core.
  85. //
  86. GLOBAL_REMOVE_IF_UNREFERENCED BOOLEAN gLoadFixedAddressCodeMemoryReady = FALSE;
  87. /**
  88. Enter critical section by gaining lock on gMemoryLock.
  89. **/
  90. VOID
  91. CoreAcquireMemoryLock (
  92. VOID
  93. )
  94. {
  95. CoreAcquireLock (&gMemoryLock);
  96. }
  97. /**
  98. Exit critical section by releasing lock on gMemoryLock.
  99. **/
  100. VOID
  101. CoreReleaseMemoryLock (
  102. VOID
  103. )
  104. {
  105. CoreReleaseLock (&gMemoryLock);
  106. }
  107. /**
  108. Internal function. Removes a descriptor entry.
  109. @param Entry The entry to remove
  110. **/
  111. VOID
  112. RemoveMemoryMapEntry (
  113. IN OUT MEMORY_MAP *Entry
  114. )
  115. {
  116. RemoveEntryList (&Entry->Link);
  117. Entry->Link.ForwardLink = NULL;
  118. if (Entry->FromPages) {
  119. //
  120. // Insert the free memory map descriptor to the end of mFreeMemoryMapEntryList
  121. //
  122. InsertTailList (&mFreeMemoryMapEntryList, &Entry->Link);
  123. }
  124. }
  125. /**
  126. Internal function. Adds a ranges to the memory map.
  127. The range must not already exist in the map.
  128. @param Type The type of memory range to add
  129. @param Start The starting address in the memory range Must be
  130. paged aligned
  131. @param End The last address in the range Must be the last
  132. byte of a page
  133. @param Attribute The attributes of the memory range to add
  134. **/
  135. VOID
  136. CoreAddRange (
  137. IN EFI_MEMORY_TYPE Type,
  138. IN EFI_PHYSICAL_ADDRESS Start,
  139. IN EFI_PHYSICAL_ADDRESS End,
  140. IN UINT64 Attribute
  141. )
  142. {
  143. LIST_ENTRY *Link;
  144. MEMORY_MAP *Entry;
  145. ASSERT ((Start & EFI_PAGE_MASK) == 0);
  146. ASSERT (End > Start);
  147. ASSERT_LOCKED (&gMemoryLock);
  148. DEBUG ((DEBUG_PAGE, "AddRange: %lx-%lx to %d\n", Start, End, Type));
  149. //
  150. // If memory of type EfiConventionalMemory is being added that includes the page
  151. // starting at address 0, then zero the page starting at address 0. This has
  152. // two benifits. It helps find NULL pointer bugs and it also maximizes
  153. // compatibility with operating systems that may evaluate memory in this page
  154. // for legacy data structures. If memory of any other type is added starting
  155. // at address 0, then do not zero the page at address 0 because the page is being
  156. // used for other purposes.
  157. //
  158. if ((Type == EfiConventionalMemory) && (Start == 0) && (End >= EFI_PAGE_SIZE - 1)) {
  159. if ((PcdGet8 (PcdNullPointerDetectionPropertyMask) & BIT0) == 0) {
  160. SetMem ((VOID *)(UINTN)Start, EFI_PAGE_SIZE, 0);
  161. }
  162. }
  163. //
  164. // Memory map being altered so updated key
  165. //
  166. mMemoryMapKey += 1;
  167. //
  168. // UEFI 2.0 added an event group for notificaiton on memory map changes.
  169. // So we need to signal this Event Group every time the memory map changes.
  170. // If we are in EFI 1.10 compatability mode no event groups will be
  171. // found and nothing will happen we we call this function. These events
  172. // will get signaled but since a lock is held around the call to this
  173. // function the notificaiton events will only be called after this function
  174. // returns and the lock is released.
  175. //
  176. CoreNotifySignalList (&gEfiEventMemoryMapChangeGuid);
  177. //
  178. // Look for adjoining memory descriptor
  179. //
  180. // Two memory descriptors can only be merged if they have the same Type
  181. // and the same Attribute
  182. //
  183. Link = gMemoryMap.ForwardLink;
  184. while (Link != &gMemoryMap) {
  185. Entry = CR (Link, MEMORY_MAP, Link, MEMORY_MAP_SIGNATURE);
  186. Link = Link->ForwardLink;
  187. if (Entry->Type != Type) {
  188. continue;
  189. }
  190. if (Entry->Attribute != Attribute) {
  191. continue;
  192. }
  193. if (Entry->End + 1 == Start) {
  194. Start = Entry->Start;
  195. RemoveMemoryMapEntry (Entry);
  196. } else if (Entry->Start == End + 1) {
  197. End = Entry->End;
  198. RemoveMemoryMapEntry (Entry);
  199. }
  200. }
  201. //
  202. // Add descriptor
  203. //
  204. mMapStack[mMapDepth].Signature = MEMORY_MAP_SIGNATURE;
  205. mMapStack[mMapDepth].FromPages = FALSE;
  206. mMapStack[mMapDepth].Type = Type;
  207. mMapStack[mMapDepth].Start = Start;
  208. mMapStack[mMapDepth].End = End;
  209. mMapStack[mMapDepth].VirtualStart = 0;
  210. mMapStack[mMapDepth].Attribute = Attribute;
  211. InsertTailList (&gMemoryMap, &mMapStack[mMapDepth].Link);
  212. mMapDepth += 1;
  213. ASSERT (mMapDepth < MAX_MAP_DEPTH);
  214. return;
  215. }
  216. /**
  217. Internal function. Deque a descriptor entry from the mFreeMemoryMapEntryList.
  218. If the list is emtry, then allocate a new page to refuel the list.
  219. Please Note this algorithm to allocate the memory map descriptor has a property
  220. that the memory allocated for memory entries always grows, and will never really be freed
  221. For example, if the current boot uses 2000 memory map entries at the maximum point, but
  222. ends up with only 50 at the time the OS is booted, then the memory associated with the 1950
  223. memory map entries is still allocated from EfiBootServicesMemory.
  224. @return The Memory map descriptor dequed from the mFreeMemoryMapEntryList
  225. **/
  226. MEMORY_MAP *
  227. AllocateMemoryMapEntry (
  228. VOID
  229. )
  230. {
  231. MEMORY_MAP *FreeDescriptorEntries;
  232. MEMORY_MAP *Entry;
  233. UINTN Index;
  234. if (IsListEmpty (&mFreeMemoryMapEntryList)) {
  235. //
  236. // The list is empty, to allocate one page to refuel the list
  237. //
  238. FreeDescriptorEntries = CoreAllocatePoolPages (
  239. EfiBootServicesData,
  240. EFI_SIZE_TO_PAGES (DEFAULT_PAGE_ALLOCATION_GRANULARITY),
  241. DEFAULT_PAGE_ALLOCATION_GRANULARITY,
  242. FALSE
  243. );
  244. if (FreeDescriptorEntries != NULL) {
  245. //
  246. // Enque the free memmory map entries into the list
  247. //
  248. for (Index = 0; Index < DEFAULT_PAGE_ALLOCATION_GRANULARITY / sizeof (MEMORY_MAP); Index++) {
  249. FreeDescriptorEntries[Index].Signature = MEMORY_MAP_SIGNATURE;
  250. InsertTailList (&mFreeMemoryMapEntryList, &FreeDescriptorEntries[Index].Link);
  251. }
  252. } else {
  253. return NULL;
  254. }
  255. }
  256. //
  257. // dequeue the first descriptor from the list
  258. //
  259. Entry = CR (mFreeMemoryMapEntryList.ForwardLink, MEMORY_MAP, Link, MEMORY_MAP_SIGNATURE);
  260. RemoveEntryList (&Entry->Link);
  261. return Entry;
  262. }
  263. /**
  264. Internal function. Moves any memory descriptors that are on the
  265. temporary descriptor stack to heap.
  266. **/
  267. VOID
  268. CoreFreeMemoryMapStack (
  269. VOID
  270. )
  271. {
  272. MEMORY_MAP *Entry;
  273. MEMORY_MAP *Entry2;
  274. LIST_ENTRY *Link2;
  275. ASSERT_LOCKED (&gMemoryLock);
  276. //
  277. // If already freeing the map stack, then return
  278. //
  279. if (mFreeMapStack != 0) {
  280. return;
  281. }
  282. //
  283. // Move the temporary memory descriptor stack into pool
  284. //
  285. mFreeMapStack += 1;
  286. while (mMapDepth != 0) {
  287. //
  288. // Deque an memory map entry from mFreeMemoryMapEntryList
  289. //
  290. Entry = AllocateMemoryMapEntry ();
  291. ASSERT (Entry);
  292. //
  293. // Update to proper entry
  294. //
  295. mMapDepth -= 1;
  296. if (mMapStack[mMapDepth].Link.ForwardLink != NULL) {
  297. //
  298. // Move this entry to general memory
  299. //
  300. RemoveEntryList (&mMapStack[mMapDepth].Link);
  301. mMapStack[mMapDepth].Link.ForwardLink = NULL;
  302. CopyMem (Entry, &mMapStack[mMapDepth], sizeof (MEMORY_MAP));
  303. Entry->FromPages = TRUE;
  304. //
  305. // Find insertion location
  306. //
  307. for (Link2 = gMemoryMap.ForwardLink; Link2 != &gMemoryMap; Link2 = Link2->ForwardLink) {
  308. Entry2 = CR (Link2, MEMORY_MAP, Link, MEMORY_MAP_SIGNATURE);
  309. if (Entry2->FromPages && (Entry2->Start > Entry->Start)) {
  310. break;
  311. }
  312. }
  313. InsertTailList (Link2, &Entry->Link);
  314. } else {
  315. //
  316. // This item of mMapStack[mMapDepth] has already been dequeued from gMemoryMap list,
  317. // so here no need to move it to memory.
  318. //
  319. InsertTailList (&mFreeMemoryMapEntryList, &Entry->Link);
  320. }
  321. }
  322. mFreeMapStack -= 1;
  323. }
  324. /**
  325. Find untested but initialized memory regions in GCD map and convert them to be DXE allocatable.
  326. **/
  327. BOOLEAN
  328. PromoteMemoryResource (
  329. VOID
  330. )
  331. {
  332. LIST_ENTRY *Link;
  333. EFI_GCD_MAP_ENTRY *Entry;
  334. BOOLEAN Promoted;
  335. EFI_PHYSICAL_ADDRESS StartAddress;
  336. EFI_PHYSICAL_ADDRESS EndAddress;
  337. EFI_GCD_MEMORY_SPACE_DESCRIPTOR Descriptor;
  338. DEBUG ((DEBUG_PAGE, "Promote the memory resource\n"));
  339. CoreAcquireGcdMemoryLock ();
  340. Promoted = FALSE;
  341. Link = mGcdMemorySpaceMap.ForwardLink;
  342. while (Link != &mGcdMemorySpaceMap) {
  343. Entry = CR (Link, EFI_GCD_MAP_ENTRY, Link, EFI_GCD_MAP_SIGNATURE);
  344. if ((Entry->GcdMemoryType == EfiGcdMemoryTypeReserved) &&
  345. (Entry->EndAddress < MAX_ALLOC_ADDRESS) &&
  346. ((Entry->Capabilities & (EFI_MEMORY_PRESENT | EFI_MEMORY_INITIALIZED | EFI_MEMORY_TESTED)) ==
  347. (EFI_MEMORY_PRESENT | EFI_MEMORY_INITIALIZED)))
  348. {
  349. //
  350. // Update the GCD map
  351. //
  352. if ((Entry->Capabilities & EFI_MEMORY_MORE_RELIABLE) == EFI_MEMORY_MORE_RELIABLE) {
  353. Entry->GcdMemoryType = EfiGcdMemoryTypeMoreReliable;
  354. } else {
  355. Entry->GcdMemoryType = EfiGcdMemoryTypeSystemMemory;
  356. }
  357. Entry->Capabilities |= EFI_MEMORY_TESTED;
  358. Entry->ImageHandle = gDxeCoreImageHandle;
  359. Entry->DeviceHandle = NULL;
  360. //
  361. // Add to allocable system memory resource
  362. //
  363. CoreAddRange (
  364. EfiConventionalMemory,
  365. Entry->BaseAddress,
  366. Entry->EndAddress,
  367. Entry->Capabilities & ~(EFI_MEMORY_PRESENT | EFI_MEMORY_INITIALIZED | EFI_MEMORY_TESTED | EFI_MEMORY_RUNTIME)
  368. );
  369. CoreFreeMemoryMapStack ();
  370. Promoted = TRUE;
  371. }
  372. Link = Link->ForwardLink;
  373. }
  374. CoreReleaseGcdMemoryLock ();
  375. if (!Promoted) {
  376. //
  377. // If freed-memory guard is enabled, we could promote pages from
  378. // guarded free pages.
  379. //
  380. Promoted = PromoteGuardedFreePages (&StartAddress, &EndAddress);
  381. if (Promoted) {
  382. if (!EFI_ERROR (CoreGetMemorySpaceDescriptor (StartAddress, &Descriptor))) {
  383. CoreAddRange (
  384. EfiConventionalMemory,
  385. StartAddress,
  386. EndAddress,
  387. Descriptor.Capabilities & ~(EFI_MEMORY_PRESENT | EFI_MEMORY_INITIALIZED |
  388. EFI_MEMORY_TESTED | EFI_MEMORY_RUNTIME)
  389. );
  390. }
  391. }
  392. }
  393. return Promoted;
  394. }
  395. /**
  396. This function try to allocate Runtime code & Boot time code memory range. If LMFA enabled, 2 patchable PCD
  397. PcdLoadFixAddressRuntimeCodePageNumber & PcdLoadFixAddressBootTimeCodePageNumber which are set by tools will record the
  398. size of boot time and runtime code.
  399. **/
  400. VOID
  401. CoreLoadingFixedAddressHook (
  402. VOID
  403. )
  404. {
  405. UINT32 RuntimeCodePageNumber;
  406. UINT32 BootTimeCodePageNumber;
  407. EFI_PHYSICAL_ADDRESS RuntimeCodeBase;
  408. EFI_PHYSICAL_ADDRESS BootTimeCodeBase;
  409. EFI_STATUS Status;
  410. //
  411. // Make sure these 2 areas are not initialzied.
  412. //
  413. if (!gLoadFixedAddressCodeMemoryReady) {
  414. RuntimeCodePageNumber = PcdGet32 (PcdLoadFixAddressRuntimeCodePageNumber);
  415. BootTimeCodePageNumber = PcdGet32 (PcdLoadFixAddressBootTimeCodePageNumber);
  416. RuntimeCodeBase = (EFI_PHYSICAL_ADDRESS)(gLoadModuleAtFixAddressConfigurationTable.DxeCodeTopAddress - EFI_PAGES_TO_SIZE (RuntimeCodePageNumber));
  417. BootTimeCodeBase = (EFI_PHYSICAL_ADDRESS)(RuntimeCodeBase - EFI_PAGES_TO_SIZE (BootTimeCodePageNumber));
  418. //
  419. // Try to allocate runtime memory.
  420. //
  421. Status = CoreAllocatePages (
  422. AllocateAddress,
  423. EfiRuntimeServicesCode,
  424. RuntimeCodePageNumber,
  425. &RuntimeCodeBase
  426. );
  427. if (EFI_ERROR (Status)) {
  428. //
  429. // Runtime memory allocation failed
  430. //
  431. return;
  432. }
  433. //
  434. // Try to allocate boot memory.
  435. //
  436. Status = CoreAllocatePages (
  437. AllocateAddress,
  438. EfiBootServicesCode,
  439. BootTimeCodePageNumber,
  440. &BootTimeCodeBase
  441. );
  442. if (EFI_ERROR (Status)) {
  443. //
  444. // boot memory allocation failed. Free Runtime code range and will try the allocation again when
  445. // new memory range is installed.
  446. //
  447. CoreFreePages (
  448. RuntimeCodeBase,
  449. RuntimeCodePageNumber
  450. );
  451. return;
  452. }
  453. gLoadFixedAddressCodeMemoryReady = TRUE;
  454. }
  455. return;
  456. }
  457. /**
  458. Called to initialize the memory map and add descriptors to
  459. the current descriptor list.
  460. The first descriptor that is added must be general usable
  461. memory as the addition allocates heap.
  462. @param Type The type of memory to add
  463. @param Start The starting address in the memory range Must be
  464. page aligned
  465. @param NumberOfPages The number of pages in the range
  466. @param Attribute Attributes of the memory to add
  467. @return None. The range is added to the memory map
  468. **/
  469. VOID
  470. CoreAddMemoryDescriptor (
  471. IN EFI_MEMORY_TYPE Type,
  472. IN EFI_PHYSICAL_ADDRESS Start,
  473. IN UINT64 NumberOfPages,
  474. IN UINT64 Attribute
  475. )
  476. {
  477. EFI_PHYSICAL_ADDRESS End;
  478. EFI_STATUS Status;
  479. UINTN Index;
  480. UINTN FreeIndex;
  481. if ((Start & EFI_PAGE_MASK) != 0) {
  482. return;
  483. }
  484. if ((Type >= EfiMaxMemoryType) && (Type < MEMORY_TYPE_OEM_RESERVED_MIN)) {
  485. return;
  486. }
  487. CoreAcquireMemoryLock ();
  488. End = Start + LShiftU64 (NumberOfPages, EFI_PAGE_SHIFT) - 1;
  489. CoreAddRange (Type, Start, End, Attribute);
  490. CoreFreeMemoryMapStack ();
  491. CoreReleaseMemoryLock ();
  492. ApplyMemoryProtectionPolicy (
  493. EfiMaxMemoryType,
  494. Type,
  495. Start,
  496. LShiftU64 (NumberOfPages, EFI_PAGE_SHIFT)
  497. );
  498. //
  499. // If Loading Module At Fixed Address feature is enabled. try to allocate memory with Runtime code & Boot time code type
  500. //
  501. if (PcdGet64 (PcdLoadModuleAtFixAddressEnable) != 0) {
  502. CoreLoadingFixedAddressHook ();
  503. }
  504. //
  505. // Check to see if the statistics for the different memory types have already been established
  506. //
  507. if (mMemoryTypeInformationInitialized) {
  508. return;
  509. }
  510. //
  511. // Loop through each memory type in the order specified by the gMemoryTypeInformation[] array
  512. //
  513. for (Index = 0; gMemoryTypeInformation[Index].Type != EfiMaxMemoryType; Index++) {
  514. //
  515. // Make sure the memory type in the gMemoryTypeInformation[] array is valid
  516. //
  517. Type = (EFI_MEMORY_TYPE)(gMemoryTypeInformation[Index].Type);
  518. if ((UINT32)Type > EfiMaxMemoryType) {
  519. continue;
  520. }
  521. if (gMemoryTypeInformation[Index].NumberOfPages != 0) {
  522. //
  523. // Allocate pages for the current memory type from the top of available memory
  524. //
  525. Status = CoreAllocatePages (
  526. AllocateAnyPages,
  527. Type,
  528. gMemoryTypeInformation[Index].NumberOfPages,
  529. &mMemoryTypeStatistics[Type].BaseAddress
  530. );
  531. if (EFI_ERROR (Status)) {
  532. //
  533. // If an error occurs allocating the pages for the current memory type, then
  534. // free all the pages allocates for the previous memory types and return. This
  535. // operation with be retied when/if more memory is added to the system
  536. //
  537. for (FreeIndex = 0; FreeIndex < Index; FreeIndex++) {
  538. //
  539. // Make sure the memory type in the gMemoryTypeInformation[] array is valid
  540. //
  541. Type = (EFI_MEMORY_TYPE)(gMemoryTypeInformation[FreeIndex].Type);
  542. if ((UINT32)Type > EfiMaxMemoryType) {
  543. continue;
  544. }
  545. if (gMemoryTypeInformation[FreeIndex].NumberOfPages != 0) {
  546. CoreFreePages (
  547. mMemoryTypeStatistics[Type].BaseAddress,
  548. gMemoryTypeInformation[FreeIndex].NumberOfPages
  549. );
  550. mMemoryTypeStatistics[Type].BaseAddress = 0;
  551. mMemoryTypeStatistics[Type].MaximumAddress = MAX_ALLOC_ADDRESS;
  552. }
  553. }
  554. return;
  555. }
  556. //
  557. // Compute the address at the top of the current statistics
  558. //
  559. mMemoryTypeStatistics[Type].MaximumAddress =
  560. mMemoryTypeStatistics[Type].BaseAddress +
  561. LShiftU64 (gMemoryTypeInformation[Index].NumberOfPages, EFI_PAGE_SHIFT) - 1;
  562. //
  563. // If the current base address is the lowest address so far, then update the default
  564. // maximum address
  565. //
  566. if (mMemoryTypeStatistics[Type].BaseAddress < mDefaultMaximumAddress) {
  567. mDefaultMaximumAddress = mMemoryTypeStatistics[Type].BaseAddress - 1;
  568. }
  569. }
  570. }
  571. //
  572. // There was enough system memory for all the the memory types were allocated. So,
  573. // those memory areas can be freed for future allocations, and all future memory
  574. // allocations can occur within their respective bins
  575. //
  576. for (Index = 0; gMemoryTypeInformation[Index].Type != EfiMaxMemoryType; Index++) {
  577. //
  578. // Make sure the memory type in the gMemoryTypeInformation[] array is valid
  579. //
  580. Type = (EFI_MEMORY_TYPE)(gMemoryTypeInformation[Index].Type);
  581. if ((UINT32)Type > EfiMaxMemoryType) {
  582. continue;
  583. }
  584. if (gMemoryTypeInformation[Index].NumberOfPages != 0) {
  585. CoreFreePages (
  586. mMemoryTypeStatistics[Type].BaseAddress,
  587. gMemoryTypeInformation[Index].NumberOfPages
  588. );
  589. mMemoryTypeStatistics[Type].NumberOfPages = gMemoryTypeInformation[Index].NumberOfPages;
  590. gMemoryTypeInformation[Index].NumberOfPages = 0;
  591. }
  592. }
  593. //
  594. // If the number of pages reserved for a memory type is 0, then all allocations for that type
  595. // should be in the default range.
  596. //
  597. for (Type = (EFI_MEMORY_TYPE)0; Type < EfiMaxMemoryType; Type++) {
  598. for (Index = 0; gMemoryTypeInformation[Index].Type != EfiMaxMemoryType; Index++) {
  599. if (Type == (EFI_MEMORY_TYPE)gMemoryTypeInformation[Index].Type) {
  600. mMemoryTypeStatistics[Type].InformationIndex = Index;
  601. }
  602. }
  603. mMemoryTypeStatistics[Type].CurrentNumberOfPages = 0;
  604. if (mMemoryTypeStatistics[Type].MaximumAddress == MAX_ALLOC_ADDRESS) {
  605. mMemoryTypeStatistics[Type].MaximumAddress = mDefaultMaximumAddress;
  606. }
  607. }
  608. mMemoryTypeInformationInitialized = TRUE;
  609. }
  610. /**
  611. Internal function. Converts a memory range to the specified type or attributes.
  612. The range must exist in the memory map. Either ChangingType or
  613. ChangingAttributes must be set, but not both.
  614. @param Start The first address of the range Must be page
  615. aligned
  616. @param NumberOfPages The number of pages to convert
  617. @param ChangingType Boolean indicating that type value should be changed
  618. @param NewType The new type for the memory range
  619. @param ChangingAttributes Boolean indicating that attributes value should be changed
  620. @param NewAttributes The new attributes for the memory range
  621. @retval EFI_INVALID_PARAMETER Invalid parameter
  622. @retval EFI_NOT_FOUND Could not find a descriptor cover the specified
  623. range or convertion not allowed.
  624. @retval EFI_SUCCESS Successfully converts the memory range to the
  625. specified type.
  626. **/
  627. EFI_STATUS
  628. CoreConvertPagesEx (
  629. IN UINT64 Start,
  630. IN UINT64 NumberOfPages,
  631. IN BOOLEAN ChangingType,
  632. IN EFI_MEMORY_TYPE NewType,
  633. IN BOOLEAN ChangingAttributes,
  634. IN UINT64 NewAttributes
  635. )
  636. {
  637. UINT64 NumberOfBytes;
  638. UINT64 End;
  639. UINT64 RangeEnd;
  640. UINT64 Attribute;
  641. EFI_MEMORY_TYPE MemType;
  642. LIST_ENTRY *Link;
  643. MEMORY_MAP *Entry;
  644. Entry = NULL;
  645. NumberOfBytes = LShiftU64 (NumberOfPages, EFI_PAGE_SHIFT);
  646. End = Start + NumberOfBytes - 1;
  647. ASSERT (NumberOfPages);
  648. ASSERT ((Start & EFI_PAGE_MASK) == 0);
  649. ASSERT (End > Start);
  650. ASSERT_LOCKED (&gMemoryLock);
  651. ASSERT ((ChangingType == FALSE) || (ChangingAttributes == FALSE));
  652. if ((NumberOfPages == 0) || ((Start & EFI_PAGE_MASK) != 0) || (Start >= End)) {
  653. return EFI_INVALID_PARAMETER;
  654. }
  655. //
  656. // Convert the entire range
  657. //
  658. while (Start < End) {
  659. //
  660. // Find the entry that the covers the range
  661. //
  662. for (Link = gMemoryMap.ForwardLink; Link != &gMemoryMap; Link = Link->ForwardLink) {
  663. Entry = CR (Link, MEMORY_MAP, Link, MEMORY_MAP_SIGNATURE);
  664. if ((Entry->Start <= Start) && (Entry->End > Start)) {
  665. break;
  666. }
  667. }
  668. if (Link == &gMemoryMap) {
  669. DEBUG ((DEBUG_ERROR | DEBUG_PAGE, "ConvertPages: failed to find range %lx - %lx\n", Start, End));
  670. return EFI_NOT_FOUND;
  671. }
  672. //
  673. // If we are converting the type of the range from EfiConventionalMemory to
  674. // another type, we have to ensure that the entire range is covered by a
  675. // single entry.
  676. //
  677. if (ChangingType && (NewType != EfiConventionalMemory)) {
  678. if (Entry->End < End) {
  679. DEBUG ((DEBUG_ERROR | DEBUG_PAGE, "ConvertPages: range %lx - %lx covers multiple entries\n", Start, End));
  680. return EFI_NOT_FOUND;
  681. }
  682. }
  683. //
  684. // Convert range to the end, or to the end of the descriptor
  685. // if that's all we've got
  686. //
  687. RangeEnd = End;
  688. ASSERT (Entry != NULL);
  689. if (Entry->End < End) {
  690. RangeEnd = Entry->End;
  691. }
  692. if (ChangingType) {
  693. DEBUG ((DEBUG_PAGE, "ConvertRange: %lx-%lx to type %d\n", Start, RangeEnd, NewType));
  694. }
  695. if (ChangingAttributes) {
  696. DEBUG ((DEBUG_PAGE, "ConvertRange: %lx-%lx to attr %lx\n", Start, RangeEnd, NewAttributes));
  697. }
  698. if (ChangingType) {
  699. //
  700. // Debug code - verify conversion is allowed
  701. //
  702. if (!((NewType == EfiConventionalMemory) ? 1 : 0) ^ ((Entry->Type == EfiConventionalMemory) ? 1 : 0)) {
  703. DEBUG ((DEBUG_ERROR | DEBUG_PAGE, "ConvertPages: Incompatible memory types, "));
  704. if (Entry->Type == EfiConventionalMemory) {
  705. DEBUG ((DEBUG_ERROR | DEBUG_PAGE, "the pages to free have been freed\n"));
  706. } else {
  707. DEBUG ((DEBUG_ERROR | DEBUG_PAGE, "the pages to allocate have been allocated\n"));
  708. }
  709. return EFI_NOT_FOUND;
  710. }
  711. //
  712. // Update counters for the number of pages allocated to each memory type
  713. //
  714. if ((UINT32)Entry->Type < EfiMaxMemoryType) {
  715. if (((Start >= mMemoryTypeStatistics[Entry->Type].BaseAddress) && (Start <= mMemoryTypeStatistics[Entry->Type].MaximumAddress)) ||
  716. ((Start >= mDefaultBaseAddress) && (Start <= mDefaultMaximumAddress)))
  717. {
  718. if (NumberOfPages > mMemoryTypeStatistics[Entry->Type].CurrentNumberOfPages) {
  719. mMemoryTypeStatistics[Entry->Type].CurrentNumberOfPages = 0;
  720. } else {
  721. mMemoryTypeStatistics[Entry->Type].CurrentNumberOfPages -= NumberOfPages;
  722. }
  723. }
  724. }
  725. if ((UINT32)NewType < EfiMaxMemoryType) {
  726. if (((Start >= mMemoryTypeStatistics[NewType].BaseAddress) && (Start <= mMemoryTypeStatistics[NewType].MaximumAddress)) ||
  727. ((Start >= mDefaultBaseAddress) && (Start <= mDefaultMaximumAddress)))
  728. {
  729. mMemoryTypeStatistics[NewType].CurrentNumberOfPages += NumberOfPages;
  730. if (mMemoryTypeStatistics[NewType].CurrentNumberOfPages > gMemoryTypeInformation[mMemoryTypeStatistics[NewType].InformationIndex].NumberOfPages) {
  731. gMemoryTypeInformation[mMemoryTypeStatistics[NewType].InformationIndex].NumberOfPages = (UINT32)mMemoryTypeStatistics[NewType].CurrentNumberOfPages;
  732. }
  733. }
  734. }
  735. }
  736. //
  737. // Pull range out of descriptor
  738. //
  739. if (Entry->Start == Start) {
  740. //
  741. // Clip start
  742. //
  743. Entry->Start = RangeEnd + 1;
  744. } else if (Entry->End == RangeEnd) {
  745. //
  746. // Clip end
  747. //
  748. Entry->End = Start - 1;
  749. } else {
  750. //
  751. // Pull it out of the center, clip current
  752. //
  753. //
  754. // Add a new one
  755. //
  756. mMapStack[mMapDepth].Signature = MEMORY_MAP_SIGNATURE;
  757. mMapStack[mMapDepth].FromPages = FALSE;
  758. mMapStack[mMapDepth].Type = Entry->Type;
  759. mMapStack[mMapDepth].Start = RangeEnd+1;
  760. mMapStack[mMapDepth].End = Entry->End;
  761. //
  762. // Inherit Attribute from the Memory Descriptor that is being clipped
  763. //
  764. mMapStack[mMapDepth].Attribute = Entry->Attribute;
  765. Entry->End = Start - 1;
  766. ASSERT (Entry->Start < Entry->End);
  767. Entry = &mMapStack[mMapDepth];
  768. InsertTailList (&gMemoryMap, &Entry->Link);
  769. mMapDepth += 1;
  770. ASSERT (mMapDepth < MAX_MAP_DEPTH);
  771. }
  772. //
  773. // The new range inherits the same Attribute as the Entry
  774. // it is being cut out of unless attributes are being changed
  775. //
  776. if (ChangingType) {
  777. Attribute = Entry->Attribute;
  778. MemType = NewType;
  779. } else {
  780. Attribute = NewAttributes;
  781. MemType = Entry->Type;
  782. }
  783. //
  784. // If the descriptor is empty, then remove it from the map
  785. //
  786. if (Entry->Start == Entry->End + 1) {
  787. RemoveMemoryMapEntry (Entry);
  788. Entry = NULL;
  789. }
  790. //
  791. // Add our new range in. Don't do this for freed pages if freed-memory
  792. // guard is enabled.
  793. //
  794. if (!IsHeapGuardEnabled (GUARD_HEAP_TYPE_FREED) ||
  795. !ChangingType ||
  796. (MemType != EfiConventionalMemory))
  797. {
  798. CoreAddRange (MemType, Start, RangeEnd, Attribute);
  799. }
  800. if (ChangingType && (MemType == EfiConventionalMemory)) {
  801. //
  802. // Avoid calling DEBUG_CLEAR_MEMORY() for an address of 0 because this
  803. // macro will ASSERT() if address is 0. Instead, CoreAddRange() guarantees
  804. // that the page starting at address 0 is always filled with zeros.
  805. //
  806. if (Start == 0) {
  807. if (RangeEnd > EFI_PAGE_SIZE) {
  808. DEBUG_CLEAR_MEMORY ((VOID *)(UINTN)EFI_PAGE_SIZE, (UINTN)(RangeEnd - EFI_PAGE_SIZE + 1));
  809. }
  810. } else {
  811. DEBUG_CLEAR_MEMORY ((VOID *)(UINTN)Start, (UINTN)(RangeEnd - Start + 1));
  812. }
  813. }
  814. //
  815. // Move any map descriptor stack to general pool
  816. //
  817. CoreFreeMemoryMapStack ();
  818. //
  819. // Bump the starting address, and convert the next range
  820. //
  821. Start = RangeEnd + 1;
  822. }
  823. //
  824. // Converted the whole range, done
  825. //
  826. return EFI_SUCCESS;
  827. }
  828. /**
  829. Internal function. Converts a memory range to the specified type.
  830. The range must exist in the memory map.
  831. @param Start The first address of the range Must be page
  832. aligned
  833. @param NumberOfPages The number of pages to convert
  834. @param NewType The new type for the memory range
  835. @retval EFI_INVALID_PARAMETER Invalid parameter
  836. @retval EFI_NOT_FOUND Could not find a descriptor cover the specified
  837. range or convertion not allowed.
  838. @retval EFI_SUCCESS Successfully converts the memory range to the
  839. specified type.
  840. **/
  841. EFI_STATUS
  842. CoreConvertPages (
  843. IN UINT64 Start,
  844. IN UINT64 NumberOfPages,
  845. IN EFI_MEMORY_TYPE NewType
  846. )
  847. {
  848. return CoreConvertPagesEx (Start, NumberOfPages, TRUE, NewType, FALSE, 0);
  849. }
  850. /**
  851. Internal function. Converts a memory range to use new attributes.
  852. @param Start The first address of the range Must be page
  853. aligned
  854. @param NumberOfPages The number of pages to convert
  855. @param NewAttributes The new attributes value for the range.
  856. **/
  857. VOID
  858. CoreUpdateMemoryAttributes (
  859. IN EFI_PHYSICAL_ADDRESS Start,
  860. IN UINT64 NumberOfPages,
  861. IN UINT64 NewAttributes
  862. )
  863. {
  864. CoreAcquireMemoryLock ();
  865. //
  866. // Update the attributes to the new value
  867. //
  868. CoreConvertPagesEx (Start, NumberOfPages, FALSE, (EFI_MEMORY_TYPE)0, TRUE, NewAttributes);
  869. CoreReleaseMemoryLock ();
  870. }
  871. /**
  872. Internal function. Finds a consecutive free page range below
  873. the requested address.
  874. @param MaxAddress The address that the range must be below
  875. @param MinAddress The address that the range must be above
  876. @param NumberOfPages Number of pages needed
  877. @param NewType The type of memory the range is going to be
  878. turned into
  879. @param Alignment Bits to align with
  880. @param NeedGuard Flag to indicate Guard page is needed or not
  881. @return The base address of the range, or 0 if the range was not found
  882. **/
  883. UINT64
  884. CoreFindFreePagesI (
  885. IN UINT64 MaxAddress,
  886. IN UINT64 MinAddress,
  887. IN UINT64 NumberOfPages,
  888. IN EFI_MEMORY_TYPE NewType,
  889. IN UINTN Alignment,
  890. IN BOOLEAN NeedGuard
  891. )
  892. {
  893. UINT64 NumberOfBytes;
  894. UINT64 Target;
  895. UINT64 DescStart;
  896. UINT64 DescEnd;
  897. UINT64 DescNumberOfBytes;
  898. LIST_ENTRY *Link;
  899. MEMORY_MAP *Entry;
  900. if ((MaxAddress < EFI_PAGE_MASK) || (NumberOfPages == 0)) {
  901. return 0;
  902. }
  903. if ((MaxAddress & EFI_PAGE_MASK) != EFI_PAGE_MASK) {
  904. //
  905. // If MaxAddress is not aligned to the end of a page
  906. //
  907. //
  908. // Change MaxAddress to be 1 page lower
  909. //
  910. MaxAddress -= (EFI_PAGE_MASK + 1);
  911. //
  912. // Set MaxAddress to a page boundary
  913. //
  914. MaxAddress &= ~(UINT64)EFI_PAGE_MASK;
  915. //
  916. // Set MaxAddress to end of the page
  917. //
  918. MaxAddress |= EFI_PAGE_MASK;
  919. }
  920. NumberOfBytes = LShiftU64 (NumberOfPages, EFI_PAGE_SHIFT);
  921. Target = 0;
  922. for (Link = gMemoryMap.ForwardLink; Link != &gMemoryMap; Link = Link->ForwardLink) {
  923. Entry = CR (Link, MEMORY_MAP, Link, MEMORY_MAP_SIGNATURE);
  924. //
  925. // If it's not a free entry, don't bother with it
  926. //
  927. if (Entry->Type != EfiConventionalMemory) {
  928. continue;
  929. }
  930. DescStart = Entry->Start;
  931. DescEnd = Entry->End;
  932. //
  933. // If desc is past max allowed address or below min allowed address, skip it
  934. //
  935. if ((DescStart >= MaxAddress) || (DescEnd < MinAddress)) {
  936. continue;
  937. }
  938. //
  939. // If desc ends past max allowed address, clip the end
  940. //
  941. if (DescEnd >= MaxAddress) {
  942. DescEnd = MaxAddress;
  943. }
  944. DescEnd = ((DescEnd + 1) & (~((UINT64)Alignment - 1))) - 1;
  945. // Skip if DescEnd is less than DescStart after alignment clipping
  946. if (DescEnd < DescStart) {
  947. continue;
  948. }
  949. //
  950. // Compute the number of bytes we can used from this
  951. // descriptor, and see it's enough to satisfy the request
  952. //
  953. DescNumberOfBytes = DescEnd - DescStart + 1;
  954. if (DescNumberOfBytes >= NumberOfBytes) {
  955. //
  956. // If the start of the allocated range is below the min address allowed, skip it
  957. //
  958. if ((DescEnd - NumberOfBytes + 1) < MinAddress) {
  959. continue;
  960. }
  961. //
  962. // If this is the best match so far remember it
  963. //
  964. if (DescEnd > Target) {
  965. if (NeedGuard) {
  966. DescEnd = AdjustMemoryS (
  967. DescEnd + 1 - DescNumberOfBytes,
  968. DescNumberOfBytes,
  969. NumberOfBytes
  970. );
  971. if (DescEnd == 0) {
  972. continue;
  973. }
  974. }
  975. Target = DescEnd;
  976. }
  977. }
  978. }
  979. //
  980. // If this is a grow down, adjust target to be the allocation base
  981. //
  982. Target -= NumberOfBytes - 1;
  983. //
  984. // If we didn't find a match, return 0
  985. //
  986. if ((Target & EFI_PAGE_MASK) != 0) {
  987. return 0;
  988. }
  989. return Target;
  990. }
  991. /**
  992. Internal function. Finds a consecutive free page range below
  993. the requested address
  994. @param MaxAddress The address that the range must be below
  995. @param NoPages Number of pages needed
  996. @param NewType The type of memory the range is going to be
  997. turned into
  998. @param Alignment Bits to align with
  999. @param NeedGuard Flag to indicate Guard page is needed or not
  1000. @return The base address of the range, or 0 if the range was not found.
  1001. **/
  1002. UINT64
  1003. FindFreePages (
  1004. IN UINT64 MaxAddress,
  1005. IN UINT64 NoPages,
  1006. IN EFI_MEMORY_TYPE NewType,
  1007. IN UINTN Alignment,
  1008. IN BOOLEAN NeedGuard
  1009. )
  1010. {
  1011. UINT64 Start;
  1012. //
  1013. // Attempt to find free pages in the preferred bin based on the requested memory type
  1014. //
  1015. if (((UINT32)NewType < EfiMaxMemoryType) && (MaxAddress >= mMemoryTypeStatistics[NewType].MaximumAddress)) {
  1016. Start = CoreFindFreePagesI (
  1017. mMemoryTypeStatistics[NewType].MaximumAddress,
  1018. mMemoryTypeStatistics[NewType].BaseAddress,
  1019. NoPages,
  1020. NewType,
  1021. Alignment,
  1022. NeedGuard
  1023. );
  1024. if (Start != 0) {
  1025. return Start;
  1026. }
  1027. }
  1028. //
  1029. // Attempt to find free pages in the default allocation bin
  1030. //
  1031. if (MaxAddress >= mDefaultMaximumAddress) {
  1032. Start = CoreFindFreePagesI (
  1033. mDefaultMaximumAddress,
  1034. 0,
  1035. NoPages,
  1036. NewType,
  1037. Alignment,
  1038. NeedGuard
  1039. );
  1040. if (Start != 0) {
  1041. if (Start < mDefaultBaseAddress) {
  1042. mDefaultBaseAddress = Start;
  1043. }
  1044. return Start;
  1045. }
  1046. }
  1047. //
  1048. // The allocation did not succeed in any of the prefered bins even after
  1049. // promoting resources. Attempt to find free pages anywhere is the requested
  1050. // address range. If this allocation fails, then there are not enough
  1051. // resources anywhere to satisfy the request.
  1052. //
  1053. Start = CoreFindFreePagesI (
  1054. MaxAddress,
  1055. 0,
  1056. NoPages,
  1057. NewType,
  1058. Alignment,
  1059. NeedGuard
  1060. );
  1061. if (Start != 0) {
  1062. return Start;
  1063. }
  1064. //
  1065. // If allocations from the preferred bins fail, then attempt to promote memory resources.
  1066. //
  1067. if (!PromoteMemoryResource ()) {
  1068. return 0;
  1069. }
  1070. //
  1071. // If any memory resources were promoted, then re-attempt the allocation
  1072. //
  1073. return FindFreePages (MaxAddress, NoPages, NewType, Alignment, NeedGuard);
  1074. }
  1075. /**
  1076. Allocates pages from the memory map.
  1077. @param Type The type of allocation to perform
  1078. @param MemoryType The type of memory to turn the allocated pages
  1079. into
  1080. @param NumberOfPages The number of pages to allocate
  1081. @param Memory A pointer to receive the base allocated memory
  1082. address
  1083. @param NeedGuard Flag to indicate Guard page is needed or not
  1084. @return Status. On success, Memory is filled in with the base address allocated
  1085. @retval EFI_INVALID_PARAMETER Parameters violate checking rules defined in
  1086. spec.
  1087. @retval EFI_NOT_FOUND Could not allocate pages match the requirement.
  1088. @retval EFI_OUT_OF_RESOURCES No enough pages to allocate.
  1089. @retval EFI_SUCCESS Pages successfully allocated.
  1090. **/
  1091. EFI_STATUS
  1092. EFIAPI
  1093. CoreInternalAllocatePages (
  1094. IN EFI_ALLOCATE_TYPE Type,
  1095. IN EFI_MEMORY_TYPE MemoryType,
  1096. IN UINTN NumberOfPages,
  1097. IN OUT EFI_PHYSICAL_ADDRESS *Memory,
  1098. IN BOOLEAN NeedGuard
  1099. )
  1100. {
  1101. EFI_STATUS Status;
  1102. UINT64 Start;
  1103. UINT64 NumberOfBytes;
  1104. UINT64 End;
  1105. UINT64 MaxAddress;
  1106. UINTN Alignment;
  1107. EFI_MEMORY_TYPE CheckType;
  1108. if ((UINT32)Type >= MaxAllocateType) {
  1109. return EFI_INVALID_PARAMETER;
  1110. }
  1111. if (((MemoryType >= EfiMaxMemoryType) && (MemoryType < MEMORY_TYPE_OEM_RESERVED_MIN)) ||
  1112. (MemoryType == EfiConventionalMemory) || (MemoryType == EfiPersistentMemory) || (MemoryType == EfiUnacceptedMemoryType))
  1113. {
  1114. return EFI_INVALID_PARAMETER;
  1115. }
  1116. if (Memory == NULL) {
  1117. return EFI_INVALID_PARAMETER;
  1118. }
  1119. Alignment = DEFAULT_PAGE_ALLOCATION_GRANULARITY;
  1120. if ((MemoryType == EfiACPIReclaimMemory) ||
  1121. (MemoryType == EfiACPIMemoryNVS) ||
  1122. (MemoryType == EfiRuntimeServicesCode) ||
  1123. (MemoryType == EfiRuntimeServicesData))
  1124. {
  1125. Alignment = RUNTIME_PAGE_ALLOCATION_GRANULARITY;
  1126. }
  1127. if (Type == AllocateAddress) {
  1128. if ((*Memory & (Alignment - 1)) != 0) {
  1129. return EFI_NOT_FOUND;
  1130. }
  1131. }
  1132. NumberOfPages += EFI_SIZE_TO_PAGES (Alignment) - 1;
  1133. NumberOfPages &= ~(EFI_SIZE_TO_PAGES (Alignment) - 1);
  1134. //
  1135. // If this is for below a particular address, then
  1136. //
  1137. Start = *Memory;
  1138. //
  1139. // The max address is the max natively addressable address for the processor
  1140. //
  1141. MaxAddress = MAX_ALLOC_ADDRESS;
  1142. //
  1143. // Check for Type AllocateAddress,
  1144. // if NumberOfPages is 0 or
  1145. // if (NumberOfPages << EFI_PAGE_SHIFT) is above MAX_ALLOC_ADDRESS or
  1146. // if (Start + NumberOfBytes) rolls over 0 or
  1147. // if Start is above MAX_ALLOC_ADDRESS or
  1148. // if End is above MAX_ALLOC_ADDRESS,
  1149. // if Start..End overlaps any tracked MemoryTypeStatistics range
  1150. // return EFI_NOT_FOUND.
  1151. //
  1152. if (Type == AllocateAddress) {
  1153. if ((NumberOfPages == 0) ||
  1154. (NumberOfPages > RShiftU64 (MaxAddress, EFI_PAGE_SHIFT)))
  1155. {
  1156. return EFI_NOT_FOUND;
  1157. }
  1158. NumberOfBytes = LShiftU64 (NumberOfPages, EFI_PAGE_SHIFT);
  1159. End = Start + NumberOfBytes - 1;
  1160. if ((Start >= End) ||
  1161. (Start > MaxAddress) ||
  1162. (End > MaxAddress))
  1163. {
  1164. return EFI_NOT_FOUND;
  1165. }
  1166. //
  1167. // A driver is allowed to call AllocatePages using an AllocateAddress type. This type of
  1168. // AllocatePage request the exact physical address if it is not used. The existing code
  1169. // will allow this request even in 'special' pages. The problem with this is that the
  1170. // reason to have 'special' pages for OS hibernate/resume is defeated as memory is
  1171. // fragmented.
  1172. //
  1173. for (CheckType = (EFI_MEMORY_TYPE)0; CheckType < EfiMaxMemoryType; CheckType++) {
  1174. if ((MemoryType != CheckType) &&
  1175. mMemoryTypeStatistics[CheckType].Special &&
  1176. (mMemoryTypeStatistics[CheckType].NumberOfPages > 0))
  1177. {
  1178. if ((Start >= mMemoryTypeStatistics[CheckType].BaseAddress) &&
  1179. (Start <= mMemoryTypeStatistics[CheckType].MaximumAddress))
  1180. {
  1181. return EFI_NOT_FOUND;
  1182. }
  1183. if ((End >= mMemoryTypeStatistics[CheckType].BaseAddress) &&
  1184. (End <= mMemoryTypeStatistics[CheckType].MaximumAddress))
  1185. {
  1186. return EFI_NOT_FOUND;
  1187. }
  1188. if ((Start < mMemoryTypeStatistics[CheckType].BaseAddress) &&
  1189. (End > mMemoryTypeStatistics[CheckType].MaximumAddress))
  1190. {
  1191. return EFI_NOT_FOUND;
  1192. }
  1193. }
  1194. }
  1195. }
  1196. if (Type == AllocateMaxAddress) {
  1197. MaxAddress = Start;
  1198. }
  1199. CoreAcquireMemoryLock ();
  1200. //
  1201. // If not a specific address, then find an address to allocate
  1202. //
  1203. if (Type != AllocateAddress) {
  1204. Start = FindFreePages (
  1205. MaxAddress,
  1206. NumberOfPages,
  1207. MemoryType,
  1208. Alignment,
  1209. NeedGuard
  1210. );
  1211. if (Start == 0) {
  1212. Status = EFI_OUT_OF_RESOURCES;
  1213. goto Done;
  1214. }
  1215. }
  1216. //
  1217. // Convert pages from FreeMemory to the requested type
  1218. //
  1219. if (NeedGuard) {
  1220. Status = CoreConvertPagesWithGuard (Start, NumberOfPages, MemoryType);
  1221. } else {
  1222. Status = CoreConvertPages (Start, NumberOfPages, MemoryType);
  1223. }
  1224. if (EFI_ERROR (Status)) {
  1225. //
  1226. // If requested memory region is unavailable it may be untested memory
  1227. // Attempt to promote memory resources, then re-attempt the allocation
  1228. //
  1229. if (PromoteMemoryResource ()) {
  1230. if (NeedGuard) {
  1231. Status = CoreConvertPagesWithGuard (Start, NumberOfPages, MemoryType);
  1232. } else {
  1233. Status = CoreConvertPages (Start, NumberOfPages, MemoryType);
  1234. }
  1235. }
  1236. }
  1237. Done:
  1238. CoreReleaseMemoryLock ();
  1239. if (!EFI_ERROR (Status)) {
  1240. if (NeedGuard) {
  1241. SetGuardForMemory (Start, NumberOfPages);
  1242. }
  1243. *Memory = Start;
  1244. }
  1245. return Status;
  1246. }
  1247. /**
  1248. Allocates pages from the memory map.
  1249. @param Type The type of allocation to perform
  1250. @param MemoryType The type of memory to turn the allocated pages
  1251. into
  1252. @param NumberOfPages The number of pages to allocate
  1253. @param Memory A pointer to receive the base allocated memory
  1254. address
  1255. @return Status. On success, Memory is filled in with the base address allocated
  1256. @retval EFI_INVALID_PARAMETER Parameters violate checking rules defined in
  1257. spec.
  1258. @retval EFI_NOT_FOUND Could not allocate pages match the requirement.
  1259. @retval EFI_OUT_OF_RESOURCES No enough pages to allocate.
  1260. @retval EFI_SUCCESS Pages successfully allocated.
  1261. **/
  1262. EFI_STATUS
  1263. EFIAPI
  1264. CoreAllocatePages (
  1265. IN EFI_ALLOCATE_TYPE Type,
  1266. IN EFI_MEMORY_TYPE MemoryType,
  1267. IN UINTN NumberOfPages,
  1268. OUT EFI_PHYSICAL_ADDRESS *Memory
  1269. )
  1270. {
  1271. EFI_STATUS Status;
  1272. BOOLEAN NeedGuard;
  1273. NeedGuard = IsPageTypeToGuard (MemoryType, Type) && !mOnGuarding;
  1274. Status = CoreInternalAllocatePages (
  1275. Type,
  1276. MemoryType,
  1277. NumberOfPages,
  1278. Memory,
  1279. NeedGuard
  1280. );
  1281. if (!EFI_ERROR (Status)) {
  1282. CoreUpdateProfile (
  1283. (EFI_PHYSICAL_ADDRESS)(UINTN)RETURN_ADDRESS (0),
  1284. MemoryProfileActionAllocatePages,
  1285. MemoryType,
  1286. EFI_PAGES_TO_SIZE (NumberOfPages),
  1287. (VOID *)(UINTN)*Memory,
  1288. NULL
  1289. );
  1290. InstallMemoryAttributesTableOnMemoryAllocation (MemoryType);
  1291. ApplyMemoryProtectionPolicy (
  1292. EfiConventionalMemory,
  1293. MemoryType,
  1294. *Memory,
  1295. EFI_PAGES_TO_SIZE (NumberOfPages)
  1296. );
  1297. }
  1298. return Status;
  1299. }
  1300. /**
  1301. Frees previous allocated pages.
  1302. @param Memory Base address of memory being freed
  1303. @param NumberOfPages The number of pages to free
  1304. @param MemoryType Pointer to memory type
  1305. @retval EFI_NOT_FOUND Could not find the entry that covers the range
  1306. @retval EFI_INVALID_PARAMETER Address not aligned
  1307. @return EFI_SUCCESS -Pages successfully freed.
  1308. **/
  1309. EFI_STATUS
  1310. EFIAPI
  1311. CoreInternalFreePages (
  1312. IN EFI_PHYSICAL_ADDRESS Memory,
  1313. IN UINTN NumberOfPages,
  1314. OUT EFI_MEMORY_TYPE *MemoryType OPTIONAL
  1315. )
  1316. {
  1317. EFI_STATUS Status;
  1318. LIST_ENTRY *Link;
  1319. MEMORY_MAP *Entry;
  1320. UINTN Alignment;
  1321. BOOLEAN IsGuarded;
  1322. //
  1323. // Free the range
  1324. //
  1325. CoreAcquireMemoryLock ();
  1326. //
  1327. // Find the entry that the covers the range
  1328. //
  1329. IsGuarded = FALSE;
  1330. Entry = NULL;
  1331. for (Link = gMemoryMap.ForwardLink; Link != &gMemoryMap; Link = Link->ForwardLink) {
  1332. Entry = CR (Link, MEMORY_MAP, Link, MEMORY_MAP_SIGNATURE);
  1333. if ((Entry->Start <= Memory) && (Entry->End > Memory)) {
  1334. break;
  1335. }
  1336. }
  1337. if (Link == &gMemoryMap) {
  1338. Status = EFI_NOT_FOUND;
  1339. goto Done;
  1340. }
  1341. Alignment = DEFAULT_PAGE_ALLOCATION_GRANULARITY;
  1342. ASSERT (Entry != NULL);
  1343. if ((Entry->Type == EfiACPIReclaimMemory) ||
  1344. (Entry->Type == EfiACPIMemoryNVS) ||
  1345. (Entry->Type == EfiRuntimeServicesCode) ||
  1346. (Entry->Type == EfiRuntimeServicesData))
  1347. {
  1348. Alignment = RUNTIME_PAGE_ALLOCATION_GRANULARITY;
  1349. }
  1350. if ((Memory & (Alignment - 1)) != 0) {
  1351. Status = EFI_INVALID_PARAMETER;
  1352. goto Done;
  1353. }
  1354. NumberOfPages += EFI_SIZE_TO_PAGES (Alignment) - 1;
  1355. NumberOfPages &= ~(EFI_SIZE_TO_PAGES (Alignment) - 1);
  1356. if (MemoryType != NULL) {
  1357. *MemoryType = Entry->Type;
  1358. }
  1359. IsGuarded = IsPageTypeToGuard (Entry->Type, AllocateAnyPages) &&
  1360. IsMemoryGuarded (Memory);
  1361. if (IsGuarded) {
  1362. Status = CoreConvertPagesWithGuard (
  1363. Memory,
  1364. NumberOfPages,
  1365. EfiConventionalMemory
  1366. );
  1367. } else {
  1368. Status = CoreConvertPages (Memory, NumberOfPages, EfiConventionalMemory);
  1369. }
  1370. Done:
  1371. CoreReleaseMemoryLock ();
  1372. return Status;
  1373. }
  1374. /**
  1375. Frees previous allocated pages.
  1376. @param Memory Base address of memory being freed
  1377. @param NumberOfPages The number of pages to free
  1378. @retval EFI_NOT_FOUND Could not find the entry that covers the range
  1379. @retval EFI_INVALID_PARAMETER Address not aligned
  1380. @return EFI_SUCCESS -Pages successfully freed.
  1381. **/
  1382. EFI_STATUS
  1383. EFIAPI
  1384. CoreFreePages (
  1385. IN EFI_PHYSICAL_ADDRESS Memory,
  1386. IN UINTN NumberOfPages
  1387. )
  1388. {
  1389. EFI_STATUS Status;
  1390. EFI_MEMORY_TYPE MemoryType;
  1391. Status = CoreInternalFreePages (Memory, NumberOfPages, &MemoryType);
  1392. if (!EFI_ERROR (Status)) {
  1393. GuardFreedPagesChecked (Memory, NumberOfPages);
  1394. CoreUpdateProfile (
  1395. (EFI_PHYSICAL_ADDRESS)(UINTN)RETURN_ADDRESS (0),
  1396. MemoryProfileActionFreePages,
  1397. MemoryType,
  1398. EFI_PAGES_TO_SIZE (NumberOfPages),
  1399. (VOID *)(UINTN)Memory,
  1400. NULL
  1401. );
  1402. InstallMemoryAttributesTableOnMemoryAllocation (MemoryType);
  1403. ApplyMemoryProtectionPolicy (
  1404. MemoryType,
  1405. EfiConventionalMemory,
  1406. Memory,
  1407. EFI_PAGES_TO_SIZE (NumberOfPages)
  1408. );
  1409. }
  1410. return Status;
  1411. }
  1412. /**
  1413. This function checks to see if the last memory map descriptor in a memory map
  1414. can be merged with any of the other memory map descriptors in a memorymap.
  1415. Memory descriptors may be merged if they are adjacent and have the same type
  1416. and attributes.
  1417. @param MemoryMap A pointer to the start of the memory map.
  1418. @param MemoryMapDescriptor A pointer to the last descriptor in MemoryMap.
  1419. @param DescriptorSize The size, in bytes, of an individual
  1420. EFI_MEMORY_DESCRIPTOR.
  1421. @return A pointer to the next available descriptor in MemoryMap
  1422. **/
  1423. EFI_MEMORY_DESCRIPTOR *
  1424. MergeMemoryMapDescriptor (
  1425. IN EFI_MEMORY_DESCRIPTOR *MemoryMap,
  1426. IN EFI_MEMORY_DESCRIPTOR *MemoryMapDescriptor,
  1427. IN UINTN DescriptorSize
  1428. )
  1429. {
  1430. //
  1431. // Traverse the array of descriptors in MemoryMap
  1432. //
  1433. for ( ; MemoryMap != MemoryMapDescriptor; MemoryMap = NEXT_MEMORY_DESCRIPTOR (MemoryMap, DescriptorSize)) {
  1434. //
  1435. // Check to see if the Type fields are identical.
  1436. //
  1437. if (MemoryMap->Type != MemoryMapDescriptor->Type) {
  1438. continue;
  1439. }
  1440. //
  1441. // Check to see if the Attribute fields are identical.
  1442. //
  1443. if (MemoryMap->Attribute != MemoryMapDescriptor->Attribute) {
  1444. continue;
  1445. }
  1446. //
  1447. // Check to see if MemoryMapDescriptor is immediately above MemoryMap
  1448. //
  1449. if (MemoryMap->PhysicalStart + EFI_PAGES_TO_SIZE ((UINTN)MemoryMap->NumberOfPages) == MemoryMapDescriptor->PhysicalStart) {
  1450. //
  1451. // Merge MemoryMapDescriptor into MemoryMap
  1452. //
  1453. MemoryMap->NumberOfPages += MemoryMapDescriptor->NumberOfPages;
  1454. //
  1455. // Return MemoryMapDescriptor as the next available slot int he MemoryMap array
  1456. //
  1457. return MemoryMapDescriptor;
  1458. }
  1459. //
  1460. // Check to see if MemoryMapDescriptor is immediately below MemoryMap
  1461. //
  1462. if (MemoryMap->PhysicalStart - EFI_PAGES_TO_SIZE ((UINTN)MemoryMapDescriptor->NumberOfPages) == MemoryMapDescriptor->PhysicalStart) {
  1463. //
  1464. // Merge MemoryMapDescriptor into MemoryMap
  1465. //
  1466. MemoryMap->PhysicalStart = MemoryMapDescriptor->PhysicalStart;
  1467. MemoryMap->VirtualStart = MemoryMapDescriptor->VirtualStart;
  1468. MemoryMap->NumberOfPages += MemoryMapDescriptor->NumberOfPages;
  1469. //
  1470. // Return MemoryMapDescriptor as the next available slot int he MemoryMap array
  1471. //
  1472. return MemoryMapDescriptor;
  1473. }
  1474. }
  1475. //
  1476. // MemoryMapDescrtiptor could not be merged with any descriptors in MemoryMap.
  1477. //
  1478. // Return the slot immediately after MemoryMapDescriptor as the next available
  1479. // slot in the MemoryMap array
  1480. //
  1481. return NEXT_MEMORY_DESCRIPTOR (MemoryMapDescriptor, DescriptorSize);
  1482. }
  1483. /**
  1484. This function returns a copy of the current memory map. The map is an array of
  1485. memory descriptors, each of which describes a contiguous block of memory.
  1486. @param MemoryMapSize A pointer to the size, in bytes, of the
  1487. MemoryMap buffer. On input, this is the size of
  1488. the buffer allocated by the caller. On output,
  1489. it is the size of the buffer returned by the
  1490. firmware if the buffer was large enough, or the
  1491. size of the buffer needed to contain the map if
  1492. the buffer was too small.
  1493. @param MemoryMap A pointer to the buffer in which firmware places
  1494. the current memory map.
  1495. @param MapKey A pointer to the location in which firmware
  1496. returns the key for the current memory map.
  1497. @param DescriptorSize A pointer to the location in which firmware
  1498. returns the size, in bytes, of an individual
  1499. EFI_MEMORY_DESCRIPTOR.
  1500. @param DescriptorVersion A pointer to the location in which firmware
  1501. returns the version number associated with the
  1502. EFI_MEMORY_DESCRIPTOR.
  1503. @retval EFI_SUCCESS The memory map was returned in the MemoryMap
  1504. buffer.
  1505. @retval EFI_BUFFER_TOO_SMALL The MemoryMap buffer was too small. The current
  1506. buffer size needed to hold the memory map is
  1507. returned in MemoryMapSize.
  1508. @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value.
  1509. **/
  1510. EFI_STATUS
  1511. EFIAPI
  1512. CoreGetMemoryMap (
  1513. IN OUT UINTN *MemoryMapSize,
  1514. IN OUT EFI_MEMORY_DESCRIPTOR *MemoryMap,
  1515. OUT UINTN *MapKey,
  1516. OUT UINTN *DescriptorSize,
  1517. OUT UINT32 *DescriptorVersion
  1518. )
  1519. {
  1520. EFI_STATUS Status;
  1521. UINTN Size;
  1522. UINTN BufferSize;
  1523. UINTN NumberOfEntries;
  1524. LIST_ENTRY *Link;
  1525. MEMORY_MAP *Entry;
  1526. EFI_GCD_MAP_ENTRY *GcdMapEntry;
  1527. EFI_GCD_MAP_ENTRY MergeGcdMapEntry;
  1528. EFI_MEMORY_TYPE Type;
  1529. EFI_MEMORY_DESCRIPTOR *MemoryMapStart;
  1530. EFI_MEMORY_DESCRIPTOR *MemoryMapEnd;
  1531. //
  1532. // Make sure the parameters are valid
  1533. //
  1534. if (MemoryMapSize == NULL) {
  1535. return EFI_INVALID_PARAMETER;
  1536. }
  1537. CoreAcquireGcdMemoryLock ();
  1538. //
  1539. // Count the number of Reserved and runtime MMIO entries
  1540. // And, count the number of Persistent entries.
  1541. //
  1542. NumberOfEntries = 0;
  1543. for (Link = mGcdMemorySpaceMap.ForwardLink; Link != &mGcdMemorySpaceMap; Link = Link->ForwardLink) {
  1544. GcdMapEntry = CR (Link, EFI_GCD_MAP_ENTRY, Link, EFI_GCD_MAP_SIGNATURE);
  1545. if ((GcdMapEntry->GcdMemoryType == EfiGcdMemoryTypePersistent) ||
  1546. (GcdMapEntry->GcdMemoryType == EfiGcdMemoryTypeReserved) ||
  1547. ((GcdMapEntry->GcdMemoryType == EfiGcdMemoryTypeMemoryMappedIo) &&
  1548. ((GcdMapEntry->Attributes & EFI_MEMORY_RUNTIME) == EFI_MEMORY_RUNTIME)))
  1549. {
  1550. NumberOfEntries++;
  1551. }
  1552. }
  1553. Size = sizeof (EFI_MEMORY_DESCRIPTOR);
  1554. //
  1555. // Make sure Size != sizeof(EFI_MEMORY_DESCRIPTOR). This will
  1556. // prevent people from having pointer math bugs in their code.
  1557. // now you have to use *DescriptorSize to make things work.
  1558. //
  1559. Size += sizeof (UINT64) - (Size % sizeof (UINT64));
  1560. if (DescriptorSize != NULL) {
  1561. *DescriptorSize = Size;
  1562. }
  1563. if (DescriptorVersion != NULL) {
  1564. *DescriptorVersion = EFI_MEMORY_DESCRIPTOR_VERSION;
  1565. }
  1566. CoreAcquireMemoryLock ();
  1567. //
  1568. // Compute the buffer size needed to fit the entire map
  1569. //
  1570. BufferSize = Size * NumberOfEntries;
  1571. for (Link = gMemoryMap.ForwardLink; Link != &gMemoryMap; Link = Link->ForwardLink) {
  1572. BufferSize += Size;
  1573. }
  1574. if (*MemoryMapSize < BufferSize) {
  1575. Status = EFI_BUFFER_TOO_SMALL;
  1576. goto Done;
  1577. }
  1578. if (MemoryMap == NULL) {
  1579. Status = EFI_INVALID_PARAMETER;
  1580. goto Done;
  1581. }
  1582. //
  1583. // Build the map
  1584. //
  1585. ZeroMem (MemoryMap, BufferSize);
  1586. MemoryMapStart = MemoryMap;
  1587. for (Link = gMemoryMap.ForwardLink; Link != &gMemoryMap; Link = Link->ForwardLink) {
  1588. Entry = CR (Link, MEMORY_MAP, Link, MEMORY_MAP_SIGNATURE);
  1589. ASSERT (Entry->VirtualStart == 0);
  1590. //
  1591. // Convert internal map into an EFI_MEMORY_DESCRIPTOR
  1592. //
  1593. MemoryMap->Type = Entry->Type;
  1594. MemoryMap->PhysicalStart = Entry->Start;
  1595. MemoryMap->VirtualStart = Entry->VirtualStart;
  1596. MemoryMap->NumberOfPages = RShiftU64 (Entry->End - Entry->Start + 1, EFI_PAGE_SHIFT);
  1597. //
  1598. // If the memory type is EfiConventionalMemory, then determine if the range is part of a
  1599. // memory type bin and needs to be converted to the same memory type as the rest of the
  1600. // memory type bin in order to minimize EFI Memory Map changes across reboots. This
  1601. // improves the chances for a successful S4 resume in the presence of minor page allocation
  1602. // differences across reboots.
  1603. //
  1604. if (MemoryMap->Type == EfiConventionalMemory) {
  1605. for (Type = (EFI_MEMORY_TYPE)0; Type < EfiMaxMemoryType; Type++) {
  1606. if (mMemoryTypeStatistics[Type].Special &&
  1607. (mMemoryTypeStatistics[Type].NumberOfPages > 0) &&
  1608. (Entry->Start >= mMemoryTypeStatistics[Type].BaseAddress) &&
  1609. (Entry->End <= mMemoryTypeStatistics[Type].MaximumAddress))
  1610. {
  1611. MemoryMap->Type = Type;
  1612. }
  1613. }
  1614. }
  1615. MemoryMap->Attribute = Entry->Attribute;
  1616. if (MemoryMap->Type < EfiMaxMemoryType) {
  1617. if (mMemoryTypeStatistics[MemoryMap->Type].Runtime) {
  1618. MemoryMap->Attribute |= EFI_MEMORY_RUNTIME;
  1619. }
  1620. }
  1621. //
  1622. // Check to see if the new Memory Map Descriptor can be merged with an
  1623. // existing descriptor if they are adjacent and have the same attributes
  1624. //
  1625. MemoryMap = MergeMemoryMapDescriptor (MemoryMapStart, MemoryMap, Size);
  1626. }
  1627. ZeroMem (&MergeGcdMapEntry, sizeof (MergeGcdMapEntry));
  1628. GcdMapEntry = NULL;
  1629. for (Link = mGcdMemorySpaceMap.ForwardLink; ; Link = Link->ForwardLink) {
  1630. if (Link != &mGcdMemorySpaceMap) {
  1631. //
  1632. // Merge adjacent same type and attribute GCD memory range
  1633. //
  1634. GcdMapEntry = CR (Link, EFI_GCD_MAP_ENTRY, Link, EFI_GCD_MAP_SIGNATURE);
  1635. if ((MergeGcdMapEntry.Capabilities == GcdMapEntry->Capabilities) &&
  1636. (MergeGcdMapEntry.Attributes == GcdMapEntry->Attributes) &&
  1637. (MergeGcdMapEntry.GcdMemoryType == GcdMapEntry->GcdMemoryType) &&
  1638. (MergeGcdMapEntry.GcdIoType == GcdMapEntry->GcdIoType))
  1639. {
  1640. MergeGcdMapEntry.EndAddress = GcdMapEntry->EndAddress;
  1641. continue;
  1642. }
  1643. }
  1644. if ((MergeGcdMapEntry.GcdMemoryType == EfiGcdMemoryTypeReserved) ||
  1645. ((MergeGcdMapEntry.GcdMemoryType == EfiGcdMemoryTypeMemoryMappedIo) &&
  1646. ((MergeGcdMapEntry.Attributes & EFI_MEMORY_RUNTIME) == EFI_MEMORY_RUNTIME)))
  1647. {
  1648. //
  1649. // Page Align GCD range is required. When it is converted to EFI_MEMORY_DESCRIPTOR,
  1650. // it will be recorded as page PhysicalStart and NumberOfPages.
  1651. //
  1652. ASSERT ((MergeGcdMapEntry.BaseAddress & EFI_PAGE_MASK) == 0);
  1653. ASSERT (((MergeGcdMapEntry.EndAddress - MergeGcdMapEntry.BaseAddress + 1) & EFI_PAGE_MASK) == 0);
  1654. //
  1655. // Create EFI_MEMORY_DESCRIPTOR for every Reserved and runtime MMIO GCD entries
  1656. //
  1657. MemoryMap->PhysicalStart = MergeGcdMapEntry.BaseAddress;
  1658. MemoryMap->VirtualStart = 0;
  1659. MemoryMap->NumberOfPages = RShiftU64 ((MergeGcdMapEntry.EndAddress - MergeGcdMapEntry.BaseAddress + 1), EFI_PAGE_SHIFT);
  1660. MemoryMap->Attribute = (MergeGcdMapEntry.Attributes & ~EFI_MEMORY_PORT_IO) |
  1661. (MergeGcdMapEntry.Capabilities & (EFI_CACHE_ATTRIBUTE_MASK | EFI_MEMORY_ATTRIBUTE_MASK));
  1662. if (MergeGcdMapEntry.GcdMemoryType == EfiGcdMemoryTypeReserved) {
  1663. MemoryMap->Type = EfiReservedMemoryType;
  1664. } else if (MergeGcdMapEntry.GcdMemoryType == EfiGcdMemoryTypeMemoryMappedIo) {
  1665. if ((MergeGcdMapEntry.Attributes & EFI_MEMORY_PORT_IO) == EFI_MEMORY_PORT_IO) {
  1666. MemoryMap->Type = EfiMemoryMappedIOPortSpace;
  1667. } else {
  1668. MemoryMap->Type = EfiMemoryMappedIO;
  1669. }
  1670. }
  1671. //
  1672. // Check to see if the new Memory Map Descriptor can be merged with an
  1673. // existing descriptor if they are adjacent and have the same attributes
  1674. //
  1675. MemoryMap = MergeMemoryMapDescriptor (MemoryMapStart, MemoryMap, Size);
  1676. }
  1677. if (MergeGcdMapEntry.GcdMemoryType == EfiGcdMemoryTypePersistent) {
  1678. //
  1679. // Page Align GCD range is required. When it is converted to EFI_MEMORY_DESCRIPTOR,
  1680. // it will be recorded as page PhysicalStart and NumberOfPages.
  1681. //
  1682. ASSERT ((MergeGcdMapEntry.BaseAddress & EFI_PAGE_MASK) == 0);
  1683. ASSERT (((MergeGcdMapEntry.EndAddress - MergeGcdMapEntry.BaseAddress + 1) & EFI_PAGE_MASK) == 0);
  1684. //
  1685. // Create EFI_MEMORY_DESCRIPTOR for every Persistent GCD entries
  1686. //
  1687. MemoryMap->PhysicalStart = MergeGcdMapEntry.BaseAddress;
  1688. MemoryMap->VirtualStart = 0;
  1689. MemoryMap->NumberOfPages = RShiftU64 ((MergeGcdMapEntry.EndAddress - MergeGcdMapEntry.BaseAddress + 1), EFI_PAGE_SHIFT);
  1690. MemoryMap->Attribute = MergeGcdMapEntry.Attributes | EFI_MEMORY_NV |
  1691. (MergeGcdMapEntry.Capabilities & (EFI_CACHE_ATTRIBUTE_MASK | EFI_MEMORY_ATTRIBUTE_MASK));
  1692. MemoryMap->Type = EfiPersistentMemory;
  1693. //
  1694. // Check to see if the new Memory Map Descriptor can be merged with an
  1695. // existing descriptor if they are adjacent and have the same attributes
  1696. //
  1697. MemoryMap = MergeMemoryMapDescriptor (MemoryMapStart, MemoryMap, Size);
  1698. }
  1699. if (MergeGcdMapEntry.GcdMemoryType == EFI_GCD_MEMORY_TYPE_UNACCEPTED) {
  1700. //
  1701. // Page Align GCD range is required. When it is converted to EFI_MEMORY_DESCRIPTOR,
  1702. // it will be recorded as page PhysicalStart and NumberOfPages.
  1703. //
  1704. ASSERT ((MergeGcdMapEntry.BaseAddress & EFI_PAGE_MASK) == 0);
  1705. ASSERT (((MergeGcdMapEntry.EndAddress - MergeGcdMapEntry.BaseAddress + 1) & EFI_PAGE_MASK) == 0);
  1706. //
  1707. // Create EFI_MEMORY_DESCRIPTOR for every Unaccepted GCD entries
  1708. //
  1709. MemoryMap->PhysicalStart = MergeGcdMapEntry.BaseAddress;
  1710. MemoryMap->VirtualStart = 0;
  1711. MemoryMap->NumberOfPages = RShiftU64 ((MergeGcdMapEntry.EndAddress - MergeGcdMapEntry.BaseAddress + 1), EFI_PAGE_SHIFT);
  1712. MemoryMap->Attribute = MergeGcdMapEntry.Attributes |
  1713. (MergeGcdMapEntry.Capabilities & (EFI_MEMORY_RP | EFI_MEMORY_WP | EFI_MEMORY_XP | EFI_MEMORY_RO |
  1714. EFI_MEMORY_UC | EFI_MEMORY_UCE | EFI_MEMORY_WC | EFI_MEMORY_WT | EFI_MEMORY_WB));
  1715. MemoryMap->Type = EfiUnacceptedMemoryType;
  1716. //
  1717. // Check to see if the new Memory Map Descriptor can be merged with an
  1718. // existing descriptor if they are adjacent and have the same attributes
  1719. //
  1720. MemoryMap = MergeMemoryMapDescriptor (MemoryMapStart, MemoryMap, Size);
  1721. }
  1722. if (Link == &mGcdMemorySpaceMap) {
  1723. //
  1724. // break loop when arrive at head.
  1725. //
  1726. break;
  1727. }
  1728. if (GcdMapEntry != NULL) {
  1729. //
  1730. // Copy new GCD map entry for the following GCD range merge
  1731. //
  1732. CopyMem (&MergeGcdMapEntry, GcdMapEntry, sizeof (MergeGcdMapEntry));
  1733. }
  1734. }
  1735. //
  1736. // Compute the size of the buffer actually used after all memory map descriptor merge operations
  1737. //
  1738. BufferSize = ((UINT8 *)MemoryMap - (UINT8 *)MemoryMapStart);
  1739. //
  1740. // Note: Some OSs will treat EFI_MEMORY_DESCRIPTOR.Attribute as really
  1741. // set attributes and change memory paging attribute accordingly.
  1742. // But current EFI_MEMORY_DESCRIPTOR.Attribute is assigned by
  1743. // value from Capabilities in GCD memory map. This might cause
  1744. // boot problems. Clearing all page-access permission related
  1745. // capabilities can workaround it. Following code is supposed to
  1746. // be removed once the usage of EFI_MEMORY_DESCRIPTOR.Attribute
  1747. // is clarified in UEFI spec and adopted by both EDK-II Core and
  1748. // all supported OSs.
  1749. //
  1750. MemoryMapEnd = MemoryMap;
  1751. MemoryMap = MemoryMapStart;
  1752. while (MemoryMap < MemoryMapEnd) {
  1753. MemoryMap->Attribute &= ~(UINT64)EFI_MEMORY_ACCESS_MASK;
  1754. MemoryMap = NEXT_MEMORY_DESCRIPTOR (MemoryMap, Size);
  1755. }
  1756. MergeMemoryMap (MemoryMapStart, &BufferSize, Size);
  1757. MemoryMapEnd = (EFI_MEMORY_DESCRIPTOR *)((UINT8 *)MemoryMapStart + BufferSize);
  1758. Status = EFI_SUCCESS;
  1759. Done:
  1760. //
  1761. // Update the map key finally
  1762. //
  1763. if (MapKey != NULL) {
  1764. *MapKey = mMemoryMapKey;
  1765. }
  1766. CoreReleaseMemoryLock ();
  1767. CoreReleaseGcdMemoryLock ();
  1768. *MemoryMapSize = BufferSize;
  1769. DEBUG_CODE (
  1770. DumpGuardedMemoryBitmap ();
  1771. );
  1772. return Status;
  1773. }
  1774. /**
  1775. Internal function. Used by the pool functions to allocate pages
  1776. to back pool allocation requests.
  1777. @param PoolType The type of memory for the new pool pages
  1778. @param NumberOfPages No of pages to allocate
  1779. @param Alignment Bits to align.
  1780. @param NeedGuard Flag to indicate Guard page is needed or not
  1781. @return The allocated memory, or NULL
  1782. **/
  1783. VOID *
  1784. CoreAllocatePoolPages (
  1785. IN EFI_MEMORY_TYPE PoolType,
  1786. IN UINTN NumberOfPages,
  1787. IN UINTN Alignment,
  1788. IN BOOLEAN NeedGuard
  1789. )
  1790. {
  1791. UINT64 Start;
  1792. //
  1793. // Find the pages to convert
  1794. //
  1795. Start = FindFreePages (
  1796. MAX_ALLOC_ADDRESS,
  1797. NumberOfPages,
  1798. PoolType,
  1799. Alignment,
  1800. NeedGuard
  1801. );
  1802. //
  1803. // Convert it to boot services data
  1804. //
  1805. if (Start == 0) {
  1806. DEBUG ((DEBUG_ERROR | DEBUG_PAGE, "AllocatePoolPages: failed to allocate %d pages\n", (UINT32)NumberOfPages));
  1807. } else {
  1808. if (NeedGuard) {
  1809. CoreConvertPagesWithGuard (Start, NumberOfPages, PoolType);
  1810. } else {
  1811. CoreConvertPages (Start, NumberOfPages, PoolType);
  1812. }
  1813. }
  1814. return (VOID *)(UINTN)Start;
  1815. }
  1816. /**
  1817. Internal function. Frees pool pages allocated via AllocatePoolPages ()
  1818. @param Memory The base address to free
  1819. @param NumberOfPages The number of pages to free
  1820. **/
  1821. VOID
  1822. CoreFreePoolPages (
  1823. IN EFI_PHYSICAL_ADDRESS Memory,
  1824. IN UINTN NumberOfPages
  1825. )
  1826. {
  1827. CoreConvertPages (Memory, NumberOfPages, EfiConventionalMemory);
  1828. }
  1829. /**
  1830. Make sure the memory map is following all the construction rules,
  1831. it is the last time to check memory map error before exit boot services.
  1832. @param MapKey Memory map key
  1833. @retval EFI_INVALID_PARAMETER Memory map not consistent with construction
  1834. rules.
  1835. @retval EFI_SUCCESS Valid memory map.
  1836. **/
  1837. EFI_STATUS
  1838. CoreTerminateMemoryMap (
  1839. IN UINTN MapKey
  1840. )
  1841. {
  1842. EFI_STATUS Status;
  1843. LIST_ENTRY *Link;
  1844. MEMORY_MAP *Entry;
  1845. Status = EFI_SUCCESS;
  1846. CoreAcquireMemoryLock ();
  1847. if (MapKey == mMemoryMapKey) {
  1848. //
  1849. // Make sure the memory map is following all the construction rules
  1850. // This is the last chance we will be able to display any messages on
  1851. // the console devices.
  1852. //
  1853. for (Link = gMemoryMap.ForwardLink; Link != &gMemoryMap; Link = Link->ForwardLink) {
  1854. Entry = CR (Link, MEMORY_MAP, Link, MEMORY_MAP_SIGNATURE);
  1855. if (Entry->Type < EfiMaxMemoryType) {
  1856. if (mMemoryTypeStatistics[Entry->Type].Runtime) {
  1857. ASSERT (Entry->Type != EfiACPIReclaimMemory);
  1858. ASSERT (Entry->Type != EfiACPIMemoryNVS);
  1859. if ((Entry->Start & (RUNTIME_PAGE_ALLOCATION_GRANULARITY - 1)) != 0) {
  1860. DEBUG ((DEBUG_ERROR | DEBUG_PAGE, "ExitBootServices: A RUNTIME memory entry is not on a proper alignment.\n"));
  1861. Status = EFI_INVALID_PARAMETER;
  1862. goto Done;
  1863. }
  1864. if (((Entry->End + 1) & (RUNTIME_PAGE_ALLOCATION_GRANULARITY - 1)) != 0) {
  1865. DEBUG ((DEBUG_ERROR | DEBUG_PAGE, "ExitBootServices: A RUNTIME memory entry is not on a proper alignment.\n"));
  1866. Status = EFI_INVALID_PARAMETER;
  1867. goto Done;
  1868. }
  1869. }
  1870. }
  1871. }
  1872. //
  1873. // The map key they gave us matches what we expect. Fall through and
  1874. // return success. In an ideal world we would clear out all of
  1875. // EfiBootServicesCode and EfiBootServicesData. However this function
  1876. // is not the last one called by ExitBootServices(), so we have to
  1877. // preserve the memory contents.
  1878. //
  1879. } else {
  1880. Status = EFI_INVALID_PARAMETER;
  1881. }
  1882. Done:
  1883. CoreReleaseMemoryLock ();
  1884. return Status;
  1885. }