38
38
#define SIZE_1GB 0x40000000
39
39
#endif
40
40
41
+ #ifndef SECTOR_SHIFT
42
+ #define SECTOR_SHIFT 9
43
+ #endif
44
+
41
45
#define EFI_BLOCK_IO_PROTOCOL_REVISION3 0x00020031
42
46
43
47
/**
@@ -279,22 +283,27 @@ SynchronousRequest (
279
283
IN EFI_LBA Lba ,
280
284
IN UINTN BufferSize ,
281
285
IN OUT volatile VOID * Buffer ,
282
- IN BOOLEAN RequestIsWrite
286
+ IN BOOLEAN RequestIsWrite ,
287
+ IN UINT32 RequestType
283
288
)
284
289
{
285
290
UINT32 BlockSize ;
286
291
volatile VIRTIO_BLK_REQ Request ;
292
+ VIRTIO_DISCARD_RANGE EraseRange ;
287
293
volatile UINT8 * HostStatus ;
288
294
VOID * HostStatusBuffer ;
289
295
DESC_INDICES Indices ;
290
296
VOID * RequestMapping ;
291
297
VOID * StatusMapping ;
292
298
VOID * BufferMapping ;
299
+ VOID * EraseRangeMapping ;
293
300
EFI_PHYSICAL_ADDRESS BufferDeviceAddress ;
294
301
EFI_PHYSICAL_ADDRESS HostStatusDeviceAddress ;
295
302
EFI_PHYSICAL_ADDRESS RequestDeviceAddress ;
303
+ EFI_PHYSICAL_ADDRESS EraseRangeDeviceAddress ;
296
304
EFI_STATUS Status ;
297
305
EFI_STATUS UnmapStatus ;
306
+ UINT32 Flags = 0 ;
298
307
299
308
BlockSize = Dev -> BlockIoMedia .BlockSize ;
300
309
@@ -313,12 +322,23 @@ SynchronousRequest (
313
322
// Prepare virtio-blk request header, setting zero size for flush.
314
323
// IO Priority is homogeneously 0.
315
324
//
316
- Request .Type = RequestIsWrite ?
317
- (BufferSize == 0 ? VIRTIO_BLK_T_FLUSH : VIRTIO_BLK_T_OUT ) :
318
- VIRTIO_BLK_T_IN ;
319
325
Request .IoPrio = 0 ;
320
326
Request .Sector = MultU64x32 (Lba , BlockSize / 512 );
321
327
328
+ if (RequestType != VIRTIO_BLK_T_DISCARD ) {
329
+ Request .Type = RequestIsWrite ?
330
+ (BufferSize == 0 ? VIRTIO_BLK_T_FLUSH : VIRTIO_BLK_T_OUT ) :
331
+ VIRTIO_BLK_T_IN ;
332
+ }
333
+ else {
334
+ Request .Type = RequestType ;
335
+
336
+ Flags |= VIRTIO_BLK_WRITE_ZEROES_FLAG_UNMAP ;
337
+ EraseRange .Sector = Request .Sector ;
338
+ EraseRange .num_sectors = BufferSize >> SECTOR_SHIFT ;;
339
+ EraseRange .flags = Flags ;
340
+ }
341
+
322
342
//
323
343
// Host status is bi-directional (we preset with a value and expect the
324
344
// device to update it). Allocate a host status buffer which can be mapped
@@ -356,20 +376,30 @@ SynchronousRequest (
356
376
// Map data buffer
357
377
//
358
378
if (BufferSize > 0 ) {
359
- Status = VirtioMapAllBytesInSharedBuffer (
360
- Dev -> VirtIo ,
361
- (RequestIsWrite ?
362
- VirtioOperationBusMasterRead :
363
- VirtioOperationBusMasterWrite ),
364
- (VOID * ) Buffer ,
365
- BufferSize ,
366
- & BufferDeviceAddress ,
367
- & BufferMapping
368
- );
369
- if (EFI_ERROR (Status )) {
370
- Status = EFI_DEVICE_ERROR ;
371
- goto UnmapRequestBuffer ;
372
- }
379
+ if (RequestType == VIRTIO_BLK_T_DISCARD )
380
+ Status = VirtioMapAllBytesInSharedBuffer (
381
+ Dev -> VirtIo ,
382
+ VirtioOperationBusMasterRead ,
383
+ (VOID * ) & EraseRange ,
384
+ sizeof (EraseRange ),
385
+ & EraseRangeDeviceAddress ,
386
+ & EraseRangeMapping
387
+ );
388
+ else
389
+ Status = VirtioMapAllBytesInSharedBuffer (
390
+ Dev -> VirtIo ,
391
+ (RequestIsWrite ?
392
+ VirtioOperationBusMasterRead :
393
+ VirtioOperationBusMasterWrite ),
394
+ (VOID * ) Buffer ,
395
+ BufferSize ,
396
+ & BufferDeviceAddress ,
397
+ & BufferMapping
398
+ );
399
+ if (EFI_ERROR (Status )) {
400
+ Status = EFI_DEVICE_ERROR ;
401
+ goto UnmapRequestBuffer ;
402
+ }
373
403
}
374
404
375
405
//
@@ -417,26 +447,36 @@ SynchronousRequest (
417
447
// data buffer for read/write in second desc
418
448
//
419
449
if (BufferSize > 0 ) {
420
- //
421
- // From virtio-0.9.5, 2.3.2 Descriptor Table:
422
- // "no descriptor chain may be more than 2^32 bytes long in total".
423
- //
424
- // The predicate is ensured by the call contract above (for flush), or
425
- // VerifyReadWriteRequest() (for read/write). It also implies that
426
- // converting BufferSize to UINT32 will not truncate it.
427
- //
428
- ASSERT (BufferSize <= SIZE_1GB );
450
+ if (RequestType == VIRTIO_BLK_T_DISCARD )
451
+ VirtioAppendDesc (
452
+ & Dev -> Ring ,
453
+ EraseRangeDeviceAddress ,
454
+ sizeof (EraseRange ),
455
+ VRING_DESC_F_NEXT ,
456
+ & Indices
457
+ );
458
+ else {
459
+ //
460
+ // From virtio-0.9.5, 2.3.2 Descriptor Table:
461
+ // "no descriptor chain may be more than 2^32 bytes long in total".
462
+ //
463
+ // The predicate is ensured by the call contract above (for flush), or
464
+ // VerifyReadWriteRequest() (for read/write). It also implies that
465
+ // converting BufferSize to UINT32 will not truncate it.
466
+ //
467
+ ASSERT (BufferSize <= SIZE_1GB );
429
468
430
- //
431
- // VRING_DESC_F_WRITE is interpreted from the host's point of view.
432
- //
433
- VirtioAppendDesc (
434
- & Dev -> Ring ,
435
- BufferDeviceAddress ,
436
- (UINT32 ) BufferSize ,
437
- VRING_DESC_F_NEXT | (RequestIsWrite ? 0 : VRING_DESC_F_WRITE ),
438
- & Indices
439
- );
469
+ //
470
+ // VRING_DESC_F_WRITE is interpreted from the host's point of view.
471
+ //
472
+ VirtioAppendDesc (
473
+ & Dev -> Ring ,
474
+ BufferDeviceAddress ,
475
+ (UINT32 ) BufferSize ,
476
+ VRING_DESC_F_NEXT | (RequestIsWrite ? 0 : VRING_DESC_F_WRITE ),
477
+ & Indices
478
+ );
479
+ }
440
480
}
441
481
442
482
//
@@ -469,13 +509,16 @@ SynchronousRequest (
469
509
470
510
UnmapDataBuffer :
471
511
if (BufferSize > 0 ) {
472
- UnmapStatus = Dev -> VirtIo -> UnmapSharedBuffer (Dev -> VirtIo , BufferMapping );
473
- if (EFI_ERROR (UnmapStatus ) && !RequestIsWrite && !EFI_ERROR (Status )) {
474
- //
475
- // Data from the bus master may not reach the caller; fail the request.
476
- //
477
- Status = EFI_DEVICE_ERROR ;
478
- }
512
+ if (RequestType == VIRTIO_BLK_T_DISCARD )
513
+ UnmapStatus = Dev -> VirtIo -> UnmapSharedBuffer (Dev -> VirtIo , EraseRangeMapping );
514
+ else
515
+ UnmapStatus = Dev -> VirtIo -> UnmapSharedBuffer (Dev -> VirtIo , BufferMapping );
516
+ if (EFI_ERROR (UnmapStatus ) && !RequestIsWrite && !EFI_ERROR (Status )) {
517
+ //
518
+ // Data from the bus master may not reach the caller; fail the request.
519
+ //
520
+ Status = EFI_DEVICE_ERROR ;
521
+ }
479
522
}
480
523
481
524
UnmapRequestBuffer :
@@ -518,7 +561,8 @@ VirtioBlkReadBlocksInternal (
518
561
Lba ,
519
562
BufferSize ,
520
563
Buffer ,
521
- FALSE // RequestIsRead
564
+ FALSE, // RequestIsRead
565
+ VIRTIO_BLK_T_INVALID
522
566
);
523
567
}
524
568
@@ -633,7 +677,8 @@ VirtioBlkWriteBlocksInternal (
633
677
Lba ,
634
678
BufferSize ,
635
679
Buffer ,
636
- TRUE // RequestIsWrite
680
+ TRUE, // RequestIsWrite
681
+ VIRTIO_BLK_T_INVALID
637
682
);
638
683
639
684
return Status ;
@@ -718,6 +763,49 @@ VirtioBlkWriteBlocks (
718
763
return Status ;
719
764
}
720
765
766
+ /**
767
+
768
+ EraseBlocks() operation for virtio-blk.
769
+
770
+ RequestType that pass to SynchronousRequest() is VIRTIO_BLK_T_DISCARD.
771
+
772
+ **/
773
+
774
+ EFI_STATUS
775
+ EFIAPI
776
+ VirtioBlkEraseBlocks (
777
+ IN EFI_ERASE_BLOCK_PROTOCOL * This ,
778
+ IN __attribute__((unused )) UINT32 MediaId ,
779
+ IN EFI_LBA Lba ,
780
+ IN OUT __attribute__((unused )) EFI_ERASE_BLOCK_TOKEN * Token ,
781
+ IN UINTN Size
782
+ )
783
+ {
784
+ EFI_STATUS Status ;
785
+ VBLK_DEV * Dev ;
786
+ UINT64 Features ;
787
+
788
+ Dev = VIRTIO_BLK_FROM_ERASE_BLOCK (This );
789
+
790
+ Status = Dev -> VirtIo -> GetDeviceFeatures (Dev -> VirtIo , & Features );
791
+ if (EFI_ERROR (Status )) {
792
+ return Status ;
793
+ }
794
+
795
+ if (Features & VIRTIO_BLK_F_DISCARD )
796
+ Status = SynchronousRequest (
797
+ Dev ,
798
+ Lba ,
799
+ Size ,
800
+ NULL ,
801
+ TRUE, // RequestIsWrite
802
+ VIRTIO_BLK_T_DISCARD
803
+ );
804
+ else
805
+ Status = EFI_UNSUPPORTED ;
806
+
807
+ return Status ;
808
+ }
721
809
722
810
/**
723
811
@@ -751,7 +839,8 @@ VirtioBlkFlushBlocks (
751
839
0 , // Lba
752
840
0 , // BufferSize
753
841
NULL , // Buffer
754
- TRUE // RequestIsWrite
842
+ TRUE, // RequestIsWrite
843
+ VIRTIO_BLK_T_INVALID
755
844
) :
756
845
EFI_SUCCESS ;
757
846
}
@@ -885,8 +974,8 @@ VirtioBlkInit (
885
974
}
886
975
887
976
Features &= VIRTIO_BLK_F_BLK_SIZE | VIRTIO_BLK_F_TOPOLOGY | VIRTIO_BLK_F_RO |
888
- VIRTIO_BLK_F_FLUSH | VIRTIO_F_VERSION_1 |
889
- VIRTIO_F_IOMMU_PLATFORM ;
977
+ VIRTIO_BLK_F_FLUSH | VIRTIO_F_VERSION_1 | VIRTIO_F_IOMMU_PLATFORM |
978
+ VIRTIO_BLK_F_DISCARD | VIRTIO_BLK_F_WRITE_ZEROES ;
890
979
891
980
//
892
981
// In virtio-1.0, feature negotiation is expected to complete before queue
@@ -990,6 +1079,7 @@ VirtioBlkInit (
990
1079
Dev -> BlockIo .ReadBlocks = & VirtioBlkReadBlocks ;
991
1080
Dev -> BlockIo .WriteBlocks = & VirtioBlkWriteBlocks ;
992
1081
Dev -> BlockIo .FlushBlocks = & VirtioBlkFlushBlocks ;
1082
+ Dev -> EraseBlock .EraseBlocks = & VirtioBlkEraseBlocks ;
993
1083
Dev -> BlockIoMedia .MediaId = 0 ;
994
1084
Dev -> BlockIoMedia .RemovableMedia = FALSE;
995
1085
Dev -> BlockIoMedia .MediaPresent = TRUE;
0 commit comments