#include <linux/linkage.h>
#endif
-/* Allow ports to override the default behavior */
-static unsigned long do_bootelf_exec(ulong (*entry)(int, char * const[]),
- int argc, char *const argv[])
-{
- unsigned long ret;
-
- /*
- * pass address parameter as argv[0] (aka command name),
- * and all remaining args
- */
- ret = entry(argc, argv);
-
- return ret;
-}
-
/* Interpreter command to boot an arbitrary ELF image from memory */
int do_bootelf(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
{
#endif
unsigned long addr; /* Address of the ELF image */
unsigned long rc; /* Return value from user code */
- char *sload = NULL;
- int rcode = 0;
+ int rcode = CMD_RET_SUCCESS;
+ Bootelf_flags flags = {0};
/* Consume 'bootelf' */
argc--; argv++;
/* Check for [-p|-s] flag. */
if (argc >= 1 && (argv[0][0] == '-' && \
(argv[0][1] == 'p' || argv[0][1] == 's'))) {
- sload = argv[0];
+ if (argv[0][1] == 'p')
+ flags.phdr = 1;
+ log_debug("Using ELF header format %s\n",
+ flags.phdr ? "phdr" : "shdr");
/* Consume flag. */
argc--; argv++;
}
} else
addr = image_load_addr;
- if (!valid_elf_image(addr))
- return 1;
-
- if (sload && sload[1] == 'p')
- addr = load_elf_image_phdr(addr);
- else
- addr = load_elf_image_shdr(addr);
-
#if CONFIG_IS_ENABLED(CMD_ELF_FDT_SETUP)
if (fdt_addr) {
- printf("## Setting up FDT at 0x%08lx ...\n", fdt_addr);
+ log_debug("Setting up FDT at 0x%08lx ...\n", fdt_addr);
flush();
if (image_setup_libfdt(&img, (void *)fdt_addr, NULL))
}
#endif
- if (!env_get_autostart())
- return rcode;
-
- printf("## Starting application at 0x%08lx ...\n", addr);
- flush();
+ if (env_get_autostart()) {
+ flags.autostart = 1;
+ log_debug("Starting application at 0x%08lx ...\n", addr);
+ flush();
+ }
/*
* pass address parameter as argv[0] (aka command name),
- * and all remaining args
+ * and all remaining arguments
*/
- rc = do_bootelf_exec((void *)addr, argc, argv);
+ rc = bootelf(addr, flags, argc, argv);
if (rc != 0)
- rcode = 1;
+ rcode = CMD_RET_FAILURE;
- printf("## Application terminated, rc = 0x%lx\n", rc);
+ if (flags.autostart)
+ {
+ if (ENOEXEC == errno)
+ log_err("Invalid ELF image\n");
+ else
+ log_debug("## Application terminated, rc = 0x%lx\n", rc);
+ }
return rcode;
}
#ifndef __ASSEMBLY__
#include "compiler.h"
+/* Flag param bits for bootelf() function */
+typedef struct {
+ unsigned phdr : 1; /* load via program (not section) headers */
+ unsigned autostart : 1; /* Start ELF after loading */
+} Bootelf_flags;
+
/* This version doesn't work for 64-bit ABIs - Erik */
/* These typedefs need to be handled better */
#define R_RISCV_RELATIVE 3
#ifndef __ASSEMBLY__
+unsigned long bootelf_exec(ulong (*entry)(int, char * const[]),
+ int argc, char *const argv[]);
+unsigned long bootelf(unsigned long addr, Bootelf_flags flags,
+ int argc, char *const argv[]);
int valid_elf_image(unsigned long addr);
unsigned long load_elf64_image_phdr(unsigned long addr);
unsigned long load_elf64_image_shdr(unsigned long addr);
#include <cpu_func.h>
#include <elf.h>
#include <env.h>
+#include <errno.h>
#include <net.h>
#include <vxworks.h>
#ifdef CONFIG_X86
#include <linux/linkage.h>
#endif
+/**
+ * bootelf_exec() - start the ELF image execution.
+ *
+ * @entry: address of entry point of ELF.
+ *
+ * May by used to allow ports to override the default behavior.
+ */
+unsigned long bootelf_exec(ulong (*entry)(int, char * const[]),
+ int argc, char *const argv[])
+{
+ return entry(argc, argv);
+}
+
+/**
+ * bootelf() - Boot ELF from memory.
+ *
+ * @addr: Loading address of ELF in memory.
+ * @flags: Bits like ELF_PHDR to control boot details.
+ * @argc: May be used to pass command line arguments (maybe unused).
+ * Necessary for backward compatibility with the CLI command.
+ * If unused, must be 0.
+ * @argv: see @argc. If unused, must be NULL.
+ * Return: Number returned by ELF application.
+ *
+ * Sets errno = ENOEXEC if the ELF image is not valid.
+ */
+unsigned long bootelf(unsigned long addr, Bootelf_flags flags,
+ int argc, char *const argv[])
+{
+ unsigned long entry_addr;
+ char *args[] = {"", NULL};
+
+ errno = 0;
+
+ if (!valid_elf_image(addr)) {
+ errno = ENOEXEC;
+ return 1;
+ }
+
+ entry_addr = flags.phdr ? load_elf_image_phdr(addr)
+ : load_elf_image_shdr(addr);
+
+ if (!flags.autostart)
+ return 0;
+
+ if (!argc && !argv) {
+ argc = 1;
+ argv = args;
+ }
+
+ return bootelf_exec((void *)entry_addr, argc, argv);
+}
+
/*
* A very simple ELF64 loader, assumes the image is valid, returns the
* entry point address.