Annotation of sys/arch/aviion/stand/a2coff/a2coff.c, Revision 1.1
1.1 ! nbrk 1: /* $OpenBSD: a2coff.c,v 1.2 2006/05/14 17:49:54 miod Exp $ */
! 2: /*
! 3: * Copyright (c) 2006, Miodrag Vallat
! 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: *
! 14: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
! 15: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
! 16: * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
! 17: * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
! 18: * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
! 19: * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
! 20: * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
! 21: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
! 22: * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
! 23: * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
! 24: * POSSIBILITY OF SUCH DAMAGE.
! 25: */
! 26:
! 27: /*
! 28: * Quick and dirty a.out to 88K BCS ECOFF converter. Will only work for
! 29: * standalone binaries with no relocations, and will drop symbols.
! 30: * Also, bss is merged into the data section to cope with PROMs which
! 31: * do not zero-fill the bss upon loading (sad but true).
! 32: *
! 33: * This should really only be used to build a BSD/dg88k bootloader.
! 34: */
! 35:
! 36: #include <unistd.h>
! 37: #include <stdlib.h>
! 38: #include <err.h>
! 39: #include <fcntl.h>
! 40: #include <stdio.h>
! 41: #include <string.h>
! 42: #include <sys/types.h>
! 43:
! 44: #include <a.out.h>
! 45: /* overwrite __LDPGSZ if not a native binary */
! 46: #ifndef m88k
! 47: #undef __LDPGSZ
! 48: #define __LDPGSZ 0x1000
! 49: #endif /* m88k */
! 50:
! 51: /*
! 52: * We can't use the standard ecoff defines, first, because the system
! 53: * we are building this tool on might not have ecoff support at all (thus
! 54: * no <machine/ecoff_machdep.h> file), second, because the common defines
! 55: * do not know about the scnhdr changes for 88K BCS.
! 56: * So we'll provide our own, working, definitions.
! 57: */
! 58: #if 0 /* defined(_KERN_DO_ECOFF) */
! 59: #include <sys/exec_ecoff.h>
! 60: #else
! 61: struct ecoff_filehdr {
! 62: u_short f_magic; /* magic number */
! 63: u_short f_nscns; /* # of sections */
! 64: u_int f_timdat; /* time and date stamp */
! 65: u_long f_symptr; /* file offset of symbol table */
! 66: u_int f_nsyms; /* # of symbol table entries */
! 67: u_short f_opthdr; /* sizeof the optional header */
! 68: u_short f_flags; /* flags??? */
! 69: };
! 70:
! 71: struct ecoff_aouthdr {
! 72: u_short magic;
! 73: u_short vstamp;
! 74: #if 0
! 75: ECOFF_PAD
! 76: #endif
! 77: u_long tsize;
! 78: u_long dsize;
! 79: u_long bsize;
! 80: u_long entry;
! 81: u_long text_start;
! 82: u_long data_start;
! 83: #if 0 /* not on m88k */
! 84: u_long bss_start;
! 85: ECOFF_MACHDEP;
! 86: #endif
! 87: };
! 88:
! 89: struct ecoff_scnhdr { /* needed for size info */
! 90: char s_name[8]; /* name */
! 91: u_long s_paddr; /* physical addr? for ROMing?*/
! 92: u_long s_vaddr; /* virtual addr? */
! 93: u_long s_size; /* size */
! 94: u_long s_scnptr; /* file offset of raw data */
! 95: u_long s_relptr; /* file offset of reloc data */
! 96: u_long s_lnnoptr; /* file offset of line data */
! 97: #if 0
! 98: u_short s_nreloc; /* # of relocation entries */
! 99: u_short s_nlnno; /* # of line entries */
! 100: #else
! 101: /* m88k specific changes */
! 102: u_long s_nreloc;
! 103: union {
! 104: u_long _s_nlnno;
! 105: u_long _s_vendor;
! 106: } _s_s;
! 107: #define s_nlnno _s_s._s_nlnno
! 108: #define s_vendor _s_s._s_vendor
! 109: #endif
! 110: u_long s_flags;
! 111: };
! 112:
! 113: struct ecoff_exechdr {
! 114: struct ecoff_filehdr f;
! 115: struct ecoff_aouthdr a;
! 116: };
! 117: #endif
! 118:
! 119: #define round(qty, pow2) (((qty) + (pow2 - 1)) & ~(pow2 - 1UL))
! 120:
! 121: void copybits(int, int, u_int32_t);
! 122: void usage(void);
! 123: void zerobits(int, u_int32_t);
! 124:
! 125: int
! 126: main(int argc, char *argv[])
! 127: {
! 128: struct exec head;
! 129: struct ecoff_exechdr ehead;
! 130: struct ecoff_scnhdr escn[3];
! 131: int infd, outfd;
! 132: int n;
! 133:
! 134: if (argc != 3)
! 135: usage();
! 136:
! 137: infd = open(argv[1], O_RDONLY);
! 138: if (infd < 0)
! 139: err(1, argv[1]);
! 140:
! 141: outfd = open(argv[2], O_WRONLY | O_TRUNC | O_CREAT, 0644);
! 142: if (outfd < 0)
! 143: err(1, argv[2]);
! 144:
! 145: n = read(infd, &head, sizeof(head));
! 146: if (n < sizeof(head))
! 147: err(1, "read");
! 148:
! 149: if (N_BADMAG(head)) {
! 150: printf("%s: bad magic number\n", argv[1]);
! 151: exit(1);
! 152: }
! 153:
! 154: if (head.a_trsize || head.a_drsize) {
! 155: printf("%s: has relocations\n", argv[1]);
! 156: exit(1);
! 157: }
! 158:
! 159: /*
! 160: * Header
! 161: */
! 162:
! 163: ehead.f.f_magic = 0x016d; /* MC88OMAGIC */
! 164: ehead.f.f_nscns = 3;
! 165: ehead.f.f_timdat = 0; /* ignored */
! 166: ehead.f.f_symptr = 0; /* ignored */
! 167: ehead.f.f_nsyms = 0; /* ignored */
! 168: ehead.f.f_opthdr = sizeof ehead.a;
! 169: ehead.f.f_flags = 0x020f;
! 170: /* F_RELFLG | F_EXEC | F_LNNO | 8 | F_AR16WR */
! 171:
! 172: ehead.a.magic = N_GETMAGIC(head);
! 173: ehead.a.vstamp = 0; /* ignored */
! 174: ehead.a.tsize = head.a_text; /* ignored */
! 175: ehead.a.dsize = head.a_data; /* ignored */
! 176: ehead.a.bsize = head.a_bss; /* ignored */
! 177: ehead.a.entry = head.a_entry;
! 178: ehead.a.text_start = N_TXTADDR(head); /* ignored */
! 179: ehead.a.data_start = N_DATADDR(head); /* ignored */
! 180:
! 181: n = write(outfd, &ehead, sizeof(ehead));
! 182: if (n < sizeof(ehead))
! 183: err(1, "write");
! 184:
! 185: /*
! 186: * Sections.
! 187: * Note that we merge .bss into .data since the PROM will not
! 188: * clear it and locore does not do this either.
! 189: */
! 190:
! 191: strncpy(escn[0].s_name, ".text", sizeof escn[0].s_name);
! 192: escn[0].s_paddr = N_TXTADDR(head); /* ignored, 1:1 mapping */
! 193: escn[0].s_size = round(head.a_text, 8);
! 194: escn[0].s_scnptr = round(sizeof(ehead) + sizeof(escn), 0x10);
! 195: escn[0].s_relptr = 0;
! 196: escn[0].s_lnnoptr = 0;
! 197: escn[0].s_nlnno = 0;
! 198: escn[0].s_flags = 0x20; /* STYP_TEXT */
! 199:
! 200: strncpy(escn[1].s_name, ".data", sizeof escn[1].s_name);
! 201: escn[1].s_paddr = N_DATADDR(head); /* ignored, 1:1 mapping */
! 202: escn[1].s_scnptr = escn[0].s_scnptr + escn[0].s_size;
! 203: escn[1].s_size = round(head.a_data + head.a_bss, 8);
! 204: escn[1].s_relptr = 0;
! 205: escn[1].s_lnnoptr = 0;
! 206: escn[1].s_nlnno = 0;
! 207: escn[1].s_flags = 0x40; /* STYP_DATA */
! 208:
! 209: strncpy(escn[2].s_name, ".bss", sizeof escn[2].s_name);
! 210: escn[2].s_paddr = N_BSSADDR(head) + head.a_bss; /* ignored, 1:1 mapping */
! 211: escn[2].s_scnptr = 0; /* nothing in the file */
! 212: escn[2].s_size = 0;
! 213: escn[2].s_relptr = 0;
! 214: escn[2].s_lnnoptr = 0;
! 215: escn[2].s_nlnno = 0;
! 216: escn[2].s_flags = 0x80; /* STYP_BSS */
! 217:
! 218: /* adjust load addresses */
! 219: escn[0].s_paddr += (head.a_entry & ~(__LDPGSZ - 1)) - __LDPGSZ;
! 220: escn[1].s_paddr += (head.a_entry & ~(__LDPGSZ - 1)) - __LDPGSZ;
! 221: escn[2].s_paddr += (head.a_entry & ~(__LDPGSZ - 1)) - __LDPGSZ;
! 222: escn[0].s_vaddr = escn[0].s_paddr;
! 223: escn[1].s_vaddr = escn[1].s_paddr;
! 224: escn[2].s_vaddr = escn[2].s_paddr;
! 225:
! 226: n = write(outfd, &escn, sizeof(escn));
! 227: if (n < sizeof(escn))
! 228: err(1, "write");
! 229:
! 230: /*
! 231: * Copy text section
! 232: */
! 233:
! 234: #ifdef DEBUG
! 235: printf("copying %s: source %lx dest %lx size %x\n",
! 236: escn[0].s_name, N_TXTOFF(head), escn[0].s_scnptr, head.a_text);
! 237: #endif
! 238: lseek(outfd, escn[0].s_scnptr, SEEK_SET);
! 239: lseek(infd, N_TXTOFF(head), SEEK_SET);
! 240: copybits(infd, outfd, head.a_text);
! 241:
! 242: /*
! 243: * Copy data section
! 244: */
! 245:
! 246: #ifdef DEBUG
! 247: printf("copying %s: source %lx dest %lx size %x\n",
! 248: escn[1].s_name, N_DATOFF(head), escn[1].s_scnptr, head.a_data);
! 249: #endif
! 250: lseek(outfd, escn[1].s_scnptr, SEEK_SET);
! 251: lseek(infd, N_DATOFF(head), SEEK_SET);
! 252: copybits(infd, outfd, head.a_data);
! 253:
! 254: /*
! 255: * ``Copy'' bss section
! 256: */
! 257:
! 258: #ifdef DEBUG
! 259: printf("copying %s: size %lx\n",
! 260: escn[2].s_name, round(head.a_data + head.a_bss, 8) - head.a_data);
! 261: #endif
! 262: zerobits(outfd, round(head.a_data + head.a_bss, 8) - head.a_data);
! 263:
! 264: close(infd);
! 265: close(outfd);
! 266: exit(0);
! 267: }
! 268:
! 269: char buf[4096];
! 270: #define min(a ,b) ((a) < (b) ? (a) : (b))
! 271:
! 272: void
! 273: copybits(int from, int to, u_int32_t count)
! 274: {
! 275: int chunk;
! 276:
! 277: while (count != 0) {
! 278: chunk = min(count, sizeof buf);
! 279: if (read(from, buf, chunk) < chunk)
! 280: err(1, "read");
! 281: if (write(to, buf, chunk) < chunk)
! 282: err(1, "write");
! 283: count -= chunk;
! 284: }
! 285: }
! 286:
! 287: void
! 288: zerobits(int to, u_int32_t count)
! 289: {
! 290: int chunk;
! 291:
! 292: bzero(buf, sizeof buf);
! 293: while (count != 0) {
! 294: chunk = min(count, sizeof buf);
! 295: if (write(to, buf, chunk) < chunk)
! 296: err(1, "write");
! 297: count -= chunk;
! 298: }
! 299: }
! 300:
! 301: __dead void
! 302: usage(void)
! 303: {
! 304: extern char *__progname;
! 305:
! 306: fprintf(stderr, "usage: %s infile outfile\n", __progname);
! 307: exit(1);
! 308: }
CVSweb