Skip to contentSkip to conversation

cmd_elf: CONFIG_ELF_SIMPLE_LOAD: load ELFs according to PHDRs

PATCH Superseded Mike Frysinger 2 participants 6 messages Nov 2, 2008 – Oct 6, 2010

v1 of 2 Superseded Latest is v2 →

lore
Share & tools
lore
#0 lore raw

PATCH 1/1 cmd_elf: CONFIG_ELF_SIMPLE_LOAD: load ELFs according to PHDRs

The current ELF loading function does a lot of work above and beyond a simple "loading". It ignores the real load addresses and loads things into their virtual (runtime) address. This is undesirable when we just want it to load an ELF and let the ELF do the actual C runtime init.

---
 common/cmd_elf.c |   27 +++++++++++++++++++++++++++
 1 files changed, 27 insertions(+), 0 deletions(-)
common/cmd_elf.c +27 -0
index 3ebb6d9..7b82749 100644
@@ -276,6 +276,32 @@ int valid_elf_image (unsigned long addr)
  * A very simple elf loader, assumes the image is valid, returns the
  * entry point address.
  * ====================================================================== */
+#ifdef CONFIG_ELF_SIMPLE_LOAD
+unsigned long load_elf_image (unsigned long addr)
+{
+	Elf32_Ehdr *ehdr;
+	Elf32_Phdr *phdr;
+	unsigned long entry;
+	size_t i;
+
+	ehdr = (Elf32_Ehdr *) addr;
+	phdr = (Elf32_Phdr *) (addr + ehdr->e_phoff);
+
+	entry = ehdr->e_entry;
+
+	/* Load each program header */
+	for (i = 0; i < ehdr->e_phnum; ++i) {
+		void *dst = (void *) phdr->p_paddr;
+		void *src = (void *) addr + phdr->p_offset;
+		printf ("Loading phdr %i to 0x%p (%i bytes)\n",
+		        i, dst, phdr->p_filesz);
+		memcpy (dst, src, phdr->p_filesz);
+		++phdr;
+	}
+
+	return entry;
+}
+#else
 unsigned long load_elf_image (unsigned long addr)
 {
 	Elf32_Ehdr *ehdr;		/* Elf header structure pointer     */
@@ -327,6 +353,7 @@ unsigned long load_elf_image (unsigned long addr)
 
 	return ehdr->e_entry;
 }
+#endif
 
 /* ====================================================================== */
 U_BOOT_CMD(
Signature · 1 line
1.6.0.3
#1 lore raw

PATCH 1/1 cmd_elf: CONFIG_ELF_SIMPLE_LOAD: load ELFs according to PHDRs

Dear Mike,

Quoted 4 lines · In message <[email protected]> you wrote:

The current ELF loading function does a lot of work above and beyond a simple "loading". It ignores the real load addresses and loads things into their virtual (runtime) address. This is undesirable when we just want it to load an ELF and let the ELF do the actual C runtime init.

I apologize for the late review...

common/cmd_elf.c int valid_elf_image (unsigned long addr) · line 280

Quoted 2 lines
common/cmd_elf.c +2 -0
+#ifdef CONFIG_ELF_SIMPLE_LOAD
+unsigned long load_elf_image (unsigned long addr)

...

...but would it not make sense to allow to make the decision which behaviour fits the user's requirements at runtime instead of compile time?

We could either make this depend on some environment variable setting, or on a command line option when running the command.

If you prefer to stick with the CONFIG_ELF_SIMPLE_LOAD solution, then this variable has to be documented in the README.

Best regards,

Wolfgang Denk

Signature · 4 lines
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
The Gates in my computer are AND, OR and NOT; they are not Bill.
#2 lore raw

PATCH 1/1 cmd_elf: CONFIG_ELF_SIMPLE_LOAD: load ELFs according to PHDRs

Quoted 17 lines · On Friday 05 December 2008 17:21:27 Wolfgang Denk wrote:
Quoted 4 lines · In message <[email protected]> you wrote:

The current ELF loading function does a lot of work above and beyond a simple "loading". It ignores the real load addresses and loads things into their virtual (runtime) address. This is undesirable when we just want it to load an ELF and let the ELF do the actual C runtime init.

I apologize for the late review...

common/cmd_elf.c int valid_elf_image (unsigned long addr) · line 280

Quoted 2 lines
common/cmd_elf.c +2 -0
+#ifdef CONFIG_ELF_SIMPLE_LOAD
+unsigned long load_elf_image (unsigned long addr)

...

...but would it not make sense to allow to make the decision which behaviour fits the user's requirements at runtime instead of compile time?

Quoted 6 lines

We could either make this depend on some environment variable setting, or on a command line option when running the command.

If you prefer to stick with the CONFIG_ELF_SIMPLE_LOAD solution, then this variable has to be documented in the README.

it doesnt matter to me which route is taken so long as the default can be controlled (so via env is ok as you can set the default env values). if you prefer one over the other, let me know. otherwise simply updating the README is the easiest route for me ...
-mike
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 835 bytes
Desc: This is a digitally signed message part.
Url : http://lists.denx.de/pipermail/u-boot/attachments/20081205/9ba137e8/attachment.pgp

#3 lore raw

PATCH 1/1 cmd_elf: CONFIG_ELF_SIMPLE_LOAD: load ELFs according to PHDRs

Dear Mike,

Quoted 9 lines · in message <[email protected]> you wrote:
Quoted 9 lines

...but would it not make sense to allow to make the decision which behaviour fits the user's requirements at runtime instead of compile time?

We could either make this depend on some environment variable setting, or on a command line option when running the command.

Quoted 7 lines
Quoted 2 lines

If you prefer to stick with the CONFIG_ELF_SIMPLE_LOAD solution, then this variable has to be documented in the README.

it doesnt matter to me which route is taken so long as the default can be controlled (so via env is ok as you can set the default env values). if you prefer one over the other, let me know. otherwise simply updating the README is the easiest route for me ...

Well, my preference is a command line option; I think we should move into that direction instead of adding more and more magic environment variables.

But if you submit a patch that uses environment variables I would not object either.

Thanks.

Best regards,

Wolfgang Denk

Signature · 5 lines
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
To the systems programmer,  users  and  applications  serve  only  to
provide a test load.
#4 lore raw

PATCH 1/1 cmd_elf: add an option for loading ELFs according to PHDRs

In reply to Mike Frysinger

The current ELF loading function does a lot of work above and beyond a simple "loading". It ignores the real load addresses and loads things into their virtual (runtime) address. This is undesirable when we just want it to load an ELF and let the ELF do the actual C runtime init.

So add a command line option to let people choose to load via either the program or section headers. I'd prefer to have program header loading be the default, but this would break historical behavior, so I'll leave section header loading as the norm.

---
 common/cmd_elf.c |   62 ++++++++++++++++++++++++++++++++++++++++++++++-------
 1 files changed, 53 insertions(+), 9 deletions(-)
common/cmd_elf.c +53 -9
index 104d6e6..bf32612 100644
@@ -25,7 +25,8 @@ DECLARE_GLOBAL_DATA_PTR;
 #endif
 
 int valid_elf_image (unsigned long addr);
-unsigned long load_elf_image (unsigned long addr);
+static unsigned long load_elf_image_phdr(unsigned long addr);
+static unsigned long load_elf_image_shdr(unsigned long addr);
 
 /* Allow ports to override the default behavior */
 __attribute__((weak))
@@ -61,19 +62,34 @@ int do_bootelf (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 {
 	unsigned long addr;		/* Address of the ELF image     */
 	unsigned long rc;		/* Return value from user code  */
+	char *sload, *saddr;
 
 	/* -------------------------------------------------- */
 	int rcode = 0;
 
-	if (argc < 2)
-		addr = load_addr;
+	sload = saddr = NULL;
+	if (argc == 3) {
+		sload = argv[1];
+		saddr = argv[2];
+	} else if (argc == 2) {
+		if (argv[1][0] == '-')
+			sload = argv[1];
+		else
+			saddr = argv[1];
+	}
+
+	if (saddr)
+		addr = simple_strtoul(saddr, NULL, 16);
 	else
-		addr = simple_strtoul (argv[1], NULL, 16);
+		addr = load_addr;
 
 	if (!valid_elf_image (addr))
 		return 1;
 
-	addr = load_elf_image (addr);
+	if (sload && sload[1] == 'p')
+		addr = load_elf_image_phdr(addr);
+	else
+		addr = load_elf_image_shdr(addr);
 
 	printf ("## Starting application@0x%08lx ...\n", addr);
 
@@ -204,7 +220,7 @@ int do_bootvx (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 	 */
 
 	if (valid_elf_image (addr)) {
-		addr = load_elf_image (addr);
+		addr = load_elf_image_shdr (addr);
 	} else {
 		puts ("## Not an ELF image, assuming binary\n");
 		/* leave addr as load_addr */
@@ -258,7 +274,33 @@ int valid_elf_image (unsigned long addr)
  * A very simple elf loader, assumes the image is valid, returns the
  * entry point address.
  * ====================================================================== */
-unsigned long load_elf_image (unsigned long addr)
+static unsigned long load_elf_image_phdr(unsigned long addr)
+{
+	Elf32_Ehdr *ehdr;		/* Elf header structure pointer     */
+	Elf32_Phdr *phdr;		/* Program header structure pointer */
+	int i;
+
+	ehdr = (Elf32_Ehdr *) addr;
+	phdr = (Elf32_Phdr *) (addr + ehdr->e_phoff);
+
+	/* Load each program header */
+	for (i = 0; i < ehdr->e_phnum; ++i) {
+		void *dst = (void *) phdr->p_paddr;
+		void *src = (void *) addr + phdr->p_offset;
+		debug("Loading phdr %i to 0x%p (%i bytes)\n",
+			i, dst, phdr->p_filesz);
+		if (phdr->p_filesz)
+			memcpy(dst, src, phdr->p_filesz);
+		if (phdr->p_filesz != phdr->p_memsz)
+			memset(dst + phdr->p_filesz, 0x00, phdr->p_memsz - phdr->p_filesz);
+		flush_cache((unsigned long)dst, phdr->p_filesz);
+		++phdr;
+	}
+
+	return ehdr->e_entry;
+}
+
+static unsigned long load_elf_image_shdr(unsigned long addr)
 {
 	Elf32_Ehdr *ehdr;		/* Elf header structure pointer     */
 	Elf32_Shdr *shdr;		/* Section header structure pointer */
@@ -312,9 +354,11 @@ unsigned long load_elf_image (unsigned long addr)
 
 /* ====================================================================== */
 U_BOOT_CMD(
-	bootelf,      2,      0,      do_bootelf,
+	bootelf,      3,      0,      do_bootelf,
 	"Boot from an ELF image in memory",
-	" [address] - load address of ELF image."
+	"[-p|-s] [address]\n"
+	"\t- load ELF image at [address] via program headers (-p)\n"
+	"\t  or via section headers (-s)"
 );
 
 U_BOOT_CMD(
Signature · 1 line
1.7.3.1
#5 lore raw

PATCH 1/1 cmd_elf: add an option for loading ELFs according to PHDRs

Dear Mike Frysinger,

Quoted 10 lines · In message <[email protected]> you wrote:

The current ELF loading function does a lot of work above and beyond a simple "loading". It ignores the real load addresses and loads things into their virtual (runtime) address. This is undesirable when we just want it to load an ELF and let the ELF do the actual C runtime init.

So add a command line option to let people choose to load via either the program or section headers. I'd prefer to have program header loading be the default, but this would break historical behavior, so I'll leave section header loading as the norm.

Quoted 4 lines
---
 common/cmd_elf.c |   62 ++++++++++++++++++++++++++++++++++++++++++++++-------
 1 files changed, 53 insertions(+), 9 deletions(-)

Applied, thanks.

Best regards,

Wolfgang Denk

Signature · 6 lines
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
When properly administered, vacations do not  diminish  productivity:
for every week you're away and get nothing done, there's another when
your boss is away and you get twice as much done.  -- Daniel B. Luten