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