2 Opal Password PEI driver which is used to unlock Opal Password for S3.
4 Copyright (c) 2016 - 2019, Intel Corporation. All rights reserved.<BR>
5 SPDX-License-Identifier: BSD-2-Clause-Patent
9 #include "OpalPasswordPei.h"
11 EFI_GUID mOpalDeviceLockBoxGuid
= OPAL_DEVICE_LOCKBOX_GUID
;
14 Send a security protocol command to a device that receives data and/or the result
15 of one or more commands sent by SendData.
17 The ReceiveData function sends a security protocol command to the given MediaId.
18 The security protocol command sent is defined by SecurityProtocolId and contains
19 the security protocol specific data SecurityProtocolSpecificData. The function
20 returns the data from the security protocol command in PayloadBuffer.
22 For devices supporting the SCSI command set, the security protocol command is sent
23 using the SECURITY PROTOCOL IN command defined in SPC-4.
25 For devices supporting the ATA command set, the security protocol command is sent
26 using one of the TRUSTED RECEIVE commands defined in ATA8-ACS if PayloadBufferSize
29 If the PayloadBufferSize is zero, the security protocol command is sent using the
30 Trusted Non-Data command defined in ATA8-ACS.
32 If PayloadBufferSize is too small to store the available data from the security
33 protocol command, the function shall copy PayloadBufferSize bytes into the
34 PayloadBuffer and return EFI_WARN_BUFFER_TOO_SMALL.
36 If PayloadBuffer or PayloadTransferSize is NULL and PayloadBufferSize is non-zero,
37 the function shall return EFI_INVALID_PARAMETER.
39 If the given MediaId does not support security protocol commands, the function shall
40 return EFI_UNSUPPORTED. If there is no media in the device, the function returns
41 EFI_NO_MEDIA. If the MediaId is not the ID for the current media in the device,
42 the function returns EFI_MEDIA_CHANGED.
44 If the security protocol fails to complete within the Timeout period, the function
45 shall return EFI_TIMEOUT.
47 If the security protocol command completes without an error, the function shall
48 return EFI_SUCCESS. If the security protocol command completes with an error, the
49 function shall return EFI_DEVICE_ERROR.
51 @param This Indicates a pointer to the calling context.
52 @param MediaId ID of the medium to receive data from.
53 @param Timeout The timeout, in 100ns units, to use for the execution
54 of the security protocol command. A Timeout value of 0
55 means that this function will wait indefinitely for the
56 security protocol command to execute. If Timeout is greater
57 than zero, then this function will return EFI_TIMEOUT
58 if the time required to execute the receive data command
59 is greater than Timeout.
60 @param SecurityProtocolId The value of the "Security Protocol" parameter of
61 the security protocol command to be sent.
62 @param SecurityProtocolSpecificData The value of the "Security Protocol Specific" parameter
63 of the security protocol command to be sent.
64 @param PayloadBufferSize Size in bytes of the payload data buffer.
65 @param PayloadBuffer A pointer to a destination buffer to store the security
66 protocol command specific payload data for the security
67 protocol command. The caller is responsible for having
68 either implicit or explicit ownership of the buffer.
69 @param PayloadTransferSize A pointer to a buffer to store the size in bytes of the
70 data written to the payload data buffer.
72 @retval EFI_SUCCESS The security protocol command completed successfully.
73 @retval EFI_WARN_BUFFER_TOO_SMALL The PayloadBufferSize was too small to store the available
74 data from the device. The PayloadBuffer contains the truncated data.
75 @retval EFI_UNSUPPORTED The given MediaId does not support security protocol commands.
76 @retval EFI_DEVICE_ERROR The security protocol command completed with an error.
77 @retval EFI_NO_MEDIA There is no media in the device.
78 @retval EFI_MEDIA_CHANGED The MediaId is not for the current media.
79 @retval EFI_INVALID_PARAMETER The PayloadBuffer or PayloadTransferSize is NULL and
80 PayloadBufferSize is non-zero.
81 @retval EFI_TIMEOUT A timeout occurred while waiting for the security
82 protocol command to execute.
88 IN EFI_STORAGE_SECURITY_COMMAND_PROTOCOL
*This
,
91 IN UINT8 SecurityProtocolId
,
92 IN UINT16 SecurityProtocolSpecificData
,
93 IN UINTN PayloadBufferSize
,
94 OUT VOID
*PayloadBuffer
,
95 OUT UINTN
*PayloadTransferSize
98 OPAL_PEI_DEVICE
*PeiDev
;
100 PeiDev
= OPAL_PEI_DEVICE_FROM_THIS (This
);
101 if (PeiDev
== NULL
) {
102 return EFI_DEVICE_ERROR
;
105 return PeiDev
->SscPpi
->ReceiveData (
108 SSC_PPI_GENERIC_TIMEOUT
,
110 SecurityProtocolSpecificData
,
118 Send a security protocol command to a device.
120 The SendData function sends a security protocol command containing the payload
121 PayloadBuffer to the given MediaId. The security protocol command sent is
122 defined by SecurityProtocolId and contains the security protocol specific data
123 SecurityProtocolSpecificData. If the underlying protocol command requires a
124 specific padding for the command payload, the SendData function shall add padding
125 bytes to the command payload to satisfy the padding requirements.
127 For devices supporting the SCSI command set, the security protocol command is sent
128 using the SECURITY PROTOCOL OUT command defined in SPC-4.
130 For devices supporting the ATA command set, the security protocol command is sent
131 using one of the TRUSTED SEND commands defined in ATA8-ACS if PayloadBufferSize
132 is non-zero. If the PayloadBufferSize is zero, the security protocol command is
133 sent using the Trusted Non-Data command defined in ATA8-ACS.
135 If PayloadBuffer is NULL and PayloadBufferSize is non-zero, the function shall
136 return EFI_INVALID_PARAMETER.
138 If the given MediaId does not support security protocol commands, the function
139 shall return EFI_UNSUPPORTED. If there is no media in the device, the function
140 returns EFI_NO_MEDIA. If the MediaId is not the ID for the current media in the
141 device, the function returns EFI_MEDIA_CHANGED.
143 If the security protocol fails to complete within the Timeout period, the function
144 shall return EFI_TIMEOUT.
146 If the security protocol command completes without an error, the function shall return
147 EFI_SUCCESS. If the security protocol command completes with an error, the function
148 shall return EFI_DEVICE_ERROR.
150 @param This Indicates a pointer to the calling context.
151 @param MediaId ID of the medium to receive data from.
152 @param Timeout The timeout, in 100ns units, to use for the execution
153 of the security protocol command. A Timeout value of 0
154 means that this function will wait indefinitely for the
155 security protocol command to execute. If Timeout is greater
156 than zero, then this function will return EFI_TIMEOUT
157 if the time required to execute the send data command
158 is greater than Timeout.
159 @param SecurityProtocolId The value of the "Security Protocol" parameter of
160 the security protocol command to be sent.
161 @param SecurityProtocolSpecificData The value of the "Security Protocol Specific" parameter
162 of the security protocol command to be sent.
163 @param PayloadBufferSize Size in bytes of the payload data buffer.
164 @param PayloadBuffer A pointer to a destination buffer to store the security
165 protocol command specific payload data for the security
168 @retval EFI_SUCCESS The security protocol command completed successfully.
169 @retval EFI_UNSUPPORTED The given MediaId does not support security protocol commands.
170 @retval EFI_DEVICE_ERROR The security protocol command completed with an error.
171 @retval EFI_NO_MEDIA There is no media in the device.
172 @retval EFI_MEDIA_CHANGED The MediaId is not for the current media.
173 @retval EFI_INVALID_PARAMETER The PayloadBuffer is NULL and PayloadBufferSize is non-zero.
174 @retval EFI_TIMEOUT A timeout occurred while waiting for the security
175 protocol command to execute.
181 IN EFI_STORAGE_SECURITY_COMMAND_PROTOCOL
*This
,
184 IN UINT8 SecurityProtocolId
,
185 IN UINT16 SecurityProtocolSpecificData
,
186 IN UINTN PayloadBufferSize
,
187 IN VOID
*PayloadBuffer
190 OPAL_PEI_DEVICE
*PeiDev
;
192 PeiDev
= OPAL_PEI_DEVICE_FROM_THIS (This
);
193 if (PeiDev
== NULL
) {
194 return EFI_DEVICE_ERROR
;
197 return PeiDev
->SscPpi
->SendData (
200 SSC_PPI_GENERIC_TIMEOUT
,
202 SecurityProtocolSpecificData
,
210 The function returns whether or not the device is Opal Locked.
211 TRUE means that the device is partially or fully locked.
212 This will perform a Level 0 Discovery and parse the locking feature descriptor
214 @param[in] OpalDev Opal object to determine if locked.
215 @param[out] BlockSidSupported Whether device support BlockSid feature.
220 OPAL_PEI_DEVICE
*OpalDev
,
221 BOOLEAN
*BlockSidSupported
224 OPAL_SESSION Session
;
225 OPAL_DISK_SUPPORT_ATTRIBUTE SupportedAttributes
;
226 TCG_LOCKING_FEATURE_DESCRIPTOR LockingFeature
;
227 UINT16 OpalBaseComId
;
230 Session
.Sscp
= &OpalDev
->Sscp
;
233 Ret
= OpalGetSupportedAttributesInfo (&Session
, &SupportedAttributes
, &OpalBaseComId
);
234 if (Ret
!= TcgResultSuccess
) {
238 Session
.OpalBaseComId
= OpalBaseComId
;
239 *BlockSidSupported
= SupportedAttributes
.BlockSid
== 1 ? TRUE
: FALSE
;
241 Ret
= OpalGetLockingInfo (&Session
, &LockingFeature
);
242 if (Ret
!= TcgResultSuccess
) {
246 return OpalDeviceLocked (&SupportedAttributes
, &LockingFeature
);
250 Unlock OPAL password for S3.
252 @param[in] OpalDev Opal object to unlock.
257 IN OPAL_PEI_DEVICE
*OpalDev
261 OPAL_SESSION Session
;
262 BOOLEAN BlockSidSupport
;
263 UINT32 PpStorageFlags
;
264 BOOLEAN BlockSIDEnabled
;
266 BlockSidSupport
= FALSE
;
267 if (IsOpalDeviceLocked (OpalDev
, &BlockSidSupport
)) {
268 ZeroMem (&Session
, sizeof (Session
));
269 Session
.Sscp
= &OpalDev
->Sscp
;
271 Session
.OpalBaseComId
= OpalDev
->Device
->OpalBaseComId
;
273 Result
= OpalUtilUpdateGlobalLockingRange (
275 OpalDev
->Device
->Password
,
276 OpalDev
->Device
->PasswordLength
,
282 "%a() OpalUtilUpdateGlobalLockingRange() Result = 0x%x\n",
288 PpStorageFlags
= Tcg2PhysicalPresenceLibGetManagementFlags ();
289 if ((PpStorageFlags
& TCG2_BIOS_STORAGE_MANAGEMENT_FLAG_ENABLE_BLOCK_SID
) != 0) {
290 BlockSIDEnabled
= TRUE
;
292 BlockSIDEnabled
= FALSE
;
295 if (BlockSIDEnabled
&& BlockSidSupport
) {
296 DEBUG ((DEBUG_INFO
, "OpalPassword: S3 phase send BlockSid command to device!\n"));
297 ZeroMem (&Session
, sizeof (Session
));
298 Session
.Sscp
= &OpalDev
->Sscp
;
300 Session
.OpalBaseComId
= OpalDev
->Device
->OpalBaseComId
;
301 Result
= OpalBlockSid (&Session
, TRUE
);
304 "%a() OpalBlockSid() Result = 0x%x\n",
312 Unlock the OPAL NVM Express and ATA devices for S3.
314 @param[in] SscPpi Pointer to the EDKII_PEI_STORAGE_SECURITY_CMD_PPI instance.
318 UnlockOpalPasswordDevices (
319 IN EDKII_PEI_STORAGE_SECURITY_CMD_PPI
*SscPpi
323 UINT8
*DevInfoBuffer
;
325 OPAL_DEVICE_LOCKBOX_DATA
*DevInfo
;
327 EFI_DEVICE_PATH_PROTOCOL
*SscDevicePath
;
328 UINTN SscDevicePathLength
;
330 UINTN SscDeviceIndex
;
331 OPAL_PEI_DEVICE OpalDev
;
334 // Get OPAL devices info from LockBox.
336 DevInfoBuffer
= &DummyData
;
337 DevInfoLength
= sizeof (DummyData
);
338 Status
= RestoreLockBox (&mOpalDeviceLockBoxGuid
, DevInfoBuffer
, &DevInfoLength
);
339 if (Status
== EFI_BUFFER_TOO_SMALL
) {
340 DevInfoBuffer
= AllocatePages (EFI_SIZE_TO_PAGES (DevInfoLength
));
341 if (DevInfoBuffer
!= NULL
) {
342 Status
= RestoreLockBox (&mOpalDeviceLockBoxGuid
, DevInfoBuffer
, &DevInfoLength
);
346 if ((DevInfoBuffer
== NULL
) || (DevInfoBuffer
== &DummyData
)) {
348 } else if (EFI_ERROR (Status
)) {
349 FreePages (DevInfoBuffer
, EFI_SIZE_TO_PAGES (DevInfoLength
));
354 // Go through all the devices managed by the SSC PPI instance.
356 Status
= SscPpi
->GetNumberofDevices (SscPpi
, &SscDeviceNum
);
357 if (EFI_ERROR (Status
)) {
361 for (SscDeviceIndex
= 1; SscDeviceIndex
<= SscDeviceNum
; SscDeviceIndex
++) {
362 Status
= SscPpi
->GetDevicePath (
365 &SscDevicePathLength
,
368 if (SscDevicePathLength
<= sizeof (EFI_DEVICE_PATH_PROTOCOL
)) {
370 // Device path validity check.
376 // Search the device in the restored LockBox.
378 for (DevInfo
= (OPAL_DEVICE_LOCKBOX_DATA
*)DevInfoBuffer
;
379 (UINTN
)DevInfo
< ((UINTN
)DevInfoBuffer
+ DevInfoLength
);
380 DevInfo
= (OPAL_DEVICE_LOCKBOX_DATA
*)((UINTN
)DevInfo
+ DevInfo
->Length
))
383 // Find the matching device.
385 if ((DevInfo
->DevicePathLength
>= SscDevicePathLength
) &&
389 SscDevicePathLength
- sizeof (EFI_DEVICE_PATH_PROTOCOL
)
392 OpalDev
.Signature
= OPAL_PEI_DEVICE_SIGNATURE
;
393 OpalDev
.Sscp
.ReceiveData
= SecurityReceiveData
;
394 OpalDev
.Sscp
.SendData
= SecuritySendData
;
395 OpalDev
.Device
= DevInfo
;
396 OpalDev
.Context
= NULL
;
397 OpalDev
.SscPpi
= SscPpi
;
398 OpalDev
.DeviceIndex
= SscDeviceIndex
;
399 UnlockOpalPassword (&OpalDev
);
406 ZeroMem (DevInfoBuffer
, DevInfoLength
);
407 FreePages (DevInfoBuffer
, EFI_SIZE_TO_PAGES (DevInfoLength
));
411 One notified function at the installation of EDKII_PEI_STORAGE_SECURITY_CMD_PPI.
412 It is to unlock OPAL password for S3.
414 @param[in] PeiServices Indirect reference to the PEI Services Table.
415 @param[in] NotifyDescriptor Address of the notification descriptor data structure.
416 @param[in] Ppi Address of the PPI that was installed.
418 @return Status of the notification.
419 The status code returned from this function is ignored.
424 OpalPasswordStorageSecurityPpiNotify (
425 IN EFI_PEI_SERVICES
**PeiServices
,
426 IN EFI_PEI_NOTIFY_DESCRIPTOR
*NotifyDesc
,
430 DEBUG ((DEBUG_INFO
, "%a entered at S3 resume!\n", __FUNCTION__
));
432 UnlockOpalPasswordDevices ((EDKII_PEI_STORAGE_SECURITY_CMD_PPI
*)Ppi
);
434 DEBUG ((DEBUG_INFO
, "%a exit at S3 resume!\n", __FUNCTION__
));
439 EFI_PEI_NOTIFY_DESCRIPTOR mOpalPasswordStorageSecurityPpiNotifyDesc
= {
440 (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK
| EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
),
441 &gEdkiiPeiStorageSecurityCommandPpiGuid
,
442 OpalPasswordStorageSecurityPpiNotify
446 Main entry for this module.
448 @param FileHandle Handle of the file being invoked.
449 @param PeiServices Pointer to PEI Services table.
451 @return Status from PeiServicesNotifyPpi.
456 OpalPasswordPeiInit (
457 IN EFI_PEI_FILE_HANDLE FileHandle
,
458 IN CONST EFI_PEI_SERVICES
**PeiServices
462 EFI_BOOT_MODE BootMode
;
464 Status
= PeiServicesGetBootMode (&BootMode
);
465 if ((EFI_ERROR (Status
)) || (BootMode
!= BOOT_ON_S3_RESUME
)) {
466 return EFI_UNSUPPORTED
;
469 DEBUG ((DEBUG_INFO
, "%a: Enters in S3 path.\n", __FUNCTION__
));
471 Status
= PeiServicesNotifyPpi (&mOpalPasswordStorageSecurityPpiNotifyDesc
);
472 ASSERT_EFI_ERROR (Status
);