• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /** @file
2   NvmExpressDxe driver is used to manage non-volatile memory subsystem which follows
3   NVM Express specification.
4 
5   Copyright (c) 2013 - 2016, Intel Corporation. All rights reserved.<BR>
6   This program and the accompanying materials
7   are licensed and made available under the terms and conditions of the BSD License
8   which accompanies this distribution.  The full text of the license may be found at
9   http://opensource.org/licenses/bsd-license.php.
10 
11   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
13 
14 **/
15 
16 #include "NvmExpress.h"
17 
18 /**
19   Read some sectors from the device.
20 
21   @param  Device                 The pointer to the NVME_DEVICE_PRIVATE_DATA data structure.
22   @param  Buffer                 The buffer used to store the data read from the device.
23   @param  Lba                    The start block number.
24   @param  Blocks                 Total block number to be read.
25 
26   @retval EFI_SUCCESS            Datum are read from the device.
27   @retval Others                 Fail to read all the datum.
28 
29 **/
30 EFI_STATUS
ReadSectors(IN NVME_DEVICE_PRIVATE_DATA * Device,IN UINT64 Buffer,IN UINT64 Lba,IN UINT32 Blocks)31 ReadSectors (
32   IN NVME_DEVICE_PRIVATE_DATA           *Device,
33   IN UINT64                             Buffer,
34   IN UINT64                             Lba,
35   IN UINT32                             Blocks
36   )
37 {
38   NVME_CONTROLLER_PRIVATE_DATA             *Private;
39   UINT32                                   Bytes;
40   EFI_NVM_EXPRESS_PASS_THRU_COMMAND_PACKET CommandPacket;
41   EFI_NVM_EXPRESS_COMMAND                  Command;
42   EFI_NVM_EXPRESS_COMPLETION               Completion;
43   EFI_STATUS                               Status;
44   UINT32                                   BlockSize;
45 
46   Private    = Device->Controller;
47   BlockSize  = Device->Media.BlockSize;
48   Bytes      = Blocks * BlockSize;
49 
50   ZeroMem (&CommandPacket, sizeof(EFI_NVM_EXPRESS_PASS_THRU_COMMAND_PACKET));
51   ZeroMem (&Command, sizeof(EFI_NVM_EXPRESS_COMMAND));
52   ZeroMem (&Completion, sizeof(EFI_NVM_EXPRESS_COMPLETION));
53 
54   CommandPacket.NvmeCmd        = &Command;
55   CommandPacket.NvmeCompletion = &Completion;
56 
57   CommandPacket.NvmeCmd->Cdw0.Opcode = NVME_IO_READ_OPC;
58   CommandPacket.NvmeCmd->Nsid        = Device->NamespaceId;
59   CommandPacket.TransferBuffer       = (VOID *)(UINTN)Buffer;
60 
61   CommandPacket.TransferLength = Bytes;
62   CommandPacket.CommandTimeout = NVME_GENERIC_TIMEOUT;
63   CommandPacket.QueueType      = NVME_IO_QUEUE;
64 
65   CommandPacket.NvmeCmd->Cdw10 = (UINT32)Lba;
66   CommandPacket.NvmeCmd->Cdw11 = (UINT32)RShiftU64(Lba, 32);
67   CommandPacket.NvmeCmd->Cdw12 = (Blocks - 1) & 0xFFFF;
68 
69   CommandPacket.NvmeCmd->Flags = CDW10_VALID | CDW11_VALID | CDW12_VALID;
70 
71   Status = Private->Passthru.PassThru (
72                                &Private->Passthru,
73                                Device->NamespaceId,
74                                &CommandPacket,
75                                NULL
76                                );
77 
78   return Status;
79 }
80 
81 /**
82   Write some sectors to the device.
83 
84   @param  Device                 The pointer to the NVME_DEVICE_PRIVATE_DATA data structure.
85   @param  Buffer                 The buffer to be written into the device.
86   @param  Lba                    The start block number.
87   @param  Blocks                 Total block number to be written.
88 
89   @retval EFI_SUCCESS            Datum are written into the buffer.
90   @retval Others                 Fail to write all the datum.
91 
92 **/
93 EFI_STATUS
WriteSectors(IN NVME_DEVICE_PRIVATE_DATA * Device,IN UINT64 Buffer,IN UINT64 Lba,IN UINT32 Blocks)94 WriteSectors (
95   IN NVME_DEVICE_PRIVATE_DATA      *Device,
96   IN UINT64                        Buffer,
97   IN UINT64                        Lba,
98   IN UINT32                        Blocks
99   )
100 {
101   NVME_CONTROLLER_PRIVATE_DATA             *Private;
102   EFI_NVM_EXPRESS_PASS_THRU_COMMAND_PACKET CommandPacket;
103   EFI_NVM_EXPRESS_COMMAND                  Command;
104   EFI_NVM_EXPRESS_COMPLETION               Completion;
105   EFI_STATUS                               Status;
106   UINT32                                   Bytes;
107   UINT32                                   BlockSize;
108 
109   Private    = Device->Controller;
110   BlockSize  = Device->Media.BlockSize;
111   Bytes      = Blocks * BlockSize;
112 
113   ZeroMem (&CommandPacket, sizeof(EFI_NVM_EXPRESS_PASS_THRU_COMMAND_PACKET));
114   ZeroMem (&Command, sizeof(EFI_NVM_EXPRESS_COMMAND));
115   ZeroMem (&Completion, sizeof(EFI_NVM_EXPRESS_COMPLETION));
116 
117   CommandPacket.NvmeCmd        = &Command;
118   CommandPacket.NvmeCompletion = &Completion;
119 
120   CommandPacket.NvmeCmd->Cdw0.Opcode = NVME_IO_WRITE_OPC;
121   CommandPacket.NvmeCmd->Nsid  = Device->NamespaceId;
122   CommandPacket.TransferBuffer = (VOID *)(UINTN)Buffer;
123 
124   CommandPacket.TransferLength = Bytes;
125   CommandPacket.CommandTimeout = NVME_GENERIC_TIMEOUT;
126   CommandPacket.QueueType      = NVME_IO_QUEUE;
127 
128   CommandPacket.NvmeCmd->Cdw10 = (UINT32)Lba;
129   CommandPacket.NvmeCmd->Cdw11 = (UINT32)RShiftU64(Lba, 32);
130   //
131   // Set Force Unit Access bit (bit 30) to use write-through behaviour
132   //
133   CommandPacket.NvmeCmd->Cdw12 = ((Blocks - 1) & 0xFFFF) | BIT30;
134 
135   CommandPacket.MetadataBuffer = NULL;
136   CommandPacket.MetadataLength = 0;
137 
138   CommandPacket.NvmeCmd->Flags = CDW10_VALID | CDW11_VALID | CDW12_VALID;
139 
140   Status = Private->Passthru.PassThru (
141                                &Private->Passthru,
142                                Device->NamespaceId,
143                                &CommandPacket,
144                                NULL
145                                );
146 
147   return Status;
148 }
149 
150 /**
151   Read some blocks from the device.
152 
153   @param  Device                 The pointer to the NVME_DEVICE_PRIVATE_DATA data structure.
154   @param  Buffer                 The buffer used to store the data read from the device.
155   @param  Lba                    The start block number.
156   @param  Blocks                 Total block number to be read.
157 
158   @retval EFI_SUCCESS            Datum are read from the device.
159   @retval Others                 Fail to read all the datum.
160 
161 **/
162 EFI_STATUS
NvmeRead(IN NVME_DEVICE_PRIVATE_DATA * Device,OUT VOID * Buffer,IN UINT64 Lba,IN UINTN Blocks)163 NvmeRead (
164   IN     NVME_DEVICE_PRIVATE_DATA       *Device,
165      OUT VOID                           *Buffer,
166   IN     UINT64                         Lba,
167   IN     UINTN                          Blocks
168   )
169 {
170   EFI_STATUS                       Status;
171   UINT32                           BlockSize;
172   NVME_CONTROLLER_PRIVATE_DATA     *Private;
173   UINT32                           MaxTransferBlocks;
174   UINTN                            OrginalBlocks;
175   BOOLEAN                          IsEmpty;
176   EFI_TPL                          OldTpl;
177 
178   //
179   // Wait for the device's asynchronous I/O queue to become empty.
180   //
181   while (TRUE) {
182     OldTpl  = gBS->RaiseTPL (TPL_NOTIFY);
183     IsEmpty = IsListEmpty (&Device->AsyncQueue);
184     gBS->RestoreTPL (OldTpl);
185 
186     if (IsEmpty) {
187       break;
188     }
189 
190     gBS->Stall (100);
191   }
192 
193   Status        = EFI_SUCCESS;
194   Private       = Device->Controller;
195   BlockSize     = Device->Media.BlockSize;
196   OrginalBlocks = Blocks;
197 
198   if (Private->ControllerData->Mdts != 0) {
199     MaxTransferBlocks = (1 << (Private->ControllerData->Mdts)) * (1 << (Private->Cap.Mpsmin + 12)) / BlockSize;
200   } else {
201     MaxTransferBlocks = 1024;
202   }
203 
204   while (Blocks > 0) {
205     if (Blocks > MaxTransferBlocks) {
206       Status = ReadSectors (Device, (UINT64)(UINTN)Buffer, Lba, MaxTransferBlocks);
207 
208       Blocks -= MaxTransferBlocks;
209       Buffer  = (VOID *)(UINTN)((UINT64)(UINTN)Buffer + MaxTransferBlocks * BlockSize);
210       Lba    += MaxTransferBlocks;
211     } else {
212       Status = ReadSectors (Device, (UINT64)(UINTN)Buffer, Lba, (UINT32)Blocks);
213       Blocks = 0;
214     }
215 
216     if (EFI_ERROR(Status)) {
217       break;
218     }
219   }
220 
221   DEBUG ((EFI_D_VERBOSE, "%a: Lba = 0x%08Lx, Original = 0x%08Lx, "
222     "Remaining = 0x%08Lx, BlockSize = 0x%x, Status = %r\n", __FUNCTION__, Lba,
223     (UINT64)OrginalBlocks, (UINT64)Blocks, BlockSize, Status));
224 
225   return Status;
226 }
227 
228 /**
229   Write some blocks to the device.
230 
231   @param  Device                 The pointer to the NVME_DEVICE_PRIVATE_DATA data structure.
232   @param  Buffer                 The buffer to be written into the device.
233   @param  Lba                    The start block number.
234   @param  Blocks                 Total block number to be written.
235 
236   @retval EFI_SUCCESS            Datum are written into the buffer.
237   @retval Others                 Fail to write all the datum.
238 
239 **/
240 EFI_STATUS
NvmeWrite(IN NVME_DEVICE_PRIVATE_DATA * Device,IN VOID * Buffer,IN UINT64 Lba,IN UINTN Blocks)241 NvmeWrite (
242   IN NVME_DEVICE_PRIVATE_DATA           *Device,
243   IN VOID                               *Buffer,
244   IN UINT64                             Lba,
245   IN UINTN                              Blocks
246   )
247 {
248   EFI_STATUS                       Status;
249   UINT32                           BlockSize;
250   NVME_CONTROLLER_PRIVATE_DATA     *Private;
251   UINT32                           MaxTransferBlocks;
252   UINTN                            OrginalBlocks;
253   BOOLEAN                          IsEmpty;
254   EFI_TPL                          OldTpl;
255 
256   //
257   // Wait for the device's asynchronous I/O queue to become empty.
258   //
259   while (TRUE) {
260     OldTpl  = gBS->RaiseTPL (TPL_NOTIFY);
261     IsEmpty = IsListEmpty (&Device->AsyncQueue);
262     gBS->RestoreTPL (OldTpl);
263 
264     if (IsEmpty) {
265       break;
266     }
267 
268     gBS->Stall (100);
269   }
270 
271   Status        = EFI_SUCCESS;
272   Private       = Device->Controller;
273   BlockSize     = Device->Media.BlockSize;
274   OrginalBlocks = Blocks;
275 
276   if (Private->ControllerData->Mdts != 0) {
277     MaxTransferBlocks = (1 << (Private->ControllerData->Mdts)) * (1 << (Private->Cap.Mpsmin + 12)) / BlockSize;
278   } else {
279     MaxTransferBlocks = 1024;
280   }
281 
282   while (Blocks > 0) {
283     if (Blocks > MaxTransferBlocks) {
284       Status = WriteSectors (Device, (UINT64)(UINTN)Buffer, Lba, MaxTransferBlocks);
285 
286       Blocks -= MaxTransferBlocks;
287       Buffer  = (VOID *)(UINTN)((UINT64)(UINTN)Buffer + MaxTransferBlocks * BlockSize);
288       Lba    += MaxTransferBlocks;
289     } else {
290       Status = WriteSectors (Device, (UINT64)(UINTN)Buffer, Lba, (UINT32)Blocks);
291       Blocks = 0;
292     }
293 
294     if (EFI_ERROR(Status)) {
295       break;
296     }
297   }
298 
299   DEBUG ((EFI_D_VERBOSE, "%a: Lba = 0x%08Lx, Original = 0x%08Lx, "
300     "Remaining = 0x%08Lx, BlockSize = 0x%x, Status = %r\n", __FUNCTION__, Lba,
301     (UINT64)OrginalBlocks, (UINT64)Blocks, BlockSize, Status));
302 
303   return Status;
304 }
305 
306 /**
307   Flushes all modified data to the device.
308 
309   @param  Device                 The pointer to the NVME_DEVICE_PRIVATE_DATA data structure.
310 
311   @retval EFI_SUCCESS            Datum are written into the buffer.
312   @retval Others                 Fail to write all the datum.
313 
314 **/
315 EFI_STATUS
NvmeFlush(IN NVME_DEVICE_PRIVATE_DATA * Device)316 NvmeFlush (
317   IN NVME_DEVICE_PRIVATE_DATA      *Device
318   )
319 {
320   NVME_CONTROLLER_PRIVATE_DATA             *Private;
321   EFI_NVM_EXPRESS_PASS_THRU_COMMAND_PACKET CommandPacket;
322   EFI_NVM_EXPRESS_COMMAND                  Command;
323   EFI_NVM_EXPRESS_COMPLETION               Completion;
324   EFI_STATUS                               Status;
325 
326   Private = Device->Controller;
327 
328   ZeroMem (&CommandPacket, sizeof(EFI_NVM_EXPRESS_PASS_THRU_COMMAND_PACKET));
329   ZeroMem (&Command, sizeof(EFI_NVM_EXPRESS_COMMAND));
330   ZeroMem (&Completion, sizeof(EFI_NVM_EXPRESS_COMPLETION));
331 
332   CommandPacket.NvmeCmd        = &Command;
333   CommandPacket.NvmeCompletion = &Completion;
334 
335   CommandPacket.NvmeCmd->Cdw0.Opcode = NVME_IO_FLUSH_OPC;
336   CommandPacket.NvmeCmd->Nsid  = Device->NamespaceId;
337   CommandPacket.CommandTimeout = NVME_GENERIC_TIMEOUT;
338   CommandPacket.QueueType      = NVME_IO_QUEUE;
339 
340   Status = Private->Passthru.PassThru (
341                                &Private->Passthru,
342                                Device->NamespaceId,
343                                &CommandPacket,
344                                NULL
345                                );
346 
347   return Status;
348 }
349 
350 /**
351   Nonblocking I/O callback funtion when the event is signaled.
352 
353   @param[in]  Event     The Event this notify function registered to.
354   @param[in]  Context   Pointer to the context data registered to the
355                         Event.
356 
357 **/
358 VOID
359 EFIAPI
AsyncIoCallback(IN EFI_EVENT Event,IN VOID * Context)360 AsyncIoCallback (
361   IN EFI_EVENT                Event,
362   IN VOID                     *Context
363   )
364 {
365   NVME_BLKIO2_SUBTASK         *Subtask;
366   NVME_BLKIO2_REQUEST         *Request;
367   NVME_CQ                     *Completion;
368   EFI_BLOCK_IO2_TOKEN         *Token;
369 
370   gBS->CloseEvent (Event);
371 
372   Subtask    = (NVME_BLKIO2_SUBTASK *) Context;
373   Completion = (NVME_CQ *) Subtask->CommandPacket->NvmeCompletion;
374   Request    = Subtask->BlockIo2Request;
375   Token      = Request->Token;
376 
377   if (Token->TransactionStatus == EFI_SUCCESS) {
378     //
379     // If previous subtask already fails, do not check the result of
380     // subsequent subtasks.
381     //
382     if ((Completion->Sct != 0) || (Completion->Sc != 0)) {
383       Token->TransactionStatus = EFI_DEVICE_ERROR;
384 
385       //
386       // Dump completion entry status for debugging.
387       //
388       DEBUG_CODE_BEGIN();
389         NvmeDumpStatus (Completion);
390       DEBUG_CODE_END();
391     }
392   }
393 
394   //
395   // Remove the subtask from the BlockIo2 subtasks list.
396   //
397   RemoveEntryList (&Subtask->Link);
398 
399   if (IsListEmpty (&Request->SubtasksQueue) && Request->LastSubtaskSubmitted) {
400     //
401     // Remove the BlockIo2 request from the device asynchronous queue.
402     //
403     RemoveEntryList (&Request->Link);
404     FreePool (Request);
405     gBS->SignalEvent (Token->Event);
406   }
407 
408   FreePool (Subtask->CommandPacket->NvmeCmd);
409   FreePool (Subtask->CommandPacket->NvmeCompletion);
410   FreePool (Subtask->CommandPacket);
411   FreePool (Subtask);
412 }
413 
414 /**
415   Read some sectors from the device in an asynchronous manner.
416 
417   @param  Device        The pointer to the NVME_DEVICE_PRIVATE_DATA data
418                         structure.
419   @param  Request       The pointer to the NVME_BLKIO2_REQUEST data structure.
420   @param  Buffer        The buffer used to store the data read from the device.
421   @param  Lba           The start block number.
422   @param  Blocks        Total block number to be read.
423   @param  IsLast        The last subtask of an asynchronous read request.
424 
425   @retval EFI_SUCCESS   Asynchronous read request has been queued.
426   @retval Others        Fail to send the asynchronous request.
427 
428 **/
429 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)430 AsyncReadSectors (
431   IN NVME_DEVICE_PRIVATE_DATA           *Device,
432   IN NVME_BLKIO2_REQUEST                *Request,
433   IN UINT64                             Buffer,
434   IN UINT64                             Lba,
435   IN UINT32                             Blocks,
436   IN BOOLEAN                            IsLast
437   )
438 {
439   NVME_CONTROLLER_PRIVATE_DATA             *Private;
440   UINT32                                   Bytes;
441   NVME_BLKIO2_SUBTASK                      *Subtask;
442   EFI_NVM_EXPRESS_PASS_THRU_COMMAND_PACKET *CommandPacket;
443   EFI_NVM_EXPRESS_COMMAND                  *Command;
444   EFI_NVM_EXPRESS_COMPLETION               *Completion;
445   EFI_STATUS                               Status;
446   UINT32                                   BlockSize;
447   EFI_TPL                                  OldTpl;
448 
449   Private       = Device->Controller;
450   BlockSize     = Device->Media.BlockSize;
451   Bytes         = Blocks * BlockSize;
452   CommandPacket = NULL;
453   Command       = NULL;
454   Completion    = NULL;
455 
456   Subtask = AllocateZeroPool (sizeof (NVME_BLKIO2_SUBTASK));
457   if (Subtask == NULL) {
458     Status = EFI_OUT_OF_RESOURCES;
459     goto ErrorExit;
460   }
461 
462   Subtask->Signature       = NVME_BLKIO2_SUBTASK_SIGNATURE;
463   Subtask->IsLast          = IsLast;
464   Subtask->NamespaceId     = Device->NamespaceId;
465   Subtask->BlockIo2Request = Request;
466 
467   CommandPacket = AllocateZeroPool (sizeof (EFI_NVM_EXPRESS_PASS_THRU_COMMAND_PACKET));
468   if (CommandPacket == NULL) {
469     Status = EFI_OUT_OF_RESOURCES;
470     goto ErrorExit;
471   } else {
472     Subtask->CommandPacket = CommandPacket;
473   }
474 
475   Command = AllocateZeroPool (sizeof (EFI_NVM_EXPRESS_COMMAND));
476   if (Command == NULL) {
477     Status = EFI_OUT_OF_RESOURCES;
478     goto ErrorExit;
479   }
480 
481   Completion = AllocateZeroPool (sizeof (EFI_NVM_EXPRESS_COMPLETION));
482   if (Completion == NULL) {
483     Status = EFI_OUT_OF_RESOURCES;
484     goto ErrorExit;
485   }
486 
487   //
488   // Create Event
489   //
490   Status = gBS->CreateEvent (
491                   EVT_NOTIFY_SIGNAL,
492                   TPL_NOTIFY,
493                   AsyncIoCallback,
494                   Subtask,
495                   &Subtask->Event
496                   );
497   if (EFI_ERROR(Status)) {
498     goto ErrorExit;
499   }
500 
501   CommandPacket->NvmeCmd        = Command;
502   CommandPacket->NvmeCompletion = Completion;
503 
504   CommandPacket->NvmeCmd->Cdw0.Opcode = NVME_IO_READ_OPC;
505   CommandPacket->NvmeCmd->Nsid        = Device->NamespaceId;
506   CommandPacket->TransferBuffer       = (VOID *)(UINTN)Buffer;
507 
508   CommandPacket->TransferLength = Bytes;
509   CommandPacket->CommandTimeout = NVME_GENERIC_TIMEOUT;
510   CommandPacket->QueueType      = NVME_IO_QUEUE;
511 
512   CommandPacket->NvmeCmd->Cdw10 = (UINT32)Lba;
513   CommandPacket->NvmeCmd->Cdw11 = (UINT32)RShiftU64(Lba, 32);
514   CommandPacket->NvmeCmd->Cdw12 = (Blocks - 1) & 0xFFFF;
515 
516   CommandPacket->NvmeCmd->Flags = CDW10_VALID | CDW11_VALID | CDW12_VALID;
517 
518   OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
519   InsertTailList (&Private->UnsubmittedSubtasks, &Subtask->Link);
520   Request->UnsubmittedSubtaskNum++;
521   gBS->RestoreTPL (OldTpl);
522 
523   return EFI_SUCCESS;
524 
525 ErrorExit:
526   //
527   // Resource cleanup if asynchronous read request has not been queued.
528   //
529   if (Completion != NULL) {
530     FreePool (Completion);
531   }
532 
533   if (Command != NULL) {
534     FreePool (Command);
535   }
536 
537   if (CommandPacket != NULL) {
538     FreePool (CommandPacket);
539   }
540 
541   if (Subtask != NULL) {
542     if (Subtask->Event != NULL) {
543       gBS->CloseEvent (Subtask->Event);
544     }
545 
546     FreePool (Subtask);
547   }
548 
549   return Status;
550 }
551 
552 /**
553   Write some sectors from the device in an asynchronous manner.
554 
555   @param  Device        The pointer to the NVME_DEVICE_PRIVATE_DATA data
556                         structure.
557   @param  Request       The pointer to the NVME_BLKIO2_REQUEST data structure.
558   @param  Buffer        The buffer used to store the data written to the
559                         device.
560   @param  Lba           The start block number.
561   @param  Blocks        Total block number to be written.
562   @param  IsLast        The last subtask of an asynchronous write request.
563 
564   @retval EFI_SUCCESS   Asynchronous write request has been queued.
565   @retval Others        Fail to send the asynchronous request.
566 
567 **/
568 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)569 AsyncWriteSectors (
570   IN NVME_DEVICE_PRIVATE_DATA           *Device,
571   IN NVME_BLKIO2_REQUEST                *Request,
572   IN UINT64                             Buffer,
573   IN UINT64                             Lba,
574   IN UINT32                             Blocks,
575   IN BOOLEAN                            IsLast
576   )
577 {
578   NVME_CONTROLLER_PRIVATE_DATA             *Private;
579   UINT32                                   Bytes;
580   NVME_BLKIO2_SUBTASK                      *Subtask;
581   EFI_NVM_EXPRESS_PASS_THRU_COMMAND_PACKET *CommandPacket;
582   EFI_NVM_EXPRESS_COMMAND                  *Command;
583   EFI_NVM_EXPRESS_COMPLETION               *Completion;
584   EFI_STATUS                               Status;
585   UINT32                                   BlockSize;
586   EFI_TPL                                  OldTpl;
587 
588   Private       = Device->Controller;
589   BlockSize     = Device->Media.BlockSize;
590   Bytes         = Blocks * BlockSize;
591   CommandPacket = NULL;
592   Command       = NULL;
593   Completion    = NULL;
594 
595   Subtask = AllocateZeroPool (sizeof (NVME_BLKIO2_SUBTASK));
596   if (Subtask == NULL) {
597     Status = EFI_OUT_OF_RESOURCES;
598     goto ErrorExit;
599   }
600 
601   Subtask->Signature       = NVME_BLKIO2_SUBTASK_SIGNATURE;
602   Subtask->IsLast          = IsLast;
603   Subtask->NamespaceId     = Device->NamespaceId;
604   Subtask->BlockIo2Request = Request;
605 
606   CommandPacket = AllocateZeroPool (sizeof (EFI_NVM_EXPRESS_PASS_THRU_COMMAND_PACKET));
607   if (CommandPacket == NULL) {
608     Status = EFI_OUT_OF_RESOURCES;
609     goto ErrorExit;
610   } else {
611     Subtask->CommandPacket = CommandPacket;
612   }
613 
614   Command = AllocateZeroPool (sizeof (EFI_NVM_EXPRESS_COMMAND));
615   if (Command == NULL) {
616     Status = EFI_OUT_OF_RESOURCES;
617     goto ErrorExit;
618   }
619 
620   Completion = AllocateZeroPool (sizeof (EFI_NVM_EXPRESS_COMPLETION));
621   if (Completion == NULL) {
622     Status = EFI_OUT_OF_RESOURCES;
623     goto ErrorExit;
624   }
625 
626   //
627   // Create Event
628   //
629   Status = gBS->CreateEvent (
630                   EVT_NOTIFY_SIGNAL,
631                   TPL_NOTIFY,
632                   AsyncIoCallback,
633                   Subtask,
634                   &Subtask->Event
635                   );
636   if (EFI_ERROR(Status)) {
637     goto ErrorExit;
638   }
639 
640   CommandPacket->NvmeCmd        = Command;
641   CommandPacket->NvmeCompletion = Completion;
642 
643   CommandPacket->NvmeCmd->Cdw0.Opcode = NVME_IO_WRITE_OPC;
644   CommandPacket->NvmeCmd->Nsid        = Device->NamespaceId;
645   CommandPacket->TransferBuffer       = (VOID *)(UINTN)Buffer;
646 
647   CommandPacket->TransferLength = Bytes;
648   CommandPacket->CommandTimeout = NVME_GENERIC_TIMEOUT;
649   CommandPacket->QueueType      = NVME_IO_QUEUE;
650 
651   CommandPacket->NvmeCmd->Cdw10 = (UINT32)Lba;
652   CommandPacket->NvmeCmd->Cdw11 = (UINT32)RShiftU64(Lba, 32);
653   //
654   // Set Force Unit Access bit (bit 30) to use write-through behaviour
655   //
656   CommandPacket->NvmeCmd->Cdw12 = ((Blocks - 1) & 0xFFFF) | BIT30;
657 
658   CommandPacket->NvmeCmd->Flags = CDW10_VALID | CDW11_VALID | CDW12_VALID;
659 
660   OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
661   InsertTailList (&Private->UnsubmittedSubtasks, &Subtask->Link);
662   Request->UnsubmittedSubtaskNum++;
663   gBS->RestoreTPL (OldTpl);
664 
665   return EFI_SUCCESS;
666 
667 ErrorExit:
668   //
669   // Resource cleanup if asynchronous read request has not been queued.
670   //
671   if (Completion != NULL) {
672     FreePool (Completion);
673   }
674 
675   if (Command != NULL) {
676     FreePool (Command);
677   }
678 
679   if (CommandPacket != NULL) {
680     FreePool (CommandPacket);
681   }
682 
683   if (Subtask != NULL) {
684     if (Subtask->Event != NULL) {
685       gBS->CloseEvent (Subtask->Event);
686     }
687 
688     FreePool (Subtask);
689   }
690 
691   return Status;
692 }
693 
694 /**
695   Read some blocks from the device in an asynchronous manner.
696 
697   @param  Device        The pointer to the NVME_DEVICE_PRIVATE_DATA data
698                         structure.
699   @param  Buffer        The buffer used to store the data read from the device.
700   @param  Lba           The start block number.
701   @param  Blocks        Total block number to be read.
702   @param  Token         A pointer to the token associated with the transaction.
703 
704   @retval EFI_SUCCESS   Data are read from the device.
705   @retval Others        Fail to read all the data.
706 
707 **/
708 EFI_STATUS
NvmeAsyncRead(IN NVME_DEVICE_PRIVATE_DATA * Device,OUT VOID * Buffer,IN UINT64 Lba,IN UINTN Blocks,IN EFI_BLOCK_IO2_TOKEN * Token)709 NvmeAsyncRead (
710   IN     NVME_DEVICE_PRIVATE_DATA       *Device,
711      OUT VOID                           *Buffer,
712   IN     UINT64                         Lba,
713   IN     UINTN                          Blocks,
714   IN     EFI_BLOCK_IO2_TOKEN            *Token
715   )
716 {
717   EFI_STATUS                       Status;
718   UINT32                           BlockSize;
719   NVME_CONTROLLER_PRIVATE_DATA     *Private;
720   NVME_BLKIO2_REQUEST              *BlkIo2Req;
721   UINT32                           MaxTransferBlocks;
722   UINTN                            OrginalBlocks;
723   BOOLEAN                          IsEmpty;
724   EFI_TPL                          OldTpl;
725 
726   Status        = EFI_SUCCESS;
727   Private       = Device->Controller;
728   BlockSize     = Device->Media.BlockSize;
729   OrginalBlocks = Blocks;
730   BlkIo2Req     = AllocateZeroPool (sizeof (NVME_BLKIO2_REQUEST));
731   if (BlkIo2Req == NULL) {
732     return EFI_OUT_OF_RESOURCES;
733   }
734 
735   BlkIo2Req->Signature = NVME_BLKIO2_REQUEST_SIGNATURE;
736   BlkIo2Req->Token     = Token;
737 
738   OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
739   InsertTailList (&Device->AsyncQueue, &BlkIo2Req->Link);
740   gBS->RestoreTPL (OldTpl);
741 
742   InitializeListHead (&BlkIo2Req->SubtasksQueue);
743 
744   if (Private->ControllerData->Mdts != 0) {
745     MaxTransferBlocks = (1 << (Private->ControllerData->Mdts)) * (1 << (Private->Cap.Mpsmin + 12)) / BlockSize;
746   } else {
747     MaxTransferBlocks = 1024;
748   }
749 
750   while (Blocks > 0) {
751     if (Blocks > MaxTransferBlocks) {
752       Status = AsyncReadSectors (
753                  Device,
754                  BlkIo2Req, (UINT64)(UINTN)Buffer,
755                  Lba,
756                  MaxTransferBlocks,
757                  FALSE
758                  );
759 
760       Blocks -= MaxTransferBlocks;
761       Buffer  = (VOID *)(UINTN)((UINT64)(UINTN)Buffer + MaxTransferBlocks * BlockSize);
762       Lba    += MaxTransferBlocks;
763     } else {
764       Status = AsyncReadSectors (
765                  Device,
766                  BlkIo2Req,
767                  (UINT64)(UINTN)Buffer,
768                  Lba,
769                  (UINT32)Blocks,
770                  TRUE
771                  );
772 
773       Blocks = 0;
774     }
775 
776     if (EFI_ERROR(Status)) {
777       OldTpl  = gBS->RaiseTPL (TPL_NOTIFY);
778       IsEmpty = IsListEmpty (&BlkIo2Req->SubtasksQueue) &&
779                 (BlkIo2Req->UnsubmittedSubtaskNum == 0);
780 
781       if (IsEmpty) {
782         //
783         // Remove the BlockIo2 request from the device asynchronous queue.
784         //
785         RemoveEntryList (&BlkIo2Req->Link);
786         FreePool (BlkIo2Req);
787         Status = EFI_DEVICE_ERROR;
788       } else {
789         //
790         // There are previous BlockIo2 subtasks still running, EFI_SUCCESS
791         // should be returned to make sure that the caller does not free
792         // resources still using by these requests.
793         //
794         Status = EFI_SUCCESS;
795         Token->TransactionStatus = EFI_DEVICE_ERROR;
796         BlkIo2Req->LastSubtaskSubmitted = TRUE;
797       }
798 
799       gBS->RestoreTPL (OldTpl);
800 
801       break;
802     }
803   }
804 
805   DEBUG ((EFI_D_VERBOSE, "%a: Lba = 0x%08Lx, Original = 0x%08Lx, "
806     "Remaining = 0x%08Lx, BlockSize = 0x%x, Status = %r\n", __FUNCTION__, Lba,
807     (UINT64)OrginalBlocks, (UINT64)Blocks, BlockSize, Status));
808 
809   return Status;
810 }
811 
812 /**
813   Write some blocks from the device in an asynchronous manner.
814 
815   @param  Device        The pointer to the NVME_DEVICE_PRIVATE_DATA data
816                         structure.
817   @param  Buffer        The buffer used to store the data written to the
818                         device.
819   @param  Lba           The start block number.
820   @param  Blocks        Total block number to be written.
821   @param  Token         A pointer to the token associated with the transaction.
822 
823   @retval EFI_SUCCESS   Data are written to the device.
824   @retval Others        Fail to write all the data.
825 
826 **/
827 EFI_STATUS
NvmeAsyncWrite(IN NVME_DEVICE_PRIVATE_DATA * Device,IN VOID * Buffer,IN UINT64 Lba,IN UINTN Blocks,IN EFI_BLOCK_IO2_TOKEN * Token)828 NvmeAsyncWrite (
829   IN NVME_DEVICE_PRIVATE_DATA           *Device,
830   IN VOID                               *Buffer,
831   IN UINT64                             Lba,
832   IN UINTN                              Blocks,
833   IN EFI_BLOCK_IO2_TOKEN                *Token
834   )
835 {
836   EFI_STATUS                       Status;
837   UINT32                           BlockSize;
838   NVME_CONTROLLER_PRIVATE_DATA     *Private;
839   NVME_BLKIO2_REQUEST              *BlkIo2Req;
840   UINT32                           MaxTransferBlocks;
841   UINTN                            OrginalBlocks;
842   BOOLEAN                          IsEmpty;
843   EFI_TPL                          OldTpl;
844 
845   Status        = EFI_SUCCESS;
846   Private       = Device->Controller;
847   BlockSize     = Device->Media.BlockSize;
848   OrginalBlocks = Blocks;
849   BlkIo2Req     = AllocateZeroPool (sizeof (NVME_BLKIO2_REQUEST));
850   if (BlkIo2Req == NULL) {
851     return EFI_OUT_OF_RESOURCES;
852   }
853 
854   BlkIo2Req->Signature = NVME_BLKIO2_REQUEST_SIGNATURE;
855   BlkIo2Req->Token     = Token;
856 
857   OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
858   InsertTailList (&Device->AsyncQueue, &BlkIo2Req->Link);
859   gBS->RestoreTPL (OldTpl);
860 
861   InitializeListHead (&BlkIo2Req->SubtasksQueue);
862 
863   if (Private->ControllerData->Mdts != 0) {
864     MaxTransferBlocks = (1 << (Private->ControllerData->Mdts)) * (1 << (Private->Cap.Mpsmin + 12)) / BlockSize;
865   } else {
866     MaxTransferBlocks = 1024;
867   }
868 
869   while (Blocks > 0) {
870     if (Blocks > MaxTransferBlocks) {
871       Status  = AsyncWriteSectors (
872                   Device,
873                   BlkIo2Req,
874                   (UINT64)(UINTN)Buffer,
875                   Lba,
876                   MaxTransferBlocks,
877                   FALSE
878                   );
879 
880       Blocks -= MaxTransferBlocks;
881       Buffer  = (VOID *)(UINTN)((UINT64)(UINTN)Buffer + MaxTransferBlocks * BlockSize);
882       Lba    += MaxTransferBlocks;
883     } else {
884       Status = AsyncWriteSectors (
885                  Device,
886                  BlkIo2Req,
887                  (UINT64)(UINTN)Buffer,
888                  Lba,
889                  (UINT32)Blocks,
890                  TRUE
891                  );
892 
893       Blocks = 0;
894     }
895 
896     if (EFI_ERROR(Status)) {
897       OldTpl  = gBS->RaiseTPL (TPL_NOTIFY);
898       IsEmpty = IsListEmpty (&BlkIo2Req->SubtasksQueue) &&
899                 (BlkIo2Req->UnsubmittedSubtaskNum == 0);
900 
901       if (IsEmpty) {
902         //
903         // Remove the BlockIo2 request from the device asynchronous queue.
904         //
905         RemoveEntryList (&BlkIo2Req->Link);
906         FreePool (BlkIo2Req);
907         Status = EFI_DEVICE_ERROR;
908       } else {
909         //
910         // There are previous BlockIo2 subtasks still running, EFI_SUCCESS
911         // should be returned to make sure that the caller does not free
912         // resources still using by these requests.
913         //
914         Status = EFI_SUCCESS;
915         Token->TransactionStatus = EFI_DEVICE_ERROR;
916         BlkIo2Req->LastSubtaskSubmitted = TRUE;
917       }
918 
919       gBS->RestoreTPL (OldTpl);
920 
921       break;
922     }
923   }
924 
925   DEBUG ((EFI_D_VERBOSE, "%a: Lba = 0x%08Lx, Original = 0x%08Lx, "
926     "Remaining = 0x%08Lx, BlockSize = 0x%x, Status = %r\n", __FUNCTION__, Lba,
927     (UINT64)OrginalBlocks, (UINT64)Blocks, BlockSize, Status));
928 
929   return Status;
930 }
931 
932 /**
933   Reset the Block Device.
934 
935   @param  This                 Indicates a pointer to the calling context.
936   @param  ExtendedVerification Driver may perform diagnostics on reset.
937 
938   @retval EFI_SUCCESS          The device was reset.
939   @retval EFI_DEVICE_ERROR     The device is not functioning properly and could
940                                not be reset.
941 
942 **/
943 EFI_STATUS
944 EFIAPI
NvmeBlockIoReset(IN EFI_BLOCK_IO_PROTOCOL * This,IN BOOLEAN ExtendedVerification)945 NvmeBlockIoReset (
946   IN  EFI_BLOCK_IO_PROTOCOL   *This,
947   IN  BOOLEAN                 ExtendedVerification
948   )
949 {
950   EFI_TPL                         OldTpl;
951   NVME_CONTROLLER_PRIVATE_DATA    *Private;
952   NVME_DEVICE_PRIVATE_DATA        *Device;
953   EFI_STATUS                      Status;
954 
955   if (This == NULL) {
956     return EFI_INVALID_PARAMETER;
957   }
958 
959   //
960   // For Nvm Express subsystem, reset block device means reset controller.
961   //
962   OldTpl  = gBS->RaiseTPL (TPL_CALLBACK);
963 
964   Device  = NVME_DEVICE_PRIVATE_DATA_FROM_BLOCK_IO (This);
965 
966   Private = Device->Controller;
967 
968   Status  = NvmeControllerInit (Private);
969 
970   if (EFI_ERROR (Status)) {
971     Status = EFI_DEVICE_ERROR;
972   }
973 
974   gBS->RestoreTPL (OldTpl);
975 
976   return Status;
977 }
978 
979 /**
980   Read BufferSize bytes from Lba into Buffer.
981 
982   @param  This       Indicates a pointer to the calling context.
983   @param  MediaId    Id of the media, changes every time the media is replaced.
984   @param  Lba        The starting Logical Block Address to read from.
985   @param  BufferSize Size of Buffer, must be a multiple of device block size.
986   @param  Buffer     A pointer to the destination buffer for the data. The caller is
987                      responsible for either having implicit or explicit ownership of the buffer.
988 
989   @retval EFI_SUCCESS           The data was read correctly from the device.
990   @retval EFI_DEVICE_ERROR      The device reported an error while performing the read.
991   @retval EFI_NO_MEDIA          There is no media in the device.
992   @retval EFI_MEDIA_CHANGED     The MediaId does not matched the current device.
993   @retval EFI_BAD_BUFFER_SIZE   The Buffer was not a multiple of the block size of the device.
994   @retval EFI_INVALID_PARAMETER The read request contains LBAs that are not valid,
995                                 or the buffer is not on proper alignment.
996 
997 **/
998 EFI_STATUS
999 EFIAPI
NvmeBlockIoReadBlocks(IN EFI_BLOCK_IO_PROTOCOL * This,IN UINT32 MediaId,IN EFI_LBA Lba,IN UINTN BufferSize,OUT VOID * Buffer)1000 NvmeBlockIoReadBlocks (
1001   IN  EFI_BLOCK_IO_PROTOCOL   *This,
1002   IN  UINT32                  MediaId,
1003   IN  EFI_LBA                 Lba,
1004   IN  UINTN                   BufferSize,
1005   OUT VOID                    *Buffer
1006   )
1007 {
1008   NVME_DEVICE_PRIVATE_DATA          *Device;
1009   EFI_STATUS                        Status;
1010   EFI_BLOCK_IO_MEDIA                *Media;
1011   UINTN                             BlockSize;
1012   UINTN                             NumberOfBlocks;
1013   UINTN                             IoAlign;
1014   EFI_TPL                           OldTpl;
1015 
1016   //
1017   // Check parameters.
1018   //
1019   if (This == NULL) {
1020     return EFI_INVALID_PARAMETER;
1021   }
1022 
1023   Media = This->Media;
1024 
1025   if (MediaId != Media->MediaId) {
1026     return EFI_MEDIA_CHANGED;
1027   }
1028 
1029   if (Buffer == NULL) {
1030     return EFI_INVALID_PARAMETER;
1031   }
1032 
1033   if (BufferSize == 0) {
1034     return EFI_SUCCESS;
1035   }
1036 
1037   BlockSize = Media->BlockSize;
1038   if ((BufferSize % BlockSize) != 0) {
1039     return EFI_BAD_BUFFER_SIZE;
1040   }
1041 
1042   NumberOfBlocks  = BufferSize / BlockSize;
1043   if ((Lba + NumberOfBlocks - 1) > Media->LastBlock) {
1044     return EFI_INVALID_PARAMETER;
1045   }
1046 
1047   IoAlign = Media->IoAlign;
1048   if (IoAlign > 0 && (((UINTN) Buffer & (IoAlign - 1)) != 0)) {
1049     return EFI_INVALID_PARAMETER;
1050   }
1051 
1052   OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
1053 
1054   Device = NVME_DEVICE_PRIVATE_DATA_FROM_BLOCK_IO (This);
1055 
1056   Status = NvmeRead (Device, Buffer, Lba, NumberOfBlocks);
1057 
1058   gBS->RestoreTPL (OldTpl);
1059   return Status;
1060 }
1061 
1062 /**
1063   Write BufferSize bytes from Lba into Buffer.
1064 
1065   @param  This       Indicates a pointer to the calling context.
1066   @param  MediaId    The media ID that the write request is for.
1067   @param  Lba        The starting logical block address to be written. The caller is
1068                      responsible for writing to only legitimate locations.
1069   @param  BufferSize Size of Buffer, must be a multiple of device block size.
1070   @param  Buffer     A pointer to the source buffer for the data.
1071 
1072   @retval EFI_SUCCESS           The data was written correctly to the device.
1073   @retval EFI_WRITE_PROTECTED   The device can not be written to.
1074   @retval EFI_DEVICE_ERROR      The device reported an error while performing the write.
1075   @retval EFI_NO_MEDIA          There is no media in the device.
1076   @retval EFI_MEDIA_CHNAGED     The MediaId does not matched the current device.
1077   @retval EFI_BAD_BUFFER_SIZE   The Buffer was not a multiple of the block size of the device.
1078   @retval EFI_INVALID_PARAMETER The write request contains LBAs that are not valid,
1079                                 or the buffer is not on proper alignment.
1080 
1081 **/
1082 EFI_STATUS
1083 EFIAPI
NvmeBlockIoWriteBlocks(IN EFI_BLOCK_IO_PROTOCOL * This,IN UINT32 MediaId,IN EFI_LBA Lba,IN UINTN BufferSize,IN VOID * Buffer)1084 NvmeBlockIoWriteBlocks (
1085   IN  EFI_BLOCK_IO_PROTOCOL   *This,
1086   IN  UINT32                  MediaId,
1087   IN  EFI_LBA                 Lba,
1088   IN  UINTN                   BufferSize,
1089   IN  VOID                    *Buffer
1090   )
1091 {
1092   NVME_DEVICE_PRIVATE_DATA          *Device;
1093   EFI_STATUS                        Status;
1094   EFI_BLOCK_IO_MEDIA                *Media;
1095   UINTN                             BlockSize;
1096   UINTN                             NumberOfBlocks;
1097   UINTN                             IoAlign;
1098   EFI_TPL                           OldTpl;
1099 
1100   //
1101   // Check parameters.
1102   //
1103   if (This == NULL) {
1104     return EFI_INVALID_PARAMETER;
1105   }
1106 
1107   Media = This->Media;
1108 
1109   if (MediaId != Media->MediaId) {
1110     return EFI_MEDIA_CHANGED;
1111   }
1112 
1113   if (Buffer == NULL) {
1114     return EFI_INVALID_PARAMETER;
1115   }
1116 
1117   if (BufferSize == 0) {
1118     return EFI_SUCCESS;
1119   }
1120 
1121   BlockSize = Media->BlockSize;
1122   if ((BufferSize % BlockSize) != 0) {
1123     return EFI_BAD_BUFFER_SIZE;
1124   }
1125 
1126   NumberOfBlocks  = BufferSize / BlockSize;
1127   if ((Lba + NumberOfBlocks - 1) > Media->LastBlock) {
1128     return EFI_INVALID_PARAMETER;
1129   }
1130 
1131   IoAlign = Media->IoAlign;
1132   if (IoAlign > 0 && (((UINTN) Buffer & (IoAlign - 1)) != 0)) {
1133     return EFI_INVALID_PARAMETER;
1134   }
1135 
1136   OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
1137 
1138   Device = NVME_DEVICE_PRIVATE_DATA_FROM_BLOCK_IO (This);
1139 
1140   Status = NvmeWrite (Device, Buffer, Lba, NumberOfBlocks);
1141 
1142   gBS->RestoreTPL (OldTpl);
1143 
1144   return Status;
1145 }
1146 
1147 /**
1148   Flush the Block Device.
1149 
1150   @param  This              Indicates a pointer to the calling context.
1151 
1152   @retval EFI_SUCCESS       All outstanding data was written to the device.
1153   @retval EFI_DEVICE_ERROR  The device reported an error while writing back the data.
1154   @retval EFI_NO_MEDIA      There is no media in the device.
1155 
1156 **/
1157 EFI_STATUS
1158 EFIAPI
NvmeBlockIoFlushBlocks(IN EFI_BLOCK_IO_PROTOCOL * This)1159 NvmeBlockIoFlushBlocks (
1160   IN  EFI_BLOCK_IO_PROTOCOL   *This
1161   )
1162 {
1163   NVME_DEVICE_PRIVATE_DATA          *Device;
1164   EFI_STATUS                        Status;
1165   EFI_TPL                           OldTpl;
1166 
1167   //
1168   // Check parameters.
1169   //
1170   if (This == NULL) {
1171     return EFI_INVALID_PARAMETER;
1172   }
1173 
1174   OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
1175 
1176   Device = NVME_DEVICE_PRIVATE_DATA_FROM_BLOCK_IO (This);
1177 
1178   Status = NvmeFlush (Device);
1179 
1180   gBS->RestoreTPL (OldTpl);
1181 
1182   return Status;
1183 }
1184 
1185 /**
1186   Reset the block device hardware.
1187 
1188   @param[in]  This                 Indicates a pointer to the calling context.
1189   @param[in]  ExtendedVerification Indicates that the driver may perform a more
1190                                    exhausive verfication operation of the
1191                                    device during reset.
1192 
1193   @retval EFI_SUCCESS          The device was reset.
1194   @retval EFI_DEVICE_ERROR     The device is not functioning properly and could
1195                                not be reset.
1196 
1197 **/
1198 EFI_STATUS
1199 EFIAPI
NvmeBlockIoResetEx(IN EFI_BLOCK_IO2_PROTOCOL * This,IN BOOLEAN ExtendedVerification)1200 NvmeBlockIoResetEx (
1201   IN EFI_BLOCK_IO2_PROTOCOL  *This,
1202   IN BOOLEAN                 ExtendedVerification
1203   )
1204 {
1205   EFI_STATUS                      Status;
1206   NVME_DEVICE_PRIVATE_DATA        *Device;
1207   NVME_CONTROLLER_PRIVATE_DATA    *Private;
1208   BOOLEAN                         IsEmpty;
1209   EFI_TPL                         OldTpl;
1210 
1211   if (This == NULL) {
1212     return EFI_INVALID_PARAMETER;
1213   }
1214 
1215   Device  = NVME_DEVICE_PRIVATE_DATA_FROM_BLOCK_IO2 (This);
1216   Private = Device->Controller;
1217 
1218   //
1219   // Wait for the asynchronous PassThru queue to become empty.
1220   //
1221   while (TRUE) {
1222     OldTpl  = gBS->RaiseTPL (TPL_NOTIFY);
1223     IsEmpty = IsListEmpty (&Private->AsyncPassThruQueue) &&
1224               IsListEmpty (&Private->UnsubmittedSubtasks);
1225     gBS->RestoreTPL (OldTpl);
1226 
1227     if (IsEmpty) {
1228       break;
1229     }
1230 
1231     gBS->Stall (100);
1232   }
1233 
1234   OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
1235 
1236   Status  = NvmeControllerInit (Private);
1237 
1238   if (EFI_ERROR (Status)) {
1239     Status = EFI_DEVICE_ERROR;
1240   }
1241 
1242   gBS->RestoreTPL (OldTpl);
1243 
1244   return Status;
1245 }
1246 
1247 /**
1248   Read BufferSize bytes from Lba into Buffer.
1249 
1250   This function reads the requested number of blocks from the device. All the
1251   blocks are read, or an error is returned.
1252   If EFI_DEVICE_ERROR, EFI_NO_MEDIA,_or EFI_MEDIA_CHANGED is returned and
1253   non-blocking I/O is being used, the Event associated with this request will
1254   not be signaled.
1255 
1256   @param[in]       This       Indicates a pointer to the calling context.
1257   @param[in]       MediaId    Id of the media, changes every time the media is
1258                               replaced.
1259   @param[in]       Lba        The starting Logical Block Address to read from.
1260   @param[in, out]  Token      A pointer to the token associated with the
1261                               transaction.
1262   @param[in]       BufferSize Size of Buffer, must be a multiple of device
1263                               block size.
1264   @param[out]      Buffer     A pointer to the destination buffer for the data.
1265                               The caller is responsible for either having
1266                               implicit or explicit ownership of the buffer.
1267 
1268   @retval EFI_SUCCESS           The read request was queued if Token->Event is
1269                                 not NULL.The data was read correctly from the
1270                                 device if the Token->Event is NULL.
1271   @retval EFI_DEVICE_ERROR      The device reported an error while performing
1272                                 the read.
1273   @retval EFI_NO_MEDIA          There is no media in the device.
1274   @retval EFI_MEDIA_CHANGED     The MediaId is not for the current media.
1275   @retval EFI_BAD_BUFFER_SIZE   The BufferSize parameter is not a multiple of
1276                                 the intrinsic block size of the device.
1277   @retval EFI_INVALID_PARAMETER The read request contains LBAs that are not
1278                                 valid, or the buffer is not on proper
1279                                 alignment.
1280   @retval EFI_OUT_OF_RESOURCES  The request could not be completed due to a
1281                                 lack of resources.
1282 
1283 **/
1284 EFI_STATUS
1285 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)1286 NvmeBlockIoReadBlocksEx (
1287   IN     EFI_BLOCK_IO2_PROTOCOL *This,
1288   IN     UINT32                 MediaId,
1289   IN     EFI_LBA                Lba,
1290   IN OUT EFI_BLOCK_IO2_TOKEN    *Token,
1291   IN     UINTN                  BufferSize,
1292      OUT VOID                  *Buffer
1293   )
1294 {
1295   NVME_DEVICE_PRIVATE_DATA        *Device;
1296   EFI_STATUS                      Status;
1297   EFI_BLOCK_IO_MEDIA              *Media;
1298   UINTN                           BlockSize;
1299   UINTN                           NumberOfBlocks;
1300   UINTN                           IoAlign;
1301   EFI_TPL                         OldTpl;
1302 
1303   //
1304   // Check parameters.
1305   //
1306   if (This == NULL) {
1307     return EFI_INVALID_PARAMETER;
1308   }
1309 
1310   Media = This->Media;
1311 
1312   if (MediaId != Media->MediaId) {
1313     return EFI_MEDIA_CHANGED;
1314   }
1315 
1316   if (Buffer == NULL) {
1317     return EFI_INVALID_PARAMETER;
1318   }
1319 
1320   if (BufferSize == 0) {
1321     if ((Token != NULL) && (Token->Event != NULL)) {
1322       Token->TransactionStatus = EFI_SUCCESS;
1323       gBS->SignalEvent (Token->Event);
1324     }
1325     return EFI_SUCCESS;
1326   }
1327 
1328   BlockSize = Media->BlockSize;
1329   if ((BufferSize % BlockSize) != 0) {
1330     return EFI_BAD_BUFFER_SIZE;
1331   }
1332 
1333   NumberOfBlocks  = BufferSize / BlockSize;
1334   if ((Lba + NumberOfBlocks - 1) > Media->LastBlock) {
1335     return EFI_INVALID_PARAMETER;
1336   }
1337 
1338   IoAlign = Media->IoAlign;
1339   if (IoAlign > 0 && (((UINTN) Buffer & (IoAlign - 1)) != 0)) {
1340     return EFI_INVALID_PARAMETER;
1341   }
1342 
1343   OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
1344 
1345   Device = NVME_DEVICE_PRIVATE_DATA_FROM_BLOCK_IO2 (This);
1346 
1347   if ((Token != NULL) && (Token->Event != NULL)) {
1348     Token->TransactionStatus = EFI_SUCCESS;
1349     Status = NvmeAsyncRead (Device, Buffer, Lba, NumberOfBlocks, Token);
1350   } else {
1351     Status = NvmeRead (Device, Buffer, Lba, NumberOfBlocks);
1352   }
1353 
1354   gBS->RestoreTPL (OldTpl);
1355   return Status;
1356 }
1357 
1358 /**
1359   Write BufferSize bytes from Lba into Buffer.
1360 
1361   This function writes the requested number of blocks to the device. All blocks
1362   are written, or an error is returned.If EFI_DEVICE_ERROR, EFI_NO_MEDIA,
1363   EFI_WRITE_PROTECTED or EFI_MEDIA_CHANGED is returned and non-blocking I/O is
1364   being used, the Event associated with this request will not be signaled.
1365 
1366   @param[in]       This       Indicates a pointer to the calling context.
1367   @param[in]       MediaId    The media ID that the write request is for.
1368   @param[in]       Lba        The starting logical block address to be written.
1369                               The caller is responsible for writing to only
1370                               legitimate locations.
1371   @param[in, out]  Token      A pointer to the token associated with the
1372                               transaction.
1373   @param[in]       BufferSize Size of Buffer, must be a multiple of device
1374                               block size.
1375   @param[in]       Buffer     A pointer to the source buffer for the data.
1376 
1377   @retval EFI_SUCCESS           The write request was queued if Event is not
1378                                 NULL.
1379                                 The data was written correctly to the device if
1380                                 the Event is NULL.
1381   @retval EFI_WRITE_PROTECTED   The device can not be written to.
1382   @retval EFI_NO_MEDIA          There is no media in the device.
1383   @retval EFI_MEDIA_CHNAGED     The MediaId does not matched the current
1384                                 device.
1385   @retval EFI_DEVICE_ERROR      The device reported an error while performing
1386                                 the write.
1387   @retval EFI_BAD_BUFFER_SIZE   The Buffer was not a multiple of the block size
1388                                 of the device.
1389   @retval EFI_INVALID_PARAMETER The write request contains LBAs that are not
1390                                 valid, or the buffer is not on proper
1391                                 alignment.
1392   @retval EFI_OUT_OF_RESOURCES  The request could not be completed due to a
1393                                 lack of resources.
1394 
1395 **/
1396 EFI_STATUS
1397 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)1398 NvmeBlockIoWriteBlocksEx (
1399   IN     EFI_BLOCK_IO2_PROTOCOL  *This,
1400   IN     UINT32                 MediaId,
1401   IN     EFI_LBA                Lba,
1402   IN OUT EFI_BLOCK_IO2_TOKEN    *Token,
1403   IN     UINTN                  BufferSize,
1404   IN     VOID                   *Buffer
1405   )
1406 {
1407   NVME_DEVICE_PRIVATE_DATA        *Device;
1408   EFI_STATUS                      Status;
1409   EFI_BLOCK_IO_MEDIA              *Media;
1410   UINTN                           BlockSize;
1411   UINTN                           NumberOfBlocks;
1412   UINTN                           IoAlign;
1413   EFI_TPL                         OldTpl;
1414 
1415   //
1416   // Check parameters.
1417   //
1418   if (This == NULL) {
1419     return EFI_INVALID_PARAMETER;
1420   }
1421 
1422   Media = This->Media;
1423 
1424   if (MediaId != Media->MediaId) {
1425     return EFI_MEDIA_CHANGED;
1426   }
1427 
1428   if (Buffer == NULL) {
1429     return EFI_INVALID_PARAMETER;
1430   }
1431 
1432   if (BufferSize == 0) {
1433     if ((Token != NULL) && (Token->Event != NULL)) {
1434       Token->TransactionStatus = EFI_SUCCESS;
1435       gBS->SignalEvent (Token->Event);
1436     }
1437     return EFI_SUCCESS;
1438   }
1439 
1440   BlockSize = Media->BlockSize;
1441   if ((BufferSize % BlockSize) != 0) {
1442     return EFI_BAD_BUFFER_SIZE;
1443   }
1444 
1445   NumberOfBlocks  = BufferSize / BlockSize;
1446   if ((Lba + NumberOfBlocks - 1) > Media->LastBlock) {
1447     return EFI_INVALID_PARAMETER;
1448   }
1449 
1450   IoAlign = Media->IoAlign;
1451   if (IoAlign > 0 && (((UINTN) Buffer & (IoAlign - 1)) != 0)) {
1452     return EFI_INVALID_PARAMETER;
1453   }
1454 
1455   OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
1456 
1457   Device = NVME_DEVICE_PRIVATE_DATA_FROM_BLOCK_IO2 (This);
1458 
1459   if ((Token != NULL) && (Token->Event != NULL)) {
1460     Token->TransactionStatus = EFI_SUCCESS;
1461     Status = NvmeAsyncWrite (Device, Buffer, Lba, NumberOfBlocks, Token);
1462   } else {
1463     Status = NvmeWrite (Device, Buffer, Lba, NumberOfBlocks);
1464   }
1465 
1466   gBS->RestoreTPL (OldTpl);
1467   return Status;
1468 }
1469 
1470 /**
1471   Flush the Block Device.
1472 
1473   If EFI_DEVICE_ERROR, EFI_NO_MEDIA,_EFI_WRITE_PROTECTED or EFI_MEDIA_CHANGED
1474   is returned and non-blocking I/O is being used, the Event associated with
1475   this request will not be signaled.
1476 
1477   @param[in]      This     Indicates a pointer to the calling context.
1478   @param[in,out]  Token    A pointer to the token associated with the
1479                            transaction.
1480 
1481   @retval EFI_SUCCESS          The flush request was queued if Event is not
1482                                NULL.
1483                                All outstanding data was written correctly to
1484                                the device if the Event is NULL.
1485   @retval EFI_DEVICE_ERROR     The device reported an error while writting back
1486                                the data.
1487   @retval EFI_WRITE_PROTECTED  The device cannot be written to.
1488   @retval EFI_NO_MEDIA         There is no media in the device.
1489   @retval EFI_MEDIA_CHANGED    The MediaId is not for the current media.
1490   @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack
1491                                of resources.
1492 
1493 **/
1494 EFI_STATUS
1495 EFIAPI
NvmeBlockIoFlushBlocksEx(IN EFI_BLOCK_IO2_PROTOCOL * This,IN OUT EFI_BLOCK_IO2_TOKEN * Token)1496 NvmeBlockIoFlushBlocksEx (
1497   IN     EFI_BLOCK_IO2_PROTOCOL   *This,
1498   IN OUT EFI_BLOCK_IO2_TOKEN      *Token
1499   )
1500 {
1501   NVME_DEVICE_PRIVATE_DATA        *Device;
1502   BOOLEAN                         IsEmpty;
1503   EFI_TPL                         OldTpl;
1504 
1505   //
1506   // Check parameters.
1507   //
1508   if (This == NULL) {
1509     return EFI_INVALID_PARAMETER;
1510   }
1511 
1512   Device = NVME_DEVICE_PRIVATE_DATA_FROM_BLOCK_IO2 (This);
1513 
1514   //
1515   // Wait for the asynchronous I/O queue to become empty.
1516   //
1517   while (TRUE) {
1518     OldTpl  = gBS->RaiseTPL (TPL_NOTIFY);
1519     IsEmpty = IsListEmpty (&Device->AsyncQueue);
1520     gBS->RestoreTPL (OldTpl);
1521 
1522     if (IsEmpty) {
1523       break;
1524     }
1525 
1526     gBS->Stall (100);
1527   }
1528 
1529   //
1530   // Signal caller event
1531   //
1532   if ((Token != NULL) && (Token->Event != NULL)) {
1533     Token->TransactionStatus = EFI_SUCCESS;
1534     gBS->SignalEvent (Token->Event);
1535   }
1536 
1537   return EFI_SUCCESS;
1538 }
1539 
1540 /**
1541   Trust transfer data from/to NVMe device.
1542 
1543   This function performs one NVMe transaction to do a trust transfer from/to NVMe device.
1544 
1545   @param  Private                      The pointer to the NVME_CONTROLLER_PRIVATE_DATA data structure.
1546   @param  Buffer                       The pointer to the current transaction buffer.
1547   @param  SecurityProtocolId           The value of the "Security Protocol" parameter of
1548                                        the security protocol command to be sent.
1549   @param  SecurityProtocolSpecificData The value of the "Security Protocol Specific" parameter
1550                                        of the security protocol command to be sent.
1551   @param  TransferLength               The block number or sector count of the transfer.
1552   @param  IsTrustSend                  Indicates whether it is a trust send operation or not.
1553   @param  Timeout                      The timeout, in 100ns units, to use for the execution
1554                                        of the security protocol command. A Timeout value of 0
1555                                        means that this function will wait indefinitely for the
1556                                        security protocol command to execute. If Timeout is greater
1557                                        than zero, then this function will return EFI_TIMEOUT
1558                                        if the time required to execute the receive data command
1559                                        is greater than Timeout.
1560   @param  TransferLengthOut            A pointer to a buffer to store the size in bytes of the data
1561                                        written to the buffer. Ignore it when IsTrustSend is TRUE.
1562 
1563   @retval EFI_SUCCESS       The data transfer is complete successfully.
1564   @return others            Some error occurs when transferring data.
1565 
1566 **/
1567 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)1568 TrustTransferNvmeDevice (
1569   IN OUT NVME_CONTROLLER_PRIVATE_DATA      *Private,
1570   IN OUT VOID                              *Buffer,
1571   IN UINT8                                 SecurityProtocolId,
1572   IN UINT16                                SecurityProtocolSpecificData,
1573   IN UINTN                                 TransferLength,
1574   IN BOOLEAN                               IsTrustSend,
1575   IN UINT64                                Timeout,
1576   OUT UINTN                                *TransferLengthOut
1577   )
1578 {
1579   EFI_NVM_EXPRESS_PASS_THRU_COMMAND_PACKET CommandPacket;
1580   EFI_NVM_EXPRESS_COMMAND                  Command;
1581   EFI_NVM_EXPRESS_COMPLETION               Completion;
1582   EFI_STATUS                               Status;
1583   UINT16                                   SpecificData;
1584 
1585   ZeroMem (&CommandPacket, sizeof (EFI_NVM_EXPRESS_PASS_THRU_COMMAND_PACKET));
1586   ZeroMem (&Command, sizeof (EFI_NVM_EXPRESS_COMMAND));
1587   ZeroMem (&Completion, sizeof (EFI_NVM_EXPRESS_COMPLETION));
1588 
1589   CommandPacket.NvmeCmd        = &Command;
1590   CommandPacket.NvmeCompletion = &Completion;
1591 
1592   //
1593   // Change Endianness of SecurityProtocolSpecificData
1594   //
1595   SpecificData = (((SecurityProtocolSpecificData << 8) & 0xFF00) | (SecurityProtocolSpecificData >> 8));
1596 
1597   if (IsTrustSend) {
1598     Command.Cdw0.Opcode          = NVME_ADMIN_SECURITY_SEND_CMD;
1599     CommandPacket.TransferBuffer = Buffer;
1600     CommandPacket.TransferLength = (UINT32)TransferLength;
1601     CommandPacket.NvmeCmd->Cdw10 = (UINT32)((SecurityProtocolId << 24) | (SpecificData << 8));
1602     CommandPacket.NvmeCmd->Cdw11 = (UINT32)TransferLength;
1603   } else {
1604     Command.Cdw0.Opcode          = NVME_ADMIN_SECURITY_RECEIVE_CMD;
1605     CommandPacket.TransferBuffer = Buffer;
1606     CommandPacket.TransferLength = (UINT32)TransferLength;
1607     CommandPacket.NvmeCmd->Cdw10 = (UINT32)((SecurityProtocolId << 24) | (SpecificData << 8));
1608     CommandPacket.NvmeCmd->Cdw11 = (UINT32)TransferLength;
1609   }
1610 
1611   CommandPacket.NvmeCmd->Flags = CDW10_VALID | CDW11_VALID;
1612   CommandPacket.NvmeCmd->Nsid  = NVME_CONTROLLER_ID;
1613   CommandPacket.CommandTimeout = Timeout;
1614   CommandPacket.QueueType      = NVME_ADMIN_QUEUE;
1615 
1616   Status = Private->Passthru.PassThru (
1617                                &Private->Passthru,
1618                                NVME_CONTROLLER_ID,
1619                                &CommandPacket,
1620                                NULL
1621                                );
1622 
1623   if (!IsTrustSend) {
1624     if (EFI_ERROR (Status))  {
1625       *TransferLengthOut = 0;
1626     } else {
1627       *TransferLengthOut = (UINTN) TransferLength;
1628     }
1629   }
1630 
1631   return Status;
1632 }
1633 
1634 /**
1635   Send a security protocol command to a device that receives data and/or the result
1636   of one or more commands sent by SendData.
1637 
1638   The ReceiveData function sends a security protocol command to the given MediaId.
1639   The security protocol command sent is defined by SecurityProtocolId and contains
1640   the security protocol specific data SecurityProtocolSpecificData. The function
1641   returns the data from the security protocol command in PayloadBuffer.
1642 
1643   For devices supporting the SCSI command set, the security protocol command is sent
1644   using the SECURITY PROTOCOL IN command defined in SPC-4.
1645 
1646   For devices supporting the ATA command set, the security protocol command is sent
1647   using one of the TRUSTED RECEIVE commands defined in ATA8-ACS if PayloadBufferSize
1648   is non-zero.
1649 
1650   If the PayloadBufferSize is zero, the security protocol command is sent using the
1651   Trusted Non-Data command defined in ATA8-ACS.
1652 
1653   If PayloadBufferSize is too small to store the available data from the security
1654   protocol command, the function shall copy PayloadBufferSize bytes into the
1655   PayloadBuffer and return EFI_WARN_BUFFER_TOO_SMALL.
1656 
1657   If PayloadBuffer or PayloadTransferSize is NULL and PayloadBufferSize is non-zero,
1658   the function shall return EFI_INVALID_PARAMETER.
1659 
1660   If the given MediaId does not support security protocol commands, the function shall
1661   return EFI_UNSUPPORTED. If there is no media in the device, the function returns
1662   EFI_NO_MEDIA. If the MediaId is not the ID for the current media in the device,
1663   the function returns EFI_MEDIA_CHANGED.
1664 
1665   If the security protocol fails to complete within the Timeout period, the function
1666   shall return EFI_TIMEOUT.
1667 
1668   If the security protocol command completes without an error, the function shall
1669   return EFI_SUCCESS. If the security protocol command completes with an error, the
1670   function shall return EFI_DEVICE_ERROR.
1671 
1672   @param  This                         Indicates a pointer to the calling context.
1673   @param  MediaId                      ID of the medium to receive data from.
1674   @param  Timeout                      The timeout, in 100ns units, to use for the execution
1675                                        of the security protocol command. A Timeout value of 0
1676                                        means that this function will wait indefinitely for the
1677                                        security protocol command to execute. If Timeout is greater
1678                                        than zero, then this function will return EFI_TIMEOUT
1679                                        if the time required to execute the receive data command
1680                                        is greater than Timeout.
1681   @param  SecurityProtocolId           The value of the "Security Protocol" parameter of
1682                                        the security protocol command to be sent.
1683   @param  SecurityProtocolSpecificData The value of the "Security Protocol Specific" parameter
1684                                        of the security protocol command to be sent.
1685   @param  PayloadBufferSize            Size in bytes of the payload data buffer.
1686   @param  PayloadBuffer                A pointer to a destination buffer to store the security
1687                                        protocol command specific payload data for the security
1688                                        protocol command. The caller is responsible for having
1689                                        either implicit or explicit ownership of the buffer.
1690   @param  PayloadTransferSize          A pointer to a buffer to store the size in bytes of the
1691                                        data written to the payload data buffer.
1692 
1693   @retval EFI_SUCCESS                  The security protocol command completed successfully.
1694   @retval EFI_WARN_BUFFER_TOO_SMALL    The PayloadBufferSize was too small to store the available
1695                                        data from the device. The PayloadBuffer contains the truncated data.
1696   @retval EFI_UNSUPPORTED              The given MediaId does not support security protocol commands.
1697   @retval EFI_DEVICE_ERROR             The security protocol command completed with an error.
1698   @retval EFI_NO_MEDIA                 There is no media in the device.
1699   @retval EFI_MEDIA_CHANGED            The MediaId is not for the current media.
1700   @retval EFI_INVALID_PARAMETER        The PayloadBuffer or PayloadTransferSize is NULL and
1701                                        PayloadBufferSize is non-zero.
1702   @retval EFI_TIMEOUT                  A timeout occurred while waiting for the security
1703                                        protocol command to execute.
1704 
1705 **/
1706 EFI_STATUS
1707 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)1708 NvmeStorageSecurityReceiveData (
1709   IN  EFI_STORAGE_SECURITY_COMMAND_PROTOCOL    *This,
1710   IN  UINT32                                   MediaId,
1711   IN  UINT64                                   Timeout,
1712   IN  UINT8                                    SecurityProtocolId,
1713   IN  UINT16                                   SecurityProtocolSpecificData,
1714   IN  UINTN                                    PayloadBufferSize,
1715   OUT VOID                                     *PayloadBuffer,
1716   OUT UINTN                                    *PayloadTransferSize
1717   )
1718 {
1719   EFI_STATUS                       Status;
1720   NVME_DEVICE_PRIVATE_DATA         *Device;
1721 
1722   Status  = EFI_SUCCESS;
1723 
1724   if ((PayloadBuffer == NULL) || (PayloadTransferSize == NULL) || (PayloadBufferSize == 0)) {
1725     return EFI_INVALID_PARAMETER;
1726   }
1727 
1728   Device = NVME_DEVICE_PRIVATE_DATA_FROM_STORAGE_SECURITY (This);
1729 
1730   if (MediaId != Device->BlockIo.Media->MediaId) {
1731     return EFI_MEDIA_CHANGED;
1732   }
1733 
1734   if (!Device->BlockIo.Media->MediaPresent) {
1735     return EFI_NO_MEDIA;
1736   }
1737 
1738   Status = TrustTransferNvmeDevice (
1739              Device->Controller,
1740              PayloadBuffer,
1741              SecurityProtocolId,
1742              SecurityProtocolSpecificData,
1743              PayloadBufferSize,
1744              FALSE,
1745              Timeout,
1746              PayloadTransferSize
1747              );
1748 
1749   return Status;
1750 }
1751 
1752 /**
1753   Send a security protocol command to a device.
1754 
1755   The SendData function sends a security protocol command containing the payload
1756   PayloadBuffer to the given MediaId. The security protocol command sent is
1757   defined by SecurityProtocolId and contains the security protocol specific data
1758   SecurityProtocolSpecificData. If the underlying protocol command requires a
1759   specific padding for the command payload, the SendData function shall add padding
1760   bytes to the command payload to satisfy the padding requirements.
1761 
1762   For devices supporting the SCSI command set, the security protocol command is sent
1763   using the SECURITY PROTOCOL OUT command defined in SPC-4.
1764 
1765   For devices supporting the ATA command set, the security protocol command is sent
1766   using one of the TRUSTED SEND commands defined in ATA8-ACS if PayloadBufferSize
1767   is non-zero. If the PayloadBufferSize is zero, the security protocol command is
1768   sent using the Trusted Non-Data command defined in ATA8-ACS.
1769 
1770   If PayloadBuffer is NULL and PayloadBufferSize is non-zero, the function shall
1771   return EFI_INVALID_PARAMETER.
1772 
1773   If the given MediaId does not support security protocol commands, the function
1774   shall return EFI_UNSUPPORTED. If there is no media in the device, the function
1775   returns EFI_NO_MEDIA. If the MediaId is not the ID for the current media in the
1776   device, the function returns EFI_MEDIA_CHANGED.
1777 
1778   If the security protocol fails to complete within the Timeout period, the function
1779   shall return EFI_TIMEOUT.
1780 
1781   If the security protocol command completes without an error, the function shall return
1782   EFI_SUCCESS. If the security protocol command completes with an error, the function
1783   shall return EFI_DEVICE_ERROR.
1784 
1785   @param  This                         Indicates a pointer to the calling context.
1786   @param  MediaId                      ID of the medium to receive data from.
1787   @param  Timeout                      The timeout, in 100ns units, to use for the execution
1788                                        of the security protocol command. A Timeout value of 0
1789                                        means that this function will wait indefinitely for the
1790                                        security protocol command to execute. If Timeout is greater
1791                                        than zero, then this function will return EFI_TIMEOUT
1792                                        if the time required to execute the send data command
1793                                        is greater than Timeout.
1794   @param  SecurityProtocolId           The value of the "Security Protocol" parameter of
1795                                        the security protocol command to be sent.
1796   @param  SecurityProtocolSpecificData The value of the "Security Protocol Specific" parameter
1797                                        of the security protocol command to be sent.
1798   @param  PayloadBufferSize            Size in bytes of the payload data buffer.
1799   @param  PayloadBuffer                A pointer to a destination buffer to store the security
1800                                        protocol command specific payload data for the security
1801                                        protocol command.
1802 
1803   @retval EFI_SUCCESS                  The security protocol command completed successfully.
1804   @retval EFI_UNSUPPORTED              The given MediaId does not support security protocol commands.
1805   @retval EFI_DEVICE_ERROR             The security protocol command completed with an error.
1806   @retval EFI_NO_MEDIA                 There is no media in the device.
1807   @retval EFI_MEDIA_CHANGED            The MediaId is not for the current media.
1808   @retval EFI_INVALID_PARAMETER        The PayloadBuffer is NULL and PayloadBufferSize is non-zero.
1809   @retval EFI_TIMEOUT                  A timeout occurred while waiting for the security
1810                                        protocol command to execute.
1811 
1812 **/
1813 EFI_STATUS
1814 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)1815 NvmeStorageSecuritySendData (
1816   IN EFI_STORAGE_SECURITY_COMMAND_PROTOCOL    *This,
1817   IN UINT32                                   MediaId,
1818   IN UINT64                                   Timeout,
1819   IN UINT8                                    SecurityProtocolId,
1820   IN UINT16                                   SecurityProtocolSpecificData,
1821   IN UINTN                                    PayloadBufferSize,
1822   IN VOID                                     *PayloadBuffer
1823   )
1824 {
1825   EFI_STATUS                       Status;
1826   NVME_DEVICE_PRIVATE_DATA         *Device;
1827 
1828   Status  = EFI_SUCCESS;
1829 
1830   if ((PayloadBuffer == NULL) && (PayloadBufferSize != 0)) {
1831     return EFI_INVALID_PARAMETER;
1832   }
1833 
1834   Device = NVME_DEVICE_PRIVATE_DATA_FROM_STORAGE_SECURITY (This);
1835 
1836   if (MediaId != Device->BlockIo.Media->MediaId) {
1837     return EFI_MEDIA_CHANGED;
1838   }
1839 
1840   if (!Device->BlockIo.Media->MediaPresent) {
1841     return EFI_NO_MEDIA;
1842   }
1843 
1844   Status = TrustTransferNvmeDevice (
1845              Device->Controller,
1846              PayloadBuffer,
1847              SecurityProtocolId,
1848              SecurityProtocolSpecificData,
1849              PayloadBufferSize,
1850              TRUE,
1851              Timeout,
1852              NULL
1853              );
1854 
1855   return Status;
1856 }
1857 
1858 
1859 
1860 
1861