[PATCH v2 00/24] blk: Rationalise the block interface

Johan Jonker jbx6244 at gmail.com
Sun Aug 14 08:33:55 CEST 2022



On 8/12/22 17:11, Simon Glass wrote:
> Hi Johan,
> 
> On Fri, 12 Aug 2022 at 07:51, Johan Jonker <jbx6244 at gmail.com> wrote:
>>
>> Hi Simon and others,
>>
>> Some comments. Have a look if it's useful.
>> Include is an example of how currently a new Rockchip external RKNAND FTL block device must be included in U-boot.
>> Changes must be made all over the place. EFI has now become a somewhat "obligation" for block devices, then handling
>> should be made more easy I propose.
>>
>> 1:
>> The creation and removal of block devices is kind of dynamic with the blk_create_device function.
>> Is it possible to make the necessary functions in efi_device_path.c and part.c more flexible as well by
>> a new "blk_create_efi_device()" and "blk_remove_efi_device()" function? So everything combined in one function.
> 
> Do you mean to automatically create a device with the right uclass?
> Yes I think that could be done, but I have not looked at it.

Hi,

Some comments...
Reduced the number of public CC's.
I have included a patch with call back function as example, so efi_device_path.c and part.c don't have to be changed for every new block device.
Make EFI framework code without class specific things.
TODO define	{ UCLASS_XXXXX, "xxxxx" }, in class driver and not in a fixed array.
Look up for xxxxx ==> UCLASS_XXXXX needs a lot more work which is out of scope for my capacity now.

Kind regards,

Johan Jonker

===

This list name should be specified in the class driver.
Lookup functions need a rework then to get rid of this fixed array.


static struct {
	enum uclass_id id;
	const char *name;
} uclass_idname_str[] = {
	{ UCLASS_IDE, "ide" },
	{ UCLASS_SCSI, "scsi" },
	{ UCLASS_USB, "usb" },
	{ UCLASS_MMC,  "mmc" },
	{ UCLASS_AHCI, "sata" },
	{ UCLASS_ROOT, "host" },
	{ UCLASS_NVME, "nvme" },
	{ UCLASS_EFI_MEDIA, "efi" },
	{ UCLASS_EFI_LOADER, "efiloader" },
	{ UCLASS_VIRTIO, "virtio" },
	{ UCLASS_PVBLOCK, "pvblock" },
	{ UCLASS_RKNAND, "rknand" },
};

===
Example for new call back functions:

void rknand_part_header(struct blk_desc *dev_desc)
{
	puts("RKNAND");
}

void rknand_dev_print(struct blk_desc *dev_desc)
{
	printf ("Vendor: %s Rev: %s Prod: %s\n",
		dev_desc->vendor,
		dev_desc->revision,
		dev_desc->product);
}

extern unsigned int dp_size(struct udevice *dev);
extern void *dp_fill(void *buf, struct udevice *dev);

/* GUID used as root for Rockchip RKNAND devices */
#define U_BOOT_RKNAND_DEV_GUID \
	EFI_GUID(0xe39f6cbb, 0x055a, 0x45a0, \
		 0xb2, 0x75, 0x56, 0x0d, 0xa5, 0x22, 0x25, 0x99)

const efi_guid_t efi_guid_rknand_dev = U_BOOT_RKNAND_DEV_GUID;

unsigned int rknand_dp_size(struct udevice *dev)
{
	return dp_size(dev->parent) + sizeof(struct efi_device_path_vendor) + 1;
}

void *rknand_dp_fill(void *buf, struct udevice *dev)
{
	struct efi_device_path_vendor *dp;
	struct blk_desc *desc = dev_get_uclass_plat(dev);

	dp_fill(buf, dev->parent);
	dp = buf;
	++dp;
	dp->dp.type = DEVICE_PATH_TYPE_HARDWARE_DEVICE;
	dp->dp.sub_type = DEVICE_PATH_SUB_TYPE_VENDOR;
	dp->dp.length = sizeof(*dp) + 1;
	memcpy(&dp->guid, &efi_guid_rknand_dev, sizeof(efi_guid_t));
	dp->vendor_data[0] = desc->devnum;
	return &dp->vendor_data[1];
}

static int rknand_blk_probe(struct udevice *udev)
{
	struct rknand_dev *ndev = dev_get_priv(udev->parent);
	struct blk_desc *desc = dev_get_uclass_plat(udev);

	debug("%s %d %p ndev = %p %p\n", __func__, __LINE__,
	      udev, ndev, udev->parent);
	ndev->dev = udev;
	desc->uclass_id = UCLASS_RKNAND;
	desc->lba = ndev->density;
	desc->log2blksz = 9;
	desc->blksz = 512;
	desc->bdev = udev;
	desc->devnum = 0;

//======

/* new call back functions */

	desc->dev_print = &rknand_dev_print;
	desc->part_header = &rknand_part_header;
	udev->dp_size = &rknand_dp_size;
	udev->dp_fill = &rknand_dp_fill;

//======
	sprintf(desc->vendor, "0x%.4x", 0x2207);
	memcpy(desc->product, "rknand", sizeof("rknand"));
	memcpy(desc->revision, "V1.00", sizeof("V1.00"));
	part_init(desc);
	return 0;
}
===
> 
>>
>> 2:
>> Make the class list more dynamic/expendable. Each time a new clas is needed the source code must be changed.
>> Include a function that returns a generated class number that takes in account the existing know classes.
>> ie,: "uclass_create" and "uclass_remove".
>>
>> Example block device creation:
>>
>>         ret = uclass_get_device(UCLASS_RK_IDB, 0, &dev);
>>
>> // Be able to use a dynamic generated UCLASS for block devices.
>>
>>         if (ret) {
>>                 printf("no IDB device found\n");
>>                 return CMD_RET_FAILURE;
>>         }
>>         ret = blk_get_device(IF_TYPE_RK_IDB, 0, &bdev);
>>         if (ret) {
>>                 ret = blk_create_device(dev, "idb_blk", "blk",
>>                                         IF_TYPE_RK_IDB, 0, 512,
>>                                         LBA, &bdev);
>>                 if (ret)
>>                         return ret;
>>
>>                 ret = blk_probe_or_unbind(bdev);
>>                 if (ret)
>>                         return ret;
>>         }
>>
>> Example block device removal:
>>
>>         ret = blk_find_device(IF_TYPE_RK_IDB, 0, &bdev);
> 
> Note that the IF_TYPE goes away with this series and there is just the uclass.
> 
>>
>> // Be able to find back a dynamic generated UCLASS.
>>
>>         if (ret) {
>>                 printf("no IDB blk device found\n");
>>                 return 0;
>>         }
>>
>>         device_remove(bdev, DM_REMOVE_NORMAL);
>>         device_unbind(bdev);
>>
>> Make efi functions more flexible by replacing switch() functions by call back functions for:
>>
>> dp_fill
>> dp_size
>> dev_print
>> print_part_header
>>
>> Add them with "blk_create_efi_device()" in a structure.
>> If not defined fall back to standard functions.
> 
> We are trying to integrate EFI better into U-Boot so that it uses the
> normal devices. At present it has some parallel infrastructure.
> 
> Please take a look at your patch after applying this series, then let
> me know what you think is needed.
> 
> Regards,
> Simon
> 
> 
> 
>>
>> ====
>>
>> Kind regards,
>>
>> Johan Jonker
>>
>> On 8/12/22 03:34, Simon Glass wrote:
>>> The block interface has two separate implementations, one using driver
>>> model and one not. The latter is really only needed for SPL, where
>>> size constraints allegedly don't allow use of driver model. Of course
>>> we still need space for filesystems and other code, so it isn't clear
>>> that driver model is anything more than the straw that breaks the
>>> camel's back.
>>>
>>> The driver model version uses a uclass ID for the interface time, but
>>> converts back and forth between that and if_type, which is the legacy
>>> type.
>>>
>>> The HAVE_BLOCK_DEVICE define is mostly a hangover from the old days.
>>> At present its main purpose is to enable the legacy block implementation
>>> in SPL.
>>>
>>> Finally the use of 'select' to enable BLK does not work very well. It
>>> causes kconfig errors when another option depends on BLK and it is
>>> not recommended by the kconfig style guide.
>>>
>>> This series aims to clean things up:
>>> - Enable BLK based on whether different media types are used, but still
>>>   allow boards to disable it
>>> - Rename HAVE_BLOCK_DEVICE to indicates its real purpose
>>> - Drop if_type and use the uclass instead
>>> - Drop some obsolete if_type values
>>>
>>> An issue not resolved by this series is that the sandbox host interface
>>> does not actually have a device. At present it uses the root device, which
>>> was convenience for the driver model conversion but not really correct. It
>>> should be possible to clean this up, in a future series.
>>>
>>> Another minor issue is the use of UCLASS_USB for a mass-storage device.
>>> This has been the case for a while and is not addresed by this series,
>>> other than to add a comment.
>>>
>>> Note that this test relies on Tom Rini's series to drop various boards
>>> including warp and cm_t335
>>>
>>> Finally, a patch is included to make binman put fake files in a
>>> subdirectory, since repeated runs of certain boards can cause unrelated
>>> failues (e.g. chromebook_coral) when fake files are left around.
>>>
>>> Changes in v2:
>>> - Update commit message
>>> - Fix SPL_PARTITIONS too
>>> - Add SATA also
>>> - Refer to a suffix, not a prefix
>>> - Add new patch to handle UCLASS_EFI_MEDIA in dev_print()
>>> - Add new patch to drop ifname field from struct efi_disk_obj
>>> - Use conv_uclass_id() instead of the confusing uclass_id_to_uclass_id()
>>>
>>
>> From d0bb794b966a0134a6f321a414b48c28e8894180 Mon Sep 17 00:00:00 2001
>> From: Johan Jonker <jbx6244 at gmail.com>
>> Date: Sun, 7 Aug 2022 15:25:55 +0200
>> Subject: prepare rknand
>>
>>
>> diff --git a/disk/part.c b/disk/part.c
>> index 79955c7fb0..3f8b97a6c6 100644
>> --- a/disk/part.c
>> +++ b/disk/part.c
>> @@ -150,6 +150,7 @@ void dev_print (struct blk_desc *dev_desc)
>>         case IF_TYPE_USB:
>>         case IF_TYPE_NVME:
>>         case IF_TYPE_PVBLOCK:
>> +       case IF_TYPE_RKNAND:
>>         case IF_TYPE_HOST:
>>                 printf ("Vendor: %s Rev: %s Prod: %s\n",
>>                         dev_desc->vendor,
>> @@ -293,6 +294,9 @@ static void print_part_header(const char *type, struct blk_desc *dev_desc)
>>         case IF_TYPE_PVBLOCK:
>>                 puts("PV BLOCK");
>>                 break;
>> +       case IF_TYPE_RKNAND:
>> +               puts("RKNAND");
>> +               break;
>>         case IF_TYPE_VIRTIO:
>>                 puts("VirtIO");
>>                 break;
>> diff --git a/drivers/block/blk-uclass.c b/drivers/block/blk-uclass.c
>> index 0b5f219d90..28b21836c4 100644
>> --- a/drivers/block/blk-uclass.c
>> +++ b/drivers/block/blk-uclass.c
>> @@ -33,6 +33,7 @@ static const char *if_typename_str[IF_TYPE_COUNT] = {
>>         [IF_TYPE_VIRTIO]        = "virtio",
>>         [IF_TYPE_PVBLOCK]       = "pvblock",
>>         [IF_TYPE_RK_IDB]        = "idb",
>> +       [IF_TYPE_RKNAND]        = "rknand",
>>  };
>>
>>  static enum uclass_id if_type_uclass_id[IF_TYPE_COUNT] = {
>> @@ -51,6 +52,7 @@ static enum uclass_id if_type_uclass_id[IF_TYPE_COUNT] = {
>>         [IF_TYPE_VIRTIO]        = UCLASS_VIRTIO,
>>         [IF_TYPE_PVBLOCK]       = UCLASS_PVBLOCK,
>>         [IF_TYPE_RK_IDB]        = UCLASS_RK_IDB,
>> +       [IF_TYPE_RKNAND]        = UCLASS_RKNAND,
>>  };
>>
>>  static enum if_type if_typename_to_iftype(const char *if_typename)
>> diff --git a/include/blk.h b/include/blk.h
>> index a73cc577a0..56f2415e21 100644
>> --- a/include/blk.h
>> +++ b/include/blk.h
>> @@ -30,6 +30,7 @@ enum if_type {
>>         IF_TYPE_USB,
>>         IF_TYPE_DOC,
>>         IF_TYPE_MMC,
>> +       IF_TYPE_RKNAND,
>>         IF_TYPE_SD,
>>         IF_TYPE_SATA,
>>         IF_TYPE_HOST,
>> diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h
>> index 38a227f006..b102cdf46e 100644
>> --- a/include/dm/uclass-id.h
>> +++ b/include/dm/uclass-id.h
>> @@ -104,6 +104,7 @@ enum uclass_id {
>>         UCLASS_REGULATOR,       /* Regulator device */
>>         UCLASS_REMOTEPROC,      /* Remote Processor device */
>>         UCLASS_RESET,           /* Reset controller device */
>> +       UCLASS_RKNAND,          /* Rockchip nand device with ftl */
>>         UCLASS_RK_IDB,          /* Rockchip IDB device */
>>         UCLASS_RNG,             /* Random Number Generator */
>>         UCLASS_RTC,             /* Real time clock device */
>> diff --git a/include/efi_loader.h b/include/efi_loader.h
>> index 44d426035a..ddc7082ad6 100644
>> --- a/include/efi_loader.h
>> +++ b/include/efi_loader.h
>> @@ -145,6 +145,10 @@ static inline efi_status_t efi_launch_capsules(void)
>>  #define U_BOOT_IDB_DEV_GUID \
>>         EFI_GUID(0xadc021df, 0x5f24, 0x464f, \
>>                  0x9a, 0x88, 0xdb, 0xee, 0x3f, 0x1d, 0x14, 0x0f)
>> +/* GUID used as root for Rockchip RKNAND devices */
>> +#define U_BOOT_RKNAND_DEV_GUID \
>> +       EFI_GUID(0xe39f6cbb, 0x055a, 0x45a0, \
>> +                0xb2, 0x75, 0x56, 0x0d, 0xa5, 0x22, 0x25, 0x99)
>>
>>  /* Use internal device tree when starting UEFI application */
>>  #define EFI_FDT_USE_INTERNAL NULL
>> diff --git a/lib/efi_loader/efi_device_path.c b/lib/efi_loader/efi_device_path.c
>> index b7535373e7..9691f02b2e 100644
>> --- a/lib/efi_loader/efi_device_path.c
>> +++ b/lib/efi_loader/efi_device_path.c
>> @@ -31,6 +31,9 @@ const efi_guid_t efi_guid_virtio_dev = U_BOOT_VIRTIO_DEV_GUID;
>>  #if CONFIG_IS_ENABLED(ROCKCHIP_IDB)
>>  const efi_guid_t efi_guid_idb_dev = U_BOOT_IDB_DEV_GUID;
>>  #endif
>> +#if CONFIG_IS_ENABLED(RKNAND)
>> +const efi_guid_t efi_guid_rknand_dev = U_BOOT_IDB_DEV_GUID;
>> +#endif
>>
>>  /* template END node: */
>>  static const struct efi_device_path END = {
>> @@ -578,6 +581,16 @@ __maybe_unused static unsigned int dp_size(struct udevice *dev)
>>                         return dp_size(dev->parent)
>>                                 + sizeof(struct efi_device_path_vendor) + 1;
>>  #endif
>> +#if CONFIG_IS_ENABLED(RKNAND)
>> +               case UCLASS_RKNAND:
>> +                        /*
>> +                         * Rockchip IDB device will be represented
>> +                         * as vendor device with extra one byte for
>> +                         * device number
>> +                         */
>> +                       return dp_size(dev->parent)
>> +                               + sizeof(struct efi_device_path_vendor) + 1;
>> +#endif
>>  #if CONFIG_IS_ENABLED(ROCKCHIP_IDB)
>>                 case UCLASS_RK_IDB:
>>                          /*
>> @@ -680,6 +693,23 @@ __maybe_unused static void *dp_fill(void *buf, struct udevice *dev)
>>                         return &dp->vendor_data[1];
>>                         }
>>  #endif
>> +#if CONFIG_IS_ENABLED(RKNAND)
>> +               case UCLASS_RKNAND: {
>> +                       struct efi_device_path_vendor *dp;
>> +                       struct blk_desc *desc = dev_get_uclass_plat(dev);
>> +
>> +                       dp_fill(buf, dev->parent);
>> +                       dp = buf;
>> +                       ++dp;
>> +                       dp->dp.type = DEVICE_PATH_TYPE_HARDWARE_DEVICE;
>> +                       dp->dp.sub_type = DEVICE_PATH_SUB_TYPE_VENDOR;
>> +                       dp->dp.length = sizeof(*dp) + 1;
>> +                       memcpy(&dp->guid, &efi_guid_rknand_dev,
>> +                              sizeof(efi_guid_t));
>> +                       dp->vendor_data[0] = desc->devnum;
>> +                       return &dp->vendor_data[1];
>> +                       }
>> +#endif
>>  #if CONFIG_IS_ENABLED(ROCKCHIP_IDB)
>>                 case UCLASS_RK_IDB: {
>>                         struct efi_device_path_vendor *dp;


>From 70ef594197302f3497dac1fa98f419be143257d1 Mon Sep 17 00:00:00 2001
From: Johan Jonker <jbx6244 at gmail.com>
Date: Sat, 13 Aug 2022 20:51:51 +0200
Subject: [PATCH 1/2] disk: part: add call back functions for print_part_header
 and dev_print

In order to be able to add more block devices without changing
the part.c file add call back functions for print_part_header
and dev_print.

Signed-off-by: Johan Jonker <jbx6244 at gmail.com>
---
 disk/part.c   | 8 ++++++--
 include/blk.h | 2 ++
 2 files changed, 8 insertions(+), 2 deletions(-)

diff --git a/disk/part.c b/disk/part.c
index d73318c8..42e88fc7 100644
--- a/disk/part.c
+++ b/disk/part.c
@@ -120,7 +120,9 @@ void dev_print(struct blk_desc *dev_desc)
 		return;
 	}
 
-	switch (dev_desc->uclass_id) {
+	if (dev_desc->dev_print) {
+		dev_desc->dev_print(dev_desc);
+	} else switch (dev_desc->uclass_id) {
 	case UCLASS_SCSI:
 		printf ("(%d:%d) Vendor: %s Prod.: %s Rev: %s\n",
 			dev_desc->target,dev_desc->lun,
@@ -248,7 +250,9 @@ static void print_part_header(const char *type, struct blk_desc *dev_desc)
 	CONFIG_IS_ENABLED(AMIGA_PARTITION) || \
 	CONFIG_IS_ENABLED(EFI_PARTITION)
 	puts ("\nPartition Map for ");
-	switch (dev_desc->uclass_id) {
+	if (dev_desc->part_header) {
+		dev_desc->part_header(dev_desc);
+	} else switch (dev_desc->uclass_id) {
 	case UCLASS_IDE:
 		puts ("IDE");
 		break;
diff --git a/include/blk.h b/include/blk.h
index cdc6f0fc..f158f039 100644
--- a/include/blk.h
+++ b/include/blk.h
@@ -69,6 +69,8 @@ struct blk_desc {
 	lbaint_t	lba;		/* number of blocks */
 	unsigned long	blksz;		/* block size */
 	int		log2blksz;	/* for convenience: log2(blksz) */
+	void		(*part_header)(struct blk_desc *dev_desc); /* print_part_header in part.c */
+	void		(*dev_print)(struct blk_desc *dev_desc); /* rknand_dev_print in part.c */
 	char		vendor[BLK_VEN_SIZE + 1]; /* device vendor string */
 	char		product[BLK_PRD_SIZE + 1]; /* device product number */
 	char		revision[BLK_REV_SIZE + 1]; /* firmware revision */
-- 
2.20.1


>From 8f05d7887955393e0b14cae43f061703694306a4 Mon Sep 17 00:00:00 2001
From: Johan Jonker <jbx6244 at gmail.com>
Date: Sat, 13 Aug 2022 21:11:50 +0200
Subject: [PATCH 2/2] lib: efi_loader: efi_device_path: add dp_fill and dp_size
 call back functions

In order to be able to add more block devices without changing
the efi_device_path.c file add dp_fill and dp_size call back functions

Signed-off-by: Johan Jonker <jbx6244 at gmail.com>
---
 include/dm/device.h              |  2 ++
 lib/efi_loader/efi_device_path.c | 12 ++++++++----
 2 files changed, 10 insertions(+), 4 deletions(-)

diff --git a/include/dm/device.h b/include/dm/device.h
index 12c6ba37..add219be 100644
--- a/include/dm/device.h
+++ b/include/dm/device.h
@@ -194,6 +194,8 @@ struct udevice {
 #if CONFIG_IS_ENABLED(DM_DMA)
 	ulong dma_offset;
 #endif
+	unsigned int (*dp_size)(struct udevice *dev);
+	void * (*dp_fill)(void *buf, struct udevice *dev);
 };
 
 static inline int dm_udevice_size(void)
diff --git a/lib/efi_loader/efi_device_path.c b/lib/efi_loader/efi_device_path.c
index 9787033c..57ac31f1 100644
--- a/lib/efi_loader/efi_device_path.c
+++ b/lib/efi_loader/efi_device_path.c
@@ -515,7 +515,7 @@ bool efi_dp_is_multi_instance(const struct efi_device_path *dp)
 /* size of device-path not including END node for device and all parents
  * up to the root device.
  */
-__maybe_unused static unsigned int dp_size(struct udevice *dev)
+__maybe_unused unsigned int dp_size(struct udevice *dev)
 {
 	if (!dev || !dev->driver)
 		return sizeof(ROOT);
@@ -529,7 +529,9 @@ __maybe_unused static unsigned int dp_size(struct udevice *dev)
 		return dp_size(dev->parent) +
 			sizeof(struct efi_device_path_mac_addr);
 	case UCLASS_BLK:
-		switch (dev->parent->uclass->uc_drv->id) {
+		if (dev->dp_size) {
+			return dev->dp_size(dev);
+		} else switch (dev->parent->uclass->uc_drv->id) {
 #ifdef CONFIG_IDE
 		case UCLASS_IDE:
 			return dp_size(dev->parent) +
@@ -600,7 +602,7 @@ __maybe_unused static unsigned int dp_size(struct udevice *dev)
  * @dev		device
  * Return:	pointer to the end of the device path
  */
-__maybe_unused static void *dp_fill(void *buf, struct udevice *dev)
+__maybe_unused void *dp_fill(void *buf, struct udevice *dev)
 {
 	if (!dev || !dev->driver)
 		return buf;
@@ -631,7 +633,9 @@ __maybe_unused static void *dp_fill(void *buf, struct udevice *dev)
 	}
 #endif
 	case UCLASS_BLK:
-		switch (dev->parent->uclass->uc_drv->id) {
+		if (dev->dp_fill) {
+			return dev->dp_fill(buf, dev);
+		} else switch (dev->parent->uclass->uc_drv->id) {
 #ifdef CONFIG_SANDBOX
 		case UCLASS_ROOT: {
 			/* stop traversing parents at this point: */
-- 
2.20.1



More information about the U-Boot mailing list