summaryrefslogtreecommitdiffstats
path: root/MdeModulePkg/Universal/Variable/RuntimeDxe/TcgMorLockDxe.c
blob: b85f08c48c1130eca8191367fc7aee68eb599cbf (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
/** @file
  TCG MOR (Memory Overwrite Request) Lock Control support (DXE version).

  This module clears MemoryOverwriteRequestControlLock variable to indicate
  MOR lock control unsupported.

Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
Copyright (c) Microsoft Corporation.
SPDX-License-Identifier: BSD-2-Clause-Patent

**/

#include <PiDxe.h>
#include <Guid/MemoryOverwriteControl.h>
#include <IndustryStandard/MemoryOverwriteRequestControlLock.h>
#include <Library/DebugLib.h>
#include <Library/BaseLib.h>
#include <Library/BaseMemoryLib.h>
#include "Variable.h"

#include <Protocol/VariablePolicy.h>
#include <Library/VariablePolicyHelperLib.h>

/**
  This service is an MOR/MorLock checker handler for the SetVariable().

  @param[in]  VariableName the name of the vendor's variable, as a
                           Null-Terminated Unicode String
  @param[in]  VendorGuid   Unify identifier for vendor.
  @param[in]  Attributes   Attributes bitmask to set for the variable.
  @param[in]  DataSize     The size in bytes of Data-Buffer.
  @param[in]  Data         Point to the content of the variable.

  @retval  EFI_SUCCESS            The MOR/MorLock check pass, and Variable
                                  driver can store the variable data.
  @retval  EFI_INVALID_PARAMETER  The MOR/MorLock data or data size or
                                  attributes is not allowed for MOR variable.
  @retval  EFI_ACCESS_DENIED      The MOR/MorLock is locked.
  @retval  EFI_ALREADY_STARTED    The MorLock variable is handled inside this
                                  function. Variable driver can just return
                                  EFI_SUCCESS.
**/
EFI_STATUS
SetVariableCheckHandlerMor (
  IN CHAR16     *VariableName,
  IN EFI_GUID   *VendorGuid,
  IN UINT32     Attributes,
  IN UINTN      DataSize,
  IN VOID       *Data
  )
{
  //
  // Just let it pass. No need provide protection for DXE version.
  //
  return EFI_SUCCESS;
}

/**
  Initialization for MOR Control Lock.

  @retval EFI_SUCCESS     MorLock initialization success.
  @return Others          Some error occurs.
**/
EFI_STATUS
MorLockInit (
  VOID
  )
{
  //
  // Always clear variable to report unsupported to OS.
  // The reason is that the DXE version is not proper to provide *protection*.
  // BIOS should use SMM version variable driver to provide such capability.
  //
  VariableServiceSetVariable (
    MEMORY_OVERWRITE_REQUEST_CONTROL_LOCK_NAME,
    &gEfiMemoryOverwriteRequestControlLockGuid,
    0,                                          // Attributes
    0,                                          // DataSize
    NULL                                        // Data
    );

  //
  // The MOR variable can effectively improve platform security only when the
  // MorLock variable protects the MOR variable. In turn MorLock cannot be made
  // secure without SMM support in the platform firmware (see above).
  //
  // Thus, delete the MOR variable, should it exist for any reason (some OSes
  // are known to create MOR unintentionally, in an attempt to set it), then
  // also lock the MOR variable, in order to prevent other modules from
  // creating it.
  //
  VariableServiceSetVariable (
    MEMORY_OVERWRITE_REQUEST_VARIABLE_NAME,
    &gEfiMemoryOverwriteControlDataGuid,
    0,                                      // Attributes
    0,                                      // DataSize
    NULL                                    // Data
    );

  return EFI_SUCCESS;
}

/**
  Delayed initialization for MOR Control Lock at EndOfDxe.

  This function performs any operations queued by MorLockInit().
**/
VOID
MorLockInitAtEndOfDxe (
  VOID
  )
{
  EFI_STATUS                        Status;
  EDKII_VARIABLE_POLICY_PROTOCOL    *VariablePolicy;

  // First, we obviously need to locate the VariablePolicy protocol.
  Status = gBS->LocateProtocol( &gEdkiiVariablePolicyProtocolGuid, NULL, (VOID**)&VariablePolicy );
  if (EFI_ERROR( Status )) {
    DEBUG(( DEBUG_ERROR, "%a - Could not locate VariablePolicy protocol! %r\n", __FUNCTION__, Status ));
    return;
  }

  // If we're successful, go ahead and set the policies to protect the target variables.
  Status = RegisterBasicVariablePolicy( VariablePolicy,
                                        &gEfiMemoryOverwriteRequestControlLockGuid,
                                        MEMORY_OVERWRITE_REQUEST_CONTROL_LOCK_NAME,
                                        VARIABLE_POLICY_NO_MIN_SIZE,
                                        VARIABLE_POLICY_NO_MAX_SIZE,
                                        VARIABLE_POLICY_NO_MUST_ATTR,
                                        VARIABLE_POLICY_NO_CANT_ATTR,
                                        VARIABLE_POLICY_TYPE_LOCK_NOW );
  if (EFI_ERROR( Status )) {
    DEBUG(( DEBUG_ERROR, "%a - Could not lock variable %s! %r\n", __FUNCTION__, MEMORY_OVERWRITE_REQUEST_CONTROL_LOCK_NAME, Status ));
  }
  Status = RegisterBasicVariablePolicy( VariablePolicy,
                                        &gEfiMemoryOverwriteControlDataGuid,
                                        MEMORY_OVERWRITE_REQUEST_VARIABLE_NAME,
                                        VARIABLE_POLICY_NO_MIN_SIZE,
                                        VARIABLE_POLICY_NO_MAX_SIZE,
                                        VARIABLE_POLICY_NO_MUST_ATTR,
                                        VARIABLE_POLICY_NO_CANT_ATTR,
                                        VARIABLE_POLICY_TYPE_LOCK_NOW );
  if (EFI_ERROR( Status )) {
    DEBUG(( DEBUG_ERROR, "%a - Could not lock variable %s! %r\n", __FUNCTION__, MEMORY_OVERWRITE_REQUEST_VARIABLE_NAME, Status ));
  }

  return;
}