Skip to content
This repository was archived by the owner on May 5, 2025. It is now read-only.

Commit cfa89c5

Browse files
yang-kaixbuildslave
authored andcommitted
Implement erase block function for virtio block
This pacth is to add support for erasing block protocol and implementing erase block function of virtio block Change-Id: I0df36ab44a9e20cc151be374ca01e9cf30e31a2a Tracked-On: https://jira.devtools.intel.com/browse/OAM-71085 Signed-off-by: Yang, Kai <[email protected]> Reviewed-on: https://android.intel.com:443/656295
1 parent 90366e8 commit cfa89c5

File tree

16 files changed

+509
-51
lines changed

16 files changed

+509
-51
lines changed

drivers/nvme/nvme.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,7 @@ static storage_t nvme_storage = {
115115
.init = _init,
116116
.read = _read,
117117
.write = _write,
118+
.erase = NULL,
118119
.pci_function = 0,
119120
.pci_device = 0,
120121
};

drivers/sdhci_mmc/sdhci_mmc.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,7 @@ static storage_t sdhci_mmc_storage = {
177177
.init = _init,
178178
.read = _read,
179179
.write = _write,
180+
.erase = NULL,
180181
.pci_function = 0,
181182
.pci_device = 0,
182183
};

drivers/ufs/ufs.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,7 @@ static storage_t storage_ufs_storage = {
117117
.init = _init,
118118
.read = _read,
119119
.write = _write,
120+
.erase = NULL,
120121
.pci_function = 0,
121122
.pci_device = 0,
122123
};

drivers/virtual_media/VirtioBlk.c

Lines changed: 139 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,10 @@
3838
#define SIZE_1GB 0x40000000
3939
#endif
4040

41+
#ifndef SECTOR_SHIFT
42+
#define SECTOR_SHIFT 9
43+
#endif
44+
4145
#define EFI_BLOCK_IO_PROTOCOL_REVISION3 0x00020031
4246

4347
/**
@@ -279,22 +283,27 @@ SynchronousRequest (
279283
IN EFI_LBA Lba,
280284
IN UINTN BufferSize,
281285
IN OUT volatile VOID *Buffer,
282-
IN BOOLEAN RequestIsWrite
286+
IN BOOLEAN RequestIsWrite,
287+
IN UINT32 RequestType
283288
)
284289
{
285290
UINT32 BlockSize;
286291
volatile VIRTIO_BLK_REQ Request;
292+
VIRTIO_DISCARD_RANGE EraseRange;
287293
volatile UINT8 *HostStatus;
288294
VOID *HostStatusBuffer;
289295
DESC_INDICES Indices;
290296
VOID *RequestMapping;
291297
VOID *StatusMapping;
292298
VOID *BufferMapping;
299+
VOID *EraseRangeMapping;
293300
EFI_PHYSICAL_ADDRESS BufferDeviceAddress;
294301
EFI_PHYSICAL_ADDRESS HostStatusDeviceAddress;
295302
EFI_PHYSICAL_ADDRESS RequestDeviceAddress;
303+
EFI_PHYSICAL_ADDRESS EraseRangeDeviceAddress;
296304
EFI_STATUS Status;
297305
EFI_STATUS UnmapStatus;
306+
UINT32 Flags = 0;
298307

299308
BlockSize = Dev->BlockIoMedia.BlockSize;
300309

@@ -313,12 +322,23 @@ SynchronousRequest (
313322
// Prepare virtio-blk request header, setting zero size for flush.
314323
// IO Priority is homogeneously 0.
315324
//
316-
Request.Type = RequestIsWrite ?
317-
(BufferSize == 0 ? VIRTIO_BLK_T_FLUSH : VIRTIO_BLK_T_OUT) :
318-
VIRTIO_BLK_T_IN;
319325
Request.IoPrio = 0;
320326
Request.Sector = MultU64x32(Lba, BlockSize / 512);
321327

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+
322342
//
323343
// Host status is bi-directional (we preset with a value and expect the
324344
// device to update it). Allocate a host status buffer which can be mapped
@@ -356,20 +376,30 @@ SynchronousRequest (
356376
// Map data buffer
357377
//
358378
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+
}
373403
}
374404

375405
//
@@ -417,26 +447,36 @@ SynchronousRequest (
417447
// data buffer for read/write in second desc
418448
//
419449
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);
429468

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+
}
440480
}
441481

442482
//
@@ -469,13 +509,16 @@ SynchronousRequest (
469509

470510
UnmapDataBuffer:
471511
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+
}
479522
}
480523

481524
UnmapRequestBuffer:
@@ -518,7 +561,8 @@ VirtioBlkReadBlocksInternal (
518561
Lba,
519562
BufferSize,
520563
Buffer,
521-
FALSE // RequestIsRead
564+
FALSE, // RequestIsRead
565+
VIRTIO_BLK_T_INVALID
522566
);
523567
}
524568

@@ -633,7 +677,8 @@ VirtioBlkWriteBlocksInternal (
633677
Lba,
634678
BufferSize,
635679
Buffer,
636-
TRUE // RequestIsWrite
680+
TRUE, // RequestIsWrite
681+
VIRTIO_BLK_T_INVALID
637682
);
638683

639684
return Status;
@@ -718,6 +763,49 @@ VirtioBlkWriteBlocks (
718763
return Status;
719764
}
720765

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+
}
721809

722810
/**
723811
@@ -751,7 +839,8 @@ VirtioBlkFlushBlocks (
751839
0, // Lba
752840
0, // BufferSize
753841
NULL, // Buffer
754-
TRUE // RequestIsWrite
842+
TRUE, // RequestIsWrite
843+
VIRTIO_BLK_T_INVALID
755844
) :
756845
EFI_SUCCESS;
757846
}
@@ -885,8 +974,8 @@ VirtioBlkInit (
885974
}
886975

887976
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;
890979

891980
//
892981
// In virtio-1.0, feature negotiation is expected to complete before queue
@@ -990,6 +1079,7 @@ VirtioBlkInit (
9901079
Dev->BlockIo.ReadBlocks = &VirtioBlkReadBlocks;
9911080
Dev->BlockIo.WriteBlocks = &VirtioBlkWriteBlocks;
9921081
Dev->BlockIo.FlushBlocks = &VirtioBlkFlushBlocks;
1082+
Dev->EraseBlock.EraseBlocks = &VirtioBlkEraseBlocks;
9931083
Dev->BlockIoMedia.MediaId = 0;
9941084
Dev->BlockIoMedia.RemovableMedia = FALSE;
9951085
Dev->BlockIoMedia.MediaPresent = TRUE;

drivers/virtual_media/VirtioBlk.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,8 @@ typedef struct {
5959
#define VIRTIO_BLK_F_SCSI BIT7
6060
#define VIRTIO_BLK_F_FLUSH BIT9 // identical to "write cache enabled"
6161
#define VIRTIO_BLK_F_TOPOLOGY BIT10 // information on optimal I/O alignment
62+
#define VIRTIO_BLK_F_DISCARD BIT13 // DISCARD is supported
63+
#define VIRTIO_BLK_F_WRITE_ZEROES BIT14 // WRITE ZEROES is supported
6264

6365
//
6466
// We keep the status byte separate from the rest of the virtio-blk request
@@ -73,12 +75,24 @@ typedef struct {
7375
} VIRTIO_BLK_REQ;
7476
#pragma pack()
7577

78+
typedef struct {
79+
UINT64 Sector;
80+
UINT32 num_sectors;
81+
UINT32 flags;
82+
} VIRTIO_DISCARD_RANGE;
83+
84+
/* Unmap this range (only valid for write zeroes command) */
85+
#define VIRTIO_BLK_WRITE_ZEROES_FLAG_UNMAP 0x00000001
86+
7687
#define VIRTIO_BLK_T_IN 0x00000000
7788
#define VIRTIO_BLK_T_OUT 0x00000001
7889
#define VIRTIO_BLK_T_SCSI_CMD 0x00000002
7990
#define VIRTIO_BLK_T_SCSI_CMD_OUT 0x00000003
8091
#define VIRTIO_BLK_T_FLUSH 0x00000004
8192
#define VIRTIO_BLK_T_FLUSH_OUT 0x00000005
93+
#define VIRTIO_BLK_T_DISCARD 0x0000000B
94+
#define VIRTIO_BLK_T_WRITE_ZEROES 0x0000000D
95+
#define VIRTIO_BLK_T_INVALID 0x000000FF
8296
#define VIRTIO_BLK_T_BARRIER BIT31
8397

8498
#define VIRTIO_BLK_S_OK 0x00

drivers/virtual_media/VirtioBlkAccessLib.c

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,31 @@ VirtioWriteBlocks (
112112
return VirtioBlkWriteBlocks(&gBlkdev->BlockIo, DeviceIndex, StartLBA, DataSize, DataAddress);
113113
}
114114

115+
/**
116+
This function erase a specified number of device blocks.
117+
118+
@param[in] DeviceIndex Specifies the block device to which the function wants
119+
to talk.
120+
@param[in] StartLBA The starting logical block address to be erased.
121+
The caller is responsible for erasing only legitimate locations.
122+
@param[in] Size The size in bytes to be erased. This must be a multiple of the
123+
physical block size of the device.
124+
125+
@retval EFI_SUCCESS The operation is done correctly.
126+
@retval Others The operation fails.
127+
128+
**/
129+
EFI_STATUS
130+
EFIAPI
131+
VirtioEraseBlocks (
132+
IN UINTN DeviceIndex,
133+
IN EFI_LBA StartLBA,
134+
IN UINTN Size
135+
)
136+
{
137+
return VirtioBlkEraseBlocks(&gBlkdev->EraseBlock, DeviceIndex, StartLBA, NULL, Size);
138+
}
139+
115140

116141
/**
117142
This function initializes VirtioBlk device

0 commit comments

Comments
 (0)