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