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