123c98c9417908188207408afa3f6901b8aca826aqhuang/** @file 2504214c4870e9183418014634268ce630eb5332algao UEFI Memory pool management functions. 3504214c4870e9183418014634268ce630eb5332algao 4a671a0120a2fd8e8cb402741cf5e8652e27f38b5Liming GaoCopyright (c) 2006 - 2015, Intel Corporation. All rights reserved.<BR> 5cd5ebaa06dca3e6ef3c464081e6defe00d358c69hhtianThis program and the accompanying materials 623c98c9417908188207408afa3f6901b8aca826aqhuangare licensed and made available under the terms and conditions of the BSD License 723c98c9417908188207408afa3f6901b8aca826aqhuangwhich accompanies this distribution. The full text of the license may be found at 823c98c9417908188207408afa3f6901b8aca826aqhuanghttp://opensource.org/licenses/bsd-license.php 923c98c9417908188207408afa3f6901b8aca826aqhuang 1023c98c9417908188207408afa3f6901b8aca826aqhuangTHE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 1123c98c9417908188207408afa3f6901b8aca826aqhuangWITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. 1228a00297189c323096aae8e2975de94e8549613cyshang 13504214c4870e9183418014634268ce630eb5332algao**/ 1428a00297189c323096aae8e2975de94e8549613cyshang 159c4ac31cca01b4a503c36616770ea3157bf3bb9eqhuang#include "DxeMain.h" 16ec90508b3d3ff22a698a0446cb09d551d7466045eric_tian#include "Imem.h" 1728a00297189c323096aae8e2975de94e8549613cyshang 18f3f2e05db8c89628498ec4efdb16184747824c63qhuang#define POOL_FREE_SIGNATURE SIGNATURE_32('p','f','r','0') 1928a00297189c323096aae8e2975de94e8549613cyshangtypedef struct { 2028a00297189c323096aae8e2975de94e8549613cyshang UINT32 Signature; 2128a00297189c323096aae8e2975de94e8549613cyshang UINT32 Index; 2228a00297189c323096aae8e2975de94e8549613cyshang LIST_ENTRY Link; 2328a00297189c323096aae8e2975de94e8549613cyshang} POOL_FREE; 2428a00297189c323096aae8e2975de94e8549613cyshang 2528a00297189c323096aae8e2975de94e8549613cyshang 26f3f2e05db8c89628498ec4efdb16184747824c63qhuang#define POOL_HEAD_SIGNATURE SIGNATURE_32('p','h','d','0') 2728a00297189c323096aae8e2975de94e8549613cyshangtypedef struct { 2828a00297189c323096aae8e2975de94e8549613cyshang UINT32 Signature; 29bb683bf4656730be2210fe3964e20d8c36d19eb5Star Zeng UINT32 Reserved; 3028a00297189c323096aae8e2975de94e8549613cyshang EFI_MEMORY_TYPE Type; 31bb683bf4656730be2210fe3964e20d8c36d19eb5Star Zeng UINTN Size; 3228a00297189c323096aae8e2975de94e8549613cyshang CHAR8 Data[1]; 3328a00297189c323096aae8e2975de94e8549613cyshang} POOL_HEAD; 3428a00297189c323096aae8e2975de94e8549613cyshang 35f3f2e05db8c89628498ec4efdb16184747824c63qhuang#define SIZE_OF_POOL_HEAD OFFSET_OF(POOL_HEAD,Data) 3628a00297189c323096aae8e2975de94e8549613cyshang 37f3f2e05db8c89628498ec4efdb16184747824c63qhuang#define POOL_TAIL_SIGNATURE SIGNATURE_32('p','t','a','l') 3828a00297189c323096aae8e2975de94e8549613cyshangtypedef struct { 3928a00297189c323096aae8e2975de94e8549613cyshang UINT32 Signature; 40bb683bf4656730be2210fe3964e20d8c36d19eb5Star Zeng UINT32 Reserved; 41bb683bf4656730be2210fe3964e20d8c36d19eb5Star Zeng UINTN Size; 4228a00297189c323096aae8e2975de94e8549613cyshang} POOL_TAIL; 4328a00297189c323096aae8e2975de94e8549613cyshang 4428a00297189c323096aae8e2975de94e8549613cyshang#define POOL_OVERHEAD (SIZE_OF_POOL_HEAD + sizeof(POOL_TAIL)) 4528a00297189c323096aae8e2975de94e8549613cyshang 4628a00297189c323096aae8e2975de94e8549613cyshang#define HEAD_TO_TAIL(a) \ 4728a00297189c323096aae8e2975de94e8549613cyshang ((POOL_TAIL *) (((CHAR8 *) (a)) + (a)->Size - sizeof(POOL_TAIL))); 4828a00297189c323096aae8e2975de94e8549613cyshang 49f2c7daf675d246261bd5e034b78e200017057df6Ard Biesheuvel// 50f2c7daf675d246261bd5e034b78e200017057df6Ard Biesheuvel// Each element is the sum of the 2 previous ones: this allows us to migrate 51f2c7daf675d246261bd5e034b78e200017057df6Ard Biesheuvel// blocks between bins by splitting them up, while not wasting too much memory 52f2c7daf675d246261bd5e034b78e200017057df6Ard Biesheuvel// as we would in a strict power-of-2 sequence 53f2c7daf675d246261bd5e034b78e200017057df6Ard Biesheuvel// 54f2c7daf675d246261bd5e034b78e200017057df6Ard BiesheuvelSTATIC CONST UINT16 mPoolSizeTable[] = { 55f2c7daf675d246261bd5e034b78e200017057df6Ard Biesheuvel 64, 128, 192, 320, 512, 832, 1344, 2176, 3520, 5696, 9216, 14912, 24128 56f2c7daf675d246261bd5e034b78e200017057df6Ard Biesheuvel}; 5728a00297189c323096aae8e2975de94e8549613cyshang 58f2c7daf675d246261bd5e034b78e200017057df6Ard Biesheuvel#define SIZE_TO_LIST(a) (GetPoolIndexFromSize (a)) 59f2c7daf675d246261bd5e034b78e200017057df6Ard Biesheuvel#define LIST_TO_SIZE(a) (mPoolSizeTable [a]) 6028a00297189c323096aae8e2975de94e8549613cyshang 61f2c7daf675d246261bd5e034b78e200017057df6Ard Biesheuvel#define MAX_POOL_LIST (sizeof (mPoolSizeTable) / sizeof (mPoolSizeTable[0])) 6228a00297189c323096aae8e2975de94e8549613cyshang 6328a00297189c323096aae8e2975de94e8549613cyshang#define MAX_POOL_SIZE (MAX_ADDRESS - POOL_OVERHEAD) 6428a00297189c323096aae8e2975de94e8549613cyshang 6528a00297189c323096aae8e2975de94e8549613cyshang// 6628a00297189c323096aae8e2975de94e8549613cyshang// Globals 6728a00297189c323096aae8e2975de94e8549613cyshang// 6828a00297189c323096aae8e2975de94e8549613cyshang 69f3f2e05db8c89628498ec4efdb16184747824c63qhuang#define POOL_SIGNATURE SIGNATURE_32('p','l','s','t') 7028a00297189c323096aae8e2975de94e8549613cyshangtypedef struct { 7128a00297189c323096aae8e2975de94e8549613cyshang INTN Signature; 7228a00297189c323096aae8e2975de94e8549613cyshang UINTN Used; 7328a00297189c323096aae8e2975de94e8549613cyshang EFI_MEMORY_TYPE MemoryType; 7428a00297189c323096aae8e2975de94e8549613cyshang LIST_ENTRY FreeList[MAX_POOL_LIST]; 7528a00297189c323096aae8e2975de94e8549613cyshang LIST_ENTRY Link; 76022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang} POOL; 7728a00297189c323096aae8e2975de94e8549613cyshang 7828a00297189c323096aae8e2975de94e8549613cyshang// 79e94a9ff7271367e649ee4f9a86da1f1bea6d112eqhuang// Pool header for each memory type. 80e94a9ff7271367e649ee4f9a86da1f1bea6d112eqhuang// 81e94a9ff7271367e649ee4f9a86da1f1bea6d112eqhuangPOOL mPoolHead[EfiMaxMemoryType]; 82e94a9ff7271367e649ee4f9a86da1f1bea6d112eqhuang 8328a00297189c323096aae8e2975de94e8549613cyshang// 84e94a9ff7271367e649ee4f9a86da1f1bea6d112eqhuang// List of pool header to search for the appropriate memory type. 8528a00297189c323096aae8e2975de94e8549613cyshang// 8657b4ecb94bceac2484dd9367b2ad111b05e17d97qhuangLIST_ENTRY mPoolHeadList = INITIALIZE_LIST_HEAD_VARIABLE (mPoolHeadList); 8728a00297189c323096aae8e2975de94e8549613cyshang 88dd51e45b6fc28b5240d37dd941aea5231f14db90Shumin Qiu/** 89dd51e45b6fc28b5240d37dd941aea5231f14db90Shumin Qiu Get pool size table index from the specified size. 90dd51e45b6fc28b5240d37dd941aea5231f14db90Shumin Qiu 91dd51e45b6fc28b5240d37dd941aea5231f14db90Shumin Qiu @param Size The specified size to get index from pool table. 92dd51e45b6fc28b5240d37dd941aea5231f14db90Shumin Qiu 93dd51e45b6fc28b5240d37dd941aea5231f14db90Shumin Qiu @return The index of pool size table. 94dd51e45b6fc28b5240d37dd941aea5231f14db90Shumin Qiu 95dd51e45b6fc28b5240d37dd941aea5231f14db90Shumin Qiu**/ 96f2c7daf675d246261bd5e034b78e200017057df6Ard BiesheuvelSTATIC 97f2c7daf675d246261bd5e034b78e200017057df6Ard BiesheuvelUINTN 98f2c7daf675d246261bd5e034b78e200017057df6Ard BiesheuvelGetPoolIndexFromSize ( 99f2c7daf675d246261bd5e034b78e200017057df6Ard Biesheuvel UINTN Size 100f2c7daf675d246261bd5e034b78e200017057df6Ard Biesheuvel ) 101f2c7daf675d246261bd5e034b78e200017057df6Ard Biesheuvel{ 102f2c7daf675d246261bd5e034b78e200017057df6Ard Biesheuvel UINTN Index; 103f2c7daf675d246261bd5e034b78e200017057df6Ard Biesheuvel 104f2c7daf675d246261bd5e034b78e200017057df6Ard Biesheuvel for (Index = 0; Index < MAX_POOL_LIST; Index++) { 105f2c7daf675d246261bd5e034b78e200017057df6Ard Biesheuvel if (mPoolSizeTable [Index] >= Size) { 106f2c7daf675d246261bd5e034b78e200017057df6Ard Biesheuvel return Index; 107f2c7daf675d246261bd5e034b78e200017057df6Ard Biesheuvel } 108f2c7daf675d246261bd5e034b78e200017057df6Ard Biesheuvel } 109f2c7daf675d246261bd5e034b78e200017057df6Ard Biesheuvel return MAX_POOL_LIST; 110f2c7daf675d246261bd5e034b78e200017057df6Ard Biesheuvel} 111162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang 112162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang/** 113162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang Called to initialize the pool. 114162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang 115162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang**/ 11628a00297189c323096aae8e2975de94e8549613cyshangVOID 11728a00297189c323096aae8e2975de94e8549613cyshangCoreInitializePool ( 11828a00297189c323096aae8e2975de94e8549613cyshang VOID 11928a00297189c323096aae8e2975de94e8549613cyshang ) 12028a00297189c323096aae8e2975de94e8549613cyshang{ 12128a00297189c323096aae8e2975de94e8549613cyshang UINTN Type; 12228a00297189c323096aae8e2975de94e8549613cyshang UINTN Index; 12328a00297189c323096aae8e2975de94e8549613cyshang 12428a00297189c323096aae8e2975de94e8549613cyshang for (Type=0; Type < EfiMaxMemoryType; Type++) { 125e94a9ff7271367e649ee4f9a86da1f1bea6d112eqhuang mPoolHead[Type].Signature = 0; 126e94a9ff7271367e649ee4f9a86da1f1bea6d112eqhuang mPoolHead[Type].Used = 0; 127e94a9ff7271367e649ee4f9a86da1f1bea6d112eqhuang mPoolHead[Type].MemoryType = (EFI_MEMORY_TYPE) Type; 12828a00297189c323096aae8e2975de94e8549613cyshang for (Index=0; Index < MAX_POOL_LIST; Index++) { 129bb683bf4656730be2210fe3964e20d8c36d19eb5Star Zeng InitializeListHead (&mPoolHead[Type].FreeList[Index]); 13028a00297189c323096aae8e2975de94e8549613cyshang } 13128a00297189c323096aae8e2975de94e8549613cyshang } 13228a00297189c323096aae8e2975de94e8549613cyshang} 13328a00297189c323096aae8e2975de94e8549613cyshang 13428a00297189c323096aae8e2975de94e8549613cyshang 135162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang/** 13628a00297189c323096aae8e2975de94e8549613cyshang Look up pool head for specified memory type. 13728a00297189c323096aae8e2975de94e8549613cyshang 138022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang @param MemoryType Memory type of which pool head is looked for 13928a00297189c323096aae8e2975de94e8549613cyshang 140162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang @return Pointer of Corresponding pool head. 14128a00297189c323096aae8e2975de94e8549613cyshang 142162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang**/ 143162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuangPOOL * 144162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuangLookupPoolHead ( 145162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang IN EFI_MEMORY_TYPE MemoryType 146162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang ) 14728a00297189c323096aae8e2975de94e8549613cyshang{ 14828a00297189c323096aae8e2975de94e8549613cyshang LIST_ENTRY *Link; 14928a00297189c323096aae8e2975de94e8549613cyshang POOL *Pool; 15028a00297189c323096aae8e2975de94e8549613cyshang UINTN Index; 15128a00297189c323096aae8e2975de94e8549613cyshang 1523d78c020d22023d35d27b48817d73ff31a361ac7rsun if ((UINT32)MemoryType < EfiMaxMemoryType) { 153e94a9ff7271367e649ee4f9a86da1f1bea6d112eqhuang return &mPoolHead[MemoryType]; 15428a00297189c323096aae8e2975de94e8549613cyshang } 15528a00297189c323096aae8e2975de94e8549613cyshang 156dc8d93ca0c9a798fe4e23f68b5b5adc032bf5509eric_tian // 1578ee25f48770dcb139b2313f57bd1449465149f7dStar Zeng // MemoryType values in the range 0x80000000..0xFFFFFFFF are reserved for use by UEFI 1588ee25f48770dcb139b2313f57bd1449465149f7dStar Zeng // OS loaders that are provided by operating system vendors. 1598ee25f48770dcb139b2313f57bd1449465149f7dStar Zeng // MemoryType values in the range 0x70000000..0x7FFFFFFF are reserved for OEM use. 160dc8d93ca0c9a798fe4e23f68b5b5adc032bf5509eric_tian // 1618ee25f48770dcb139b2313f57bd1449465149f7dStar Zeng if ((UINT32) MemoryType >= MEMORY_TYPE_OEM_RESERVED_MIN) { 16228a00297189c323096aae8e2975de94e8549613cyshang 163e94a9ff7271367e649ee4f9a86da1f1bea6d112eqhuang for (Link = mPoolHeadList.ForwardLink; Link != &mPoolHeadList; Link = Link->ForwardLink) { 16428a00297189c323096aae8e2975de94e8549613cyshang Pool = CR(Link, POOL, Link, POOL_SIGNATURE); 16528a00297189c323096aae8e2975de94e8549613cyshang if (Pool->MemoryType == MemoryType) { 16628a00297189c323096aae8e2975de94e8549613cyshang return Pool; 16728a00297189c323096aae8e2975de94e8549613cyshang } 16828a00297189c323096aae8e2975de94e8549613cyshang } 16928a00297189c323096aae8e2975de94e8549613cyshang 17028a00297189c323096aae8e2975de94e8549613cyshang Pool = CoreAllocatePoolI (EfiBootServicesData, sizeof (POOL)); 17128a00297189c323096aae8e2975de94e8549613cyshang if (Pool == NULL) { 17228a00297189c323096aae8e2975de94e8549613cyshang return NULL; 17328a00297189c323096aae8e2975de94e8549613cyshang } 17428a00297189c323096aae8e2975de94e8549613cyshang 17528a00297189c323096aae8e2975de94e8549613cyshang Pool->Signature = POOL_SIGNATURE; 17628a00297189c323096aae8e2975de94e8549613cyshang Pool->Used = 0; 17728a00297189c323096aae8e2975de94e8549613cyshang Pool->MemoryType = MemoryType; 17828a00297189c323096aae8e2975de94e8549613cyshang for (Index=0; Index < MAX_POOL_LIST; Index++) { 17928a00297189c323096aae8e2975de94e8549613cyshang InitializeListHead (&Pool->FreeList[Index]); 18028a00297189c323096aae8e2975de94e8549613cyshang } 18128a00297189c323096aae8e2975de94e8549613cyshang 182e94a9ff7271367e649ee4f9a86da1f1bea6d112eqhuang InsertHeadList (&mPoolHeadList, &Pool->Link); 18328a00297189c323096aae8e2975de94e8549613cyshang 18428a00297189c323096aae8e2975de94e8549613cyshang return Pool; 18528a00297189c323096aae8e2975de94e8549613cyshang } 18628a00297189c323096aae8e2975de94e8549613cyshang 18728a00297189c323096aae8e2975de94e8549613cyshang return NULL; 18828a00297189c323096aae8e2975de94e8549613cyshang} 18928a00297189c323096aae8e2975de94e8549613cyshang 190022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang 19128a00297189c323096aae8e2975de94e8549613cyshang 192162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang/** 193162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang Allocate pool of a particular type. 194162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang 195022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang @param PoolType Type of pool to allocate 196022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang @param Size The amount of pool to allocate 197022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang @param Buffer The address to return a pointer to the allocated 198022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang pool 199162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang 2003e0587010e36d36d6374c8ca9956e9bfbc8da7a8ydong @retval EFI_INVALID_PARAMETER PoolType not valid or Buffer is NULL. 201a671a0120a2fd8e8cb402741cf5e8652e27f38b5Liming Gao PoolType was EfiPersistentMemory. 202022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang @retval EFI_OUT_OF_RESOURCES Size exceeds max pool size or allocation failed. 203162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang @retval EFI_SUCCESS Pool successfully allocated. 204162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang 205162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang**/ 20628a00297189c323096aae8e2975de94e8549613cyshangEFI_STATUS 20728a00297189c323096aae8e2975de94e8549613cyshangEFIAPI 20884edd20bd0756ef5719835498d4283435d6b5e77Star ZengCoreInternalAllocatePool ( 20928a00297189c323096aae8e2975de94e8549613cyshang IN EFI_MEMORY_TYPE PoolType, 21028a00297189c323096aae8e2975de94e8549613cyshang IN UINTN Size, 21128a00297189c323096aae8e2975de94e8549613cyshang OUT VOID **Buffer 21228a00297189c323096aae8e2975de94e8549613cyshang ) 21328a00297189c323096aae8e2975de94e8549613cyshang{ 21428a00297189c323096aae8e2975de94e8549613cyshang EFI_STATUS Status; 21528a00297189c323096aae8e2975de94e8549613cyshang 21628a00297189c323096aae8e2975de94e8549613cyshang // 21728a00297189c323096aae8e2975de94e8549613cyshang // If it's not a valid type, fail it 21828a00297189c323096aae8e2975de94e8549613cyshang // 2198ee25f48770dcb139b2313f57bd1449465149f7dStar Zeng if ((PoolType >= EfiMaxMemoryType && PoolType < MEMORY_TYPE_OEM_RESERVED_MIN) || 220a671a0120a2fd8e8cb402741cf5e8652e27f38b5Liming Gao (PoolType == EfiConventionalMemory) || (PoolType == EfiPersistentMemory)) { 22128a00297189c323096aae8e2975de94e8549613cyshang return EFI_INVALID_PARAMETER; 22228a00297189c323096aae8e2975de94e8549613cyshang } 223022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang 2243e0587010e36d36d6374c8ca9956e9bfbc8da7a8ydong if (Buffer == NULL) { 2253e0587010e36d36d6374c8ca9956e9bfbc8da7a8ydong return EFI_INVALID_PARAMETER; 2263e0587010e36d36d6374c8ca9956e9bfbc8da7a8ydong } 2273e0587010e36d36d6374c8ca9956e9bfbc8da7a8ydong 22828a00297189c323096aae8e2975de94e8549613cyshang *Buffer = NULL; 229022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang 23028a00297189c323096aae8e2975de94e8549613cyshang // 23128a00297189c323096aae8e2975de94e8549613cyshang // If size is too large, fail it 23228a00297189c323096aae8e2975de94e8549613cyshang // Base on the EFI spec, return status of EFI_OUT_OF_RESOURCES 23328a00297189c323096aae8e2975de94e8549613cyshang // 23428a00297189c323096aae8e2975de94e8549613cyshang if (Size > MAX_POOL_SIZE) { 23528a00297189c323096aae8e2975de94e8549613cyshang return EFI_OUT_OF_RESOURCES; 23628a00297189c323096aae8e2975de94e8549613cyshang } 23728a00297189c323096aae8e2975de94e8549613cyshang 23828a00297189c323096aae8e2975de94e8549613cyshang // 23928a00297189c323096aae8e2975de94e8549613cyshang // Acquire the memory lock and make the allocation 24028a00297189c323096aae8e2975de94e8549613cyshang // 24128a00297189c323096aae8e2975de94e8549613cyshang Status = CoreAcquireLockOrFail (&gMemoryLock); 24228a00297189c323096aae8e2975de94e8549613cyshang if (EFI_ERROR (Status)) { 24328a00297189c323096aae8e2975de94e8549613cyshang return EFI_OUT_OF_RESOURCES; 24428a00297189c323096aae8e2975de94e8549613cyshang } 24528a00297189c323096aae8e2975de94e8549613cyshang 24628a00297189c323096aae8e2975de94e8549613cyshang *Buffer = CoreAllocatePoolI (PoolType, Size); 24728a00297189c323096aae8e2975de94e8549613cyshang CoreReleaseMemoryLock (); 24828a00297189c323096aae8e2975de94e8549613cyshang return (*Buffer != NULL) ? EFI_SUCCESS : EFI_OUT_OF_RESOURCES; 24928a00297189c323096aae8e2975de94e8549613cyshang} 25028a00297189c323096aae8e2975de94e8549613cyshang 25184edd20bd0756ef5719835498d4283435d6b5e77Star Zeng/** 25284edd20bd0756ef5719835498d4283435d6b5e77Star Zeng Allocate pool of a particular type. 25384edd20bd0756ef5719835498d4283435d6b5e77Star Zeng 25484edd20bd0756ef5719835498d4283435d6b5e77Star Zeng @param PoolType Type of pool to allocate 25584edd20bd0756ef5719835498d4283435d6b5e77Star Zeng @param Size The amount of pool to allocate 25684edd20bd0756ef5719835498d4283435d6b5e77Star Zeng @param Buffer The address to return a pointer to the allocated 25784edd20bd0756ef5719835498d4283435d6b5e77Star Zeng pool 25884edd20bd0756ef5719835498d4283435d6b5e77Star Zeng 25984edd20bd0756ef5719835498d4283435d6b5e77Star Zeng @retval EFI_INVALID_PARAMETER PoolType not valid or Buffer is NULL. 26084edd20bd0756ef5719835498d4283435d6b5e77Star Zeng @retval EFI_OUT_OF_RESOURCES Size exceeds max pool size or allocation failed. 26184edd20bd0756ef5719835498d4283435d6b5e77Star Zeng @retval EFI_SUCCESS Pool successfully allocated. 26284edd20bd0756ef5719835498d4283435d6b5e77Star Zeng 26384edd20bd0756ef5719835498d4283435d6b5e77Star Zeng**/ 26484edd20bd0756ef5719835498d4283435d6b5e77Star ZengEFI_STATUS 26584edd20bd0756ef5719835498d4283435d6b5e77Star ZengEFIAPI 26684edd20bd0756ef5719835498d4283435d6b5e77Star ZengCoreAllocatePool ( 26784edd20bd0756ef5719835498d4283435d6b5e77Star Zeng IN EFI_MEMORY_TYPE PoolType, 26884edd20bd0756ef5719835498d4283435d6b5e77Star Zeng IN UINTN Size, 26984edd20bd0756ef5719835498d4283435d6b5e77Star Zeng OUT VOID **Buffer 27084edd20bd0756ef5719835498d4283435d6b5e77Star Zeng ) 27184edd20bd0756ef5719835498d4283435d6b5e77Star Zeng{ 27284edd20bd0756ef5719835498d4283435d6b5e77Star Zeng EFI_STATUS Status; 27328a00297189c323096aae8e2975de94e8549613cyshang 27484edd20bd0756ef5719835498d4283435d6b5e77Star Zeng Status = CoreInternalAllocatePool (PoolType, Size, Buffer); 27584edd20bd0756ef5719835498d4283435d6b5e77Star Zeng if (!EFI_ERROR (Status)) { 27684edd20bd0756ef5719835498d4283435d6b5e77Star Zeng CoreUpdateProfile ((EFI_PHYSICAL_ADDRESS) (UINTN) RETURN_ADDRESS (0), MemoryProfileActionAllocatePool, PoolType, Size, *Buffer); 27784edd20bd0756ef5719835498d4283435d6b5e77Star Zeng } 27884edd20bd0756ef5719835498d4283435d6b5e77Star Zeng return Status; 27984edd20bd0756ef5719835498d4283435d6b5e77Star Zeng} 28028a00297189c323096aae8e2975de94e8549613cyshang 281162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang/** 28228a00297189c323096aae8e2975de94e8549613cyshang Internal function to allocate pool of a particular type. 28328a00297189c323096aae8e2975de94e8549613cyshang Caller must have the memory lock held 28428a00297189c323096aae8e2975de94e8549613cyshang 285022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang @param PoolType Type of pool to allocate 286022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang @param Size The amount of pool to allocate 28728a00297189c323096aae8e2975de94e8549613cyshang 288162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang @return The allocate pool, or NULL 28928a00297189c323096aae8e2975de94e8549613cyshang 290162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang**/ 291162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuangVOID * 292162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuangCoreAllocatePoolI ( 293162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang IN EFI_MEMORY_TYPE PoolType, 294162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang IN UINTN Size 295162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang ) 29628a00297189c323096aae8e2975de94e8549613cyshang{ 29728a00297189c323096aae8e2975de94e8549613cyshang POOL *Pool; 29828a00297189c323096aae8e2975de94e8549613cyshang POOL_FREE *Free; 29928a00297189c323096aae8e2975de94e8549613cyshang POOL_HEAD *Head; 30028a00297189c323096aae8e2975de94e8549613cyshang POOL_TAIL *Tail; 30128a00297189c323096aae8e2975de94e8549613cyshang CHAR8 *NewPage; 30228a00297189c323096aae8e2975de94e8549613cyshang VOID *Buffer; 30328a00297189c323096aae8e2975de94e8549613cyshang UINTN Index; 30428a00297189c323096aae8e2975de94e8549613cyshang UINTN FSize; 3056860b92c847caff16b8cbc58ca31e3dbf9c5e5ccArd Biesheuvel UINTN Offset, MaxOffset; 30628a00297189c323096aae8e2975de94e8549613cyshang UINTN NoPages; 3077970100ccbd48e6f931b078cb8e615eabee26141Ard Biesheuvel UINTN Granularity; 30828a00297189c323096aae8e2975de94e8549613cyshang 30928a00297189c323096aae8e2975de94e8549613cyshang ASSERT_LOCKED (&gMemoryLock); 31028a00297189c323096aae8e2975de94e8549613cyshang 3117970100ccbd48e6f931b078cb8e615eabee26141Ard Biesheuvel if (PoolType == EfiACPIReclaimMemory || 3127970100ccbd48e6f931b078cb8e615eabee26141Ard Biesheuvel PoolType == EfiACPIMemoryNVS || 3137970100ccbd48e6f931b078cb8e615eabee26141Ard Biesheuvel PoolType == EfiRuntimeServicesCode || 3147970100ccbd48e6f931b078cb8e615eabee26141Ard Biesheuvel PoolType == EfiRuntimeServicesData) { 3157970100ccbd48e6f931b078cb8e615eabee26141Ard Biesheuvel 3167970100ccbd48e6f931b078cb8e615eabee26141Ard Biesheuvel Granularity = EFI_ACPI_RUNTIME_PAGE_ALLOCATION_ALIGNMENT; 3177970100ccbd48e6f931b078cb8e615eabee26141Ard Biesheuvel } else { 3187970100ccbd48e6f931b078cb8e615eabee26141Ard Biesheuvel Granularity = DEFAULT_PAGE_ALLOCATION; 3197970100ccbd48e6f931b078cb8e615eabee26141Ard Biesheuvel } 3207970100ccbd48e6f931b078cb8e615eabee26141Ard Biesheuvel 32128a00297189c323096aae8e2975de94e8549613cyshang // 32228a00297189c323096aae8e2975de94e8549613cyshang // Adjust the size by the pool header & tail overhead 32328a00297189c323096aae8e2975de94e8549613cyshang // 324022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang 32528a00297189c323096aae8e2975de94e8549613cyshang // 32628a00297189c323096aae8e2975de94e8549613cyshang // Adjusting the Size to be of proper alignment so that 32728a00297189c323096aae8e2975de94e8549613cyshang // we don't get an unaligned access fault later when 32828a00297189c323096aae8e2975de94e8549613cyshang // pool_Tail is being initialized 32928a00297189c323096aae8e2975de94e8549613cyshang // 330f0d5cbb66aa222e3eb0777d0d4b0d70a03d49188qhuang Size = ALIGN_VARIABLE (Size); 33128a00297189c323096aae8e2975de94e8549613cyshang 33228a00297189c323096aae8e2975de94e8549613cyshang Size += POOL_OVERHEAD; 33328a00297189c323096aae8e2975de94e8549613cyshang Index = SIZE_TO_LIST(Size); 33428a00297189c323096aae8e2975de94e8549613cyshang Pool = LookupPoolHead (PoolType); 33528a00297189c323096aae8e2975de94e8549613cyshang if (Pool== NULL) { 33628a00297189c323096aae8e2975de94e8549613cyshang return NULL; 33728a00297189c323096aae8e2975de94e8549613cyshang } 33828a00297189c323096aae8e2975de94e8549613cyshang Head = NULL; 33928a00297189c323096aae8e2975de94e8549613cyshang 34028a00297189c323096aae8e2975de94e8549613cyshang // 34128a00297189c323096aae8e2975de94e8549613cyshang // If allocation is over max size, just allocate pages for the request 34228a00297189c323096aae8e2975de94e8549613cyshang // (slow) 34328a00297189c323096aae8e2975de94e8549613cyshang // 344f2c7daf675d246261bd5e034b78e200017057df6Ard Biesheuvel if (Index >= SIZE_TO_LIST (Granularity)) { 3457970100ccbd48e6f931b078cb8e615eabee26141Ard Biesheuvel NoPages = EFI_SIZE_TO_PAGES(Size) + EFI_SIZE_TO_PAGES (Granularity) - 1; 3467970100ccbd48e6f931b078cb8e615eabee26141Ard Biesheuvel NoPages &= ~(UINTN)(EFI_SIZE_TO_PAGES (Granularity) - 1); 3477970100ccbd48e6f931b078cb8e615eabee26141Ard Biesheuvel Head = CoreAllocatePoolPages (PoolType, NoPages, Granularity); 34828a00297189c323096aae8e2975de94e8549613cyshang goto Done; 34928a00297189c323096aae8e2975de94e8549613cyshang } 35028a00297189c323096aae8e2975de94e8549613cyshang 35128a00297189c323096aae8e2975de94e8549613cyshang // 35228a00297189c323096aae8e2975de94e8549613cyshang // If there's no free pool in the proper list size, go get some more pages 35328a00297189c323096aae8e2975de94e8549613cyshang // 35428a00297189c323096aae8e2975de94e8549613cyshang if (IsListEmpty (&Pool->FreeList[Index])) { 35528a00297189c323096aae8e2975de94e8549613cyshang 3566860b92c847caff16b8cbc58ca31e3dbf9c5e5ccArd Biesheuvel Offset = LIST_TO_SIZE (Index); 3576860b92c847caff16b8cbc58ca31e3dbf9c5e5ccArd Biesheuvel MaxOffset = Granularity; 3586860b92c847caff16b8cbc58ca31e3dbf9c5e5ccArd Biesheuvel 3596860b92c847caff16b8cbc58ca31e3dbf9c5e5ccArd Biesheuvel // 3606860b92c847caff16b8cbc58ca31e3dbf9c5e5ccArd Biesheuvel // Check the bins holding larger blocks, and carve one up if needed 3616860b92c847caff16b8cbc58ca31e3dbf9c5e5ccArd Biesheuvel // 3626860b92c847caff16b8cbc58ca31e3dbf9c5e5ccArd Biesheuvel while (++Index < SIZE_TO_LIST (Granularity)) { 3636860b92c847caff16b8cbc58ca31e3dbf9c5e5ccArd Biesheuvel if (!IsListEmpty (&Pool->FreeList[Index])) { 3646860b92c847caff16b8cbc58ca31e3dbf9c5e5ccArd Biesheuvel Free = CR (Pool->FreeList[Index].ForwardLink, POOL_FREE, Link, POOL_FREE_SIGNATURE); 3656860b92c847caff16b8cbc58ca31e3dbf9c5e5ccArd Biesheuvel RemoveEntryList (&Free->Link); 3666860b92c847caff16b8cbc58ca31e3dbf9c5e5ccArd Biesheuvel NewPage = (VOID *) Free; 3676860b92c847caff16b8cbc58ca31e3dbf9c5e5ccArd Biesheuvel MaxOffset = LIST_TO_SIZE (Index); 3686860b92c847caff16b8cbc58ca31e3dbf9c5e5ccArd Biesheuvel goto Carve; 3696860b92c847caff16b8cbc58ca31e3dbf9c5e5ccArd Biesheuvel } 3706860b92c847caff16b8cbc58ca31e3dbf9c5e5ccArd Biesheuvel } 3716860b92c847caff16b8cbc58ca31e3dbf9c5e5ccArd Biesheuvel 37228a00297189c323096aae8e2975de94e8549613cyshang // 37328a00297189c323096aae8e2975de94e8549613cyshang // Get another page 37428a00297189c323096aae8e2975de94e8549613cyshang // 3757970100ccbd48e6f931b078cb8e615eabee26141Ard Biesheuvel NewPage = CoreAllocatePoolPages(PoolType, EFI_SIZE_TO_PAGES (Granularity), Granularity); 37628a00297189c323096aae8e2975de94e8549613cyshang if (NewPage == NULL) { 37728a00297189c323096aae8e2975de94e8549613cyshang goto Done; 37828a00297189c323096aae8e2975de94e8549613cyshang } 37928a00297189c323096aae8e2975de94e8549613cyshang 38028a00297189c323096aae8e2975de94e8549613cyshang // 381f8aabf6e4c199e92498512e1d0cf9a347b62e491Ard Biesheuvel // Serve the allocation request from the head of the allocated block 38228a00297189c323096aae8e2975de94e8549613cyshang // 3836860b92c847caff16b8cbc58ca31e3dbf9c5e5ccArd BiesheuvelCarve: 384f8aabf6e4c199e92498512e1d0cf9a347b62e491Ard Biesheuvel Head = (POOL_HEAD *) NewPage; 385f8aabf6e4c199e92498512e1d0cf9a347b62e491Ard Biesheuvel 386f8aabf6e4c199e92498512e1d0cf9a347b62e491Ard Biesheuvel // 387f8aabf6e4c199e92498512e1d0cf9a347b62e491Ard Biesheuvel // Carve up remaining space into free pool blocks 388f8aabf6e4c199e92498512e1d0cf9a347b62e491Ard Biesheuvel // 3896860b92c847caff16b8cbc58ca31e3dbf9c5e5ccArd Biesheuvel Index--; 3906860b92c847caff16b8cbc58ca31e3dbf9c5e5ccArd Biesheuvel while (Offset < MaxOffset) { 39128a00297189c323096aae8e2975de94e8549613cyshang ASSERT (Index < MAX_POOL_LIST); 39228a00297189c323096aae8e2975de94e8549613cyshang FSize = LIST_TO_SIZE(Index); 39328a00297189c323096aae8e2975de94e8549613cyshang 3946860b92c847caff16b8cbc58ca31e3dbf9c5e5ccArd Biesheuvel while (Offset + FSize <= MaxOffset) { 395022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang Free = (POOL_FREE *) &NewPage[Offset]; 39628a00297189c323096aae8e2975de94e8549613cyshang Free->Signature = POOL_FREE_SIGNATURE; 39728a00297189c323096aae8e2975de94e8549613cyshang Free->Index = (UINT32)Index; 39828a00297189c323096aae8e2975de94e8549613cyshang InsertHeadList (&Pool->FreeList[Index], &Free->Link); 399162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang Offset += FSize; 40028a00297189c323096aae8e2975de94e8549613cyshang } 40128a00297189c323096aae8e2975de94e8549613cyshang Index -= 1; 40228a00297189c323096aae8e2975de94e8549613cyshang } 40328a00297189c323096aae8e2975de94e8549613cyshang 4046860b92c847caff16b8cbc58ca31e3dbf9c5e5ccArd Biesheuvel ASSERT (Offset == MaxOffset); 405f8aabf6e4c199e92498512e1d0cf9a347b62e491Ard Biesheuvel goto Done; 40628a00297189c323096aae8e2975de94e8549613cyshang } 40728a00297189c323096aae8e2975de94e8549613cyshang 40828a00297189c323096aae8e2975de94e8549613cyshang // 40928a00297189c323096aae8e2975de94e8549613cyshang // Remove entry from free pool list 41028a00297189c323096aae8e2975de94e8549613cyshang // 41128a00297189c323096aae8e2975de94e8549613cyshang Free = CR (Pool->FreeList[Index].ForwardLink, POOL_FREE, Link, POOL_FREE_SIGNATURE); 41228a00297189c323096aae8e2975de94e8549613cyshang RemoveEntryList (&Free->Link); 41328a00297189c323096aae8e2975de94e8549613cyshang 41428a00297189c323096aae8e2975de94e8549613cyshang Head = (POOL_HEAD *) Free; 41528a00297189c323096aae8e2975de94e8549613cyshang 41628a00297189c323096aae8e2975de94e8549613cyshangDone: 41728a00297189c323096aae8e2975de94e8549613cyshang Buffer = NULL; 41828a00297189c323096aae8e2975de94e8549613cyshang 41928a00297189c323096aae8e2975de94e8549613cyshang if (Head != NULL) { 420022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang 42128a00297189c323096aae8e2975de94e8549613cyshang // 42228a00297189c323096aae8e2975de94e8549613cyshang // If we have a pool buffer, fill in the header & tail info 42328a00297189c323096aae8e2975de94e8549613cyshang // 42428a00297189c323096aae8e2975de94e8549613cyshang Head->Signature = POOL_HEAD_SIGNATURE; 425bb683bf4656730be2210fe3964e20d8c36d19eb5Star Zeng Head->Size = Size; 42628a00297189c323096aae8e2975de94e8549613cyshang Head->Type = (EFI_MEMORY_TYPE) PoolType; 42728a00297189c323096aae8e2975de94e8549613cyshang Tail = HEAD_TO_TAIL (Head); 42828a00297189c323096aae8e2975de94e8549613cyshang Tail->Signature = POOL_TAIL_SIGNATURE; 429bb683bf4656730be2210fe3964e20d8c36d19eb5Star Zeng Tail->Size = Size; 43028a00297189c323096aae8e2975de94e8549613cyshang Buffer = Head->Data; 43128a00297189c323096aae8e2975de94e8549613cyshang DEBUG_CLEAR_MEMORY (Buffer, Size - POOL_OVERHEAD); 43228a00297189c323096aae8e2975de94e8549613cyshang 433e94a9ff7271367e649ee4f9a86da1f1bea6d112eqhuang DEBUG (( 434e94a9ff7271367e649ee4f9a86da1f1bea6d112eqhuang DEBUG_POOL, 43557b4ecb94bceac2484dd9367b2ad111b05e17d97qhuang "AllocatePoolI: Type %x, Addr %p (len %lx) %,ld\n", PoolType, 436022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang Buffer, 43757b4ecb94bceac2484dd9367b2ad111b05e17d97qhuang (UINT64)(Size - POOL_OVERHEAD), 43857b4ecb94bceac2484dd9367b2ad111b05e17d97qhuang (UINT64) Pool->Used 439e94a9ff7271367e649ee4f9a86da1f1bea6d112eqhuang )); 44028a00297189c323096aae8e2975de94e8549613cyshang 44128a00297189c323096aae8e2975de94e8549613cyshang // 44228a00297189c323096aae8e2975de94e8549613cyshang // Account the allocation 44328a00297189c323096aae8e2975de94e8549613cyshang // 44428a00297189c323096aae8e2975de94e8549613cyshang Pool->Used += Size; 44528a00297189c323096aae8e2975de94e8549613cyshang 44628a00297189c323096aae8e2975de94e8549613cyshang } else { 44757b4ecb94bceac2484dd9367b2ad111b05e17d97qhuang DEBUG ((DEBUG_ERROR | DEBUG_POOL, "AllocatePool: failed to allocate %ld bytes\n", (UINT64) Size)); 44828a00297189c323096aae8e2975de94e8549613cyshang } 44928a00297189c323096aae8e2975de94e8549613cyshang 45028a00297189c323096aae8e2975de94e8549613cyshang return Buffer; 45128a00297189c323096aae8e2975de94e8549613cyshang} 452022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang 45328a00297189c323096aae8e2975de94e8549613cyshang 45428a00297189c323096aae8e2975de94e8549613cyshang 455162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang/** 45628a00297189c323096aae8e2975de94e8549613cyshang Frees pool. 45728a00297189c323096aae8e2975de94e8549613cyshang 458022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang @param Buffer The allocated pool entry to free 45928a00297189c323096aae8e2975de94e8549613cyshang 460022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang @retval EFI_INVALID_PARAMETER Buffer is not a valid value. 461162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang @retval EFI_SUCCESS Pool successfully freed. 46228a00297189c323096aae8e2975de94e8549613cyshang 463162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang**/ 464162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuangEFI_STATUS 465162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuangEFIAPI 46684edd20bd0756ef5719835498d4283435d6b5e77Star ZengCoreInternalFreePool ( 467162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang IN VOID *Buffer 468162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang ) 46928a00297189c323096aae8e2975de94e8549613cyshang{ 47028a00297189c323096aae8e2975de94e8549613cyshang EFI_STATUS Status; 47128a00297189c323096aae8e2975de94e8549613cyshang 472e94a9ff7271367e649ee4f9a86da1f1bea6d112eqhuang if (Buffer == NULL) { 47328a00297189c323096aae8e2975de94e8549613cyshang return EFI_INVALID_PARAMETER; 47428a00297189c323096aae8e2975de94e8549613cyshang } 47528a00297189c323096aae8e2975de94e8549613cyshang 47628a00297189c323096aae8e2975de94e8549613cyshang CoreAcquireMemoryLock (); 47728a00297189c323096aae8e2975de94e8549613cyshang Status = CoreFreePoolI (Buffer); 47828a00297189c323096aae8e2975de94e8549613cyshang CoreReleaseMemoryLock (); 47928a00297189c323096aae8e2975de94e8549613cyshang return Status; 48028a00297189c323096aae8e2975de94e8549613cyshang} 48128a00297189c323096aae8e2975de94e8549613cyshang 48284edd20bd0756ef5719835498d4283435d6b5e77Star Zeng/** 48384edd20bd0756ef5719835498d4283435d6b5e77Star Zeng Frees pool. 48484edd20bd0756ef5719835498d4283435d6b5e77Star Zeng 48584edd20bd0756ef5719835498d4283435d6b5e77Star Zeng @param Buffer The allocated pool entry to free 48684edd20bd0756ef5719835498d4283435d6b5e77Star Zeng 48784edd20bd0756ef5719835498d4283435d6b5e77Star Zeng @retval EFI_INVALID_PARAMETER Buffer is not a valid value. 48884edd20bd0756ef5719835498d4283435d6b5e77Star Zeng @retval EFI_SUCCESS Pool successfully freed. 48984edd20bd0756ef5719835498d4283435d6b5e77Star Zeng 49084edd20bd0756ef5719835498d4283435d6b5e77Star Zeng**/ 49184edd20bd0756ef5719835498d4283435d6b5e77Star ZengEFI_STATUS 49284edd20bd0756ef5719835498d4283435d6b5e77Star ZengEFIAPI 49384edd20bd0756ef5719835498d4283435d6b5e77Star ZengCoreFreePool ( 49484edd20bd0756ef5719835498d4283435d6b5e77Star Zeng IN VOID *Buffer 49584edd20bd0756ef5719835498d4283435d6b5e77Star Zeng ) 49684edd20bd0756ef5719835498d4283435d6b5e77Star Zeng{ 49784edd20bd0756ef5719835498d4283435d6b5e77Star Zeng EFI_STATUS Status; 498736a692e7c0210eb71c01c39731ef97383d606ebHot Tian 499736a692e7c0210eb71c01c39731ef97383d606ebHot Tian Status = CoreInternalFreePool (Buffer); 500736a692e7c0210eb71c01c39731ef97383d606ebHot Tian if (!EFI_ERROR (Status)) { 501736a692e7c0210eb71c01c39731ef97383d606ebHot Tian CoreUpdateProfile ((EFI_PHYSICAL_ADDRESS) (UINTN) RETURN_ADDRESS (0), MemoryProfileActionFreePool, (EFI_MEMORY_TYPE) 0, 0, Buffer); 502736a692e7c0210eb71c01c39731ef97383d606ebHot Tian } 503736a692e7c0210eb71c01c39731ef97383d606ebHot Tian return Status; 504736a692e7c0210eb71c01c39731ef97383d606ebHot Tian} 50528a00297189c323096aae8e2975de94e8549613cyshang 506162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang/** 50728a00297189c323096aae8e2975de94e8549613cyshang Internal function to free a pool entry. 50828a00297189c323096aae8e2975de94e8549613cyshang Caller must have the memory lock held 50928a00297189c323096aae8e2975de94e8549613cyshang 510022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang @param Buffer The allocated pool entry to free 51128a00297189c323096aae8e2975de94e8549613cyshang 512022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang @retval EFI_INVALID_PARAMETER Buffer not valid 513162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang @retval EFI_SUCCESS Buffer successfully freed. 51428a00297189c323096aae8e2975de94e8549613cyshang 515162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang**/ 516162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuangEFI_STATUS 517162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuangCoreFreePoolI ( 518162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang IN VOID *Buffer 519162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang ) 52028a00297189c323096aae8e2975de94e8549613cyshang{ 52128a00297189c323096aae8e2975de94e8549613cyshang POOL *Pool; 52228a00297189c323096aae8e2975de94e8549613cyshang POOL_HEAD *Head; 52328a00297189c323096aae8e2975de94e8549613cyshang POOL_TAIL *Tail; 52428a00297189c323096aae8e2975de94e8549613cyshang POOL_FREE *Free; 52528a00297189c323096aae8e2975de94e8549613cyshang UINTN Index; 52628a00297189c323096aae8e2975de94e8549613cyshang UINTN NoPages; 52728a00297189c323096aae8e2975de94e8549613cyshang UINTN Size; 52828a00297189c323096aae8e2975de94e8549613cyshang CHAR8 *NewPage; 529162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang UINTN Offset; 53028a00297189c323096aae8e2975de94e8549613cyshang BOOLEAN AllFree; 5317970100ccbd48e6f931b078cb8e615eabee26141Ard Biesheuvel UINTN Granularity; 53228a00297189c323096aae8e2975de94e8549613cyshang 53357b4ecb94bceac2484dd9367b2ad111b05e17d97qhuang ASSERT(Buffer != NULL); 53428a00297189c323096aae8e2975de94e8549613cyshang // 53528a00297189c323096aae8e2975de94e8549613cyshang // Get the head & tail of the pool entry 53628a00297189c323096aae8e2975de94e8549613cyshang // 53728a00297189c323096aae8e2975de94e8549613cyshang Head = CR (Buffer, POOL_HEAD, Data, POOL_HEAD_SIGNATURE); 53857b4ecb94bceac2484dd9367b2ad111b05e17d97qhuang ASSERT(Head != NULL); 53928a00297189c323096aae8e2975de94e8549613cyshang 54028a00297189c323096aae8e2975de94e8549613cyshang if (Head->Signature != POOL_HEAD_SIGNATURE) { 54128a00297189c323096aae8e2975de94e8549613cyshang return EFI_INVALID_PARAMETER; 54228a00297189c323096aae8e2975de94e8549613cyshang } 54328a00297189c323096aae8e2975de94e8549613cyshang 54428a00297189c323096aae8e2975de94e8549613cyshang Tail = HEAD_TO_TAIL (Head); 54557b4ecb94bceac2484dd9367b2ad111b05e17d97qhuang ASSERT(Tail != NULL); 54628a00297189c323096aae8e2975de94e8549613cyshang 54728a00297189c323096aae8e2975de94e8549613cyshang // 54828a00297189c323096aae8e2975de94e8549613cyshang // Debug 54928a00297189c323096aae8e2975de94e8549613cyshang // 55028a00297189c323096aae8e2975de94e8549613cyshang ASSERT (Tail->Signature == POOL_TAIL_SIGNATURE); 55128a00297189c323096aae8e2975de94e8549613cyshang ASSERT (Head->Size == Tail->Size); 55228a00297189c323096aae8e2975de94e8549613cyshang ASSERT_LOCKED (&gMemoryLock); 55328a00297189c323096aae8e2975de94e8549613cyshang 55428a00297189c323096aae8e2975de94e8549613cyshang if (Tail->Signature != POOL_TAIL_SIGNATURE) { 55528a00297189c323096aae8e2975de94e8549613cyshang return EFI_INVALID_PARAMETER; 55628a00297189c323096aae8e2975de94e8549613cyshang } 55728a00297189c323096aae8e2975de94e8549613cyshang 55828a00297189c323096aae8e2975de94e8549613cyshang if (Head->Size != Tail->Size) { 55928a00297189c323096aae8e2975de94e8549613cyshang return EFI_INVALID_PARAMETER; 56028a00297189c323096aae8e2975de94e8549613cyshang } 56128a00297189c323096aae8e2975de94e8549613cyshang 56228a00297189c323096aae8e2975de94e8549613cyshang // 56328a00297189c323096aae8e2975de94e8549613cyshang // Determine the pool type and account for it 56428a00297189c323096aae8e2975de94e8549613cyshang // 56528a00297189c323096aae8e2975de94e8549613cyshang Size = Head->Size; 56628a00297189c323096aae8e2975de94e8549613cyshang Pool = LookupPoolHead (Head->Type); 56728a00297189c323096aae8e2975de94e8549613cyshang if (Pool == NULL) { 56828a00297189c323096aae8e2975de94e8549613cyshang return EFI_INVALID_PARAMETER; 56928a00297189c323096aae8e2975de94e8549613cyshang } 57028a00297189c323096aae8e2975de94e8549613cyshang Pool->Used -= Size; 57157b4ecb94bceac2484dd9367b2ad111b05e17d97qhuang DEBUG ((DEBUG_POOL, "FreePool: %p (len %lx) %,ld\n", Head->Data, (UINT64)(Head->Size - POOL_OVERHEAD), (UINT64) Pool->Used)); 57228a00297189c323096aae8e2975de94e8549613cyshang 5737970100ccbd48e6f931b078cb8e615eabee26141Ard Biesheuvel if (Head->Type == EfiACPIReclaimMemory || 5747970100ccbd48e6f931b078cb8e615eabee26141Ard Biesheuvel Head->Type == EfiACPIMemoryNVS || 5757970100ccbd48e6f931b078cb8e615eabee26141Ard Biesheuvel Head->Type == EfiRuntimeServicesCode || 5767970100ccbd48e6f931b078cb8e615eabee26141Ard Biesheuvel Head->Type == EfiRuntimeServicesData) { 5777970100ccbd48e6f931b078cb8e615eabee26141Ard Biesheuvel 5787970100ccbd48e6f931b078cb8e615eabee26141Ard Biesheuvel Granularity = EFI_ACPI_RUNTIME_PAGE_ALLOCATION_ALIGNMENT; 5797970100ccbd48e6f931b078cb8e615eabee26141Ard Biesheuvel } else { 5807970100ccbd48e6f931b078cb8e615eabee26141Ard Biesheuvel Granularity = DEFAULT_PAGE_ALLOCATION; 5817970100ccbd48e6f931b078cb8e615eabee26141Ard Biesheuvel } 5827970100ccbd48e6f931b078cb8e615eabee26141Ard Biesheuvel 58328a00297189c323096aae8e2975de94e8549613cyshang // 584022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang // Determine the pool list 58528a00297189c323096aae8e2975de94e8549613cyshang // 58628a00297189c323096aae8e2975de94e8549613cyshang Index = SIZE_TO_LIST(Size); 58728a00297189c323096aae8e2975de94e8549613cyshang DEBUG_CLEAR_MEMORY (Head, Size); 58828a00297189c323096aae8e2975de94e8549613cyshang 58928a00297189c323096aae8e2975de94e8549613cyshang // 59028a00297189c323096aae8e2975de94e8549613cyshang // If it's not on the list, it must be pool pages 59128a00297189c323096aae8e2975de94e8549613cyshang // 592f2c7daf675d246261bd5e034b78e200017057df6Ard Biesheuvel if (Index >= SIZE_TO_LIST (Granularity)) { 59328a00297189c323096aae8e2975de94e8549613cyshang 59428a00297189c323096aae8e2975de94e8549613cyshang // 59528a00297189c323096aae8e2975de94e8549613cyshang // Return the memory pages back to free memory 59628a00297189c323096aae8e2975de94e8549613cyshang // 5977970100ccbd48e6f931b078cb8e615eabee26141Ard Biesheuvel NoPages = EFI_SIZE_TO_PAGES(Size) + EFI_SIZE_TO_PAGES (Granularity) - 1; 5987970100ccbd48e6f931b078cb8e615eabee26141Ard Biesheuvel NoPages &= ~(UINTN)(EFI_SIZE_TO_PAGES (Granularity) - 1); 59928a00297189c323096aae8e2975de94e8549613cyshang CoreFreePoolPages ((EFI_PHYSICAL_ADDRESS) (UINTN) Head, NoPages); 60028a00297189c323096aae8e2975de94e8549613cyshang 60128a00297189c323096aae8e2975de94e8549613cyshang } else { 60228a00297189c323096aae8e2975de94e8549613cyshang 60328a00297189c323096aae8e2975de94e8549613cyshang // 60428a00297189c323096aae8e2975de94e8549613cyshang // Put the pool entry onto the free pool list 60528a00297189c323096aae8e2975de94e8549613cyshang // 60628a00297189c323096aae8e2975de94e8549613cyshang Free = (POOL_FREE *) Head; 60757b4ecb94bceac2484dd9367b2ad111b05e17d97qhuang ASSERT(Free != NULL); 60828a00297189c323096aae8e2975de94e8549613cyshang Free->Signature = POOL_FREE_SIGNATURE; 60928a00297189c323096aae8e2975de94e8549613cyshang Free->Index = (UINT32)Index; 61028a00297189c323096aae8e2975de94e8549613cyshang InsertHeadList (&Pool->FreeList[Index], &Free->Link); 61128a00297189c323096aae8e2975de94e8549613cyshang 61228a00297189c323096aae8e2975de94e8549613cyshang // 613022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang // See if all the pool entries in the same page as Free are freed pool 61428a00297189c323096aae8e2975de94e8549613cyshang // entries 61528a00297189c323096aae8e2975de94e8549613cyshang // 6167970100ccbd48e6f931b078cb8e615eabee26141Ard Biesheuvel NewPage = (CHAR8 *)((UINTN)Free & ~(Granularity - 1)); 61728a00297189c323096aae8e2975de94e8549613cyshang Free = (POOL_FREE *) &NewPage[0]; 618e94a9ff7271367e649ee4f9a86da1f1bea6d112eqhuang ASSERT(Free != NULL); 61928a00297189c323096aae8e2975de94e8549613cyshang 62028a00297189c323096aae8e2975de94e8549613cyshang if (Free->Signature == POOL_FREE_SIGNATURE) { 62128a00297189c323096aae8e2975de94e8549613cyshang 62228a00297189c323096aae8e2975de94e8549613cyshang AllFree = TRUE; 623162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang Offset = 0; 624022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang 6257970100ccbd48e6f931b078cb8e615eabee26141Ard Biesheuvel while ((Offset < Granularity) && (AllFree)) { 6267e8e22056b721203f29b3ee982a64e98b0cbc22aArd Biesheuvel Free = (POOL_FREE *) &NewPage[Offset]; 6277e8e22056b721203f29b3ee982a64e98b0cbc22aArd Biesheuvel ASSERT(Free != NULL); 6287e8e22056b721203f29b3ee982a64e98b0cbc22aArd Biesheuvel if (Free->Signature != POOL_FREE_SIGNATURE) { 6297e8e22056b721203f29b3ee982a64e98b0cbc22aArd Biesheuvel AllFree = FALSE; 63028a00297189c323096aae8e2975de94e8549613cyshang } 6317e8e22056b721203f29b3ee982a64e98b0cbc22aArd Biesheuvel Offset += LIST_TO_SIZE(Free->Index); 63228a00297189c323096aae8e2975de94e8549613cyshang } 63328a00297189c323096aae8e2975de94e8549613cyshang 63428a00297189c323096aae8e2975de94e8549613cyshang if (AllFree) { 63528a00297189c323096aae8e2975de94e8549613cyshang 63628a00297189c323096aae8e2975de94e8549613cyshang // 637022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang // All of the pool entries in the same page as Free are free pool 63828a00297189c323096aae8e2975de94e8549613cyshang // entries 63928a00297189c323096aae8e2975de94e8549613cyshang // Remove all of these pool entries from the free loop lists. 64028a00297189c323096aae8e2975de94e8549613cyshang // 64128a00297189c323096aae8e2975de94e8549613cyshang Free = (POOL_FREE *) &NewPage[0]; 64257b4ecb94bceac2484dd9367b2ad111b05e17d97qhuang ASSERT(Free != NULL); 643162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang Offset = 0; 644022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang 6457970100ccbd48e6f931b078cb8e615eabee26141Ard Biesheuvel while (Offset < Granularity) { 6467e8e22056b721203f29b3ee982a64e98b0cbc22aArd Biesheuvel Free = (POOL_FREE *) &NewPage[Offset]; 6477e8e22056b721203f29b3ee982a64e98b0cbc22aArd Biesheuvel ASSERT(Free != NULL); 6487e8e22056b721203f29b3ee982a64e98b0cbc22aArd Biesheuvel RemoveEntryList (&Free->Link); 6497e8e22056b721203f29b3ee982a64e98b0cbc22aArd Biesheuvel Offset += LIST_TO_SIZE(Free->Index); 65028a00297189c323096aae8e2975de94e8549613cyshang } 65128a00297189c323096aae8e2975de94e8549613cyshang 65228a00297189c323096aae8e2975de94e8549613cyshang // 65328a00297189c323096aae8e2975de94e8549613cyshang // Free the page 65428a00297189c323096aae8e2975de94e8549613cyshang // 6557970100ccbd48e6f931b078cb8e615eabee26141Ard Biesheuvel CoreFreePoolPages ((EFI_PHYSICAL_ADDRESS) (UINTN)NewPage, EFI_SIZE_TO_PAGES (Granularity)); 65628a00297189c323096aae8e2975de94e8549613cyshang } 65728a00297189c323096aae8e2975de94e8549613cyshang } 65828a00297189c323096aae8e2975de94e8549613cyshang } 65928a00297189c323096aae8e2975de94e8549613cyshang 66028a00297189c323096aae8e2975de94e8549613cyshang // 661022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang // If this is an OS specific memory type, then check to see if the last 66228a00297189c323096aae8e2975de94e8549613cyshang // portion of that memory type has been freed. If it has, then free the 66328a00297189c323096aae8e2975de94e8549613cyshang // list entry for that memory type 66428a00297189c323096aae8e2975de94e8549613cyshang // 6653d78c020d22023d35d27b48817d73ff31a361ac7rsun if ((INT32)Pool->MemoryType < 0 && Pool->Used == 0) { 66628a00297189c323096aae8e2975de94e8549613cyshang RemoveEntryList (&Pool->Link); 66728a00297189c323096aae8e2975de94e8549613cyshang CoreFreePoolI (Pool); 66828a00297189c323096aae8e2975de94e8549613cyshang } 66928a00297189c323096aae8e2975de94e8549613cyshang 67028a00297189c323096aae8e2975de94e8549613cyshang return EFI_SUCCESS; 67128a00297189c323096aae8e2975de94e8549613cyshang} 67284edd20bd0756ef5719835498d4283435d6b5e77Star Zeng 673