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