2 Save the S3 data to S3 boot script.
4 Copyright (c) 2006 - 2015, 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 }
128 This is an internal function to add a terminate node the entry, recalculate the table
129 length and fill into the table.
131 @return the base address of the boot script table.
134 S3BootScriptInternalCloseTable (
139 EFI_BOOT_SCRIPT_TERMINATE ScriptTerminate
;
140 EFI_BOOT_SCRIPT_TABLE_HEADER
*ScriptTableInfo
;
141 S3TableBase
= mS3BootScriptTablePtr
->TableBase
;
143 if (S3TableBase
== NULL
) {
145 // the table is not exist
150 // Append the termination entry.
152 ScriptTerminate
.OpCode
= S3_BOOT_SCRIPT_LIB_TERMINATE_OPCODE
;
153 ScriptTerminate
.Length
= (UINT8
) sizeof (EFI_BOOT_SCRIPT_TERMINATE
);
154 CopyMem (mS3BootScriptTablePtr
->TableBase
+ mS3BootScriptTablePtr
->TableLength
, &ScriptTerminate
, sizeof (EFI_BOOT_SCRIPT_TERMINATE
));
156 // fill the table length
158 ScriptTableInfo
= (EFI_BOOT_SCRIPT_TABLE_HEADER
*)(mS3BootScriptTablePtr
->TableBase
);
159 ScriptTableInfo
->TableLength
= mS3BootScriptTablePtr
->TableLength
+ sizeof (EFI_BOOT_SCRIPT_TERMINATE
);
165 // NOTE: Here we did NOT adjust the mS3BootScriptTablePtr->TableLength to
166 // mS3BootScriptTablePtr->TableLength + sizeof (EFI_BOOT_SCRIPT_TERMINATE).
167 // Because maybe after SmmReadyToLock, we still need add entries into the table,
168 // and the entry should be added start before this TERMINATE node.
173 This function save boot script data to LockBox.
177 SaveBootScriptDataToLockBox (
184 // Save whole memory copy into LockBox.
185 // It will be used to restore data at S3 resume.
187 Status
= SaveLockBox (
188 &mBootScriptDataGuid
,
189 (VOID
*)mS3BootScriptTablePtr
->TableBase
,
190 EFI_PAGES_TO_SIZE (mS3BootScriptTablePtr
->TableMemoryPageNumber
)
192 ASSERT_EFI_ERROR (Status
);
194 Status
= SetLockBoxAttributes (&mBootScriptDataGuid
, LOCK_BOX_ATTRIBUTE_RESTORE_IN_PLACE
);
195 ASSERT_EFI_ERROR (Status
);
198 // Just need save TableBase.
199 // Do not update other field because they will NOT be used in S3.
201 Status
= SaveLockBox (
202 &mBootScriptTableBaseGuid
,
203 (VOID
*)&mS3BootScriptTablePtr
->TableBase
,
204 sizeof(mS3BootScriptTablePtr
->TableBase
)
206 ASSERT_EFI_ERROR (Status
);
208 Status
= SetLockBoxAttributes (&mBootScriptTableBaseGuid
, LOCK_BOX_ATTRIBUTE_RESTORE_IN_PLACE
);
209 ASSERT_EFI_ERROR (Status
);
213 This is the Event call back function to notify the Library the system is entering
216 @param Event Pointer to this event
217 @param Context Event handler private data
221 S3BootScriptEventCallBack (
230 // Try to locate it because EfiCreateProtocolNotifyEvent will trigger it once when registration.
231 // Just return if it is not found.
233 Status
= gBS
->LocateProtocol (
234 &gEfiDxeSmmReadyToLockProtocolGuid
,
238 if (EFI_ERROR (Status
)) {
243 // Here we should tell the library that we are entering SmmLocked phase.
244 // and the memory page number occupied by the table should not grow anymore.
246 if (!mS3BootScriptTablePtr
->SmmLocked
) {
248 // Before SmmReadyToLock, we need not write the terminate node when adding a node to boot scipt table
249 // or else, that will impact the performance. However, after SmmReadyToLock, we should append terminate
250 // node on every add to boot script table.
252 S3BootScriptInternalCloseTable ();
253 mS3BootScriptTablePtr
->SmmLocked
= TRUE
;
256 // Save BootScript data to lockbox
258 SaveBootScriptDataToLockBox ();
263 This is the Event call back function is triggered in SMM to notify the Library
264 the system is entering SmmLocked phase and set InSmm flag.
266 @param Protocol Points to the protocol's unique identifier
267 @param Interface Points to the interface instance
268 @param Handle The handle on which the interface was installed
270 @retval EFI_SUCCESS SmmEventCallback runs successfully
274 S3BootScriptSmmEventCallBack (
275 IN CONST EFI_GUID
*Protocol
,
281 // Check if it is already done
283 if (mS3BootScriptTablePtr
== mS3BootScriptTableSmmPtr
) {
288 // Last chance to call-out, just make sure SmmLocked is set.
290 S3BootScriptEventCallBack (NULL
, NULL
);
293 // Save a SMM copy. If TableBase is NOT null, it means SMM copy has been ready, skip copy mem.
295 if (mS3BootScriptTableSmmPtr
->TableBase
== NULL
) {
296 CopyMem (mS3BootScriptTableSmmPtr
, mS3BootScriptTablePtr
, sizeof(*mS3BootScriptTablePtr
));
299 // Set InSmm, we allow boot script update when InSmm, but not allow boot script outside SMM.
300 // InSmm will only be checked if SmmLocked is TRUE.
302 mS3BootScriptTableSmmPtr
->InSmm
= TRUE
;
305 // We should not use ACPI Reserved copy, because it is not safe.
307 mS3BootScriptTablePtr
= mS3BootScriptTableSmmPtr
;
313 This function is to save boot time boot script data to LockBox.
315 Because there may be INSERT boot script at runtime in SMM.
316 The boot time copy will be used to restore data after back from S3.
317 Otherwise the data inserted may cause some boot time boot script data lost
318 if only BootScriptData used.
322 SaveBootTimeDataToLockBox (
329 // ACPI Reserved copy is not safe, restore from BootScriptData LockBox first,
330 // and then save the data to BootScriptDataBootTime LockBox.
332 Status
= RestoreLockBox (
333 &mBootScriptDataGuid
,
337 ASSERT_EFI_ERROR (Status
);
340 // Save BootScriptDataBootTime
341 // It will be used to restore data after back from S3.
343 Status
= SaveLockBox (
344 &mBootScriptDataBootTimeGuid
,
345 (VOID
*) mS3BootScriptTablePtr
->TableBase
,
346 mS3BootScriptTablePtr
->BootTimeScriptLength
348 ASSERT_EFI_ERROR (Status
);
352 This function save boot script SMM private data to LockBox with BackFromS3 = TRUE at runtime.
353 S3 resume will help restore it to tell the Library the system is back from S3.
357 SaveSmmPriviateDataToLockBoxAtRuntime (
364 // Save boot script SMM private data with BackFromS3 = TRUE.
366 mS3BootScriptTablePtr
->BackFromS3
= TRUE
;
367 Status
= SaveLockBox (
368 &mBootScriptSmmPrivateDataGuid
,
369 (VOID
*) mS3BootScriptTablePtr
,
370 sizeof (SCRIPT_TABLE_PRIVATE_DATA
)
372 ASSERT_EFI_ERROR (Status
);
374 Status
= SetLockBoxAttributes (&mBootScriptSmmPrivateDataGuid
, LOCK_BOX_ATTRIBUTE_RESTORE_IN_PLACE
);
375 ASSERT_EFI_ERROR (Status
);
378 // Set BackFromS3 flag back to FALSE to indicate that now is not back from S3.
380 mS3BootScriptTablePtr
->BackFromS3
= FALSE
;
384 This is the Event call back function is triggered in SMM to notify the Library
385 the system is entering runtime phase.
387 @param[in] Protocol Points to the protocol's unique identifier
388 @param[in] Interface Points to the interface instance
389 @param[in] Handle The handle on which the interface was installed
391 @retval EFI_SUCCESS SmmAtRuntimeCallBack runs successfully
395 S3BootScriptSmmAtRuntimeCallBack (
396 IN CONST EFI_GUID
*Protocol
,
401 if (!mS3BootScriptTablePtr
->AtRuntime
) {
402 mS3BootScriptTablePtr
->BootTimeScriptLength
= (UINT32
) (mS3BootScriptTablePtr
->TableLength
+ sizeof (EFI_BOOT_SCRIPT_TERMINATE
));
403 SaveBootTimeDataToLockBox ();
405 mS3BootScriptTablePtr
->AtRuntime
= TRUE
;
406 SaveSmmPriviateDataToLockBoxAtRuntime ();
414 this function just identify it is a smm driver or non-smm driver linked against
417 @param ImageHandle The firmware allocated handle for the EFI image.
418 @param SystemTable A pointer to the EFI System Table.
420 @retval RETURN_SUCCESS Allocate the global memory space to store S3 boot script table private data
421 @retval RETURN_OUT_OF_RESOURCES No enough memory to allocated.
425 S3BootScriptLibInitialize (
426 IN EFI_HANDLE ImageHandle
,
427 IN EFI_SYSTEM_TABLE
*SystemTable
431 SCRIPT_TABLE_PRIVATE_DATA
*S3TablePtr
;
432 SCRIPT_TABLE_PRIVATE_DATA
*S3TableSmmPtr
;
434 EFI_SMM_BASE2_PROTOCOL
*SmmBase2
;
436 EFI_SMM_SYSTEM_TABLE2
*Smst
;
437 EFI_PHYSICAL_ADDRESS Buffer
;
440 if (!PcdGetBool (PcdAcpiS3Enable
)) {
441 return RETURN_SUCCESS
;
444 S3TablePtr
= (SCRIPT_TABLE_PRIVATE_DATA
*)(UINTN
)PcdGet64(PcdS3BootScriptTablePrivateDataPtr
);
446 // The Boot script private data is not be initialized. create it
448 if (S3TablePtr
== 0) {
449 Buffer
= SIZE_4GB
- 1;
450 Status
= gBS
->AllocatePages (
452 EfiReservedMemoryType
,
453 EFI_SIZE_TO_PAGES(sizeof(SCRIPT_TABLE_PRIVATE_DATA
)),
456 if (EFI_ERROR (Status
)) {
457 return RETURN_OUT_OF_RESOURCES
;
459 S3TablePtr
= (VOID
*) (UINTN
) Buffer
;
461 Status
= PcdSet64S (PcdS3BootScriptTablePrivateDataPtr
, (UINT64
) (UINTN
)S3TablePtr
);
462 ASSERT_EFI_ERROR (Status
);
463 ZeroMem (S3TablePtr
, sizeof(SCRIPT_TABLE_PRIVATE_DATA
));
465 // Create event to notify the library system enter the SmmLocked phase.
467 Event
= EfiCreateProtocolNotifyEvent (
468 &gEfiDxeSmmReadyToLockProtocolGuid
,
470 S3BootScriptEventCallBack
,
474 ASSERT (Event
!= NULL
);
476 mS3BootScriptTablePtr
= S3TablePtr
;
479 // Get InSmm, we need to register SmmReadyToLock if this library is linked to SMM driver.
481 Status
= gBS
->LocateProtocol (&gEfiSmmBase2ProtocolGuid
, NULL
, (VOID
**) &SmmBase2
);
482 if (EFI_ERROR (Status
)) {
483 return RETURN_SUCCESS
;
485 Status
= SmmBase2
->InSmm (SmmBase2
, &InSmm
);
486 if (EFI_ERROR (Status
)) {
487 return RETURN_SUCCESS
;
490 return RETURN_SUCCESS
;
493 // Good, we are in SMM
495 Status
= SmmBase2
->GetSmstLocation (SmmBase2
, &Smst
);
496 if (EFI_ERROR (Status
)) {
497 return RETURN_SUCCESS
;
500 S3TableSmmPtr
= (SCRIPT_TABLE_PRIVATE_DATA
*)(UINTN
)PcdGet64(PcdS3BootScriptTablePrivateSmmDataPtr
);
502 // The Boot script private data in SMM is not be initialized. create it
504 if (S3TableSmmPtr
== 0) {
505 Status
= Smst
->SmmAllocatePool (
506 EfiRuntimeServicesData
,
507 sizeof(SCRIPT_TABLE_PRIVATE_DATA
),
508 (VOID
**) &S3TableSmmPtr
510 if (EFI_ERROR (Status
)) {
511 return RETURN_OUT_OF_RESOURCES
;
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.
522 Status
= Smst
->SmmRegisterProtocolNotify (
523 &gEdkiiSmmExitBootServicesProtocolGuid
,
524 S3BootScriptSmmAtRuntimeCallBack
,
527 ASSERT_EFI_ERROR (Status
);
530 Status
= Smst
->SmmRegisterProtocolNotify (
531 &gEdkiiSmmLegacyBootProtocolGuid
,
532 S3BootScriptSmmAtRuntimeCallBack
,
535 ASSERT_EFI_ERROR (Status
);
537 mS3BootScriptTableSmmPtr
= S3TableSmmPtr
;
540 // Register SmmReadyToLock notification.
543 Status
= Smst
->SmmRegisterProtocolNotify (
544 &gEfiSmmReadyToLockProtocolGuid
,
545 S3BootScriptSmmEventCallBack
,
548 ASSERT_EFI_ERROR (Status
);
550 return RETURN_SUCCESS
;
553 To get the start address from which a new boot time s3 boot script entry will write into.
554 If the table is not exist, the functio will first allocate a buffer for the table
555 If the table buffer is not enough for the new entry, in non-smm mode, the funtion will
556 invoke reallocate to enlarge buffer.
558 @param EntryLength the new entry length.
560 @retval the address from which the a new s3 boot script entry will write into
563 S3BootScriptGetBootTimeEntryAddAddress (
567 EFI_PHYSICAL_ADDRESS S3TableBase
;
568 EFI_PHYSICAL_ADDRESS NewS3TableBase
;
573 EFI_BOOT_SCRIPT_TABLE_HEADER
*ScriptTableInfo
;
575 S3TableBase
= (EFI_PHYSICAL_ADDRESS
)(UINTN
)(mS3BootScriptTablePtr
->TableBase
);
576 if (S3TableBase
== 0) {
578 // The table is not exist. This is the first to add entry.
579 // Allocate ACPI script table space under 4G memory.
581 S3TableBase
= 0xffffffff;
582 Status
= gBS
->AllocatePages (
584 EfiReservedMemoryType
,
585 2 + PcdGet16(PcdS3BootScriptRuntimeTableReservePageNumber
),
586 (EFI_PHYSICAL_ADDRESS
*)&S3TableBase
589 if (EFI_ERROR(Status
)) {
590 ASSERT_EFI_ERROR (Status
);
596 ScriptTableInfo
= (EFI_BOOT_SCRIPT_TABLE_HEADER
*)(UINTN
)S3TableBase
;
597 ScriptTableInfo
->OpCode
= S3_BOOT_SCRIPT_LIB_TABLE_OPCODE
;
598 ScriptTableInfo
->Length
= (UINT8
) sizeof (EFI_BOOT_SCRIPT_TABLE_HEADER
);
599 ScriptTableInfo
->Version
= BOOT_SCRIPT_TABLE_VERSION
;
600 ScriptTableInfo
->TableLength
= 0; // will be calculate at CloseTable
601 mS3BootScriptTablePtr
->TableLength
= sizeof (EFI_BOOT_SCRIPT_TABLE_HEADER
);
602 mS3BootScriptTablePtr
->TableBase
= (UINT8
*)(UINTN
)S3TableBase
;
603 mS3BootScriptTablePtr
->TableMemoryPageNumber
= (UINT16
)(2 + PcdGet16(PcdS3BootScriptRuntimeTableReservePageNumber
));
606 // Here we do not count the reserved memory for runtime script table.
607 PageNumber
= (UINT16
) (mS3BootScriptTablePtr
->TableMemoryPageNumber
- PcdGet16(PcdS3BootScriptRuntimeTableReservePageNumber
));
608 TableLength
= mS3BootScriptTablePtr
->TableLength
;
609 if ((UINTN
) EFI_PAGES_TO_SIZE ((UINTN
) PageNumber
) < (UINTN
) (TableLength
+ EntryLength
+ sizeof (EFI_BOOT_SCRIPT_TERMINATE
))) {
611 // The buffer is too small to hold the table, Reallocate the buffer
613 NewS3TableBase
= 0xffffffff;
614 Status
= gBS
->AllocatePages (
616 EfiReservedMemoryType
,
617 2 + PageNumber
+ PcdGet16(PcdS3BootScriptRuntimeTableReservePageNumber
),
618 (EFI_PHYSICAL_ADDRESS
*)&NewS3TableBase
621 if (EFI_ERROR(Status
)) {
622 ASSERT_EFI_ERROR (Status
);
626 CopyMem ((VOID
*)(UINTN
)NewS3TableBase
, (VOID
*)(UINTN
)S3TableBase
, TableLength
);
627 gBS
->FreePages (S3TableBase
, mS3BootScriptTablePtr
->TableMemoryPageNumber
);
629 mS3BootScriptTablePtr
->TableBase
= (UINT8
*)(UINTN
)NewS3TableBase
;
630 mS3BootScriptTablePtr
->TableMemoryPageNumber
= (UINT16
) (2 + PageNumber
+ PcdGet16(PcdS3BootScriptRuntimeTableReservePageNumber
));
633 // calculate the the start address for the new entry.
635 NewEntryPtr
= mS3BootScriptTablePtr
->TableBase
+ TableLength
;
638 // update the table lenghth
640 mS3BootScriptTablePtr
->TableLength
= TableLength
+ EntryLength
;
643 // In the boot time, we will not append the termination entry to the boot script
644 // table until the callers think there is no boot time data that should be added and
645 // it is caller's responsibility to explicit call the CloseTable.
652 To get the start address from which a new runtime(after SmmReadyToLock) s3 boot script entry will write into.
653 In this case, it should be ensured that there is enough buffer to hold the entry.
655 @param EntryLength the new entry length.
657 @retval the address from which the a new s3 runtime(after SmmReadyToLock) script entry will write into
660 S3BootScriptGetRuntimeEntryAddAddress (
668 // Check if the memory range reserved for S3 Boot Script table is large enough to hold the node.
670 if ((UINTN
) (mS3BootScriptTablePtr
->TableLength
+ EntryLength
+ sizeof (EFI_BOOT_SCRIPT_TERMINATE
)) <= (UINTN
) EFI_PAGES_TO_SIZE ((UINTN
) (mS3BootScriptTablePtr
->TableMemoryPageNumber
))) {
671 NewEntryPtr
= mS3BootScriptTablePtr
->TableBase
+ mS3BootScriptTablePtr
->TableLength
;
672 mS3BootScriptTablePtr
->TableLength
= mS3BootScriptTablePtr
->TableLength
+ EntryLength
;
674 // Append a terminate node on every insert
676 S3BootScriptInternalCloseTable ();
678 return (UINT8
*)NewEntryPtr
;
682 This function is to restore boot time boot script data from LockBox.
686 RestoreBootTimeDataFromLockBox (
694 // Restore boot time boot script data from LockBox.
696 LockBoxLength
= mS3BootScriptTablePtr
->BootTimeScriptLength
;
697 Status
= RestoreLockBox (
698 &mBootScriptDataBootTimeGuid
,
699 (VOID
*) mS3BootScriptTablePtr
->TableBase
,
702 ASSERT_EFI_ERROR (Status
);
705 // Update the data to BootScriptData LockBox.
707 Status
= UpdateLockBox (
708 &mBootScriptDataGuid
,
710 (VOID
*) mS3BootScriptTablePtr
->TableBase
,
713 ASSERT_EFI_ERROR (Status
);
716 // Update TableLength.
718 mS3BootScriptTablePtr
->TableLength
= (UINT32
) (mS3BootScriptTablePtr
->BootTimeScriptLength
- sizeof (EFI_BOOT_SCRIPT_TERMINATE
));
722 To get the start address from which a new s3 boot script entry will write into.
724 @param EntryLength the new entry length.
726 @retval the address from which the a new s3 boot script entry will write into
729 S3BootScriptGetEntryAddAddress (
735 if (mS3BootScriptTablePtr
->SmmLocked
) {
737 // We need check InSmm, because after SmmReadyToLock, only SMM driver is allowed to write boot script.
739 if (!mS3BootScriptTablePtr
->InSmm
) {
741 // Add DEBUG ERROR, so that we can find it after SmmReadyToLock.
742 // Do not use ASSERT, because we may have test to invoke this interface.
744 DEBUG ((EFI_D_ERROR
, "FATAL ERROR: Set boot script outside SMM after SmmReadyToLock!!!\n"));
748 if (mS3BootScriptTablePtr
->BackFromS3
) {
750 // Back from S3, restore boot time boot script data from LockBox
751 // and set BackFromS3 flag back to FALSE.
753 RestoreBootTimeDataFromLockBox ();
754 mS3BootScriptTablePtr
->BackFromS3
= FALSE
;
757 NewEntryPtr
= S3BootScriptGetRuntimeEntryAddAddress (EntryLength
);
759 NewEntryPtr
= S3BootScriptGetBootTimeEntryAddAddress (EntryLength
);
766 Sync BootScript LockBox data.
768 @param Script The address from where the boot script has been added or updated.
778 UINT32 TotalScriptLength
;
780 if (!mS3BootScriptTablePtr
->SmmLocked
|| !mS3BootScriptTablePtr
->InSmm
) {
782 // If it is not after SmmReadyToLock in SMM,
788 ScriptOffset
= (UINT32
) (Script
- mS3BootScriptTablePtr
->TableBase
);
790 TotalScriptLength
= (UINT32
) (mS3BootScriptTablePtr
->TableLength
+ sizeof (EFI_BOOT_SCRIPT_TERMINATE
));
793 // Update BootScriptData
794 // So in S3 resume, the data can be restored correctly.
796 Status
= UpdateLockBox (
797 &mBootScriptDataGuid
,
799 (VOID
*)((UINTN
)mS3BootScriptTablePtr
->TableBase
+ ScriptOffset
),
800 TotalScriptLength
- ScriptOffset
802 ASSERT_EFI_ERROR (Status
);
805 // Now the length field is updated, need sync to lockbox.
806 // So at S3 resume, the data can be restored correctly.
808 Status
= UpdateLockBox (
809 &mBootScriptDataGuid
,
810 OFFSET_OF (EFI_BOOT_SCRIPT_TABLE_HEADER
, TableLength
),
812 sizeof (TotalScriptLength
)
814 ASSERT_EFI_ERROR (Status
);
818 This is an function to close the S3 boot script table. The function could only be called in
819 BOOT time phase. To comply with the Framework spec definition on
820 EFI_BOOT_SCRIPT_SAVE_PROTOCOL.CloseTable(), this function will fulfill following things:
821 1. Closes the specified boot script table
822 2. It allocates a new memory pool to duplicate all the boot scripts in the specified table.
823 Once this function is called, the table maintained by the library will be destroyed
824 after it is copied into the allocated pool.
825 3. Any attempts to add a script record after calling this function will cause a new table
826 to be created by the library.
827 4. The base address of the allocated pool will be returned in Address. Note that after
828 using the boot script table, the CALLER is responsible for freeing the pool that is allocated
831 In Spec PI1.1, this EFI_BOOT_SCRIPT_SAVE_PROTOCOL.CloseTable() is retired. To provides this API for now is
832 for Framework Spec compatibility.
834 If anyone does call CloseTable() on a real platform, then the caller is responsible for figuring out
835 how to get the script to run at S3 resume because the boot script maintained by the lib will be
838 @return the base address of the new copy of the boot script table.
839 @note this function could only called in boot time phase
844 S3BootScriptCloseTable (
852 EFI_BOOT_SCRIPT_TABLE_HEADER
*ScriptTableInfo
;
854 S3TableBase
= mS3BootScriptTablePtr
->TableBase
;
855 if (S3TableBase
== 0) {
859 // Append the termination record the S3 boot script table
861 S3BootScriptInternalCloseTable();
862 TableLength
= mS3BootScriptTablePtr
->TableLength
+ sizeof (EFI_BOOT_SCRIPT_TERMINATE
);
864 // Allocate the buffer and copy the boot script to the buffer.
866 Status
= gBS
->AllocatePool (
871 if (EFI_ERROR (Status
)) {
874 CopyMem (Buffer
, S3TableBase
, TableLength
);
877 // Destroy the table maintained by the library so that the next write operation
878 // will write the record to the first entry of the table.
880 // Fill the table header.
881 ScriptTableInfo
= (EFI_BOOT_SCRIPT_TABLE_HEADER
*)S3TableBase
;
882 ScriptTableInfo
->OpCode
= S3_BOOT_SCRIPT_LIB_TABLE_OPCODE
;
883 ScriptTableInfo
->Length
= (UINT8
) sizeof (EFI_BOOT_SCRIPT_TABLE_HEADER
);
884 ScriptTableInfo
->TableLength
= 0; // will be calculate at close the table
886 mS3BootScriptTablePtr
->TableLength
= sizeof (EFI_BOOT_SCRIPT_TABLE_HEADER
);
890 Save I/O write to boot script
892 @param Width The width of the I/O operations.Enumerated in S3_BOOT_SCRIPT_LIB_WIDTH.
893 @param Address The base address of the I/O operations.
894 @param Count The number of I/O operations to perform.
895 @param Buffer The source buffer from which to write data.
897 @retval RETURN_OUT_OF_RESOURCES Not enough memory for the table do operation.
898 @retval RETURN_SUCCESS Opcode is added.
902 S3BootScriptSaveIoWrite (
903 IN S3_BOOT_SCRIPT_LIB_WIDTH Width
,
913 EFI_BOOT_SCRIPT_IO_WRITE ScriptIoWrite
;
915 WidthInByte
= (UINT8
) (0x01 << (Width
& 0x03));
916 Length
= (UINT8
)(sizeof (EFI_BOOT_SCRIPT_IO_WRITE
) + (WidthInByte
* Count
));
918 Script
= S3BootScriptGetEntryAddAddress (Length
);
919 if (Script
== NULL
) {
920 return RETURN_OUT_OF_RESOURCES
;
925 ScriptIoWrite
.OpCode
= EFI_BOOT_SCRIPT_IO_WRITE_OPCODE
;
926 ScriptIoWrite
.Length
= Length
;
927 ScriptIoWrite
.Width
= Width
;
928 ScriptIoWrite
.Address
= Address
;
929 ScriptIoWrite
.Count
= (UINT32
) Count
;
930 CopyMem ((VOID
*)Script
, (VOID
*)&ScriptIoWrite
, sizeof(EFI_BOOT_SCRIPT_IO_WRITE
));
931 CopyMem ((VOID
*)(Script
+ sizeof (EFI_BOOT_SCRIPT_IO_WRITE
)), Buffer
, WidthInByte
* Count
);
933 SyncBootScript (Script
);
935 return RETURN_SUCCESS
;
939 Adds a record for an I/O modify operation into a S3 boot script table
941 @param Width The width of the I/O operations.Enumerated in S3_BOOT_SCRIPT_LIB_WIDTH.
942 @param Address The base address of the I/O operations.
943 @param Data A pointer to the data to be OR-ed.
944 @param DataMask A pointer to the data mask to be AND-ed with the data read from the register
946 @retval RETURN_OUT_OF_RESOURCES Not enough memory for the table do operation.
947 @retval RETURN_SUCCESS Opcode is added.
951 S3BootScriptSaveIoReadWrite (
952 IN S3_BOOT_SCRIPT_LIB_WIDTH Width
,
961 EFI_BOOT_SCRIPT_IO_READ_WRITE ScriptIoReadWrite
;
963 WidthInByte
= (UINT8
) (0x01 << (Width
& 0x03));
964 Length
= (UINT8
)(sizeof (EFI_BOOT_SCRIPT_IO_READ_WRITE
) + (WidthInByte
* 2));
966 Script
= S3BootScriptGetEntryAddAddress (Length
);
967 if (Script
== NULL
) {
968 return RETURN_OUT_OF_RESOURCES
;
973 ScriptIoReadWrite
.OpCode
= EFI_BOOT_SCRIPT_IO_READ_WRITE_OPCODE
;
974 ScriptIoReadWrite
.Length
= Length
;
975 ScriptIoReadWrite
.Width
= Width
;
976 ScriptIoReadWrite
.Address
= Address
;
978 CopyMem ((VOID
*)Script
, (VOID
*)&ScriptIoReadWrite
, sizeof(EFI_BOOT_SCRIPT_IO_READ_WRITE
));
979 CopyMem ((VOID
*)(Script
+ sizeof (EFI_BOOT_SCRIPT_IO_READ_WRITE
)), Data
, WidthInByte
);
980 CopyMem ((VOID
*)(Script
+ sizeof (EFI_BOOT_SCRIPT_IO_READ_WRITE
) + WidthInByte
), DataMask
, WidthInByte
);
982 SyncBootScript (Script
);
984 return RETURN_SUCCESS
;
987 Adds a record for a memory write operation into a specified boot script table.
989 @param Width The width of the I/O operations.Enumerated in S3_BOOT_SCRIPT_LIB_WIDTH.
990 @param Address The base address of the memory operations
991 @param Count The number of memory operations to perform.
992 @param Buffer The source buffer from which to write the data.
994 @retval RETURN_OUT_OF_RESOURCES Not enough memory for the table do operation.
995 @retval RETURN_SUCCESS Opcode is added.
999 S3BootScriptSaveMemWrite (
1000 IN S3_BOOT_SCRIPT_LIB_WIDTH Width
,
1009 EFI_BOOT_SCRIPT_MEM_WRITE ScriptMemWrite
;
1011 WidthInByte
= (UINT8
) (0x01 << (Width
& 0x03));
1012 Length
= (UINT8
)(sizeof (EFI_BOOT_SCRIPT_MEM_WRITE
) + (WidthInByte
* Count
));
1014 Script
= S3BootScriptGetEntryAddAddress (Length
);
1015 if (Script
== NULL
) {
1016 return RETURN_OUT_OF_RESOURCES
;
1019 // Build script data
1021 ScriptMemWrite
.OpCode
= EFI_BOOT_SCRIPT_MEM_WRITE_OPCODE
;
1022 ScriptMemWrite
.Length
= Length
;
1023 ScriptMemWrite
.Width
= Width
;
1024 ScriptMemWrite
.Address
= Address
;
1025 ScriptMemWrite
.Count
= (UINT32
) Count
;
1027 CopyMem ((VOID
*)Script
, (VOID
*)&ScriptMemWrite
, sizeof(EFI_BOOT_SCRIPT_MEM_WRITE
));
1028 CopyMem ((VOID
*)(Script
+ sizeof (EFI_BOOT_SCRIPT_MEM_WRITE
)), Buffer
, WidthInByte
* Count
);
1030 SyncBootScript (Script
);
1032 return RETURN_SUCCESS
;
1035 Adds a record for a memory modify operation into a specified boot script table.
1037 @param Width The width of the I/O operations.Enumerated in S3_BOOT_SCRIPT_LIB_WIDTH.
1038 @param Address The base address of the memory operations. Address needs alignment if required
1039 @param Data A pointer to the data to be OR-ed.
1040 @param DataMask A pointer to the data mask to be AND-ed with the data read from the register.
1042 @retval RETURN_OUT_OF_RESOURCES Not enough memory for the table do operation.
1043 @retval RETURN_SUCCESS Opcode is added.
1047 S3BootScriptSaveMemReadWrite (
1048 IN S3_BOOT_SCRIPT_LIB_WIDTH Width
,
1057 EFI_BOOT_SCRIPT_MEM_READ_WRITE ScriptMemReadWrite
;
1059 WidthInByte
= (UINT8
) (0x01 << (Width
& 0x03));
1060 Length
= (UINT8
)(sizeof (EFI_BOOT_SCRIPT_MEM_READ_WRITE
) + (WidthInByte
* 2));
1062 Script
= S3BootScriptGetEntryAddAddress (Length
);
1063 if (Script
== NULL
) {
1064 return RETURN_OUT_OF_RESOURCES
;
1067 // Build script data
1069 ScriptMemReadWrite
.OpCode
= EFI_BOOT_SCRIPT_MEM_READ_WRITE_OPCODE
;
1070 ScriptMemReadWrite
.Length
= Length
;
1071 ScriptMemReadWrite
.Width
= Width
;
1072 ScriptMemReadWrite
.Address
= Address
;
1074 CopyMem ((VOID
*)Script
, (VOID
*)&ScriptMemReadWrite
, sizeof (EFI_BOOT_SCRIPT_MEM_READ_WRITE
));
1075 CopyMem ((VOID
*)(Script
+ sizeof (EFI_BOOT_SCRIPT_MEM_READ_WRITE
)), Data
, WidthInByte
);
1076 CopyMem ((VOID
*)(Script
+ sizeof (EFI_BOOT_SCRIPT_MEM_READ_WRITE
) + WidthInByte
), DataMask
, WidthInByte
);
1078 SyncBootScript (Script
);
1080 return RETURN_SUCCESS
;
1083 Adds a record for a PCI configuration space write operation into a specified boot script table.
1085 @param Width The width of the I/O operations.Enumerated in S3_BOOT_SCRIPT_LIB_WIDTH.
1086 @param Address The address within the PCI configuration space.
1087 @param Count The number of PCI operations to perform.
1088 @param Buffer The source buffer from which to write the data.
1090 @retval RETURN_OUT_OF_RESOURCES Not enough memory for the table do operation.
1091 @retval RETURN_SUCCESS Opcode is added.
1092 @note A known Limitations in the implementation which is 64bits operations are not supported.
1097 S3BootScriptSavePciCfgWrite (
1098 IN S3_BOOT_SCRIPT_LIB_WIDTH Width
,
1107 EFI_BOOT_SCRIPT_PCI_CONFIG_WRITE ScriptPciWrite
;
1109 if (Width
== S3BootScriptWidthUint64
||
1110 Width
== S3BootScriptWidthFifoUint64
||
1111 Width
== S3BootScriptWidthFillUint64
) {
1112 return EFI_INVALID_PARAMETER
;
1115 WidthInByte
= (UINT8
) (0x01 << (Width
& 0x03));
1116 Length
= (UINT8
)(sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG_WRITE
) + (WidthInByte
* Count
));
1118 Script
= S3BootScriptGetEntryAddAddress (Length
);
1119 if (Script
== NULL
) {
1120 return RETURN_OUT_OF_RESOURCES
;
1123 // Build script data
1125 ScriptPciWrite
.OpCode
= EFI_BOOT_SCRIPT_PCI_CONFIG_WRITE_OPCODE
;
1126 ScriptPciWrite
.Length
= Length
;
1127 ScriptPciWrite
.Width
= Width
;
1128 ScriptPciWrite
.Address
= Address
;
1129 ScriptPciWrite
.Count
= (UINT32
) Count
;
1131 CopyMem ((VOID
*)Script
, (VOID
*)&ScriptPciWrite
, sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG_WRITE
));
1132 CopyMem ((VOID
*)(Script
+ sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG_WRITE
)), Buffer
, WidthInByte
* Count
);
1134 SyncBootScript (Script
);
1136 return RETURN_SUCCESS
;
1139 Adds a record for a PCI configuration space modify operation into a specified boot script table.
1141 @param Width The width of the I/O operations.Enumerated in S3_BOOT_SCRIPT_LIB_WIDTH.
1142 @param Address The address within the PCI configuration space.
1143 @param Data A pointer to the data to be OR-ed.The size depends on Width.
1144 @param DataMask A pointer to the data mask to be AND-ed.
1146 @retval RETURN_OUT_OF_RESOURCES Not enough memory for the table do operation.
1147 @retval RETURN__SUCCESS Opcode is added.
1148 @note A known Limitations in the implementation which is 64bits operations are not supported.
1153 S3BootScriptSavePciCfgReadWrite (
1154 IN S3_BOOT_SCRIPT_LIB_WIDTH Width
,
1163 EFI_BOOT_SCRIPT_PCI_CONFIG_READ_WRITE ScriptPciReadWrite
;
1165 if (Width
== S3BootScriptWidthUint64
||
1166 Width
== S3BootScriptWidthFifoUint64
||
1167 Width
== S3BootScriptWidthFillUint64
) {
1168 return EFI_INVALID_PARAMETER
;
1171 WidthInByte
= (UINT8
) (0x01 << (Width
& 0x03));
1172 Length
= (UINT8
)(sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG_READ_WRITE
) + (WidthInByte
* 2));
1174 Script
= S3BootScriptGetEntryAddAddress (Length
);
1175 if (Script
== NULL
) {
1176 return RETURN_OUT_OF_RESOURCES
;
1179 // Build script data
1181 ScriptPciReadWrite
.OpCode
= EFI_BOOT_SCRIPT_PCI_CONFIG_READ_WRITE_OPCODE
;
1182 ScriptPciReadWrite
.Length
= Length
;
1183 ScriptPciReadWrite
.Width
= Width
;
1184 ScriptPciReadWrite
.Address
= Address
;
1186 CopyMem ((VOID
*)Script
, (VOID
*)&ScriptPciReadWrite
, sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG_READ_WRITE
));
1187 CopyMem ((VOID
*)(Script
+ sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG_READ_WRITE
)), Data
, WidthInByte
);
1189 (VOID
*)(Script
+ sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG_READ_WRITE
) + WidthInByte
),
1194 SyncBootScript (Script
);
1196 return RETURN_SUCCESS
;
1199 Adds a record for a PCI configuration 2 space write operation into a specified boot script table.
1201 @param Width The width of the I/O operations.Enumerated in S3_BOOT_SCRIPT_LIB_WIDTH.
1202 @param Segment The PCI segment number for Address.
1203 @param Address The address within the PCI configuration space.
1204 @param Count The number of PCI operations to perform.
1205 @param Buffer The source buffer from which to write the data.
1207 @retval RETURN_OUT_OF_RESOURCES Not enough memory for the table do operation.
1208 @retval RETURN_SUCCESS Opcode is added.
1209 @note A known Limitations in the implementation which is non-zero Segment and 64bits operations are not supported.
1214 S3BootScriptSavePciCfg2Write (
1215 IN S3_BOOT_SCRIPT_LIB_WIDTH Width
,
1225 EFI_BOOT_SCRIPT_PCI_CONFIG2_WRITE ScriptPciWrite2
;
1228 Width
== S3BootScriptWidthUint64
||
1229 Width
== S3BootScriptWidthFifoUint64
||
1230 Width
== S3BootScriptWidthFillUint64
) {
1231 return EFI_INVALID_PARAMETER
;
1234 WidthInByte
= (UINT8
) (0x01 << (Width
& 0x03));
1235 Length
= (UINT8
)(sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG2_WRITE
) + (WidthInByte
* Count
));
1237 Script
= S3BootScriptGetEntryAddAddress (Length
);
1238 if (Script
== NULL
) {
1239 return RETURN_OUT_OF_RESOURCES
;
1242 // Build script data
1244 ScriptPciWrite2
.OpCode
= EFI_BOOT_SCRIPT_PCI_CONFIG2_WRITE_OPCODE
;
1245 ScriptPciWrite2
.Length
= Length
;
1246 ScriptPciWrite2
.Width
= Width
;
1247 ScriptPciWrite2
.Address
= Address
;
1248 ScriptPciWrite2
.Segment
= Segment
;
1249 ScriptPciWrite2
.Count
= (UINT32
)Count
;
1251 CopyMem ((VOID
*)Script
, (VOID
*)&ScriptPciWrite2
, sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG2_WRITE
));
1252 CopyMem ((VOID
*)(Script
+ sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG2_WRITE
)), Buffer
, WidthInByte
* Count
);
1254 SyncBootScript (Script
);
1256 return RETURN_SUCCESS
;
1259 Adds a record for a PCI configuration 2 space modify operation into a specified boot script table.
1261 @param Width The width of the I/O operations.Enumerated in S3_BOOT_SCRIPT_LIB_WIDTH.
1262 @param Segment The PCI segment number for Address.
1263 @param Address The address within the PCI configuration space.
1264 @param Data A pointer to the data to be OR-ed. The size depends on Width.
1265 @param DataMask A pointer to the data mask to be AND-ed.
1267 @retval RETURN_OUT_OF_RESOURCES Not enough memory for the table do operation.
1268 @retval RETURN_SUCCESS Opcode is added.
1269 @note A known Limitations in the implementation which is non-zero Segment and 64bits operations are not supported.
1274 S3BootScriptSavePciCfg2ReadWrite (
1275 IN S3_BOOT_SCRIPT_LIB_WIDTH Width
,
1285 EFI_BOOT_SCRIPT_PCI_CONFIG2_READ_WRITE ScriptPciReadWrite2
;
1288 Width
== S3BootScriptWidthUint64
||
1289 Width
== S3BootScriptWidthFifoUint64
||
1290 Width
== S3BootScriptWidthFillUint64
) {
1291 return EFI_INVALID_PARAMETER
;
1294 WidthInByte
= (UINT8
) (0x01 << (Width
& 0x03));
1295 Length
= (UINT8
)(sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG2_READ_WRITE
) + (WidthInByte
* 2));
1297 Script
= S3BootScriptGetEntryAddAddress (Length
);
1298 if (Script
== NULL
) {
1299 return RETURN_OUT_OF_RESOURCES
;
1302 // Build script data
1304 ScriptPciReadWrite2
.OpCode
= EFI_BOOT_SCRIPT_PCI_CONFIG2_READ_WRITE_OPCODE
;
1305 ScriptPciReadWrite2
.Length
= Length
;
1306 ScriptPciReadWrite2
.Width
= Width
;
1307 ScriptPciReadWrite2
.Segment
= Segment
;
1308 ScriptPciReadWrite2
.Address
= Address
;
1310 CopyMem ((VOID
*)Script
, (VOID
*)&ScriptPciReadWrite2
, sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG2_READ_WRITE
));
1311 CopyMem ((VOID
*)(Script
+ sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG2_READ_WRITE
)), Data
, WidthInByte
);
1313 (VOID
*)(Script
+ sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG2_READ_WRITE
) + WidthInByte
),
1318 SyncBootScript (Script
);
1320 return RETURN_SUCCESS
;
1324 Checks the parameter of S3BootScriptSaveSmbusExecute().
1326 This function checks the input parameters of SmbusExecute(). If the input parameters are valid
1327 for certain SMBus bus protocol, it will return EFI_SUCCESS; otherwise, it will return certain
1328 error code based on the input SMBus bus protocol.
1330 @param SmBusAddress Address that encodes the SMBUS Slave Address, SMBUS Command, SMBUS Data Length,
1332 @param Operation Signifies which particular SMBus hardware protocol instance that
1333 it will use to execute the SMBus transactions. This SMBus
1334 hardware protocol is defined by the SMBus Specification and is
1336 @param Length Signifies the number of bytes that this operation will do. The
1337 maximum number of bytes can be revision specific and operation
1338 specific. This field will contain the actual number of bytes that
1339 are executed for this operation. Not all operations require this
1341 @param Buffer Contains the value of data to execute to the SMBus slave device.
1342 Not all operations require this argument. The length of this
1343 buffer is identified by Length.
1345 @retval EFI_SUCCESS All the parameters are valid for the corresponding SMBus bus
1347 @retval EFI_INVALID_PARAMETER Operation is not defined in EFI_SMBUS_OPERATION.
1348 @retval EFI_INVALID_PARAMETER Length/Buffer is NULL for operations except for EfiSmbusQuickRead
1349 and EfiSmbusQuickWrite. Length is outside the range of valid
1351 @retval EFI_UNSUPPORTED The SMBus operation or PEC is not supported.
1352 @retval EFI_BUFFER_TOO_SMALL Buffer is not sufficient for this operation.
1357 IN UINTN SmBusAddress
,
1358 IN EFI_SMBUS_OPERATION Operation
,
1359 IN OUT UINTN
*Length
,
1365 EFI_SMBUS_DEVICE_COMMAND Command
;
1368 Command
= SMBUS_LIB_COMMAND (SmBusAddress
);
1369 PecCheck
= SMBUS_LIB_PEC (SmBusAddress
);
1371 // Set default value to be 2:
1372 // for SmbusReadWord, SmbusWriteWord and SmbusProcessCall.
1375 Status
= EFI_SUCCESS
;
1376 switch (Operation
) {
1377 case EfiSmbusQuickRead
:
1378 case EfiSmbusQuickWrite
:
1379 if (PecCheck
|| Command
!= 0) {
1380 return EFI_UNSUPPORTED
;
1383 case EfiSmbusReceiveByte
:
1384 case EfiSmbusSendByte
:
1386 return EFI_UNSUPPORTED
;
1389 // Cascade to check length parameter.
1391 case EfiSmbusReadByte
:
1392 case EfiSmbusWriteByte
:
1395 // Cascade to check length parameter.
1397 case EfiSmbusReadWord
:
1398 case EfiSmbusWriteWord
:
1399 case EfiSmbusProcessCall
:
1400 if (Buffer
== NULL
|| Length
== NULL
) {
1401 return EFI_INVALID_PARAMETER
;
1402 } else if (*Length
< RequiredLen
) {
1403 Status
= EFI_BUFFER_TOO_SMALL
;
1405 *Length
= RequiredLen
;
1407 case EfiSmbusReadBlock
:
1408 case EfiSmbusWriteBlock
:
1409 case EfiSmbusBWBRProcessCall
:
1410 if ((Buffer
== NULL
) ||
1412 (*Length
< MIN_SMBUS_BLOCK_LEN
) ||
1413 (*Length
> MAX_SMBUS_BLOCK_LEN
)) {
1414 return EFI_INVALID_PARAMETER
;
1418 return EFI_INVALID_PARAMETER
;
1424 Adds a record for an SMBus command execution into a specified boot script table.
1426 @param SmBusAddress Address that encodes the SMBUS Slave Address, SMBUS Command, SMBUS Data Length, and PEC.
1427 @param Operation Indicates which particular SMBus protocol it will use to execute the SMBus
1429 @param Length A pointer to signify the number of bytes that this operation will do.
1430 @param Buffer Contains the value of data to execute to the SMBUS slave device.
1432 @retval RETURN_OUT_OF_RESOURCES Not enough memory for the table do operation.
1433 @retval RETURN_SUCCESS Opcode is added.
1437 S3BootScriptSaveSmbusExecute (
1438 IN UINTN SmBusAddress
,
1439 IN EFI_SMBUS_OPERATION Operation
,
1448 EFI_BOOT_SCRIPT_SMBUS_EXECUTE ScriptSmbusExecute
;
1450 if (Length
== NULL
) {
1453 BufferLength
= *Length
;
1456 Status
= CheckParameters (SmBusAddress
, Operation
, &BufferLength
, Buffer
);
1457 if (EFI_ERROR (Status
)) {
1461 DataSize
= (UINT8
)(sizeof (EFI_BOOT_SCRIPT_SMBUS_EXECUTE
) + BufferLength
);
1463 Script
= S3BootScriptGetEntryAddAddress (DataSize
);
1464 if (Script
== NULL
) {
1465 return RETURN_OUT_OF_RESOURCES
;
1468 // Build script data
1470 ScriptSmbusExecute
.OpCode
= EFI_BOOT_SCRIPT_SMBUS_EXECUTE_OPCODE
;
1471 ScriptSmbusExecute
.Length
= DataSize
;
1472 ScriptSmbusExecute
.SmBusAddress
= (UINT64
) SmBusAddress
;
1473 ScriptSmbusExecute
.Operation
= Operation
;
1474 ScriptSmbusExecute
.DataSize
= (UINT32
) BufferLength
;
1476 CopyMem ((VOID
*)Script
, (VOID
*)&ScriptSmbusExecute
, sizeof (EFI_BOOT_SCRIPT_SMBUS_EXECUTE
));
1478 (VOID
*)(Script
+ sizeof (EFI_BOOT_SCRIPT_SMBUS_EXECUTE
)),
1483 SyncBootScript (Script
);
1485 return RETURN_SUCCESS
;
1488 Adds a record for an execution stall on the processor into a specified boot script table.
1490 @param Duration Duration in microseconds of the stall
1492 @retval RETURN_OUT_OF_RESOURCES Not enough memory for the table do operation.
1493 @retval RETURN_SUCCESS Opcode is added.
1497 S3BootScriptSaveStall (
1503 EFI_BOOT_SCRIPT_STALL ScriptStall
;
1505 Length
= (UINT8
)(sizeof (EFI_BOOT_SCRIPT_STALL
));
1507 Script
= S3BootScriptGetEntryAddAddress (Length
);
1508 if (Script
== NULL
) {
1509 return RETURN_OUT_OF_RESOURCES
;
1512 // Build script data
1514 ScriptStall
.OpCode
= EFI_BOOT_SCRIPT_STALL_OPCODE
;
1515 ScriptStall
.Length
= Length
;
1516 ScriptStall
.Duration
= Duration
;
1518 CopyMem ((VOID
*)Script
, (VOID
*)&ScriptStall
, sizeof (EFI_BOOT_SCRIPT_STALL
));
1520 SyncBootScript (Script
);
1522 return RETURN_SUCCESS
;
1525 Adds a record for dispatching specified arbitrary code into a specified boot script table.
1527 @param EntryPoint Entry point of the code to be dispatched.
1528 @param Context Argument to be passed into the EntryPoint of the code to be dispatched.
1530 @retval RETURN_OUT_OF_RESOURCES Not enough memory for the table do operation.
1531 @retval RETURN_SUCCESS Opcode is added.
1535 S3BootScriptSaveDispatch2 (
1536 IN VOID
*EntryPoint
,
1542 EFI_BOOT_SCRIPT_DISPATCH_2 ScriptDispatch2
;
1543 Length
= (UINT8
)(sizeof (EFI_BOOT_SCRIPT_DISPATCH_2
));
1545 Script
= S3BootScriptGetEntryAddAddress (Length
);
1546 if (Script
== NULL
) {
1547 return RETURN_OUT_OF_RESOURCES
;
1550 // Build script data
1552 ScriptDispatch2
.OpCode
= EFI_BOOT_SCRIPT_DISPATCH_2_OPCODE
;
1553 ScriptDispatch2
.Length
= Length
;
1554 ScriptDispatch2
.EntryPoint
= (EFI_PHYSICAL_ADDRESS
)(UINTN
)EntryPoint
;
1555 ScriptDispatch2
.Context
= (EFI_PHYSICAL_ADDRESS
)(UINTN
)Context
;
1557 CopyMem ((VOID
*)Script
, (VOID
*)&ScriptDispatch2
, sizeof (EFI_BOOT_SCRIPT_DISPATCH_2
));
1559 SyncBootScript (Script
);
1561 return RETURN_SUCCESS
;
1565 Adds a record for memory reads of the memory location and continues when the exit criteria is
1566 satisfied or after a defined duration.
1568 Please aware, below interface is different with PI specification, Vol 5:
1569 EFI_S3_SAVE_STATE_PROTOCOL.Write() for EFI_BOOT_SCRIPT_MEM_POLL_OPCODE.
1570 "Duration" below is microseconds, while "Delay" in PI specification means
1571 the number of 100ns units to poll.
1573 @param Width The width of the memory operations.
1574 @param Address The base address of the memory operations.
1575 @param BitMask A pointer to the bit mask to be AND-ed with the data read from the register.
1576 @param BitValue A pointer to the data value after to be Masked.
1577 @param Duration Duration in microseconds of the stall.
1578 @param LoopTimes The times of the register polling.
1580 @retval RETURN_OUT_OF_RESOURCES Not enough memory for the table do operation.
1581 @retval RETURN_SUCCESS Opcode is added.
1586 S3BootScriptSaveMemPoll (
1587 IN S3_BOOT_SCRIPT_LIB_WIDTH Width
,
1598 EFI_BOOT_SCRIPT_MEM_POLL ScriptMemPoll
;
1600 WidthInByte
= (UINT8
) (0x01 << (Width
& 0x03));
1602 Length
= (UINT8
)(sizeof (EFI_BOOT_SCRIPT_MEM_POLL
) + (WidthInByte
* 2));
1604 Script
= S3BootScriptGetEntryAddAddress (Length
);
1605 if (Script
== NULL
) {
1606 return RETURN_OUT_OF_RESOURCES
;
1609 // Build script data
1611 ScriptMemPoll
.OpCode
= EFI_BOOT_SCRIPT_MEM_POLL_OPCODE
;
1612 ScriptMemPoll
.Length
= Length
;
1613 ScriptMemPoll
.Width
= Width
;
1614 ScriptMemPoll
.Address
= Address
;
1615 ScriptMemPoll
.Duration
= Duration
;
1616 ScriptMemPoll
.LoopTimes
= LoopTimes
;
1618 CopyMem ((UINT8
*) (Script
+ sizeof (EFI_BOOT_SCRIPT_MEM_POLL
)), BitValue
, WidthInByte
);
1619 CopyMem ((UINT8
*) (Script
+ sizeof (EFI_BOOT_SCRIPT_MEM_POLL
) + WidthInByte
), BitMask
, WidthInByte
);
1620 CopyMem ((VOID
*)Script
, (VOID
*)&ScriptMemPoll
, sizeof (EFI_BOOT_SCRIPT_MEM_POLL
));
1622 SyncBootScript (Script
);
1624 return RETURN_SUCCESS
;
1627 Store arbitrary information in the boot script table. This opcode is a no-op on dispatch and is only
1628 used for debugging script issues.
1630 @param InformationLength Length of the data in bytes
1631 @param Information Information to be logged in the boot scrpit
1633 @retval RETURN_OUT_OF_RESOURCES Not enough memory for the table do operation.
1634 @retval RETURN_SUCCESS Opcode is added.
1639 S3BootScriptSaveInformation (
1640 IN UINT32 InformationLength
,
1641 IN VOID
*Information
1646 EFI_BOOT_SCRIPT_INFORMATION ScriptInformation
;
1648 Length
= (UINT8
)(sizeof (EFI_BOOT_SCRIPT_INFORMATION
) + InformationLength
);
1650 Script
= S3BootScriptGetEntryAddAddress (Length
);
1651 if (Script
== NULL
) {
1652 return RETURN_OUT_OF_RESOURCES
;
1655 // Build script data
1657 ScriptInformation
.OpCode
= EFI_BOOT_SCRIPT_INFORMATION_OPCODE
;
1658 ScriptInformation
.Length
= Length
;
1661 ScriptInformation
.InformationLength
= InformationLength
;
1663 CopyMem ((VOID
*)Script
, (VOID
*)&ScriptInformation
, sizeof (EFI_BOOT_SCRIPT_INFORMATION
));
1664 CopyMem ((VOID
*)(Script
+ sizeof (EFI_BOOT_SCRIPT_INFORMATION
)), (VOID
*) Information
, (UINTN
) InformationLength
);
1666 SyncBootScript (Script
);
1668 return RETURN_SUCCESS
;
1672 Store a string in the boot script table. This opcode is a no-op on dispatch and is only
1673 used for debugging script issues.
1675 @param String The string to save to boot script table
1677 @retval RETURN_OUT_OF_RESOURCES Not enough memory for the table do operation.
1678 @retval RETURN_SUCCESS Opcode is added.
1683 S3BootScriptSaveInformationAsciiString (
1684 IN CONST CHAR8
*String
1687 return S3BootScriptSaveInformation (
1688 (UINT32
) AsciiStrLen (String
) + 1,
1693 Adds a record for dispatching specified arbitrary code into a specified boot script table.
1695 @param EntryPoint Entry point of the code to be dispatched.
1697 @retval RETURN_OUT_OF_RESOURCES Not enough memory for the table do operation.
1698 @retval RETURN_SUCCESS Opcode is added.
1702 S3BootScriptSaveDispatch (
1708 EFI_BOOT_SCRIPT_DISPATCH ScriptDispatch
;
1710 Length
= (UINT8
)(sizeof (EFI_BOOT_SCRIPT_DISPATCH
));
1712 Script
= S3BootScriptGetEntryAddAddress (Length
);
1713 if (Script
== NULL
) {
1714 return RETURN_OUT_OF_RESOURCES
;
1717 // Build script data
1719 ScriptDispatch
.OpCode
= EFI_BOOT_SCRIPT_DISPATCH_OPCODE
;
1720 ScriptDispatch
.Length
= Length
;
1721 ScriptDispatch
.EntryPoint
= (EFI_PHYSICAL_ADDRESS
)(UINTN
)EntryPoint
;
1723 CopyMem ((VOID
*)Script
, (VOID
*)&ScriptDispatch
, sizeof (EFI_BOOT_SCRIPT_DISPATCH
));
1725 SyncBootScript (Script
);
1727 return RETURN_SUCCESS
;
1731 Adds a record for I/O reads the I/O location and continues when the exit criteria is satisfied or after a
1734 @param Width The width of the I/O operations.
1735 @param Address The base address of the I/O operations.
1736 @param Data The comparison value used for the polling exit criteria.
1737 @param DataMask Mask used for the polling criteria. The bits in the bytes below Width which are zero
1738 in Data are ignored when polling the memory address.
1739 @param Delay The number of 100ns units to poll. Note that timer available may be of poorer
1740 granularity so the delay may be longer.
1742 @retval RETURN_OUT_OF_RESOURCES Not enough memory for the table do operation.
1743 @retval RETURN_SUCCESS Opcode is added.
1748 S3BootScriptSaveIoPoll (
1749 IN S3_BOOT_SCRIPT_LIB_WIDTH Width
,
1759 EFI_BOOT_SCRIPT_IO_POLL ScriptIoPoll
;
1762 WidthInByte
= (UINT8
) (0x01 << (Width
& 0x03));
1763 Length
= (UINT8
)(sizeof (EFI_BOOT_SCRIPT_IO_POLL
) + (WidthInByte
* 2));
1765 Script
= S3BootScriptGetEntryAddAddress (Length
);
1766 if (Script
== NULL
) {
1767 return RETURN_OUT_OF_RESOURCES
;
1770 // Build script data
1772 ScriptIoPoll
.OpCode
= EFI_BOOT_SCRIPT_IO_POLL_OPCODE
;
1773 ScriptIoPoll
.Length
= (UINT8
) (sizeof (EFI_BOOT_SCRIPT_IO_POLL
) + (WidthInByte
* 2));
1774 ScriptIoPoll
.Width
= Width
;
1775 ScriptIoPoll
.Address
= Address
;
1776 ScriptIoPoll
.Delay
= Delay
;
1778 CopyMem ((VOID
*)Script
, (VOID
*)&ScriptIoPoll
, sizeof (EFI_BOOT_SCRIPT_IO_POLL
));
1779 CopyMem ((UINT8
*) (Script
+ sizeof (EFI_BOOT_SCRIPT_IO_POLL
)), Data
, WidthInByte
);
1780 CopyMem ((UINT8
*) (Script
+ sizeof (EFI_BOOT_SCRIPT_IO_POLL
) + WidthInByte
), DataMask
, WidthInByte
);
1782 SyncBootScript (Script
);
1784 return RETURN_SUCCESS
;
1788 Adds a record for PCI configuration space reads and continues when the exit criteria is satisfied or
1789 after a defined duration.
1791 @param Width The width of the I/O operations.
1792 @param Address The address within the PCI configuration space.
1793 @param Data The comparison value used for the polling exit criteria.
1794 @param DataMask Mask used for the polling criteria. The bits in the bytes below Width which are zero
1795 in Data are ignored when polling the memory address
1796 @param Delay The number of 100ns units to poll. Note that timer available may be of poorer
1797 granularity so the delay may be longer.
1799 @retval RETURN_OUT_OF_RESOURCES Not enough memory for the table do operation.
1800 @retval RETURN_SUCCESS Opcode is added.
1801 @note A known Limitations in the implementation which is 64bits operations are not supported.
1806 S3BootScriptSavePciPoll (
1807 IN S3_BOOT_SCRIPT_LIB_WIDTH Width
,
1817 EFI_BOOT_SCRIPT_PCI_CONFIG_POLL ScriptPciPoll
;
1819 if (Width
== S3BootScriptWidthUint64
||
1820 Width
== S3BootScriptWidthFifoUint64
||
1821 Width
== S3BootScriptWidthFillUint64
) {
1822 return EFI_INVALID_PARAMETER
;
1825 WidthInByte
= (UINT8
) (0x01 << (Width
& 0x03));
1826 Length
= (UINT8
)(sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG_POLL
) + (WidthInByte
* 2));
1828 Script
= S3BootScriptGetEntryAddAddress (Length
);
1829 if (Script
== NULL
) {
1830 return RETURN_OUT_OF_RESOURCES
;
1833 // Build script data
1835 ScriptPciPoll
.OpCode
= EFI_BOOT_SCRIPT_PCI_CONFIG_POLL_OPCODE
;
1836 ScriptPciPoll
.Length
= (UINT8
) (sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG_POLL
) + (WidthInByte
* 2));
1837 ScriptPciPoll
.Width
= Width
;
1838 ScriptPciPoll
.Address
= Address
;
1839 ScriptPciPoll
.Delay
= Delay
;
1841 CopyMem ((VOID
*)Script
, (VOID
*)&ScriptPciPoll
, sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG_POLL
));
1842 CopyMem ((UINT8
*) (Script
+ sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG_POLL
)), Data
, WidthInByte
);
1843 CopyMem ((UINT8
*) (Script
+ sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG_POLL
) + WidthInByte
), DataMask
, WidthInByte
);
1845 SyncBootScript (Script
);
1847 return RETURN_SUCCESS
;
1850 Adds a record for PCI configuration space reads and continues when the exit criteria is satisfied or
1851 after a defined duration.
1853 @param Width The width of the I/O operations.
1854 @param Segment The PCI segment number for Address.
1855 @param Address The address within the PCI configuration space.
1856 @param Data The comparison value used for the polling exit criteria.
1857 @param DataMask Mask used for the polling criteria. The bits in the bytes below Width which are zero
1858 in Data are ignored when polling the memory address
1859 @param Delay The number of 100ns units to poll. Note that timer available may be of poorer
1860 granularity so the delay may be longer.
1862 @retval RETURN_OUT_OF_RESOURCES Not enough memory for the table do operation.
1863 @retval RETURN_SUCCESS Opcode is added.
1864 @note A known Limitations in the implementation which is non-zero Segment and 64bits operations are not supported.
1869 S3BootScriptSavePci2Poll (
1870 IN S3_BOOT_SCRIPT_LIB_WIDTH Width
,
1881 EFI_BOOT_SCRIPT_PCI_CONFIG2_POLL ScriptPci2Poll
;
1884 Width
== S3BootScriptWidthUint64
||
1885 Width
== S3BootScriptWidthFifoUint64
||
1886 Width
== S3BootScriptWidthFillUint64
) {
1887 return EFI_INVALID_PARAMETER
;
1890 WidthInByte
= (UINT8
) (0x01 << (Width
& 0x03));
1891 Length
= (UINT8
)(sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG2_POLL
) + (WidthInByte
* 2));
1893 Script
= S3BootScriptGetEntryAddAddress (Length
);
1894 if (Script
== NULL
) {
1895 return RETURN_OUT_OF_RESOURCES
;
1898 // Build script data
1900 ScriptPci2Poll
.OpCode
= EFI_BOOT_SCRIPT_PCI_CONFIG2_POLL_OPCODE
;
1901 ScriptPci2Poll
.Length
= (UINT8
) (sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG2_POLL
) + (WidthInByte
* 2));
1902 ScriptPci2Poll
.Width
= Width
;
1903 ScriptPci2Poll
.Segment
= Segment
;
1904 ScriptPci2Poll
.Address
= Address
;
1905 ScriptPci2Poll
.Delay
= Delay
;
1907 CopyMem ((VOID
*)Script
, (VOID
*)&ScriptPci2Poll
, sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG2_POLL
));
1908 CopyMem ((UINT8
*) (Script
+ sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG2_POLL
)), Data
, WidthInByte
);
1909 CopyMem ((UINT8
*) (Script
+ sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG2_POLL
) + WidthInByte
), DataMask
, WidthInByte
);
1911 SyncBootScript (Script
);
1913 return RETURN_SUCCESS
;
1916 Do the calculation of start address from which a new s3 boot script entry will write into.
1918 @param EntryLength The new entry length.
1919 @param Position specifies the position in the boot script table where the opcode will be
1920 inserted, either before or after, depending on BeforeOrAfter.
1921 @param BeforeOrAfter The flag to indicate to insert the nod before or after the position.
1922 This parameter is effective when InsertFlag is TRUE
1923 @param Script return out the position from which the a new s3 boot script entry will write into
1926 S3BootScriptCalculateInsertAddress (
1927 IN UINT8 EntryLength
,
1928 IN VOID
*Position OPTIONAL
,
1929 IN BOOLEAN BeforeOrAfter OPTIONAL
,
1935 UINTN PositionOffset
;
1936 EFI_BOOT_SCRIPT_COMMON_HEADER ScriptHeader
;
1938 // The entry inserting to table is already added to the end of the table
1940 TableLength
= mS3BootScriptTablePtr
->TableLength
- EntryLength
;
1941 S3TableBase
= mS3BootScriptTablePtr
->TableBase
;
1943 // calculate the Position offset
1945 if (Position
!= NULL
) {
1946 PositionOffset
= (UINTN
) ((UINT8
*)Position
- S3TableBase
);
1949 // If the BeforeOrAfter is FALSE, that means to insert the node right after the node.
1951 if (!BeforeOrAfter
) {
1952 CopyMem ((VOID
*)&ScriptHeader
, Position
, sizeof(EFI_BOOT_SCRIPT_COMMON_HEADER
));
1953 PositionOffset
+= (ScriptHeader
.Length
);
1956 // Insert the node before the adjusted Position
1958 CopyMem (S3TableBase
+PositionOffset
+EntryLength
, S3TableBase
+PositionOffset
, TableLength
- PositionOffset
);
1960 // calculate the the start address for the new entry.
1962 *Script
= S3TableBase
+ PositionOffset
;
1965 if (!BeforeOrAfter
) {
1967 // Insert the node to the end of the table
1969 *Script
= S3TableBase
+ TableLength
;
1972 // Insert the node to the beginning of the table
1974 PositionOffset
= (UINTN
) sizeof(EFI_BOOT_SCRIPT_TABLE_HEADER
);
1975 CopyMem (S3TableBase
+PositionOffset
+EntryLength
, S3TableBase
+PositionOffset
, TableLength
- PositionOffset
);
1976 *Script
= S3TableBase
+ PositionOffset
;
1981 Move the last boot script entry to the position
1983 @param BeforeOrAfter Specifies whether the opcode is stored before (TRUE) or after (FALSE) the position
1984 in the boot script table specified by Position. If Position is NULL or points to
1985 NULL then the new opcode is inserted at the beginning of the table (if TRUE) or end
1986 of the table (if FALSE).
1987 @param Position On entry, specifies the position in the boot script table where the opcode will be
1988 inserted, either before or after, depending on BeforeOrAfter. On exit, specifies
1989 the position of the inserted opcode in the boot script table.
1991 @retval RETURN_OUT_OF_RESOURCES The table is not available.
1992 @retval RETURN_INVALID_PARAMETER The Position is not a valid position in the boot script table.
1993 @retval RETURN_SUCCESS Opcode is inserted.
1997 S3BootScriptMoveLastOpcode (
1998 IN BOOLEAN BeforeOrAfter
,
1999 IN OUT VOID
**Position OPTIONAL
2006 EFI_BOOT_SCRIPT_COMMON_HEADER ScriptHeader
;
2007 BOOLEAN ValidatePosition
;
2009 UINT8 TempBootScriptEntry
[BOOT_SCRIPT_NODE_MAX_LENGTH
];
2011 ValidatePosition
= FALSE
;
2012 TempPosition
= (Position
== NULL
) ? NULL
:(*Position
);
2015 // Check that the script is initialized and synced without adding an entry to the script.
2017 Script
= S3BootScriptGetEntryAddAddress (0);
2018 if (Script
== NULL
) {
2019 return RETURN_OUT_OF_RESOURCES
;
2021 Script
= mS3BootScriptTablePtr
->TableBase
;
2023 StartAddress
= (UINTN
) Script
;
2024 TableLength
= mS3BootScriptTablePtr
->TableLength
;
2025 Script
= Script
+ sizeof(EFI_BOOT_SCRIPT_TABLE_HEADER
);
2026 LastOpcode
= Script
;
2028 // Find the last boot Script Entry which is not the terminate node
2030 while ((UINTN
) Script
< (UINTN
) (StartAddress
+ TableLength
)) {
2031 CopyMem ((VOID
*)&ScriptHeader
, Script
, sizeof(EFI_BOOT_SCRIPT_COMMON_HEADER
));
2032 if (TempPosition
!= NULL
&& TempPosition
== Script
) {
2034 // If the position is specified, the position must be pointed to a boot script entry start address.
2036 ValidatePosition
= TRUE
;
2038 if (ScriptHeader
.OpCode
!= S3_BOOT_SCRIPT_LIB_TERMINATE_OPCODE
) {
2039 LastOpcode
= Script
;
2041 Script
= Script
+ ScriptHeader
.Length
;
2044 // If the position is specified, but not the start of a boot script entry, it is a invalid input
2046 if (TempPosition
!= NULL
&& !ValidatePosition
) {
2047 return RETURN_INVALID_PARAMETER
;
2050 CopyMem ((VOID
*)&ScriptHeader
, LastOpcode
, sizeof(EFI_BOOT_SCRIPT_COMMON_HEADER
));
2052 CopyMem((VOID
*)TempBootScriptEntry
, LastOpcode
, ScriptHeader
.Length
);
2054 // Find the right position to write the node in
2056 S3BootScriptCalculateInsertAddress (
2057 ScriptHeader
.Length
,
2063 // Copy the node to Boot script table
2065 CopyMem((VOID
*)Script
, (VOID
*)TempBootScriptEntry
, ScriptHeader
.Length
);
2067 SyncBootScript (Script
);
2070 // return out the Position
2072 if (Position
!= NULL
) {
2075 return RETURN_SUCCESS
;
2078 Create a Label node in the boot script table.
2080 @param BeforeOrAfter Specifies whether the opcode is stored before (TRUE) or after (FALSE) the position
2081 in the boot script table specified by Position. If Position is NULL or points to
2082 NULL then the new opcode is inserted at the beginning of the table (if TRUE) or end
2083 of the table (if FALSE).
2084 @param Position On entry, specifies the position in the boot script table where the opcode will be
2085 inserted, either before or after, depending on BeforeOrAfter. On exit, specifies
2086 the position of the inserted opcode in the boot script table.
2087 @param InformationLength Length of the label in bytes
2088 @param Information Label to be logged in the boot scrpit
2090 @retval RETURN_INVALID_PARAMETER The Position is not a valid position in the boot script table.
2091 @retval RETURN_OUT_OF_RESOURCES Not enough memory for the table do operation.
2092 @retval RETURN_SUCCESS Opcode is added.
2097 S3BootScriptLabelInternal (
2098 IN BOOLEAN BeforeOrAfter
,
2099 IN OUT VOID
**Position OPTIONAL
,
2100 IN UINT32 InformationLength
,
2101 IN CONST CHAR8
*Information
2106 EFI_BOOT_SCRIPT_INFORMATION ScriptInformation
;
2108 Length
= (UINT8
)(sizeof (EFI_BOOT_SCRIPT_INFORMATION
) + InformationLength
);
2110 Script
= S3BootScriptGetEntryAddAddress (Length
);
2111 if (Script
== NULL
) {
2112 return RETURN_OUT_OF_RESOURCES
;
2115 // Build script data
2117 ScriptInformation
.OpCode
= S3_BOOT_SCRIPT_LIB_LABEL_OPCODE
;
2118 ScriptInformation
.Length
= Length
;
2121 ScriptInformation
.InformationLength
= InformationLength
;
2123 CopyMem ((VOID
*)Script
, (VOID
*)&ScriptInformation
, sizeof (EFI_BOOT_SCRIPT_INFORMATION
));
2124 CopyMem ((VOID
*)(Script
+ sizeof (EFI_BOOT_SCRIPT_INFORMATION
)), (VOID
*) Information
, (UINTN
) InformationLength
);
2126 SyncBootScript (Script
);
2128 return S3BootScriptMoveLastOpcode (BeforeOrAfter
, Position
);
2132 Find a label within the boot script table and, if not present, optionally create it.
2134 @param BeforeOrAfter Specifies whether the opcode is stored before (TRUE)
2135 or after (FALSE) the position in the boot script table
2136 specified by Position.
2137 @param CreateIfNotFound Specifies whether the label will be created if the label
2138 does not exists (TRUE) or not (FALSE).
2139 @param Position On entry, specifies the position in the boot script table
2140 where the opcode will be inserted, either before or after,
2141 depending on BeforeOrAfter. On exit, specifies the position
2142 of the inserted opcode in the boot script table.
2143 @param Label Points to the label which will be inserted in the boot script table.
2145 @retval EFI_SUCCESS The operation succeeded. A record was added into the
2146 specified script table.
2147 @retval EFI_INVALID_PARAMETER The parameter is illegal or the given boot script is not supported.
2148 If the opcode is unknow or not supported because of the PCD
2150 @retval EFI_OUT_OF_RESOURCES There is insufficient memory to store the boot script.
2156 IN BOOLEAN BeforeOrAfter
,
2157 IN BOOLEAN CreateIfNotFound
,
2158 IN OUT VOID
**Position OPTIONAL
,
2159 IN CONST CHAR8
*Label
2165 EFI_BOOT_SCRIPT_COMMON_HEADER ScriptHeader
;
2166 EFI_BOOT_SCRIPT_TABLE_HEADER TableHeader
;
2171 if (Label
== NULL
) {
2172 return EFI_INVALID_PARAMETER
;
2175 // Check empty Label
2177 if (Label
[0] == '\0') {
2178 return EFI_INVALID_PARAMETER
;
2182 // Check that the script is initialized and synced without adding an entry to the script.
2183 // The code must search for the label first before it knows if a new entry needs
2186 Script
= S3BootScriptGetEntryAddAddress (0);
2187 if (Script
== NULL
) {
2188 return RETURN_OUT_OF_RESOURCES
;
2192 // Check the header and search for existing label.
2194 Script
= mS3BootScriptTablePtr
->TableBase
;
2195 CopyMem ((VOID
*)&TableHeader
, Script
, sizeof(EFI_BOOT_SCRIPT_TABLE_HEADER
));
2196 if (TableHeader
.OpCode
!= S3_BOOT_SCRIPT_LIB_TABLE_OPCODE
) {
2197 return EFI_INVALID_PARAMETER
;
2199 StartAddress
= (UINTN
) Script
;
2200 TableLength
= mS3BootScriptTablePtr
->TableLength
;
2201 Script
= Script
+ TableHeader
.Length
;
2202 while ((UINTN
) Script
< (UINTN
) (StartAddress
+ TableLength
)) {
2204 CopyMem ((VOID
*)&ScriptHeader
, Script
, sizeof(EFI_BOOT_SCRIPT_COMMON_HEADER
));
2205 if (ScriptHeader
.OpCode
== S3_BOOT_SCRIPT_LIB_LABEL_OPCODE
) {
2206 if (AsciiStrCmp ((CHAR8
*)(UINTN
)(Script
+sizeof(EFI_BOOT_SCRIPT_INFORMATION
)), Label
) == 0) {
2207 (*Position
) = Script
;
2211 Script
= Script
+ ScriptHeader
.Length
;
2213 if (CreateIfNotFound
) {
2214 LabelLength
= (UINT32
)AsciiStrSize(Label
);
2215 return S3BootScriptLabelInternal (BeforeOrAfter
,Position
, LabelLength
, Label
);
2217 return EFI_NOT_FOUND
;
2222 Compare two positions in the boot script table and return their relative position.
2223 @param Position1 The positions in the boot script table to compare
2224 @param Position2 The positions in the boot script table to compare
2225 @param RelativePosition On return, points to the result of the comparison
2227 @retval EFI_SUCCESS The operation succeeded. A record was added into the
2228 specified script table.
2229 @retval EFI_INVALID_PARAMETER The parameter is illegal or the given boot script is not supported.
2230 If the opcode is unknow or not supported because of the PCD
2232 @retval EFI_OUT_OF_RESOURCES There is insufficient memory to store the boot script.
2237 S3BootScriptCompare (
2238 IN UINT8
*Position1
,
2239 IN UINT8
*Position2
,
2240 OUT UINTN
*RelativePosition
2246 if (RelativePosition
== NULL
) {
2247 return EFI_INVALID_PARAMETER
;
2251 // Check that the script is initialized and synced without adding an entry to the script.
2253 Script
= S3BootScriptGetEntryAddAddress (0);
2254 if (Script
== NULL
) {
2255 return RETURN_OUT_OF_RESOURCES
;
2257 Script
= mS3BootScriptTablePtr
->TableBase
;
2260 // mS3BootScriptTablePtr->TableLength does not include the termination node, so add it up
2262 TableLength
= mS3BootScriptTablePtr
->TableLength
+ sizeof (EFI_BOOT_SCRIPT_TERMINATE
);
2263 if (Position1
< Script
|| Position1
> Script
+TableLength
) {
2264 return EFI_INVALID_PARAMETER
;
2266 if (Position2
< Script
|| Position2
> Script
+TableLength
) {
2267 return EFI_INVALID_PARAMETER
;
2269 *RelativePosition
= (Position1
< Position2
)?-1:((Position1
== Position2
)?0:1);