Add debug info when allocate pages failed in PeiMain.
[mirror_edk2.git] / EdkModulePkg / Core / Pei / Memory / MemoryServices.c
CommitLineData
878ddf1f 1/*++\r
2\r
3Copyright (c) 2006, Intel Corporation \r
4All rights reserved. This program and the accompanying materials \r
5are licensed and made available under the terms and conditions of the BSD License \r
6which accompanies this distribution. The full text of the license may be found at \r
7http://opensource.org/licenses/bsd-license.php \r
8 \r
9THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
10WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. \r
11\r
12Module Name:\r
13\r
14 MemoryServices.c\r
15\r
16Abstract:\r
17\r
18 EFI PEI Core memory services\r
19\r
20--*/\r
21\r
22#include <PeiMain.h>\r
23\r
24VOID\r
25InitializeMemoryServices (\r
26 IN EFI_PEI_SERVICES **PeiServices,\r
27 IN EFI_PEI_STARTUP_DESCRIPTOR *PeiStartupDescriptor,\r
28 IN PEI_CORE_INSTANCE *OldCoreData\r
29 )\r
30/*++\r
31\r
32Routine Description:\r
33\r
34 Initialize the memory services.\r
35\r
36Arguments:\r
37\r
38 PeiServices - The PEI core services table.\r
39 PeiStartupDescriptor - Information and services provided by SEC phase.\r
40 OldCoreData - Pointer to the PEI Core data.\r
41 NULL if being run in non-permament memory mode.\r
42\r
43Returns:\r
44\r
45 None\r
46\r
47--*/\r
48{\r
49 PEI_CORE_INSTANCE *PrivateData;\r
50 UINT64 SizeOfCarHeap;\r
51\r
52 PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS (PeiServices);\r
53 PrivateData->SwitchStackSignal = FALSE;\r
54\r
55 if (OldCoreData == NULL) {\r
56\r
57 PrivateData->PeiMemoryInstalled = FALSE;\r
58\r
59 PrivateData->BottomOfCarHeap = (VOID *) (((UINTN)(VOID *)(&PrivateData))\r
60 & (~((PeiStartupDescriptor->SizeOfCacheAsRam) - 1))); \r
61 PrivateData->TopOfCarHeap = (VOID *)((UINTN)(PrivateData->BottomOfCarHeap) + PeiStartupDescriptor->SizeOfCacheAsRam);\r
62 //\r
63 // SizeOfCarHeap is 1/2 (arbitrary) of CacheAsRam Size.\r
64 //\r
65 SizeOfCarHeap = (UINT64) PeiStartupDescriptor->SizeOfCacheAsRam;\r
66 SizeOfCarHeap = RShiftU64 (SizeOfCarHeap, 1);\r
67 \r
2ce31132 68 DEBUG_CODE_BEGIN ();\r
69 PrivateData->SizeOfCacheAsRam = PeiStartupDescriptor->SizeOfCacheAsRam;\r
70 PrivateData->MaxTopOfCarHeap = (VOID *) ((UINTN) PrivateData->BottomOfCarHeap + (UINTN) SizeOfCarHeap);\r
71 DEBUG_CODE_END ();\r
878ddf1f 72\r
73 PrivateData->HobList.Raw = PrivateData->BottomOfCarHeap;\r
74 \r
75 PeiCoreBuildHobHandoffInfoTable (\r
76 BOOT_WITH_FULL_CONFIGURATION,\r
77 (EFI_PHYSICAL_ADDRESS) (UINTN) PrivateData->BottomOfCarHeap,\r
78 (UINTN) SizeOfCarHeap\r
79 );\r
80 //\r
81 // Copy PeiServices from ROM to Cache in PrivateData\r
82 //\r
83 CopyMem (&(PrivateData->ServiceTableShadow), *PeiServices, sizeof (EFI_PEI_SERVICES));\r
84\r
85 //\r
86 // Set PS to point to ServiceTableShadow in Cache\r
87 //\r
88 PrivateData->PS = &(PrivateData->ServiceTableShadow);\r
89 } else {\r
90 // \r
91 // Set PS to point to ServiceTableShadow in Cache one time after the \r
92 // stack switched to main memory \r
93 // \r
94 PrivateData->PS = &(PrivateData->ServiceTableShadow); \r
95} \r
96\r
97 return;\r
98}\r
99\r
100EFI_STATUS\r
101EFIAPI\r
102PeiInstallPeiMemory (\r
103 IN EFI_PEI_SERVICES **PeiServices,\r
104 IN EFI_PHYSICAL_ADDRESS MemoryBegin,\r
105 IN UINT64 MemoryLength\r
106 )\r
107/*++\r
108\r
109Routine Description:\r
110\r
111 Install the permanent memory is now available.\r
112 Creates HOB (PHIT and Stack).\r
113\r
114Arguments:\r
115\r
116 PeiServices - The PEI core services table.\r
117 MemoryBegin - Start of memory address.\r
118 MemoryLength - Length of memory.\r
119\r
120Returns:\r
121\r
122 Status - EFI_SUCCESS\r
123 \r
124--*/\r
125{\r
126 PEI_CORE_INSTANCE *PrivateData;\r
127 EFI_HOB_HANDOFF_INFO_TABLE *OldHandOffHob;\r
128 EFI_HOB_HANDOFF_INFO_TABLE *NewHandOffHob;\r
129 UINT64 PeiStackSize;\r
130 UINT64 EfiFreeMemorySize;\r
131 EFI_PHYSICAL_ADDRESS PhysicalAddressOfOldHob;\r
132 \r
133 PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS (PeiServices);\r
134\r
135 PrivateData->SwitchStackSignal = TRUE;\r
136 PrivateData->PeiMemoryInstalled = TRUE;\r
137\r
138 PrivateData->StackBase = MemoryBegin;\r
139 \r
140 PeiStackSize = RShiftU64 (MemoryLength, 1);\r
141 if (PEI_STACK_SIZE > PeiStackSize) {\r
142 PrivateData->StackSize = PeiStackSize;\r
143 } else {\r
144 PrivateData->StackSize = PEI_STACK_SIZE;\r
145 }\r
146\r
147 OldHandOffHob = PrivateData->HobList.HandoffInformationTable;\r
148\r
149 PrivateData->HobList.Raw = (VOID *)((UINTN)(MemoryBegin + PrivateData->StackSize));\r
150 NewHandOffHob = PrivateData->HobList.HandoffInformationTable;\r
151 PhysicalAddressOfOldHob = (EFI_PHYSICAL_ADDRESS) (UINTN) OldHandOffHob;\r
152\r
153 EfiFreeMemorySize = OldHandOffHob->EfiFreeMemoryBottom - PhysicalAddressOfOldHob;\r
154 \r
155 DEBUG ((EFI_D_INFO, "HOBLIST address before memory init = 0x%08x\n", OldHandOffHob));\r
156 DEBUG ((EFI_D_INFO, "HOBLIST address after memory init = 0x%08x\n", NewHandOffHob));\r
157\r
158 CopyMem (\r
159 NewHandOffHob,\r
160 OldHandOffHob,\r
161 (UINTN)EfiFreeMemorySize\r
162 );\r
163\r
164 NewHandOffHob->EfiMemoryTop = MemoryBegin + MemoryLength;\r
165 NewHandOffHob->EfiFreeMemoryTop = NewHandOffHob->EfiMemoryTop;\r
166 NewHandOffHob->EfiMemoryBottom = MemoryBegin;\r
167 \r
168 NewHandOffHob->EfiFreeMemoryBottom = (UINTN)NewHandOffHob + EfiFreeMemorySize; \r
169 \r
170 NewHandOffHob->EfiEndOfHobList = (UINTN)NewHandOffHob +\r
171 (OldHandOffHob->EfiEndOfHobList -\r
172 PhysicalAddressOfOldHob);\r
173\r
174 ConvertPpiPointers (PeiServices, OldHandOffHob, NewHandOffHob);\r
175\r
176 BuildStackHob (PrivateData->StackBase, PrivateData->StackSize);\r
177 \r
178\r
179 return EFI_SUCCESS; \r
180}\r
181\r
182EFI_STATUS\r
183EFIAPI\r
184PeiAllocatePages (\r
185 IN EFI_PEI_SERVICES **PeiServices,\r
186 IN EFI_MEMORY_TYPE MemoryType,\r
187 IN UINTN Pages,\r
188 OUT EFI_PHYSICAL_ADDRESS *Memory\r
189 )\r
190/*++\r
191\r
192Routine Description:\r
193\r
194 Memory allocation service on permanent memory, \r
195 not usable prior to the memory installation.\r
196\r
197Arguments:\r
198\r
199 PeiServices - The PEI core services table.\r
200 MemoryType - Type of memory to allocate.\r
201 Pages - Number of pages to allocate.\r
202 Memory - Pointer of memory allocated.\r
203\r
204Returns:\r
205\r
206 Status - EFI_SUCCESS The allocation was successful\r
207 EFI_INVALID_PARAMETER Only AllocateAnyAddress is supported.\r
208 EFI_NOT_AVAILABLE_YET Called with permanent memory not available\r
209 EFI_OUT_OF_RESOURCES There is not enough HOB heap to satisfy the requirement\r
210 to allocate the number of pages.\r
211\r
212--*/\r
213{\r
214 PEI_CORE_INSTANCE *PrivateData;\r
215 EFI_PEI_HOB_POINTERS Hob;\r
216 EFI_PHYSICAL_ADDRESS Offset;\r
217\r
218 PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS (PeiServices);\r
219\r
220 //\r
221 // Check if Hob already available\r
222 //\r
223 if (!PrivateData->PeiMemoryInstalled) {\r
224 return EFI_NOT_AVAILABLE_YET;\r
225 }\r
226\r
227 Hob.Raw = PrivateData->HobList.Raw;\r
228\r
229 //\r
230 // Check to see if on 4k boundary\r
231 //\r
232 Offset = Hob.HandoffInformationTable->EfiFreeMemoryTop & 0xFFF;\r
233\r
234 //\r
235 // If not aligned, make the allocation aligned.\r
236 //\r
237 if (Offset != 0) {\r
238 Hob.HandoffInformationTable->EfiFreeMemoryTop -= Offset;\r
239 }\r
240\r
241 //\r
242 // Verify that there is sufficient memory to satisfy the allocation\r
243 //\r
244 if (Hob.HandoffInformationTable->EfiFreeMemoryTop - ((Pages * EFI_PAGE_SIZE) + sizeof (EFI_HOB_MEMORY_ALLOCATION)) < \r
245 Hob.HandoffInformationTable->EfiFreeMemoryBottom) {\r
e75ac0cc
LG
246 DEBUG ((EFI_D_ERROR, "AllocatePages failed: No 0x%x Pages is available.\n", Pages));\r
247 DEBUG ((EFI_D_ERROR, "There is only left 0x%x pages memory resource to be allocated.\n", \\r
af9e69ff 248 EFI_SIZE_TO_PAGES ((UINTN) (Hob.HandoffInformationTable->EfiFreeMemoryTop - Hob.HandoffInformationTable->EfiFreeMemoryBottom))));\r
878ddf1f 249 return EFI_OUT_OF_RESOURCES;\r
250 } else {\r
251 //\r
252 // Update the PHIT to reflect the memory usage\r
253 //\r
254 Hob.HandoffInformationTable->EfiFreeMemoryTop -= Pages * EFI_PAGE_SIZE;\r
255\r
256 //\r
257 // Update the value for the caller\r
258 //\r
259 *Memory = Hob.HandoffInformationTable->EfiFreeMemoryTop;\r
260\r
261 //\r
262 // Create a memory allocation HOB.\r
263 //\r
264 BuildMemoryAllocationHob (\r
265 Hob.HandoffInformationTable->EfiFreeMemoryTop,\r
266 Pages * EFI_PAGE_SIZE + Offset,\r
267 MemoryType\r
268 );\r
269\r
270 return EFI_SUCCESS;\r
271 }\r
272}\r
273\r
274\r
275EFI_STATUS\r
276EFIAPI\r
277PeiAllocatePool (\r
278 IN EFI_PEI_SERVICES **PeiServices,\r
279 IN UINTN Size,\r
280 OUT VOID **Buffer\r
281 )\r
282/*++\r
283\r
284Routine Description:\r
285\r
286 Memory allocation service on the CAR. \r
287\r
288Arguments:\r
289\r
290 PeiServices - The PEI core services table.\r
291\r
292 Size - Amount of memory required\r
293\r
294 Buffer - Address of pointer to the buffer\r
295\r
296Returns:\r
297\r
298 Status - EFI_SUCCESS The allocation was successful\r
299 EFI_OUT_OF_RESOURCES There is not enough heap to satisfy the requirement\r
300 to allocate the requested size.\r
301 \r
302--*/\r
303{\r
304 EFI_STATUS Status;\r
305 EFI_HOB_MEMORY_POOL *Hob;\r
306\r
a3657e3e 307 //\r
511710d6 308 // If some "post-memory" PEIM wishes to allocate larger pool,\r
a3657e3e 309 // it should use AllocatePages service instead.\r
310 //\r
311 ASSERT (Size < 0x10000 - sizeof (EFI_HOB_MEMORY_POOL));\r
84a99d48 312 Status = PeiServicesCreateHob (\r
878ddf1f 313 EFI_HOB_TYPE_PEI_MEMORY_POOL,\r
314 (UINT16)(sizeof (EFI_HOB_MEMORY_POOL) + Size),\r
315 (VOID **)&Hob\r
316 );\r
317 *Buffer = Hob+1; \r
318\r
319\r
320 return Status;\r
321}\r