TianoCore EDK2 master
Loading...
Searching...
No Matches
SaveLongModeContext.c
Go to the documentation of this file.
1
10#include <Uefi.h>
11
12#include <Protocol/Capsule.h>
15
16#include <Guid/CapsuleVendor.h>
17#include <Guid/AcpiS3Context.h>
18
19#include <Library/DebugLib.h>
20#include <Library/PcdLib.h>
24#include <Library/BaseLib.h>
25#include <Library/UefiLib.h>
27
28//
29// 8 extra pages for PF handler.
30//
31#define EXTRA_PAGE_TABLE_PAGES 8
32
43VOID *
45 IN UINTN Size
46 )
47{
48 UINTN Pages;
50 EFI_STATUS Status;
51 VOID *Buffer;
52
53 Pages = EFI_SIZE_TO_PAGES (Size);
54 Address = 0xffffffff;
55
56 Status = gBS->AllocatePages (
59 Pages,
60 &Address
61 );
62 ASSERT_EFI_ERROR (Status);
63
64 Buffer = (VOID *)(UINTN)Address;
65 ZeroMem (Buffer, Size);
66
67 return Buffer;
68}
69
77VOID
78EFIAPI
80 IN EFI_EVENT Event,
81 IN VOID *Context
82 )
83{
84 EFI_STATUS Status;
85 EDKII_VARIABLE_LOCK_PROTOCOL *VariableLock;
86
87 //
88 // Mark EFI_CAPSULE_LONG_MODE_BUFFER_NAME variable to read-only if the Variable Lock protocol exists
89 //
90 Status = gBS->LocateProtocol (&gEdkiiVariableLockProtocolGuid, NULL, (VOID **)&VariableLock);
91 if (!EFI_ERROR (Status)) {
92 Status = VariableLock->RequestToLock (VariableLock, EFI_CAPSULE_LONG_MODE_BUFFER_NAME, &gEfiCapsuleVendorGuid);
93 ASSERT_EFI_ERROR (Status);
94 }
95}
96
102VOID
103EFIAPI
105 VOID
106 )
107{
108 UINTN ExtraPageTablePages;
109 UINT32 RegEax;
110 UINT32 RegEdx;
111 UINTN TotalPagesNum;
112 UINT8 PhysicalAddressBits;
113 UINT32 NumberOfPml4EntriesNeeded;
114 UINT32 NumberOfPdpEntriesNeeded;
115 BOOLEAN Page1GSupport;
116 EFI_CAPSULE_LONG_MODE_BUFFER LongModeBuffer;
117 EFI_STATUS Status;
118 VOID *Registration;
119
120 //
121 // Calculate the size of page table, allocate the memory.
122 //
123 Page1GSupport = FALSE;
124 if (PcdGetBool (PcdUse1GPageTable)) {
125 AsmCpuid (0x80000000, &RegEax, NULL, NULL, NULL);
126 if (RegEax >= 0x80000001) {
127 AsmCpuid (0x80000001, NULL, NULL, NULL, &RegEdx);
128 if ((RegEdx & BIT26) != 0) {
129 Page1GSupport = TRUE;
130 }
131 }
132 }
133
134 //
135 // Create 4G page table by default,
136 // and let PF handler to handle > 4G request.
137 //
138 PhysicalAddressBits = 32;
139 ExtraPageTablePages = EXTRA_PAGE_TABLE_PAGES;
140
141 //
142 // Calculate the table entries needed.
143 //
144 if (PhysicalAddressBits <= 39 ) {
145 NumberOfPml4EntriesNeeded = 1;
146 NumberOfPdpEntriesNeeded = (UINT32)LShiftU64 (1, (PhysicalAddressBits - 30));
147 } else {
148 NumberOfPml4EntriesNeeded = (UINT32)LShiftU64 (1, (PhysicalAddressBits - 39));
149 NumberOfPdpEntriesNeeded = 512;
150 }
151
152 if (!Page1GSupport) {
153 TotalPagesNum = (NumberOfPdpEntriesNeeded + 1) * NumberOfPml4EntriesNeeded + 1;
154 } else {
155 TotalPagesNum = NumberOfPml4EntriesNeeded + 1;
156 }
157
158 TotalPagesNum += ExtraPageTablePages;
159 DEBUG ((DEBUG_INFO, "CapsuleRuntimeDxe X64 TotalPagesNum - 0x%x pages\n", TotalPagesNum));
160
161 LongModeBuffer.PageTableAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)AllocateReservedMemoryBelow4G (EFI_PAGES_TO_SIZE (TotalPagesNum));
162 ASSERT (LongModeBuffer.PageTableAddress != 0);
163
164 //
165 // Allocate stack
166 //
167 LongModeBuffer.StackSize = PcdGet32 (PcdCapsulePeiLongModeStackSize);
168 LongModeBuffer.StackBaseAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)AllocateReservedMemoryBelow4G (PcdGet32 (PcdCapsulePeiLongModeStackSize));
169 ASSERT (LongModeBuffer.StackBaseAddress != 0);
170
171 Status = gRT->SetVariable (
172 EFI_CAPSULE_LONG_MODE_BUFFER_NAME,
173 &gEfiCapsuleVendorGuid,
174 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,
176 &LongModeBuffer
177 );
178 if (!EFI_ERROR (Status)) {
179 //
180 // Register callback function upon VariableLockProtocol
181 // to lock EFI_CAPSULE_LONG_MODE_BUFFER_NAME variable to avoid malicious code to update it.
182 //
184 &gEdkiiVariableLockProtocolGuid,
185 TPL_CALLBACK,
187 NULL,
188 &Registration
189 );
190 } else {
191 DEBUG ((DEBUG_ERROR, "FATAL ERROR: CapsuleLongModeBuffer cannot be saved: %r. Capsule in PEI may fail!\n", Status));
192 gBS->FreePages (LongModeBuffer.StackBaseAddress, EFI_SIZE_TO_PAGES (LongModeBuffer.StackSize));
193 }
194}
195
200VOID
202 VOID
203 )
204{
205 if ((FeaturePcdGet (PcdSupportUpdateCapsuleReset)) && (FeaturePcdGet (PcdDxeIplSwitchToLongMode))) {
206 //
207 // Allocate memory for Capsule IA32 PEIM, it will create page table to transfer to long mode to access capsule above 4GB.
208 //
210 }
211}
UINT64 UINTN
UINT64 EFIAPI LShiftU64(IN UINT64 Operand, IN UINTN Count)
Definition: LShiftU64.c:28
VOID *EFIAPI ZeroMem(OUT VOID *Buffer, IN UINTN Length)
EFI_RUNTIME_SERVICES * gRT
#define NULL
Definition: Base.h:319
#define TRUE
Definition: Base.h:301
#define FALSE
Definition: Base.h:307
#define IN
Definition: Base.h:279
#define ASSERT_EFI_ERROR(StatusParameter)
Definition: DebugLib.h:462
#define DEBUG(Expression)
Definition: DebugLib.h:434
UINT32 EFIAPI AsmCpuid(IN UINT32 Index, OUT UINT32 *RegisterEax OPTIONAL, OUT UINT32 *RegisterEbx OPTIONAL, OUT UINT32 *RegisterEcx OPTIONAL, OUT UINT32 *RegisterEdx OPTIONAL)
Definition: CpuId.c:36
#define PcdGet32(TokenName)
Definition: PcdLib.h:362
#define PcdGetBool(TokenName)
Definition: PcdLib.h:401
#define FeaturePcdGet(TokenName)
Definition: PcdLib.h:50
VOID SaveLongModeContext(VOID)
UINT64 EFI_PHYSICAL_ADDRESS
Definition: UefiBaseType.h:50
#define EFI_PAGES_TO_SIZE(Pages)
Definition: UefiBaseType.h:213
RETURN_STATUS EFI_STATUS
Definition: UefiBaseType.h:29
VOID * EFI_EVENT
Definition: UefiBaseType.h:37
#define EFI_SIZE_TO_PAGES(Size)
Definition: UefiBaseType.h:200
EFI_BOOT_SERVICES * gBS
EFI_EVENT EFIAPI EfiCreateProtocolNotifyEvent(IN EFI_GUID *ProtocolGuid, IN EFI_TPL NotifyTpl, IN EFI_EVENT_NOTIFY NotifyFunction, IN VOID *NotifyContext OPTIONAL, OUT VOID **Registration)
Definition: UefiLib.c:134
@ EfiReservedMemoryType
#define EFI_VARIABLE_NON_VOLATILE
@ AllocateMaxAddress
Definition: UefiSpec.h:38
VOID * AllocateReservedMemoryBelow4G(IN UINTN Size)
VOID EFIAPI VariableLockCapsuleLongModeBufferVariable(IN EFI_EVENT Event, IN VOID *Context)
VOID EFIAPI PrepareContextForCapsulePei(VOID)