On Thu, 26 Jun 2014 14:11:32 -0700 Owen Kirby <osk@xxxxxxxxxx> wrote: Here are some ELF-unrelated comments on your patch: 1. please use 'git send-email' for sending patches; 2. please use scripts/checkpatch.pl on your patches before sending them to maillist; My checkpatch.pl reports about errors: total: 28 errors, 28 warnings, 399 lines checked > From 1edc77c7b960d5b42ac3c03000ac5063018195f9 Mon Sep 17 00:00:00 2001 > From: Owen Kirby <osk@xxxxxxxxxx> > Date: Thu, 26 Jun 2014 13:40:06 -0700 > Subject: [PATCH] Support for booting ELF images. > > This patch adds a bootelf command to load and execute OS kernels from the ELF format. > > Signed-off-by: Owen Kirby <osk@xxxxxxxxxx> > --- > commands/Kconfig | 7 ++ > commands/Makefile | 1 + > commands/bootelf.c | 112 ++++++++++++++++++++++++++ > common/Kconfig | 3 + > common/Makefile | 1 + > common/elf.c | 222 ++++++++++++++++++++++++++++++++++++++++++++++++++++ > common/filetype.c | 3 + > include/elf.h | 4 + > include/filetype.h | 1 + > 9 files changed, 354 insertions(+) > create mode 100644 commands/bootelf.c > create mode 100644 common/elf.c > > diff --git a/commands/Kconfig b/commands/Kconfig > index cc014f3..c4e4649 100644 > --- a/commands/Kconfig > +++ b/commands/Kconfig > @@ -507,6 +507,13 @@ config CMD_BOOTU > compile in the 'bootu' command to start raw (uncompressed) > Linux images > > +config CMD_BOOTELF > + select ELF > + tristate > + prompt "elf" > + help > + compile the 'bootelf' command to start ELF images > + > config FLEXIBLE_BOOTARGS > bool > prompt "flexible Linux bootargs generation" > diff --git a/commands/Makefile b/commands/Makefile > index e463031..fd57811 100644 > --- a/commands/Makefile > +++ b/commands/Makefile > @@ -1,5 +1,6 @@ > obj-$(CONFIG_STDDEV) += stddev.o > obj-$(CONFIG_CMD_BOOTM) += bootm.o > +obj-$(CONFIG_CMD_BOOTELF) += bootelf.o > obj-$(CONFIG_CMD_UIMAGE) += uimage.o > obj-$(CONFIG_CMD_LINUX16) += linux16.o > obj-$(CONFIG_CMD_LOADB) += loadb.o > diff --git a/commands/bootelf.c b/commands/bootelf.c > new file mode 100644 > index 0000000..dc38b9e > --- /dev/null > +++ b/commands/bootelf.c > @@ -0,0 +1,112 @@ > +/* > + * bootelf.c - ELF booting code > + * > + * Copyright (c) 2014 Owen Kirby <osk@xxxxxxxxxx>, Exegin Technologies Limited > + * > + * partly based on U-Boot ELF code. > + * > + * See file CREDITS for list of people who contributed to this > + * project. > + * > + * This program is free software; you can redistribute it and/or modify > + * it under the terms of the GNU General Public License version 2 > + * as published by the Free Software Foundation. > + * > + * This program is distributed in the hope that it will be useful, > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > + * GNU General Public License for more details. > + */ > +#include <common.h> > +#include <command.h> > +#include <malloc.h> > +#include <fcntl.h> > +#include <fs.h> > +#include <elf.h> > + > +static int do_readelf(int argc, char *argv[]) > +{ > + void *hdr; > + int fd; > + > + if (argc < 2) > + return COMMAND_ERROR_USAGE; > + > + fd = open(argv[1], O_RDONLY); > + if (fd < 0) { > + printf("could not open: %s\n", errno_str()); > + return 1; > + } > + hdr = elf_load_header(fd); > + if (!hdr) { > + close(fd); > + return 1; > + } > + elf_print_header(hdr); > + free(hdr); > + close(fd); > + return 0; > +} > + > +BAREBOX_CMD_START(readelf) > + .cmd = do_readelf, > + .usage = "Read an ELF image header", > +BAREBOX_CMD_END > + > +static int do_bootelf(int argc, char *argv[]) > +{ > + void *hdr; > + void *addr; > + int (*func)(int argc, char *argv[]); > + int fd; > + > + if (argc < 2) > + return COMMAND_ERROR_USAGE; > + > + fd = open(argv[1], O_RDONLY); > + if (fd < 0) { > + printf("could not open: %s\n", errno_str()); > + return 1; > + } > + > + /* Print the ELF header for the user. */ > + hdr = elf_load_header(fd); > + if (!hdr) { > + close(fd); > + return 1; > + } > + elf_print_header(hdr); > + free(hdr); > + > + /* Load the ELF sections. */ > + addr = elf_load_sections(fd); > + if (!addr) { > + close(fd); > + return 1; > + } > + > + /* Launch the application */ > + printf("## Starting application at 0x%p ...\n", addr); > + console_flush(); > + func = addr; > + shutdown_barebox(); > + > + if (do_execute) > + do_execute(func, argc - 1, &argv[1]); > + else > + func(argc - 1, &argv[1]); > + > + /* > + * The application returned. Since we have shutdown barebox and > + * we know nothing about the state of the cpu/memory we can't > + * do anything here. > + */ > + while (1); > + return 0; > +} > + > +BAREBOX_CMD_START(bootelf) > + .cmd = do_bootelf, > + .usage = "Boot an ELF image", > +BAREBOX_CMD_END > + > diff --git a/common/Kconfig b/common/Kconfig > index 0031cc8..0d22a58 100644 > --- a/common/Kconfig > +++ b/common/Kconfig > @@ -53,6 +53,9 @@ config UIMAGE > select CRC32 > bool > > +config ELF > + bool > + > config GLOBALVAR > bool > > diff --git a/common/Makefile b/common/Makefile > index 204241c..9decc96 100644 > --- a/common/Makefile > +++ b/common/Makefile > @@ -21,6 +21,7 @@ obj-$(CONFIG_CONSOLE_FULL) += console.o > obj-$(CONFIG_CONSOLE_SIMPLE) += console_simple.o > obj-$(CONFIG_DIGEST) += digest.o > obj-$(CONFIG_DDR_SPD) += ddr_spd.o > +obj-$(CONFIG_ELF) += elf.o > obj-$(CONFIG_ENV_HANDLING) += environment.o > obj-$(CONFIG_ENVIRONMENT_VARIABLES) += env.o > obj-$(CONFIG_FILETYPE) += filetype.o > diff --git a/common/elf.c b/common/elf.c > new file mode 100644 > index 0000000..1383ccc > --- /dev/null > +++ b/common/elf.c > @@ -0,0 +1,222 @@ > +/* > + * elf.c - ELF handling code > + * > + * Copyright (c) 2014 Owen Kirby <osk@xxxxxxxxxx>, Exegin Technologies Limited > + * > + * partly based on U-Boot ELF code. > + * > + * See file CREDITS for list of people who contributed to this > + * project. > + * > + * This program is free software; you can redistribute it and/or modify > + * it under the terms of the GNU General Public License version 2 > + * as published by the Free Software Foundation. > + * > + * This program is distributed in the hope that it will be useful, > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > + * GNU General Public License for more details. > + */ > +#include <common.h> > +#include <malloc.h> > +#include <fcntl.h> > +#include <fs.h> > +#include <elf.h> > + > +const char *elf_types[] = { > + [ET_NONE] = "None", > + [ET_REL] = "Relocatable", > + [ET_EXEC] = "Executable", > + [ET_DYN] = "Dynamic", > + [ET_CORE] = "Core Dump", > +}; > + > +void *elf_load_header(int fd) > +{ > + unsigned char ident[EI_NIDENT]; > + > + if ((lseek(fd, 0, SEEK_SET) < 0) || (read(fd, ident, sizeof(ident)) < 0)) { > + printf("could not read ident header: %s\n", errno_str()); > + return NULL; > + } > + /* Ensure we find the ELF magic number. */ > + if (strncmp(ident, ELFMAG, SELFMAG)) { > + printf("Bad Magic Number\n"); > + return NULL; > + } > + > + /* Read the ELF32 header. */ > + if (ident[EI_CLASS] == ELFCLASS32) { > + Elf32_Ehdr *hdr = xzalloc(sizeof(Elf32_Ehdr)); > + memcpy(hdr->e_ident, ident, EI_NIDENT); > + if (read(fd, &hdr->e_type, sizeof(*hdr) - EI_NIDENT) >= 0) return hdr; > + printf("could not read ELF header: %s\n", errno_str()); > + free(hdr); > + return NULL; > + } > + if (ident[EI_CLASS] == ELFCLASS64) { > + Elf64_Ehdr *hdr = xzalloc(sizeof(Elf64_Ehdr)); > + memcpy(hdr->e_ident, ident, EI_NIDENT); > + if (read(fd, &hdr->e_type, sizeof(*hdr) - EI_NIDENT) >= 0) return hdr; > + printf("could not read ELF header: %s\n", errno_str()); > + free(hdr); > + return NULL; > + } > + printf("Unknown ELF image class\n"); > + return NULL; > +} /* elf_load_header */ > +EXPORT_SYMBOL(elf_load_header); > + > +#define ELF_FMT " %-16s" > + > +/* A rough clone of readelf for debugging and stuff. */ > +void elf_print_header(const void *hdr) > +{ > + const unsigned char *ident = hdr; > + int i; > + > + /* Ensure we find the ELF magic number. */ > + if (strncmp(ident, ELFMAG, SELFMAG)) { > + printf("Bad Magic Number\n"); > + return; > + } > + printf(" Magic:"); > + for (i=0; i<EI_NIDENT; i++) printf(" %02x", ident[i]); > + printf("\n"); > + > + /* Print the rest of the ident string. */ > + switch (ident[EI_CLASS]) { > + case ELFCLASSNONE: printf(ELF_FMT "%s\n", "Class:", "None"); break; > + case ELFCLASS32: printf(ELF_FMT "%s\n", "Class:", "ELF32"); break; > + case ELFCLASS64: printf(ELF_FMT "%s\n", "Class:", "ELF64"); break; > + default: printf(ELF_FMT "%s\n", "Class:", "Invalid"); break; > + } /* switch */ > + switch (ident[EI_DATA]) { > + case ELFDATANONE: printf(ELF_FMT "%s\n", "Data:", "None"); break; > + case ELFDATA2LSB: printf(ELF_FMT "%s\n", "Data:", "2's compliment, litte endian"); break; > + case ELFDATA2MSB: printf(ELF_FMT "%s\n", "Data:", "2's compliment, big endian"); break; > + default: printf(ELF_FMT "%s\n", "Data:", "Invalid"); break; > + } /* switch */ > + printf(ELF_FMT "0x%x\n", "Version:", ident[EI_VERSION]); > + /* TODO: OS/ABI */ > + > + if (ident[EI_CLASS] == ELFCLASS32) { > + const Elf32_Ehdr *elf32 = (const Elf32_Ehdr *)hdr; > + if (elf32->e_type <= ARRAY_SIZE(elf_types)) > + printf(ELF_FMT "%s\n", "Type:", elf_types[elf32->e_type]); > + else > + printf(ELF_FMT "0x%x\n", "Type:", elf32->e_type); > + printf(ELF_FMT "0x%x\n", "Machine:", elf32->e_machine); > + printf(ELF_FMT "0x%x\n", "Version:", elf32->e_version); > + printf(ELF_FMT "0x%lx\n", "Entry point:", (unsigned long)elf32->e_entry); > + printf(ELF_FMT "0x%08x\n", "Flags:", elf32->e_flags); > + } > + else if (ident[EI_CLASS] == ELFCLASS64) { > + const Elf64_Ehdr *elf64 = (const Elf64_Ehdr *)hdr; > + if (elf64->e_type <= ARRAY_SIZE(elf_types)) > + printf(ELF_FMT "%s\n", "Type:", elf_types[elf64->e_type]); > + else > + printf(ELF_FMT "0x%x\n", "Type:", elf64->e_type); > + printf(ELF_FMT "0x%x\n", "Machine:", elf64->e_machine); > + printf(ELF_FMT "0x%x\n", "Version:", elf64->e_version); > + printf(ELF_FMT "0x%llx\n", "Entry point:", (unsigned long long)elf64->e_entry); > + printf(ELF_FMT "0x%08x\n", "Flags:", elf64->e_flags); > + } > + /* TODO: Print the section/program header offsets. */ > +} /* elf_print_header */ > +EXPORT_SYMBOL(elf_print_header); > + > +static void *elf32_load_sections(int fd, Elf32_Ehdr *hdr) > +{ > + unsigned long off; > + unsigned char *strtab = NULL; > + size_t strtabsz = 0; > + Elf32_Shdr shdr; > + int i; > + > + /* We can only load executable images. */ > + if (hdr->e_type != ET_EXEC) { > + printf("ELF image is not executable\n"); > + return NULL; > + } > + > + /* Find the string table from among the section headers. */ > + off = hdr->e_shoff + (hdr->e_shstrndx * sizeof(shdr)); > + if ((lseek(fd, off, SEEK_SET) < 0) || (read(fd, &shdr, sizeof(shdr)) < 0)) { > + printf("could not read string section header: %s\n", errno_str()); > + return NULL; > + } > + if ((shdr.sh_type == SHT_STRTAB) && (shdr.sh_size)) { > + strtabsz = shdr.sh_size; > + strtab = xzalloc(shdr.sh_size); > + if (!strtab) { > + printf("could not allocate memory for string table\n"); > + return NULL; > + } > + if ((lseek(fd, shdr.sh_offset, SEEK_SET) < 0) || (read(fd, strtab, shdr.sh_size) < 0)) { > + printf("could not read string table section: %s\n", errno_str()); > + free(strtab); > + return NULL; > + } > + } > + > + /* Load the program sections. */ > + for (i = 0; i < hdr->e_shnum; i++) { > + /* Read the next section header */ > + off = hdr->e_shoff + (i * sizeof(shdr)); > + if ((lseek(fd, off, SEEK_SET) < 0) || (read(fd, &shdr, sizeof(shdr)) < 0)) { > + printf("could not read section header: %s\n", errno_str()); > + free(strtab); > + return NULL; > + } > + /* Ignore unallocated or empty sections. */ > + if (!(shdr.sh_flags & SHF_ALLOC)) continue; > + if (!shdr.sh_addr || !shdr.sh_size) continue; > + > + /* Inform the user. */ > + if (strtab) { > + printf("%sing %s @ 0x%08lx (%ld bytes)\n", > + (shdr.sh_type == SHT_NOBITS) ? "Clear" : "Load", > + &strtab[shdr.sh_name], > + (unsigned long) shdr.sh_addr, > + (long) shdr.sh_size); > + } > + > + /* Program the section. */ > + if (shdr.sh_type == SHT_NOBITS) { > + memset((void *)shdr.sh_addr, 0, shdr.sh_size); > + } else { > + if ((lseek(fd, shdr.sh_offset, SEEK_SET) < 0) || > + (read(fd, (void *)shdr.sh_addr, shdr.sh_size) < 0)) { > + printf("could not read section data: %s\n", errno_str()); > + free(strtab); > + return NULL; > + } > + } > + } /* for */ > + > + /* Success. */ > + free(strtab); > + return (void *)hdr->e_entry; > +} /* elf32_load_sections */ > + > +void *elf_load_sections(int fd) > +{ > + unsigned char *hdr; > + void *entry; > + > + /* Load the ELF header. */ > + hdr = elf_load_header(fd); > + if (!hdr) return NULL; > + if (hdr[EI_CLASS] == ELFCLASS32) { > + entry = elf32_load_sections(fd, (Elf32_Ehdr *)hdr); > + } > + else { > + printf("Unsupported ELF image class\n"); > + entry = NULL; > + } > + free(hdr); > + return entry; > +} /* elf_load_sections */ > +EXPORT_SYMBOL(elf_load_sections); > + > diff --git a/common/filetype.c b/common/filetype.c > index 0b5da30..0f46fda 100644 > --- a/common/filetype.c > +++ b/common/filetype.c > @@ -52,6 +52,7 @@ static const struct filetype_str filetype_str[] = { > [filetype_ext] = { "ext filesystem", "ext" }, > [filetype_gpt] = { "GUID Partition Table", "gpt" }, > [filetype_bpk] = { "Binary PacKage", "bpk" }, > + [filetype_elf] = { "executable and linkable file", "elf" }, > [filetype_barebox_env] = { "barebox environment file", "bbenv" }, > }; > > @@ -227,6 +228,8 @@ enum filetype file_detect_type(const void *_buf, size_t bufsize) > return filetype_mips_barebox; > if (buf[0] == be32_to_cpu(0x534F4659)) > return filetype_bpk; > + if (strncmp(buf8, "\177ELF", 4) == 0) > + return filetype_elf; > > if (bufsize < 64) > return filetype_unknown; > diff --git a/include/elf.h b/include/elf.h > index 6d4addf..357814f 100644 > --- a/include/elf.h > +++ b/include/elf.h > @@ -397,4 +397,8 @@ static inline void arch_write_notes(struct file *file) { } > #define ELF_CORE_WRITE_EXTRA_NOTES arch_write_notes(file) > #endif /* ARCH_HAVE_EXTRA_ELF_NOTES */ > > +void *elf_load_header(int fd); > +void elf_print_header(const void *hdr); > +void *elf_load_sections(int fd); > + > #endif /* _LINUX_ELF_H */ > diff --git a/include/filetype.h b/include/filetype.h > index c20a4f9..c4f776f 100644 > --- a/include/filetype.h > +++ b/include/filetype.h > @@ -30,6 +30,7 @@ enum filetype { > filetype_ubifs, > filetype_bpk, > filetype_barebox_env, > + filetype_elf, > filetype_max, > }; > > -- > 1.7.9.5 > > > > _______________________________________________ > barebox mailing list > barebox@xxxxxxxxxxxxxxxxxxx > http://lists.infradead.org/mailman/listinfo/barebox -- -- Best regards, Antony Pavlov _______________________________________________ barebox mailing list barebox@xxxxxxxxxxxxxxxxxxx http://lists.infradead.org/mailman/listinfo/barebox