2 Responsibility of this file is to load the DXE Core from a Firmware Volume.
4 Copyright (c) 2016 HP Development Company, L.P.
5 Copyright (c) 2006 - 2020, Intel Corporation. All rights reserved.<BR>
6 SPDX-License-Identifier: BSD-2-Clause-Patent
10 #include "PeilessStartupInternal.h"
11 #include <Library/DebugLib.h>
12 #include <Library/BaseLib.h>
13 #include <Library/BaseMemoryLib.h>
14 #include <Library/MemoryAllocationLib.h>
15 #include <Library/PcdLib.h>
16 #include <Guid/MemoryTypeInformation.h>
17 #include <Guid/MemoryAllocationHob.h>
18 #include <Guid/PcdDataBaseSignatureGuid.h>
19 #include <Register/Intel/Cpuid.h>
20 #include <Library/PrePiLib.h>
21 #include "X64/PageTables.h"
22 #include <Library/ReportStatusCodeLib.h>
24 #define STACK_SIZE 0x20000
27 Transfers control to DxeCore.
29 This function performs a CPU architecture specific operations to execute
30 the entry point of DxeCore
32 @param DxeCoreEntryPoint The entry point of DxeCore.
37 IN EFI_PHYSICAL_ADDRESS DxeCoreEntryPoint
45 // Clear page 0 and mark it as allocated if NULL pointer detection is enabled.
47 if (IsNullDetectionEnabled ()) {
48 ClearFirst4KPage (GetHobList ());
49 BuildMemoryAllocationHob (0, EFI_PAGES_TO_SIZE (1), EfiBootServicesData
);
53 // Allocate 128KB for the Stack
55 BaseOfStack
= AllocatePages (EFI_SIZE_TO_PAGES (STACK_SIZE
));
56 ASSERT (BaseOfStack
!= NULL
);
59 // Compute the top of the stack we were allocated. Pre-allocate a UINTN
62 TopOfStack
= (VOID
*)((UINTN
)BaseOfStack
+ EFI_SIZE_TO_PAGES (STACK_SIZE
) * EFI_PAGE_SIZE
- CPU_STACK_ALIGNMENT
);
63 TopOfStack
= ALIGN_POINTER (TopOfStack
, CPU_STACK_ALIGNMENT
);
65 DEBUG ((DEBUG_INFO
, "BaseOfStack=0x%x, TopOfStack=0x%x\n", BaseOfStack
, TopOfStack
));
68 // Create page table and save PageMapLevel4 to CR3
70 PageTables
= CreateIdentityMappingPageTables (
71 (EFI_PHYSICAL_ADDRESS
)(UINTN
)BaseOfStack
,
74 if (PageTables
== 0) {
75 DEBUG ((DEBUG_ERROR
, "Failed to create idnetity mapping page tables.\n"));
79 AsmWriteCr3 (PageTables
);
82 // Update the contents of BSP stack HOB to reflect the real stack info passed to DxeCore.
84 UpdateStackHob ((EFI_PHYSICAL_ADDRESS
)(UINTN
)BaseOfStack
, STACK_SIZE
);
86 DEBUG ((DEBUG_INFO
, "SwitchStack then Jump to DxeCore\n"));
88 // Transfer the control to the entry point of DxeCore.
91 (SWITCH_STACK_ENTRY_POINT
)(UINTN
)DxeCoreEntryPoint
,
99 Searches DxeCore in all firmware Volumes and loads the first
100 instance that contains DxeCore.
102 @return FileHandle of DxeCore to load DxeCore.
108 IN OUT EFI_PEI_FILE_HANDLE
*FileHandle
112 EFI_PEI_FV_HANDLE VolumeHandle
;
114 if (FileHandle
== NULL
) {
116 return EFI_INVALID_PARAMETER
;
122 // Caller passed in a specific FV to try, so only try that one
124 Status
= FfsFindNextVolume (FvInstance
, &VolumeHandle
);
125 if (!EFI_ERROR (Status
)) {
126 Status
= FfsFindNextFile (EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE
, VolumeHandle
, FileHandle
);
128 // Assume the FV that contains multiple compressed FVs.
129 // So decompress the compressed FVs
130 Status
= FfsProcessFvFile (*FileHandle
);
131 ASSERT_EFI_ERROR (Status
);
132 Status
= FfsAnyFvFindFirstFile (EFI_FV_FILETYPE_DXE_CORE
, &VolumeHandle
, FileHandle
);
140 This function finds DXE Core in the firmware volume and transfer the control to
143 @return EFI_SUCCESS DXE core was successfully loaded.
144 @return EFI_OUT_OF_RESOURCES There are not enough resources to load DXE core.
154 EFI_FV_FILE_INFO DxeCoreFileInfo
;
155 EFI_PHYSICAL_ADDRESS DxeCoreAddress
;
157 EFI_PHYSICAL_ADDRESS DxeCoreEntryPoint
;
158 EFI_PEI_FILE_HANDLE FileHandle
;
162 // Look in all the FVs present and find the DXE Core FileHandle
164 Status
= FindDxeCore (FvInstance
, &FileHandle
);
166 if (EFI_ERROR (Status
)) {
172 // Load the DXE Core from a Firmware Volume.
174 Status
= FfsFindSectionData (EFI_SECTION_PE32
, FileHandle
, &PeCoffImage
);
175 if (EFI_ERROR (Status
)) {
179 Status
= LoadPeCoffImage (PeCoffImage
, &DxeCoreAddress
, &DxeCoreSize
, &DxeCoreEntryPoint
);
180 ASSERT_EFI_ERROR (Status
);
183 // Extract the DxeCore GUID file name.
185 Status
= FfsGetFileInfo (FileHandle
, &DxeCoreFileInfo
);
186 ASSERT_EFI_ERROR (Status
);
189 // Add HOB for the DXE Core
192 &DxeCoreFileInfo
.FileName
,
194 ALIGN_VALUE (DxeCoreSize
, EFI_PAGE_SIZE
),
199 DEBUG_INFO
| DEBUG_LOAD
,
200 "Loading DXE CORE at 0x%11p EntryPoint=0x%11p\n",
201 (VOID
*)(UINTN
)DxeCoreAddress
,
202 FUNCTION_ENTRY_POINT (DxeCoreEntryPoint
)
205 // Transfer control to the DXE Core
206 // The hand off state is simply a pointer to the HOB list
208 HandOffToDxeCore (DxeCoreEntryPoint
);
211 // If we get here, then the DXE Core returned. This is an error
212 // DxeCore should not return.
217 return EFI_OUT_OF_RESOURCES
;