[U-Boot] [PATCH v3 3/3] common: Generic loader for file system

Simon Glass
2018-06-27T21:03:15Z

Hi Tien Fong,

On 27 June 2018 at 01:41, Chee, Tien Fong <tien.fong.chee@intel.com> wrote:
> On Mon, 2018-06-25 at 21:58 -0600, Simon Glass wrote:
>> Hi,
>>
>> On 25 June 2018 at 07:28, <tien.fong.chee@intel.com> wrote:
>> >
>> > From: Tien Fong Chee <tien.fong.chee@intel.com>
>> >
>> > This is file system generic loader which can be used to load
>> > the file image from the storage into target such as memory.
>> > The consumer driver would then use this loader to program whatever,
>> > ie. the FPGA device.
>> >
>> > Signed-off-by: Tien Fong Chee <tien.fong.chee@intel.com>
>> > ---
>> > drivers/misc/Kconfig | 10 ++
>> > drivers/misc/Makefile | 1 +
>> > drivers/misc/fs_loader.c | 238
>> > +++++++++++++++++++++++++++++++++++++++++++++++
>> > include/dm/uclass-id.h | 1 +
>> > include/fs_loader.h | 28 ++++++
>> > 5 files changed, 278 insertions(+)
>> > create mode 100644 drivers/misc/fs_loader.c
>> > create mode 100644 include/fs_loader.h
>> This is definitely looking good. I think we need to figure out the
>> binding to devices, to use phandles instead of strings. Also we need
>> a
>> sandbox driver and test.
>>
>> I'm a little worried that you are blazing a trail here, but it is a
>> valuable trail :-)
>>
>> Tom, do you have any ideas / thoughts on the design?
>>
> yeah, this part is most challenging, because this driver is designed
> based on file system implementation, which is abstract from physical
> device. So, it requires data like interface type, device number and
> partition to work. Wonder how we can get those data if based on
> physical storage node.
>> >
>> >
>> > diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
>> > index 17b3a80..4163b4f 100644
>> > --- a/drivers/misc/Kconfig
>> > +++ b/drivers/misc/Kconfig
>> > @@ -277,4 +277,14 @@ config GDSYS_RXAUI_CTRL
>> > depends on MISC
>> > help
>> > Support gdsys FPGA's RXAUI control.
>> > +
>> > +config FS_LOADER
>> > + bool "Enable loader driver for file system"
>> > + help
>> > + This is file system generic loader which can be used to
>> > load
>> > + the file image from the storage into target such as
>> > memory.
>> > +
>> > + The consumer driver would then use this loader to program
>> > whatever,
>> > + ie. the FPGA device.
>> > +
>> > endmenu
>> > diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
>> > index 4ce9d21..67a36f8 100644
>> > --- a/drivers/misc/Makefile
>> > +++ b/drivers/misc/Makefile
>> > @@ -54,3 +54,4 @@ obj-$(CONFIG_STM32_RCC) += stm32_rcc.o
>> > obj-$(CONFIG_STM32MP_FUSE) += stm32mp_fuse.o
>> > obj-$(CONFIG_SYS_DPAA_QBMAN) += fsl_portals.o
>> > obj-$(CONFIG_GDSYS_RXAUI_CTRL) += gdsys_rxaui_ctrl.o
>> > +obj-$(CONFIG_FS_LOADER) += fs_loader.o
>> > diff --git a/drivers/misc/fs_loader.c b/drivers/misc/fs_loader.c
>> > new file mode 100644
>> > index 0000000..0dc385f
>> > --- /dev/null
>> > +++ b/drivers/misc/fs_loader.c
>> > @@ -0,0 +1,238 @@
>> > +/*
>> > + * Copyright (C) 2018 Intel Corporation <www.intel.com>
>> > + *
>> > + * SPDX-License-Identifier: GPL-2.0
>> > + */
>> > +#include <common.h>
>> > +#include <dm.h>
>> > +#include <errno.h>
>> > +#include <fs.h>
>> > +#include <fs_loader.h>
>> > +#include <linux/string.h>
>> > +#include <malloc.h>
>> > +#include <spl.h>
>> > +
>> > +DECLARE_GLOBAL_DATA_PTR;
>> > +
>> > +struct firmware_priv {
>> > + const char *name; /* Filename */
>> > + u32 offset; /* Offset of reading a file */
>> > +};
>> > +
>> > +static int select_fs_dev(struct device_platdata *plat)
>> > +{
>> > + int ret;
>> > +
>> > + if (!strcmp("mmc", plat->name)) {
>> > + ret = fs_set_blk_dev("mmc", plat->devpart,
>> > FS_TYPE_ANY);
>> > + } else if (!strcmp("usb", plat->name)) {
>> > + ret = fs_set_blk_dev("usb", plat->devpart,
>> > FS_TYPE_ANY);
>> > + } else if (!strcmp("sata", plat->name)) {
>> > + ret = fs_set_blk_dev("sata", plat->devpart,
>> > FS_TYPE_ANY);
>> For these I think you can look up the phandle to obtain the device,
>> then check its uclass to find out its type.
>>
> How to find the interface type of the file system based on the physical
> device node? Some devices like NAND and QSPI could share the similar
> interface type like UBI.

See my other email on this.

>> >
>> > + } else if (!strcmp("ubi", plat->name)) {
>> > + if (plat->ubivol)
>> > + ret = fs_set_blk_dev("ubi", NULL,
>> > FS_TYPE_UBIFS);
>> > + else
>> > + ret = -ENODEV;
>> > + } else {
>> > + debug("Error: unsupported storage device.\n");
>> > + return -ENODEV;
>> > + }
>> > +
>> > + if (ret)
>> > + debug("Error: could not access storage.\n");
>> > +
>> > + return ret;
>> > +}
>> > +
>> > +static void set_storage_devpart(struct device_platdata *plat, char
>> > *devpart)
>> > +{
>> > + plat->devpart = devpart;
>> > +}
>> > +
>> > +static void set_storage_mtdpart(struct device_platdata *plat, char
>> > *mtdpart)
>> > +{
>> > + plat->mtdpart = mtdpart;
>> > +}
>> > +
>> > +static void set_storage_ubivol(struct device_platdata *plat, char
>> > *ubivol)
>> > +{
>> > + plat->ubivol = ubivol;
>> > +}
>> > +
>> > +/**
>> > + * _request_firmware_prepare - Prepare firmware struct.
>> > + *
>> > + * @firmware_p: Pointer to pointer to firmware image.
>> > + * @name: Name of firmware file.
>> > + * @dbuf: Address of buffer to load firmware into.
>> > + * @size: Size of buffer.
>> > + * @offset: Offset of a file for start reading into buffer.
>> > + *
>> > + * Return: Negative value if fail, 0 for successful.
>> > + */
>> > +static int _request_firmware_prepare(struct firmware **firmware_p,
>> Can you please move this to be the last arg and rename to firmwarep?
>>
> Okay.
>> >
>> > + const char *name, void
>> > *dbuf,device to ubi
>> > + size_t size, u32 offset)
>> > +{
>> > + struct firmware *firmware;
>> > + struct firmware_priv *fw_priv;
>> > +
>> > + *firmware_p = NULL;
>> > +
>> > + if (!name || name[0] == '\0')
>> > + return -EINVAL;
>> > +
>> > + firmware = calloc(1, sizeof(*firmware));
>> > + if (!firmware)
>> > + return -ENOMEM;
>> > +
>> > + fw_priv = calloc(1, sizeof(*fw_priv));
>> > + if (!fw_priv) {
>> > + free(firmware);
>> > + return -ENOMEM;
>> > + }
>> > +
>> > + fw_priv->name = name;
>> > + fw_priv->offset = offset;
>> > + firmware->data = dbuf;
>> > + firmware->size = size;
>> > + firmware->priv = fw_priv;
>> > + *firmware_p = firmware;
>> > +
>> > + return 0;
>> > +}
>> > +
>> > +/**
>> > + * fw_get_filesystem_firmware - load firmware into an allocated
>> > buffer.
>> > + * @plat: Platform data such as storage and partition firmware
>> > loading from.
>> > + * @firmware_p: pointer to firmware image.
>> > + *
>> > + * Return: Size of total read, negative value when error.
>> > + */
>> > +static int fw_get_filesystem_firmware(struct device_platdata
>> > *plat,
>> > + struct firmware *firmware_p)
>> s/firmware_p/firmware/
>>
> Okay.
>> >
>> > +{
>> > + struct firmware_priv *fw_priv = NULL;
>> > + loff_t actread;
>> > + char *dev_part, *ubi_mtdpart, *ubi_volume;
>> > + int ret;
>> > +
>> > + dev_part = env_get("fw_dev_part");
>> > + if (dev_part)
>> > + set_storage_devpart(plat, dev_part);
>> > +
>> > + ubi_mtdpart = env_get("fw_ubi_mtdpart");
>> > + if (ubi_mtdpart)
>> > + set_storage_mtdpart(plat, ubi_mtdpart);
>> Do you mean that the storage partition comes from the environment? I
>> thought it came from the FDT?
>>
> This driver is designed not only supporting the FDT, it also work with
> U-boot env, U-boot script and without FDT.
>
> For example, fpga loadfs commands from U-boot console can call this
> driver to load bitstream file from the storage.

OK, but in that case why use environment? Can't you just put the
parameters in the command?

[..]

Regards,
Simon