On Thu, 26 Jun 2014 14:11:32 -0700
Owen Kirby <[email protected]> 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 <[email protected]>
> 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 <[email protected]>
> ---
>  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 <[email protected]>, 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 <[email protected]>, 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
> [email protected]
> http://lists.infradead.org/mailman/listinfo/barebox


-- 
-- 
Best regards,
  Antony Pavlov

_______________________________________________
barebox mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/barebox

Reply via email to