#include <Library/DebugLib.h>\r
#include <Library/BaseLib.h>\r
#include <Library/BaseMemoryLib.h>\r
+#include <Library/UefiBootServicesTableLib.h>\r
#include "Variable.h"\r
\r
typedef struct {\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
// 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
UINTN MorSize;\r
EFI_STATUS MorStatus;\r
+ EFI_STATUS TcgStatus;\r
+ VOID *TcgInterface;\r
\r
if (!mMorLockInitializationRequired) {\r
//\r
\r
if (MorStatus == EFI_BUFFER_TOO_SMALL) {\r
//\r
- // The MOR variable exists; set the MOR Control Lock variable to report the\r
- // capability to the OS.\r
+ // The MOR variable exists.\r
//\r
- SetMorLockVariable (0);\r
- return;\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
+ TcgStatus = gBS->LocateProtocol (\r
+ &gEfiTcgProtocolGuid,\r
+ NULL, // Registration\r
+ &TcgInterface\r
+ );\r
+ if (EFI_ERROR (TcgStatus)) {\r
+ TcgStatus = gBS->LocateProtocol (\r
+ &gEfiTcg2ProtocolGuid,\r
+ NULL, // Registration\r
+ &TcgInterface\r
+ );\r
+ }\r
+\r
+ if (!EFI_ERROR (TcgStatus)) {\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 platform does not support the MOR variable. Delete the MOR Control\r
- // Lock variable (should it exists for some reason) and prevent other modules\r
- // from creating it.\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