#include <Protocol/SmmFirmwareVolumeBlock.h>\r
#include <Protocol/SmmFaultTolerantWrite.h>\r
#include <Protocol/SmmAccess2.h>\r
+#include <Protocol/SmmEndOfDxe.h>\r
\r
#include <Library/SmmServicesTableLib.h>\r
\r
EFI_GUID mZeroGuid = {0, 0, 0, {0, 0, 0, 0, 0, 0, 0, 0}};\r
UINT8 *mVariableBufferPayload = NULL;\r
UINTN mVariableBufferPayloadSize;\r
+extern BOOLEAN mEndOfDxe;\r
+extern BOOLEAN mEnableLocking;\r
+\r
+/**\r
+\r
+ This code sets variable in storage blocks (Volatile or Non-Volatile).\r
+\r
+ @param VariableName Name of Variable to be found.\r
+ @param VendorGuid Variable vendor GUID.\r
+ @param Attributes Attribute value of the variable found\r
+ @param DataSize Size of Data found. If size is less than the\r
+ data, this value contains the required size.\r
+ @param Data Data pointer.\r
+\r
+ @return EFI_INVALID_PARAMETER Invalid parameter.\r
+ @return EFI_SUCCESS Set successfully.\r
+ @return EFI_OUT_OF_RESOURCES Resource not enough to set variable.\r
+ @return EFI_NOT_FOUND Not found.\r
+ @return EFI_WRITE_PROTECTED Variable is read-only.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+SmmVariableSetVariable (\r
+ IN CHAR16 *VariableName,\r
+ IN EFI_GUID *VendorGuid,\r
+ IN UINT32 Attributes,\r
+ IN UINTN DataSize,\r
+ IN VOID *Data\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+\r
+ //\r
+ // Disable write protection when the calling SetVariable() through EFI_SMM_VARIABLE_PROTOCOL.\r
+ //\r
+ mEnableLocking = FALSE;\r
+ Status = VariableServiceSetVariable (\r
+ VariableName,\r
+ VendorGuid,\r
+ Attributes,\r
+ DataSize,\r
+ Data\r
+ );\r
+ mEnableLocking = TRUE;\r
+ return Status;\r
+}\r
\r
EFI_SMM_VARIABLE_PROTOCOL gSmmVariable = {\r
VariableServiceGetVariable,\r
VariableServiceGetNextVariableName,\r
- VariableServiceSetVariable,\r
+ SmmVariableSetVariable,\r
VariableServiceQueryVariableInfo\r
};\r
\r
-\r
/**\r
Return TRUE if ExitBootServices () has been called.\r
\r
SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME *GetNextVariableName;\r
SMM_VARIABLE_COMMUNICATE_QUERY_VARIABLE_INFO *QueryVariableInfo;\r
VARIABLE_INFO_ENTRY *VariableInfo;\r
+ SMM_VARIABLE_COMMUNICATE_LOCK_VARIABLE *VariableToLock;\r
UINTN InfoSize;\r
UINTN NameBufferSize;\r
UINTN CommBufferPayloadSize;\r
+ UINTN TempCommBufferSize;\r
\r
//\r
// If input is invalid, stop processing this SMI\r
return EFI_SUCCESS;\r
}\r
\r
- if (*CommBufferSize < SMM_VARIABLE_COMMUNICATE_HEADER_SIZE) {\r
+ TempCommBufferSize = *CommBufferSize;\r
+\r
+ if (TempCommBufferSize < SMM_VARIABLE_COMMUNICATE_HEADER_SIZE) {\r
DEBUG ((EFI_D_ERROR, "SmmVariableHandler: SMM communication buffer size invalid!\n"));\r
return EFI_SUCCESS;\r
}\r
- CommBufferPayloadSize = *CommBufferSize - SMM_VARIABLE_COMMUNICATE_HEADER_SIZE;\r
+ CommBufferPayloadSize = TempCommBufferSize - SMM_VARIABLE_COMMUNICATE_HEADER_SIZE;\r
if (CommBufferPayloadSize > mVariableBufferPayloadSize) {\r
DEBUG ((EFI_D_ERROR, "SmmVariableHandler: SMM communication buffer payload size invalid!\n"));\r
return EFI_SUCCESS;\r
}\r
\r
- if (!InternalIsAddressValid ((UINTN)CommBuffer, *CommBufferSize)) {\r
+ if (!InternalIsAddressValid ((UINTN)CommBuffer, TempCommBufferSize)) {\r
DEBUG ((EFI_D_ERROR, "SmmVariableHandler: SMM communication buffer in SMRAM or overflow!\n"));\r
return EFI_SUCCESS;\r
}\r
break;\r
\r
case SMM_VARIABLE_FUNCTION_READY_TO_BOOT:\r
+ mEndOfDxe = TRUE;\r
if (AtRuntime()) {\r
Status = EFI_UNSUPPORTED;\r
break;\r
\r
case SMM_VARIABLE_FUNCTION_GET_STATISTICS:\r
VariableInfo = (VARIABLE_INFO_ENTRY *) SmmVariableFunctionHeader->Data;\r
- InfoSize = *CommBufferSize - SMM_VARIABLE_COMMUNICATE_HEADER_SIZE;\r
+ InfoSize = TempCommBufferSize - SMM_VARIABLE_COMMUNICATE_HEADER_SIZE;\r
\r
//\r
// Do not need to check SmmVariableFunctionHeader->Data in SMRAM here. \r
*CommBufferSize = InfoSize + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE;\r
break;\r
\r
+ case SMM_VARIABLE_FUNCTION_LOCK_VARIABLE:\r
+ if (mEndOfDxe) {\r
+ Status = EFI_ACCESS_DENIED;\r
+ } else {\r
+ VariableToLock = (SMM_VARIABLE_COMMUNICATE_LOCK_VARIABLE *) SmmVariableFunctionHeader->Data;\r
+ Status = VariableLockRequestToLock (\r
+ NULL,\r
+ VariableToLock->Name,\r
+ &VariableToLock->Guid\r
+ );\r
+ }\r
+ break;\r
+\r
default:\r
Status = EFI_UNSUPPORTED;\r
}\r
return EFI_SUCCESS;\r
}\r
\r
+/**\r
+ SMM END_OF_DXE protocol notification event handler.\r
+\r
+ @param Protocol Points to the protocol's unique identifier\r
+ @param Interface Points to the interface instance\r
+ @param Handle The handle on which the interface was installed\r
+\r
+ @retval EFI_SUCCESS SmmEndOfDxeCallback runs successfully\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+SmmEndOfDxeCallback (\r
+ IN CONST EFI_GUID *Protocol,\r
+ IN VOID *Interface,\r
+ IN EFI_HANDLE Handle\r
+ )\r
+{\r
+ DEBUG ((EFI_D_INFO, "[Variable]END_OF_DXE is signaled\n"));\r
+ mEndOfDxe = TRUE;\r
+ return EFI_SUCCESS;\r
+}\r
\r
/**\r
SMM Fault Tolerant Write protocol notification event handler.\r
EFI_SMM_FIRMWARE_VOLUME_BLOCK_PROTOCOL *FvbProtocol;\r
EFI_SMM_FAULT_TOLERANT_WRITE_PROTOCOL *FtwProtocol;\r
EFI_PHYSICAL_ADDRESS NvStorageVariableBase;\r
+ UINTN FtwMaxBlockSize;\r
\r
if (mVariableModuleGlobal->FvbInstance != NULL) {\r
return EFI_SUCCESS;\r
return Status;\r
}\r
\r
+ Status = FtwProtocol->GetMaxBlockSize (FtwProtocol, &FtwMaxBlockSize);\r
+ if (!EFI_ERROR (Status)) {\r
+ ASSERT (PcdGet32 (PcdFlashNvStorageVariableSize) <= FtwMaxBlockSize);\r
+ }\r
+\r
//\r
// Find the proper FVB protocol for variable.\r
//\r
VOID *SmmFtwRegistration;\r
EFI_SMM_ACCESS2_PROTOCOL *SmmAccess;\r
UINTN Size;\r
+ VOID *SmmEndOfDxeRegistration;\r
\r
//\r
// Variable initialize.\r
);\r
ASSERT_EFI_ERROR (Status);\r
\r
+ //\r
+ // Register EFI_SMM_END_OF_DXE_PROTOCOL_GUID notify function.\r
+ //\r
+ Status = gSmst->SmmRegisterProtocolNotify (\r
+ &gEfiSmmEndOfDxeProtocolGuid,\r
+ SmmEndOfDxeCallback,\r
+ &SmmEndOfDxeRegistration\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
//\r
// Register FtwNotificationEvent () notify function.\r
// \r