coreboot/util/mkelfImage/main/mkelfImage.c
<<
>>
Prefs
   1#include <stdarg.h>
   2#include <errno.h>
   3#include <string.h>
   4#include <stdint.h>
   5#include <stdlib.h>
   6#include <sys/types.h>
   7#include <sys/stat.h>
   8#include <fcntl.h>
   9#include <unistd.h>
  10#include <stdio.h>
  11#include <getopt.h>
  12#ifdef HAVE_ZLIB_H
  13#include <zlib.h>
  14#endif
  15#include "elf.h"
  16#include "elf_boot.h"
  17#include "mkelfImage.h"
  18
  19static struct file_type file_type[] = {
  20        { "linux-i386", linux_i386_probe, linux_i386_mkelf, linux_i386_usage },
  21        { "bzImage-i386", bzImage_i386_probe, linux_i386_mkelf, linux_i386_usage },
  22        { "vmlinux-i386", vmlinux_i386_probe, linux_i386_mkelf, linux_i386_usage },
  23        { "linux-ia64", linux_ia64_probe, linux_ia64_mkelf, linux_ia64_usage },
  24};
  25static const int file_types = sizeof(file_type)/sizeof(file_type[0]);
  26
  27void die(char *fmt, ...)
  28{
  29        va_list args;
  30        va_start(args, fmt);
  31        vfprintf(stderr, fmt, args);
  32        va_end(args);
  33        exit(1);
  34}
  35
  36
  37
  38/**************************************************************************
  39IPCHKSUM - Checksum IP Header
  40**************************************************************************/
  41uint16_t ipchksum(const void *data, unsigned long length)
  42{
  43        unsigned long sum;
  44        unsigned long i;
  45        const uint8_t *ptr;
  46
  47        /* In the most straight forward way possible,
  48         * compute an ip style checksum.
  49         */
  50        sum = 0;
  51        ptr = data;
  52        for(i = 0; i < length; i++) {
  53                unsigned long value;
  54                value = ptr[i];
  55                if (i & 1) {
  56                        value <<= 8;
  57                }
  58                /* Add the new value */
  59                sum += value;
  60                /* Wrap around the carry */
  61                if (sum > 0xFFFF) {
  62                        sum = (sum + (sum >> 16)) & 0xFFFF;
  63                }
  64        }
  65        return (~cpu_to_le16(sum)) & 0xFFFF;
  66}
  67
  68uint16_t add_ipchksums(unsigned long offset, uint16_t sum, uint16_t new)
  69{
  70        unsigned long checksum;
  71        sum = ~sum & 0xFFFF;
  72        new = ~new & 0xFFFF;
  73        if (offset & 1) {
  74                /* byte swap the sum if it came from an odd offset
  75                 * since the computation is endian independant this
  76                 * works.
  77                 */
  78                new = bswap_16(new);
  79        }
  80        checksum = sum + new;
  81        if (checksum > 0xFFFF) {
  82                checksum -= 0xFFFF;
  83        }
  84        return (~checksum) & 0xFFFF;
  85}
  86
  87void *xmalloc(size_t size, const char *name)
  88{
  89        void *buf;
  90        buf = malloc(size);
  91        if (!buf) {
  92                die("Cannot malloc %ld bytes to hold %s: %s\n",
  93                        size + 0UL, name, strerror(errno));
  94        }
  95        return buf;
  96}
  97
  98void *xrealloc(void *ptr, size_t size, const char *name)
  99{
 100        void *buf;
 101        buf = realloc(ptr, size);
 102        if (!buf) {
 103                die("Cannot realloc %ld bytes to hold %s: %s\n",
 104                        size + 0UL, name, strerror(errno));
 105        }
 106        return buf;
 107}
 108
 109
 110char *slurp_file(const char *filename, off_t *r_size)
 111{
 112        int fd;
 113        char *buf;
 114        off_t size, progress;
 115        ssize_t result;
 116        struct stat stats;
 117
 118
 119        if (!filename) {
 120                *r_size = 0;
 121                return 0;
 122        }
 123        fd = open(filename, O_RDONLY);
 124        if (fd < 0) {
 125                die("Cannot open `%s': %s\n",
 126                        filename, strerror(errno));
 127        }
 128        result = fstat(fd, &stats);
 129        if (result < 0) {
 130                die("Cannot stat: %s: %s\n",
 131                        filename, strerror(errno));
 132        }
 133        size = stats.st_size;
 134        *r_size = size;
 135        buf = xmalloc(size, filename);
 136        progress = 0;
 137        while(progress < size) {
 138                result = read(fd, buf + progress, size - progress);
 139                if (result < 0) {
 140                        if ((errno == EINTR) || (errno == EAGAIN))
 141                                continue;
 142                        die("read on %s of %ld bytes failed: %s\n",
 143                                filename, (size - progress)+ 0UL, strerror(errno));
 144                }
 145                progress += result;
 146        }
 147        result = close(fd);
 148        if (result < 0) {
 149                die("Close of %s failed: %s\n",
 150                        filename, strerror(errno));
 151        }
 152        return buf;
 153}
 154
 155#if HAVE_ZLIB_H
 156char *slurp_decompress_file(const char *filename, off_t *r_size)
 157{
 158        gzFile fp;
 159        int errnum;
 160        const char *msg;
 161        char *buf;
 162        off_t size, allocated;
 163        ssize_t result;
 164
 165        if (!filename) {
 166                *r_size = 0;
 167                return 0;
 168        }
 169        fp = gzopen(filename, "rb");
 170        if (fp == 0) {
 171                msg = gzerror(fp, &errnum);
 172                if (errnum == Z_ERRNO) {
 173                        msg = strerror(errno);
 174                }
 175                die("Cannot open `%s': %s\n", filename, msg);
 176        }
 177        size = 0;
 178        allocated = 65536;
 179        buf = xmalloc(allocated, filename);
 180        do {
 181                if (size == allocated) {
 182                        allocated <<= 1;
 183                        buf = xrealloc(buf, allocated, filename);
 184                }
 185                result = gzread(fp, buf + size, allocated - size);
 186                if (result < 0) {
 187                        if ((errno == EINTR) || (errno == EAGAIN))
 188                                continue;
 189
 190                        msg = gzerror(fp, &errnum);
 191                        if (errnum == Z_ERRNO) {
 192                                msg = strerror(errno);
 193                        }
 194                        die ("read on %s of %ld bytes failed: %s\n",
 195                                filename, (allocated - size) + 0UL, msg);
 196                }
 197                size += result;
 198        } while(result > 0);
 199        result = gzclose(fp);
 200        if (result != Z_OK) {
 201                msg = gzerror(fp, &errnum);
 202                if (errnum == Z_ERRNO) {
 203                        msg = strerror(errno);
 204                }
 205                die ("Close of %s failed: %s\n", filename, msg);
 206        }
 207        *r_size =  size;
 208        return buf;
 209}
 210#else
 211char *slurp_decompress_file(const char *filename, off_t *r_size)
 212{
 213        return slurp_file(filename, r_size);
 214}
 215#endif
 216
 217struct memelfphdr *add_program_headers(struct memelfheader *ehdr, int count)
 218{
 219        struct memelfphdr *phdr;
 220        int i;
 221        ehdr->e_phnum = count;
 222        ehdr->e_phdr = phdr = xmalloc(count *sizeof(*phdr), "Program headers");
 223        /* Set the default values */
 224        for(i = 0; i < count; i++) {
 225                phdr[i].p_type   = PT_LOAD;
 226                phdr[i].p_flags  = PF_R | PF_W | PF_X;
 227                phdr[i].p_vaddr  = 0;
 228                phdr[i].p_paddr  = 0;
 229                phdr[i].p_filesz = 0;
 230                phdr[i].p_memsz  = 0;
 231                phdr[i].p_data   = 0;
 232        }
 233        return phdr;
 234}
 235
 236struct memelfnote *add_notes(struct memelfheader *ehdr, int count)
 237{
 238        struct memelfnote *notes;
 239        ehdr->e_notenum = count;
 240        ehdr->e_notes = notes = xmalloc(count *sizeof(*notes), "Notes");
 241        memset(notes, 0, count *sizeof(*notes));
 242        return notes;
 243}
 244
 245static int sizeof_notes(struct memelfnote *note, int notes)
 246{
 247        int size;
 248        int i;
 249
 250        size = 0;
 251        for(i = 0; i < notes; i++) {
 252                size += sizeof(Elf_Nhdr);
 253                size += roundup(strlen(note[i].n_name)+1, 4);
 254                size += roundup(note[i].n_descsz, 4);
 255        }
 256        return size;
 257}
 258
 259static uint16_t cpu_to_elf16(struct memelfheader *ehdr, uint16_t val)
 260{
 261        if (ehdr->ei_data == ELFDATA2LSB) {
 262                return cpu_to_le16(val);
 263        }
 264        else if (ehdr->ei_data == ELFDATA2MSB) {
 265                return cpu_to_be16(val);
 266        }
 267        die("Uknown elf layout in cpu_to_elf16");
 268        return 0;
 269}
 270
 271static uint32_t cpu_to_elf32(struct memelfheader *ehdr, uint32_t val)
 272{
 273        if (ehdr->ei_data == ELFDATA2LSB) {
 274                return cpu_to_le32(val);
 275        }
 276        else if (ehdr->ei_data == ELFDATA2MSB) {
 277                return cpu_to_be32(val);
 278        }
 279        die("Uknown elf layout in cpu_to_elf32");
 280        return 0;
 281}
 282
 283static uint64_t cpu_to_elf64(struct memelfheader *ehdr, uint64_t val)
 284{
 285        if (ehdr->ei_data == ELFDATA2LSB) {
 286                return cpu_to_le64(val);
 287        }
 288        else if (ehdr->ei_data == ELFDATA2MSB) {
 289                return cpu_to_be64(val);
 290        }
 291        die("Uknown elf layout in cpu_to_elf64");
 292        return 0;
 293}
 294
 295static void serialize_notes(char *buf, struct memelfheader *ehdr)
 296{
 297        struct Elf_Nhdr hdr;
 298        struct memelfnote *note;
 299        int notes;
 300        size_t size, offset;
 301        int i;
 302
 303        /* Clear the buffer */
 304        note = ehdr->e_notes;
 305        notes = ehdr->e_notenum;
 306        size = sizeof_notes(note, notes);
 307        memset(buf, 0, size);
 308
 309        /* Write the Elf Notes */
 310        offset = 0;
 311        for(i = 0; i < notes; i++) {
 312                /* Compute the note header */
 313                size_t n_namesz;
 314                n_namesz = strlen(note[i].n_name) +1;
 315                hdr.n_namesz = cpu_to_elf32(ehdr, n_namesz);
 316                hdr.n_descsz = cpu_to_elf32(ehdr, note[i].n_descsz);
 317                hdr.n_type   = cpu_to_elf32(ehdr, note[i].n_type);
 318
 319                /* Copy the note into the buffer */
 320                memcpy(buf + offset, &hdr,       sizeof(hdr));
 321                offset += sizeof(hdr);
 322                memcpy(buf + offset, note[i].n_name, n_namesz);
 323                offset += roundup(n_namesz, 4);
 324                memcpy(buf + offset, note[i].n_desc, note[i].n_descsz);
 325                offset += roundup(note[i].n_descsz, 4);
 326
 327        }
 328}
 329static void serialize_ehdr(char *buf, struct memelfheader *ehdr)
 330{
 331        if (ehdr->ei_class == ELFCLASS32) {
 332                Elf32_Ehdr *hdr = (Elf32_Ehdr *)buf;
 333                hdr->e_ident[EI_MAG0]    = ELFMAG0;
 334                hdr->e_ident[EI_MAG1]    = ELFMAG1;
 335                hdr->e_ident[EI_MAG2]    = ELFMAG2;
 336                hdr->e_ident[EI_MAG3]    = ELFMAG3;
 337                hdr->e_ident[EI_CLASS]   = ehdr->ei_class;
 338                hdr->e_ident[EI_DATA]    = ehdr->ei_data;
 339                hdr->e_ident[EI_VERSION] = EV_CURRENT;
 340                hdr->e_type      = cpu_to_elf16(ehdr, ehdr->e_type);
 341                hdr->e_machine   = cpu_to_elf16(ehdr, ehdr->e_machine);
 342                hdr->e_version   = cpu_to_elf32(ehdr, EV_CURRENT);
 343                hdr->e_entry     = cpu_to_elf32(ehdr, ehdr->e_entry);
 344                hdr->e_phoff     = cpu_to_elf32(ehdr, sizeof(*hdr));
 345                hdr->e_shoff     = cpu_to_elf32(ehdr, 0);
 346                hdr->e_flags     = cpu_to_elf32(ehdr, ehdr->e_flags);
 347                hdr->e_ehsize    = cpu_to_elf16(ehdr, sizeof(*hdr));
 348                hdr->e_phentsize = cpu_to_elf16(ehdr, sizeof(Elf32_Phdr));
 349                hdr->e_phnum     = cpu_to_elf16(ehdr, ehdr->e_phnum);
 350                hdr->e_shentsize = cpu_to_elf16(ehdr, 0);
 351                hdr->e_shnum     = cpu_to_elf16(ehdr, 0);
 352                hdr->e_shstrndx  = cpu_to_elf16(ehdr, 0);
 353        }
 354        else if (ehdr->ei_class == ELFCLASS64) {
 355                Elf64_Ehdr *hdr = (Elf64_Ehdr *)buf;
 356                hdr->e_ident[EI_MAG0]    = ELFMAG0;
 357                hdr->e_ident[EI_MAG1]    = ELFMAG1;
 358                hdr->e_ident[EI_MAG2]    = ELFMAG2;
 359                hdr->e_ident[EI_MAG3]    = ELFMAG3;
 360                hdr->e_ident[EI_CLASS]   = ehdr->ei_class;
 361                hdr->e_ident[EI_DATA]    = ehdr->ei_data;
 362                hdr->e_ident[EI_VERSION] = EV_CURRENT;
 363                hdr->e_type      = cpu_to_elf16(ehdr, ehdr->e_type);
 364                hdr->e_machine   = cpu_to_elf16(ehdr, ehdr->e_machine);
 365                hdr->e_version   = cpu_to_elf32(ehdr, EV_CURRENT);
 366                hdr->e_entry     = cpu_to_elf64(ehdr, ehdr->e_entry);
 367                hdr->e_phoff     = cpu_to_elf64(ehdr, sizeof(*hdr));
 368                hdr->e_shoff     = cpu_to_elf64(ehdr, 0);
 369                hdr->e_flags     = cpu_to_elf32(ehdr, ehdr->e_flags);
 370                hdr->e_ehsize    = cpu_to_elf16(ehdr, sizeof(*hdr));
 371                hdr->e_phentsize = cpu_to_elf16(ehdr, sizeof(Elf64_Phdr));
 372                hdr->e_phnum     = cpu_to_elf16(ehdr, ehdr->e_phnum);
 373                hdr->e_shentsize = cpu_to_elf16(ehdr, 0);
 374                hdr->e_shnum     = cpu_to_elf16(ehdr, 0);
 375                hdr->e_shstrndx  = cpu_to_elf16(ehdr, 0);
 376        }
 377        else die("Uknown elf class: %x\n", ehdr->ei_class);
 378}
 379static void serialize_phdrs(char *buf, struct memelfheader *ehdr, size_t note_size)
 380{
 381        int i;
 382        size_t offset, note_offset;
 383        if (ehdr->ei_class == ELFCLASS32) {
 384                Elf32_Phdr *phdr = (Elf32_Phdr *)buf;
 385                note_offset =
 386                        sizeof(Elf32_Ehdr) + (sizeof(Elf32_Phdr)*ehdr->e_phnum);
 387                offset = note_offset + note_size;
 388                for(i = 0; i < ehdr->e_phnum; i++) {
 389                        struct memelfphdr *hdr = ehdr->e_phdr + i;
 390                        phdr[i].p_type   = cpu_to_elf32(ehdr, hdr->p_type);
 391                        phdr[i].p_offset = cpu_to_elf32(ehdr, offset);
 392                        phdr[i].p_vaddr  = cpu_to_elf32(ehdr, hdr->p_vaddr);
 393                        phdr[i].p_paddr  = cpu_to_elf32(ehdr, hdr->p_paddr);
 394                        phdr[i].p_filesz = cpu_to_elf32(ehdr, hdr->p_filesz);
 395                        phdr[i].p_memsz  = cpu_to_elf32(ehdr, hdr->p_memsz);
 396                        phdr[i].p_flags  = cpu_to_elf32(ehdr, hdr->p_flags);
 397                        phdr[i].p_align  = cpu_to_elf32(ehdr, 0);
 398                        if (phdr[i].p_type == PT_NOTE) {
 399                                phdr[i].p_filesz = cpu_to_elf32(ehdr, note_size);
 400                                phdr[i].p_memsz  = cpu_to_elf32(ehdr, note_size);
 401                                phdr[i].p_offset = cpu_to_elf32(ehdr, note_offset);
 402                        } else {
 403                                offset += hdr->p_filesz;
 404                        }
 405                }
 406        }
 407        else if (ehdr->ei_class == ELFCLASS64) {
 408                Elf64_Phdr *phdr = (Elf64_Phdr *)buf;
 409                note_offset =
 410                        sizeof(Elf64_Ehdr) + (sizeof(Elf64_Phdr)*ehdr->e_phnum);
 411                offset = note_offset + note_size;
 412                for(i = 0; i < ehdr->e_phnum; i++) {
 413                        struct memelfphdr *hdr = ehdr->e_phdr + i;
 414                        phdr[i].p_type   = cpu_to_elf32(ehdr, hdr->p_type);
 415                        phdr[i].p_flags  = cpu_to_elf32(ehdr, hdr->p_flags);
 416                        phdr[i].p_offset = cpu_to_elf64(ehdr, offset);
 417                        phdr[i].p_vaddr  = cpu_to_elf64(ehdr, hdr->p_vaddr);
 418                        phdr[i].p_paddr  = cpu_to_elf64(ehdr, hdr->p_paddr);
 419                        phdr[i].p_filesz = cpu_to_elf64(ehdr, hdr->p_filesz);
 420                        phdr[i].p_memsz  = cpu_to_elf64(ehdr, hdr->p_memsz);
 421                        phdr[i].p_align  = cpu_to_elf64(ehdr, 0);
 422                        if (phdr[i].p_type == PT_NOTE) {
 423                                phdr[i].p_filesz = cpu_to_elf64(ehdr, note_size);
 424                                phdr[i].p_memsz  = cpu_to_elf64(ehdr, note_size);
 425                                phdr[i].p_offset = cpu_to_elf64(ehdr, note_offset);
 426                        } else {
 427                                offset += hdr->p_filesz;
 428                        }
 429                }
 430        }
 431        else {
 432                die("Unknwon elf class: %x\n", ehdr->ei_class);
 433        }
 434}
 435
 436static void write_buf(int fd, char *buf, size_t size)
 437{
 438        size_t progress = 0;
 439        ssize_t result;
 440        while(progress < size) {
 441                result = write(fd, buf + progress, size - progress);
 442                if (result < 0) {
 443                        if ((errno == EAGAIN) || (errno == EINTR)) {
 444                                continue;
 445                        }
 446                        die ("write of %ld bytes failed: %s\n",
 447                                size - progress, strerror(errno));
 448                }
 449                progress += result;
 450        }
 451}
 452static void write_elf(struct memelfheader *ehdr, char *output)
 453{
 454        size_t ehdr_size;
 455        size_t phdr_size;
 456        size_t note_size;
 457        size_t size;
 458        uint16_t checksum;
 459        size_t bytes;
 460        char *buf;
 461        int result, fd;
 462        int i;
 463        /* Prep for adding the checksum */
 464        for(i = 0; i < ehdr->e_notenum; i++) {
 465                if ((memcmp(ehdr->e_notes[i].n_name, "ELFBoot", 8) == 0) &&
 466                        (ehdr->e_notes[i].n_type == EIN_PROGRAM_CHECKSUM)) {
 467                        ehdr->e_notes[i].n_desc = &checksum;
 468                        ehdr->e_notes[i].n_descsz = 2;
 469                }
 470        }
 471        /* Compute the sizes */
 472        ehdr_size = 0;
 473        phdr_size = 0;
 474        note_size = 0;
 475        if (ehdr->e_notenum) {
 476                note_size = sizeof_notes(ehdr->e_notes, ehdr->e_notenum);
 477        }
 478        if (ehdr->ei_class == ELFCLASS32) {
 479                ehdr_size = sizeof(Elf32_Ehdr);
 480                phdr_size = sizeof(Elf32_Phdr) * ehdr->e_phnum;
 481        }
 482        else if (ehdr->ei_class == ELFCLASS64) {
 483                ehdr_size = sizeof(Elf64_Ehdr);
 484                phdr_size = sizeof(Elf64_Phdr) * ehdr->e_phnum;
 485        }
 486        else {
 487                die("Unknown elf class: %x\n", ehdr->ei_class);
 488        }
 489
 490        /* Allocate a buffer to temporarily hold the serialized forms */
 491        size = ehdr_size + phdr_size + note_size;
 492        buf = xmalloc(size, "Elf Headers");
 493        memset(buf, 0, size);
 494        serialize_ehdr(buf, ehdr);
 495        serialize_phdrs(buf + ehdr_size, ehdr, note_size);
 496
 497        /* Compute the checksum... */
 498        checksum = ipchksum(buf, ehdr_size + phdr_size);
 499        bytes = ehdr_size + phdr_size;
 500        for(i = 0; i < ehdr->e_phnum; i++) {
 501                checksum = add_ipchksums(bytes, checksum,
 502                        ipchksum(ehdr->e_phdr[i].p_data, ehdr->e_phdr[i].p_filesz));
 503                bytes += ehdr->e_phdr[i].p_memsz;
 504        }
 505
 506        /* Compute the final form of the notes */
 507        serialize_notes(buf + ehdr_size + phdr_size, ehdr);
 508
 509        /* Now write the elf image */
 510        fd = open(output, O_WRONLY | O_CREAT | O_EXCL, S_IRUSR | S_IRGRP | S_IROTH);
 511        if (fd < 0) {
 512                die("Cannot open ``%s'':%s\n",
 513                        output, strerror(errno));
 514        }
 515        write_buf(fd, buf, size);
 516        for(i = 0; i < ehdr->e_phnum; i++) {
 517                write_buf(fd, ehdr->e_phdr[i].p_data, ehdr->e_phdr[i].p_filesz);
 518        }
 519        result = close(fd);
 520        if (result < 0) {
 521                die("Close on %s failed: %s\n",
 522                        output, strerror(errno));
 523        }
 524}
 525
 526static void version(void)
 527{
 528        printf("mkelfImage " VERSION " released " RELEASE_DATE "\n");
 529}
 530void usage(void)
 531{
 532        int i;
 533        version();
 534        printf(
 535                "Usage: mkelfImage [OPTION]... <kernel> <elf_kernel>\n"
 536                "Build an ELF bootable kernel image from a normal kernel image\n"
 537                "\n"
 538                " -h, --help                  Print this help.\n"
 539                " -v, --version               Print the version of kexec.\n"
 540                "     --kernel=<filename>     Set the kernel to <filename>\n"
 541                "     --output=<filename>     Output to <filename>\n"
 542                " -t, --type=TYPE             Specify the new kernel is of <type>.\n"
 543                "\n"
 544                "Supported kernel types: \n"
 545                );
 546        for(i = 0; i < file_types; i++) {
 547                printf("%s\n", file_type[i].name);
 548                file_type[i].usage();
 549        }
 550        printf("\n");
 551}
 552
 553void error(char *fmt, ...)
 554{
 555        va_list args;
 556        va_start(args, fmt);
 557        vfprintf(stderr, fmt, args);
 558        va_end(args);
 559        usage();
 560        exit(1);
 561}
 562
 563int main(int argc, char **argv)
 564{
 565        int opt;
 566        int fileind;
 567        char *type, *kernel, *output;
 568        off_t kernel_size;
 569        char *kernel_buf;
 570        int result;
 571        int i;
 572        struct memelfheader hdr;
 573
 574        static const struct option options[] = {
 575                MKELF_OPTIONS
 576                { 0, 0, 0, 0 },
 577        };
 578        static const char short_options[] = MKELF_OPT_STR;
 579
 580        memset(&hdr, 0, sizeof(hdr));
 581        kernel = 0;
 582        output = 0;
 583
 584        /* Get the default type from the program name */
 585        type = strrchr(argv[0], '/');
 586        if (!type) type = argv[0];
 587        if (memcmp(type, "mkelf-", 6) == 0) {
 588                type = type + 6;
 589        } else {
 590                type = 0;
 591        }
 592        opterr = 0; /* Don't complain about unrecognized options here */
 593        while ((opt = getopt_long(argc, argv, short_options, options, 0)) != -1) {
 594                switch(opt) {
 595                case OPT_HELP:
 596                        usage();
 597                        return 0;
 598                case OPT_VERSION:
 599                        version();
 600                        return 0;
 601                case OPT_KERNEL:
 602                        kernel = optarg;
 603                        break;
 604                case OPT_OUTPUT:
 605                        output = optarg;
 606                        break;
 607                case OPT_TYPE:
 608                        type = optarg;
 609                        break;
 610                default:
 611                        break;
 612                }
 613        }
 614        fileind = optind;
 615
 616        /* Reset getopt for the next pass */
 617        opterr = 1;
 618        optind = 1;
 619
 620        if (argc - fileind > 0) {
 621                kernel = argv[fileind++];
 622        }
 623        if (argc - fileind > 0) {
 624                output = argv[fileind++];
 625        }
 626        if (!kernel) {
 627                error("No kernel specified!\n");
 628        }
 629        if (!output) {
 630                error("No output file specified!\n");
 631        }
 632        if (argc - fileind > 0) {
 633                error("%d extra options specified!\n", argc - fileind);
 634        }
 635
 636        /* slurp in the input kernel */
 637        kernel_buf = slurp_decompress_file(kernel, &kernel_size);
 638
 639        /* Find/verify the kernel type */
 640        for(i = 0; i < file_types; i++) {
 641                char *reason;
 642                if (type && (strcmp(type, file_type[i].name) != 0)) {
 643                        continue;
 644                }
 645                reason = file_type[i].probe(kernel_buf, kernel_size);
 646                if (reason == 0) {
 647                        break;
 648                }
 649                if (type) {
 650                        die("Not %s: %s\n", type, reason);
 651                }
 652        }
 653        if (i == file_types) {
 654                die("Can not determine the file type of %s\n", kernel);
 655        }
 656        result = file_type[i].mkelf(argc, argv, &hdr, kernel_buf, kernel_size);
 657        if (result < 0) {
 658                die("Cannot create %s result: %d\n", output, result);
 659        }
 660        /* open the output file */
 661        write_elf(&hdr, output);
 662        return 0;
 663}
 664
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.