]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Core/Pei/Memory/MemoryServices.c
1) If PeiLoadImage fails, the section extraction PPI or Decompress PPI may not be...
[mirror_edk2.git] / MdeModulePkg / 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 PEI_CORE_INSTANCE *PrivateData,
27 IN CONST EFI_SEC_PEI_HAND_OFF *SecCoreData,
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 SecCoreData - Points to a data structure containing information about the PEI core's operating
40 environment, such as the size and location of temporary RAM, the stack location and
41 the BFV location.
42
43 OldCoreData - Pointer to the PEI Core data.
44 NULL if being run in non-permament memory mode.
45
46 Returns:
47
48 None
49
50 --*/
51 {
52 PrivateData->SwitchStackSignal = FALSE;
53
54 if (OldCoreData == NULL) {
55
56 PrivateData->PeiMemoryInstalled = FALSE;
57
58 PrivateData->BottomOfCarHeap = SecCoreData->PeiTemporaryRamBase;
59 PrivateData->TopOfCarHeap = (VOID *)((UINTN)(PrivateData->BottomOfCarHeap) + SecCoreData->PeiTemporaryRamSize);
60
61 DEBUG_CODE_BEGIN ();
62 PrivateData->SizeOfCacheAsRam = SecCoreData->PeiTemporaryRamSize + SecCoreData->StackSize;
63 PrivateData->MaxTopOfCarHeap = (VOID *) ((UINTN) PrivateData->BottomOfCarHeap + (UINTN) PrivateData->SizeOfCacheAsRam);
64 PrivateData->StackBase = (EFI_PHYSICAL_ADDRESS) (UINTN) SecCoreData->StackBase;
65 PrivateData->StackSize = (UINT64) SecCoreData->StackSize;
66 DEBUG_CODE_END ();
67
68 PrivateData->HobList.Raw = PrivateData->BottomOfCarHeap;
69
70 PeiCoreBuildHobHandoffInfoTable (
71 BOOT_WITH_FULL_CONFIGURATION,
72 (EFI_PHYSICAL_ADDRESS) (UINTN) PrivateData->BottomOfCarHeap,
73 (UINTN) SecCoreData->PeiTemporaryRamSize
74 );
75
76 //
77 // Set PS to point to ServiceTableShadow in Cache
78 //
79 PrivateData->PS = &(PrivateData->ServiceTableShadow);
80 }
81
82 return;
83 }
84
85 EFI_STATUS
86 EFIAPI
87 PeiInstallPeiMemory (
88 IN CONST EFI_PEI_SERVICES **PeiServices,
89 IN EFI_PHYSICAL_ADDRESS MemoryBegin,
90 IN UINT64 MemoryLength
91 )
92 /*++
93
94 Routine Description:
95
96 Install the permanent memory is now available.
97 Creates HOB (PHIT and Stack).
98
99 Arguments:
100
101 PeiServices - The PEI core services table.
102 MemoryBegin - Start of memory address.
103 MemoryLength - Length of memory.
104
105 Returns:
106
107 Status - EFI_SUCCESS
108
109 --*/
110 {
111 PEI_CORE_INSTANCE *PrivateData;
112 EFI_HOB_HANDOFF_INFO_TABLE *OldHandOffHob;
113 EFI_HOB_HANDOFF_INFO_TABLE *NewHandOffHob;
114 UINT64 PeiStackSize;
115 UINT64 EfiFreeMemorySize;
116 EFI_PHYSICAL_ADDRESS PhysicalAddressOfOldHob;
117
118 DEBUG ((EFI_D_INFO, "PeiInstallPeiMemory MemoryBegin 0x%LX, MemoryLength 0x%LX\n", MemoryBegin, MemoryLength));
119
120 PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS (PeiServices);
121
122 PrivateData->SwitchStackSignal = TRUE;
123 PrivateData->PeiMemoryInstalled = TRUE;
124
125 PrivateData->StackBase = MemoryBegin;
126
127 PeiStackSize = RShiftU64 (MemoryLength, 1);
128 if (PEI_STACK_SIZE > PeiStackSize) {
129 PrivateData->StackSize = PeiStackSize;
130 } else {
131 PrivateData->StackSize = PEI_STACK_SIZE;
132 }
133
134 OldHandOffHob = PrivateData->HobList.HandoffInformationTable;
135
136 PrivateData->HobList.Raw = (VOID *)((UINTN)(MemoryBegin + PrivateData->StackSize));
137 NewHandOffHob = PrivateData->HobList.HandoffInformationTable;
138 PhysicalAddressOfOldHob = (EFI_PHYSICAL_ADDRESS) (UINTN) OldHandOffHob;
139
140 EfiFreeMemorySize = OldHandOffHob->EfiFreeMemoryBottom - PhysicalAddressOfOldHob;
141
142 DEBUG ((EFI_D_INFO, "HOBLIST address before memory init = 0x%p\n", OldHandOffHob));
143 DEBUG ((EFI_D_INFO, "HOBLIST address after memory init = 0x%p\n", NewHandOffHob));
144
145 CopyMem (
146 NewHandOffHob,
147 OldHandOffHob,
148 (UINTN)EfiFreeMemorySize
149 );
150
151 NewHandOffHob->EfiMemoryTop = MemoryBegin + MemoryLength;
152 NewHandOffHob->EfiFreeMemoryTop = NewHandOffHob->EfiMemoryTop;
153 NewHandOffHob->EfiMemoryBottom = MemoryBegin;
154
155 NewHandOffHob->EfiFreeMemoryBottom = (UINTN)NewHandOffHob + EfiFreeMemorySize;
156
157 NewHandOffHob->EfiEndOfHobList = (UINTN)NewHandOffHob +
158 (OldHandOffHob->EfiEndOfHobList -
159 PhysicalAddressOfOldHob);
160
161 //
162 // For IPF in CAR mode the real memory access is uncached,in InstallPeiMemory()
163 // the 63-bit of address is set to 1.
164 //
165 SWITCH_TO_CACHE_MODE (PrivateData);
166
167 ConvertPpiPointers (PeiServices, OldHandOffHob, NewHandOffHob);
168
169 BuildStackHob (PrivateData->StackBase, PrivateData->StackSize);
170
171
172 return EFI_SUCCESS;
173 }
174
175 EFI_STATUS
176 EFIAPI
177 PeiAllocatePages (
178 IN CONST EFI_PEI_SERVICES **PeiServices,
179 IN EFI_MEMORY_TYPE MemoryType,
180 IN UINTN Pages,
181 OUT EFI_PHYSICAL_ADDRESS *Memory
182 )
183 /*++
184
185 Routine Description:
186
187 Memory allocation service on permanent memory,
188 not usable prior to the memory installation.
189
190 Arguments:
191
192 PeiServices - The PEI core services table.
193 MemoryType - Type of memory to allocate.
194 Pages - Number of pages to allocate.
195 Memory - Pointer of memory allocated.
196
197 Returns:
198
199 Status - EFI_SUCCESS The allocation was successful
200 EFI_INVALID_PARAMETER Only AllocateAnyAddress is supported.
201 EFI_NOT_AVAILABLE_YET Called with permanent memory not available
202 EFI_OUT_OF_RESOURCES There is not enough HOB heap to satisfy the requirement
203 to allocate the number of pages.
204
205 --*/
206 {
207 PEI_CORE_INSTANCE *PrivateData;
208 EFI_PEI_HOB_POINTERS Hob;
209 EFI_PHYSICAL_ADDRESS Offset;
210
211 PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS (PeiServices);
212
213 //
214 // Check if Hob already available
215 //
216 if (!PrivateData->PeiMemoryInstalled) {
217 return EFI_NOT_AVAILABLE_YET;
218 }
219
220 Hob.Raw = PrivateData->HobList.Raw;
221
222 //
223 // Check to see if on 4k boundary
224 //
225 Offset = Hob.HandoffInformationTable->EfiFreeMemoryTop & 0xFFF;
226
227 //
228 // If not aligned, make the allocation aligned.
229 //
230 if (Offset != 0) {
231 Hob.HandoffInformationTable->EfiFreeMemoryTop -= Offset;
232 }
233
234 ASSERT (Hob.HandoffInformationTable->EfiFreeMemoryTop >= Hob.HandoffInformationTable->EfiFreeMemoryBottom);
235 //
236 // Verify that there is sufficient memory to satisfy the allocation
237 //
238 if (Hob.HandoffInformationTable->EfiFreeMemoryTop - ((Pages * EFI_PAGE_SIZE) + sizeof (EFI_HOB_MEMORY_ALLOCATION)) <
239 Hob.HandoffInformationTable->EfiFreeMemoryBottom) {
240 DEBUG ((EFI_D_ERROR, "AllocatePages failed: No 0x%x Pages is available.\n", Pages));
241 DEBUG ((EFI_D_ERROR, "There is only left 0x%x pages memory resource to be allocated.\n", \
242 EFI_SIZE_TO_PAGES ((UINTN) (Hob.HandoffInformationTable->EfiFreeMemoryTop - Hob.HandoffInformationTable->EfiFreeMemoryBottom))));
243 return EFI_OUT_OF_RESOURCES;
244 } else {
245 //
246 // Update the PHIT to reflect the memory usage
247 //
248 Hob.HandoffInformationTable->EfiFreeMemoryTop -= Pages * EFI_PAGE_SIZE;
249
250 //
251 // Update the value for the caller
252 //
253 *Memory = Hob.HandoffInformationTable->EfiFreeMemoryTop;
254
255 //
256 // Create a memory allocation HOB.
257 //
258 BuildMemoryAllocationHob (
259 Hob.HandoffInformationTable->EfiFreeMemoryTop,
260 Pages * EFI_PAGE_SIZE,
261 MemoryType
262 );
263
264 return EFI_SUCCESS;
265 }
266 }
267
268
269 EFI_STATUS
270 EFIAPI
271 PeiAllocatePool (
272 IN CONST EFI_PEI_SERVICES **PeiServices,
273 IN UINTN Size,
274 OUT VOID **Buffer
275 )
276 /*++
277
278 Routine Description:
279
280 Memory allocation service on the CAR.
281
282 Arguments:
283
284 PeiServices - The PEI core services table.
285
286 Size - Amount of memory required
287
288 Buffer - Address of pointer to the buffer
289
290 Returns:
291
292 Status - EFI_SUCCESS The allocation was successful
293 EFI_OUT_OF_RESOURCES There is not enough heap to satisfy the requirement
294 to allocate the requested size.
295
296 --*/
297 {
298 EFI_STATUS Status;
299 EFI_HOB_MEMORY_POOL *Hob;
300
301 //
302 // If some "post-memory" PEIM wishes to allocate larger pool,
303 // it should use AllocatePages service instead.
304 //
305 ASSERT (Size < 0x10000 - sizeof (EFI_HOB_MEMORY_POOL));
306 Status = PeiServicesCreateHob (
307 EFI_HOB_TYPE_MEMORY_POOL,
308 (UINT16)(sizeof (EFI_HOB_MEMORY_POOL) + Size),
309 (VOID **)&Hob
310 );
311 *Buffer = Hob+1;
312
313
314 return Status;
315 }