X-Git-Url: https://git.proxmox.com/?a=blobdiff_plain;f=MdeModulePkg%2FUniversal%2FVariable%2FRuntimeDxe%2FVariableSmm.c;h=3e35219d053ab05cd01e307ac5428d1be87f8c7c;hb=7cd69959463ac9c761163ed8e8a93907b68e70da;hp=fb16af31b1a999863077ebe81dd527e124336124;hpb=8021f4c716cfd9fae0ac6d4a0a9bee2dbcf13d29;p=mirror_edk2.git diff --git a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.c b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.c index fb16af31b1..3e35219d05 100644 --- a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.c +++ b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.c @@ -14,7 +14,8 @@ VariableServiceSetVariable(), VariableServiceQueryVariableInfo(), ReclaimForOS(), SmmVariableGetStatistics() should also do validation based on its own knowledge. -Copyright (c) 2010 - 2015, Intel Corporation. All rights reserved.
+Copyright (c) 2010 - 2019, Intel Corporation. All rights reserved.
+Copyright (c) 2018, Linaro, Ltd. All rights reserved.
This program and the accompanying materials are licensed and made available under the terms and conditions of the BSD License which accompanies this distribution. The full text of the license may be found at @@ -28,24 +29,17 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. #include #include #include -#include +#include #include -#include -#include +#include #include -#include #include "Variable.h" -extern VARIABLE_INFO_ENTRY *gVariableInfo; -EFI_HANDLE mSmmVariableHandle = NULL; -EFI_HANDLE mVariableHandle = NULL; BOOLEAN mAtRuntime = FALSE; UINT8 *mVariableBufferPayload = NULL; UINTN mVariableBufferPayloadSize; -extern BOOLEAN mEndOfDxe; -extern VAR_CHECK_REQUEST_SOURCE mRequestSource; /** SecureBoot Hook for SetVariable. @@ -200,7 +194,7 @@ ReleaseLockOnlyAtBootTime ( } /** - Retrive the SMM Fault Tolerent Write protocol interface. + Retrieve the SMM Fault Tolerent Write protocol interface. @param[out] FtwProtocol The interface of SMM Ftw protocol @@ -219,7 +213,7 @@ GetFtwProtocol ( // // Locate Smm Fault Tolerent Write protocol // - Status = gSmst->SmmLocateProtocol ( + Status = gMmst->MmLocateProtocol ( &gEfiSmmFaultTolerantWriteProtocolGuid, NULL, FtwProtocol @@ -229,7 +223,7 @@ GetFtwProtocol ( /** - Retrive the SMM FVB protocol interface by HANDLE. + Retrieve the SMM FVB protocol interface by HANDLE. @param[in] FvBlockHandle The handle of SMM FVB protocol that provides services for reading, writing, and erasing the target block. @@ -249,7 +243,7 @@ GetFvbByHandle ( // // To get the SMM FVB protocol interface on the handle // - return gSmst->SmmHandleProtocol ( + return gMmst->MmHandleProtocol ( FvBlockHandle, &gEfiSmmFirmwareVolumeBlockProtocolGuid, (VOID **) FvBlock @@ -288,7 +282,7 @@ GetFvbCountAndBuffer ( BufferSize = 0; *NumberHandles = 0; *Buffer = NULL; - Status = gSmst->SmmLocateHandle ( + Status = gMmst->MmLocateHandle ( ByProtocol, &gEfiSmmFirmwareVolumeBlockProtocolGuid, NULL, @@ -304,7 +298,7 @@ GetFvbCountAndBuffer ( return EFI_OUT_OF_RESOURCES; } - Status = gSmst->SmmLocateHandle ( + Status = gMmst->MmLocateHandle ( ByProtocol, &gEfiSmmFirmwareVolumeBlockProtocolGuid, NULL, @@ -350,9 +344,10 @@ SmmVariableGetStatistics ( ) { VARIABLE_INFO_ENTRY *VariableInfo; - UINTN NameLength; + UINTN NameSize; UINTN StatisticsInfoSize; CHAR16 *InfoName; + UINTN InfoNameMaxSize; EFI_GUID VendorGuid; if (InfoEntry == NULL) { @@ -364,21 +359,28 @@ SmmVariableGetStatistics ( return EFI_UNSUPPORTED; } - StatisticsInfoSize = sizeof (VARIABLE_INFO_ENTRY) + StrSize (VariableInfo->Name); + StatisticsInfoSize = sizeof (VARIABLE_INFO_ENTRY); if (*InfoSize < StatisticsInfoSize) { *InfoSize = StatisticsInfoSize; return EFI_BUFFER_TOO_SMALL; } InfoName = (CHAR16 *)(InfoEntry + 1); + InfoNameMaxSize = (*InfoSize - sizeof (VARIABLE_INFO_ENTRY)); CopyGuid (&VendorGuid, &InfoEntry->VendorGuid); - if (CompareGuid (&VendorGuid, &gZeroGuid)) { + if (IsZeroGuid (&VendorGuid)) { // // Return the first variable info // + NameSize = StrSize (VariableInfo->Name); + StatisticsInfoSize = sizeof (VARIABLE_INFO_ENTRY) + NameSize; + if (*InfoSize < StatisticsInfoSize) { + *InfoSize = StatisticsInfoSize; + return EFI_BUFFER_TOO_SMALL; + } CopyMem (InfoEntry, VariableInfo, sizeof (VARIABLE_INFO_ENTRY)); - CopyMem (InfoName, VariableInfo->Name, StrSize (VariableInfo->Name)); + CopyMem (InfoName, VariableInfo->Name, NameSize); *InfoSize = StatisticsInfoSize; return EFI_SUCCESS; } @@ -388,9 +390,9 @@ SmmVariableGetStatistics ( // while (VariableInfo != NULL) { if (CompareGuid (&VariableInfo->VendorGuid, &VendorGuid)) { - NameLength = StrSize (VariableInfo->Name); - if (NameLength == StrSize (InfoName)) { - if (CompareMem (VariableInfo->Name, InfoName, NameLength) == 0) { + NameSize = StrSize (VariableInfo->Name); + if (NameSize <= InfoNameMaxSize) { + if (CompareMem (VariableInfo->Name, InfoName, NameSize) == 0) { // // Find the match one // @@ -410,14 +412,15 @@ SmmVariableGetStatistics ( // // Output the new variable info // - StatisticsInfoSize = sizeof (VARIABLE_INFO_ENTRY) + StrSize (VariableInfo->Name); + NameSize = StrSize (VariableInfo->Name); + StatisticsInfoSize = sizeof (VARIABLE_INFO_ENTRY) + NameSize; if (*InfoSize < StatisticsInfoSize) { *InfoSize = StatisticsInfoSize; return EFI_BUFFER_TOO_SMALL; } CopyMem (InfoEntry, VariableInfo, sizeof (VARIABLE_INFO_ENTRY)); - CopyMem (InfoName, VariableInfo->Name, StrSize (VariableInfo->Name)); + CopyMem (InfoName, VariableInfo->Name, NameSize); *InfoSize = StatisticsInfoSize; return EFI_SUCCESS; @@ -492,7 +495,7 @@ SmmVariableHandler ( return EFI_SUCCESS; } - if (!SmmIsBufferOutsideSmmValid ((UINTN)CommBuffer, TempCommBufferSize)) { + if (!VariableSmmIsBufferOutsideSmmValid ((UINTN)CommBuffer, TempCommBufferSize)) { DEBUG ((EFI_D_ERROR, "SmmVariableHandler: SMM communication buffer in SMRAM or overflow!\n")); return EFI_SUCCESS; } @@ -529,6 +532,12 @@ SmmVariableHandler ( goto EXIT; } + // + // The VariableSpeculationBarrier() call here is to ensure the previous + // range/content checks for the CommBuffer have been completed before the + // subsequent consumption of the CommBuffer content. + // + VariableSpeculationBarrier (); if (SmmVariableHeader->NameSize < sizeof (CHAR16) || SmmVariableHeader->Name[SmmVariableHeader->NameSize/sizeof (CHAR16) - 1] != L'\0') { // // Make sure VariableName is A Null-terminated string. @@ -623,6 +632,12 @@ SmmVariableHandler ( goto EXIT; } + // + // The VariableSpeculationBarrier() call here is to ensure the previous + // range/content checks for the CommBuffer have been completed before the + // subsequent consumption of the CommBuffer content. + // + VariableSpeculationBarrier (); if (SmmVariableHeader->NameSize < sizeof (CHAR16) || SmmVariableHeader->Name[SmmVariableHeader->NameSize/sizeof (CHAR16) - 1] != L'\0') { // // Make sure VariableName is A Null-terminated string. @@ -671,6 +686,7 @@ SmmVariableHandler ( break; } if (!mEndOfDxe) { + MorLockInitAtEndOfDxe (); mEndOfDxe = TRUE; VarCheckLibInitializeAtEndOfDxe (NULL); // @@ -696,11 +712,10 @@ SmmVariableHandler ( // It is covered by previous CommBuffer check // - if (!SmmIsBufferOutsideSmmValid ((EFI_PHYSICAL_ADDRESS)(UINTN)CommBufferSize, sizeof(UINTN))) { - DEBUG ((EFI_D_ERROR, "GetStatistics: SMM communication buffer in SMRAM!\n")); - Status = EFI_ACCESS_DENIED; - goto EXIT; - } + // + // Do not need to check CommBufferSize buffer as it should point to SMRAM + // that was used by SMM core to cache CommSize from SmmCommunication protocol. + // Status = SmmVariableGetStatistics (VariableInfo, &InfoSize); *CommBufferSize = InfoSize + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE; @@ -758,6 +773,12 @@ SmmVariableHandler ( goto EXIT; } + // + // The VariableSpeculationBarrier() call here is to ensure the previous + // range/content checks for the CommBuffer have been completed before the + // subsequent consumption of the CommBuffer content. + // + VariableSpeculationBarrier (); if (CommVariableProperty->NameSize < sizeof (CHAR16) || CommVariableProperty->Name[CommVariableProperty->NameSize/sizeof (CHAR16) - 1] != L'\0') { // // Make sure VariableName is A Null-terminated string. @@ -804,6 +825,7 @@ SmmEndOfDxeCallback ( ) { DEBUG ((EFI_D_INFO, "[Variable]SMM_END_OF_DXE is signaled\n")); + MorLockInitAtEndOfDxe (); mEndOfDxe = TRUE; VarCheckLibInitializeAtEndOfDxe (NULL); // @@ -817,6 +839,28 @@ SmmEndOfDxeCallback ( return EFI_SUCCESS; } +/** + Initializes variable write service for SMM. + +**/ +VOID +VariableWriteServiceInitializeSmm ( + VOID + ) +{ + EFI_STATUS Status; + + Status = VariableWriteServiceInitialize (); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "Variable write service initialization failed. Status = %r\n", Status)); + } + + // + // Notify the variable wrapper driver the variable write service is ready + // + VariableNotifySmmWriteReady (); +} + /** SMM Fault Tolerant Write protocol notification event handler. @@ -840,6 +884,7 @@ SmmFtwNotificationEvent ( ) { EFI_STATUS Status; + EFI_PHYSICAL_ADDRESS VariableStoreBase; EFI_SMM_FIRMWARE_VOLUME_BLOCK_PROTOCOL *FvbProtocol; EFI_SMM_FAULT_TOLERANT_WRITE_PROTOCOL *FtwProtocol; EFI_PHYSICAL_ADDRESS NvStorageVariableBase; @@ -862,13 +907,17 @@ SmmFtwNotificationEvent ( ASSERT (PcdGet32 (PcdFlashNvStorageVariableSize) <= FtwMaxBlockSize); } + NvStorageVariableBase = NV_STORAGE_VARIABLE_BASE; + VariableStoreBase = NvStorageVariableBase + mNvFvHeaderCache->HeaderLength; + + // + // Let NonVolatileVariableBase point to flash variable store base directly after FTW ready. + // + mVariableModuleGlobal->VariableGlobal.NonVolatileVariableBase = VariableStoreBase; + // // Find the proper FVB protocol for variable. // - NvStorageVariableBase = (EFI_PHYSICAL_ADDRESS) PcdGet64 (PcdFlashNvStorageVariableBase64); - if (NvStorageVariableBase == 0) { - NvStorageVariableBase = (EFI_PHYSICAL_ADDRESS) PcdGet32 (PcdFlashNvStorageVariableBase); - } Status = GetFvbInfoByAddress (NvStorageVariableBase, NULL, &FvbProtocol); if (EFI_ERROR (Status)) { return EFI_NOT_FOUND; @@ -876,21 +925,10 @@ SmmFtwNotificationEvent ( mVariableModuleGlobal->FvbInstance = FvbProtocol; - Status = VariableWriteServiceInitialize (); - if (EFI_ERROR (Status)) { - DEBUG ((DEBUG_ERROR, "Variable write service initialization failed. Status = %r\n", Status)); - } - // - // Notify the variable wrapper driver the variable write service is ready + // Initializes variable write service after FTW was ready. // - Status = gBS->InstallProtocolInterface ( - &mSmmVariableHandle, - &gSmmVariableWriteGuid, - EFI_NATIVE_INTERFACE, - NULL - ); - ASSERT_EFI_ERROR (Status); + VariableWriteServiceInitializeSmm (); return EFI_SUCCESS; } @@ -902,17 +940,13 @@ SmmFtwNotificationEvent ( for variable read and write services being available. It also registers a notification function for an EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE event. - @param[in] ImageHandle The firmware allocated handle for the EFI image. - @param[in] SystemTable A pointer to the EFI System Table. - @retval EFI_SUCCESS Variable service successfully initialized. **/ EFI_STATUS EFIAPI -VariableServiceInitialize ( - IN EFI_HANDLE ImageHandle, - IN EFI_SYSTEM_TABLE *SystemTable +MmVariableServiceInitialize ( + VOID ) { EFI_STATUS Status; @@ -930,7 +964,7 @@ VariableServiceInitialize ( // Install the Smm Variable Protocol on a new handle. // VariableHandle = NULL; - Status = gSmst->SmmInstallProtocolInterface ( + Status = gMmst->MmInstallProtocolInterface ( &VariableHandle, &gEfiSmmVariableProtocolGuid, EFI_NATIVE_INTERFACE, @@ -938,7 +972,7 @@ VariableServiceInitialize ( ); ASSERT_EFI_ERROR (Status); - Status = gSmst->SmmInstallProtocolInterface ( + Status = gMmst->MmInstallProtocolInterface ( &VariableHandle, &gEdkiiSmmVarCheckProtocolGuid, EFI_NATIVE_INTERFACE, @@ -946,10 +980,10 @@ VariableServiceInitialize ( ); ASSERT_EFI_ERROR (Status); - mVariableBufferPayloadSize = GetNonVolatileMaxVariableSize () + + mVariableBufferPayloadSize = GetMaxVariableSize () + OFFSET_OF (SMM_VARIABLE_COMMUNICATE_VAR_CHECK_VARIABLE_PROPERTY, Name) - GetVariableHeaderSize (); - Status = gSmst->SmmAllocatePool ( + Status = gMmst->MmAllocatePool ( EfiRuntimeServicesData, mVariableBufferPayloadSize, (VOID **)&mVariableBufferPayload @@ -960,41 +994,42 @@ VariableServiceInitialize ( /// Register SMM variable SMI handler /// VariableHandle = NULL; - Status = gSmst->SmiHandlerRegister (SmmVariableHandler, &gEfiSmmVariableProtocolGuid, &VariableHandle); + Status = gMmst->MmiHandlerRegister (SmmVariableHandler, &gEfiSmmVariableProtocolGuid, &VariableHandle); ASSERT_EFI_ERROR (Status); // // Notify the variable wrapper driver the variable service is ready // - Status = SystemTable->BootServices->InstallProtocolInterface ( - &mVariableHandle, - &gEfiSmmVariableProtocolGuid, - EFI_NATIVE_INTERFACE, - &gSmmVariable - ); - ASSERT_EFI_ERROR (Status); + VariableNotifySmmReady (); // // Register EFI_SMM_END_OF_DXE_PROTOCOL_GUID notify function. // - Status = gSmst->SmmRegisterProtocolNotify ( - &gEfiSmmEndOfDxeProtocolGuid, + Status = gMmst->MmRegisterProtocolNotify ( + &gEfiMmEndOfDxeProtocolGuid, SmmEndOfDxeCallback, &SmmEndOfDxeRegistration ); ASSERT_EFI_ERROR (Status); - // - // Register FtwNotificationEvent () notify function. - // - Status = gSmst->SmmRegisterProtocolNotify ( - &gEfiSmmFaultTolerantWriteProtocolGuid, - SmmFtwNotificationEvent, - &SmmFtwRegistration - ); - ASSERT_EFI_ERROR (Status); - - SmmFtwNotificationEvent (NULL, NULL, NULL); + if (!PcdGetBool (PcdEmuVariableNvModeEnable)) { + // + // Register FtwNotificationEvent () notify function. + // + Status = gMmst->MmRegisterProtocolNotify ( + &gEfiSmmFaultTolerantWriteProtocolGuid, + SmmFtwNotificationEvent, + &SmmFtwRegistration + ); + ASSERT_EFI_ERROR (Status); + + SmmFtwNotificationEvent (NULL, NULL, NULL); + } else { + // + // Emulated non-volatile variable mode does not depend on FVB and FTW. + // + VariableWriteServiceInitializeSmm (); + } return EFI_SUCCESS; }