0b0f3cab068bae2eafd63baf37bf6e9984f676c2
[linux-drm-fsl-dcu.git] / arch / mips / boot / elf2ecoff.c
1 /*
2  * Copyright (c) 1995
3  *      Ted Lemon (hereinafter referred to as the author)
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  * 3. The name of the author may not be used to endorse or promote products
14  *    derived from this software without specific prior written permission.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND
17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE
20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26  * SUCH DAMAGE.
27  */
28
29 /* elf2ecoff.c
30
31    This program converts an elf executable to an ECOFF executable.
32    No symbol table is retained.   This is useful primarily in building
33    net-bootable kernels for machines (e.g., DECstation and Alpha) which
34    only support the ECOFF object file format. */
35
36 #include <stdio.h>
37 #include <string.h>
38 #include <errno.h>
39 #include <sys/types.h>
40 #include <fcntl.h>
41 #include <unistd.h>
42 #include <elf.h>
43 #include <limits.h>
44 #include <netinet/in.h>
45 #include <stdlib.h>
46
47 #include "ecoff.h"
48
49 /*
50  * Some extra ELF definitions
51  */
52 #define PT_MIPS_REGINFO 0x70000000      /* Register usage information */
53
54 /* -------------------------------------------------------------------- */
55
56 struct sect {
57         unsigned long vaddr;
58         unsigned long len;
59 };
60
61 int *symTypeTable;
62 int must_convert_endian;
63 int format_bigendian;
64
65 static void copy(int out, int in, off_t offset, off_t size)
66 {
67         char ibuf[4096];
68         int remaining, cur, count;
69
70         /* Go to the start of the ELF symbol table... */
71         if (lseek(in, offset, SEEK_SET) < 0) {
72                 perror("copy: lseek");
73                 exit(1);
74         }
75
76         remaining = size;
77         while (remaining) {
78                 cur = remaining;
79                 if (cur > sizeof ibuf)
80                         cur = sizeof ibuf;
81                 remaining -= cur;
82                 if ((count = read(in, ibuf, cur)) != cur) {
83                         fprintf(stderr, "copy: read: %s\n",
84                                 count ? strerror(errno) :
85                                 "premature end of file");
86                         exit(1);
87                 }
88                 if ((count = write(out, ibuf, cur)) != cur) {
89                         perror("copy: write");
90                         exit(1);
91                 }
92         }
93 }
94
95 /*
96  * Combine two segments, which must be contiguous.   If pad is true, it's
97  * okay for there to be padding between.
98  */
99 static void combine(struct sect *base, struct sect *new, int pad)
100 {
101         if (!base->len)
102                 *base = *new;
103         else if (new->len) {
104                 if (base->vaddr + base->len != new->vaddr) {
105                         if (pad)
106                                 base->len = new->vaddr - base->vaddr;
107                         else {
108                                 fprintf(stderr,
109                                         "Non-contiguous data can't be converted.\n");
110                                 exit(1);
111                         }
112                 }
113                 base->len += new->len;
114         }
115 }
116
117 static int phcmp(const void *v1, const void *v2)
118 {
119         const Elf32_Phdr *h1 = v1;
120         const Elf32_Phdr *h2 = v2;
121
122         if (h1->p_vaddr > h2->p_vaddr)
123                 return 1;
124         else if (h1->p_vaddr < h2->p_vaddr)
125                 return -1;
126         else
127                 return 0;
128 }
129
130 static char *saveRead(int file, off_t offset, off_t len, char *name)
131 {
132         char *tmp;
133         int count;
134         off_t off;
135         if ((off = lseek(file, offset, SEEK_SET)) < 0) {
136                 fprintf(stderr, "%s: fseek: %s\n", name, strerror(errno));
137                 exit(1);
138         }
139         if (!(tmp = (char *) malloc(len))) {
140                 fprintf(stderr, "%s: Can't allocate %ld bytes.\n", name,
141                         len);
142                 exit(1);
143         }
144         count = read(file, tmp, len);
145         if (count != len) {
146                 fprintf(stderr, "%s: read: %s.\n",
147                         name,
148                         count ? strerror(errno) : "End of file reached");
149                 exit(1);
150         }
151         return tmp;
152 }
153
154 #define swab16(x) \
155         ((unsigned short)( \
156                 (((unsigned short)(x) & (unsigned short)0x00ffU) << 8) | \
157                 (((unsigned short)(x) & (unsigned short)0xff00U) >> 8) ))
158
159 #define swab32(x) \
160         ((unsigned int)( \
161                 (((unsigned int)(x) & (unsigned int)0x000000ffUL) << 24) | \
162                 (((unsigned int)(x) & (unsigned int)0x0000ff00UL) <<  8) | \
163                 (((unsigned int)(x) & (unsigned int)0x00ff0000UL) >>  8) | \
164                 (((unsigned int)(x) & (unsigned int)0xff000000UL) >> 24) ))
165
166 static void convert_elf_hdr(Elf32_Ehdr * e)
167 {
168         e->e_type = swab16(e->e_type);
169         e->e_machine = swab16(e->e_machine);
170         e->e_version = swab32(e->e_version);
171         e->e_entry = swab32(e->e_entry);
172         e->e_phoff = swab32(e->e_phoff);
173         e->e_shoff = swab32(e->e_shoff);
174         e->e_flags = swab32(e->e_flags);
175         e->e_ehsize = swab16(e->e_ehsize);
176         e->e_phentsize = swab16(e->e_phentsize);
177         e->e_phnum = swab16(e->e_phnum);
178         e->e_shentsize = swab16(e->e_shentsize);
179         e->e_shnum = swab16(e->e_shnum);
180         e->e_shstrndx = swab16(e->e_shstrndx);
181 }
182
183 static void convert_elf_phdrs(Elf32_Phdr * p, int num)
184 {
185         int i;
186
187         for (i = 0; i < num; i++, p++) {
188                 p->p_type = swab32(p->p_type);
189                 p->p_offset = swab32(p->p_offset);
190                 p->p_vaddr = swab32(p->p_vaddr);
191                 p->p_paddr = swab32(p->p_paddr);
192                 p->p_filesz = swab32(p->p_filesz);
193                 p->p_memsz = swab32(p->p_memsz);
194                 p->p_flags = swab32(p->p_flags);
195                 p->p_align = swab32(p->p_align);
196         }
197
198 }
199
200 static void convert_elf_shdrs(Elf32_Shdr * s, int num)
201 {
202         int i;
203
204         for (i = 0; i < num; i++, s++) {
205                 s->sh_name = swab32(s->sh_name);
206                 s->sh_type = swab32(s->sh_type);
207                 s->sh_flags = swab32(s->sh_flags);
208                 s->sh_addr = swab32(s->sh_addr);
209                 s->sh_offset = swab32(s->sh_offset);
210                 s->sh_size = swab32(s->sh_size);
211                 s->sh_link = swab32(s->sh_link);
212                 s->sh_info = swab32(s->sh_info);
213                 s->sh_addralign = swab32(s->sh_addralign);
214                 s->sh_entsize = swab32(s->sh_entsize);
215         }
216 }
217
218 static void convert_ecoff_filehdr(struct filehdr *f)
219 {
220         f->f_magic = swab16(f->f_magic);
221         f->f_nscns = swab16(f->f_nscns);
222         f->f_timdat = swab32(f->f_timdat);
223         f->f_symptr = swab32(f->f_symptr);
224         f->f_nsyms = swab32(f->f_nsyms);
225         f->f_opthdr = swab16(f->f_opthdr);
226         f->f_flags = swab16(f->f_flags);
227 }
228
229 static void convert_ecoff_aouthdr(struct aouthdr *a)
230 {
231         a->magic = swab16(a->magic);
232         a->vstamp = swab16(a->vstamp);
233         a->tsize = swab32(a->tsize);
234         a->dsize = swab32(a->dsize);
235         a->bsize = swab32(a->bsize);
236         a->entry = swab32(a->entry);
237         a->text_start = swab32(a->text_start);
238         a->data_start = swab32(a->data_start);
239         a->bss_start = swab32(a->bss_start);
240         a->gprmask = swab32(a->gprmask);
241         a->cprmask[0] = swab32(a->cprmask[0]);
242         a->cprmask[1] = swab32(a->cprmask[1]);
243         a->cprmask[2] = swab32(a->cprmask[2]);
244         a->cprmask[3] = swab32(a->cprmask[3]);
245         a->gp_value = swab32(a->gp_value);
246 }
247
248 static void convert_ecoff_esecs(struct scnhdr *s, int num)
249 {
250         int i;
251
252         for (i = 0; i < num; i++, s++) {
253                 s->s_paddr = swab32(s->s_paddr);
254                 s->s_vaddr = swab32(s->s_vaddr);
255                 s->s_size = swab32(s->s_size);
256                 s->s_scnptr = swab32(s->s_scnptr);
257                 s->s_relptr = swab32(s->s_relptr);
258                 s->s_lnnoptr = swab32(s->s_lnnoptr);
259                 s->s_nreloc = swab16(s->s_nreloc);
260                 s->s_nlnno = swab16(s->s_nlnno);
261                 s->s_flags = swab32(s->s_flags);
262         }
263 }
264
265 int main(int argc, char *argv[])
266 {
267         Elf32_Ehdr ex;
268         Elf32_Phdr *ph;
269         Elf32_Shdr *sh;
270         char *shstrtab;
271         int i, pad;
272         struct sect text, data, bss;
273         struct filehdr efh;
274         struct aouthdr eah;
275         struct scnhdr esecs[6];
276         int infile, outfile;
277         unsigned long cur_vma = ULONG_MAX;
278         int addflag = 0;
279         int nosecs;
280
281         text.len = data.len = bss.len = 0;
282         text.vaddr = data.vaddr = bss.vaddr = 0;
283
284         /* Check args... */
285         if (argc < 3 || argc > 4) {
286               usage:
287                 fprintf(stderr,
288                         "usage: elf2ecoff <elf executable> <ecoff executable> [-a]\n");
289                 exit(1);
290         }
291         if (argc == 4) {
292                 if (strcmp(argv[3], "-a"))
293                         goto usage;
294                 addflag = 1;
295         }
296
297         /* Try the input file... */
298         if ((infile = open(argv[1], O_RDONLY)) < 0) {
299                 fprintf(stderr, "Can't open %s for read: %s\n",
300                         argv[1], strerror(errno));
301                 exit(1);
302         }
303
304         /* Read the header, which is at the beginning of the file... */
305         i = read(infile, &ex, sizeof ex);
306         if (i != sizeof ex) {
307                 fprintf(stderr, "ex: %s: %s.\n",
308                         argv[1],
309                         i ? strerror(errno) : "End of file reached");
310                 exit(1);
311         }
312
313         if (ex.e_ident[EI_DATA] == ELFDATA2MSB)
314                 format_bigendian = 1;
315
316         if (ntohs(0xaa55) == 0xaa55) {
317                 if (!format_bigendian)
318                         must_convert_endian = 1;
319         } else {
320                 if (format_bigendian)
321                         must_convert_endian = 1;
322         }
323         if (must_convert_endian)
324                 convert_elf_hdr(&ex);
325
326         /* Read the program headers... */
327         ph = (Elf32_Phdr *) saveRead(infile, ex.e_phoff,
328                                      ex.e_phnum * sizeof(Elf32_Phdr),
329                                      "ph");
330         if (must_convert_endian)
331                 convert_elf_phdrs(ph, ex.e_phnum);
332         /* Read the section headers... */
333         sh = (Elf32_Shdr *) saveRead(infile, ex.e_shoff,
334                                      ex.e_shnum * sizeof(Elf32_Shdr),
335                                      "sh");
336         if (must_convert_endian)
337                 convert_elf_shdrs(sh, ex.e_shnum);
338         /* Read in the section string table. */
339         shstrtab = saveRead(infile, sh[ex.e_shstrndx].sh_offset,
340                             sh[ex.e_shstrndx].sh_size, "shstrtab");
341
342         /* Figure out if we can cram the program header into an ECOFF
343            header...  Basically, we can't handle anything but loadable
344            segments, but we can ignore some kinds of segments.  We can't
345            handle holes in the address space.  Segments may be out of order,
346            so we sort them first. */
347
348         qsort(ph, ex.e_phnum, sizeof(Elf32_Phdr), phcmp);
349
350         for (i = 0; i < ex.e_phnum; i++) {
351                 /* Section types we can ignore... */
352                 switch (ph[i].p_type) {
353                 case PT_NULL:
354                 case PT_NOTE:
355                 case PT_PHDR:
356                 case PT_MIPS_REGINFO:
357                         continue;
358
359                 case PT_LOAD:
360                         /* Writable (data) segment? */
361                         if (ph[i].p_flags & PF_W) {
362                                 struct sect ndata, nbss;
363
364                                 ndata.vaddr = ph[i].p_vaddr;
365                                 ndata.len = ph[i].p_filesz;
366                                 nbss.vaddr = ph[i].p_vaddr + ph[i].p_filesz;
367                                 nbss.len = ph[i].p_memsz - ph[i].p_filesz;
368
369                                 combine(&data, &ndata, 0);
370                                 combine(&bss, &nbss, 1);
371                         } else {
372                                 struct sect ntxt;
373
374                                 ntxt.vaddr = ph[i].p_vaddr;
375                                 ntxt.len = ph[i].p_filesz;
376
377                                 combine(&text, &ntxt, 0);
378                         }
379                         /* Remember the lowest segment start address. */
380                         if (ph[i].p_vaddr < cur_vma)
381                                 cur_vma = ph[i].p_vaddr;
382                         break;
383
384                 default:
385                         /* Section types we can't handle... */
386                         fprintf(stderr,
387                                 "Program header %d type %d can't be converted.\n",
388                                 ex.e_phnum, ph[i].p_type);
389                         exit(1);
390                 }
391         }
392
393         /* Sections must be in order to be converted... */
394         if (text.vaddr > data.vaddr || data.vaddr > bss.vaddr ||
395             text.vaddr + text.len > data.vaddr
396             || data.vaddr + data.len > bss.vaddr) {
397                 fprintf(stderr,
398                         "Sections ordering prevents a.out conversion.\n");
399                 exit(1);
400         }
401
402         /* If there's a data section but no text section, then the loader
403            combined everything into one section.   That needs to be the
404            text section, so just make the data section zero length following
405            text. */
406         if (data.len && !text.len) {
407                 text = data;
408                 data.vaddr = text.vaddr + text.len;
409                 data.len = 0;
410         }
411
412         /* If there is a gap between text and data, we'll fill it when we copy
413            the data, so update the length of the text segment as represented in
414            a.out to reflect that, since a.out doesn't allow gaps in the program
415            address space. */
416         if (text.vaddr + text.len < data.vaddr)
417                 text.len = data.vaddr - text.vaddr;
418
419         /* We now have enough information to cons up an a.out header... */
420         eah.magic = OMAGIC;
421         eah.vstamp = 200;
422         eah.tsize = text.len;
423         eah.dsize = data.len;
424         eah.bsize = bss.len;
425         eah.entry = ex.e_entry;
426         eah.text_start = text.vaddr;
427         eah.data_start = data.vaddr;
428         eah.bss_start = bss.vaddr;
429         eah.gprmask = 0xf3fffffe;
430         memset(&eah.cprmask, '\0', sizeof eah.cprmask);
431         eah.gp_value = 0;       /* unused. */
432
433         if (format_bigendian)
434                 efh.f_magic = MIPSEBMAGIC;
435         else
436                 efh.f_magic = MIPSELMAGIC;
437         if (addflag)
438                 nosecs = 6;
439         else
440                 nosecs = 3;
441         efh.f_nscns = nosecs;
442         efh.f_timdat = 0;       /* bogus */
443         efh.f_symptr = 0;
444         efh.f_nsyms = 0;
445         efh.f_opthdr = sizeof eah;
446         efh.f_flags = 0x100f;   /* Stripped, not sharable. */
447
448         memset(esecs, 0, sizeof esecs);
449         strcpy(esecs[0].s_name, ".text");
450         strcpy(esecs[1].s_name, ".data");
451         strcpy(esecs[2].s_name, ".bss");
452         if (addflag) {
453                 strcpy(esecs[3].s_name, ".rdata");
454                 strcpy(esecs[4].s_name, ".sdata");
455                 strcpy(esecs[5].s_name, ".sbss");
456         }
457         esecs[0].s_paddr = esecs[0].s_vaddr = eah.text_start;
458         esecs[1].s_paddr = esecs[1].s_vaddr = eah.data_start;
459         esecs[2].s_paddr = esecs[2].s_vaddr = eah.bss_start;
460         if (addflag) {
461                 esecs[3].s_paddr = esecs[3].s_vaddr = 0;
462                 esecs[4].s_paddr = esecs[4].s_vaddr = 0;
463                 esecs[5].s_paddr = esecs[5].s_vaddr = 0;
464         }
465         esecs[0].s_size = eah.tsize;
466         esecs[1].s_size = eah.dsize;
467         esecs[2].s_size = eah.bsize;
468         if (addflag) {
469                 esecs[3].s_size = 0;
470                 esecs[4].s_size = 0;
471                 esecs[5].s_size = 0;
472         }
473         esecs[0].s_scnptr = N_TXTOFF(efh, eah);
474         esecs[1].s_scnptr = N_DATOFF(efh, eah);
475 #define ECOFF_SEGMENT_ALIGNMENT(a) 0x10
476 #define ECOFF_ROUND(s, a) (((s)+(a)-1)&~((a)-1))
477         esecs[2].s_scnptr = esecs[1].s_scnptr +
478             ECOFF_ROUND(esecs[1].s_size, ECOFF_SEGMENT_ALIGNMENT(&eah));
479         if (addflag) {
480                 esecs[3].s_scnptr = 0;
481                 esecs[4].s_scnptr = 0;
482                 esecs[5].s_scnptr = 0;
483         }
484         esecs[0].s_relptr = esecs[1].s_relptr = esecs[2].s_relptr = 0;
485         esecs[0].s_lnnoptr = esecs[1].s_lnnoptr = esecs[2].s_lnnoptr = 0;
486         esecs[0].s_nreloc = esecs[1].s_nreloc = esecs[2].s_nreloc = 0;
487         esecs[0].s_nlnno = esecs[1].s_nlnno = esecs[2].s_nlnno = 0;
488         if (addflag) {
489                 esecs[3].s_relptr = esecs[4].s_relptr
490                     = esecs[5].s_relptr = 0;
491                 esecs[3].s_lnnoptr = esecs[4].s_lnnoptr
492                     = esecs[5].s_lnnoptr = 0;
493                 esecs[3].s_nreloc = esecs[4].s_nreloc = esecs[5].s_nreloc =
494                     0;
495                 esecs[3].s_nlnno = esecs[4].s_nlnno = esecs[5].s_nlnno = 0;
496         }
497         esecs[0].s_flags = 0x20;
498         esecs[1].s_flags = 0x40;
499         esecs[2].s_flags = 0x82;
500         if (addflag) {
501                 esecs[3].s_flags = 0x100;
502                 esecs[4].s_flags = 0x200;
503                 esecs[5].s_flags = 0x400;
504         }
505
506         /* Make the output file... */
507         if ((outfile = open(argv[2], O_WRONLY | O_CREAT, 0777)) < 0) {
508                 fprintf(stderr, "Unable to create %s: %s\n", argv[2],
509                         strerror(errno));
510                 exit(1);
511         }
512
513         if (must_convert_endian)
514                 convert_ecoff_filehdr(&efh);
515         /* Write the headers... */
516         i = write(outfile, &efh, sizeof efh);
517         if (i != sizeof efh) {
518                 perror("efh: write");
519                 exit(1);
520
521                 for (i = 0; i < nosecs; i++) {
522                         printf
523                             ("Section %d: %s phys %lx  size %lx  file offset %lx\n",
524                              i, esecs[i].s_name, esecs[i].s_paddr,
525                              esecs[i].s_size, esecs[i].s_scnptr);
526                 }
527         }
528         fprintf(stderr, "wrote %d byte file header.\n", i);
529
530         if (must_convert_endian)
531                 convert_ecoff_aouthdr(&eah);
532         i = write(outfile, &eah, sizeof eah);
533         if (i != sizeof eah) {
534                 perror("eah: write");
535                 exit(1);
536         }
537         fprintf(stderr, "wrote %d byte a.out header.\n", i);
538
539         if (must_convert_endian)
540                 convert_ecoff_esecs(&esecs[0], nosecs);
541         i = write(outfile, &esecs, nosecs * sizeof(struct scnhdr));
542         if (i != nosecs * sizeof(struct scnhdr)) {
543                 perror("esecs: write");
544                 exit(1);
545         }
546         fprintf(stderr, "wrote %d bytes of section headers.\n", i);
547
548         pad = (sizeof(efh) + sizeof(eah) + nosecs * sizeof(struct scnhdr)) & 15;
549         if (pad) {
550                 pad = 16 - pad;
551                 i = write(outfile, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0", pad);
552                 if (i < 0) {
553                         perror("ipad: write");
554                         exit(1);
555                 }
556                 fprintf(stderr, "wrote %d byte pad.\n", i);
557         }
558
559         /*
560          * Copy the loadable sections.   Zero-fill any gaps less than 64k;
561          * complain about any zero-filling, and die if we're asked to zero-fill
562          * more than 64k.
563          */
564         for (i = 0; i < ex.e_phnum; i++) {
565                 /* Unprocessable sections were handled above, so just verify that
566                    the section can be loaded before copying. */
567                 if (ph[i].p_type == PT_LOAD && ph[i].p_filesz) {
568                         if (cur_vma != ph[i].p_vaddr) {
569                                 unsigned long gap =
570                                     ph[i].p_vaddr - cur_vma;
571                                 char obuf[1024];
572                                 if (gap > 65536) {
573                                         fprintf(stderr,
574                                                 "Intersegment gap (%ld bytes) too large.\n",
575                                                 gap);
576                                         exit(1);
577                                 }
578                                 fprintf(stderr,
579                                         "Warning: %ld byte intersegment gap.\n",
580                                         gap);
581                                 memset(obuf, 0, sizeof obuf);
582                                 while (gap) {
583                                         int count =
584                                             write(outfile, obuf,
585                                                   (gap >
586                                                    sizeof obuf ? sizeof
587                                                    obuf : gap));
588                                         if (count < 0) {
589                                                 fprintf(stderr,
590                                                         "Error writing gap: %s\n",
591                                                         strerror(errno));
592                                                 exit(1);
593                                         }
594                                         gap -= count;
595                                 }
596                         }
597                         fprintf(stderr, "writing %d bytes...\n",
598                                 ph[i].p_filesz);
599                         copy(outfile, infile, ph[i].p_offset,
600                              ph[i].p_filesz);
601                         cur_vma = ph[i].p_vaddr + ph[i].p_filesz;
602                 }
603         }
604
605         /*
606          * Write a page of padding for boot PROMS that read entire pages.
607          * Without this, they may attempt to read past the end of the
608          * data section, incur an error, and refuse to boot.
609          */
610         {
611                 char obuf[4096];
612                 memset(obuf, 0, sizeof obuf);
613                 if (write(outfile, obuf, sizeof(obuf)) != sizeof(obuf)) {
614                         fprintf(stderr, "Error writing PROM padding: %s\n",
615                                 strerror(errno));
616                         exit(1);
617                 }
618         }
619
620         /* Looks like we won... */
621         exit(0);
622 }