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