memory.c 51 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096
  1. /*++
  2. Copyright (c) 2014 Minoca Corp. All Rights Reserved
  3. Module Name:
  4. memory.c
  5. Abstract:
  6. This module implements core UEFI memory map services.
  7. Author:
  8. Evan Green 27-Feb-2014
  9. Environment:
  10. Firmware
  11. --*/
  12. //
  13. // ------------------------------------------------------------------- Includes
  14. //
  15. #include "ueficore.h"
  16. //
  17. // ---------------------------------------------------------------- Definitions
  18. //
  19. #define EFI_DEFAULT_PAGE_ALLOCATION_ALIGNMENT EFI_PAGE_SIZE
  20. #define EFI_ACPI_RUNTIME_PAGE_ALLOCATION_ALIGNMENT EFI_PAGE_SIZE
  21. //
  22. // Define the maximum number of temporary descriptors that will ever be
  23. // needed simultaneously.
  24. //
  25. #define EFI_DESCRIPTOR_STACK_SIZE 6
  26. //
  27. // ------------------------------------------------------ Data Type Definitions
  28. //
  29. typedef struct _EFI_MEMORY_TYPE_STATISTICS {
  30. EFI_PHYSICAL_ADDRESS BaseAddress;
  31. EFI_PHYSICAL_ADDRESS MaximumAddress;
  32. UINT64 CurrentPageCount;
  33. UINT64 PageCount;
  34. UINTN InformationIndex;
  35. BOOLEAN Special;
  36. BOOLEAN Runtime;
  37. } EFI_MEMORY_TYPE_STATISTICS, *PEFI_MEMORY_TYPE_STATISTICS;
  38. typedef struct _EFI_MEMORY_TYPE_INFORMATION {
  39. UINT32 Type;
  40. UINT32 PageCount;
  41. } EFI_MEMORY_TYPE_INFORMATION, *PEFI_MEMORY_TYPE_INFORMATION;
  42. typedef struct _EFI_MEMORY_MAP_ENTRY {
  43. LIST_ENTRY ListEntry;
  44. BOOL Temporary;
  45. EFI_MEMORY_DESCRIPTOR Descriptor;
  46. } EFI_MEMORY_MAP_ENTRY, *PEFI_MEMORY_MAP_ENTRY;
  47. //
  48. // ----------------------------------------------- Internal Function Prototypes
  49. //
  50. VOID
  51. EfipCoreAddMemoryDescriptor (
  52. EFI_MEMORY_TYPE Type,
  53. EFI_PHYSICAL_ADDRESS Start,
  54. UINT64 PageCount,
  55. UINT64 Attribute
  56. );
  57. UINT64
  58. EfipCoreFindFreePages (
  59. UINT64 MaxAddress,
  60. UINT64 PageCount,
  61. EFI_MEMORY_TYPE NewType,
  62. UINTN Alignment
  63. );
  64. UINT64
  65. EfipCoreFindFreePagesInRange (
  66. UINT64 MaxAddress,
  67. UINT64 MinAddress,
  68. UINT64 PageCount,
  69. EFI_MEMORY_TYPE NewType,
  70. UINTN Alignment
  71. );
  72. EFI_STATUS
  73. EfipCoreConvertPages (
  74. UINT64 Start,
  75. UINT64 PageCount,
  76. EFI_MEMORY_TYPE NewType
  77. );
  78. VOID
  79. EfipCoreAddRange (
  80. EFI_MEMORY_TYPE Type,
  81. EFI_PHYSICAL_ADDRESS Start,
  82. EFI_PHYSICAL_ADDRESS End,
  83. UINT64 Attribute
  84. );
  85. EFI_MEMORY_DESCRIPTOR *
  86. EfipCoreMergeMemoryMapDescriptor (
  87. EFI_MEMORY_DESCRIPTOR *MemoryMap,
  88. EFI_MEMORY_DESCRIPTOR *LastDescriptor,
  89. UINTN DescriptorSize
  90. );
  91. VOID
  92. EfipCoreRemoveMemoryMapEntry (
  93. PEFI_MEMORY_MAP_ENTRY Entry
  94. );
  95. VOID
  96. EfipCoreFlushMemoryMapStack (
  97. VOID
  98. );
  99. PEFI_MEMORY_MAP_ENTRY
  100. EfipCoreAllocateMemoryMapEntry (
  101. VOID
  102. );
  103. VOID
  104. EfipDebugPrintMemoryMap (
  105. EFI_MEMORY_DESCRIPTOR *Map,
  106. UINTN MapSize,
  107. UINTN DescriptorSize
  108. );
  109. VOID
  110. EfipDebugPrintMemoryDescriptor (
  111. EFI_MEMORY_DESCRIPTOR *Descriptor
  112. );
  113. //
  114. // -------------------------------------------------------------------- Globals
  115. //
  116. //
  117. // Store the memory "lock", which really just helps prevent re-entering
  118. // functions in a notify ISR.
  119. //
  120. EFI_LOCK EfiMemoryLock;
  121. //
  122. // Store the memory map itself, which is just a list of EFI_MEMORY_MAP_ENTRY
  123. // structures.
  124. //
  125. LIST_ENTRY EfiMemoryMap;
  126. //
  127. // Store the memory map key, essentially a sequence number on the memory map.
  128. //
  129. UINTN EfiMemoryMapKey;
  130. //
  131. // Store a list of free descriptors to use.
  132. //
  133. LIST_ENTRY EfiFreeDescriptorList;
  134. //
  135. // Define the default memory range to search.
  136. //
  137. EFI_PHYSICAL_ADDRESS EfiDefaultMaximumAddress = MAX_ADDRESS;
  138. EFI_PHYSICAL_ADDRESS EfiDefaultBaseAddress = MAX_ADDRESS;
  139. //
  140. // Define the stack of temporary descriptors used during operations.
  141. //
  142. UINTN EfiDescriptorStackSize = 0;
  143. EFI_MEMORY_MAP_ENTRY EfiDescriptorStack[EFI_DESCRIPTOR_STACK_SIZE];
  144. BOOLEAN EfiDescriptorStackFreeInProgress = FALSE;
  145. //
  146. // Store memory statistics, which help cluster allocations of the same type
  147. // together.
  148. //
  149. BOOLEAN EfiMemoryTypeInformationInitialized = FALSE;
  150. EFI_MEMORY_TYPE_STATISTICS EfiMemoryStatistics[EfiMaxMemoryType + 1] = {
  151. {0, MAX_ADDRESS, 0, 0, EfiMaxMemoryType, TRUE, FALSE},
  152. {0, MAX_ADDRESS, 0, 0, EfiMaxMemoryType, FALSE, FALSE},
  153. {0, MAX_ADDRESS, 0, 0, EfiMaxMemoryType, FALSE, FALSE},
  154. {0, MAX_ADDRESS, 0, 0, EfiMaxMemoryType, FALSE, FALSE},
  155. {0, MAX_ADDRESS, 0, 0, EfiMaxMemoryType, FALSE, FALSE},
  156. {0, MAX_ADDRESS, 0, 0, EfiMaxMemoryType, TRUE, TRUE},
  157. {0, MAX_ADDRESS, 0, 0, EfiMaxMemoryType, TRUE, TRUE},
  158. {0, MAX_ADDRESS, 0, 0, EfiMaxMemoryType, FALSE, FALSE},
  159. {0, MAX_ADDRESS, 0, 0, EfiMaxMemoryType, FALSE, FALSE},
  160. {0, MAX_ADDRESS, 0, 0, EfiMaxMemoryType, TRUE, FALSE},
  161. {0, MAX_ADDRESS, 0, 0, EfiMaxMemoryType, TRUE, FALSE},
  162. {0, MAX_ADDRESS, 0, 0, EfiMaxMemoryType, FALSE, FALSE},
  163. {0, MAX_ADDRESS, 0, 0, EfiMaxMemoryType, FALSE, FALSE},
  164. {0, MAX_ADDRESS, 0, 0, EfiMaxMemoryType, TRUE, TRUE},
  165. {0, MAX_ADDRESS, 0, 0, EfiMaxMemoryType, FALSE, FALSE}
  166. };
  167. EFI_MEMORY_TYPE_INFORMATION EfiMemoryTypeInformation[EfiMaxMemoryType + 1] = {
  168. {EfiReservedMemoryType, 0},
  169. {EfiLoaderCode, 0},
  170. {EfiLoaderData, 0},
  171. {EfiBootServicesCode, 0},
  172. {EfiBootServicesData, 0},
  173. {EfiRuntimeServicesCode, 0},
  174. {EfiRuntimeServicesData, 0},
  175. {EfiConventionalMemory, 0},
  176. {EfiUnusableMemory, 0},
  177. {EfiACPIReclaimMemory, 0},
  178. {EfiACPIMemoryNVS, 0},
  179. {EfiMemoryMappedIO, 0},
  180. {EfiMemoryMappedIOPortSpace, 0},
  181. {EfiPalCode, 0},
  182. {EfiMaxMemoryType, 0}
  183. };
  184. //
  185. // ------------------------------------------------------------------ Functions
  186. //
  187. EFIAPI
  188. EFI_STATUS
  189. EfiCoreAllocatePages (
  190. EFI_ALLOCATE_TYPE Type,
  191. EFI_MEMORY_TYPE MemoryType,
  192. UINTN Pages,
  193. EFI_PHYSICAL_ADDRESS *Memory
  194. )
  195. /*++
  196. Routine Description:
  197. This routine allocates memory pages from the system.
  198. Arguments:
  199. Type - Supplies the allocation strategy to use.
  200. MemoryType - Supplies the memory type of the allocation.
  201. Pages - Supplies the number of contiguous EFI_PAGE_SIZE pages.
  202. Memory - Supplies a pointer that on input contains a physical address whose
  203. use depends on the allocation strategy. On output, the physical address
  204. of the allocation will be returned.
  205. Return Value:
  206. EFI_SUCCESS on success.
  207. EFI_INVALID_PARAMETER if the Type or MemoryType are invalid, or Memory is
  208. NULL.
  209. EFI_OUT_OF_RESOURCES if the pages could not be allocated.
  210. EFI_NOT_FOUND if the requested pages could not be found.
  211. --*/
  212. {
  213. UINTN Alignment;
  214. UINT64 MaxAddress;
  215. UINT64 Start;
  216. EFI_STATUS Status;
  217. if (Type >= MaxAllocateType) {
  218. return EFI_INVALID_PARAMETER;
  219. }
  220. if ((((UINT32)MemoryType >= EfiMaxMemoryType) &&
  221. ((UINT32)MemoryType < 0x7FFFFFFF)) ||
  222. (MemoryType == EfiConventionalMemory)) {
  223. return EFI_INVALID_PARAMETER;
  224. }
  225. if (Memory == NULL) {
  226. return EFI_INVALID_PARAMETER;
  227. }
  228. Alignment = EFI_DEFAULT_PAGE_ALLOCATION_ALIGNMENT;
  229. if ((MemoryType == EfiACPIReclaimMemory) ||
  230. (MemoryType == EfiACPIMemoryNVS) ||
  231. (MemoryType == EfiRuntimeServicesCode) ||
  232. (MemoryType == EfiRuntimeServicesData)) {
  233. Alignment = EFI_ACPI_RUNTIME_PAGE_ALLOCATION_ALIGNMENT;
  234. }
  235. if (Type == AllocateAddress) {
  236. if ((*Memory & (Alignment - 1)) != 0) {
  237. return EFI_NOT_FOUND;
  238. }
  239. }
  240. Pages += EFI_SIZE_TO_PAGES(Alignment) - 1;
  241. Pages &= ~(EFI_SIZE_TO_PAGES(Alignment) - 1);
  242. Start = *Memory;
  243. MaxAddress = MAX_ADDRESS;
  244. if (Type == AllocateMaxAddress) {
  245. MaxAddress = Start;
  246. }
  247. EfiCoreAcquireLock(&EfiMemoryLock);
  248. //
  249. // If no specific address was requested, then locate some pages.
  250. //
  251. if (Type != AllocateAddress) {
  252. Start = EfipCoreFindFreePages(MaxAddress, Pages, MemoryType, Alignment);
  253. if (Start == 0) {
  254. Status = EFI_OUT_OF_RESOURCES;
  255. goto CoreAllocatePagesEnd;
  256. }
  257. }
  258. //
  259. // Mark the pages as allocated.
  260. //
  261. Status = EfipCoreConvertPages(Start, Pages, MemoryType);
  262. CoreAllocatePagesEnd:
  263. EfiCoreReleaseLock(&EfiMemoryLock);
  264. if (!EFI_ERROR(Status)) {
  265. *Memory = Start;
  266. }
  267. return Status;
  268. }
  269. EFIAPI
  270. EFI_STATUS
  271. EfiCoreFreePages (
  272. EFI_PHYSICAL_ADDRESS Memory,
  273. UINTN Pages
  274. )
  275. /*++
  276. Routine Description:
  277. This routine frees memory pages back to the system.
  278. Arguments:
  279. Memory - Supplies the base physical address of the allocation to free.
  280. Pages - Supplies the number of pages to free.
  281. Return Value:
  282. EFI_SUCCESS on success.
  283. EFI_INVALID_PARAMETER if the memory is not page aligned or is invalid.
  284. EFI_NOT_FOUND if the requested pages were not allocated.
  285. --*/
  286. {
  287. UINTN Alignment;
  288. PLIST_ENTRY CurrentEntry;
  289. PEFI_MEMORY_MAP_ENTRY Entry;
  290. UINT64 EntryEnd;
  291. UINT64 EntryStart;
  292. EFI_STATUS Status;
  293. EfiCoreAcquireLock(&EfiMemoryLock);
  294. Entry = NULL;
  295. CurrentEntry = EfiMemoryMap.Next;
  296. while (CurrentEntry != &EfiMemoryMap) {
  297. Entry = LIST_VALUE(CurrentEntry, EFI_MEMORY_MAP_ENTRY, ListEntry);
  298. EntryStart = Entry->Descriptor.PhysicalStart;
  299. EntryEnd = EntryStart +
  300. (Entry->Descriptor.NumberOfPages << EFI_PAGE_SHIFT) - 1;
  301. if ((EntryStart <= Memory) && (EntryEnd > Memory)) {
  302. break;
  303. }
  304. CurrentEntry = CurrentEntry->Next;
  305. }
  306. if (CurrentEntry == &EfiMemoryMap) {
  307. Status = EFI_NOT_FOUND;
  308. goto CoreFreePagesEnd;
  309. }
  310. Alignment = EFI_DEFAULT_PAGE_ALLOCATION_ALIGNMENT;
  311. ASSERT(Entry != NULL);
  312. if ((Entry->Descriptor.Type == EfiACPIReclaimMemory) ||
  313. (Entry->Descriptor.Type == EfiACPIMemoryNVS) ||
  314. (Entry->Descriptor.Type == EfiRuntimeServicesCode) ||
  315. (Entry->Descriptor.Type == EfiRuntimeServicesData)) {
  316. Alignment = EFI_ACPI_RUNTIME_PAGE_ALLOCATION_ALIGNMENT;
  317. }
  318. if ((Memory & (Alignment - 1)) != 0) {
  319. Status = EFI_INVALID_PARAMETER;
  320. goto CoreFreePagesEnd;
  321. }
  322. Pages += EFI_SIZE_TO_PAGES(Alignment) - 1;
  323. Pages &= ~(EFI_SIZE_TO_PAGES(Alignment) - 1);
  324. Status = EfipCoreConvertPages(Memory, Pages, EfiConventionalMemory);
  325. if (EFI_ERROR(Status)) {
  326. goto CoreFreePagesEnd;
  327. }
  328. CoreFreePagesEnd:
  329. EfiCoreReleaseLock(&EfiMemoryLock);
  330. return Status;
  331. }
  332. EFIAPI
  333. EFI_STATUS
  334. EfiCoreGetMemoryMap (
  335. UINTN *MemoryMapSize,
  336. EFI_MEMORY_DESCRIPTOR *MemoryMap,
  337. UINTN *MapKey,
  338. UINTN *DescriptorSize,
  339. UINT32 *DescriptorVersion
  340. )
  341. /*++
  342. Routine Description:
  343. This routine returns the current memory map.
  344. Arguments:
  345. MemoryMapSize - Supplies a pointer to the size, in bytes, of the memory
  346. map buffer. On input, this is the size of the buffer allocated by the
  347. caller. On output, this is the size of the buffer returned by the
  348. firmware if the buffer was large enough, or the size of the buffer
  349. needed if the buffer was too small.
  350. MemoryMap - Supplies a pointer to a caller-allocated buffer where the
  351. memory map will be written on success.
  352. MapKey - Supplies a pointer where the firmware returns the map key.
  353. DescriptorSize - Supplies a pointer where the firmware returns the size of
  354. the EFI_MEMORY_DESCRIPTOR structure.
  355. DescriptorVersion - Supplies a pointer where the firmware returns the
  356. version number associated with the EFI_MEMORY_DESCRIPTOR structure.
  357. Return Value:
  358. EFI_SUCCESS on success.
  359. EFI_BUFFER_TOO_SMALL if the supplied buffer was too small. The size needed
  360. is returned in the size parameter.
  361. EFI_INVALID_PARAMETER if the supplied size or memory map pointers are NULL.
  362. --*/
  363. {
  364. UINTN BufferSize;
  365. PLIST_ENTRY CurrentEntry;
  366. PEFI_MEMORY_MAP_ENTRY Entry;
  367. UINT64 EntryEnd;
  368. UINT64 EntryStart;
  369. EFI_MEMORY_DESCRIPTOR *MemoryMapStart;
  370. UINTN Size;
  371. EFI_STATUS Status;
  372. EFI_MEMORY_TYPE Type;
  373. if (MemoryMapSize == NULL) {
  374. return EFI_INVALID_PARAMETER;
  375. }
  376. Size = sizeof(EFI_MEMORY_DESCRIPTOR);
  377. //
  378. // Artificially change the reported size to foil folks using pointer
  379. // arithmetic. This forces them to use the returned descriptor size.
  380. //
  381. Size += sizeof(UINT64) - (Size % sizeof(UINT64));
  382. if (DescriptorSize != NULL) {
  383. *DescriptorSize = Size;
  384. }
  385. if (DescriptorVersion != NULL) {
  386. *DescriptorVersion = EFI_MEMORY_DESCRIPTOR_VERSION;
  387. }
  388. EfiCoreAcquireLock(&EfiMemoryLock);
  389. //
  390. // Compute the size required to contain the entire map.
  391. //
  392. BufferSize = 0;
  393. CurrentEntry = EfiMemoryMap.Next;
  394. while (CurrentEntry != &EfiMemoryMap) {
  395. Entry = LIST_VALUE(CurrentEntry, EFI_MEMORY_MAP_ENTRY, ListEntry);
  396. BufferSize += Size;
  397. CurrentEntry = CurrentEntry->Next;
  398. }
  399. if (*MemoryMapSize < BufferSize) {
  400. Status = EFI_BUFFER_TOO_SMALL;
  401. goto CoreGetMemoryMapEnd;
  402. }
  403. if (MemoryMap == NULL) {
  404. Status = EFI_INVALID_PARAMETER;
  405. goto CoreGetMemoryMapEnd;
  406. }
  407. //
  408. // Build the memory map.
  409. //
  410. EfiCoreSetMemory(MemoryMap, BufferSize, 0);
  411. MemoryMapStart = MemoryMap;
  412. CurrentEntry = EfiMemoryMap.Next;
  413. while (CurrentEntry != &EfiMemoryMap) {
  414. Entry = LIST_VALUE(CurrentEntry, EFI_MEMORY_MAP_ENTRY, ListEntry);
  415. CurrentEntry = CurrentEntry->Next;
  416. ASSERT(Entry->Descriptor.VirtualStart == 0);
  417. EfiCoreCopyMemory(MemoryMap,
  418. &(Entry->Descriptor),
  419. sizeof(EFI_MEMORY_DESCRIPTOR));
  420. //
  421. // If the memory type is free memory, then determine if the range is
  422. // part of a memory type bin and needs to be converted to the same
  423. // memory type as the rest of the memory type bin in order to minimize
  424. // EFI memory map changes across reboots. This improves the chances for
  425. // a successful S4 resume in the presence of minor page allocation
  426. // differences across reboots.
  427. //
  428. if (MemoryMap->Type == EfiConventionalMemory) {
  429. EntryStart = Entry->Descriptor.PhysicalStart;
  430. EntryEnd = EntryStart +
  431. (Entry->Descriptor.NumberOfPages << EFI_PAGE_SHIFT) - 1;
  432. for (Type = 0; Type < EfiMaxMemoryType; Type += 1) {
  433. if ((EfiMemoryStatistics[Type].Special != FALSE) &&
  434. (EfiMemoryStatistics[Type].PageCount > 0) &&
  435. (EntryStart >= EfiMemoryStatistics[Type].BaseAddress) &&
  436. (EntryEnd <= EfiMemoryStatistics[Type].MaximumAddress)) {
  437. MemoryMap->Type = Type;
  438. }
  439. }
  440. }
  441. if ((MemoryMap->Type < EfiMaxMemoryType) &&
  442. (EfiMemoryStatistics[MemoryMap->Type].Runtime != FALSE)) {
  443. MemoryMap->Attribute |= EFI_MEMORY_RUNTIME;
  444. }
  445. //
  446. // Check to see if the new memory map descriptor can be merged with an
  447. // existing descriptor.
  448. //
  449. MemoryMap = EfipCoreMergeMemoryMapDescriptor(MemoryMapStart,
  450. MemoryMap,
  451. Size);
  452. }
  453. //
  454. // Compute the buffer size actually used after all the merge operations.
  455. //
  456. BufferSize = (UINTN)MemoryMap - (UINTN)MemoryMapStart;
  457. Status = EFI_SUCCESS;
  458. CoreGetMemoryMapEnd:
  459. if (MapKey != NULL) {
  460. *MapKey = EfiMemoryMapKey;
  461. }
  462. EfiCoreReleaseLock(&EfiMemoryLock);
  463. *MemoryMapSize = BufferSize;
  464. return Status;
  465. }
  466. VOID *
  467. EfiCoreAllocatePoolPages (
  468. EFI_MEMORY_TYPE PoolType,
  469. UINTN PageCount,
  470. UINTN Alignment
  471. )
  472. /*++
  473. Routine Description:
  474. This routine allocates pages to back pool allocations and memory map
  475. descriptors.
  476. Arguments:
  477. PoolType - Supplies the memory type of the allocation.
  478. PageCount - Supplies the number of pages to allocate.
  479. Alignment - Supplies the required alignment.
  480. Return Value:
  481. Returns a pointer to the allocated memory on success.
  482. NULL on allocation failure.
  483. --*/
  484. {
  485. UINT64 Start;
  486. Start = EfipCoreFindFreePages(MAX_ADDRESS, PageCount, PoolType, Alignment);
  487. ASSERT(Start != 0);
  488. if (Start != 0) {
  489. EfipCoreConvertPages(Start, PageCount, PoolType);
  490. }
  491. return (VOID *)(UINTN)Start;
  492. }
  493. VOID
  494. EfiCoreFreePoolPages (
  495. EFI_PHYSICAL_ADDRESS Memory,
  496. UINTN PageCount
  497. )
  498. /*++
  499. Routine Description:
  500. This routine frees pages allocated for pool or descriptor.
  501. Arguments:
  502. Memory - Supplies the address of the allocation.
  503. PageCount - Supplies the number of pages to free.
  504. Return Value:
  505. None.
  506. --*/
  507. {
  508. EfipCoreConvertPages(Memory, PageCount, EfiConventionalMemory);
  509. return;
  510. }
  511. EFI_STATUS
  512. EfiCoreInitializeMemoryServices (
  513. VOID *FirmwareLowestAddress,
  514. UINTN FirmwareSize,
  515. VOID *StackBase,
  516. UINTN StackSize
  517. )
  518. /*++
  519. Routine Description:
  520. This routine initializes core UEFI memory services.
  521. Arguments:
  522. FirmwareLowestAddress - Supplies the lowest address where the firmware was
  523. loaded into memory.
  524. FirmwareSize - Supplies the size of the firmware image in memory, in bytes.
  525. StackBase - Supplies the base (lowest) address of the stack.
  526. StackSize - Supplies the size in bytes of the stack. This should be at
  527. least 0x4000 bytes (16kB).
  528. Return Value:
  529. EFI status code.
  530. --*/
  531. {
  532. EFI_MEMORY_DESCRIPTOR *Entry;
  533. EFI_PHYSICAL_ADDRESS EntryAddress;
  534. EFI_MEMORY_DESCRIPTOR *FreeEntry;
  535. UINTN Index;
  536. EFI_MEMORY_DESCRIPTOR *PlatformMap;
  537. UINTN PlatformMapSize;
  538. EFI_STATUS Status;
  539. EfiCoreInitializeLock(&EfiMemoryLock, TPL_NOTIFY);
  540. INITIALIZE_LIST_HEAD(&EfiMemoryMap);
  541. INITIALIZE_LIST_HEAD(&EfiFreeDescriptorList);
  542. //
  543. // Get the blank platform memory map.
  544. //
  545. Status = EfiPlatformGetInitialMemoryMap(&PlatformMap, &PlatformMapSize);
  546. if (EFI_ERROR(Status)) {
  547. goto CoreInitializeMemoryServicesEnd;
  548. }
  549. //
  550. // Find the biggest free descriptor and add that one first.
  551. //
  552. FreeEntry = NULL;
  553. for (Index = 0; Index < PlatformMapSize; Index += 1) {
  554. Entry = &(PlatformMap[Index]);
  555. if ((Entry->Type == EfiConventionalMemory) &&
  556. (Entry->PhysicalStart < MAX_ADDRESS) &&
  557. ((FreeEntry == NULL) ||
  558. (Entry->NumberOfPages > FreeEntry->NumberOfPages))) {
  559. FreeEntry = Entry;
  560. }
  561. }
  562. if (FreeEntry == NULL) {
  563. Status = EFI_OUT_OF_RESOURCES;
  564. goto CoreInitializeMemoryServicesEnd;
  565. }
  566. EfipCoreAddMemoryDescriptor(FreeEntry->Type,
  567. FreeEntry->PhysicalStart,
  568. FreeEntry->NumberOfPages,
  569. FreeEntry->Attribute);
  570. //
  571. // Now add all the other entries.
  572. //
  573. for (Index = 0; Index < PlatformMapSize; Index += 1) {
  574. Entry = &(PlatformMap[Index]);
  575. if (Entry == FreeEntry) {
  576. continue;
  577. }
  578. EfipCoreAddMemoryDescriptor(Entry->Type,
  579. Entry->PhysicalStart,
  580. Entry->NumberOfPages,
  581. Entry->Attribute);
  582. }
  583. Status = EfiCoreInitializePool();
  584. if (EFI_ERROR(Status)) {
  585. goto CoreInitializeMemoryServicesEnd;
  586. }
  587. //
  588. // Add the firmware image and stack as boot services code and data.
  589. //
  590. EntryAddress = (UINTN)FirmwareLowestAddress & ~EFI_PAGE_MASK;
  591. FirmwareSize += (UINTN)FirmwareLowestAddress & EFI_PAGE_MASK;
  592. Status = EfiCoreAllocatePages(AllocateAddress,
  593. EfiBootServicesCode,
  594. EFI_SIZE_TO_PAGES(FirmwareSize),
  595. &EntryAddress);
  596. if (EFI_ERROR(Status)) {
  597. RtlDebugPrint("Failed to add firmware image to memory map.\n");
  598. goto CoreInitializeMemoryServicesEnd;
  599. }
  600. EntryAddress = (UINTN)StackBase;
  601. ASSERT((EntryAddress & EFI_PAGE_MASK) == 0);
  602. ASSERT((StackSize & EFI_PAGE_MASK) == 0);
  603. Status = EfiCoreAllocatePages(AllocateAddress,
  604. EfiBootServicesData,
  605. EFI_SIZE_TO_PAGES(StackSize),
  606. &EntryAddress);
  607. if (EFI_ERROR(Status)) {
  608. RtlDebugPrint("Failed to add firmware stack to memory map.\n");
  609. goto CoreInitializeMemoryServicesEnd;
  610. }
  611. CoreInitializeMemoryServicesEnd:
  612. return Status;
  613. }
  614. EFI_STATUS
  615. EfiCoreTerminateMemoryServices (
  616. UINTN MapKey
  617. )
  618. /*++
  619. Routine Description:
  620. This routine terminates memory services.
  621. Arguments:
  622. MapKey - Supplies the map key reported by the boot application. This is
  623. checked against the current map key to ensure the boot application has
  624. an up to date view of the world.
  625. Return Value:
  626. EFI_SUCCESS on success.
  627. EFI_INVALID_PARAMETER if the map key is not valid or the memory map is
  628. not consistent.
  629. --*/
  630. {
  631. PLIST_ENTRY CurrentEntry;
  632. PEFI_MEMORY_MAP_ENTRY Entry;
  633. EFI_STATUS Status;
  634. Status = EFI_SUCCESS;
  635. EfiCoreAcquireLock(&EfiMemoryLock);
  636. if (MapKey == EfiMemoryMapKey) {
  637. CurrentEntry = EfiMemoryMap.Next;
  638. while (CurrentEntry != &EfiMemoryMap) {
  639. Entry = LIST_VALUE(CurrentEntry, EFI_MEMORY_MAP_ENTRY, ListEntry);
  640. CurrentEntry = CurrentEntry->Next;
  641. if ((Entry->Descriptor.Attribute & EFI_MEMORY_RUNTIME) != 0) {
  642. if ((Entry->Descriptor.Type == EfiACPIReclaimMemory) ||
  643. (Entry->Descriptor.Type == EfiACPIMemoryNVS)) {
  644. RtlDebugPrint("ExitBootServices: ACPI memory entry has "
  645. "Runtime attribute set!\n");
  646. Status = EFI_INVALID_PARAMETER;
  647. goto CoreTerminateMemoryServicesEnd;
  648. }
  649. if ((Entry->Descriptor.PhysicalStart &
  650. (EFI_ACPI_RUNTIME_PAGE_ALLOCATION_ALIGNMENT - 1)) != 0) {
  651. RtlDebugPrint("ExitBootServices: Runtime entry is not "
  652. "aligned.\n");
  653. Status = EFI_INVALID_PARAMETER;
  654. goto CoreTerminateMemoryServicesEnd;
  655. }
  656. }
  657. }
  658. //
  659. // The boot application has a stale copy of the memory map. Fail.
  660. //
  661. } else {
  662. Status = EFI_INVALID_PARAMETER;
  663. }
  664. CoreTerminateMemoryServicesEnd:
  665. EfiCoreReleaseLock(&EfiMemoryLock);
  666. return Status;
  667. }
  668. //
  669. // --------------------------------------------------------- Internal Functions
  670. //
  671. VOID
  672. EfipCoreAddMemoryDescriptor (
  673. EFI_MEMORY_TYPE Type,
  674. EFI_PHYSICAL_ADDRESS Start,
  675. UINT64 PageCount,
  676. UINT64 Attribute
  677. )
  678. /*++
  679. Routine Description:
  680. This routine is called to initialize the memory map and add descriptors.
  681. The first descriptor added must be general usable memory.
  682. Arguments:
  683. Type - Supplies the type of memory to add.
  684. Start - Supplies the starting physical address. This must be page aligned.
  685. PageCount - Supplies the number of pages being described.
  686. Attribute - Supplies the memory attributes of the region.
  687. Return Value:
  688. None.
  689. --*/
  690. {
  691. EFI_PHYSICAL_ADDRESS End;
  692. UINTN FreeIndex;
  693. UINTN Index;
  694. EFI_STATUS Status;
  695. if ((Start & EFI_PAGE_MASK) != 0) {
  696. return;
  697. }
  698. if ((Type >= EfiMaxMemoryType) && (Type < 0x7FFFFFFF)) {
  699. return;
  700. }
  701. EfiCoreAcquireLock(&EfiMemoryLock);
  702. End = Start + EFI_PAGES_TO_SIZE(PageCount) - 1;
  703. EfipCoreAddRange(Type, Start, End, Attribute);
  704. EfipCoreFlushMemoryMapStack();
  705. EfiCoreReleaseLock(&EfiMemoryLock);
  706. //
  707. // The rest of this function initializes the memory statistics.
  708. //
  709. if (EfiMemoryTypeInformationInitialized != FALSE) {
  710. return;
  711. }
  712. //
  713. // Loop through each memory type in the order specified by the type
  714. // information array.
  715. //
  716. for (Index = 0;
  717. EfiMemoryTypeInformation[Index].Type != EfiMaxMemoryType;
  718. Index += 1) {
  719. Type = (EFI_MEMORY_TYPE)(EfiMemoryTypeInformation[Index].Type);
  720. if ((UINT32)Type > EfiMaxMemoryType) {
  721. continue;
  722. }
  723. if (EfiMemoryTypeInformation[Index].PageCount == 0) {
  724. continue;
  725. }
  726. //
  727. // Allocate pages for the memory type from the top of available memory.
  728. //
  729. Status = EfiCoreAllocatePages(AllocateAnyPages,
  730. Type,
  731. EfiMemoryTypeInformation[Index].PageCount,
  732. &(EfiMemoryStatistics[Type].BaseAddress));
  733. if (EFI_ERROR(Status)) {
  734. //
  735. // If an error occurred, free all pages allocated for the previous
  736. // memory types.
  737. //
  738. for (FreeIndex = 0; FreeIndex < Index; FreeIndex += 1) {
  739. Type =
  740. (EFI_MEMORY_TYPE)(EfiMemoryTypeInformation[FreeIndex].Type);
  741. if ((UINT32)Type > EfiMaxMemoryType) {
  742. continue;
  743. }
  744. if (EfiMemoryTypeInformation[FreeIndex].PageCount != 0) {
  745. EfiCoreFreePages(
  746. EfiMemoryStatistics[Type].BaseAddress,
  747. EfiMemoryTypeInformation[FreeIndex].PageCount);
  748. EfiMemoryStatistics[Type].BaseAddress = 0;
  749. EfiMemoryStatistics[Type].MaximumAddress = MAX_ADDRESS;
  750. }
  751. }
  752. return;
  753. }
  754. //
  755. // Compute the address at the top of the current statistics.
  756. //
  757. EfiMemoryStatistics[Type].MaximumAddress =
  758. EfiMemoryStatistics[Type].BaseAddress +
  759. EFI_PAGES_TO_SIZE(EfiMemoryTypeInformation[Index].PageCount) - 1;
  760. //
  761. // If the current base address is the lowest so far, update the default
  762. // max address.
  763. //
  764. if (EfiMemoryStatistics[Type].BaseAddress < EfiDefaultMaximumAddress) {
  765. EfiDefaultMaximumAddress =
  766. EfiMemoryStatistics[Type].BaseAddress - 1;
  767. }
  768. }
  769. //
  770. // There was enough system memory for all the memory types. Free those
  771. // allocated pages now, and now future allocations of that type will fit
  772. // into those slots. This avoids fragmentation.
  773. //
  774. for (Index = 0;
  775. EfiMemoryTypeInformation[Index].Type != EfiMaxMemoryType;
  776. Index += 1) {
  777. Type = (EFI_MEMORY_TYPE)(EfiMemoryTypeInformation[Index].Type);
  778. if ((UINT32)Type > EfiMaxMemoryType) {
  779. continue;
  780. }
  781. if (EfiMemoryTypeInformation[Index].PageCount == 0) {
  782. continue;
  783. }
  784. EfiCoreFreePages(EfiMemoryStatistics[Type].BaseAddress,
  785. EfiMemoryTypeInformation[Index].PageCount);
  786. EfiMemoryStatistics[Type].PageCount =
  787. EfiMemoryTypeInformation[Index].PageCount;
  788. EfiMemoryTypeInformation[Index].PageCount = 0;
  789. }
  790. //
  791. // If the number of pages reserved for a memory type is zero, then all
  792. // allocations for that type should be in the default range.
  793. //
  794. for (Type = (EFI_MEMORY_TYPE)0;
  795. Type < EfiMaxMemoryType;
  796. Type += 1) {
  797. for (Index = 0;
  798. EfiMemoryTypeInformation[Index].Type != EfiMaxMemoryType;
  799. Index += 1) {
  800. if (Type == (EFI_MEMORY_TYPE)EfiMemoryTypeInformation[Index].Type) {
  801. EfiMemoryStatistics[Type].InformationIndex = Index;
  802. }
  803. }
  804. EfiMemoryStatistics[Type].CurrentPageCount = 0;
  805. if (EfiMemoryStatistics[Type].MaximumAddress == MAX_ADDRESS) {
  806. EfiMemoryStatistics[Type].MaximumAddress = EfiDefaultMaximumAddress;
  807. }
  808. }
  809. EfiMemoryTypeInformationInitialized = TRUE;
  810. return;
  811. }
  812. UINT64
  813. EfipCoreFindFreePages (
  814. UINT64 MaxAddress,
  815. UINT64 PageCount,
  816. EFI_MEMORY_TYPE NewType,
  817. UINTN Alignment
  818. )
  819. /*++
  820. Routine Description:
  821. This routine attempts to find a consecutive range of free pages below the
  822. given maximum address.
  823. Arguments:
  824. MaxAddress - Supplies the maximum address that the allocation must stay
  825. below.
  826. PageCount - Supplies the number of pages to allocate.
  827. NewType - Supplies the type of memory this range is going to be turned into.
  828. Alignment - Supplies the required alignment of the allocation.
  829. Return Value:
  830. Returns the physical address of the base of the allocation on success.
  831. 0 if the range was not found.
  832. --*/
  833. {
  834. UINT64 Start;
  835. //
  836. // First try to find free pages in the range where there are already
  837. // descriptors of this type hanging around.
  838. //
  839. if (((UINT32)NewType < EfiMaxMemoryType) &&
  840. (MaxAddress >= EfiMemoryStatistics[NewType].MaximumAddress)) {
  841. Start = EfipCoreFindFreePagesInRange(
  842. EfiMemoryStatistics[NewType].MaximumAddress,
  843. EfiMemoryStatistics[NewType].BaseAddress,
  844. PageCount,
  845. NewType,
  846. Alignment);
  847. if (Start != 0) {
  848. return Start;
  849. }
  850. }
  851. //
  852. // Attempt to find free pages in the default area.
  853. //
  854. if (MaxAddress >= EfiDefaultMaximumAddress) {
  855. Start = EfipCoreFindFreePagesInRange(EfiDefaultMaximumAddress,
  856. 0,
  857. PageCount,
  858. NewType,
  859. Alignment);
  860. if (Start != 0) {
  861. if (Start < EfiDefaultBaseAddress) {
  862. EfiDefaultBaseAddress = Start;
  863. }
  864. return Start;
  865. }
  866. }
  867. //
  868. // Find free pages anywhere in the specified range. This is the most
  869. // permissive search. If this doesn't work, it's not happening.
  870. //
  871. Start = EfipCoreFindFreePagesInRange(MaxAddress,
  872. 0,
  873. PageCount,
  874. NewType,
  875. Alignment);
  876. return Start;
  877. }
  878. UINT64
  879. EfipCoreFindFreePagesInRange (
  880. UINT64 MaxAddress,
  881. UINT64 MinAddress,
  882. UINT64 PageCount,
  883. EFI_MEMORY_TYPE NewType,
  884. UINTN Alignment
  885. )
  886. /*++
  887. Routine Description:
  888. This routine attempts to find a consecutive range of free pages within the
  889. specified range.
  890. Arguments:
  891. MaxAddress - Supplies the maximum address that the allocation must stay
  892. below.
  893. MinAddress - Supplies the minimum address that the allocation must stay
  894. at or above.
  895. PageCount - Supplies the number of pages to allocate.
  896. NewType - Supplies the type of memory this range is going to be turned into.
  897. Alignment - Supplies the required alignment of the allocation.
  898. Return Value:
  899. Returns the physical address of the base of the allocation on success.
  900. 0 if the range was not found.
  901. --*/
  902. {
  903. UINT64 ByteCount;
  904. PLIST_ENTRY CurrentEntry;
  905. PEFI_MEMORY_MAP_ENTRY Entry;
  906. UINT64 EntryEnd;
  907. UINT64 EntrySize;
  908. UINT64 EntryStart;
  909. UINT64 Target;
  910. if ((MaxAddress < EFI_PAGE_MASK) || (PageCount == 0)) {
  911. return 0;
  912. }
  913. //
  914. // Chop the max address down if it's not one below a page boundary.
  915. //
  916. if ((MaxAddress & EFI_PAGE_MASK) != EFI_PAGE_MASK) {
  917. MaxAddress -= EFI_PAGE_MASK + 1;
  918. MaxAddress &= ~EFI_PAGE_MASK;
  919. MaxAddress |= EFI_PAGE_MASK;
  920. }
  921. ByteCount = PageCount << EFI_PAGE_SHIFT;
  922. Target = 0;
  923. CurrentEntry = EfiMemoryMap.Next;
  924. while (CurrentEntry != &EfiMemoryMap) {
  925. Entry = LIST_VALUE(CurrentEntry, EFI_MEMORY_MAP_ENTRY, ListEntry);
  926. CurrentEntry = CurrentEntry->Next;
  927. if (Entry->Descriptor.Type != EfiConventionalMemory) {
  928. continue;
  929. }
  930. EntryStart = Entry->Descriptor.PhysicalStart;
  931. EntryEnd = EntryStart +
  932. (Entry->Descriptor.NumberOfPages << EFI_PAGE_SHIFT);
  933. //
  934. // Skip descriptors that are outside of the requested range.
  935. //
  936. if ((EntryStart >= MaxAddress) || (EntryEnd < MinAddress)) {
  937. continue;
  938. }
  939. //
  940. // If the descriptor ends past the maximum allowed address, clip it.
  941. //
  942. if (EntryEnd > MaxAddress) {
  943. EntryEnd = MaxAddress;
  944. }
  945. EntryEnd = ((EntryEnd + 1) & (~(Alignment - 1))) - 1;
  946. //
  947. // If the entry is big enough, and does not dip below the minimum
  948. // address, then it works.
  949. //
  950. EntrySize = EntryEnd - EntryStart + 1;
  951. if (EntrySize >= ByteCount) {
  952. if ((EntryEnd - ByteCount + 1) < MinAddress) {
  953. continue;
  954. }
  955. //
  956. // If this is the highest match, save it.
  957. //
  958. if (EntryEnd > Target) {
  959. Target = EntryEnd;
  960. }
  961. }
  962. }
  963. if (Target == 0) {
  964. return 0;
  965. }
  966. ASSERT(Target > ByteCount);
  967. Target -= ByteCount - 1;
  968. if ((Target & EFI_PAGE_MASK) != 0) {
  969. return 0;
  970. }
  971. return Target;
  972. }
  973. EFI_STATUS
  974. EfipCoreConvertPages (
  975. UINT64 Start,
  976. UINT64 PageCount,
  977. EFI_MEMORY_TYPE NewType
  978. )
  979. /*++
  980. Routine Description:
  981. This routine converts a given range to the specified type. The range must
  982. already exist in the memory map.
  983. Arguments:
  984. Start - Supplies the first address in the range. This must be page aligned.
  985. PageCount - Supplies the number of pages in the range.
  986. NewType - Supplies the type to convert the pages to.
  987. Return Value:
  988. EFI_SUCCESS on success.
  989. EFI_INVALID_PARAMETER if the page count is zero, the address is not
  990. aligned, or the type is invalid.
  991. EFI_NOT_FOUND if no existing descriptor covers the given region.
  992. --*/
  993. {
  994. UINT64 Attribute;
  995. UINT64 ByteCount;
  996. PLIST_ENTRY CurrentEntry;
  997. UINT64 End;
  998. PEFI_MEMORY_MAP_ENTRY Entry;
  999. UINT64 EntryEnd;
  1000. UINT64 EntryStart;
  1001. EFI_MEMORY_TYPE EntryType;
  1002. UINTN InformationIndex;
  1003. PEFI_MEMORY_MAP_ENTRY NewEntry;
  1004. UINT64 RangeEnd;
  1005. ByteCount = PageCount << EFI_PAGE_SHIFT;
  1006. Entry = NULL;
  1007. End = Start + ByteCount - 1;
  1008. ASSERT((PageCount != 0) && ((Start & EFI_PAGE_MASK) == 0) &&
  1009. (End > Start) && (EfiCoreIsLockHeld(&EfiMemoryLock) != FALSE));
  1010. if ((PageCount == 0) || ((Start & EFI_PAGE_MASK) != 0) ||
  1011. (Start > Start + ByteCount)) {
  1012. return EFI_INVALID_PARAMETER;
  1013. }
  1014. //
  1015. // Loop until the entire range is converted.
  1016. //
  1017. while (Start < End) {
  1018. //
  1019. // Loop through looking for the descriptor that contains this range.
  1020. //
  1021. CurrentEntry = EfiMemoryMap.Next;
  1022. while (CurrentEntry != &EfiMemoryMap) {
  1023. Entry = LIST_VALUE(CurrentEntry, EFI_MEMORY_MAP_ENTRY, ListEntry);
  1024. EntryStart = Entry->Descriptor.PhysicalStart;
  1025. EntryEnd = EntryStart +
  1026. (Entry->Descriptor.NumberOfPages << EFI_PAGE_SHIFT) - 1;
  1027. if ((EntryStart <= Start) && (EntryEnd > Start)) {
  1028. break;
  1029. }
  1030. CurrentEntry = CurrentEntry->Next;
  1031. }
  1032. if (CurrentEntry == &EfiMemoryMap) {
  1033. return EFI_NOT_FOUND;
  1034. }
  1035. //
  1036. // Convert the range to the end, or to the end of the descriptor if the
  1037. // range covers more than the descriptor.
  1038. //
  1039. RangeEnd = End;
  1040. if (EntryEnd < End) {
  1041. RangeEnd = EntryEnd;
  1042. }
  1043. //
  1044. // Verify the conversion is allowed.
  1045. //
  1046. EntryType = Entry->Descriptor.Type;
  1047. if (NewType == EfiConventionalMemory) {
  1048. if (EntryType == EfiConventionalMemory) {
  1049. return EFI_NOT_FOUND;
  1050. }
  1051. } else {
  1052. if (EntryType != EfiConventionalMemory) {
  1053. return EFI_NOT_FOUND;
  1054. }
  1055. }
  1056. //
  1057. // Update the counters for the number of pages allocated to each
  1058. // memory type.
  1059. //
  1060. if ((UINT32)EntryType < EfiMaxMemoryType) {
  1061. if (((Start >= EfiMemoryStatistics[EntryType].BaseAddress) &&
  1062. (Start <= EfiMemoryStatistics[EntryType].MaximumAddress)) ||
  1063. ((Start >= EfiDefaultBaseAddress) &&
  1064. (Start <= EfiDefaultMaximumAddress))) {
  1065. if (PageCount >=
  1066. EfiMemoryStatistics[EntryType].CurrentPageCount) {
  1067. EfiMemoryStatistics[EntryType].CurrentPageCount = 0;
  1068. } else {
  1069. EfiMemoryStatistics[EntryType].CurrentPageCount -=
  1070. PageCount;
  1071. }
  1072. }
  1073. }
  1074. if ((UINT32)NewType < EfiMaxMemoryType) {
  1075. if (((Start > EfiMemoryStatistics[NewType].BaseAddress) &&
  1076. (Start <= EfiMemoryStatistics[NewType].MaximumAddress)) ||
  1077. ((Start >= EfiDefaultBaseAddress) &&
  1078. (Start <= EfiDefaultMaximumAddress))) {
  1079. EfiMemoryStatistics[NewType].CurrentPageCount += PageCount;
  1080. InformationIndex =
  1081. EfiMemoryStatistics[NewType].InformationIndex;
  1082. if (EfiMemoryStatistics[NewType].CurrentPageCount >
  1083. EfiMemoryTypeInformation[InformationIndex].PageCount) {
  1084. EfiMemoryTypeInformation[InformationIndex].PageCount =
  1085. (UINT32)EfiMemoryStatistics[NewType].CurrentPageCount;
  1086. }
  1087. }
  1088. }
  1089. //
  1090. // Pull the requested range out of the descriptor.
  1091. //
  1092. if (EntryStart == Start) {
  1093. EntryStart = RangeEnd + 1;
  1094. } else if (EntryEnd == RangeEnd) {
  1095. EntryEnd = Start - 1;
  1096. //
  1097. // The descriptor is being split in two. Clip the end of current one
  1098. // and add a new one for the remainder.
  1099. //
  1100. } else {
  1101. ASSERT(EfiDescriptorStackSize < EFI_DESCRIPTOR_STACK_SIZE);
  1102. NewEntry = &(EfiDescriptorStack[EfiDescriptorStackSize]);
  1103. EfiDescriptorStackSize += 1;
  1104. NewEntry->Temporary = TRUE;
  1105. NewEntry->Descriptor.Type = EntryType;
  1106. NewEntry->Descriptor.PhysicalStart = RangeEnd + 1;
  1107. NewEntry->Descriptor.VirtualStart = 0;
  1108. NewEntry->Descriptor.NumberOfPages =
  1109. (EntryEnd + 1 - RangeEnd) >> EFI_PAGE_SHIFT;
  1110. NewEntry->Descriptor.Attribute = Entry->Descriptor.Attribute;
  1111. EntryEnd = Start - 1;
  1112. ASSERT(EntryStart < EntryEnd);
  1113. INSERT_BEFORE(&(NewEntry->ListEntry), &EfiMemoryMap);
  1114. }
  1115. Attribute = Entry->Descriptor.Attribute;
  1116. if (EntryStart == EntryEnd + 1) {
  1117. EfipCoreRemoveMemoryMapEntry(Entry);
  1118. Entry = NULL;
  1119. } else {
  1120. Entry->Descriptor.PhysicalStart = EntryStart;
  1121. Entry->Descriptor.NumberOfPages =
  1122. (EntryEnd + 1 - EntryStart) >> EFI_PAGE_SHIFT;
  1123. }
  1124. //
  1125. // Add the new range in.
  1126. //
  1127. EfipCoreAddRange(NewType, Start, RangeEnd, Attribute);
  1128. //
  1129. // Flush the temporary descriptors out to real descriptors.
  1130. //
  1131. EfipCoreFlushMemoryMapStack();
  1132. //
  1133. // Move on to the next range.
  1134. //
  1135. Start = RangeEnd + 1;
  1136. }
  1137. return EFI_SUCCESS;
  1138. }
  1139. VOID
  1140. EfipCoreAddRange (
  1141. EFI_MEMORY_TYPE Type,
  1142. EFI_PHYSICAL_ADDRESS Start,
  1143. EFI_PHYSICAL_ADDRESS End,
  1144. UINT64 Attribute
  1145. )
  1146. /*++
  1147. Routine Description:
  1148. This routine adds a range to the memory map. The range must not already
  1149. exist in the memory map.
  1150. Arguments:
  1151. Type - Supplies the memory type of the range.
  1152. Start - Supplies the starting address of the range. This must be page
  1153. aligned.
  1154. End - Supplies the ending address of the range, inclusive. This must be the
  1155. last byte of a page.
  1156. Attribute - Supplies the attributes of the range to add.
  1157. Return Value:
  1158. None.
  1159. --*/
  1160. {
  1161. PLIST_ENTRY CurrentEntry;
  1162. PEFI_MEMORY_MAP_ENTRY Entry;
  1163. UINT64 EntryEnd;
  1164. UINT64 EntryStart;
  1165. PEFI_MEMORY_MAP_ENTRY NewEntry;
  1166. ASSERT((Start & EFI_PAGE_MASK) == 0);
  1167. ASSERT(End > Start);
  1168. ASSERT(EfiCoreIsLockHeld(&EfiMemoryLock) != FALSE);
  1169. //
  1170. // If free memory is being added that includes page zero, zero out that
  1171. // page.
  1172. //
  1173. if ((Type == EfiConventionalMemory) &&
  1174. (Start == 0) &&
  1175. (End >= EFI_PAGE_SIZE - 1)) {
  1176. EfiCoreSetMemory((VOID *)(UINTN)Start, EFI_PAGE_SIZE, 0);
  1177. }
  1178. //
  1179. // The memory map is being altered, so update the map key.
  1180. //
  1181. EfiMemoryMapKey += 1;
  1182. //
  1183. // Notify the event group wired to listen for memory map changes.
  1184. // Since the TPL is raised the notification functions will only be called
  1185. // after the lock is released.
  1186. //
  1187. EfipCoreNotifySignalList(&EfiEventMemoryMapChangeGuid);
  1188. //
  1189. // Look for descriptors to coalesce with.
  1190. //
  1191. CurrentEntry = EfiMemoryMap.Next;
  1192. while (CurrentEntry != &EfiMemoryMap) {
  1193. Entry = LIST_VALUE(CurrentEntry, EFI_MEMORY_MAP_ENTRY, ListEntry);
  1194. CurrentEntry = CurrentEntry->Next;
  1195. if (Entry->Descriptor.Type != Type) {
  1196. continue;
  1197. }
  1198. if (Entry->Descriptor.Attribute != Attribute) {
  1199. continue;
  1200. }
  1201. EntryStart = Entry->Descriptor.PhysicalStart;
  1202. EntryEnd = EntryStart +
  1203. (Entry->Descriptor.NumberOfPages << EFI_PAGE_SHIFT) - 1;
  1204. if (EntryEnd + 1 == EntryStart) {
  1205. Start = EntryStart;
  1206. EfipCoreRemoveMemoryMapEntry(Entry);
  1207. } else if (EntryStart == End + 1) {
  1208. End = EntryEnd;
  1209. EfipCoreRemoveMemoryMapEntry(Entry);
  1210. }
  1211. }
  1212. //
  1213. // Add the new descriptor.
  1214. //
  1215. ASSERT(EfiDescriptorStackSize < EFI_DESCRIPTOR_STACK_SIZE);
  1216. NewEntry = &(EfiDescriptorStack[EfiDescriptorStackSize]);
  1217. EfiDescriptorStackSize += 1;
  1218. NewEntry->Temporary = TRUE;
  1219. NewEntry->Descriptor.Type = Type;
  1220. NewEntry->Descriptor.PhysicalStart = Start;
  1221. NewEntry->Descriptor.VirtualStart = 0;
  1222. NewEntry->Descriptor.NumberOfPages = (End + 1 - Start) >> EFI_PAGE_SHIFT;
  1223. NewEntry->Descriptor.Attribute = Attribute;
  1224. INSERT_BEFORE(&(NewEntry->ListEntry), &EfiMemoryMap);
  1225. return;
  1226. }
  1227. EFI_MEMORY_DESCRIPTOR *
  1228. EfipCoreMergeMemoryMapDescriptor (
  1229. EFI_MEMORY_DESCRIPTOR *MemoryMap,
  1230. EFI_MEMORY_DESCRIPTOR *LastDescriptor,
  1231. UINTN DescriptorSize
  1232. )
  1233. /*++
  1234. Routine Description:
  1235. This routine checks to see if memory descriptros can be merged together.
  1236. Descriptors qualify for merging if they are adjacent and have the same
  1237. attributes.
  1238. Arguments:
  1239. MemoryMap - Supplies a pointer to the start of the memory map.
  1240. LastDescriptor - Supplies a pointer to the last descriptor in the map.
  1241. DescriptorSize - Supplies the size of an individual EFI memory descriptor.
  1242. Return Value:
  1243. Returns a pointer to the next available descriptor in the memory map.
  1244. --*/
  1245. {
  1246. //
  1247. // Loop over each entry in the map.
  1248. //
  1249. while (MemoryMap != LastDescriptor) {
  1250. if ((MemoryMap->Type != LastDescriptor->Type) ||
  1251. (MemoryMap->Attribute != LastDescriptor->Attribute)) {
  1252. MemoryMap =
  1253. (EFI_MEMORY_DESCRIPTOR *)((UINT8 *)MemoryMap + DescriptorSize);
  1254. continue;
  1255. }
  1256. //
  1257. // Check to see if the given descriptor is immediately above this
  1258. // descriptor.
  1259. //
  1260. if (MemoryMap->PhysicalStart +
  1261. EFI_PAGES_TO_SIZE((UINTN)MemoryMap->NumberOfPages) ==
  1262. LastDescriptor->PhysicalStart) {
  1263. MemoryMap->NumberOfPages += LastDescriptor->NumberOfPages;
  1264. return LastDescriptor;
  1265. }
  1266. //
  1267. // Check to see if the last descriptor is immediately below this one.
  1268. //
  1269. if (MemoryMap->PhysicalStart -
  1270. EFI_PAGES_TO_SIZE((UINTN)LastDescriptor->NumberOfPages) ==
  1271. LastDescriptor->PhysicalStart) {
  1272. MemoryMap->PhysicalStart = LastDescriptor->PhysicalStart;
  1273. MemoryMap->VirtualStart = LastDescriptor->VirtualStart;
  1274. MemoryMap->NumberOfPages += LastDescriptor->NumberOfPages;
  1275. return LastDescriptor;
  1276. }
  1277. //
  1278. // Move on to the next descriptor.
  1279. //
  1280. MemoryMap =
  1281. (EFI_MEMORY_DESCRIPTOR *)((UINT8 *)MemoryMap + DescriptorSize);
  1282. }
  1283. //
  1284. // Nothing coalesces, the next descriptor is the one after the last one.
  1285. //
  1286. LastDescriptor = (EFI_MEMORY_DESCRIPTOR *)((UINT8 *)LastDescriptor +
  1287. DescriptorSize);
  1288. return LastDescriptor;
  1289. }
  1290. VOID
  1291. EfipCoreRemoveMemoryMapEntry (
  1292. PEFI_MEMORY_MAP_ENTRY Entry
  1293. )
  1294. /*++
  1295. Routine Description:
  1296. This routine removes a descriptor entry and places it on a free list for
  1297. later use.
  1298. Arguments:
  1299. Entry - Supplies a pointer to the entry to remove.
  1300. Return Value:
  1301. None.
  1302. --*/
  1303. {
  1304. LIST_REMOVE(&(Entry->ListEntry));
  1305. Entry->ListEntry.Next = NULL;
  1306. if (Entry->Temporary == FALSE) {
  1307. INSERT_BEFORE(&(Entry->ListEntry), &EfiFreeDescriptorList);
  1308. }
  1309. return;
  1310. }
  1311. VOID
  1312. EfipCoreFlushMemoryMapStack (
  1313. VOID
  1314. )
  1315. /*++
  1316. Routine Description:
  1317. This routine replaces all temporary memory map entries with real allocated
  1318. memory map entries.
  1319. Arguments:
  1320. None.
  1321. Return Value:
  1322. None.
  1323. --*/
  1324. {
  1325. PLIST_ENTRY CurrentEntry;
  1326. PEFI_MEMORY_MAP_ENTRY Entry;
  1327. PEFI_MEMORY_MAP_ENTRY NewEntry;
  1328. PEFI_MEMORY_MAP_ENTRY StackEntry;
  1329. //
  1330. // Avoid re-entering this function.
  1331. //
  1332. if (EfiDescriptorStackFreeInProgress != FALSE) {
  1333. return;
  1334. }
  1335. EfiDescriptorStackFreeInProgress = TRUE;
  1336. while (EfiDescriptorStackSize != 0) {
  1337. NewEntry = EfipCoreAllocateMemoryMapEntry();
  1338. ASSERT(NewEntry != NULL);
  1339. EfiDescriptorStackSize -= 1;
  1340. StackEntry = &(EfiDescriptorStack[EfiDescriptorStackSize]);
  1341. //
  1342. // If it's in the memory map, then create a replacement copy.
  1343. //
  1344. if (StackEntry->ListEntry.Next != NULL) {
  1345. LIST_REMOVE(&(StackEntry->ListEntry));
  1346. StackEntry->ListEntry.Next = NULL;
  1347. EfiCoreCopyMemory(NewEntry,
  1348. StackEntry,
  1349. sizeof(EFI_MEMORY_MAP_ENTRY));
  1350. NewEntry->Temporary = FALSE;
  1351. //
  1352. // Find the proper insertion location.
  1353. //
  1354. CurrentEntry = EfiMemoryMap.Next;
  1355. while (CurrentEntry != &EfiMemoryMap) {
  1356. Entry = LIST_VALUE(CurrentEntry,
  1357. EFI_MEMORY_MAP_ENTRY,
  1358. ListEntry);
  1359. if ((Entry->Temporary == FALSE) &&
  1360. (Entry->Descriptor.PhysicalStart >
  1361. NewEntry->Descriptor.PhysicalStart)) {
  1362. break;
  1363. }
  1364. CurrentEntry = CurrentEntry->Next;
  1365. }
  1366. INSERT_BEFORE(&(NewEntry->ListEntry), CurrentEntry);
  1367. //
  1368. // This descriptor was already removed, so the descriptor just
  1369. // allocated isn't needed.
  1370. //
  1371. } else {
  1372. INSERT_AFTER(&(NewEntry->ListEntry), &EfiFreeDescriptorList);
  1373. }
  1374. }
  1375. EfiDescriptorStackFreeInProgress = FALSE;
  1376. return;
  1377. }
  1378. PEFI_MEMORY_MAP_ENTRY
  1379. EfipCoreAllocateMemoryMapEntry (
  1380. VOID
  1381. )
  1382. /*++
  1383. Routine Description:
  1384. This routine allocates a new memory map entry. It uses the free list to
  1385. reuse previous descriptors. If that's empty, it allocates a page from the
  1386. memory map and uses that to create more descriptors.
  1387. Arguments:
  1388. None.
  1389. Return Value:
  1390. None.
  1391. --*/
  1392. {
  1393. PEFI_MEMORY_MAP_ENTRY Entries;
  1394. PEFI_MEMORY_MAP_ENTRY Entry;
  1395. UINTN EntryCount;
  1396. UINTN Index;
  1397. if (LIST_EMPTY(&EfiFreeDescriptorList) != FALSE) {
  1398. Entries = EfiCoreAllocatePoolPages(
  1399. EfiBootServicesData,
  1400. EFI_SIZE_TO_PAGES(EFI_MEMORY_EXPANSION_SIZE),
  1401. EFI_MEMORY_EXPANSION_SIZE);
  1402. if (Entries != NULL) {
  1403. EntryCount = EFI_MEMORY_EXPANSION_SIZE /
  1404. sizeof(EFI_MEMORY_MAP_ENTRY);
  1405. for (Index = 0; Index < EntryCount; Index += 1) {
  1406. INSERT_BEFORE(&(Entries[Index].ListEntry),
  1407. &EfiFreeDescriptorList);
  1408. }
  1409. } else {
  1410. //
  1411. // The system just exhausted all memory, and won't do well after
  1412. // this.
  1413. //
  1414. ASSERT(FALSE);
  1415. return NULL;
  1416. }
  1417. }
  1418. ASSERT(LIST_EMPTY(&EfiFreeDescriptorList) == FALSE);
  1419. Entry = LIST_VALUE(EfiFreeDescriptorList.Next,
  1420. EFI_MEMORY_MAP_ENTRY,
  1421. ListEntry);
  1422. LIST_REMOVE(&(Entry->ListEntry));
  1423. return Entry;
  1424. }
  1425. VOID
  1426. EfipDebugPrintMemoryMap (
  1427. EFI_MEMORY_DESCRIPTOR *Map,
  1428. UINTN MapSize,
  1429. UINTN DescriptorSize
  1430. )
  1431. /*++
  1432. Routine Description:
  1433. This routine prints an EFI memory map out to the debugger.
  1434. Arguments:
  1435. Map - Supplies a pointer to the memory map.
  1436. MapSize - Supplies the size of the map in bytes.
  1437. DescriptorSize - Supplies the size of a single descriptor.
  1438. Return Value:
  1439. None.
  1440. --*/
  1441. {
  1442. EFI_MEMORY_DESCRIPTOR *Descriptor;
  1443. UINT64 Megabytes;
  1444. UINTN Offset;
  1445. UINT64 TotalPages;
  1446. RtlDebugPrint("EFI Memory map at 0x%08I64x\n", Map);
  1447. TotalPages = 0;
  1448. Offset = 0;
  1449. while (Offset < MapSize) {
  1450. Descriptor = (EFI_MEMORY_DESCRIPTOR *)((VOID *)Map + Offset);
  1451. EfipDebugPrintMemoryDescriptor(Descriptor);
  1452. TotalPages += Descriptor->NumberOfPages;
  1453. Offset += DescriptorSize;
  1454. }
  1455. Megabytes = (TotalPages << EFI_PAGE_SHIFT) / (1024ULL * 1024ULL);
  1456. RtlDebugPrint("Total Pages: 0x%I64x (%I64dMB)\n\n", TotalPages, Megabytes);
  1457. return;
  1458. }
  1459. VOID
  1460. EfipDebugPrintMemoryDescriptor (
  1461. EFI_MEMORY_DESCRIPTOR *Descriptor
  1462. )
  1463. /*++
  1464. Routine Description:
  1465. This routine prints an EFI memory descriptor out to the debugger.
  1466. Arguments:
  1467. Descriptor - Supplies a pointer to the descriptor to print.
  1468. Return Value:
  1469. None.
  1470. --*/
  1471. {
  1472. CHAR8 *TypeString;
  1473. switch (Descriptor->Type) {
  1474. case EfiReservedMemoryType:
  1475. TypeString = "ReservedMemoryType";
  1476. break;
  1477. case EfiLoaderCode:
  1478. TypeString = "LoaderCode";
  1479. break;
  1480. case EfiLoaderData:
  1481. TypeString = "LoaderData";
  1482. break;
  1483. case EfiBootServicesCode:
  1484. TypeString = "BootServicesCode";
  1485. break;
  1486. case EfiBootServicesData:
  1487. TypeString = "BootServicesData";
  1488. break;
  1489. case EfiRuntimeServicesCode:
  1490. TypeString = "RuntimeServicesCode";
  1491. break;
  1492. case EfiRuntimeServicesData:
  1493. TypeString = "RuntimeServicesData";
  1494. break;
  1495. case EfiConventionalMemory:
  1496. TypeString = "ConventionalMemory";
  1497. break;
  1498. case EfiUnusableMemory:
  1499. TypeString = "UnusableMemory";
  1500. break;
  1501. case EfiACPIReclaimMemory:
  1502. TypeString = "ACPIReclaimMemory";
  1503. break;
  1504. case EfiACPIMemoryNVS:
  1505. TypeString = "ACPIMemoryNVS";
  1506. break;
  1507. case EfiMemoryMappedIO:
  1508. TypeString = "MemoryMappedIO";
  1509. break;
  1510. case EfiMemoryMappedIOPortSpace:
  1511. TypeString = "MemoryMappedIOPortSpace";
  1512. break;
  1513. case EfiPalCode:
  1514. TypeString = "PalCode";
  1515. break;
  1516. default:
  1517. TypeString = "INVALID";
  1518. break;
  1519. }
  1520. RtlDebugPrint("%24s PA 0x%8I64x (VA 0x%I64x) PageCount 0x%8I64x "
  1521. "Attr 0x%x\n",
  1522. TypeString,
  1523. Descriptor->PhysicalStart,
  1524. Descriptor->VirtualStart,
  1525. Descriptor->NumberOfPages,
  1526. Descriptor->Attribute);
  1527. return;
  1528. }