]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Library/PiSmmCoreMemoryAllocationLib/MemoryAllocationLib.c
MdeModulePkg: Fix the build fail issue on VS2008\VS2010\GCC
[mirror_edk2.git] / MdeModulePkg / Library / PiSmmCoreMemoryAllocationLib / MemoryAllocationLib.c
CommitLineData
713b7781 1/** @file\r
2 Support routines for memory allocation routines based on SMM Core internal functions.\r
2d28f3b7
QS
3 \r
4 The PI System Management Mode Core Interface Specification only allows the use\r
5 of EfiRuntimeServicesCode and EfiRuntimeServicesData memory types for memory \r
6 allocations as the SMRAM space should be reserved after BDS phase. The functions \r
7 in the Memory Allocation Library use EfiBootServicesData as the default memory \r
8 allocation type. For this SMM specific instance of the Memory Allocation Library, \r
9 EfiRuntimeServicesData is used as the default memory type for all allocations. \r
10 In addition, allocation for the Reserved memory types are not supported and will \r
11 always return NULL.\r
713b7781 12\r
842b1242 13 Copyright (c) 2006 - 2015, Intel Corporation. All rights reserved.<BR>\r
cd5ebaa0 14 This program and the accompanying materials \r
713b7781 15 are licensed and made available under the terms and conditions of the BSD License \r
16 which accompanies this distribution. The full text of the license may be found at \r
17 http://opensource.org/licenses/bsd-license.php \r
18\r
19 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
20 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. \r
21\r
22**/\r
23\r
24#include <PiSmm.h>\r
25\r
34401578 26#include <Protocol/SmmAccess2.h>\r
713b7781 27#include <Library/MemoryAllocationLib.h>\r
34401578 28#include <Library/UefiBootServicesTableLib.h>\r
713b7781 29#include <Library/BaseMemoryLib.h>\r
30#include <Library/DebugLib.h>\r
31#include "PiSmmCoreMemoryAllocationServices.h"\r
32\r
f3b6e048
SZ
33EFI_SMRAM_DESCRIPTOR *mSmmCoreMemoryAllocLibSmramRanges = NULL;\r
34UINTN mSmmCoreMemoryAllocLibSmramRangeCount = 0;\r
34401578
LG
35\r
36/**\r
37 Check whether the start address of buffer is within any of the SMRAM ranges.\r
38\r
39 @param[in] Buffer The pointer to the buffer to be checked.\r
40\r
41 @retval TURE The buffer is in SMRAM ranges.\r
42 @retval FALSE The buffer is out of SMRAM ranges.\r
43**/\r
44BOOLEAN\r
45EFIAPI\r
46BufferInSmram (\r
47 IN VOID *Buffer\r
48 )\r
49{\r
50 UINTN Index;\r
51\r
f3b6e048
SZ
52 for (Index = 0; Index < mSmmCoreMemoryAllocLibSmramRangeCount; Index ++) {\r
53 if (((EFI_PHYSICAL_ADDRESS) (UINTN) Buffer >= mSmmCoreMemoryAllocLibSmramRanges[Index].CpuStart) && \r
54 ((EFI_PHYSICAL_ADDRESS) (UINTN) Buffer < (mSmmCoreMemoryAllocLibSmramRanges[Index].CpuStart + mSmmCoreMemoryAllocLibSmramRanges[Index].PhysicalSize))) {\r
34401578
LG
55 return TRUE;\r
56 }\r
57 }\r
58\r
59 return FALSE;\r
60}\r
61\r
713b7781 62/**\r
63 Allocates one or more 4KB pages of a certain memory type.\r
64\r
65 Allocates the number of 4KB pages of a certain memory type and returns a pointer to the allocated\r
66 buffer. The buffer returned is aligned on a 4KB boundary. If Pages is 0, then NULL is returned.\r
67 If there is not enough memory remaining to satisfy the request, then NULL is returned.\r
68\r
69 @param MemoryType The type of memory to allocate.\r
70 @param Pages The number of 4 KB pages to allocate.\r
71\r
72 @return A pointer to the allocated buffer or NULL if allocation fails.\r
73\r
74**/\r
75VOID *\r
76InternalAllocatePages (\r
77 IN EFI_MEMORY_TYPE MemoryType, \r
78 IN UINTN Pages\r
79 )\r
80{\r
81 EFI_STATUS Status;\r
82 EFI_PHYSICAL_ADDRESS Memory; \r
83\r
84 if (Pages == 0) {\r
85 return NULL;\r
86 }\r
87\r
88 Status = SmmAllocatePages (AllocateAnyPages, MemoryType, Pages, &Memory);\r
89 if (EFI_ERROR (Status)) {\r
90 return NULL;\r
91 }\r
92 return (VOID *) (UINTN) Memory;\r
93}\r
94\r
95/**\r
2d28f3b7 96 Allocates one or more 4KB pages of type EfiRuntimeServicesData.\r
713b7781 97\r
2d28f3b7 98 Allocates the number of 4KB pages of type EfiRuntimeServicesData and returns a pointer to the\r
713b7781 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
102\r
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
106\r
107**/\r
108VOID *\r
109EFIAPI\r
110AllocatePages (\r
111 IN UINTN Pages\r
112 )\r
113{\r
114 return InternalAllocatePages (EfiRuntimeServicesData, Pages);\r
115}\r
116\r
117/**\r
118 Allocates one or more 4KB pages of type EfiRuntimeServicesData.\r
119\r
120 Allocates the number of 4KB pages of type EfiRuntimeServicesData and returns a pointer to the\r
121 allocated buffer. The buffer returned is aligned on a 4KB boundary. If Pages is 0, then NULL\r
122 is returned. If there is not enough memory remaining to satisfy the request, then NULL is\r
123 returned.\r
124\r
125 @param Pages The number of 4 KB pages to allocate.\r
126\r
127 @return A pointer to the allocated buffer or NULL if allocation fails.\r
128\r
129**/\r
130VOID *\r
131EFIAPI\r
132AllocateRuntimePages (\r
133 IN UINTN Pages\r
134 )\r
135{\r
136 return InternalAllocatePages (EfiRuntimeServicesData, Pages);\r
137}\r
138\r
139/**\r
140 Allocates one or more 4KB pages of type EfiReservedMemoryType.\r
141\r
142 Allocates the number of 4KB pages of type EfiReservedMemoryType and returns a pointer to the\r
143 allocated buffer. The buffer returned is aligned on a 4KB boundary. If Pages is 0, then NULL\r
144 is returned. If there is not enough memory remaining to satisfy the request, then NULL is\r
145 returned.\r
146\r
147 @param Pages The number of 4 KB pages to allocate.\r
148\r
149 @return A pointer to the allocated buffer or NULL if allocation fails.\r
150\r
151**/\r
152VOID *\r
153EFIAPI\r
154AllocateReservedPages (\r
155 IN UINTN Pages\r
156 )\r
157{\r
158 return NULL;\r
159}\r
160\r
161/**\r
162 Frees one or more 4KB pages that were previously allocated with one of the page allocation\r
163 functions in the Memory Allocation Library.\r
164\r
165 Frees the number of 4KB pages specified by Pages from the buffer specified by Buffer. Buffer\r
166 must have been allocated on a previous call to the page allocation services of the Memory\r
167 Allocation Library. If it is not possible to free allocated pages, then this function will\r
168 perform no actions.\r
169 \r
170 If Buffer was not allocated with a page allocation function in the Memory Allocation Library,\r
171 then ASSERT().\r
172 If Pages is zero, then ASSERT().\r
173 \r
174 @param Buffer Pointer to the buffer of pages to free.\r
175 @param Pages The number of 4 KB pages to free.\r
176\r
177**/\r
178VOID\r
179EFIAPI\r
180FreePages (\r
181 IN VOID *Buffer,\r
182 IN UINTN Pages\r
183 )\r
184{\r
185 EFI_STATUS Status;\r
186\r
187 ASSERT (Pages != 0);\r
34401578
LG
188 if (BufferInSmram (Buffer)) {\r
189 //\r
190 // When Buffer is in SMRAM range, it should be allocated by SmmAllocatePages() service.\r
191 // So, SmmFreePages() service is used to free it.\r
192 //\r
193 Status = SmmFreePages ((EFI_PHYSICAL_ADDRESS) (UINTN) Buffer, Pages);\r
194 } else {\r
195 //\r
196 // When Buffer is out of SMRAM range, it should be allocated by gBS->AllocatePages() service.\r
197 // So, gBS->FreePages() service is used to free it.\r
198 //\r
199 Status = gBS->FreePages ((EFI_PHYSICAL_ADDRESS) (UINTN) Buffer, Pages);\r
200 }\r
713b7781 201 ASSERT_EFI_ERROR (Status);\r
202}\r
203\r
204/**\r
205 Allocates one or more 4KB pages of a certain memory type at a specified alignment.\r
206\r
207 Allocates the number of 4KB pages specified by Pages of a certain memory type with an alignment\r
208 specified by Alignment. The allocated buffer is returned. If Pages is 0, then NULL is returned.\r
209 If there is not enough memory at the specified alignment remaining to satisfy the request, then\r
210 NULL is returned.\r
211 If Alignment is not a power of two and Alignment is not zero, then ASSERT().\r
91403ce9 212 If Pages plus EFI_SIZE_TO_PAGES (Alignment) overflows, then ASSERT().\r
713b7781 213\r
214 @param MemoryType The type of memory to allocate.\r
215 @param Pages The number of 4 KB pages to allocate.\r
216 @param Alignment The requested alignment of the allocation. Must be a power of two.\r
217 If Alignment is zero, then byte alignment is used.\r
218\r
219 @return A pointer to the allocated buffer or NULL if allocation fails.\r
220\r
221**/\r
222VOID *\r
223InternalAllocateAlignedPages (\r
224 IN EFI_MEMORY_TYPE MemoryType, \r
225 IN UINTN Pages,\r
226 IN UINTN Alignment\r
227 )\r
228{\r
229 EFI_STATUS Status;\r
230 EFI_PHYSICAL_ADDRESS Memory;\r
231 UINTN AlignedMemory;\r
232 UINTN AlignmentMask;\r
233 UINTN UnalignedPages;\r
234 UINTN RealPages;\r
235\r
236 //\r
237 // Alignment must be a power of two or zero.\r
238 //\r
239 ASSERT ((Alignment & (Alignment - 1)) == 0);\r
240 \r
241 if (Pages == 0) {\r
242 return NULL;\r
243 }\r
244 if (Alignment > EFI_PAGE_SIZE) {\r
245 //\r
e50a226b 246 // Calculate the total number of pages since alignment is larger than page size.\r
713b7781 247 //\r
248 AlignmentMask = Alignment - 1;\r
249 RealPages = Pages + EFI_SIZE_TO_PAGES (Alignment);\r
250 //\r
251 // Make sure that Pages plus EFI_SIZE_TO_PAGES (Alignment) does not overflow.\r
252 //\r
253 ASSERT (RealPages > Pages);\r
254 \r
255 Status = SmmAllocatePages (AllocateAnyPages, MemoryType, RealPages, &Memory);\r
256 if (EFI_ERROR (Status)) {\r
257 return NULL;\r
258 }\r
259 AlignedMemory = ((UINTN) Memory + AlignmentMask) & ~AlignmentMask;\r
260 UnalignedPages = EFI_SIZE_TO_PAGES (AlignedMemory - (UINTN) Memory);\r
261 if (UnalignedPages > 0) {\r
262 //\r
263 // Free first unaligned page(s).\r
264 //\r
265 Status = SmmFreePages (Memory, UnalignedPages);\r
266 ASSERT_EFI_ERROR (Status);\r
267 }\r
268 Memory = (EFI_PHYSICAL_ADDRESS) (AlignedMemory + EFI_PAGES_TO_SIZE (Pages));\r
269 UnalignedPages = RealPages - Pages - UnalignedPages;\r
270 if (UnalignedPages > 0) {\r
271 //\r
272 // Free last unaligned page(s).\r
273 //\r
274 Status = SmmFreePages (Memory, UnalignedPages);\r
275 ASSERT_EFI_ERROR (Status);\r
276 }\r
277 } else {\r
278 //\r
279 // Do not over-allocate pages in this case.\r
280 //\r
281 Status = SmmAllocatePages (AllocateAnyPages, MemoryType, Pages, &Memory);\r
282 if (EFI_ERROR (Status)) {\r
283 return NULL;\r
284 }\r
285 AlignedMemory = (UINTN) Memory;\r
286 }\r
287 return (VOID *) AlignedMemory;\r
288}\r
289\r
290/**\r
2d28f3b7 291 Allocates one or more 4KB pages of type EfiRuntimeServicesData at a specified alignment.\r
713b7781 292\r
2d28f3b7 293 Allocates the number of 4KB pages specified by Pages of type EfiRuntimeServicesData with an\r
713b7781 294 alignment specified by Alignment. The allocated buffer is returned. If Pages is 0, then NULL is\r
295 returned. If there is not enough memory at the specified alignment remaining to satisfy the\r
296 request, then NULL is returned.\r
297 \r
298 If Alignment is not a power of two and Alignment is not zero, then ASSERT().\r
91403ce9 299 If Pages plus EFI_SIZE_TO_PAGES (Alignment) overflows, then ASSERT().\r
713b7781 300\r
301 @param Pages The number of 4 KB pages to allocate.\r
302 @param Alignment The requested alignment of the allocation. Must be a power of two.\r
303 If Alignment is zero, then byte alignment is used.\r
304\r
305 @return A pointer to the allocated buffer or NULL if allocation fails.\r
306\r
307**/\r
308VOID *\r
309EFIAPI\r
310AllocateAlignedPages (\r
311 IN UINTN Pages,\r
312 IN UINTN Alignment\r
313 )\r
314{\r
315 return InternalAllocateAlignedPages (EfiRuntimeServicesData, Pages, Alignment);\r
316}\r
317\r
318/**\r
319 Allocates one or more 4KB pages of type EfiRuntimeServicesData at a specified alignment.\r
320\r
321 Allocates the number of 4KB pages specified by Pages of type EfiRuntimeServicesData with an\r
322 alignment specified by Alignment. The allocated buffer is returned. If Pages is 0, then NULL is\r
323 returned. If there is not enough memory at the specified alignment remaining to satisfy the\r
324 request, then NULL is returned.\r
325 \r
326 If Alignment is not a power of two and Alignment is not zero, then ASSERT().\r
91403ce9 327 If Pages plus EFI_SIZE_TO_PAGES (Alignment) overflows, then ASSERT().\r
713b7781 328\r
329 @param Pages The number of 4 KB pages to allocate.\r
330 @param Alignment The requested alignment of the allocation. Must be a power of two.\r
331 If Alignment is zero, then byte alignment is used.\r
332\r
333 @return A pointer to the allocated buffer or NULL if allocation fails.\r
334\r
335**/\r
336VOID *\r
337EFIAPI\r
338AllocateAlignedRuntimePages (\r
339 IN UINTN Pages,\r
340 IN UINTN Alignment\r
341 )\r
342{\r
343 return InternalAllocateAlignedPages (EfiRuntimeServicesData, Pages, Alignment);\r
344}\r
345\r
346/**\r
347 Allocates one or more 4KB pages of type EfiReservedMemoryType at a specified alignment.\r
348\r
349 Allocates the number of 4KB pages specified by Pages of type EfiReservedMemoryType with an\r
350 alignment specified by Alignment. The allocated buffer is returned. If Pages is 0, then NULL is\r
351 returned. If there is not enough memory at the specified alignment remaining to satisfy the\r
352 request, then NULL is returned.\r
353 \r
354 If Alignment is not a power of two and Alignment is not zero, then ASSERT().\r
91403ce9 355 If Pages plus EFI_SIZE_TO_PAGES (Alignment) overflows, then ASSERT().\r
713b7781 356\r
357 @param Pages The number of 4 KB pages to allocate.\r
358 @param Alignment The requested alignment of the allocation. Must be a power of two.\r
359 If Alignment is zero, then byte alignment is used.\r
360\r
361 @return A pointer to the allocated buffer or NULL if allocation fails.\r
362\r
363**/\r
364VOID *\r
365EFIAPI\r
366AllocateAlignedReservedPages (\r
367 IN UINTN Pages,\r
368 IN UINTN Alignment\r
369 )\r
370{\r
371 return NULL;\r
372}\r
373\r
374/**\r
375 Frees one or more 4KB pages that were previously allocated with one of the aligned page\r
376 allocation functions in the Memory Allocation Library.\r
377\r
378 Frees the number of 4KB pages specified by Pages from the buffer specified by Buffer. Buffer\r
379 must have been allocated on a previous call to the aligned page allocation services of the Memory\r
380 Allocation Library. If it is not possible to free allocated pages, then this function will \r
381 perform no actions.\r
382 \r
383 If Buffer was not allocated with an aligned page allocation function in the Memory Allocation\r
384 Library, then ASSERT().\r
385 If Pages is zero, then ASSERT().\r
386 \r
387 @param Buffer Pointer to the buffer of pages to free.\r
388 @param Pages The number of 4 KB pages to free.\r
389\r
390**/\r
391VOID\r
392EFIAPI\r
393FreeAlignedPages (\r
394 IN VOID *Buffer,\r
395 IN UINTN Pages\r
396 )\r
397{\r
398 EFI_STATUS Status;\r
399\r
400 ASSERT (Pages != 0);\r
34401578
LG
401 if (BufferInSmram (Buffer)) {\r
402 //\r
403 // When Buffer is in SMRAM range, it should be allocated by SmmAllocatePages() service.\r
404 // So, SmmFreePages() service is used to free it.\r
405 //\r
406 Status = SmmFreePages ((EFI_PHYSICAL_ADDRESS) (UINTN) Buffer, Pages);\r
407 } else {\r
408 //\r
409 // When Buffer is out of SMRAM range, it should be allocated by gBS->AllocatePages() service.\r
410 // So, gBS->FreePages() service is used to free it.\r
411 //\r
412 Status = gBS->FreePages ((EFI_PHYSICAL_ADDRESS) (UINTN) Buffer, Pages);\r
413 }\r
713b7781 414 ASSERT_EFI_ERROR (Status);\r
415}\r
416\r
417/**\r
418 Allocates a buffer of a certain pool type.\r
419\r
420 Allocates the number bytes specified by AllocationSize of a certain pool type and returns a\r
421 pointer to the allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is\r
422 returned. If there is not enough memory remaining to satisfy the request, then NULL is returned.\r
423\r
424 @param MemoryType The type of memory to allocate.\r
425 @param AllocationSize The number of bytes to allocate.\r
426\r
427 @return A pointer to the allocated buffer or NULL if allocation fails.\r
428\r
429**/\r
430VOID *\r
431InternalAllocatePool (\r
432 IN EFI_MEMORY_TYPE MemoryType, \r
433 IN UINTN AllocationSize\r
434 )\r
435{\r
436 EFI_STATUS Status;\r
437 VOID *Memory;\r
438\r
4e1005ec
ED
439 Memory = NULL;\r
440\r
713b7781 441 Status = SmmAllocatePool (MemoryType, AllocationSize, &Memory);\r
442 if (EFI_ERROR (Status)) {\r
443 Memory = NULL;\r
444 }\r
445 return Memory;\r
446}\r
447\r
448/**\r
2d28f3b7 449 Allocates a buffer of type EfiRuntimeServicesData.\r
713b7781 450\r
2d28f3b7 451 Allocates the number bytes specified by AllocationSize of type EfiRuntimeServicesData and returns a\r
713b7781 452 pointer to the allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is\r
453 returned. If there is not enough memory remaining to satisfy the request, then NULL is returned.\r
454\r
455 @param AllocationSize The number of bytes to allocate.\r
456\r
457 @return A pointer to the allocated buffer or NULL if allocation fails.\r
458\r
459**/\r
460VOID *\r
461EFIAPI\r
462AllocatePool (\r
463 IN UINTN AllocationSize\r
464 )\r
465{\r
466 return InternalAllocatePool (EfiRuntimeServicesData, AllocationSize);\r
467}\r
468\r
469/**\r
470 Allocates a buffer of type EfiRuntimeServicesData.\r
471\r
472 Allocates the number bytes specified by AllocationSize of type EfiRuntimeServicesData and returns\r
473 a pointer to the allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is\r
474 returned. If there is not enough memory remaining to satisfy the request, then NULL is returned.\r
475\r
476 @param AllocationSize The number of bytes to allocate.\r
477\r
478 @return A pointer to the allocated buffer or NULL if allocation fails.\r
479\r
480**/\r
481VOID *\r
482EFIAPI\r
483AllocateRuntimePool (\r
484 IN UINTN AllocationSize\r
485 )\r
486{\r
487 return InternalAllocatePool (EfiRuntimeServicesData, AllocationSize);\r
488}\r
489\r
490/**\r
491 Allocates a buffer of type EfiReservedMemoryType.\r
492\r
493 Allocates the number bytes specified by AllocationSize of type EfiReservedMemoryType and returns\r
494 a pointer to the allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is\r
495 returned. If there is not enough memory remaining to satisfy the request, then NULL is returned.\r
496\r
497 @param AllocationSize The number of bytes to allocate.\r
498\r
499 @return A pointer to the allocated buffer or NULL if allocation fails.\r
500\r
501**/\r
502VOID *\r
503EFIAPI\r
504AllocateReservedPool (\r
505 IN UINTN AllocationSize\r
506 )\r
507{\r
508 return NULL;\r
509}\r
510\r
511/**\r
512 Allocates and zeros a buffer of a certain pool type.\r
513\r
514 Allocates the number bytes specified by AllocationSize of a certain pool type, clears the buffer\r
515 with zeros, and returns a pointer to the allocated buffer. If AllocationSize is 0, then a valid\r
516 buffer of 0 size is returned. If there is not enough memory remaining to satisfy the request,\r
517 then NULL is returned.\r
518\r
519 @param PoolType The type of memory to allocate.\r
520 @param AllocationSize The number of bytes to allocate and zero.\r
521\r
522 @return A pointer to the allocated buffer or NULL if allocation fails.\r
523\r
524**/\r
525VOID *\r
526InternalAllocateZeroPool (\r
527 IN EFI_MEMORY_TYPE PoolType, \r
528 IN UINTN AllocationSize\r
529 ) \r
530{\r
531 VOID *Memory;\r
532\r
533 Memory = InternalAllocatePool (PoolType, AllocationSize);\r
534 if (Memory != NULL) {\r
535 Memory = ZeroMem (Memory, AllocationSize);\r
536 }\r
537 return Memory;\r
538}\r
539\r
540/**\r
2d28f3b7 541 Allocates and zeros a buffer of type EfiRuntimeServicesData.\r
713b7781 542\r
2d28f3b7 543 Allocates the number bytes specified by AllocationSize of type EfiRuntimeServicesData, clears the\r
713b7781 544 buffer with zeros, and returns a pointer to the allocated buffer. If AllocationSize is 0, then a\r
545 valid buffer of 0 size is returned. If there is not enough memory remaining to satisfy the\r
546 request, then NULL is returned.\r
547\r
548 @param AllocationSize The number of bytes to allocate and zero.\r
549\r
550 @return A pointer to the allocated buffer or NULL if allocation fails.\r
551\r
552**/\r
553VOID *\r
554EFIAPI\r
555AllocateZeroPool (\r
556 IN UINTN AllocationSize\r
557 )\r
558{\r
559 return InternalAllocateZeroPool (EfiRuntimeServicesData, AllocationSize);\r
560}\r
561\r
562/**\r
563 Allocates and zeros a buffer of type EfiRuntimeServicesData.\r
564\r
565 Allocates the number bytes specified by AllocationSize of type EfiRuntimeServicesData, clears the\r
566 buffer with zeros, and returns a pointer to the allocated buffer. If AllocationSize is 0, then a\r
567 valid buffer of 0 size is returned. If there is not enough memory remaining to satisfy the\r
568 request, then NULL is returned.\r
569\r
570 @param AllocationSize The number of bytes to allocate and zero.\r
571\r
572 @return A pointer to the allocated buffer or NULL if allocation fails.\r
573\r
574**/\r
575VOID *\r
576EFIAPI\r
577AllocateRuntimeZeroPool (\r
578 IN UINTN AllocationSize\r
579 )\r
580{\r
581 return InternalAllocateZeroPool (EfiRuntimeServicesData, AllocationSize);\r
582}\r
583\r
584/**\r
585 Allocates and zeros a buffer of type EfiReservedMemoryType.\r
586\r
587 Allocates the number bytes specified by AllocationSize of type EfiReservedMemoryType, clears the\r
588 buffer with zeros, and returns a pointer to the allocated buffer. If AllocationSize is 0, then a\r
589 valid buffer of 0 size is returned. If there is not enough memory remaining to satisfy the\r
590 request, then NULL is returned.\r
591\r
592 @param AllocationSize The number of bytes to allocate and zero.\r
593\r
594 @return A pointer to the allocated buffer or NULL if allocation fails.\r
595\r
596**/\r
597VOID *\r
598EFIAPI\r
599AllocateReservedZeroPool (\r
600 IN UINTN AllocationSize\r
601 )\r
602{\r
603 return NULL;\r
604}\r
605\r
606/**\r
607 Copies a buffer to an allocated buffer of a certain pool type.\r
608\r
609 Allocates the number bytes specified by AllocationSize of a certain pool type, copies\r
610 AllocationSize bytes from Buffer to the newly allocated buffer, and returns a pointer to the\r
611 allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is returned. If there\r
612 is not enough memory remaining to satisfy the request, then NULL is returned.\r
613 If Buffer is NULL, then ASSERT().\r
614 If AllocationSize is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). \r
615\r
616 @param PoolType The type of pool to allocate.\r
617 @param AllocationSize The number of bytes to allocate and zero.\r
618 @param Buffer The buffer to copy to the allocated buffer.\r
619\r
620 @return A pointer to the allocated buffer or NULL if allocation fails.\r
621\r
622**/\r
623VOID *\r
624InternalAllocateCopyPool (\r
625 IN EFI_MEMORY_TYPE PoolType, \r
626 IN UINTN AllocationSize,\r
627 IN CONST VOID *Buffer\r
628 ) \r
629{\r
630 VOID *Memory;\r
631\r
632 ASSERT (Buffer != NULL);\r
633 ASSERT (AllocationSize <= (MAX_ADDRESS - (UINTN) Buffer + 1));\r
634\r
635 Memory = InternalAllocatePool (PoolType, AllocationSize);\r
636 if (Memory != NULL) {\r
637 Memory = CopyMem (Memory, Buffer, AllocationSize);\r
638 }\r
639 return Memory;\r
640} \r
641\r
642/**\r
2d28f3b7 643 Copies a buffer to an allocated buffer of type EfiRuntimeServicesData.\r
713b7781 644\r
2d28f3b7 645 Allocates the number bytes specified by AllocationSize of type EfiRuntimeServicesData, copies\r
713b7781 646 AllocationSize bytes from Buffer to the newly allocated buffer, and returns a pointer to the\r
647 allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is returned. If there\r
648 is not enough memory remaining to satisfy the request, then NULL is returned.\r
649 \r
650 If Buffer is NULL, then ASSERT().\r
651 If AllocationSize is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). \r
652\r
653 @param AllocationSize The number of bytes to allocate and zero.\r
654 @param Buffer The buffer to copy to the allocated buffer.\r
655\r
656 @return A pointer to the allocated buffer or NULL if allocation fails.\r
657\r
658**/\r
659VOID *\r
660EFIAPI\r
661AllocateCopyPool (\r
662 IN UINTN AllocationSize,\r
663 IN CONST VOID *Buffer\r
664 )\r
665{\r
666 return InternalAllocateCopyPool (EfiRuntimeServicesData, AllocationSize, Buffer);\r
667}\r
668\r
669/**\r
670 Copies a buffer to an allocated buffer of type EfiRuntimeServicesData.\r
671\r
672 Allocates the number bytes specified by AllocationSize of type EfiRuntimeServicesData, copies\r
673 AllocationSize bytes from Buffer to the newly allocated buffer, and returns a pointer to the\r
674 allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is returned. If there\r
675 is not enough memory remaining to satisfy the request, then NULL is returned.\r
676 \r
677 If Buffer is NULL, then ASSERT().\r
678 If AllocationSize is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). \r
679\r
680 @param AllocationSize The number of bytes to allocate and zero.\r
681 @param Buffer The buffer to copy to the allocated buffer.\r
682\r
683 @return A pointer to the allocated buffer or NULL if allocation fails.\r
684\r
685**/\r
686VOID *\r
687EFIAPI\r
688AllocateRuntimeCopyPool (\r
689 IN UINTN AllocationSize,\r
690 IN CONST VOID *Buffer\r
691 )\r
692{\r
693 return InternalAllocateCopyPool (EfiRuntimeServicesData, AllocationSize, Buffer);\r
694}\r
695\r
696/**\r
697 Copies a buffer to an allocated buffer of type EfiReservedMemoryType.\r
698\r
699 Allocates the number bytes specified by AllocationSize of type EfiReservedMemoryType, copies\r
700 AllocationSize bytes from Buffer to the newly allocated buffer, and returns a pointer to the\r
701 allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is returned. If there\r
702 is not enough memory remaining to satisfy the request, then NULL is returned.\r
703 \r
704 If Buffer is NULL, then ASSERT().\r
705 If AllocationSize is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). \r
706\r
707 @param AllocationSize The number of bytes to allocate and zero.\r
708 @param Buffer The buffer to copy to the allocated buffer.\r
709\r
710 @return A pointer to the allocated buffer or NULL if allocation fails.\r
711\r
712**/\r
713VOID *\r
714EFIAPI\r
715AllocateReservedCopyPool (\r
716 IN UINTN AllocationSize,\r
717 IN CONST VOID *Buffer\r
718 )\r
719{\r
720 return NULL;\r
721}\r
722\r
723/**\r
724 Reallocates a buffer of a specified memory type.\r
725\r
726 Allocates and zeros the number bytes specified by NewSize from memory of the type\r
727 specified by PoolType. If OldBuffer is not NULL, then the smaller of OldSize and \r
728 NewSize bytes are copied from OldBuffer to the newly allocated buffer, and \r
729 OldBuffer is freed. A pointer to the newly allocated buffer is returned. \r
730 If NewSize is 0, then a valid buffer of 0 size is returned. If there is not \r
731 enough memory remaining to satisfy the request, then NULL is returned.\r
732 \r
733 If the allocation of the new buffer is successful and the smaller of NewSize and OldSize\r
734 is greater than (MAX_ADDRESS - OldBuffer + 1), then ASSERT().\r
735\r
736 @param PoolType The type of pool to allocate.\r
737 @param OldSize The size, in bytes, of OldBuffer.\r
738 @param NewSize The size, in bytes, of the buffer to reallocate.\r
739 @param OldBuffer The buffer to copy to the allocated buffer. This is an optional \r
740 parameter that may be NULL.\r
741\r
742 @return A pointer to the allocated buffer or NULL if allocation fails.\r
743\r
744**/\r
745VOID *\r
746InternalReallocatePool (\r
747 IN EFI_MEMORY_TYPE PoolType, \r
748 IN UINTN OldSize,\r
749 IN UINTN NewSize,\r
750 IN VOID *OldBuffer OPTIONAL\r
751 )\r
752{\r
753 VOID *NewBuffer;\r
754\r
755 NewBuffer = InternalAllocateZeroPool (PoolType, NewSize);\r
756 if (NewBuffer != NULL && OldBuffer != NULL) {\r
757 CopyMem (NewBuffer, OldBuffer, MIN (OldSize, NewSize));\r
758 FreePool (OldBuffer);\r
759 }\r
760 return NewBuffer;\r
761}\r
762\r
763/**\r
2d28f3b7 764 Reallocates a buffer of type EfiRuntimeServicesData.\r
713b7781 765\r
766 Allocates and zeros the number bytes specified by NewSize from memory of type\r
2d28f3b7 767 EfiRuntimeServicesData. If OldBuffer is not NULL, then the smaller of OldSize and \r
713b7781 768 NewSize bytes are copied from OldBuffer to the newly allocated buffer, and \r
769 OldBuffer is freed. A pointer to the newly allocated buffer is returned. \r
770 If NewSize is 0, then a valid buffer of 0 size is returned. If there is not \r
771 enough memory remaining to satisfy the request, then NULL is returned.\r
772 \r
773 If the allocation of the new buffer is successful and the smaller of NewSize and OldSize\r
774 is greater than (MAX_ADDRESS - OldBuffer + 1), then ASSERT().\r
775\r
776 @param OldSize The size, in bytes, of OldBuffer.\r
777 @param NewSize The size, in bytes, of the buffer to reallocate.\r
778 @param OldBuffer The buffer to copy to the allocated buffer. This is an optional \r
779 parameter that may be NULL.\r
780\r
781 @return A pointer to the allocated buffer or NULL if allocation fails.\r
782\r
783**/\r
784VOID *\r
785EFIAPI\r
786ReallocatePool (\r
787 IN UINTN OldSize,\r
788 IN UINTN NewSize,\r
789 IN VOID *OldBuffer OPTIONAL\r
790 )\r
791{\r
792 return InternalReallocatePool (EfiRuntimeServicesData, OldSize, NewSize, OldBuffer);\r
793}\r
794\r
795/**\r
796 Reallocates a buffer of type EfiRuntimeServicesData.\r
797\r
798 Allocates and zeros the number bytes specified by NewSize from memory of type\r
799 EfiRuntimeServicesData. If OldBuffer is not NULL, then the smaller of OldSize and \r
800 NewSize bytes are copied from OldBuffer to the newly allocated buffer, and \r
801 OldBuffer is freed. A pointer to the newly allocated buffer is returned. \r
802 If NewSize is 0, then a valid buffer of 0 size is returned. If there is not \r
803 enough memory remaining to satisfy the request, then NULL is returned.\r
804\r
805 If the allocation of the new buffer is successful and the smaller of NewSize and OldSize\r
806 is greater than (MAX_ADDRESS - OldBuffer + 1), then ASSERT().\r
807\r
808 @param OldSize The size, in bytes, of OldBuffer.\r
809 @param NewSize The size, in bytes, of the buffer to reallocate.\r
810 @param OldBuffer The buffer to copy to the allocated buffer. This is an optional \r
811 parameter that may be NULL.\r
812\r
813 @return A pointer to the allocated buffer or NULL if allocation fails.\r
814\r
815**/\r
816VOID *\r
817EFIAPI\r
818ReallocateRuntimePool (\r
819 IN UINTN OldSize,\r
820 IN UINTN NewSize,\r
821 IN VOID *OldBuffer OPTIONAL\r
822 )\r
823{\r
824 return InternalReallocatePool (EfiRuntimeServicesData, OldSize, NewSize, OldBuffer);\r
825}\r
826\r
827/**\r
828 Reallocates a buffer of type EfiReservedMemoryType.\r
829\r
830 Allocates and zeros the number bytes specified by NewSize from memory of type\r
831 EfiReservedMemoryType. If OldBuffer is not NULL, then the smaller of OldSize and \r
832 NewSize bytes are copied from OldBuffer to the newly allocated buffer, and \r
833 OldBuffer is freed. A pointer to the newly allocated buffer is returned. \r
834 If NewSize is 0, then a valid buffer of 0 size is returned. If there is not \r
835 enough memory remaining to satisfy the request, then NULL is returned.\r
836\r
837 If the allocation of the new buffer is successful and the smaller of NewSize and OldSize\r
838 is greater than (MAX_ADDRESS - OldBuffer + 1), then ASSERT().\r
839\r
840 @param OldSize The size, in bytes, of OldBuffer.\r
841 @param NewSize The size, in bytes, of the buffer to reallocate.\r
842 @param OldBuffer The buffer to copy to the allocated buffer. This is an optional \r
843 parameter that may be NULL.\r
844\r
845 @return A pointer to the allocated buffer or NULL if allocation fails.\r
846\r
847**/\r
848VOID *\r
849EFIAPI\r
850ReallocateReservedPool (\r
851 IN UINTN OldSize,\r
852 IN UINTN NewSize,\r
853 IN VOID *OldBuffer OPTIONAL\r
854 )\r
855{\r
856 return NULL;\r
857}\r
858\r
859/**\r
860 Frees a buffer that was previously allocated with one of the pool allocation functions in the\r
861 Memory Allocation Library.\r
862\r
863 Frees the buffer specified by Buffer. Buffer must have been allocated on a previous call to the\r
864 pool allocation services of the Memory Allocation Library. If it is not possible to free pool\r
865 resources, then this function will perform no actions.\r
866 \r
867 If Buffer was not allocated with a pool allocation function in the Memory Allocation Library,\r
868 then ASSERT().\r
869\r
870 @param Buffer Pointer to the buffer to free.\r
871\r
872**/\r
873VOID\r
874EFIAPI\r
875FreePool (\r
876 IN VOID *Buffer\r
877 )\r
878{\r
879 EFI_STATUS Status;\r
880\r
34401578
LG
881 if (BufferInSmram (Buffer)) {\r
882 //\r
883 // When Buffer is in SMRAM range, it should be allocated by SmmAllocatePool() service.\r
884 // So, SmmFreePool() service is used to free it.\r
885 //\r
886 Status = SmmFreePool (Buffer);\r
887 } else {\r
888 //\r
889 // When Buffer is out of SMRAM range, it should be allocated by gBS->AllocatePool() service.\r
890 // So, gBS->FreePool() service is used to free it.\r
891 //\r
892 Status = gBS->FreePool (Buffer);\r
893 }\r
713b7781 894 ASSERT_EFI_ERROR (Status);\r
895}\r
896\r
842b1242
JY
897/**\r
898 The constructor function calls SmmInitializeMemoryServices to initialize memory in SMRAM.\r
899\r
900 @param ImageHandle The firmware allocated handle for the EFI image.\r
901 @param SystemTable A pointer to the EFI System Table.\r
902\r
903 @retval EFI_SUCCESS The constructor always returns EFI_SUCCESS.\r
904\r
905**/\r
906EFI_STATUS\r
907EFIAPI\r
908PiSmmCoreMemoryAllocationLibConstructor (\r
909 IN EFI_HANDLE ImageHandle,\r
910 IN EFI_SYSTEM_TABLE *SystemTable\r
911 )\r
912{\r
913 SMM_CORE_PRIVATE_DATA *SmmCorePrivate;\r
f3b6e048 914 UINTN Size;\r
842b1242
JY
915\r
916 SmmCorePrivate = (SMM_CORE_PRIVATE_DATA *)ImageHandle;\r
917 //\r
918 // Initialize memory service using free SMRAM\r
919 //\r
920 SmmInitializeMemoryServices (SmmCorePrivate->SmramRangeCount, SmmCorePrivate->SmramRanges);\r
f3b6e048 921\r
c03beb76 922 mSmmCoreMemoryAllocLibSmramRangeCount = SmmCorePrivate->SmramRangeCount;\r
f3b6e048
SZ
923 Size = mSmmCoreMemoryAllocLibSmramRangeCount * sizeof (EFI_SMRAM_DESCRIPTOR);\r
924 mSmmCoreMemoryAllocLibSmramRanges = (EFI_SMRAM_DESCRIPTOR *) AllocatePool (Size);\r
925 ASSERT (mSmmCoreMemoryAllocLibSmramRanges != NULL);\r
c03beb76 926 CopyMem (mSmmCoreMemoryAllocLibSmramRanges, SmmCorePrivate->SmramRanges, Size);\r
f3b6e048 927\r
842b1242
JY
928 return EFI_SUCCESS;\r
929}\r