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 S3TablePtr
= (SCRIPT_TABLE_PRIVATE_DATA
*)(UINTN
)PcdGet64(PcdS3BootScriptTablePrivateDataPtr
);
442 // The Boot script private data is not be initialized. create it
444 if (S3TablePtr
== 0) {
445 Buffer
= SIZE_4GB
- 1;
446 Status
= gBS
->AllocatePages (
448 EfiReservedMemoryType
,
449 EFI_SIZE_TO_PAGES(sizeof(SCRIPT_TABLE_PRIVATE_DATA
)),
452 if (EFI_ERROR (Status
)) {
453 return RETURN_OUT_OF_RESOURCES
;
455 S3TablePtr
= (VOID
*) (UINTN
) Buffer
;
457 PcdSet64 (PcdS3BootScriptTablePrivateDataPtr
, (UINT64
) (UINTN
)S3TablePtr
);
458 ZeroMem (S3TablePtr
, sizeof(SCRIPT_TABLE_PRIVATE_DATA
));
460 // Create event to notify the library system enter the SmmLocked phase.
462 Event
= EfiCreateProtocolNotifyEvent (
463 &gEfiDxeSmmReadyToLockProtocolGuid
,
465 S3BootScriptEventCallBack
,
469 ASSERT (Event
!= NULL
);
471 mS3BootScriptTablePtr
= S3TablePtr
;
474 // Get InSmm, we need to register SmmReadyToLock if this library is linked to SMM driver.
476 Status
= gBS
->LocateProtocol (&gEfiSmmBase2ProtocolGuid
, NULL
, (VOID
**) &SmmBase2
);
477 if (EFI_ERROR (Status
)) {
478 return RETURN_SUCCESS
;
480 Status
= SmmBase2
->InSmm (SmmBase2
, &InSmm
);
481 if (EFI_ERROR (Status
)) {
482 return RETURN_SUCCESS
;
485 return RETURN_SUCCESS
;
488 // Good, we are in SMM
490 Status
= SmmBase2
->GetSmstLocation (SmmBase2
, &Smst
);
491 if (EFI_ERROR (Status
)) {
492 return RETURN_SUCCESS
;
495 S3TableSmmPtr
= (SCRIPT_TABLE_PRIVATE_DATA
*)(UINTN
)PcdGet64(PcdS3BootScriptTablePrivateSmmDataPtr
);
497 // The Boot script private data in SMM is not be initialized. create it
499 if (S3TableSmmPtr
== 0) {
500 Status
= Smst
->SmmAllocatePool (
501 EfiRuntimeServicesData
,
502 sizeof(SCRIPT_TABLE_PRIVATE_DATA
),
503 (VOID
**) &S3TableSmmPtr
505 if (EFI_ERROR (Status
)) {
506 return RETURN_OUT_OF_RESOURCES
;
509 PcdSet64 (PcdS3BootScriptTablePrivateSmmDataPtr
, (UINT64
) (UINTN
)S3TableSmmPtr
);
510 ZeroMem (S3TableSmmPtr
, sizeof(SCRIPT_TABLE_PRIVATE_DATA
));
513 // Register SmmExitBootServices and SmmLegacyBoot notification.
516 Status
= Smst
->SmmRegisterProtocolNotify (
517 &gEdkiiSmmExitBootServicesProtocolGuid
,
518 S3BootScriptSmmAtRuntimeCallBack
,
521 ASSERT_EFI_ERROR (Status
);
524 Status
= Smst
->SmmRegisterProtocolNotify (
525 &gEdkiiSmmLegacyBootProtocolGuid
,
526 S3BootScriptSmmAtRuntimeCallBack
,
529 ASSERT_EFI_ERROR (Status
);
531 mS3BootScriptTableSmmPtr
= S3TableSmmPtr
;
534 // Register SmmReadyToLock notification.
537 Status
= Smst
->SmmRegisterProtocolNotify (
538 &gEfiSmmReadyToLockProtocolGuid
,
539 S3BootScriptSmmEventCallBack
,
542 ASSERT_EFI_ERROR (Status
);
544 return RETURN_SUCCESS
;
547 To get the start address from which a new boot time s3 boot script entry will write into.
548 If the table is not exist, the functio will first allocate a buffer for the table
549 If the table buffer is not enough for the new entry, in non-smm mode, the funtion will
550 invoke reallocate to enlarge buffer.
552 @param EntryLength the new entry length.
554 @retval the address from which the a new s3 boot script entry will write into
557 S3BootScriptGetBootTimeEntryAddAddress (
561 EFI_PHYSICAL_ADDRESS S3TableBase
;
562 EFI_PHYSICAL_ADDRESS NewS3TableBase
;
567 EFI_BOOT_SCRIPT_TABLE_HEADER
*ScriptTableInfo
;
569 S3TableBase
= (EFI_PHYSICAL_ADDRESS
)(UINTN
)(mS3BootScriptTablePtr
->TableBase
);
570 if (S3TableBase
== 0) {
572 // The table is not exist. This is the first to add entry.
573 // Allocate ACPI script table space under 4G memory.
575 S3TableBase
= 0xffffffff;
576 Status
= gBS
->AllocatePages (
578 EfiReservedMemoryType
,
579 2 + PcdGet16(PcdS3BootScriptRuntimeTableReservePageNumber
),
580 (EFI_PHYSICAL_ADDRESS
*)&S3TableBase
583 if (EFI_ERROR(Status
)) {
584 ASSERT_EFI_ERROR (Status
);
590 ScriptTableInfo
= (EFI_BOOT_SCRIPT_TABLE_HEADER
*)(UINTN
)S3TableBase
;
591 ScriptTableInfo
->OpCode
= S3_BOOT_SCRIPT_LIB_TABLE_OPCODE
;
592 ScriptTableInfo
->Length
= (UINT8
) sizeof (EFI_BOOT_SCRIPT_TABLE_HEADER
);
593 ScriptTableInfo
->Version
= BOOT_SCRIPT_TABLE_VERSION
;
594 ScriptTableInfo
->TableLength
= 0; // will be calculate at CloseTable
595 mS3BootScriptTablePtr
->TableLength
= sizeof (EFI_BOOT_SCRIPT_TABLE_HEADER
);
596 mS3BootScriptTablePtr
->TableBase
= (UINT8
*)(UINTN
)S3TableBase
;
597 mS3BootScriptTablePtr
->TableMemoryPageNumber
= (UINT16
)(2 + PcdGet16(PcdS3BootScriptRuntimeTableReservePageNumber
));
600 // Here we do not count the reserved memory for runtime script table.
601 PageNumber
= (UINT16
) (mS3BootScriptTablePtr
->TableMemoryPageNumber
- PcdGet16(PcdS3BootScriptRuntimeTableReservePageNumber
));
602 TableLength
= mS3BootScriptTablePtr
->TableLength
;
603 if ((UINTN
) EFI_PAGES_TO_SIZE ((UINTN
) PageNumber
) < (UINTN
) (TableLength
+ EntryLength
+ sizeof (EFI_BOOT_SCRIPT_TERMINATE
))) {
605 // The buffer is too small to hold the table, Reallocate the buffer
607 NewS3TableBase
= 0xffffffff;
608 Status
= gBS
->AllocatePages (
610 EfiReservedMemoryType
,
611 2 + PageNumber
+ PcdGet16(PcdS3BootScriptRuntimeTableReservePageNumber
),
612 (EFI_PHYSICAL_ADDRESS
*)&NewS3TableBase
615 if (EFI_ERROR(Status
)) {
616 ASSERT_EFI_ERROR (Status
);
620 CopyMem ((VOID
*)(UINTN
)NewS3TableBase
, (VOID
*)(UINTN
)S3TableBase
, TableLength
);
621 gBS
->FreePages (S3TableBase
, mS3BootScriptTablePtr
->TableMemoryPageNumber
);
623 mS3BootScriptTablePtr
->TableBase
= (UINT8
*)(UINTN
)NewS3TableBase
;
624 mS3BootScriptTablePtr
->TableMemoryPageNumber
= (UINT16
) (2 + PageNumber
+ PcdGet16(PcdS3BootScriptRuntimeTableReservePageNumber
));
627 // calculate the the start address for the new entry.
629 NewEntryPtr
= mS3BootScriptTablePtr
->TableBase
+ TableLength
;
632 // update the table lenghth
634 mS3BootScriptTablePtr
->TableLength
= TableLength
+ EntryLength
;
637 // In the boot time, we will not append the termination entry to the boot script
638 // table until the callers think there is no boot time data that should be added and
639 // it is caller's responsibility to explicit call the CloseTable.
646 To get the start address from which a new runtime(after SmmReadyToLock) s3 boot script entry will write into.
647 In this case, it should be ensured that there is enough buffer to hold the entry.
649 @param EntryLength the new entry length.
651 @retval the address from which the a new s3 runtime(after SmmReadyToLock) script entry will write into
654 S3BootScriptGetRuntimeEntryAddAddress (
662 // Check if the memory range reserved for S3 Boot Script table is large enough to hold the node.
664 if ((UINTN
) (mS3BootScriptTablePtr
->TableLength
+ EntryLength
+ sizeof (EFI_BOOT_SCRIPT_TERMINATE
)) <= (UINTN
) EFI_PAGES_TO_SIZE ((UINTN
) (mS3BootScriptTablePtr
->TableMemoryPageNumber
))) {
665 NewEntryPtr
= mS3BootScriptTablePtr
->TableBase
+ mS3BootScriptTablePtr
->TableLength
;
666 mS3BootScriptTablePtr
->TableLength
= mS3BootScriptTablePtr
->TableLength
+ EntryLength
;
668 // Append a terminate node on every insert
670 S3BootScriptInternalCloseTable ();
672 return (UINT8
*)NewEntryPtr
;
676 This function is to restore boot time boot script data from LockBox.
680 RestoreBootTimeDataFromLockBox (
688 // Restore boot time boot script data from LockBox.
690 LockBoxLength
= mS3BootScriptTablePtr
->BootTimeScriptLength
;
691 Status
= RestoreLockBox (
692 &mBootScriptDataBootTimeGuid
,
693 (VOID
*) mS3BootScriptTablePtr
->TableBase
,
696 ASSERT_EFI_ERROR (Status
);
699 // Update the data to BootScriptData LockBox.
701 Status
= UpdateLockBox (
702 &mBootScriptDataGuid
,
704 (VOID
*) mS3BootScriptTablePtr
->TableBase
,
707 ASSERT_EFI_ERROR (Status
);
710 // Update TableLength.
712 mS3BootScriptTablePtr
->TableLength
= (UINT32
) (mS3BootScriptTablePtr
->BootTimeScriptLength
- sizeof (EFI_BOOT_SCRIPT_TERMINATE
));
716 To get the start address from which a new s3 boot script entry will write into.
718 @param EntryLength the new entry length.
720 @retval the address from which the a new s3 boot script entry will write into
723 S3BootScriptGetEntryAddAddress (
729 if (mS3BootScriptTablePtr
->SmmLocked
) {
731 // We need check InSmm, because after SmmReadyToLock, only SMM driver is allowed to write boot script.
733 if (!mS3BootScriptTablePtr
->InSmm
) {
735 // Add DEBUG ERROR, so that we can find it after SmmReadyToLock.
736 // Do not use ASSERT, because we may have test to invoke this interface.
738 DEBUG ((EFI_D_ERROR
, "FATAL ERROR: Set boot script outside SMM after SmmReadyToLock!!!\n"));
742 if (mS3BootScriptTablePtr
->BackFromS3
) {
744 // Back from S3, restore boot time boot script data from LockBox
745 // and set BackFromS3 flag back to FALSE.
747 RestoreBootTimeDataFromLockBox ();
748 mS3BootScriptTablePtr
->BackFromS3
= FALSE
;
751 NewEntryPtr
= S3BootScriptGetRuntimeEntryAddAddress (EntryLength
);
753 NewEntryPtr
= S3BootScriptGetBootTimeEntryAddAddress (EntryLength
);
760 Sync BootScript LockBox data.
762 @param Script The address from where the boot script has been added or updated.
772 UINT32 TotalScriptLength
;
774 if (!mS3BootScriptTablePtr
->SmmLocked
|| !mS3BootScriptTablePtr
->InSmm
) {
776 // If it is not after SmmReadyToLock in SMM,
782 ScriptOffset
= (UINT32
) (Script
- mS3BootScriptTablePtr
->TableBase
);
784 TotalScriptLength
= (UINT32
) (mS3BootScriptTablePtr
->TableLength
+ sizeof (EFI_BOOT_SCRIPT_TERMINATE
));
787 // Update BootScriptData
788 // So in S3 resume, the data can be restored correctly.
790 Status
= UpdateLockBox (
791 &mBootScriptDataGuid
,
793 (VOID
*)((UINTN
)mS3BootScriptTablePtr
->TableBase
+ ScriptOffset
),
794 TotalScriptLength
- ScriptOffset
796 ASSERT_EFI_ERROR (Status
);
799 // Now the length field is updated, need sync to lockbox.
800 // So at S3 resume, the data can be restored correctly.
802 Status
= UpdateLockBox (
803 &mBootScriptDataGuid
,
804 OFFSET_OF (EFI_BOOT_SCRIPT_TABLE_HEADER
, TableLength
),
806 sizeof (TotalScriptLength
)
808 ASSERT_EFI_ERROR (Status
);
812 This is an function to close the S3 boot script table. The function could only be called in
813 BOOT time phase. To comply with the Framework spec definition on
814 EFI_BOOT_SCRIPT_SAVE_PROTOCOL.CloseTable(), this function will fulfill following things:
815 1. Closes the specified boot script table
816 2. It allocates a new memory pool to duplicate all the boot scripts in the specified table.
817 Once this function is called, the table maintained by the library will be destroyed
818 after it is copied into the allocated pool.
819 3. Any attempts to add a script record after calling this function will cause a new table
820 to be created by the library.
821 4. The base address of the allocated pool will be returned in Address. Note that after
822 using the boot script table, the CALLER is responsible for freeing the pool that is allocated
825 In Spec PI1.1, this EFI_BOOT_SCRIPT_SAVE_PROTOCOL.CloseTable() is retired. To provides this API for now is
826 for Framework Spec compatibility.
828 If anyone does call CloseTable() on a real platform, then the caller is responsible for figuring out
829 how to get the script to run at S3 resume because the boot script maintained by the lib will be
832 @return the base address of the new copy of the boot script table.
833 @note this function could only called in boot time phase
838 S3BootScriptCloseTable (
846 EFI_BOOT_SCRIPT_TABLE_HEADER
*ScriptTableInfo
;
848 S3TableBase
= mS3BootScriptTablePtr
->TableBase
;
849 if (S3TableBase
== 0) {
853 // Append the termination record the S3 boot script table
855 S3BootScriptInternalCloseTable();
856 TableLength
= mS3BootScriptTablePtr
->TableLength
+ sizeof (EFI_BOOT_SCRIPT_TERMINATE
);
858 // Allocate the buffer and copy the boot script to the buffer.
860 Status
= gBS
->AllocatePool (
865 if (EFI_ERROR (Status
)) {
868 CopyMem (Buffer
, S3TableBase
, TableLength
);
871 // Destroy the table maintained by the library so that the next write operation
872 // will write the record to the first entry of the table.
874 // Fill the table header.
875 ScriptTableInfo
= (EFI_BOOT_SCRIPT_TABLE_HEADER
*)S3TableBase
;
876 ScriptTableInfo
->OpCode
= S3_BOOT_SCRIPT_LIB_TABLE_OPCODE
;
877 ScriptTableInfo
->Length
= (UINT8
) sizeof (EFI_BOOT_SCRIPT_TABLE_HEADER
);
878 ScriptTableInfo
->TableLength
= 0; // will be calculate at close the table
880 mS3BootScriptTablePtr
->TableLength
= sizeof (EFI_BOOT_SCRIPT_TABLE_HEADER
);
884 Save I/O write to boot script
886 @param Width The width of the I/O operations.Enumerated in S3_BOOT_SCRIPT_LIB_WIDTH.
887 @param Address The base address of the I/O operations.
888 @param Count The number of I/O operations to perform.
889 @param Buffer The source buffer from which to write data.
891 @retval RETURN_OUT_OF_RESOURCES Not enough memory for the table do operation.
892 @retval RETURN_SUCCESS Opcode is added.
896 S3BootScriptSaveIoWrite (
897 IN S3_BOOT_SCRIPT_LIB_WIDTH Width
,
907 EFI_BOOT_SCRIPT_IO_WRITE ScriptIoWrite
;
909 WidthInByte
= (UINT8
) (0x01 << (Width
& 0x03));
910 Length
= (UINT8
)(sizeof (EFI_BOOT_SCRIPT_IO_WRITE
) + (WidthInByte
* Count
));
912 Script
= S3BootScriptGetEntryAddAddress (Length
);
913 if (Script
== NULL
) {
914 return RETURN_OUT_OF_RESOURCES
;
919 ScriptIoWrite
.OpCode
= EFI_BOOT_SCRIPT_IO_WRITE_OPCODE
;
920 ScriptIoWrite
.Length
= Length
;
921 ScriptIoWrite
.Width
= Width
;
922 ScriptIoWrite
.Address
= Address
;
923 ScriptIoWrite
.Count
= (UINT32
) Count
;
924 CopyMem ((VOID
*)Script
, (VOID
*)&ScriptIoWrite
, sizeof(EFI_BOOT_SCRIPT_IO_WRITE
));
925 CopyMem ((VOID
*)(Script
+ sizeof (EFI_BOOT_SCRIPT_IO_WRITE
)), Buffer
, WidthInByte
* Count
);
927 SyncBootScript (Script
);
929 return RETURN_SUCCESS
;
933 Adds a record for an I/O modify operation into a S3 boot script table
935 @param Width The width of the I/O operations.Enumerated in S3_BOOT_SCRIPT_LIB_WIDTH.
936 @param Address The base address of the I/O operations.
937 @param Data A pointer to the data to be OR-ed.
938 @param DataMask A pointer to the data mask to be AND-ed with the data read from the register
940 @retval RETURN_OUT_OF_RESOURCES Not enough memory for the table do operation.
941 @retval RETURN_SUCCESS Opcode is added.
945 S3BootScriptSaveIoReadWrite (
946 IN S3_BOOT_SCRIPT_LIB_WIDTH Width
,
955 EFI_BOOT_SCRIPT_IO_READ_WRITE ScriptIoReadWrite
;
957 WidthInByte
= (UINT8
) (0x01 << (Width
& 0x03));
958 Length
= (UINT8
)(sizeof (EFI_BOOT_SCRIPT_IO_READ_WRITE
) + (WidthInByte
* 2));
960 Script
= S3BootScriptGetEntryAddAddress (Length
);
961 if (Script
== NULL
) {
962 return RETURN_OUT_OF_RESOURCES
;
967 ScriptIoReadWrite
.OpCode
= EFI_BOOT_SCRIPT_IO_READ_WRITE_OPCODE
;
968 ScriptIoReadWrite
.Length
= Length
;
969 ScriptIoReadWrite
.Width
= Width
;
970 ScriptIoReadWrite
.Address
= Address
;
972 CopyMem ((VOID
*)Script
, (VOID
*)&ScriptIoReadWrite
, sizeof(EFI_BOOT_SCRIPT_IO_READ_WRITE
));
973 CopyMem ((VOID
*)(Script
+ sizeof (EFI_BOOT_SCRIPT_IO_READ_WRITE
)), Data
, WidthInByte
);
974 CopyMem ((VOID
*)(Script
+ sizeof (EFI_BOOT_SCRIPT_IO_READ_WRITE
) + WidthInByte
), DataMask
, WidthInByte
);
976 SyncBootScript (Script
);
978 return RETURN_SUCCESS
;
981 Adds a record for a memory write operation into a specified boot script table.
983 @param Width The width of the I/O operations.Enumerated in S3_BOOT_SCRIPT_LIB_WIDTH.
984 @param Address The base address of the memory operations
985 @param Count The number of memory operations to perform.
986 @param Buffer The source buffer from which to write the data.
988 @retval RETURN_OUT_OF_RESOURCES Not enough memory for the table do operation.
989 @retval RETURN_SUCCESS Opcode is added.
993 S3BootScriptSaveMemWrite (
994 IN S3_BOOT_SCRIPT_LIB_WIDTH Width
,
1003 EFI_BOOT_SCRIPT_MEM_WRITE ScriptMemWrite
;
1005 WidthInByte
= (UINT8
) (0x01 << (Width
& 0x03));
1006 Length
= (UINT8
)(sizeof (EFI_BOOT_SCRIPT_MEM_WRITE
) + (WidthInByte
* Count
));
1008 Script
= S3BootScriptGetEntryAddAddress (Length
);
1009 if (Script
== NULL
) {
1010 return RETURN_OUT_OF_RESOURCES
;
1013 // Build script data
1015 ScriptMemWrite
.OpCode
= EFI_BOOT_SCRIPT_MEM_WRITE_OPCODE
;
1016 ScriptMemWrite
.Length
= Length
;
1017 ScriptMemWrite
.Width
= Width
;
1018 ScriptMemWrite
.Address
= Address
;
1019 ScriptMemWrite
.Count
= (UINT32
) Count
;
1021 CopyMem ((VOID
*)Script
, (VOID
*)&ScriptMemWrite
, sizeof(EFI_BOOT_SCRIPT_MEM_WRITE
));
1022 CopyMem ((VOID
*)(Script
+ sizeof (EFI_BOOT_SCRIPT_MEM_WRITE
)), Buffer
, WidthInByte
* Count
);
1024 SyncBootScript (Script
);
1026 return RETURN_SUCCESS
;
1029 Adds a record for a memory modify operation into a specified boot script table.
1031 @param Width The width of the I/O operations.Enumerated in S3_BOOT_SCRIPT_LIB_WIDTH.
1032 @param Address The base address of the memory operations. Address needs alignment if required
1033 @param Data A pointer to the data to be OR-ed.
1034 @param DataMask A pointer to the data mask to be AND-ed with the data read from the register.
1036 @retval RETURN_OUT_OF_RESOURCES Not enough memory for the table do operation.
1037 @retval RETURN_SUCCESS Opcode is added.
1041 S3BootScriptSaveMemReadWrite (
1042 IN S3_BOOT_SCRIPT_LIB_WIDTH Width
,
1051 EFI_BOOT_SCRIPT_MEM_READ_WRITE ScriptMemReadWrite
;
1053 WidthInByte
= (UINT8
) (0x01 << (Width
& 0x03));
1054 Length
= (UINT8
)(sizeof (EFI_BOOT_SCRIPT_MEM_READ_WRITE
) + (WidthInByte
* 2));
1056 Script
= S3BootScriptGetEntryAddAddress (Length
);
1057 if (Script
== NULL
) {
1058 return RETURN_OUT_OF_RESOURCES
;
1061 // Build script data
1063 ScriptMemReadWrite
.OpCode
= EFI_BOOT_SCRIPT_MEM_READ_WRITE_OPCODE
;
1064 ScriptMemReadWrite
.Length
= Length
;
1065 ScriptMemReadWrite
.Width
= Width
;
1066 ScriptMemReadWrite
.Address
= Address
;
1068 CopyMem ((VOID
*)Script
, (VOID
*)&ScriptMemReadWrite
, sizeof (EFI_BOOT_SCRIPT_MEM_READ_WRITE
));
1069 CopyMem ((VOID
*)(Script
+ sizeof (EFI_BOOT_SCRIPT_MEM_READ_WRITE
)), Data
, WidthInByte
);
1070 CopyMem ((VOID
*)(Script
+ sizeof (EFI_BOOT_SCRIPT_MEM_READ_WRITE
) + WidthInByte
), DataMask
, WidthInByte
);
1072 SyncBootScript (Script
);
1074 return RETURN_SUCCESS
;
1077 Adds a record for a PCI configuration space write operation into a specified boot script table.
1079 @param Width The width of the I/O operations.Enumerated in S3_BOOT_SCRIPT_LIB_WIDTH.
1080 @param Address The address within the PCI configuration space.
1081 @param Count The number of PCI operations to perform.
1082 @param Buffer The source buffer from which to write the data.
1084 @retval RETURN_OUT_OF_RESOURCES Not enough memory for the table do operation.
1085 @retval RETURN_SUCCESS Opcode is added.
1086 @note A known Limitations in the implementation which is 64bits operations are not supported.
1091 S3BootScriptSavePciCfgWrite (
1092 IN S3_BOOT_SCRIPT_LIB_WIDTH Width
,
1101 EFI_BOOT_SCRIPT_PCI_CONFIG_WRITE ScriptPciWrite
;
1103 if (Width
== S3BootScriptWidthUint64
||
1104 Width
== S3BootScriptWidthFifoUint64
||
1105 Width
== S3BootScriptWidthFillUint64
) {
1106 return EFI_INVALID_PARAMETER
;
1109 WidthInByte
= (UINT8
) (0x01 << (Width
& 0x03));
1110 Length
= (UINT8
)(sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG_WRITE
) + (WidthInByte
* Count
));
1112 Script
= S3BootScriptGetEntryAddAddress (Length
);
1113 if (Script
== NULL
) {
1114 return RETURN_OUT_OF_RESOURCES
;
1117 // Build script data
1119 ScriptPciWrite
.OpCode
= EFI_BOOT_SCRIPT_PCI_CONFIG_WRITE_OPCODE
;
1120 ScriptPciWrite
.Length
= Length
;
1121 ScriptPciWrite
.Width
= Width
;
1122 ScriptPciWrite
.Address
= Address
;
1123 ScriptPciWrite
.Count
= (UINT32
) Count
;
1125 CopyMem ((VOID
*)Script
, (VOID
*)&ScriptPciWrite
, sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG_WRITE
));
1126 CopyMem ((VOID
*)(Script
+ sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG_WRITE
)), Buffer
, WidthInByte
* Count
);
1128 SyncBootScript (Script
);
1130 return RETURN_SUCCESS
;
1133 Adds a record for a PCI configuration space modify operation into a specified boot script table.
1135 @param Width The width of the I/O operations.Enumerated in S3_BOOT_SCRIPT_LIB_WIDTH.
1136 @param Address The address within the PCI configuration space.
1137 @param Data A pointer to the data to be OR-ed.The size depends on Width.
1138 @param DataMask A pointer to the data mask to be AND-ed.
1140 @retval RETURN_OUT_OF_RESOURCES Not enough memory for the table do operation.
1141 @retval RETURN__SUCCESS Opcode is added.
1142 @note A known Limitations in the implementation which is 64bits operations are not supported.
1147 S3BootScriptSavePciCfgReadWrite (
1148 IN S3_BOOT_SCRIPT_LIB_WIDTH Width
,
1157 EFI_BOOT_SCRIPT_PCI_CONFIG_READ_WRITE ScriptPciReadWrite
;
1159 if (Width
== S3BootScriptWidthUint64
||
1160 Width
== S3BootScriptWidthFifoUint64
||
1161 Width
== S3BootScriptWidthFillUint64
) {
1162 return EFI_INVALID_PARAMETER
;
1165 WidthInByte
= (UINT8
) (0x01 << (Width
& 0x03));
1166 Length
= (UINT8
)(sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG_READ_WRITE
) + (WidthInByte
* 2));
1168 Script
= S3BootScriptGetEntryAddAddress (Length
);
1169 if (Script
== NULL
) {
1170 return RETURN_OUT_OF_RESOURCES
;
1173 // Build script data
1175 ScriptPciReadWrite
.OpCode
= EFI_BOOT_SCRIPT_PCI_CONFIG_READ_WRITE_OPCODE
;
1176 ScriptPciReadWrite
.Length
= Length
;
1177 ScriptPciReadWrite
.Width
= Width
;
1178 ScriptPciReadWrite
.Address
= Address
;
1180 CopyMem ((VOID
*)Script
, (VOID
*)&ScriptPciReadWrite
, sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG_READ_WRITE
));
1181 CopyMem ((VOID
*)(Script
+ sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG_READ_WRITE
)), Data
, WidthInByte
);
1183 (VOID
*)(Script
+ sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG_READ_WRITE
) + WidthInByte
),
1188 SyncBootScript (Script
);
1190 return RETURN_SUCCESS
;
1193 Adds a record for a PCI configuration 2 space write operation into a specified boot script table.
1195 @param Width The width of the I/O operations.Enumerated in S3_BOOT_SCRIPT_LIB_WIDTH.
1196 @param Segment The PCI segment number for Address.
1197 @param Address The address within the PCI configuration space.
1198 @param Count The number of PCI operations to perform.
1199 @param Buffer The source buffer from which to write the data.
1201 @retval RETURN_OUT_OF_RESOURCES Not enough memory for the table do operation.
1202 @retval RETURN_SUCCESS Opcode is added.
1203 @note A known Limitations in the implementation which is non-zero Segment and 64bits operations are not supported.
1208 S3BootScriptSavePciCfg2Write (
1209 IN S3_BOOT_SCRIPT_LIB_WIDTH Width
,
1219 EFI_BOOT_SCRIPT_PCI_CONFIG2_WRITE ScriptPciWrite2
;
1222 Width
== S3BootScriptWidthUint64
||
1223 Width
== S3BootScriptWidthFifoUint64
||
1224 Width
== S3BootScriptWidthFillUint64
) {
1225 return EFI_INVALID_PARAMETER
;
1228 WidthInByte
= (UINT8
) (0x01 << (Width
& 0x03));
1229 Length
= (UINT8
)(sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG2_WRITE
) + (WidthInByte
* Count
));
1231 Script
= S3BootScriptGetEntryAddAddress (Length
);
1232 if (Script
== NULL
) {
1233 return RETURN_OUT_OF_RESOURCES
;
1236 // Build script data
1238 ScriptPciWrite2
.OpCode
= EFI_BOOT_SCRIPT_PCI_CONFIG2_WRITE_OPCODE
;
1239 ScriptPciWrite2
.Length
= Length
;
1240 ScriptPciWrite2
.Width
= Width
;
1241 ScriptPciWrite2
.Address
= Address
;
1242 ScriptPciWrite2
.Segment
= Segment
;
1243 ScriptPciWrite2
.Count
= (UINT32
)Count
;
1245 CopyMem ((VOID
*)Script
, (VOID
*)&ScriptPciWrite2
, sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG2_WRITE
));
1246 CopyMem ((VOID
*)(Script
+ sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG2_WRITE
)), Buffer
, WidthInByte
* Count
);
1248 SyncBootScript (Script
);
1250 return RETURN_SUCCESS
;
1253 Adds a record for a PCI configuration 2 space modify operation into a specified boot script table.
1255 @param Width The width of the I/O operations.Enumerated in S3_BOOT_SCRIPT_LIB_WIDTH.
1256 @param Segment The PCI segment number for Address.
1257 @param Address The address within the PCI configuration space.
1258 @param Data A pointer to the data to be OR-ed. The size depends on Width.
1259 @param DataMask A pointer to the data mask to be AND-ed.
1261 @retval RETURN_OUT_OF_RESOURCES Not enough memory for the table do operation.
1262 @retval RETURN_SUCCESS Opcode is added.
1263 @note A known Limitations in the implementation which is non-zero Segment and 64bits operations are not supported.
1268 S3BootScriptSavePciCfg2ReadWrite (
1269 IN S3_BOOT_SCRIPT_LIB_WIDTH Width
,
1279 EFI_BOOT_SCRIPT_PCI_CONFIG2_READ_WRITE ScriptPciReadWrite2
;
1282 Width
== S3BootScriptWidthUint64
||
1283 Width
== S3BootScriptWidthFifoUint64
||
1284 Width
== S3BootScriptWidthFillUint64
) {
1285 return EFI_INVALID_PARAMETER
;
1288 WidthInByte
= (UINT8
) (0x01 << (Width
& 0x03));
1289 Length
= (UINT8
)(sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG2_READ_WRITE
) + (WidthInByte
* 2));
1291 Script
= S3BootScriptGetEntryAddAddress (Length
);
1292 if (Script
== NULL
) {
1293 return RETURN_OUT_OF_RESOURCES
;
1296 // Build script data
1298 ScriptPciReadWrite2
.OpCode
= EFI_BOOT_SCRIPT_PCI_CONFIG2_READ_WRITE_OPCODE
;
1299 ScriptPciReadWrite2
.Length
= Length
;
1300 ScriptPciReadWrite2
.Width
= Width
;
1301 ScriptPciReadWrite2
.Segment
= Segment
;
1302 ScriptPciReadWrite2
.Address
= Address
;
1304 CopyMem ((VOID
*)Script
, (VOID
*)&ScriptPciReadWrite2
, sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG2_READ_WRITE
));
1305 CopyMem ((VOID
*)(Script
+ sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG2_READ_WRITE
)), Data
, WidthInByte
);
1307 (VOID
*)(Script
+ sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG2_READ_WRITE
) + WidthInByte
),
1312 SyncBootScript (Script
);
1314 return RETURN_SUCCESS
;
1318 Checks the parameter of S3BootScriptSaveSmbusExecute().
1320 This function checks the input parameters of SmbusExecute(). If the input parameters are valid
1321 for certain SMBus bus protocol, it will return EFI_SUCCESS; otherwise, it will return certain
1322 error code based on the input SMBus bus protocol.
1324 @param SmBusAddress Address that encodes the SMBUS Slave Address, SMBUS Command, SMBUS Data Length,
1326 @param Operation Signifies which particular SMBus hardware protocol instance that
1327 it will use to execute the SMBus transactions. This SMBus
1328 hardware protocol is defined by the SMBus Specification and is
1330 @param Length Signifies the number of bytes that this operation will do. The
1331 maximum number of bytes can be revision specific and operation
1332 specific. This field will contain the actual number of bytes that
1333 are executed for this operation. Not all operations require this
1335 @param Buffer Contains the value of data to execute to the SMBus slave device.
1336 Not all operations require this argument. The length of this
1337 buffer is identified by Length.
1339 @retval EFI_SUCCESS All the parameters are valid for the corresponding SMBus bus
1341 @retval EFI_INVALID_PARAMETER Operation is not defined in EFI_SMBUS_OPERATION.
1342 @retval EFI_INVALID_PARAMETER Length/Buffer is NULL for operations except for EfiSmbusQuickRead
1343 and EfiSmbusQuickWrite. Length is outside the range of valid
1345 @retval EFI_UNSUPPORTED The SMBus operation or PEC is not supported.
1346 @retval EFI_BUFFER_TOO_SMALL Buffer is not sufficient for this operation.
1351 IN UINTN SmBusAddress
,
1352 IN EFI_SMBUS_OPERATION Operation
,
1353 IN OUT UINTN
*Length
,
1359 EFI_SMBUS_DEVICE_COMMAND Command
;
1362 Command
= SMBUS_LIB_COMMAND (SmBusAddress
);
1363 PecCheck
= SMBUS_LIB_PEC (SmBusAddress
);
1365 // Set default value to be 2:
1366 // for SmbusReadWord, SmbusWriteWord and SmbusProcessCall.
1369 Status
= EFI_SUCCESS
;
1370 switch (Operation
) {
1371 case EfiSmbusQuickRead
:
1372 case EfiSmbusQuickWrite
:
1373 if (PecCheck
|| Command
!= 0) {
1374 return EFI_UNSUPPORTED
;
1377 case EfiSmbusReceiveByte
:
1378 case EfiSmbusSendByte
:
1380 return EFI_UNSUPPORTED
;
1383 // Cascade to check length parameter.
1385 case EfiSmbusReadByte
:
1386 case EfiSmbusWriteByte
:
1389 // Cascade to check length parameter.
1391 case EfiSmbusReadWord
:
1392 case EfiSmbusWriteWord
:
1393 case EfiSmbusProcessCall
:
1394 if (Buffer
== NULL
|| Length
== NULL
) {
1395 return EFI_INVALID_PARAMETER
;
1396 } else if (*Length
< RequiredLen
) {
1397 Status
= EFI_BUFFER_TOO_SMALL
;
1399 *Length
= RequiredLen
;
1401 case EfiSmbusReadBlock
:
1402 case EfiSmbusWriteBlock
:
1403 case EfiSmbusBWBRProcessCall
:
1404 if ((Buffer
== NULL
) ||
1406 (*Length
< MIN_SMBUS_BLOCK_LEN
) ||
1407 (*Length
> MAX_SMBUS_BLOCK_LEN
)) {
1408 return EFI_INVALID_PARAMETER
;
1412 return EFI_INVALID_PARAMETER
;
1418 Adds a record for an SMBus command execution into a specified boot script table.
1420 @param SmBusAddress Address that encodes the SMBUS Slave Address, SMBUS Command, SMBUS Data Length, and PEC.
1421 @param Operation Indicates which particular SMBus protocol it will use to execute the SMBus
1423 @param Length A pointer to signify the number of bytes that this operation will do.
1424 @param Buffer Contains the value of data to execute to the SMBUS slave device.
1426 @retval RETURN_OUT_OF_RESOURCES Not enough memory for the table do operation.
1427 @retval RETURN_SUCCESS Opcode is added.
1431 S3BootScriptSaveSmbusExecute (
1432 IN UINTN SmBusAddress
,
1433 IN EFI_SMBUS_OPERATION Operation
,
1442 EFI_BOOT_SCRIPT_SMBUS_EXECUTE ScriptSmbusExecute
;
1444 if (Length
== NULL
) {
1447 BufferLength
= *Length
;
1450 Status
= CheckParameters (SmBusAddress
, Operation
, &BufferLength
, Buffer
);
1451 if (EFI_ERROR (Status
)) {
1455 DataSize
= (UINT8
)(sizeof (EFI_BOOT_SCRIPT_SMBUS_EXECUTE
) + BufferLength
);
1457 Script
= S3BootScriptGetEntryAddAddress (DataSize
);
1458 if (Script
== NULL
) {
1459 return RETURN_OUT_OF_RESOURCES
;
1462 // Build script data
1464 ScriptSmbusExecute
.OpCode
= EFI_BOOT_SCRIPT_SMBUS_EXECUTE_OPCODE
;
1465 ScriptSmbusExecute
.Length
= DataSize
;
1466 ScriptSmbusExecute
.SmBusAddress
= (UINT64
) SmBusAddress
;
1467 ScriptSmbusExecute
.Operation
= Operation
;
1468 ScriptSmbusExecute
.DataSize
= (UINT32
) BufferLength
;
1470 CopyMem ((VOID
*)Script
, (VOID
*)&ScriptSmbusExecute
, sizeof (EFI_BOOT_SCRIPT_SMBUS_EXECUTE
));
1472 (VOID
*)(Script
+ sizeof (EFI_BOOT_SCRIPT_SMBUS_EXECUTE
)),
1477 SyncBootScript (Script
);
1479 return RETURN_SUCCESS
;
1482 Adds a record for an execution stall on the processor into a specified boot script table.
1484 @param Duration Duration in microseconds of the stall
1486 @retval RETURN_OUT_OF_RESOURCES Not enough memory for the table do operation.
1487 @retval RETURN_SUCCESS Opcode is added.
1491 S3BootScriptSaveStall (
1497 EFI_BOOT_SCRIPT_STALL ScriptStall
;
1499 Length
= (UINT8
)(sizeof (EFI_BOOT_SCRIPT_STALL
));
1501 Script
= S3BootScriptGetEntryAddAddress (Length
);
1502 if (Script
== NULL
) {
1503 return RETURN_OUT_OF_RESOURCES
;
1506 // Build script data
1508 ScriptStall
.OpCode
= EFI_BOOT_SCRIPT_STALL_OPCODE
;
1509 ScriptStall
.Length
= Length
;
1510 ScriptStall
.Duration
= Duration
;
1512 CopyMem ((VOID
*)Script
, (VOID
*)&ScriptStall
, sizeof (EFI_BOOT_SCRIPT_STALL
));
1514 SyncBootScript (Script
);
1516 return RETURN_SUCCESS
;
1519 Adds a record for dispatching specified arbitrary code into a specified boot script table.
1521 @param EntryPoint Entry point of the code to be dispatched.
1522 @param Context Argument to be passed into the EntryPoint of the code to be dispatched.
1524 @retval RETURN_OUT_OF_RESOURCES Not enough memory for the table do operation.
1525 @retval RETURN_SUCCESS Opcode is added.
1529 S3BootScriptSaveDispatch2 (
1530 IN VOID
*EntryPoint
,
1536 EFI_BOOT_SCRIPT_DISPATCH_2 ScriptDispatch2
;
1537 Length
= (UINT8
)(sizeof (EFI_BOOT_SCRIPT_DISPATCH_2
));
1539 Script
= S3BootScriptGetEntryAddAddress (Length
);
1540 if (Script
== NULL
) {
1541 return RETURN_OUT_OF_RESOURCES
;
1544 // Build script data
1546 ScriptDispatch2
.OpCode
= EFI_BOOT_SCRIPT_DISPATCH_2_OPCODE
;
1547 ScriptDispatch2
.Length
= Length
;
1548 ScriptDispatch2
.EntryPoint
= (EFI_PHYSICAL_ADDRESS
)(UINTN
)EntryPoint
;
1549 ScriptDispatch2
.Context
= (EFI_PHYSICAL_ADDRESS
)(UINTN
)Context
;
1551 CopyMem ((VOID
*)Script
, (VOID
*)&ScriptDispatch2
, sizeof (EFI_BOOT_SCRIPT_DISPATCH_2
));
1553 SyncBootScript (Script
);
1555 return RETURN_SUCCESS
;
1559 Adds a record for memory reads of the memory location and continues when the exit criteria is
1560 satisfied or after a defined duration.
1562 Please aware, below interface is different with PI specification, Vol 5:
1563 EFI_S3_SAVE_STATE_PROTOCOL.Write() for EFI_BOOT_SCRIPT_MEM_POLL_OPCODE.
1564 "Duration" below is microseconds, while "Delay" in PI specification means
1565 the number of 100ns units to poll.
1567 @param Width The width of the memory operations.
1568 @param Address The base address of the memory operations.
1569 @param BitMask A pointer to the bit mask to be AND-ed with the data read from the register.
1570 @param BitValue A pointer to the data value after to be Masked.
1571 @param Duration Duration in microseconds of the stall.
1572 @param LoopTimes The times of the register polling.
1574 @retval RETURN_OUT_OF_RESOURCES Not enough memory for the table do operation.
1575 @retval RETURN_SUCCESS Opcode is added.
1580 S3BootScriptSaveMemPoll (
1581 IN S3_BOOT_SCRIPT_LIB_WIDTH Width
,
1592 EFI_BOOT_SCRIPT_MEM_POLL ScriptMemPoll
;
1594 WidthInByte
= (UINT8
) (0x01 << (Width
& 0x03));
1596 Length
= (UINT8
)(sizeof (EFI_BOOT_SCRIPT_MEM_POLL
) + (WidthInByte
* 2));
1598 Script
= S3BootScriptGetEntryAddAddress (Length
);
1599 if (Script
== NULL
) {
1600 return RETURN_OUT_OF_RESOURCES
;
1603 // Build script data
1605 ScriptMemPoll
.OpCode
= EFI_BOOT_SCRIPT_MEM_POLL_OPCODE
;
1606 ScriptMemPoll
.Length
= Length
;
1607 ScriptMemPoll
.Width
= Width
;
1608 ScriptMemPoll
.Address
= Address
;
1609 ScriptMemPoll
.Duration
= Duration
;
1610 ScriptMemPoll
.LoopTimes
= LoopTimes
;
1612 CopyMem ((UINT8
*) (Script
+ sizeof (EFI_BOOT_SCRIPT_MEM_POLL
)), BitValue
, WidthInByte
);
1613 CopyMem ((UINT8
*) (Script
+ sizeof (EFI_BOOT_SCRIPT_MEM_POLL
) + WidthInByte
), BitMask
, WidthInByte
);
1614 CopyMem ((VOID
*)Script
, (VOID
*)&ScriptMemPoll
, sizeof (EFI_BOOT_SCRIPT_MEM_POLL
));
1616 SyncBootScript (Script
);
1618 return RETURN_SUCCESS
;
1621 Store arbitrary information in the boot script table. This opcode is a no-op on dispatch and is only
1622 used for debugging script issues.
1624 @param InformationLength Length of the data in bytes
1625 @param Information Information to be logged in the boot scrpit
1627 @retval RETURN_OUT_OF_RESOURCES Not enough memory for the table do operation.
1628 @retval RETURN_SUCCESS Opcode is added.
1633 S3BootScriptSaveInformation (
1634 IN UINT32 InformationLength
,
1635 IN VOID
*Information
1640 EFI_BOOT_SCRIPT_INFORMATION ScriptInformation
;
1642 Length
= (UINT8
)(sizeof (EFI_BOOT_SCRIPT_INFORMATION
) + InformationLength
);
1644 Script
= S3BootScriptGetEntryAddAddress (Length
);
1645 if (Script
== NULL
) {
1646 return RETURN_OUT_OF_RESOURCES
;
1649 // Build script data
1651 ScriptInformation
.OpCode
= EFI_BOOT_SCRIPT_INFORMATION_OPCODE
;
1652 ScriptInformation
.Length
= Length
;
1655 ScriptInformation
.InformationLength
= InformationLength
;
1657 CopyMem ((VOID
*)Script
, (VOID
*)&ScriptInformation
, sizeof (EFI_BOOT_SCRIPT_INFORMATION
));
1658 CopyMem ((VOID
*)(Script
+ sizeof (EFI_BOOT_SCRIPT_INFORMATION
)), (VOID
*) Information
, (UINTN
) InformationLength
);
1660 SyncBootScript (Script
);
1662 return RETURN_SUCCESS
;
1666 Store a string in the boot script table. This opcode is a no-op on dispatch and is only
1667 used for debugging script issues.
1669 @param String The string to save to boot script table
1671 @retval RETURN_OUT_OF_RESOURCES Not enough memory for the table do operation.
1672 @retval RETURN_SUCCESS Opcode is added.
1677 S3BootScriptSaveInformationAsciiString (
1678 IN CONST CHAR8
*String
1681 return S3BootScriptSaveInformation (
1682 (UINT32
) AsciiStrLen (String
) + 1,
1687 Adds a record for dispatching specified arbitrary code into a specified boot script table.
1689 @param EntryPoint Entry point of the code to be dispatched.
1691 @retval RETURN_OUT_OF_RESOURCES Not enough memory for the table do operation.
1692 @retval RETURN_SUCCESS Opcode is added.
1696 S3BootScriptSaveDispatch (
1702 EFI_BOOT_SCRIPT_DISPATCH ScriptDispatch
;
1704 Length
= (UINT8
)(sizeof (EFI_BOOT_SCRIPT_DISPATCH
));
1706 Script
= S3BootScriptGetEntryAddAddress (Length
);
1707 if (Script
== NULL
) {
1708 return RETURN_OUT_OF_RESOURCES
;
1711 // Build script data
1713 ScriptDispatch
.OpCode
= EFI_BOOT_SCRIPT_DISPATCH_OPCODE
;
1714 ScriptDispatch
.Length
= Length
;
1715 ScriptDispatch
.EntryPoint
= (EFI_PHYSICAL_ADDRESS
)(UINTN
)EntryPoint
;
1717 CopyMem ((VOID
*)Script
, (VOID
*)&ScriptDispatch
, sizeof (EFI_BOOT_SCRIPT_DISPATCH
));
1719 SyncBootScript (Script
);
1721 return RETURN_SUCCESS
;
1725 Adds a record for I/O reads the I/O location and continues when the exit criteria is satisfied or after a
1728 @param Width The width of the I/O operations.
1729 @param Address The base address of the I/O operations.
1730 @param Data The comparison value used for the polling exit criteria.
1731 @param DataMask Mask used for the polling criteria. The bits in the bytes below Width which are zero
1732 in Data are ignored when polling the memory address.
1733 @param Delay The number of 100ns units to poll. Note that timer available may be of poorer
1734 granularity so the delay may be longer.
1736 @retval RETURN_OUT_OF_RESOURCES Not enough memory for the table do operation.
1737 @retval RETURN_SUCCESS Opcode is added.
1742 S3BootScriptSaveIoPoll (
1743 IN S3_BOOT_SCRIPT_LIB_WIDTH Width
,
1753 EFI_BOOT_SCRIPT_IO_POLL ScriptIoPoll
;
1756 WidthInByte
= (UINT8
) (0x01 << (Width
& 0x03));
1757 Length
= (UINT8
)(sizeof (EFI_BOOT_SCRIPT_IO_POLL
) + (WidthInByte
* 2));
1759 Script
= S3BootScriptGetEntryAddAddress (Length
);
1760 if (Script
== NULL
) {
1761 return RETURN_OUT_OF_RESOURCES
;
1764 // Build script data
1766 ScriptIoPoll
.OpCode
= EFI_BOOT_SCRIPT_IO_POLL_OPCODE
;
1767 ScriptIoPoll
.Length
= (UINT8
) (sizeof (EFI_BOOT_SCRIPT_IO_POLL
) + (WidthInByte
* 2));
1768 ScriptIoPoll
.Width
= Width
;
1769 ScriptIoPoll
.Address
= Address
;
1770 ScriptIoPoll
.Delay
= Delay
;
1772 CopyMem ((VOID
*)Script
, (VOID
*)&ScriptIoPoll
, sizeof (EFI_BOOT_SCRIPT_IO_POLL
));
1773 CopyMem ((UINT8
*) (Script
+ sizeof (EFI_BOOT_SCRIPT_IO_POLL
)), Data
, WidthInByte
);
1774 CopyMem ((UINT8
*) (Script
+ sizeof (EFI_BOOT_SCRIPT_IO_POLL
) + WidthInByte
), DataMask
, WidthInByte
);
1776 SyncBootScript (Script
);
1778 return RETURN_SUCCESS
;
1782 Adds a record for PCI configuration space reads and continues when the exit criteria is satisfied or
1783 after a defined duration.
1785 @param Width The width of the I/O operations.
1786 @param Address The address within the PCI configuration space.
1787 @param Data The comparison value used for the polling exit criteria.
1788 @param DataMask Mask used for the polling criteria. The bits in the bytes below Width which are zero
1789 in Data are ignored when polling the memory address
1790 @param Delay The number of 100ns units to poll. Note that timer available may be of poorer
1791 granularity so the delay may be longer.
1793 @retval RETURN_OUT_OF_RESOURCES Not enough memory for the table do operation.
1794 @retval RETURN_SUCCESS Opcode is added.
1795 @note A known Limitations in the implementation which is 64bits operations are not supported.
1800 S3BootScriptSavePciPoll (
1801 IN S3_BOOT_SCRIPT_LIB_WIDTH Width
,
1811 EFI_BOOT_SCRIPT_PCI_CONFIG_POLL ScriptPciPoll
;
1813 if (Width
== S3BootScriptWidthUint64
||
1814 Width
== S3BootScriptWidthFifoUint64
||
1815 Width
== S3BootScriptWidthFillUint64
) {
1816 return EFI_INVALID_PARAMETER
;
1819 WidthInByte
= (UINT8
) (0x01 << (Width
& 0x03));
1820 Length
= (UINT8
)(sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG_POLL
) + (WidthInByte
* 2));
1822 Script
= S3BootScriptGetEntryAddAddress (Length
);
1823 if (Script
== NULL
) {
1824 return RETURN_OUT_OF_RESOURCES
;
1827 // Build script data
1829 ScriptPciPoll
.OpCode
= EFI_BOOT_SCRIPT_PCI_CONFIG_POLL_OPCODE
;
1830 ScriptPciPoll
.Length
= (UINT8
) (sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG_POLL
) + (WidthInByte
* 2));
1831 ScriptPciPoll
.Width
= Width
;
1832 ScriptPciPoll
.Address
= Address
;
1833 ScriptPciPoll
.Delay
= Delay
;
1835 CopyMem ((VOID
*)Script
, (VOID
*)&ScriptPciPoll
, sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG_POLL
));
1836 CopyMem ((UINT8
*) (Script
+ sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG_POLL
)), Data
, WidthInByte
);
1837 CopyMem ((UINT8
*) (Script
+ sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG_POLL
) + WidthInByte
), DataMask
, WidthInByte
);
1839 SyncBootScript (Script
);
1841 return RETURN_SUCCESS
;
1844 Adds a record for PCI configuration space reads and continues when the exit criteria is satisfied or
1845 after a defined duration.
1847 @param Width The width of the I/O operations.
1848 @param Segment The PCI segment number for Address.
1849 @param Address The address within the PCI configuration space.
1850 @param Data The comparison value used for the polling exit criteria.
1851 @param DataMask Mask used for the polling criteria. The bits in the bytes below Width which are zero
1852 in Data are ignored when polling the memory address
1853 @param Delay The number of 100ns units to poll. Note that timer available may be of poorer
1854 granularity so the delay may be longer.
1856 @retval RETURN_OUT_OF_RESOURCES Not enough memory for the table do operation.
1857 @retval RETURN_SUCCESS Opcode is added.
1858 @note A known Limitations in the implementation which is non-zero Segment and 64bits operations are not supported.
1863 S3BootScriptSavePci2Poll (
1864 IN S3_BOOT_SCRIPT_LIB_WIDTH Width
,
1875 EFI_BOOT_SCRIPT_PCI_CONFIG2_POLL ScriptPci2Poll
;
1878 Width
== S3BootScriptWidthUint64
||
1879 Width
== S3BootScriptWidthFifoUint64
||
1880 Width
== S3BootScriptWidthFillUint64
) {
1881 return EFI_INVALID_PARAMETER
;
1884 WidthInByte
= (UINT8
) (0x01 << (Width
& 0x03));
1885 Length
= (UINT8
)(sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG2_POLL
) + (WidthInByte
* 2));
1887 Script
= S3BootScriptGetEntryAddAddress (Length
);
1888 if (Script
== NULL
) {
1889 return RETURN_OUT_OF_RESOURCES
;
1892 // Build script data
1894 ScriptPci2Poll
.OpCode
= EFI_BOOT_SCRIPT_PCI_CONFIG2_POLL_OPCODE
;
1895 ScriptPci2Poll
.Length
= (UINT8
) (sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG2_POLL
) + (WidthInByte
* 2));
1896 ScriptPci2Poll
.Width
= Width
;
1897 ScriptPci2Poll
.Segment
= Segment
;
1898 ScriptPci2Poll
.Address
= Address
;
1899 ScriptPci2Poll
.Delay
= Delay
;
1901 CopyMem ((VOID
*)Script
, (VOID
*)&ScriptPci2Poll
, sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG2_POLL
));
1902 CopyMem ((UINT8
*) (Script
+ sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG2_POLL
)), Data
, WidthInByte
);
1903 CopyMem ((UINT8
*) (Script
+ sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG2_POLL
) + WidthInByte
), DataMask
, WidthInByte
);
1905 SyncBootScript (Script
);
1907 return RETURN_SUCCESS
;
1910 Do the calculation of start address from which a new s3 boot script entry will write into.
1912 @param EntryLength The new entry length.
1913 @param Position specifies the position in the boot script table where the opcode will be
1914 inserted, either before or after, depending on BeforeOrAfter.
1915 @param BeforeOrAfter The flag to indicate to insert the nod before or after the position.
1916 This parameter is effective when InsertFlag is TRUE
1917 @param Script return out the position from which the a new s3 boot script entry will write into
1920 S3BootScriptCalculateInsertAddress (
1921 IN UINT8 EntryLength
,
1922 IN VOID
*Position OPTIONAL
,
1923 IN BOOLEAN BeforeOrAfter OPTIONAL
,
1929 UINTN PositionOffset
;
1930 EFI_BOOT_SCRIPT_COMMON_HEADER ScriptHeader
;
1932 // The entry inserting to table is already added to the end of the table
1934 TableLength
= mS3BootScriptTablePtr
->TableLength
- EntryLength
;
1935 S3TableBase
= mS3BootScriptTablePtr
->TableBase
;
1937 // calculate the Position offset
1939 if (Position
!= NULL
) {
1940 PositionOffset
= (UINTN
) ((UINT8
*)Position
- S3TableBase
);
1943 // If the BeforeOrAfter is FALSE, that means to insert the node right after the node.
1945 if (!BeforeOrAfter
) {
1946 CopyMem ((VOID
*)&ScriptHeader
, Position
, sizeof(EFI_BOOT_SCRIPT_COMMON_HEADER
));
1947 PositionOffset
+= (ScriptHeader
.Length
);
1950 // Insert the node before the adjusted Position
1952 CopyMem (S3TableBase
+PositionOffset
+EntryLength
, S3TableBase
+PositionOffset
, TableLength
- PositionOffset
);
1954 // calculate the the start address for the new entry.
1956 *Script
= S3TableBase
+ PositionOffset
;
1959 if (!BeforeOrAfter
) {
1961 // Insert the node to the end of the table
1963 *Script
= S3TableBase
+ TableLength
;
1966 // Insert the node to the beginning of the table
1968 PositionOffset
= (UINTN
) sizeof(EFI_BOOT_SCRIPT_TABLE_HEADER
);
1969 CopyMem (S3TableBase
+PositionOffset
+EntryLength
, S3TableBase
+PositionOffset
, TableLength
- PositionOffset
);
1970 *Script
= S3TableBase
+ PositionOffset
;
1975 Move the last boot script entry to the position
1977 @param BeforeOrAfter Specifies whether the opcode is stored before (TRUE) or after (FALSE) the position
1978 in the boot script table specified by Position. If Position is NULL or points to
1979 NULL then the new opcode is inserted at the beginning of the table (if TRUE) or end
1980 of the table (if FALSE).
1981 @param Position On entry, specifies the position in the boot script table where the opcode will be
1982 inserted, either before or after, depending on BeforeOrAfter. On exit, specifies
1983 the position of the inserted opcode in the boot script table.
1985 @retval RETURN_OUT_OF_RESOURCES The table is not available.
1986 @retval RETURN_INVALID_PARAMETER The Position is not a valid position in the boot script table.
1987 @retval RETURN_SUCCESS Opcode is inserted.
1991 S3BootScriptMoveLastOpcode (
1992 IN BOOLEAN BeforeOrAfter
,
1993 IN OUT VOID
**Position OPTIONAL
2000 EFI_BOOT_SCRIPT_COMMON_HEADER ScriptHeader
;
2001 BOOLEAN ValidatePosition
;
2003 UINT8 TempBootScriptEntry
[BOOT_SCRIPT_NODE_MAX_LENGTH
];
2005 ValidatePosition
= FALSE
;
2006 TempPosition
= (Position
== NULL
) ? NULL
:(*Position
);
2009 // Check that the script is initialized and synced without adding an entry to the script.
2011 Script
= S3BootScriptGetEntryAddAddress (0);
2012 if (Script
== NULL
) {
2013 return RETURN_OUT_OF_RESOURCES
;
2015 Script
= mS3BootScriptTablePtr
->TableBase
;
2017 StartAddress
= (UINTN
) Script
;
2018 TableLength
= mS3BootScriptTablePtr
->TableLength
;
2019 Script
= Script
+ sizeof(EFI_BOOT_SCRIPT_TABLE_HEADER
);
2020 LastOpcode
= Script
;
2022 // Find the last boot Script Entry which is not the terminate node
2024 while ((UINTN
) Script
< (UINTN
) (StartAddress
+ TableLength
)) {
2025 CopyMem ((VOID
*)&ScriptHeader
, Script
, sizeof(EFI_BOOT_SCRIPT_COMMON_HEADER
));
2026 if (TempPosition
!= NULL
&& TempPosition
== Script
) {
2028 // If the position is specified, the position must be pointed to a boot script entry start address.
2030 ValidatePosition
= TRUE
;
2032 if (ScriptHeader
.OpCode
!= S3_BOOT_SCRIPT_LIB_TERMINATE_OPCODE
) {
2033 LastOpcode
= Script
;
2035 Script
= Script
+ ScriptHeader
.Length
;
2038 // If the position is specified, but not the start of a boot script entry, it is a invalid input
2040 if (TempPosition
!= NULL
&& !ValidatePosition
) {
2041 return RETURN_INVALID_PARAMETER
;
2044 CopyMem ((VOID
*)&ScriptHeader
, LastOpcode
, sizeof(EFI_BOOT_SCRIPT_COMMON_HEADER
));
2046 CopyMem((VOID
*)TempBootScriptEntry
, LastOpcode
, ScriptHeader
.Length
);
2048 // Find the right position to write the node in
2050 S3BootScriptCalculateInsertAddress (
2051 ScriptHeader
.Length
,
2057 // Copy the node to Boot script table
2059 CopyMem((VOID
*)Script
, (VOID
*)TempBootScriptEntry
, ScriptHeader
.Length
);
2061 SyncBootScript (Script
);
2064 // return out the Position
2066 if (Position
!= NULL
) {
2069 return RETURN_SUCCESS
;
2072 Create a Label node in the boot script table.
2074 @param BeforeOrAfter Specifies whether the opcode is stored before (TRUE) or after (FALSE) the position
2075 in the boot script table specified by Position. If Position is NULL or points to
2076 NULL then the new opcode is inserted at the beginning of the table (if TRUE) or end
2077 of the table (if FALSE).
2078 @param Position On entry, specifies the position in the boot script table where the opcode will be
2079 inserted, either before or after, depending on BeforeOrAfter. On exit, specifies
2080 the position of the inserted opcode in the boot script table.
2081 @param InformationLength Length of the label in bytes
2082 @param Information Label to be logged in the boot scrpit
2084 @retval RETURN_INVALID_PARAMETER The Position is not a valid position in the boot script table.
2085 @retval RETURN_OUT_OF_RESOURCES Not enough memory for the table do operation.
2086 @retval RETURN_SUCCESS Opcode is added.
2091 S3BootScriptLabelInternal (
2092 IN BOOLEAN BeforeOrAfter
,
2093 IN OUT VOID
**Position OPTIONAL
,
2094 IN UINT32 InformationLength
,
2095 IN CONST CHAR8
*Information
2100 EFI_BOOT_SCRIPT_INFORMATION ScriptInformation
;
2102 Length
= (UINT8
)(sizeof (EFI_BOOT_SCRIPT_INFORMATION
) + InformationLength
);
2104 Script
= S3BootScriptGetEntryAddAddress (Length
);
2105 if (Script
== NULL
) {
2106 return RETURN_OUT_OF_RESOURCES
;
2109 // Build script data
2111 ScriptInformation
.OpCode
= S3_BOOT_SCRIPT_LIB_LABEL_OPCODE
;
2112 ScriptInformation
.Length
= Length
;
2115 ScriptInformation
.InformationLength
= InformationLength
;
2117 CopyMem ((VOID
*)Script
, (VOID
*)&ScriptInformation
, sizeof (EFI_BOOT_SCRIPT_INFORMATION
));
2118 CopyMem ((VOID
*)(Script
+ sizeof (EFI_BOOT_SCRIPT_INFORMATION
)), (VOID
*) Information
, (UINTN
) InformationLength
);
2120 SyncBootScript (Script
);
2122 return S3BootScriptMoveLastOpcode (BeforeOrAfter
, Position
);
2126 Find a label within the boot script table and, if not present, optionally create it.
2128 @param BeforeOrAfter Specifies whether the opcode is stored before (TRUE)
2129 or after (FALSE) the position in the boot script table
2130 specified by Position.
2131 @param CreateIfNotFound Specifies whether the label will be created if the label
2132 does not exists (TRUE) or not (FALSE).
2133 @param Position On entry, specifies the position in the boot script table
2134 where the opcode will be inserted, either before or after,
2135 depending on BeforeOrAfter. On exit, specifies the position
2136 of the inserted opcode in the boot script table.
2137 @param Label Points to the label which will be inserted in the boot script table.
2139 @retval EFI_SUCCESS The operation succeeded. A record was added into the
2140 specified script table.
2141 @retval EFI_INVALID_PARAMETER The parameter is illegal or the given boot script is not supported.
2142 If the opcode is unknow or not supported because of the PCD
2144 @retval EFI_OUT_OF_RESOURCES There is insufficient memory to store the boot script.
2150 IN BOOLEAN BeforeOrAfter
,
2151 IN BOOLEAN CreateIfNotFound
,
2152 IN OUT VOID
**Position OPTIONAL
,
2153 IN CONST CHAR8
*Label
2159 EFI_BOOT_SCRIPT_COMMON_HEADER ScriptHeader
;
2160 EFI_BOOT_SCRIPT_TABLE_HEADER TableHeader
;
2165 if (Label
== NULL
) {
2166 return EFI_INVALID_PARAMETER
;
2169 // Check empty Label
2171 if (Label
[0] == '\0') {
2172 return EFI_INVALID_PARAMETER
;
2176 // Check that the script is initialized and synced without adding an entry to the script.
2177 // The code must search for the label first before it knows if a new entry needs
2180 Script
= S3BootScriptGetEntryAddAddress (0);
2181 if (Script
== NULL
) {
2182 return RETURN_OUT_OF_RESOURCES
;
2186 // Check the header and search for existing label.
2188 Script
= mS3BootScriptTablePtr
->TableBase
;
2189 CopyMem ((VOID
*)&TableHeader
, Script
, sizeof(EFI_BOOT_SCRIPT_TABLE_HEADER
));
2190 if (TableHeader
.OpCode
!= S3_BOOT_SCRIPT_LIB_TABLE_OPCODE
) {
2191 return EFI_INVALID_PARAMETER
;
2193 StartAddress
= (UINTN
) Script
;
2194 TableLength
= mS3BootScriptTablePtr
->TableLength
;
2195 Script
= Script
+ TableHeader
.Length
;
2196 while ((UINTN
) Script
< (UINTN
) (StartAddress
+ TableLength
)) {
2198 CopyMem ((VOID
*)&ScriptHeader
, Script
, sizeof(EFI_BOOT_SCRIPT_COMMON_HEADER
));
2199 if (ScriptHeader
.OpCode
== S3_BOOT_SCRIPT_LIB_LABEL_OPCODE
) {
2200 if (AsciiStrCmp ((CHAR8
*)(UINTN
)(Script
+sizeof(EFI_BOOT_SCRIPT_INFORMATION
)), Label
) == 0) {
2201 (*Position
) = Script
;
2205 Script
= Script
+ ScriptHeader
.Length
;
2207 if (CreateIfNotFound
) {
2208 LabelLength
= (UINT32
)AsciiStrSize(Label
);
2209 return S3BootScriptLabelInternal (BeforeOrAfter
,Position
, LabelLength
, Label
);
2211 return EFI_NOT_FOUND
;
2216 Compare two positions in the boot script table and return their relative position.
2217 @param Position1 The positions in the boot script table to compare
2218 @param Position2 The positions in the boot script table to compare
2219 @param RelativePosition On return, points to the result of the comparison
2221 @retval EFI_SUCCESS The operation succeeded. A record was added into the
2222 specified script table.
2223 @retval EFI_INVALID_PARAMETER The parameter is illegal or the given boot script is not supported.
2224 If the opcode is unknow or not supported because of the PCD
2226 @retval EFI_OUT_OF_RESOURCES There is insufficient memory to store the boot script.
2231 S3BootScriptCompare (
2232 IN UINT8
*Position1
,
2233 IN UINT8
*Position2
,
2234 OUT UINTN
*RelativePosition
2240 if (RelativePosition
== NULL
) {
2241 return EFI_INVALID_PARAMETER
;
2245 // Check that the script is initialized and synced without adding an entry to the script.
2247 Script
= S3BootScriptGetEntryAddAddress (0);
2248 if (Script
== NULL
) {
2249 return RETURN_OUT_OF_RESOURCES
;
2251 Script
= mS3BootScriptTablePtr
->TableBase
;
2254 // mS3BootScriptTablePtr->TableLength does not include the termination node, so add it up
2256 TableLength
= mS3BootScriptTablePtr
->TableLength
+ sizeof (EFI_BOOT_SCRIPT_TERMINATE
);
2257 if (Position1
< Script
|| Position1
> Script
+TableLength
) {
2258 return EFI_INVALID_PARAMETER
;
2260 if (Position2
< Script
|| Position2
> Script
+TableLength
) {
2261 return EFI_INVALID_PARAMETER
;
2263 *RelativePosition
= (Position1
< Position2
)?-1:((Position1
== Position2
)?0:1);