]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Core/Pei/Memory/MemoryServices.c
The BaseAddress and Length should be align PAGE according to PI specification for...
[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 PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS (PeiServices);
119
120 PrivateData->SwitchStackSignal = TRUE;
121 PrivateData->PeiMemoryInstalled = TRUE;
122
123 PrivateData->StackBase = MemoryBegin;
124
125 PeiStackSize = RShiftU64 (MemoryLength, 1);
126 if (PEI_STACK_SIZE > PeiStackSize) {
127 PrivateData->StackSize = PeiStackSize;
128 } else {
129 PrivateData->StackSize = PEI_STACK_SIZE;
130 }
131
132 OldHandOffHob = PrivateData->HobList.HandoffInformationTable;
133
134 PrivateData->HobList.Raw = (VOID *)((UINTN)(MemoryBegin + PrivateData->StackSize));
135 NewHandOffHob = PrivateData->HobList.HandoffInformationTable;
136 PhysicalAddressOfOldHob = (EFI_PHYSICAL_ADDRESS) (UINTN) OldHandOffHob;
137
138 EfiFreeMemorySize = OldHandOffHob->EfiFreeMemoryBottom - PhysicalAddressOfOldHob;
139
140 DEBUG ((EFI_D_INFO, "HOBLIST address before memory init = 0x%08x\n", OldHandOffHob));
141 DEBUG ((EFI_D_INFO, "HOBLIST address after memory init = 0x%08x\n", NewHandOffHob));
142
143 CopyMem (
144 NewHandOffHob,
145 OldHandOffHob,
146 (UINTN)EfiFreeMemorySize
147 );
148
149 NewHandOffHob->EfiMemoryTop = MemoryBegin + MemoryLength;
150 NewHandOffHob->EfiFreeMemoryTop = NewHandOffHob->EfiMemoryTop;
151 NewHandOffHob->EfiMemoryBottom = MemoryBegin;
152
153 NewHandOffHob->EfiFreeMemoryBottom = (UINTN)NewHandOffHob + EfiFreeMemorySize;
154
155 NewHandOffHob->EfiEndOfHobList = (UINTN)NewHandOffHob +
156 (OldHandOffHob->EfiEndOfHobList -
157 PhysicalAddressOfOldHob);
158
159 ConvertPpiPointers (PeiServices, OldHandOffHob, NewHandOffHob);
160
161 BuildStackHob (PrivateData->StackBase, PrivateData->StackSize);
162
163
164 return EFI_SUCCESS;
165 }
166
167 EFI_STATUS
168 EFIAPI
169 PeiAllocatePages (
170 IN CONST EFI_PEI_SERVICES **PeiServices,
171 IN EFI_MEMORY_TYPE MemoryType,
172 IN UINTN Pages,
173 OUT EFI_PHYSICAL_ADDRESS *Memory
174 )
175 /*++
176
177 Routine Description:
178
179 Memory allocation service on permanent memory,
180 not usable prior to the memory installation.
181
182 Arguments:
183
184 PeiServices - The PEI core services table.
185 MemoryType - Type of memory to allocate.
186 Pages - Number of pages to allocate.
187 Memory - Pointer of memory allocated.
188
189 Returns:
190
191 Status - EFI_SUCCESS The allocation was successful
192 EFI_INVALID_PARAMETER Only AllocateAnyAddress is supported.
193 EFI_NOT_AVAILABLE_YET Called with permanent memory not available
194 EFI_OUT_OF_RESOURCES There is not enough HOB heap to satisfy the requirement
195 to allocate the number of pages.
196
197 --*/
198 {
199 PEI_CORE_INSTANCE *PrivateData;
200 EFI_PEI_HOB_POINTERS Hob;
201 EFI_PHYSICAL_ADDRESS Offset;
202
203 PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS (PeiServices);
204
205 //
206 // Check if Hob already available
207 //
208 if (!PrivateData->PeiMemoryInstalled) {
209 return EFI_NOT_AVAILABLE_YET;
210 }
211
212 Hob.Raw = PrivateData->HobList.Raw;
213
214 //
215 // Check to see if on 4k boundary
216 //
217 Offset = Hob.HandoffInformationTable->EfiFreeMemoryTop & 0xFFF;
218
219 //
220 // If not aligned, make the allocation aligned.
221 //
222 if (Offset != 0) {
223 Hob.HandoffInformationTable->EfiFreeMemoryTop -= Offset;
224 }
225
226 //
227 // Verify that there is sufficient memory to satisfy the allocation
228 //
229 if (Hob.HandoffInformationTable->EfiFreeMemoryTop - ((Pages * EFI_PAGE_SIZE) + sizeof (EFI_HOB_MEMORY_ALLOCATION)) <
230 Hob.HandoffInformationTable->EfiFreeMemoryBottom) {
231 DEBUG ((EFI_D_ERROR, "AllocatePages failed: No 0x%x Pages is available.\n", Pages));
232 DEBUG ((EFI_D_ERROR, "There is only left 0x%x pages memory resource to be allocated.\n", \
233 EFI_SIZE_TO_PAGES ((UINTN) (Hob.HandoffInformationTable->EfiFreeMemoryTop - Hob.HandoffInformationTable->EfiFreeMemoryBottom))));
234 return EFI_OUT_OF_RESOURCES;
235 } else {
236 //
237 // Update the PHIT to reflect the memory usage
238 //
239 Hob.HandoffInformationTable->EfiFreeMemoryTop -= Pages * EFI_PAGE_SIZE;
240
241 //
242 // Update the value for the caller
243 //
244 *Memory = Hob.HandoffInformationTable->EfiFreeMemoryTop;
245
246 //
247 // Create a memory allocation HOB.
248 //
249 BuildMemoryAllocationHob (
250 Hob.HandoffInformationTable->EfiFreeMemoryTop,
251 Pages * EFI_PAGE_SIZE,
252 MemoryType
253 );
254
255 return EFI_SUCCESS;
256 }
257 }
258
259
260 EFI_STATUS
261 EFIAPI
262 PeiAllocatePool (
263 IN CONST EFI_PEI_SERVICES **PeiServices,
264 IN UINTN Size,
265 OUT VOID **Buffer
266 )
267 /*++
268
269 Routine Description:
270
271 Memory allocation service on the CAR.
272
273 Arguments:
274
275 PeiServices - The PEI core services table.
276
277 Size - Amount of memory required
278
279 Buffer - Address of pointer to the buffer
280
281 Returns:
282
283 Status - EFI_SUCCESS The allocation was successful
284 EFI_OUT_OF_RESOURCES There is not enough heap to satisfy the requirement
285 to allocate the requested size.
286
287 --*/
288 {
289 EFI_STATUS Status;
290 EFI_HOB_MEMORY_POOL *Hob;
291
292 //
293 // If some "post-memory" PEIM wishes to allocate larger pool,
294 // it should use AllocatePages service instead.
295 //
296 ASSERT (Size < 0x10000 - sizeof (EFI_HOB_MEMORY_POOL));
297 Status = PeiServicesCreateHob (
298 EFI_HOB_TYPE_MEMORY_POOL,
299 (UINT16)(sizeof (EFI_HOB_MEMORY_POOL) + Size),
300 (VOID **)&Hob
301 );
302 *Buffer = Hob+1;
303
304
305 return Status;
306 }