X-Git-Url: https://git.proxmox.com/?p=mirror_edk2.git;a=blobdiff_plain;f=MdeModulePkg%2FLibrary%2FPiDxeS3BootScriptLib%2FBootScriptSave.c;h=0ff73211acc44a7de6aba29bc45485bca3a1b761;hp=afb5ed1bb345f80d472b393297b62faa5765be65;hb=d6f38e374ece00f1f8176007c9d3e8eff1f2308f;hpb=3aa764ed7477d45ee78c7080c9f7624e62d10346
diff --git a/MdeModulePkg/Library/PiDxeS3BootScriptLib/BootScriptSave.c b/MdeModulePkg/Library/PiDxeS3BootScriptLib/BootScriptSave.c
index afb5ed1bb3..0ff73211ac 100644
--- a/MdeModulePkg/Library/PiDxeS3BootScriptLib/BootScriptSave.c
+++ b/MdeModulePkg/Library/PiDxeS3BootScriptLib/BootScriptSave.c
@@ -1,7 +1,7 @@
/** @file
- Save the S3 data to S3 boot script.
-
- Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.
+ Save the S3 data to S3 boot script.
+
+ Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.
This program and the accompanying materials
are licensed and made available under the terms and conditions
@@ -19,46 +19,124 @@
Data structure usage:
- +------------------------------+<-- PcdS3BootScriptTablePrivateDataPtr
+ +------------------------------+<------- PcdS3BootScriptTablePrivateDataPtr
+ | SCRIPT_TABLE_PRIVATE_DATA | (mS3BootScriptTablePtr, Before SmmReadyToLock)
+ | TableBase |--- PcdS3BootScriptTablePrivateSmmDataPtr
+ | TableLength |--|-- (mS3BootScriptTablePtr = mS3BootScriptTableSmmPtr, After SmmReadyToLock InSmm)
+ | TableMemoryPageNumber |--|-|----
+ | AtRuntime | | | |
+ | InSmm | | | |
+ | BootTimeScriptLength |--|-|---|---
+ | SmmLocked | | | | |
+ | BackFromS3 | | | | |
+ +------------------------------+ | | | |
+ | | | |
+ +------------------------------+<-- | | |
+ | EFI_BOOT_SCRIPT_TABLE_HEADER | | | |
+ | TableLength |----|-- | |
+ +------------------------------+ | | | |
+ | ...... | | | | |
+ +------------------------------+<---- | | |
+ | EFI_BOOT_SCRIPT_TERMINATE | | | |
+ +------------------------------+<------ | |
+ | |
+ | |
+ mBootScriptDataBootTimeGuid LockBox: | |
+ Used to restore data after back from S3| |
+ to handle potential INSERT boot script | |
+ at runtime. | |
+ +------------------------------+ | |
+ | Boot Time Boot Script | | |
+ | Before SmmReadyToLock | | |
+ | | | |
+ | | | |
+ +------------------------------+ | |
+ | Boot Time Boot Script | | |
+ | After SmmReadyToLock InSmm | | |
+ | | | |
+ +------------------------------+<-------|--|
+ | |
+ | |
+ mBootScriptDataGuid LockBox: (IN_PLACE) | |
+ Used to restore data at S3 resume. | |
+ +------------------------------+ | |
+ | Boot Time Boot Script | | |
+ | Before SmmReadyToLock | | |
+ | | | |
+ | | | |
+ +------------------------------+ | |
+ | Boot Time Boot Script | | |
+ | After SmmReadyToLock InSmm | | |
+ | | | |
+ +------------------------------+<-------|---
+ | Runtime Boot Script | |
+ | After SmmReadyToLock InSmm | |
+ +------------------------------+ |
+ | ...... | |
+ +------------------------------+<--------
+
+
+ mBootScriptTableBaseGuid LockBox: (IN_PLACE)
+ +------------------------------+
+ | mS3BootScriptTablePtr-> |
+ | TableBase |
+ +------------------------------+
+
+
+ mBootScriptSmmPrivateDataGuid LockBox: (IN_PLACE)
+ SMM private data with BackFromS3 = TRUE
+ at runtime. S3 will help restore it to
+ tell the Library the system is back from S3.
+ +------------------------------+
| SCRIPT_TABLE_PRIVATE_DATA |
- | TableBase |---
- | TableLength |--|--
- | AtRuntime | | |
- | InSmm | | |
- +------------------------------+ | |
- | |
- +------------------------------+<-- |
- | EFI_BOOT_SCRIPT_TABLE_HEADER | |
- | TableLength |----|--
- +------------------------------+ | |
- | ...... | | |
- +------------------------------+<---- |
- | EFI_BOOT_SCRIPT_TERMINATE | |
- +------------------------------+<------
+ | TableBase |
+ | TableLength |
+ | TableMemoryPageNumber |
+ | AtRuntime |
+ | InSmm |
+ | BootTimeScriptLength |
+ | SmmLocked |
+ | BackFromS3 = TRUE |
+ +------------------------------+
**/
SCRIPT_TABLE_PRIVATE_DATA *mS3BootScriptTablePtr;
-EFI_EVENT mEnterRuntimeEvent;
+
//
-// Allocate SMM copy because we can not use mS3BootScriptTablePtr when we AtRuntime in InSmm.
+// Allocate SMM copy because we can not use mS3BootScriptTablePtr after SmmReadyToLock in InSmm.
//
SCRIPT_TABLE_PRIVATE_DATA *mS3BootScriptTableSmmPtr;
-UINTN mLockBoxLength;
EFI_GUID mBootScriptDataGuid = {
0xaea6b965, 0xdcf5, 0x4311, { 0xb4, 0xb8, 0xf, 0x12, 0x46, 0x44, 0x94, 0xd2 }
};
-EFI_GUID mBootScriptHeaderDataGuid = {
+EFI_GUID mBootScriptDataBootTimeGuid = {
+ 0xb5af1d7a, 0xb8cf, 0x4eb3, { 0x89, 0x25, 0xa8, 0x20, 0xe1, 0x6b, 0x68, 0x7d }
+};
+
+EFI_GUID mBootScriptTableBaseGuid = {
0x1810ab4a, 0x2314, 0x4df6, { 0x81, 0xeb, 0x67, 0xc6, 0xec, 0x5, 0x85, 0x91 }
};
+EFI_GUID mBootScriptSmmPrivateDataGuid = {
+ 0x627ee2da, 0x3bf9, 0x439b, { 0x92, 0x9f, 0x2e, 0xe, 0x6e, 0x9d, 0xba, 0x62 }
+};
+
+EFI_EVENT mEventDxeSmmReadyToLock = NULL;
+VOID *mRegistrationSmmExitBootServices = NULL;
+VOID *mRegistrationSmmLegacyBoot = NULL;
+VOID *mRegistrationSmmReadyToLock = NULL;
+BOOLEAN mS3BootScriptTableAllocated = FALSE;
+BOOLEAN mS3BootScriptTableSmmAllocated = FALSE;
+EFI_SMM_SYSTEM_TABLE2 *mSmst = NULL;
+
/**
This is an internal function to add a terminate node the entry, recalculate the table
length and fill into the table.
- @return the base address of the boot script tble.
+ @return the base address of the boot script table.
**/
UINT8*
S3BootScriptInternalCloseTable (
@@ -93,18 +171,15 @@ S3BootScriptInternalCloseTable (
return S3TableBase;
//
// NOTE: Here we did NOT adjust the mS3BootScriptTablePtr->TableLength to
- // mS3BootScriptTablePtr->TableLength + sizeof (EFI_BOOT_SCRIPT_TERMINATE). Because
- // maybe in runtime, we still need add entries into the table, and the runtime entry should be
- // added start before this TERMINATE node.
+ // mS3BootScriptTablePtr->TableLength + sizeof (EFI_BOOT_SCRIPT_TERMINATE).
+ // Because maybe after SmmReadyToLock, we still need add entries into the table,
+ // and the entry should be added start before this TERMINATE node.
//
}
/**
This function save boot script data to LockBox.
- 1. BootSriptPrivate data, BootScript data - Image and DispatchContext are handled by platform.
- 2. BootScriptExecutor, BootScriptExecutor context
- - ACPI variable - (PI version) sould be handled by SMM driver. S3 Page table is handled here.
- - ACPI variable - framework version is already handled by Framework CPU driver.
+
**/
VOID
SaveBootScriptDataToLockBox (
@@ -114,13 +189,13 @@ SaveBootScriptDataToLockBox (
EFI_STATUS Status;
//
- // mS3BootScriptTablePtr->TableLength does not include EFI_BOOT_SCRIPT_TERMINATE, because we need add entry at runtime.
- // Save all info here, just in case that no one will add boot script entry in SMM.
+ // Save whole memory copy into LockBox.
+ // It will be used to restore data at S3 resume.
//
Status = SaveLockBox (
&mBootScriptDataGuid,
(VOID *)mS3BootScriptTablePtr->TableBase,
- mS3BootScriptTablePtr->TableLength + sizeof(EFI_BOOT_SCRIPT_TERMINATE)
+ EFI_PAGES_TO_SIZE (mS3BootScriptTablePtr->TableMemoryPageNumber)
);
ASSERT_EFI_ERROR (Status);
@@ -132,22 +207,22 @@ SaveBootScriptDataToLockBox (
// Do not update other field because they will NOT be used in S3.
//
Status = SaveLockBox (
- &mBootScriptHeaderDataGuid,
+ &mBootScriptTableBaseGuid,
(VOID *)&mS3BootScriptTablePtr->TableBase,
sizeof(mS3BootScriptTablePtr->TableBase)
);
ASSERT_EFI_ERROR (Status);
- Status = SetLockBoxAttributes (&mBootScriptHeaderDataGuid, LOCK_BOX_ATTRIBUTE_RESTORE_IN_PLACE);
+ Status = SetLockBoxAttributes (&mBootScriptTableBaseGuid, LOCK_BOX_ATTRIBUTE_RESTORE_IN_PLACE);
ASSERT_EFI_ERROR (Status);
}
/**
This is the Event call back function to notify the Library the system is entering
- run time phase.
+ SmmLocked phase.
@param Event Pointer to this event
- @param Context Event hanlder private data
+ @param Context Event handler private data
**/
VOID
EFIAPI
@@ -173,28 +248,29 @@ S3BootScriptEventCallBack (
}
//
- // Here we should tell the library that we are enter into runtime phase. and
- // the memory page number occupied by the table should not grow anymore.
+ // Here we should tell the library that we are entering SmmLocked phase.
+ // and the memory page number occupied by the table should not grow anymore.
//
- if (!mS3BootScriptTablePtr->AtRuntime) {
+ if (!mS3BootScriptTablePtr->SmmLocked) {
//
- // In boot time, we need not write the terminate node when adding a node to boot scipt table
- // or else, that will impact the performance. However, in runtime, we should append terminate
- // node on every add to boot script table
+ // Before SmmReadyToLock, we need not write the terminate node when adding a node to boot scipt table
+ // or else, that will impact the performance. However, after SmmReadyToLock, we should append terminate
+ // node on every add to boot script table.
//
S3BootScriptInternalCloseTable ();
- mS3BootScriptTablePtr->AtRuntime = TRUE;
+ mS3BootScriptTablePtr->SmmLocked = TRUE;
//
// Save BootScript data to lockbox
//
SaveBootScriptDataToLockBox ();
}
-}
+}
+
/**
- This is the Event call back function is triggered in SMM to notify the Library the system is entering
- run time phase and set InSmm flag.
-
+ This is the Event call back function is triggered in SMM to notify the Library
+ the system is entering SmmLocked phase and set InSmm flag.
+
@param Protocol Points to the protocol's unique identifier
@param Interface Points to the interface instance
@param Handle The handle on which the interface was installed
@@ -217,7 +293,7 @@ S3BootScriptSmmEventCallBack (
}
//
- // Last chance to call-out, just make sure AtRuntime is set
+ // Last chance to call-out, just make sure SmmLocked is set.
//
S3BootScriptEventCallBack (NULL, NULL);
@@ -226,22 +302,117 @@ S3BootScriptSmmEventCallBack (
//
if (mS3BootScriptTableSmmPtr->TableBase == NULL) {
CopyMem (mS3BootScriptTableSmmPtr, mS3BootScriptTablePtr, sizeof(*mS3BootScriptTablePtr));
+
+ //
+ // Set InSmm, we allow boot script update when InSmm, but not allow boot script outside SMM.
+ // InSmm will only be checked if SmmLocked is TRUE.
+ //
+ mS3BootScriptTableSmmPtr->InSmm = TRUE;
}
//
- // We should not use ACPINvs copy, because it is not safe.
+ // We should not use ACPI Reserved copy, because it is not safe.
//
mS3BootScriptTablePtr = mS3BootScriptTableSmmPtr;
+ return EFI_SUCCESS;
+}
+
+/**
+ This function is to save boot time boot script data to LockBox.
+
+ Because there may be INSERT boot script at runtime in SMM.
+ The boot time copy will be used to restore data after back from S3.
+ Otherwise the data inserted may cause some boot time boot script data lost
+ if only BootScriptData used.
+
+**/
+VOID
+SaveBootTimeDataToLockBox (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // ACPI Reserved copy is not safe, restore from BootScriptData LockBox first,
+ // and then save the data to BootScriptDataBootTime LockBox.
+ //
+ Status = RestoreLockBox (
+ &mBootScriptDataGuid,
+ NULL,
+ NULL
+ );
+ ASSERT_EFI_ERROR (Status);
+
//
- // Set InSmm, we allow boot script update when InSmm, but not allow boot script outside SMM.
- // InSmm will only be checked if AtRuntime is TRUE.
+ // Save BootScriptDataBootTime
+ // It will be used to restore data after back from S3.
//
- mS3BootScriptTablePtr->InSmm = TRUE;
+ Status = SaveLockBox (
+ &mBootScriptDataBootTimeGuid,
+ (VOID *) mS3BootScriptTablePtr->TableBase,
+ mS3BootScriptTablePtr->BootTimeScriptLength
+ );
+ ASSERT_EFI_ERROR (Status);
+}
+
+/**
+ This function save boot script SMM private data to LockBox with BackFromS3 = TRUE at runtime.
+ S3 resume will help restore it to tell the Library the system is back from S3.
+
+**/
+VOID
+SaveSmmPriviateDataToLockBoxAtRuntime (
+ VOID
+ )
+{
+ EFI_STATUS Status;
//
- // Record LockBoxLength
+ // Save boot script SMM private data with BackFromS3 = TRUE.
//
- mLockBoxLength = mS3BootScriptTableSmmPtr->TableLength + sizeof(EFI_BOOT_SCRIPT_TERMINATE);
+ mS3BootScriptTablePtr->BackFromS3 = TRUE;
+ Status = SaveLockBox (
+ &mBootScriptSmmPrivateDataGuid,
+ (VOID *) mS3BootScriptTablePtr,
+ sizeof (SCRIPT_TABLE_PRIVATE_DATA)
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ Status = SetLockBoxAttributes (&mBootScriptSmmPrivateDataGuid, LOCK_BOX_ATTRIBUTE_RESTORE_IN_PLACE);
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Set BackFromS3 flag back to FALSE to indicate that now is not back from S3.
+ //
+ mS3BootScriptTablePtr->BackFromS3 = FALSE;
+}
+
+/**
+ This is the Event call back function is triggered in SMM to notify the Library
+ the system is entering runtime phase.
+
+ @param[in] Protocol Points to the protocol's unique identifier
+ @param[in] Interface Points to the interface instance
+ @param[in] Handle The handle on which the interface was installed
+
+ @retval EFI_SUCCESS SmmAtRuntimeCallBack runs successfully
+ **/
+EFI_STATUS
+EFIAPI
+S3BootScriptSmmAtRuntimeCallBack (
+ IN CONST EFI_GUID *Protocol,
+ IN VOID *Interface,
+ IN EFI_HANDLE Handle
+ )
+{
+ if (!mS3BootScriptTablePtr->AtRuntime) {
+ mS3BootScriptTablePtr->BootTimeScriptLength = (UINT32) (mS3BootScriptTablePtr->TableLength + sizeof (EFI_BOOT_SCRIPT_TERMINATE));
+ SaveBootTimeDataToLockBox ();
+
+ mS3BootScriptTablePtr->AtRuntime = TRUE;
+ SaveSmmPriviateDataToLockBoxAtRuntime ();
+ }
return EFI_SUCCESS;
}
@@ -254,8 +425,8 @@ S3BootScriptSmmEventCallBack (
@param ImageHandle The firmware allocated handle for the EFI image.
@param SystemTable A pointer to the EFI System Table.
- @retval RETURN_SUCCESS Allocate the global memory space to store S3 boot script table private data
- @retval RETURN_OUT_OF_RESOURCES No enough memory to allocated.
+ @retval RETURN_SUCCESS The constructor always returns RETURN_SUCCESS.
+
**/
RETURN_STATUS
EFIAPI
@@ -270,7 +441,6 @@ S3BootScriptLibInitialize (
VOID *Registration;
EFI_SMM_BASE2_PROTOCOL *SmmBase2;
BOOLEAN InSmm;
- EFI_SMM_SYSTEM_TABLE2 *Smst;
EFI_PHYSICAL_ADDRESS Buffer;
S3TablePtr = (SCRIPT_TABLE_PRIVATE_DATA*)(UINTN)PcdGet64(PcdS3BootScriptTablePrivateDataPtr);
@@ -281,29 +451,29 @@ S3BootScriptLibInitialize (
Buffer = SIZE_4GB - 1;
Status = gBS->AllocatePages (
AllocateMaxAddress,
- EfiACPIMemoryNVS,
+ EfiReservedMemoryType,
EFI_SIZE_TO_PAGES(sizeof(SCRIPT_TABLE_PRIVATE_DATA)),
&Buffer
);
- if (EFI_ERROR (Status)) {
- return RETURN_OUT_OF_RESOURCES;
- }
+ ASSERT_EFI_ERROR (Status);
+ mS3BootScriptTableAllocated = TRUE;
S3TablePtr = (VOID *) (UINTN) Buffer;
- PcdSet64 (PcdS3BootScriptTablePrivateDataPtr, (UINT64) (UINTN)S3TablePtr);
- ZeroMem (S3TablePtr, sizeof(SCRIPT_TABLE_PRIVATE_DATA));
+ Status = PcdSet64S (PcdS3BootScriptTablePrivateDataPtr, (UINT64) (UINTN)S3TablePtr);
+ ASSERT_EFI_ERROR (Status);
+ ZeroMem (S3TablePtr, sizeof(SCRIPT_TABLE_PRIVATE_DATA));
//
- // create event to notify the library system enter the runtime phase
+ // Create event to notify the library system enter the SmmLocked phase.
//
- mEnterRuntimeEvent = EfiCreateProtocolNotifyEvent (
- &gEfiDxeSmmReadyToLockProtocolGuid,
- TPL_CALLBACK,
- S3BootScriptEventCallBack,
- NULL,
- &Registration
- );
- ASSERT (mEnterRuntimeEvent != NULL);
- }
+ mEventDxeSmmReadyToLock = EfiCreateProtocolNotifyEvent (
+ &gEfiDxeSmmReadyToLockProtocolGuid,
+ TPL_CALLBACK,
+ S3BootScriptEventCallBack,
+ NULL,
+ &Registration
+ );
+ ASSERT (mEventDxeSmmReadyToLock != NULL);
+ }
mS3BootScriptTablePtr = S3TablePtr;
//
@@ -323,7 +493,7 @@ S3BootScriptLibInitialize (
//
// Good, we are in SMM
//
- Status = SmmBase2->GetSmstLocation (SmmBase2, &Smst);
+ Status = SmmBase2->GetSmstLocation (SmmBase2, &mSmst);
if (EFI_ERROR (Status)) {
return RETURN_SUCCESS;
}
@@ -333,33 +503,137 @@ S3BootScriptLibInitialize (
// The Boot script private data in SMM is not be initialized. create it
//
if (S3TableSmmPtr == 0) {
- Status = Smst->SmmAllocatePool (
+ Status = mSmst->SmmAllocatePool (
EfiRuntimeServicesData,
sizeof(SCRIPT_TABLE_PRIVATE_DATA),
(VOID **) &S3TableSmmPtr
);
- if (EFI_ERROR (Status)) {
- return RETURN_OUT_OF_RESOURCES;
- }
+ ASSERT_EFI_ERROR (Status);
+ mS3BootScriptTableSmmAllocated = TRUE;
- PcdSet64 (PcdS3BootScriptTablePrivateSmmDataPtr, (UINT64) (UINTN)S3TableSmmPtr);
+ Status = PcdSet64S (PcdS3BootScriptTablePrivateSmmDataPtr, (UINT64) (UINTN)S3TableSmmPtr);
+ ASSERT_EFI_ERROR (Status);
ZeroMem (S3TableSmmPtr, sizeof(SCRIPT_TABLE_PRIVATE_DATA));
+
+ //
+ // Register SmmExitBootServices and SmmLegacyBoot notification.
+ //
+ Status = mSmst->SmmRegisterProtocolNotify (
+ &gEdkiiSmmExitBootServicesProtocolGuid,
+ S3BootScriptSmmAtRuntimeCallBack,
+ &mRegistrationSmmExitBootServices
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ Status = mSmst->SmmRegisterProtocolNotify (
+ &gEdkiiSmmLegacyBootProtocolGuid,
+ S3BootScriptSmmAtRuntimeCallBack,
+ &mRegistrationSmmLegacyBoot
+ );
+ ASSERT_EFI_ERROR (Status);
}
mS3BootScriptTableSmmPtr = S3TableSmmPtr;
//
- // Then register event after lock
+ // Register SmmReadyToLock notification.
//
- Registration = NULL;
- Status = Smst->SmmRegisterProtocolNotify (
+ Status = mSmst->SmmRegisterProtocolNotify (
&gEfiSmmReadyToLockProtocolGuid,
S3BootScriptSmmEventCallBack,
- &Registration
+ &mRegistrationSmmReadyToLock
);
ASSERT_EFI_ERROR (Status);
return RETURN_SUCCESS;
}
+
+/**
+ Library Destructor to free the resources allocated by
+ S3BootScriptLibInitialize() and unregister callbacks.
+
+ NOTICE: The destructor doesn't support unloading as a separate action, and it
+ only supports unloading if the containing driver's entry point function fails.
+
+ @param ImageHandle The firmware allocated handle for the EFI image.
+ @param SystemTable A pointer to the EFI System Table.
+
+ @retval RETURN_SUCCESS The destructor always returns RETURN_SUCCESS.
+
+**/
+RETURN_STATUS
+EFIAPI
+S3BootScriptLibDeinitialize (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+
+ DEBUG ((EFI_D_INFO, "%a() in %a module\n", __FUNCTION__, gEfiCallerBaseName));
+
+ if (mEventDxeSmmReadyToLock != NULL) {
+ //
+ // Close the DxeSmmReadyToLock event.
+ //
+ Status = gBS->CloseEvent (mEventDxeSmmReadyToLock);
+ ASSERT_EFI_ERROR (Status);
+ }
+
+ if (mSmst != NULL) {
+ if (mRegistrationSmmExitBootServices != NULL) {
+ //
+ // Unregister SmmExitBootServices notification.
+ //
+ Status = mSmst->SmmRegisterProtocolNotify (
+ &gEdkiiSmmExitBootServicesProtocolGuid,
+ NULL,
+ &mRegistrationSmmExitBootServices
+ );
+ ASSERT_EFI_ERROR (Status);
+ }
+ if (mRegistrationSmmLegacyBoot != NULL) {
+ //
+ // Unregister SmmLegacyBoot notification.
+ //
+ Status = mSmst->SmmRegisterProtocolNotify (
+ &gEdkiiSmmLegacyBootProtocolGuid,
+ NULL,
+ &mRegistrationSmmLegacyBoot
+ );
+ ASSERT_EFI_ERROR (Status);
+ }
+ if (mRegistrationSmmReadyToLock != NULL) {
+ //
+ // Unregister SmmReadyToLock notification.
+ //
+ Status = mSmst->SmmRegisterProtocolNotify (
+ &gEfiSmmReadyToLockProtocolGuid,
+ NULL,
+ &mRegistrationSmmReadyToLock
+ );
+ ASSERT_EFI_ERROR (Status);
+ }
+ }
+
+ //
+ // Free the resources allocated and set PCDs to 0.
+ //
+ if (mS3BootScriptTableAllocated) {
+ Status = gBS->FreePages ((EFI_PHYSICAL_ADDRESS) (UINTN) mS3BootScriptTablePtr, EFI_SIZE_TO_PAGES(sizeof(SCRIPT_TABLE_PRIVATE_DATA)));
+ ASSERT_EFI_ERROR (Status);
+ Status = PcdSet64S (PcdS3BootScriptTablePrivateDataPtr, 0);
+ ASSERT_EFI_ERROR (Status);
+ }
+ if ((mSmst != NULL) && mS3BootScriptTableSmmAllocated) {
+ Status = mSmst->SmmFreePool (mS3BootScriptTableSmmPtr);
+ ASSERT_EFI_ERROR (Status);
+ Status = PcdSet64S (PcdS3BootScriptTablePrivateSmmDataPtr, 0);
+ ASSERT_EFI_ERROR (Status);
+ }
+
+ return RETURN_SUCCESS;
+}
+
/**
To get the start address from which a new boot time s3 boot script entry will write into.
If the table is not exist, the functio will first allocate a buffer for the table
@@ -385,14 +659,14 @@ S3BootScriptGetBootTimeEntryAddAddress (
S3TableBase = (EFI_PHYSICAL_ADDRESS)(UINTN)(mS3BootScriptTablePtr->TableBase);
if (S3TableBase == 0) {
+ //
// The table is not exist. This is the first to add entry.
- // Allocate ACPI script table space under 4G memory. We need it to save
- // some settings done by CSM, which runs after normal script table closed
+ // Allocate ACPI script table space under 4G memory.
//
S3TableBase = 0xffffffff;
Status = gBS->AllocatePages (
AllocateMaxAddress,
- EfiACPIMemoryNVS,
+ EfiReservedMemoryType,
2 + PcdGet16(PcdS3BootScriptRuntimeTableReservePageNumber),
(EFI_PHYSICAL_ADDRESS*)&S3TableBase
);
@@ -407,6 +681,7 @@ S3BootScriptGetBootTimeEntryAddAddress (
ScriptTableInfo = (EFI_BOOT_SCRIPT_TABLE_HEADER*)(UINTN)S3TableBase;
ScriptTableInfo->OpCode = S3_BOOT_SCRIPT_LIB_TABLE_OPCODE;
ScriptTableInfo->Length = (UINT8) sizeof (EFI_BOOT_SCRIPT_TABLE_HEADER);
+ ScriptTableInfo->Version = BOOT_SCRIPT_TABLE_VERSION;
ScriptTableInfo->TableLength = 0; // will be calculate at CloseTable
mS3BootScriptTablePtr->TableLength = sizeof (EFI_BOOT_SCRIPT_TABLE_HEADER);
mS3BootScriptTablePtr->TableBase = (UINT8*)(UINTN)S3TableBase;
@@ -414,16 +689,16 @@ S3BootScriptGetBootTimeEntryAddAddress (
}
// Here we do not count the reserved memory for runtime script table.
- PageNumber = (UINT16)(mS3BootScriptTablePtr->TableMemoryPageNumber - PcdGet16(PcdS3BootScriptRuntimeTableReservePageNumber));
+ PageNumber = (UINT16) (mS3BootScriptTablePtr->TableMemoryPageNumber - PcdGet16(PcdS3BootScriptRuntimeTableReservePageNumber));
TableLength = mS3BootScriptTablePtr->TableLength;
- if ((UINT32)(PageNumber * EFI_PAGE_SIZE) < (TableLength + EntryLength + sizeof (EFI_BOOT_SCRIPT_TERMINATE))) {
+ if ((UINTN) EFI_PAGES_TO_SIZE ((UINTN) PageNumber) < (UINTN) (TableLength + EntryLength + sizeof (EFI_BOOT_SCRIPT_TERMINATE))) {
//
// The buffer is too small to hold the table, Reallocate the buffer
//
NewS3TableBase = 0xffffffff;
Status = gBS->AllocatePages (
AllocateMaxAddress,
- EfiACPIMemoryNVS,
+ EfiReservedMemoryType,
2 + PageNumber + PcdGet16(PcdS3BootScriptRuntimeTableReservePageNumber),
(EFI_PHYSICAL_ADDRESS*)&NewS3TableBase
);
@@ -459,12 +734,12 @@ S3BootScriptGetBootTimeEntryAddAddress (
return NewEntryPtr;
}
/**
- To get the start address from which a new runtime s3 boot script entry will write into.
+ To get the start address from which a new runtime(after SmmReadyToLock) s3 boot script entry will write into.
In this case, it should be ensured that there is enough buffer to hold the entry.
@param EntryLength the new entry length.
- @retval the address from which the a new s3 runtime script entry will write into
+ @retval the address from which the a new s3 runtime(after SmmReadyToLock) script entry will write into
**/
UINT8*
S3BootScriptGetRuntimeEntryAddAddress (
@@ -477,7 +752,7 @@ S3BootScriptGetRuntimeEntryAddAddress (
//
// Check if the memory range reserved for S3 Boot Script table is large enough to hold the node.
//
- if (mS3BootScriptTablePtr->TableLength + EntryLength + sizeof (EFI_BOOT_SCRIPT_TERMINATE) <= EFI_PAGES_TO_SIZE((UINT32)(mS3BootScriptTablePtr->TableMemoryPageNumber))) {
+ if ((UINTN) (mS3BootScriptTablePtr->TableLength + EntryLength + sizeof (EFI_BOOT_SCRIPT_TERMINATE)) <= (UINTN) EFI_PAGES_TO_SIZE ((UINTN) (mS3BootScriptTablePtr->TableMemoryPageNumber))) {
NewEntryPtr = mS3BootScriptTablePtr->TableBase + mS3BootScriptTablePtr->TableLength;
mS3BootScriptTablePtr->TableLength = mS3BootScriptTablePtr->TableLength + EntryLength;
//
@@ -487,12 +762,53 @@ S3BootScriptGetRuntimeEntryAddAddress (
}
return (UINT8*)NewEntryPtr;
}
+
+/**
+ This function is to restore boot time boot script data from LockBox.
+
+**/
+VOID
+RestoreBootTimeDataFromLockBox (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ UINTN LockBoxLength;
+
+ //
+ // Restore boot time boot script data from LockBox.
+ //
+ LockBoxLength = mS3BootScriptTablePtr->BootTimeScriptLength;
+ Status = RestoreLockBox (
+ &mBootScriptDataBootTimeGuid,
+ (VOID *) mS3BootScriptTablePtr->TableBase,
+ &LockBoxLength
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Update the data to BootScriptData LockBox.
+ //
+ Status = UpdateLockBox (
+ &mBootScriptDataGuid,
+ 0,
+ (VOID *) mS3BootScriptTablePtr->TableBase,
+ LockBoxLength
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Update TableLength.
+ //
+ mS3BootScriptTablePtr->TableLength = (UINT32) (mS3BootScriptTablePtr->BootTimeScriptLength - sizeof (EFI_BOOT_SCRIPT_TERMINATE));
+}
+
/**
To get the start address from which a new s3 boot script entry will write into.
@param EntryLength the new entry length.
- @retval the address from which the a new s3 runtime script entry will write into
+ @retval the address from which the a new s3 boot script entry will write into
**/
UINT8*
S3BootScriptGetEntryAddAddress (
@@ -500,56 +816,31 @@ S3BootScriptGetEntryAddAddress (
)
{
UINT8* NewEntryPtr;
- EFI_BOOT_SCRIPT_TABLE_HEADER TableHeader;
- EFI_STATUS Status;
- if (mS3BootScriptTablePtr->AtRuntime) {
+ if (mS3BootScriptTablePtr->SmmLocked) {
//
- // We need check InSmm when AtRuntime, because after SmmReadyToLock, only SMM driver is allowed to write boot script.
+ // We need check InSmm, because after SmmReadyToLock, only SMM driver is allowed to write boot script.
//
if (!mS3BootScriptTablePtr->InSmm) {
//
- // Add DEBUG ERROR, so that we can find it at boot time.
- // Do not use ASSERT, because we may have test invoke this interface.
+ // Add DEBUG ERROR, so that we can find it after SmmReadyToLock.
+ // Do not use ASSERT, because we may have test to invoke this interface.
//
- DEBUG ((EFI_D_ERROR, "FATAL ERROR: Set boot script after ReadyToLock!!!\n"));
+ DEBUG ((EFI_D_ERROR, "FATAL ERROR: Set boot script outside SMM after SmmReadyToLock!!!\n"));
return NULL;
}
- //
- // NOTE: OS will restore ACPINvs data. After S3, the table length in mS3BootScriptTableSmmPtr (SMM) is different with
- // table length in BootScriptTable header (ACPINvs).
- // So here we need sync them. We choose ACPINvs table length, because we want to override the boot script saved
- // in SMM every time.
- //
- ASSERT (mS3BootScriptTablePtr == mS3BootScriptTableSmmPtr);
- CopyMem ((VOID*)&TableHeader, (VOID*)mS3BootScriptTablePtr->TableBase, sizeof(EFI_BOOT_SCRIPT_TABLE_HEADER));
- if (mS3BootScriptTablePtr->TableLength + sizeof(EFI_BOOT_SCRIPT_TERMINATE) != TableHeader.TableLength) {
- //
- // Restore it to use original value
+ if (mS3BootScriptTablePtr->BackFromS3) {
//
- RestoreLockBox (&mBootScriptDataGuid, NULL, NULL);
+ // Back from S3, restore boot time boot script data from LockBox
+ // and set BackFromS3 flag back to FALSE.
//
- // Copy it again to get original value
- // NOTE: We should NOT use TableHeader.TableLength, because it is already updated to be whole length.
- //
- mS3BootScriptTablePtr->TableLength = (UINT32)(mLockBoxLength - sizeof(EFI_BOOT_SCRIPT_TERMINATE));
+ RestoreBootTimeDataFromLockBox ();
+ mS3BootScriptTablePtr->BackFromS3 = FALSE;
}
NewEntryPtr = S3BootScriptGetRuntimeEntryAddAddress (EntryLength);
- //
- // Now the length field is updated, need sync to lockbox.
- // So in S3 resume, the data can be restored correctly.
- //
- CopyMem ((VOID*)&TableHeader, (VOID*)mS3BootScriptTablePtr->TableBase, sizeof(EFI_BOOT_SCRIPT_TABLE_HEADER));
- Status = UpdateLockBox (
- &mBootScriptDataGuid,
- OFFSET_OF(EFI_BOOT_SCRIPT_TABLE_HEADER, TableLength),
- &TableHeader.TableLength,
- sizeof(TableHeader.TableLength)
- );
- ASSERT_EFI_ERROR (Status);
- } else {
+ } else {
NewEntryPtr = S3BootScriptGetBootTimeEntryAddAddress (EntryLength);
}
return NewEntryPtr;
@@ -558,26 +849,52 @@ S3BootScriptGetEntryAddAddress (
/**
Sync BootScript LockBox data.
+
+ @param Script The address from where the boot script has been added or updated.
+
**/
VOID
SyncBootScript (
- VOID
+ IN UINT8 *Script
)
{
EFI_STATUS Status;
+ UINT32 ScriptOffset;
+ UINT32 TotalScriptLength;
- if (!mS3BootScriptTablePtr->AtRuntime || !mS3BootScriptTablePtr->InSmm) {
+ if (!mS3BootScriptTablePtr->SmmLocked || !mS3BootScriptTablePtr->InSmm) {
+ //
+ // If it is not after SmmReadyToLock in SMM,
+ // just return.
+ //
return ;
}
+
+ ScriptOffset = (UINT32) (Script - mS3BootScriptTablePtr->TableBase);
+
+ TotalScriptLength = (UINT32) (mS3BootScriptTablePtr->TableLength + sizeof (EFI_BOOT_SCRIPT_TERMINATE));
+
//
- // Update Terminate
+ // Update BootScriptData
// So in S3 resume, the data can be restored correctly.
//
Status = UpdateLockBox (
&mBootScriptDataGuid,
- mLockBoxLength - sizeof(EFI_BOOT_SCRIPT_TERMINATE),
- (VOID *)((UINTN)mS3BootScriptTablePtr->TableBase + mLockBoxLength - sizeof(EFI_BOOT_SCRIPT_TERMINATE)),
- sizeof(EFI_BOOT_SCRIPT_TERMINATE)
+ ScriptOffset,
+ (VOID *)((UINTN)mS3BootScriptTablePtr->TableBase + ScriptOffset),
+ TotalScriptLength - ScriptOffset
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Now the length field is updated, need sync to lockbox.
+ // So at S3 resume, the data can be restored correctly.
+ //
+ Status = UpdateLockBox (
+ &mBootScriptDataGuid,
+ OFFSET_OF (EFI_BOOT_SCRIPT_TABLE_HEADER, TableLength),
+ &TotalScriptLength,
+ sizeof (TotalScriptLength)
);
ASSERT_EFI_ERROR (Status);
}
@@ -600,10 +917,10 @@ SyncBootScript (
for Framework Spec compatibility.
If anyone does call CloseTable() on a real platform, then the caller is responsible for figuring out
- how to get the script to run on an S3 resume because the boot script maintained by the lib will be
+ how to get the script to run at S3 resume because the boot script maintained by the lib will be
destroyed.
- @return the base address of the new copy of the boot script tble.
+ @return the base address of the new copy of the boot script table.
@note this function could only called in boot time phase
**/
@@ -698,7 +1015,7 @@ S3BootScriptSaveIoWrite (
CopyMem ((VOID*)Script, (VOID*)&ScriptIoWrite, sizeof(EFI_BOOT_SCRIPT_IO_WRITE));
CopyMem ((VOID*)(Script + sizeof (EFI_BOOT_SCRIPT_IO_WRITE)), Buffer, WidthInByte * Count);
- SyncBootScript ();
+ SyncBootScript (Script);
return RETURN_SUCCESS;
}
@@ -747,7 +1064,7 @@ S3BootScriptSaveIoReadWrite (
CopyMem ((VOID*)(Script + sizeof (EFI_BOOT_SCRIPT_IO_READ_WRITE)), Data, WidthInByte);
CopyMem ((VOID*)(Script + sizeof (EFI_BOOT_SCRIPT_IO_READ_WRITE) + WidthInByte), DataMask, WidthInByte);
- SyncBootScript ();
+ SyncBootScript (Script);
return RETURN_SUCCESS;
}
@@ -795,7 +1112,7 @@ S3BootScriptSaveMemWrite (
CopyMem ((VOID*)Script, (VOID*)&ScriptMemWrite, sizeof(EFI_BOOT_SCRIPT_MEM_WRITE));
CopyMem ((VOID*)(Script + sizeof (EFI_BOOT_SCRIPT_MEM_WRITE)), Buffer, WidthInByte * Count);
- SyncBootScript ();
+ SyncBootScript (Script);
return RETURN_SUCCESS;
}
@@ -843,7 +1160,7 @@ S3BootScriptSaveMemReadWrite (
CopyMem ((VOID*)(Script + sizeof (EFI_BOOT_SCRIPT_MEM_READ_WRITE)), Data, WidthInByte);
CopyMem ((VOID*)(Script + sizeof (EFI_BOOT_SCRIPT_MEM_READ_WRITE) + WidthInByte), DataMask, WidthInByte);
- SyncBootScript ();
+ SyncBootScript (Script);
return RETURN_SUCCESS;
}
@@ -857,6 +1174,8 @@ S3BootScriptSaveMemReadWrite (
@retval RETURN_OUT_OF_RESOURCES Not enough memory for the table do operation.
@retval RETURN_SUCCESS Opcode is added.
+ @note A known Limitations in the implementation which is 64bits operations are not supported.
+
**/
RETURN_STATUS
EFIAPI
@@ -872,6 +1191,12 @@ S3BootScriptSavePciCfgWrite (
UINT8 WidthInByte;
EFI_BOOT_SCRIPT_PCI_CONFIG_WRITE ScriptPciWrite;
+ if (Width == S3BootScriptWidthUint64 ||
+ Width == S3BootScriptWidthFifoUint64 ||
+ Width == S3BootScriptWidthFillUint64) {
+ return EFI_INVALID_PARAMETER;
+ }
+
WidthInByte = (UINT8) (0x01 << (Width & 0x03));
Length = (UINT8)(sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG_WRITE) + (WidthInByte * Count));
@@ -891,7 +1216,7 @@ S3BootScriptSavePciCfgWrite (
CopyMem ((VOID*)Script, (VOID*)&ScriptPciWrite, sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG_WRITE));
CopyMem ((VOID*)(Script + sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG_WRITE)), Buffer, WidthInByte * Count);
- SyncBootScript ();
+ SyncBootScript (Script);
return RETURN_SUCCESS;
}
@@ -905,6 +1230,8 @@ S3BootScriptSavePciCfgWrite (
@retval RETURN_OUT_OF_RESOURCES Not enough memory for the table do operation.
@retval RETURN__SUCCESS Opcode is added.
+ @note A known Limitations in the implementation which is 64bits operations are not supported.
+
**/
RETURN_STATUS
EFIAPI
@@ -920,6 +1247,12 @@ S3BootScriptSavePciCfgReadWrite (
UINT8 WidthInByte;
EFI_BOOT_SCRIPT_PCI_CONFIG_READ_WRITE ScriptPciReadWrite;
+ if (Width == S3BootScriptWidthUint64 ||
+ Width == S3BootScriptWidthFifoUint64 ||
+ Width == S3BootScriptWidthFillUint64) {
+ return EFI_INVALID_PARAMETER;
+ }
+
WidthInByte = (UINT8) (0x01 << (Width & 0x03));
Length = (UINT8)(sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG_READ_WRITE) + (WidthInByte * 2));
@@ -943,12 +1276,12 @@ S3BootScriptSavePciCfgReadWrite (
WidthInByte
);
- SyncBootScript ();
+ SyncBootScript (Script);
return RETURN_SUCCESS;
}
/**
- Adds a record for a PCI configuration space modify operation into a specified boot script table.
+ Adds a record for a PCI configuration 2 space write operation into a specified boot script table.
@param Width The width of the I/O operations.Enumerated in S3_BOOT_SCRIPT_LIB_WIDTH.
@param Segment The PCI segment number for Address.
@@ -958,6 +1291,8 @@ S3BootScriptSavePciCfgReadWrite (
@retval RETURN_OUT_OF_RESOURCES Not enough memory for the table do operation.
@retval RETURN_SUCCESS Opcode is added.
+ @note A known Limitations in the implementation which is non-zero Segment and 64bits operations are not supported.
+
**/
RETURN_STATUS
EFIAPI
@@ -973,7 +1308,14 @@ S3BootScriptSavePciCfg2Write (
UINT8 *Script;
UINT8 WidthInByte;
EFI_BOOT_SCRIPT_PCI_CONFIG2_WRITE ScriptPciWrite2;
-
+
+ if (Segment != 0 ||
+ Width == S3BootScriptWidthUint64 ||
+ Width == S3BootScriptWidthFifoUint64 ||
+ Width == S3BootScriptWidthFillUint64) {
+ return EFI_INVALID_PARAMETER;
+ }
+
WidthInByte = (UINT8) (0x01 << (Width & 0x03));
Length = (UINT8)(sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG2_WRITE) + (WidthInByte * Count));
@@ -994,12 +1336,12 @@ S3BootScriptSavePciCfg2Write (
CopyMem ((VOID*)Script, (VOID*)&ScriptPciWrite2, sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG2_WRITE));
CopyMem ((VOID*)(Script + sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG2_WRITE)), Buffer, WidthInByte * Count);
- SyncBootScript ();
+ SyncBootScript (Script);
return RETURN_SUCCESS;
}
/**
- Adds a record for a PCI configuration space modify operation into a specified boot script table.
+ Adds a record for a PCI configuration 2 space modify operation into a specified boot script table.
@param Width The width of the I/O operations.Enumerated in S3_BOOT_SCRIPT_LIB_WIDTH.
@param Segment The PCI segment number for Address.
@@ -1009,6 +1351,8 @@ S3BootScriptSavePciCfg2Write (
@retval RETURN_OUT_OF_RESOURCES Not enough memory for the table do operation.
@retval RETURN_SUCCESS Opcode is added.
+ @note A known Limitations in the implementation which is non-zero Segment and 64bits operations are not supported.
+
**/
RETURN_STATUS
EFIAPI
@@ -1024,6 +1368,13 @@ S3BootScriptSavePciCfg2ReadWrite (
UINT8 *Script;
UINT8 WidthInByte;
EFI_BOOT_SCRIPT_PCI_CONFIG2_READ_WRITE ScriptPciReadWrite2;
+
+ if (Segment != 0 ||
+ Width == S3BootScriptWidthUint64 ||
+ Width == S3BootScriptWidthFifoUint64 ||
+ Width == S3BootScriptWidthFillUint64) {
+ return EFI_INVALID_PARAMETER;
+ }
WidthInByte = (UINT8) (0x01 << (Width & 0x03));
Length = (UINT8)(sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG2_READ_WRITE) + (WidthInByte * 2));
@@ -1049,10 +1400,111 @@ S3BootScriptSavePciCfg2ReadWrite (
WidthInByte
);
- SyncBootScript ();
+ SyncBootScript (Script);
return RETURN_SUCCESS;
}
+
+/**
+ Checks the parameter of S3BootScriptSaveSmbusExecute().
+
+ This function checks the input parameters of SmbusExecute(). If the input parameters are valid
+ for certain SMBus bus protocol, it will return EFI_SUCCESS; otherwise, it will return certain
+ error code based on the input SMBus bus protocol.
+
+ @param SmBusAddress Address that encodes the SMBUS Slave Address, SMBUS Command, SMBUS Data Length,
+ and PEC.
+ @param Operation Signifies which particular SMBus hardware protocol instance that
+ it will use to execute the SMBus transactions. This SMBus
+ hardware protocol is defined by the SMBus Specification and is
+ not related to EFI.
+ @param Length Signifies the number of bytes that this operation will do. The
+ maximum number of bytes can be revision specific and operation
+ specific. This field will contain the actual number of bytes that
+ are executed for this operation. Not all operations require this
+ argument.
+ @param Buffer Contains the value of data to execute to the SMBus slave device.
+ Not all operations require this argument. The length of this
+ buffer is identified by Length.
+
+ @retval EFI_SUCCESS All the parameters are valid for the corresponding SMBus bus
+ protocol.
+ @retval EFI_INVALID_PARAMETER Operation is not defined in EFI_SMBUS_OPERATION.
+ @retval EFI_INVALID_PARAMETER Length/Buffer is NULL for operations except for EfiSmbusQuickRead
+ and EfiSmbusQuickWrite. Length is outside the range of valid
+ values.
+ @retval EFI_UNSUPPORTED The SMBus operation or PEC is not supported.
+ @retval EFI_BUFFER_TOO_SMALL Buffer is not sufficient for this operation.
+
+**/
+EFI_STATUS
+CheckParameters (
+ IN UINTN SmBusAddress,
+ IN EFI_SMBUS_OPERATION Operation,
+ IN OUT UINTN *Length,
+ IN VOID *Buffer
+ )
+{
+ EFI_STATUS Status;
+ UINTN RequiredLen;
+ EFI_SMBUS_DEVICE_COMMAND Command;
+ BOOLEAN PecCheck;
+
+ Command = SMBUS_LIB_COMMAND (SmBusAddress);
+ PecCheck = SMBUS_LIB_PEC (SmBusAddress);
+ //
+ // Set default value to be 2:
+ // for SmbusReadWord, SmbusWriteWord and SmbusProcessCall.
+ //
+ RequiredLen = 2;
+ Status = EFI_SUCCESS;
+ switch (Operation) {
+ case EfiSmbusQuickRead:
+ case EfiSmbusQuickWrite:
+ if (PecCheck || Command != 0) {
+ return EFI_UNSUPPORTED;
+ }
+ break;
+ case EfiSmbusReceiveByte:
+ case EfiSmbusSendByte:
+ if (Command != 0) {
+ return EFI_UNSUPPORTED;
+ }
+ //
+ // Cascade to check length parameter.
+ //
+ case EfiSmbusReadByte:
+ case EfiSmbusWriteByte:
+ RequiredLen = 1;
+ //
+ // Cascade to check length parameter.
+ //
+ case EfiSmbusReadWord:
+ case EfiSmbusWriteWord:
+ case EfiSmbusProcessCall:
+ if (Buffer == NULL || Length == NULL) {
+ return EFI_INVALID_PARAMETER;
+ } else if (*Length < RequiredLen) {
+ Status = EFI_BUFFER_TOO_SMALL;
+ }
+ *Length = RequiredLen;
+ break;
+ case EfiSmbusReadBlock:
+ case EfiSmbusWriteBlock:
+ case EfiSmbusBWBRProcessCall:
+ if ((Buffer == NULL) ||
+ (Length == NULL) ||
+ (*Length < MIN_SMBUS_BLOCK_LEN) ||
+ (*Length > MAX_SMBUS_BLOCK_LEN)) {
+ return EFI_INVALID_PARAMETER;
+ }
+ break;
+ default:
+ return EFI_INVALID_PARAMETER;
+ }
+ return Status;
+}
+
/**
Adds a record for an SMBus command execution into a specified boot script table.
@@ -1074,11 +1526,24 @@ S3BootScriptSaveSmbusExecute (
IN VOID *Buffer
)
{
+ EFI_STATUS Status;
+ UINTN BufferLength;
UINT8 DataSize;
UINT8 *Script;
EFI_BOOT_SCRIPT_SMBUS_EXECUTE ScriptSmbusExecute;
- DataSize = (UINT8)(sizeof (EFI_BOOT_SCRIPT_SMBUS_EXECUTE) + (*Length));
+ if (Length == NULL) {
+ BufferLength = 0;
+ } else {
+ BufferLength = *Length;
+ }
+
+ Status = CheckParameters (SmBusAddress, Operation, &BufferLength, Buffer);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ DataSize = (UINT8)(sizeof (EFI_BOOT_SCRIPT_SMBUS_EXECUTE) + BufferLength);
Script = S3BootScriptGetEntryAddAddress (DataSize);
if (Script == NULL) {
@@ -1091,16 +1556,16 @@ S3BootScriptSaveSmbusExecute (
ScriptSmbusExecute.Length = DataSize;
ScriptSmbusExecute.SmBusAddress = (UINT64) SmBusAddress;
ScriptSmbusExecute.Operation = Operation;
- ScriptSmbusExecute.DataSize = (UINT32) *Length;
+ ScriptSmbusExecute.DataSize = (UINT32) BufferLength;
CopyMem ((VOID*)Script, (VOID*)&ScriptSmbusExecute, sizeof (EFI_BOOT_SCRIPT_SMBUS_EXECUTE));
CopyMem (
(VOID*)(Script + sizeof (EFI_BOOT_SCRIPT_SMBUS_EXECUTE)),
Buffer,
- (*Length)
+ BufferLength
);
- SyncBootScript ();
+ SyncBootScript (Script);
return RETURN_SUCCESS;
}
@@ -1137,12 +1602,12 @@ S3BootScriptSaveStall (
CopyMem ((VOID*)Script, (VOID*)&ScriptStall, sizeof (EFI_BOOT_SCRIPT_STALL));
- SyncBootScript ();
+ SyncBootScript (Script);
return RETURN_SUCCESS;
}
/**
- Adds a record for an execution stall on the processor into a specified boot script table.
+ Adds a record for dispatching specified arbitrary code into a specified boot script table.
@param EntryPoint Entry point of the code to be dispatched.
@param Context Argument to be passed into the EntryPoint of the code to be dispatched.
@@ -1176,7 +1641,7 @@ S3BootScriptSaveDispatch2 (
CopyMem ((VOID*)Script, (VOID*)&ScriptDispatch2, sizeof (EFI_BOOT_SCRIPT_DISPATCH_2));
- SyncBootScript ();
+ SyncBootScript (Script);
return RETURN_SUCCESS;
@@ -1184,7 +1649,12 @@ S3BootScriptSaveDispatch2 (
/**
Adds a record for memory reads of the memory location and continues when the exit criteria is
satisfied or after a defined duration.
-
+
+ Please aware, below interface is different with PI specification, Vol 5:
+ EFI_S3_SAVE_STATE_PROTOCOL.Write() for EFI_BOOT_SCRIPT_MEM_POLL_OPCODE.
+ "Duration" below is microseconds, while "Delay" in PI specification means
+ the number of 100ns units to poll.
+
@param Width The width of the memory operations.
@param Address The base address of the memory operations.
@param BitMask A pointer to the bit mask to be AND-ed with the data read from the register.
@@ -1234,7 +1704,7 @@ S3BootScriptSaveMemPoll (
CopyMem ((UINT8 *) (Script + sizeof (EFI_BOOT_SCRIPT_MEM_POLL) + WidthInByte), BitMask, WidthInByte);
CopyMem ((VOID*)Script, (VOID*)&ScriptMemPoll, sizeof (EFI_BOOT_SCRIPT_MEM_POLL));
- SyncBootScript ();
+ SyncBootScript (Script);
return RETURN_SUCCESS;
}
@@ -1278,7 +1748,7 @@ S3BootScriptSaveInformation (
CopyMem ((VOID*)Script, (VOID*)&ScriptInformation, sizeof (EFI_BOOT_SCRIPT_INFORMATION));
CopyMem ((VOID*)(Script + sizeof (EFI_BOOT_SCRIPT_INFORMATION)), (VOID *) Information, (UINTN) InformationLength);
- SyncBootScript ();
+ SyncBootScript (Script);
return RETURN_SUCCESS;
@@ -1337,7 +1807,7 @@ S3BootScriptSaveDispatch (
CopyMem ((VOID*)Script, (VOID*)&ScriptDispatch, sizeof (EFI_BOOT_SCRIPT_DISPATCH));
- SyncBootScript ();
+ SyncBootScript (Script);
return RETURN_SUCCESS;
@@ -1394,7 +1864,7 @@ S3BootScriptSaveIoPoll (
CopyMem ((UINT8 *) (Script + sizeof (EFI_BOOT_SCRIPT_IO_POLL)), Data, WidthInByte);
CopyMem ((UINT8 *) (Script + sizeof (EFI_BOOT_SCRIPT_IO_POLL) + WidthInByte), DataMask, WidthInByte);
- SyncBootScript ();
+ SyncBootScript (Script);
return RETURN_SUCCESS;
}
@@ -1413,6 +1883,7 @@ S3BootScriptSaveIoPoll (
@retval RETURN_OUT_OF_RESOURCES Not enough memory for the table do operation.
@retval RETURN_SUCCESS Opcode is added.
+ @note A known Limitations in the implementation which is 64bits operations are not supported.
**/
RETURN_STATUS
@@ -1430,6 +1901,12 @@ S3BootScriptSavePciPoll (
UINT8 Length;
EFI_BOOT_SCRIPT_PCI_CONFIG_POLL ScriptPciPoll;
+ if (Width == S3BootScriptWidthUint64 ||
+ Width == S3BootScriptWidthFifoUint64 ||
+ Width == S3BootScriptWidthFillUint64) {
+ return EFI_INVALID_PARAMETER;
+ }
+
WidthInByte = (UINT8) (0x01 << (Width & 0x03));
Length = (UINT8)(sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG_POLL) + (WidthInByte * 2));
@@ -1450,7 +1927,7 @@ S3BootScriptSavePciPoll (
CopyMem ((UINT8 *) (Script + sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG_POLL)), Data, WidthInByte);
CopyMem ((UINT8 *) (Script + sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG_POLL) + WidthInByte), DataMask, WidthInByte);
- SyncBootScript ();
+ SyncBootScript (Script);
return RETURN_SUCCESS;
}
@@ -1469,9 +1946,8 @@ S3BootScriptSavePciPoll (
@retval RETURN_OUT_OF_RESOURCES Not enough memory for the table do operation.
@retval RETURN_SUCCESS Opcode is added.
- @note A known Limitations in the implementation: When interpreting the opcode EFI_BOOT_SCRIPT_PCI_CONFIG2_WRITE_OPCODE
- EFI_BOOT_SCRIPT_PCI_CONFIG2_READ_WRITE_OPCODE and EFI_BOOT_SCRIPT_PCI_CONFIG2_POLL_OPCODE, the 'Segment' parameter is assumed as
- Zero, or else, assert.
+ @note A known Limitations in the implementation which is non-zero Segment and 64bits operations are not supported.
+
**/
RETURN_STATUS
EFIAPI
@@ -1488,7 +1964,14 @@ S3BootScriptSavePci2Poll (
UINT8 *Script;
UINT8 Length;
EFI_BOOT_SCRIPT_PCI_CONFIG2_POLL ScriptPci2Poll;
-
+
+ if (Segment != 0 ||
+ Width == S3BootScriptWidthUint64 ||
+ Width == S3BootScriptWidthFifoUint64 ||
+ Width == S3BootScriptWidthFillUint64) {
+ return EFI_INVALID_PARAMETER;
+ }
+
WidthInByte = (UINT8) (0x01 << (Width & 0x03));
Length = (UINT8)(sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG2_POLL) + (WidthInByte * 2));
@@ -1510,7 +1993,7 @@ S3BootScriptSavePci2Poll (
CopyMem ((UINT8 *) (Script + sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG2_POLL)), Data, WidthInByte);
CopyMem ((UINT8 *) (Script + sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG2_POLL) + WidthInByte), DataMask, WidthInByte);
- SyncBootScript ();
+ SyncBootScript (Script);
return RETURN_SUCCESS;
}
@@ -1612,10 +2095,16 @@ S3BootScriptMoveLastOpcode (
ValidatePosition = FALSE;
TempPosition = (Position == NULL) ? NULL:(*Position);
- Script = mS3BootScriptTablePtr->TableBase;
- if (Script == 0) {
- return EFI_OUT_OF_RESOURCES;
+
+ //
+ // Check that the script is initialized and synced without adding an entry to the script.
+ //
+ Script = S3BootScriptGetEntryAddAddress (0);
+ if (Script == NULL) {
+ return RETURN_OUT_OF_RESOURCES;
}
+ Script = mS3BootScriptTablePtr->TableBase;
+
StartAddress = (UINTN) Script;
TableLength = mS3BootScriptTablePtr->TableLength;
Script = Script + sizeof(EFI_BOOT_SCRIPT_TABLE_HEADER);
@@ -1658,7 +2147,10 @@ S3BootScriptMoveLastOpcode (
//
// Copy the node to Boot script table
//
- CopyMem((VOID*)Script, (VOID*)TempBootScriptEntry, ScriptHeader.Length);
+ CopyMem((VOID*)Script, (VOID*)TempBootScriptEntry, ScriptHeader.Length);
+
+ SyncBootScript (Script);
+
//
// return out the Position
//
@@ -1716,6 +2208,8 @@ S3BootScriptLabelInternal (
CopyMem ((VOID*)Script, (VOID*)&ScriptInformation, sizeof (EFI_BOOT_SCRIPT_INFORMATION));
CopyMem ((VOID*)(Script + sizeof (EFI_BOOT_SCRIPT_INFORMATION)), (VOID *) Information, (UINTN) InformationLength);
+ SyncBootScript (Script);
+
return S3BootScriptMoveLastOpcode (BeforeOrAfter, Position);
}
@@ -1770,8 +2264,8 @@ S3BootScriptLabel (
}
//
- // Check that the script is initialized without adding an entry to the script.
- // The code must search for the label first befor it knows if a new entry needs
+ // Check that the script is initialized and synced without adding an entry to the script.
+ // The code must search for the label first before it knows if a new entry needs
// to be added.
//
Script = S3BootScriptGetEntryAddAddress (0);
@@ -1834,13 +2328,19 @@ S3BootScriptCompare (
UINT8* Script;
UINT32 TableLength;
- Script = mS3BootScriptTablePtr->TableBase;
- if (Script == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
if (RelativePosition == NULL) {
return EFI_INVALID_PARAMETER;
}
+
+ //
+ // Check that the script is initialized and synced without adding an entry to the script.
+ //
+ Script = S3BootScriptGetEntryAddAddress (0);
+ if (Script == NULL) {
+ return RETURN_OUT_OF_RESOURCES;
+ }
+ Script = mS3BootScriptTablePtr->TableBase;
+
//
// mS3BootScriptTablePtr->TableLength does not include the termination node, so add it up
//