aboutsummaryrefslogtreecommitdiff
path: root/util/mkelfImage/main/mkelfImage.c
diff options
context:
space:
mode:
Diffstat (limited to 'util/mkelfImage/main/mkelfImage.c')
-rw-r--r--util/mkelfImage/main/mkelfImage.c663
1 files changed, 0 insertions, 663 deletions
diff --git a/util/mkelfImage/main/mkelfImage.c b/util/mkelfImage/main/mkelfImage.c
deleted file mode 100644
index 0dcc8c2fc1..0000000000
--- a/util/mkelfImage/main/mkelfImage.c
+++ /dev/null
@@ -1,663 +0,0 @@
-#include <stdarg.h>
-#include <errno.h>
-#include <string.h>
-#include <stdint.h>
-#include <stdlib.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <stdio.h>
-#include <getopt.h>
-#ifdef HAVE_ZLIB_H
-#include <zlib.h>
-#endif
-#include "elf.h"
-#include "elf_boot.h"
-#include "mkelfImage.h"
-
-static struct file_type file_type[] = {
- { "linux-i386", linux_i386_probe, linux_i386_mkelf, linux_i386_usage },
- { "bzImage-i386", bzImage_i386_probe, linux_i386_mkelf, linux_i386_usage },
- { "vmlinux-i386", vmlinux_i386_probe, linux_i386_mkelf, linux_i386_usage },
- { "linux-ia64", linux_ia64_probe, linux_ia64_mkelf, linux_ia64_usage },
-};
-static const int file_types = sizeof(file_type)/sizeof(file_type[0]);
-
-void die(char *fmt, ...)
-{
- va_list args;
- va_start(args, fmt);
- vfprintf(stderr, fmt, args);
- va_end(args);
- exit(1);
-}
-
-
-
-/**************************************************************************
-IPCHKSUM - Checksum IP Header
-**************************************************************************/
-uint16_t ipchksum(const void *data, unsigned long length)
-{
- unsigned long sum;
- unsigned long i;
- const uint8_t *ptr;
-
- /* In the most straight forward way possible,
- * compute an ip style checksum.
- */
- sum = 0;
- ptr = data;
- for(i = 0; i < length; i++) {
- unsigned long value;
- value = ptr[i];
- if (i & 1) {
- value <<= 8;
- }
- /* Add the new value */
- sum += value;
- /* Wrap around the carry */
- if (sum > 0xFFFF) {
- sum = (sum + (sum >> 16)) & 0xFFFF;
- }
- }
- return (~cpu_to_le16(sum)) & 0xFFFF;
-}
-
-uint16_t add_ipchksums(unsigned long offset, uint16_t sum, uint16_t new)
-{
- unsigned long checksum;
- sum = ~sum & 0xFFFF;
- new = ~new & 0xFFFF;
- if (offset & 1) {
- /* byte swap the sum if it came from an odd offset
- * since the computation is endian independant this
- * works.
- */
- new = bswap_16(new);
- }
- checksum = sum + new;
- if (checksum > 0xFFFF) {
- checksum -= 0xFFFF;
- }
- return (~checksum) & 0xFFFF;
-}
-
-void *xmalloc(size_t size, const char *name)
-{
- void *buf;
- buf = malloc(size);
- if (!buf) {
- die("Cannot malloc %ld bytes to hold %s: %s\n",
- size + 0UL, name, strerror(errno));
- }
- return buf;
-}
-
-void *xrealloc(void *ptr, size_t size, const char *name)
-{
- void *buf;
- buf = realloc(ptr, size);
- if (!buf) {
- die("Cannot realloc %ld bytes to hold %s: %s\n",
- size + 0UL, name, strerror(errno));
- }
- return buf;
-}
-
-
-char *slurp_file(const char *filename, off_t *r_size)
-{
- int fd;
- char *buf;
- off_t size, progress;
- ssize_t result;
- struct stat stats;
-
-
- if (!filename) {
- *r_size = 0;
- return 0;
- }
- fd = open(filename, O_RDONLY);
- if (fd < 0) {
- die("Cannot open `%s': %s\n",
- filename, strerror(errno));
- }
- result = fstat(fd, &stats);
- if (result < 0) {
- die("Cannot stat: %s: %s\n",
- filename, strerror(errno));
- }
- size = stats.st_size;
- *r_size = size;
- buf = xmalloc(size, filename);
- progress = 0;
- while(progress < size) {
- result = read(fd, buf + progress, size - progress);
- if (result < 0) {
- if ((errno == EINTR) || (errno == EAGAIN))
- continue;
- die("read on %s of %ld bytes failed: %s\n",
- filename, (size - progress)+ 0UL, strerror(errno));
- }
- progress += result;
- }
- result = close(fd);
- if (result < 0) {
- die("Close of %s failed: %s\n",
- filename, strerror(errno));
- }
- return buf;
-}
-
-#if HAVE_ZLIB_H
-char *slurp_decompress_file(const char *filename, off_t *r_size)
-{
- gzFile fp;
- int errnum;
- const char *msg;
- char *buf;
- off_t size, allocated;
- ssize_t result;
-
- if (!filename) {
- *r_size = 0;
- return 0;
- }
- fp = gzopen(filename, "rb");
- if (fp == 0) {
- msg = gzerror(fp, &errnum);
- if (errnum == Z_ERRNO) {
- msg = strerror(errno);
- }
- die("Cannot open `%s': %s\n", filename, msg);
- }
- size = 0;
- allocated = 65536;
- buf = xmalloc(allocated, filename);
- do {
- if (size == allocated) {
- allocated <<= 1;
- buf = xrealloc(buf, allocated, filename);
- }
- result = gzread(fp, buf + size, allocated - size);
- if (result < 0) {
- if ((errno == EINTR) || (errno == EAGAIN))
- continue;
-
- msg = gzerror(fp, &errnum);
- if (errnum == Z_ERRNO) {
- msg = strerror(errno);
- }
- die ("read on %s of %ld bytes failed: %s\n",
- filename, (allocated - size) + 0UL, msg);
- }
- size += result;
- } while(result > 0);
- result = gzclose(fp);
- if (result != Z_OK) {
- msg = gzerror(fp, &errnum);
- if (errnum == Z_ERRNO) {
- msg = strerror(errno);
- }
- die ("Close of %s failed: %s\n", filename, msg);
- }
- *r_size = size;
- return buf;
-}
-#else
-char *slurp_decompress_file(const char *filename, off_t *r_size)
-{
- return slurp_file(filename, r_size);
-}
-#endif
-
-struct memelfphdr *add_program_headers(struct memelfheader *ehdr, int count)
-{
- struct memelfphdr *phdr;
- int i;
- ehdr->e_phnum = count;
- ehdr->e_phdr = phdr = xmalloc(count *sizeof(*phdr), "Program headers");
- /* Set the default values */
- for(i = 0; i < count; i++) {
- phdr[i].p_type = PT_LOAD;
- phdr[i].p_flags = PF_R | PF_W | PF_X;
- phdr[i].p_vaddr = 0;
- phdr[i].p_paddr = 0;
- phdr[i].p_filesz = 0;
- phdr[i].p_memsz = 0;
- phdr[i].p_data = 0;
- }
- return phdr;
-}
-
-struct memelfnote *add_notes(struct memelfheader *ehdr, int count)
-{
- struct memelfnote *notes;
- ehdr->e_notenum = count;
- ehdr->e_notes = notes = xmalloc(count *sizeof(*notes), "Notes");
- memset(notes, 0, count *sizeof(*notes));
- return notes;
-}
-
-static int sizeof_notes(struct memelfnote *note, int notes)
-{
- int size;
- int i;
-
- size = 0;
- for(i = 0; i < notes; i++) {
- size += sizeof(Elf_Nhdr);
- size += roundup(strlen(note[i].n_name)+1, 4);
- size += roundup(note[i].n_descsz, 4);
- }
- return size;
-}
-
-static uint16_t cpu_to_elf16(struct memelfheader *ehdr, uint16_t val)
-{
- if (ehdr->ei_data == ELFDATA2LSB) {
- return cpu_to_le16(val);
- }
- else if (ehdr->ei_data == ELFDATA2MSB) {
- return cpu_to_be16(val);
- }
- die("Uknown elf layout in cpu_to_elf16");
- return 0;
-}
-
-static uint32_t cpu_to_elf32(struct memelfheader *ehdr, uint32_t val)
-{
- if (ehdr->ei_data == ELFDATA2LSB) {
- return cpu_to_le32(val);
- }
- else if (ehdr->ei_data == ELFDATA2MSB) {
- return cpu_to_be32(val);
- }
- die("Uknown elf layout in cpu_to_elf32");
- return 0;
-}
-
-static uint64_t cpu_to_elf64(struct memelfheader *ehdr, uint64_t val)
-{
- if (ehdr->ei_data == ELFDATA2LSB) {
- return cpu_to_le64(val);
- }
- else if (ehdr->ei_data == ELFDATA2MSB) {
- return cpu_to_be64(val);
- }
- die("Uknown elf layout in cpu_to_elf64");
- return 0;
-}
-
-static void serialize_notes(char *buf, struct memelfheader *ehdr)
-{
- struct Elf_Nhdr hdr;
- struct memelfnote *note;
- int notes;
- size_t size, offset;
- int i;
-
- /* Clear the buffer */
- note = ehdr->e_notes;
- notes = ehdr->e_notenum;
- size = sizeof_notes(note, notes);
- memset(buf, 0, size);
-
- /* Write the Elf Notes */
- offset = 0;
- for(i = 0; i < notes; i++) {
- /* Compute the note header */
- size_t n_namesz;
- n_namesz = strlen(note[i].n_name) +1;
- hdr.n_namesz = cpu_to_elf32(ehdr, n_namesz);
- hdr.n_descsz = cpu_to_elf32(ehdr, note[i].n_descsz);
- hdr.n_type = cpu_to_elf32(ehdr, note[i].n_type);
-
- /* Copy the note into the buffer */
- memcpy(buf + offset, &hdr, sizeof(hdr));
- offset += sizeof(hdr);
- memcpy(buf + offset, note[i].n_name, n_namesz);
- offset += roundup(n_namesz, 4);
- memcpy(buf + offset, note[i].n_desc, note[i].n_descsz);
- offset += roundup(note[i].n_descsz, 4);
-
- }
-}
-static void serialize_ehdr(char *buf, struct memelfheader *ehdr)
-{
- if (ehdr->ei_class == ELFCLASS32) {
- Elf32_Ehdr *hdr = (Elf32_Ehdr *)buf;
- hdr->e_ident[EI_MAG0] = ELFMAG0;
- hdr->e_ident[EI_MAG1] = ELFMAG1;
- hdr->e_ident[EI_MAG2] = ELFMAG2;
- hdr->e_ident[EI_MAG3] = ELFMAG3;
- hdr->e_ident[EI_CLASS] = ehdr->ei_class;
- hdr->e_ident[EI_DATA] = ehdr->ei_data;
- hdr->e_ident[EI_VERSION] = EV_CURRENT;
- hdr->e_type = cpu_to_elf16(ehdr, ehdr->e_type);
- hdr->e_machine = cpu_to_elf16(ehdr, ehdr->e_machine);
- hdr->e_version = cpu_to_elf32(ehdr, EV_CURRENT);
- hdr->e_entry = cpu_to_elf32(ehdr, ehdr->e_entry);
- hdr->e_phoff = cpu_to_elf32(ehdr, sizeof(*hdr));
- hdr->e_shoff = cpu_to_elf32(ehdr, 0);
- hdr->e_flags = cpu_to_elf32(ehdr, ehdr->e_flags);
- hdr->e_ehsize = cpu_to_elf16(ehdr, sizeof(*hdr));
- hdr->e_phentsize = cpu_to_elf16(ehdr, sizeof(Elf32_Phdr));
- hdr->e_phnum = cpu_to_elf16(ehdr, ehdr->e_phnum);
- hdr->e_shentsize = cpu_to_elf16(ehdr, 0);
- hdr->e_shnum = cpu_to_elf16(ehdr, 0);
- hdr->e_shstrndx = cpu_to_elf16(ehdr, 0);
- }
- else if (ehdr->ei_class == ELFCLASS64) {
- Elf64_Ehdr *hdr = (Elf64_Ehdr *)buf;
- hdr->e_ident[EI_MAG0] = ELFMAG0;
- hdr->e_ident[EI_MAG1] = ELFMAG1;
- hdr->e_ident[EI_MAG2] = ELFMAG2;
- hdr->e_ident[EI_MAG3] = ELFMAG3;
- hdr->e_ident[EI_CLASS] = ehdr->ei_class;
- hdr->e_ident[EI_DATA] = ehdr->ei_data;
- hdr->e_ident[EI_VERSION] = EV_CURRENT;
- hdr->e_type = cpu_to_elf16(ehdr, ehdr->e_type);
- hdr->e_machine = cpu_to_elf16(ehdr, ehdr->e_machine);
- hdr->e_version = cpu_to_elf32(ehdr, EV_CURRENT);
- hdr->e_entry = cpu_to_elf64(ehdr, ehdr->e_entry);
- hdr->e_phoff = cpu_to_elf64(ehdr, sizeof(*hdr));
- hdr->e_shoff = cpu_to_elf64(ehdr, 0);
- hdr->e_flags = cpu_to_elf32(ehdr, ehdr->e_flags);
- hdr->e_ehsize = cpu_to_elf16(ehdr, sizeof(*hdr));
- hdr->e_phentsize = cpu_to_elf16(ehdr, sizeof(Elf64_Phdr));
- hdr->e_phnum = cpu_to_elf16(ehdr, ehdr->e_phnum);
- hdr->e_shentsize = cpu_to_elf16(ehdr, 0);
- hdr->e_shnum = cpu_to_elf16(ehdr, 0);
- hdr->e_shstrndx = cpu_to_elf16(ehdr, 0);
- }
- else die("Uknown elf class: %x\n", ehdr->ei_class);
-}
-static void serialize_phdrs(char *buf, struct memelfheader *ehdr, size_t note_size)
-{
- int i;
- size_t offset, note_offset;
- if (ehdr->ei_class == ELFCLASS32) {
- Elf32_Phdr *phdr = (Elf32_Phdr *)buf;
- note_offset =
- sizeof(Elf32_Ehdr) + (sizeof(Elf32_Phdr)*ehdr->e_phnum);
- offset = note_offset + note_size;
- for(i = 0; i < ehdr->e_phnum; i++) {
- struct memelfphdr *hdr = ehdr->e_phdr + i;
- phdr[i].p_type = cpu_to_elf32(ehdr, hdr->p_type);
- phdr[i].p_offset = cpu_to_elf32(ehdr, offset);
- phdr[i].p_vaddr = cpu_to_elf32(ehdr, hdr->p_vaddr);
- phdr[i].p_paddr = cpu_to_elf32(ehdr, hdr->p_paddr);
- phdr[i].p_filesz = cpu_to_elf32(ehdr, hdr->p_filesz);
- phdr[i].p_memsz = cpu_to_elf32(ehdr, hdr->p_memsz);
- phdr[i].p_flags = cpu_to_elf32(ehdr, hdr->p_flags);
- phdr[i].p_align = cpu_to_elf32(ehdr, 0);
- if (phdr[i].p_type == PT_NOTE) {
- phdr[i].p_filesz = cpu_to_elf32(ehdr, note_size);
- phdr[i].p_memsz = cpu_to_elf32(ehdr, note_size);
- phdr[i].p_offset = cpu_to_elf32(ehdr, note_offset);
- } else {
- offset += hdr->p_filesz;
- }
- }
- }
- else if (ehdr->ei_class == ELFCLASS64) {
- Elf64_Phdr *phdr = (Elf64_Phdr *)buf;
- note_offset =
- sizeof(Elf64_Ehdr) + (sizeof(Elf64_Phdr)*ehdr->e_phnum);
- offset = note_offset + note_size;
- for(i = 0; i < ehdr->e_phnum; i++) {
- struct memelfphdr *hdr = ehdr->e_phdr + i;
- phdr[i].p_type = cpu_to_elf32(ehdr, hdr->p_type);
- phdr[i].p_flags = cpu_to_elf32(ehdr, hdr->p_flags);
- phdr[i].p_offset = cpu_to_elf64(ehdr, offset);
- phdr[i].p_vaddr = cpu_to_elf64(ehdr, hdr->p_vaddr);
- phdr[i].p_paddr = cpu_to_elf64(ehdr, hdr->p_paddr);
- phdr[i].p_filesz = cpu_to_elf64(ehdr, hdr->p_filesz);
- phdr[i].p_memsz = cpu_to_elf64(ehdr, hdr->p_memsz);
- phdr[i].p_align = cpu_to_elf64(ehdr, 0);
- if (phdr[i].p_type == PT_NOTE) {
- phdr[i].p_filesz = cpu_to_elf64(ehdr, note_size);
- phdr[i].p_memsz = cpu_to_elf64(ehdr, note_size);
- phdr[i].p_offset = cpu_to_elf64(ehdr, note_offset);
- } else {
- offset += hdr->p_filesz;
- }
- }
- }
- else {
- die("Unknwon elf class: %x\n", ehdr->ei_class);
- }
-}
-
-static void write_buf(int fd, char *buf, size_t size)
-{
- size_t progress = 0;
- ssize_t result;
- while(progress < size) {
- result = write(fd, buf + progress, size - progress);
- if (result < 0) {
- if ((errno == EAGAIN) || (errno == EINTR)) {
- continue;
- }
- die ("write of %ld bytes failed: %s\n",
- size - progress, strerror(errno));
- }
- progress += result;
- }
-}
-static void write_elf(struct memelfheader *ehdr, char *output)
-{
- size_t ehdr_size;
- size_t phdr_size;
- size_t note_size;
- size_t size;
- uint16_t checksum;
- size_t bytes;
- char *buf;
- int result, fd;
- int i;
- /* Prep for adding the checksum */
- for(i = 0; i < ehdr->e_notenum; i++) {
- if ((memcmp(ehdr->e_notes[i].n_name, "ELFBoot", 8) == 0) &&
- (ehdr->e_notes[i].n_type == EIN_PROGRAM_CHECKSUM)) {
- ehdr->e_notes[i].n_desc = &checksum;
- ehdr->e_notes[i].n_descsz = 2;
- }
- }
- /* Compute the sizes */
- ehdr_size = 0;
- phdr_size = 0;
- note_size = 0;
- if (ehdr->e_notenum) {
- note_size = sizeof_notes(ehdr->e_notes, ehdr->e_notenum);
- }
- if (ehdr->ei_class == ELFCLASS32) {
- ehdr_size = sizeof(Elf32_Ehdr);
- phdr_size = sizeof(Elf32_Phdr) * ehdr->e_phnum;
- }
- else if (ehdr->ei_class == ELFCLASS64) {
- ehdr_size = sizeof(Elf64_Ehdr);
- phdr_size = sizeof(Elf64_Phdr) * ehdr->e_phnum;
- }
- else {
- die("Unknown elf class: %x\n", ehdr->ei_class);
- }
-
- /* Allocate a buffer to temporarily hold the serialized forms */
- size = ehdr_size + phdr_size + note_size;
- buf = xmalloc(size, "Elf Headers");
- memset(buf, 0, size);
- serialize_ehdr(buf, ehdr);
- serialize_phdrs(buf + ehdr_size, ehdr, note_size);
-
- /* Compute the checksum... */
- checksum = ipchksum(buf, ehdr_size + phdr_size);
- bytes = ehdr_size + phdr_size;
- for(i = 0; i < ehdr->e_phnum; i++) {
- checksum = add_ipchksums(bytes, checksum,
- ipchksum(ehdr->e_phdr[i].p_data, ehdr->e_phdr[i].p_filesz));
- bytes += ehdr->e_phdr[i].p_memsz;
- }
-
- /* Compute the final form of the notes */
- serialize_notes(buf + ehdr_size + phdr_size, ehdr);
-
- /* Now write the elf image */
- fd = open(output, O_WRONLY | O_CREAT | O_EXCL, S_IRUSR | S_IRGRP | S_IROTH);
- if (fd < 0) {
- die("Cannot open ``%s'':%s\n",
- output, strerror(errno));
- }
- write_buf(fd, buf, size);
- for(i = 0; i < ehdr->e_phnum; i++) {
- write_buf(fd, ehdr->e_phdr[i].p_data, ehdr->e_phdr[i].p_filesz);
- }
- result = close(fd);
- if (result < 0) {
- die("Close on %s failed: %s\n",
- output, strerror(errno));
- }
-}
-
-static void version(void)
-{
- printf("mkelfImage " VERSION " released " RELEASE_DATE "\n");
-}
-void usage(void)
-{
- int i;
- version();
- printf(
- "Usage: mkelfImage [OPTION]... <kernel> <elf_kernel>\n"
- "Build an ELF bootable kernel image from a normal kernel image\n"
- "\n"
- " -h, --help Print this help.\n"
- " -v, --version Print the version of kexec.\n"
- " --kernel=<filename> Set the kernel to <filename>\n"
- " --output=<filename> Output to <filename>\n"
- " -t, --type=TYPE Specify the new kernel is of <type>.\n"
- "\n"
- "Supported kernel types: \n"
- );
- for(i = 0; i < file_types; i++) {
- printf("%s\n", file_type[i].name);
- file_type[i].usage();
- }
- printf("\n");
-}
-
-void error(char *fmt, ...)
-{
- va_list args;
- va_start(args, fmt);
- vfprintf(stderr, fmt, args);
- va_end(args);
- usage();
- exit(1);
-}
-
-int main(int argc, char **argv)
-{
- int opt;
- int fileind;
- char *type, *kernel, *output;
- off_t kernel_size;
- char *kernel_buf;
- int result;
- int i;
- struct memelfheader hdr;
-
- static const struct option options[] = {
- MKELF_OPTIONS
- { 0, 0, 0, 0 },
- };
- static const char short_options[] = MKELF_OPT_STR;
-
- memset(&hdr, 0, sizeof(hdr));
- kernel = 0;
- output = 0;
-
- /* Get the default type from the program name */
- type = strrchr(argv[0], '/');
- if (!type) type = argv[0];
- if (memcmp(type, "mkelf-", 6) == 0) {
- type = type + 6;
- } else {
- type = 0;
- }
- opterr = 0; /* Don't complain about unrecognized options here */
- while ((opt = getopt_long(argc, argv, short_options, options, 0)) != -1) {
- switch(opt) {
- case OPT_HELP:
- usage();
- return 0;
- case OPT_VERSION:
- version();
- return 0;
- case OPT_KERNEL:
- kernel = optarg;
- break;
- case OPT_OUTPUT:
- output = optarg;
- break;
- case OPT_TYPE:
- type = optarg;
- break;
- default:
- break;
- }
- }
- fileind = optind;
-
- /* Reset getopt for the next pass */
- opterr = 1;
- optind = 1;
-
- if (argc - fileind > 0) {
- kernel = argv[fileind++];
- }
- if (argc - fileind > 0) {
- output = argv[fileind++];
- }
- if (!kernel) {
- error("No kernel specified!\n");
- }
- if (!output) {
- error("No output file specified!\n");
- }
- if (argc - fileind > 0) {
- error("%d extra options specified!\n", argc - fileind);
- }
-
- /* slurp in the input kernel */
- kernel_buf = slurp_decompress_file(kernel, &kernel_size);
-
- /* Find/verify the kernel type */
- for(i = 0; i < file_types; i++) {
- char *reason;
- if (type && (strcmp(type, file_type[i].name) != 0)) {
- continue;
- }
- reason = file_type[i].probe(kernel_buf, kernel_size);
- if (reason == 0) {
- break;
- }
- if (type) {
- die("Not %s: %s\n", type, reason);
- }
- }
- if (i == file_types) {
- die("Can not determine the file type of %s\n", kernel);
- }
- result = file_type[i].mkelf(argc, argv, &hdr, kernel_buf, kernel_size);
- if (result < 0) {
- die("Cannot create %s result: %d\n", output, result);
- }
- /* open the output file */
- write_elf(&hdr, output);
- return 0;
-}