]> git.proxmox.com Git - mirror_edk2.git/blame - MdePkg/Library/PeiMemoryAllocationLib/MemoryAllocationLib.c
Re-Follow...
[mirror_edk2.git] / MdePkg / Library / PeiMemoryAllocationLib / MemoryAllocationLib.c
CommitLineData
878ddf1f 1/** @file\r
2 Support routines for memory allocation routines for use with drivers.\r
3\r
4 Copyright (c) 2006, Intel Corporation<BR>\r
5 All rights reserved. This program and the accompanying materials \r
6 are licensed and made available under the terms and conditions of the BSD License \r
7 which accompanies this distribution. The full text of the license may be found at \r
8 http://opensource.org/licenses/bsd-license.php \r
9\r
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. \r
12\r
13 Module Name: MemoryAllocationLib.c\r
14\r
15**/\r
16\r
17\r
878ddf1f 18/**\r
1f33a17f 19 Allocates one or more 4KB pages of a certain memory type.\r
878ddf1f 20\r
1f33a17f 21 Allocates the number of 4KB pages of a certain memory type and returns a pointer to the allocated\r
22 buffer. The buffer returned is aligned on a 4KB boundary. If Pages is 0, then NULL is returned.\r
878ddf1f 23 If there is not enough memory remaining to satisfy the request, then NULL is returned.\r
24\r
1f33a17f 25 @param MemoryType The type of memory to allocate.\r
26 @param Pages The number of 4 KB pages to allocate.\r
27\r
28 @return A pointer to the allocated buffer or NULL if allocation fails.\r
29\r
878ddf1f 30**/\r
31VOID *\r
32InternalAllocatePages (\r
33 IN EFI_MEMORY_TYPE MemoryType, \r
34 IN UINTN Pages\r
35 )\r
36{\r
37 EFI_STATUS Status;\r
38 EFI_PHYSICAL_ADDRESS Memory; \r
39 EFI_PEI_SERVICES **PeiServices;\r
40\r
41 if (Pages == 0) {\r
42 return NULL;\r
43 }\r
44\r
45 PeiServices = GetPeiServicesTablePointer ();\r
46 Status = (*PeiServices)->AllocatePages (PeiServices, MemoryType, Pages, &Memory);\r
47 if (EFI_ERROR (Status)) {\r
48 Memory = 0;\r
49 }\r
50 return (VOID *) (UINTN) Memory;\r
51}\r
52\r
53/**\r
1f33a17f 54 Allocates one or more 4KB pages of type EfiBootServicesData.\r
878ddf1f 55\r
1f33a17f 56 Allocates the number of 4KB pages of type EfiBootServicesData and returns a pointer to the\r
57 allocated buffer. The buffer returned is aligned on a 4KB boundary. If Pages is 0, then NULL\r
58 is returned. If there is not enough memory remaining to satisfy the request, then NULL is\r
59 returned.\r
878ddf1f 60\r
1f33a17f 61 @param Pages The number of 4 KB pages to allocate.\r
62\r
63 @return A pointer to the allocated buffer or NULL if allocation fails.\r
878ddf1f 64\r
65**/\r
66VOID *\r
67EFIAPI\r
68AllocatePages (\r
69 IN UINTN Pages\r
70 )\r
71{\r
72 return InternalAllocatePages (EfiBootServicesData, Pages);\r
73}\r
74\r
75/**\r
1f33a17f 76 Allocates one or more 4KB pages of type EfiRuntimeServicesData.\r
878ddf1f 77\r
1f33a17f 78 Allocates the number of 4KB pages of type EfiRuntimeServicesData and returns a pointer to the\r
79 allocated buffer. The buffer returned is aligned on a 4KB boundary. If Pages is 0, then NULL\r
80 is returned. If there is not enough memory remaining to satisfy the request, then NULL is\r
81 returned.\r
878ddf1f 82\r
1f33a17f 83 @param Pages The number of 4 KB pages to allocate.\r
84\r
85 @return A pointer to the allocated buffer or NULL if allocation fails.\r
878ddf1f 86\r
87**/\r
88VOID *\r
89EFIAPI\r
90AllocateRuntimePages (\r
91 IN UINTN Pages\r
92 )\r
93{\r
94 return InternalAllocatePages (EfiRuntimeServicesData, Pages);\r
95}\r
96\r
97/**\r
1f33a17f 98 Allocates one or more 4KB pages of type EfiReservedMemoryType.\r
878ddf1f 99\r
1f33a17f 100 Allocates the number of 4KB pages of type EfiReservedMemoryType and returns a pointer to the\r
101 allocated buffer. The buffer returned is aligned on a 4KB boundary. If Pages is 0, then NULL\r
102 is returned. If there is not enough memory remaining to satisfy the request, then NULL is\r
103 returned.\r
878ddf1f 104\r
1f33a17f 105 @param Pages The number of 4 KB pages to allocate.\r
106\r
107 @return A pointer to the allocated buffer or NULL if allocation fails.\r
878ddf1f 108\r
109**/\r
110VOID *\r
111EFIAPI\r
112AllocateReservedPages (\r
113 IN UINTN Pages\r
114 )\r
115{\r
116 return InternalAllocatePages (EfiReservedMemoryType, Pages);\r
117}\r
118\r
119/**\r
1f33a17f 120 Frees one or more 4KB pages that were previously allocated with one of the page allocation\r
121 functions in the Memory Allocation Library.\r
122\r
123 Frees the number of 4KB pages specified by Pages from the buffer specified by Buffer. Buffer\r
124 must have been allocated on a previous call to the page allocation services of the Memory\r
125 Allocation Library.\r
126 If Buffer was not allocated with a page allocation function in the Memory Allocation Library,\r
127 then ASSERT().\r
128 If Pages is zero, then ASSERT().\r
129 \r
130 @param Buffer Pointer to the buffer of pages to free.\r
131 @param Pages The number of 4 KB pages to free.\r
878ddf1f 132\r
133**/\r
134VOID\r
135EFIAPI\r
136FreePages (\r
137 IN VOID *Buffer,\r
138 IN UINTN Pages\r
139 )\r
140{\r
141 //\r
142 // PEI phase does not support to free pages, so leave it as NOP.\r
143 //\r
144}\r
145\r
146/**\r
1f33a17f 147 Allocates one or more 4KB pages of a certain memory type at a specified alignment.\r
148\r
149 Allocates the number of 4KB pages specified by Pages of a certain memory type with an alignment\r
150 specified by Alignment. The allocated buffer is returned. If Pages is 0, then NULL is returned.\r
151 If there is not enough memory at the specified alignment remaining to satisfy the request, then\r
152 NULL is returned.\r
153 If Alignment is not a power of two and Alignment is not zero, then ASSERT().\r
878ddf1f 154\r
1f33a17f 155 @param MemoryType The type of memory to allocate.\r
156 @param Pages The number of 4 KB pages to allocate.\r
157 @param Alignment The requested alignment of the allocation. Must be a power of two.\r
158 If Alignment is zero, then byte alignment is used.\r
878ddf1f 159\r
1f33a17f 160 @return A pointer to the allocated buffer or NULL if allocation fails.\r
878ddf1f 161\r
162**/\r
163VOID *\r
164InternalAllocateAlignedPages (\r
165 IN EFI_MEMORY_TYPE MemoryType, \r
166 IN UINTN Pages,\r
167 IN UINTN Alignment\r
168 )\r
169{\r
170 VOID *Memory;\r
171 UINTN AlignmentMask;\r
172\r
173 //\r
174 // Alignment must be a power of two or zero.\r
175 //\r
176 ASSERT ((Alignment & (Alignment - 1)) == 0);\r
177\r
178 if (Pages == 0) {\r
179 return NULL;\r
180 }\r
181 //\r
a3657e3e 182 // Make sure that Pages plus EFI_SIZE_TO_PAGES (Alignment) does not overflow.\r
183 //\r
184 ASSERT (Pages <= (MAX_ADDRESS - EFI_SIZE_TO_PAGES (Alignment)));\r
185 //\r
878ddf1f 186 // We would rather waste some memory to save PEI code size.\r
187 //\r
188 Memory = InternalAllocatePages (MemoryType, Pages + EFI_SIZE_TO_PAGES (Alignment));\r
189 if (Alignment == 0) {\r
190 AlignmentMask = Alignment;\r
191 } else {\r
192 AlignmentMask = Alignment - 1; \r
193 }\r
194 return (VOID *) (UINTN) (((UINTN) Memory + AlignmentMask) & ~AlignmentMask);\r
195}\r
196\r
197/**\r
1f33a17f 198 Allocates one or more 4KB pages of type EfiBootServicesData at a specified alignment.\r
878ddf1f 199\r
1f33a17f 200 Allocates the number of 4KB pages specified by Pages of type EfiBootServicesData with an\r
201 alignment specified by Alignment. The allocated buffer is returned. If Pages is 0, then NULL is\r
202 returned. If there is not enough memory at the specified alignment remaining to satisfy the\r
203 request, then NULL is returned.\r
204 If Alignment is not a power of two and Alignment is not zero, then ASSERT().\r
878ddf1f 205\r
1f33a17f 206 @param Pages The number of 4 KB pages to allocate.\r
207 @param Alignment The requested alignment of the allocation. Must be a power of two.\r
208 If Alignment is zero, then byte alignment is used.\r
209\r
210 @return A pointer to the allocated buffer or NULL if allocation fails.\r
878ddf1f 211\r
212**/\r
213VOID *\r
214EFIAPI\r
215AllocateAlignedPages (\r
216 IN UINTN Pages,\r
217 IN UINTN Alignment\r
218 )\r
219{\r
220 return InternalAllocateAlignedPages (EfiBootServicesData, Pages, Alignment);\r
221}\r
222\r
223/**\r
1f33a17f 224 Allocates one or more 4KB pages of type EfiRuntimeServicesData at a specified alignment.\r
225\r
226 Allocates the number of 4KB pages specified by Pages of type EfiRuntimeServicesData with an\r
227 alignment specified by Alignment. The allocated buffer is returned. If Pages is 0, then NULL is\r
228 returned. If there is not enough memory at the specified alignment remaining to satisfy the\r
229 request, then NULL is returned.\r
230 If Alignment is not a power of two and Alignment is not zero, then ASSERT().\r
878ddf1f 231\r
1f33a17f 232 @param Pages The number of 4 KB pages to allocate.\r
233 @param Alignment The requested alignment of the allocation. Must be a power of two.\r
234 If Alignment is zero, then byte alignment is used.\r
878ddf1f 235\r
1f33a17f 236 @return A pointer to the allocated buffer or NULL if allocation fails.\r
878ddf1f 237\r
238**/\r
239VOID *\r
240EFIAPI\r
241AllocateAlignedRuntimePages (\r
242 IN UINTN Pages,\r
243 IN UINTN Alignment\r
244 )\r
245{\r
246 return InternalAllocateAlignedPages (EfiRuntimeServicesData, Pages, Alignment);\r
247}\r
248\r
249/**\r
250 Allocates one or more 4KB pages of type EfiReservedMemoryType at a specified alignment.\r
251\r
1f33a17f 252 Allocates the number of 4KB pages specified by Pages of type EfiReservedMemoryType with an\r
253 alignment specified by Alignment. The allocated buffer is returned. If Pages is 0, then NULL is\r
254 returned. If there is not enough memory at the specified alignment remaining to satisfy the\r
255 request, then NULL is returned.\r
256 If Alignment is not a power of two and Alignment is not zero, then ASSERT().\r
878ddf1f 257\r
1f33a17f 258 @param Pages The number of 4 KB pages to allocate.\r
259 @param Alignment The requested alignment of the allocation. Must be a power of two.\r
260 If Alignment is zero, then byte alignment is used.\r
261\r
262 @return A pointer to the allocated buffer or NULL if allocation fails.\r
878ddf1f 263\r
264**/\r
265VOID *\r
266EFIAPI\r
267AllocateAlignedReservedPages (\r
268 IN UINTN Pages,\r
269 IN UINTN Alignment\r
270 )\r
271{\r
272 return InternalAllocateAlignedPages (EfiReservedMemoryType, Pages, Alignment);\r
273}\r
274\r
275/**\r
1f33a17f 276 Frees one or more 4KB pages that were previously allocated with one of the aligned page\r
277 allocation functions in the Memory Allocation Library.\r
278\r
279 Frees the number of 4KB pages specified by Pages from the buffer specified by Buffer. Buffer\r
280 must have been allocated on a previous call to the aligned page allocation services of the Memory\r
281 Allocation Library.\r
282 If Buffer was not allocated with an aligned page allocation function in the Memory Allocation\r
283 Library, then ASSERT().\r
284 If Pages is zero, then ASSERT().\r
285 \r
286 @param Buffer Pointer to the buffer of pages to free.\r
287 @param Pages The number of 4 KB pages to free.\r
878ddf1f 288\r
289**/\r
290VOID\r
291EFIAPI\r
292FreeAlignedPages (\r
293 IN VOID *Buffer,\r
294 IN UINTN Pages\r
295 )\r
296{\r
297 //\r
298 // PEI phase does not support to free pages, so leave it as NOP.\r
299 //\r
300}\r
301\r
302/**\r
1f33a17f 303 Allocates a buffer of a certain pool type.\r
878ddf1f 304\r
1f33a17f 305 Allocates the number bytes specified by AllocationSize of a certain pool type and returns a\r
306 pointer to the allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is\r
307 returned. If there is not enough memory remaining to satisfy the request, then NULL is returned.\r
878ddf1f 308\r
1f33a17f 309 @param MemoryType The type of memory to allocate.\r
310 @param AllocationSize The number of bytes to allocate.\r
311\r
312 @return A pointer to the allocated buffer or NULL if allocation fails.\r
878ddf1f 313\r
314**/\r
315VOID *\r
316InternalAllocatePool (\r
317 IN EFI_MEMORY_TYPE MemoryType, \r
318 IN UINTN AllocationSize\r
319 )\r
320{\r
321 //\r
322 // If we need lots of small runtime/reserved memory type from PEI in the future, \r
323 // we can consider providing a more complex algorithm that allocates runtime pages and \r
324 // provide pool allocations from those pages. \r
325 //\r
326 return InternalAllocatePages (MemoryType, EFI_SIZE_TO_PAGES (AllocationSize));\r
327}\r
328\r
329/**\r
330 Allocates a buffer of type EfiBootServicesData.\r
331\r
1f33a17f 332 Allocates the number bytes specified by AllocationSize of type EfiBootServicesData and returns a\r
333 pointer to the allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is\r
334 returned. If there is not enough memory remaining to satisfy the request, then NULL is returned.\r
878ddf1f 335\r
1f33a17f 336 @param AllocationSize The number of bytes to allocate.\r
337\r
338 @return A pointer to the allocated buffer or NULL if allocation fails.\r
878ddf1f 339\r
340**/\r
341VOID *\r
342EFIAPI\r
343AllocatePool (\r
344 IN UINTN AllocationSize\r
345 )\r
346{\r
347 EFI_STATUS Status;\r
348 EFI_PEI_SERVICES **PeiServices;\r
349 VOID *Buffer;\r
350 \r
351 PeiServices = GetPeiServicesTablePointer ();\r
352\r
353 Status = (*PeiServices)->AllocatePool (PeiServices, AllocationSize, &Buffer);\r
354 if (EFI_ERROR (Status)) {\r
355 Buffer = NULL;\r
356 }\r
357 return Buffer;\r
358}\r
359\r
360/**\r
361 Allocates a buffer of type EfiRuntimeServicesData.\r
362\r
1f33a17f 363 Allocates the number bytes specified by AllocationSize of type EfiRuntimeServicesData and returns\r
364 a pointer to the allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is\r
365 returned. If there is not enough memory remaining to satisfy the request, then NULL is returned.\r
878ddf1f 366\r
1f33a17f 367 @param AllocationSize The number of bytes to allocate.\r
368\r
369 @return A pointer to the allocated buffer or NULL if allocation fails.\r
878ddf1f 370\r
371**/\r
372VOID *\r
373EFIAPI\r
374AllocateRuntimePool (\r
375 IN UINTN AllocationSize\r
376 )\r
377{\r
378 return InternalAllocatePool (EfiRuntimeServicesData, AllocationSize);\r
379}\r
380\r
381/**\r
1f33a17f 382 Allocates a buffer of type EfieservedMemoryType.\r
878ddf1f 383\r
1f33a17f 384 Allocates the number bytes specified by AllocationSize of type EfieservedMemoryType and returns\r
385 a pointer to the allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is\r
386 returned. If there is not enough memory remaining to satisfy the request, then NULL is returned.\r
878ddf1f 387\r
1f33a17f 388 @param AllocationSize The number of bytes to allocate.\r
389\r
390 @return A pointer to the allocated buffer or NULL if allocation fails.\r
878ddf1f 391\r
392**/\r
393VOID *\r
394EFIAPI\r
395AllocateReservedPool (\r
396 IN UINTN AllocationSize\r
397 )\r
398{\r
399 return InternalAllocatePool (EfiReservedMemoryType, AllocationSize);\r
400}\r
401\r
402/**\r
403 Allocates and zeros a buffer of a certian pool type.\r
404\r
1f33a17f 405 Allocates the number bytes specified by AllocationSize of a certian pool type, clears the buffer\r
406 with zeros, and returns a pointer to the allocated buffer. If AllocationSize is 0, then a valid\r
407 buffer of 0 size is returned. If there is not enough memory remaining to satisfy the request,\r
408 then NULL is returned.\r
878ddf1f 409\r
1f33a17f 410 @param PoolType The type of memory to allocate.\r
411 @param AllocationSize The number of bytes to allocate and zero.\r
412\r
413 @return A pointer to the allocated buffer or NULL if allocation fails.\r
878ddf1f 414\r
415**/\r
416VOID *\r
417InternalAllocateZeroPool (\r
418 IN EFI_MEMORY_TYPE PoolType, \r
419 IN UINTN AllocationSize\r
420 ) \r
421{\r
422 VOID *Memory;\r
423\r
424 Memory = InternalAllocatePool (PoolType, AllocationSize);\r
425 if (Memory != NULL) {\r
426 Memory = ZeroMem (Memory, AllocationSize);\r
427 }\r
428 return Memory;\r
429}\r
430\r
431/**\r
432 Allocates and zeros a buffer of type EfiBootServicesData.\r
433\r
1f33a17f 434 Allocates the number bytes specified by AllocationSize of type EfiBootServicesData, clears the\r
435 buffer with zeros, and returns a pointer to the allocated buffer. If AllocationSize is 0, then a\r
436 valid buffer of 0 size is returned. If there is not enough memory remaining to satisfy the\r
437 request, then NULL is returned.\r
878ddf1f 438\r
1f33a17f 439 @param AllocationSize The number of bytes to allocate and zero.\r
440\r
441 @return A pointer to the allocated buffer or NULL if allocation fails.\r
878ddf1f 442\r
443**/\r
444VOID *\r
445EFIAPI\r
446AllocateZeroPool (\r
447 IN UINTN AllocationSize\r
448 )\r
449{\r
450 VOID *Memory;\r
451\r
452 Memory = AllocatePool (AllocationSize);\r
453 if (Memory != NULL) {\r
454 Memory = ZeroMem (Memory, AllocationSize);\r
455 }\r
456 return Memory;\r
457}\r
458\r
459/**\r
460 Allocates and zeros a buffer of type EfiRuntimeServicesData.\r
461\r
1f33a17f 462 Allocates the number bytes specified by AllocationSize of type EfiRuntimeServicesData, clears the\r
463 buffer with zeros, and returns a pointer to the allocated buffer. If AllocationSize is 0, then a\r
464 valid buffer of 0 size is returned. If there is not enough memory remaining to satisfy the\r
465 request, then NULL is returned.\r
878ddf1f 466\r
1f33a17f 467 @param AllocationSize The number of bytes to allocate and zero.\r
468\r
469 @return A pointer to the allocated buffer or NULL if allocation fails.\r
878ddf1f 470\r
471**/\r
472VOID *\r
473EFIAPI\r
474AllocateRuntimeZeroPool (\r
475 IN UINTN AllocationSize\r
476 )\r
477{\r
478 return InternalAllocateZeroPool (EfiRuntimeServicesData, AllocationSize);\r
479}\r
480\r
481/**\r
482 Allocates and zeros a buffer of type EfiReservedMemoryType.\r
483\r
1f33a17f 484 Allocates the number bytes specified by AllocationSize of type EfiReservedMemoryType, clears the\r
485 buffer with zeros, and returns a pointer to the allocated buffer. If AllocationSize is 0, then a\r
486 valid buffer of 0 size is returned. If there is not enough memory remaining to satisfy the\r
487 request, then NULL is returned.\r
878ddf1f 488\r
1f33a17f 489 @param AllocationSize The number of bytes to allocate and zero.\r
490\r
491 @return A pointer to the allocated buffer or NULL if allocation fails.\r
878ddf1f 492\r
493**/\r
494VOID *\r
495EFIAPI\r
496AllocateReservedZeroPool (\r
497 IN UINTN AllocationSize\r
498 )\r
499{\r
500 return InternalAllocateZeroPool (EfiReservedMemoryType, AllocationSize);\r
501}\r
502\r
503/**\r
1f33a17f 504 Copies a buffer to an allocated buffer of a certian pool type.\r
878ddf1f 505\r
1f33a17f 506 Allocates the number bytes specified by AllocationSize of a certian pool type, copies\r
507 AllocationSize bytes from Buffer to the newly allocated buffer, and returns a pointer to the\r
508 allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is returned. If there\r
509 is not enough memory remaining to satisfy the request, then NULL is returned.\r
510 If Buffer is NULL, then ASSERT().\r
511