]> git.proxmox.com Git - mirror_edk2.git/blame - MdePkg/Library/DxeMemoryAllocationLib/MemoryAllocationLib.c
Adjust coding style for MemoryAllocationLib.
[mirror_edk2.git] / MdePkg / Library / DxeMemoryAllocationLib / 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\r
40 if (Pages == 0) {\r
41 return NULL;\r
42 }\r
43\r
44 Status = gBS->AllocatePages (AllocateAnyPages, MemoryType, Pages, &Memory);\r
45 if (EFI_ERROR (Status)) {\r
46 Memory = 0;\r
47 }\r
48 return (VOID *) (UINTN) Memory;\r
49}\r
50\r
51/**\r
1f33a17f 52 Allocates one or more 4KB pages of type EfiBootServicesData.\r
878ddf1f 53\r
1f33a17f 54 Allocates the number of 4KB pages of type EfiBootServicesData and returns a pointer to the\r
55 allocated buffer. The buffer returned is aligned on a 4KB boundary. If Pages is 0, then NULL\r
56 is returned. If there is not enough memory remaining to satisfy the request, then NULL is\r
57 returned.\r
878ddf1f 58\r
1f33a17f 59 @param Pages The number of 4 KB pages to allocate.\r
60\r
61 @return A pointer to the allocated buffer or NULL if allocation fails.\r
878ddf1f 62\r
63**/\r
64VOID *\r
65EFIAPI\r
66AllocatePages (\r
67 IN UINTN Pages\r
68 )\r
69{\r
70 return InternalAllocatePages (EfiBootServicesData, Pages);\r
71}\r
72\r
73/**\r
1f33a17f 74 Allocates one or more 4KB pages of type EfiRuntimeServicesData.\r
878ddf1f 75\r
1f33a17f 76 Allocates the number of 4KB pages of type EfiRuntimeServicesData and returns a pointer to the\r
77 allocated buffer. The buffer returned is aligned on a 4KB boundary. If Pages is 0, then NULL\r
78 is returned. If there is not enough memory remaining to satisfy the request, then NULL is\r
79 returned.\r
878ddf1f 80\r
1f33a17f 81 @param Pages The number of 4 KB pages to allocate.\r
82\r
83 @return A pointer to the allocated buffer or NULL if allocation fails.\r
878ddf1f 84\r
85**/\r
86VOID *\r
87EFIAPI\r
88AllocateRuntimePages (\r
89 IN UINTN Pages\r
90 )\r
91{\r
92 return InternalAllocatePages (EfiRuntimeServicesData, Pages);\r
93}\r
94\r
95/**\r
1f33a17f 96 Allocates one or more 4KB pages of type EfiReservedMemoryType.\r
878ddf1f 97\r
1f33a17f 98 Allocates the number of 4KB pages of type EfiReservedMemoryType and returns a pointer to the\r
99 allocated buffer. The buffer returned is aligned on a 4KB boundary. If Pages is 0, then NULL\r
100 is returned. If there is not enough memory remaining to satisfy the request, then NULL is\r
101 returned.\r
878ddf1f 102\r
1f33a17f 103 @param Pages The number of 4 KB pages to allocate.\r
104\r
105 @return A pointer to the allocated buffer or NULL if allocation fails.\r
878ddf1f 106\r
107**/\r
108VOID *\r
109EFIAPI\r
110AllocateReservedPages (\r
111 IN UINTN Pages\r
112 )\r
113{\r
114 return InternalAllocatePages (EfiReservedMemoryType, Pages);\r
115}\r
116\r
117/**\r
1f33a17f 118 Frees one or more 4KB pages that were previously allocated with one of the page allocation\r
119 functions in the Memory Allocation Library.\r
120\r
121 Frees the number of 4KB pages specified by Pages from the buffer specified by Buffer. Buffer\r
122 must have been allocated on a previous call to the page allocation services of the Memory\r
123 Allocation Library.\r
124 If Buffer was not allocated with a page allocation function in the Memory Allocation Library,\r
125 then ASSERT().\r
126 If Pages is zero, then ASSERT().\r
127 \r
128 @param Buffer Pointer to the buffer of pages to free.\r
129 @param Pages The number of 4 KB pages to free.\r
878ddf1f 130\r
131**/\r
132VOID\r
133EFIAPI\r
134FreePages (\r
135 IN VOID *Buffer,\r
136 IN UINTN Pages\r
137 )\r
138{\r
139 EFI_STATUS Status;\r
140\r
141 ASSERT (Pages != 0);\r
142 Status = gBS->FreePages ((EFI_PHYSICAL_ADDRESS) (UINTN) Buffer, Pages);\r
143 ASSERT_EFI_ERROR (Status);\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
878ddf1f 148\r
1f33a17f 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
159\r
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 EFI_STATUS Status;\r
171 EFI_PHYSICAL_ADDRESS Memory;\r
172 UINTN AlignedMemory;\r
173 UINTN AlignmentMask;\r
174 UINTN UnalignedPages;\r
175 UINTN RealPages;\r
176\r
177 //\r
178 // Alignment must be a power of two or zero.\r
179 //\r
180 ASSERT ((Alignment & (Alignment - 1)) == 0);\r
181 \r
182 if (Pages == 0) {\r
183 return NULL;\r
184 }\r
185 if (Alignment > EFI_PAGE_SIZE) {\r
186 //\r
187 // Caculate the total number of pages since alignment is larger than page size.\r
188 //\r
189 AlignmentMask = Alignment - 1;\r
190 RealPages = Pages + EFI_SIZE_TO_PAGES (Alignment);\r
a3657e3e 191 //\r
192 // Make sure that Pages plus EFI_SIZE_TO_PAGES (Alignment) does not overflow.\r
193 //\r
194 ASSERT (RealPages > Pages);\r
195 \r
878ddf1f 196 Status = gBS->AllocatePages (AllocateAnyPages, MemoryType, RealPages, &Memory);\r
197 if (EFI_ERROR (Status)) {\r
198 return NULL;\r
199 }\r
200 AlignedMemory = ((UINTN) Memory + AlignmentMask) & ~AlignmentMask;\r
201 UnalignedPages = EFI_SIZE_TO_PAGES ((UINTN) Memory - AlignedMemory);\r
202 if (UnalignedPages > 0) {\r
203 //\r
204 // Free first unaligned page(s).\r
205 //\r
206 Status = gBS->FreePages (Memory, UnalignedPages);\r
207 ASSERT_EFI_ERROR (Status);\r
208 }\r
209 Memory = (EFI_PHYSICAL_ADDRESS) (AlignedMemory + EFI_PAGES_TO_SIZE (Pages));\r
210 UnalignedPages = RealPages - Pages - UnalignedPages;\r
211 if (UnalignedPages > 0) {\r
212 //\r
213 // Free last unaligned page(s).\r
214 //\r
215 Status = gBS->FreePages (Memory, UnalignedPages);\r
216 ASSERT_EFI_ERROR (Status);\r
217 }\r
218 } else {\r
219 //\r
220 // Do not over-allocate pages in this case.\r
221 //\r
222 Status = gBS->AllocatePages (AllocateAnyPages, MemoryType, Pages, &Memory);\r
223 if (EFI_ERROR (Status)) {\r
224 return NULL;\r
225 }\r
226 AlignedMemory = (UINTN) Memory;\r
227 }\r
228 return (VOID *) AlignedMemory;\r
229}\r
230\r
231/**\r
1f33a17f 232 Allocates one or more 4KB pages of type EfiBootServicesData at a specified alignment.\r
233\r
234 Allocates the number of 4KB pages specified by Pages of type EfiBootServicesData with an\r
235 alignment specified by Alignment. The allocated buffer is returned. If Pages is 0, then NULL is\r
236 returned. If there is not enough memory at the specified alignment remaining to satisfy the\r
237 request, then NULL is returned.\r
238 If Alignment is not a power of two and Alignment is not zero, then ASSERT().\r
878ddf1f 239\r
1f33a17f 240 @param Pages The number of 4 KB pages to allocate.\r
241 @param Alignment The requested alignment of the allocation. Must be a power of two.\r
242 If Alignment is zero, then byte alignment is used.\r
878ddf1f 243\r
1f33a17f 244 @return A pointer to the allocated buffer or NULL if allocation fails.\r
878ddf1f 245\r
246**/\r
247VOID *\r
248EFIAPI\r
249AllocateAlignedPages (\r
250 IN UINTN Pages,\r
251 IN UINTN Alignment\r
252 )\r
253{\r
254 return InternalAllocateAlignedPages (EfiBootServicesData, Pages, Alignment);\r
255}\r
256\r
257/**\r
1f33a17f 258 Allocates one or more 4KB pages of type EfiRuntimeServicesData at a specified alignment.\r
878ddf1f 259\r
1f33a17f 260 Allocates the number of 4KB pages specified by Pages of type EfiRuntimeServicesData with an\r
261 alignment specified by Alignment. The allocated buffer is returned. If Pages is 0, then NULL is\r
262 returned. If there is not enough memory at the specified alignment remaining to satisfy the\r
263 request, then NULL is returned.\r
264 If Alignment is not a power of two and Alignment is not zero, then ASSERT().\r
878ddf1f 265\r
1f33a17f 266 @param Pages The number of 4 KB pages to allocate.\r
267 @param Alignment The requested alignment of the allocation. Must be a power of two.\r
268 If Alignment is zero, then byte alignment is used.\r
269\r
270 @return A pointer to the allocated buffer or NULL if allocation fails.\r
878ddf1f 271\r
272**/\r
273VOID *\r
274EFIAPI\r
275AllocateAlignedRuntimePages (\r
276 IN UINTN Pages,\r
277 IN UINTN Alignment\r
278 )\r
279{\r
280 return InternalAllocateAlignedPages (EfiRuntimeServicesData, Pages, Alignment);\r
281}\r
282\r
283/**\r
284 Allocates one or more 4KB pages of type EfiReservedMemoryType at a specified alignment.\r
285\r
1f33a17f 286 Allocates the number of 4KB pages specified by Pages of type EfiReservedMemoryType with an\r
287 alignment specified by Alignment. The allocated buffer is returned. If Pages is 0, then NULL is\r
288 returned. If there is not enough memory at the specified alignment remaining to satisfy the\r
289 request, then NULL is returned.\r
290 If Alignment is not a power of two and Alignment is not zero, then ASSERT().\r
291\r
292 @param Pages The number of 4 KB pages to allocate.\r
293 @param Alignment The requested alignment of the allocation. Must be a power of two.\r
294 If Alignment is zero, then byte alignment is used.\r
878ddf1f 295\r
1f33a17f 296 @return A pointer to the allocated buffer or NULL if allocation fails.\r
878ddf1f 297\r
298**/\r
299VOID *\r
300EFIAPI\r
301AllocateAlignedReservedPages (\r
302 IN UINTN Pages,\r
303 IN UINTN Alignment\r
304 )\r
305{\r
306 return InternalAllocateAlignedPages (EfiReservedMemoryType, Pages, Alignment);\r
307}\r
308\r
309/**\r
1f33a17f 310 Frees one or more 4KB pages that were previously allocated with one of the aligned page\r
311 allocation functions in the Memory Allocation Library.\r
312\r
313 Frees the number of 4KB pages specified by Pages from the buffer specified by Buffer. Buffer\r
314 must have been allocated on a previous call to the aligned page allocation services of the Memory\r
315 Allocation Library.\r
316 If Buffer was not allocated with an aligned page allocation function in the Memory Allocation\r
317 Library, then ASSERT().\r
318 If Pages is zero, then ASSERT().\r
319 \r
320 @param Buffer Pointer to the buffer of pages to free.\r
321 @param Pages The number of 4 KB pages to free.\r
878ddf1f 322\r
323**/\r
324VOID\r
325EFIAPI\r
326FreeAlignedPages (\r
327 IN VOID *Buffer,\r
328 IN UINTN Pages\r
329 )\r
330{\r
331 EFI_STATUS Status;\r
332\r
333 ASSERT (Pages != 0);\r
334 Status = gBS->FreePages ((EFI_PHYSICAL_ADDRESS) (UINTN) Buffer, Pages);\r
335 ASSERT_EFI_ERROR (Status);\r
336}\r
337\r
338/**\r
1f33a17f 339 Allocates a buffer of a certain pool type.\r
878ddf1f 340\r
1f33a17f 341 Allocates the number bytes specified by AllocationSize of a certain pool type and returns a\r
342 pointer to the allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is\r
343 returned. If there is not enough memory remaining to satisfy the request, then NULL is returned.\r
878ddf1f 344\r
1f33a17f 345 @param MemoryType The type of memory to allocate.\r
346 @param AllocationSize The number of bytes to allocate.\r
347\r
348 @return A pointer to the allocated buffer or NULL if allocation fails.\r
878ddf1f 349\r
350**/\r
351VOID *\r
352InternalAllocatePool (\r
353 IN EFI_MEMORY_TYPE MemoryType, \r
354 IN UINTN AllocationSize\r
355 )\r
356{\r
357 EFI_STATUS Status;\r
358 VOID *Memory;\r
359\r
360 Status = gBS->AllocatePool (MemoryType, AllocationSize, &Memory);\r
361 if (EFI_ERROR (Status)) {\r
362 Memory = NULL;\r
363 }\r
364 return Memory;\r
365}\r
366\r
367/**\r
368 Allocates a buffer of type EfiBootServicesData.\r
369\r
1f33a17f 370 Allocates the number bytes specified by AllocationSize of type EfiBootServicesData and returns a\r
371 pointer to the allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is\r
372 returned. If there is not enough memory remaining to satisfy the request, then NULL is returned.\r
878ddf1f 373\r
1f33a17f 374 @param AllocationSize The number of bytes to allocate.\r
375\r
376 @return A pointer to the allocated buffer or NULL if allocation fails.\r
878ddf1f 377\r
378**/\r
379VOID *\r
380EFIAPI\r
381AllocatePool (\r
382 IN UINTN AllocationSize\r
383 )\r
384{\r
385 return InternalAllocatePool (EfiBootServicesData, AllocationSize);\r
386}\r
387\r
388/**\r
389 Allocates a buffer of type EfiRuntimeServicesData.\r
390\r
1f33a17f 391 Allocates the number bytes specified by AllocationSize of type EfiRuntimeServicesData and returns\r
392 a pointer to the allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is\r
393 returned. If there is not enough memory remaining to satisfy the request, then NULL is returned.\r
878ddf1f 394\r
1f33a17f 395 @param AllocationSize The number of bytes to allocate.\r
396\r
397 @return A pointer to the allocated buffer or NULL if allocation fails.\r
878ddf1f 398\r
399**/\r
400VOID *\r
401EFIAPI\r
402AllocateRuntimePool (\r
403 IN UINTN AllocationSize\r
404 )\r
405{\r
406 return InternalAllocatePool (EfiRuntimeServicesData, AllocationSize);\r
407}\r
408\r
409/**\r
1f33a17f 410 Allocates a buffer of type EfieservedMemoryType.\r
878ddf1f 411\r
1f33a17f 412 Allocates the number bytes specified by AllocationSize of type EfieservedMemoryType and returns\r
413 a pointer to the allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is\r
414 returned. If there is not enough memory remaining to satisfy the request, then NULL is returned.\r
878ddf1f 415\r
1f33a17f 416 @param AllocationSize The number of bytes to allocate.\r
417\r
418 @return A pointer to the allocated buffer or NULL if allocation fails.\r
878ddf1f 419\r
420**/\r
421VOID *\r
422EFIAPI\r
423AllocateReservedPool (\r
424 IN UINTN AllocationSize\r
425 )\r
426{\r
427 return InternalAllocatePool (EfiReservedMemoryType, AllocationSize);\r
428}\r
429\r
430/**\r
431 Allocates and zeros a buffer of a certian pool type.\r
432\r
1f33a17f 433 Allocates the number bytes specified by AllocationSize of a certian pool type, clears the buffer\r
434 with zeros, and returns a pointer to the allocated buffer. If AllocationSize is 0, then a valid\r
435 buffer of 0 size is returned. If there is not enough memory remaining to satisfy the request,\r
436 then NULL is returned.\r
878ddf1f 437\r
1f33a17f 438 @param PoolType The type of memory to allocate.\r
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
445InternalAllocateZeroPool (\r
446 IN EFI_MEMORY_TYPE PoolType, \r
447 IN UINTN AllocationSize\r
448 ) \r
449{\r
450 VOID *Memory;\r
1f33a17f 451\r
878ddf1f 452 Memory = InternalAllocatePool (PoolType, 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 EfiBootServicesData.\r
461\r
1f33a17f 462 Allocates the number bytes specified by AllocationSize of type EfiBootServicesData, 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
474AllocateZeroPool (\r
475 IN UINTN AllocationSize\r
476 )\r
477{\r
478 return InternalAllocateZeroPool (EfiBootServicesData, AllocationSize);\r
479}\r
480\r
481/**\r
482 Allocates and zeros a buffer of type EfiRuntimeServicesData.\r
483\r
1f33a17f 484 Allocates the number bytes specified by AllocationSize of type EfiRuntimeServicesData, 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
496AllocateRuntimeZeroPool (\r
497 IN UINTN AllocationSize\r
498 )\r
499{\r
500 return InternalAllocateZeroPool (EfiRuntimeServicesData, AllocationSize);\r
501}\r
502\r
503/**\r
504 Allocates and zeros a buffer of type EfiReservedMemoryType.\r
505\r
1f33a17f 506 Allocates the number bytes specified by AllocationSize of type EfiReservedMemoryType, clears the\r
507 buffer with zeros, and returns a pointer to the allocated buffer. If AllocationSize is 0, then a\r
508 valid buffer of 0 size is returned. If there is not enough memory remaining to satisfy the\r
509 request, then NULL is returned.\r
878ddf1f 510\r
1f33a17f 511 @param AllocationSize The number of bytes to allocate and zero.\r
512\r
513 @return A pointer to the allocated buffer or NULL if allocation fails.\r
878ddf1f 514\r
515**/\r
516VOID *\r
517EFIAPI\r
518AllocateReservedZeroPool (\r
519 IN UINTN AllocationSize\r
520 )\r
521{\r
522 return InternalAllocateZeroPool (EfiReservedMemoryType, AllocationSize);\r
523}\r
524\r
525/**\r
1f33a17f 526 Copies a buffer to an allocated buffer of a certian pool type.\r
878ddf1f 527\r
1f33a17f 528 Allocates the number bytes specified by AllocationSize of a certian pool type, copies\r
529 AllocationSize bytes from Buffer to the newly allocated buffer, and returns a pointer to the\r
530 allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is returned. If there\r
531 is not enough memory remaining to satisfy the request, then NULL is returned.\r
532 If Buffer is NULL, then ASSERT().\r
533