1 | /** @file
|
---|
2 | This is the code for Boot Script Executer module.
|
---|
3 |
|
---|
4 | This driver is dispatched by Dxe core and the driver will reload itself to ACPI reserved memory
|
---|
5 | in the entry point. The functionality is to interpret and restore the S3 boot script
|
---|
6 |
|
---|
7 | Copyright (c) 2006 - 2022, Intel Corporation. All rights reserved.<BR>
|
---|
8 | Copyright (c) 2017, AMD Incorporated. All rights reserved.<BR>
|
---|
9 |
|
---|
10 | SPDX-License-Identifier: BSD-2-Clause-Patent
|
---|
11 |
|
---|
12 | **/
|
---|
13 |
|
---|
14 | #include "ScriptExecute.h"
|
---|
15 |
|
---|
16 | EFI_GUID mBootScriptExecutorImageGuid = {
|
---|
17 | 0x9a8d3433, 0x9fe8, 0x42b6, { 0x87, 0xb, 0x1e, 0x31, 0xc8, 0x4e, 0xbe, 0x3b }
|
---|
18 | };
|
---|
19 |
|
---|
20 | BOOLEAN mPage1GSupport = FALSE;
|
---|
21 | UINT64 mAddressEncMask = 0;
|
---|
22 |
|
---|
23 | /**
|
---|
24 | Entry function of Boot script exector. This function will be executed in
|
---|
25 | S3 boot path.
|
---|
26 | This function should not return, because it is invoked by switch stack.
|
---|
27 |
|
---|
28 | @param AcpiS3Context a pointer to a structure of ACPI_S3_CONTEXT
|
---|
29 | @param PeiS3ResumeState a pointer to a structure of PEI_S3_RESUME_STATE
|
---|
30 |
|
---|
31 | @retval EFI_INVALID_PARAMETER - OS waking vector not found
|
---|
32 | @retval EFI_UNSUPPORTED - something wrong when we resume to OS
|
---|
33 | **/
|
---|
34 | EFI_STATUS
|
---|
35 | EFIAPI
|
---|
36 | S3BootScriptExecutorEntryFunction (
|
---|
37 | IN ACPI_S3_CONTEXT *AcpiS3Context,
|
---|
38 | IN PEI_S3_RESUME_STATE *PeiS3ResumeState
|
---|
39 | )
|
---|
40 | {
|
---|
41 | EFI_ACPI_4_0_FIRMWARE_ACPI_CONTROL_STRUCTURE *Facs;
|
---|
42 | EFI_STATUS Status;
|
---|
43 | UINTN TempStackTop;
|
---|
44 | UINTN TempStack[0x10];
|
---|
45 | UINTN AsmTransferControl16Address;
|
---|
46 | IA32_DESCRIPTOR IdtDescriptor;
|
---|
47 |
|
---|
48 | //
|
---|
49 | // Disable interrupt of Debug timer, since new IDT table cannot handle it.
|
---|
50 | //
|
---|
51 | SaveAndSetDebugTimerInterrupt (FALSE);
|
---|
52 |
|
---|
53 | AsmReadIdtr (&IdtDescriptor);
|
---|
54 | //
|
---|
55 | // Restore IDT for debug
|
---|
56 | //
|
---|
57 | SetIdtEntry (AcpiS3Context);
|
---|
58 |
|
---|
59 | //
|
---|
60 | // Initialize Debug Agent to support source level debug in S3 path, it will disable interrupt and Debug Timer.
|
---|
61 | //
|
---|
62 | InitializeDebugAgent (DEBUG_AGENT_INIT_S3, (VOID *)&IdtDescriptor, NULL);
|
---|
63 |
|
---|
64 | //
|
---|
65 | // Because not install BootScriptExecute PPI(used just in this module), So just pass NULL
|
---|
66 | // for that parameter.
|
---|
67 | //
|
---|
68 | Status = S3BootScriptExecute ();
|
---|
69 |
|
---|
70 | //
|
---|
71 | // If invalid script table or opcode in S3 boot script table.
|
---|
72 | //
|
---|
73 | ASSERT_EFI_ERROR (Status);
|
---|
74 |
|
---|
75 | if (EFI_ERROR (Status)) {
|
---|
76 | CpuDeadLoop ();
|
---|
77 | return Status;
|
---|
78 | }
|
---|
79 |
|
---|
80 | AsmWbinvd ();
|
---|
81 |
|
---|
82 | //
|
---|
83 | // Get ACPI Table Address
|
---|
84 | //
|
---|
85 | Facs = (EFI_ACPI_4_0_FIRMWARE_ACPI_CONTROL_STRUCTURE *)((UINTN)(AcpiS3Context->AcpiFacsTable));
|
---|
86 |
|
---|
87 | //
|
---|
88 | // We need turn back to S3Resume - install boot script done ppi and report status code on S3resume.
|
---|
89 | //
|
---|
90 | if (PeiS3ResumeState != 0) {
|
---|
91 | //
|
---|
92 | // Need report status back to S3ResumePeim.
|
---|
93 | // If boot script execution is failed, S3ResumePeim wil report the error status code.
|
---|
94 | //
|
---|
95 | PeiS3ResumeState->ReturnStatus = (UINT64)(UINTN)Status;
|
---|
96 | if (FeaturePcdGet (PcdDxeIplSwitchToLongMode)) {
|
---|
97 | //
|
---|
98 | // X64 DXE to IA32 PEI S3 Resume
|
---|
99 | //
|
---|
100 | DEBUG ((DEBUG_INFO, "Call AsmDisablePaging64() to return to S3 Resume in PEI Phase\n"));
|
---|
101 | PeiS3ResumeState->AsmTransferControl = (EFI_PHYSICAL_ADDRESS)(UINTN)AsmTransferControl32;
|
---|
102 |
|
---|
103 | if ((Facs != NULL) &&
|
---|
104 | (Facs->Signature == EFI_ACPI_4_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_SIGNATURE) &&
|
---|
105 | (Facs->FirmwareWakingVector != 0))
|
---|
106 | {
|
---|
107 | //
|
---|
108 | // more step needed - because relative address is handled differently between X64 and IA32.
|
---|
109 | //
|
---|
110 | AsmTransferControl16Address = (UINTN)AsmTransferControl16;
|
---|
111 | AsmFixAddress16 = (UINT32)AsmTransferControl16Address;
|
---|
112 | AsmJmpAddr32 = (UINT32)((Facs->FirmwareWakingVector & 0xF) | ((Facs->FirmwareWakingVector & 0xFFFF0) << 12));
|
---|
113 | }
|
---|
114 |
|
---|
115 | AsmDisablePaging64 (
|
---|
116 | PeiS3ResumeState->ReturnCs,
|
---|
117 | (UINT32)PeiS3ResumeState->ReturnEntryPoint,
|
---|
118 | (UINT32)(UINTN)AcpiS3Context,
|
---|
119 | (UINT32)(UINTN)PeiS3ResumeState,
|
---|
120 | (UINT32)PeiS3ResumeState->ReturnStackPointer
|
---|
121 | );
|
---|
122 | } else {
|
---|
123 | //
|
---|
124 | // IA32 DXE to IA32 PEI S3 Resume / X64 DXE to X64 PEI S3 Resume
|
---|
125 | //
|
---|
126 | DEBUG ((DEBUG_INFO, "Call SwitchStack() to return to S3 Resume in PEI Phase\n"));
|
---|
127 | PeiS3ResumeState->AsmTransferControl = (EFI_PHYSICAL_ADDRESS)(UINTN)AsmTransferControl;
|
---|
128 |
|
---|
129 | SwitchStack (
|
---|
130 | (SWITCH_STACK_ENTRY_POINT)(UINTN)PeiS3ResumeState->ReturnEntryPoint,
|
---|
131 | (VOID *)(UINTN)AcpiS3Context,
|
---|
132 | (VOID *)(UINTN)PeiS3ResumeState,
|
---|
133 | (VOID *)(UINTN)PeiS3ResumeState->ReturnStackPointer
|
---|
134 | );
|
---|
135 | }
|
---|
136 |
|
---|
137 | //
|
---|
138 | // Never run to here
|
---|
139 | //
|
---|
140 | CpuDeadLoop ();
|
---|
141 | return EFI_UNSUPPORTED;
|
---|
142 | }
|
---|
143 |
|
---|
144 | //
|
---|
145 | // S3ResumePeim does not provide a way to jump back to itself, so resume to OS here directly
|
---|
146 | //
|
---|
147 | if (Facs->XFirmwareWakingVector != 0) {
|
---|
148 | //
|
---|
149 | // Switch to native waking vector
|
---|
150 | //
|
---|
151 | TempStackTop = (UINTN)&TempStack + sizeof (TempStack);
|
---|
152 | if ((Facs->Version == EFI_ACPI_4_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_VERSION) &&
|
---|
153 | ((Facs->Flags & EFI_ACPI_4_0_64BIT_WAKE_SUPPORTED_F) != 0) &&
|
---|
154 | ((Facs->OspmFlags & EFI_ACPI_4_0_OSPM_64BIT_WAKE__F) != 0))
|
---|
155 | {
|
---|
156 | //
|
---|
157 | // X64 long mode waking vector
|
---|
158 | //
|
---|
159 | DEBUG ((DEBUG_INFO, "Transfer from 64bit DXE to 64bit OS waking vector - %x\r\n", (UINTN)Facs->XFirmwareWakingVector));
|
---|
160 | if (sizeof (UINTN) == sizeof (UINT64)) {
|
---|
161 | //
|
---|
162 | // 64bit DXE calls to 64bit OS S3 waking vector
|
---|
163 | //
|
---|
164 | SwitchStack (
|
---|
165 | (SWITCH_STACK_ENTRY_POINT)(UINTN)Facs->XFirmwareWakingVector,
|
---|
166 | NULL,
|
---|
167 | NULL,
|
---|
168 | (VOID *)(UINTN)TempStackTop
|
---|
169 | );
|
---|
170 | } else {
|
---|
171 | // Unsupported for 32bit DXE, 64bit OS vector
|
---|
172 | DEBUG ((DEBUG_ERROR, "Unsupported for 32bit DXE transfer to 64bit OS waking vector!\r\n"));
|
---|
173 | ASSERT (FALSE);
|
---|
174 | }
|
---|
175 | } else {
|
---|
176 | //
|
---|
177 | // IA32 protected mode waking vector (Page disabled)
|
---|
178 | //
|
---|
179 | DEBUG ((DEBUG_INFO, "Transfer to 32bit OS waking vector - %x\r\n", (UINTN)Facs->XFirmwareWakingVector));
|
---|
180 | if (sizeof (UINTN) == sizeof (UINT64)) {
|
---|
181 | //
|
---|
182 | // 64bit DXE calls to 32bit OS S3 waking vector
|
---|
183 | //
|
---|
184 | AsmDisablePaging64 (
|
---|
185 | 0x10,
|
---|
186 | (UINT32)Facs->XFirmwareWakingVector,
|
---|
187 | 0,
|
---|
188 | 0,
|
---|
189 | (UINT32)TempStackTop
|
---|
190 | );
|
---|
191 | } else {
|
---|
192 | //
|
---|
193 | // 32bit DXE calls to 32bit OS S3 waking vector
|
---|
194 | //
|
---|
195 | SwitchStack (
|
---|
196 | (SWITCH_STACK_ENTRY_POINT)(UINTN)Facs->XFirmwareWakingVector,
|
---|
197 | NULL,
|
---|
198 | NULL,
|
---|
199 | (VOID *)(UINTN)TempStackTop
|
---|
200 | );
|
---|
201 | }
|
---|
202 | }
|
---|
203 | } else {
|
---|
204 | //
|
---|
205 | // 16bit Realmode waking vector
|
---|
206 | //
|
---|
207 | DEBUG ((DEBUG_INFO, "Transfer to 16bit OS waking vector - %x\r\n", (UINTN)Facs->FirmwareWakingVector));
|
---|
208 | AsmTransferControl (Facs->FirmwareWakingVector, 0x0);
|
---|
209 | }
|
---|
210 |
|
---|
211 | //
|
---|
212 | // Never run to here
|
---|
213 | //
|
---|
214 | CpuDeadLoop ();
|
---|
215 | return EFI_UNSUPPORTED;
|
---|
216 | }
|
---|
217 |
|
---|
218 | /**
|
---|
219 | Register image to memory profile.
|
---|
220 |
|
---|
221 | @param FileName File name of the image.
|
---|
222 | @param ImageBase Image base address.
|
---|
223 | @param ImageSize Image size.
|
---|
224 | @param FileType File type of the image.
|
---|
225 |
|
---|
226 | **/
|
---|
227 | VOID
|
---|
228 | RegisterMemoryProfileImage (
|
---|
229 | IN EFI_GUID *FileName,
|
---|
230 | IN PHYSICAL_ADDRESS ImageBase,
|
---|
231 | IN UINT64 ImageSize,
|
---|
232 | IN EFI_FV_FILETYPE FileType
|
---|
233 | )
|
---|
234 | {
|
---|
235 | EFI_STATUS Status;
|
---|
236 | EDKII_MEMORY_PROFILE_PROTOCOL *ProfileProtocol;
|
---|
237 | MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *FilePath;
|
---|
238 | UINT8 TempBuffer[sizeof (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH) + sizeof (EFI_DEVICE_PATH_PROTOCOL)];
|
---|
239 |
|
---|
240 | if ((PcdGet8 (PcdMemoryProfilePropertyMask) & BIT0) != 0) {
|
---|
241 | FilePath = (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *)TempBuffer;
|
---|
242 | Status = gBS->LocateProtocol (&gEdkiiMemoryProfileGuid, NULL, (VOID **)&ProfileProtocol);
|
---|
243 | if (!EFI_ERROR (Status)) {
|
---|
244 | EfiInitializeFwVolDevicepathNode (FilePath, FileName);
|
---|
245 | SetDevicePathEndNode (FilePath + 1);
|
---|
246 |
|
---|
247 | Status = ProfileProtocol->RegisterImage (
|
---|
248 | ProfileProtocol,
|
---|
249 | (EFI_DEVICE_PATH_PROTOCOL *)FilePath,
|
---|
250 | ImageBase,
|
---|
251 | ImageSize,
|
---|
252 | FileType
|
---|
253 | );
|
---|
254 | }
|
---|
255 | }
|
---|
256 | }
|
---|
257 |
|
---|
258 | /**
|
---|
259 | This is the Event notification function to reload BootScriptExecutor image
|
---|
260 | to RESERVED mem and save it to LockBox.
|
---|
261 |
|
---|
262 | @param Event Pointer to this event
|
---|
263 | @param Context Event handler private data
|
---|
264 | **/
|
---|
265 | VOID
|
---|
266 | EFIAPI
|
---|
267 | ReadyToLockEventNotify (
|
---|
268 | IN EFI_EVENT Event,
|
---|
269 | IN VOID *Context
|
---|
270 | )
|
---|
271 | {
|
---|
272 | EFI_STATUS Status;
|
---|
273 | VOID *Interface;
|
---|
274 | UINT8 *Buffer;
|
---|
275 | UINTN BufferSize;
|
---|
276 | EFI_HANDLE NewImageHandle;
|
---|
277 | UINTN Pages;
|
---|
278 | EFI_PHYSICAL_ADDRESS FfsBuffer;
|
---|
279 | PE_COFF_LOADER_IMAGE_CONTEXT ImageContext;
|
---|
280 | EFI_GCD_MEMORY_SPACE_DESCRIPTOR MemDesc;
|
---|
281 |
|
---|
282 | Status = gBS->LocateProtocol (&gEfiDxeSmmReadyToLockProtocolGuid, NULL, &Interface);
|
---|
283 | if (EFI_ERROR (Status)) {
|
---|
284 | return;
|
---|
285 | }
|
---|
286 |
|
---|
287 | //
|
---|
288 | // A workaround: Here we install a dummy handle
|
---|
289 | //
|
---|
290 | NewImageHandle = NULL;
|
---|
291 | Status = gBS->InstallProtocolInterface (
|
---|
292 | &NewImageHandle,
|
---|
293 | &gEfiCallerIdGuid,
|
---|
294 | EFI_NATIVE_INTERFACE,
|
---|
295 | NULL
|
---|
296 | );
|
---|
297 | ASSERT_EFI_ERROR (Status);
|
---|
298 |
|
---|
299 | //
|
---|
300 | // Reload BootScriptExecutor image itself to RESERVED mem
|
---|
301 | //
|
---|
302 | Status = GetSectionFromAnyFv (
|
---|
303 | &gEfiCallerIdGuid,
|
---|
304 | EFI_SECTION_PE32,
|
---|
305 | 0,
|
---|
306 | (VOID **)&Buffer,
|
---|
307 | &BufferSize
|
---|
308 | );
|
---|
309 | ASSERT_EFI_ERROR (Status);
|
---|
310 | ImageContext.Handle = Buffer;
|
---|
311 | ImageContext.ImageRead = PeCoffLoaderImageReadFromMemory;
|
---|
312 | //
|
---|
313 | // Get information about the image being loaded
|
---|
314 | //
|
---|
315 | Status = PeCoffLoaderGetImageInfo (&ImageContext);
|
---|
316 | ASSERT_EFI_ERROR (Status);
|
---|
317 | if (ImageContext.SectionAlignment > EFI_PAGE_SIZE) {
|
---|
318 | Pages = EFI_SIZE_TO_PAGES ((UINTN)(ImageContext.ImageSize + ImageContext.SectionAlignment));
|
---|
319 | } else {
|
---|
320 | Pages = EFI_SIZE_TO_PAGES ((UINTN)ImageContext.ImageSize);
|
---|
321 | }
|
---|
322 |
|
---|
323 | FfsBuffer = 0xFFFFFFFF;
|
---|
324 | Status = gBS->AllocatePages (
|
---|
325 | AllocateMaxAddress,
|
---|
326 | EfiReservedMemoryType,
|
---|
327 | Pages,
|
---|
328 | &FfsBuffer
|
---|
329 | );
|
---|
330 | ASSERT_EFI_ERROR (Status);
|
---|
331 |
|
---|
332 | //
|
---|
333 | // Make sure that the buffer can be used to store code.
|
---|
334 | //
|
---|
335 | Status = gDS->GetMemorySpaceDescriptor (FfsBuffer, &MemDesc);
|
---|
336 | if (!EFI_ERROR (Status) && ((MemDesc.Attributes & EFI_MEMORY_XP) != 0)) {
|
---|
337 | gDS->SetMemorySpaceAttributes (
|
---|
338 | FfsBuffer,
|
---|
339 | EFI_PAGES_TO_SIZE (Pages),
|
---|
340 | MemDesc.Attributes & (~EFI_MEMORY_XP)
|
---|
341 | );
|
---|
342 | }
|
---|
343 |
|
---|
344 | ImageContext.ImageAddress = (PHYSICAL_ADDRESS)(UINTN)FfsBuffer;
|
---|
345 | //
|
---|
346 | // Align buffer on section boundary
|
---|
347 | //
|
---|
348 | ImageContext.ImageAddress += ImageContext.SectionAlignment - 1;
|
---|
349 | ImageContext.ImageAddress &= ~((EFI_PHYSICAL_ADDRESS)ImageContext.SectionAlignment - 1);
|
---|
350 | //
|
---|
351 | // Load the image to our new buffer
|
---|
352 | //
|
---|
353 | Status = PeCoffLoaderLoadImage (&ImageContext);
|
---|
354 | ASSERT_EFI_ERROR (Status);
|
---|
355 |
|
---|
356 | //
|
---|
357 | // Relocate the image in our new buffer
|
---|
358 | //
|
---|
359 | Status = PeCoffLoaderRelocateImage (&ImageContext);
|
---|
360 | ASSERT_EFI_ERROR (Status);
|
---|
361 |
|
---|
362 | //
|
---|
363 | // Free the buffer allocated by ReadSection since the image has been relocated in the new buffer
|
---|
364 | //
|
---|
365 | gBS->FreePool (Buffer);
|
---|
366 |
|
---|
367 | //
|
---|
368 | // Flush the instruction cache so the image data is written before we execute it
|
---|
369 | //
|
---|
370 | InvalidateInstructionCacheRange ((VOID *)(UINTN)ImageContext.ImageAddress, (UINTN)ImageContext.ImageSize);
|
---|
371 |
|
---|
372 | RegisterMemoryProfileImage (
|
---|
373 | &gEfiCallerIdGuid,
|
---|
374 | ImageContext.ImageAddress,
|
---|
375 | ImageContext.ImageSize,
|
---|
376 | EFI_FV_FILETYPE_DRIVER
|
---|
377 | );
|
---|
378 |
|
---|
379 | Status = ((EFI_IMAGE_ENTRY_POINT)(UINTN)(ImageContext.EntryPoint))(NewImageHandle, gST);
|
---|
380 | ASSERT_EFI_ERROR (Status);
|
---|
381 |
|
---|
382 | //
|
---|
383 | // Additional step for BootScript integrity
|
---|
384 | // Save BootScriptExecutor image
|
---|
385 | //
|
---|
386 | Status = SaveLockBox (
|
---|
387 | &mBootScriptExecutorImageGuid,
|
---|
388 | (VOID *)(UINTN)ImageContext.ImageAddress,
|
---|
389 | (UINTN)ImageContext.ImageSize
|
---|
390 | );
|
---|
391 | ASSERT_EFI_ERROR (Status);
|
---|
392 |
|
---|
393 | Status = SetLockBoxAttributes (&mBootScriptExecutorImageGuid, LOCK_BOX_ATTRIBUTE_RESTORE_IN_PLACE);
|
---|
394 | ASSERT_EFI_ERROR (Status);
|
---|
395 |
|
---|
396 | gBS->CloseEvent (Event);
|
---|
397 | }
|
---|
398 |
|
---|
399 | /**
|
---|
400 | Entrypoint of Boot script exector driver, this function will be executed in
|
---|
401 | normal boot phase and invoked by DXE dispatch.
|
---|
402 |
|
---|
403 | @param[in] ImageHandle The firmware allocated handle for the EFI image.
|
---|
404 | @param[in] SystemTable A pointer to the EFI System Table.
|
---|
405 |
|
---|
406 | @retval EFI_SUCCESS The entry point is executed successfully.
|
---|
407 | @retval other Some error occurs when executing this entry point.
|
---|
408 | **/
|
---|
409 | EFI_STATUS
|
---|
410 | EFIAPI
|
---|
411 | BootScriptExecutorEntryPoint (
|
---|
412 | IN EFI_HANDLE ImageHandle,
|
---|
413 | IN EFI_SYSTEM_TABLE *SystemTable
|
---|
414 | )
|
---|
415 | {
|
---|
416 | UINTN BufferSize;
|
---|
417 | UINTN Pages;
|
---|
418 | BOOT_SCRIPT_EXECUTOR_VARIABLE *EfiBootScriptExecutorVariable;
|
---|
419 | EFI_PHYSICAL_ADDRESS BootScriptExecutorBuffer;
|
---|
420 | EFI_STATUS Status;
|
---|
421 | VOID *DevicePath;
|
---|
422 | EFI_EVENT ReadyToLockEvent;
|
---|
423 | VOID *Registration;
|
---|
424 | UINT32 RegEax;
|
---|
425 | UINT32 RegEdx;
|
---|
426 |
|
---|
427 | if (!PcdGetBool (PcdAcpiS3Enable)) {
|
---|
428 | return EFI_UNSUPPORTED;
|
---|
429 | }
|
---|
430 |
|
---|
431 | //
|
---|
432 | // Make sure AddressEncMask is contained to smallest supported address field.
|
---|
433 | //
|
---|
434 | mAddressEncMask = PcdGet64 (PcdPteMemoryEncryptionAddressOrMask) & PAGING_1G_ADDRESS_MASK_64;
|
---|
435 |
|
---|
436 | //
|
---|
437 | // Test if the gEfiCallerIdGuid of this image is already installed. if not, the entry
|
---|
438 | // point is loaded by DXE code which is the first time loaded. or else, it is already
|
---|
439 | // be reloaded be itself.This is a work-around
|
---|
440 | //
|
---|
441 | Status = gBS->LocateProtocol (&gEfiCallerIdGuid, NULL, &DevicePath);
|
---|
442 | if (EFI_ERROR (Status)) {
|
---|
443 | //
|
---|
444 | // Create ReadyToLock event to reload BootScriptExecutor image
|
---|
445 | // to RESERVED mem and save it to LockBox.
|
---|
446 | //
|
---|
447 | ReadyToLockEvent = EfiCreateProtocolNotifyEvent (
|
---|
448 | &gEfiDxeSmmReadyToLockProtocolGuid,
|
---|
449 | TPL_NOTIFY,
|
---|
450 | ReadyToLockEventNotify,
|
---|
451 | NULL,
|
---|
452 | &Registration
|
---|
453 | );
|
---|
454 | ASSERT (ReadyToLockEvent != NULL);
|
---|
455 | } else {
|
---|
456 | //
|
---|
457 | // the entry point is invoked after reloading. following code only run in RESERVED mem
|
---|
458 | //
|
---|
459 | if (PcdGetBool (PcdUse1GPageTable)) {
|
---|
460 | AsmCpuid (0x80000000, &RegEax, NULL, NULL, NULL);
|
---|
461 | if (RegEax >= 0x80000001) {
|
---|
462 | AsmCpuid (0x80000001, NULL, NULL, NULL, &RegEdx);
|
---|
463 | if ((RegEdx & BIT26) != 0) {
|
---|
464 | mPage1GSupport = TRUE;
|
---|
465 | }
|
---|
466 | }
|
---|
467 | }
|
---|
468 |
|
---|
469 | BufferSize = sizeof (BOOT_SCRIPT_EXECUTOR_VARIABLE);
|
---|
470 |
|
---|
471 | BootScriptExecutorBuffer = 0xFFFFFFFF;
|
---|
472 | Pages = EFI_SIZE_TO_PAGES (BufferSize);
|
---|
473 | Status = gBS->AllocatePages (
|
---|
474 | AllocateMaxAddress,
|
---|
475 | EfiReservedMemoryType,
|
---|
476 | Pages,
|
---|
477 | &BootScriptExecutorBuffer
|
---|
478 | );
|
---|
479 | ASSERT_EFI_ERROR (Status);
|
---|
480 |
|
---|
481 | EfiBootScriptExecutorVariable = (BOOT_SCRIPT_EXECUTOR_VARIABLE *)(UINTN)BootScriptExecutorBuffer;
|
---|
482 | EfiBootScriptExecutorVariable->BootScriptExecutorEntrypoint = (UINTN)S3BootScriptExecutorEntryFunction;
|
---|
483 |
|
---|
484 | Status = SaveLockBox (
|
---|
485 | &gEfiBootScriptExecutorVariableGuid,
|
---|
486 | &BootScriptExecutorBuffer,
|
---|
487 | sizeof (BootScriptExecutorBuffer)
|
---|
488 | );
|
---|
489 | ASSERT_EFI_ERROR (Status);
|
---|
490 |
|
---|
491 | //
|
---|
492 | // Additional step for BootScript integrity
|
---|
493 | // Save BootScriptExecutor context
|
---|
494 | //
|
---|
495 | Status = SaveLockBox (
|
---|
496 | &gEfiBootScriptExecutorContextGuid,
|
---|
497 | EfiBootScriptExecutorVariable,
|
---|
498 | sizeof (*EfiBootScriptExecutorVariable)
|
---|
499 | );
|
---|
500 | ASSERT_EFI_ERROR (Status);
|
---|
501 |
|
---|
502 | Status = SetLockBoxAttributes (&gEfiBootScriptExecutorContextGuid, LOCK_BOX_ATTRIBUTE_RESTORE_IN_PLACE);
|
---|
503 | ASSERT_EFI_ERROR (Status);
|
---|
504 | }
|
---|
505 |
|
---|
506 | return EFI_SUCCESS;
|
---|
507 | }
|
---|