1 /** @file
2   NvmExpressDxe driver is used to manage non-volatile memory subsystem which follows
3   NVM Express specification.
4 
5   Copyright (c) 2013 - 2018, Intel Corporation. All rights reserved.<BR>
6   SPDX-License-Identifier: BSD-2-Clause-Patent
7 
8 **/
9 
10 #include "NvmExpress.h"
11 
12 /**
13   Read some sectors from the device.
14 
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.
19 
20   @retval EFI_SUCCESS            Datum are read from the device.
21   @retval Others                 Fail to read all the datum.
22 
23 **/
24 EFI_STATUS
ReadSectors(IN NVME_DEVICE_PRIVATE_DATA * Device,IN UINT64 Buffer,IN UINT64 Lba,IN UINT32 Blocks)25 ReadSectors (
26   IN NVME_DEVICE_PRIVATE_DATA           *Device,
27   IN UINT64                             Buffer,
28   IN UINT64                             Lba,
29   IN UINT32                             Blocks
30   )
31 {
32   NVME_CONTROLLER_PRIVATE_DATA             *Private;
33   UINT32                                   Bytes;
34   EFI_NVM_EXPRESS_PASS_THRU_COMMAND_PACKET CommandPacket;
35   EFI_NVM_EXPRESS_COMMAND                  Command;
36   EFI_NVM_EXPRESS_COMPLETION               Completion;
37   EFI_STATUS                               Status;
38   UINT32                                   BlockSize;
39 
40   Private    = Device->Controller;
41   BlockSize  = Device->Media.BlockSize;
42   Bytes      = Blocks * BlockSize;
43 
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));
47 
48   CommandPacket.NvmeCmd        = &Command;
49   CommandPacket.NvmeCompletion = &Completion;
50 
51   CommandPacket.NvmeCmd->Cdw0.Opcode = NVME_IO_READ_OPC;
52   CommandPacket.NvmeCmd->Nsid        = Device->NamespaceId;
53   CommandPacket.TransferBuffer       = (VOID *)(UINTN)Buffer;
54 
55   CommandPacket.TransferLength = Bytes;
56   CommandPacket.CommandTimeout = NVME_GENERIC_TIMEOUT;
57   CommandPacket.QueueType      = NVME_IO_QUEUE;
58 
59   CommandPacket.NvmeCmd->Cdw10 = (UINT32)Lba;
60   CommandPacket.NvmeCmd->Cdw11 = (UINT32)RShiftU64(Lba, 32);
61   CommandPacket.NvmeCmd->Cdw12 = (Blocks - 1) & 0xFFFF;
62 
63   CommandPacket.NvmeCmd->Flags = CDW10_VALID | CDW11_VALID | CDW12_VALID;
64 
65   Status = Private->Passthru.PassThru (
66                                &Private->Passthru,
67                                Device->NamespaceId,
68                                &CommandPacket,
69                                NULL
70                                );
71 
72   return Status;
73 }
74 
75 /**
76   Write some sectors to the device.
77 
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.
82 
83   @retval EFI_SUCCESS            Datum are written into the buffer.
84   @retval Others                 Fail to write all the datum.
85 
86 **/
87 EFI_STATUS
WriteSectors(IN NVME_DEVICE_PRIVATE_DATA * Device,IN UINT64 Buffer,IN UINT64 Lba,IN UINT32 Blocks)88 WriteSectors (
89   IN NVME_DEVICE_PRIVATE_DATA      *Device,
90   IN UINT64                        Buffer,
91   IN UINT64                        Lba,
92   IN UINT32                        Blocks
93   )
94 {
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;
99   EFI_STATUS                               Status;
100   UINT32                                   Bytes;
101   UINT32                                   BlockSize;
102 
103   Private    = Device->Controller;
104   BlockSize  = Device->Media.BlockSize;
105   Bytes      = Blocks * BlockSize;
106 
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));
110 
111   CommandPacket.NvmeCmd        = &Command;
112   CommandPacket.NvmeCompletion = &Completion;
113 
114   CommandPacket.NvmeCmd->Cdw0.Opcode = NVME_IO_WRITE_OPC;
115   CommandPacket.NvmeCmd->Nsid  = Device->NamespaceId;
116   CommandPacket.TransferBuffer = (VOID *)(UINTN)Buffer;
117 
118   CommandPacket.TransferLength = Bytes;
119   CommandPacket.CommandTimeout = NVME_GENERIC_TIMEOUT;
120   CommandPacket.QueueType      = NVME_IO_QUEUE;
121 
122   CommandPacket.NvmeCmd->Cdw10 = (UINT32)Lba;
123   CommandPacket.NvmeCmd->Cdw11 = (UINT32)RShiftU64(Lba, 32);
124   //
125   // Set Force Unit Access bit (bit 30) to use write-through behaviour
126   //
127   CommandPacket.NvmeCmd->Cdw12 = ((Blocks - 1) & 0xFFFF) | BIT30;
128 
129   CommandPacket.MetadataBuffer = NULL;
130   CommandPacket.MetadataLength = 0;
131 
132   CommandPacket.NvmeCmd->Flags = CDW10_VALID | CDW11_VALID | CDW12_VALID;
133 
134   Status = Private->Passthru.PassThru (
135                                &Private->Passthru,
136                                Device->NamespaceId,
137                                &CommandPacket,
138                                NULL
139                                );
140 
141   return Status;
142 }
143 
144 /**
145   Read some blocks from the device.
146 
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.
151 
152   @retval EFI_SUCCESS            Datum are read from the device.
153   @retval Others                 Fail to read all the datum.
154 
155 **/
156 EFI_STATUS
NvmeRead(IN NVME_DEVICE_PRIVATE_DATA * Device,OUT VOID * Buffer,IN UINT64 Lba,IN UINTN Blocks)157 NvmeRead (
158   IN     NVME_DEVICE_PRIVATE_DATA       *Device,
159      OUT VOID                           *Buffer,
160   IN     UINT64                         Lba,
161   IN     UINTN                          Blocks
162   )
163 {
164   EFI_STATUS                       Status;
165   UINT32                           BlockSize;
166   NVME_CONTROLLER_PRIVATE_DATA     *Private;
167   UINT32                           MaxTransferBlocks;
168   UINTN                            OrginalBlocks;
169   BOOLEAN                          IsEmpty;
170   EFI_TPL                          OldTpl;
171 
172   //
173   // Wait for the device's asynchronous I/O queue to become empty.
174   //
175   while (TRUE) {
176     OldTpl  = gBS->RaiseTPL (TPL_NOTIFY);
177     IsEmpty = IsListEmpty (&Device->AsyncQueue);
178     gBS->RestoreTPL (OldTpl);
179 
180     if (IsEmpty) {
181       break;
182     }
183 
184     gBS->Stall (100);
185   }
186 
187   Status        = EFI_SUCCESS;
188   Private       = Device->Controller;
189   BlockSize     = Device->Media.BlockSize;
190   OrginalBlocks = Blocks;
191 
192   if (Private->ControllerData->Mdts != 0) {
193     MaxTransferBlocks = (1 << (Private->ControllerData->Mdts)) * (1 << (Private->Cap.Mpsmin + 12)) / BlockSize;
194   } else {
195     MaxTransferBlocks = 1024;
196   }
197 
198   while (Blocks > 0) {
199     if (Blocks > MaxTransferBlocks) {
200       Status = ReadSectors (Device, (UINT64)(UINTN)Buffer, Lba, MaxTransferBlocks);
201 
202       Blocks -= MaxTransferBlocks;
203       Buffer  = (VOID *)(UINTN)((UINT64)(UINTN)Buffer + MaxTransferBlocks * BlockSize);
204       Lba    += MaxTransferBlocks;
205     } else {
206       Status = ReadSectors (Device, (UINT64)(UINTN)Buffer, Lba, (UINT32)Blocks);
207       Blocks = 0;
208     }
209 
210     if (EFI_ERROR(Status)) {
211       break;
212     }
213   }
214 
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));
218 
219   return Status;
220 }
221 
222 /**
223   Write some blocks to the device.
224 
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.
229 
230   @retval EFI_SUCCESS            Datum are written into the buffer.
231   @retval Others                 Fail to write all the datum.
232 
233 **/
234 EFI_STATUS
NvmeWrite(IN NVME_DEVICE_PRIVATE_DATA * Device,IN VOID * Buffer,IN UINT64 Lba,IN UINTN Blocks)235 NvmeWrite (
236   IN NVME_DEVICE_PRIVATE_DATA           *Device,
237   IN VOID                               *Buffer,
238   IN UINT64                             Lba,
239   IN UINTN                              Blocks
240   )
241 {
242   EFI_STATUS                       Status;
243   UINT32                           BlockSize;
244   NVME_CONTROLLER_PRIVATE_DATA     *Private;
245   UINT32                           MaxTransferBlocks;
246   UINTN                            OrginalBlocks;
247   BOOLEAN                          IsEmpty;
248   EFI_TPL                          OldTpl;
249 
250   //
251   // Wait for the device's asynchronous I/O queue to become empty.
252   //
253   while (TRUE) {
254     OldTpl  = gBS->RaiseTPL (TPL_NOTIFY);
255     IsEmpty = IsListEmpty (&Device->AsyncQueue);
256     gBS->RestoreTPL (OldTpl);
257 
258     if (IsEmpty) {
259       break;
260     }
261 
262     gBS->Stall (100);
263   }
264 
265   Status        = EFI_SUCCESS;
266   Private       = Device->Controller;
267   BlockSize     = Device->Media.BlockSize;
268   OrginalBlocks = Blocks;
269 
270   if (Private->ControllerData->Mdts != 0) {
271     MaxTransferBlocks = (1 << (Private->ControllerData->Mdts)) * (1 << (Private->Cap.Mpsmin + 12)) / BlockSize;
272   } else {
273     MaxTransferBlocks = 1024;
274   }
275 
276   while (Blocks > 0) {
277     if (Blocks > MaxTransferBlocks) {
278       Status = WriteSectors (Device, (UINT64)(UINTN)Buffer, Lba, MaxTransferBlocks);
279 
280       Blocks -= MaxTransferBlocks;
281       Buffer  = (VOID *)(UINTN)((UINT64)(UINTN)Buffer + MaxTransferBlocks * BlockSize);
282       Lba    += MaxTransferBlocks;
283     } else {
284       Status = WriteSectors (Device, (UINT64)(UINTN)Buffer, Lba, (UINT32)Blocks);
285       Blocks = 0;
286     }
287 
288     if (EFI_ERROR(Status)) {
289       break;
290     }
291   }
292 
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));
296 
297   return Status;
298 }
299 
300 /**
301   Flushes all modified data to the device.
302 
303   @param  Device                 The pointer to the NVME_DEVICE_PRIVATE_DATA data structure.
304 
305   @retval EFI_SUCCESS            Datum are written into the buffer.
306   @retval Others                 Fail to write all the datum.
307 
308 **/
309 EFI_STATUS
NvmeFlush(IN NVME_DEVICE_PRIVATE_DATA * Device)310 NvmeFlush (
311   IN NVME_DEVICE_PRIVATE_DATA      *Device
312   )
313 {
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;
318   EFI_STATUS                               Status;
319 
320   Private = Device->Controller;
321 
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));
325 
326   CommandPacket.NvmeCmd        = &Command;
327   CommandPacket.NvmeCompletion = &Completion;
328 
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;
333 
334   Status = Private->Passthru.PassThru (
335                                &Private->Passthru,
336                                Device->NamespaceId,
337                                &CommandPacket,
338                                NULL
339                                );
340 
341   return Status;
342 }
343 
344 /**
345   Nonblocking I/O callback funtion when the event is signaled.
346 
347   @param[in]  Event     The Event this notify function registered to.
348   @param[in]  Context   Pointer to the context data registered to the
349                         Event.
350 
351 **/
352 VOID
353 EFIAPI
AsyncIoCallback(IN EFI_EVENT Event,IN VOID * Context)354 AsyncIoCallback (
355   IN EFI_EVENT                Event,
356   IN VOID                     *Context
357   )
358 {
359   NVME_BLKIO2_SUBTASK         *Subtask;
360   NVME_BLKIO2_REQUEST         *Request;
361   NVME_CQ                     *Completion;
362   EFI_BLOCK_IO2_TOKEN         *Token;
363 
364   gBS->CloseEvent (Event);
365 
366   Subtask    = (NVME_BLKIO2_SUBTASK *) Context;
367   Completion = (NVME_CQ *) Subtask->CommandPacket->NvmeCompletion;
368   Request    = Subtask->BlockIo2Request;
369   Token      = Request->Token;
370 
371   if (Token->TransactionStatus == EFI_SUCCESS) {
372     //
373     // If previous subtask already fails, do not check the result of
374     // subsequent subtasks.
375     //
376     if ((Completion->Sct != 0) || (Completion->Sc != 0)) {
377       Token->TransactionStatus = EFI_DEVICE_ERROR;
378 
379       //
380       // Dump completion entry status for debugging.
381       //
382       DEBUG_CODE_BEGIN();
383         NvmeDumpStatus (Completion);
384       DEBUG_CODE_END();
385     }
386   }
387 
388   //
389   // Remove the subtask from the BlockIo2 subtasks list.
390   //
391   RemoveEntryList (&Subtask->Link);
392 
393   if (IsListEmpty (&Request->SubtasksQueue) && Request->LastSubtaskSubmitted) {
394     //
395     // Remove the BlockIo2 request from the device asynchronous queue.
396     //
397     RemoveEntryList (&Request->Link);
398     FreePool (Request);
399     gBS->SignalEvent (Token->Event);
400   }
401 
402   FreePool (Subtask->CommandPacket->NvmeCmd);
403   FreePool (Subtask->CommandPacket->NvmeCompletion);
404   FreePool (Subtask->CommandPacket);
405   FreePool (Subtask);
406 }
407 
408 /**
409   Read some sectors from the device in an asynchronous manner.
410 
411   @param  Device        The pointer to the NVME_DEVICE_PRIVATE_DATA data
412                         structure.
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.
418 
419   @retval EFI_SUCCESS   Asynchronous read request has been queued.
420   @retval Others        Fail to send the asynchronous request.
421 
422 **/
423 EFI_STATUS
AsyncReadSectors(IN NVME_DEVICE_PRIVATE_DATA * Device,IN NVME_BLKIO2_REQUEST * Request,IN UINT64 Buffer,IN UINT64 Lba,IN UINT32 Blocks,IN BOOLEAN IsLast)424 AsyncReadSectors (
425   IN NVME_DEVICE_PRIVATE_DATA           *Device,
426   IN NVME_BLKIO2_REQUEST                *Request,
427   IN UINT64                             Buffer,
428   IN UINT64                             Lba,
429   IN UINT32                             Blocks,
430   IN BOOLEAN                            IsLast
431   )
432 {
433   NVME_CONTROLLER_PRIVATE_DATA             *Private;
434   UINT32                                   Bytes;
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;
439   EFI_STATUS                               Status;
440   UINT32                                   BlockSize;
441   EFI_TPL                                  OldTpl;
442 
443   Private       = Device->Controller;
444   BlockSize     = Device->Media.BlockSize;
445   Bytes         = Blocks * BlockSize;
446   CommandPacket = NULL;
447   Command       = NULL;
448   Completion    = NULL;
449 
450   Subtask = AllocateZeroPool (sizeof (NVME_BLKIO2_SUBTASK));
451   if (Subtask == NULL) {
452     Status = EFI_OUT_OF_RESOURCES;
453     goto ErrorExit;
454   }
455 
456   Subtask->Signature       = NVME_BLKIO2_SUBTASK_SIGNATURE;
457   Subtask->IsLast          = IsLast;
458   Subtask->NamespaceId     = Device->NamespaceId;
459   Subtask->BlockIo2Request = Request;
460 
461   CommandPacket = AllocateZeroPool (sizeof (EFI_NVM_EXPRESS_PASS_THRU_COMMAND_PACKET));
462   if (CommandPacket == NULL) {
463     Status = EFI_OUT_OF_RESOURCES;
464     goto ErrorExit;
465   } else {
466     Subtask->CommandPacket = CommandPacket;
467   }
468 
469   Command = AllocateZeroPool (sizeof (EFI_NVM_EXPRESS_COMMAND));
470   if (Command == NULL) {
471     Status = EFI_OUT_OF_RESOURCES;
472     goto ErrorExit;
473   }
474 
475   Completion = AllocateZeroPool (sizeof (EFI_NVM_EXPRESS_COMPLETION));
476   if (Completion == NULL) {
477     Status = EFI_OUT_OF_RESOURCES;
478     goto ErrorExit;
479   }
480 
481   //
482   // Create Event
483   //
484   Status = gBS->CreateEvent (
485                   EVT_NOTIFY_SIGNAL,
486                   TPL_NOTIFY,
487                   AsyncIoCallback,
488                   Subtask,
489                   &Subtask->Event
490                   );
491   if (EFI_ERROR(Status)) {
492     goto ErrorExit;
493   }
494 
495   CommandPacket->NvmeCmd        = Command;
496   CommandPacket->NvmeCompletion = Completion;
497 
498   CommandPacket->NvmeCmd->Cdw0.Opcode = NVME_IO_READ_OPC;
499   CommandPacket->NvmeCmd->Nsid        = Device->NamespaceId;
500   CommandPacket->TransferBuffer       = (VOID *)(UINTN)Buffer;
501 
502   CommandPacket->TransferLength = Bytes;
503   CommandPacket->CommandTimeout = NVME_GENERIC_TIMEOUT;
504   CommandPacket->QueueType      = NVME_IO_QUEUE;
505 
506   CommandPacket->NvmeCmd->Cdw10 = (UINT32)Lba;
507   CommandPacket->NvmeCmd->Cdw11 = (UINT32)RShiftU64(Lba, 32);
508   CommandPacket->NvmeCmd->Cdw12 = (Blocks - 1) & 0xFFFF;
509 
510   CommandPacket->NvmeCmd->Flags = CDW10_VALID | CDW11_VALID | CDW12_VALID;
511 
512   OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
513   InsertTailList (&Private->UnsubmittedSubtasks, &Subtask->Link);
514   Request->UnsubmittedSubtaskNum++;
515   gBS->RestoreTPL (OldTpl);
516 
517   return EFI_SUCCESS;
518 
519 ErrorExit:
520   //
521   // Resource cleanup if asynchronous read request has not been queued.
522   //
523   if (Completion != NULL) {
524     FreePool (Completion);
525   }
526 
527   if (Command != NULL) {
528     FreePool (Command);
529   }
530 
531   if (CommandPacket != NULL) {
532     FreePool (CommandPacket);
533   }
534 
535   if (Subtask != NULL) {
536     if (Subtask->Event != NULL) {
537       gBS->CloseEvent (Subtask->Event);
538     }
539 
540     FreePool (Subtask);
541   }
542 
543   return Status;
544 }
545 
546 /**
547   Write some sectors from the device in an asynchronous manner.
548 
549   @param  Device        The pointer to the NVME_DEVICE_PRIVATE_DATA data
550                         structure.
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
553                         device.
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.
557 
558   @retval EFI_SUCCESS   Asynchronous write request has been queued.
559   @retval Others        Fail to send the asynchronous request.
560 
561 **/
562 EFI_STATUS
AsyncWriteSectors(IN NVME_DEVICE_PRIVATE_DATA * Device,IN NVME_BLKIO2_REQUEST * Request,IN UINT64 Buffer,IN UINT64 Lba,IN UINT32 Blocks,IN BOOLEAN IsLast)563 AsyncWriteSectors (
564   IN NVME_DEVICE_PRIVATE_DATA           *Device,
565   IN NVME_BLKIO2_REQUEST                *Request,
566   IN UINT64                             Buffer,
567   IN UINT64                             Lba,
568   IN UINT32                             Blocks,
569   IN BOOLEAN                            IsLast
570   )
571 {
572   NVME_CONTROLLER_PRIVATE_DATA             *Private;
573   UINT32                                   Bytes;
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;
578   EFI_STATUS                               Status;
579   UINT32                                   BlockSize;
580   EFI_TPL                                  OldTpl;
581 
582   Private       = Device->Controller;
583   BlockSize     = Device->Media.BlockSize;
584   Bytes         = Blocks * BlockSize;
585   CommandPacket = NULL;
586   Command       = NULL;
587   Completion    = NULL;
588 
589   Subtask = AllocateZeroPool (sizeof (NVME_BLKIO2_SUBTASK));
590   if (Subtask == NULL) {
591     Status = EFI_OUT_OF_RESOURCES;
592     goto ErrorExit;
593   }
594 
595   Subtask->Signature       = NVME_BLKIO2_SUBTASK_SIGNATURE;
596   Subtask->IsLast          = IsLast;
597   Subtask->NamespaceId     = Device->NamespaceId;
598   Subtask->BlockIo2Request = Request;
599 
600   CommandPacket = AllocateZeroPool (sizeof (EFI_NVM_EXPRESS_PASS_THRU_COMMAND_PACKET));
601   if (CommandPacket == NULL) {
602     Status = EFI_OUT_OF_RESOURCES;
603     goto ErrorExit;
604   } else {
605     Subtask->CommandPacket = CommandPacket;
606   }
607 
608   Command = AllocateZeroPool (sizeof (EFI_NVM_EXPRESS_COMMAND));
609   if (Command == NULL) {
610     Status = EFI_OUT_OF_RESOURCES;
611     goto ErrorExit;
612   }
613 
614   Completion = AllocateZeroPool (sizeof (EFI_NVM_EXPRESS_COMPLETION));
615   if (Completion == NULL) {
616     Status = EFI_OUT_OF_RESOURCES;
617     goto ErrorExit;
618   }
619 
620   //
621   // Create Event
622   //
623   Status = gBS->CreateEvent (
624                   EVT_NOTIFY_SIGNAL,
625                   TPL_NOTIFY,
626                   AsyncIoCallback,
627                   Subtask,
628                   &Subtask->Event
629                   );
630   if (EFI_ERROR(Status)) {
631     goto ErrorExit;
632   }
633 
634   CommandPacket->NvmeCmd        = Command;
635   CommandPacket->NvmeCompletion = Completion;
636 
637   CommandPacket->NvmeCmd->Cdw0.Opcode = NVME_IO_WRITE_OPC;
638   CommandPacket->NvmeCmd->Nsid        = Device->NamespaceId;
639   CommandPacket->TransferBuffer       = (VOID *)(UINTN)Buffer;
640 
641   CommandPacket->TransferLength = Bytes;
642   CommandPacket->CommandTimeout = NVME_GENERIC_TIMEOUT;
643   CommandPacket->QueueType      = NVME_IO_QUEUE;
644 
645   CommandPacket->NvmeCmd->Cdw10 = (UINT32)Lba;
646   CommandPacket->NvmeCmd->Cdw11 = (UINT32)RShiftU64(Lba, 32);
647   //
648   // Set Force Unit Access bit (bit 30) to use write-through behaviour
649   //
650   CommandPacket->NvmeCmd->Cdw12 = ((Blocks - 1) & 0xFFFF) | BIT30;
651 
652   CommandPacket->NvmeCmd->Flags = CDW10_VALID | CDW11_VALID | CDW12_VALID;
653 
654   OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
655   InsertTailList (&Private->UnsubmittedSubtasks, &Subtask->Link);
656   Request->UnsubmittedSubtaskNum++;
657   gBS->RestoreTPL (OldTpl);
658 
659   return EFI_SUCCESS;
660 
661 ErrorExit:
662   //
663   // Resource cleanup if asynchronous read request has not been queued.
664   //
665   if (Completion != NULL) {
666     FreePool (Completion);
667   }
668 
669   if (Command != NULL) {
670     FreePool (Command);
671   }
672 
673   if (CommandPacket != NULL) {
674     FreePool (CommandPacket);
675   }
676 
677   if (Subtask != NULL) {
678     if (Subtask->Event != NULL) {
679       gBS->CloseEvent (Subtask->Event);
680     }
681 
682     FreePool (Subtask);
683   }
684 
685   return Status;
686 }
687 
688 /**
689   Read some blocks from the device in an asynchronous manner.
690 
691   @param  Device        The pointer to the NVME_DEVICE_PRIVATE_DATA data
692                         structure.
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.
697 
698   @retval EFI_SUCCESS   Data are read from the device.
699   @retval Others        Fail to read all the data.
700 
701 **/
702 EFI_STATUS
NvmeAsyncRead(IN NVME_DEVICE_PRIVATE_DATA * Device,OUT VOID * Buffer,IN UINT64 Lba,IN UINTN Blocks,IN EFI_BLOCK_IO2_TOKEN * Token)703 NvmeAsyncRead (
704   IN     NVME_DEVICE_PRIVATE_DATA       *Device,
705      OUT VOID                           *Buffer,
706   IN     UINT64                         Lba,
707   IN     UINTN                          Blocks,
708   IN     EFI_BLOCK_IO2_TOKEN            *Token
709   )
710 {
711   EFI_STATUS                       Status;
712   UINT32                           BlockSize;
713   NVME_CONTROLLER_PRIVATE_DATA     *Private;
714   NVME_BLKIO2_REQUEST              *BlkIo2Req;
715   UINT32                           MaxTransferBlocks;
716   UINTN                            OrginalBlocks;
717   BOOLEAN                          IsEmpty;
718   EFI_TPL                          OldTpl;
719 
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;
727   }
728 
729   BlkIo2Req->Signature = NVME_BLKIO2_REQUEST_SIGNATURE;
730   BlkIo2Req->Token     = Token;
731 
732   OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
733   InsertTailList (&Device->AsyncQueue, &BlkIo2Req->Link);
734   gBS->RestoreTPL (OldTpl);
735 
736   InitializeListHead (&BlkIo2Req->SubtasksQueue);
737 
738   if (Private->ControllerData->Mdts != 0) {
739     MaxTransferBlocks = (1 << (Private->ControllerData->Mdts)) * (1 << (Private->Cap.Mpsmin + 12)) / BlockSize;
740   } else {
741     MaxTransferBlocks = 1024;
742   }
743 
744   while (Blocks > 0) {
745     if (Blocks > MaxTransferBlocks) {
746       Status = AsyncReadSectors (
747                  Device,
748                  BlkIo2Req, (UINT64)(UINTN)Buffer,
749                  Lba,
750                  MaxTransferBlocks,
751                  FALSE
752                  );
753 
754       Blocks -= MaxTransferBlocks;
755       Buffer  = (VOID *)(UINTN)((UINT64)(UINTN)Buffer + MaxTransferBlocks * BlockSize);
756       Lba    += MaxTransferBlocks;
757     } else {
758       Status = AsyncReadSectors (
759                  Device,
760                  BlkIo2Req,
761                  (UINT64)(UINTN)Buffer,
762                  Lba,
763                  (UINT32)Blocks,
764                  TRUE
765                  );
766 
767       Blocks = 0;
768     }
769 
770     if (EFI_ERROR(Status)) {
771       OldTpl  = gBS->RaiseTPL (TPL_NOTIFY);
772       IsEmpty = IsListEmpty (&BlkIo2Req->SubtasksQueue) &&
773                 (BlkIo2Req->UnsubmittedSubtaskNum == 0);
774 
775       if (IsEmpty) {
776         //
777         // Remove the BlockIo2 request from the device asynchronous queue.
778         //
779         RemoveEntryList (&BlkIo2Req->Link);
780         FreePool (BlkIo2Req);
781         Status = EFI_DEVICE_ERROR;
782       } else {
783         //
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.
787         //
788         Status = EFI_SUCCESS;
789         Token->TransactionStatus = EFI_DEVICE_ERROR;
790         BlkIo2Req->LastSubtaskSubmitted = TRUE;
791       }
792 
793       gBS->RestoreTPL (OldTpl);
794 
795       break;
796     }
797   }
798 
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));
802 
803   return Status;
804 }
805 
806 /**
807   Write some blocks from the device in an asynchronous manner.
808 
809   @param  Device        The pointer to the NVME_DEVICE_PRIVATE_DATA data
810                         structure.
811   @param  Buffer        The buffer used to store the data written to the
812                         device.
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.
816 
817   @retval EFI_SUCCESS   Data are written to the device.
818   @retval Others        Fail to write all the data.
819 
820 **/
821 EFI_STATUS
NvmeAsyncWrite(IN NVME_DEVICE_PRIVATE_DATA * Device,IN VOID * Buffer,IN UINT64 Lba,IN UINTN Blocks,IN EFI_BLOCK_IO2_TOKEN * Token)822 NvmeAsyncWrite (
823   IN NVME_DEVICE_PRIVATE_DATA           *Device,
824   IN VOID                               *Buffer,
825   IN UINT64                             Lba,
826   IN UINTN                              Blocks,
827   IN EFI_BLOCK_IO2_TOKEN                *Token
828   )
829 {
830   EFI_STATUS                       Status;
831   UINT32                           BlockSize;
832   NVME_CONTROLLER_PRIVATE_DATA     *Private;
833   NVME_BLKIO2_REQUEST              *BlkIo2Req;
834   UINT32                           MaxTransferBlocks;
835   UINTN                            OrginalBlocks;
836   BOOLEAN                          IsEmpty;
837   EFI_TPL                          OldTpl;
838 
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;
846   }
847 
848   BlkIo2Req->Signature = NVME_BLKIO2_REQUEST_SIGNATURE;
849   BlkIo2Req->Token     = Token;
850 
851   OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
852   InsertTailList (&Device->AsyncQueue, &BlkIo2Req->Link);
853   gBS->RestoreTPL (OldTpl);
854 
855   InitializeListHead (&BlkIo2Req->SubtasksQueue);
856 
857   if (Private->ControllerData->Mdts != 0) {
858     MaxTransferBlocks = (1 << (Private->ControllerData->Mdts)) * (1 << (Private->Cap.Mpsmin + 12)) / BlockSize;
859   } else {
860     MaxTransferBlocks = 1024;
861   }
862 
863   while (Blocks > 0) {
864     if (Blocks > MaxTransferBlocks) {
865       Status  = AsyncWriteSectors (
866                   Device,
867                   BlkIo2Req,
868                   (UINT64)(UINTN)Buffer,
869                   Lba,
870                   MaxTransferBlocks,
871                   FALSE
872                   );
873 
874       Blocks -= MaxTransferBlocks;
875       Buffer  = (VOID *)(UINTN)((UINT64)(UINTN)Buffer + MaxTransferBlocks * BlockSize);
876       Lba    += MaxTransferBlocks;
877     } else {
878       Status = AsyncWriteSectors (
879                  Device,
880                  BlkIo2Req,
881                  (UINT64)(UINTN)Buffer,
882                  Lba,
883                  (UINT32)Blocks,
884                  TRUE
885                  );
886 
887       Blocks = 0;
888     }
889 
890     if (EFI_ERROR(Status)) {
891       OldTpl  = gBS->RaiseTPL (TPL_NOTIFY);
892       IsEmpty = IsListEmpty (&BlkIo2Req->SubtasksQueue) &&
893                 (BlkIo2Req->UnsubmittedSubtaskNum == 0);
894 
895       if (IsEmpty) {
896         //
897         // Remove the BlockIo2 request from the device asynchronous queue.
898         //
899         RemoveEntryList (&BlkIo2Req->Link);
900         FreePool (BlkIo2Req);
901         Status = EFI_DEVICE_ERROR;
902       } else {
903         //
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.
907         //
908         Status = EFI_SUCCESS;
909         Token->TransactionStatus = EFI_DEVICE_ERROR;
910         BlkIo2Req->LastSubtaskSubmitted = TRUE;
911       }
912 
913       gBS->RestoreTPL (OldTpl);
914 
915       break;
916     }
917   }
918 
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));
922 
923   return Status;
924 }
925 
926 /**
927   Reset the Block Device.
928 
929   @param  This                 Indicates a pointer to the calling context.
930   @param  ExtendedVerification Driver may perform diagnostics on reset.
931 
932   @retval EFI_SUCCESS          The device was reset.
933   @retval EFI_DEVICE_ERROR     The device is not functioning properly and could
934                                not be reset.
935 
936 **/
937 EFI_STATUS
938 EFIAPI
NvmeBlockIoReset(IN EFI_BLOCK_IO_PROTOCOL * This,IN BOOLEAN ExtendedVerification)939 NvmeBlockIoReset (
940   IN  EFI_BLOCK_IO_PROTOCOL   *This,
941   IN  BOOLEAN                 ExtendedVerification
942   )
943 {
944   EFI_TPL                         OldTpl;
945   NVME_CONTROLLER_PRIVATE_DATA    *Private;
946   NVME_DEVICE_PRIVATE_DATA        *Device;
947   EFI_STATUS                      Status;
948 
949   if (This == NULL) {
950     return EFI_INVALID_PARAMETER;
951   }
952 
953   //
954   // For Nvm Express subsystem, reset block device means reset controller.
955   //
956   OldTpl  = gBS->RaiseTPL (TPL_CALLBACK);
957 
958   Device  = NVME_DEVICE_PRIVATE_DATA_FROM_BLOCK_IO (This);
959 
960   Private = Device->Controller;
961 
962   Status  = NvmeControllerInit (Private);
963 
964   if (EFI_ERROR (Status)) {
965     Status = EFI_DEVICE_ERROR;
966   }
967 
968   gBS->RestoreTPL (OldTpl);
969 
970   return Status;
971 }
972 
973 /**
974   Read BufferSize bytes from Lba into Buffer.
975 
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.
982 
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.
990 
991 **/
992 EFI_STATUS
993 EFIAPI
NvmeBlockIoReadBlocks(IN EFI_BLOCK_IO_PROTOCOL * This,IN UINT32 MediaId,IN EFI_LBA Lba,IN UINTN BufferSize,OUT VOID * Buffer)994 NvmeBlockIoReadBlocks (
995   IN  EFI_BLOCK_IO_PROTOCOL   *This,
996   IN  UINT32                  MediaId,
997   IN  EFI_LBA                 Lba,
998   IN  UINTN                   BufferSize,
999   OUT VOID                    *Buffer
1000   )
1001 {
1002   NVME_DEVICE_PRIVATE_DATA          *Device;
1003   EFI_STATUS                        Status;
1004   EFI_BLOCK_IO_MEDIA                *Media;
1005   UINTN                             BlockSize;
1006   UINTN                             NumberOfBlocks;
1007   UINTN                             IoAlign;
1008   EFI_TPL                           OldTpl;
1009 
1010   //
1011   // Check parameters.
1012   //
1013   if (This == NULL) {
1014     return EFI_INVALID_PARAMETER;
1015   }
1016 
1017   Media = This->Media;
1018 
1019   if (MediaId != Media->MediaId) {
1020     return EFI_MEDIA_CHANGED;
1021   }
1022 
1023   if (Buffer == NULL) {
1024     return EFI_INVALID_PARAMETER;
1025   }
1026 
1027   if (BufferSize == 0) {
1028     return EFI_SUCCESS;
1029   }
1030 
1031   BlockSize = Media->BlockSize;
1032   if ((BufferSize % BlockSize) != 0) {
1033     return EFI_BAD_BUFFER_SIZE;
1034   }
1035 
1036   NumberOfBlocks  = BufferSize / BlockSize;
1037   if ((Lba + NumberOfBlocks - 1) > Media->LastBlock) {
1038     return EFI_INVALID_PARAMETER;
1039   }
1040 
1041   IoAlign = Media->IoAlign;
1042   if (IoAlign > 0 && (((UINTN) Buffer & (IoAlign - 1)) != 0)) {
1043     return EFI_INVALID_PARAMETER;
1044   }
1045 
1046   OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
1047 
1048   Device = NVME_DEVICE_PRIVATE_DATA_FROM_BLOCK_IO (This);
1049 
1050   Status = NvmeRead (Device, Buffer, Lba, NumberOfBlocks);
1051 
1052   gBS->RestoreTPL (OldTpl);
1053   return Status;
1054 }
1055 
1056 /**
1057   Write BufferSize bytes from Lba into Buffer.
1058 
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.
1065 
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.
1074 
1075 **/
1076 EFI_STATUS
1077 EFIAPI
NvmeBlockIoWriteBlocks(IN EFI_BLOCK_IO_PROTOCOL * This,IN UINT32 MediaId,IN EFI_LBA Lba,IN UINTN BufferSize,IN VOID * Buffer)1078 NvmeBlockIoWriteBlocks (
1079   IN  EFI_BLOCK_IO_PROTOCOL   *This,
1080   IN  UINT32                  MediaId,
1081   IN  EFI_LBA                 Lba,
1082   IN  UINTN                   BufferSize,
1083   IN  VOID                    *Buffer
1084   )
1085 {
1086   NVME_DEVICE_PRIVATE_DATA          *Device;
1087   EFI_STATUS                        Status;
1088   EFI_BLOCK_IO_MEDIA                *Media;
1089   UINTN                             BlockSize;
1090   UINTN                             NumberOfBlocks;
1091   UINTN                             IoAlign;
1092   EFI_TPL                           OldTpl;
1093 
1094   //
1095   // Check parameters.
1096   //
1097   if (This == NULL) {
1098     return EFI_INVALID_PARAMETER;
1099   }
1100 
1101   Media = This->Media;
1102 
1103   if (MediaId != Media->MediaId) {
1104     return EFI_MEDIA_CHANGED;
1105   }
1106 
1107   if (Buffer == NULL) {
1108     return EFI_INVALID_PARAMETER;
1109   }
1110 
1111   if (BufferSize == 0) {
1112     return EFI_SUCCESS;
1113   }
1114 
1115   BlockSize = Media->BlockSize;
1116   if ((BufferSize % BlockSize) != 0) {
1117     return EFI_BAD_BUFFER_SIZE;
1118   }
1119 
1120   NumberOfBlocks  = BufferSize / BlockSize;
1121   if ((Lba + NumberOfBlocks - 1) > Media->LastBlock) {
1122     return EFI_INVALID_PARAMETER;
1123   }
1124 
1125   IoAlign = Media->IoAlign;
1126   if (IoAlign > 0 && (((UINTN) Buffer & (IoAlign - 1)) != 0)) {
1127     return EFI_INVALID_PARAMETER;
1128   }
1129 
1130   OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
1131 
1132   Device = NVME_DEVICE_PRIVATE_DATA_FROM_BLOCK_IO (This);
1133 
1134   Status = NvmeWrite (Device, Buffer, Lba, NumberOfBlocks);
1135 
1136   gBS->RestoreTPL (OldTpl);
1137 
1138   return Status;
1139 }
1140 
1141 /**
1142   Flush the Block Device.
1143 
1144   @param  This              Indicates a pointer to the calling context.
1145 
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.
1149 
1150 **/
1151 EFI_STATUS
1152 EFIAPI
NvmeBlockIoFlushBlocks(IN EFI_BLOCK_IO_PROTOCOL * This)1153 NvmeBlockIoFlushBlocks (
1154   IN  EFI_BLOCK_IO_PROTOCOL   *This
1155   )
1156 {
1157   NVME_DEVICE_PRIVATE_DATA          *Device;
1158   EFI_STATUS                        Status;
1159   EFI_TPL                           OldTpl;
1160 
1161   //
1162   // Check parameters.
1163   //
1164   if (This == NULL) {
1165     return EFI_INVALID_PARAMETER;
1166   }
1167 
1168   OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
1169 
1170   Device = NVME_DEVICE_PRIVATE_DATA_FROM_BLOCK_IO (This);
1171 
1172   Status = NvmeFlush (Device);
1173 
1174   gBS->RestoreTPL (OldTpl);
1175 
1176   return Status;
1177 }
1178 
1179 /**
1180   Reset the block device hardware.
1181 
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.
1186 
1187   @retval EFI_SUCCESS          The device was reset.
1188   @retval EFI_DEVICE_ERROR     The device is not functioning properly and could
1189                                not be reset.
1190 
1191 **/
1192 EFI_STATUS
1193 EFIAPI
NvmeBlockIoResetEx(IN EFI_BLOCK_IO2_PROTOCOL * This,IN BOOLEAN ExtendedVerification)1194 NvmeBlockIoResetEx (
1195   IN EFI_BLOCK_IO2_PROTOCOL  *This,
1196   IN BOOLEAN                 ExtendedVerification
1197   )
1198 {
1199   EFI_STATUS                      Status;
1200   NVME_DEVICE_PRIVATE_DATA        *Device;
1201   NVME_CONTROLLER_PRIVATE_DATA    *Private;
1202   BOOLEAN                         IsEmpty;
1203   EFI_TPL                         OldTpl;
1204 
1205   if (This == NULL) {
1206     return EFI_INVALID_PARAMETER;
1207   }
1208 
1209   Device  = NVME_DEVICE_PRIVATE_DATA_FROM_BLOCK_IO2 (This);
1210   Private = Device->Controller;
1211 
1212   //
1213   // Wait for the asynchronous PassThru queue to become empty.
1214   //
1215   while (TRUE) {
1216     OldTpl  = gBS->RaiseTPL (TPL_NOTIFY);
1217     IsEmpty = IsListEmpty (&Private->AsyncPassThruQueue) &&
1218               IsListEmpty (&Private->UnsubmittedSubtasks);
1219     gBS->RestoreTPL (OldTpl);
1220 
1221     if (IsEmpty) {
1222       break;
1223     }
1224 
1225     gBS->Stall (100);
1226   }
1227 
1228   OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
1229 
1230   Status  = NvmeControllerInit (Private);
1231 
1232   if (EFI_ERROR (Status)) {
1233     Status = EFI_DEVICE_ERROR;
1234   }
1235 
1236   gBS->RestoreTPL (OldTpl);
1237 
1238   return Status;
1239 }
1240 
1241 /**
1242   Read BufferSize bytes from Lba into Buffer.
1243 
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
1248   not be signaled.
1249 
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
1252                               replaced.
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
1255                               transaction.
1256   @param[in]       BufferSize Size of Buffer, must be a multiple of device
1257                               block size.
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.
1261 
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
1266                                 the read.
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
1273                                 alignment.
1274   @retval EFI_OUT_OF_RESOURCES  The request could not be completed due to a
1275                                 lack of resources.
1276 
1277 **/
1278 EFI_STATUS
1279 EFIAPI
NvmeBlockIoReadBlocksEx(IN EFI_BLOCK_IO2_PROTOCOL * This,IN UINT32 MediaId,IN EFI_LBA Lba,IN OUT EFI_BLOCK_IO2_TOKEN * Token,IN UINTN BufferSize,OUT VOID * Buffer)1280 NvmeBlockIoReadBlocksEx (
1281   IN     EFI_BLOCK_IO2_PROTOCOL *This,
1282   IN     UINT32                 MediaId,
1283   IN     EFI_LBA                Lba,
1284   IN OUT EFI_BLOCK_IO2_TOKEN    *Token,
1285   IN     UINTN                  BufferSize,
1286      OUT VOID                  *Buffer
1287   )
1288 {
1289   NVME_DEVICE_PRIVATE_DATA        *Device;
1290   EFI_STATUS                      Status;
1291   EFI_BLOCK_IO_MEDIA              *Media;
1292   UINTN                           BlockSize;
1293   UINTN                           NumberOfBlocks;
1294   UINTN                           IoAlign;
1295   EFI_TPL                         OldTpl;
1296 
1297   //
1298   // Check parameters.
1299   //
1300   if (This == NULL) {
1301     return EFI_INVALID_PARAMETER;
1302   }
1303 
1304   Media = This->Media;
1305 
1306   if (MediaId != Media->MediaId) {
1307     return EFI_MEDIA_CHANGED;
1308   }
1309 
1310   if (Buffer == NULL) {
1311     return EFI_INVALID_PARAMETER;
1312   }
1313 
1314   if (BufferSize == 0) {
1315     if ((Token != NULL) && (Token->Event != NULL)) {
1316       Token->TransactionStatus = EFI_SUCCESS;
1317       gBS->SignalEvent (Token->Event);
1318     }
1319     return EFI_SUCCESS;
1320   }
1321 
1322   BlockSize = Media->BlockSize;
1323   if ((BufferSize % BlockSize) != 0) {
1324     return EFI_BAD_BUFFER_SIZE;
1325   }
1326 
1327   NumberOfBlocks  = BufferSize / BlockSize;
1328   if ((Lba + NumberOfBlocks - 1) > Media->LastBlock) {
1329     return EFI_INVALID_PARAMETER;
1330   }
1331 
1332   IoAlign = Media->IoAlign;
1333   if (IoAlign > 0 && (((UINTN) Buffer & (IoAlign - 1)) != 0)) {
1334     return EFI_INVALID_PARAMETER;
1335   }
1336 
1337   OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
1338 
1339   Device = NVME_DEVICE_PRIVATE_DATA_FROM_BLOCK_IO2 (This);
1340 
1341   if ((Token != NULL) && (Token->Event != NULL)) {
1342     Token->TransactionStatus = EFI_SUCCESS;
1343     Status = NvmeAsyncRead (Device, Buffer, Lba, NumberOfBlocks, Token);
1344   } else {
1345     Status = NvmeRead (Device, Buffer, Lba, NumberOfBlocks);
1346   }
1347 
1348   gBS->RestoreTPL (OldTpl);
1349   return Status;
1350 }
1351 
1352 /**
1353   Write BufferSize bytes from Lba into Buffer.
1354 
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.
1359 
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
1366                               transaction.
1367   @param[in]       BufferSize Size of Buffer, must be a multiple of device
1368                               block size.
1369   @param[in]       Buffer     A pointer to the source buffer for the data.
1370 
1371   @retval EFI_SUCCESS           The write request was queued if Event is not
1372                                 NULL.
1373                                 The data was written correctly to the device if
1374                                 the Event is NULL.
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
1378                                 device.
1379   @retval EFI_DEVICE_ERROR      The device reported an error while performing
1380                                 the write.
1381   @retval EFI_BAD_BUFFER_SIZE   The Buffer was not a multiple of the block size
1382                                 of the device.
1383   @retval EFI_INVALID_PARAMETER The write request contains LBAs that are not
1384                                 valid, or the buffer is not on proper
1385                                 alignment.
1386   @retval EFI_OUT_OF_RESOURCES  The request could not be completed due to a
1387                                 lack of resources.
1388 
1389 **/
1390 EFI_STATUS
1391 EFIAPI
NvmeBlockIoWriteBlocksEx(IN EFI_BLOCK_IO2_PROTOCOL * This,IN UINT32 MediaId,IN EFI_LBA Lba,IN OUT EFI_BLOCK_IO2_TOKEN * Token,IN UINTN BufferSize,IN VOID * Buffer)1392 NvmeBlockIoWriteBlocksEx (
1393   IN     EFI_BLOCK_IO2_PROTOCOL  *This,
1394   IN     UINT32                 MediaId,
1395   IN     EFI_LBA                Lba,
1396   IN OUT EFI_BLOCK_IO2_TOKEN    *Token,
1397   IN     UINTN                  BufferSize,
1398   IN     VOID                   *Buffer
1399   )
1400 {
1401   NVME_DEVICE_PRIVATE_DATA        *Device;
1402   EFI_STATUS                      Status;
1403   EFI_BLOCK_IO_MEDIA              *Media;
1404   UINTN                           BlockSize;
1405   UINTN                           NumberOfBlocks;
1406   UINTN                           IoAlign;
1407   EFI_TPL                         OldTpl;
1408 
1409   //
1410   // Check parameters.
1411   //
1412   if (This == NULL) {
1413     return EFI_INVALID_PARAMETER;
1414   }
1415 
1416   Media = This->Media;
1417 
1418   if (MediaId != Media->MediaId) {
1419     return EFI_MEDIA_CHANGED;
1420   }
1421 
1422   if (Buffer == NULL) {
1423     return EFI_INVALID_PARAMETER;
1424   }
1425 
1426   if (BufferSize == 0) {
1427     if ((Token != NULL) && (Token->Event != NULL)) {
1428       Token->TransactionStatus = EFI_SUCCESS;
1429       gBS->SignalEvent (Token->Event);
1430     }
1431     return EFI_SUCCESS;
1432   }
1433 
1434   BlockSize = Media->BlockSize;
1435   if ((BufferSize % BlockSize) != 0) {
1436     return EFI_BAD_BUFFER_SIZE;
1437   }
1438 
1439   NumberOfBlocks  = BufferSize / BlockSize;
1440   if ((Lba + NumberOfBlocks - 1) > Media->LastBlock) {
1441     return EFI_INVALID_PARAMETER;
1442   }
1443 
1444   IoAlign = Media->IoAlign;
1445   if (IoAlign > 0 && (((UINTN) Buffer & (IoAlign - 1)) != 0)) {
1446     return EFI_INVALID_PARAMETER;
1447   }
1448 
1449   OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
1450 
1451   Device = NVME_DEVICE_PRIVATE_DATA_FROM_BLOCK_IO2 (This);
1452 
1453   if ((Token != NULL) && (Token->Event != NULL)) {
1454     Token->TransactionStatus = EFI_SUCCESS;
1455     Status = NvmeAsyncWrite (Device, Buffer, Lba, NumberOfBlocks, Token);
1456   } else {
1457     Status = NvmeWrite (Device, Buffer, Lba, NumberOfBlocks);
1458   }
1459 
1460   gBS->RestoreTPL (OldTpl);
1461   return Status;
1462 }
1463 
1464 /**
1465   Flush the Block Device.
1466 
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.
1470 
1471   @param[in]      This     Indicates a pointer to the calling context.
1472   @param[in,out]  Token    A pointer to the token associated with the
1473                            transaction.
1474 
1475   @retval EFI_SUCCESS          The flush request was queued if Event is not
1476                                NULL.
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
1480                                the data.
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
1485                                of resources.
1486 
1487 **/
1488 EFI_STATUS
1489 EFIAPI
NvmeBlockIoFlushBlocksEx(IN EFI_BLOCK_IO2_PROTOCOL * This,IN OUT EFI_BLOCK_IO2_TOKEN * Token)1490 NvmeBlockIoFlushBlocksEx (
1491   IN     EFI_BLOCK_IO2_PROTOCOL   *This,
1492   IN OUT EFI_BLOCK_IO2_TOKEN      *Token
1493   )
1494 {
1495   NVME_DEVICE_PRIVATE_DATA        *Device;
1496   BOOLEAN                         IsEmpty;
1497   EFI_TPL                         OldTpl;
1498 
1499   //
1500   // Check parameters.
1501   //
1502   if (This == NULL) {
1503     return EFI_INVALID_PARAMETER;
1504   }
1505 
1506   Device = NVME_DEVICE_PRIVATE_DATA_FROM_BLOCK_IO2 (This);
1507 
1508   //
1509   // Wait for the asynchronous I/O queue to become empty.
1510   //
1511   while (TRUE) {
1512     OldTpl  = gBS->RaiseTPL (TPL_NOTIFY);
1513     IsEmpty = IsListEmpty (&Device->AsyncQueue);
1514     gBS->RestoreTPL (OldTpl);
1515 
1516     if (IsEmpty) {
1517       break;
1518     }
1519 
1520     gBS->Stall (100);
1521   }
1522 
1523   //
1524   // Signal caller event
1525   //
1526   if ((Token != NULL) && (Token->Event != NULL)) {
1527     Token->TransactionStatus = EFI_SUCCESS;
1528     gBS->SignalEvent (Token->Event);
1529   }
1530 
1531   return EFI_SUCCESS;
1532 }
1533 
1534 /**
1535   Trust transfer data from/to NVMe device.
1536 
1537   This function performs one NVMe transaction to do a trust transfer from/to NVMe device.
1538 
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.
1556 
1557   @retval EFI_SUCCESS       The data transfer is complete successfully.
1558   @return others            Some error occurs when transferring data.
1559 
1560 **/
1561 EFI_STATUS
TrustTransferNvmeDevice(IN OUT NVME_CONTROLLER_PRIVATE_DATA * Private,IN OUT VOID * Buffer,IN UINT8 SecurityProtocolId,IN UINT16 SecurityProtocolSpecificData,IN UINTN TransferLength,IN BOOLEAN IsTrustSend,IN UINT64 Timeout,OUT UINTN * TransferLengthOut)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,
1569   IN UINT64                                Timeout,
1570   OUT UINTN                                *TransferLengthOut
1571   )
1572 {
1573   EFI_NVM_EXPRESS_PASS_THRU_COMMAND_PACKET CommandPacket;
1574   EFI_NVM_EXPRESS_COMMAND                  Command;
1575   EFI_NVM_EXPRESS_COMPLETION               Completion;
1576   EFI_STATUS                               Status;
1577   UINT16                                   SpecificData;
1578 
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));
1582 
1583   CommandPacket.NvmeCmd        = &Command;
1584   CommandPacket.NvmeCompletion = &Completion;
1585 
1586   //
1587   // Change Endianness of SecurityProtocolSpecificData
1588   //
1589   SpecificData = (((SecurityProtocolSpecificData << 8) & 0xFF00) | (SecurityProtocolSpecificData >> 8));
1590 
1591   if (IsTrustSend) {
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;
1597   } else {
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;
1603   }
1604 
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;
1609 
1610   Status = Private->Passthru.PassThru (
1611                                &Private->Passthru,
1612                                NVME_CONTROLLER_ID,
1613                                &CommandPacket,
1614                                NULL
1615                                );
1616 
1617   if (!IsTrustSend) {
1618     if (EFI_ERROR (Status))  {
1619       *TransferLengthOut = 0;
1620     } else {
1621       *TransferLengthOut = (UINTN) TransferLength;
1622     }
1623   }
1624 
1625   return Status;
1626 }
1627 
1628 /**
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.
1631 
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.
1636 
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.
1639 
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
1642   is non-zero.
1643 
1644   If the PayloadBufferSize is zero, the security protocol command is sent using the
1645   Trusted Non-Data command defined in ATA8-ACS.
1646 
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.
1650 
1651   If PayloadBuffer or PayloadTransferSize is NULL and PayloadBufferSize is non-zero,
1652   the function shall return EFI_INVALID_PARAMETER.
1653 
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.
1658 
1659   If the security protocol fails to complete within the Timeout period, the function
1660   shall return EFI_TIMEOUT.
1661 
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.
1665 
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.
1686 
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.
1698 
1699 **/
1700 EFI_STATUS
1701 EFIAPI
NvmeStorageSecurityReceiveData(IN EFI_STORAGE_SECURITY_COMMAND_PROTOCOL * This,IN UINT32 MediaId,IN UINT64 Timeout,IN UINT8 SecurityProtocolId,IN UINT16 SecurityProtocolSpecificData,IN UINTN PayloadBufferSize,OUT VOID * PayloadBuffer,OUT UINTN * PayloadTransferSize)1702 NvmeStorageSecurityReceiveData (
1703   IN  EFI_STORAGE_SECURITY_COMMAND_PROTOCOL    *This,
1704   IN  UINT32                                   MediaId,
1705   IN  UINT64                                   Timeout,
1706   IN  UINT8                                    SecurityProtocolId,
1707   IN  UINT16                                   SecurityProtocolSpecificData,
1708   IN  UINTN                                    PayloadBufferSize,
1709   OUT VOID                                     *PayloadBuffer,
1710   OUT UINTN                                    *PayloadTransferSize
1711   )
1712 {
1713   EFI_STATUS                       Status;
1714   NVME_DEVICE_PRIVATE_DATA         *Device;
1715 
1716   Status  = EFI_SUCCESS;
1717 
1718   if ((PayloadBuffer == NULL) || (PayloadTransferSize == NULL) || (PayloadBufferSize == 0)) {
1719     return EFI_INVALID_PARAMETER;
1720   }
1721 
1722   Device = NVME_DEVICE_PRIVATE_DATA_FROM_STORAGE_SECURITY (This);
1723 
1724   if (MediaId != Device->BlockIo.Media->MediaId) {
1725     return EFI_MEDIA_CHANGED;
1726   }
1727 
1728   if (!Device->BlockIo.Media->MediaPresent) {
1729     return EFI_NO_MEDIA;
1730   }
1731 
1732   Status = TrustTransferNvmeDevice (
1733              Device->Controller,
1734              PayloadBuffer,
1735              SecurityProtocolId,
1736              SecurityProtocolSpecificData,
1737              PayloadBufferSize,
1738              FALSE,
1739              Timeout,
1740              PayloadTransferSize
1741              );
1742 
1743   return Status;
1744 }
1745 
1746 /**
1747   Send a security protocol command to a device.
1748 
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.
1755 
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.
1758 
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.
1763 
1764   If PayloadBuffer is NULL and PayloadBufferSize is non-zero, the function shall
1765   return EFI_INVALID_PARAMETER.
1766 
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.
1771 
1772   If the security protocol fails to complete within the Timeout period, the function
1773   shall return EFI_TIMEOUT.
1774 
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.
1778 
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
1795                                        protocol command.
1796 
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.
1805 
1806 **/
1807 EFI_STATUS
1808 EFIAPI
NvmeStorageSecuritySendData(IN EFI_STORAGE_SECURITY_COMMAND_PROTOCOL * This,IN UINT32 MediaId,IN UINT64 Timeout,IN UINT8 SecurityProtocolId,IN UINT16 SecurityProtocolSpecificData,IN UINTN PayloadBufferSize,IN VOID * PayloadBuffer)1809 NvmeStorageSecuritySendData (
1810   IN EFI_STORAGE_SECURITY_COMMAND_PROTOCOL    *This,
1811   IN UINT32                                   MediaId,
1812   IN UINT64                                   Timeout,
1813   IN UINT8                                    SecurityProtocolId,
1814   IN UINT16                                   SecurityProtocolSpecificData,
1815   IN UINTN                                    PayloadBufferSize,
1816   IN VOID                                     *PayloadBuffer
1817   )
1818 {
1819   EFI_STATUS                       Status;
1820   NVME_DEVICE_PRIVATE_DATA         *Device;
1821 
1822   Status  = EFI_SUCCESS;
1823 
1824   if ((PayloadBuffer == NULL) && (PayloadBufferSize != 0)) {
1825     return EFI_INVALID_PARAMETER;
1826   }
1827 
1828   Device = NVME_DEVICE_PRIVATE_DATA_FROM_STORAGE_SECURITY (This);
1829 
1830   if (MediaId != Device->BlockIo.Media->MediaId) {
1831     return EFI_MEDIA_CHANGED;
1832   }
1833 
1834   if (!Device->BlockIo.Media->MediaPresent) {
1835     return EFI_NO_MEDIA;
1836   }
1837 
1838   Status = TrustTransferNvmeDevice (
1839              Device->Controller,
1840              PayloadBuffer,
1841              SecurityProtocolId,
1842              SecurityProtocolSpecificData,
1843              PayloadBufferSize,
1844              TRUE,
1845              Timeout,
1846              NULL
1847              );
1848 
1849   return Status;
1850 }
1851 
1852 
1853 
1854 
1855