2 The NvmExpressPei driver is used to manage non-volatile memory subsystem
3 which follows NVM Express specification at PEI phase.
5 Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
7 This program and the accompanying materials
8 are licensed and made available under the terms and conditions
9 of the BSD License which accompanies this distribution. The
10 full text of the license may be found at
11 http://opensource.org/licenses/bsd-license.php
13 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
14 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
18 #include "NvmExpressPei.h"
21 Trust transfer data from/to NVM Express device.
23 This function performs one NVMe transaction to do a trust transfer from/to NVM
26 @param[in] Private The pointer to the PEI_NVME_CONTROLLER_PRIVATE_DATA
28 @param[in,out] Buffer The pointer to the current transaction buffer.
29 @param[in] SecurityProtocolId
30 The value of the "Security Protocol" parameter
31 of the security protocol command to be sent.
32 @param[in] SecurityProtocolSpecificData
33 The value of the "Security Protocol Specific"
34 parameter of the security protocol command to
36 @param[in] TransferLength The block number or sector count of the transfer.
37 @param[in] IsTrustSend Indicates whether it is a trust send operation
39 @param[in] Timeout The timeout, in 100ns units, to use for the
40 execution of the security protocol command.
41 A Timeout value of 0 means that this function
42 will wait indefinitely for the security protocol
43 command to execute. If Timeout is greater than
44 zero, then this function will return EFI_TIMEOUT
45 if the time required to execute the receive
46 data command is greater than Timeout.
47 @param[out] TransferLengthOut A pointer to a buffer to store the size in bytes
48 of the data written to the buffer. Ignore it
49 when IsTrustSend is TRUE.
51 @retval EFI_SUCCESS The data transfer is complete successfully.
52 @return others Some error occurs when transferring data.
56 TrustTransferNvmeDevice (
57 IN PEI_NVME_CONTROLLER_PRIVATE_DATA
*Private
,
59 IN UINT8 SecurityProtocolId
,
60 IN UINT16 SecurityProtocolSpecificData
,
61 IN UINTN TransferLength
,
62 IN BOOLEAN IsTrustSend
,
64 OUT UINTN
*TransferLengthOut
67 EDKII_PEI_NVM_EXPRESS_PASS_THRU_COMMAND_PACKET CommandPacket
;
68 EDKII_PEI_NVM_EXPRESS_COMMAND Command
;
69 EDKII_PEI_NVM_EXPRESS_COMPLETION Completion
;
73 ZeroMem (&CommandPacket
, sizeof(EDKII_PEI_NVM_EXPRESS_PASS_THRU_COMMAND_PACKET
));
74 ZeroMem (&Command
, sizeof(EDKII_PEI_NVM_EXPRESS_COMMAND
));
75 ZeroMem (&Completion
, sizeof(EDKII_PEI_NVM_EXPRESS_COMPLETION
));
77 CommandPacket
.NvmeCmd
= &Command
;
78 CommandPacket
.NvmeCompletion
= &Completion
;
81 // Change Endianness of SecurityProtocolSpecificData
83 SpecificData
= (((SecurityProtocolSpecificData
<< 8) & 0xFF00) | (SecurityProtocolSpecificData
>> 8));
86 Command
.Cdw0
.Opcode
= NVME_ADMIN_SECURITY_SEND_CMD
;
87 CommandPacket
.TransferBuffer
= Buffer
;
88 CommandPacket
.TransferLength
= (UINT32
)TransferLength
;
89 CommandPacket
.NvmeCmd
->Cdw10
= (UINT32
)((SecurityProtocolId
<< 24) | (SpecificData
<< 8));
90 CommandPacket
.NvmeCmd
->Cdw11
= (UINT32
)TransferLength
;
92 Command
.Cdw0
.Opcode
= NVME_ADMIN_SECURITY_RECEIVE_CMD
;
93 CommandPacket
.TransferBuffer
= Buffer
;
94 CommandPacket
.TransferLength
= (UINT32
)TransferLength
;
95 CommandPacket
.NvmeCmd
->Cdw10
= (UINT32
)((SecurityProtocolId
<< 24) | (SpecificData
<< 8));
96 CommandPacket
.NvmeCmd
->Cdw11
= (UINT32
)TransferLength
;
99 CommandPacket
.NvmeCmd
->Flags
= CDW10_VALID
| CDW11_VALID
;
100 CommandPacket
.NvmeCmd
->Nsid
= NVME_CONTROLLER_NSID
;
101 CommandPacket
.CommandTimeout
= Timeout
;
102 CommandPacket
.QueueType
= NVME_ADMIN_QUEUE
;
104 Status
= NvmePassThru (
106 NVME_CONTROLLER_NSID
,
111 if (EFI_ERROR (Status
)) {
112 *TransferLengthOut
= 0;
114 *TransferLengthOut
= (UINTN
) TransferLength
;
122 Gets the count of storage security devices that one specific driver detects.
124 @param[in] This The PPI instance pointer.
125 @param[out] NumberofDevices The number of storage security devices discovered.
127 @retval EFI_SUCCESS The operation performed successfully.
128 @retval EFI_INVALID_PARAMETER The parameters are invalid.
133 NvmeStorageSecurityGetDeviceNo (
134 IN EDKII_PEI_STORAGE_SECURITY_CMD_PPI
*This
,
135 OUT UINTN
*NumberofDevices
138 PEI_NVME_CONTROLLER_PRIVATE_DATA
*Private
;
140 if (This
== NULL
|| NumberofDevices
== NULL
) {
141 return EFI_INVALID_PARAMETER
;
144 Private
= GET_NVME_PEIM_HC_PRIVATE_DATA_FROM_THIS_STROAGE_SECURITY (This
);
145 *NumberofDevices
= Private
->ActiveNamespaceNum
;
151 Gets the device path of a specific storage security device.
153 @param[in] This The PPI instance pointer.
154 @param[in] DeviceIndex Specifies the storage security device to which
155 the function wants to talk. Because the driver
156 that implements Storage Security Command PPIs
157 will manage multiple storage devices, the PPIs
158 that want to talk to a single device must specify
159 the device index that was assigned during the
160 enumeration process. This index is a number from
161 one to NumberofDevices.
162 @param[out] DevicePathLength The length of the device path in bytes specified
164 @param[out] DevicePath The device path of storage security device.
165 This field re-uses EFI Device Path Protocol as
166 defined by Section 10.2 EFI Device Path Protocol
167 of UEFI 2.7 Specification.
169 @retval EFI_SUCCESS The operation succeeds.
170 @retval EFI_INVALID_PARAMETER DevicePathLength or DevicePath is NULL.
171 @retval EFI_NOT_FOUND The specified storage security device not found.
172 @retval EFI_OUT_OF_RESOURCES The operation fails due to lack of resources.
177 NvmeStorageSecurityGetDevicePath (
178 IN EDKII_PEI_STORAGE_SECURITY_CMD_PPI
*This
,
179 IN UINTN DeviceIndex
,
180 OUT UINTN
*DevicePathLength
,
181 OUT EFI_DEVICE_PATH_PROTOCOL
**DevicePath
184 PEI_NVME_CONTROLLER_PRIVATE_DATA
*Private
;
186 if (This
== NULL
|| DevicePathLength
== NULL
|| DevicePath
== NULL
) {
187 return EFI_INVALID_PARAMETER
;
190 Private
= GET_NVME_PEIM_HC_PRIVATE_DATA_FROM_THIS_STROAGE_SECURITY (This
);
191 if ((DeviceIndex
== 0) || (DeviceIndex
> Private
->ActiveNamespaceNum
)) {
192 return EFI_INVALID_PARAMETER
;
195 return NvmeBuildDevicePath (
197 Private
->NamespaceInfo
[DeviceIndex
-1].NamespaceId
,
198 Private
->NamespaceInfo
[DeviceIndex
-1].NamespaceUuid
,
205 Send a security protocol command to a device that receives data and/or the result
206 of one or more commands sent by SendData.
208 The ReceiveData function sends a security protocol command to the given DeviceIndex.
209 The security protocol command sent is defined by SecurityProtocolId and contains
210 the security protocol specific data SecurityProtocolSpecificData. The function
211 returns the data from the security protocol command in PayloadBuffer.
213 For devices supporting the SCSI command set, the security protocol command is sent
214 using the SECURITY PROTOCOL IN command defined in SPC-4.
216 For devices supporting the ATA command set, the security protocol command is sent
217 using one of the TRUSTED RECEIVE commands defined in ATA8-ACS if PayloadBufferSize
220 If the PayloadBufferSize is zero, the security protocol command is sent using the
221 Trusted Non-Data command defined in ATA8-ACS.
223 If PayloadBufferSize is too small to store the available data from the security
224 protocol command, the function shall copy PayloadBufferSize bytes into the
225 PayloadBuffer and return EFI_WARN_BUFFER_TOO_SMALL.
227 If PayloadBuffer or PayloadTransferSize is NULL and PayloadBufferSize is non-zero,
228 the function shall return EFI_INVALID_PARAMETER.
230 If the given DeviceIndex does not support security protocol commands, the function
231 shall return EFI_UNSUPPORTED.
233 If the security protocol fails to complete within the Timeout period, the function
234 shall return EFI_TIMEOUT.
236 If the security protocol command completes without an error, the function shall
237 return EFI_SUCCESS. If the security protocol command completes with an error, the
238 function shall return EFI_DEVICE_ERROR.
240 @param[in] This The PPI instance pointer.
241 @param[in] DeviceIndex Specifies the storage security device to which the
242 function wants to talk. Because the driver that
243 implements Storage Security Command PPIs will manage
244 multiple storage devices, the PPIs that want to talk
245 to a single device must specify the device index
246 that was assigned during the enumeration process.
247 This index is a number from one to NumberofDevices.
248 @param[in] Timeout The timeout, in 100ns units, to use for the execution
249 of the security protocol command. A Timeout value
250 of 0 means that this function will wait indefinitely
251 for the security protocol command to execute. If
252 Timeout is greater than zero, then this function
253 will return EFI_TIMEOUT if the time required to
254 execute the receive data command is greater than
256 @param[in] SecurityProtocolId
257 The value of the "Security Protocol" parameter of
258 the security protocol command to be sent.
259 @param[in] SecurityProtocolSpecificData
260 The value of the "Security Protocol Specific"
261 parameter of the security protocol command to be
263 @param[in] PayloadBufferSize
264 Size in bytes of the payload data buffer.
265 @param[out] PayloadBuffer A pointer to a destination buffer to store the
266 security protocol command specific payload data
267 for the security protocol command. The caller is
268 responsible for having either implicit or explicit
269 ownership of the buffer.
270 @param[out] PayloadTransferSize
271 A pointer to a buffer to store the size in bytes
272 of the data written to the payload data buffer.
274 @retval EFI_SUCCESS The security protocol command completed
276 @retval EFI_WARN_BUFFER_TOO_SMALL The PayloadBufferSize was too small to
277 store the available data from the device.
278 The PayloadBuffer contains the truncated
280 @retval EFI_UNSUPPORTED The given DeviceIndex does not support
281 security protocol commands.
282 @retval EFI_DEVICE_ERROR The security protocol command completed
284 @retval EFI_INVALID_PARAMETER The PayloadBuffer or PayloadTransferSize
285 is NULL and PayloadBufferSize is non-zero.
286 @retval EFI_TIMEOUT A timeout occurred while waiting for the
287 security protocol command to execute.
292 NvmeStorageSecurityReceiveData (
293 IN EDKII_PEI_STORAGE_SECURITY_CMD_PPI
*This
,
294 IN UINTN DeviceIndex
,
296 IN UINT8 SecurityProtocolId
,
297 IN UINT16 SecurityProtocolSpecificData
,
298 IN UINTN PayloadBufferSize
,
299 OUT VOID
*PayloadBuffer
,
300 OUT UINTN
*PayloadTransferSize
303 PEI_NVME_CONTROLLER_PRIVATE_DATA
*Private
;
306 if ((PayloadBuffer
== NULL
) || (PayloadTransferSize
== NULL
) || (PayloadBufferSize
== 0)) {
307 return EFI_INVALID_PARAMETER
;
310 Private
= GET_NVME_PEIM_HC_PRIVATE_DATA_FROM_THIS_STROAGE_SECURITY (This
);
312 Status
= TrustTransferNvmeDevice (
316 SecurityProtocolSpecificData
,
327 Send a security protocol command to a device.
329 The SendData function sends a security protocol command containing the payload
330 PayloadBuffer to the given DeviceIndex. The security protocol command sent is
331 defined by SecurityProtocolId and contains the security protocol specific data
332 SecurityProtocolSpecificData. If the underlying protocol command requires a
333 specific padding for the command payload, the SendData function shall add padding
334 bytes to the command payload to satisfy the padding requirements.
336 For devices supporting the SCSI command set, the security protocol command is
337 sent using the SECURITY PROTOCOL OUT command defined in SPC-4.
339 For devices supporting the ATA command set, the security protocol command is
340 sent using one of the TRUSTED SEND commands defined in ATA8-ACS if PayloadBufferSize
341 is non-zero. If the PayloadBufferSize is zero, the security protocol command
342 is sent using the Trusted Non-Data command defined in ATA8-ACS.
344 If PayloadBuffer is NULL and PayloadBufferSize is non-zero, the function shall
345 return EFI_INVALID_PARAMETER.
347 If the given DeviceIndex does not support security protocol commands, the function
348 shall return EFI_UNSUPPORTED.
350 If the security protocol fails to complete within the Timeout period, the function
351 shall return EFI_TIMEOUT.
353 If the security protocol command completes without an error, the function shall
354 return EFI_SUCCESS. If the security protocol command completes with an error,
355 the functio shall return EFI_DEVICE_ERROR.
357 @param[in] This The PPI instance pointer.
358 @param[in] DeviceIndex The ID of the device.
359 @param[in] Timeout The timeout, in 100ns units, to use for the execution
360 of the security protocol command. A Timeout value
361 of 0 means that this function will wait indefinitely
362 for the security protocol command to execute. If
363 Timeout is greater than zero, then this function
364 will return EFI_TIMEOUT if the time required to
365 execute the receive data command is greater than
367 @param[in] SecurityProtocolId
368 The value of the "Security Protocol" parameter of
369 the security protocol command to be sent.
370 @param[in] SecurityProtocolSpecificData
371 The value of the "Security Protocol Specific"
372 parameter of the security protocol command to be
374 @param[in] PayloadBufferSize Size in bytes of the payload data buffer.
375 @param[in] PayloadBuffer A pointer to a destination buffer to store the
376 security protocol command specific payload data
377 for the security protocol command.
379 @retval EFI_SUCCESS The security protocol command completed successfully.
380 @retval EFI_UNSUPPORTED The given DeviceIndex does not support security
382 @retval EFI_DEVICE_ERROR The security protocol command completed with
384 @retval EFI_INVALID_PARAMETER The PayloadBuffer is NULL and PayloadBufferSize
386 @retval EFI_TIMEOUT A timeout occurred while waiting for the security
387 protocol command to execute.
392 NvmeStorageSecuritySendData (
393 IN EDKII_PEI_STORAGE_SECURITY_CMD_PPI
*This
,
394 IN UINTN DeviceIndex
,
396 IN UINT8 SecurityProtocolId
,
397 IN UINT16 SecurityProtocolSpecificData
,
398 IN UINTN PayloadBufferSize
,
399 IN VOID
*PayloadBuffer
402 PEI_NVME_CONTROLLER_PRIVATE_DATA
*Private
;
405 if ((PayloadBuffer
== NULL
) && (PayloadBufferSize
!= 0)) {
406 return EFI_INVALID_PARAMETER
;
409 Private
= GET_NVME_PEIM_HC_PRIVATE_DATA_FROM_THIS_STROAGE_SECURITY (This
);
411 Status
= TrustTransferNvmeDevice (
415 SecurityProtocolSpecificData
,