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