]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Core/Pei/Memory/MemoryServices.c
Make sure the base address of stack base and base address of hob start is in page...
[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 if (MemoryLength > (MAX_ADDRESS - MemoryBegin + 1))
119 return EFI_INVALID_PARAMETER;
120
121
122 DEBUG ((EFI_D_INFO, "PeiInstallPeiMemory MemoryBegin 0x%LX, MemoryLength 0x%LX\n", MemoryBegin, MemoryLength));
123
124 PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS (PeiServices);
125
126 PrivateData->SwitchStackSignal = TRUE;
127 PrivateData->PeiMemoryInstalled = TRUE;
128
129 //
130 // Ensure the stack base is in page alignment
131 //
132 PrivateData->StackBase = ((UINTN)MemoryBegin + (EFI_PAGE_SIZE - 1)) & EFI_PAGE_SIZE;
133
134 PeiStackSize = (RShiftU64 (MemoryLength, 1) + (EFI_PAGE_SIZE - 1)) & EFI_PAGE_SIZE;
135 if (PEI_STACK_SIZE > PeiStackSize) {
136 PrivateData->StackSize = PeiStackSize;
137 } else {
138 PrivateData->StackSize = PEI_STACK_SIZE;
139 }
140
141 OldHandOffHob = PrivateData->HobList.HandoffInformationTable;
142
143 PrivateData->HobList.Raw = (VOID *)((UINTN)(PrivateData->StackBase + PrivateData->StackSize));
144 NewHandOffHob = PrivateData->HobList.HandoffInformationTable;
145 PhysicalAddressOfOldHob = (EFI_PHYSICAL_ADDRESS) (UINTN) OldHandOffHob;
146
147 EfiFreeMemorySize = OldHandOffHob->EfiFreeMemoryBottom - PhysicalAddressOfOldHob;
148
149 DEBUG ((EFI_D_INFO, "HOBLIST address before memory init = 0x%p\n", OldHandOffHob));
150 DEBUG ((EFI_D_INFO, "HOBLIST address after memory init = 0x%p\n", NewHandOffHob));
151
152 CopyMem (
153 NewHandOffHob,
154 OldHandOffHob,
155 (UINTN)EfiFreeMemorySize
156 );
157
158 NewHandOffHob->EfiMemoryTop = MemoryBegin + MemoryLength;
159 NewHandOffHob->EfiFreeMemoryTop = NewHandOffHob->EfiMemoryTop;
160 NewHandOffHob->EfiMemoryBottom = MemoryBegin;
161
162 NewHandOffHob->EfiFreeMemoryBottom = (UINTN)NewHandOffHob + EfiFreeMemorySize;
163
164 NewHandOffHob->EfiEndOfHobList = (UINTN)NewHandOffHob +
165 (OldHandOffHob->EfiEndOfHobList -
166 PhysicalAddressOfOldHob);
167
168 //
169 // For IPF in CAR mode the real memory access is uncached,in InstallPeiMemory()
170 // the 63-bit of address is set to 1.
171 //
172 SWITCH_TO_CACHE_MODE (PrivateData);
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 CONST 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 ASSERT (Hob.HandoffInformationTable->EfiFreeMemoryTop >= Hob.HandoffInformationTable->EfiFreeMemoryBottom);
242 //
243 // Verify that there is sufficient memory to satisfy the allocation
244 //
245 if (Hob.HandoffInformationTable->EfiFreeMemoryTop - ((Pages * EFI_PAGE_SIZE) + sizeof (EFI_HOB_MEMORY_ALLOCATION)) <
246 Hob.HandoffInformationTable->EfiFreeMemoryBottom) {
247 DEBUG ((EFI_D_ERROR, "AllocatePages failed: No 0x%x Pages is available.\n", Pages));
248 DEBUG ((EFI_D_ERROR, "There is only left 0x%x pages memory resource to be allocated.\n", \
249 EFI_SIZE_TO_PAGES ((UINTN) (Hob.HandoffInformationTable->EfiFreeMemoryTop - Hob.HandoffInformationTable->EfiFreeMemoryBottom))));
250 return EFI_OUT_OF_RESOURCES;
251 } else {
252 //
253 // Update the PHIT to reflect the memory usage
254 //
255 Hob.HandoffInformationTable->EfiFreeMemoryTop -= Pages * EFI_PAGE_SIZE;
256
257 //
258 // Update the value for the caller
259 //
260 *Memory = Hob.HandoffInformationTable->EfiFreeMemoryTop;
261
262 //
263 // Create a memory allocation HOB.
264 //
265 BuildMemoryAllocationHob (
266 Hob.HandoffInformationTable->EfiFreeMemoryTop,
267 Pages * EFI_PAGE_SIZE,
268 MemoryType
269 );
270
271 return EFI_SUCCESS;
272 }
273 }
274
275
276 EFI_STATUS
277 EFIAPI
278 PeiAllocatePool (
279 IN CONST EFI_PEI_SERVICES **PeiServices,
280 IN UINTN Size,
281 OUT VOID **Buffer
282 )
283 /*++
284
285 Routine Description:
286
287 Memory allocation service on the CAR.
288
289 Arguments:
290
291 PeiServices - The PEI core services table.
292
293 Size - Amount of memory required
294
295 Buffer - Address of pointer to the buffer
296
297 Returns:
298
299 Status - EFI_SUCCESS The allocation was successful
300 EFI_OUT_OF_RESOURCES There is not enough heap to satisfy the requirement
301 to allocate the requested size.
302
303 --*/
304 {
305 EFI_STATUS Status;
306 EFI_HOB_MEMORY_POOL *Hob;
307
308 //
309 // If some "post-memory" PEIM wishes to allocate larger pool,
310 // it should use AllocatePages service instead.
311 //
312 ASSERT (Size < 0x10000 - sizeof (EFI_HOB_MEMORY_POOL));
313 Status = PeiServicesCreateHob (
314 EFI_HOB_TYPE_MEMORY_POOL,
315 (UINT16)(sizeof (EFI_HOB_MEMORY_POOL) + Size),
316 (VOID **)&Hob
317 );
318 *Buffer = Hob+1;
319
320
321 return Status;
322 }