Since some people disapprove of white space cleanups mixed in regular commits
[coreboot.git] / util / mkelfImage / main / mkelfImage.c
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
19 static 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 };
25 static const int file_types = sizeof(file_type)/sizeof(file_type[0]);
26
27 void 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 /**************************************************************************
39 IPCHKSUM - Checksum IP Header
40 **************************************************************************/
41 uint16_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
68 uint16_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
87 void *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
98 void *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
110 char *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
156 char *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
211 char *slurp_decompress_file(const char *filename, off_t *r_size)
212 {
213         return slurp_file(filename, r_size);
214 }
215 #endif
216
217 struct 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
236 struct 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
245 static 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
259 static 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
271 static 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
283 static 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
295 static 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 }
329 static 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 }
379 static 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
436 static 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 }
452 static 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
526 static void version(void)
527 {
528         printf("mkelfImage " VERSION " released " RELEASE_DATE "\n");
529 }
530 void 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
553 void 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
563 int 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 }