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 This program and the accompanying materials
7 are licensed and made available under the terms and conditions of the BSD License
8 which accompanies this distribution. The full text of the license may be found at
9 http://opensource.org/licenses/bsd-license.php.
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
16 #include "NvmExpress.h"
19 Read some sectors from the device.
21 @param Device The pointer to the NVME_DEVICE_PRIVATE_DATA data structure.
22 @param Buffer The buffer used to store the data read from the device.
23 @param Lba The start block number.
24 @param Blocks Total block number to be read.
26 @retval EFI_SUCCESS Datum are read from the device.
27 @retval Others Fail to read all the datum.
32 IN NVME_DEVICE_PRIVATE_DATA
*Device
,
38 NVME_CONTROLLER_PRIVATE_DATA
*Private
;
40 EFI_NVM_EXPRESS_PASS_THRU_COMMAND_PACKET CommandPacket
;
41 EFI_NVM_EXPRESS_COMMAND Command
;
42 EFI_NVM_EXPRESS_COMPLETION Completion
;
46 Private
= Device
->Controller
;
47 BlockSize
= Device
->Media
.BlockSize
;
48 Bytes
= Blocks
* BlockSize
;
50 ZeroMem (&CommandPacket
, sizeof(EFI_NVM_EXPRESS_PASS_THRU_COMMAND_PACKET
));
51 ZeroMem (&Command
, sizeof(EFI_NVM_EXPRESS_COMMAND
));
52 ZeroMem (&Completion
, sizeof(EFI_NVM_EXPRESS_COMPLETION
));
54 CommandPacket
.NvmeCmd
= &Command
;
55 CommandPacket
.NvmeCompletion
= &Completion
;
57 CommandPacket
.NvmeCmd
->Cdw0
.Opcode
= NVME_IO_READ_OPC
;
58 CommandPacket
.NvmeCmd
->Nsid
= Device
->NamespaceId
;
59 CommandPacket
.TransferBuffer
= (VOID
*)(UINTN
)Buffer
;
61 CommandPacket
.TransferLength
= Bytes
;
62 CommandPacket
.CommandTimeout
= NVME_GENERIC_TIMEOUT
;
63 CommandPacket
.QueueType
= NVME_IO_QUEUE
;
65 CommandPacket
.NvmeCmd
->Cdw10
= (UINT32
)Lba
;
66 CommandPacket
.NvmeCmd
->Cdw11
= (UINT32
)RShiftU64(Lba
, 32);
67 CommandPacket
.NvmeCmd
->Cdw12
= (Blocks
- 1) & 0xFFFF;
69 CommandPacket
.NvmeCmd
->Flags
= CDW10_VALID
| CDW11_VALID
| CDW12_VALID
;
71 Status
= Private
->Passthru
.PassThru (
82 Write some sectors to the device.
84 @param Device The pointer to the NVME_DEVICE_PRIVATE_DATA data structure.
85 @param Buffer The buffer to be written into the device.
86 @param Lba The start block number.
87 @param Blocks Total block number to be written.
89 @retval EFI_SUCCESS Datum are written into the buffer.
90 @retval Others Fail to write all the datum.
95 IN NVME_DEVICE_PRIVATE_DATA
*Device
,
101 NVME_CONTROLLER_PRIVATE_DATA
*Private
;
102 EFI_NVM_EXPRESS_PASS_THRU_COMMAND_PACKET CommandPacket
;
103 EFI_NVM_EXPRESS_COMMAND Command
;
104 EFI_NVM_EXPRESS_COMPLETION Completion
;
109 Private
= Device
->Controller
;
110 BlockSize
= Device
->Media
.BlockSize
;
111 Bytes
= Blocks
* BlockSize
;
113 ZeroMem (&CommandPacket
, sizeof(EFI_NVM_EXPRESS_PASS_THRU_COMMAND_PACKET
));
114 ZeroMem (&Command
, sizeof(EFI_NVM_EXPRESS_COMMAND
));
115 ZeroMem (&Completion
, sizeof(EFI_NVM_EXPRESS_COMPLETION
));
117 CommandPacket
.NvmeCmd
= &Command
;
118 CommandPacket
.NvmeCompletion
= &Completion
;
120 CommandPacket
.NvmeCmd
->Cdw0
.Opcode
= NVME_IO_WRITE_OPC
;
121 CommandPacket
.NvmeCmd
->Nsid
= Device
->NamespaceId
;
122 CommandPacket
.TransferBuffer
= (VOID
*)(UINTN
)Buffer
;
124 CommandPacket
.TransferLength
= Bytes
;
125 CommandPacket
.CommandTimeout
= NVME_GENERIC_TIMEOUT
;
126 CommandPacket
.QueueType
= NVME_IO_QUEUE
;
128 CommandPacket
.NvmeCmd
->Cdw10
= (UINT32
)Lba
;
129 CommandPacket
.NvmeCmd
->Cdw11
= (UINT32
)RShiftU64(Lba
, 32);
131 // Set Force Unit Access bit (bit 30) to use write-through behaviour
133 CommandPacket
.NvmeCmd
->Cdw12
= ((Blocks
- 1) & 0xFFFF) | BIT30
;
135 CommandPacket
.MetadataBuffer
= NULL
;
136 CommandPacket
.MetadataLength
= 0;
138 CommandPacket
.NvmeCmd
->Flags
= CDW10_VALID
| CDW11_VALID
| CDW12_VALID
;
140 Status
= Private
->Passthru
.PassThru (
151 Read some blocks from the device.
153 @param Device The pointer to the NVME_DEVICE_PRIVATE_DATA data structure.
154 @param Buffer The buffer used to store the data read from the device.
155 @param Lba The start block number.
156 @param Blocks Total block number to be read.
158 @retval EFI_SUCCESS Datum are read from the device.
159 @retval Others Fail to read all the datum.
164 IN NVME_DEVICE_PRIVATE_DATA
*Device
,
172 NVME_CONTROLLER_PRIVATE_DATA
*Private
;
173 UINT32 MaxTransferBlocks
;
179 // Wait for the device's asynchronous I/O queue to become empty.
182 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
183 IsEmpty
= IsListEmpty (&Device
->AsyncQueue
);
184 gBS
->RestoreTPL (OldTpl
);
193 Status
= EFI_SUCCESS
;
194 Private
= Device
->Controller
;
195 BlockSize
= Device
->Media
.BlockSize
;
196 OrginalBlocks
= Blocks
;
198 if (Private
->ControllerData
->Mdts
!= 0) {
199 MaxTransferBlocks
= (1 << (Private
->ControllerData
->Mdts
)) * (1 << (Private
->Cap
.Mpsmin
+ 12)) / BlockSize
;
201 MaxTransferBlocks
= 1024;
205 if (Blocks
> MaxTransferBlocks
) {
206 Status
= ReadSectors (Device
, (UINT64
)(UINTN
)Buffer
, Lba
, MaxTransferBlocks
);
208 Blocks
-= MaxTransferBlocks
;
209 Buffer
= (VOID
*)(UINTN
)((UINT64
)(UINTN
)Buffer
+ MaxTransferBlocks
* BlockSize
);
210 Lba
+= MaxTransferBlocks
;
212 Status
= ReadSectors (Device
, (UINT64
)(UINTN
)Buffer
, Lba
, (UINT32
)Blocks
);
216 if (EFI_ERROR(Status
)) {
221 DEBUG ((DEBUG_BLKIO
, "%a: Lba = 0x%08Lx, Original = 0x%08Lx, "
222 "Remaining = 0x%08Lx, BlockSize = 0x%x, Status = %r\n", __FUNCTION__
, Lba
,
223 (UINT64
)OrginalBlocks
, (UINT64
)Blocks
, BlockSize
, Status
));
229 Write some blocks to the device.
231 @param Device The pointer to the NVME_DEVICE_PRIVATE_DATA data structure.
232 @param Buffer The buffer to be written into the device.
233 @param Lba The start block number.
234 @param Blocks Total block number to be written.
236 @retval EFI_SUCCESS Datum are written into the buffer.
237 @retval Others Fail to write all the datum.
242 IN NVME_DEVICE_PRIVATE_DATA
*Device
,
250 NVME_CONTROLLER_PRIVATE_DATA
*Private
;
251 UINT32 MaxTransferBlocks
;
257 // Wait for the device's asynchronous I/O queue to become empty.
260 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
261 IsEmpty
= IsListEmpty (&Device
->AsyncQueue
);
262 gBS
->RestoreTPL (OldTpl
);
271 Status
= EFI_SUCCESS
;
272 Private
= Device
->Controller
;
273 BlockSize
= Device
->Media
.BlockSize
;
274 OrginalBlocks
= Blocks
;
276 if (Private
->ControllerData
->Mdts
!= 0) {
277 MaxTransferBlocks
= (1 << (Private
->ControllerData
->Mdts
)) * (1 << (Private
->Cap
.Mpsmin
+ 12)) / BlockSize
;
279 MaxTransferBlocks
= 1024;
283 if (Blocks
> MaxTransferBlocks
) {
284 Status
= WriteSectors (Device
, (UINT64
)(UINTN
)Buffer
, Lba
, MaxTransferBlocks
);
286 Blocks
-= MaxTransferBlocks
;
287 Buffer
= (VOID
*)(UINTN
)((UINT64
)(UINTN
)Buffer
+ MaxTransferBlocks
* BlockSize
);
288 Lba
+= MaxTransferBlocks
;
290 Status
= WriteSectors (Device
, (UINT64
)(UINTN
)Buffer
, Lba
, (UINT32
)Blocks
);
294 if (EFI_ERROR(Status
)) {
299 DEBUG ((DEBUG_BLKIO
, "%a: Lba = 0x%08Lx, Original = 0x%08Lx, "
300 "Remaining = 0x%08Lx, BlockSize = 0x%x, Status = %r\n", __FUNCTION__
, Lba
,
301 (UINT64
)OrginalBlocks
, (UINT64
)Blocks
, BlockSize
, Status
));
307 Flushes all modified data to the device.
309 @param Device The pointer to the NVME_DEVICE_PRIVATE_DATA data structure.
311 @retval EFI_SUCCESS Datum are written into the buffer.
312 @retval Others Fail to write all the datum.
317 IN NVME_DEVICE_PRIVATE_DATA
*Device
320 NVME_CONTROLLER_PRIVATE_DATA
*Private
;
321 EFI_NVM_EXPRESS_PASS_THRU_COMMAND_PACKET CommandPacket
;
322 EFI_NVM_EXPRESS_COMMAND Command
;
323 EFI_NVM_EXPRESS_COMPLETION Completion
;
326 Private
= Device
->Controller
;
328 ZeroMem (&CommandPacket
, sizeof(EFI_NVM_EXPRESS_PASS_THRU_COMMAND_PACKET
));
329 ZeroMem (&Command
, sizeof(EFI_NVM_EXPRESS_COMMAND
));
330 ZeroMem (&Completion
, sizeof(EFI_NVM_EXPRESS_COMPLETION
));
332 CommandPacket
.NvmeCmd
= &Command
;
333 CommandPacket
.NvmeCompletion
= &Completion
;
335 CommandPacket
.NvmeCmd
->Cdw0
.Opcode
= NVME_IO_FLUSH_OPC
;
336 CommandPacket
.NvmeCmd
->Nsid
= Device
->NamespaceId
;
337 CommandPacket
.CommandTimeout
= NVME_GENERIC_TIMEOUT
;
338 CommandPacket
.QueueType
= NVME_IO_QUEUE
;
340 Status
= Private
->Passthru
.PassThru (
351 Nonblocking I/O callback funtion when the event is signaled.
353 @param[in] Event The Event this notify function registered to.
354 @param[in] Context Pointer to the context data registered to the
365 NVME_BLKIO2_SUBTASK
*Subtask
;
366 NVME_BLKIO2_REQUEST
*Request
;
368 EFI_BLOCK_IO2_TOKEN
*Token
;
370 gBS
->CloseEvent (Event
);
372 Subtask
= (NVME_BLKIO2_SUBTASK
*) Context
;
373 Completion
= (NVME_CQ
*) Subtask
->CommandPacket
->NvmeCompletion
;
374 Request
= Subtask
->BlockIo2Request
;
375 Token
= Request
->Token
;
377 if (Token
->TransactionStatus
== EFI_SUCCESS
) {
379 // If previous subtask already fails, do not check the result of
380 // subsequent subtasks.
382 if ((Completion
->Sct
!= 0) || (Completion
->Sc
!= 0)) {
383 Token
->TransactionStatus
= EFI_DEVICE_ERROR
;
386 // Dump completion entry status for debugging.
389 NvmeDumpStatus (Completion
);
395 // Remove the subtask from the BlockIo2 subtasks list.
397 RemoveEntryList (&Subtask
->Link
);
399 if (IsListEmpty (&Request
->SubtasksQueue
) && Request
->LastSubtaskSubmitted
) {
401 // Remove the BlockIo2 request from the device asynchronous queue.
403 RemoveEntryList (&Request
->Link
);
405 gBS
->SignalEvent (Token
->Event
);
408 FreePool (Subtask
->CommandPacket
->NvmeCmd
);
409 FreePool (Subtask
->CommandPacket
->NvmeCompletion
);
410 FreePool (Subtask
->CommandPacket
);
415 Read some sectors from the device in an asynchronous manner.
417 @param Device The pointer to the NVME_DEVICE_PRIVATE_DATA data
419 @param Request The pointer to the NVME_BLKIO2_REQUEST data structure.
420 @param Buffer The buffer used to store the data read from the device.
421 @param Lba The start block number.
422 @param Blocks Total block number to be read.
423 @param IsLast The last subtask of an asynchronous read request.
425 @retval EFI_SUCCESS Asynchronous read request has been queued.
426 @retval Others Fail to send the asynchronous request.
431 IN NVME_DEVICE_PRIVATE_DATA
*Device
,
432 IN NVME_BLKIO2_REQUEST
*Request
,
439 NVME_CONTROLLER_PRIVATE_DATA
*Private
;
441 NVME_BLKIO2_SUBTASK
*Subtask
;
442 EFI_NVM_EXPRESS_PASS_THRU_COMMAND_PACKET
*CommandPacket
;
443 EFI_NVM_EXPRESS_COMMAND
*Command
;
444 EFI_NVM_EXPRESS_COMPLETION
*Completion
;
449 Private
= Device
->Controller
;
450 BlockSize
= Device
->Media
.BlockSize
;
451 Bytes
= Blocks
* BlockSize
;
452 CommandPacket
= NULL
;
456 Subtask
= AllocateZeroPool (sizeof (NVME_BLKIO2_SUBTASK
));
457 if (Subtask
== NULL
) {
458 Status
= EFI_OUT_OF_RESOURCES
;
462 Subtask
->Signature
= NVME_BLKIO2_SUBTASK_SIGNATURE
;
463 Subtask
->IsLast
= IsLast
;
464 Subtask
->NamespaceId
= Device
->NamespaceId
;
465 Subtask
->BlockIo2Request
= Request
;
467 CommandPacket
= AllocateZeroPool (sizeof (EFI_NVM_EXPRESS_PASS_THRU_COMMAND_PACKET
));
468 if (CommandPacket
== NULL
) {
469 Status
= EFI_OUT_OF_RESOURCES
;
472 Subtask
->CommandPacket
= CommandPacket
;
475 Command
= AllocateZeroPool (sizeof (EFI_NVM_EXPRESS_COMMAND
));
476 if (Command
== NULL
) {
477 Status
= EFI_OUT_OF_RESOURCES
;
481 Completion
= AllocateZeroPool (sizeof (EFI_NVM_EXPRESS_COMPLETION
));
482 if (Completion
== NULL
) {
483 Status
= EFI_OUT_OF_RESOURCES
;
490 Status
= gBS
->CreateEvent (
497 if (EFI_ERROR(Status
)) {
501 CommandPacket
->NvmeCmd
= Command
;
502 CommandPacket
->NvmeCompletion
= Completion
;
504 CommandPacket
->NvmeCmd
->Cdw0
.Opcode
= NVME_IO_READ_OPC
;
505 CommandPacket
->NvmeCmd
->Nsid
= Device
->NamespaceId
;
506 CommandPacket
->TransferBuffer
= (VOID
*)(UINTN
)Buffer
;
508 CommandPacket
->TransferLength
= Bytes
;
509 CommandPacket
->CommandTimeout
= NVME_GENERIC_TIMEOUT
;
510 CommandPacket
->QueueType
= NVME_IO_QUEUE
;
512 CommandPacket
->NvmeCmd
->Cdw10
= (UINT32
)Lba
;
513 CommandPacket
->NvmeCmd
->Cdw11
= (UINT32
)RShiftU64(Lba
, 32);
514 CommandPacket
->NvmeCmd
->Cdw12
= (Blocks
- 1) & 0xFFFF;
516 CommandPacket
->NvmeCmd
->Flags
= CDW10_VALID
| CDW11_VALID
| CDW12_VALID
;
518 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
519 InsertTailList (&Private
->UnsubmittedSubtasks
, &Subtask
->Link
);
520 Request
->UnsubmittedSubtaskNum
++;
521 gBS
->RestoreTPL (OldTpl
);
527 // Resource cleanup if asynchronous read request has not been queued.
529 if (Completion
!= NULL
) {
530 FreePool (Completion
);
533 if (Command
!= NULL
) {
537 if (CommandPacket
!= NULL
) {
538 FreePool (CommandPacket
);
541 if (Subtask
!= NULL
) {
542 if (Subtask
->Event
!= NULL
) {
543 gBS
->CloseEvent (Subtask
->Event
);
553 Write some sectors from the device in an asynchronous manner.
555 @param Device The pointer to the NVME_DEVICE_PRIVATE_DATA data
557 @param Request The pointer to the NVME_BLKIO2_REQUEST data structure.
558 @param Buffer The buffer used to store the data written to the
560 @param Lba The start block number.
561 @param Blocks Total block number to be written.
562 @param IsLast The last subtask of an asynchronous write request.
564 @retval EFI_SUCCESS Asynchronous write request has been queued.
565 @retval Others Fail to send the asynchronous request.
570 IN NVME_DEVICE_PRIVATE_DATA
*Device
,
571 IN NVME_BLKIO2_REQUEST
*Request
,
578 NVME_CONTROLLER_PRIVATE_DATA
*Private
;
580 NVME_BLKIO2_SUBTASK
*Subtask
;
581 EFI_NVM_EXPRESS_PASS_THRU_COMMAND_PACKET
*CommandPacket
;
582 EFI_NVM_EXPRESS_COMMAND
*Command
;
583 EFI_NVM_EXPRESS_COMPLETION
*Completion
;
588 Private
= Device
->Controller
;
589 BlockSize
= Device
->Media
.BlockSize
;
590 Bytes
= Blocks
* BlockSize
;
591 CommandPacket
= NULL
;
595 Subtask
= AllocateZeroPool (sizeof (NVME_BLKIO2_SUBTASK
));
596 if (Subtask
== NULL
) {
597 Status
= EFI_OUT_OF_RESOURCES
;
601 Subtask
->Signature
= NVME_BLKIO2_SUBTASK_SIGNATURE
;
602 Subtask
->IsLast
= IsLast
;
603 Subtask
->NamespaceId
= Device
->NamespaceId
;
604 Subtask
->BlockIo2Request
= Request
;
606 CommandPacket
= AllocateZeroPool (sizeof (EFI_NVM_EXPRESS_PASS_THRU_COMMAND_PACKET
));
607 if (CommandPacket
== NULL
) {
608 Status
= EFI_OUT_OF_RESOURCES
;
611 Subtask
->CommandPacket
= CommandPacket
;
614 Command
= AllocateZeroPool (sizeof (EFI_NVM_EXPRESS_COMMAND
));
615 if (Command
== NULL
) {
616 Status
= EFI_OUT_OF_RESOURCES
;
620 Completion
= AllocateZeroPool (sizeof (EFI_NVM_EXPRESS_COMPLETION
));
621 if (Completion
== NULL
) {
622 Status
= EFI_OUT_OF_RESOURCES
;
629 Status
= gBS
->CreateEvent (
636 if (EFI_ERROR(Status
)) {
640 CommandPacket
->NvmeCmd
= Command
;
641 CommandPacket
->NvmeCompletion
= Completion
;
643 CommandPacket
->NvmeCmd
->Cdw0
.Opcode
= NVME_IO_WRITE_OPC
;
644 CommandPacket
->NvmeCmd
->Nsid
= Device
->NamespaceId
;
645 CommandPacket
->TransferBuffer
= (VOID
*)(UINTN
)Buffer
;
647 CommandPacket
->TransferLength
= Bytes
;
648 CommandPacket
->CommandTimeout
= NVME_GENERIC_TIMEOUT
;
649 CommandPacket
->QueueType
= NVME_IO_QUEUE
;
651 CommandPacket
->NvmeCmd
->Cdw10
= (UINT32
)Lba
;
652 CommandPacket
->NvmeCmd
->Cdw11
= (UINT32
)RShiftU64(Lba
, 32);
654 // Set Force Unit Access bit (bit 30) to use write-through behaviour
656 CommandPacket
->NvmeCmd
->Cdw12
= ((Blocks
- 1) & 0xFFFF) | BIT30
;
658 CommandPacket
->NvmeCmd
->Flags
= CDW10_VALID
| CDW11_VALID
| CDW12_VALID
;
660 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
661 InsertTailList (&Private
->UnsubmittedSubtasks
, &Subtask
->Link
);
662 Request
->UnsubmittedSubtaskNum
++;
663 gBS
->RestoreTPL (OldTpl
);
669 // Resource cleanup if asynchronous read request has not been queued.
671 if (Completion
!= NULL
) {
672 FreePool (Completion
);
675 if (Command
!= NULL
) {
679 if (CommandPacket
!= NULL
) {
680 FreePool (CommandPacket
);
683 if (Subtask
!= NULL
) {
684 if (Subtask
->Event
!= NULL
) {
685 gBS
->CloseEvent (Subtask
->Event
);
695 Read some blocks from the device in an asynchronous manner.
697 @param Device The pointer to the NVME_DEVICE_PRIVATE_DATA data
699 @param Buffer The buffer used to store the data read from the device.
700 @param Lba The start block number.
701 @param Blocks Total block number to be read.
702 @param Token A pointer to the token associated with the transaction.
704 @retval EFI_SUCCESS Data are read from the device.
705 @retval Others Fail to read all the data.
710 IN NVME_DEVICE_PRIVATE_DATA
*Device
,
714 IN EFI_BLOCK_IO2_TOKEN
*Token
719 NVME_CONTROLLER_PRIVATE_DATA
*Private
;
720 NVME_BLKIO2_REQUEST
*BlkIo2Req
;
721 UINT32 MaxTransferBlocks
;
726 Status
= EFI_SUCCESS
;
727 Private
= Device
->Controller
;
728 BlockSize
= Device
->Media
.BlockSize
;
729 OrginalBlocks
= Blocks
;
730 BlkIo2Req
= AllocateZeroPool (sizeof (NVME_BLKIO2_REQUEST
));
731 if (BlkIo2Req
== NULL
) {
732 return EFI_OUT_OF_RESOURCES
;
735 BlkIo2Req
->Signature
= NVME_BLKIO2_REQUEST_SIGNATURE
;
736 BlkIo2Req
->Token
= Token
;
738 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
739 InsertTailList (&Device
->AsyncQueue
, &BlkIo2Req
->Link
);
740 gBS
->RestoreTPL (OldTpl
);
742 InitializeListHead (&BlkIo2Req
->SubtasksQueue
);
744 if (Private
->ControllerData
->Mdts
!= 0) {
745 MaxTransferBlocks
= (1 << (Private
->ControllerData
->Mdts
)) * (1 << (Private
->Cap
.Mpsmin
+ 12)) / BlockSize
;
747 MaxTransferBlocks
= 1024;
751 if (Blocks
> MaxTransferBlocks
) {
752 Status
= AsyncReadSectors (
754 BlkIo2Req
, (UINT64
)(UINTN
)Buffer
,
760 Blocks
-= MaxTransferBlocks
;
761 Buffer
= (VOID
*)(UINTN
)((UINT64
)(UINTN
)Buffer
+ MaxTransferBlocks
* BlockSize
);
762 Lba
+= MaxTransferBlocks
;
764 Status
= AsyncReadSectors (
767 (UINT64
)(UINTN
)Buffer
,
776 if (EFI_ERROR(Status
)) {
777 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
778 IsEmpty
= IsListEmpty (&BlkIo2Req
->SubtasksQueue
) &&
779 (BlkIo2Req
->UnsubmittedSubtaskNum
== 0);
783 // Remove the BlockIo2 request from the device asynchronous queue.
785 RemoveEntryList (&BlkIo2Req
->Link
);
786 FreePool (BlkIo2Req
);
787 Status
= EFI_DEVICE_ERROR
;
790 // There are previous BlockIo2 subtasks still running, EFI_SUCCESS
791 // should be returned to make sure that the caller does not free
792 // resources still using by these requests.
794 Status
= EFI_SUCCESS
;
795 Token
->TransactionStatus
= EFI_DEVICE_ERROR
;
796 BlkIo2Req
->LastSubtaskSubmitted
= TRUE
;
799 gBS
->RestoreTPL (OldTpl
);
805 DEBUG ((DEBUG_BLKIO
, "%a: Lba = 0x%08Lx, Original = 0x%08Lx, "
806 "Remaining = 0x%08Lx, BlockSize = 0x%x, Status = %r\n", __FUNCTION__
, Lba
,
807 (UINT64
)OrginalBlocks
, (UINT64
)Blocks
, BlockSize
, Status
));
813 Write some blocks from the device in an asynchronous manner.
815 @param Device The pointer to the NVME_DEVICE_PRIVATE_DATA data
817 @param Buffer The buffer used to store the data written to the
819 @param Lba The start block number.
820 @param Blocks Total block number to be written.
821 @param Token A pointer to the token associated with the transaction.
823 @retval EFI_SUCCESS Data are written to the device.
824 @retval Others Fail to write all the data.
829 IN NVME_DEVICE_PRIVATE_DATA
*Device
,
833 IN EFI_BLOCK_IO2_TOKEN
*Token
838 NVME_CONTROLLER_PRIVATE_DATA
*Private
;
839 NVME_BLKIO2_REQUEST
*BlkIo2Req
;
840 UINT32 MaxTransferBlocks
;
845 Status
= EFI_SUCCESS
;
846 Private
= Device
->Controller
;
847 BlockSize
= Device
->Media
.BlockSize
;
848 OrginalBlocks
= Blocks
;
849 BlkIo2Req
= AllocateZeroPool (sizeof (NVME_BLKIO2_REQUEST
));
850 if (BlkIo2Req
== NULL
) {
851 return EFI_OUT_OF_RESOURCES
;
854 BlkIo2Req
->Signature
= NVME_BLKIO2_REQUEST_SIGNATURE
;
855 BlkIo2Req
->Token
= Token
;
857 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
858 InsertTailList (&Device
->AsyncQueue
, &BlkIo2Req
->Link
);
859 gBS
->RestoreTPL (OldTpl
);
861 InitializeListHead (&BlkIo2Req
->SubtasksQueue
);
863 if (Private
->ControllerData
->Mdts
!= 0) {
864 MaxTransferBlocks
= (1 << (Private
->ControllerData
->Mdts
)) * (1 << (Private
->Cap
.Mpsmin
+ 12)) / BlockSize
;
866 MaxTransferBlocks
= 1024;
870 if (Blocks
> MaxTransferBlocks
) {
871 Status
= AsyncWriteSectors (
874 (UINT64
)(UINTN
)Buffer
,
880 Blocks
-= MaxTransferBlocks
;
881 Buffer
= (VOID
*)(UINTN
)((UINT64
)(UINTN
)Buffer
+ MaxTransferBlocks
* BlockSize
);
882 Lba
+= MaxTransferBlocks
;
884 Status
= AsyncWriteSectors (
887 (UINT64
)(UINTN
)Buffer
,
896 if (EFI_ERROR(Status
)) {
897 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
898 IsEmpty
= IsListEmpty (&BlkIo2Req
->SubtasksQueue
) &&
899 (BlkIo2Req
->UnsubmittedSubtaskNum
== 0);
903 // Remove the BlockIo2 request from the device asynchronous queue.
905 RemoveEntryList (&BlkIo2Req
->Link
);
906 FreePool (BlkIo2Req
);
907 Status
= EFI_DEVICE_ERROR
;
910 // There are previous BlockIo2 subtasks still running, EFI_SUCCESS
911 // should be returned to make sure that the caller does not free
912 // resources still using by these requests.
914 Status
= EFI_SUCCESS
;
915 Token
->TransactionStatus
= EFI_DEVICE_ERROR
;
916 BlkIo2Req
->LastSubtaskSubmitted
= TRUE
;
919 gBS
->RestoreTPL (OldTpl
);
925 DEBUG ((DEBUG_BLKIO
, "%a: Lba = 0x%08Lx, Original = 0x%08Lx, "
926 "Remaining = 0x%08Lx, BlockSize = 0x%x, Status = %r\n", __FUNCTION__
, Lba
,
927 (UINT64
)OrginalBlocks
, (UINT64
)Blocks
, BlockSize
, Status
));
933 Reset the Block Device.
935 @param This Indicates a pointer to the calling context.
936 @param ExtendedVerification Driver may perform diagnostics on reset.
938 @retval EFI_SUCCESS The device was reset.
939 @retval EFI_DEVICE_ERROR The device is not functioning properly and could
946 IN EFI_BLOCK_IO_PROTOCOL
*This
,
947 IN BOOLEAN ExtendedVerification
951 NVME_CONTROLLER_PRIVATE_DATA
*Private
;
952 NVME_DEVICE_PRIVATE_DATA
*Device
;
956 return EFI_INVALID_PARAMETER
;
960 // For Nvm Express subsystem, reset block device means reset controller.
962 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
964 Device
= NVME_DEVICE_PRIVATE_DATA_FROM_BLOCK_IO (This
);
966 Private
= Device
->Controller
;
968 Status
= NvmeControllerInit (Private
);
970 if (EFI_ERROR (Status
)) {
971 Status
= EFI_DEVICE_ERROR
;
974 gBS
->RestoreTPL (OldTpl
);
980 Read BufferSize bytes from Lba into Buffer.
982 @param This Indicates a pointer to the calling context.
983 @param MediaId Id of the media, changes every time the media is replaced.
984 @param Lba The starting Logical Block Address to read from.
985 @param BufferSize Size of Buffer, must be a multiple of device block size.
986 @param Buffer A pointer to the destination buffer for the data. The caller is
987 responsible for either having implicit or explicit ownership of the buffer.
989 @retval EFI_SUCCESS The data was read correctly from the device.
990 @retval EFI_DEVICE_ERROR The device reported an error while performing the read.
991 @retval EFI_NO_MEDIA There is no media in the device.
992 @retval EFI_MEDIA_CHANGED The MediaId does not matched the current device.
993 @retval EFI_BAD_BUFFER_SIZE The Buffer was not a multiple of the block size of the device.
994 @retval EFI_INVALID_PARAMETER The read request contains LBAs that are not valid,
995 or the buffer is not on proper alignment.
1000 NvmeBlockIoReadBlocks (
1001 IN EFI_BLOCK_IO_PROTOCOL
*This
,
1004 IN UINTN BufferSize
,
1008 NVME_DEVICE_PRIVATE_DATA
*Device
;
1010 EFI_BLOCK_IO_MEDIA
*Media
;
1012 UINTN NumberOfBlocks
;
1017 // Check parameters.
1020 return EFI_INVALID_PARAMETER
;
1023 Media
= This
->Media
;
1025 if (MediaId
!= Media
->MediaId
) {
1026 return EFI_MEDIA_CHANGED
;
1029 if (Buffer
== NULL
) {
1030 return EFI_INVALID_PARAMETER
;
1033 if (BufferSize
== 0) {
1037 BlockSize
= Media
->BlockSize
;
1038 if ((BufferSize
% BlockSize
) != 0) {
1039 return EFI_BAD_BUFFER_SIZE
;
1042 NumberOfBlocks
= BufferSize
/ BlockSize
;
1043 if ((Lba
+ NumberOfBlocks
- 1) > Media
->LastBlock
) {
1044 return EFI_INVALID_PARAMETER
;
1047 IoAlign
= Media
->IoAlign
;
1048 if (IoAlign
> 0 && (((UINTN
) Buffer
& (IoAlign
- 1)) != 0)) {
1049 return EFI_INVALID_PARAMETER
;
1052 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
1054 Device
= NVME_DEVICE_PRIVATE_DATA_FROM_BLOCK_IO (This
);
1056 Status
= NvmeRead (Device
, Buffer
, Lba
, NumberOfBlocks
);
1058 gBS
->RestoreTPL (OldTpl
);
1063 Write BufferSize bytes from Lba into Buffer.
1065 @param This Indicates a pointer to the calling context.
1066 @param MediaId The media ID that the write request is for.
1067 @param Lba The starting logical block address to be written. The caller is
1068 responsible for writing to only legitimate locations.
1069 @param BufferSize Size of Buffer, must be a multiple of device block size.
1070 @param Buffer A pointer to the source buffer for the data.
1072 @retval EFI_SUCCESS The data was written correctly to the device.
1073 @retval EFI_WRITE_PROTECTED The device can not be written to.
1074 @retval EFI_DEVICE_ERROR The device reported an error while performing the write.
1075 @retval EFI_NO_MEDIA There is no media in the device.
1076 @retval EFI_MEDIA_CHNAGED The MediaId does not matched the current device.
1077 @retval EFI_BAD_BUFFER_SIZE The Buffer was not a multiple of the block size of the device.
1078 @retval EFI_INVALID_PARAMETER The write request contains LBAs that are not valid,
1079 or the buffer is not on proper alignment.
1084 NvmeBlockIoWriteBlocks (
1085 IN EFI_BLOCK_IO_PROTOCOL
*This
,
1088 IN UINTN BufferSize
,
1092 NVME_DEVICE_PRIVATE_DATA
*Device
;
1094 EFI_BLOCK_IO_MEDIA
*Media
;
1096 UINTN NumberOfBlocks
;
1101 // Check parameters.
1104 return EFI_INVALID_PARAMETER
;
1107 Media
= This
->Media
;
1109 if (MediaId
!= Media
->MediaId
) {
1110 return EFI_MEDIA_CHANGED
;
1113 if (Buffer
== NULL
) {
1114 return EFI_INVALID_PARAMETER
;
1117 if (BufferSize
== 0) {
1121 BlockSize
= Media
->BlockSize
;
1122 if ((BufferSize
% BlockSize
) != 0) {
1123 return EFI_BAD_BUFFER_SIZE
;
1126 NumberOfBlocks
= BufferSize
/ BlockSize
;
1127 if ((Lba
+ NumberOfBlocks
- 1) > Media
->LastBlock
) {
1128 return EFI_INVALID_PARAMETER
;
1131 IoAlign
= Media
->IoAlign
;
1132 if (IoAlign
> 0 && (((UINTN
) Buffer
& (IoAlign
- 1)) != 0)) {
1133 return EFI_INVALID_PARAMETER
;
1136 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
1138 Device
= NVME_DEVICE_PRIVATE_DATA_FROM_BLOCK_IO (This
);
1140 Status
= NvmeWrite (Device
, Buffer
, Lba
, NumberOfBlocks
);
1142 gBS
->RestoreTPL (OldTpl
);
1148 Flush the Block Device.
1150 @param This Indicates a pointer to the calling context.
1152 @retval EFI_SUCCESS All outstanding data was written to the device.
1153 @retval EFI_DEVICE_ERROR The device reported an error while writing back the data.
1154 @retval EFI_NO_MEDIA There is no media in the device.
1159 NvmeBlockIoFlushBlocks (
1160 IN EFI_BLOCK_IO_PROTOCOL
*This
1163 NVME_DEVICE_PRIVATE_DATA
*Device
;
1168 // Check parameters.
1171 return EFI_INVALID_PARAMETER
;
1174 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
1176 Device
= NVME_DEVICE_PRIVATE_DATA_FROM_BLOCK_IO (This
);
1178 Status
= NvmeFlush (Device
);
1180 gBS
->RestoreTPL (OldTpl
);
1186 Reset the block device hardware.
1188 @param[in] This Indicates a pointer to the calling context.
1189 @param[in] ExtendedVerification Indicates that the driver may perform a more
1190 exhausive verfication operation of the
1191 device during reset.
1193 @retval EFI_SUCCESS The device was reset.
1194 @retval EFI_DEVICE_ERROR The device is not functioning properly and could
1200 NvmeBlockIoResetEx (
1201 IN EFI_BLOCK_IO2_PROTOCOL
*This
,
1202 IN BOOLEAN ExtendedVerification
1206 NVME_DEVICE_PRIVATE_DATA
*Device
;
1207 NVME_CONTROLLER_PRIVATE_DATA
*Private
;
1212 return EFI_INVALID_PARAMETER
;
1215 Device
= NVME_DEVICE_PRIVATE_DATA_FROM_BLOCK_IO2 (This
);
1216 Private
= Device
->Controller
;
1219 // Wait for the asynchronous PassThru queue to become empty.
1222 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
1223 IsEmpty
= IsListEmpty (&Private
->AsyncPassThruQueue
) &&
1224 IsListEmpty (&Private
->UnsubmittedSubtasks
);
1225 gBS
->RestoreTPL (OldTpl
);
1234 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
1236 Status
= NvmeControllerInit (Private
);
1238 if (EFI_ERROR (Status
)) {
1239 Status
= EFI_DEVICE_ERROR
;
1242 gBS
->RestoreTPL (OldTpl
);
1248 Read BufferSize bytes from Lba into Buffer.
1250 This function reads the requested number of blocks from the device. All the
1251 blocks are read, or an error is returned.
1252 If EFI_DEVICE_ERROR, EFI_NO_MEDIA,_or EFI_MEDIA_CHANGED is returned and
1253 non-blocking I/O is being used, the Event associated with this request will
1256 @param[in] This Indicates a pointer to the calling context.
1257 @param[in] MediaId Id of the media, changes every time the media is
1259 @param[in] Lba The starting Logical Block Address to read from.
1260 @param[in, out] Token A pointer to the token associated with the
1262 @param[in] BufferSize Size of Buffer, must be a multiple of device
1264 @param[out] Buffer A pointer to the destination buffer for the data.
1265 The caller is responsible for either having
1266 implicit or explicit ownership of the buffer.
1268 @retval EFI_SUCCESS The read request was queued if Token->Event is
1269 not NULL.The data was read correctly from the
1270 device if the Token->Event is NULL.
1271 @retval EFI_DEVICE_ERROR The device reported an error while performing
1273 @retval EFI_NO_MEDIA There is no media in the device.
1274 @retval EFI_MEDIA_CHANGED The MediaId is not for the current media.
1275 @retval EFI_BAD_BUFFER_SIZE The BufferSize parameter is not a multiple of
1276 the intrinsic block size of the device.
1277 @retval EFI_INVALID_PARAMETER The read request contains LBAs that are not
1278 valid, or the buffer is not on proper
1280 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a
1286 NvmeBlockIoReadBlocksEx (
1287 IN EFI_BLOCK_IO2_PROTOCOL
*This
,
1290 IN OUT EFI_BLOCK_IO2_TOKEN
*Token
,
1291 IN UINTN BufferSize
,
1295 NVME_DEVICE_PRIVATE_DATA
*Device
;
1297 EFI_BLOCK_IO_MEDIA
*Media
;
1299 UINTN NumberOfBlocks
;
1304 // Check parameters.
1307 return EFI_INVALID_PARAMETER
;
1310 Media
= This
->Media
;
1312 if (MediaId
!= Media
->MediaId
) {
1313 return EFI_MEDIA_CHANGED
;
1316 if (Buffer
== NULL
) {
1317 return EFI_INVALID_PARAMETER
;
1320 if (BufferSize
== 0) {
1321 if ((Token
!= NULL
) && (Token
->Event
!= NULL
)) {
1322 Token
->TransactionStatus
= EFI_SUCCESS
;
1323 gBS
->SignalEvent (Token
->Event
);
1328 BlockSize
= Media
->BlockSize
;
1329 if ((BufferSize
% BlockSize
) != 0) {
1330 return EFI_BAD_BUFFER_SIZE
;
1333 NumberOfBlocks
= BufferSize
/ BlockSize
;
1334 if ((Lba
+ NumberOfBlocks
- 1) > Media
->LastBlock
) {
1335 return EFI_INVALID_PARAMETER
;
1338 IoAlign
= Media
->IoAlign
;
1339 if (IoAlign
> 0 && (((UINTN
) Buffer
& (IoAlign
- 1)) != 0)) {
1340 return EFI_INVALID_PARAMETER
;
1343 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
1345 Device
= NVME_DEVICE_PRIVATE_DATA_FROM_BLOCK_IO2 (This
);
1347 if ((Token
!= NULL
) && (Token
->Event
!= NULL
)) {
1348 Token
->TransactionStatus
= EFI_SUCCESS
;
1349 Status
= NvmeAsyncRead (Device
, Buffer
, Lba
, NumberOfBlocks
, Token
);
1351 Status
= NvmeRead (Device
, Buffer
, Lba
, NumberOfBlocks
);
1354 gBS
->RestoreTPL (OldTpl
);
1359 Write BufferSize bytes from Lba into Buffer.
1361 This function writes the requested number of blocks to the device. All blocks
1362 are written, or an error is returned.If EFI_DEVICE_ERROR, EFI_NO_MEDIA,
1363 EFI_WRITE_PROTECTED or EFI_MEDIA_CHANGED is returned and non-blocking I/O is
1364 being used, the Event associated with this request will not be signaled.
1366 @param[in] This Indicates a pointer to the calling context.
1367 @param[in] MediaId The media ID that the write request is for.
1368 @param[in] Lba The starting logical block address to be written.
1369 The caller is responsible for writing to only
1370 legitimate locations.
1371 @param[in, out] Token A pointer to the token associated with the
1373 @param[in] BufferSize Size of Buffer, must be a multiple of device
1375 @param[in] Buffer A pointer to the source buffer for the data.
1377 @retval EFI_SUCCESS The write request was queued if Event is not
1379 The data was written correctly to the device if
1381 @retval EFI_WRITE_PROTECTED The device can not be written to.
1382 @retval EFI_NO_MEDIA There is no media in the device.
1383 @retval EFI_MEDIA_CHNAGED The MediaId does not matched the current
1385 @retval EFI_DEVICE_ERROR The device reported an error while performing
1387 @retval EFI_BAD_BUFFER_SIZE The Buffer was not a multiple of the block size
1389 @retval EFI_INVALID_PARAMETER The write request contains LBAs that are not
1390 valid, or the buffer is not on proper
1392 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a
1398 NvmeBlockIoWriteBlocksEx (
1399 IN EFI_BLOCK_IO2_PROTOCOL
*This
,
1402 IN OUT EFI_BLOCK_IO2_TOKEN
*Token
,
1403 IN UINTN BufferSize
,
1407 NVME_DEVICE_PRIVATE_DATA
*Device
;
1409 EFI_BLOCK_IO_MEDIA
*Media
;
1411 UINTN NumberOfBlocks
;
1416 // Check parameters.
1419 return EFI_INVALID_PARAMETER
;
1422 Media
= This
->Media
;
1424 if (MediaId
!= Media
->MediaId
) {
1425 return EFI_MEDIA_CHANGED
;
1428 if (Buffer
== NULL
) {
1429 return EFI_INVALID_PARAMETER
;
1432 if (BufferSize
== 0) {
1433 if ((Token
!= NULL
) && (Token
->Event
!= NULL
)) {
1434 Token
->TransactionStatus
= EFI_SUCCESS
;
1435 gBS
->SignalEvent (Token
->Event
);
1440 BlockSize
= Media
->BlockSize
;
1441 if ((BufferSize
% BlockSize
) != 0) {
1442 return EFI_BAD_BUFFER_SIZE
;
1445 NumberOfBlocks
= BufferSize
/ BlockSize
;
1446 if ((Lba
+ NumberOfBlocks
- 1) > Media
->LastBlock
) {
1447 return EFI_INVALID_PARAMETER
;
1450 IoAlign
= Media
->IoAlign
;
1451 if (IoAlign
> 0 && (((UINTN
) Buffer
& (IoAlign
- 1)) != 0)) {
1452 return EFI_INVALID_PARAMETER
;
1455 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
1457 Device
= NVME_DEVICE_PRIVATE_DATA_FROM_BLOCK_IO2 (This
);
1459 if ((Token
!= NULL
) && (Token
->Event
!= NULL
)) {
1460 Token
->TransactionStatus
= EFI_SUCCESS
;
1461 Status
= NvmeAsyncWrite (Device
, Buffer
, Lba
, NumberOfBlocks
, Token
);
1463 Status
= NvmeWrite (Device
, Buffer
, Lba
, NumberOfBlocks
);
1466 gBS
->RestoreTPL (OldTpl
);
1471 Flush the Block Device.
1473 If EFI_DEVICE_ERROR, EFI_NO_MEDIA,_EFI_WRITE_PROTECTED or EFI_MEDIA_CHANGED
1474 is returned and non-blocking I/O is being used, the Event associated with
1475 this request will not be signaled.
1477 @param[in] This Indicates a pointer to the calling context.
1478 @param[in,out] Token A pointer to the token associated with the
1481 @retval EFI_SUCCESS The flush request was queued if Event is not
1483 All outstanding data was written correctly to
1484 the device if the Event is NULL.
1485 @retval EFI_DEVICE_ERROR The device reported an error while writting back
1487 @retval EFI_WRITE_PROTECTED The device cannot be written to.
1488 @retval EFI_NO_MEDIA There is no media in the device.
1489 @retval EFI_MEDIA_CHANGED The MediaId is not for the current media.
1490 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack
1496 NvmeBlockIoFlushBlocksEx (
1497 IN EFI_BLOCK_IO2_PROTOCOL
*This
,
1498 IN OUT EFI_BLOCK_IO2_TOKEN
*Token
1501 NVME_DEVICE_PRIVATE_DATA
*Device
;
1506 // Check parameters.
1509 return EFI_INVALID_PARAMETER
;
1512 Device
= NVME_DEVICE_PRIVATE_DATA_FROM_BLOCK_IO2 (This
);
1515 // Wait for the asynchronous I/O queue to become empty.
1518 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
1519 IsEmpty
= IsListEmpty (&Device
->AsyncQueue
);
1520 gBS
->RestoreTPL (OldTpl
);
1530 // Signal caller event
1532 if ((Token
!= NULL
) && (Token
->Event
!= NULL
)) {
1533 Token
->TransactionStatus
= EFI_SUCCESS
;
1534 gBS
->SignalEvent (Token
->Event
);
1541 Trust transfer data from/to NVMe device.
1543 This function performs one NVMe transaction to do a trust transfer from/to NVMe device.
1545 @param Private The pointer to the NVME_CONTROLLER_PRIVATE_DATA data structure.
1546 @param Buffer The pointer to the current transaction buffer.
1547 @param SecurityProtocolId The value of the "Security Protocol" parameter of
1548 the security protocol command to be sent.
1549 @param SecurityProtocolSpecificData The value of the "Security Protocol Specific" parameter
1550 of the security protocol command to be sent.
1551 @param TransferLength The block number or sector count of the transfer.
1552 @param IsTrustSend Indicates whether it is a trust send operation or not.
1553 @param Timeout The timeout, in 100ns units, to use for the execution
1554 of the security protocol command. A Timeout value of 0
1555 means that this function will wait indefinitely for the
1556 security protocol command to execute. If Timeout is greater
1557 than zero, then this function will return EFI_TIMEOUT
1558 if the time required to execute the receive data command
1559 is greater than Timeout.
1560 @param TransferLengthOut A pointer to a buffer to store the size in bytes of the data
1561 written to the buffer. Ignore it when IsTrustSend is TRUE.
1563 @retval EFI_SUCCESS The data transfer is complete successfully.
1564 @return others Some error occurs when transferring data.
1568 TrustTransferNvmeDevice (
1569 IN OUT NVME_CONTROLLER_PRIVATE_DATA
*Private
,
1570 IN OUT VOID
*Buffer
,
1571 IN UINT8 SecurityProtocolId
,
1572 IN UINT16 SecurityProtocolSpecificData
,
1573 IN UINTN TransferLength
,
1574 IN BOOLEAN IsTrustSend
,
1576 OUT UINTN
*TransferLengthOut
1579 EFI_NVM_EXPRESS_PASS_THRU_COMMAND_PACKET CommandPacket
;
1580 EFI_NVM_EXPRESS_COMMAND Command
;
1581 EFI_NVM_EXPRESS_COMPLETION Completion
;
1583 UINT16 SpecificData
;
1585 ZeroMem (&CommandPacket
, sizeof (EFI_NVM_EXPRESS_PASS_THRU_COMMAND_PACKET
));
1586 ZeroMem (&Command
, sizeof (EFI_NVM_EXPRESS_COMMAND
));
1587 ZeroMem (&Completion
, sizeof (EFI_NVM_EXPRESS_COMPLETION
));
1589 CommandPacket
.NvmeCmd
= &Command
;
1590 CommandPacket
.NvmeCompletion
= &Completion
;
1593 // Change Endianness of SecurityProtocolSpecificData
1595 SpecificData
= (((SecurityProtocolSpecificData
<< 8) & 0xFF00) | (SecurityProtocolSpecificData
>> 8));
1598 Command
.Cdw0
.Opcode
= NVME_ADMIN_SECURITY_SEND_CMD
;
1599 CommandPacket
.TransferBuffer
= Buffer
;
1600 CommandPacket
.TransferLength
= (UINT32
)TransferLength
;
1601 CommandPacket
.NvmeCmd
->Cdw10
= (UINT32
)((SecurityProtocolId
<< 24) | (SpecificData
<< 8));
1602 CommandPacket
.NvmeCmd
->Cdw11
= (UINT32
)TransferLength
;
1604 Command
.Cdw0
.Opcode
= NVME_ADMIN_SECURITY_RECEIVE_CMD
;
1605 CommandPacket
.TransferBuffer
= Buffer
;
1606 CommandPacket
.TransferLength
= (UINT32
)TransferLength
;
1607 CommandPacket
.NvmeCmd
->Cdw10
= (UINT32
)((SecurityProtocolId
<< 24) | (SpecificData
<< 8));
1608 CommandPacket
.NvmeCmd
->Cdw11
= (UINT32
)TransferLength
;
1611 CommandPacket
.NvmeCmd
->Flags
= CDW10_VALID
| CDW11_VALID
;
1612 CommandPacket
.NvmeCmd
->Nsid
= NVME_CONTROLLER_ID
;
1613 CommandPacket
.CommandTimeout
= Timeout
;
1614 CommandPacket
.QueueType
= NVME_ADMIN_QUEUE
;
1616 Status
= Private
->Passthru
.PassThru (
1624 if (EFI_ERROR (Status
)) {
1625 *TransferLengthOut
= 0;
1627 *TransferLengthOut
= (UINTN
) TransferLength
;
1635 Send a security protocol command to a device that receives data and/or the result
1636 of one or more commands sent by SendData.
1638 The ReceiveData function sends a security protocol command to the given MediaId.
1639 The security protocol command sent is defined by SecurityProtocolId and contains
1640 the security protocol specific data SecurityProtocolSpecificData. The function
1641 returns the data from the security protocol command in PayloadBuffer.
1643 For devices supporting the SCSI command set, the security protocol command is sent
1644 using the SECURITY PROTOCOL IN command defined in SPC-4.
1646 For devices supporting the ATA command set, the security protocol command is sent
1647 using one of the TRUSTED RECEIVE commands defined in ATA8-ACS if PayloadBufferSize
1650 If the PayloadBufferSize is zero, the security protocol command is sent using the
1651 Trusted Non-Data command defined in ATA8-ACS.
1653 If PayloadBufferSize is too small to store the available data from the security
1654 protocol command, the function shall copy PayloadBufferSize bytes into the
1655 PayloadBuffer and return EFI_WARN_BUFFER_TOO_SMALL.
1657 If PayloadBuffer or PayloadTransferSize is NULL and PayloadBufferSize is non-zero,
1658 the function shall return EFI_INVALID_PARAMETER.
1660 If the given MediaId does not support security protocol commands, the function shall
1661 return EFI_UNSUPPORTED. If there is no media in the device, the function returns
1662 EFI_NO_MEDIA. If the MediaId is not the ID for the current media in the device,
1663 the function returns EFI_MEDIA_CHANGED.
1665 If the security protocol fails to complete within the Timeout period, the function
1666 shall return EFI_TIMEOUT.
1668 If the security protocol command completes without an error, the function shall
1669 return EFI_SUCCESS. If the security protocol command completes with an error, the
1670 function shall return EFI_DEVICE_ERROR.
1672 @param This Indicates a pointer to the calling context.
1673 @param MediaId ID of the medium to receive data from.
1674 @param Timeout The timeout, in 100ns units, to use for the execution
1675 of the security protocol command. A Timeout value of 0
1676 means that this function will wait indefinitely for the
1677 security protocol command to execute. If Timeout is greater
1678 than zero, then this function will return EFI_TIMEOUT
1679 if the time required to execute the receive data command
1680 is greater than Timeout.
1681 @param SecurityProtocolId The value of the "Security Protocol" parameter of
1682 the security protocol command to be sent.
1683 @param SecurityProtocolSpecificData The value of the "Security Protocol Specific" parameter
1684 of the security protocol command to be sent.
1685 @param PayloadBufferSize Size in bytes of the payload data buffer.
1686 @param PayloadBuffer A pointer to a destination buffer to store the security
1687 protocol command specific payload data for the security
1688 protocol command. The caller is responsible for having
1689 either implicit or explicit ownership of the buffer.
1690 @param PayloadTransferSize A pointer to a buffer to store the size in bytes of the
1691 data written to the payload data buffer.
1693 @retval EFI_SUCCESS The security protocol command completed successfully.
1694 @retval EFI_WARN_BUFFER_TOO_SMALL The PayloadBufferSize was too small to store the available
1695 data from the device. The PayloadBuffer contains the truncated data.
1696 @retval EFI_UNSUPPORTED The given MediaId does not support security protocol commands.
1697 @retval EFI_DEVICE_ERROR The security protocol command completed with an error.
1698 @retval EFI_NO_MEDIA There is no media in the device.
1699 @retval EFI_MEDIA_CHANGED The MediaId is not for the current media.
1700 @retval EFI_INVALID_PARAMETER The PayloadBuffer or PayloadTransferSize is NULL and
1701 PayloadBufferSize is non-zero.
1702 @retval EFI_TIMEOUT A timeout occurred while waiting for the security
1703 protocol command to execute.
1708 NvmeStorageSecurityReceiveData (
1709 IN EFI_STORAGE_SECURITY_COMMAND_PROTOCOL
*This
,
1712 IN UINT8 SecurityProtocolId
,
1713 IN UINT16 SecurityProtocolSpecificData
,
1714 IN UINTN PayloadBufferSize
,
1715 OUT VOID
*PayloadBuffer
,
1716 OUT UINTN
*PayloadTransferSize
1720 NVME_DEVICE_PRIVATE_DATA
*Device
;
1722 Status
= EFI_SUCCESS
;
1724 if ((PayloadBuffer
== NULL
) || (PayloadTransferSize
== NULL
) || (PayloadBufferSize
== 0)) {
1725 return EFI_INVALID_PARAMETER
;
1728 Device
= NVME_DEVICE_PRIVATE_DATA_FROM_STORAGE_SECURITY (This
);
1730 if (MediaId
!= Device
->BlockIo
.Media
->MediaId
) {
1731 return EFI_MEDIA_CHANGED
;
1734 if (!Device
->BlockIo
.Media
->MediaPresent
) {
1735 return EFI_NO_MEDIA
;
1738 Status
= TrustTransferNvmeDevice (
1742 SecurityProtocolSpecificData
,
1753 Send a security protocol command to a device.
1755 The SendData function sends a security protocol command containing the payload
1756 PayloadBuffer to the given MediaId. The security protocol command sent is
1757 defined by SecurityProtocolId and contains the security protocol specific data
1758 SecurityProtocolSpecificData. If the underlying protocol command requires a
1759 specific padding for the command payload, the SendData function shall add padding
1760 bytes to the command payload to satisfy the padding requirements.
1762 For devices supporting the SCSI command set, the security protocol command is sent
1763 using the SECURITY PROTOCOL OUT command defined in SPC-4.
1765 For devices supporting the ATA command set, the security protocol command is sent
1766 using one of the TRUSTED SEND commands defined in ATA8-ACS if PayloadBufferSize
1767 is non-zero. If the PayloadBufferSize is zero, the security protocol command is
1768 sent using the Trusted Non-Data command defined in ATA8-ACS.
1770 If PayloadBuffer is NULL and PayloadBufferSize is non-zero, the function shall
1771 return EFI_INVALID_PARAMETER.
1773 If the given MediaId does not support security protocol commands, the function
1774 shall return EFI_UNSUPPORTED. If there is no media in the device, the function
1775 returns EFI_NO_MEDIA. If the MediaId is not the ID for the current media in the
1776 device, the function returns EFI_MEDIA_CHANGED.
1778 If the security protocol fails to complete within the Timeout period, the function
1779 shall return EFI_TIMEOUT.
1781 If the security protocol command completes without an error, the function shall return
1782 EFI_SUCCESS. If the security protocol command completes with an error, the function
1783 shall return EFI_DEVICE_ERROR.
1785 @param This Indicates a pointer to the calling context.
1786 @param MediaId ID of the medium to receive data from.
1787 @param Timeout The timeout, in 100ns units, to use for the execution
1788 of the security protocol command. A Timeout value of 0
1789 means that this function will wait indefinitely for the
1790 security protocol command to execute. If Timeout is greater
1791 than zero, then this function will return EFI_TIMEOUT
1792 if the time required to execute the send data command
1793 is greater than Timeout.
1794 @param SecurityProtocolId The value of the "Security Protocol" parameter of
1795 the security protocol command to be sent.
1796 @param SecurityProtocolSpecificData The value of the "Security Protocol Specific" parameter
1797 of the security protocol command to be sent.
1798 @param PayloadBufferSize Size in bytes of the payload data buffer.
1799 @param PayloadBuffer A pointer to a destination buffer to store the security
1800 protocol command specific payload data for the security
1803 @retval EFI_SUCCESS The security protocol command completed successfully.
1804 @retval EFI_UNSUPPORTED The given MediaId does not support security protocol commands.
1805 @retval EFI_DEVICE_ERROR The security protocol command completed with an error.
1806 @retval EFI_NO_MEDIA There is no media in the device.
1807 @retval EFI_MEDIA_CHANGED The MediaId is not for the current media.
1808 @retval EFI_INVALID_PARAMETER The PayloadBuffer is NULL and PayloadBufferSize is non-zero.
1809 @retval EFI_TIMEOUT A timeout occurred while waiting for the security
1810 protocol command to execute.
1815 NvmeStorageSecuritySendData (
1816 IN EFI_STORAGE_SECURITY_COMMAND_PROTOCOL
*This
,
1819 IN UINT8 SecurityProtocolId
,
1820 IN UINT16 SecurityProtocolSpecificData
,
1821 IN UINTN PayloadBufferSize
,
1822 IN VOID
*PayloadBuffer
1826 NVME_DEVICE_PRIVATE_DATA
*Device
;
1828 Status
= EFI_SUCCESS
;
1830 if ((PayloadBuffer
== NULL
) && (PayloadBufferSize
!= 0)) {
1831 return EFI_INVALID_PARAMETER
;
1834 Device
= NVME_DEVICE_PRIVATE_DATA_FROM_STORAGE_SECURITY (This
);
1836 if (MediaId
!= Device
->BlockIo
.Media
->MediaId
) {
1837 return EFI_MEDIA_CHANGED
;
1840 if (!Device
->BlockIo
.Media
->MediaPresent
) {
1841 return EFI_NO_MEDIA
;
1844 Status
= TrustTransferNvmeDevice (
1848 SecurityProtocolSpecificData
,