]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Core/PiSmmCore/Pool.c
Fix non-boolean comparison expression.
[mirror_edk2.git] / MdeModulePkg / Core / PiSmmCore / Pool.c
CommitLineData
e42e9404 1/** @file\r
2 SMM Memory pool management functions.\r
3\r
4 Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>\r
5 This program and the accompanying materials are licensed and made available \r
6 under the terms and conditions of the BSD License which accompanies this \r
7 distribution. The full text of the license may be found at \r
8 http://opensource.org/licenses/bsd-license.php \r
9\r
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. \r
12\r
13**/\r
14\r
15#include "PiSmmCore.h"\r
16\r
17//\r
18// MIN_POOL_SHIFT must not be less than 5\r
19//\r
20#define MIN_POOL_SHIFT 6\r
21#define MIN_POOL_SIZE (1 << MIN_POOL_SHIFT)\r
22\r
23//\r
24// MAX_POOL_SHIFT must not be less than EFI_PAGE_SHIFT - 1\r
25//\r
26#define MAX_POOL_SHIFT (EFI_PAGE_SHIFT - 1)\r
27#define MAX_POOL_SIZE (1 << MAX_POOL_SHIFT)\r
28\r
29//\r
30// MAX_POOL_INDEX are calculated by maximum and minimum pool sizes\r
31//\r
32#define MAX_POOL_INDEX (MAX_POOL_SHIFT - MIN_POOL_SHIFT + 1)\r
33\r
34typedef struct {\r
35 UINTN Size;\r
36 BOOLEAN Available;\r
37} POOL_HEADER;\r
38\r
39typedef struct {\r
40 POOL_HEADER Header;\r
41 LIST_ENTRY Link;\r
42} FREE_POOL_HEADER;\r
43\r
44LIST_ENTRY mSmmPoolLists[MAX_POOL_INDEX];\r
45\r
46/**\r
47 Called to initialize the memory service.\r
48\r
49 @param SmramRangeCount Number of SMRAM Regions\r
50 @param SmramRanges Pointer to SMRAM Descriptors\r
51\r
52**/\r
53VOID\r
54SmmInitializeMemoryServices (\r
55 IN UINTN SmramRangeCount,\r
56 IN EFI_SMRAM_DESCRIPTOR *SmramRanges\r
57 )\r
58{\r
59 UINTN Index;\r
60\r
61 //\r
62 // Initialize Pool list\r
63 //\r
64 for (Index = sizeof (mSmmPoolLists) / sizeof (*mSmmPoolLists); Index > 0;) {\r
65 InitializeListHead (&mSmmPoolLists[--Index]);\r
66 }\r
67\r
68 //\r
69 // Initialize free SMRAM regions\r
70 //\r
71 for (Index = 0; Index < SmramRangeCount; Index++) {\r
72 SmmAddMemoryRegion (\r
73 SmramRanges[Index].CpuStart,\r
74 SmramRanges[Index].PhysicalSize,\r
75 EfiConventionalMemory,\r
76 SmramRanges[Index].RegionState\r
77 );\r
78 }\r
79}\r
80\r
81/**\r
82 Internal Function. Allocate a pool by specified PoolIndex.\r
83\r
84 @param PoolIndex Index which indicate the Pool size.\r
85 @param FreePoolHdr The returned Free pool.\r
86\r
87 @retval EFI_OUT_OF_RESOURCES Allocation failed.\r
88 @retval EFI_SUCCESS Pool successfully allocated.\r
89\r
90**/\r
91EFI_STATUS\r
92InternalAllocPoolByIndex (\r
93 IN UINTN PoolIndex,\r
94 OUT FREE_POOL_HEADER **FreePoolHdr\r
95 )\r
96{\r
97 EFI_STATUS Status;\r
98 FREE_POOL_HEADER *Hdr;\r
99\r
52c0d06b 100 ASSERT (PoolIndex <= MAX_POOL_INDEX);\r
e42e9404 101 Status = EFI_SUCCESS;\r
102 if (PoolIndex == MAX_POOL_INDEX) {\r
103 Hdr = (FREE_POOL_HEADER *)AllocatePages (EFI_SIZE_TO_PAGES (MAX_POOL_SIZE << 1));\r
104 if (Hdr == NULL) {\r
5b422a7b 105 return EFI_OUT_OF_RESOURCES;\r
e42e9404 106 }\r
107 } else if (!IsListEmpty (&mSmmPoolLists[PoolIndex])) {\r
108 Hdr = BASE_CR (GetFirstNode (&mSmmPoolLists[PoolIndex]), FREE_POOL_HEADER, Link);\r
109 RemoveEntryList (&Hdr->Link);\r
110 } else {\r
111 Status = InternalAllocPoolByIndex (PoolIndex + 1, &Hdr);\r
112 if (!EFI_ERROR (Status)) {\r
113 Hdr->Header.Size >>= 1;\r
114 Hdr->Header.Available = TRUE;\r
115 InsertHeadList (&mSmmPoolLists[PoolIndex], &Hdr->Link);\r
116 Hdr = (FREE_POOL_HEADER*)((UINT8*)Hdr + Hdr->Header.Size);\r
117 }\r
118 }\r
119\r
120 if (!EFI_ERROR (Status)) {\r
121 Hdr->Header.Size = MIN_POOL_SIZE << PoolIndex;\r
122 Hdr->Header.Available = FALSE;\r
123 }\r
124\r
125 *FreePoolHdr = Hdr;\r
126 return Status;\r
127}\r
128\r
129/**\r
130 Internal Function. Free a pool by specified PoolIndex.\r
131\r
132 @param FreePoolHdr The pool to free.\r
133\r
134 @retval EFI_SUCCESS Pool successfully freed.\r
135\r
136**/\r
137EFI_STATUS\r
138InternalFreePoolByIndex (\r
139 IN FREE_POOL_HEADER *FreePoolHdr\r
140 )\r
141{\r
142 UINTN PoolIndex;\r
143\r
144 ASSERT ((FreePoolHdr->Header.Size & (FreePoolHdr->Header.Size - 1)) == 0);\r
145 ASSERT (((UINTN)FreePoolHdr & (FreePoolHdr->Header.Size - 1)) == 0);\r
146 ASSERT (FreePoolHdr->Header.Size >= MIN_POOL_SIZE);\r
147\r
148 PoolIndex = HighBitSet32 ((UINT32)FreePoolHdr->Header.Size) - MIN_POOL_SHIFT;\r
149 FreePoolHdr->Header.Available = TRUE;\r
5b422a7b 150 ASSERT (PoolIndex < MAX_POOL_INDEX);\r
e42e9404 151 InsertHeadList (&mSmmPoolLists[PoolIndex], &FreePoolHdr->Link);\r
152 return EFI_SUCCESS;\r
153}\r
154\r
155/**\r
156 Allocate pool of a particular type.\r
157\r
158 @param PoolType Type of pool to allocate.\r
159 @param Size The amount of pool to allocate.\r
160 @param Buffer The address to return a pointer to the allocated\r
161 pool.\r
162\r
163 @retval EFI_INVALID_PARAMETER PoolType not valid.\r
164 @retval EFI_OUT_OF_RESOURCES Size exceeds max pool size or allocation failed.\r
165 @retval EFI_SUCCESS Pool successfully allocated.\r
166\r
167**/\r
168EFI_STATUS\r
169EFIAPI\r
170SmmAllocatePool (\r
171 IN EFI_MEMORY_TYPE PoolType,\r
172 IN UINTN Size,\r
173 OUT VOID **Buffer\r
174 )\r
175{\r
176 POOL_HEADER *PoolHdr;\r
177 FREE_POOL_HEADER *FreePoolHdr;\r
178 EFI_STATUS Status;\r
179 EFI_PHYSICAL_ADDRESS Address;\r
180 UINTN PoolIndex;\r
181\r
182 if (PoolType != EfiRuntimeServicesCode &&\r
183 PoolType != EfiRuntimeServicesData) {\r
184 return EFI_INVALID_PARAMETER;\r
185 }\r
186\r
187 if (Size == 0) {\r
188 *Buffer = NULL;\r
189 return EFI_SUCCESS;\r
190 }\r
191\r
192 Size += sizeof (*PoolHdr);\r
193 if (Size > MAX_POOL_SIZE) {\r
194 Size = EFI_SIZE_TO_PAGES (Size);\r
195 Status = SmmAllocatePages (AllocateAnyPages, PoolType, Size, &Address);\r
196 if (EFI_ERROR (Status)) {\r
197 return Status;\r
198 }\r
199\r
200 PoolHdr = (POOL_HEADER*)(UINTN)Address;\r
201 PoolHdr->Size = EFI_PAGES_TO_SIZE (Size);\r
202 PoolHdr->Available = FALSE;\r
203 *Buffer = PoolHdr + 1;\r
204 return Status;\r
205 }\r
206\r
207 Size = (Size + MIN_POOL_SIZE - 1) >> MIN_POOL_SHIFT;\r
208 PoolIndex = HighBitSet32 ((UINT32)Size);\r
209 if ((Size & (Size - 1)) != 0) {\r
210 PoolIndex++;\r
211 }\r
212\r
213 Status = InternalAllocPoolByIndex (PoolIndex, &FreePoolHdr);\r
214 *Buffer = &FreePoolHdr->Header + 1;\r
215 return Status;\r
216}\r
217\r
218/**\r
219 Frees pool.\r
220\r
221 @param Buffer The allocated pool entry to free.\r
222\r
223 @retval EFI_INVALID_PARAMETER Buffer is not a valid value.\r
224 @retval EFI_SUCCESS Pool successfully freed.\r
225\r
226**/\r
227EFI_STATUS\r
228EFIAPI\r
229SmmFreePool (\r
230 IN VOID *Buffer\r
231 )\r
232{\r
233 FREE_POOL_HEADER *FreePoolHdr;\r
234\r
235 if (Buffer == NULL) {\r
236 return EFI_INVALID_PARAMETER;\r
237 }\r
238\r
239 FreePoolHdr = (FREE_POOL_HEADER*)((POOL_HEADER*)Buffer - 1);\r
240 ASSERT (!FreePoolHdr->Header.Available);\r
241\r
242 if (FreePoolHdr->Header.Size > MAX_POOL_SIZE) {\r
243 ASSERT (((UINTN)FreePoolHdr & EFI_PAGE_MASK) == 0);\r
244 ASSERT ((FreePoolHdr->Header.Size & EFI_PAGE_MASK) == 0);\r
245 return SmmFreePages (\r
246 (EFI_PHYSICAL_ADDRESS)(UINTN)FreePoolHdr,\r
247 EFI_SIZE_TO_PAGES (FreePoolHdr->Header.Size)\r
248 );\r
249 }\r
250 return InternalFreePoolByIndex (FreePoolHdr);\r
251}\r