GNU Linux-libre 4.19.286-gnu1
[releases.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 #include <stdint.h>
47 #include <inttypes.h>
48
49 #include "ecoff.h"
50
51 /*
52  * Some extra ELF definitions
53  */
54 #define PT_MIPS_REGINFO         0x70000000      /* Register usage information */
55 #define PT_MIPS_ABIFLAGS        0x70000003      /* Records ABI related flags  */
56
57 /* -------------------------------------------------------------------- */
58
59 struct sect {
60         uint32_t vaddr;
61         uint32_t len;
62 };
63
64 int *symTypeTable;
65 int must_convert_endian;
66 int format_bigendian;
67
68 static void copy(int out, int in, off_t offset, off_t size)
69 {
70         char ibuf[4096];
71         int remaining, cur, count;
72
73         /* Go to the start of the ELF symbol table... */
74         if (lseek(in, offset, SEEK_SET) < 0) {
75                 perror("copy: lseek");
76                 exit(1);
77         }
78
79         remaining = size;
80         while (remaining) {
81                 cur = remaining;
82                 if (cur > sizeof ibuf)
83                         cur = sizeof ibuf;
84                 remaining -= cur;
85                 if ((count = read(in, ibuf, cur)) != cur) {
86                         fprintf(stderr, "copy: read: %s\n",
87                                 count ? strerror(errno) :
88                                 "premature end of file");
89                         exit(1);
90                 }
91                 if ((count = write(out, ibuf, cur)) != cur) {
92                         perror("copy: write");
93                         exit(1);
94                 }
95         }
96 }
97
98 /*
99  * Combine two segments, which must be contiguous.   If pad is true, it's
100  * okay for there to be padding between.
101  */
102 static void combine(struct sect *base, struct sect *new, int pad)
103 {
104         if (!base->len)
105                 *base = *new;
106         else if (new->len) {
107                 if (base->vaddr + base->len != new->vaddr) {
108                         if (pad)
109                                 base->len = new->vaddr - base->vaddr;
110                         else {
111                                 fprintf(stderr,
112                                         "Non-contiguous data can't be converted.\n");
113                                 exit(1);
114                         }
115                 }
116                 base->len += new->len;
117         }
118 }
119
120 static int phcmp(const void *v1, const void *v2)
121 {
122         const Elf32_Phdr *h1 = v1;
123         const Elf32_Phdr *h2 = v2;
124
125         if (h1->p_vaddr > h2->p_vaddr)
126                 return 1;
127         else if (h1->p_vaddr < h2->p_vaddr)
128                 return -1;
129         else
130                 return 0;
131 }
132
133 static char *saveRead(int file, off_t offset, off_t len, char *name)
134 {
135         char *tmp;
136         int count;
137         off_t off;
138         if ((off = lseek(file, offset, SEEK_SET)) < 0) {
139                 fprintf(stderr, "%s: fseek: %s\n", name, strerror(errno));
140                 exit(1);
141         }
142         if (!(tmp = (char *) malloc(len))) {
143                 fprintf(stderr, "%s: Can't allocate %ld bytes.\n", name,
144                         len);
145                 exit(1);
146         }
147         count = read(file, tmp, len);
148         if (count != len) {
149                 fprintf(stderr, "%s: read: %s.\n",
150                         name,
151                         count ? strerror(errno) : "End of file reached");
152                 exit(1);
153         }
154         return tmp;
155 }
156
157 #define swab16(x) \
158         ((uint16_t)( \
159                 (((uint16_t)(x) & (uint16_t)0x00ffU) << 8) | \
160                 (((uint16_t)(x) & (uint16_t)0xff00U) >> 8) ))
161
162 #define swab32(x) \
163         ((unsigned int)( \
164                 (((uint32_t)(x) & (uint32_t)0x000000ffUL) << 24) | \
165                 (((uint32_t)(x) & (uint32_t)0x0000ff00UL) <<  8) | \
166                 (((uint32_t)(x) & (uint32_t)0x00ff0000UL) >>  8) | \
167                 (((uint32_t)(x) & (uint32_t)0xff000000UL) >> 24) ))
168
169 static void convert_elf_hdr(Elf32_Ehdr * e)
170 {
171         e->e_type = swab16(e->e_type);
172         e->e_machine = swab16(e->e_machine);
173         e->e_version = swab32(e->e_version);
174         e->e_entry = swab32(e->e_entry);
175         e->e_phoff = swab32(e->e_phoff);
176         e->e_shoff = swab32(e->e_shoff);
177         e->e_flags = swab32(e->e_flags);
178         e->e_ehsize = swab16(e->e_ehsize);
179         e->e_phentsize = swab16(e->e_phentsize);
180         e->e_phnum = swab16(e->e_phnum);
181         e->e_shentsize = swab16(e->e_shentsize);
182         e->e_shnum = swab16(e->e_shnum);
183         e->e_shstrndx = swab16(e->e_shstrndx);
184 }
185
186 static void convert_elf_phdrs(Elf32_Phdr * p, int num)
187 {
188         int i;
189
190         for (i = 0; i < num; i++, p++) {
191                 p->p_type = swab32(p->p_type);
192                 p->p_offset = swab32(p->p_offset);
193                 p->p_vaddr = swab32(p->p_vaddr);
194                 p->p_paddr = swab32(p->p_paddr);
195                 p->p_filesz = swab32(p->p_filesz);
196                 p->p_memsz = swab32(p->p_memsz);
197                 p->p_flags = swab32(p->p_flags);
198                 p->p_align = swab32(p->p_align);
199         }
200
201 }
202
203 static void convert_elf_shdrs(Elf32_Shdr * s, int num)
204 {
205         int i;
206
207         for (i = 0; i < num; i++, s++) {
208                 s->sh_name = swab32(s->sh_name);
209                 s->sh_type = swab32(s->sh_type);
210                 s->sh_flags = swab32(s->sh_flags);
211                 s->sh_addr = swab32(s->sh_addr);
212                 s->sh_offset = swab32(s->sh_offset);
213                 s->sh_size = swab32(s->sh_size);
214                 s->sh_link = swab32(s->sh_link);
215                 s->sh_info = swab32(s->sh_info);
216                 s->sh_addralign = swab32(s->sh_addralign);
217                 s->sh_entsize = swab32(s->sh_entsize);
218         }
219 }
220
221 static void convert_ecoff_filehdr(struct filehdr *f)
222 {
223         f->f_magic = swab16(f->f_magic);
224         f->f_nscns = swab16(f->f_nscns);
225         f->f_timdat = swab32(f->f_timdat);
226         f->f_symptr = swab32(f->f_symptr);
227         f->f_nsyms = swab32(f->f_nsyms);
228         f->f_opthdr = swab16(f->f_opthdr);
229         f->f_flags = swab16(f->f_flags);
230 }
231
232 static void convert_ecoff_aouthdr(struct aouthdr *a)
233 {
234         a->magic = swab16(a->magic);
235         a->vstamp = swab16(a->vstamp);
236         a->tsize = swab32(a->tsize);
237         a->dsize = swab32(a->dsize);
238         a->bsize = swab32(a->bsize);
239         a->entry = swab32(a->entry);
240         a->text_start = swab32(a->text_start);
241         a->data_start = swab32(a->data_start);
242         a->bss_start = swab32(a->bss_start);
243         a->gprmask = swab32(a->gprmask);
244         a->cprmask[0] = swab32(a->cprmask[0]);
245         a->cprmask[1] = swab32(a->cprmask[1]);
246         a->cprmask[2] = swab32(a->cprmask[2]);
247         a->cprmask[3] = swab32(a->cprmask[3]);
248         a->gp_value = swab32(a->gp_value);
249 }
250
251 static void convert_ecoff_esecs(struct scnhdr *s, int num)
252 {
253         int i;
254
255         for (i = 0; i < num; i++, s++) {
256                 s->s_paddr = swab32(s->s_paddr);
257                 s->s_vaddr = swab32(s->s_vaddr);
258                 s->s_size = swab32(s->s_size);
259                 s->s_scnptr = swab32(s->s_scnptr);
260                 s->s_relptr = swab32(s->s_relptr);
261                 s->s_lnnoptr = swab32(s->s_lnnoptr);
262                 s->s_nreloc = swab16(s->s_nreloc);
263                 s->s_nlnno = swab16(s->s_nlnno);
264                 s->s_flags = swab32(s->s_flags);
265         }
266 }
267
268 int main(int argc, char *argv[])
269 {
270         Elf32_Ehdr ex;
271         Elf32_Phdr *ph;
272         Elf32_Shdr *sh;
273         int i, pad;
274         struct sect text, data, bss;
275         struct filehdr efh;
276         struct aouthdr eah;
277         struct scnhdr esecs[6];
278         int infile, outfile;
279         uint32_t cur_vma = UINT32_MAX;
280         int addflag = 0;
281         int nosecs;
282
283         text.len = data.len = bss.len = 0;
284         text.vaddr = data.vaddr = bss.vaddr = 0;
285
286         /* Check args... */
287         if (argc < 3 || argc > 4) {
288               usage:
289                 fprintf(stderr,
290                         "usage: elf2ecoff <elf executable> <ecoff executable> [-a]\n");
291                 exit(1);
292         }
293         if (argc == 4) {
294                 if (strcmp(argv[3], "-a"))
295                         goto usage;
296                 addflag = 1;
297         }
298
299         /* Try the input file... */
300         if ((infile = open(argv[1], O_RDONLY)) < 0) {
301                 fprintf(stderr, "Can't open %s for read: %s\n",
302                         argv[1], strerror(errno));
303                 exit(1);
304         }
305
306         /* Read the header, which is at the beginning of the file... */
307         i = read(infile, &ex, sizeof ex);
308         if (i != sizeof ex) {
309                 fprintf(stderr, "ex: %s: %s.\n",
310                         argv[1],
311                         i ? strerror(errno) : "End of file reached");
312                 exit(1);
313         }
314
315         if (ex.e_ident[EI_DATA] == ELFDATA2MSB)
316                 format_bigendian = 1;
317
318         if (ntohs(0xaa55) == 0xaa55) {
319                 if (!format_bigendian)
320                         must_convert_endian = 1;
321         } else {
322                 if (format_bigendian)
323                         must_convert_endian = 1;
324         }
325         if (must_convert_endian)
326                 convert_elf_hdr(&ex);
327
328         /* Read the program headers... */
329         ph = (Elf32_Phdr *) saveRead(infile, ex.e_phoff,
330                                      ex.e_phnum * sizeof(Elf32_Phdr),
331                                      "ph");
332         if (must_convert_endian)
333                 convert_elf_phdrs(ph, ex.e_phnum);
334         /* Read the section headers... */
335         sh = (Elf32_Shdr *) saveRead(infile, ex.e_shoff,
336                                      ex.e_shnum * sizeof(Elf32_Shdr),
337                                      "sh");
338         if (must_convert_endian)
339                 convert_elf_shdrs(sh, ex.e_shnum);
340
341         /* Figure out if we can cram the program header into an ECOFF
342            header...  Basically, we can't handle anything but loadable
343            segments, but we can ignore some kinds of segments.  We can't
344            handle holes in the address space.  Segments may be out of order,
345            so we sort them first. */
346
347         qsort(ph, ex.e_phnum, sizeof(Elf32_Phdr), phcmp);
348
349         for (i = 0; i < ex.e_phnum; i++) {
350                 /* Section types we can ignore... */
351                 switch (ph[i].p_type) {
352                 case PT_NULL:
353                 case PT_NOTE:
354                 case PT_PHDR:
355                 case PT_MIPS_REGINFO:
356                 case PT_MIPS_ABIFLAGS:
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 %"PRIx32"  size %"PRIx32"\t file offset %"PRIx32"\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                                 uint32_t gap = ph[i].p_vaddr - cur_vma;
570                                 char obuf[1024];
571                                 if (gap > 65536) {
572                                         fprintf(stderr,
573                                                 "Intersegment gap (%"PRId32" bytes) too large.\n",
574                                                 gap);
575                                         exit(1);
576                                 }
577                                 fprintf(stderr,
578                                         "Warning: %d byte intersegment gap.\n",
579                                         gap);
580                                 memset(obuf, 0, sizeof obuf);
581                                 while (gap) {
582                                         int count =
583                                             write(outfile, obuf,
584                                                   (gap >
585                                                    sizeof obuf ? sizeof
586                                                    obuf : gap));
587                                         if (count < 0) {
588                                                 fprintf(stderr,
589                                                         "Error writing gap: %s\n",
590                                                         strerror(errno));
591                                                 exit(1);
592                                         }
593                                         gap -= count;
594                                 }
595                         }
596                         fprintf(stderr, "writing %d bytes...\n",
597                                 ph[i].p_filesz);
598                         copy(outfile, infile, ph[i].p_offset,
599                              ph[i].p_filesz);
600                         cur_vma = ph[i].p_vaddr + ph[i].p_filesz;
601                 }
602         }
603
604         /*
605          * Write a page of padding for boot PROMS that read entire pages.
606          * Without this, they may attempt to read past the end of the
607          * data section, incur an error, and refuse to boot.
608          */
609         {
610                 char obuf[4096];
611                 memset(obuf, 0, sizeof obuf);
612                 if (write(outfile, obuf, sizeof(obuf)) != sizeof(obuf)) {
613                         fprintf(stderr, "Error writing PROM padding: %s\n",
614                                 strerror(errno));
615                         exit(1);
616                 }
617         }
618
619         /* Looks like we won... */
620         exit(0);
621 }