2 NvmExpressDxe driver is used to manage non-volatile memory subsystem which follows
3 NVM Express specification.
5 Copyright (c) 2013 - 2018, Intel Corporation. All rights reserved.<BR>
6 SPDX-License-Identifier: BSD-2-Clause-Patent
10 #include "NvmExpress.h"
13 Read some sectors from the device.
15 @param Device The pointer to the NVME_DEVICE_PRIVATE_DATA data structure.
16 @param Buffer The buffer used to store the data read from the device.
17 @param Lba The start block number.
18 @param Blocks Total block number to be read.
20 @retval EFI_SUCCESS Datum are read from the device.
21 @retval Others Fail to read all the datum.
26 IN NVME_DEVICE_PRIVATE_DATA
*Device
,
32 NVME_CONTROLLER_PRIVATE_DATA
*Private
;
34 EFI_NVM_EXPRESS_PASS_THRU_COMMAND_PACKET CommandPacket
;
35 EFI_NVM_EXPRESS_COMMAND Command
;
36 EFI_NVM_EXPRESS_COMPLETION Completion
;
40 Private
= Device
->Controller
;
41 BlockSize
= Device
->Media
.BlockSize
;
42 Bytes
= Blocks
* BlockSize
;
44 ZeroMem (&CommandPacket
, sizeof (EFI_NVM_EXPRESS_PASS_THRU_COMMAND_PACKET
));
45 ZeroMem (&Command
, sizeof (EFI_NVM_EXPRESS_COMMAND
));
46 ZeroMem (&Completion
, sizeof (EFI_NVM_EXPRESS_COMPLETION
));
48 CommandPacket
.NvmeCmd
= &Command
;
49 CommandPacket
.NvmeCompletion
= &Completion
;
51 CommandPacket
.NvmeCmd
->Cdw0
.Opcode
= NVME_IO_READ_OPC
;
52 CommandPacket
.NvmeCmd
->Nsid
= Device
->NamespaceId
;
53 CommandPacket
.TransferBuffer
= (VOID
*)(UINTN
)Buffer
;
55 CommandPacket
.TransferLength
= Bytes
;
56 CommandPacket
.CommandTimeout
= NVME_GENERIC_TIMEOUT
;
57 CommandPacket
.QueueType
= NVME_IO_QUEUE
;
59 CommandPacket
.NvmeCmd
->Cdw10
= (UINT32
)Lba
;
60 CommandPacket
.NvmeCmd
->Cdw11
= (UINT32
)RShiftU64 (Lba
, 32);
61 CommandPacket
.NvmeCmd
->Cdw12
= (Blocks
- 1) & 0xFFFF;
63 CommandPacket
.NvmeCmd
->Flags
= CDW10_VALID
| CDW11_VALID
| CDW12_VALID
;
65 Status
= Private
->Passthru
.PassThru (
76 Write some sectors to the device.
78 @param Device The pointer to the NVME_DEVICE_PRIVATE_DATA data structure.
79 @param Buffer The buffer to be written into the device.
80 @param Lba The start block number.
81 @param Blocks Total block number to be written.
83 @retval EFI_SUCCESS Datum are written into the buffer.
84 @retval Others Fail to write all the datum.
89 IN NVME_DEVICE_PRIVATE_DATA
*Device
,
95 NVME_CONTROLLER_PRIVATE_DATA
*Private
;
96 EFI_NVM_EXPRESS_PASS_THRU_COMMAND_PACKET CommandPacket
;
97 EFI_NVM_EXPRESS_COMMAND Command
;
98 EFI_NVM_EXPRESS_COMPLETION Completion
;
103 Private
= Device
->Controller
;
104 BlockSize
= Device
->Media
.BlockSize
;
105 Bytes
= Blocks
* BlockSize
;
107 ZeroMem (&CommandPacket
, sizeof (EFI_NVM_EXPRESS_PASS_THRU_COMMAND_PACKET
));
108 ZeroMem (&Command
, sizeof (EFI_NVM_EXPRESS_COMMAND
));
109 ZeroMem (&Completion
, sizeof (EFI_NVM_EXPRESS_COMPLETION
));
111 CommandPacket
.NvmeCmd
= &Command
;
112 CommandPacket
.NvmeCompletion
= &Completion
;
114 CommandPacket
.NvmeCmd
->Cdw0
.Opcode
= NVME_IO_WRITE_OPC
;
115 CommandPacket
.NvmeCmd
->Nsid
= Device
->NamespaceId
;
116 CommandPacket
.TransferBuffer
= (VOID
*)(UINTN
)Buffer
;
118 CommandPacket
.TransferLength
= Bytes
;
119 CommandPacket
.CommandTimeout
= NVME_GENERIC_TIMEOUT
;
120 CommandPacket
.QueueType
= NVME_IO_QUEUE
;
122 CommandPacket
.NvmeCmd
->Cdw10
= (UINT32
)Lba
;
123 CommandPacket
.NvmeCmd
->Cdw11
= (UINT32
)RShiftU64 (Lba
, 32);
125 // Set Force Unit Access bit (bit 30) to use write-through behaviour
127 CommandPacket
.NvmeCmd
->Cdw12
= ((Blocks
- 1) & 0xFFFF) | BIT30
;
129 CommandPacket
.MetadataBuffer
= NULL
;
130 CommandPacket
.MetadataLength
= 0;
132 CommandPacket
.NvmeCmd
->Flags
= CDW10_VALID
| CDW11_VALID
| CDW12_VALID
;
134 Status
= Private
->Passthru
.PassThru (
145 Read some blocks from the device.
147 @param Device The pointer to the NVME_DEVICE_PRIVATE_DATA data structure.
148 @param Buffer The buffer used to store the data read from the device.
149 @param Lba The start block number.
150 @param Blocks Total block number to be read.
152 @retval EFI_SUCCESS Datum are read from the device.
153 @retval Others Fail to read all the datum.
158 IN NVME_DEVICE_PRIVATE_DATA
*Device
,
166 NVME_CONTROLLER_PRIVATE_DATA
*Private
;
167 UINT32 MaxTransferBlocks
;
173 // Wait for the device's asynchronous I/O queue to become empty.
176 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
177 IsEmpty
= IsListEmpty (&Device
->AsyncQueue
);
178 gBS
->RestoreTPL (OldTpl
);
187 Status
= EFI_SUCCESS
;
188 Private
= Device
->Controller
;
189 BlockSize
= Device
->Media
.BlockSize
;
190 OrginalBlocks
= Blocks
;
192 if (Private
->ControllerData
->Mdts
!= 0) {
193 MaxTransferBlocks
= (1 << (Private
->ControllerData
->Mdts
)) * (1 << (Private
->Cap
.Mpsmin
+ 12)) / BlockSize
;
195 MaxTransferBlocks
= 1024;
199 if (Blocks
> MaxTransferBlocks
) {
200 Status
= ReadSectors (Device
, (UINT64
)(UINTN
)Buffer
, Lba
, MaxTransferBlocks
);
202 Blocks
-= MaxTransferBlocks
;
203 Buffer
= (VOID
*)(UINTN
)((UINT64
)(UINTN
)Buffer
+ MaxTransferBlocks
* BlockSize
);
204 Lba
+= MaxTransferBlocks
;
206 Status
= ReadSectors (Device
, (UINT64
)(UINTN
)Buffer
, Lba
, (UINT32
)Blocks
);
210 if (EFI_ERROR (Status
)) {
217 "%a: Lba = 0x%08Lx, Original = 0x%08Lx, "
218 "Remaining = 0x%08Lx, BlockSize = 0x%x, Status = %r\n",
221 (UINT64
)OrginalBlocks
,
231 Write some blocks to the device.
233 @param Device The pointer to the NVME_DEVICE_PRIVATE_DATA data structure.
234 @param Buffer The buffer to be written into the device.
235 @param Lba The start block number.
236 @param Blocks Total block number to be written.
238 @retval EFI_SUCCESS Datum are written into the buffer.
239 @retval Others Fail to write all the datum.
244 IN NVME_DEVICE_PRIVATE_DATA
*Device
,
252 NVME_CONTROLLER_PRIVATE_DATA
*Private
;
253 UINT32 MaxTransferBlocks
;
259 // Wait for the device's asynchronous I/O queue to become empty.
262 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
263 IsEmpty
= IsListEmpty (&Device
->AsyncQueue
);
264 gBS
->RestoreTPL (OldTpl
);
273 Status
= EFI_SUCCESS
;
274 Private
= Device
->Controller
;
275 BlockSize
= Device
->Media
.BlockSize
;
276 OrginalBlocks
= Blocks
;
278 if (Private
->ControllerData
->Mdts
!= 0) {
279 MaxTransferBlocks
= (1 << (Private
->ControllerData
->Mdts
)) * (1 << (Private
->Cap
.Mpsmin
+ 12)) / BlockSize
;
281 MaxTransferBlocks
= 1024;
285 if (Blocks
> MaxTransferBlocks
) {
286 Status
= WriteSectors (Device
, (UINT64
)(UINTN
)Buffer
, Lba
, MaxTransferBlocks
);
288 Blocks
-= MaxTransferBlocks
;
289 Buffer
= (VOID
*)(UINTN
)((UINT64
)(UINTN
)Buffer
+ MaxTransferBlocks
* BlockSize
);
290 Lba
+= MaxTransferBlocks
;
292 Status
= WriteSectors (Device
, (UINT64
)(UINTN
)Buffer
, Lba
, (UINT32
)Blocks
);
296 if (EFI_ERROR (Status
)) {
303 "%a: Lba = 0x%08Lx, Original = 0x%08Lx, "
304 "Remaining = 0x%08Lx, BlockSize = 0x%x, Status = %r\n",
307 (UINT64
)OrginalBlocks
,
317 Flushes all modified data to the device.
319 @param Device The pointer to the NVME_DEVICE_PRIVATE_DATA data structure.
321 @retval EFI_SUCCESS Datum are written into the buffer.
322 @retval Others Fail to write all the datum.
327 IN NVME_DEVICE_PRIVATE_DATA
*Device
330 NVME_CONTROLLER_PRIVATE_DATA
*Private
;
331 EFI_NVM_EXPRESS_PASS_THRU_COMMAND_PACKET CommandPacket
;
332 EFI_NVM_EXPRESS_COMMAND Command
;
333 EFI_NVM_EXPRESS_COMPLETION Completion
;
336 Private
= Device
->Controller
;
338 ZeroMem (&CommandPacket
, sizeof (EFI_NVM_EXPRESS_PASS_THRU_COMMAND_PACKET
));
339 ZeroMem (&Command
, sizeof (EFI_NVM_EXPRESS_COMMAND
));
340 ZeroMem (&Completion
, sizeof (EFI_NVM_EXPRESS_COMPLETION
));
342 CommandPacket
.NvmeCmd
= &Command
;
343 CommandPacket
.NvmeCompletion
= &Completion
;
345 CommandPacket
.NvmeCmd
->Cdw0
.Opcode
= NVME_IO_FLUSH_OPC
;
346 CommandPacket
.NvmeCmd
->Nsid
= Device
->NamespaceId
;
347 CommandPacket
.CommandTimeout
= NVME_GENERIC_TIMEOUT
;
348 CommandPacket
.QueueType
= NVME_IO_QUEUE
;
350 Status
= Private
->Passthru
.PassThru (
361 Nonblocking I/O callback funtion when the event is signaled.
363 @param[in] Event The Event this notify function registered to.
364 @param[in] Context Pointer to the context data registered to the
375 NVME_BLKIO2_SUBTASK
*Subtask
;
376 NVME_BLKIO2_REQUEST
*Request
;
378 EFI_BLOCK_IO2_TOKEN
*Token
;
380 gBS
->CloseEvent (Event
);
382 Subtask
= (NVME_BLKIO2_SUBTASK
*)Context
;
383 Completion
= (NVME_CQ
*)Subtask
->CommandPacket
->NvmeCompletion
;
384 Request
= Subtask
->BlockIo2Request
;
385 Token
= Request
->Token
;
387 if (Token
->TransactionStatus
== EFI_SUCCESS
) {
389 // If previous subtask already fails, do not check the result of
390 // subsequent subtasks.
392 if ((Completion
->Sct
!= 0) || (Completion
->Sc
!= 0)) {
393 Token
->TransactionStatus
= EFI_DEVICE_ERROR
;
396 // Dump completion entry status for debugging.
399 NvmeDumpStatus (Completion
);
405 // Remove the subtask from the BlockIo2 subtasks list.
407 RemoveEntryList (&Subtask
->Link
);
409 if (IsListEmpty (&Request
->SubtasksQueue
) && Request
->LastSubtaskSubmitted
) {
411 // Remove the BlockIo2 request from the device asynchronous queue.
413 RemoveEntryList (&Request
->Link
);
415 gBS
->SignalEvent (Token
->Event
);
418 FreePool (Subtask
->CommandPacket
->NvmeCmd
);
419 FreePool (Subtask
->CommandPacket
->NvmeCompletion
);
420 FreePool (Subtask
->CommandPacket
);
425 Read some sectors from the device in an asynchronous manner.
427 @param Device The pointer to the NVME_DEVICE_PRIVATE_DATA data
429 @param Request The pointer to the NVME_BLKIO2_REQUEST data structure.
430 @param Buffer The buffer used to store the data read from the device.
431 @param Lba The start block number.
432 @param Blocks Total block number to be read.
433 @param IsLast The last subtask of an asynchronous read request.
435 @retval EFI_SUCCESS Asynchronous read request has been queued.
436 @retval Others Fail to send the asynchronous request.
441 IN NVME_DEVICE_PRIVATE_DATA
*Device
,
442 IN NVME_BLKIO2_REQUEST
*Request
,
449 NVME_CONTROLLER_PRIVATE_DATA
*Private
;
451 NVME_BLKIO2_SUBTASK
*Subtask
;
452 EFI_NVM_EXPRESS_PASS_THRU_COMMAND_PACKET
*CommandPacket
;
453 EFI_NVM_EXPRESS_COMMAND
*Command
;
454 EFI_NVM_EXPRESS_COMPLETION
*Completion
;
459 Private
= Device
->Controller
;
460 BlockSize
= Device
->Media
.BlockSize
;
461 Bytes
= Blocks
* BlockSize
;
462 CommandPacket
= NULL
;
466 Subtask
= AllocateZeroPool (sizeof (NVME_BLKIO2_SUBTASK
));
467 if (Subtask
== NULL
) {
468 Status
= EFI_OUT_OF_RESOURCES
;
472 Subtask
->Signature
= NVME_BLKIO2_SUBTASK_SIGNATURE
;
473 Subtask
->IsLast
= IsLast
;
474 Subtask
->NamespaceId
= Device
->NamespaceId
;
475 Subtask
->BlockIo2Request
= Request
;
477 CommandPacket
= AllocateZeroPool (sizeof (EFI_NVM_EXPRESS_PASS_THRU_COMMAND_PACKET
));
478 if (CommandPacket
== NULL
) {
479 Status
= EFI_OUT_OF_RESOURCES
;
482 Subtask
->CommandPacket
= CommandPacket
;
485 Command
= AllocateZeroPool (sizeof (EFI_NVM_EXPRESS_COMMAND
));
486 if (Command
== NULL
) {
487 Status
= EFI_OUT_OF_RESOURCES
;
491 Completion
= AllocateZeroPool (sizeof (EFI_NVM_EXPRESS_COMPLETION
));
492 if (Completion
== NULL
) {
493 Status
= EFI_OUT_OF_RESOURCES
;
500 Status
= gBS
->CreateEvent (
507 if (EFI_ERROR (Status
)) {
511 CommandPacket
->NvmeCmd
= Command
;
512 CommandPacket
->NvmeCompletion
= Completion
;
514 CommandPacket
->NvmeCmd
->Cdw0
.Opcode
= NVME_IO_READ_OPC
;
515 CommandPacket
->NvmeCmd
->Nsid
= Device
->NamespaceId
;
516 CommandPacket
->TransferBuffer
= (VOID
*)(UINTN
)Buffer
;
518 CommandPacket
->TransferLength
= Bytes
;
519 CommandPacket
->CommandTimeout
= NVME_GENERIC_TIMEOUT
;
520 CommandPacket
->QueueType
= NVME_IO_QUEUE
;
522 CommandPacket
->NvmeCmd
->Cdw10
= (UINT32
)Lba
;
523 CommandPacket
->NvmeCmd
->Cdw11
= (UINT32
)RShiftU64 (Lba
, 32);
524 CommandPacket
->NvmeCmd
->Cdw12
= (Blocks
- 1) & 0xFFFF;
526 CommandPacket
->NvmeCmd
->Flags
= CDW10_VALID
| CDW11_VALID
| CDW12_VALID
;
528 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
529 InsertTailList (&Private
->UnsubmittedSubtasks
, &Subtask
->Link
);
530 Request
->UnsubmittedSubtaskNum
++;
531 gBS
->RestoreTPL (OldTpl
);
537 // Resource cleanup if asynchronous read request has not been queued.
539 if (Completion
!= NULL
) {
540 FreePool (Completion
);
543 if (Command
!= NULL
) {
547 if (CommandPacket
!= NULL
) {
548 FreePool (CommandPacket
);
551 if (Subtask
!= NULL
) {
552 if (Subtask
->Event
!= NULL
) {
553 gBS
->CloseEvent (Subtask
->Event
);
563 Write some sectors from the device in an asynchronous manner.
565 @param Device The pointer to the NVME_DEVICE_PRIVATE_DATA data
567 @param Request The pointer to the NVME_BLKIO2_REQUEST data structure.
568 @param Buffer The buffer used to store the data written to the
570 @param Lba The start block number.
571 @param Blocks Total block number to be written.
572 @param IsLast The last subtask of an asynchronous write request.
574 @retval EFI_SUCCESS Asynchronous write request has been queued.
575 @retval Others Fail to send the asynchronous request.
580 IN NVME_DEVICE_PRIVATE_DATA
*Device
,
581 IN NVME_BLKIO2_REQUEST
*Request
,
588 NVME_CONTROLLER_PRIVATE_DATA
*Private
;
590 NVME_BLKIO2_SUBTASK
*Subtask
;
591 EFI_NVM_EXPRESS_PASS_THRU_COMMAND_PACKET
*CommandPacket
;
592 EFI_NVM_EXPRESS_COMMAND
*Command
;
593 EFI_NVM_EXPRESS_COMPLETION
*Completion
;
598 Private
= Device
->Controller
;
599 BlockSize
= Device
->Media
.BlockSize
;
600 Bytes
= Blocks
* BlockSize
;
601 CommandPacket
= NULL
;
605 Subtask
= AllocateZeroPool (sizeof (NVME_BLKIO2_SUBTASK
));
606 if (Subtask
== NULL
) {
607 Status
= EFI_OUT_OF_RESOURCES
;
611 Subtask
->Signature
= NVME_BLKIO2_SUBTASK_SIGNATURE
;
612 Subtask
->IsLast
= IsLast
;
613 Subtask
->NamespaceId
= Device
->NamespaceId
;
614 Subtask
->BlockIo2Request
= Request
;
616 CommandPacket
= AllocateZeroPool (sizeof (EFI_NVM_EXPRESS_PASS_THRU_COMMAND_PACKET
));
617 if (CommandPacket
== NULL
) {
618 Status
= EFI_OUT_OF_RESOURCES
;
621 Subtask
->CommandPacket
= CommandPacket
;
624 Command
= AllocateZeroPool (sizeof (EFI_NVM_EXPRESS_COMMAND
));
625 if (Command
== NULL
) {
626 Status
= EFI_OUT_OF_RESOURCES
;
630 Completion
= AllocateZeroPool (sizeof (EFI_NVM_EXPRESS_COMPLETION
));
631 if (Completion
== NULL
) {
632 Status
= EFI_OUT_OF_RESOURCES
;
639 Status
= gBS
->CreateEvent (
646 if (EFI_ERROR (Status
)) {
650 CommandPacket
->NvmeCmd
= Command
;
651 CommandPacket
->NvmeCompletion
= Completion
;
653 CommandPacket
->NvmeCmd
->Cdw0
.Opcode
= NVME_IO_WRITE_OPC
;
654 CommandPacket
->NvmeCmd
->Nsid
= Device
->NamespaceId
;
655 CommandPacket
->TransferBuffer
= (VOID
*)(UINTN
)Buffer
;
657 CommandPacket
->TransferLength
= Bytes
;
658 CommandPacket
->CommandTimeout
= NVME_GENERIC_TIMEOUT
;
659 CommandPacket
->QueueType
= NVME_IO_QUEUE
;
661 CommandPacket
->NvmeCmd
->Cdw10
= (UINT32
)Lba
;
662 CommandPacket
->NvmeCmd
->Cdw11
= (UINT32
)RShiftU64 (Lba
, 32);
664 // Set Force Unit Access bit (bit 30) to use write-through behaviour
666 CommandPacket
->NvmeCmd
->Cdw12
= ((Blocks
- 1) & 0xFFFF) | BIT30
;
668 CommandPacket
->NvmeCmd
->Flags
= CDW10_VALID
| CDW11_VALID
| CDW12_VALID
;
670 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
671 InsertTailList (&Private
->UnsubmittedSubtasks
, &Subtask
->Link
);
672 Request
->UnsubmittedSubtaskNum
++;
673 gBS
->RestoreTPL (OldTpl
);
679 // Resource cleanup if asynchronous read request has not been queued.
681 if (Completion
!= NULL
) {
682 FreePool (Completion
);
685 if (Command
!= NULL
) {
689 if (CommandPacket
!= NULL
) {
690 FreePool (CommandPacket
);
693 if (Subtask
!= NULL
) {
694 if (Subtask
->Event
!= NULL
) {
695 gBS
->CloseEvent (Subtask
->Event
);
705 Read some blocks from the device in an asynchronous manner.
707 @param Device The pointer to the NVME_DEVICE_PRIVATE_DATA data
709 @param Buffer The buffer used to store the data read from the device.
710 @param Lba The start block number.
711 @param Blocks Total block number to be read.
712 @param Token A pointer to the token associated with the transaction.
714 @retval EFI_SUCCESS Data are read from the device.
715 @retval Others Fail to read all the data.
720 IN NVME_DEVICE_PRIVATE_DATA
*Device
,
724 IN EFI_BLOCK_IO2_TOKEN
*Token
729 NVME_CONTROLLER_PRIVATE_DATA
*Private
;
730 NVME_BLKIO2_REQUEST
*BlkIo2Req
;
731 UINT32 MaxTransferBlocks
;
736 Status
= EFI_SUCCESS
;
737 Private
= Device
->Controller
;
738 BlockSize
= Device
->Media
.BlockSize
;
739 OrginalBlocks
= Blocks
;
740 BlkIo2Req
= AllocateZeroPool (sizeof (NVME_BLKIO2_REQUEST
));
741 if (BlkIo2Req
== NULL
) {
742 return EFI_OUT_OF_RESOURCES
;
745 BlkIo2Req
->Signature
= NVME_BLKIO2_REQUEST_SIGNATURE
;
746 BlkIo2Req
->Token
= Token
;
748 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
749 InsertTailList (&Device
->AsyncQueue
, &BlkIo2Req
->Link
);
750 gBS
->RestoreTPL (OldTpl
);
752 InitializeListHead (&BlkIo2Req
->SubtasksQueue
);
754 if (Private
->ControllerData
->Mdts
!= 0) {
755 MaxTransferBlocks
= (1 << (Private
->ControllerData
->Mdts
)) * (1 << (Private
->Cap
.Mpsmin
+ 12)) / BlockSize
;
757 MaxTransferBlocks
= 1024;
761 if (Blocks
> MaxTransferBlocks
) {
762 Status
= AsyncReadSectors (
765 (UINT64
)(UINTN
)Buffer
,
771 Blocks
-= MaxTransferBlocks
;
772 Buffer
= (VOID
*)(UINTN
)((UINT64
)(UINTN
)Buffer
+ MaxTransferBlocks
* BlockSize
);
773 Lba
+= MaxTransferBlocks
;
775 Status
= AsyncReadSectors (
778 (UINT64
)(UINTN
)Buffer
,
787 if (EFI_ERROR (Status
)) {
788 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
789 IsEmpty
= IsListEmpty (&BlkIo2Req
->SubtasksQueue
) &&
790 (BlkIo2Req
->UnsubmittedSubtaskNum
== 0);
794 // Remove the BlockIo2 request from the device asynchronous queue.
796 RemoveEntryList (&BlkIo2Req
->Link
);
797 FreePool (BlkIo2Req
);
798 Status
= EFI_DEVICE_ERROR
;
801 // There are previous BlockIo2 subtasks still running, EFI_SUCCESS
802 // should be returned to make sure that the caller does not free
803 // resources still using by these requests.
805 Status
= EFI_SUCCESS
;
806 Token
->TransactionStatus
= EFI_DEVICE_ERROR
;
807 BlkIo2Req
->LastSubtaskSubmitted
= TRUE
;
810 gBS
->RestoreTPL (OldTpl
);
818 "%a: Lba = 0x%08Lx, Original = 0x%08Lx, "
819 "Remaining = 0x%08Lx, BlockSize = 0x%x, Status = %r\n",
822 (UINT64
)OrginalBlocks
,
832 Write some blocks from the device in an asynchronous manner.
834 @param Device The pointer to the NVME_DEVICE_PRIVATE_DATA data
836 @param Buffer The buffer used to store the data written to the
838 @param Lba The start block number.
839 @param Blocks Total block number to be written.
840 @param Token A pointer to the token associated with the transaction.
842 @retval EFI_SUCCESS Data are written to the device.
843 @retval Others Fail to write all the data.
848 IN NVME_DEVICE_PRIVATE_DATA
*Device
,
852 IN EFI_BLOCK_IO2_TOKEN
*Token
857 NVME_CONTROLLER_PRIVATE_DATA
*Private
;
858 NVME_BLKIO2_REQUEST
*BlkIo2Req
;
859 UINT32 MaxTransferBlocks
;
864 Status
= EFI_SUCCESS
;
865 Private
= Device
->Controller
;
866 BlockSize
= Device
->Media
.BlockSize
;
867 OrginalBlocks
= Blocks
;
868 BlkIo2Req
= AllocateZeroPool (sizeof (NVME_BLKIO2_REQUEST
));
869 if (BlkIo2Req
== NULL
) {
870 return EFI_OUT_OF_RESOURCES
;
873 BlkIo2Req
->Signature
= NVME_BLKIO2_REQUEST_SIGNATURE
;
874 BlkIo2Req
->Token
= Token
;
876 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
877 InsertTailList (&Device
->AsyncQueue
, &BlkIo2Req
->Link
);
878 gBS
->RestoreTPL (OldTpl
);
880 InitializeListHead (&BlkIo2Req
->SubtasksQueue
);
882 if (Private
->ControllerData
->Mdts
!= 0) {
883 MaxTransferBlocks
= (1 << (Private
->ControllerData
->Mdts
)) * (1 << (Private
->Cap
.Mpsmin
+ 12)) / BlockSize
;
885 MaxTransferBlocks
= 1024;
889 if (Blocks
> MaxTransferBlocks
) {
890 Status
= AsyncWriteSectors (
893 (UINT64
)(UINTN
)Buffer
,
899 Blocks
-= MaxTransferBlocks
;
900 Buffer
= (VOID
*)(UINTN
)((UINT64
)(UINTN
)Buffer
+ MaxTransferBlocks
* BlockSize
);
901 Lba
+= MaxTransferBlocks
;
903 Status
= AsyncWriteSectors (
906 (UINT64
)(UINTN
)Buffer
,
915 if (EFI_ERROR (Status
)) {
916 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
917 IsEmpty
= IsListEmpty (&BlkIo2Req
->SubtasksQueue
) &&
918 (BlkIo2Req
->UnsubmittedSubtaskNum
== 0);
922 // Remove the BlockIo2 request from the device asynchronous queue.
924 RemoveEntryList (&BlkIo2Req
->Link
);
925 FreePool (BlkIo2Req
);
926 Status
= EFI_DEVICE_ERROR
;
929 // There are previous BlockIo2 subtasks still running, EFI_SUCCESS
930 // should be returned to make sure that the caller does not free
931 // resources still using by these requests.
933 Status
= EFI_SUCCESS
;
934 Token
->TransactionStatus
= EFI_DEVICE_ERROR
;
935 BlkIo2Req
->LastSubtaskSubmitted
= TRUE
;
938 gBS
->RestoreTPL (OldTpl
);
946 "%a: Lba = 0x%08Lx, Original = 0x%08Lx, "
947 "Remaining = 0x%08Lx, BlockSize = 0x%x, Status = %r\n",
950 (UINT64
)OrginalBlocks
,
960 Reset the Block Device.
962 @param This Indicates a pointer to the calling context.
963 @param ExtendedVerification Driver may perform diagnostics on reset.
965 @retval EFI_SUCCESS The device was reset.
966 @retval EFI_DEVICE_ERROR The device is not functioning properly and could
973 IN EFI_BLOCK_IO_PROTOCOL
*This
,
974 IN BOOLEAN ExtendedVerification
978 NVME_CONTROLLER_PRIVATE_DATA
*Private
;
979 NVME_DEVICE_PRIVATE_DATA
*Device
;
983 return EFI_INVALID_PARAMETER
;
987 // For Nvm Express subsystem, reset block device means reset controller.
989 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
991 Device
= NVME_DEVICE_PRIVATE_DATA_FROM_BLOCK_IO (This
);
993 Private
= Device
->Controller
;
995 Status
= NvmeControllerInit (Private
);
997 if (EFI_ERROR (Status
)) {
998 Status
= EFI_DEVICE_ERROR
;
1001 gBS
->RestoreTPL (OldTpl
);
1007 Read BufferSize bytes from Lba into Buffer.
1009 @param This Indicates a pointer to the calling context.
1010 @param MediaId Id of the media, changes every time the media is replaced.
1011 @param Lba The starting Logical Block Address to read from.
1012 @param BufferSize Size of Buffer, must be a multiple of device block size.
1013 @param Buffer A pointer to the destination buffer for the data. The caller is
1014 responsible for either having implicit or explicit ownership of the buffer.
1016 @retval EFI_SUCCESS The data was read correctly from the device.
1017 @retval EFI_DEVICE_ERROR The device reported an error while performing the read.
1018 @retval EFI_NO_MEDIA There is no media in the device.
1019 @retval EFI_MEDIA_CHANGED The MediaId does not matched the current device.
1020 @retval EFI_BAD_BUFFER_SIZE The Buffer was not a multiple of the block size of the device.
1021 @retval EFI_INVALID_PARAMETER The read request contains LBAs that are not valid,
1022 or the buffer is not on proper alignment.
1027 NvmeBlockIoReadBlocks (
1028 IN EFI_BLOCK_IO_PROTOCOL
*This
,
1031 IN UINTN BufferSize
,
1035 NVME_DEVICE_PRIVATE_DATA
*Device
;
1037 EFI_BLOCK_IO_MEDIA
*Media
;
1039 UINTN NumberOfBlocks
;
1044 // Check parameters.
1047 return EFI_INVALID_PARAMETER
;
1050 Media
= This
->Media
;
1052 if (MediaId
!= Media
->MediaId
) {
1053 return EFI_MEDIA_CHANGED
;
1056 if (Buffer
== NULL
) {
1057 return EFI_INVALID_PARAMETER
;
1060 if (BufferSize
== 0) {
1064 BlockSize
= Media
->BlockSize
;
1065 if ((BufferSize
% BlockSize
) != 0) {
1066 return EFI_BAD_BUFFER_SIZE
;
1069 NumberOfBlocks
= BufferSize
/ BlockSize
;
1070 if ((Lba
+ NumberOfBlocks
- 1) > Media
->LastBlock
) {
1071 return EFI_INVALID_PARAMETER
;
1074 IoAlign
= Media
->IoAlign
;
1075 if ((IoAlign
> 0) && (((UINTN
)Buffer
& (IoAlign
- 1)) != 0)) {
1076 return EFI_INVALID_PARAMETER
;
1079 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
1081 Device
= NVME_DEVICE_PRIVATE_DATA_FROM_BLOCK_IO (This
);
1083 Status
= NvmeRead (Device
, Buffer
, Lba
, NumberOfBlocks
);
1085 gBS
->RestoreTPL (OldTpl
);
1090 Write BufferSize bytes from Lba into Buffer.
1092 @param This Indicates a pointer to the calling context.
1093 @param MediaId The media ID that the write request is for.
1094 @param Lba The starting logical block address to be written. The caller is
1095 responsible for writing to only legitimate locations.
1096 @param BufferSize Size of Buffer, must be a multiple of device block size.
1097 @param Buffer A pointer to the source buffer for the data.
1099 @retval EFI_SUCCESS The data was written correctly to the device.
1100 @retval EFI_WRITE_PROTECTED The device can not be written to.
1101 @retval EFI_DEVICE_ERROR The device reported an error while performing the write.
1102 @retval EFI_NO_MEDIA There is no media in the device.
1103 @retval EFI_MEDIA_CHNAGED The MediaId does not matched the current device.
1104 @retval EFI_BAD_BUFFER_SIZE The Buffer was not a multiple of the block size of the device.
1105 @retval EFI_INVALID_PARAMETER The write request contains LBAs that are not valid,
1106 or the buffer is not on proper alignment.
1111 NvmeBlockIoWriteBlocks (
1112 IN EFI_BLOCK_IO_PROTOCOL
*This
,
1115 IN UINTN BufferSize
,
1119 NVME_DEVICE_PRIVATE_DATA
*Device
;
1121 EFI_BLOCK_IO_MEDIA
*Media
;
1123 UINTN NumberOfBlocks
;
1128 // Check parameters.
1131 return EFI_INVALID_PARAMETER
;
1134 Media
= This
->Media
;
1136 if (MediaId
!= Media
->MediaId
) {
1137 return EFI_MEDIA_CHANGED
;
1140 if (Buffer
== NULL
) {
1141 return EFI_INVALID_PARAMETER
;
1144 if (BufferSize
== 0) {
1148 BlockSize
= Media
->BlockSize
;
1149 if ((BufferSize
% BlockSize
) != 0) {
1150 return EFI_BAD_BUFFER_SIZE
;
1153 NumberOfBlocks
= BufferSize
/ BlockSize
;
1154 if ((Lba
+ NumberOfBlocks
- 1) > Media
->LastBlock
) {
1155 return EFI_INVALID_PARAMETER
;
1158 IoAlign
= Media
->IoAlign
;
1159 if ((IoAlign
> 0) && (((UINTN
)Buffer
& (IoAlign
- 1)) != 0)) {
1160 return EFI_INVALID_PARAMETER
;
1163 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
1165 Device
= NVME_DEVICE_PRIVATE_DATA_FROM_BLOCK_IO (This
);
1167 Status
= NvmeWrite (Device
, Buffer
, Lba
, NumberOfBlocks
);
1169 gBS
->RestoreTPL (OldTpl
);
1175 Flush the Block Device.
1177 @param This Indicates a pointer to the calling context.
1179 @retval EFI_SUCCESS All outstanding data was written to the device.
1180 @retval EFI_DEVICE_ERROR The device reported an error while writing back the data.
1181 @retval EFI_NO_MEDIA There is no media in the device.
1186 NvmeBlockIoFlushBlocks (
1187 IN EFI_BLOCK_IO_PROTOCOL
*This
1190 NVME_DEVICE_PRIVATE_DATA
*Device
;
1195 // Check parameters.
1198 return EFI_INVALID_PARAMETER
;
1201 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
1203 Device
= NVME_DEVICE_PRIVATE_DATA_FROM_BLOCK_IO (This
);
1205 Status
= NvmeFlush (Device
);
1207 gBS
->RestoreTPL (OldTpl
);
1213 Reset the block device hardware.
1215 @param[in] This Indicates a pointer to the calling context.
1216 @param[in] ExtendedVerification Indicates that the driver may perform a more
1217 exhausive verfication operation of the
1218 device during reset.
1220 @retval EFI_SUCCESS The device was reset.
1221 @retval EFI_DEVICE_ERROR The device is not functioning properly and could
1227 NvmeBlockIoResetEx (
1228 IN EFI_BLOCK_IO2_PROTOCOL
*This
,
1229 IN BOOLEAN ExtendedVerification
1233 NVME_DEVICE_PRIVATE_DATA
*Device
;
1234 NVME_CONTROLLER_PRIVATE_DATA
*Private
;
1239 return EFI_INVALID_PARAMETER
;
1242 Device
= NVME_DEVICE_PRIVATE_DATA_FROM_BLOCK_IO2 (This
);
1243 Private
= Device
->Controller
;
1246 // Wait for the asynchronous PassThru queue to become empty.
1249 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
1250 IsEmpty
= IsListEmpty (&Private
->AsyncPassThruQueue
) &&
1251 IsListEmpty (&Private
->UnsubmittedSubtasks
);
1252 gBS
->RestoreTPL (OldTpl
);
1261 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
1263 Status
= NvmeControllerInit (Private
);
1265 if (EFI_ERROR (Status
)) {
1266 Status
= EFI_DEVICE_ERROR
;
1269 gBS
->RestoreTPL (OldTpl
);
1275 Read BufferSize bytes from Lba into Buffer.
1277 This function reads the requested number of blocks from the device. All the
1278 blocks are read, or an error is returned.
1279 If EFI_DEVICE_ERROR, EFI_NO_MEDIA,_or EFI_MEDIA_CHANGED is returned and
1280 non-blocking I/O is being used, the Event associated with this request will
1283 @param[in] This Indicates a pointer to the calling context.
1284 @param[in] MediaId Id of the media, changes every time the media is
1286 @param[in] Lba The starting Logical Block Address to read from.
1287 @param[in, out] Token A pointer to the token associated with the
1289 @param[in] BufferSize Size of Buffer, must be a multiple of device
1291 @param[out] Buffer A pointer to the destination buffer for the data.
1292 The caller is responsible for either having
1293 implicit or explicit ownership of the buffer.
1295 @retval EFI_SUCCESS The read request was queued if Token->Event is
1296 not NULL.The data was read correctly from the
1297 device if the Token->Event is NULL.
1298 @retval EFI_DEVICE_ERROR The device reported an error while performing
1300 @retval EFI_NO_MEDIA There is no media in the device.
1301 @retval EFI_MEDIA_CHANGED The MediaId is not for the current media.
1302 @retval EFI_BAD_BUFFER_SIZE The BufferSize parameter is not a multiple of
1303 the intrinsic block size of the device.
1304 @retval EFI_INVALID_PARAMETER The read request contains LBAs that are not
1305 valid, or the buffer is not on proper
1307 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a
1313 NvmeBlockIoReadBlocksEx (
1314 IN EFI_BLOCK_IO2_PROTOCOL
*This
,
1317 IN OUT EFI_BLOCK_IO2_TOKEN
*Token
,
1318 IN UINTN BufferSize
,
1322 NVME_DEVICE_PRIVATE_DATA
*Device
;
1324 EFI_BLOCK_IO_MEDIA
*Media
;
1326 UINTN NumberOfBlocks
;
1331 // Check parameters.
1334 return EFI_INVALID_PARAMETER
;
1337 Media
= This
->Media
;
1339 if (MediaId
!= Media
->MediaId
) {
1340 return EFI_MEDIA_CHANGED
;
1343 if (Buffer
== NULL
) {
1344 return EFI_INVALID_PARAMETER
;
1347 if (BufferSize
== 0) {
1348 if ((Token
!= NULL
) && (Token
->Event
!= NULL
)) {
1349 Token
->TransactionStatus
= EFI_SUCCESS
;
1350 gBS
->SignalEvent (Token
->Event
);
1356 BlockSize
= Media
->BlockSize
;
1357 if ((BufferSize
% BlockSize
) != 0) {
1358 return EFI_BAD_BUFFER_SIZE
;
1361 NumberOfBlocks
= BufferSize
/ BlockSize
;
1362 if ((Lba
+ NumberOfBlocks
- 1) > Media
->LastBlock
) {
1363 return EFI_INVALID_PARAMETER
;
1366 IoAlign
= Media
->IoAlign
;
1367 if ((IoAlign
> 0) && (((UINTN
)Buffer
& (IoAlign
- 1)) != 0)) {
1368 return EFI_INVALID_PARAMETER
;
1371 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
1373 Device
= NVME_DEVICE_PRIVATE_DATA_FROM_BLOCK_IO2 (This
);
1375 if ((Token
!= NULL
) && (Token
->Event
!= NULL
)) {
1376 Token
->TransactionStatus
= EFI_SUCCESS
;
1377 Status
= NvmeAsyncRead (Device
, Buffer
, Lba
, NumberOfBlocks
, Token
);
1379 Status
= NvmeRead (Device
, Buffer
, Lba
, NumberOfBlocks
);
1382 gBS
->RestoreTPL (OldTpl
);
1387 Write BufferSize bytes from Lba into Buffer.
1389 This function writes the requested number of blocks to the device. All blocks
1390 are written, or an error is returned.If EFI_DEVICE_ERROR, EFI_NO_MEDIA,
1391 EFI_WRITE_PROTECTED or EFI_MEDIA_CHANGED is returned and non-blocking I/O is
1392 being used, the Event associated with this request will not be signaled.
1394 @param[in] This Indicates a pointer to the calling context.
1395 @param[in] MediaId The media ID that the write request is for.
1396 @param[in] Lba The starting logical block address to be written.
1397 The caller is responsible for writing to only
1398 legitimate locations.
1399 @param[in, out] Token A pointer to the token associated with the
1401 @param[in] BufferSize Size of Buffer, must be a multiple of device
1403 @param[in] Buffer A pointer to the source buffer for the data.
1405 @retval EFI_SUCCESS The write request was queued if Event is not
1407 The data was written correctly to the device if
1409 @retval EFI_WRITE_PROTECTED The device can not be written to.
1410 @retval EFI_NO_MEDIA There is no media in the device.
1411 @retval EFI_MEDIA_CHNAGED The MediaId does not matched the current
1413 @retval EFI_DEVICE_ERROR The device reported an error while performing
1415 @retval EFI_BAD_BUFFER_SIZE The Buffer was not a multiple of the block size
1417 @retval EFI_INVALID_PARAMETER The write request contains LBAs that are not
1418 valid, or the buffer is not on proper
1420 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a
1426 NvmeBlockIoWriteBlocksEx (
1427 IN EFI_BLOCK_IO2_PROTOCOL
*This
,
1430 IN OUT EFI_BLOCK_IO2_TOKEN
*Token
,
1431 IN UINTN BufferSize
,
1435 NVME_DEVICE_PRIVATE_DATA
*Device
;
1437 EFI_BLOCK_IO_MEDIA
*Media
;
1439 UINTN NumberOfBlocks
;
1444 // Check parameters.
1447 return EFI_INVALID_PARAMETER
;
1450 Media
= This
->Media
;
1452 if (MediaId
!= Media
->MediaId
) {
1453 return EFI_MEDIA_CHANGED
;
1456 if (Buffer
== NULL
) {
1457 return EFI_INVALID_PARAMETER
;
1460 if (BufferSize
== 0) {
1461 if ((Token
!= NULL
) && (Token
->Event
!= NULL
)) {
1462 Token
->TransactionStatus
= EFI_SUCCESS
;
1463 gBS
->SignalEvent (Token
->Event
);
1469 BlockSize
= Media
->BlockSize
;
1470 if ((BufferSize
% BlockSize
) != 0) {
1471 return EFI_BAD_BUFFER_SIZE
;
1474 NumberOfBlocks
= BufferSize
/ BlockSize
;
1475 if ((Lba
+ NumberOfBlocks
- 1) > Media
->LastBlock
) {
1476 return EFI_INVALID_PARAMETER
;
1479 IoAlign
= Media
->IoAlign
;
1480 if ((IoAlign
> 0) && (((UINTN
)Buffer
& (IoAlign
- 1)) != 0)) {
1481 return EFI_INVALID_PARAMETER
;
1484 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
1486 Device
= NVME_DEVICE_PRIVATE_DATA_FROM_BLOCK_IO2 (This
);
1488 if ((Token
!= NULL
) && (Token
->Event
!= NULL
)) {
1489 Token
->TransactionStatus
= EFI_SUCCESS
;
1490 Status
= NvmeAsyncWrite (Device
, Buffer
, Lba
, NumberOfBlocks
, Token
);
1492 Status
= NvmeWrite (Device
, Buffer
, Lba
, NumberOfBlocks
);
1495 gBS
->RestoreTPL (OldTpl
);
1500 Flush the Block Device.
1502 If EFI_DEVICE_ERROR, EFI_NO_MEDIA,_EFI_WRITE_PROTECTED or EFI_MEDIA_CHANGED
1503 is returned and non-blocking I/O is being used, the Event associated with
1504 this request will not be signaled.
1506 @param[in] This Indicates a pointer to the calling context.
1507 @param[in,out] Token A pointer to the token associated with the
1510 @retval EFI_SUCCESS The flush request was queued if Event is not
1512 All outstanding data was written correctly to
1513 the device if the Event is NULL.
1514 @retval EFI_DEVICE_ERROR The device reported an error while writting back
1516 @retval EFI_WRITE_PROTECTED The device cannot be written to.
1517 @retval EFI_NO_MEDIA There is no media in the device.
1518 @retval EFI_MEDIA_CHANGED The MediaId is not for the current media.
1519 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack
1525 NvmeBlockIoFlushBlocksEx (
1526 IN EFI_BLOCK_IO2_PROTOCOL
*This
,
1527 IN OUT EFI_BLOCK_IO2_TOKEN
*Token
1530 NVME_DEVICE_PRIVATE_DATA
*Device
;
1535 // Check parameters.
1538 return EFI_INVALID_PARAMETER
;
1541 Device
= NVME_DEVICE_PRIVATE_DATA_FROM_BLOCK_IO2 (This
);
1544 // Wait for the asynchronous I/O queue to become empty.
1547 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
1548 IsEmpty
= IsListEmpty (&Device
->AsyncQueue
);
1549 gBS
->RestoreTPL (OldTpl
);
1559 // Signal caller event
1561 if ((Token
!= NULL
) && (Token
->Event
!= NULL
)) {
1562 Token
->TransactionStatus
= EFI_SUCCESS
;
1563 gBS
->SignalEvent (Token
->Event
);
1570 Trust transfer data from/to NVMe device.
1572 This function performs one NVMe transaction to do a trust transfer from/to NVMe device.
1574 @param Private The pointer to the NVME_CONTROLLER_PRIVATE_DATA data structure.
1575 @param Buffer The pointer to the current transaction buffer.
1576 @param SecurityProtocolId The value of the "Security Protocol" parameter of
1577 the security protocol command to be sent.
1578 @param SecurityProtocolSpecificData The value of the "Security Protocol Specific" parameter
1579 of the security protocol command to be sent.
1580 @param TransferLength The block number or sector count of the transfer.
1581 @param IsTrustSend Indicates whether it is a trust send operation or not.
1582 @param Timeout The timeout, in 100ns units, to use for the execution
1583 of the security protocol command. A Timeout value of 0
1584 means that this function will wait indefinitely for the
1585 security protocol command to execute. If Timeout is greater
1586 than zero, then this function will return EFI_TIMEOUT
1587 if the time required to execute the receive data command
1588 is greater than Timeout.
1589 @param TransferLengthOut A pointer to a buffer to store the size in bytes of the data
1590 written to the buffer. Ignore it when IsTrustSend is TRUE.
1592 @retval EFI_SUCCESS The data transfer is complete successfully.
1593 @return others Some error occurs when transferring data.
1597 TrustTransferNvmeDevice (
1598 IN OUT NVME_CONTROLLER_PRIVATE_DATA
*Private
,
1599 IN OUT VOID
*Buffer
,
1600 IN UINT8 SecurityProtocolId
,
1601 IN UINT16 SecurityProtocolSpecificData
,
1602 IN UINTN TransferLength
,
1603 IN BOOLEAN IsTrustSend
,
1605 OUT UINTN
*TransferLengthOut
1608 EFI_NVM_EXPRESS_PASS_THRU_COMMAND_PACKET CommandPacket
;
1609 EFI_NVM_EXPRESS_COMMAND Command
;
1610 EFI_NVM_EXPRESS_COMPLETION Completion
;
1612 UINT16 SpecificData
;
1614 ZeroMem (&CommandPacket
, sizeof (EFI_NVM_EXPRESS_PASS_THRU_COMMAND_PACKET
));
1615 ZeroMem (&Command
, sizeof (EFI_NVM_EXPRESS_COMMAND
));
1616 ZeroMem (&Completion
, sizeof (EFI_NVM_EXPRESS_COMPLETION
));
1618 CommandPacket
.NvmeCmd
= &Command
;
1619 CommandPacket
.NvmeCompletion
= &Completion
;
1622 // Change Endianness of SecurityProtocolSpecificData
1624 SpecificData
= (((SecurityProtocolSpecificData
<< 8) & 0xFF00) | (SecurityProtocolSpecificData
>> 8));
1627 Command
.Cdw0
.Opcode
= NVME_ADMIN_SECURITY_SEND_CMD
;
1628 CommandPacket
.TransferBuffer
= Buffer
;
1629 CommandPacket
.TransferLength
= (UINT32
)TransferLength
;
1630 CommandPacket
.NvmeCmd
->Cdw10
= (UINT32
)((SecurityProtocolId
<< 24) | (SpecificData
<< 8));
1631 CommandPacket
.NvmeCmd
->Cdw11
= (UINT32
)TransferLength
;
1633 Command
.Cdw0
.Opcode
= NVME_ADMIN_SECURITY_RECEIVE_CMD
;
1634 CommandPacket
.TransferBuffer
= Buffer
;
1635 CommandPacket
.TransferLength
= (UINT32
)TransferLength
;
1636 CommandPacket
.NvmeCmd
->Cdw10
= (UINT32
)((SecurityProtocolId
<< 24) | (SpecificData
<< 8));
1637 CommandPacket
.NvmeCmd
->Cdw11
= (UINT32
)TransferLength
;
1640 CommandPacket
.NvmeCmd
->Flags
= CDW10_VALID
| CDW11_VALID
;
1641 CommandPacket
.NvmeCmd
->Nsid
= NVME_CONTROLLER_ID
;
1642 CommandPacket
.CommandTimeout
= Timeout
;
1643 CommandPacket
.QueueType
= NVME_ADMIN_QUEUE
;
1645 Status
= Private
->Passthru
.PassThru (
1653 if (EFI_ERROR (Status
)) {
1654 *TransferLengthOut
= 0;
1656 *TransferLengthOut
= (UINTN
)TransferLength
;
1664 Send a security protocol command to a device that receives data and/or the result
1665 of one or more commands sent by SendData.
1667 The ReceiveData function sends a security protocol command to the given MediaId.
1668 The security protocol command sent is defined by SecurityProtocolId and contains
1669 the security protocol specific data SecurityProtocolSpecificData. The function
1670 returns the data from the security protocol command in PayloadBuffer.
1672 For devices supporting the SCSI command set, the security protocol command is sent
1673 using the SECURITY PROTOCOL IN command defined in SPC-4.
1675 For devices supporting the ATA command set, the security protocol command is sent
1676 using one of the TRUSTED RECEIVE commands defined in ATA8-ACS if PayloadBufferSize
1679 If the PayloadBufferSize is zero, the security protocol command is sent using the
1680 Trusted Non-Data command defined in ATA8-ACS.
1682 If PayloadBufferSize is too small to store the available data from the security
1683 protocol command, the function shall copy PayloadBufferSize bytes into the
1684 PayloadBuffer and return EFI_WARN_BUFFER_TOO_SMALL.
1686 If PayloadBuffer or PayloadTransferSize is NULL and PayloadBufferSize is non-zero,
1687 the function shall return EFI_INVALID_PARAMETER.
1689 If the given MediaId does not support security protocol commands, the function shall
1690 return EFI_UNSUPPORTED. If there is no media in the device, the function returns
1691 EFI_NO_MEDIA. If the MediaId is not the ID for the current media in the device,
1692 the function returns EFI_MEDIA_CHANGED.
1694 If the security protocol fails to complete within the Timeout period, the function
1695 shall return EFI_TIMEOUT.
1697 If the security protocol command completes without an error, the function shall
1698 return EFI_SUCCESS. If the security protocol command completes with an error, the
1699 function shall return EFI_DEVICE_ERROR.
1701 @param This Indicates a pointer to the calling context.
1702 @param MediaId ID of the medium to receive data from.
1703 @param Timeout The timeout, in 100ns units, to use for the execution
1704 of the security protocol command. A Timeout value of 0
1705 means that this function will wait indefinitely for the
1706 security protocol command to execute. If Timeout is greater
1707 than zero, then this function will return EFI_TIMEOUT
1708 if the time required to execute the receive data command
1709 is greater than Timeout.
1710 @param SecurityProtocolId The value of the "Security Protocol" parameter of
1711 the security protocol command to be sent.
1712 @param SecurityProtocolSpecificData The value of the "Security Protocol Specific" parameter
1713 of the security protocol command to be sent.
1714 @param PayloadBufferSize Size in bytes of the payload data buffer.
1715 @param PayloadBuffer A pointer to a destination buffer to store the security
1716 protocol command specific payload data for the security
1717 protocol command. The caller is responsible for having
1718 either implicit or explicit ownership of the buffer.
1719 @param PayloadTransferSize A pointer to a buffer to store the size in bytes of the
1720 data written to the payload data buffer.
1722 @retval EFI_SUCCESS The security protocol command completed successfully.
1723 @retval EFI_WARN_BUFFER_TOO_SMALL The PayloadBufferSize was too small to store the available
1724 data from the device. The PayloadBuffer contains the truncated data.
1725 @retval EFI_UNSUPPORTED The given MediaId does not support security protocol commands.
1726 @retval EFI_DEVICE_ERROR The security protocol command completed with an error.
1727 @retval EFI_NO_MEDIA There is no media in the device.
1728 @retval EFI_MEDIA_CHANGED The MediaId is not for the current media.
1729 @retval EFI_INVALID_PARAMETER The PayloadBuffer or PayloadTransferSize is NULL and
1730 PayloadBufferSize is non-zero.
1731 @retval EFI_TIMEOUT A timeout occurred while waiting for the security
1732 protocol command to execute.
1737 NvmeStorageSecurityReceiveData (
1738 IN EFI_STORAGE_SECURITY_COMMAND_PROTOCOL
*This
,
1741 IN UINT8 SecurityProtocolId
,
1742 IN UINT16 SecurityProtocolSpecificData
,
1743 IN UINTN PayloadBufferSize
,
1744 OUT VOID
*PayloadBuffer
,
1745 OUT UINTN
*PayloadTransferSize
1749 NVME_DEVICE_PRIVATE_DATA
*Device
;
1751 Status
= EFI_SUCCESS
;
1753 if ((PayloadBuffer
== NULL
) || (PayloadTransferSize
== NULL
) || (PayloadBufferSize
== 0)) {
1754 return EFI_INVALID_PARAMETER
;
1757 Device
= NVME_DEVICE_PRIVATE_DATA_FROM_STORAGE_SECURITY (This
);
1759 if (MediaId
!= Device
->BlockIo
.Media
->MediaId
) {
1760 return EFI_MEDIA_CHANGED
;
1763 if (!Device
->BlockIo
.Media
->MediaPresent
) {
1764 return EFI_NO_MEDIA
;
1767 Status
= TrustTransferNvmeDevice (
1771 SecurityProtocolSpecificData
,
1782 Send a security protocol command to a device.
1784 The SendData function sends a security protocol command containing the payload
1785 PayloadBuffer to the given MediaId. The security protocol command sent is
1786 defined by SecurityProtocolId and contains the security protocol specific data
1787 SecurityProtocolSpecificData. If the underlying protocol command requires a
1788 specific padding for the command payload, the SendData function shall add padding
1789 bytes to the command payload to satisfy the padding requirements.
1791 For devices supporting the SCSI command set, the security protocol command is sent
1792 using the SECURITY PROTOCOL OUT command defined in SPC-4.
1794 For devices supporting the ATA command set, the security protocol command is sent
1795 using one of the TRUSTED SEND commands defined in ATA8-ACS if PayloadBufferSize
1796 is non-zero. If the PayloadBufferSize is zero, the security protocol command is
1797 sent using the Trusted Non-Data command defined in ATA8-ACS.
1799 If PayloadBuffer is NULL and PayloadBufferSize is non-zero, the function shall
1800 return EFI_INVALID_PARAMETER.
1802 If the given MediaId does not support security protocol commands, the function
1803 shall return EFI_UNSUPPORTED. If there is no media in the device, the function
1804 returns EFI_NO_MEDIA. If the MediaId is not the ID for the current media in the
1805 device, the function returns EFI_MEDIA_CHANGED.
1807 If the security protocol fails to complete within the Timeout period, the function
1808 shall return EFI_TIMEOUT.
1810 If the security protocol command completes without an error, the function shall return
1811 EFI_SUCCESS. If the security protocol command completes with an error, the function
1812 shall return EFI_DEVICE_ERROR.
1814 @param This Indicates a pointer to the calling context.
1815 @param MediaId ID of the medium to receive data from.
1816 @param Timeout The timeout, in 100ns units, to use for the execution
1817 of the security protocol command. A Timeout value of 0
1818 means that this function will wait indefinitely for the
1819 security protocol command to execute. If Timeout is greater
1820 than zero, then this function will return EFI_TIMEOUT
1821 if the time required to execute the send data command
1822 is greater than Timeout.
1823 @param SecurityProtocolId The value of the "Security Protocol" parameter of
1824 the security protocol command to be sent.
1825 @param SecurityProtocolSpecificData The value of the "Security Protocol Specific" parameter
1826 of the security protocol command to be sent.
1827 @param PayloadBufferSize Size in bytes of the payload data buffer.
1828 @param PayloadBuffer A pointer to a destination buffer to store the security
1829 protocol command specific payload data for the security
1832 @retval EFI_SUCCESS The security protocol command completed successfully.
1833 @retval EFI_UNSUPPORTED The given MediaId does not support security protocol commands.
1834 @retval EFI_DEVICE_ERROR The security protocol command completed with an error.
1835 @retval EFI_NO_MEDIA There is no media in the device.
1836 @retval EFI_MEDIA_CHANGED The MediaId is not for the current media.
1837 @retval EFI_INVALID_PARAMETER The PayloadBuffer is NULL and PayloadBufferSize is non-zero.
1838 @retval EFI_TIMEOUT A timeout occurred while waiting for the security
1839 protocol command to execute.
1844 NvmeStorageSecuritySendData (
1845 IN EFI_STORAGE_SECURITY_COMMAND_PROTOCOL
*This
,
1848 IN UINT8 SecurityProtocolId
,
1849 IN UINT16 SecurityProtocolSpecificData
,
1850 IN UINTN PayloadBufferSize
,
1851 IN VOID
*PayloadBuffer
1855 NVME_DEVICE_PRIVATE_DATA
*Device
;
1857 Status
= EFI_SUCCESS
;
1859 if ((PayloadBuffer
== NULL
) && (PayloadBufferSize
!= 0)) {
1860 return EFI_INVALID_PARAMETER
;
1863 Device
= NVME_DEVICE_PRIVATE_DATA_FROM_STORAGE_SECURITY (This
);
1865 if (MediaId
!= Device
->BlockIo
.Media
->MediaId
) {
1866 return EFI_MEDIA_CHANGED
;
1869 if (!Device
->BlockIo
.Media
->MediaPresent
) {
1870 return EFI_NO_MEDIA
;
1873 Status
= TrustTransferNvmeDevice (
1877 SecurityProtocolSpecificData
,