2 Save the S3 data to S3 boot script.
4 Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.<BR>
6 This program and the accompanying materials
7 are licensed and made available under the terms and conditions
8 of the BSD License which accompanies this distribution. The
9 full text of the license may be found at
10 http://opensource.org/licenses/bsd-license.php
12 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
13 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
16 #include "InternalBootScriptLib.h"
22 +------------------------------+<------- PcdS3BootScriptTablePrivateDataPtr
23 | SCRIPT_TABLE_PRIVATE_DATA | (mS3BootScriptTablePtr, Before SmmReadyToLock)
24 | TableBase |--- PcdS3BootScriptTablePrivateSmmDataPtr
25 | TableLength |--|-- (mS3BootScriptTablePtr = mS3BootScriptTableSmmPtr, After SmmReadyToLock InSmm)
26 | TableMemoryPageNumber |--|-|----
29 | BootTimeScriptLength |--|-|---|---
31 | BackFromS3 | | | | |
32 +------------------------------+ | | | |
34 +------------------------------+<-- | | |
35 | EFI_BOOT_SCRIPT_TABLE_HEADER | | | |
36 | TableLength |----|-- | |
37 +------------------------------+ | | | |
39 +------------------------------+<---- | | |
40 | EFI_BOOT_SCRIPT_TERMINATE | | | |
41 +------------------------------+<------ | |
44 mBootScriptDataBootTimeGuid LockBox: | |
45 Used to restore data after back from S3| |
46 to handle potential INSERT boot script | |
48 +------------------------------+ | |
49 | Boot Time Boot Script | | |
50 | Before SmmReadyToLock | | |
53 +------------------------------+ | |
54 | Boot Time Boot Script | | |
55 | After SmmReadyToLock InSmm | | |
57 +------------------------------+<-------|--|
60 mBootScriptDataGuid LockBox: (IN_PLACE) | |
61 Used to restore data at S3 resume. | |
62 +------------------------------+ | |
63 | Boot Time Boot Script | | |
64 | Before SmmReadyToLock | | |
67 +------------------------------+ | |
68 | Boot Time Boot Script | | |
69 | After SmmReadyToLock InSmm | | |
71 +------------------------------+<-------|---
72 | Runtime Boot Script | |
73 | After SmmReadyToLock InSmm | |
74 +------------------------------+ |
76 +------------------------------+<--------
79 mBootScriptTableBaseGuid LockBox: (IN_PLACE)
80 +------------------------------+
81 | mS3BootScriptTablePtr-> |
83 +------------------------------+
86 mBootScriptSmmPrivateDataGuid LockBox: (IN_PLACE)
87 SMM private data with BackFromS3 = TRUE
88 at runtime. S3 will help restore it to
89 tell the Library the system is back from S3.
90 +------------------------------+
91 | SCRIPT_TABLE_PRIVATE_DATA |
94 | TableMemoryPageNumber |
97 | BootTimeScriptLength |
100 +------------------------------+
104 SCRIPT_TABLE_PRIVATE_DATA
*mS3BootScriptTablePtr
;
107 // Allocate SMM copy because we can not use mS3BootScriptTablePtr after SmmReadyToLock in InSmm.
109 SCRIPT_TABLE_PRIVATE_DATA
*mS3BootScriptTableSmmPtr
;
111 EFI_GUID mBootScriptDataGuid
= {
112 0xaea6b965, 0xdcf5, 0x4311, { 0xb4, 0xb8, 0xf, 0x12, 0x46, 0x44, 0x94, 0xd2 }
115 EFI_GUID mBootScriptDataBootTimeGuid
= {
116 0xb5af1d7a, 0xb8cf, 0x4eb3, { 0x89, 0x25, 0xa8, 0x20, 0xe1, 0x6b, 0x68, 0x7d }
119 EFI_GUID mBootScriptTableBaseGuid
= {
120 0x1810ab4a, 0x2314, 0x4df6, { 0x81, 0xeb, 0x67, 0xc6, 0xec, 0x5, 0x85, 0x91 }
123 EFI_GUID mBootScriptSmmPrivateDataGuid
= {
124 0x627ee2da, 0x3bf9, 0x439b, { 0x92, 0x9f, 0x2e, 0xe, 0x6e, 0x9d, 0xba, 0x62 }
127 EFI_EVENT mEventDxeSmmReadyToLock
= NULL
;
128 VOID
*mRegistrationSmmExitBootServices
= NULL
;
129 VOID
*mRegistrationSmmLegacyBoot
= NULL
;
130 VOID
*mRegistrationSmmReadyToLock
= NULL
;
131 BOOLEAN mS3BootScriptTableAllocated
= FALSE
;
132 BOOLEAN mS3BootScriptTableSmmAllocated
= FALSE
;
133 EFI_SMM_SYSTEM_TABLE2
*mSmst
= NULL
;
136 This is an internal function to add a terminate node the entry, recalculate the table
137 length and fill into the table.
139 @return the base address of the boot script table.
142 S3BootScriptInternalCloseTable (
147 EFI_BOOT_SCRIPT_TERMINATE ScriptTerminate
;
148 EFI_BOOT_SCRIPT_TABLE_HEADER
*ScriptTableInfo
;
149 S3TableBase
= mS3BootScriptTablePtr
->TableBase
;
151 if (S3TableBase
== NULL
) {
153 // the table is not exist
158 // Append the termination entry.
160 ScriptTerminate
.OpCode
= S3_BOOT_SCRIPT_LIB_TERMINATE_OPCODE
;
161 ScriptTerminate
.Length
= (UINT8
) sizeof (EFI_BOOT_SCRIPT_TERMINATE
);
162 CopyMem (mS3BootScriptTablePtr
->TableBase
+ mS3BootScriptTablePtr
->TableLength
, &ScriptTerminate
, sizeof (EFI_BOOT_SCRIPT_TERMINATE
));
164 // fill the table length
166 ScriptTableInfo
= (EFI_BOOT_SCRIPT_TABLE_HEADER
*)(mS3BootScriptTablePtr
->TableBase
);
167 ScriptTableInfo
->TableLength
= mS3BootScriptTablePtr
->TableLength
+ sizeof (EFI_BOOT_SCRIPT_TERMINATE
);
173 // NOTE: Here we did NOT adjust the mS3BootScriptTablePtr->TableLength to
174 // mS3BootScriptTablePtr->TableLength + sizeof (EFI_BOOT_SCRIPT_TERMINATE).
175 // Because maybe after SmmReadyToLock, we still need add entries into the table,
176 // and the entry should be added start before this TERMINATE node.
181 This function save boot script data to LockBox.
185 SaveBootScriptDataToLockBox (
192 // Save whole memory copy into LockBox.
193 // It will be used to restore data at S3 resume.
195 Status
= SaveLockBox (
196 &mBootScriptDataGuid
,
197 (VOID
*)mS3BootScriptTablePtr
->TableBase
,
198 EFI_PAGES_TO_SIZE (mS3BootScriptTablePtr
->TableMemoryPageNumber
)
200 ASSERT_EFI_ERROR (Status
);
202 Status
= SetLockBoxAttributes (&mBootScriptDataGuid
, LOCK_BOX_ATTRIBUTE_RESTORE_IN_PLACE
);
203 ASSERT_EFI_ERROR (Status
);
206 // Just need save TableBase.
207 // Do not update other field because they will NOT be used in S3.
209 Status
= SaveLockBox (
210 &mBootScriptTableBaseGuid
,
211 (VOID
*)&mS3BootScriptTablePtr
->TableBase
,
212 sizeof(mS3BootScriptTablePtr
->TableBase
)
214 ASSERT_EFI_ERROR (Status
);
216 Status
= SetLockBoxAttributes (&mBootScriptTableBaseGuid
, LOCK_BOX_ATTRIBUTE_RESTORE_IN_PLACE
);
217 ASSERT_EFI_ERROR (Status
);
221 This is the Event call back function to notify the Library the system is entering
224 @param Event Pointer to this event
225 @param Context Event handler private data
229 S3BootScriptEventCallBack (
238 // Try to locate it because EfiCreateProtocolNotifyEvent will trigger it once when registration.
239 // Just return if it is not found.
241 Status
= gBS
->LocateProtocol (
242 &gEfiDxeSmmReadyToLockProtocolGuid
,
246 if (EFI_ERROR (Status
)) {
251 // Here we should tell the library that we are entering SmmLocked phase.
252 // and the memory page number occupied by the table should not grow anymore.
254 if (!mS3BootScriptTablePtr
->SmmLocked
) {
256 // Before SmmReadyToLock, we need not write the terminate node when adding a node to boot scipt table
257 // or else, that will impact the performance. However, after SmmReadyToLock, we should append terminate
258 // node on every add to boot script table.
260 S3BootScriptInternalCloseTable ();
261 mS3BootScriptTablePtr
->SmmLocked
= TRUE
;
264 // Save BootScript data to lockbox
266 SaveBootScriptDataToLockBox ();
271 This is the Event call back function is triggered in SMM to notify the Library
272 the system is entering SmmLocked phase and set InSmm flag.
274 @param Protocol Points to the protocol's unique identifier
275 @param Interface Points to the interface instance
276 @param Handle The handle on which the interface was installed
278 @retval EFI_SUCCESS SmmEventCallback runs successfully
282 S3BootScriptSmmEventCallBack (
283 IN CONST EFI_GUID
*Protocol
,
289 // Check if it is already done
291 if (mS3BootScriptTablePtr
== mS3BootScriptTableSmmPtr
) {
296 // Last chance to call-out, just make sure SmmLocked is set.
298 S3BootScriptEventCallBack (NULL
, NULL
);
301 // Save a SMM copy. If TableBase is NOT null, it means SMM copy has been ready, skip copy mem.
303 if (mS3BootScriptTableSmmPtr
->TableBase
== NULL
) {
304 CopyMem (mS3BootScriptTableSmmPtr
, mS3BootScriptTablePtr
, sizeof(*mS3BootScriptTablePtr
));
307 // Set InSmm, we allow boot script update when InSmm, but not allow boot script outside SMM.
308 // InSmm will only be checked if SmmLocked is TRUE.
310 mS3BootScriptTableSmmPtr
->InSmm
= TRUE
;
313 // We should not use ACPI Reserved copy, because it is not safe.
315 mS3BootScriptTablePtr
= mS3BootScriptTableSmmPtr
;
321 This function is to save boot time boot script data to LockBox.
323 Because there may be INSERT boot script at runtime in SMM.
324 The boot time copy will be used to restore data after back from S3.
325 Otherwise the data inserted may cause some boot time boot script data lost
326 if only BootScriptData used.
330 SaveBootTimeDataToLockBox (
337 // ACPI Reserved copy is not safe, restore from BootScriptData LockBox first,
338 // and then save the data to BootScriptDataBootTime LockBox.
340 Status
= RestoreLockBox (
341 &mBootScriptDataGuid
,
345 ASSERT_EFI_ERROR (Status
);
348 // Save BootScriptDataBootTime
349 // It will be used to restore data after back from S3.
351 Status
= SaveLockBox (
352 &mBootScriptDataBootTimeGuid
,
353 (VOID
*) mS3BootScriptTablePtr
->TableBase
,
354 mS3BootScriptTablePtr
->BootTimeScriptLength
356 ASSERT_EFI_ERROR (Status
);
360 This function save boot script SMM private data to LockBox with BackFromS3 = TRUE at runtime.
361 S3 resume will help restore it to tell the Library the system is back from S3.
365 SaveSmmPriviateDataToLockBoxAtRuntime (
372 // Save boot script SMM private data with BackFromS3 = TRUE.
374 mS3BootScriptTablePtr
->BackFromS3
= TRUE
;
375 Status
= SaveLockBox (
376 &mBootScriptSmmPrivateDataGuid
,
377 (VOID
*) mS3BootScriptTablePtr
,
378 sizeof (SCRIPT_TABLE_PRIVATE_DATA
)
380 ASSERT_EFI_ERROR (Status
);
382 Status
= SetLockBoxAttributes (&mBootScriptSmmPrivateDataGuid
, LOCK_BOX_ATTRIBUTE_RESTORE_IN_PLACE
);
383 ASSERT_EFI_ERROR (Status
);
386 // Set BackFromS3 flag back to FALSE to indicate that now is not back from S3.
388 mS3BootScriptTablePtr
->BackFromS3
= FALSE
;
392 This is the Event call back function is triggered in SMM to notify the Library
393 the system is entering runtime phase.
395 @param[in] Protocol Points to the protocol's unique identifier
396 @param[in] Interface Points to the interface instance
397 @param[in] Handle The handle on which the interface was installed
399 @retval EFI_SUCCESS SmmAtRuntimeCallBack runs successfully
403 S3BootScriptSmmAtRuntimeCallBack (
404 IN CONST EFI_GUID
*Protocol
,
409 if (!mS3BootScriptTablePtr
->AtRuntime
) {
410 mS3BootScriptTablePtr
->BootTimeScriptLength
= (UINT32
) (mS3BootScriptTablePtr
->TableLength
+ sizeof (EFI_BOOT_SCRIPT_TERMINATE
));
411 SaveBootTimeDataToLockBox ();
413 mS3BootScriptTablePtr
->AtRuntime
= TRUE
;
414 SaveSmmPriviateDataToLockBoxAtRuntime ();
422 this function just identify it is a smm driver or non-smm driver linked against
425 @param ImageHandle The firmware allocated handle for the EFI image.
426 @param SystemTable A pointer to the EFI System Table.
428 @retval RETURN_SUCCESS The constructor always returns RETURN_SUCCESS.
433 S3BootScriptLibInitialize (
434 IN EFI_HANDLE ImageHandle
,
435 IN EFI_SYSTEM_TABLE
*SystemTable
439 SCRIPT_TABLE_PRIVATE_DATA
*S3TablePtr
;
440 SCRIPT_TABLE_PRIVATE_DATA
*S3TableSmmPtr
;
442 EFI_SMM_BASE2_PROTOCOL
*SmmBase2
;
444 EFI_PHYSICAL_ADDRESS Buffer
;
446 S3TablePtr
= (SCRIPT_TABLE_PRIVATE_DATA
*)(UINTN
)PcdGet64(PcdS3BootScriptTablePrivateDataPtr
);
448 // The Boot script private data is not be initialized. create it
450 if (S3TablePtr
== 0) {
451 Buffer
= SIZE_4GB
- 1;
452 Status
= gBS
->AllocatePages (
454 EfiReservedMemoryType
,
455 EFI_SIZE_TO_PAGES(sizeof(SCRIPT_TABLE_PRIVATE_DATA
)),
458 ASSERT_EFI_ERROR (Status
);
459 mS3BootScriptTableAllocated
= TRUE
;
460 S3TablePtr
= (VOID
*) (UINTN
) Buffer
;
462 Status
= PcdSet64S (PcdS3BootScriptTablePrivateDataPtr
, (UINT64
) (UINTN
)S3TablePtr
);
463 ASSERT_EFI_ERROR (Status
);
464 ZeroMem (S3TablePtr
, sizeof(SCRIPT_TABLE_PRIVATE_DATA
));
466 // Create event to notify the library system enter the SmmLocked phase.
468 mEventDxeSmmReadyToLock
= EfiCreateProtocolNotifyEvent (
469 &gEfiDxeSmmReadyToLockProtocolGuid
,
471 S3BootScriptEventCallBack
,
475 ASSERT (mEventDxeSmmReadyToLock
!= NULL
);
477 mS3BootScriptTablePtr
= S3TablePtr
;
480 // Get InSmm, we need to register SmmReadyToLock if this library is linked to SMM driver.
482 Status
= gBS
->LocateProtocol (&gEfiSmmBase2ProtocolGuid
, NULL
, (VOID
**) &SmmBase2
);
483 if (EFI_ERROR (Status
)) {
484 return RETURN_SUCCESS
;
486 Status
= SmmBase2
->InSmm (SmmBase2
, &InSmm
);
487 if (EFI_ERROR (Status
)) {
488 return RETURN_SUCCESS
;
491 return RETURN_SUCCESS
;
494 // Good, we are in SMM
496 Status
= SmmBase2
->GetSmstLocation (SmmBase2
, &mSmst
);
497 if (EFI_ERROR (Status
)) {
498 return RETURN_SUCCESS
;
501 S3TableSmmPtr
= (SCRIPT_TABLE_PRIVATE_DATA
*)(UINTN
)PcdGet64(PcdS3BootScriptTablePrivateSmmDataPtr
);
503 // The Boot script private data in SMM is not be initialized. create it
505 if (S3TableSmmPtr
== 0) {
506 Status
= mSmst
->SmmAllocatePool (
507 EfiRuntimeServicesData
,
508 sizeof(SCRIPT_TABLE_PRIVATE_DATA
),
509 (VOID
**) &S3TableSmmPtr
511 ASSERT_EFI_ERROR (Status
);
512 mS3BootScriptTableSmmAllocated
= TRUE
;
514 Status
= PcdSet64S (PcdS3BootScriptTablePrivateSmmDataPtr
, (UINT64
) (UINTN
)S3TableSmmPtr
);
515 ASSERT_EFI_ERROR (Status
);
516 ZeroMem (S3TableSmmPtr
, sizeof(SCRIPT_TABLE_PRIVATE_DATA
));
519 // Register SmmExitBootServices and SmmLegacyBoot notification.
521 Status
= mSmst
->SmmRegisterProtocolNotify (
522 &gEdkiiSmmExitBootServicesProtocolGuid
,
523 S3BootScriptSmmAtRuntimeCallBack
,
524 &mRegistrationSmmExitBootServices
526 ASSERT_EFI_ERROR (Status
);
528 Status
= mSmst
->SmmRegisterProtocolNotify (
529 &gEdkiiSmmLegacyBootProtocolGuid
,
530 S3BootScriptSmmAtRuntimeCallBack
,
531 &mRegistrationSmmLegacyBoot
533 ASSERT_EFI_ERROR (Status
);
535 mS3BootScriptTableSmmPtr
= S3TableSmmPtr
;
538 // Register SmmReadyToLock notification.
540 Status
= mSmst
->SmmRegisterProtocolNotify (
541 &gEfiSmmReadyToLockProtocolGuid
,
542 S3BootScriptSmmEventCallBack
,
543 &mRegistrationSmmReadyToLock
545 ASSERT_EFI_ERROR (Status
);
547 return RETURN_SUCCESS
;
551 Library Destructor to free the resources allocated by
552 S3BootScriptLibInitialize() and unregister callbacks.
554 NOTICE: The destructor doesn't support unloading as a separate action, and it
555 only supports unloading if the containing driver's entry point function fails.
557 @param ImageHandle The firmware allocated handle for the EFI image.
558 @param SystemTable A pointer to the EFI System Table.
560 @retval RETURN_SUCCESS The destructor always returns RETURN_SUCCESS.
565 S3BootScriptLibDeinitialize (
566 IN EFI_HANDLE ImageHandle
,
567 IN EFI_SYSTEM_TABLE
*SystemTable
572 DEBUG ((EFI_D_INFO
, "%a() in %a module\n", __FUNCTION__
, gEfiCallerBaseName
));
574 if (mEventDxeSmmReadyToLock
!= NULL
) {
576 // Close the DxeSmmReadyToLock event.
578 Status
= gBS
->CloseEvent (mEventDxeSmmReadyToLock
);
579 ASSERT_EFI_ERROR (Status
);
583 if (mRegistrationSmmExitBootServices
!= NULL
) {
585 // Unregister SmmExitBootServices notification.
587 Status
= mSmst
->SmmRegisterProtocolNotify (
588 &gEdkiiSmmExitBootServicesProtocolGuid
,
590 &mRegistrationSmmExitBootServices
592 ASSERT_EFI_ERROR (Status
);
594 if (mRegistrationSmmLegacyBoot
!= NULL
) {
596 // Unregister SmmLegacyBoot notification.
598 Status
= mSmst
->SmmRegisterProtocolNotify (
599 &gEdkiiSmmLegacyBootProtocolGuid
,
601 &mRegistrationSmmLegacyBoot
603 ASSERT_EFI_ERROR (Status
);
605 if (mRegistrationSmmReadyToLock
!= NULL
) {
607 // Unregister SmmReadyToLock notification.
609 Status
= mSmst
->SmmRegisterProtocolNotify (
610 &gEfiSmmReadyToLockProtocolGuid
,
612 &mRegistrationSmmReadyToLock
614 ASSERT_EFI_ERROR (Status
);
619 // Free the resources allocated and set PCDs to 0.
621 if (mS3BootScriptTableAllocated
) {
622 Status
= gBS
->FreePages ((EFI_PHYSICAL_ADDRESS
) (UINTN
) mS3BootScriptTablePtr
, EFI_SIZE_TO_PAGES(sizeof(SCRIPT_TABLE_PRIVATE_DATA
)));
623 ASSERT_EFI_ERROR (Status
);
624 Status
= PcdSet64S (PcdS3BootScriptTablePrivateDataPtr
, 0);
625 ASSERT_EFI_ERROR (Status
);
627 if ((mSmst
!= NULL
) && mS3BootScriptTableSmmAllocated
) {
628 Status
= mSmst
->SmmFreePool (mS3BootScriptTableSmmPtr
);
629 ASSERT_EFI_ERROR (Status
);
630 Status
= PcdSet64S (PcdS3BootScriptTablePrivateSmmDataPtr
, 0);
631 ASSERT_EFI_ERROR (Status
);
634 return RETURN_SUCCESS
;
638 To get the start address from which a new boot time s3 boot script entry will write into.
639 If the table is not exist, the functio will first allocate a buffer for the table
640 If the table buffer is not enough for the new entry, in non-smm mode, the funtion will
641 invoke reallocate to enlarge buffer.
643 @param EntryLength the new entry length.
645 @retval the address from which the a new s3 boot script entry will write into
648 S3BootScriptGetBootTimeEntryAddAddress (
652 EFI_PHYSICAL_ADDRESS S3TableBase
;
653 EFI_PHYSICAL_ADDRESS NewS3TableBase
;
658 EFI_BOOT_SCRIPT_TABLE_HEADER
*ScriptTableInfo
;
660 S3TableBase
= (EFI_PHYSICAL_ADDRESS
)(UINTN
)(mS3BootScriptTablePtr
->TableBase
);
661 if (S3TableBase
== 0) {
663 // The table is not exist. This is the first to add entry.
664 // Allocate ACPI script table space under 4G memory.
666 S3TableBase
= 0xffffffff;
667 Status
= gBS
->AllocatePages (
669 EfiReservedMemoryType
,
670 2 + PcdGet16(PcdS3BootScriptRuntimeTableReservePageNumber
),
671 (EFI_PHYSICAL_ADDRESS
*)&S3TableBase
674 if (EFI_ERROR(Status
)) {
675 ASSERT_EFI_ERROR (Status
);
681 ScriptTableInfo
= (EFI_BOOT_SCRIPT_TABLE_HEADER
*)(UINTN
)S3TableBase
;
682 ScriptTableInfo
->OpCode
= S3_BOOT_SCRIPT_LIB_TABLE_OPCODE
;
683 ScriptTableInfo
->Length
= (UINT8
) sizeof (EFI_BOOT_SCRIPT_TABLE_HEADER
);
684 ScriptTableInfo
->Version
= BOOT_SCRIPT_TABLE_VERSION
;
685 ScriptTableInfo
->TableLength
= 0; // will be calculate at CloseTable
686 mS3BootScriptTablePtr
->TableLength
= sizeof (EFI_BOOT_SCRIPT_TABLE_HEADER
);
687 mS3BootScriptTablePtr
->TableBase
= (UINT8
*)(UINTN
)S3TableBase
;
688 mS3BootScriptTablePtr
->TableMemoryPageNumber
= (UINT16
)(2 + PcdGet16(PcdS3BootScriptRuntimeTableReservePageNumber
));
691 // Here we do not count the reserved memory for runtime script table.
692 PageNumber
= (UINT16
) (mS3BootScriptTablePtr
->TableMemoryPageNumber
- PcdGet16(PcdS3BootScriptRuntimeTableReservePageNumber
));
693 TableLength
= mS3BootScriptTablePtr
->TableLength
;
694 if ((UINTN
) EFI_PAGES_TO_SIZE ((UINTN
) PageNumber
) < (UINTN
) (TableLength
+ EntryLength
+ sizeof (EFI_BOOT_SCRIPT_TERMINATE
))) {
696 // The buffer is too small to hold the table, Reallocate the buffer
698 NewS3TableBase
= 0xffffffff;
699 Status
= gBS
->AllocatePages (
701 EfiReservedMemoryType
,
702 2 + PageNumber
+ PcdGet16(PcdS3BootScriptRuntimeTableReservePageNumber
),
703 (EFI_PHYSICAL_ADDRESS
*)&NewS3TableBase
706 if (EFI_ERROR(Status
)) {
707 ASSERT_EFI_ERROR (Status
);
711 CopyMem ((VOID
*)(UINTN
)NewS3TableBase
, (VOID
*)(UINTN
)S3TableBase
, TableLength
);
712 gBS
->FreePages (S3TableBase
, mS3BootScriptTablePtr
->TableMemoryPageNumber
);
714 mS3BootScriptTablePtr
->TableBase
= (UINT8
*)(UINTN
)NewS3TableBase
;
715 mS3BootScriptTablePtr
->TableMemoryPageNumber
= (UINT16
) (2 + PageNumber
+ PcdGet16(PcdS3BootScriptRuntimeTableReservePageNumber
));
718 // calculate the the start address for the new entry.
720 NewEntryPtr
= mS3BootScriptTablePtr
->TableBase
+ TableLength
;
723 // update the table lenghth
725 mS3BootScriptTablePtr
->TableLength
= TableLength
+ EntryLength
;
728 // In the boot time, we will not append the termination entry to the boot script
729 // table until the callers think there is no boot time data that should be added and
730 // it is caller's responsibility to explicit call the CloseTable.
737 To get the start address from which a new runtime(after SmmReadyToLock) s3 boot script entry will write into.
738 In this case, it should be ensured that there is enough buffer to hold the entry.
740 @param EntryLength the new entry length.
742 @retval the address from which the a new s3 runtime(after SmmReadyToLock) script entry will write into
745 S3BootScriptGetRuntimeEntryAddAddress (
753 // Check if the memory range reserved for S3 Boot Script table is large enough to hold the node.
755 if ((UINTN
) (mS3BootScriptTablePtr
->TableLength
+ EntryLength
+ sizeof (EFI_BOOT_SCRIPT_TERMINATE
)) <= (UINTN
) EFI_PAGES_TO_SIZE ((UINTN
) (mS3BootScriptTablePtr
->TableMemoryPageNumber
))) {
756 NewEntryPtr
= mS3BootScriptTablePtr
->TableBase
+ mS3BootScriptTablePtr
->TableLength
;
757 mS3BootScriptTablePtr
->TableLength
= mS3BootScriptTablePtr
->TableLength
+ EntryLength
;
759 // Append a terminate node on every insert
761 S3BootScriptInternalCloseTable ();
763 return (UINT8
*)NewEntryPtr
;
767 This function is to restore boot time boot script data from LockBox.
771 RestoreBootTimeDataFromLockBox (
779 // Restore boot time boot script data from LockBox.
781 LockBoxLength
= mS3BootScriptTablePtr
->BootTimeScriptLength
;
782 Status
= RestoreLockBox (
783 &mBootScriptDataBootTimeGuid
,
784 (VOID
*) mS3BootScriptTablePtr
->TableBase
,
787 ASSERT_EFI_ERROR (Status
);
790 // Update the data to BootScriptData LockBox.
792 Status
= UpdateLockBox (
793 &mBootScriptDataGuid
,
795 (VOID
*) mS3BootScriptTablePtr
->TableBase
,
798 ASSERT_EFI_ERROR (Status
);
801 // Update TableLength.
803 mS3BootScriptTablePtr
->TableLength
= (UINT32
) (mS3BootScriptTablePtr
->BootTimeScriptLength
- sizeof (EFI_BOOT_SCRIPT_TERMINATE
));
807 To get the start address from which a new s3 boot script entry will write into.
809 @param EntryLength the new entry length.
811 @retval the address from which the a new s3 boot script entry will write into
814 S3BootScriptGetEntryAddAddress (
820 if (mS3BootScriptTablePtr
->SmmLocked
) {
822 // We need check InSmm, because after SmmReadyToLock, only SMM driver is allowed to write boot script.
824 if (!mS3BootScriptTablePtr
->InSmm
) {
826 // Add DEBUG ERROR, so that we can find it after SmmReadyToLock.
827 // Do not use ASSERT, because we may have test to invoke this interface.
829 DEBUG ((EFI_D_ERROR
, "FATAL ERROR: Set boot script outside SMM after SmmReadyToLock!!!\n"));
833 if (mS3BootScriptTablePtr
->BackFromS3
) {
835 // Back from S3, restore boot time boot script data from LockBox
836 // and set BackFromS3 flag back to FALSE.
838 RestoreBootTimeDataFromLockBox ();
839 mS3BootScriptTablePtr
->BackFromS3
= FALSE
;
842 NewEntryPtr
= S3BootScriptGetRuntimeEntryAddAddress (EntryLength
);
844 NewEntryPtr
= S3BootScriptGetBootTimeEntryAddAddress (EntryLength
);
851 Sync BootScript LockBox data.
853 @param Script The address from where the boot script has been added or updated.
863 UINT32 TotalScriptLength
;
865 if (!mS3BootScriptTablePtr
->SmmLocked
|| !mS3BootScriptTablePtr
->InSmm
) {
867 // If it is not after SmmReadyToLock in SMM,
873 ScriptOffset
= (UINT32
) (Script
- mS3BootScriptTablePtr
->TableBase
);
875 TotalScriptLength
= (UINT32
) (mS3BootScriptTablePtr
->TableLength
+ sizeof (EFI_BOOT_SCRIPT_TERMINATE
));
878 // Update BootScriptData
879 // So in S3 resume, the data can be restored correctly.
881 Status
= UpdateLockBox (
882 &mBootScriptDataGuid
,
884 (VOID
*)((UINTN
)mS3BootScriptTablePtr
->TableBase
+ ScriptOffset
),
885 TotalScriptLength
- ScriptOffset
887 ASSERT_EFI_ERROR (Status
);
890 // Now the length field is updated, need sync to lockbox.
891 // So at S3 resume, the data can be restored correctly.
893 Status
= UpdateLockBox (
894 &mBootScriptDataGuid
,
895 OFFSET_OF (EFI_BOOT_SCRIPT_TABLE_HEADER
, TableLength
),
897 sizeof (TotalScriptLength
)
899 ASSERT_EFI_ERROR (Status
);
903 This is an function to close the S3 boot script table. The function could only be called in
904 BOOT time phase. To comply with the Framework spec definition on
905 EFI_BOOT_SCRIPT_SAVE_PROTOCOL.CloseTable(), this function will fulfill following things:
906 1. Closes the specified boot script table
907 2. It allocates a new memory pool to duplicate all the boot scripts in the specified table.
908 Once this function is called, the table maintained by the library will be destroyed
909 after it is copied into the allocated pool.
910 3. Any attempts to add a script record after calling this function will cause a new table
911 to be created by the library.
912 4. The base address of the allocated pool will be returned in Address. Note that after
913 using the boot script table, the CALLER is responsible for freeing the pool that is allocated
916 In Spec PI1.1, this EFI_BOOT_SCRIPT_SAVE_PROTOCOL.CloseTable() is retired. To provides this API for now is
917 for Framework Spec compatibility.
919 If anyone does call CloseTable() on a real platform, then the caller is responsible for figuring out
920 how to get the script to run at S3 resume because the boot script maintained by the lib will be
923 @return the base address of the new copy of the boot script table.
924 @note this function could only called in boot time phase
929 S3BootScriptCloseTable (
937 EFI_BOOT_SCRIPT_TABLE_HEADER
*ScriptTableInfo
;
939 S3TableBase
= mS3BootScriptTablePtr
->TableBase
;
940 if (S3TableBase
== 0) {
944 // Append the termination record the S3 boot script table
946 S3BootScriptInternalCloseTable();
947 TableLength
= mS3BootScriptTablePtr
->TableLength
+ sizeof (EFI_BOOT_SCRIPT_TERMINATE
);
949 // Allocate the buffer and copy the boot script to the buffer.
951 Status
= gBS
->AllocatePool (
956 if (EFI_ERROR (Status
)) {
959 CopyMem (Buffer
, S3TableBase
, TableLength
);
962 // Destroy the table maintained by the library so that the next write operation
963 // will write the record to the first entry of the table.
965 // Fill the table header.
966 ScriptTableInfo
= (EFI_BOOT_SCRIPT_TABLE_HEADER
*)S3TableBase
;
967 ScriptTableInfo
->OpCode
= S3_BOOT_SCRIPT_LIB_TABLE_OPCODE
;
968 ScriptTableInfo
->Length
= (UINT8
) sizeof (EFI_BOOT_SCRIPT_TABLE_HEADER
);
969 ScriptTableInfo
->TableLength
= 0; // will be calculate at close the table
971 mS3BootScriptTablePtr
->TableLength
= sizeof (EFI_BOOT_SCRIPT_TABLE_HEADER
);
975 Save I/O write to boot script
977 @param Width The width of the I/O operations.Enumerated in S3_BOOT_SCRIPT_LIB_WIDTH.
978 @param Address The base address of the I/O operations.
979 @param Count The number of I/O operations to perform.
980 @param Buffer The source buffer from which to write data.
982 @retval RETURN_OUT_OF_RESOURCES Not enough memory for the table do operation.
983 @retval RETURN_SUCCESS Opcode is added.
987 S3BootScriptSaveIoWrite (
988 IN S3_BOOT_SCRIPT_LIB_WIDTH Width
,
998 EFI_BOOT_SCRIPT_IO_WRITE ScriptIoWrite
;
1000 WidthInByte
= (UINT8
) (0x01 << (Width
& 0x03));
1001 Length
= (UINT8
)(sizeof (EFI_BOOT_SCRIPT_IO_WRITE
) + (WidthInByte
* Count
));
1003 Script
= S3BootScriptGetEntryAddAddress (Length
);
1004 if (Script
== NULL
) {
1005 return RETURN_OUT_OF_RESOURCES
;
1010 ScriptIoWrite
.OpCode
= EFI_BOOT_SCRIPT_IO_WRITE_OPCODE
;
1011 ScriptIoWrite
.Length
= Length
;
1012 ScriptIoWrite
.Width
= Width
;
1013 ScriptIoWrite
.Address
= Address
;
1014 ScriptIoWrite
.Count
= (UINT32
) Count
;
1015 CopyMem ((VOID
*)Script
, (VOID
*)&ScriptIoWrite
, sizeof(EFI_BOOT_SCRIPT_IO_WRITE
));
1016 CopyMem ((VOID
*)(Script
+ sizeof (EFI_BOOT_SCRIPT_IO_WRITE
)), Buffer
, WidthInByte
* Count
);
1018 SyncBootScript (Script
);
1020 return RETURN_SUCCESS
;
1024 Adds a record for an I/O modify operation into a S3 boot script table
1026 @param Width The width of the I/O operations.Enumerated in S3_BOOT_SCRIPT_LIB_WIDTH.
1027 @param Address The base address of the I/O operations.
1028 @param Data A pointer to the data to be OR-ed.
1029 @param DataMask A pointer to the data mask to be AND-ed with the data read from the register
1031 @retval RETURN_OUT_OF_RESOURCES Not enough memory for the table do operation.
1032 @retval RETURN_SUCCESS Opcode is added.
1036 S3BootScriptSaveIoReadWrite (
1037 IN S3_BOOT_SCRIPT_LIB_WIDTH Width
,
1046 EFI_BOOT_SCRIPT_IO_READ_WRITE ScriptIoReadWrite
;
1048 WidthInByte
= (UINT8
) (0x01 << (Width
& 0x03));
1049 Length
= (UINT8
)(sizeof (EFI_BOOT_SCRIPT_IO_READ_WRITE
) + (WidthInByte
* 2));
1051 Script
= S3BootScriptGetEntryAddAddress (Length
);
1052 if (Script
== NULL
) {
1053 return RETURN_OUT_OF_RESOURCES
;
1056 // Build script data
1058 ScriptIoReadWrite
.OpCode
= EFI_BOOT_SCRIPT_IO_READ_WRITE_OPCODE
;
1059 ScriptIoReadWrite
.Length
= Length
;
1060 ScriptIoReadWrite
.Width
= Width
;
1061 ScriptIoReadWrite
.Address
= Address
;
1063 CopyMem ((VOID
*)Script
, (VOID
*)&ScriptIoReadWrite
, sizeof(EFI_BOOT_SCRIPT_IO_READ_WRITE
));
1064 CopyMem ((VOID
*)(Script
+ sizeof (EFI_BOOT_SCRIPT_IO_READ_WRITE
)), Data
, WidthInByte
);
1065 CopyMem ((VOID
*)(Script
+ sizeof (EFI_BOOT_SCRIPT_IO_READ_WRITE
) + WidthInByte
), DataMask
, WidthInByte
);
1067 SyncBootScript (Script
);
1069 return RETURN_SUCCESS
;
1072 Adds a record for a memory write operation into a specified boot script table.
1074 @param Width The width of the I/O operations.Enumerated in S3_BOOT_SCRIPT_LIB_WIDTH.
1075 @param Address The base address of the memory operations
1076 @param Count The number of memory operations to perform.
1077 @param Buffer The source buffer from which to write the data.
1079 @retval RETURN_OUT_OF_RESOURCES Not enough memory for the table do operation.
1080 @retval RETURN_SUCCESS Opcode is added.
1084 S3BootScriptSaveMemWrite (
1085 IN S3_BOOT_SCRIPT_LIB_WIDTH Width
,
1094 EFI_BOOT_SCRIPT_MEM_WRITE ScriptMemWrite
;
1096 WidthInByte
= (UINT8
) (0x01 << (Width
& 0x03));
1097 Length
= (UINT8
)(sizeof (EFI_BOOT_SCRIPT_MEM_WRITE
) + (WidthInByte
* Count
));
1099 Script
= S3BootScriptGetEntryAddAddress (Length
);
1100 if (Script
== NULL
) {
1101 return RETURN_OUT_OF_RESOURCES
;
1104 // Build script data
1106 ScriptMemWrite
.OpCode
= EFI_BOOT_SCRIPT_MEM_WRITE_OPCODE
;
1107 ScriptMemWrite
.Length
= Length
;
1108 ScriptMemWrite
.Width
= Width
;
1109 ScriptMemWrite
.Address
= Address
;
1110 ScriptMemWrite
.Count
= (UINT32
) Count
;
1112 CopyMem ((VOID
*)Script
, (VOID
*)&ScriptMemWrite
, sizeof(EFI_BOOT_SCRIPT_MEM_WRITE
));
1113 CopyMem ((VOID
*)(Script
+ sizeof (EFI_BOOT_SCRIPT_MEM_WRITE
)), Buffer
, WidthInByte
* Count
);
1115 SyncBootScript (Script
);
1117 return RETURN_SUCCESS
;
1120 Adds a record for a memory modify operation into a specified boot script table.
1122 @param Width The width of the I/O operations.Enumerated in S3_BOOT_SCRIPT_LIB_WIDTH.
1123 @param Address The base address of the memory operations. Address needs alignment if required
1124 @param Data A pointer to the data to be OR-ed.
1125 @param DataMask A pointer to the data mask to be AND-ed with the data read from the register.
1127 @retval RETURN_OUT_OF_RESOURCES Not enough memory for the table do operation.
1128 @retval RETURN_SUCCESS Opcode is added.
1132 S3BootScriptSaveMemReadWrite (
1133 IN S3_BOOT_SCRIPT_LIB_WIDTH Width
,
1142 EFI_BOOT_SCRIPT_MEM_READ_WRITE ScriptMemReadWrite
;
1144 WidthInByte
= (UINT8
) (0x01 << (Width
& 0x03));
1145 Length
= (UINT8
)(sizeof (EFI_BOOT_SCRIPT_MEM_READ_WRITE
) + (WidthInByte
* 2));
1147 Script
= S3BootScriptGetEntryAddAddress (Length
);
1148 if (Script
== NULL
) {
1149 return RETURN_OUT_OF_RESOURCES
;
1152 // Build script data
1154 ScriptMemReadWrite
.OpCode
= EFI_BOOT_SCRIPT_MEM_READ_WRITE_OPCODE
;
1155 ScriptMemReadWrite
.Length
= Length
;
1156 ScriptMemReadWrite
.Width
= Width
;
1157 ScriptMemReadWrite
.Address
= Address
;
1159 CopyMem ((VOID
*)Script
, (VOID
*)&ScriptMemReadWrite
, sizeof (EFI_BOOT_SCRIPT_MEM_READ_WRITE
));
1160 CopyMem ((VOID
*)(Script
+ sizeof (EFI_BOOT_SCRIPT_MEM_READ_WRITE
)), Data
, WidthInByte
);
1161 CopyMem ((VOID
*)(Script
+ sizeof (EFI_BOOT_SCRIPT_MEM_READ_WRITE
) + WidthInByte
), DataMask
, WidthInByte
);
1163 SyncBootScript (Script
);
1165 return RETURN_SUCCESS
;
1168 Adds a record for a PCI configuration space write operation into a specified boot script table.
1170 @param Width The width of the I/O operations.Enumerated in S3_BOOT_SCRIPT_LIB_WIDTH.
1171 @param Address The address within the PCI configuration space.
1172 @param Count The number of PCI operations to perform.
1173 @param Buffer The source buffer from which to write the data.
1175 @retval RETURN_OUT_OF_RESOURCES Not enough memory for the table do operation.
1176 @retval RETURN_SUCCESS Opcode is added.
1177 @note A known Limitations in the implementation which is 64bits operations are not supported.
1182 S3BootScriptSavePciCfgWrite (
1183 IN S3_BOOT_SCRIPT_LIB_WIDTH Width
,
1192 EFI_BOOT_SCRIPT_PCI_CONFIG_WRITE ScriptPciWrite
;
1194 if (Width
== S3BootScriptWidthUint64
||
1195 Width
== S3BootScriptWidthFifoUint64
||
1196 Width
== S3BootScriptWidthFillUint64
) {
1197 return EFI_INVALID_PARAMETER
;
1200 WidthInByte
= (UINT8
) (0x01 << (Width
& 0x03));
1201 Length
= (UINT8
)(sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG_WRITE
) + (WidthInByte
* Count
));
1203 Script
= S3BootScriptGetEntryAddAddress (Length
);
1204 if (Script
== NULL
) {
1205 return RETURN_OUT_OF_RESOURCES
;
1208 // Build script data
1210 ScriptPciWrite
.OpCode
= EFI_BOOT_SCRIPT_PCI_CONFIG_WRITE_OPCODE
;
1211 ScriptPciWrite
.Length
= Length
;
1212 ScriptPciWrite
.Width
= Width
;
1213 ScriptPciWrite
.Address
= Address
;
1214 ScriptPciWrite
.Count
= (UINT32
) Count
;
1216 CopyMem ((VOID
*)Script
, (VOID
*)&ScriptPciWrite
, sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG_WRITE
));
1217 CopyMem ((VOID
*)(Script
+ sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG_WRITE
)), Buffer
, WidthInByte
* Count
);
1219 SyncBootScript (Script
);
1221 return RETURN_SUCCESS
;
1224 Adds a record for a PCI configuration space modify operation into a specified boot script table.
1226 @param Width The width of the I/O operations.Enumerated in S3_BOOT_SCRIPT_LIB_WIDTH.
1227 @param Address The address within the PCI configuration space.
1228 @param Data A pointer to the data to be OR-ed.The size depends on Width.
1229 @param DataMask A pointer to the data mask to be AND-ed.
1231 @retval RETURN_OUT_OF_RESOURCES Not enough memory for the table do operation.
1232 @retval RETURN__SUCCESS Opcode is added.
1233 @note A known Limitations in the implementation which is 64bits operations are not supported.
1238 S3BootScriptSavePciCfgReadWrite (
1239 IN S3_BOOT_SCRIPT_LIB_WIDTH Width
,
1248 EFI_BOOT_SCRIPT_PCI_CONFIG_READ_WRITE ScriptPciReadWrite
;
1250 if (Width
== S3BootScriptWidthUint64
||
1251 Width
== S3BootScriptWidthFifoUint64
||
1252 Width
== S3BootScriptWidthFillUint64
) {
1253 return EFI_INVALID_PARAMETER
;
1256 WidthInByte
= (UINT8
) (0x01 << (Width
& 0x03));
1257 Length
= (UINT8
)(sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG_READ_WRITE
) + (WidthInByte
* 2));
1259 Script
= S3BootScriptGetEntryAddAddress (Length
);
1260 if (Script
== NULL
) {
1261 return RETURN_OUT_OF_RESOURCES
;
1264 // Build script data
1266 ScriptPciReadWrite
.OpCode
= EFI_BOOT_SCRIPT_PCI_CONFIG_READ_WRITE_OPCODE
;
1267 ScriptPciReadWrite
.Length
= Length
;
1268 ScriptPciReadWrite
.Width
= Width
;
1269 ScriptPciReadWrite
.Address
= Address
;
1271 CopyMem ((VOID
*)Script
, (VOID
*)&ScriptPciReadWrite
, sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG_READ_WRITE
));
1272 CopyMem ((VOID
*)(Script
+ sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG_READ_WRITE
)), Data
, WidthInByte
);
1274 (VOID
*)(Script
+ sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG_READ_WRITE
) + WidthInByte
),
1279 SyncBootScript (Script
);
1281 return RETURN_SUCCESS
;
1284 Adds a record for a PCI configuration 2 space write operation into a specified boot script table.
1286 @param Width The width of the I/O operations.Enumerated in S3_BOOT_SCRIPT_LIB_WIDTH.
1287 @param Segment The PCI segment number for Address.
1288 @param Address The address within the PCI configuration space.
1289 @param Count The number of PCI operations to perform.
1290 @param Buffer The source buffer from which to write the data.
1292 @retval RETURN_OUT_OF_RESOURCES Not enough memory for the table do operation.
1293 @retval RETURN_SUCCESS Opcode is added.
1294 @note A known Limitations in the implementation which is non-zero Segment and 64bits operations are not supported.
1299 S3BootScriptSavePciCfg2Write (
1300 IN S3_BOOT_SCRIPT_LIB_WIDTH Width
,
1310 EFI_BOOT_SCRIPT_PCI_CONFIG2_WRITE ScriptPciWrite2
;
1313 Width
== S3BootScriptWidthUint64
||
1314 Width
== S3BootScriptWidthFifoUint64
||
1315 Width
== S3BootScriptWidthFillUint64
) {
1316 return EFI_INVALID_PARAMETER
;
1319 WidthInByte
= (UINT8
) (0x01 << (Width
& 0x03));
1320 Length
= (UINT8
)(sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG2_WRITE
) + (WidthInByte
* Count
));
1322 Script
= S3BootScriptGetEntryAddAddress (Length
);
1323 if (Script
== NULL
) {
1324 return RETURN_OUT_OF_RESOURCES
;
1327 // Build script data
1329 ScriptPciWrite2
.OpCode
= EFI_BOOT_SCRIPT_PCI_CONFIG2_WRITE_OPCODE
;
1330 ScriptPciWrite2
.Length
= Length
;
1331 ScriptPciWrite2
.Width
= Width
;
1332 ScriptPciWrite2
.Address
= Address
;
1333 ScriptPciWrite2
.Segment
= Segment
;
1334 ScriptPciWrite2
.Count
= (UINT32
)Count
;
1336 CopyMem ((VOID
*)Script
, (VOID
*)&ScriptPciWrite2
, sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG2_WRITE
));
1337 CopyMem ((VOID
*)(Script
+ sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG2_WRITE
)), Buffer
, WidthInByte
* Count
);
1339 SyncBootScript (Script
);
1341 return RETURN_SUCCESS
;
1344 Adds a record for a PCI configuration 2 space modify operation into a specified boot script table.
1346 @param Width The width of the I/O operations.Enumerated in S3_BOOT_SCRIPT_LIB_WIDTH.
1347 @param Segment The PCI segment number for Address.
1348 @param Address The address within the PCI configuration space.
1349 @param Data A pointer to the data to be OR-ed. The size depends on Width.
1350 @param DataMask A pointer to the data mask to be AND-ed.
1352 @retval RETURN_OUT_OF_RESOURCES Not enough memory for the table do operation.
1353 @retval RETURN_SUCCESS Opcode is added.
1354 @note A known Limitations in the implementation which is non-zero Segment and 64bits operations are not supported.
1359 S3BootScriptSavePciCfg2ReadWrite (
1360 IN S3_BOOT_SCRIPT_LIB_WIDTH Width
,
1370 EFI_BOOT_SCRIPT_PCI_CONFIG2_READ_WRITE ScriptPciReadWrite2
;
1373 Width
== S3BootScriptWidthUint64
||
1374 Width
== S3BootScriptWidthFifoUint64
||
1375 Width
== S3BootScriptWidthFillUint64
) {
1376 return EFI_INVALID_PARAMETER
;
1379 WidthInByte
= (UINT8
) (0x01 << (Width
& 0x03));
1380 Length
= (UINT8
)(sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG2_READ_WRITE
) + (WidthInByte
* 2));
1382 Script
= S3BootScriptGetEntryAddAddress (Length
);
1383 if (Script
== NULL
) {
1384 return RETURN_OUT_OF_RESOURCES
;
1387 // Build script data
1389 ScriptPciReadWrite2
.OpCode
= EFI_BOOT_SCRIPT_PCI_CONFIG2_READ_WRITE_OPCODE
;
1390 ScriptPciReadWrite2
.Length
= Length
;
1391 ScriptPciReadWrite2
.Width
= Width
;
1392 ScriptPciReadWrite2
.Segment
= Segment
;
1393 ScriptPciReadWrite2
.Address
= Address
;
1395 CopyMem ((VOID
*)Script
, (VOID
*)&ScriptPciReadWrite2
, sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG2_READ_WRITE
));
1396 CopyMem ((VOID
*)(Script
+ sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG2_READ_WRITE
)), Data
, WidthInByte
);
1398 (VOID
*)(Script
+ sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG2_READ_WRITE
) + WidthInByte
),
1403 SyncBootScript (Script
);
1405 return RETURN_SUCCESS
;
1409 Checks the parameter of S3BootScriptSaveSmbusExecute().
1411 This function checks the input parameters of SmbusExecute(). If the input parameters are valid
1412 for certain SMBus bus protocol, it will return EFI_SUCCESS; otherwise, it will return certain
1413 error code based on the input SMBus bus protocol.
1415 @param SmBusAddress Address that encodes the SMBUS Slave Address, SMBUS Command, SMBUS Data Length,
1417 @param Operation Signifies which particular SMBus hardware protocol instance that
1418 it will use to execute the SMBus transactions. This SMBus
1419 hardware protocol is defined by the SMBus Specification and is
1421 @param Length Signifies the number of bytes that this operation will do. The
1422 maximum number of bytes can be revision specific and operation
1423 specific. This field will contain the actual number of bytes that
1424 are executed for this operation. Not all operations require this
1426 @param Buffer Contains the value of data to execute to the SMBus slave device.
1427 Not all operations require this argument. The length of this
1428 buffer is identified by Length.
1430 @retval EFI_SUCCESS All the parameters are valid for the corresponding SMBus bus
1432 @retval EFI_INVALID_PARAMETER Operation is not defined in EFI_SMBUS_OPERATION.
1433 @retval EFI_INVALID_PARAMETER Length/Buffer is NULL for operations except for EfiSmbusQuickRead
1434 and EfiSmbusQuickWrite. Length is outside the range of valid
1436 @retval EFI_UNSUPPORTED The SMBus operation or PEC is not supported.
1437 @retval EFI_BUFFER_TOO_SMALL Buffer is not sufficient for this operation.
1442 IN UINTN SmBusAddress
,
1443 IN EFI_SMBUS_OPERATION Operation
,
1444 IN OUT UINTN
*Length
,
1450 EFI_SMBUS_DEVICE_COMMAND Command
;
1453 Command
= SMBUS_LIB_COMMAND (SmBusAddress
);
1454 PecCheck
= SMBUS_LIB_PEC (SmBusAddress
);
1456 // Set default value to be 2:
1457 // for SmbusReadWord, SmbusWriteWord and SmbusProcessCall.
1460 Status
= EFI_SUCCESS
;
1461 switch (Operation
) {
1462 case EfiSmbusQuickRead
:
1463 case EfiSmbusQuickWrite
:
1464 if (PecCheck
|| Command
!= 0) {
1465 return EFI_UNSUPPORTED
;
1468 case EfiSmbusReceiveByte
:
1469 case EfiSmbusSendByte
:
1471 return EFI_UNSUPPORTED
;
1474 // Cascade to check length parameter.
1476 case EfiSmbusReadByte
:
1477 case EfiSmbusWriteByte
:
1480 // Cascade to check length parameter.
1482 case EfiSmbusReadWord
:
1483 case EfiSmbusWriteWord
:
1484 case EfiSmbusProcessCall
:
1485 if (Buffer
== NULL
|| Length
== NULL
) {
1486 return EFI_INVALID_PARAMETER
;
1487 } else if (*Length
< RequiredLen
) {
1488 Status
= EFI_BUFFER_TOO_SMALL
;
1490 *Length
= RequiredLen
;
1492 case EfiSmbusReadBlock
:
1493 case EfiSmbusWriteBlock
:
1494 case EfiSmbusBWBRProcessCall
:
1495 if ((Buffer
== NULL
) ||
1497 (*Length
< MIN_SMBUS_BLOCK_LEN
) ||
1498 (*Length
> MAX_SMBUS_BLOCK_LEN
)) {
1499 return EFI_INVALID_PARAMETER
;
1503 return EFI_INVALID_PARAMETER
;
1509 Adds a record for an SMBus command execution into a specified boot script table.
1511 @param SmBusAddress Address that encodes the SMBUS Slave Address, SMBUS Command, SMBUS Data Length, and PEC.
1512 @param Operation Indicates which particular SMBus protocol it will use to execute the SMBus
1514 @param Length A pointer to signify the number of bytes that this operation will do.
1515 @param Buffer Contains the value of data to execute to the SMBUS slave device.
1517 @retval RETURN_OUT_OF_RESOURCES Not enough memory for the table do operation.
1518 @retval RETURN_SUCCESS Opcode is added.
1522 S3BootScriptSaveSmbusExecute (
1523 IN UINTN SmBusAddress
,
1524 IN EFI_SMBUS_OPERATION Operation
,
1533 EFI_BOOT_SCRIPT_SMBUS_EXECUTE ScriptSmbusExecute
;
1535 if (Length
== NULL
) {
1538 BufferLength
= *Length
;
1541 Status
= CheckParameters (SmBusAddress
, Operation
, &BufferLength
, Buffer
);
1542 if (EFI_ERROR (Status
)) {
1546 DataSize
= (UINT8
)(sizeof (EFI_BOOT_SCRIPT_SMBUS_EXECUTE
) + BufferLength
);
1548 Script
= S3BootScriptGetEntryAddAddress (DataSize
);
1549 if (Script
== NULL
) {
1550 return RETURN_OUT_OF_RESOURCES
;
1553 // Build script data
1555 ScriptSmbusExecute
.OpCode
= EFI_BOOT_SCRIPT_SMBUS_EXECUTE_OPCODE
;
1556 ScriptSmbusExecute
.Length
= DataSize
;
1557 ScriptSmbusExecute
.SmBusAddress
= (UINT64
) SmBusAddress
;
1558 ScriptSmbusExecute
.Operation
= Operation
;
1559 ScriptSmbusExecute
.DataSize
= (UINT32
) BufferLength
;
1561 CopyMem ((VOID
*)Script
, (VOID
*)&ScriptSmbusExecute
, sizeof (EFI_BOOT_SCRIPT_SMBUS_EXECUTE
));
1563 (VOID
*)(Script
+ sizeof (EFI_BOOT_SCRIPT_SMBUS_EXECUTE
)),
1568 SyncBootScript (Script
);
1570 return RETURN_SUCCESS
;
1573 Adds a record for an execution stall on the processor into a specified boot script table.
1575 @param Duration Duration in microseconds of the stall
1577 @retval RETURN_OUT_OF_RESOURCES Not enough memory for the table do operation.
1578 @retval RETURN_SUCCESS Opcode is added.
1582 S3BootScriptSaveStall (
1588 EFI_BOOT_SCRIPT_STALL ScriptStall
;
1590 Length
= (UINT8
)(sizeof (EFI_BOOT_SCRIPT_STALL
));
1592 Script
= S3BootScriptGetEntryAddAddress (Length
);
1593 if (Script
== NULL
) {
1594 return RETURN_OUT_OF_RESOURCES
;
1597 // Build script data
1599 ScriptStall
.OpCode
= EFI_BOOT_SCRIPT_STALL_OPCODE
;
1600 ScriptStall
.Length
= Length
;
1601 ScriptStall
.Duration
= Duration
;
1603 CopyMem ((VOID
*)Script
, (VOID
*)&ScriptStall
, sizeof (EFI_BOOT_SCRIPT_STALL
));
1605 SyncBootScript (Script
);
1607 return RETURN_SUCCESS
;
1610 Adds a record for dispatching specified arbitrary code into a specified boot script table.
1612 @param EntryPoint Entry point of the code to be dispatched.
1613 @param Context Argument to be passed into the EntryPoint of the code to be dispatched.
1615 @retval RETURN_OUT_OF_RESOURCES Not enough memory for the table do operation.
1616 @retval RETURN_SUCCESS Opcode is added.
1620 S3BootScriptSaveDispatch2 (
1621 IN VOID
*EntryPoint
,
1627 EFI_BOOT_SCRIPT_DISPATCH_2 ScriptDispatch2
;
1628 Length
= (UINT8
)(sizeof (EFI_BOOT_SCRIPT_DISPATCH_2
));
1630 Script
= S3BootScriptGetEntryAddAddress (Length
);
1631 if (Script
== NULL
) {
1632 return RETURN_OUT_OF_RESOURCES
;
1635 // Build script data
1637 ScriptDispatch2
.OpCode
= EFI_BOOT_SCRIPT_DISPATCH_2_OPCODE
;
1638 ScriptDispatch2
.Length
= Length
;
1639 ScriptDispatch2
.EntryPoint
= (EFI_PHYSICAL_ADDRESS
)(UINTN
)EntryPoint
;
1640 ScriptDispatch2
.Context
= (EFI_PHYSICAL_ADDRESS
)(UINTN
)Context
;
1642 CopyMem ((VOID
*)Script
, (VOID
*)&ScriptDispatch2
, sizeof (EFI_BOOT_SCRIPT_DISPATCH_2
));
1644 SyncBootScript (Script
);
1646 return RETURN_SUCCESS
;
1650 Adds a record for memory reads of the memory location and continues when the exit criteria is
1651 satisfied or after a defined duration.
1653 Please aware, below interface is different with PI specification, Vol 5:
1654 EFI_S3_SAVE_STATE_PROTOCOL.Write() for EFI_BOOT_SCRIPT_MEM_POLL_OPCODE.
1655 "Duration" below is microseconds, while "Delay" in PI specification means
1656 the number of 100ns units to poll.
1658 @param Width The width of the memory operations.
1659 @param Address The base address of the memory operations.
1660 @param BitMask A pointer to the bit mask to be AND-ed with the data read from the register.
1661 @param BitValue A pointer to the data value after to be Masked.
1662 @param Duration Duration in microseconds of the stall.
1663 @param LoopTimes The times of the register polling.
1665 @retval RETURN_OUT_OF_RESOURCES Not enough memory for the table do operation.
1666 @retval RETURN_SUCCESS Opcode is added.
1671 S3BootScriptSaveMemPoll (
1672 IN S3_BOOT_SCRIPT_LIB_WIDTH Width
,
1683 EFI_BOOT_SCRIPT_MEM_POLL ScriptMemPoll
;
1685 WidthInByte
= (UINT8
) (0x01 << (Width
& 0x03));
1687 Length
= (UINT8
)(sizeof (EFI_BOOT_SCRIPT_MEM_POLL
) + (WidthInByte
* 2));
1689 Script
= S3BootScriptGetEntryAddAddress (Length
);
1690 if (Script
== NULL
) {
1691 return RETURN_OUT_OF_RESOURCES
;
1694 // Build script data
1696 ScriptMemPoll
.OpCode
= EFI_BOOT_SCRIPT_MEM_POLL_OPCODE
;
1697 ScriptMemPoll
.Length
= Length
;
1698 ScriptMemPoll
.Width
= Width
;
1699 ScriptMemPoll
.Address
= Address
;
1700 ScriptMemPoll
.Duration
= Duration
;
1701 ScriptMemPoll
.LoopTimes
= LoopTimes
;
1703 CopyMem ((UINT8
*) (Script
+ sizeof (EFI_BOOT_SCRIPT_MEM_POLL
)), BitValue
, WidthInByte
);
1704 CopyMem ((UINT8
*) (Script
+ sizeof (EFI_BOOT_SCRIPT_MEM_POLL
) + WidthInByte
), BitMask
, WidthInByte
);
1705 CopyMem ((VOID
*)Script
, (VOID
*)&ScriptMemPoll
, sizeof (EFI_BOOT_SCRIPT_MEM_POLL
));
1707 SyncBootScript (Script
);
1709 return RETURN_SUCCESS
;
1712 Store arbitrary information in the boot script table. This opcode is a no-op on dispatch and is only
1713 used for debugging script issues.
1715 @param InformationLength Length of the data in bytes
1716 @param Information Information to be logged in the boot scrpit
1718 @retval RETURN_OUT_OF_RESOURCES Not enough memory for the table do operation.
1719 @retval RETURN_SUCCESS Opcode is added.
1724 S3BootScriptSaveInformation (
1725 IN UINT32 InformationLength
,
1726 IN VOID
*Information
1731 EFI_BOOT_SCRIPT_INFORMATION ScriptInformation
;
1733 Length
= (UINT8
)(sizeof (EFI_BOOT_SCRIPT_INFORMATION
) + InformationLength
);
1735 Script
= S3BootScriptGetEntryAddAddress (Length
);
1736 if (Script
== NULL
) {
1737 return RETURN_OUT_OF_RESOURCES
;
1740 // Build script data
1742 ScriptInformation
.OpCode
= EFI_BOOT_SCRIPT_INFORMATION_OPCODE
;
1743 ScriptInformation
.Length
= Length
;
1746 ScriptInformation
.InformationLength
= InformationLength
;
1748 CopyMem ((VOID
*)Script
, (VOID
*)&ScriptInformation
, sizeof (EFI_BOOT_SCRIPT_INFORMATION
));
1749 CopyMem ((VOID
*)(Script
+ sizeof (EFI_BOOT_SCRIPT_INFORMATION
)), (VOID
*) Information
, (UINTN
) InformationLength
);
1751 SyncBootScript (Script
);
1753 return RETURN_SUCCESS
;
1757 Store a string in the boot script table. This opcode is a no-op on dispatch and is only
1758 used for debugging script issues.
1760 @param String The string to save to boot script table
1762 @retval RETURN_OUT_OF_RESOURCES Not enough memory for the table do operation.
1763 @retval RETURN_SUCCESS Opcode is added.
1768 S3BootScriptSaveInformationAsciiString (
1769 IN CONST CHAR8
*String
1772 return S3BootScriptSaveInformation (
1773 (UINT32
) AsciiStrLen (String
) + 1,
1778 Adds a record for dispatching specified arbitrary code into a specified boot script table.
1780 @param EntryPoint Entry point of the code to be dispatched.
1782 @retval RETURN_OUT_OF_RESOURCES Not enough memory for the table do operation.
1783 @retval RETURN_SUCCESS Opcode is added.
1787 S3BootScriptSaveDispatch (
1793 EFI_BOOT_SCRIPT_DISPATCH ScriptDispatch
;
1795 Length
= (UINT8
)(sizeof (EFI_BOOT_SCRIPT_DISPATCH
));
1797 Script
= S3BootScriptGetEntryAddAddress (Length
);
1798 if (Script
== NULL
) {
1799 return RETURN_OUT_OF_RESOURCES
;
1802 // Build script data
1804 ScriptDispatch
.OpCode
= EFI_BOOT_SCRIPT_DISPATCH_OPCODE
;
1805 ScriptDispatch
.Length
= Length
;
1806 ScriptDispatch
.EntryPoint
= (EFI_PHYSICAL_ADDRESS
)(UINTN
)EntryPoint
;
1808 CopyMem ((VOID
*)Script
, (VOID
*)&ScriptDispatch
, sizeof (EFI_BOOT_SCRIPT_DISPATCH
));
1810 SyncBootScript (Script
);
1812 return RETURN_SUCCESS
;
1816 Adds a record for I/O reads the I/O location and continues when the exit criteria is satisfied or after a
1819 @param Width The width of the I/O operations.
1820 @param Address The base address of the I/O operations.
1821 @param Data The comparison value used for the polling exit criteria.
1822 @param DataMask Mask used for the polling criteria. The bits in the bytes below Width which are zero
1823 in Data are ignored when polling the memory address.
1824 @param Delay The number of 100ns units to poll. Note that timer available may be of poorer
1825 granularity so the delay may be longer.
1827 @retval RETURN_OUT_OF_RESOURCES Not enough memory for the table do operation.
1828 @retval RETURN_SUCCESS Opcode is added.
1833 S3BootScriptSaveIoPoll (
1834 IN S3_BOOT_SCRIPT_LIB_WIDTH Width
,
1844 EFI_BOOT_SCRIPT_IO_POLL ScriptIoPoll
;
1847 WidthInByte
= (UINT8
) (0x01 << (Width
& 0x03));
1848 Length
= (UINT8
)(sizeof (EFI_BOOT_SCRIPT_IO_POLL
) + (WidthInByte
* 2));
1850 Script
= S3BootScriptGetEntryAddAddress (Length
);
1851 if (Script
== NULL
) {
1852 return RETURN_OUT_OF_RESOURCES
;
1855 // Build script data
1857 ScriptIoPoll
.OpCode
= EFI_BOOT_SCRIPT_IO_POLL_OPCODE
;
1858 ScriptIoPoll
.Length
= (UINT8
) (sizeof (EFI_BOOT_SCRIPT_IO_POLL
) + (WidthInByte
* 2));
1859 ScriptIoPoll
.Width
= Width
;
1860 ScriptIoPoll
.Address
= Address
;
1861 ScriptIoPoll
.Delay
= Delay
;
1863 CopyMem ((VOID
*)Script
, (VOID
*)&ScriptIoPoll
, sizeof (EFI_BOOT_SCRIPT_IO_POLL
));
1864 CopyMem ((UINT8
*) (Script
+ sizeof (EFI_BOOT_SCRIPT_IO_POLL
)), Data
, WidthInByte
);
1865 CopyMem ((UINT8
*) (Script
+ sizeof (EFI_BOOT_SCRIPT_IO_POLL
) + WidthInByte
), DataMask
, WidthInByte
);
1867 SyncBootScript (Script
);
1869 return RETURN_SUCCESS
;
1873 Adds a record for PCI configuration space reads and continues when the exit criteria is satisfied or
1874 after a defined duration.
1876 @param Width The width of the I/O operations.
1877 @param Address The address within the PCI configuration space.
1878 @param Data The comparison value used for the polling exit criteria.
1879 @param DataMask Mask used for the polling criteria. The bits in the bytes below Width which are zero
1880 in Data are ignored when polling the memory address
1881 @param Delay The number of 100ns units to poll. Note that timer available may be of poorer
1882 granularity so the delay may be longer.
1884 @retval RETURN_OUT_OF_RESOURCES Not enough memory for the table do operation.
1885 @retval RETURN_SUCCESS Opcode is added.
1886 @note A known Limitations in the implementation which is 64bits operations are not supported.
1891 S3BootScriptSavePciPoll (
1892 IN S3_BOOT_SCRIPT_LIB_WIDTH Width
,
1902 EFI_BOOT_SCRIPT_PCI_CONFIG_POLL ScriptPciPoll
;
1904 if (Width
== S3BootScriptWidthUint64
||
1905 Width
== S3BootScriptWidthFifoUint64
||
1906 Width
== S3BootScriptWidthFillUint64
) {
1907 return EFI_INVALID_PARAMETER
;
1910 WidthInByte
= (UINT8
) (0x01 << (Width
& 0x03));
1911 Length
= (UINT8
)(sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG_POLL
) + (WidthInByte
* 2));
1913 Script
= S3BootScriptGetEntryAddAddress (Length
);
1914 if (Script
== NULL
) {
1915 return RETURN_OUT_OF_RESOURCES
;
1918 // Build script data
1920 ScriptPciPoll
.OpCode
= EFI_BOOT_SCRIPT_PCI_CONFIG_POLL_OPCODE
;
1921 ScriptPciPoll
.Length
= (UINT8
) (sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG_POLL
) + (WidthInByte
* 2));
1922 ScriptPciPoll
.Width
= Width
;
1923 ScriptPciPoll
.Address
= Address
;
1924 ScriptPciPoll
.Delay
= Delay
;
1926 CopyMem ((VOID
*)Script
, (VOID
*)&ScriptPciPoll
, sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG_POLL
));
1927 CopyMem ((UINT8
*) (Script
+ sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG_POLL
)), Data
, WidthInByte
);
1928 CopyMem ((UINT8
*) (Script
+ sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG_POLL
) + WidthInByte
), DataMask
, WidthInByte
);
1930 SyncBootScript (Script
);
1932 return RETURN_SUCCESS
;
1935 Adds a record for PCI configuration space reads and continues when the exit criteria is satisfied or
1936 after a defined duration.
1938 @param Width The width of the I/O operations.
1939 @param Segment The PCI segment number for Address.
1940 @param Address The address within the PCI configuration space.
1941 @param Data The comparison value used for the polling exit criteria.
1942 @param DataMask Mask used for the polling criteria. The bits in the bytes below Width which are zero
1943 in Data are ignored when polling the memory address
1944 @param Delay The number of 100ns units to poll. Note that timer available may be of poorer
1945 granularity so the delay may be longer.
1947 @retval RETURN_OUT_OF_RESOURCES Not enough memory for the table do operation.
1948 @retval RETURN_SUCCESS Opcode is added.
1949 @note A known Limitations in the implementation which is non-zero Segment and 64bits operations are not supported.
1954 S3BootScriptSavePci2Poll (
1955 IN S3_BOOT_SCRIPT_LIB_WIDTH Width
,
1966 EFI_BOOT_SCRIPT_PCI_CONFIG2_POLL ScriptPci2Poll
;
1969 Width
== S3BootScriptWidthUint64
||
1970 Width
== S3BootScriptWidthFifoUint64
||
1971 Width
== S3BootScriptWidthFillUint64
) {
1972 return EFI_INVALID_PARAMETER
;
1975 WidthInByte
= (UINT8
) (0x01 << (Width
& 0x03));
1976 Length
= (UINT8
)(sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG2_POLL
) + (WidthInByte
* 2));
1978 Script
= S3BootScriptGetEntryAddAddress (Length
);
1979 if (Script
== NULL
) {
1980 return RETURN_OUT_OF_RESOURCES
;
1983 // Build script data
1985 ScriptPci2Poll
.OpCode
= EFI_BOOT_SCRIPT_PCI_CONFIG2_POLL_OPCODE
;
1986 ScriptPci2Poll
.Length
= (UINT8
) (sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG2_POLL
) + (WidthInByte
* 2));
1987 ScriptPci2Poll
.Width
= Width
;
1988 ScriptPci2Poll
.Segment
= Segment
;
1989 ScriptPci2Poll
.Address
= Address
;
1990 ScriptPci2Poll
.Delay
= Delay
;
1992 CopyMem ((VOID
*)Script
, (VOID
*)&ScriptPci2Poll
, sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG2_POLL
));
1993 CopyMem ((UINT8
*) (Script
+ sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG2_POLL
)), Data
, WidthInByte
);
1994 CopyMem ((UINT8
*) (Script
+ sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG2_POLL
) + WidthInByte
), DataMask
, WidthInByte
);
1996 SyncBootScript (Script
);
1998 return RETURN_SUCCESS
;
2001 Do the calculation of start address from which a new s3 boot script entry will write into.
2003 @param EntryLength The new entry length.
2004 @param Position specifies the position in the boot script table where the opcode will be
2005 inserted, either before or after, depending on BeforeOrAfter.
2006 @param BeforeOrAfter The flag to indicate to insert the nod before or after the position.
2007 This parameter is effective when InsertFlag is TRUE
2008 @param Script return out the position from which the a new s3 boot script entry will write into
2011 S3BootScriptCalculateInsertAddress (
2012 IN UINT8 EntryLength
,
2013 IN VOID
*Position OPTIONAL
,
2014 IN BOOLEAN BeforeOrAfter OPTIONAL
,
2020 UINTN PositionOffset
;
2021 EFI_BOOT_SCRIPT_COMMON_HEADER ScriptHeader
;
2023 // The entry inserting to table is already added to the end of the table
2025 TableLength
= mS3BootScriptTablePtr
->TableLength
- EntryLength
;
2026 S3TableBase
= mS3BootScriptTablePtr
->TableBase
;
2028 // calculate the Position offset
2030 if (Position
!= NULL
) {
2031 PositionOffset
= (UINTN
) ((UINT8
*)Position
- S3TableBase
);
2034 // If the BeforeOrAfter is FALSE, that means to insert the node right after the node.
2036 if (!BeforeOrAfter
) {
2037 CopyMem ((VOID
*)&ScriptHeader
, Position
, sizeof(EFI_BOOT_SCRIPT_COMMON_HEADER
));
2038 PositionOffset
+= (ScriptHeader
.Length
);
2041 // Insert the node before the adjusted Position
2043 CopyMem (S3TableBase
+PositionOffset
+EntryLength
, S3TableBase
+PositionOffset
, TableLength
- PositionOffset
);
2045 // calculate the the start address for the new entry.
2047 *Script
= S3TableBase
+ PositionOffset
;
2050 if (!BeforeOrAfter
) {
2052 // Insert the node to the end of the table
2054 *Script
= S3TableBase
+ TableLength
;
2057 // Insert the node to the beginning of the table
2059 PositionOffset
= (UINTN
) sizeof(EFI_BOOT_SCRIPT_TABLE_HEADER
);
2060 CopyMem (S3TableBase
+PositionOffset
+EntryLength
, S3TableBase
+PositionOffset
, TableLength
- PositionOffset
);
2061 *Script
= S3TableBase
+ PositionOffset
;
2066 Move the last boot script entry to the position
2068 @param BeforeOrAfter Specifies whether the opcode is stored before (TRUE) or after (FALSE) the position
2069 in the boot script table specified by Position. If Position is NULL or points to
2070 NULL then the new opcode is inserted at the beginning of the table (if TRUE) or end
2071 of the table (if FALSE).
2072 @param Position On entry, specifies the position in the boot script table where the opcode will be
2073 inserted, either before or after, depending on BeforeOrAfter. On exit, specifies
2074 the position of the inserted opcode in the boot script table.
2076 @retval RETURN_OUT_OF_RESOURCES The table is not available.
2077 @retval RETURN_INVALID_PARAMETER The Position is not a valid position in the boot script table.
2078 @retval RETURN_SUCCESS Opcode is inserted.
2082 S3BootScriptMoveLastOpcode (
2083 IN BOOLEAN BeforeOrAfter
,
2084 IN OUT VOID
**Position OPTIONAL
2091 EFI_BOOT_SCRIPT_COMMON_HEADER ScriptHeader
;
2092 BOOLEAN ValidatePosition
;
2094 UINT8 TempBootScriptEntry
[BOOT_SCRIPT_NODE_MAX_LENGTH
];
2096 ValidatePosition
= FALSE
;
2097 TempPosition
= (Position
== NULL
) ? NULL
:(*Position
);
2100 // Check that the script is initialized and synced without adding an entry to the script.
2102 Script
= S3BootScriptGetEntryAddAddress (0);
2103 if (Script
== NULL
) {
2104 return RETURN_OUT_OF_RESOURCES
;
2106 Script
= mS3BootScriptTablePtr
->TableBase
;
2108 StartAddress
= (UINTN
) Script
;
2109 TableLength
= mS3BootScriptTablePtr
->TableLength
;
2110 Script
= Script
+ sizeof(EFI_BOOT_SCRIPT_TABLE_HEADER
);
2111 LastOpcode
= Script
;
2113 // Find the last boot Script Entry which is not the terminate node
2115 while ((UINTN
) Script
< (UINTN
) (StartAddress
+ TableLength
)) {
2116 CopyMem ((VOID
*)&ScriptHeader
, Script
, sizeof(EFI_BOOT_SCRIPT_COMMON_HEADER
));
2117 if (TempPosition
!= NULL
&& TempPosition
== Script
) {
2119 // If the position is specified, the position must be pointed to a boot script entry start address.
2121 ValidatePosition
= TRUE
;
2123 if (ScriptHeader
.OpCode
!= S3_BOOT_SCRIPT_LIB_TERMINATE_OPCODE
) {
2124 LastOpcode
= Script
;
2126 Script
= Script
+ ScriptHeader
.Length
;
2129 // If the position is specified, but not the start of a boot script entry, it is a invalid input
2131 if (TempPosition
!= NULL
&& !ValidatePosition
) {
2132 return RETURN_INVALID_PARAMETER
;
2135 CopyMem ((VOID
*)&ScriptHeader
, LastOpcode
, sizeof(EFI_BOOT_SCRIPT_COMMON_HEADER
));
2137 CopyMem((VOID
*)TempBootScriptEntry
, LastOpcode
, ScriptHeader
.Length
);
2139 // Find the right position to write the node in
2141 S3BootScriptCalculateInsertAddress (
2142 ScriptHeader
.Length
,
2148 // Copy the node to Boot script table
2150 CopyMem((VOID
*)Script
, (VOID
*)TempBootScriptEntry
, ScriptHeader
.Length
);
2152 SyncBootScript (Script
);
2155 // return out the Position
2157 if (Position
!= NULL
) {
2160 return RETURN_SUCCESS
;
2163 Create a Label node in the boot script table.
2165 @param BeforeOrAfter Specifies whether the opcode is stored before (TRUE) or after (FALSE) the position
2166 in the boot script table specified by Position. If Position is NULL or points to
2167 NULL then the new opcode is inserted at the beginning of the table (if TRUE) or end
2168 of the table (if FALSE).
2169 @param Position On entry, specifies the position in the boot script table where the opcode will be
2170 inserted, either before or after, depending on BeforeOrAfter. On exit, specifies
2171 the position of the inserted opcode in the boot script table.
2172 @param InformationLength Length of the label in bytes
2173 @param Information Label to be logged in the boot scrpit
2175 @retval RETURN_INVALID_PARAMETER The Position is not a valid position in the boot script table.
2176 @retval RETURN_OUT_OF_RESOURCES Not enough memory for the table do operation.
2177 @retval RETURN_SUCCESS Opcode is added.
2182 S3BootScriptLabelInternal (
2183 IN BOOLEAN BeforeOrAfter
,
2184 IN OUT VOID
**Position OPTIONAL
,
2185 IN UINT32 InformationLength
,
2186 IN CONST CHAR8
*Information
2191 EFI_BOOT_SCRIPT_INFORMATION ScriptInformation
;
2193 Length
= (UINT8
)(sizeof (EFI_BOOT_SCRIPT_INFORMATION
) + InformationLength
);
2195 Script
= S3BootScriptGetEntryAddAddress (Length
);
2196 if (Script
== NULL
) {
2197 return RETURN_OUT_OF_RESOURCES
;
2200 // Build script data
2202 ScriptInformation
.OpCode
= S3_BOOT_SCRIPT_LIB_LABEL_OPCODE
;
2203 ScriptInformation
.Length
= Length
;
2206 ScriptInformation
.InformationLength
= InformationLength
;
2208 CopyMem ((VOID
*)Script
, (VOID
*)&ScriptInformation
, sizeof (EFI_BOOT_SCRIPT_INFORMATION
));
2209 CopyMem ((VOID
*)(Script
+ sizeof (EFI_BOOT_SCRIPT_INFORMATION
)), (VOID
*) Information
, (UINTN
) InformationLength
);
2211 SyncBootScript (Script
);
2213 return S3BootScriptMoveLastOpcode (BeforeOrAfter
, Position
);
2217 Find a label within the boot script table and, if not present, optionally create it.
2219 @param BeforeOrAfter Specifies whether the opcode is stored before (TRUE)
2220 or after (FALSE) the position in the boot script table
2221 specified by Position.
2222 @param CreateIfNotFound Specifies whether the label will be created if the label
2223 does not exists (TRUE) or not (FALSE).
2224 @param Position On entry, specifies the position in the boot script table
2225 where the opcode will be inserted, either before or after,
2226 depending on BeforeOrAfter. On exit, specifies the position
2227 of the inserted opcode in the boot script table.
2228 @param Label Points to the label which will be inserted in the boot script table.
2230 @retval EFI_SUCCESS The operation succeeded. A record was added into the
2231 specified script table.
2232 @retval EFI_INVALID_PARAMETER The parameter is illegal or the given boot script is not supported.
2233 If the opcode is unknow or not supported because of the PCD
2235 @retval EFI_OUT_OF_RESOURCES There is insufficient memory to store the boot script.
2241 IN BOOLEAN BeforeOrAfter
,
2242 IN BOOLEAN CreateIfNotFound
,
2243 IN OUT VOID
**Position OPTIONAL
,
2244 IN CONST CHAR8
*Label
2250 EFI_BOOT_SCRIPT_COMMON_HEADER ScriptHeader
;
2251 EFI_BOOT_SCRIPT_TABLE_HEADER TableHeader
;
2256 if (Label
== NULL
) {
2257 return EFI_INVALID_PARAMETER
;
2260 // Check empty Label
2262 if (Label
[0] == '\0') {
2263 return EFI_INVALID_PARAMETER
;
2267 // Check that the script is initialized and synced without adding an entry to the script.
2268 // The code must search for the label first before it knows if a new entry needs
2271 Script
= S3BootScriptGetEntryAddAddress (0);
2272 if (Script
== NULL
) {
2273 return RETURN_OUT_OF_RESOURCES
;
2277 // Check the header and search for existing label.
2279 Script
= mS3BootScriptTablePtr
->TableBase
;
2280 CopyMem ((VOID
*)&TableHeader
, Script
, sizeof(EFI_BOOT_SCRIPT_TABLE_HEADER
));
2281 if (TableHeader
.OpCode
!= S3_BOOT_SCRIPT_LIB_TABLE_OPCODE
) {
2282 return EFI_INVALID_PARAMETER
;
2284 StartAddress
= (UINTN
) Script
;
2285 TableLength
= mS3BootScriptTablePtr
->TableLength
;
2286 Script
= Script
+ TableHeader
.Length
;
2287 while ((UINTN
) Script
< (UINTN
) (StartAddress
+ TableLength
)) {
2289 CopyMem ((VOID
*)&ScriptHeader
, Script
, sizeof(EFI_BOOT_SCRIPT_COMMON_HEADER
));
2290 if (ScriptHeader
.OpCode
== S3_BOOT_SCRIPT_LIB_LABEL_OPCODE
) {
2291 if (AsciiStrCmp ((CHAR8
*)(UINTN
)(Script
+sizeof(EFI_BOOT_SCRIPT_INFORMATION
)), Label
) == 0) {
2292 (*Position
) = Script
;
2296 Script
= Script
+ ScriptHeader
.Length
;
2298 if (CreateIfNotFound
) {
2299 LabelLength
= (UINT32
)AsciiStrSize(Label
);
2300 return S3BootScriptLabelInternal (BeforeOrAfter
,Position
, LabelLength
, Label
);
2302 return EFI_NOT_FOUND
;
2307 Compare two positions in the boot script table and return their relative position.
2308 @param Position1 The positions in the boot script table to compare
2309 @param Position2 The positions in the boot script table to compare
2310 @param RelativePosition On return, points to the result of the comparison
2312 @retval EFI_SUCCESS The operation succeeded. A record was added into the
2313 specified script table.
2314 @retval EFI_INVALID_PARAMETER The parameter is illegal or the given boot script is not supported.
2315 If the opcode is unknow or not supported because of the PCD
2317 @retval EFI_OUT_OF_RESOURCES There is insufficient memory to store the boot script.
2322 S3BootScriptCompare (
2323 IN UINT8
*Position1
,
2324 IN UINT8
*Position2
,
2325 OUT UINTN
*RelativePosition
2331 if (RelativePosition
== NULL
) {
2332 return EFI_INVALID_PARAMETER
;
2336 // Check that the script is initialized and synced without adding an entry to the script.
2338 Script
= S3BootScriptGetEntryAddAddress (0);
2339 if (Script
== NULL
) {
2340 return RETURN_OUT_OF_RESOURCES
;
2342 Script
= mS3BootScriptTablePtr
->TableBase
;
2345 // mS3BootScriptTablePtr->TableLength does not include the termination node, so add it up
2347 TableLength
= mS3BootScriptTablePtr
->TableLength
+ sizeof (EFI_BOOT_SCRIPT_TERMINATE
);
2348 if (Position1
< Script
|| Position1
> Script
+TableLength
) {
2349 return EFI_INVALID_PARAMETER
;
2351 if (Position2
< Script
|| Position2
> Script
+TableLength
) {
2352 return EFI_INVALID_PARAMETER
;
2354 *RelativePosition
= (Position1
< Position2
)?-1:((Position1
== Position2
)?0:1);