This module initilizes MemoryOverwriteRequestControlLock variable.\r
This module adds Variable Hook and check MemoryOverwriteRequestControlLock.\r
\r
-Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>\r
-This program and the accompanying materials\r
-are licensed and made available under the terms and conditions of the BSD License\r
-which accompanies this distribution. The full text of the license may be found at\r
-http://opensource.org/licenses/bsd-license.php\r
-\r
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<BR>\r
+SPDX-License-Identifier: BSD-2-Clause-Patent\r
\r
**/\r
\r
{MEMORY_OVERWRITE_REQUEST_CONTROL_LOCK_NAME, &gEfiMemoryOverwriteRequestControlLockGuid},\r
};\r
\r
+BOOLEAN mMorPassThru = FALSE;\r
+\r
#define MOR_LOCK_DATA_UNLOCKED 0x0\r
#define MOR_LOCK_DATA_LOCKED_WITHOUT_KEY 0x1\r
#define MOR_LOCK_DATA_LOCKED_WITH_KEY 0x2\r
MorLockStateLocked = 1,\r
} MOR_LOCK_STATE;\r
\r
+BOOLEAN mMorLockInitializationRequired = FALSE;\r
UINT8 mMorLockKey[MOR_LOCK_V2_KEY_SIZE];\r
BOOLEAN mMorLockKeyEmpty = TRUE;\r
BOOLEAN mMorLockPassThru = FALSE;\r
@retval EFI_DEVICE_ERROR The variable could not be saved due to a hardware failure.\r
@retval EFI_WRITE_PROTECTED The variable in question is read-only.\r
@retval EFI_WRITE_PROTECTED The variable in question cannot be deleted.\r
- @retval EFI_SECURITY_VIOLATION The variable could not be written due to EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS\r
+ @retval EFI_SECURITY_VIOLATION The variable could not be written due to EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS\r
set but the AuthInfo does NOT pass the validation check carried\r
out by the firmware.\r
@retval EFI_NOT_FOUND The variable trying to be updated or deleted was not found.\r
// Basic Check\r
//\r
if (Attributes == 0 || DataSize == 0 || Data == NULL) {\r
- return EFI_WRITE_PROTECTED;\r
+ //\r
+ // Permit deletion for passthru request, deny it otherwise.\r
+ //\r
+ return mMorLockPassThru ? EFI_SUCCESS : EFI_WRITE_PROTECTED;\r
}\r
\r
if ((Attributes != (EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS)) ||\r
//\r
if (DataSize == MOR_LOCK_V1_SIZE) {\r
//\r
- // V1 - lock permenantly\r
+ // V1 - lock permanently\r
//\r
if (*(UINT8 *)Data == MOR_LOCK_DATA_UNLOCKED) {\r
//\r
/**\r
This service is an MOR/MorLock checker handler for the SetVariable().\r
\r
- @param VariableName the name of the vendor's variable, as a\r
- Null-Terminated Unicode String\r
- @param VendorGuid Unify identifier for vendor.\r
- @param Attributes Point to memory location to return the attributes of variable. If the point\r
- is NULL, the parameter would be ignored.\r
- @param DataSize The size in bytes of Data-Buffer.\r
- @param Data Point to the content of the variable.\r
-\r
- @retval EFI_SUCCESS The MOR/MorLock check pass, and Variable driver can store the variable data.\r
- @retval EFI_INVALID_PARAMETER The MOR/MorLock data or data size or attributes is not allowed for MOR variable.\r
+ @param[in] VariableName the name of the vendor's variable, as a\r
+ Null-Terminated Unicode String\r
+ @param[in] VendorGuid Unify identifier for vendor.\r
+ @param[in] Attributes Attributes bitmask to set for the variable.\r
+ @param[in] DataSize The size in bytes of Data-Buffer.\r
+ @param[in] Data Point to the content of the variable.\r
+\r
+ @retval EFI_SUCCESS The MOR/MorLock check pass, and Variable\r
+ driver can store the variable data.\r
+ @retval EFI_INVALID_PARAMETER The MOR/MorLock data or data size or\r
+ attributes is not allowed for MOR variable.\r
@retval EFI_ACCESS_DENIED The MOR/MorLock is locked.\r
- @retval EFI_ALREADY_STARTED The MorLock variable is handled inside this function.\r
- Variable driver can just return EFI_SUCCESS.\r
+ @retval EFI_ALREADY_STARTED The MorLock variable is handled inside this\r
+ function. Variable driver can just return\r
+ EFI_SUCCESS.\r
**/\r
EFI_STATUS\r
SetVariableCheckHandlerMor (\r
// Mor Variable\r
//\r
\r
+ //\r
+ // Permit deletion for passthru request.\r
+ //\r
+ if (((Attributes == 0) || (DataSize == 0)) && mMorPassThru) {\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
//\r
// Basic Check\r
//\r
}\r
\r
/**\r
- Initialization for MOR Lock Control.\r
+ Initialization for MOR Control Lock.\r
\r
- @retval EFI_SUCEESS MorLock initialization success.\r
+ @retval EFI_SUCCESS MorLock initialization success.\r
@return Others Some error occurs.\r
**/\r
EFI_STATUS\r
VOID\r
)\r
{\r
+ mMorLockInitializationRequired = TRUE;\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Delayed initialization for MOR Control Lock at EndOfDxe.\r
+\r
+ This function performs any operations queued by MorLockInit().\r
+**/\r
+VOID\r
+MorLockInitAtEndOfDxe (\r
+ VOID\r
+ )\r
+{\r
+ UINTN MorSize;\r
+ EFI_STATUS MorStatus;\r
+\r
+ if (!mMorLockInitializationRequired) {\r
+ //\r
+ // The EFI_SMM_FAULT_TOLERANT_WRITE_PROTOCOL has never been installed, thus\r
+ // the variable write service is unavailable. This should never happen.\r
+ //\r
+ ASSERT (FALSE);\r
+ return;\r
+ }\r
+\r
+ //\r
+ // Check if the MOR variable exists.\r
+ //\r
+ MorSize = 0;\r
+ MorStatus = VariableServiceGetVariable (\r
+ MEMORY_OVERWRITE_REQUEST_VARIABLE_NAME,\r
+ &gEfiMemoryOverwriteControlDataGuid,\r
+ NULL, // Attributes\r
+ &MorSize,\r
+ NULL // Data\r
+ );\r
//\r
- // Set variable to report capability to OS\r
+ // We provided a zero-sized buffer, so the above call can never succeed.\r
//\r
- return SetMorLockVariable (0);\r
+ ASSERT (EFI_ERROR (MorStatus));\r
+\r
+ if (MorStatus == EFI_BUFFER_TOO_SMALL) {\r
+ //\r
+ // The MOR variable exists.\r
+ //\r
+ // Some OSes don't follow the TCG's Platform Reset Attack Mitigation spec\r
+ // in that the OS should never create the MOR variable, only read and write\r
+ // it -- these OSes (unintentionally) create MOR if the platform firmware\r
+ // does not produce it. Whether this is the case (from the last OS boot)\r
+ // can be deduced from the absence of the TCG / TCG2 protocols, as edk2's\r
+ // MOR implementation depends on (one of) those protocols.\r
+ //\r
+ if (VariableHaveTcgProtocols ()) {\r
+ //\r
+ // The MOR variable originates from the platform firmware; set the MOR\r
+ // Control Lock variable to report the locking capability to the OS.\r
+ //\r
+ SetMorLockVariable (0);\r
+ return;\r
+ }\r
+\r
+ //\r
+ // The MOR variable's origin is inexplicable; delete it.\r
+ //\r
+ DEBUG ((\r
+ DEBUG_WARN,\r
+ "%a: deleting unexpected / unsupported variable %g:%s\n",\r
+ __FUNCTION__,\r
+ &gEfiMemoryOverwriteControlDataGuid,\r
+ MEMORY_OVERWRITE_REQUEST_VARIABLE_NAME\r
+ ));\r
+\r
+ mMorPassThru = TRUE;\r
+ VariableServiceSetVariable (\r
+ MEMORY_OVERWRITE_REQUEST_VARIABLE_NAME,\r
+ &gEfiMemoryOverwriteControlDataGuid,\r
+ 0, // Attributes\r
+ 0, // DataSize\r
+ NULL // Data\r
+ );\r
+ mMorPassThru = FALSE;\r
+ }\r
+\r
+ //\r
+ // The MOR variable is absent; the platform firmware does not support it.\r
+ // Lock the variable so that no other module may create it.\r
+ //\r
+ VariableLockRequestToLock (\r
+ NULL, // This\r
+ MEMORY_OVERWRITE_REQUEST_VARIABLE_NAME,\r
+ &gEfiMemoryOverwriteControlDataGuid\r
+ );\r
+\r
+ //\r
+ // Delete the MOR Control Lock variable too (should it exists for some\r
+ // reason) and prevent other modules from creating it.\r
+ //\r
+ mMorLockPassThru = TRUE;\r
+ VariableServiceSetVariable (\r
+ MEMORY_OVERWRITE_REQUEST_CONTROL_LOCK_NAME,\r
+ &gEfiMemoryOverwriteRequestControlLockGuid,\r
+ 0, // Attributes\r
+ 0, // DataSize\r
+ NULL // Data\r
+ );\r
+ mMorLockPassThru = FALSE;\r
+\r
+ VariableLockRequestToLock (\r
+ NULL, // This\r
+ MEMORY_OVERWRITE_REQUEST_CONTROL_LOCK_NAME,\r
+ &gEfiMemoryOverwriteRequestControlLockGuid\r
+ );\r
}\r