Skip to contentSkip to conversation

Generic firmware loader

PATCH Superseded tien.fong.chee at intel.com 3 participants 7 messages Feb 27, 2018 – Feb 28, 2018

v9 of 10 Superseded Latest is v10 →

lore
Share & tools
lore
#0 lore raw

v9 cover Generic firmware loader

From: Tien Fong Chee <[email protected]>

This patchset contains generic firmware loader which is very close to Linux firmware loader but for U-Boot framework. Generic firmware loader can be used load whatever into target location, and then consumer driver would use it to program whatever, ie. the FPGA. This version mainly resolved comments from Marek Vasut in [v8].

This series is working on top of u-boot.git -
http://git.denx.de/u-boot.git .

[v8]: https://www.mail-archive.com/u-boot at lists.denx.de/msg278735.html

v8 -> v9 changes:
-----------------
- Swap these two -- mount first and umount seconds.
- Removed #ifdef CONFIG_SPL.
- Adding depends on SPL to config GENERIC_FIRMWARE_LOADER at Kconfig.
- Set mode=0 to usb_stor_scan.
- Sata device number be pulled from devpart in default_locations table.
- Removed debug for CONFIG_SPL.
- Adding UBI to default_location table.

Patchset history
----------------
[v1]: https://www.mail-archive.com/u-boot at lists.denx.de/msg271905.html [v2]: https://www.mail-archive.com/u-boot at lists.denx.de/msg271979.html [v3]: https://www.mail-archive.com/u-boot at lists.denx.de/msg272039.html [v4]: https://www.mail-archive.com/u-boot at lists.denx.de/msg272432.html [v5]: https://www.mail-archive.com/u-boot at lists.denx.de/msg272771.html [v6]: https://www.mail-archive.com/u-boot at lists.denx.de/msg273961.html [v7]: https://www.mail-archive.com/u-boot at lists.denx.de/msg276775.html

Tien Fong Chee (4):
spl: Remove static declaration on spl_mmc_find_device function
cmd: ubifs: Move ubifs_initialized checking into cmd_ubifs_umount()
cmd: ubifs: Factor out some checking codes into cmd_ubifs_mount()
common: Generic firmware loader for file system

 cmd/ubifs.c                |  40 ++---
 common/Kconfig             |  10 ++
 common/Makefile            |   1 +
 common/fs_loader.c         | 365 +++++++++++++++++++++++++++++++++++++++++++++
 common/spl/spl_mmc.c       |   2 +-
 doc/README.firmware_loader |  83 +++++++++++
 include/fs_loader.h        |  28 ++++
 include/spl.h              |   2 +
 include/ubi_uboot.h        |   2 +
 9 files changed, 515 insertions(+), 18 deletions(-)
 create mode 100644 common/fs_loader.c
 create mode 100644 doc/README.firmware_loader
 create mode 100644 include/fs_loader.h
Signature · 1 line
2.2.0
#1 lore raw

PATCH v9 1/4 spl: Remove static declaration on spl_mmc_find_device function

From: Tien Fong Chee <[email protected]>

This patch removes the static declation on spl_mmc_find_device_function so this function is accessible by the caller from other file. This patch is required for later patch.

---
 common/spl/spl_mmc.c | 2 +-
 include/spl.h        | 2 ++
 2 files changed, 3 insertions(+), 1 deletion(-)
common/spl/spl_mmc.c +1 -1
index 351f4ed..f1c4168 100644
@@ -114,7 +114,7 @@ static int spl_mmc_get_device_index(u32 boot_device)
 	return -ENODEV;
 }
 
-static int spl_mmc_find_device(struct mmc **mmcp, u32 boot_device)
+int spl_mmc_find_device(struct mmc **mmcp, u32 boot_device)
 {
 #if CONFIG_IS_ENABLED(DM_MMC)
 	struct udevice *dev;
include/spl.h +2 -0
index c14448b..60424d7 100644
@@ -12,6 +12,7 @@
 /* Platform-specific defines */
 #include <linux/compiler.h>
 #include <asm/spl.h>
+#include <mmc.h>
 
 /* Value in r0 indicates we booted from U-Boot */
 #define UBOOT_NOT_LOADED_FROM_SPL	0x13578642
@@ -83,6 +84,7 @@ void preloader_console_init(void);
 u32 spl_boot_device(void);
 u32 spl_boot_mode(const u32 boot_device);
 void spl_set_bd(void);
+int spl_mmc_find_device(struct mmc **mmcp, u32 boot_device);
 
 /**
  * spl_set_header_raw_uboot() - Set up a standard SPL image structure
Signature · 1 line
2.2.0
#2 lore raw

PATCH v9 2/4 cmd: ubifs: Move ubifs_initialized checking into cmd_ubifs_umount()

In reply to tien.fong.chee at intel.com

From: Tien Fong Chee <[email protected]>

cmd_ubifs_umount() function would be called directly instead of involving whole command machinery in generic firmware loader, so checking on ubifs_initialized status need to be done in cmd_ubifs_umount() without breaking original functionality design.

---
 cmd/ubifs.c         | 18 +++++++++---------
 include/ubi_uboot.h |  1 +
 2 files changed, 10 insertions(+), 9 deletions(-)
cmd/ubifs.c +9 -9
index 5e9d357..0d059ca 100644
@@ -51,11 +51,18 @@ int ubifs_is_mounted(void)
 	return ubifs_mounted;
 }
 
-void cmd_ubifs_umount(void)
+int cmd_ubifs_umount(void)
 {
+	if (ubifs_initialized == 0) {
+		printf("No UBIFS volume mounted!\n");
+		return -1;
+	}
+
 	uboot_ubifs_umount();
 	ubifs_mounted = 0;
 	ubifs_initialized = 0;
+
+	return 0;
 }
 
 static int do_ubifs_umount(cmd_tbl_t *cmdtp, int flag, int argc,
@@ -64,14 +71,7 @@ static int do_ubifs_umount(cmd_tbl_t *cmdtp, int flag, int argc,
 	if (argc != 1)
 		return CMD_RET_USAGE;
 
-	if (ubifs_initialized == 0) {
-		printf("No UBIFS volume mounted!\n");
-		return -1;
-	}
-
-	cmd_ubifs_umount();
-
-	return 0;
+	return cmd_ubifs_umount();
 }
 
 static int do_ubifs_ls(cmd_tbl_t *cmdtp, int flag, int argc,
include/ubi_uboot.h +1 -0
index 80acbcb..827dbfc 100644
@@ -75,5 +75,6 @@ extern int ubi_volume_write(char *volume, void *buf, size_t size);
 extern int ubi_volume_read(char *volume, char *buf, size_t size);
 
 extern struct ubi_device *ubi_devices[];
+int cmd_ubifs_umount(void);
 
 #endif
Signature · 1 line
2.2.0
#3 lore raw

PATCH v9 3/4 cmd: ubifs: Factor out some checking codes into cmd_ubifs_mount()

In reply to tien.fong.chee at intel.com

From: Tien Fong Chee <[email protected]>

cmd_ubifs_mount() function would be called directly instead of involving whole command machinery for mounting ubifs in generic firmware loader, so some checking codes need to be factored out into cmd_ubifs_mount() without breaking original functionality design.

---
 cmd/ubifs.c         | 22 ++++++++++++++--------
 include/ubi_uboot.h |  1 +
 2 files changed, 15 insertions(+), 8 deletions(-)
cmd/ubifs.c +14 -8
index 0d059ca..8339bed 100644
@@ -20,16 +20,10 @@
 static int ubifs_initialized;
 static int ubifs_mounted;
 
-static int do_ubifs_mount(cmd_tbl_t *cmdtp, int flag, int argc,
-				char * const argv[])
+int cmd_ubifs_mount(char *vol_name)
 {
-	char *vol_name;
 	int ret;
 
-	if (argc != 2)
-		return CMD_RET_USAGE;
-
-	vol_name = argv[1];
 	debug("Using volume %s\n", vol_name);
 
 	if (ubifs_initialized == 0) {
@@ -43,7 +37,19 @@ static int do_ubifs_mount(cmd_tbl_t *cmdtp, int flag, int argc,
 
 	ubifs_mounted = 1;
 
-	return 0;
+	return ret;
+}
+static int do_ubifs_mount(cmd_tbl_t *cmdtp, int flag, int argc,
+				char * const argv[])
+{
+	char *vol_name;
+
+	if (argc != 2)
+		return CMD_RET_USAGE;
+
+	vol_name = argv[1];
+
+	return cmd_ubifs_mount(vol_name);
 }
 
 int ubifs_is_mounted(void)
include/ubi_uboot.h +1 -0
index 827dbfc..0770228 100644
@@ -75,6 +75,7 @@ extern int ubi_volume_write(char *volume, void *buf, size_t size);
 extern int ubi_volume_read(char *volume, char *buf, size_t size);
 
 extern struct ubi_device *ubi_devices[];
+int cmd_ubifs_mount(char *vol_name);
 int cmd_ubifs_umount(void);
 
 #endif
Signature · 1 line
2.2.0
#4 lore raw

PATCH v9 4/4 common: Generic firmware loader for file system

In reply to tien.fong.chee at intel.com

From: Tien Fong Chee <[email protected]>

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.

---
 common/Kconfig             |  10 ++
 common/Makefile            |   1 +
 common/fs_loader.c         | 365 +++++++++++++++++++++++++++++++++++++++++++++
 doc/README.firmware_loader |  83 +++++++++++
 include/fs_loader.h        |  28 ++++
 5 files changed, 487 insertions(+)
 create mode 100644 common/fs_loader.c
 create mode 100644 doc/README.firmware_loader
 create mode 100644 include/fs_loader.h
common/Kconfig +10 -0
index d5bc37e..ff88c6e 100644
@@ -560,6 +560,16 @@ config DISPLAY_BOARDINFO
 	  when U-Boot starts up. The board function checkboard() is called
 	  to do this.
 
+config GENERIC_FIRMWARE_LOADER
+	bool "Enable generic firmware loader driver for file system"
+	depends on SPL
+	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.
+
 menu "Start-up hooks"
 
 config ARCH_EARLY_INIT_R
common/Makefile +1 -0
index c7bde23..92d8fb3 100644
@@ -134,3 +134,4 @@ obj-$(CONFIG_$(SPL_)LOG) += log.o
 obj-$(CONFIG_$(SPL_)LOG_CONSOLE) += log_console.o
 obj-y += s_record.o
 obj-y += xyzModem.o
+obj-$(CONFIG_GENERIC_FIRMWARE_LOADER) += fs_loader.o
common/fs_loader.c new file +365 -0

365 lines not on this page · raw message

doc/README.firmware_loader new file +83 -0

83 lines not on this page · raw message

include/fs_loader.h new file +28 -0
new file mode 100644
index 0000000..60a6ba2
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2018 Intel Corporation <www.intel.com>
+ *
+ * SPDX-License-Identifier:    GPL-2.0
+ */
+#ifndef _FS_LOADER_H_
+#define _FS_LOADER_H_
+
+#include <linux/types.h>
+
+struct firmware {
+	size_t size;		/* Size of a file */
+	const u8 *data;		/* Buffer for file */
+	void *priv;		/* Firmware loader private fields */
+};
+
+struct device_location {
+	char *name;	/* Such as mmc, usb,and sata. */
+	char *devpart;  /* Use the load command dev:part conventions */
+	char *mtdpart;	/* MTD partition for ubi part */
+	char *ubivol;	/* UBI volume-name for ubifsmount */
+};
+
+int request_firmware_into_buf(struct firmware **firmware_p,
+			      const char *name,
+			      struct device_location *location,
+			      void *buf, size_t size, u32 offset);
+#endif
Signature · 1 line
2.2.0
#5 lore raw

PATCH v9 4/4 common: Generic firmware loader for file system

Hi,

Quoted 143 lines · On Tue, 27 Feb 2018 13:21:57 +0800 tien.fong.chee at intel.com wrote:

From: Tien Fong Chee <[email protected]>

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.

---
 common/Kconfig             |  10 ++
 common/Makefile            |   1 +
 common/fs_loader.c         | 365 +++++++++++++++++++++++++++++++++++++++++++++
 doc/README.firmware_loader |  83 +++++++++++
 include/fs_loader.h        |  28 ++++
 5 files changed, 487 insertions(+)
 create mode 100644 common/fs_loader.c
 create mode 100644 doc/README.firmware_loader
 create mode 100644 include/fs_loader.h
common/Kconfig +10 -0
index d5bc37e..ff88c6e 100644
@@ -560,6 +560,16 @@ config DISPLAY_BOARDINFO
 	  when U-Boot starts up. The board function checkboard() is called
 	  to do this.
 
+config GENERIC_FIRMWARE_LOADER
+	bool "Enable generic firmware loader driver for file system"
+	depends on SPL
+	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.
+
 menu "Start-up hooks"
 
 config ARCH_EARLY_INIT_R
common/Makefile +1 -0
index c7bde23..92d8fb3 100644
@@ -134,3 +134,4 @@ obj-$(CONFIG_$(SPL_)LOG) += log.o
 obj-$(CONFIG_$(SPL_)LOG_CONSOLE) += log_console.o
 obj-y += s_record.o
 obj-y += xyzModem.o
+obj-$(CONFIG_GENERIC_FIRMWARE_LOADER) += fs_loader.o
common/fs_loader.c new file +86 -0
new file mode 100644
index 0000000..7fc318f
@@ -0,0 +1,365 @@
+/*
+ * Copyright (C) 2018 Intel Corporation <www.intel.com>
+ *
+ * SPDX-License-Identifier:    GPL-2.0
+ */
+
+#include <common.h>
+#include <errno.h>
+#include <fs.h>
+#include <fs_loader.h>
+#include <nand.h>
+#include <sata.h>
+#include <spi.h>
+#include <spi_flash.h>
+#include <spl.h>
+#include <linux/string.h>
+#ifdef CONFIG_CMD_UBIFS
+#include <ubi_uboot.h>
+#include <ubifs_uboot.h>
+#endif
+#include <usb.h>
+
+struct firmware_priv {
+	const char *name;	/* Filename */
+	u32 offset;		/* Offset of reading a file */
+};
+
+static struct device_location default_locations[] = {
+	{
+		.name = "mmc",
+		.devpart = "0:1",
+	},
+	{
+		.name = "usb",
+		.devpart = "0:1",
+	},
+	{
+		.name = "sata",
+		.devpart = "0:1",
+	},
+	{
+		.name = "ubi",
+		.mtdpart = "UBI",
+		.ubivol = "ubi0",
+	},
+};
+
+/* USB build is not supported yet in SPL */
+#ifndef CONFIG_SPL_BUILD
+#ifdef CONFIG_USB_STORAGE
+static int init_usb(void)
+{
+	int err;
+
+	err = usb_init();
+	if (err)
+		return err;
+
+#ifndef CONFIG_DM_USB
+	err = usb_stor_scan(0);
+	if (err)
+		return err;
+#endif
+
+	return err;
+}
+#else
+static int init_usb(void)
+{
+	debug("Error: Cannot load flash image: no USB support\n");
+	return -ENOSYS;
+}
+#endif
+#endif
+
+#ifdef CONFIG_SATA
+static int init_storage_sata(struct device_location *location)
+{
+	char *dup_str = NULL;
+	const char *dev_str, *part_str;
+	int dev;
+
+	/* Get device ID */
+	part_str = strchr(location->devpart, ':');
+	if (part_str) {
+		dup_str = strdup(location->devpart);

common/fs_loader.c line 96

Quoted 10 lines
common/fs_loader.c new file +10 -0
+		dup_str[part_str - location->devpart] = 0;
+		dev_str = dup_str;
+		part_str++;
+	} else {
+		dev_str = location->devpart;
+	}
+
+	dev = (int)simple_strtoul(dev_str, NULL, 10);
+
+	return sata_probe(dev);

You are leaking the strdup() memory.
Furthermore, there is no need to mess around with the 'devpart' string like this. simple_strtoul() will convert the string up to the first non-digit character and return the position of this char in the second argument (if that's non-null). Thus you can easily check for a valid numerical argument.

Quoted 20 lines
common/fs_loader.c new file +20 -0
+static void set_storage_devpart(char *name, char *devpart)
+{
+	size_t i;
+
+	for (i = 0; i < ARRAY_SIZE(default_locations); i++) {
+		if (!strcmp(default_locations[i].name, name))
+			default_locations[i].devpart = devpart;
+	}
+}
+
+static void set_storage_mtdpart(char *name, char *mtdpart)
+{
+	size_t i;
+
+	for (i = 0; i < ARRAY_SIZE(default_locations); i++) {
+		if (!strcmp(default_locations[i].name, name))
+			default_locations[i].mtdpart = mtdpart;
+	}
+}
+

common/fs_loader.c line 238

Quoted 10 lines
common/fs_loader.c new file +10 -0
+static void set_storage_ubivol(char *name, char *ubivol)
+{
+	size_t i;
+
+	for (i = 0; i < ARRAY_SIZE(default_locations); i++) {
+		if (!strcmp(default_locations[i].name, name))
+			default_locations[i].ubivol = ubivol;
+	}
+}
+

The arguments to these functions could well be const.

Lothar Waßmann

#6 lore raw

PATCH v9 4/4 common: Generic firmware loader for file system

Quoted 156 lines · Lothar Waßmann

Hi,

Quoted 153 lines · On Tue, 27 Feb 2018 13:21:57 +0800 tien.fong.chee at intel.com wrote:

From: Tien Fong Chee <[email protected]>

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.

---
 common/Kconfig             |  10 ++
 common/Makefile            |   1 +
 common/fs_loader.c         | 365
+++++++++++++++++++++++++++++++++++++++++++++
 doc/README.firmware_loader |  83 +++++++++++
 include/fs_loader.h        |  28 ++++

 5 files changed, 487 insertions(+)

 create mode 100644 common/fs_loader.c
 create mode 100644 doc/README.firmware_loader
 create mode 100644 include/fs_loader.h

common/Kconfig +0 -0
index d5bc37e..ff88c6e 100644
@@ -560,6 +560,16 @@ config DISPLAY_BOARDINFO
  	  when U-Boot starts up. The board function checkboard()

is called
    to do this.

common/Kconfig +2 -0
+config GENERIC_FIRMWARE_LOADER
+	bool "Enable generic firmware loader driver for file

system"

common/Kconfig +3 -0
+	depends on SPL
+	help
+	  This is file system generic loader which can be used to

load

common/Kconfig +1 -0
+	  the file image from the storage into target such as

memory.

common/Kconfig +2 -0
+
+	  The consumer driver would then use this loader to

program whatever,

common/Kconfig +2 -0
+	  ie. the FPGA device.
+

 menu "Start-up hooks"

 config ARCH_EARLY_INIT_R

common/Makefile +0 -0
index c7bde23..92d8fb3 100644
@@ -134,3 +134,4 @@ obj-$(CONFIG_$(SPL_)LOG) += log.o

 obj-$(CONFIG_$(SPL_)LOG_CONSOLE) += log_console.o obj-y += s_record.o
 obj-y += xyzModem.o

common/Makefile +1 -0
+obj-$(CONFIG_GENERIC_FIRMWARE_LOADER) += fs_loader.o
common/fs_loader.c new file +90 -0
new file mode 100644
index 0000000..7fc318f
@@ -0,0 +1,365 @@
+/*
+ * Copyright (C) 2018 Intel Corporation <www.intel.com>
+ *
+ * SPDX-License-Identifier:    GPL-2.0
+ */
+
+#include <common.h>
+#include <errno.h>
+#include <fs.h>
+#include <fs_loader.h>
+#include <nand.h>
+#include <sata.h>
+#include <spi.h>
+#include <spi_flash.h>
+#include <spl.h>
+#include <linux/string.h>
+#ifdef CONFIG_CMD_UBIFS
+#include <ubi_uboot.h>
+#include <ubifs_uboot.h>
+#endif
+#include <usb.h>
+
+struct firmware_priv {
+	const char *name;	/* Filename */
+	u32 offset;		/* Offset of reading a file */
+};
+
+static struct device_location default_locations[] = {
+	{
+		.name = "mmc",
+		.devpart = "0:1",
+	},
+	{
+		.name = "usb",
+		.devpart = "0:1",
+	},
+	{
+		.name = "sata",
+		.devpart = "0:1",
+	},
+	{
+		.name = "ubi",
+		.mtdpart = "UBI",
+		.ubivol = "ubi0",
+	},
+};
+
+/* USB build is not supported yet in SPL */
+#ifndef CONFIG_SPL_BUILD
+#ifdef CONFIG_USB_STORAGE
+static int init_usb(void)
+{
+	int err;
+
+	err = usb_init();
+	if (err)
+		return err;
+
+#ifndef CONFIG_DM_USB
+	err = usb_stor_scan(0);
+	if (err)
+		return err;
+#endif
+
+	return err;
+}
+#else
+static int init_usb(void)
+{
+	debug("Error: Cannot load flash image: no USB support\n");
+	return -ENOSYS;
+}
+#endif
+#endif
+
+#ifdef CONFIG_SATA
+static int init_storage_sata(struct device_location *location)
+{
+	char *dup_str = NULL;
+	const char *dev_str, *part_str;
+	int dev;
+
+	/* Get device ID */
+	part_str = strchr(location->devpart, ':');
+	if (part_str) {
+		dup_str = strdup(location->devpart);
+		dup_str[part_str - location->devpart] = 0;
+		dev_str = dup_str;
+		part_str++;
+	} else {
Quoted 8 lines

common/fs_loader.c line 96

Quoted 7 lines
common/fs_loader.c new file +6 -0
+		dev_str = location->devpart;
+	}
+
+	dev = (int)simple_strtoul(dev_str, NULL, 10);
+
+	return sata_probe(dev);

You are leaking the strdup() memory.

Good catch!!

Quoted 8 lines

Furthermore, there is no need to mess around with the 'devpart' string
like this. simple_strtoul() will convert the string up to the first non-digit character and return the position of this char in the second
argument (if that's non-null). Thus you can easily check for a valid numerical argument.

Okay, i would try with simple_strtoul().

Quoted 24 lines
Quoted 24 lines
common/fs_loader.c new file +23 -0
+static void set_storage_devpart(char *name, char *devpart)
+{
+	size_t i;
+
+	for (i = 0; i < ARRAY_SIZE(default_locations); i++) {
+		if (!strcmp(default_locations[i].name, name))
+			default_locations[i].devpart = devpart;
+	}
+}
+
+static void set_storage_mtdpart(char *name, char *mtdpart)
+{
+	size_t i;
+
+	for (i = 0; i < ARRAY_SIZE(default_locations); i++) {
+		if (!strcmp(default_locations[i].name, name))
+			default_locations[i].mtdpart = mtdpart;
+	}
+}
+
+static void set_storage_ubivol(char *name, char *ubivol)
+{
+	size_t i;
Quoted 9 lines

common/fs_loader.c line 238

Quoted 7 lines
common/fs_loader.c new file +7 -0
+
+	for (i = 0; i < ARRAY_SIZE(default_locations); i++) {
+		if (!strcmp(default_locations[i].name, name))
+			default_locations[i].ubivol = ubivol;
+	}
+}
+

The arguments to these functions could well be const.

Okay. noted.

Quoted 3 lines

Lothar Waßmann