]> git.proxmox.com Git - mirror_edk2.git/blob - SecurityPkg/Tcg/MemoryOverwriteControl/TcgMor.c
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[mirror_edk2.git] / SecurityPkg / Tcg / MemoryOverwriteControl / TcgMor.c
1 /** @file
2 TCG MOR (Memory Overwrite Request) Control Driver.
3
4 This driver initialize MemoryOverwriteRequestControl variable. It
5 will clear MOR_CLEAR_MEMORY_BIT bit if it is set. It will also do TPer Reset for
6 those encrypted drives through EFI_STORAGE_SECURITY_COMMAND_PROTOCOL at EndOfDxe.
7
8 Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.<BR>
9 SPDX-License-Identifier: BSD-2-Clause-Patent
10
11 **/
12
13 #include "TcgMor.h"
14
15 UINT8 mMorControl;
16
17 /**
18 Ready to Boot Event notification handler.
19
20 @param[in] Event Event whose notification function is being invoked
21 @param[in] Context Pointer to the notification function's context
22
23 **/
24 VOID
25 EFIAPI
26 OnReadyToBoot (
27 IN EFI_EVENT Event,
28 IN VOID *Context
29 )
30 {
31 EFI_STATUS Status;
32 UINTN DataSize;
33
34 if (MOR_CLEAR_MEMORY_VALUE (mMorControl) == 0x0) {
35 //
36 // MorControl is expected, directly return to avoid unnecessary variable operation
37 //
38 return;
39 }
40
41 //
42 // Clear MOR_CLEAR_MEMORY_BIT
43 //
44 DEBUG ((DEBUG_INFO, "TcgMor: Clear MorClearMemory bit\n"));
45 mMorControl &= 0xFE;
46
47 DataSize = sizeof (mMorControl);
48 Status = gRT->SetVariable (
49 MEMORY_OVERWRITE_REQUEST_VARIABLE_NAME,
50 &gEfiMemoryOverwriteControlDataGuid,
51 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
52 DataSize,
53 &mMorControl
54 );
55 if (EFI_ERROR (Status)) {
56 DEBUG ((DEBUG_ERROR, "TcgMor: Clear MOR_CLEAR_MEMORY_BIT failure, Status = %r\n", Status));
57 }
58 }
59
60 /**
61 Send TPer Reset command to reset eDrive to lock all protected bands.
62 Typically, there are 2 mechanism for resetting eDrive. They are:
63 1. TPer Reset through IEEE 1667 protocol.
64 2. TPer Reset through native TCG protocol.
65 This routine will detect what protocol the attached eDrive conform to, TCG or
66 IEEE 1667 protocol. Then send out TPer Reset command separately.
67
68 @param[in] Ssp The pointer to EFI_STORAGE_SECURITY_COMMAND_PROTOCOL instance.
69 @param[in] MediaId ID of the medium to receive data from or send data to.
70
71 **/
72 VOID
73 InitiateTPerReset (
74 IN EFI_STORAGE_SECURITY_COMMAND_PROTOCOL *Ssp,
75 IN UINT32 MediaId
76 )
77 {
78 EFI_STATUS Status;
79 UINT8 *Buffer;
80 UINTN XferSize;
81 UINTN Len;
82 UINTN Index;
83 BOOLEAN TcgFlag;
84 BOOLEAN IeeeFlag;
85 SUPPORTED_SECURITY_PROTOCOLS_PARAMETER_DATA *Data;
86
87 Buffer = NULL;
88 TcgFlag = FALSE;
89 IeeeFlag = FALSE;
90
91 //
92 // ATA8-ACS 7.57.6.1 indicates the Transfer Length field requirements a multiple of 512.
93 // If the length of the TRUSTED RECEIVE parameter data is greater than the Transfer Length,
94 // then the device shall return the TRUSTED RECEIVE parameter data truncated to the requested Transfer Length.
95 //
96 Len = ROUNDUP512 (sizeof (SUPPORTED_SECURITY_PROTOCOLS_PARAMETER_DATA));
97 Buffer = AllocateZeroPool (Len);
98
99 if (Buffer == NULL) {
100 return;
101 }
102
103 //
104 // When the Security Protocol field is set to 00h, and SP Specific is set to 0000h in a TRUSTED RECEIVE
105 // command, the device basic information data shall be returned.
106 //
107 Status = Ssp->ReceiveData (
108 Ssp,
109 MediaId,
110 100000000, // Timeout 10-sec
111 0, // SecurityProtocol
112 0, // SecurityProtocolSpecificData
113 Len, // PayloadBufferSize,
114 Buffer, // PayloadBuffer
115 &XferSize
116 );
117 if (EFI_ERROR (Status)) {
118 goto Exit;
119 }
120
121 //
122 // In returned data, the ListLength field indicates the total length, in bytes,
123 // of the supported security protocol list.
124 //
125 Data = (SUPPORTED_SECURITY_PROTOCOLS_PARAMETER_DATA *)Buffer;
126 Len = ROUNDUP512 (
127 sizeof (SUPPORTED_SECURITY_PROTOCOLS_PARAMETER_DATA) +
128 (Data->SupportedSecurityListLength[0] << 8) +
129 (Data->SupportedSecurityListLength[1])
130 );
131
132 //
133 // Free original buffer and allocate new buffer.
134 //
135 FreePool (Buffer);
136 Buffer = AllocateZeroPool (Len);
137 if (Buffer == NULL) {
138 return;
139 }
140
141 //
142 // Read full supported security protocol list from device.
143 //
144 Status = Ssp->ReceiveData (
145 Ssp,
146 MediaId,
147 100000000, // Timeout 10-sec
148 0, // SecurityProtocol
149 0, // SecurityProtocolSpecificData
150 Len, // PayloadBufferSize,
151 Buffer, // PayloadBuffer
152 &XferSize
153 );
154
155 if (EFI_ERROR (Status)) {
156 goto Exit;
157 }
158
159 Data = (SUPPORTED_SECURITY_PROTOCOLS_PARAMETER_DATA *)Buffer;
160 Len = (Data->SupportedSecurityListLength[0] << 8) + Data->SupportedSecurityListLength[1];
161
162 //
163 // Iterate full supported security protocol list to check if TCG or IEEE 1667 protocol
164 // is supported.
165 //
166 for (Index = 0; Index < Len; Index++) {
167 if (Data->SupportedSecurityProtocol[Index] == SECURITY_PROTOCOL_TCG) {
168 //
169 // Found a TCG device.
170 //
171 TcgFlag = TRUE;
172 DEBUG ((DEBUG_INFO, "This device is a TCG protocol device\n"));
173 break;
174 }
175
176 if (Data->SupportedSecurityProtocol[Index] == SECURITY_PROTOCOL_IEEE1667) {
177 //
178 // Found a IEEE 1667 device.
179 //
180 IeeeFlag = TRUE;
181 DEBUG ((DEBUG_INFO, "This device is a IEEE 1667 protocol device\n"));
182 break;
183 }
184 }
185
186 if (!TcgFlag && !IeeeFlag) {
187 DEBUG ((DEBUG_INFO, "Neither a TCG nor IEEE 1667 protocol device is found\n"));
188 goto Exit;
189 }
190
191 if (TcgFlag) {
192 //
193 // As long as TCG protocol is supported, send out a TPer Reset
194 // TCG command to the device via the TrustedSend command with a non-zero Transfer Length.
195 //
196 Status = Ssp->SendData (
197 Ssp,
198 MediaId,
199 100000000, // Timeout 10-sec
200 SECURITY_PROTOCOL_TCG, // SecurityProtocol
201 0x0400, // SecurityProtocolSpecificData
202 512, // PayloadBufferSize,
203 Buffer // PayloadBuffer
204 );
205
206 if (!EFI_ERROR (Status)) {
207 DEBUG ((DEBUG_INFO, "Send TPer Reset Command Successfully !\n"));
208 } else {
209 DEBUG ((DEBUG_INFO, "Send TPer Reset Command Fail !\n"));
210 }
211 }
212
213 if (IeeeFlag) {
214 //
215 // TBD : Perform a TPer Reset via IEEE 1667 Protocol
216 //
217 DEBUG ((DEBUG_INFO, "IEEE 1667 Protocol didn't support yet!\n"));
218 }
219
220 Exit:
221
222 if (Buffer != NULL) {
223 FreePool (Buffer);
224 }
225 }
226
227 /**
228 Notification function of END_OF_DXE.
229
230 @param[in] Event Event whose notification function is being invoked.
231 @param[in] Context Pointer to the notification function's context.
232
233 **/
234 VOID
235 EFIAPI
236 TPerResetAtEndOfDxe (
237 IN EFI_EVENT Event,
238 IN VOID *Context
239 )
240 {
241 EFI_STORAGE_SECURITY_COMMAND_PROTOCOL *Ssp;
242 EFI_BLOCK_IO_PROTOCOL *BlockIo;
243 EFI_STATUS Status;
244 UINTN HandleCount;
245 EFI_HANDLE *HandleBuffer;
246 UINTN Index;
247
248 //
249 // Locate all SSP protocol instances.
250 //
251 HandleCount = 0;
252 HandleBuffer = NULL;
253
254 Status = gBS->LocateHandleBuffer (
255 ByProtocol,
256 &gEfiStorageSecurityCommandProtocolGuid,
257 NULL,
258 &HandleCount,
259 &HandleBuffer
260 );
261
262 if (EFI_ERROR (Status) || (HandleCount == 0) || (HandleBuffer == NULL)) {
263 return;
264 }
265
266 for (Index = 0; Index < HandleCount; Index++) {
267 //
268 // Get the SSP interface.
269 //
270 Status = gBS->HandleProtocol (
271 HandleBuffer[Index],
272 &gEfiStorageSecurityCommandProtocolGuid,
273 (VOID **)&Ssp
274 );
275
276 if (EFI_ERROR (Status)) {
277 continue;
278 }
279
280 Status = gBS->HandleProtocol (
281 HandleBuffer[Index],
282 &gEfiBlockIoProtocolGuid,
283 (VOID **)&BlockIo
284 );
285
286 if (EFI_ERROR (Status)) {
287 continue;
288 }
289
290 InitiateTPerReset (Ssp, BlockIo->Media->MediaId);
291 }
292
293 FreePool (HandleBuffer);
294 }
295
296 /**
297 Entry Point for TCG MOR Control driver.
298
299 @param[in] ImageHandle Image handle of this driver.
300 @param[in] SystemTable A Pointer to the EFI System Table.
301
302 @retval EFI_SUCCESS
303 @return Others Some error occurs.
304 **/
305 EFI_STATUS
306 EFIAPI
307 MorDriverEntryPoint (
308 IN EFI_HANDLE ImageHandle,
309 IN EFI_SYSTEM_TABLE *SystemTable
310 )
311 {
312 EFI_STATUS Status;
313 UINTN DataSize;
314 EFI_EVENT Event;
315
316 ///
317 /// The firmware is required to create the MemoryOverwriteRequestControl UEFI variable.
318 ///
319
320 DataSize = sizeof (mMorControl);
321 Status = gRT->GetVariable (
322 MEMORY_OVERWRITE_REQUEST_VARIABLE_NAME,
323 &gEfiMemoryOverwriteControlDataGuid,
324 NULL,
325 &DataSize,
326 &mMorControl
327 );
328 if (EFI_ERROR (Status)) {
329 //
330 // Set default value to 0
331 //
332 mMorControl = 0;
333 Status = gRT->SetVariable (
334 MEMORY_OVERWRITE_REQUEST_VARIABLE_NAME,
335 &gEfiMemoryOverwriteControlDataGuid,
336 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
337 DataSize,
338 &mMorControl
339 );
340 DEBUG ((DEBUG_INFO, "TcgMor: Create MOR variable! Status = %r\n", Status));
341 } else {
342 //
343 // Create a Ready To Boot Event and Clear the MorControl bit in the call back function.
344 //
345 DEBUG ((DEBUG_INFO, "TcgMor: Create ReadyToBoot Event for MorControl Bit cleaning!\n"));
346 Status = EfiCreateEventReadyToBootEx (
347 TPL_CALLBACK,
348 OnReadyToBoot,
349 NULL,
350 &Event
351 );
352 if (EFI_ERROR (Status)) {
353 return Status;
354 }
355
356 //
357 // Register EFI_END_OF_DXE_EVENT_GROUP_GUID event.
358 //
359 DEBUG ((DEBUG_INFO, "TcgMor: Create EndofDxe Event for Mor TPer Reset!\n"));
360 Status = gBS->CreateEventEx (
361 EVT_NOTIFY_SIGNAL,
362 TPL_CALLBACK,
363 TPerResetAtEndOfDxe,
364 NULL,
365 &gEfiEndOfDxeEventGroupGuid,
366 &Event
367 );
368 if (EFI_ERROR (Status)) {
369 return Status;
370 }
371 }
372
373 return Status;
374 }