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 <wangjianyu3@xiaomi.com>
This commit is contained in:
wangjianyu3 2023-08-23 01:11:24 +08:00 committed by Xiang Xiao
parent c749e4bfbd
commit 8a13da322d
3 changed files with 73 additions and 7 deletions

View file

@ -401,6 +401,12 @@ config ARCH_HAVE_TEXT_HEAP
---help--- ---help---
Special memory region for dynamic code loading 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 config ARCH_HAVE_MULTICPU
bool bool
default n default n
@ -623,6 +629,15 @@ menuconfig ARCH_ADDRENV
Support per-task address environments using the MMU... i.e., support Support per-task address environments using the MMU... i.e., support
"processes" "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 if ARCH_ADDRENV && ARCH_NEED_ADDRENV_MAPPING
config ARCH_TEXT_VBASE config ARCH_TEXT_VBASE

View file

@ -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, int elf_read(FAR struct elf_loadinfo_s *loadinfo, FAR uint8_t *buffer,
size_t readsize, off_t offset) size_t readsize, off_t offset)
{ {
size_t nsize = readsize; size_t nsize = readsize; /* Bytes to read from the object file */
ssize_t nbytes; /* Number of bytes read */ ssize_t nbytes; /* Number of bytes read */
off_t rpos; /* Position returned by lseek */ 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); 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", berr("Failed to seek to position %" PRIdOFF ": %" PRIdOFF "\n",
offset, rpos); offset, rpos);
return rpos; ret = rpos;
goto errout;
} }
/* Read the file data at offset into the user buffer */ /* 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", berr("Read from offset %" PRIdOFF " failed: %zd\n",
offset, nbytes); offset, nbytes);
return nbytes; ret = nbytes;
goto errout;
} }
} }
else if (nbytes == 0) else if (nbytes == 0)
{ {
berr("Unexpected end of file\n"); berr("Unexpected end of file\n");
return -ENODATA; ret = -ENODATA;
goto errout;
} }
else 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); elf_dumpreaddata(buffer, nsize);
return OK;
errout:
#ifdef CONFIG_ARCH_USE_COPY_SECTION
/* Free the temporary memory */
kmm_free(buffer);
#endif
return ret;
} }

View file

@ -772,6 +772,21 @@ void up_textheap_free(FAR void *p);
bool up_textheap_heapmember(FAR void *p); bool up_textheap_heapmember(FAR void *p);
#endif #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 * Name: up_setpicbase and up_getpicbase
* *