Annotation of sys/arch/sparc/stand/boot/loadfile.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: loadfile.c,v 1.5 2003/08/14 17:13:57 deraadt Exp $ */
2: /* $NetBSD: loadfile.c,v 1.3 1997/04/06 08:40:59 cgd Exp $ */
3:
4: /*
5: * Copyright (c) 1992, 1993
6: * The Regents of the University of California. All rights reserved.
7: *
8: * This code is derived from software contributed to Berkeley by
9: * Ralph Campbell.
10: *
11: * Redistribution and use in source and binary forms, with or without
12: * modification, are permitted provided that the following conditions
13: * are met:
14: * 1. Redistributions of source code must retain the above copyright
15: * notice, this list of conditions and the following disclaimer.
16: * 2. Redistributions in binary form must reproduce the above copyright
17: * notice, this list of conditions and the following disclaimer in the
18: * documentation and/or other materials provided with the distribution.
19: * 3. Neither the name of the University nor the names of its contributors
20: * may be used to endorse or promote products derived from this software
21: * without specific prior written permission.
22: *
23: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33: * SUCH DAMAGE.
34: *
35: * @(#)boot.c 8.1 (Berkeley) 6/10/93
36: */
37:
38: #define ELFSIZE 32
39:
40: #include <lib/libkern/libkern.h>
41: #include <lib/libsa/stand.h>
42: #include <sparc/stand/common/promdev.h>
43:
44: #include <sys/param.h>
45: #include <sys/exec.h>
46: #include <sys/exec_elf.h>
47:
48: #include <ddb/db_aout.h>
49:
50: #ifdef SPARC_BOOT_AOUT
51: static int aout_exec(int, struct exec *, vaddr_t *);
52: #endif
53: #ifdef SPARC_BOOT_ELF
54: static int elf_exec(int, Elf_Ehdr *, vaddr_t *);
55: #endif
56: int loadfile(int, vaddr_t *);
57:
58: vaddr_t ssym, esym;
59:
60: union {
61: #ifdef SPARC_BOOT_AOUT
62: struct exec aout;
63: #endif
64: #ifdef SPARC_BOOT_ELF
65: Elf_Ehdr elf;
66: #endif
67: } hdr;
68:
69: /*
70: * Open 'filename', read in program and return the entry point or -1 if error.
71: */
72: int
73: loadfile(int fd, vaddr_t *entryp)
74: {
75: struct devices *dp;
76: int rval;
77:
78: /* Read the exec header. */
79: if (read(fd, &hdr, sizeof(hdr)) != sizeof(hdr)) {
80: printf("read header: %s\n", strerror(errno));
81: goto err;
82: }
83:
84: #ifdef SPARC_BOOT_ELF
85: if (memcmp(ELFMAG, hdr.elf.e_ident, SELFMAG) == 0) {
86: rval = elf_exec(fd, &hdr.elf, entryp);
87: } else
88: #endif
89: #ifdef SPARC_BOOT_AOUT
90: if (!N_BADMAG(hdr.aout)) {
91: rval = aout_exec(fd, &hdr.aout, entryp);
92: } else
93: #endif
94: {
95: printf("unknown executable format\n");
96: }
97:
98: err:
99: if (fd >= 0)
100: close(fd);
101: return (rval);
102: }
103:
104: #ifdef SPARC_BOOT_AOUT
105: static int
106: aout_exec(int fd, struct exec *aout, vaddr_t *entryp)
107: {
108: caddr_t addr = (caddr_t)LOADADDR;
109: int strtablen;
110: char *strtab;
111: vaddr_t entry = (vaddr_t)LOADADDR;
112: int i;
113:
114: printf("%d", aout->a_text);
115: if (N_GETMAGIC(*aout) == ZMAGIC) {
116: entry = (vaddr_t)(addr+sizeof(struct exec));
117: addr += sizeof(struct exec);
118: }
119: /* we can't lseek() here - we may be booting off tape */
120: bcopy((char *)aout + sizeof(struct exec), addr,
121: sizeof(hdr) - sizeof(struct exec));
122: if (read(fd, (char *)addr + sizeof(hdr) - sizeof(struct exec),
123: aout->a_text - (sizeof(hdr) - sizeof(struct exec))) !=
124: aout->a_text - (sizeof(hdr) - sizeof(struct exec)))
125: goto shread;
126: addr += aout->a_text;
127: if (N_GETMAGIC(*aout) == ZMAGIC || N_GETMAGIC(*aout) == NMAGIC)
128: while ((int)addr & __LDPGSZ)
129: *addr++ = 0;
130: printf("+%d", aout->a_data);
131: if (read(fd, addr, aout->a_data) != aout->a_data)
132: goto shread;
133: addr += aout->a_data;
134: printf("+%d", aout->a_bss);
135: for (i = aout->a_bss; i ; --i)
136: *addr++ = 0;
137: if (aout->a_syms != 0) {
138: bcopy(&aout->a_syms, addr, sizeof(aout->a_syms));
139: addr += sizeof(aout->a_syms);
140: printf("+[%d", aout->a_syms);
141: if (read(fd, addr, aout->a_syms) != aout->a_syms)
142: goto shread;
143: addr += aout->a_syms;
144:
145: if (read(fd, &strtablen, sizeof(int)) != sizeof(int))
146: goto shread;
147:
148: bcopy(&strtablen, addr, sizeof(int));
149: if (i = strtablen) {
150: i -= sizeof(int);
151: addr += sizeof(int);
152: if (read(fd, addr, i) != i)
153: goto shread;
154: addr += i;
155: }
156: printf("+%d]", i);
157: esym = ((u_int)aout->a_entry - (u_int)LOADADDR) +
158: (((int)addr + sizeof(int) - 1) & ~(sizeof(int) - 1));
159: }
160: printf("=0x%x\n", addr);
161: close(fd);
162:
163: *entryp = entry;
164: return (0);
165:
166: shread:
167: printf("boot: short read\n");
168: return (1);
169: }
170: #endif /* SPARC_BOOT_AOUT */
171:
172: #ifdef SPARC_BOOT_ELF
173:
174: /*
175: * If we're booting off tape, we can't seek.
176: * Emulate forward moves with reads, and give up on backwards moves.
177: * bsd.rd ought to be correctly ordered.
178: */
179: static int
180: elf_seek(int fd, off_t relpos)
181: {
182: #define DUMBBUFSIZE 4096
183: char dumbbuf[DUMBBUFSIZE];
184: int len;
185:
186: if (relpos < 0) {
187: #ifdef DEBUG
188: printf("elf_seek: attempting to seek backwards from %llx bytes, "
189: "may fail!\n", -relpos);
190: #endif
191: if (lseek(fd, relpos, SEEK_CUR) < 0)
192: return (-1);
193: return (0);
194: }
195:
196: while (relpos != 0) {
197: len = relpos > DUMBBUFSIZE ? DUMBBUFSIZE : relpos;
198: if (read(fd, dumbbuf, len) != len)
199: return (-1);
200: relpos -= len;
201: }
202:
203: return (0);
204: #undef DUMBBUFSIZE
205: }
206:
207: static int
208: elf_exec(int fd, Elf_Ehdr *elf, vaddr_t *entryp)
209: {
210: int i;
211: int first = 1, havesyms;
212: Elf_Shdr *shp;
213: Elf_Off off;
214: size_t sz;
215: vaddr_t addr = 0;
216: Elf_Ehdr *fake_elf;
217: #define NUM_HEADERS 12 /* should be more than enough */
218: Elf_Phdr headers[NUM_HEADERS], *phdr;
219: off_t pos, newpos;
220:
221: *entryp = 0;
222:
223: #define A(x) ((x) - *entryp + (vaddr_t)LOADADDR)
224:
225: pos = sizeof(hdr);
226:
227: /* load the headers */
228: if (elf->e_phnum > NUM_HEADERS)
229: elf->e_phnum = NUM_HEADERS; /* amnesia rules */
230: newpos = elf->e_phoff;
231: if (elf_seek(fd, newpos - pos))
232: return (1);
233: pos = newpos;
234: if (read(fd, (void *)headers, elf->e_phnum * sizeof(Elf_Phdr)) !=
235: elf->e_phnum * sizeof(Elf_Phdr)) {
236: printf("read phdr: %s\n", strerror(errno));
237: return (1);
238: }
239: pos += elf->e_phnum * sizeof(Elf_Phdr);
240:
241: /* loop through the pheaders and find the entry point. */
242: for (i = 0; i < elf->e_phnum; i++) {
243: phdr = &headers[i];
244: if (phdr->p_type != PT_LOAD ||
245: (phdr->p_flags & (PF_W|PF_X)) == 0 ||
246: (phdr->p_vaddr != elf->e_entry))
247: continue;
248:
249: *entryp = phdr->p_vaddr;
250: }
251:
252: if (*entryp == 0) {
253: printf("Can't find entry point.\n");
254: return (-1);
255: }
256:
257: for (i = 0; i < elf->e_phnum; i++) {
258: phdr = &headers[i];
259: if (phdr->p_type != PT_LOAD ||
260: (phdr->p_flags & (PF_W|PF_X)) == 0)
261: continue;
262:
263: /* Read in segment. */
264: printf("%s%lu", first ? "" : "+", phdr->p_filesz);
265: newpos = phdr->p_offset;
266: if (elf_seek(fd, newpos - pos))
267: return (1);
268: pos = newpos;
269:
270: if (read(fd, (caddr_t)A(phdr->p_vaddr), phdr->p_filesz) !=
271: phdr->p_filesz) {
272: (void)printf("read text: %s\n", strerror(errno));
273: return (1);
274: }
275: pos += phdr->p_filesz;
276:
277: /* keep track of highest addr we loaded. */
278: if (first || addr < (phdr->p_vaddr + phdr->p_memsz))
279: addr = (phdr->p_vaddr + phdr->p_memsz);
280:
281: /* Zero out bss. */
282: if (phdr->p_filesz < phdr->p_memsz) {
283: printf("+%lu", phdr->p_memsz - phdr->p_filesz);
284: bzero((caddr_t)A(phdr->p_vaddr) + phdr->p_filesz,
285: phdr->p_memsz - phdr->p_filesz);
286: }
287: first = 0;
288: }
289:
290: addr = A(addr);
291: addr = roundup(addr, sizeof(long));
292:
293: ssym = addr;
294: /*
295: * Retrieve symbols.
296: */
297: addr += sizeof(Elf_Ehdr);
298:
299: newpos = elf->e_shoff;
300: if (elf_seek(fd, newpos - pos)) {
301: printf("seek to section headers: %s\n", strerror(errno));
302: return (1);
303: }
304: pos = newpos;
305:
306: sz = elf->e_shnum * sizeof(Elf_Shdr);
307: shp = (Elf_Shdr *)addr;
308: addr += roundup(sz, sizeof(long));
309:
310: if (read(fd, shp, sz) != sz) {
311: printf("read section headers: %d\n", strerror(errno));
312: return (1);
313: }
314: pos += sz;
315:
316: /*
317: * Now load the symbol sections themselves. Make sure the
318: * sections are aligned. Don't bother with string tables if
319: * there are no symbol sections.
320: */
321: off = roundup((sizeof(Elf_Ehdr) + sz), sizeof(long));
322:
323: for (havesyms = i = 0; i < elf->e_shnum; i++)
324: if (shp[i].sh_type == SHT_SYMTAB)
325: havesyms = 1;
326:
327: if (!havesyms)
328: goto no_syms;
329:
330: for (first = 1, i = 0; i < elf->e_shnum; i++) {
331: if (shp[i].sh_type == SHT_SYMTAB ||
332: shp[i].sh_type == SHT_STRTAB) {
333: printf("%s%ld", first ? " [" : "+",
334: (u_long)shp[i].sh_size);
335: newpos = shp[i].sh_offset;
336: if (elf_seek(fd, newpos - pos)) {
337: printf("lseek symbols: %s\n", strerror(errno));
338: return (1);
339: }
340: pos = newpos;
341: if (read(fd, (void *)addr, shp[i].sh_size) !=
342: shp[i].sh_size) {
343: printf("read symbols: %s\n", strerror(errno));
344: return (1);
345: }
346: pos += shp[i].sh_size;
347: addr += roundup(shp[i].sh_size, sizeof(long));
348: shp[i].sh_offset = off;
349: off += roundup(shp[i].sh_size, sizeof(long));
350: first = 0;
351: }
352: }
353: if (havesyms && first == 0)
354: printf("]");
355:
356: elf->e_phoff = 0;
357: elf->e_shoff = sizeof(Elf_Ehdr);
358: elf->e_phentsize = 0;
359: elf->e_phnum = 0;
360: bcopy(elf, (void *)ssym, sizeof(*elf));
361:
362: no_syms:
363: esym = (addr - (vaddr_t)LOADADDR) + *entryp;
364:
365: *entryp = (vaddr_t)LOADADDR;
366:
367: printf("\n");
368: return (0);
369: #undef NUM_HEADERS
370: }
371: #endif /* SPARC_BOOT_ELF */
CVSweb