[PATCH 1/4] virtio: blk: introduce virtio-block erase support

Co-developed-by: Cody Schuffelen schuffelen@google.com Signed-off-by: Cody Schuffelen schuffelen@google.com Signed-off-by: Dmitrii Merkurev dimorinny@google.com Cc: Tuomas Tynkkynen tuomas.tynkkynen@iki.fi Cc: Simon Glass sjg@chromium.org Cc: Mattijs Korpershoek mkorpershoek@baylibre.com Cc: Ying-Chun Liu (PaulLiu) paul.liu@linaro.org --- drivers/virtio/virtio_blk.c | 91 +++++++++++++++++++++++++++++++------ drivers/virtio/virtio_blk.h | 47 +++++++++++++++++++ 2 files changed, 124 insertions(+), 14 deletions(-)
diff --git a/drivers/virtio/virtio_blk.c b/drivers/virtio/virtio_blk.c index 9581058286..225b65c4d1 100644 --- a/drivers/virtio/virtio_blk.c +++ b/drivers/virtio/virtio_blk.c @@ -19,30 +19,82 @@ struct virtio_blk_priv { struct virtqueue *vq; };
+static const u32 feature[] = { + VIRTIO_BLK_F_WRITE_ZEROES +}; + +static void virtio_blk_init_header_sg(struct udevice *dev, u64 sector, u32 type, + struct virtio_blk_outhdr *out_hdr, struct virtio_sg *sg) +{ + const bool sector_is_needed = type == VIRTIO_BLK_T_IN || + type == VIRTIO_BLK_T_OUT; + + out_hdr->type = cpu_to_virtio32(dev, type); + out_hdr->sector = cpu_to_virtio64(dev, sector_is_needed ? sector : 0); + + sg->addr = out_hdr; + sg->length = sizeof(*out_hdr); +} + +static void virtio_blk_init_write_zeroes_sg(struct udevice *dev, u64 sector, lbaint_t blkcnt, + struct virtio_blk_discard_write_zeroes *wz, + struct virtio_sg *sg) +{ + wz->sector = cpu_to_virtio64(dev, sector); + wz->num_sectors = cpu_to_virtio32(dev, blkcnt); + wz->flags = cpu_to_virtio32(dev, 0); + + sg->addr = wz; + sg->length = sizeof(*wz); +} + +static void virtio_blk_init_status_sg(u8 *status, struct virtio_sg *sg) +{ + sg->addr = status; + sg->length = sizeof(*status); +} + +static void virtio_blk_init_data_sg(void *buffer, lbaint_t blkcnt, struct virtio_sg *sg) +{ + sg->addr = buffer; + sg->length = blkcnt * 512; +} + static ulong virtio_blk_do_req(struct udevice *dev, u64 sector, lbaint_t blkcnt, void *buffer, u32 type) { struct virtio_blk_priv *priv = dev_get_priv(dev); + struct virtio_blk_outhdr out_hdr; + struct virtio_blk_discard_write_zeroes wz_hdr; unsigned int num_out = 0, num_in = 0; + struct virtio_sg hdr_sg, wz_sg, data_sg, status_sg; struct virtio_sg *sgs[3]; u8 status; int ret;
- struct virtio_blk_outhdr out_hdr = { - .type = cpu_to_virtio32(dev, type), - .sector = cpu_to_virtio64(dev, sector), - }; - struct virtio_sg hdr_sg = { &out_hdr, sizeof(out_hdr) }; - struct virtio_sg data_sg = { buffer, blkcnt * 512 }; - struct virtio_sg status_sg = { &status, sizeof(status) }; - + virtio_blk_init_header_sg(dev, sector, type, &out_hdr, &hdr_sg); sgs[num_out++] = &hdr_sg;
- if (type & VIRTIO_BLK_T_OUT) - sgs[num_out++] = &data_sg; - else - sgs[num_out + num_in++] = &data_sg; - + switch (type) { + case VIRTIO_BLK_T_IN: + case VIRTIO_BLK_T_OUT: + virtio_blk_init_data_sg(buffer, blkcnt, &data_sg); + if (type & VIRTIO_BLK_T_OUT) + sgs[num_out++] = &data_sg; + else + sgs[num_out + num_in++] = &data_sg; + break; + + case VIRTIO_BLK_T_WRITE_ZEROES: + virtio_blk_init_write_zeroes_sg(dev, sector, blkcnt, &wz_hdr, &wz_sg); + sgs[num_out++] = &wz_sg; + break; + + default: + return -EINVAL; + } + + virtio_blk_init_status_sg(&status, &status_sg); sgs[num_out + num_in++] = &status_sg; log_debug("dev=%s, active=%d, priv=%p, priv->vq=%p\n", dev->name, device_active(dev), priv, priv->vq); @@ -76,6 +128,15 @@ static ulong virtio_blk_write(struct udevice *dev, lbaint_t start, VIRTIO_BLK_T_OUT); }
+static ulong virtio_blk_erase(struct udevice *dev, lbaint_t start, + lbaint_t blkcnt) +{ + if (!virtio_has_feature(dev, VIRTIO_BLK_F_WRITE_ZEROES)) + return -EOPNOTSUPP; + + return virtio_blk_do_req(dev, start, blkcnt, NULL, VIRTIO_BLK_T_WRITE_ZEROES); +} + static int virtio_blk_bind(struct udevice *dev) { struct virtio_dev_priv *uc_priv = dev_get_uclass_priv(dev->parent); @@ -105,7 +166,8 @@ static int virtio_blk_bind(struct udevice *dev) desc->bdev = dev;
/* Indicate what driver features we support */ - virtio_driver_features_init(uc_priv, NULL, 0, NULL, 0); + virtio_driver_features_init(uc_priv, feature, ARRAY_SIZE(feature), + NULL, 0);
return 0; } @@ -132,6 +194,7 @@ static int virtio_blk_probe(struct udevice *dev) static const struct blk_ops virtio_blk_ops = { .read = virtio_blk_read, .write = virtio_blk_write, + .erase = virtio_blk_erase, };
U_BOOT_DRIVER(virtio_blk) = { diff --git a/drivers/virtio/virtio_blk.h b/drivers/virtio/virtio_blk.h index 8d8e02fa2e..b37ba264df 100644 --- a/drivers/virtio/virtio_blk.h +++ b/drivers/virtio/virtio_blk.h @@ -17,6 +17,8 @@ #define VIRTIO_BLK_F_BLK_SIZE 6 /* Block size of disk is available */ #define VIRTIO_BLK_F_TOPOLOGY 10 /* Topology information is available */ #define VIRTIO_BLK_F_MQ 12 /* Support more than one vq */ +#define VIRTIO_BLK_F_DISCARD 13 /* Discard is supported */ +#define VIRTIO_BLK_F_WRITE_ZEROES 14 /* Write zeroes is supported */
/* Legacy feature bits */ #ifndef VIRTIO_BLK_NO_LEGACY @@ -65,6 +67,39 @@ struct __packed virtio_blk_config {
/* number of vqs, only available when VIRTIO_BLK_F_MQ is set */ __u16 num_queues; + + /* the next 3 entries are guarded by VIRTIO_BLK_F_DISCARD */ + /* + * The maximum discard sectors (in 512-byte sectors) for + * one segment. + */ + __u32 max_discard_sectors; + /* + * The maximum number of discard segments in a + * discard command. + */ + __u32 max_discard_seg; + /* Discard commands must be aligned to this number of sectors. */ + __u32 discard_sector_alignment; + + /* the next 3 entries are guarded by VIRTIO_BLK_F_WRITE_ZEROES */ + /* + * The maximum number of write zeroes sectors (in 512-byte sectors) in + * one segment. + */ + __u32 max_write_zeroes_sectors; + /* + * The maximum number of segments in a write zeroes + * command. + */ + __u32 max_write_zeroes_seg; + /* + * Set if a VIRTIO_BLK_T_WRITE_ZEROES request may result in the + * deallocation of one or more of the sectors. + */ + __u8 write_zeroes_may_unmap; + + __u8 unused1[3]; };
/* @@ -93,6 +128,9 @@ struct __packed virtio_blk_config { /* Get device ID command */ #define VIRTIO_BLK_T_GET_ID 8
+/* Write zeroes command */ +#define VIRTIO_BLK_T_WRITE_ZEROES 13 + #ifndef VIRTIO_BLK_NO_LEGACY /* Barrier before this op */ #define VIRTIO_BLK_T_BARRIER 0x80000000 @@ -112,6 +150,15 @@ struct virtio_blk_outhdr { __virtio64 sector; };
+struct virtio_blk_discard_write_zeroes { + /* discard/write zeroes start sector */ + __virtio64 sector; + /* number of discard/write zeroes sectors */ + __virtio32 num_sectors; + /* flags for this range */ + __virtio32 flags; +}; + #ifndef VIRTIO_BLK_NO_LEGACY struct virtio_scsi_inhdr { __virtio32 errors;

Signed-off-by: Dmitrii Merkurev dimorinny@google.com Cc: Patrick Delaunay patrick.delaunay@foss.st.com Cc: Simon Glass sjg@chromium.org Cc: Mattijs Korpershoek mkorpershoek@baylibre.com Cc: Ying-Chun Liu (PaulLiu) paul.liu@linaro.org --- drivers/fastboot/Kconfig | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-)
diff --git a/drivers/fastboot/Kconfig b/drivers/fastboot/Kconfig index 5e5855a76c..460c5e98d7 100644 --- a/drivers/fastboot/Kconfig +++ b/drivers/fastboot/Kconfig @@ -87,7 +87,7 @@ config FASTBOOT_USB_DEV config FASTBOOT_FLASH bool "Enable FASTBOOT FLASH command" default y if ARCH_SUNXI || ARCH_ROCKCHIP - depends on MMC || (MTD_RAW_NAND && CMD_MTDPARTS) + depends on MMC || (MTD_RAW_NAND && CMD_MTDPARTS) || BLK select IMAGE_SPARSE help The fastboot protocol includes a "flash" command for writing @@ -109,12 +109,16 @@ choice
config FASTBOOT_FLASH_MMC bool "FASTBOOT on MMC" - depends on MMC + depends on MMC && BLK
config FASTBOOT_FLASH_NAND bool "FASTBOOT on NAND" depends on MTD_RAW_NAND && CMD_MTDPARTS
+config FASTBOOT_FLASH_BLOCK + bool "FASTBOOT on block device" + depends on BLK + endchoice
config FASTBOOT_FLASH_MMC_DEV @@ -189,6 +193,18 @@ config FASTBOOT_MMC_USER_NAME defined here. The default target name for erasing EMMC_USER is "mmc0".
+config FASTBOOT_FLASH_BLOCK_INTERFACE_NAME + string "Define FASTBOOT block interface name" + depends on FASTBOOT_FLASH_BLOCK + help + "Fastboot block interface name (mmc, virtio, etc)" + +config FASTBOOT_FLASH_BLOCK_DEVICE_ID + int "Define FASTBOOT block device id" + depends on FASTBOOT_FLASH_BLOCK + help + "Fastboot block device id" + config FASTBOOT_GPT_NAME string "Target name for updating GPT" depends on FASTBOOT_FLASH_MMC && EFI_PARTITION

Hi Dmitrii,
Thank you for the patch and sorry for the review delay.
On mer., mars 06, 2024 at 18:59, Dmitrii Merkurev dimorinny@google.com wrote:
Signed-off-by: Dmitrii Merkurev dimorinny@google.com Cc: Patrick Delaunay patrick.delaunay@foss.st.com Cc: Simon Glass sjg@chromium.org Cc: Mattijs Korpershoek mkorpershoek@baylibre.com Cc: Ying-Chun Liu (PaulLiu) paul.liu@linaro.org
drivers/fastboot/Kconfig | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-)
diff --git a/drivers/fastboot/Kconfig b/drivers/fastboot/Kconfig index 5e5855a76c..460c5e98d7 100644 --- a/drivers/fastboot/Kconfig +++ b/drivers/fastboot/Kconfig @@ -87,7 +87,7 @@ config FASTBOOT_USB_DEV config FASTBOOT_FLASH bool "Enable FASTBOOT FLASH command" default y if ARCH_SUNXI || ARCH_ROCKCHIP
- depends on MMC || (MTD_RAW_NAND && CMD_MTDPARTS)
- depends on MMC || (MTD_RAW_NAND && CMD_MTDPARTS) || BLK select IMAGE_SPARSE help The fastboot protocol includes a "flash" command for writing
@@ -109,12 +109,16 @@ choice
config FASTBOOT_FLASH_MMC bool "FASTBOOT on MMC"
- depends on MMC
- depends on MMC && BLK
config FASTBOOT_FLASH_NAND bool "FASTBOOT on NAND" depends on MTD_RAW_NAND && CMD_MTDPARTS
+config FASTBOOT_FLASH_BLOCK
- bool "FASTBOOT on block device"
- depends on BLK
If we just apply this patch, then this KConfig option is unused. Can we please squash this into patch 3/4?
endchoice
config FASTBOOT_FLASH_MMC_DEV @@ -189,6 +193,18 @@ config FASTBOOT_MMC_USER_NAME defined here. The default target name for erasing EMMC_USER is "mmc0".
+config FASTBOOT_FLASH_BLOCK_INTERFACE_NAME
- string "Define FASTBOOT block interface name"
- depends on FASTBOOT_FLASH_BLOCK
- help
"Fastboot block interface name (mmc, virtio, etc)"
There is a finite list of supported options for this. Can we please document all of them so that users know what is valid and what not? If so, we can drop the "etc" part in the help string.
+config FASTBOOT_FLASH_BLOCK_DEVICE_ID
- int "Define FASTBOOT block device id"
- depends on FASTBOOT_FLASH_BLOCK
- help
"Fastboot block device id"
When FASTBOOT_FLASH_BLOCK=="mmc", how is FASTBOOT_FLASH_BLOCK_DEVICE_ID different from FASTBOOT_FLASH_MMC_DEV?
If they are similar, are we sure this symbol really needed?
config FASTBOOT_GPT_NAME string "Target name for updating GPT" depends on FASTBOOT_FLASH_MMC && EFI_PARTITION -- 2.44.0.278.ge034bb2e1d-goog

Hi Dmitrii,
So you plan to send a new version of this patchset ?
It would be very useful to enable fastboot onr UFS/SCSI based devices.
Thanks, Neil
On 06/03/2024 19:59, Dmitrii Merkurev wrote:
Signed-off-by: Dmitrii Merkurev dimorinny@google.com Cc: Patrick Delaunay patrick.delaunay@foss.st.com Cc: Simon Glass sjg@chromium.org Cc: Mattijs Korpershoek mkorpershoek@baylibre.com Cc: Ying-Chun Liu (PaulLiu) paul.liu@linaro.org
drivers/fastboot/Kconfig | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-)
diff --git a/drivers/fastboot/Kconfig b/drivers/fastboot/Kconfig index 5e5855a76c..460c5e98d7 100644 --- a/drivers/fastboot/Kconfig +++ b/drivers/fastboot/Kconfig @@ -87,7 +87,7 @@ config FASTBOOT_USB_DEV config FASTBOOT_FLASH bool "Enable FASTBOOT FLASH command" default y if ARCH_SUNXI || ARCH_ROCKCHIP
- depends on MMC || (MTD_RAW_NAND && CMD_MTDPARTS)
- depends on MMC || (MTD_RAW_NAND && CMD_MTDPARTS) || BLK select IMAGE_SPARSE help The fastboot protocol includes a "flash" command for writing
@@ -109,12 +109,16 @@ choice
config FASTBOOT_FLASH_MMC bool "FASTBOOT on MMC"
- depends on MMC
depends on MMC && BLK
config FASTBOOT_FLASH_NAND bool "FASTBOOT on NAND" depends on MTD_RAW_NAND && CMD_MTDPARTS
+config FASTBOOT_FLASH_BLOCK
bool "FASTBOOT on block device"
depends on BLK
endchoice
config FASTBOOT_FLASH_MMC_DEV
@@ -189,6 +193,18 @@ config FASTBOOT_MMC_USER_NAME defined here. The default target name for erasing EMMC_USER is "mmc0".
+config FASTBOOT_FLASH_BLOCK_INTERFACE_NAME
- string "Define FASTBOOT block interface name"
- depends on FASTBOOT_FLASH_BLOCK
- help
"Fastboot block interface name (mmc, virtio, etc)"
+config FASTBOOT_FLASH_BLOCK_DEVICE_ID
- int "Define FASTBOOT block device id"
- depends on FASTBOOT_FLASH_BLOCK
- help
"Fastboot block device id"
- config FASTBOOT_GPT_NAME string "Target name for updating GPT" depends on FASTBOOT_FLASH_MMC && EFI_PARTITION

Hey Neil.
Will do it by the end of the year. Only tested it with a virtio-block though.
On Thu, Nov 21, 2024 at 12:44 PM neil.armstrong@linaro.org wrote:
Hi Dmitrii,
So you plan to send a new version of this patchset ?
It would be very useful to enable fastboot onr UFS/SCSI based devices.
Thanks, Neil
On 06/03/2024 19:59, Dmitrii Merkurev wrote:
Signed-off-by: Dmitrii Merkurev dimorinny@google.com Cc: Patrick Delaunay patrick.delaunay@foss.st.com Cc: Simon Glass sjg@chromium.org Cc: Mattijs Korpershoek mkorpershoek@baylibre.com Cc: Ying-Chun Liu (PaulLiu) paul.liu@linaro.org
drivers/fastboot/Kconfig | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-)
diff --git a/drivers/fastboot/Kconfig b/drivers/fastboot/Kconfig index 5e5855a76c..460c5e98d7 100644 --- a/drivers/fastboot/Kconfig +++ b/drivers/fastboot/Kconfig @@ -87,7 +87,7 @@ config FASTBOOT_USB_DEV config FASTBOOT_FLASH bool "Enable FASTBOOT FLASH command" default y if ARCH_SUNXI || ARCH_ROCKCHIP
depends on MMC || (MTD_RAW_NAND && CMD_MTDPARTS)
depends on MMC || (MTD_RAW_NAND && CMD_MTDPARTS) || BLK select IMAGE_SPARSE help The fastboot protocol includes a "flash" command for writing
@@ -109,12 +109,16 @@ choice
config FASTBOOT_FLASH_MMC bool "FASTBOOT on MMC"
depends on MMC
depends on MMC && BLK
config FASTBOOT_FLASH_NAND bool "FASTBOOT on NAND" depends on MTD_RAW_NAND && CMD_MTDPARTS
+config FASTBOOT_FLASH_BLOCK
bool "FASTBOOT on block device"
depends on BLK
endchoice
config FASTBOOT_FLASH_MMC_DEV
@@ -189,6 +193,18 @@ config FASTBOOT_MMC_USER_NAME defined here. The default target name for erasing EMMC_USER is "mmc0".
+config FASTBOOT_FLASH_BLOCK_INTERFACE_NAME
string "Define FASTBOOT block interface name"
depends on FASTBOOT_FLASH_BLOCK
help
"Fastboot block interface name (mmc, virtio, etc)"
+config FASTBOOT_FLASH_BLOCK_DEVICE_ID
int "Define FASTBOOT block device id"
depends on FASTBOOT_FLASH_BLOCK
help
"Fastboot block device id"
- config FASTBOOT_GPT_NAME string "Target name for updating GPT" depends on FASTBOOT_FLASH_MMC && EFI_PARTITION

On lun., nov. 25, 2024 at 23:41, Dmitrii Merkurev dimorinny@google.com wrote:
Hey Neil.
Will do it by the end of the year. Only tested it with a virtio-block though.
On Thu, Nov 21, 2024 at 12:44 PM neil.armstrong@linaro.org wrote:
Hi Dmitrii,
So you plan to send a new version of this patchset ?
It would be very useful to enable fastboot onr UFS/SCSI based devices.
FYI another development for UFS/SCSI has been submitted here:
https://patchwork.ozlabs.org/project/uboot/patch/20241125110354.602124-1-qui...
Thanks, Neil
On 06/03/2024 19:59, Dmitrii Merkurev wrote:
Signed-off-by: Dmitrii Merkurev dimorinny@google.com Cc: Patrick Delaunay patrick.delaunay@foss.st.com Cc: Simon Glass sjg@chromium.org Cc: Mattijs Korpershoek mkorpershoek@baylibre.com Cc: Ying-Chun Liu (PaulLiu) paul.liu@linaro.org
drivers/fastboot/Kconfig | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-)
diff --git a/drivers/fastboot/Kconfig b/drivers/fastboot/Kconfig index 5e5855a76c..460c5e98d7 100644 --- a/drivers/fastboot/Kconfig +++ b/drivers/fastboot/Kconfig @@ -87,7 +87,7 @@ config FASTBOOT_USB_DEV config FASTBOOT_FLASH bool "Enable FASTBOOT FLASH command" default y if ARCH_SUNXI || ARCH_ROCKCHIP
depends on MMC || (MTD_RAW_NAND && CMD_MTDPARTS)
depends on MMC || (MTD_RAW_NAND && CMD_MTDPARTS) || BLK select IMAGE_SPARSE help The fastboot protocol includes a "flash" command for writing
@@ -109,12 +109,16 @@ choice
config FASTBOOT_FLASH_MMC bool "FASTBOOT on MMC"
depends on MMC
depends on MMC && BLK
config FASTBOOT_FLASH_NAND bool "FASTBOOT on NAND" depends on MTD_RAW_NAND && CMD_MTDPARTS
+config FASTBOOT_FLASH_BLOCK
bool "FASTBOOT on block device"
depends on BLK
endchoice
config FASTBOOT_FLASH_MMC_DEV
@@ -189,6 +193,18 @@ config FASTBOOT_MMC_USER_NAME defined here. The default target name for erasing EMMC_USER is "mmc0".
+config FASTBOOT_FLASH_BLOCK_INTERFACE_NAME
string "Define FASTBOOT block interface name"
depends on FASTBOOT_FLASH_BLOCK
help
"Fastboot block interface name (mmc, virtio, etc)"
+config FASTBOOT_FLASH_BLOCK_DEVICE_ID
int "Define FASTBOOT block device id"
depends on FASTBOOT_FLASH_BLOCK
help
"Fastboot block device id"
- config FASTBOOT_GPT_NAME string "Target name for updating GPT" depends on FASTBOOT_FLASH_MMC && EFI_PARTITION

Reuse common logic between existing mmc and new introduced block implementation
Signed-off-by: Dmitrii Merkurev dimorinny@google.com Cc: Alex Kiernan alex.kiernan@gmail.com Cc: Patrick Delaunay patrick.delaunay@foss.st.com Cc: Simon Glass sjg@chromium.org Cc: Mattijs Korpershoek mkorpershoek@baylibre.com Cc: Ying-Chun Liu (PaulLiu) paul.liu@linaro.org --- drivers/fastboot/Makefile | 4 +- drivers/fastboot/fb_block.c | 200 ++++++++++++++++++++++++++++++++++++ drivers/fastboot/fb_mmc.c | 120 ++-------------------- include/fb_block.h | 70 +++++++++++++ 4 files changed, 281 insertions(+), 113 deletions(-) create mode 100644 drivers/fastboot/fb_block.c create mode 100644 include/fb_block.h
diff --git a/drivers/fastboot/Makefile b/drivers/fastboot/Makefile index 048af5aa82..91e98763e8 100644 --- a/drivers/fastboot/Makefile +++ b/drivers/fastboot/Makefile @@ -3,5 +3,7 @@ obj-y += fb_common.o obj-y += fb_getvar.o obj-y += fb_command.o -obj-$(CONFIG_FASTBOOT_FLASH_MMC) += fb_mmc.o +obj-$(CONFIG_FASTBOOT_FLASH_BLOCK) += fb_block.o +# MMC reuses block implementation +obj-$(CONFIG_FASTBOOT_FLASH_MMC) += fb_block.o fb_mmc.o obj-$(CONFIG_FASTBOOT_FLASH_NAND) += fb_nand.o diff --git a/drivers/fastboot/fb_block.c b/drivers/fastboot/fb_block.c new file mode 100644 index 0000000000..908decd544 --- /dev/null +++ b/drivers/fastboot/fb_block.c @@ -0,0 +1,200 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (C) 2024 The Android Open Source Project + */ + +#include <blk.h> +#include <div64.h> +#include <fastboot-internal.h> +#include <fastboot.h> +#include <fb_block.h> +#include <image-sparse.h> +#include <part.h> + +/** + * FASTBOOT_MAX_BLOCKS_ERASE - maximum blocks to erase per derase call + * + * in the ERASE case we can have much larger buffer size since + * we're not transferring an actual buffer + */ +#define FASTBOOT_MAX_BLOCKS_ERASE 1048576 +/** + * FASTBOOT_MAX_BLOCKS_WRITE - maximum blocks to write per dwrite call + */ +#define FASTBOOT_MAX_BLOCKS_WRITE 65536 + +struct fb_block_sparse { + struct blk_desc *dev_desc; +}; + +static lbaint_t fb_block_write(struct blk_desc *block_dev, lbaint_t start, + lbaint_t blkcnt, const void *buffer) +{ + lbaint_t blk = start; + lbaint_t blks_written = 0; + lbaint_t cur_blkcnt = 0; + lbaint_t blks = 0; + int step = buffer ? FASTBOOT_MAX_BLOCKS_WRITE : FASTBOOT_MAX_BLOCKS_ERASE; + int i; + + for (i = 0; i < blkcnt; i += step) { + cur_blkcnt = min((int)blkcnt - i, step); + if (buffer) { + if (fastboot_progress_callback) + fastboot_progress_callback("writing"); + blks_written = blk_dwrite(block_dev, blk, cur_blkcnt, + buffer + (i * block_dev->blksz)); + } else { + if (fastboot_progress_callback) + fastboot_progress_callback("erasing"); + blks_written = blk_derase(block_dev, blk, cur_blkcnt); + } + blk += blks_written; + blks += blks_written; + } + return blks; +} + +static lbaint_t fb_block_sparse_write(struct sparse_storage *info, + lbaint_t blk, lbaint_t blkcnt, + const void *buffer) +{ + struct fb_block_sparse *sparse = info->priv; + struct blk_desc *dev_desc = sparse->dev_desc; + + return fb_block_write(dev_desc, blk, blkcnt, buffer); +} + +static lbaint_t fb_block_sparse_reserve(struct sparse_storage *info, + lbaint_t blk, lbaint_t blkcnt) +{ + return blkcnt; +} + +int fastboot_block_get_part_info(const char *part_name, + struct blk_desc **dev_desc, + struct disk_partition *part_info, + char *response) +{ + int ret; + const char *interface = config_opt_enabled(CONFIG_FASTBOOT_FLASH_BLOCK, + CONFIG_FASTBOOT_FLASH_BLOCK_INTERFACE_NAME, + NULL); + const int device = config_opt_enabled(CONFIG_FASTBOOT_FLASH_BLOCK, + CONFIG_FASTBOOT_FLASH_BLOCK_DEVICE_ID, -1); + + if (!part_name || !strcmp(part_name, "")) { + fastboot_fail("partition not given", response); + return -ENOENT; + } + if (!interface || !strcmp(interface, "")) { + fastboot_fail("block interface isn't provided", response); + return -EINVAL; + } + + *dev_desc = blk_get_dev(interface, device); + if (!dev_desc) { + fastboot_fail("no such device", response); + return -ENODEV; + } + + ret = part_get_info_by_name(*dev_desc, part_name, part_info); + if (ret < 0) + fastboot_fail("failed to get partition info", response); + + return ret; +} + +void fastboot_block_erase(const char *part_name, char *response) +{ + struct blk_desc *dev_desc; + struct disk_partition part_info; + lbaint_t written; + + if (fastboot_block_get_part_info(part_name, &dev_desc, &part_info, response) < 0) + return; + + written = fb_block_write(dev_desc, part_info.start, part_info.size, NULL); + if (written != part_info.size) { + fastboot_fail("failed to erase partition", response); + return; + } + + fastboot_okay(NULL, response); +} + +void fastboot_block_write_raw_image(struct blk_desc *dev_desc, + struct disk_partition *info, const char *part_name, + void *buffer, u32 download_bytes, char *response) +{ + lbaint_t blkcnt; + lbaint_t blks; + + /* determine number of blocks to write */ + blkcnt = ((download_bytes + (info->blksz - 1)) & ~(info->blksz - 1)); + blkcnt = lldiv(blkcnt, info->blksz); + + if (blkcnt > info->size) { + pr_err("too large for partition: '%s'\n", part_name); + fastboot_fail("too large for partition", response); + return; + } + + puts("Flashing Raw Image\n"); + + blks = fb_block_write(dev_desc, info->start, blkcnt, buffer); + + if (blks != blkcnt) { + pr_err("failed writing to device %d\n", dev_desc->devnum); + fastboot_fail("failed writing to device", response); + return; + } + + printf("........ wrote " LBAFU " bytes to '%s'\n", blkcnt * info->blksz, + part_name); + fastboot_okay(NULL, response); +} + +void fastboot_block_write_sparse_image(struct blk_desc *dev_desc, struct disk_partition *info, + const char *part_name, void *buffer, char *response) +{ + struct fb_block_sparse sparse_priv; + struct sparse_storage sparse; + int err; + + sparse_priv.dev_desc = dev_desc; + + sparse.blksz = info->blksz; + sparse.start = info->start; + sparse.size = info->size; + sparse.write = fb_block_sparse_write; + sparse.reserve = fb_block_sparse_reserve; + sparse.mssg = fastboot_fail; + + printf("Flashing sparse image at offset " LBAFU "\n", + sparse.start); + + sparse.priv = &sparse_priv; + err = write_sparse_image(&sparse, part_name, buffer, + response); + if (!err) + fastboot_okay(NULL, response); +} + +void fastboot_block_flash_write(const char *part_name, void *download_buffer, + u32 download_bytes, char *response) +{ + struct blk_desc *dev_desc; + struct disk_partition part_info; + + if (fastboot_block_get_part_info(part_name, &dev_desc, &part_info, response) < 0) + return; + + if (is_sparse_image(download_buffer)) { + fastboot_block_write_sparse_image(dev_desc, &part_info, part_name, + download_buffer, response); + } else { + fastboot_block_write_raw_image(dev_desc, &part_info, part_name, + download_buffer, download_bytes, response); + } +} diff --git a/drivers/fastboot/fb_mmc.c b/drivers/fastboot/fb_mmc.c index 060918e491..7894f01f63 100644 --- a/drivers/fastboot/fb_mmc.c +++ b/drivers/fastboot/fb_mmc.c @@ -9,6 +9,7 @@ #include <env.h> #include <fastboot.h> #include <fastboot-internal.h> +#include <fb_block.h> #include <fb_mmc.h> #include <image-sparse.h> #include <image.h> @@ -21,10 +22,6 @@
#define BOOT_PARTITION_NAME "boot"
-struct fb_mmc_sparse { - struct blk_desc *dev_desc; -}; - static int raw_part_get_info_by_name(struct blk_desc *dev_desc, const char *name, struct disk_partition *info) @@ -115,88 +112,6 @@ static int part_get_info_by_name_or_alias(struct blk_desc **dev_desc, return do_get_part_info(dev_desc, name, info); }
-/** - * fb_mmc_blk_write() - Write/erase MMC in chunks of FASTBOOT_MAX_BLK_WRITE - * - * @block_dev: Pointer to block device - * @start: First block to write/erase - * @blkcnt: Count of blocks - * @buffer: Pointer to data buffer for write or NULL for erase - */ -static lbaint_t fb_mmc_blk_write(struct blk_desc *block_dev, lbaint_t start, - lbaint_t blkcnt, const void *buffer) -{ - lbaint_t blk = start; - lbaint_t blks_written; - lbaint_t cur_blkcnt; - lbaint_t blks = 0; - int i; - - for (i = 0; i < blkcnt; i += FASTBOOT_MAX_BLK_WRITE) { - cur_blkcnt = min((int)blkcnt - i, FASTBOOT_MAX_BLK_WRITE); - if (buffer) { - if (fastboot_progress_callback) - fastboot_progress_callback("writing"); - blks_written = blk_dwrite(block_dev, blk, cur_blkcnt, - buffer + (i * block_dev->blksz)); - } else { - if (fastboot_progress_callback) - fastboot_progress_callback("erasing"); - blks_written = blk_derase(block_dev, blk, cur_blkcnt); - } - blk += blks_written; - blks += blks_written; - } - return blks; -} - -static lbaint_t fb_mmc_sparse_write(struct sparse_storage *info, - lbaint_t blk, lbaint_t blkcnt, const void *buffer) -{ - struct fb_mmc_sparse *sparse = info->priv; - struct blk_desc *dev_desc = sparse->dev_desc; - - return fb_mmc_blk_write(dev_desc, blk, blkcnt, buffer); -} - -static lbaint_t fb_mmc_sparse_reserve(struct sparse_storage *info, - lbaint_t blk, lbaint_t blkcnt) -{ - return blkcnt; -} - -static void write_raw_image(struct blk_desc *dev_desc, - struct disk_partition *info, const char *part_name, - void *buffer, u32 download_bytes, char *response) -{ - lbaint_t blkcnt; - lbaint_t blks; - - /* determine number of blocks to write */ - blkcnt = ((download_bytes + (info->blksz - 1)) & ~(info->blksz - 1)); - blkcnt = lldiv(blkcnt, info->blksz); - - if (blkcnt > info->size) { - pr_err("too large for partition: '%s'\n", part_name); - fastboot_fail("too large for partition", response); - return; - } - - puts("Flashing Raw Image\n"); - - blks = fb_mmc_blk_write(dev_desc, info->start, blkcnt, buffer); - - if (blks != blkcnt) { - pr_err("failed writing to device %d\n", dev_desc->devnum); - fastboot_fail("failed writing to device", response); - return; - } - - printf("........ wrote " LBAFU " bytes to '%s'\n", blkcnt * info->blksz, - part_name); - fastboot_okay(NULL, response); -} - #if defined(CONFIG_FASTBOOT_MMC_BOOT_SUPPORT) || \ defined(CONFIG_FASTBOOT_MMC_USER_SUPPORT) static int fb_mmc_erase_mmc_hwpart(struct blk_desc *dev_desc) @@ -205,7 +120,7 @@ static int fb_mmc_erase_mmc_hwpart(struct blk_desc *dev_desc)
debug("Start Erasing mmc hwpart[%u]...\n", dev_desc->hwpart);
- blks = fb_mmc_blk_write(dev_desc, 0, dev_desc->lba, NULL); + blks = fb_block_write(dev_desc, 0, dev_desc->lba, NULL);
if (blks != dev_desc->lba) { pr_err("Failed to erase mmc hwpart[%u]\n", dev_desc->hwpart); @@ -249,7 +164,7 @@ static void fb_mmc_boot_ops(struct blk_desc *dev_desc, void *buffer,
debug("Start Flashing Image to EMMC_BOOT%d...\n", hwpart);
- blks = fb_mmc_blk_write(dev_desc, 0, blkcnt, buffer); + blks = fb_block_write(dev_desc, 0, blkcnt, buffer);
if (blks != blkcnt) { pr_err("Failed to write EMMC_BOOT%d\n", hwpart); @@ -610,30 +525,11 @@ void fastboot_mmc_flash_write(const char *cmd, void *download_buffer, return;
if (is_sparse_image(download_buffer)) { - struct fb_mmc_sparse sparse_priv; - struct sparse_storage sparse; - int err; - - sparse_priv.dev_desc = dev_desc; - - sparse.blksz = info.blksz; - sparse.start = info.start; - sparse.size = info.size; - sparse.write = fb_mmc_sparse_write; - sparse.reserve = fb_mmc_sparse_reserve; - sparse.mssg = fastboot_fail; - - printf("Flashing sparse image at offset " LBAFU "\n", - sparse.start); - - sparse.priv = &sparse_priv; - err = write_sparse_image(&sparse, cmd, download_buffer, - response); - if (!err) - fastboot_okay(NULL, response); + fastboot_block_write_sparse_image(dev_desc, &info, cmd, + download_buffer, response); } else { - write_raw_image(dev_desc, &info, cmd, download_buffer, - download_bytes, response); + fastboot_block_write_raw_image(dev_desc, &info, cmd, download_buffer, + download_bytes, response); } }
@@ -697,7 +593,7 @@ void fastboot_mmc_erase(const char *cmd, char *response) printf("Erasing blocks " LBAFU " to " LBAFU " due to alignment\n", blks_start, blks_start + blks_size);
- blks = fb_mmc_blk_write(dev_desc, blks_start, blks_size, NULL); + blks = fb_block_write(dev_desc, blks_start, blks_size, NULL);
if (blks != blks_size) { pr_err("failed erasing from device %d\n", dev_desc->devnum); diff --git a/include/fb_block.h b/include/fb_block.h new file mode 100644 index 0000000000..90208e21a7 --- /dev/null +++ b/include/fb_block.h @@ -0,0 +1,70 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (C) 2024 The Android Open Source Project + */ + +#ifndef _FB_BLOCK_H_ +#define _FB_BLOCK_H_ + +struct blk_desc; +struct disk_partition; + +/** + * fastboot_block_get_part_info() - Lookup block partition by name + * + * @part_name: Named partition to lookup + * @dev_desc: Pointer to returned blk_desc pointer + * @part_info: Pointer to returned struct disk_partition + * @response: Pointer to fastboot response buffer + */ +int fastboot_block_get_part_info(const char *part_name, + struct blk_desc **dev_desc, + struct disk_partition *part_info, + char *response); + +/** + * fastboot_block_erase() - Erase partition on block device for fastboot + * + * @part_name: Named partition to erase + * @response: Pointer to fastboot response buffer + */ +void fastboot_block_erase(const char *part_name, char *response); + +/** + * fastboot_block_write_raw_image() - Write raw image to block device + * + * @dev_desc: Block device we're going write to + * @info: Partition we're going write to + * @part_name: Name of partition we're going write to + * @buffer: Downloaded buffer pointer + * @download_bytes: Size of content on downloaded buffer pointer + * @response: Pointer to fastboot response buffer + */ +void fastboot_block_write_raw_image(struct blk_desc *dev_desc, + struct disk_partition *info, const char *part_name, + void *buffer, u32 download_bytes, char *response); + +/** + * fastboot_block_write_sparse_image() - Write sparse image to block device + * + * @dev_desc: Block device we're going write to + * @info: Partition we're going write to + * @part_name: Name of partition we're going write to + * @buffer: Downloaded buffer pointer + * @response: Pointer to fastboot response buffer + */ +void fastboot_block_write_sparse_image(struct blk_desc *dev_desc, struct disk_partition *info, + const char *part_name, void *buffer, char *response); + +/** + * fastboot_block_flash_write() - Write image to block device for fastboot + * + * @part_name: Named partition to write image to + * @download_buffer: Pointer to image data + * @download_bytes: Size of image data + * @response: Pointer to fastboot response buffer + */ +void fastboot_block_flash_write(const char *part_name, void *download_buffer, + u32 download_bytes, char *response); + +#endif // _FB_BLOCK_H_

Hi Dmitrii,
Thank you for the patch and sorry for the review delay.
On mer., mars 06, 2024 at 18:59, Dmitrii Merkurev dimorinny@google.com wrote:
Reuse common logic between existing mmc and new introduced block implementation
Signed-off-by: Dmitrii Merkurev dimorinny@google.com Cc: Alex Kiernan alex.kiernan@gmail.com Cc: Patrick Delaunay patrick.delaunay@foss.st.com Cc: Simon Glass sjg@chromium.org Cc: Mattijs Korpershoek mkorpershoek@baylibre.com Cc: Ying-Chun Liu (PaulLiu) paul.liu@linaro.org
This change (when applied along with 1/4 and 2/4) introduces a build for sandbox:
$ make sandbox_defconfig $ make
[...]
drivers/fastboot/fb_mmc.c: In function 'fastboot_mmc_erase': drivers/fastboot/fb_mmc.c:596:16: warning: implicit declaration of function 'fb_block_write'; did you mean 'blk_write'? [-Wimplicit-function-declaration] 596 | blks = fb_block_write(dev_desc, blks_start, blks_size, NULL); | ^~~~~~~~~~~~~~ | blk_write
[...]
LTO u-boot /usr/bin/ld: /tmp/cczd5cS1.ltrans18.ltrans.o: in function `erase.lto_priv.0': /mnt/work/upstream/u-boot/drivers/fastboot/fb_mmc.c:596: undefined reference to `fb_block_write' collect2: error: ld returned 1 exit status make: *** [Makefile:1798: u-boot] Error 1
drivers/fastboot/Makefile | 4 +- drivers/fastboot/fb_block.c | 200 ++++++++++++++++++++++++++++++++++++ drivers/fastboot/fb_mmc.c | 120 ++-------------------- include/fb_block.h | 70 +++++++++++++ 4 files changed, 281 insertions(+), 113 deletions(-) create mode 100644 drivers/fastboot/fb_block.c create mode 100644 include/fb_block.h
diff --git a/drivers/fastboot/Makefile b/drivers/fastboot/Makefile index 048af5aa82..91e98763e8 100644 --- a/drivers/fastboot/Makefile +++ b/drivers/fastboot/Makefile @@ -3,5 +3,7 @@ obj-y += fb_common.o obj-y += fb_getvar.o obj-y += fb_command.o -obj-$(CONFIG_FASTBOOT_FLASH_MMC) += fb_mmc.o +obj-$(CONFIG_FASTBOOT_FLASH_BLOCK) += fb_block.o +# MMC reuses block implementation +obj-$(CONFIG_FASTBOOT_FLASH_MMC) += fb_block.o fb_mmc.o obj-$(CONFIG_FASTBOOT_FLASH_NAND) += fb_nand.o diff --git a/drivers/fastboot/fb_block.c b/drivers/fastboot/fb_block.c new file mode 100644 index 0000000000..908decd544 --- /dev/null +++ b/drivers/fastboot/fb_block.c @@ -0,0 +1,200 @@ +// SPDX-License-Identifier: BSD-2-Clause +/*
- Copyright (C) 2024 The Android Open Source Project
- */
+#include <blk.h> +#include <div64.h> +#include <fastboot-internal.h> +#include <fastboot.h> +#include <fb_block.h> +#include <image-sparse.h> +#include <part.h>
+/**
- FASTBOOT_MAX_BLOCKS_ERASE - maximum blocks to erase per derase call
- in the ERASE case we can have much larger buffer size since
- we're not transferring an actual buffer
- */
+#define FASTBOOT_MAX_BLOCKS_ERASE 1048576 +/**
- FASTBOOT_MAX_BLOCKS_WRITE - maximum blocks to write per dwrite call
- */
+#define FASTBOOT_MAX_BLOCKS_WRITE 65536
+struct fb_block_sparse {
- struct blk_desc *dev_desc;
+};
+static lbaint_t fb_block_write(struct blk_desc *block_dev, lbaint_t start,
lbaint_t blkcnt, const void *buffer)
+{
- lbaint_t blk = start;
- lbaint_t blks_written = 0;
- lbaint_t cur_blkcnt = 0;
- lbaint_t blks = 0;
- int step = buffer ? FASTBOOT_MAX_BLOCKS_WRITE : FASTBOOT_MAX_BLOCKS_ERASE;
- int i;
- for (i = 0; i < blkcnt; i += step) {
cur_blkcnt = min((int)blkcnt - i, step);
if (buffer) {
if (fastboot_progress_callback)
fastboot_progress_callback("writing");
blks_written = blk_dwrite(block_dev, blk, cur_blkcnt,
buffer + (i * block_dev->blksz));
} else {
if (fastboot_progress_callback)
fastboot_progress_callback("erasing");
blks_written = blk_derase(block_dev, blk, cur_blkcnt);
}
blk += blks_written;
blks += blks_written;
- }
- return blks;
+}
+static lbaint_t fb_block_sparse_write(struct sparse_storage *info,
lbaint_t blk, lbaint_t blkcnt,
const void *buffer)
+{
- struct fb_block_sparse *sparse = info->priv;
- struct blk_desc *dev_desc = sparse->dev_desc;
- return fb_block_write(dev_desc, blk, blkcnt, buffer);
+}
+static lbaint_t fb_block_sparse_reserve(struct sparse_storage *info,
lbaint_t blk, lbaint_t blkcnt)
+{
- return blkcnt;
+}
+int fastboot_block_get_part_info(const char *part_name,
struct blk_desc **dev_desc,
struct disk_partition *part_info,
char *response)
+{
- int ret;
- const char *interface = config_opt_enabled(CONFIG_FASTBOOT_FLASH_BLOCK,
CONFIG_FASTBOOT_FLASH_BLOCK_INTERFACE_NAME,
NULL);
- const int device = config_opt_enabled(CONFIG_FASTBOOT_FLASH_BLOCK,
CONFIG_FASTBOOT_FLASH_BLOCK_DEVICE_ID, -1);
- if (!part_name || !strcmp(part_name, "")) {
fastboot_fail("partition not given", response);
return -ENOENT;
- }
- if (!interface || !strcmp(interface, "")) {
fastboot_fail("block interface isn't provided", response);
return -EINVAL;
- }
- *dev_desc = blk_get_dev(interface, device);
- if (!dev_desc) {
fastboot_fail("no such device", response);
return -ENODEV;
- }
- ret = part_get_info_by_name(*dev_desc, part_name, part_info);
- if (ret < 0)
fastboot_fail("failed to get partition info", response);
- return ret;
+}
+void fastboot_block_erase(const char *part_name, char *response) +{
- struct blk_desc *dev_desc;
- struct disk_partition part_info;
- lbaint_t written;
- if (fastboot_block_get_part_info(part_name, &dev_desc, &part_info, response) < 0)
return;
- written = fb_block_write(dev_desc, part_info.start, part_info.size, NULL);
- if (written != part_info.size) {
fastboot_fail("failed to erase partition", response);
return;
- }
- fastboot_okay(NULL, response);
+}
+void fastboot_block_write_raw_image(struct blk_desc *dev_desc,
struct disk_partition *info, const char *part_name,
void *buffer, u32 download_bytes, char *response)
+{
- lbaint_t blkcnt;
- lbaint_t blks;
- /* determine number of blocks to write */
- blkcnt = ((download_bytes + (info->blksz - 1)) & ~(info->blksz - 1));
- blkcnt = lldiv(blkcnt, info->blksz);
- if (blkcnt > info->size) {
pr_err("too large for partition: '%s'\n", part_name);
fastboot_fail("too large for partition", response);
return;
- }
- puts("Flashing Raw Image\n");
- blks = fb_block_write(dev_desc, info->start, blkcnt, buffer);
- if (blks != blkcnt) {
pr_err("failed writing to device %d\n", dev_desc->devnum);
fastboot_fail("failed writing to device", response);
return;
- }
- printf("........ wrote " LBAFU " bytes to '%s'\n", blkcnt * info->blksz,
part_name);
- fastboot_okay(NULL, response);
+}
+void fastboot_block_write_sparse_image(struct blk_desc *dev_desc, struct disk_partition *info,
const char *part_name, void *buffer, char *response)
+{
- struct fb_block_sparse sparse_priv;
- struct sparse_storage sparse;
- int err;
- sparse_priv.dev_desc = dev_desc;
- sparse.blksz = info->blksz;
- sparse.start = info->start;
- sparse.size = info->size;
- sparse.write = fb_block_sparse_write;
- sparse.reserve = fb_block_sparse_reserve;
- sparse.mssg = fastboot_fail;
- printf("Flashing sparse image at offset " LBAFU "\n",
sparse.start);
- sparse.priv = &sparse_priv;
- err = write_sparse_image(&sparse, part_name, buffer,
response);
- if (!err)
fastboot_okay(NULL, response);
+}
+void fastboot_block_flash_write(const char *part_name, void *download_buffer,
u32 download_bytes, char *response)
+{
- struct blk_desc *dev_desc;
- struct disk_partition part_info;
- if (fastboot_block_get_part_info(part_name, &dev_desc, &part_info, response) < 0)
return;
- if (is_sparse_image(download_buffer)) {
fastboot_block_write_sparse_image(dev_desc, &part_info, part_name,
download_buffer, response);
- } else {
fastboot_block_write_raw_image(dev_desc, &part_info, part_name,
download_buffer, download_bytes, response);
- }
+} diff --git a/drivers/fastboot/fb_mmc.c b/drivers/fastboot/fb_mmc.c index 060918e491..7894f01f63 100644 --- a/drivers/fastboot/fb_mmc.c +++ b/drivers/fastboot/fb_mmc.c @@ -9,6 +9,7 @@ #include <env.h> #include <fastboot.h> #include <fastboot-internal.h> +#include <fb_block.h> #include <fb_mmc.h> #include <image-sparse.h> #include <image.h> @@ -21,10 +22,6 @@
#define BOOT_PARTITION_NAME "boot"
-struct fb_mmc_sparse {
- struct blk_desc *dev_desc;
-};
static int raw_part_get_info_by_name(struct blk_desc *dev_desc, const char *name, struct disk_partition *info) @@ -115,88 +112,6 @@ static int part_get_info_by_name_or_alias(struct blk_desc **dev_desc, return do_get_part_info(dev_desc, name, info); }
-/**
- fb_mmc_blk_write() - Write/erase MMC in chunks of FASTBOOT_MAX_BLK_WRITE
- @block_dev: Pointer to block device
- @start: First block to write/erase
- @blkcnt: Count of blocks
- @buffer: Pointer to data buffer for write or NULL for erase
- */
-static lbaint_t fb_mmc_blk_write(struct blk_desc *block_dev, lbaint_t start,
lbaint_t blkcnt, const void *buffer)
-{
- lbaint_t blk = start;
- lbaint_t blks_written;
- lbaint_t cur_blkcnt;
- lbaint_t blks = 0;
- int i;
- for (i = 0; i < blkcnt; i += FASTBOOT_MAX_BLK_WRITE) {
cur_blkcnt = min((int)blkcnt - i, FASTBOOT_MAX_BLK_WRITE);
if (buffer) {
if (fastboot_progress_callback)
fastboot_progress_callback("writing");
blks_written = blk_dwrite(block_dev, blk, cur_blkcnt,
buffer + (i * block_dev->blksz));
} else {
if (fastboot_progress_callback)
fastboot_progress_callback("erasing");
blks_written = blk_derase(block_dev, blk, cur_blkcnt);
}
blk += blks_written;
blks += blks_written;
- }
- return blks;
-}
-static lbaint_t fb_mmc_sparse_write(struct sparse_storage *info,
lbaint_t blk, lbaint_t blkcnt, const void *buffer)
-{
- struct fb_mmc_sparse *sparse = info->priv;
- struct blk_desc *dev_desc = sparse->dev_desc;
- return fb_mmc_blk_write(dev_desc, blk, blkcnt, buffer);
-}
-static lbaint_t fb_mmc_sparse_reserve(struct sparse_storage *info,
lbaint_t blk, lbaint_t blkcnt)
-{
- return blkcnt;
-}
-static void write_raw_image(struct blk_desc *dev_desc,
struct disk_partition *info, const char *part_name,
void *buffer, u32 download_bytes, char *response)
-{
- lbaint_t blkcnt;
- lbaint_t blks;
- /* determine number of blocks to write */
- blkcnt = ((download_bytes + (info->blksz - 1)) & ~(info->blksz - 1));
- blkcnt = lldiv(blkcnt, info->blksz);
- if (blkcnt > info->size) {
pr_err("too large for partition: '%s'\n", part_name);
fastboot_fail("too large for partition", response);
return;
- }
- puts("Flashing Raw Image\n");
- blks = fb_mmc_blk_write(dev_desc, info->start, blkcnt, buffer);
- if (blks != blkcnt) {
pr_err("failed writing to device %d\n", dev_desc->devnum);
fastboot_fail("failed writing to device", response);
return;
- }
- printf("........ wrote " LBAFU " bytes to '%s'\n", blkcnt * info->blksz,
part_name);
- fastboot_okay(NULL, response);
-}
#if defined(CONFIG_FASTBOOT_MMC_BOOT_SUPPORT) || \ defined(CONFIG_FASTBOOT_MMC_USER_SUPPORT) static int fb_mmc_erase_mmc_hwpart(struct blk_desc *dev_desc) @@ -205,7 +120,7 @@ static int fb_mmc_erase_mmc_hwpart(struct blk_desc *dev_desc)
debug("Start Erasing mmc hwpart[%u]...\n", dev_desc->hwpart);
- blks = fb_mmc_blk_write(dev_desc, 0, dev_desc->lba, NULL);
blks = fb_block_write(dev_desc, 0, dev_desc->lba, NULL);
if (blks != dev_desc->lba) { pr_err("Failed to erase mmc hwpart[%u]\n", dev_desc->hwpart);
@@ -249,7 +164,7 @@ static void fb_mmc_boot_ops(struct blk_desc *dev_desc, void *buffer,
debug("Start Flashing Image to EMMC_BOOT%d...\n", hwpart);
blks = fb_mmc_blk_write(dev_desc, 0, blkcnt, buffer);
blks = fb_block_write(dev_desc, 0, blkcnt, buffer);
if (blks != blkcnt) { pr_err("Failed to write EMMC_BOOT%d\n", hwpart);
@@ -610,30 +525,11 @@ void fastboot_mmc_flash_write(const char *cmd, void *download_buffer, return;
if (is_sparse_image(download_buffer)) {
struct fb_mmc_sparse sparse_priv;
struct sparse_storage sparse;
int err;
sparse_priv.dev_desc = dev_desc;
sparse.blksz = info.blksz;
sparse.start = info.start;
sparse.size = info.size;
sparse.write = fb_mmc_sparse_write;
sparse.reserve = fb_mmc_sparse_reserve;
sparse.mssg = fastboot_fail;
printf("Flashing sparse image at offset " LBAFU "\n",
sparse.start);
sparse.priv = &sparse_priv;
err = write_sparse_image(&sparse, cmd, download_buffer,
response);
if (!err)
fastboot_okay(NULL, response);
fastboot_block_write_sparse_image(dev_desc, &info, cmd,
} else {download_buffer, response);
write_raw_image(dev_desc, &info, cmd, download_buffer,
download_bytes, response);
fastboot_block_write_raw_image(dev_desc, &info, cmd, download_buffer,
}download_bytes, response);
}
@@ -697,7 +593,7 @@ void fastboot_mmc_erase(const char *cmd, char *response) printf("Erasing blocks " LBAFU " to " LBAFU " due to alignment\n", blks_start, blks_start + blks_size);
- blks = fb_mmc_blk_write(dev_desc, blks_start, blks_size, NULL);
blks = fb_block_write(dev_desc, blks_start, blks_size, NULL);
if (blks != blks_size) { pr_err("failed erasing from device %d\n", dev_desc->devnum);
diff --git a/include/fb_block.h b/include/fb_block.h new file mode 100644 index 0000000000..90208e21a7 --- /dev/null +++ b/include/fb_block.h @@ -0,0 +1,70 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/*
- Copyright (C) 2024 The Android Open Source Project
- */
+#ifndef _FB_BLOCK_H_ +#define _FB_BLOCK_H_
+struct blk_desc; +struct disk_partition;
+/**
- fastboot_block_get_part_info() - Lookup block partition by name
- @part_name: Named partition to lookup
- @dev_desc: Pointer to returned blk_desc pointer
- @part_info: Pointer to returned struct disk_partition
- @response: Pointer to fastboot response buffer
- */
+int fastboot_block_get_part_info(const char *part_name,
struct blk_desc **dev_desc,
struct disk_partition *part_info,
char *response);
+/**
- fastboot_block_erase() - Erase partition on block device for fastboot
- @part_name: Named partition to erase
- @response: Pointer to fastboot response buffer
- */
+void fastboot_block_erase(const char *part_name, char *response);
+/**
- fastboot_block_write_raw_image() - Write raw image to block device
- @dev_desc: Block device we're going write to
- @info: Partition we're going write to
- @part_name: Name of partition we're going write to
- @buffer: Downloaded buffer pointer
- @download_bytes: Size of content on downloaded buffer pointer
- @response: Pointer to fastboot response buffer
- */
+void fastboot_block_write_raw_image(struct blk_desc *dev_desc,
struct disk_partition *info, const char *part_name,
void *buffer, u32 download_bytes, char *response);
+/**
- fastboot_block_write_sparse_image() - Write sparse image to block device
- @dev_desc: Block device we're going write to
- @info: Partition we're going write to
- @part_name: Name of partition we're going write to
- @buffer: Downloaded buffer pointer
- @response: Pointer to fastboot response buffer
- */
+void fastboot_block_write_sparse_image(struct blk_desc *dev_desc, struct disk_partition *info,
const char *part_name, void *buffer, char *response);
+/**
- fastboot_block_flash_write() - Write image to block device for fastboot
- @part_name: Named partition to write image to
- @download_buffer: Pointer to image data
- @download_bytes: Size of image data
- @response: Pointer to fastboot response buffer
- */
+void fastboot_block_flash_write(const char *part_name, void *download_buffer,
u32 download_bytes, char *response);
+#endif // _FB_BLOCK_H_
2.44.0.278.ge034bb2e1d-goog

1. Get partition info/size 2. Erase partition 3. Flash partition 4. BCB
Signed-off-by: Dmitrii Merkurev dimorinny@google.com Cc: Alex Kiernan alex.kiernan@gmail.com Cc: Patrick Delaunay patrick.delaunay@foss.st.com Cc: Simon Glass sjg@chromium.org Cc: Mattijs Korpershoek mkorpershoek@baylibre.com Cc: Ying-Chun Liu (PaulLiu) paul.liu@linaro.org --- drivers/fastboot/fb_command.c | 8 ++++++++ drivers/fastboot/fb_common.c | 15 +++++++++++---- drivers/fastboot/fb_getvar.c | 8 +++++++- 3 files changed, 26 insertions(+), 5 deletions(-)
diff --git a/drivers/fastboot/fb_command.c b/drivers/fastboot/fb_command.c index f95f4e4ae1..67ebe02efa 100644 --- a/drivers/fastboot/fb_command.c +++ b/drivers/fastboot/fb_command.c @@ -9,6 +9,7 @@ #include <env.h> #include <fastboot.h> #include <fastboot-internal.h> +#include <fb_block.h> #include <fb_mmc.h> #include <fb_nand.h> #include <part.h> @@ -331,6 +332,10 @@ void fastboot_data_complete(char *response) */ static void __maybe_unused flash(char *cmd_parameter, char *response) { + if (IS_ENABLED(CONFIG_FASTBOOT_FLASH_BLOCK)) + fastboot_block_flash_write(cmd_parameter, fastboot_buf_addr, + image_size, response); + if (IS_ENABLED(CONFIG_FASTBOOT_FLASH_MMC)) fastboot_mmc_flash_write(cmd_parameter, fastboot_buf_addr, image_size, response); @@ -351,6 +356,9 @@ static void __maybe_unused flash(char *cmd_parameter, char *response) */ static void __maybe_unused erase(char *cmd_parameter, char *response) { + if (IS_ENABLED(CONFIG_FASTBOOT_FLASH_BLOCK)) + fastboot_block_erase(cmd_parameter, response); + if (IS_ENABLED(CONFIG_FASTBOOT_FLASH_MMC)) fastboot_mmc_erase(cmd_parameter, response);
diff --git a/drivers/fastboot/fb_common.c b/drivers/fastboot/fb_common.c index 3576b06772..7602653c0b 100644 --- a/drivers/fastboot/fb_common.c +++ b/drivers/fastboot/fb_common.c @@ -97,16 +97,23 @@ int __weak fastboot_set_reboot_flag(enum fastboot_reboot_reason reason) [FASTBOOT_REBOOT_REASON_FASTBOOTD] = "boot-fastboot", [FASTBOOT_REBOOT_REASON_RECOVERY] = "boot-recovery" }; - const int mmc_dev = config_opt_enabled(CONFIG_FASTBOOT_FLASH_MMC, - CONFIG_FASTBOOT_FLASH_MMC_DEV, -1);
- if (!IS_ENABLED(CONFIG_FASTBOOT_FLASH_MMC)) + int device = config_opt_enabled(CONFIG_FASTBOOT_FLASH_BLOCK, + CONFIG_FASTBOOT_FLASH_BLOCK_DEVICE_ID, -1); + if (device == -1) { + device = config_opt_enabled(CONFIG_FASTBOOT_FLASH_MMC, + CONFIG_FASTBOOT_FLASH_MMC_DEV, -1); + } + char *bcb_iface = config_opt_enabled(CONFIG_FASTBOOT_FLASH_BLOCK, + CONFIG_FASTBOOT_FLASH_BLOCK_INTERFACE_NAME, "mmc"); + + if (device == -1) return -EINVAL;
if (reason >= FASTBOOT_REBOOT_REASONS_COUNT) return -EINVAL;
- ret = bcb_find_partition_and_load("mmc", mmc_dev, "misc"); + ret = bcb_find_partition_and_load(bcb_iface, device, "misc"); if (ret) goto out;
diff --git a/drivers/fastboot/fb_getvar.c b/drivers/fastboot/fb_getvar.c index f65519c57b..71507009ab 100644 --- a/drivers/fastboot/fb_getvar.c +++ b/drivers/fastboot/fb_getvar.c @@ -8,6 +8,7 @@ #include <fastboot.h> #include <fastboot-internal.h> #include <fb_mmc.h> +#include <fb_block.h> #include <fb_nand.h> #include <fs.h> #include <part.h> @@ -114,7 +115,12 @@ static int getvar_get_part_info(const char *part_name, char *response, struct disk_partition disk_part; struct part_info *part_info;
- if (IS_ENABLED(CONFIG_FASTBOOT_FLASH_MMC)) { + if (IS_ENABLED(CONFIG_FASTBOOT_FLASH_BLOCK)) { + r = fastboot_block_get_part_info(part_name, &dev_desc, &disk_part, + response); + if (r >= 0 && size) + *size = disk_part.size * disk_part.blksz; + } else if (IS_ENABLED(CONFIG_FASTBOOT_FLASH_MMC)) { r = fastboot_mmc_get_part_info(part_name, &dev_desc, &disk_part, response); if (r >= 0 && size)

Hi Dmitrii,
Thank you for the patch and sorry for the review delay.
On mer., mars 06, 2024 at 18:59, Dmitrii Merkurev dimorinny@google.com wrote:
- Get partition info/size
- Erase partition
- Flash partition
- BCB
Signed-off-by: Dmitrii Merkurev dimorinny@google.com Cc: Alex Kiernan alex.kiernan@gmail.com Cc: Patrick Delaunay patrick.delaunay@foss.st.com Cc: Simon Glass sjg@chromium.org Cc: Mattijs Korpershoek mkorpershoek@baylibre.com Cc: Ying-Chun Liu (PaulLiu) paul.liu@linaro.org
drivers/fastboot/fb_command.c | 8 ++++++++ drivers/fastboot/fb_common.c | 15 +++++++++++---- drivers/fastboot/fb_getvar.c | 8 +++++++- 3 files changed, 26 insertions(+), 5 deletions(-)
diff --git a/drivers/fastboot/fb_command.c b/drivers/fastboot/fb_command.c index f95f4e4ae1..67ebe02efa 100644 --- a/drivers/fastboot/fb_command.c +++ b/drivers/fastboot/fb_command.c @@ -9,6 +9,7 @@ #include <env.h> #include <fastboot.h> #include <fastboot-internal.h> +#include <fb_block.h> #include <fb_mmc.h> #include <fb_nand.h> #include <part.h> @@ -331,6 +332,10 @@ void fastboot_data_complete(char *response) */ static void __maybe_unused flash(char *cmd_parameter, char *response) {
- if (IS_ENABLED(CONFIG_FASTBOOT_FLASH_BLOCK))
fastboot_block_flash_write(cmd_parameter, fastboot_buf_addr,
image_size, response);
- if (IS_ENABLED(CONFIG_FASTBOOT_FLASH_MMC)) fastboot_mmc_flash_write(cmd_parameter, fastboot_buf_addr, image_size, response);
@@ -351,6 +356,9 @@ static void __maybe_unused flash(char *cmd_parameter, char *response) */ static void __maybe_unused erase(char *cmd_parameter, char *response) {
- if (IS_ENABLED(CONFIG_FASTBOOT_FLASH_BLOCK))
fastboot_block_erase(cmd_parameter, response);
- if (IS_ENABLED(CONFIG_FASTBOOT_FLASH_MMC)) fastboot_mmc_erase(cmd_parameter, response);
diff --git a/drivers/fastboot/fb_common.c b/drivers/fastboot/fb_common.c index 3576b06772..7602653c0b 100644 --- a/drivers/fastboot/fb_common.c +++ b/drivers/fastboot/fb_common.c @@ -97,16 +97,23 @@ int __weak fastboot_set_reboot_flag(enum fastboot_reboot_reason reason) [FASTBOOT_REBOOT_REASON_FASTBOOTD] = "boot-fastboot", [FASTBOOT_REBOOT_REASON_RECOVERY] = "boot-recovery" };
const int mmc_dev = config_opt_enabled(CONFIG_FASTBOOT_FLASH_MMC,
CONFIG_FASTBOOT_FLASH_MMC_DEV, -1);
if (!IS_ENABLED(CONFIG_FASTBOOT_FLASH_MMC))
- int device = config_opt_enabled(CONFIG_FASTBOOT_FLASH_BLOCK,
CONFIG_FASTBOOT_FLASH_BLOCK_DEVICE_ID, -1);
- if (device == -1) {
device = config_opt_enabled(CONFIG_FASTBOOT_FLASH_MMC,
CONFIG_FASTBOOT_FLASH_MMC_DEV, -1);
- }
- char *bcb_iface = config_opt_enabled(CONFIG_FASTBOOT_FLASH_BLOCK,
Can this be made const?
With the above addressed:
Reviewed-by: Mattijs Korpershoek mkorpershoek@baylibre.com
CONFIG_FASTBOOT_FLASH_BLOCK_INTERFACE_NAME, "mmc");
if (device == -1) return -EINVAL;
if (reason >= FASTBOOT_REBOOT_REASONS_COUNT) return -EINVAL;
- ret = bcb_find_partition_and_load("mmc", mmc_dev, "misc");
- ret = bcb_find_partition_and_load(bcb_iface, device, "misc"); if (ret) goto out;
diff --git a/drivers/fastboot/fb_getvar.c b/drivers/fastboot/fb_getvar.c index f65519c57b..71507009ab 100644 --- a/drivers/fastboot/fb_getvar.c +++ b/drivers/fastboot/fb_getvar.c @@ -8,6 +8,7 @@ #include <fastboot.h> #include <fastboot-internal.h> #include <fb_mmc.h> +#include <fb_block.h> #include <fb_nand.h> #include <fs.h> #include <part.h> @@ -114,7 +115,12 @@ static int getvar_get_part_info(const char *part_name, char *response, struct disk_partition disk_part; struct part_info *part_info;
- if (IS_ENABLED(CONFIG_FASTBOOT_FLASH_MMC)) {
- if (IS_ENABLED(CONFIG_FASTBOOT_FLASH_BLOCK)) {
r = fastboot_block_get_part_info(part_name, &dev_desc, &disk_part,
response);
if (r >= 0 && size)
*size = disk_part.size * disk_part.blksz;
- } else if (IS_ENABLED(CONFIG_FASTBOOT_FLASH_MMC)) { r = fastboot_mmc_get_part_info(part_name, &dev_desc, &disk_part, response); if (r >= 0 && size)
-- 2.44.0.278.ge034bb2e1d-goog

Hi Dmitrii,
Thank you for the patch.
I'm not the virtio maintainer in U-Boot:
/mnt/work/upstream/u-boot/ $ ./scripts/get_maintainer.pl drivers/virtio/ Bin Meng bmeng.cn@gmail.com (maintainer:VirtIO) [...]
I've added Bin to the Cc list, please include him if you re-submit.
On mer., mars 06, 2024 at 18:59, Dmitrii Merkurev dimorinny@google.com wrote:
Co-developed-by: Cody Schuffelen schuffelen@google.com Signed-off-by: Cody Schuffelen schuffelen@google.com Signed-off-by: Dmitrii Merkurev dimorinny@google.com Cc: Tuomas Tynkkynen tuomas.tynkkynen@iki.fi Cc: Simon Glass sjg@chromium.org Cc: Mattijs Korpershoek mkorpershoek@baylibre.com Cc: Ying-Chun Liu (PaulLiu) paul.liu@linaro.org
I'm not super familiar with virtio, so I've not reviewed this.
However, I tested the sandbox unit tests:
uboot@db354723333a:/mnt/work/upstream/u-boot$ ./u-boot -T -c "ut dm virtio*" Bloblist at b000 not found (err=-2) sandbox_serial serial: pinctrl_select_state_full: uclass_get_device_by_phandle_id: err=-19
U-Boot 2024.04-00137-g075feb52299 (Apr 05 2024 - 07:12:35 +0000)
Reset Status: WARM Reset Status: COLD Model: sandbox DRAM: 256 MiB [nvmxip-qspi1@08000000]: the block device blk#2 ready for use [nvmxip-qspi2@08200000]: the block device blk#2 ready for use Core: 286 devices, 101 uclasses, devicetree: board WDT: Not starting wdt-gpio-toggle WDT: Not starting wdt-gpio-level WDT: Not starting wdt@0 NAND: 4100 MiB MMC: mmc2: 2 (SD), mmc1: 1 (SD), mmc0: 0 (SD) Loading Environment from nowhere... OK In: serial,cros-ec-keyb,usbkbd Out: serial,vidconsole Err: serial,vidconsole Model: sandbox Net: eth0: eth@10002000, eth5: eth@10003000, eth3: sbe5, eth6: eth@10004000, eth8: phy-test-eth, eth4: dsa-test-eth, eth2: lan0, eth7: lan1 Test: dm_test_virtio_all_ops: virtio_device.c Test: dm_test_virtio_all_ops: virtio_device.c (flat tree) Test: dm_test_virtio_base: virtio_device.c Test: dm_test_virtio_base: virtio_device.c (flat tree) Test: dm_test_virtio_missing_ops: virtio.c Test: dm_test_virtio_missing_ops: virtio.c (flat tree) Test: dm_test_virtio_remove: virtio_device.c Test: dm_test_virtio_remove: virtio_device.c (flat tree) Test: dm_test_virtio_ring: virtio_device.c Test: dm_test_virtio_ring: virtio_device.c (flat tree) Test: dm_test_virtio_rng_check_len: virtio_rng.c Test: dm_test_virtio_rng_check_len: virtio_rng.c (flat tree) Failures: 0
Tested-by: Mattijs Korpershoek mkorpershoek@baylibre.com # sandbox
drivers/virtio/virtio_blk.c | 91 +++++++++++++++++++++++++++++++------ drivers/virtio/virtio_blk.h | 47 +++++++++++++++++++ 2 files changed, 124 insertions(+), 14 deletions(-)
diff --git a/drivers/virtio/virtio_blk.c b/drivers/virtio/virtio_blk.c index 9581058286..225b65c4d1 100644 --- a/drivers/virtio/virtio_blk.c +++ b/drivers/virtio/virtio_blk.c @@ -19,30 +19,82 @@ struct virtio_blk_priv { struct virtqueue *vq; };
+static const u32 feature[] = {
- VIRTIO_BLK_F_WRITE_ZEROES
+};
+static void virtio_blk_init_header_sg(struct udevice *dev, u64 sector, u32 type,
struct virtio_blk_outhdr *out_hdr, struct virtio_sg *sg)
+{
- const bool sector_is_needed = type == VIRTIO_BLK_T_IN ||
type == VIRTIO_BLK_T_OUT;
- out_hdr->type = cpu_to_virtio32(dev, type);
- out_hdr->sector = cpu_to_virtio64(dev, sector_is_needed ? sector : 0);
- sg->addr = out_hdr;
- sg->length = sizeof(*out_hdr);
+}
+static void virtio_blk_init_write_zeroes_sg(struct udevice *dev, u64 sector, lbaint_t blkcnt,
struct virtio_blk_discard_write_zeroes *wz,
struct virtio_sg *sg)
+{
- wz->sector = cpu_to_virtio64(dev, sector);
- wz->num_sectors = cpu_to_virtio32(dev, blkcnt);
- wz->flags = cpu_to_virtio32(dev, 0);
- sg->addr = wz;
- sg->length = sizeof(*wz);
+}
+static void virtio_blk_init_status_sg(u8 *status, struct virtio_sg *sg) +{
- sg->addr = status;
- sg->length = sizeof(*status);
+}
+static void virtio_blk_init_data_sg(void *buffer, lbaint_t blkcnt, struct virtio_sg *sg) +{
- sg->addr = buffer;
- sg->length = blkcnt * 512;
+}
static ulong virtio_blk_do_req(struct udevice *dev, u64 sector, lbaint_t blkcnt, void *buffer, u32 type) { struct virtio_blk_priv *priv = dev_get_priv(dev);
- struct virtio_blk_outhdr out_hdr;
- struct virtio_blk_discard_write_zeroes wz_hdr; unsigned int num_out = 0, num_in = 0;
- struct virtio_sg hdr_sg, wz_sg, data_sg, status_sg; struct virtio_sg *sgs[3]; u8 status; int ret;
- struct virtio_blk_outhdr out_hdr = {
.type = cpu_to_virtio32(dev, type),
.sector = cpu_to_virtio64(dev, sector),
- };
- struct virtio_sg hdr_sg = { &out_hdr, sizeof(out_hdr) };
- struct virtio_sg data_sg = { buffer, blkcnt * 512 };
- struct virtio_sg status_sg = { &status, sizeof(status) };
- virtio_blk_init_header_sg(dev, sector, type, &out_hdr, &hdr_sg); sgs[num_out++] = &hdr_sg;
- if (type & VIRTIO_BLK_T_OUT)
sgs[num_out++] = &data_sg;
- else
sgs[num_out + num_in++] = &data_sg;
- switch (type) {
- case VIRTIO_BLK_T_IN:
- case VIRTIO_BLK_T_OUT:
virtio_blk_init_data_sg(buffer, blkcnt, &data_sg);
if (type & VIRTIO_BLK_T_OUT)
sgs[num_out++] = &data_sg;
else
sgs[num_out + num_in++] = &data_sg;
break;
- case VIRTIO_BLK_T_WRITE_ZEROES:
virtio_blk_init_write_zeroes_sg(dev, sector, blkcnt, &wz_hdr, &wz_sg);
sgs[num_out++] = &wz_sg;
break;
- default:
return -EINVAL;
- }
- virtio_blk_init_status_sg(&status, &status_sg); sgs[num_out + num_in++] = &status_sg; log_debug("dev=%s, active=%d, priv=%p, priv->vq=%p\n", dev->name, device_active(dev), priv, priv->vq);
@@ -76,6 +128,15 @@ static ulong virtio_blk_write(struct udevice *dev, lbaint_t start, VIRTIO_BLK_T_OUT); }
+static ulong virtio_blk_erase(struct udevice *dev, lbaint_t start,
lbaint_t blkcnt)
+{
- if (!virtio_has_feature(dev, VIRTIO_BLK_F_WRITE_ZEROES))
return -EOPNOTSUPP;
- return virtio_blk_do_req(dev, start, blkcnt, NULL, VIRTIO_BLK_T_WRITE_ZEROES);
+}
static int virtio_blk_bind(struct udevice *dev) { struct virtio_dev_priv *uc_priv = dev_get_uclass_priv(dev->parent); @@ -105,7 +166,8 @@ static int virtio_blk_bind(struct udevice *dev) desc->bdev = dev;
/* Indicate what driver features we support */
- virtio_driver_features_init(uc_priv, NULL, 0, NULL, 0);
virtio_driver_features_init(uc_priv, feature, ARRAY_SIZE(feature),
NULL, 0);
return 0;
} @@ -132,6 +194,7 @@ static int virtio_blk_probe(struct udevice *dev) static const struct blk_ops virtio_blk_ops = { .read = virtio_blk_read, .write = virtio_blk_write,
- .erase = virtio_blk_erase,
};
U_BOOT_DRIVER(virtio_blk) = { diff --git a/drivers/virtio/virtio_blk.h b/drivers/virtio/virtio_blk.h index 8d8e02fa2e..b37ba264df 100644 --- a/drivers/virtio/virtio_blk.h +++ b/drivers/virtio/virtio_blk.h @@ -17,6 +17,8 @@ #define VIRTIO_BLK_F_BLK_SIZE 6 /* Block size of disk is available */ #define VIRTIO_BLK_F_TOPOLOGY 10 /* Topology information is available */ #define VIRTIO_BLK_F_MQ 12 /* Support more than one vq */ +#define VIRTIO_BLK_F_DISCARD 13 /* Discard is supported */ +#define VIRTIO_BLK_F_WRITE_ZEROES 14 /* Write zeroes is supported */
/* Legacy feature bits */ #ifndef VIRTIO_BLK_NO_LEGACY @@ -65,6 +67,39 @@ struct __packed virtio_blk_config {
/* number of vqs, only available when VIRTIO_BLK_F_MQ is set */ __u16 num_queues;
- /* the next 3 entries are guarded by VIRTIO_BLK_F_DISCARD */
- /*
* The maximum discard sectors (in 512-byte sectors) for
* one segment.
*/
- __u32 max_discard_sectors;
- /*
* The maximum number of discard segments in a
* discard command.
*/
- __u32 max_discard_seg;
- /* Discard commands must be aligned to this number of sectors. */
- __u32 discard_sector_alignment;
- /* the next 3 entries are guarded by VIRTIO_BLK_F_WRITE_ZEROES */
- /*
* The maximum number of write zeroes sectors (in 512-byte sectors) in
* one segment.
*/
- __u32 max_write_zeroes_sectors;
- /*
* The maximum number of segments in a write zeroes
* command.
*/
- __u32 max_write_zeroes_seg;
- /*
* Set if a VIRTIO_BLK_T_WRITE_ZEROES request may result in the
* deallocation of one or more of the sectors.
*/
- __u8 write_zeroes_may_unmap;
- __u8 unused1[3];
};
/* @@ -93,6 +128,9 @@ struct __packed virtio_blk_config { /* Get device ID command */ #define VIRTIO_BLK_T_GET_ID 8
+/* Write zeroes command */ +#define VIRTIO_BLK_T_WRITE_ZEROES 13
#ifndef VIRTIO_BLK_NO_LEGACY /* Barrier before this op */ #define VIRTIO_BLK_T_BARRIER 0x80000000 @@ -112,6 +150,15 @@ struct virtio_blk_outhdr { __virtio64 sector; };
+struct virtio_blk_discard_write_zeroes {
- /* discard/write zeroes start sector */
- __virtio64 sector;
- /* number of discard/write zeroes sectors */
- __virtio32 num_sectors;
- /* flags for this range */
- __virtio32 flags;
+};
#ifndef VIRTIO_BLK_NO_LEGACY struct virtio_scsi_inhdr { __virtio32 errors; -- 2.44.0.278.ge034bb2e1d-goog

Hi Dmitrii,
Thank you for the patch.
I'm not the virtio maintainer in U-Boot:
/mnt/work/upstream/u-boot/ $ ./scripts/get_maintainer.pl drivers/virtio/ Bin Meng bmeng.cn@gmail.com (maintainer:VirtIO) [...]
I've added Bin to the Cc list, please include him if you re-submit.
On mer., mars 06, 2024 at 18:59, Dmitrii Merkurev dimorinny@google.com wrote:
Co-developed-by: Cody Schuffelen schuffelen@google.com Signed-off-by: Cody Schuffelen schuffelen@google.com Signed-off-by: Dmitrii Merkurev dimorinny@google.com Cc: Tuomas Tynkkynen tuomas.tynkkynen@iki.fi Cc: Simon Glass sjg@chromium.org Cc: Mattijs Korpershoek mkorpershoek@baylibre.com Cc: Ying-Chun Liu (PaulLiu) paul.liu@linaro.org
I'm not super familiar with virtio, so I've not reviewed this.
However, I tested the sandbox unit tests:
uboot@db354723333a:/mnt/work/upstream/u-boot$ ./u-boot -T -c "ut dm virtio*" Bloblist at b000 not found (err=-2) sandbox_serial serial: pinctrl_select_state_full: uclass_get_device_by_phandle_id: err=-19
U-Boot 2024.04-00137-g075feb52299 (Apr 05 2024 - 07:12:35 +0000)
Reset Status: WARM Reset Status: COLD Model: sandbox DRAM: 256 MiB [nvmxip-qspi1@08000000]: the block device blk#2 ready for use [nvmxip-qspi2@08200000]: the block device blk#2 ready for use Core: 286 devices, 101 uclasses, devicetree: board WDT: Not starting wdt-gpio-toggle WDT: Not starting wdt-gpio-level WDT: Not starting wdt@0 NAND: 4100 MiB MMC: mmc2: 2 (SD), mmc1: 1 (SD), mmc0: 0 (SD) Loading Environment from nowhere... OK In: serial,cros-ec-keyb,usbkbd Out: serial,vidconsole Err: serial,vidconsole Model: sandbox Net: eth0: eth@10002000, eth5: eth@10003000, eth3: sbe5, eth6: eth@10004000, eth8: phy-test-eth, eth4: dsa-test-eth, eth2: lan0, eth7: lan1 Test: dm_test_virtio_all_ops: virtio_device.c Test: dm_test_virtio_all_ops: virtio_device.c (flat tree) Test: dm_test_virtio_base: virtio_device.c Test: dm_test_virtio_base: virtio_device.c (flat tree) Test: dm_test_virtio_missing_ops: virtio.c Test: dm_test_virtio_missing_ops: virtio.c (flat tree) Test: dm_test_virtio_remove: virtio_device.c Test: dm_test_virtio_remove: virtio_device.c (flat tree) Test: dm_test_virtio_ring: virtio_device.c Test: dm_test_virtio_ring: virtio_device.c (flat tree) Test: dm_test_virtio_rng_check_len: virtio_rng.c Test: dm_test_virtio_rng_check_len: virtio_rng.c (flat tree) Failures: 0
Tested-by: Mattijs Korpershoek mkorpershoek@baylibre.com # sandbox
drivers/virtio/virtio_blk.c | 91 +++++++++++++++++++++++++++++++------ drivers/virtio/virtio_blk.h | 47 +++++++++++++++++++ 2 files changed, 124 insertions(+), 14 deletions(-)
Applied to u-boot-dm, thanks!
participants (4)
-
Dmitrii Merkurev
-
Mattijs Korpershoek
-
neil.armstrong@linaro.org
-
Simon Glass