memory.c 51 KB

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