1 /** @file
2   x64-specifc functionality for DxeLoad.
3 
4 Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
5 SPDX-License-Identifier: BSD-2-Clause-Patent
6 
7 **/
8 
9 #include "DxeIpl.h"
10 #include "X64/VirtualMemory.h"
11 
12 
13 
14 /**
15    Transfers control to DxeCore.
16 
17    This function performs a CPU architecture specific operations to execute
18    the entry point of DxeCore with the parameters of HobList.
19    It also installs EFI_END_OF_PEI_PPI to signal the end of PEI phase.
20 
21    @param DxeCoreEntryPoint         The entry point of DxeCore.
22    @param HobList                   The start of HobList passed to DxeCore.
23 
24 **/
25 VOID
HandOffToDxeCore(IN EFI_PHYSICAL_ADDRESS DxeCoreEntryPoint,IN EFI_PEI_HOB_POINTERS HobList)26 HandOffToDxeCore (
27   IN EFI_PHYSICAL_ADDRESS   DxeCoreEntryPoint,
28   IN EFI_PEI_HOB_POINTERS   HobList
29   )
30 {
31   VOID                            *BaseOfStack;
32   VOID                            *TopOfStack;
33   EFI_STATUS                      Status;
34   UINTN                           PageTables;
35   UINT32                          Index;
36   EFI_VECTOR_HANDOFF_INFO         *VectorInfo;
37   EFI_PEI_VECTOR_HANDOFF_INFO_PPI *VectorHandoffInfoPpi;
38   VOID                            *GhcbBase;
39   UINTN                           GhcbSize;
40 
41   //
42   // Clear page 0 and mark it as allocated if NULL pointer detection is enabled.
43   //
44   if (IsNullDetectionEnabled ()) {
45     ClearFirst4KPage (HobList.Raw);
46     BuildMemoryAllocationHob (0, EFI_PAGES_TO_SIZE (1), EfiBootServicesData);
47   }
48 
49   //
50   // Get Vector Hand-off Info PPI and build Guided HOB
51   //
52   Status = PeiServicesLocatePpi (
53              &gEfiVectorHandoffInfoPpiGuid,
54              0,
55              NULL,
56              (VOID **)&VectorHandoffInfoPpi
57              );
58   if (Status == EFI_SUCCESS) {
59     DEBUG ((EFI_D_INFO, "Vector Hand-off Info PPI is gotten, GUIDed HOB is created!\n"));
60     VectorInfo = VectorHandoffInfoPpi->Info;
61     Index = 1;
62     while (VectorInfo->Attribute != EFI_VECTOR_HANDOFF_LAST_ENTRY) {
63       VectorInfo ++;
64       Index ++;
65     }
66     BuildGuidDataHob (
67       &gEfiVectorHandoffInfoPpiGuid,
68       VectorHandoffInfoPpi->Info,
69       sizeof (EFI_VECTOR_HANDOFF_INFO) * Index
70       );
71   }
72 
73   //
74   // Allocate 128KB for the Stack
75   //
76   BaseOfStack = AllocatePages (EFI_SIZE_TO_PAGES (STACK_SIZE));
77   ASSERT (BaseOfStack != NULL);
78 
79   //
80   // Compute the top of the stack we were allocated. Pre-allocate a UINTN
81   // for safety.
82   //
83   TopOfStack = (VOID *) ((UINTN) BaseOfStack + EFI_SIZE_TO_PAGES (STACK_SIZE) * EFI_PAGE_SIZE - CPU_STACK_ALIGNMENT);
84   TopOfStack = ALIGN_POINTER (TopOfStack, CPU_STACK_ALIGNMENT);
85 
86   //
87   // Get the address and size of the GHCB pages
88   //
89   GhcbBase = (VOID *) PcdGet64 (PcdGhcbBase);
90   GhcbSize = PcdGet64 (PcdGhcbSize);
91 
92   PageTables = 0;
93   if (FeaturePcdGet (PcdDxeIplBuildPageTables)) {
94     //
95     // Create page table and save PageMapLevel4 to CR3
96     //
97     PageTables = CreateIdentityMappingPageTables ((EFI_PHYSICAL_ADDRESS) (UINTN) BaseOfStack, STACK_SIZE,
98                                                   (EFI_PHYSICAL_ADDRESS) (UINTN) GhcbBase, GhcbSize);
99   } else {
100     //
101     // Set NX for stack feature also require PcdDxeIplBuildPageTables be TRUE
102     // for the DxeIpl and the DxeCore are both X64.
103     //
104     ASSERT (PcdGetBool (PcdSetNxForStack) == FALSE);
105     ASSERT (PcdGetBool (PcdCpuStackGuard) == FALSE);
106   }
107 
108   //
109   // End of PEI phase signal
110   //
111   Status = PeiServicesInstallPpi (&gEndOfPeiSignalPpi);
112   ASSERT_EFI_ERROR (Status);
113 
114   if (FeaturePcdGet (PcdDxeIplBuildPageTables)) {
115     AsmWriteCr3 (PageTables);
116   }
117 
118   //
119   // Update the contents of BSP stack HOB to reflect the real stack info passed to DxeCore.
120   //
121   UpdateStackHob ((EFI_PHYSICAL_ADDRESS)(UINTN) BaseOfStack, STACK_SIZE);
122 
123   //
124   // Transfer the control to the entry point of DxeCore.
125   //
126   SwitchStack (
127     (SWITCH_STACK_ENTRY_POINT)(UINTN)DxeCoreEntryPoint,
128     HobList.Raw,
129     NULL,
130     TopOfStack
131     );
132 }
133