#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
break;\r
\r
case SMM_VARIABLE_FUNCTION_READY_TO_BOOT:\r
+ mEndOfDxe = TRUE;\r
if (AtRuntime()) {\r
Status = EFI_UNSUPPORTED;\r
break;\r
*CommBufferSize = InfoSize + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE;\r
break;\r
\r
+ case SMM_VARIABLE_FUNCTION_LOCK_VARIABLE:\r
+ if (CommBufferPayloadSize < OFFSET_OF(SMM_VARIABLE_COMMUNICATE_LOCK_VARIABLE, Name)) {\r
+ DEBUG ((EFI_D_ERROR, "RequestToLock: SMM communication buffer size invalid!\n"));\r
+ return EFI_SUCCESS;\r
+ }\r
+ //\r
+ // Copy the input communicate buffer payload to pre-allocated SMM variable buffer payload.\r
+ //\r
+ CopyMem (mVariableBufferPayload, SmmVariableFunctionHeader->Data, CommBufferPayloadSize);\r
+ VariableToLock = (SMM_VARIABLE_COMMUNICATE_LOCK_VARIABLE *) mVariableBufferPayload;\r
+\r
+ if (VariableToLock->NameSize > MAX_ADDRESS - OFFSET_OF (SMM_VARIABLE_COMMUNICATE_LOCK_VARIABLE, Name)) {\r
+ //\r
+ // Prevent InfoSize overflow happen\r
+ //\r
+ Status = EFI_ACCESS_DENIED;\r
+ goto EXIT;\r
+ }\r
+\r
+ if (VariableToLock->NameSize < sizeof (CHAR16) || VariableToLock->Name[VariableToLock->NameSize/sizeof (CHAR16) - 1] != L'\0') {\r
+ //\r
+ // Make sure VariableName is A Null-terminated string.\r
+ //\r
+ Status = EFI_ACCESS_DENIED;\r
+ goto EXIT;\r
+ }\r
+ \r
+ InfoSize = OFFSET_OF (SMM_VARIABLE_COMMUNICATE_LOCK_VARIABLE, Name) + VariableToLock->NameSize;\r
+ \r
+ //\r
+ // SMRAM range check already covered before\r
+ //\r
+ if (InfoSize > CommBufferPayloadSize) {\r
+ DEBUG ((EFI_D_ERROR, "Data size exceed communication buffer size limit!\n"));\r
+ Status = EFI_ACCESS_DENIED;\r
+ goto EXIT;\r
+ }\r
+\r
+ Status = VariableLockRequestToLock (\r
+ NULL,\r
+ VariableToLock->Name,\r
+ &VariableToLock->Guid\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
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