Annotation of sys/arch/aviion/stand/a2coff/a2coff.c, Revision 1.1.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