From 8a13da322deb2d5372aabf824b0c910a4e7fcf33 Mon Sep 17 00:00:00 2001 From: wangjianyu3 Date: Wed, 23 Aug 2023 01:11:24 +0800 Subject: [PATCH] binfmt: Support arch copy section by self for dynamic code loading This option enables architecture-specific memory copy for dynamic code loading. For example, Ambiq has MRAM regions for instruction which can't load by the memcpy directly. Signed-off-by: wangjianyu3 --- arch/Kconfig | 15 +++++++++++ binfmt/libelf/libelf_read.c | 50 +++++++++++++++++++++++++++++++------ include/nuttx/arch.h | 15 +++++++++++ 3 files changed, 73 insertions(+), 7 deletions(-) diff --git a/arch/Kconfig b/arch/Kconfig index cb25e93dad..04f8872047 100644 --- a/arch/Kconfig +++ b/arch/Kconfig @@ -401,6 +401,12 @@ config ARCH_HAVE_TEXT_HEAP ---help--- Special memory region for dynamic code loading +config ARCH_HAVE_COPY_SECTION + bool + default n + ---help--- + Section copying for dynamic code loading + config ARCH_HAVE_MULTICPU bool default n @@ -623,6 +629,15 @@ menuconfig ARCH_ADDRENV Support per-task address environments using the MMU... i.e., support "processes" +config ARCH_USE_COPY_SECTION + bool "Enable arch copy section by self for dynamic code loading" + default n + depends on ARCH_HAVE_COPY_SECTION + ---help--- + This option enables architecture-specific memory copy for + dynamic code loading. For example, Ambiq has MRAM regions + for instruction which can't load by the memcpy directly. + if ARCH_ADDRENV && ARCH_NEED_ADDRENV_MAPPING config ARCH_TEXT_VBASE diff --git a/binfmt/libelf/libelf_read.c b/binfmt/libelf/libelf_read.c index ef6feea92d..7dce05d06e 100644 --- a/binfmt/libelf/libelf_read.c +++ b/binfmt/libelf/libelf_read.c @@ -98,9 +98,23 @@ static inline void elf_dumpreaddata(FAR char *buffer, size_t buflen) int elf_read(FAR struct elf_loadinfo_s *loadinfo, FAR uint8_t *buffer, size_t readsize, off_t offset) { - size_t nsize = readsize; - ssize_t nbytes; /* Number of bytes read */ - off_t rpos; /* Position returned by lseek */ + size_t nsize = readsize; /* Bytes to read from the object file */ + ssize_t nbytes; /* Number of bytes read */ + off_t rpos; /* Position returned by lseek */ + int ret = OK; /* Return value */ + +#ifdef CONFIG_ARCH_USE_COPY_SECTION + FAR uint8_t *dest = buffer; /* Destination address - `buffer` */ + + /* Redirect `buffer` to temporary allocated memory */ + + buffer = kmm_malloc(readsize); + if (buffer == NULL) + { + berr("ERROR: Failed to allocate memory\n"); + return -ENOMEM; + } +#endif binfo("Read %zu bytes from offset %" PRIdOFF "\n", readsize, offset); @@ -115,7 +129,8 @@ int elf_read(FAR struct elf_loadinfo_s *loadinfo, FAR uint8_t *buffer, { berr("Failed to seek to position %" PRIdOFF ": %" PRIdOFF "\n", offset, rpos); - return rpos; + ret = rpos; + goto errout; } /* Read the file data at offset into the user buffer */ @@ -130,13 +145,15 @@ int elf_read(FAR struct elf_loadinfo_s *loadinfo, FAR uint8_t *buffer, { berr("Read from offset %" PRIdOFF " failed: %zd\n", offset, nbytes); - return nbytes; + ret = nbytes; + goto errout; } } else if (nbytes == 0) { berr("Unexpected end of file\n"); - return -ENODATA; + ret = -ENODATA; + goto errout; } else { @@ -145,6 +162,25 @@ int elf_read(FAR struct elf_loadinfo_s *loadinfo, FAR uint8_t *buffer, } } +#ifdef CONFIG_ARCH_USE_COPY_SECTION + /* Copy the requested data from temporary memory to destination */ + + ret = up_copy_section(dest, buffer, nsize); + if (ret < 0) + { + berr("ERROR: Failed to copy section at offset %"PRIdOFF"\n", offset); + goto errout; + } +#endif + elf_dumpreaddata(buffer, nsize); - return OK; + +errout: +#ifdef CONFIG_ARCH_USE_COPY_SECTION + /* Free the temporary memory */ + + kmm_free(buffer); +#endif + + return ret; } diff --git a/include/nuttx/arch.h b/include/nuttx/arch.h index 4a647afedb..5bad8fddf7 100644 --- a/include/nuttx/arch.h +++ b/include/nuttx/arch.h @@ -772,6 +772,21 @@ void up_textheap_free(FAR void *p); bool up_textheap_heapmember(FAR void *p); #endif +/**************************************************************************** + * Name: up_copy_section + * + * Description: + * Copy section from general temporary buffer(src) to special addr(dest). + * + * Returned Value: + * Zero (OK) on success; a negated errno value on failure. + * + ****************************************************************************/ + +#if defined(CONFIG_ARCH_USE_COPY_SECTION) +int up_copy_section(FAR void *dest, FAR const void *src, size_t n); +#endif + /**************************************************************************** * Name: up_setpicbase and up_getpicbase *