[U-Boot] [PATCH v2 0/6] remoteproc: add elf resource table loader

Add some helpers that can be called by the drivers to load the firmware resource table from an elf32 / elf64 image. The stm32 remoteproc driver makes use of it, to load the resource table before the elf image itself.
Changes since v1: -Do not fixup the DeviceTree to track the stm32 coprocessor state. Instead of this, use a dedicated register.
Fabien Dessenne (6): remoteproc: elf_loader: Add elf resource table load support stm32mp1: declare backup registers for coprocessor stm32mp1: reset coprocessor status at cold boot remoteproc: stm32: track the coprocessor state in a backup register stm32mp1: remove copro_state environment variable remoteproc: stm32: load resource table from firmware
arch/arm/mach-stm32mp/cpu.c | 7 + arch/arm/mach-stm32mp/include/mach/stm32.h | 9 + board/st/stm32mp1/stm32mp1.c | 4 +- drivers/remoteproc/rproc-elf-loader.c | 269 +++++++++++++++++++++++++++++ drivers/remoteproc/stm32_copro.c | 27 ++- include/remoteproc.h | 70 ++++++++ test/dm/remoteproc.c | 91 ++++++++-- 7 files changed, 454 insertions(+), 23 deletions(-)

Add rproc_elf_load_rsc_table(), which searches for a resource table in an elf64/elf32 image, and if found, copies it to device memory. Add also the elf32 and elf64 variants of this API. Add a test for this.
Signed-off-by: Fabien Dessenne fabien.dessenne@st.com --- drivers/remoteproc/rproc-elf-loader.c | 269 ++++++++++++++++++++++++++++++++++ include/remoteproc.h | 70 +++++++++ test/dm/remoteproc.c | 91 ++++++++++-- 3 files changed, 419 insertions(+), 11 deletions(-)
diff --git a/drivers/remoteproc/rproc-elf-loader.c b/drivers/remoteproc/rproc-elf-loader.c index b38a226..9127ea5 100644 --- a/drivers/remoteproc/rproc-elf-loader.c +++ b/drivers/remoteproc/rproc-elf-loader.c @@ -7,6 +7,39 @@ #include <elf.h> #include <remoteproc.h>
+/** + * struct resource_table - firmware resource table header + * @ver: version number + * @num: number of resource entries + * @reserved: reserved (must be zero) + * @offset: array of offsets pointing at the various resource entries + * + * A resource table is essentially a list of system resources required + * by the remote processor. It may also include configuration entries. + * If needed, the remote processor firmware should contain this table + * as a dedicated ".resource_table" ELF section. + * + * Some resources entries are mere announcements, where the host is informed + * of specific remoteproc configuration. Other entries require the host to + * do something (e.g. allocate a system resource). Sometimes a negotiation + * is expected, where the firmware requests a resource, and once allocated, + * the host should provide back its details (e.g. address of an allocated + * memory region). + * + * The header of the resource table, as expressed by this structure, + * contains a version number (should we need to change this format in the + * future), the number of available resource entries, and their offsets + * in the table. + * + * Immediately following this header are the resource entries themselves. + */ +struct resource_table { + u32 ver; + u32 num; + u32 reserved[2]; + u32 offset[0]; +} __packed; + /* Basic function to verify ELF32 image format */ int rproc_elf32_sanity_check(ulong addr, ulong size) { @@ -275,3 +308,239 @@ ulong rproc_elf_get_boot_addr(struct udevice *dev, ulong addr) else return rproc_elf32_get_boot_addr(addr); } + +/* + * Search for the resource table in an ELF32 image. + * Returns the address of the resource table section if found, NULL if there is + * no resource table section, or error pointer. + */ +static Elf32_Shdr *rproc_elf32_find_rsc_table(struct udevice *dev, + ulong fw_addr, ulong fw_size) +{ + int ret; + unsigned int i; + const char *name_table; + struct resource_table *table; + const u8 *elf_data = (void *)fw_addr; + Elf32_Ehdr *ehdr = (Elf32_Ehdr *)fw_addr; + Elf32_Shdr *shdr; + + ret = rproc_elf32_sanity_check(fw_addr, fw_size); + if (ret) { + pr_debug("Invalid ELF32 Image %d\n", ret); + return ERR_PTR(ret); + } + + /* look for the resource table and handle it */ + shdr = (Elf32_Shdr *)(elf_data + ehdr->e_shoff); + name_table = (const char *)(elf_data + + shdr[ehdr->e_shstrndx].sh_offset); + + for (i = 0; i < ehdr->e_shnum; i++, shdr++) { + u32 size = shdr->sh_size; + u32 offset = shdr->sh_offset; + + if (strcmp(name_table + shdr->sh_name, ".resource_table")) + continue; + + table = (struct resource_table *)(elf_data + offset); + + /* make sure we have the entire table */ + if (offset + size > fw_size) { + pr_debug("resource table truncated\n"); + return ERR_PTR(-ENOSPC); + } + + /* make sure table has at least the header */ + if (sizeof(*table) > size) { + pr_debug("header-less resource table\n"); + return ERR_PTR(-ENOSPC); + } + + /* we don't support any version beyond the first */ + if (table->ver != 1) { + pr_debug("unsupported fw ver: %d\n", table->ver); + return ERR_PTR(-EPROTONOSUPPORT); + } + + /* make sure reserved bytes are zeroes */ + if (table->reserved[0] || table->reserved[1]) { + pr_debug("non zero reserved bytes\n"); + return ERR_PTR(-EBADF); + } + + /* make sure the offsets array isn't truncated */ + if (table->num * sizeof(table->offset[0]) + + sizeof(*table) > size) { + pr_debug("resource table incomplete\n"); + return ERR_PTR(-ENOSPC); + } + + return shdr; + } + + return NULL; +} + +/* Load the resource table from an ELF32 image */ +int rproc_elf32_load_rsc_table(struct udevice *dev, ulong fw_addr, + ulong fw_size, ulong *rsc_addr, ulong *rsc_size) +{ + const struct dm_rproc_ops *ops; + Elf32_Shdr *shdr; + void *src, *dst; + + shdr = rproc_elf32_find_rsc_table(dev, fw_addr, fw_size); + if (!shdr) + return -ENODATA; + if (IS_ERR(shdr)) + return PTR_ERR(shdr); + + ops = rproc_get_ops(dev); + *rsc_addr = (ulong)shdr->sh_addr; + *rsc_size = (ulong)shdr->sh_size; + + src = (void *)fw_addr + shdr->sh_offset; + if (ops->device_to_virt) + dst = (void *)ops->device_to_virt(dev, *rsc_addr, *rsc_size); + else + dst = (void *)rsc_addr; + + dev_dbg(dev, "Loading resource table to 0x%8lx (%ld bytes)\n", + (ulong)dst, *rsc_size); + + memcpy(dst, src, *rsc_size); + flush_cache(rounddown((unsigned long)dst, ARCH_DMA_MINALIGN), + roundup((unsigned long)dst + *rsc_size, + ARCH_DMA_MINALIGN) - + rounddown((unsigned long)dst, ARCH_DMA_MINALIGN)); + + return 0; +} + +/* + * Search for the resource table in an ELF64 image. + * Returns the address of the resource table section if found, NULL if there is + * no resource table section, or error pointer. + */ +static Elf64_Shdr *rproc_elf64_find_rsc_table(struct udevice *dev, + ulong fw_addr, ulong fw_size) +{ + int ret; + unsigned int i; + const char *name_table; + struct resource_table *table; + const u8 *elf_data = (void *)fw_addr; + Elf64_Ehdr *ehdr = (Elf64_Ehdr *)fw_addr; + Elf64_Shdr *shdr; + + ret = rproc_elf64_sanity_check(fw_addr, fw_size); + if (ret) { + pr_debug("Invalid ELF64 Image %d\n", ret); + return ERR_PTR(ret); + } + + /* look for the resource table and handle it */ + shdr = (Elf64_Shdr *)(elf_data + ehdr->e_shoff); + name_table = (const char *)(elf_data + + shdr[ehdr->e_shstrndx].sh_offset); + + for (i = 0; i < ehdr->e_shnum; i++, shdr++) { + u64 size = shdr->sh_size; + u64 offset = shdr->sh_offset; + + if (strcmp(name_table + shdr->sh_name, ".resource_table")) + continue; + + table = (struct resource_table *)(elf_data + offset); + + /* make sure we have the entire table */ + if (offset + size > fw_size) { + pr_debug("resource table truncated\n"); + return ERR_PTR(-ENOSPC); + } + + /* make sure table has at least the header */ + if (sizeof(*table) > size) { + pr_debug("header-less resource table\n"); + return ERR_PTR(-ENOSPC); + } + + /* we don't support any version beyond the first */ + if (table->ver != 1) { + pr_debug("unsupported fw ver: %d\n", table->ver); + return ERR_PTR(-EPROTONOSUPPORT); + } + + /* make sure reserved bytes are zeroes */ + if (table->reserved[0] || table->reserved[1]) { + pr_debug("non zero reserved bytes\n"); + return ERR_PTR(-EBADF); + } + + /* make sure the offsets array isn't truncated */ + if (table->num * sizeof(table->offset[0]) + + sizeof(*table) > size) { + pr_debug("resource table incomplete\n"); + return ERR_PTR(-ENOSPC); + } + + return shdr; + } + + return NULL; +} + +/* Load the resource table from an ELF64 image */ +int rproc_elf64_load_rsc_table(struct udevice *dev, ulong fw_addr, + ulong fw_size, ulong *rsc_addr, ulong *rsc_size) +{ + const struct dm_rproc_ops *ops; + Elf64_Shdr *shdr; + void *src, *dst; + + shdr = rproc_elf64_find_rsc_table(dev, fw_addr, fw_size); + if (!shdr) + return -ENODATA; + if (IS_ERR(shdr)) + return PTR_ERR(shdr); + + ops = rproc_get_ops(dev); + *rsc_addr = (ulong)shdr->sh_addr; + *rsc_size = (ulong)shdr->sh_size; + + src = (void *)fw_addr + shdr->sh_offset; + if (ops->device_to_virt) + dst = (void *)ops->device_to_virt(dev, *rsc_addr, *rsc_size); + else + dst = (void *)rsc_addr; + + dev_dbg(dev, "Loading resource table to 0x%8lx (%ld bytes)\n", + (ulong)dst, *rsc_size); + + memcpy(dst, src, *rsc_size); + flush_cache(rounddown((unsigned long)dst, ARCH_DMA_MINALIGN), + roundup((unsigned long)dst + *rsc_size, + ARCH_DMA_MINALIGN) - + rounddown((unsigned long)dst, ARCH_DMA_MINALIGN)); + + return 0; +} + +/* Load the resource table from an ELF32 or ELF64 image */ +int rproc_elf_load_rsc_table(struct udevice *dev, ulong fw_addr, + ulong fw_size, ulong *rsc_addr, ulong *rsc_size) + +{ + Elf32_Ehdr *ehdr = (Elf32_Ehdr *)fw_addr; + + if (!fw_addr) + return -EFAULT; + + if (ehdr->e_ident[EI_CLASS] == ELFCLASS64) + return rproc_elf64_load_rsc_table(dev, fw_addr, fw_size, + rsc_addr, rsc_size); + else + return rproc_elf32_load_rsc_table(dev, fw_addr, fw_size, + rsc_addr, rsc_size); +} diff --git a/include/remoteproc.h b/include/remoteproc.h index 046cd9e..a903acb 100644 --- a/include/remoteproc.h +++ b/include/remoteproc.h @@ -277,6 +277,64 @@ int rproc_elf_load_image(struct udevice *dev, unsigned long addr, ulong size); * image. */ ulong rproc_elf_get_boot_addr(struct udevice *dev, ulong addr); + +/** + * rproc_elf32_load_rsc_table() - load the resource table from an ELF32 image + * + * Search for the resource table in an ELF32 image, and if found, copy it to + * device memory. + * + * @dev: device loading the resource table + * @fw_addr: ELF image address + * @fw_size: size of the ELF image + * @rsc_addr: pointer to the found resource table address. Updated on + * operation success + * @rsc_size: pointer to the found resource table size. Updated on operation + * success + * + * @return 0 if a valid resource table is successfully loaded, -ENODATA if there + * is no resource table (which is optional), or another appropriate error value. + */ +int rproc_elf32_load_rsc_table(struct udevice *dev, ulong fw_addr, + ulong fw_size, ulong *rsc_addr, ulong *rsc_size); +/** + * rproc_elf64_load_rsc_table() - load the resource table from an ELF64 image + * + * Search for the resource table in an ELF64 image, and if found, copy it to + * device memory. + * + * @dev: device loading the resource table + * @fw_addr: ELF image address + * @fw_size: size of the ELF image + * @rsc_addr: pointer to the found resource table address. Updated on + * operation success + * @rsc_size: pointer to the found resource table size. Updated on operation + * success + * + * @return 0 if a valid resource table is successfully loaded, -ENODATA if there + * is no resource table (which is optional), or another appropriate error value. + */ +int rproc_elf64_load_rsc_table(struct udevice *dev, ulong fw_addr, + ulong fw_size, ulong *rsc_addr, ulong *rsc_size); +/** + * rproc_elf_load_rsc_table() - load the resource table from an ELF image + * + * Auto detects if the image is ELF32 or ELF64 image and search accordingly for + * the resource table, and if found, copy it to device memory. + * + * @dev: device loading the resource table + * @fw_addr: ELF image address + * @fw_size: size of the ELF image + * @rsc_addr: pointer to the found resource table address. Updated on + * operation success + * @rsc_size: pointer to the found resource table size. Updated on operation + * success + * + * @return 0 if a valid resource table is successfully loaded, -ENODATA if there + * is no resource table (which is optional), or another appropriate error value. + */ +int rproc_elf_load_rsc_table(struct udevice *dev, ulong fw_addr, + ulong fw_size, ulong *rsc_addr, ulong *rsc_size); #else static inline int rproc_init(void) { return -ENOSYS; } static inline int rproc_dev_init(int id) { return -ENOSYS; } @@ -304,6 +362,18 @@ static inline int rproc_elf_load_image(struct udevice *dev, ulong addr, { return -ENOSYS; } static inline ulong rproc_elf_get_boot_addr(struct udevice *dev, ulong addr) { return 0; } +static inline int rproc_elf32_load_rsc_table(struct udevice *dev, ulong fw_addr, + ulong fw_size, ulong *rsc_addr, + ulong *rsc_size) +{ return -ENOSYS; } +static inline int rproc_elf64_load_rsc_table(struct udevice *dev, ulong fw_addr, + ulong fw_size, ulong *rsc_addr, + ulong *rsc_size) +{ return -ENOSYS; } +static inline int rproc_elf_load_rsc_table(struct udevice *dev, ulong fw_addr, + ulong fw_size, ulong *rsc_addr, + ulong *rsc_size) +{ return -ENOSYS; } #endif
#endif /* _RPROC_H_ */ diff --git a/test/dm/remoteproc.c b/test/dm/remoteproc.c index 1d9a9b3..4067596 100644 --- a/test/dm/remoteproc.c +++ b/test/dm/remoteproc.c @@ -103,8 +103,8 @@ static int dm_test_remoteproc_elf(struct unit_test_state *uts) 0x00, 0x00, 0x00, 0x08, /* phoff (program header offset @ 0x40)*/ 0x40, 0x00, 0x00, 0x00, - /* shoff (section header offset : none) */ - 0x00, 0x00, 0x00, 0x00, + /* shoff (section header offset @ 0x90) */ + 0x90, 0x00, 0x00, 0x00, /* flags */ 0x00, 0x00, 0x00, 0x00, /* ehsize (elf header size = 0x34) */ @@ -113,16 +113,17 @@ static int dm_test_remoteproc_elf(struct unit_test_state *uts) 0x20, 0x00, /* phnum (program header number : 1) */ 0x01, 0x00, - /* shentsize (section heade size : none) */ - 0x00, 0x00, - /* shnum (section header number: none) */ - 0x00, 0x00, - /* shstrndx (section header name section index: none) */ - 0x00, 0x00, + /* shentsize (section header size : 40 bytes) */ + 0x28, 0x00, + /* shnum (section header number: 3) */ + 0x02, 0x00, + /* shstrndx (section header name section index: 1) */ + 0x01, 0x00, /* padding */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* @0x40 - PROGRAM HEADER TABLE - */ /* type : PT_LOAD */ 0x01, 0x00, 0x00, 0x00, @@ -140,14 +141,63 @@ static int dm_test_remoteproc_elf(struct unit_test_state *uts) 0x05, 0x00, 0x00, 0x00, /* padding */ 0x00, 0x00, 0x00, 0x00, + + /* @0x60 - RESOURCE TABLE SECTION - */ + /* version */ + 0x01, 0x00, 0x00, 0x00, + /* num (0, no entries) */ + 0x00, 0x00, 0x00, 0x00, + /* Reserved */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + + /* @0x70 - SECTION'S NAMES SECTION - */ + /* section 0 name (".shrtrtab") */ + 0x2e, 0x73, 0x68, 0x73, 0x74, 0x72, 0x74, 0x61, 0x62, 0x00, + /* section 1 name (".resource_table") */ + 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, + 0x74, 0x61, 0x62, 0x6c, 0x65, 0x00, + /* padding */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + + /* @0x90 - SECTION HEADER TABLE - */ + /* Section 0 : resource table header */ + /* sh_name - index into section header string table section */ + 0x0a, 0x00, 0x00, 0x00, + /* sh_type and sh_flags */ + 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + /* sh_addr = where the resource table has to be copied to */ + 0x00, 0x00, 0x00, 0x00, + /* sh_offset = 0x60 */ + 0x60, 0x00, 0x00, 0x00, + /* sh_size = 16 bytes */ + 0x10, 0x00, 0x00, 0x00, + /* sh_link, sh_info, sh_addralign, sh_entsize */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* Section 1 : section's names section header */ + /* sh_name - index into section header string table section */ + 0x00, 0x00, 0x00, 0x00, + /* sh_type and sh_flags */ + 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* sh_addr */ + 0x00, 0x00, 0x00, 0x00, + /* sh_offset = 0x70 */ + 0x70, 0x00, 0x00, 0x00, + /* sh_size = 27 bytes */ + 0x1b, 0x00, 0x00, 0x00, + /* sh_link, sh_info, sh_addralign, sh_entsize */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }; unsigned int size = ARRAY_SIZE(valid_elf32); struct udevice *dev; - phys_addr_t loaded_firmware_paddr; - void *loaded_firmware; - u32 loaded_firmware_size; + phys_addr_t loaded_firmware_paddr, loaded_rsc_table_paddr; + void *loaded_firmware, *loaded_rsc_table; + u32 loaded_firmware_size, rsc_table_size; + ulong rsc_addr, rsc_size; Elf32_Ehdr *ehdr = (Elf32_Ehdr *)valid_elf32; Elf32_Phdr *phdr = (Elf32_Phdr *)(valid_elf32 + ehdr->e_phoff); + Elf32_Shdr *shdr = (Elf32_Shdr *)(valid_elf32 + ehdr->e_shoff);
ut_assertok(uclass_get_device(UCLASS_REMOTEPROC, 0, &dev));
@@ -178,6 +228,25 @@ static int dm_test_remoteproc_elf(struct unit_test_state *uts) 0x08000000); unmap_physmem(loaded_firmware, MAP_NOCACHE);
+ /* Resource table */ + shdr->sh_addr = CONFIG_SYS_SDRAM_BASE; + rsc_table_size = shdr->sh_size; + + loaded_rsc_table_paddr = shdr->sh_addr + DEVICE_TO_PHYSICAL_OFFSET; + loaded_rsc_table = map_physmem(loaded_rsc_table_paddr, + rsc_table_size, MAP_NOCACHE); + ut_assertnonnull(loaded_rsc_table); + memset(loaded_rsc_table, 0, rsc_table_size); + + /* Load and verify */ + ut_assertok(rproc_elf32_load_rsc_table(dev, (ulong)valid_elf32, size, + &rsc_addr, &rsc_size)); + ut_asserteq(rsc_addr, CONFIG_SYS_SDRAM_BASE); + ut_asserteq(rsc_size, rsc_table_size); + ut_assertok(memcmp(loaded_firmware, valid_elf32 + shdr->sh_offset, + shdr->sh_size)); + unmap_physmem(loaded_firmware, MAP_NOCACHE); + /* Invalid ELF Magic */ valid_elf32[0] = 0; ut_asserteq(-EPROTONOSUPPORT,

Hi Fabien,
From: Fabien DESSENNE fabien.dessenne@st.com Sent: mercredi 30 octobre 2019 14:38
Add rproc_elf_load_rsc_table(), which searches for a resource table in an elf64/elf32 image, and if found, copies it to device memory. Add also the elf32 and elf64 variants of this API. Add a test for this.
Signed-off-by: Fabien Dessenne fabien.dessenne@st.com
At least for STM32MP1 platform, I test a M4 elf firmware without resource table and it is working.
Acked-by: Patrick Delaunay patrick.delaunay@st.com
Thanks
Patrick

On 30/10/19 7:08 PM, Fabien Dessenne wrote:
Add rproc_elf_load_rsc_table(), which searches for a resource table in an elf64/elf32 image, and if found, copies it to device memory. Add also the elf32 and elf64 variants of this API. Add a test for this.
Signed-off-by: Fabien Dessenne fabien.dessenne@st.com
Reviewed-by: Lokesh Vutla lokeshvutla@ti.com
Thanks and regards, Lokesh
drivers/remoteproc/rproc-elf-loader.c | 269 ++++++++++++++++++++++++++++++++++ include/remoteproc.h | 70 +++++++++ test/dm/remoteproc.c | 91 ++++++++++-- 3 files changed, 419 insertions(+), 11 deletions(-)
diff --git a/drivers/remoteproc/rproc-elf-loader.c b/drivers/remoteproc/rproc-elf-loader.c index b38a226..9127ea5 100644 --- a/drivers/remoteproc/rproc-elf-loader.c +++ b/drivers/remoteproc/rproc-elf-loader.c @@ -7,6 +7,39 @@ #include <elf.h> #include <remoteproc.h>
+/**
- struct resource_table - firmware resource table header
- @ver: version number
- @num: number of resource entries
- @reserved: reserved (must be zero)
- @offset: array of offsets pointing at the various resource entries
- A resource table is essentially a list of system resources required
- by the remote processor. It may also include configuration entries.
- If needed, the remote processor firmware should contain this table
- as a dedicated ".resource_table" ELF section.
- Some resources entries are mere announcements, where the host is informed
- of specific remoteproc configuration. Other entries require the host to
- do something (e.g. allocate a system resource). Sometimes a negotiation
- is expected, where the firmware requests a resource, and once allocated,
- the host should provide back its details (e.g. address of an allocated
- memory region).
- The header of the resource table, as expressed by this structure,
- contains a version number (should we need to change this format in the
- future), the number of available resource entries, and their offsets
- in the table.
- Immediately following this header are the resource entries themselves.
- */
+struct resource_table {
- u32 ver;
- u32 num;
- u32 reserved[2];
- u32 offset[0];
+} __packed;
/* Basic function to verify ELF32 image format */ int rproc_elf32_sanity_check(ulong addr, ulong size) { @@ -275,3 +308,239 @@ ulong rproc_elf_get_boot_addr(struct udevice *dev, ulong addr) else return rproc_elf32_get_boot_addr(addr); }
+/*
- Search for the resource table in an ELF32 image.
- Returns the address of the resource table section if found, NULL if there is
- no resource table section, or error pointer.
- */
+static Elf32_Shdr *rproc_elf32_find_rsc_table(struct udevice *dev,
ulong fw_addr, ulong fw_size)
+{
- int ret;
- unsigned int i;
- const char *name_table;
- struct resource_table *table;
- const u8 *elf_data = (void *)fw_addr;
- Elf32_Ehdr *ehdr = (Elf32_Ehdr *)fw_addr;
- Elf32_Shdr *shdr;
- ret = rproc_elf32_sanity_check(fw_addr, fw_size);
- if (ret) {
pr_debug("Invalid ELF32 Image %d\n", ret);
return ERR_PTR(ret);
- }
- /* look for the resource table and handle it */
- shdr = (Elf32_Shdr *)(elf_data + ehdr->e_shoff);
- name_table = (const char *)(elf_data +
shdr[ehdr->e_shstrndx].sh_offset);
- for (i = 0; i < ehdr->e_shnum; i++, shdr++) {
u32 size = shdr->sh_size;
u32 offset = shdr->sh_offset;
if (strcmp(name_table + shdr->sh_name, ".resource_table"))
continue;
table = (struct resource_table *)(elf_data + offset);
/* make sure we have the entire table */
if (offset + size > fw_size) {
pr_debug("resource table truncated\n");
return ERR_PTR(-ENOSPC);
}
/* make sure table has at least the header */
if (sizeof(*table) > size) {
pr_debug("header-less resource table\n");
return ERR_PTR(-ENOSPC);
}
/* we don't support any version beyond the first */
if (table->ver != 1) {
pr_debug("unsupported fw ver: %d\n", table->ver);
return ERR_PTR(-EPROTONOSUPPORT);
}
/* make sure reserved bytes are zeroes */
if (table->reserved[0] || table->reserved[1]) {
pr_debug("non zero reserved bytes\n");
return ERR_PTR(-EBADF);
}
/* make sure the offsets array isn't truncated */
if (table->num * sizeof(table->offset[0]) +
sizeof(*table) > size) {
pr_debug("resource table incomplete\n");
return ERR_PTR(-ENOSPC);
}
return shdr;
- }
- return NULL;
+}
+/* Load the resource table from an ELF32 image */ +int rproc_elf32_load_rsc_table(struct udevice *dev, ulong fw_addr,
ulong fw_size, ulong *rsc_addr, ulong *rsc_size)
+{
- const struct dm_rproc_ops *ops;
- Elf32_Shdr *shdr;
- void *src, *dst;
- shdr = rproc_elf32_find_rsc_table(dev, fw_addr, fw_size);
- if (!shdr)
return -ENODATA;
- if (IS_ERR(shdr))
return PTR_ERR(shdr);
- ops = rproc_get_ops(dev);
- *rsc_addr = (ulong)shdr->sh_addr;
- *rsc_size = (ulong)shdr->sh_size;
- src = (void *)fw_addr + shdr->sh_offset;
- if (ops->device_to_virt)
dst = (void *)ops->device_to_virt(dev, *rsc_addr, *rsc_size);
- else
dst = (void *)rsc_addr;
- dev_dbg(dev, "Loading resource table to 0x%8lx (%ld bytes)\n",
(ulong)dst, *rsc_size);
- memcpy(dst, src, *rsc_size);
- flush_cache(rounddown((unsigned long)dst, ARCH_DMA_MINALIGN),
roundup((unsigned long)dst + *rsc_size,
ARCH_DMA_MINALIGN) -
rounddown((unsigned long)dst, ARCH_DMA_MINALIGN));
- return 0;
+}
+/*
- Search for the resource table in an ELF64 image.
- Returns the address of the resource table section if found, NULL if there is
- no resource table section, or error pointer.
- */
+static Elf64_Shdr *rproc_elf64_find_rsc_table(struct udevice *dev,
ulong fw_addr, ulong fw_size)
+{
- int ret;
- unsigned int i;
- const char *name_table;
- struct resource_table *table;
- const u8 *elf_data = (void *)fw_addr;
- Elf64_Ehdr *ehdr = (Elf64_Ehdr *)fw_addr;
- Elf64_Shdr *shdr;
- ret = rproc_elf64_sanity_check(fw_addr, fw_size);
- if (ret) {
pr_debug("Invalid ELF64 Image %d\n", ret);
return ERR_PTR(ret);
- }
- /* look for the resource table and handle it */
- shdr = (Elf64_Shdr *)(elf_data + ehdr->e_shoff);
- name_table = (const char *)(elf_data +
shdr[ehdr->e_shstrndx].sh_offset);
- for (i = 0; i < ehdr->e_shnum; i++, shdr++) {
u64 size = shdr->sh_size;
u64 offset = shdr->sh_offset;
if (strcmp(name_table + shdr->sh_name, ".resource_table"))
continue;
table = (struct resource_table *)(elf_data + offset);
/* make sure we have the entire table */
if (offset + size > fw_size) {
pr_debug("resource table truncated\n");
return ERR_PTR(-ENOSPC);
}
/* make sure table has at least the header */
if (sizeof(*table) > size) {
pr_debug("header-less resource table\n");
return ERR_PTR(-ENOSPC);
}
/* we don't support any version beyond the first */
if (table->ver != 1) {
pr_debug("unsupported fw ver: %d\n", table->ver);
return ERR_PTR(-EPROTONOSUPPORT);
}
/* make sure reserved bytes are zeroes */
if (table->reserved[0] || table->reserved[1]) {
pr_debug("non zero reserved bytes\n");
return ERR_PTR(-EBADF);
}
/* make sure the offsets array isn't truncated */
if (table->num * sizeof(table->offset[0]) +
sizeof(*table) > size) {
pr_debug("resource table incomplete\n");
return ERR_PTR(-ENOSPC);
}
return shdr;
- }
- return NULL;
+}
+/* Load the resource table from an ELF64 image */ +int rproc_elf64_load_rsc_table(struct udevice *dev, ulong fw_addr,
ulong fw_size, ulong *rsc_addr, ulong *rsc_size)
+{
- const struct dm_rproc_ops *ops;
- Elf64_Shdr *shdr;
- void *src, *dst;
- shdr = rproc_elf64_find_rsc_table(dev, fw_addr, fw_size);
- if (!shdr)
return -ENODATA;
- if (IS_ERR(shdr))
return PTR_ERR(shdr);
- ops = rproc_get_ops(dev);
- *rsc_addr = (ulong)shdr->sh_addr;
- *rsc_size = (ulong)shdr->sh_size;
- src = (void *)fw_addr + shdr->sh_offset;
- if (ops->device_to_virt)
dst = (void *)ops->device_to_virt(dev, *rsc_addr, *rsc_size);
- else
dst = (void *)rsc_addr;
- dev_dbg(dev, "Loading resource table to 0x%8lx (%ld bytes)\n",
(ulong)dst, *rsc_size);
- memcpy(dst, src, *rsc_size);
- flush_cache(rounddown((unsigned long)dst, ARCH_DMA_MINALIGN),
roundup((unsigned long)dst + *rsc_size,
ARCH_DMA_MINALIGN) -
rounddown((unsigned long)dst, ARCH_DMA_MINALIGN));
- return 0;
+}
+/* Load the resource table from an ELF32 or ELF64 image */ +int rproc_elf_load_rsc_table(struct udevice *dev, ulong fw_addr,
ulong fw_size, ulong *rsc_addr, ulong *rsc_size)
+{
- Elf32_Ehdr *ehdr = (Elf32_Ehdr *)fw_addr;
- if (!fw_addr)
return -EFAULT;
- if (ehdr->e_ident[EI_CLASS] == ELFCLASS64)
return rproc_elf64_load_rsc_table(dev, fw_addr, fw_size,
rsc_addr, rsc_size);
- else
return rproc_elf32_load_rsc_table(dev, fw_addr, fw_size,
rsc_addr, rsc_size);
+} diff --git a/include/remoteproc.h b/include/remoteproc.h index 046cd9e..a903acb 100644 --- a/include/remoteproc.h +++ b/include/remoteproc.h @@ -277,6 +277,64 @@ int rproc_elf_load_image(struct udevice *dev, unsigned long addr, ulong size);
- image.
*/ ulong rproc_elf_get_boot_addr(struct udevice *dev, ulong addr);
+/**
- rproc_elf32_load_rsc_table() - load the resource table from an ELF32 image
- Search for the resource table in an ELF32 image, and if found, copy it to
- device memory.
- @dev: device loading the resource table
- @fw_addr: ELF image address
- @fw_size: size of the ELF image
- @rsc_addr: pointer to the found resource table address. Updated on
operation success
- @rsc_size: pointer to the found resource table size. Updated on operation
success
- @return 0 if a valid resource table is successfully loaded, -ENODATA if there
- is no resource table (which is optional), or another appropriate error value.
- */
+int rproc_elf32_load_rsc_table(struct udevice *dev, ulong fw_addr,
ulong fw_size, ulong *rsc_addr, ulong *rsc_size);
+/**
- rproc_elf64_load_rsc_table() - load the resource table from an ELF64 image
- Search for the resource table in an ELF64 image, and if found, copy it to
- device memory.
- @dev: device loading the resource table
- @fw_addr: ELF image address
- @fw_size: size of the ELF image
- @rsc_addr: pointer to the found resource table address. Updated on
operation success
- @rsc_size: pointer to the found resource table size. Updated on operation
success
- @return 0 if a valid resource table is successfully loaded, -ENODATA if there
- is no resource table (which is optional), or another appropriate error value.
- */
+int rproc_elf64_load_rsc_table(struct udevice *dev, ulong fw_addr,
ulong fw_size, ulong *rsc_addr, ulong *rsc_size);
+/**
- rproc_elf_load_rsc_table() - load the resource table from an ELF image
- Auto detects if the image is ELF32 or ELF64 image and search accordingly for
- the resource table, and if found, copy it to device memory.
- @dev: device loading the resource table
- @fw_addr: ELF image address
- @fw_size: size of the ELF image
- @rsc_addr: pointer to the found resource table address. Updated on
operation success
- @rsc_size: pointer to the found resource table size. Updated on operation
success
- @return 0 if a valid resource table is successfully loaded, -ENODATA if there
- is no resource table (which is optional), or another appropriate error value.
- */
+int rproc_elf_load_rsc_table(struct udevice *dev, ulong fw_addr,
ulong fw_size, ulong *rsc_addr, ulong *rsc_size);
#else static inline int rproc_init(void) { return -ENOSYS; } static inline int rproc_dev_init(int id) { return -ENOSYS; } @@ -304,6 +362,18 @@ static inline int rproc_elf_load_image(struct udevice *dev, ulong addr, { return -ENOSYS; } static inline ulong rproc_elf_get_boot_addr(struct udevice *dev, ulong addr) { return 0; } +static inline int rproc_elf32_load_rsc_table(struct udevice *dev, ulong fw_addr,
ulong fw_size, ulong *rsc_addr,
ulong *rsc_size)
+{ return -ENOSYS; } +static inline int rproc_elf64_load_rsc_table(struct udevice *dev, ulong fw_addr,
ulong fw_size, ulong *rsc_addr,
ulong *rsc_size)
+{ return -ENOSYS; } +static inline int rproc_elf_load_rsc_table(struct udevice *dev, ulong fw_addr,
ulong fw_size, ulong *rsc_addr,
ulong *rsc_size)
+{ return -ENOSYS; } #endif
#endif /* _RPROC_H_ */ diff --git a/test/dm/remoteproc.c b/test/dm/remoteproc.c index 1d9a9b3..4067596 100644 --- a/test/dm/remoteproc.c +++ b/test/dm/remoteproc.c @@ -103,8 +103,8 @@ static int dm_test_remoteproc_elf(struct unit_test_state *uts) 0x00, 0x00, 0x00, 0x08, /* phoff (program header offset @ 0x40)*/ 0x40, 0x00, 0x00, 0x00,
/* shoff (section header offset : none) */
0x00, 0x00, 0x00, 0x00,
/* shoff (section header offset @ 0x90) */
/* flags */ 0x00, 0x00, 0x00, 0x00, /* ehsize (elf header size = 0x34) */0x90, 0x00, 0x00, 0x00,
@@ -113,16 +113,17 @@ static int dm_test_remoteproc_elf(struct unit_test_state *uts) 0x20, 0x00, /* phnum (program header number : 1) */ 0x01, 0x00,
/* shentsize (section heade size : none) */
0x00, 0x00,
/* shnum (section header number: none) */
0x00, 0x00,
/* shstrndx (section header name section index: none) */
0x00, 0x00,
/* shentsize (section header size : 40 bytes) */
0x28, 0x00,
/* shnum (section header number: 3) */
0x02, 0x00,
/* shstrndx (section header name section index: 1) */
/* padding */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,0x01, 0x00,
- /* @0x40 - PROGRAM HEADER TABLE - */ /* type : PT_LOAD */ 0x01, 0x00, 0x00, 0x00,
@@ -140,14 +141,63 @@ static int dm_test_remoteproc_elf(struct unit_test_state *uts) 0x05, 0x00, 0x00, 0x00, /* padding */ 0x00, 0x00, 0x00, 0x00,
/* @0x60 - RESOURCE TABLE SECTION - */
/* version */
0x01, 0x00, 0x00, 0x00,
/* num (0, no entries) */
0x00, 0x00, 0x00, 0x00,
/* Reserved */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* @0x70 - SECTION'S NAMES SECTION - */
/* section 0 name (".shrtrtab") */
0x2e, 0x73, 0x68, 0x73, 0x74, 0x72, 0x74, 0x61, 0x62, 0x00,
/* section 1 name (".resource_table") */
0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f,
0x74, 0x61, 0x62, 0x6c, 0x65, 0x00,
/* padding */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* @0x90 - SECTION HEADER TABLE - */
/* Section 0 : resource table header */
/* sh_name - index into section header string table section */
0x0a, 0x00, 0x00, 0x00,
/* sh_type and sh_flags */
0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
/* sh_addr = where the resource table has to be copied to */
0x00, 0x00, 0x00, 0x00,
/* sh_offset = 0x60 */
0x60, 0x00, 0x00, 0x00,
/* sh_size = 16 bytes */
0x10, 0x00, 0x00, 0x00,
/* sh_link, sh_info, sh_addralign, sh_entsize */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* Section 1 : section's names section header */
/* sh_name - index into section header string table section */
0x00, 0x00, 0x00, 0x00,
/* sh_type and sh_flags */
0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* sh_addr */
0x00, 0x00, 0x00, 0x00,
/* sh_offset = 0x70 */
0x70, 0x00, 0x00, 0x00,
/* sh_size = 27 bytes */
0x1b, 0x00, 0x00, 0x00,
/* sh_link, sh_info, sh_addralign, sh_entsize */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
}; unsigned int size = ARRAY_SIZE(valid_elf32); struct udevice *dev;0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- phys_addr_t loaded_firmware_paddr;
- void *loaded_firmware;
- u32 loaded_firmware_size;
phys_addr_t loaded_firmware_paddr, loaded_rsc_table_paddr;
void *loaded_firmware, *loaded_rsc_table;
u32 loaded_firmware_size, rsc_table_size;
ulong rsc_addr, rsc_size; Elf32_Ehdr *ehdr = (Elf32_Ehdr *)valid_elf32; Elf32_Phdr *phdr = (Elf32_Phdr *)(valid_elf32 + ehdr->e_phoff);
Elf32_Shdr *shdr = (Elf32_Shdr *)(valid_elf32 + ehdr->e_shoff);
ut_assertok(uclass_get_device(UCLASS_REMOTEPROC, 0, &dev));
@@ -178,6 +228,25 @@ static int dm_test_remoteproc_elf(struct unit_test_state *uts) 0x08000000); unmap_physmem(loaded_firmware, MAP_NOCACHE);
- /* Resource table */
- shdr->sh_addr = CONFIG_SYS_SDRAM_BASE;
- rsc_table_size = shdr->sh_size;
- loaded_rsc_table_paddr = shdr->sh_addr + DEVICE_TO_PHYSICAL_OFFSET;
- loaded_rsc_table = map_physmem(loaded_rsc_table_paddr,
rsc_table_size, MAP_NOCACHE);
- ut_assertnonnull(loaded_rsc_table);
- memset(loaded_rsc_table, 0, rsc_table_size);
- /* Load and verify */
- ut_assertok(rproc_elf32_load_rsc_table(dev, (ulong)valid_elf32, size,
&rsc_addr, &rsc_size));
- ut_asserteq(rsc_addr, CONFIG_SYS_SDRAM_BASE);
- ut_asserteq(rsc_size, rsc_table_size);
- ut_assertok(memcmp(loaded_firmware, valid_elf32 + shdr->sh_offset,
shdr->sh_size));
- unmap_physmem(loaded_firmware, MAP_NOCACHE);
- /* Invalid ELF Magic */ valid_elf32[0] = 0; ut_asserteq(-EPROTONOSUPPORT,

On Wed, Oct 30, 2019 at 02:38:28PM +0100, Fabien Dessenne wrote:
Add rproc_elf_load_rsc_table(), which searches for a resource table in an elf64/elf32 image, and if found, copies it to device memory. Add also the elf32 and elf64 variants of this API. Add a test for this.
Signed-off-by: Fabien Dessenne fabien.dessenne@st.com Acked-by: Patrick Delaunay patrick.delaunay@st.com Reviewed-by: Lokesh Vutla lokeshvutla@ti.com
Applied to u-boot/master, thanks!

Use the backup register #17 as coprocessor resource table address and backup register #18 as coprocessor state.
Signed-off-by: Fabien Dessenne fabien.dessenne@st.com --- arch/arm/mach-stm32mp/include/mach/stm32.h | 9 +++++++++ 1 file changed, 9 insertions(+)
diff --git a/arch/arm/mach-stm32mp/include/mach/stm32.h b/arch/arm/mach-stm32mp/include/mach/stm32.h index b3e9ccc..88126b8 100644 --- a/arch/arm/mach-stm32mp/include/mach/stm32.h +++ b/arch/arm/mach-stm32mp/include/mach/stm32.h @@ -86,9 +86,18 @@ enum boot_device { #define TAMP_BACKUP_REGISTER(x) (STM32_TAMP_BASE + 0x100 + 4 * x) #define TAMP_BACKUP_MAGIC_NUMBER TAMP_BACKUP_REGISTER(4) #define TAMP_BACKUP_BRANCH_ADDRESS TAMP_BACKUP_REGISTER(5) +#define TAMP_COPRO_RSC_TBL_ADDRESS TAMP_BACKUP_REGISTER(17) +#define TAMP_COPRO_STATE TAMP_BACKUP_REGISTER(18) #define TAMP_BOOT_CONTEXT TAMP_BACKUP_REGISTER(20) #define TAMP_BOOTCOUNT TAMP_BACKUP_REGISTER(21)
+#define TAMP_COPRO_STATE_OFF 0 +#define TAMP_COPRO_STATE_INIT 1 +#define TAMP_COPRO_STATE_CRUN 2 +#define TAMP_COPRO_STATE_CSTOP 3 +#define TAMP_COPRO_STATE_STANDBY 4 +#define TAMP_COPRO_STATE_CRASH 5 + #define TAMP_BOOT_MODE_MASK GENMASK(15, 8) #define TAMP_BOOT_MODE_SHIFT 8 #define TAMP_BOOT_DEVICE_MASK GENMASK(7, 4)

Hi Fabien,
From: Fabien DESSENNE fabien.dessenne@st.com Sent: mercredi 30 octobre 2019 14:38
Use the backup register #17 as coprocessor resource table address and backup register #18 as coprocessor state.
Signed-off-by: Fabien Dessenne fabien.dessenne@st.com
Acked-by: Patrick Delaunay patrick.delaunay@st.com
Thanks
Patrick

On Wed, Oct 30, 2019 at 02:38:29PM +0100, Fabien Dessenne wrote:
Use the backup register #17 as coprocessor resource table address and backup register #18 as coprocessor state.
Signed-off-by: Fabien Dessenne fabien.dessenne@st.com Acked-by: Patrick Delaunay patrick.delaunay@st.com
Applied to u-boot/master, thanks!

Reset ResourceTableAddress and CoprocessorState at cold boot, preserve these values at standby wakeup.
Signed-off-by: Fabien Dessenne fabien.dessenne@st.com --- arch/arm/mach-stm32mp/cpu.c | 7 +++++++ 1 file changed, 7 insertions(+)
diff --git a/arch/arm/mach-stm32mp/cpu.c b/arch/arm/mach-stm32mp/cpu.c index a46e843..e24abf5 100644 --- a/arch/arm/mach-stm32mp/cpu.c +++ b/arch/arm/mach-stm32mp/cpu.c @@ -34,7 +34,9 @@ #define TAMP_CR1 (STM32_TAMP_BASE + 0x00)
#define PWR_CR1 (STM32_PWR_BASE + 0x00) +#define PWR_MCUCR (STM32_PWR_BASE + 0x14) #define PWR_CR1_DBP BIT(8) +#define PWR_MCUCR_SBF BIT(6)
/* DBGMCU register */ #define DBGMCU_IDC (STM32_DBGMCU_BASE + 0x00) @@ -205,6 +207,11 @@ int arch_cpu_init(void) security_init(); update_bootmode(); #endif + /* Reset Coprocessor state unless it wakes up from Standby power mode */ + if (!(readl(PWR_MCUCR) & PWR_MCUCR_SBF)) { + writel(TAMP_COPRO_STATE_OFF, TAMP_COPRO_STATE); + writel(0, TAMP_COPRO_RSC_TBL_ADDRESS); + } #endif
boot_mode = get_bootmode();

Hi Fabien,
From: Fabien DESSENNE fabien.dessenne@st.com Sent: mercredi 30 octobre 2019 14:39
Reset ResourceTableAddress and CoprocessorState at cold boot, preserve these values at standby wakeup.
Signed-off-by: Fabien Dessenne fabien.dessenne@st.com
Acked-by: Patrick Delaunay patrick.delaunay@st.com
Thanks
Patrick

On Wed, Oct 30, 2019 at 02:38:30PM +0100, Fabien Dessenne wrote:
Reset ResourceTableAddress and CoprocessorState at cold boot, preserve these values at standby wakeup.
Signed-off-by: Fabien Dessenne fabien.dessenne@st.com Acked-by: Patrick Delaunay patrick.delaunay@st.com
Applied to u-boot/master, thanks!

Update the dedicated backup register to track the coprocessor state and rely on that register to compute the .is_running() value (which expects a return value of 0 -not 1- if the processor is running).
Signed-off-by: Fabien Dessenne fabien.dessenne@st.com --- drivers/remoteproc/stm32_copro.c | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-)
diff --git a/drivers/remoteproc/stm32_copro.c b/drivers/remoteproc/stm32_copro.c index 40bba37..dcafa54 100644 --- a/drivers/remoteproc/stm32_copro.c +++ b/drivers/remoteproc/stm32_copro.c @@ -22,14 +22,12 @@ * @hold_boot_regmap: regmap for remote processor reset hold boot * @hold_boot_offset: offset of the register controlling the hold boot setting * @hold_boot_mask: bitmask of the register for the hold boot field - * @is_running: is the remote processor running */ struct stm32_copro_privdata { struct reset_ctl reset_ctl; struct regmap *hold_boot_regmap; uint hold_boot_offset; uint hold_boot_mask; - bool is_running; };
/** @@ -165,11 +163,8 @@ static int stm32_copro_load(struct udevice *dev, ulong addr, ulong size) */ static int stm32_copro_start(struct udevice *dev) { - struct stm32_copro_privdata *priv; int ret;
- priv = dev_get_priv(dev); - /* move hold boot from true to false start the copro */ ret = stm32_copro_set_hold_boot(dev, false); if (ret) @@ -180,7 +175,8 @@ static int stm32_copro_start(struct udevice *dev) * rebooting autonomously */ ret = stm32_copro_set_hold_boot(dev, true); - priv->is_running = !ret; + writel(ret ? TAMP_COPRO_STATE_OFF : TAMP_COPRO_STATE_CRUN, + TAMP_COPRO_STATE); return ret; }
@@ -206,7 +202,7 @@ static int stm32_copro_reset(struct udevice *dev) return ret; }
- priv->is_running = false; + writel(TAMP_COPRO_STATE_OFF, TAMP_COPRO_STATE);
return 0; } @@ -224,14 +220,11 @@ static int stm32_copro_stop(struct udevice *dev) /** * stm32_copro_is_running() - Is the STM32 remote processor running * @dev: corresponding STM32 remote processor device - * @return 1 if the remote processor is running, 0 otherwise + * @return 0 if the remote processor is running, 1 otherwise */ static int stm32_copro_is_running(struct udevice *dev) { - struct stm32_copro_privdata *priv; - - priv = dev_get_priv(dev); - return priv->is_running; + return (readl(TAMP_COPRO_STATE) == TAMP_COPRO_STATE_OFF); }
static const struct dm_rproc_ops stm32_copro_ops = {

Hi Fabien,
From: Fabien DESSENNE fabien.dessenne@st.com Sent: mercredi 30 octobre 2019 14:39
Update the dedicated backup register to track the coprocessor state and rely on that register to compute the .is_running() value (which expects a return value of 0 -not 1- if the processor is running).
Signed-off-by: Fabien Dessenne fabien.dessenne@st.com
Acked-by: Patrick Delaunay patrick.delaunay@st.com
Thanks
Patrick

On Wed, Oct 30, 2019 at 02:38:31PM +0100, Fabien Dessenne wrote:
Update the dedicated backup register to track the coprocessor state and rely on that register to compute the .is_running() value (which expects a return value of 0 -not 1- if the processor is running).
Signed-off-by: Fabien Dessenne fabien.dessenne@st.com Acked-by: Patrick Delaunay patrick.delaunay@st.com
Applied to u-boot/master, thanks!

Since the coprocessor state is tracked in a backup register, there is no more need for tracking it in an environment variable : remove it.
Signed-off-by: Fabien Dessenne fabien.dessenne@st.com --- board/st/stm32mp1/stm32mp1.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/board/st/stm32mp1/stm32mp1.c b/board/st/stm32mp1/stm32mp1.c index 126af30..ea9afb6 100644 --- a/board/st/stm32mp1/stm32mp1.c +++ b/board/st/stm32mp1/stm32mp1.c @@ -935,10 +935,8 @@ static void board_copro_image_process(ulong fw_image, size_t fw_size) printf("Load Remote Processor %d with data@addr=0x%08lx %u bytes:%s\n", id, fw_image, fw_size, ret ? " Failed!" : " Success!");
- if (!ret) { + if (!ret) rproc_start(id); - env_set("copro_state", "booted"); - } }
U_BOOT_FIT_LOADABLE_HANDLER(IH_TYPE_COPRO, board_copro_image_process);

Hi Fabien,
From: Fabien DESSENNE fabien.dessenne@st.com Sent: mercredi 30 octobre 2019 14:39
Since the coprocessor state is tracked in a backup register, there is no more need for tracking it in an environment variable : remove it.
Signed-off-by: Fabien Dessenne fabien.dessenne@st.com
Acked-by: Patrick Delaunay patrick.delaunay@st.com
Thanks
Patrick

On Wed, Oct 30, 2019 at 02:38:32PM +0100, Fabien Dessenne wrote:
Since the coprocessor state is tracked in a backup register, there is no more need for tracking it in an environment variable : remove it.
Signed-off-by: Fabien Dessenne fabien.dessenne@st.com Acked-by: Patrick Delaunay patrick.delaunay@st.com
Applied to u-boot/master, thanks!

Load the optional resource table from the firmware, and write its address in the dedicated backup register.
Signed-off-by: Fabien Dessenne fabien.dessenne@st.com --- drivers/remoteproc/stm32_copro.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+)
diff --git a/drivers/remoteproc/stm32_copro.c b/drivers/remoteproc/stm32_copro.c index dcafa54..c25488f 100644 --- a/drivers/remoteproc/stm32_copro.c +++ b/drivers/remoteproc/stm32_copro.c @@ -22,12 +22,14 @@ * @hold_boot_regmap: regmap for remote processor reset hold boot * @hold_boot_offset: offset of the register controlling the hold boot setting * @hold_boot_mask: bitmask of the register for the hold boot field + * @rsc_table_addr: resource table address */ struct stm32_copro_privdata { struct reset_ctl reset_ctl; struct regmap *hold_boot_regmap; uint hold_boot_offset; uint hold_boot_mask; + ulong rsc_table_addr; };
/** @@ -139,6 +141,7 @@ static void *stm32_copro_device_to_virt(struct udevice *dev, ulong da, static int stm32_copro_load(struct udevice *dev, ulong addr, ulong size) { struct stm32_copro_privdata *priv; + ulong rsc_table_size; int ret;
priv = dev_get_priv(dev); @@ -153,6 +156,12 @@ static int stm32_copro_load(struct udevice *dev, ulong addr, ulong size) return ret; }
+ if (rproc_elf32_load_rsc_table(dev, addr, size, &priv->rsc_table_addr, + &rsc_table_size)) { + priv->rsc_table_addr = 0; + dev_warn(dev, "No valid resource table for this firmware\n"); + } + return rproc_elf32_load_image(dev, addr, size); }
@@ -163,8 +172,11 @@ static int stm32_copro_load(struct udevice *dev, ulong addr, ulong size) */ static int stm32_copro_start(struct udevice *dev) { + struct stm32_copro_privdata *priv; int ret;
+ priv = dev_get_priv(dev); + /* move hold boot from true to false start the copro */ ret = stm32_copro_set_hold_boot(dev, false); if (ret) @@ -177,6 +189,10 @@ static int stm32_copro_start(struct udevice *dev) ret = stm32_copro_set_hold_boot(dev, true); writel(ret ? TAMP_COPRO_STATE_OFF : TAMP_COPRO_STATE_CRUN, TAMP_COPRO_STATE); + if (!ret) + /* Store rsc_address in bkp register */ + writel(priv->rsc_table_addr, TAMP_COPRO_RSC_TBL_ADDRESS); + return ret; }

Hi Fabien,
From: Fabien DESSENNE fabien.dessenne@st.com Sent: mercredi 30 octobre 2019 14:39
Load the optional resource table from the firmware, and write its address in the dedicated backup register.
Signed-off-by: Fabien Dessenne fabien.dessenne@st.com
Acked-by: Patrick Delaunay patrick.delaunay@st.com
Thanks
Patrick

On Wed, Oct 30, 2019 at 02:38:33PM +0100, Fabien Dessenne wrote:
Load the optional resource table from the firmware, and write its address in the dedicated backup register.
Signed-off-by: Fabien Dessenne fabien.dessenne@st.com Acked-by: Patrick Delaunay patrick.delaunay@st.com
Applied to u-boot/master, thanks!
participants (4)
-
Fabien Dessenne
-
Lokesh Vutla
-
Patrick DELAUNAY
-
Tom Rini