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