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