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
)) {
215 DEBUG ((DEBUG_BLKIO
, "%a: Lba = 0x%08Lx, Original = 0x%08Lx, "
216 "Remaining = 0x%08Lx, BlockSize = 0x%x, Status = %r\n", __FUNCTION__
, Lba
,
217 (UINT64
)OrginalBlocks
, (UINT64
)Blocks
, BlockSize
, Status
));
223 Write some blocks to the device.
225 @param Device The pointer to the NVME_DEVICE_PRIVATE_DATA data structure.
226 @param Buffer The buffer to be written into the device.
227 @param Lba The start block number.
228 @param Blocks Total block number to be written.
230 @retval EFI_SUCCESS Datum are written into the buffer.
231 @retval Others Fail to write all the datum.
236 IN NVME_DEVICE_PRIVATE_DATA
*Device
,
244 NVME_CONTROLLER_PRIVATE_DATA
*Private
;
245 UINT32 MaxTransferBlocks
;
251 // Wait for the device's asynchronous I/O queue to become empty.
254 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
255 IsEmpty
= IsListEmpty (&Device
->AsyncQueue
);
256 gBS
->RestoreTPL (OldTpl
);
265 Status
= EFI_SUCCESS
;
266 Private
= Device
->Controller
;
267 BlockSize
= Device
->Media
.BlockSize
;
268 OrginalBlocks
= Blocks
;
270 if (Private
->ControllerData
->Mdts
!= 0) {
271 MaxTransferBlocks
= (1 << (Private
->ControllerData
->Mdts
)) * (1 << (Private
->Cap
.Mpsmin
+ 12)) / BlockSize
;
273 MaxTransferBlocks
= 1024;
277 if (Blocks
> MaxTransferBlocks
) {
278 Status
= WriteSectors (Device
, (UINT64
)(UINTN
)Buffer
, Lba
, MaxTransferBlocks
);
280 Blocks
-= MaxTransferBlocks
;
281 Buffer
= (VOID
*)(UINTN
)((UINT64
)(UINTN
)Buffer
+ MaxTransferBlocks
* BlockSize
);
282 Lba
+= MaxTransferBlocks
;
284 Status
= WriteSectors (Device
, (UINT64
)(UINTN
)Buffer
, Lba
, (UINT32
)Blocks
);
288 if (EFI_ERROR(Status
)) {
293 DEBUG ((DEBUG_BLKIO
, "%a: Lba = 0x%08Lx, Original = 0x%08Lx, "
294 "Remaining = 0x%08Lx, BlockSize = 0x%x, Status = %r\n", __FUNCTION__
, Lba
,
295 (UINT64
)OrginalBlocks
, (UINT64
)Blocks
, BlockSize
, Status
));
301 Flushes all modified data to the device.
303 @param Device The pointer to the NVME_DEVICE_PRIVATE_DATA data structure.
305 @retval EFI_SUCCESS Datum are written into the buffer.
306 @retval Others Fail to write all the datum.
311 IN NVME_DEVICE_PRIVATE_DATA
*Device
314 NVME_CONTROLLER_PRIVATE_DATA
*Private
;
315 EFI_NVM_EXPRESS_PASS_THRU_COMMAND_PACKET CommandPacket
;
316 EFI_NVM_EXPRESS_COMMAND Command
;
317 EFI_NVM_EXPRESS_COMPLETION Completion
;
320 Private
= Device
->Controller
;
322 ZeroMem (&CommandPacket
, sizeof(EFI_NVM_EXPRESS_PASS_THRU_COMMAND_PACKET
));
323 ZeroMem (&Command
, sizeof(EFI_NVM_EXPRESS_COMMAND
));
324 ZeroMem (&Completion
, sizeof(EFI_NVM_EXPRESS_COMPLETION
));
326 CommandPacket
.NvmeCmd
= &Command
;
327 CommandPacket
.NvmeCompletion
= &Completion
;
329 CommandPacket
.NvmeCmd
->Cdw0
.Opcode
= NVME_IO_FLUSH_OPC
;
330 CommandPacket
.NvmeCmd
->Nsid
= Device
->NamespaceId
;
331 CommandPacket
.CommandTimeout
= NVME_GENERIC_TIMEOUT
;
332 CommandPacket
.QueueType
= NVME_IO_QUEUE
;
334 Status
= Private
->Passthru
.PassThru (
345 Nonblocking I/O callback funtion when the event is signaled.
347 @param[in] Event The Event this notify function registered to.
348 @param[in] Context Pointer to the context data registered to the
359 NVME_BLKIO2_SUBTASK
*Subtask
;
360 NVME_BLKIO2_REQUEST
*Request
;
362 EFI_BLOCK_IO2_TOKEN
*Token
;
364 gBS
->CloseEvent (Event
);
366 Subtask
= (NVME_BLKIO2_SUBTASK
*) Context
;
367 Completion
= (NVME_CQ
*) Subtask
->CommandPacket
->NvmeCompletion
;
368 Request
= Subtask
->BlockIo2Request
;
369 Token
= Request
->Token
;
371 if (Token
->TransactionStatus
== EFI_SUCCESS
) {
373 // If previous subtask already fails, do not check the result of
374 // subsequent subtasks.
376 if ((Completion
->Sct
!= 0) || (Completion
->Sc
!= 0)) {
377 Token
->TransactionStatus
= EFI_DEVICE_ERROR
;
380 // Dump completion entry status for debugging.
383 NvmeDumpStatus (Completion
);
389 // Remove the subtask from the BlockIo2 subtasks list.
391 RemoveEntryList (&Subtask
->Link
);
393 if (IsListEmpty (&Request
->SubtasksQueue
) && Request
->LastSubtaskSubmitted
) {
395 // Remove the BlockIo2 request from the device asynchronous queue.
397 RemoveEntryList (&Request
->Link
);
399 gBS
->SignalEvent (Token
->Event
);
402 FreePool (Subtask
->CommandPacket
->NvmeCmd
);
403 FreePool (Subtask
->CommandPacket
->NvmeCompletion
);
404 FreePool (Subtask
->CommandPacket
);
409 Read some sectors from the device in an asynchronous manner.
411 @param Device The pointer to the NVME_DEVICE_PRIVATE_DATA data
413 @param Request The pointer to the NVME_BLKIO2_REQUEST data structure.
414 @param Buffer The buffer used to store the data read from the device.
415 @param Lba The start block number.
416 @param Blocks Total block number to be read.
417 @param IsLast The last subtask of an asynchronous read request.
419 @retval EFI_SUCCESS Asynchronous read request has been queued.
420 @retval Others Fail to send the asynchronous request.
425 IN NVME_DEVICE_PRIVATE_DATA
*Device
,
426 IN NVME_BLKIO2_REQUEST
*Request
,
433 NVME_CONTROLLER_PRIVATE_DATA
*Private
;
435 NVME_BLKIO2_SUBTASK
*Subtask
;
436 EFI_NVM_EXPRESS_PASS_THRU_COMMAND_PACKET
*CommandPacket
;
437 EFI_NVM_EXPRESS_COMMAND
*Command
;
438 EFI_NVM_EXPRESS_COMPLETION
*Completion
;
443 Private
= Device
->Controller
;
444 BlockSize
= Device
->Media
.BlockSize
;
445 Bytes
= Blocks
* BlockSize
;
446 CommandPacket
= NULL
;
450 Subtask
= AllocateZeroPool (sizeof (NVME_BLKIO2_SUBTASK
));
451 if (Subtask
== NULL
) {
452 Status
= EFI_OUT_OF_RESOURCES
;
456 Subtask
->Signature
= NVME_BLKIO2_SUBTASK_SIGNATURE
;
457 Subtask
->IsLast
= IsLast
;
458 Subtask
->NamespaceId
= Device
->NamespaceId
;
459 Subtask
->BlockIo2Request
= Request
;
461 CommandPacket
= AllocateZeroPool (sizeof (EFI_NVM_EXPRESS_PASS_THRU_COMMAND_PACKET
));
462 if (CommandPacket
== NULL
) {
463 Status
= EFI_OUT_OF_RESOURCES
;
466 Subtask
->CommandPacket
= CommandPacket
;
469 Command
= AllocateZeroPool (sizeof (EFI_NVM_EXPRESS_COMMAND
));
470 if (Command
== NULL
) {
471 Status
= EFI_OUT_OF_RESOURCES
;
475 Completion
= AllocateZeroPool (sizeof (EFI_NVM_EXPRESS_COMPLETION
));
476 if (Completion
== NULL
) {
477 Status
= EFI_OUT_OF_RESOURCES
;
484 Status
= gBS
->CreateEvent (
491 if (EFI_ERROR(Status
)) {
495 CommandPacket
->NvmeCmd
= Command
;
496 CommandPacket
->NvmeCompletion
= Completion
;
498 CommandPacket
->NvmeCmd
->Cdw0
.Opcode
= NVME_IO_READ_OPC
;
499 CommandPacket
->NvmeCmd
->Nsid
= Device
->NamespaceId
;
500 CommandPacket
->TransferBuffer
= (VOID
*)(UINTN
)Buffer
;
502 CommandPacket
->TransferLength
= Bytes
;
503 CommandPacket
->CommandTimeout
= NVME_GENERIC_TIMEOUT
;
504 CommandPacket
->QueueType
= NVME_IO_QUEUE
;
506 CommandPacket
->NvmeCmd
->Cdw10
= (UINT32
)Lba
;
507 CommandPacket
->NvmeCmd
->Cdw11
= (UINT32
)RShiftU64(Lba
, 32);
508 CommandPacket
->NvmeCmd
->Cdw12
= (Blocks
- 1) & 0xFFFF;
510 CommandPacket
->NvmeCmd
->Flags
= CDW10_VALID
| CDW11_VALID
| CDW12_VALID
;
512 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
513 InsertTailList (&Private
->UnsubmittedSubtasks
, &Subtask
->Link
);
514 Request
->UnsubmittedSubtaskNum
++;
515 gBS
->RestoreTPL (OldTpl
);
521 // Resource cleanup if asynchronous read request has not been queued.
523 if (Completion
!= NULL
) {
524 FreePool (Completion
);
527 if (Command
!= NULL
) {
531 if (CommandPacket
!= NULL
) {
532 FreePool (CommandPacket
);
535 if (Subtask
!= NULL
) {
536 if (Subtask
->Event
!= NULL
) {
537 gBS
->CloseEvent (Subtask
->Event
);
547 Write some sectors from the device in an asynchronous manner.
549 @param Device The pointer to the NVME_DEVICE_PRIVATE_DATA data
551 @param Request The pointer to the NVME_BLKIO2_REQUEST data structure.
552 @param Buffer The buffer used to store the data written to the
554 @param Lba The start block number.
555 @param Blocks Total block number to be written.
556 @param IsLast The last subtask of an asynchronous write request.
558 @retval EFI_SUCCESS Asynchronous write request has been queued.
559 @retval Others Fail to send the asynchronous request.
564 IN NVME_DEVICE_PRIVATE_DATA
*Device
,
565 IN NVME_BLKIO2_REQUEST
*Request
,
572 NVME_CONTROLLER_PRIVATE_DATA
*Private
;
574 NVME_BLKIO2_SUBTASK
*Subtask
;
575 EFI_NVM_EXPRESS_PASS_THRU_COMMAND_PACKET
*CommandPacket
;
576 EFI_NVM_EXPRESS_COMMAND
*Command
;
577 EFI_NVM_EXPRESS_COMPLETION
*Completion
;
582 Private
= Device
->Controller
;
583 BlockSize
= Device
->Media
.BlockSize
;
584 Bytes
= Blocks
* BlockSize
;
585 CommandPacket
= NULL
;
589 Subtask
= AllocateZeroPool (sizeof (NVME_BLKIO2_SUBTASK
));
590 if (Subtask
== NULL
) {
591 Status
= EFI_OUT_OF_RESOURCES
;
595 Subtask
->Signature
= NVME_BLKIO2_SUBTASK_SIGNATURE
;
596 Subtask
->IsLast
= IsLast
;
597 Subtask
->NamespaceId
= Device
->NamespaceId
;
598 Subtask
->BlockIo2Request
= Request
;
600 CommandPacket
= AllocateZeroPool (sizeof (EFI_NVM_EXPRESS_PASS_THRU_COMMAND_PACKET
));
601 if (CommandPacket
== NULL
) {
602 Status
= EFI_OUT_OF_RESOURCES
;
605 Subtask
->CommandPacket
= CommandPacket
;
608 Command
= AllocateZeroPool (sizeof (EFI_NVM_EXPRESS_COMMAND
));
609 if (Command
== NULL
) {
610 Status
= EFI_OUT_OF_RESOURCES
;
614 Completion
= AllocateZeroPool (sizeof (EFI_NVM_EXPRESS_COMPLETION
));
615 if (Completion
== NULL
) {
616 Status
= EFI_OUT_OF_RESOURCES
;
623 Status
= gBS
->CreateEvent (
630 if (EFI_ERROR(Status
)) {
634 CommandPacket
->NvmeCmd
= Command
;
635 CommandPacket
->NvmeCompletion
= Completion
;
637 CommandPacket
->NvmeCmd
->Cdw0
.Opcode
= NVME_IO_WRITE_OPC
;
638 CommandPacket
->NvmeCmd
->Nsid
= Device
->NamespaceId
;
639 CommandPacket
->TransferBuffer
= (VOID
*)(UINTN
)Buffer
;
641 CommandPacket
->TransferLength
= Bytes
;
642 CommandPacket
->CommandTimeout
= NVME_GENERIC_TIMEOUT
;
643 CommandPacket
->QueueType
= NVME_IO_QUEUE
;
645 CommandPacket
->NvmeCmd
->Cdw10
= (UINT32
)Lba
;
646 CommandPacket
->NvmeCmd
->Cdw11
= (UINT32
)RShiftU64(Lba
, 32);
648 // Set Force Unit Access bit (bit 30) to use write-through behaviour
650 CommandPacket
->NvmeCmd
->Cdw12
= ((Blocks
- 1) & 0xFFFF) | BIT30
;
652 CommandPacket
->NvmeCmd
->Flags
= CDW10_VALID
| CDW11_VALID
| CDW12_VALID
;
654 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
655 InsertTailList (&Private
->UnsubmittedSubtasks
, &Subtask
->Link
);
656 Request
->UnsubmittedSubtaskNum
++;
657 gBS
->RestoreTPL (OldTpl
);
663 // Resource cleanup if asynchronous read request has not been queued.
665 if (Completion
!= NULL
) {
666 FreePool (Completion
);
669 if (Command
!= NULL
) {
673 if (CommandPacket
!= NULL
) {
674 FreePool (CommandPacket
);
677 if (Subtask
!= NULL
) {
678 if (Subtask
->Event
!= NULL
) {
679 gBS
->CloseEvent (Subtask
->Event
);
689 Read some blocks from the device in an asynchronous manner.
691 @param Device The pointer to the NVME_DEVICE_PRIVATE_DATA data
693 @param Buffer The buffer used to store the data read from the device.
694 @param Lba The start block number.
695 @param Blocks Total block number to be read.
696 @param Token A pointer to the token associated with the transaction.
698 @retval EFI_SUCCESS Data are read from the device.
699 @retval Others Fail to read all the data.
704 IN NVME_DEVICE_PRIVATE_DATA
*Device
,
708 IN EFI_BLOCK_IO2_TOKEN
*Token
713 NVME_CONTROLLER_PRIVATE_DATA
*Private
;
714 NVME_BLKIO2_REQUEST
*BlkIo2Req
;
715 UINT32 MaxTransferBlocks
;
720 Status
= EFI_SUCCESS
;
721 Private
= Device
->Controller
;
722 BlockSize
= Device
->Media
.BlockSize
;
723 OrginalBlocks
= Blocks
;
724 BlkIo2Req
= AllocateZeroPool (sizeof (NVME_BLKIO2_REQUEST
));
725 if (BlkIo2Req
== NULL
) {
726 return EFI_OUT_OF_RESOURCES
;
729 BlkIo2Req
->Signature
= NVME_BLKIO2_REQUEST_SIGNATURE
;
730 BlkIo2Req
->Token
= Token
;
732 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
733 InsertTailList (&Device
->AsyncQueue
, &BlkIo2Req
->Link
);
734 gBS
->RestoreTPL (OldTpl
);
736 InitializeListHead (&BlkIo2Req
->SubtasksQueue
);
738 if (Private
->ControllerData
->Mdts
!= 0) {
739 MaxTransferBlocks
= (1 << (Private
->ControllerData
->Mdts
)) * (1 << (Private
->Cap
.Mpsmin
+ 12)) / BlockSize
;
741 MaxTransferBlocks
= 1024;
745 if (Blocks
> MaxTransferBlocks
) {
746 Status
= AsyncReadSectors (
748 BlkIo2Req
, (UINT64
)(UINTN
)Buffer
,
754 Blocks
-= MaxTransferBlocks
;
755 Buffer
= (VOID
*)(UINTN
)((UINT64
)(UINTN
)Buffer
+ MaxTransferBlocks
* BlockSize
);
756 Lba
+= MaxTransferBlocks
;
758 Status
= AsyncReadSectors (
761 (UINT64
)(UINTN
)Buffer
,
770 if (EFI_ERROR(Status
)) {
771 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
772 IsEmpty
= IsListEmpty (&BlkIo2Req
->SubtasksQueue
) &&
773 (BlkIo2Req
->UnsubmittedSubtaskNum
== 0);
777 // Remove the BlockIo2 request from the device asynchronous queue.
779 RemoveEntryList (&BlkIo2Req
->Link
);
780 FreePool (BlkIo2Req
);
781 Status
= EFI_DEVICE_ERROR
;
784 // There are previous BlockIo2 subtasks still running, EFI_SUCCESS
785 // should be returned to make sure that the caller does not free
786 // resources still using by these requests.
788 Status
= EFI_SUCCESS
;
789 Token
->TransactionStatus
= EFI_DEVICE_ERROR
;
790 BlkIo2Req
->LastSubtaskSubmitted
= TRUE
;
793 gBS
->RestoreTPL (OldTpl
);
799 DEBUG ((DEBUG_BLKIO
, "%a: Lba = 0x%08Lx, Original = 0x%08Lx, "
800 "Remaining = 0x%08Lx, BlockSize = 0x%x, Status = %r\n", __FUNCTION__
, Lba
,
801 (UINT64
)OrginalBlocks
, (UINT64
)Blocks
, BlockSize
, Status
));
807 Write some blocks from the device in an asynchronous manner.
809 @param Device The pointer to the NVME_DEVICE_PRIVATE_DATA data
811 @param Buffer The buffer used to store the data written to the
813 @param Lba The start block number.
814 @param Blocks Total block number to be written.
815 @param Token A pointer to the token associated with the transaction.
817 @retval EFI_SUCCESS Data are written to the device.
818 @retval Others Fail to write all the data.
823 IN NVME_DEVICE_PRIVATE_DATA
*Device
,
827 IN EFI_BLOCK_IO2_TOKEN
*Token
832 NVME_CONTROLLER_PRIVATE_DATA
*Private
;
833 NVME_BLKIO2_REQUEST
*BlkIo2Req
;
834 UINT32 MaxTransferBlocks
;
839 Status
= EFI_SUCCESS
;
840 Private
= Device
->Controller
;
841 BlockSize
= Device
->Media
.BlockSize
;
842 OrginalBlocks
= Blocks
;
843 BlkIo2Req
= AllocateZeroPool (sizeof (NVME_BLKIO2_REQUEST
));
844 if (BlkIo2Req
== NULL
) {
845 return EFI_OUT_OF_RESOURCES
;
848 BlkIo2Req
->Signature
= NVME_BLKIO2_REQUEST_SIGNATURE
;
849 BlkIo2Req
->Token
= Token
;
851 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
852 InsertTailList (&Device
->AsyncQueue
, &BlkIo2Req
->Link
);
853 gBS
->RestoreTPL (OldTpl
);
855 InitializeListHead (&BlkIo2Req
->SubtasksQueue
);
857 if (Private
->ControllerData
->Mdts
!= 0) {
858 MaxTransferBlocks
= (1 << (Private
->ControllerData
->Mdts
)) * (1 << (Private
->Cap
.Mpsmin
+ 12)) / BlockSize
;
860 MaxTransferBlocks
= 1024;
864 if (Blocks
> MaxTransferBlocks
) {
865 Status
= AsyncWriteSectors (
868 (UINT64
)(UINTN
)Buffer
,
874 Blocks
-= MaxTransferBlocks
;
875 Buffer
= (VOID
*)(UINTN
)((UINT64
)(UINTN
)Buffer
+ MaxTransferBlocks
* BlockSize
);
876 Lba
+= MaxTransferBlocks
;
878 Status
= AsyncWriteSectors (
881 (UINT64
)(UINTN
)Buffer
,
890 if (EFI_ERROR(Status
)) {
891 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
892 IsEmpty
= IsListEmpty (&BlkIo2Req
->SubtasksQueue
) &&
893 (BlkIo2Req
->UnsubmittedSubtaskNum
== 0);
897 // Remove the BlockIo2 request from the device asynchronous queue.
899 RemoveEntryList (&BlkIo2Req
->Link
);
900 FreePool (BlkIo2Req
);
901 Status
= EFI_DEVICE_ERROR
;
904 // There are previous BlockIo2 subtasks still running, EFI_SUCCESS
905 // should be returned to make sure that the caller does not free
906 // resources still using by these requests.
908 Status
= EFI_SUCCESS
;
909 Token
->TransactionStatus
= EFI_DEVICE_ERROR
;
910 BlkIo2Req
->LastSubtaskSubmitted
= TRUE
;
913 gBS
->RestoreTPL (OldTpl
);
919 DEBUG ((DEBUG_BLKIO
, "%a: Lba = 0x%08Lx, Original = 0x%08Lx, "
920 "Remaining = 0x%08Lx, BlockSize = 0x%x, Status = %r\n", __FUNCTION__
, Lba
,
921 (UINT64
)OrginalBlocks
, (UINT64
)Blocks
, BlockSize
, Status
));
927 Reset the Block Device.
929 @param This Indicates a pointer to the calling context.
930 @param ExtendedVerification Driver may perform diagnostics on reset.
932 @retval EFI_SUCCESS The device was reset.
933 @retval EFI_DEVICE_ERROR The device is not functioning properly and could
940 IN EFI_BLOCK_IO_PROTOCOL
*This
,
941 IN BOOLEAN ExtendedVerification
945 NVME_CONTROLLER_PRIVATE_DATA
*Private
;
946 NVME_DEVICE_PRIVATE_DATA
*Device
;
950 return EFI_INVALID_PARAMETER
;
954 // For Nvm Express subsystem, reset block device means reset controller.
956 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
958 Device
= NVME_DEVICE_PRIVATE_DATA_FROM_BLOCK_IO (This
);
960 Private
= Device
->Controller
;
962 Status
= NvmeControllerInit (Private
);
964 if (EFI_ERROR (Status
)) {
965 Status
= EFI_DEVICE_ERROR
;
968 gBS
->RestoreTPL (OldTpl
);
974 Read BufferSize bytes from Lba into Buffer.
976 @param This Indicates a pointer to the calling context.
977 @param MediaId Id of the media, changes every time the media is replaced.
978 @param Lba The starting Logical Block Address to read from.
979 @param BufferSize Size of Buffer, must be a multiple of device block size.
980 @param Buffer A pointer to the destination buffer for the data. The caller is
981 responsible for either having implicit or explicit ownership of the buffer.
983 @retval EFI_SUCCESS The data was read correctly from the device.
984 @retval EFI_DEVICE_ERROR The device reported an error while performing the read.
985 @retval EFI_NO_MEDIA There is no media in the device.
986 @retval EFI_MEDIA_CHANGED The MediaId does not matched the current device.
987 @retval EFI_BAD_BUFFER_SIZE The Buffer was not a multiple of the block size of the device.
988 @retval EFI_INVALID_PARAMETER The read request contains LBAs that are not valid,
989 or the buffer is not on proper alignment.
994 NvmeBlockIoReadBlocks (
995 IN EFI_BLOCK_IO_PROTOCOL
*This
,
1002 NVME_DEVICE_PRIVATE_DATA
*Device
;
1004 EFI_BLOCK_IO_MEDIA
*Media
;
1006 UINTN NumberOfBlocks
;
1011 // Check parameters.
1014 return EFI_INVALID_PARAMETER
;
1017 Media
= This
->Media
;
1019 if (MediaId
!= Media
->MediaId
) {
1020 return EFI_MEDIA_CHANGED
;
1023 if (Buffer
== NULL
) {
1024 return EFI_INVALID_PARAMETER
;
1027 if (BufferSize
== 0) {
1031 BlockSize
= Media
->BlockSize
;
1032 if ((BufferSize
% BlockSize
) != 0) {
1033 return EFI_BAD_BUFFER_SIZE
;
1036 NumberOfBlocks
= BufferSize
/ BlockSize
;
1037 if ((Lba
+ NumberOfBlocks
- 1) > Media
->LastBlock
) {
1038 return EFI_INVALID_PARAMETER
;
1041 IoAlign
= Media
->IoAlign
;
1042 if (IoAlign
> 0 && (((UINTN
) Buffer
& (IoAlign
- 1)) != 0)) {
1043 return EFI_INVALID_PARAMETER
;
1046 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
1048 Device
= NVME_DEVICE_PRIVATE_DATA_FROM_BLOCK_IO (This
);
1050 Status
= NvmeRead (Device
, Buffer
, Lba
, NumberOfBlocks
);
1052 gBS
->RestoreTPL (OldTpl
);
1057 Write BufferSize bytes from Lba into Buffer.
1059 @param This Indicates a pointer to the calling context.
1060 @param MediaId The media ID that the write request is for.
1061 @param Lba The starting logical block address to be written. The caller is
1062 responsible for writing to only legitimate locations.
1063 @param BufferSize Size of Buffer, must be a multiple of device block size.
1064 @param Buffer A pointer to the source buffer for the data.
1066 @retval EFI_SUCCESS The data was written correctly to the device.
1067 @retval EFI_WRITE_PROTECTED The device can not be written to.
1068 @retval EFI_DEVICE_ERROR The device reported an error while performing the write.
1069 @retval EFI_NO_MEDIA There is no media in the device.
1070 @retval EFI_MEDIA_CHNAGED The MediaId does not matched the current device.
1071 @retval EFI_BAD_BUFFER_SIZE The Buffer was not a multiple of the block size of the device.
1072 @retval EFI_INVALID_PARAMETER The write request contains LBAs that are not valid,
1073 or the buffer is not on proper alignment.
1078 NvmeBlockIoWriteBlocks (
1079 IN EFI_BLOCK_IO_PROTOCOL
*This
,
1082 IN UINTN BufferSize
,
1086 NVME_DEVICE_PRIVATE_DATA
*Device
;
1088 EFI_BLOCK_IO_MEDIA
*Media
;
1090 UINTN NumberOfBlocks
;
1095 // Check parameters.
1098 return EFI_INVALID_PARAMETER
;
1101 Media
= This
->Media
;
1103 if (MediaId
!= Media
->MediaId
) {
1104 return EFI_MEDIA_CHANGED
;
1107 if (Buffer
== NULL
) {
1108 return EFI_INVALID_PARAMETER
;
1111 if (BufferSize
== 0) {
1115 BlockSize
= Media
->BlockSize
;
1116 if ((BufferSize
% BlockSize
) != 0) {
1117 return EFI_BAD_BUFFER_SIZE
;
1120 NumberOfBlocks
= BufferSize
/ BlockSize
;
1121 if ((Lba
+ NumberOfBlocks
- 1) > Media
->LastBlock
) {
1122 return EFI_INVALID_PARAMETER
;
1125 IoAlign
= Media
->IoAlign
;
1126 if (IoAlign
> 0 && (((UINTN
) Buffer
& (IoAlign
- 1)) != 0)) {
1127 return EFI_INVALID_PARAMETER
;
1130 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
1132 Device
= NVME_DEVICE_PRIVATE_DATA_FROM_BLOCK_IO (This
);
1134 Status
= NvmeWrite (Device
, Buffer
, Lba
, NumberOfBlocks
);
1136 gBS
->RestoreTPL (OldTpl
);
1142 Flush the Block Device.
1144 @param This Indicates a pointer to the calling context.
1146 @retval EFI_SUCCESS All outstanding data was written to the device.
1147 @retval EFI_DEVICE_ERROR The device reported an error while writing back the data.
1148 @retval EFI_NO_MEDIA There is no media in the device.
1153 NvmeBlockIoFlushBlocks (
1154 IN EFI_BLOCK_IO_PROTOCOL
*This
1157 NVME_DEVICE_PRIVATE_DATA
*Device
;
1162 // Check parameters.
1165 return EFI_INVALID_PARAMETER
;
1168 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
1170 Device
= NVME_DEVICE_PRIVATE_DATA_FROM_BLOCK_IO (This
);
1172 Status
= NvmeFlush (Device
);
1174 gBS
->RestoreTPL (OldTpl
);
1180 Reset the block device hardware.
1182 @param[in] This Indicates a pointer to the calling context.
1183 @param[in] ExtendedVerification Indicates that the driver may perform a more
1184 exhausive verfication operation of the
1185 device during reset.
1187 @retval EFI_SUCCESS The device was reset.
1188 @retval EFI_DEVICE_ERROR The device is not functioning properly and could
1194 NvmeBlockIoResetEx (
1195 IN EFI_BLOCK_IO2_PROTOCOL
*This
,
1196 IN BOOLEAN ExtendedVerification
1200 NVME_DEVICE_PRIVATE_DATA
*Device
;
1201 NVME_CONTROLLER_PRIVATE_DATA
*Private
;
1206 return EFI_INVALID_PARAMETER
;
1209 Device
= NVME_DEVICE_PRIVATE_DATA_FROM_BLOCK_IO2 (This
);
1210 Private
= Device
->Controller
;
1213 // Wait for the asynchronous PassThru queue to become empty.
1216 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
1217 IsEmpty
= IsListEmpty (&Private
->AsyncPassThruQueue
) &&
1218 IsListEmpty (&Private
->UnsubmittedSubtasks
);
1219 gBS
->RestoreTPL (OldTpl
);
1228 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
1230 Status
= NvmeControllerInit (Private
);
1232 if (EFI_ERROR (Status
)) {
1233 Status
= EFI_DEVICE_ERROR
;
1236 gBS
->RestoreTPL (OldTpl
);
1242 Read BufferSize bytes from Lba into Buffer.
1244 This function reads the requested number of blocks from the device. All the
1245 blocks are read, or an error is returned.
1246 If EFI_DEVICE_ERROR, EFI_NO_MEDIA,_or EFI_MEDIA_CHANGED is returned and
1247 non-blocking I/O is being used, the Event associated with this request will
1250 @param[in] This Indicates a pointer to the calling context.
1251 @param[in] MediaId Id of the media, changes every time the media is
1253 @param[in] Lba The starting Logical Block Address to read from.
1254 @param[in, out] Token A pointer to the token associated with the
1256 @param[in] BufferSize Size of Buffer, must be a multiple of device
1258 @param[out] Buffer A pointer to the destination buffer for the data.
1259 The caller is responsible for either having
1260 implicit or explicit ownership of the buffer.
1262 @retval EFI_SUCCESS The read request was queued if Token->Event is
1263 not NULL.The data was read correctly from the
1264 device if the Token->Event is NULL.
1265 @retval EFI_DEVICE_ERROR The device reported an error while performing
1267 @retval EFI_NO_MEDIA There is no media in the device.
1268 @retval EFI_MEDIA_CHANGED The MediaId is not for the current media.
1269 @retval EFI_BAD_BUFFER_SIZE The BufferSize parameter is not a multiple of
1270 the intrinsic block size of the device.
1271 @retval EFI_INVALID_PARAMETER The read request contains LBAs that are not
1272 valid, or the buffer is not on proper
1274 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a
1280 NvmeBlockIoReadBlocksEx (
1281 IN EFI_BLOCK_IO2_PROTOCOL
*This
,
1284 IN OUT EFI_BLOCK_IO2_TOKEN
*Token
,
1285 IN UINTN BufferSize
,
1289 NVME_DEVICE_PRIVATE_DATA
*Device
;
1291 EFI_BLOCK_IO_MEDIA
*Media
;
1293 UINTN NumberOfBlocks
;
1298 // Check parameters.
1301 return EFI_INVALID_PARAMETER
;
1304 Media
= This
->Media
;
1306 if (MediaId
!= Media
->MediaId
) {
1307 return EFI_MEDIA_CHANGED
;
1310 if (Buffer
== NULL
) {
1311 return EFI_INVALID_PARAMETER
;
1314 if (BufferSize
== 0) {
1315 if ((Token
!= NULL
) && (Token
->Event
!= NULL
)) {
1316 Token
->TransactionStatus
= EFI_SUCCESS
;
1317 gBS
->SignalEvent (Token
->Event
);
1322 BlockSize
= Media
->BlockSize
;
1323 if ((BufferSize
% BlockSize
) != 0) {
1324 return EFI_BAD_BUFFER_SIZE
;
1327 NumberOfBlocks
= BufferSize
/ BlockSize
;
1328 if ((Lba
+ NumberOfBlocks
- 1) > Media
->LastBlock
) {
1329 return EFI_INVALID_PARAMETER
;
1332 IoAlign
= Media
->IoAlign
;
1333 if (IoAlign
> 0 && (((UINTN
) Buffer
& (IoAlign
- 1)) != 0)) {
1334 return EFI_INVALID_PARAMETER
;
1337 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
1339 Device
= NVME_DEVICE_PRIVATE_DATA_FROM_BLOCK_IO2 (This
);
1341 if ((Token
!= NULL
) && (Token
->Event
!= NULL
)) {
1342 Token
->TransactionStatus
= EFI_SUCCESS
;
1343 Status
= NvmeAsyncRead (Device
, Buffer
, Lba
, NumberOfBlocks
, Token
);
1345 Status
= NvmeRead (Device
, Buffer
, Lba
, NumberOfBlocks
);
1348 gBS
->RestoreTPL (OldTpl
);
1353 Write BufferSize bytes from Lba into Buffer.
1355 This function writes the requested number of blocks to the device. All blocks
1356 are written, or an error is returned.If EFI_DEVICE_ERROR, EFI_NO_MEDIA,
1357 EFI_WRITE_PROTECTED or EFI_MEDIA_CHANGED is returned and non-blocking I/O is
1358 being used, the Event associated with this request will not be signaled.
1360 @param[in] This Indicates a pointer to the calling context.
1361 @param[in] MediaId The media ID that the write request is for.
1362 @param[in] Lba The starting logical block address to be written.
1363 The caller is responsible for writing to only
1364 legitimate locations.
1365 @param[in, out] Token A pointer to the token associated with the
1367 @param[in] BufferSize Size of Buffer, must be a multiple of device
1369 @param[in] Buffer A pointer to the source buffer for the data.
1371 @retval EFI_SUCCESS The write request was queued if Event is not
1373 The data was written correctly to the device if
1375 @retval EFI_WRITE_PROTECTED The device can not be written to.
1376 @retval EFI_NO_MEDIA There is no media in the device.
1377 @retval EFI_MEDIA_CHNAGED The MediaId does not matched the current
1379 @retval EFI_DEVICE_ERROR The device reported an error while performing
1381 @retval EFI_BAD_BUFFER_SIZE The Buffer was not a multiple of the block size
1383 @retval EFI_INVALID_PARAMETER The write request contains LBAs that are not
1384 valid, or the buffer is not on proper
1386 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a
1392 NvmeBlockIoWriteBlocksEx (
1393 IN EFI_BLOCK_IO2_PROTOCOL
*This
,
1396 IN OUT EFI_BLOCK_IO2_TOKEN
*Token
,
1397 IN UINTN BufferSize
,
1401 NVME_DEVICE_PRIVATE_DATA
*Device
;
1403 EFI_BLOCK_IO_MEDIA
*Media
;
1405 UINTN NumberOfBlocks
;
1410 // Check parameters.
1413 return EFI_INVALID_PARAMETER
;
1416 Media
= This
->Media
;
1418 if (MediaId
!= Media
->MediaId
) {
1419 return EFI_MEDIA_CHANGED
;
1422 if (Buffer
== NULL
) {
1423 return EFI_INVALID_PARAMETER
;
1426 if (BufferSize
== 0) {
1427 if ((Token
!= NULL
) && (Token
->Event
!= NULL
)) {
1428 Token
->TransactionStatus
= EFI_SUCCESS
;
1429 gBS
->SignalEvent (Token
->Event
);
1434 BlockSize
= Media
->BlockSize
;
1435 if ((BufferSize
% BlockSize
) != 0) {
1436 return EFI_BAD_BUFFER_SIZE
;
1439 NumberOfBlocks
= BufferSize
/ BlockSize
;
1440 if ((Lba
+ NumberOfBlocks
- 1) > Media
->LastBlock
) {
1441 return EFI_INVALID_PARAMETER
;
1444 IoAlign
= Media
->IoAlign
;
1445 if (IoAlign
> 0 && (((UINTN
) Buffer
& (IoAlign
- 1)) != 0)) {
1446 return EFI_INVALID_PARAMETER
;
1449 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
1451 Device
= NVME_DEVICE_PRIVATE_DATA_FROM_BLOCK_IO2 (This
);
1453 if ((Token
!= NULL
) && (Token
->Event
!= NULL
)) {
1454 Token
->TransactionStatus
= EFI_SUCCESS
;
1455 Status
= NvmeAsyncWrite (Device
, Buffer
, Lba
, NumberOfBlocks
, Token
);
1457 Status
= NvmeWrite (Device
, Buffer
, Lba
, NumberOfBlocks
);
1460 gBS
->RestoreTPL (OldTpl
);
1465 Flush the Block Device.
1467 If EFI_DEVICE_ERROR, EFI_NO_MEDIA,_EFI_WRITE_PROTECTED or EFI_MEDIA_CHANGED
1468 is returned and non-blocking I/O is being used, the Event associated with
1469 this request will not be signaled.
1471 @param[in] This Indicates a pointer to the calling context.
1472 @param[in,out] Token A pointer to the token associated with the
1475 @retval EFI_SUCCESS The flush request was queued if Event is not
1477 All outstanding data was written correctly to
1478 the device if the Event is NULL.
1479 @retval EFI_DEVICE_ERROR The device reported an error while writting back
1481 @retval EFI_WRITE_PROTECTED The device cannot be written to.
1482 @retval EFI_NO_MEDIA There is no media in the device.
1483 @retval EFI_MEDIA_CHANGED The MediaId is not for the current media.
1484 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack
1490 NvmeBlockIoFlushBlocksEx (
1491 IN EFI_BLOCK_IO2_PROTOCOL
*This
,
1492 IN OUT EFI_BLOCK_IO2_TOKEN
*Token
1495 NVME_DEVICE_PRIVATE_DATA
*Device
;
1500 // Check parameters.
1503 return EFI_INVALID_PARAMETER
;
1506 Device
= NVME_DEVICE_PRIVATE_DATA_FROM_BLOCK_IO2 (This
);
1509 // Wait for the asynchronous I/O queue to become empty.
1512 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
1513 IsEmpty
= IsListEmpty (&Device
->AsyncQueue
);
1514 gBS
->RestoreTPL (OldTpl
);
1524 // Signal caller event
1526 if ((Token
!= NULL
) && (Token
->Event
!= NULL
)) {
1527 Token
->TransactionStatus
= EFI_SUCCESS
;
1528 gBS
->SignalEvent (Token
->Event
);
1535 Trust transfer data from/to NVMe device.
1537 This function performs one NVMe transaction to do a trust transfer from/to NVMe device.
1539 @param Private The pointer to the NVME_CONTROLLER_PRIVATE_DATA data structure.
1540 @param Buffer The pointer to the current transaction buffer.
1541 @param SecurityProtocolId The value of the "Security Protocol" parameter of
1542 the security protocol command to be sent.
1543 @param SecurityProtocolSpecificData The value of the "Security Protocol Specific" parameter
1544 of the security protocol command to be sent.
1545 @param TransferLength The block number or sector count of the transfer.
1546 @param IsTrustSend Indicates whether it is a trust send operation or not.
1547 @param Timeout The timeout, in 100ns units, to use for the execution
1548 of the security protocol command. A Timeout value of 0
1549 means that this function will wait indefinitely for the
1550 security protocol command to execute. If Timeout is greater
1551 than zero, then this function will return EFI_TIMEOUT
1552 if the time required to execute the receive data command
1553 is greater than Timeout.
1554 @param TransferLengthOut A pointer to a buffer to store the size in bytes of the data
1555 written to the buffer. Ignore it when IsTrustSend is TRUE.
1557 @retval EFI_SUCCESS The data transfer is complete successfully.
1558 @return others Some error occurs when transferring data.
1562 TrustTransferNvmeDevice (
1563 IN OUT NVME_CONTROLLER_PRIVATE_DATA
*Private
,
1564 IN OUT VOID
*Buffer
,
1565 IN UINT8 SecurityProtocolId
,
1566 IN UINT16 SecurityProtocolSpecificData
,
1567 IN UINTN TransferLength
,
1568 IN BOOLEAN IsTrustSend
,
1570 OUT UINTN
*TransferLengthOut
1573 EFI_NVM_EXPRESS_PASS_THRU_COMMAND_PACKET CommandPacket
;
1574 EFI_NVM_EXPRESS_COMMAND Command
;
1575 EFI_NVM_EXPRESS_COMPLETION Completion
;
1577 UINT16 SpecificData
;
1579 ZeroMem (&CommandPacket
, sizeof (EFI_NVM_EXPRESS_PASS_THRU_COMMAND_PACKET
));
1580 ZeroMem (&Command
, sizeof (EFI_NVM_EXPRESS_COMMAND
));
1581 ZeroMem (&Completion
, sizeof (EFI_NVM_EXPRESS_COMPLETION
));
1583 CommandPacket
.NvmeCmd
= &Command
;
1584 CommandPacket
.NvmeCompletion
= &Completion
;
1587 // Change Endianness of SecurityProtocolSpecificData
1589 SpecificData
= (((SecurityProtocolSpecificData
<< 8) & 0xFF00) | (SecurityProtocolSpecificData
>> 8));
1592 Command
.Cdw0
.Opcode
= NVME_ADMIN_SECURITY_SEND_CMD
;
1593 CommandPacket
.TransferBuffer
= Buffer
;
1594 CommandPacket
.TransferLength
= (UINT32
)TransferLength
;
1595 CommandPacket
.NvmeCmd
->Cdw10
= (UINT32
)((SecurityProtocolId
<< 24) | (SpecificData
<< 8));
1596 CommandPacket
.NvmeCmd
->Cdw11
= (UINT32
)TransferLength
;
1598 Command
.Cdw0
.Opcode
= NVME_ADMIN_SECURITY_RECEIVE_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
;
1605 CommandPacket
.NvmeCmd
->Flags
= CDW10_VALID
| CDW11_VALID
;
1606 CommandPacket
.NvmeCmd
->Nsid
= NVME_CONTROLLER_ID
;
1607 CommandPacket
.CommandTimeout
= Timeout
;
1608 CommandPacket
.QueueType
= NVME_ADMIN_QUEUE
;
1610 Status
= Private
->Passthru
.PassThru (
1618 if (EFI_ERROR (Status
)) {
1619 *TransferLengthOut
= 0;
1621 *TransferLengthOut
= (UINTN
) TransferLength
;
1629 Send a security protocol command to a device that receives data and/or the result
1630 of one or more commands sent by SendData.
1632 The ReceiveData function sends a security protocol command to the given MediaId.
1633 The security protocol command sent is defined by SecurityProtocolId and contains
1634 the security protocol specific data SecurityProtocolSpecificData. The function
1635 returns the data from the security protocol command in PayloadBuffer.
1637 For devices supporting the SCSI command set, the security protocol command is sent
1638 using the SECURITY PROTOCOL IN command defined in SPC-4.
1640 For devices supporting the ATA command set, the security protocol command is sent
1641 using one of the TRUSTED RECEIVE commands defined in ATA8-ACS if PayloadBufferSize
1644 If the PayloadBufferSize is zero, the security protocol command is sent using the
1645 Trusted Non-Data command defined in ATA8-ACS.
1647 If PayloadBufferSize is too small to store the available data from the security
1648 protocol command, the function shall copy PayloadBufferSize bytes into the
1649 PayloadBuffer and return EFI_WARN_BUFFER_TOO_SMALL.
1651 If PayloadBuffer or PayloadTransferSize is NULL and PayloadBufferSize is non-zero,
1652 the function shall return EFI_INVALID_PARAMETER.
1654 If the given MediaId does not support security protocol commands, the function shall
1655 return EFI_UNSUPPORTED. If there is no media in the device, the function returns
1656 EFI_NO_MEDIA. If the MediaId is not the ID for the current media in the device,
1657 the function returns EFI_MEDIA_CHANGED.
1659 If the security protocol fails to complete within the Timeout period, the function
1660 shall return EFI_TIMEOUT.
1662 If the security protocol command completes without an error, the function shall
1663 return EFI_SUCCESS. If the security protocol command completes with an error, the
1664 function shall return EFI_DEVICE_ERROR.
1666 @param This Indicates a pointer to the calling context.
1667 @param MediaId ID of the medium to receive data from.
1668 @param Timeout The timeout, in 100ns units, to use for the execution
1669 of the security protocol command. A Timeout value of 0
1670 means that this function will wait indefinitely for the
1671 security protocol command to execute. If Timeout is greater
1672 than zero, then this function will return EFI_TIMEOUT
1673 if the time required to execute the receive data command
1674 is greater than Timeout.
1675 @param SecurityProtocolId The value of the "Security Protocol" parameter of
1676 the security protocol command to be sent.
1677 @param SecurityProtocolSpecificData The value of the "Security Protocol Specific" parameter
1678 of the security protocol command to be sent.
1679 @param PayloadBufferSize Size in bytes of the payload data buffer.
1680 @param PayloadBuffer A pointer to a destination buffer to store the security
1681 protocol command specific payload data for the security
1682 protocol command. The caller is responsible for having
1683 either implicit or explicit ownership of the buffer.
1684 @param PayloadTransferSize A pointer to a buffer to store the size in bytes of the
1685 data written to the payload data buffer.
1687 @retval EFI_SUCCESS The security protocol command completed successfully.
1688 @retval EFI_WARN_BUFFER_TOO_SMALL The PayloadBufferSize was too small to store the available
1689 data from the device. The PayloadBuffer contains the truncated data.
1690 @retval EFI_UNSUPPORTED The given MediaId does not support security protocol commands.
1691 @retval EFI_DEVICE_ERROR The security protocol command completed with an error.
1692 @retval EFI_NO_MEDIA There is no media in the device.
1693 @retval EFI_MEDIA_CHANGED The MediaId is not for the current media.
1694 @retval EFI_INVALID_PARAMETER The PayloadBuffer or PayloadTransferSize is NULL and
1695 PayloadBufferSize is non-zero.
1696 @retval EFI_TIMEOUT A timeout occurred while waiting for the security
1697 protocol command to execute.
1702 NvmeStorageSecurityReceiveData (
1703 IN EFI_STORAGE_SECURITY_COMMAND_PROTOCOL
*This
,
1706 IN UINT8 SecurityProtocolId
,
1707 IN UINT16 SecurityProtocolSpecificData
,
1708 IN UINTN PayloadBufferSize
,
1709 OUT VOID
*PayloadBuffer
,
1710 OUT UINTN
*PayloadTransferSize
1714 NVME_DEVICE_PRIVATE_DATA
*Device
;
1716 Status
= EFI_SUCCESS
;
1718 if ((PayloadBuffer
== NULL
) || (PayloadTransferSize
== NULL
) || (PayloadBufferSize
== 0)) {
1719 return EFI_INVALID_PARAMETER
;
1722 Device
= NVME_DEVICE_PRIVATE_DATA_FROM_STORAGE_SECURITY (This
);
1724 if (MediaId
!= Device
->BlockIo
.Media
->MediaId
) {
1725 return EFI_MEDIA_CHANGED
;
1728 if (!Device
->BlockIo
.Media
->MediaPresent
) {
1729 return EFI_NO_MEDIA
;
1732 Status
= TrustTransferNvmeDevice (
1736 SecurityProtocolSpecificData
,
1747 Send a security protocol command to a device.
1749 The SendData function sends a security protocol command containing the payload
1750 PayloadBuffer to the given MediaId. The security protocol command sent is
1751 defined by SecurityProtocolId and contains the security protocol specific data
1752 SecurityProtocolSpecificData. If the underlying protocol command requires a
1753 specific padding for the command payload, the SendData function shall add padding
1754 bytes to the command payload to satisfy the padding requirements.
1756 For devices supporting the SCSI command set, the security protocol command is sent
1757 using the SECURITY PROTOCOL OUT command defined in SPC-4.
1759 For devices supporting the ATA command set, the security protocol command is sent
1760 using one of the TRUSTED SEND commands defined in ATA8-ACS if PayloadBufferSize
1761 is non-zero. If the PayloadBufferSize is zero, the security protocol command is
1762 sent using the Trusted Non-Data command defined in ATA8-ACS.
1764 If PayloadBuffer is NULL and PayloadBufferSize is non-zero, the function shall
1765 return EFI_INVALID_PARAMETER.
1767 If the given MediaId does not support security protocol commands, the function
1768 shall return EFI_UNSUPPORTED. If there is no media in the device, the function
1769 returns EFI_NO_MEDIA. If the MediaId is not the ID for the current media in the
1770 device, the function returns EFI_MEDIA_CHANGED.
1772 If the security protocol fails to complete within the Timeout period, the function
1773 shall return EFI_TIMEOUT.
1775 If the security protocol command completes without an error, the function shall return
1776 EFI_SUCCESS. If the security protocol command completes with an error, the function
1777 shall return EFI_DEVICE_ERROR.
1779 @param This Indicates a pointer to the calling context.
1780 @param MediaId ID of the medium to receive data from.
1781 @param Timeout The timeout, in 100ns units, to use for the execution
1782 of the security protocol command. A Timeout value of 0
1783 means that this function will wait indefinitely for the
1784 security protocol command to execute. If Timeout is greater
1785 than zero, then this function will return EFI_TIMEOUT
1786 if the time required to execute the send data command
1787 is greater than Timeout.
1788 @param SecurityProtocolId The value of the "Security Protocol" parameter of
1789 the security protocol command to be sent.
1790 @param SecurityProtocolSpecificData The value of the "Security Protocol Specific" parameter
1791 of the security protocol command to be sent.
1792 @param PayloadBufferSize Size in bytes of the payload data buffer.
1793 @param PayloadBuffer A pointer to a destination buffer to store the security
1794 protocol command specific payload data for the security
1797 @retval EFI_SUCCESS The security protocol command completed successfully.
1798 @retval EFI_UNSUPPORTED The given MediaId does not support security protocol commands.
1799 @retval EFI_DEVICE_ERROR The security protocol command completed with an error.
1800 @retval EFI_NO_MEDIA There is no media in the device.
1801 @retval EFI_MEDIA_CHANGED The MediaId is not for the current media.
1802 @retval EFI_INVALID_PARAMETER The PayloadBuffer is NULL and PayloadBufferSize is non-zero.
1803 @retval EFI_TIMEOUT A timeout occurred while waiting for the security
1804 protocol command to execute.
1809 NvmeStorageSecuritySendData (
1810 IN EFI_STORAGE_SECURITY_COMMAND_PROTOCOL
*This
,
1813 IN UINT8 SecurityProtocolId
,
1814 IN UINT16 SecurityProtocolSpecificData
,
1815 IN UINTN PayloadBufferSize
,
1816 IN VOID
*PayloadBuffer
1820 NVME_DEVICE_PRIVATE_DATA
*Device
;
1822 Status
= EFI_SUCCESS
;
1824 if ((PayloadBuffer
== NULL
) && (PayloadBufferSize
!= 0)) {
1825 return EFI_INVALID_PARAMETER
;
1828 Device
= NVME_DEVICE_PRIVATE_DATA_FROM_STORAGE_SECURITY (This
);
1830 if (MediaId
!= Device
->BlockIo
.Media
->MediaId
) {
1831 return EFI_MEDIA_CHANGED
;
1834 if (!Device
->BlockIo
.Media
->MediaPresent
) {
1835 return EFI_NO_MEDIA
;
1838 Status
= TrustTransferNvmeDevice (
1842 SecurityProtocolSpecificData
,