]> git.proxmox.com Git - mirror_edk2.git/blame - OvmfPkg/Library/PeilessStartupLib/DxeLoad.c
OvmfPkg/IntelTdx: Enable separate-fv in IntelTdx/IntelTdxX64.fdf
[mirror_edk2.git] / OvmfPkg / Library / PeilessStartupLib / DxeLoad.c
CommitLineData
4fe26784
MX
1/** @file\r
2 Responsibility of this file is to load the DXE Core from a Firmware Volume.\r
3\r
4Copyright (c) 2016 HP Development Company, L.P.\r
5Copyright (c) 2006 - 2020, Intel Corporation. All rights reserved.<BR>\r
6SPDX-License-Identifier: BSD-2-Clause-Patent\r
7\r
8**/\r
9\r
10#include "PeilessStartupInternal.h"\r
11#include <Library/DebugLib.h>\r
12#include <Library/BaseLib.h>\r
13#include <Library/BaseMemoryLib.h>\r
14#include <Library/MemoryAllocationLib.h>\r
15#include <Library/PcdLib.h>\r
16#include <Guid/MemoryTypeInformation.h>\r
17#include <Guid/MemoryAllocationHob.h>\r
18#include <Guid/PcdDataBaseSignatureGuid.h>\r
19#include <Register/Intel/Cpuid.h>\r
20#include <Library/PrePiLib.h>\r
21#include "X64/PageTables.h"\r
22#include <Library/ReportStatusCodeLib.h>\r
23\r
24#define STACK_SIZE 0x20000\r
25\r
26/**\r
27 Transfers control to DxeCore.\r
28\r
29 This function performs a CPU architecture specific operations to execute\r
30 the entry point of DxeCore\r
31\r
32 @param DxeCoreEntryPoint The entry point of DxeCore.\r
33\r
34**/\r
35VOID\r
36HandOffToDxeCore (\r
37 IN EFI_PHYSICAL_ADDRESS DxeCoreEntryPoint\r
38 )\r
39{\r
40 VOID *BaseOfStack;\r
41 VOID *TopOfStack;\r
42 UINTN PageTables;\r
43\r
44 //\r
45 // Clear page 0 and mark it as allocated if NULL pointer detection is enabled.\r
46 //\r
47 if (IsNullDetectionEnabled ()) {\r
48 ClearFirst4KPage (GetHobList ());\r
49 BuildMemoryAllocationHob (0, EFI_PAGES_TO_SIZE (1), EfiBootServicesData);\r
50 }\r
51\r
52 //\r
53 // Allocate 128KB for the Stack\r
54 //\r
55 BaseOfStack = AllocatePages (EFI_SIZE_TO_PAGES (STACK_SIZE));\r
56 ASSERT (BaseOfStack != NULL);\r
57\r
58 //\r
59 // Compute the top of the stack we were allocated. Pre-allocate a UINTN\r
60 // for safety.\r
61 //\r
62 TopOfStack = (VOID *)((UINTN)BaseOfStack + EFI_SIZE_TO_PAGES (STACK_SIZE) * EFI_PAGE_SIZE - CPU_STACK_ALIGNMENT);\r
63 TopOfStack = ALIGN_POINTER (TopOfStack, CPU_STACK_ALIGNMENT);\r
64\r
65 DEBUG ((DEBUG_INFO, "BaseOfStack=0x%x, TopOfStack=0x%x\n", BaseOfStack, TopOfStack));\r
66\r
67 //\r
68 // Create page table and save PageMapLevel4 to CR3\r
69 //\r
70 PageTables = CreateIdentityMappingPageTables (\r
71 (EFI_PHYSICAL_ADDRESS)(UINTN)BaseOfStack,\r
72 STACK_SIZE\r
73 );\r
74 if (PageTables == 0) {\r
75 DEBUG ((DEBUG_ERROR, "Failed to create idnetity mapping page tables.\n"));\r
76 CpuDeadLoop ();\r
77 }\r
78\r
79 AsmWriteCr3 (PageTables);\r
80\r
81 //\r
82 // Update the contents of BSP stack HOB to reflect the real stack info passed to DxeCore.\r
83 //\r
84 UpdateStackHob ((EFI_PHYSICAL_ADDRESS)(UINTN)BaseOfStack, STACK_SIZE);\r
85\r
86 DEBUG ((DEBUG_INFO, "SwitchStack then Jump to DxeCore\n"));\r
87 //\r
88 // Transfer the control to the entry point of DxeCore.\r
89 //\r
90 SwitchStack (\r
91 (SWITCH_STACK_ENTRY_POINT)(UINTN)DxeCoreEntryPoint,\r
92 GetHobList (),\r
93 NULL,\r
94 TopOfStack\r
95 );\r
96}\r
97\r
98/**\r
99 Searches DxeCore in all firmware Volumes and loads the first\r
100 instance that contains DxeCore.\r
101\r
102 @return FileHandle of DxeCore to load DxeCore.\r
103\r
104**/\r
105EFI_STATUS\r
106FindDxeCore (\r
107 IN INTN FvInstance,\r
108 IN OUT EFI_PEI_FILE_HANDLE *FileHandle\r
109 )\r
110{\r
111 EFI_STATUS Status;\r
112 EFI_PEI_FV_HANDLE VolumeHandle;\r
113\r
114 if (FileHandle == NULL) {\r
115 ASSERT (FALSE);\r
116 return EFI_INVALID_PARAMETER;\r
117 }\r
118\r
119 *FileHandle = NULL;\r
120\r
121 //\r
122 // Caller passed in a specific FV to try, so only try that one\r
123 //\r
124 Status = FfsFindNextVolume (FvInstance, &VolumeHandle);\r
125 if (!EFI_ERROR (Status)) {\r
126 Status = FfsFindNextFile (EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE, VolumeHandle, FileHandle);\r
127 if (*FileHandle) {\r
128 // Assume the FV that contains multiple compressed FVs.\r
129 // So decompress the compressed FVs\r
130 Status = FfsProcessFvFile (*FileHandle);\r
131 ASSERT_EFI_ERROR (Status);\r
132 Status = FfsAnyFvFindFirstFile (EFI_FV_FILETYPE_DXE_CORE, &VolumeHandle, FileHandle);\r
133 }\r
134 }\r
135\r
136 return Status;\r
137}\r
138\r
139/**\r
140 This function finds DXE Core in the firmware volume and transfer the control to\r
141 DXE core.\r
142\r
143 @return EFI_SUCCESS DXE core was successfully loaded.\r
144 @return EFI_OUT_OF_RESOURCES There are not enough resources to load DXE core.\r
145\r
146**/\r
147EFI_STATUS\r
148EFIAPI\r
149DxeLoadCore (\r
150 IN INTN FvInstance\r
151 )\r
152{\r
153 EFI_STATUS Status;\r
154 EFI_FV_FILE_INFO DxeCoreFileInfo;\r
155 EFI_PHYSICAL_ADDRESS DxeCoreAddress;\r
156 UINT64 DxeCoreSize;\r
157 EFI_PHYSICAL_ADDRESS DxeCoreEntryPoint;\r
158 EFI_PEI_FILE_HANDLE FileHandle;\r
159 VOID *PeCoffImage;\r
160\r
161 //\r
162 // Look in all the FVs present and find the DXE Core FileHandle\r
163 //\r
164 Status = FindDxeCore (FvInstance, &FileHandle);\r
165\r
166 if (EFI_ERROR (Status)) {\r
167 ASSERT (FALSE);\r
168 return Status;\r
169 }\r
170\r
171 //\r
172 // Load the DXE Core from a Firmware Volume.\r
173 //\r
174 Status = FfsFindSectionData (EFI_SECTION_PE32, FileHandle, &PeCoffImage);\r
175 if (EFI_ERROR (Status)) {\r
176 return Status;\r
177 }\r
178\r
179 Status = LoadPeCoffImage (PeCoffImage, &DxeCoreAddress, &DxeCoreSize, &DxeCoreEntryPoint);\r
180 ASSERT_EFI_ERROR (Status);\r
181\r
182 //\r
183 // Extract the DxeCore GUID file name.\r
184 //\r
185 Status = FfsGetFileInfo (FileHandle, &DxeCoreFileInfo);\r
186 ASSERT_EFI_ERROR (Status);\r
187\r
188 //\r
189 // Add HOB for the DXE Core\r
190 //\r
191 BuildModuleHob (\r
192 &DxeCoreFileInfo.FileName,\r
193 DxeCoreAddress,\r
194 ALIGN_VALUE (DxeCoreSize, EFI_PAGE_SIZE),\r
195 DxeCoreEntryPoint\r
196 );\r
197\r
198 DEBUG ((\r
199 DEBUG_INFO | DEBUG_LOAD,\r
200 "Loading DXE CORE at 0x%11p EntryPoint=0x%11p\n",\r
201 (VOID *)(UINTN)DxeCoreAddress,\r
202 FUNCTION_ENTRY_POINT (DxeCoreEntryPoint)\r
203 ));\r
204\r
205 // Transfer control to the DXE Core\r
206 // The hand off state is simply a pointer to the HOB list\r
207 //\r
208 HandOffToDxeCore (DxeCoreEntryPoint);\r
209\r
210 //\r
211 // If we get here, then the DXE Core returned. This is an error\r
212 // DxeCore should not return.\r
213 //\r
214 ASSERT (FALSE);\r
215 CpuDeadLoop ();\r
216\r
217 return EFI_OUT_OF_RESOURCES;\r
218}\r