Annotation of sys/arch/sgi/stand/boot/boot.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: boot.c,v 1.8 2007/05/11 10:28:20 jj Exp $ */
2:
3: /*
4: * Copyright (c) 2004 Opsycon AB, www.opsycon.se.
5: *
6: * Redistribution and use in source and binary forms, with or without
7: * modification, are permitted provided that the following conditions
8: * are met:
9: * 1. Redistributions of source code must retain the above copyright
10: * notice, this list of conditions and the following disclaimer.
11: * 2. Redistributions in binary form must reproduce the above copyright
12: * notice, this list of conditions and the following disclaimer in the
13: * documentation and/or other materials provided with the distribution.
14: *
15: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
16: * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17: * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18: * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
19: * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25: * SUCH DAMAGE.
26: *
27: */
28:
29: #include <sys/param.h>
30: #include <sys/stat.h>
31: #include <sys/exec.h>
32: #include <sys/exec_elf.h>
33: #include <stand.h>
34:
35: #include <mips64/arcbios.h>
36:
37: void gets(char *);
38: ssize_t read(int, void *, size_t);
39: int close(int);
40:
41: int main(int, char **);
42: void dobootopts(int, char **);
43: Elf32_Addr loadfile(char *);
44: Elf32_Addr loadfile32(int, Elf32_Ehdr *);
45: Elf32_Addr loadfile64(int, Elf64_Ehdr *);
46: int loadsymtab32(int, Elf32_Ehdr *, int);
47: int loadsymtab64(int, Elf64_Ehdr *, int);
48:
49: enum {
50: AUTO_NONE,
51: AUTO_YES,
52: AUTO_NO,
53: AUTO_MINI,
54: AUTO_DEBUG
55: } bootauto = AUTO_NONE;
56: char *OSLoadPartition = NULL;
57: char *OSLoadFilename = NULL;
58:
59: unsigned long tablebase;
60:
61: static void *
62: readtable(int fd, int offs, void *base, int size, char *name, int flags)
63: {
64: if (lseek(fd, offs, SEEK_SET) != offs ||
65: read(fd, base, size) != size) {
66: printf("\ncannot read %s table", name);
67: return 0;
68: }
69: return (void *) base;
70: }
71:
72: static void *
73: gettable(int size, char *name, int flags, size_t align)
74: {
75: long base;
76:
77: /* Put table after loaded code to support kernel DDB */
78: tablebase = roundup(tablebase, align);
79: base = tablebase;
80: tablebase += size;
81: return (void *) base;
82: }
83:
84: /*
85: */
86: int
87: main(int argc, char *argv[])
88: {
89: char line[1024];
90: int i;
91: Elf32_Addr entry;
92:
93: dobootopts(argc, argv);
94: if (OSLoadPartition != NULL) {
95: strlcpy(line, OSLoadPartition, sizeof(line));
96: i = strlen(line);
97: if (OSLoadFilename != NULL)
98: strlcpy(&line[i], OSLoadFilename, sizeof(line) - i -1);
99: } else
100: strlcpy("invalid argument setup", line, sizeof(line));
101:
102: for (entry = 0; entry < argc; entry++)
103: printf("arg %d: %s\n", entry, argv[entry]);
104: printf("\nOpenBSD/sgi Arcbios boot\n");
105:
106: printf("Boot: %s\n", line);
107:
108: entry = loadfile(line);
109: if (entry != NULL)
110: ((void (*)())entry)(argc, argv);
111: printf("Boot FAILED!\n ");
112: Bios_Restart();
113: }
114:
115: /*
116: * Decode boot options.
117: */
118: void
119: dobootopts(int argc, char **argv)
120: {
121: char *SystemPartition = NULL;
122: char *cp;
123: int i;
124:
125: for (i = 1; i < argc; i++) {
126: cp = argv[i];
127: if (cp == NULL)
128: continue;
129: if (strncmp(cp, "OSLoadOptions=", 14) == 0) {
130: if (strcmp(&cp[14], "auto") == 0)
131: bootauto = AUTO_YES;
132: else if (strcmp(&cp[14], "single") == 0)
133: bootauto = AUTO_NO;
134: else if (strcmp(&cp[14], "mini") == 0)
135: bootauto = AUTO_MINI;
136: else if (strcmp(&cp[14], "debug") == 0)
137: bootauto = AUTO_DEBUG;
138: } else if (strncmp(cp, "OSLoadPartition=", 16) == 0)
139: OSLoadPartition = &cp[16];
140: else if (strncmp(cp, "OSLoadFilename=", 15) == 0)
141: OSLoadFilename = &cp[15];
142: else if (strncmp(cp, "SystemPartition=", 16) == 0)
143: SystemPartition = &cp[16];
144: }
145: /* If "OSLoadOptions=" is missing, see if any arg was given */
146: if (bootauto == AUTO_NONE && *argv[1] == '/')
147: OSLoadFilename = argv[1];
148:
149: if (bootauto == AUTO_MINI) {
150: static char loadpart[64];
151: char *p;
152:
153: strlcpy(loadpart, argv[0], sizeof loadpart);
154: p = strstr(loadpart, "partition(8)");
155: if (p) {
156: p += strlen("partition(");
157: p[0] = '0'; p[2] = 0;
158: OSLoadPartition = loadpart;
159: OSLoadFilename = "/bsd.rd";
160: }
161: }
162: }
163:
164: /*
165: * Open 'filename', read in program and return the entry point or -1 if error.
166: */
167: Elf32_Addr
168: loadfile(fname)
169: register char *fname;
170: {
171: union {
172: Elf32_Ehdr eh32;
173: Elf64_Ehdr eh64;
174: } eh;
175: int fd;
176: Elf32_Addr entry;
177:
178: if ((fd = open(fname, 0)) < 0) {
179: printf("can't open file %s\n", fname);
180: return NULL;
181: }
182:
183: /* read the ELF header and check that it IS an ELF header */
184: if (read(fd, (char *)&eh, sizeof(eh)) != sizeof(eh)) {
185: printf("error: ELF header read error\n");
186: return NULL;
187: }
188: if (!IS_ELF(eh.eh32)) {
189: printf("not an elf file\n");
190: return NULL;
191: }
192:
193: /* Determine CLASS */
194: if (eh.eh32.e_ident[EI_CLASS] == ELFCLASS32)
195: entry = loadfile32(fd, (void *)&eh);
196: else if (eh.eh32.e_ident[EI_CLASS] == ELFCLASS64)
197: entry = loadfile64(fd, (void *)&eh);
198: else {
199: printf("unknown ELF class\n");
200: return NULL;
201: }
202: return entry;
203: }
204:
205: Elf32_Addr
206: loadfile32(int fd, Elf32_Ehdr *eh)
207: {
208: char buf[4096];
209: Elf32_Phdr *ph;
210: int i;
211:
212: ph = (Elf32_Phdr *) buf;
213: lseek(fd, eh->e_phoff, 0);
214: if (read(fd, (char *)ph, 4096) != 4096) {
215: printf("unexpected EOF\n");
216: return NULL;
217: }
218:
219: tablebase = 0;
220: printf("Loading ELF32 file\n");
221:
222: for (i = 0; i < eh->e_phnum; i++, ph++) {
223: if (ph->p_type == PT_LOAD) {
224: lseek(fd, ph->p_offset, 0);
225: printf("0x%x:0x%x, ",(long)ph->p_paddr, (long)ph->p_filesz);
226: if (read(fd, (char *)ph->p_paddr,
227: ph->p_filesz) != ph->p_filesz) {
228: printf("unexpected EOF\n");
229: return NULL;
230: }
231: if(ph->p_memsz > ph->p_filesz) {
232: printf("Zero 0x%x:0x%x, ",
233: (long)(ph->p_paddr + ph->p_filesz),
234: (long)(ph->p_memsz - ph->p_filesz));
235: bzero((void *)(ph->p_paddr + ph->p_filesz),
236: ph->p_memsz - ph->p_filesz);
237: }
238: if((ph->p_paddr + ph->p_memsz) > tablebase)
239: tablebase = ph->p_paddr + ph->p_memsz;
240: }
241: }
242: memset((void *)tablebase, 0, 4096);
243: loadsymtab32(fd, eh, 0);
244: printf("Start at 0x%x\n", eh->e_entry);
245: return(eh->e_entry);
246: }
247:
248: Elf32_Addr
249: loadfile64(int fd, Elf64_Ehdr *eh)
250: {
251: char buf[4096];
252: Elf64_Phdr *ph;
253: int i;
254:
255: ph = (Elf64_Phdr *) buf;
256: lseek(fd, eh->e_phoff, 0);
257: if (read(fd, (char *)ph, 4096) != 4096) {
258: printf("unexpected EOF\n");
259: return NULL;
260: }
261:
262: tablebase = 0;
263: printf("Loading ELF64 file\n");
264:
265: for (i = 0; i < eh->e_phnum; i++, ph++) {
266: if (ph->p_type == PT_LOAD) {
267: lseek(fd, ph->p_offset, 0);
268: printf("0x%llx:0x%llx, ",ph->p_paddr, ph->p_filesz);
269: if (read(fd, (char *)(long)ph->p_paddr,
270: ph->p_filesz) != ph->p_filesz) {
271: printf("unexpected EOF\n");
272: return NULL;
273: }
274: if(ph->p_memsz > ph->p_filesz) {
275: printf("Zero 0x%llx:0x%llx, ",
276: ph->p_paddr + ph->p_filesz,
277: ph->p_memsz - ph->p_filesz);
278: bzero((void *)(long)(ph->p_paddr + ph->p_filesz),
279: ph->p_memsz - ph->p_filesz);
280: }
281: if((ph->p_paddr + ph->p_memsz) > tablebase)
282: tablebase = ph->p_paddr + ph->p_memsz;
283: }
284: }
285: memset((void *)tablebase, 0, 4096);
286: loadsymtab64(fd, eh, 0);
287: printf("Start at 0x%llx\n", eh->e_entry);
288: return(eh->e_entry);
289: }
290:
291: int
292: loadsymtab32(int fd, Elf32_Ehdr *eh, int flags)
293: {
294: Elf32_Ehdr *keh;
295: Elf32_Shdr *shtab;
296: Elf32_Shdr *sh, *ksh, *shstrh, *strh;
297: Elf32_Sym *symtab;
298: int *symptr;
299: char *shstrtab, *strtab, *symend;
300: int i, nsym, offs, size;
301:
302: printf("Loading symbol table\n");
303: size = eh->e_shnum * sizeof(Elf32_Shdr);
304: shtab = (Elf32_Shdr *) alloc(size);
305: if (lseek (fd, eh->e_shoff, SEEK_SET) != eh->e_shoff ||
306: read (fd, shtab, size) != size) {
307: printf("Seek to section headers failed.\n");
308: return -1;
309: }
310:
311: tablebase = roundup(tablebase, sizeof(long));
312: symptr = (int *)tablebase;
313: tablebase = roundup(tablebase, 4096);
314: keh = (Elf32_Ehdr *)tablebase;
315: tablebase += sizeof(Elf32_Ehdr);
316: tablebase = roundup(tablebase, sizeof(long));
317: ksh = (Elf32_Shdr *)tablebase;
318: tablebase += roundup((sizeof(Elf32_Shdr) * eh->e_shnum), sizeof(long));
319: memcpy(ksh, shtab, roundup((sizeof(Elf32_Shdr) * eh->e_shnum), sizeof(long)));
320: sh = ksh;
321:
322: shstrh = &sh[eh->e_shstrndx];
323:
324: for (i = 0; i < eh->e_shnum; sh++, i++) {
325: if (sh->sh_type == SHT_SYMTAB)
326: break;
327: }
328: if (i >= eh->e_shnum) {
329: printf("No symbol table found!\n");
330: return -1;
331: }
332:
333: strh = &ksh[sh->sh_link];
334: nsym = sh->sh_size / sh->sh_entsize;
335: offs = sh->sh_offset;
336: size = sh->sh_size;
337:
338: /*
339: * Allocate tables in correct order so the kernel groks it.
340: * Then we read them in the order they are in the ELF file.
341: */
342: shstrtab = gettable(shstrh->sh_size, "shstrtab", flags, sizeof(long));
343: strtab = gettable(strh->sh_size, "strtab", flags, sizeof(long));
344: symtab = gettable(size, "symtab", flags, sizeof(long));
345: symend = (char *)symtab + size;
346:
347: do {
348: if(shstrh->sh_offset < offs && shstrh->sh_offset < strh->sh_offset) {
349: #if 0
350: /*
351: * We would like to read the shstrtab from the file
352: * but since this table is located in front of the shtab
353: * it is already gone. We can't position backwards
354: * outside the current segment when using tftp.
355: * Instead we create the names we need in the string
356: * table because it can be reconstructed from the info
357: * we now have access to.
358: */
359: if (!readtable (shstrh->sh_offset, (void *)shstrtab,
360: shstrh->sh_size, "shstring", flags))
361: return(0);
362: #else
363: memset(shstrtab, 0, shstrh->sh_size);
364: strncpy(shstrtab + shstrh->sh_name, ".shstrtab", 10);
365: strncpy(shstrtab + strh->sh_name, ".strtab", 10);
366: strncpy(shstrtab + sh->sh_name, ".symtab", 10);
367: #endif
368: shstrh->sh_offset = 0x7fffffff;
369: }
370:
371: if (offs < strh->sh_offset && offs < shstrh->sh_offset) {
372: if (!(readtable(fd, offs, (void *)symtab, size,
373: "sym", flags)))
374: return (0);
375: offs = 0x7fffffff;
376: }
377:
378: if (strh->sh_offset < offs && strh->sh_offset < shstrh->sh_offset) {
379: if (!(readtable (fd, strh->sh_offset, (void *)strtab,
380: strh->sh_size, "string", flags)))
381: return (0);
382: strh->sh_offset = 0x7fffffff;
383: }
384: if (offs == 0x7fffffff && strh->sh_offset == 0x7fffffff &&
385: shstrh->sh_offset == 0x7fffffff)
386: break;
387: } while(1);
388:
389: /*
390: * Update the kernel headers with the current info.
391: */
392: shstrh->sh_offset = (Elf32_Off)shstrtab - (Elf32_Off)keh;
393: strh->sh_offset = (Elf32_Off)strtab - (Elf32_Off)keh;
394: sh->sh_offset = (Elf32_Off)symtab - (Elf32_Off)keh;
395: memcpy(keh, eh, sizeof(Elf32_Ehdr));
396: keh->e_phoff = 0;
397: keh->e_shoff = sizeof(Elf32_Ehdr);
398: keh->e_phentsize = 0;
399: keh->e_phnum = 0;
400:
401: symptr[0] = (int)keh;
402: symptr[1] = roundup((int)symend, sizeof(int));
403:
404: return(0);
405:
406: }
407:
408: int
409: loadsymtab64(int fd, Elf64_Ehdr *eh, int flags)
410: {
411: Elf64_Ehdr *keh;
412: Elf64_Shdr *shtab;
413: Elf64_Shdr *sh, *ksh, *shstrh, *strh;
414: Elf64_Sym *symtab;
415: u_int64_t *symptr;
416: char *shstrtab, *strtab, *symend;
417: int i, nsym;
418: Elf64_Xword size;
419: Elf64_Off offs;
420:
421: printf("Loading symbol table\n");
422: size = eh->e_shnum * sizeof(Elf64_Shdr);
423: shtab = (Elf64_Shdr *) alloc(size);
424: if (lseek (fd, (int)eh->e_shoff, SEEK_SET) != (int)eh->e_shoff ||
425: read (fd, shtab, size) != size) {
426: printf("Seek to section headers failed.\n");
427: return -1;
428: }
429:
430: tablebase = roundup(tablebase, sizeof(u_int64_t));
431: symptr = (u_int64_t *)tablebase;
432: tablebase = roundup(tablebase, 4096);
433: keh = (Elf64_Ehdr *)tablebase;
434: tablebase += sizeof(Elf64_Ehdr);
435: tablebase = roundup(tablebase, sizeof(u_int64_t));
436: ksh = (Elf64_Shdr *)tablebase;
437: tablebase += roundup((sizeof(Elf64_Shdr) * eh->e_shnum), sizeof(u_int64_t));
438: memcpy(ksh, shtab, roundup((sizeof(Elf64_Shdr) * eh->e_shnum),
439: sizeof(u_int64_t)));
440: sh = ksh;
441:
442: shstrh = &sh[eh->e_shstrndx];
443:
444: for (i = 0; i < eh->e_shnum; sh++, i++) {
445: if (sh->sh_type == SHT_SYMTAB) {
446: break;
447: }
448: }
449: if (i >= eh->e_shnum) {
450: printf("No symbol table found!\n");
451: return -1;
452: }
453:
454: strh = &ksh[sh->sh_link];
455: nsym = sh->sh_size / sh->sh_entsize;
456: offs = sh->sh_offset;
457: size = sh->sh_size;
458:
459: /*
460: * Allocate tables in correct order so the kernel groks it.
461: * Then we read them in the order they are in the ELF file.
462: */
463: shstrtab = gettable(shstrh->sh_size, "shstrtab", flags, sizeof(u_int64_t));
464: strtab = gettable(strh->sh_size, "strtab", flags, sizeof(u_int64_t));
465: symtab = gettable(size, "symtab", flags, sizeof(u_int64_t));
466: symend = (char *)symtab + size;
467:
468: do {
469: if(shstrh->sh_offset < offs && shstrh->sh_offset < strh->sh_offset) {
470: #if 0
471: /*
472: * We would like to read the shstrtab from the file
473: * but since this table is located in front of the shtab
474: * it is already gone. We can't position backwards
475: * outside the current segment when using tftp.
476: * Instead we create the names we need in the string
477: * table because it can be reconstructed from the
478: * info we now have access to.
479: */
480: if (!readtable (shstrh->sh_offset, (void *)shstrtab,
481: shstrh->sh_size, "shstring", flags))
482: return(0);
483: #else
484: memset(shstrtab, 0, shstrh->sh_size);
485: strncpy(shstrtab + shstrh->sh_name, ".shstrtab", 10);
486: strncpy(shstrtab + strh->sh_name, ".strtab", 10);
487: strncpy(shstrtab + sh->sh_name, ".symtab", 10);
488: #endif
489: shstrh->sh_offset = 0x7fffffff;
490: }
491:
492: if (offs < strh->sh_offset && offs < shstrh->sh_offset) {
493: if (!(readtable(fd, offs, (void *)symtab,
494: size, "sym", flags)))
495: return (0);
496: offs = 0x7fffffff;
497: }
498:
499: if (strh->sh_offset < offs && strh->sh_offset < shstrh->sh_offset) {
500: if (!(readtable (fd, strh->sh_offset, (void *)strtab,
501: strh->sh_size, "string", flags))) {
502: return (0);
503: }
504: strh->sh_offset = 0x7fffffff;
505: }
506: if (offs == 0x7fffffff && strh->sh_offset == 0x7fffffff &&
507: shstrh->sh_offset == 0x7fffffff)
508: break;
509: } while(1);
510:
511: /*
512: * Update the kernel headers with the current info.
513: */
514: shstrh->sh_offset = (Elf64_Off)(long)shstrtab - (Elf64_Off)(long)keh;
515: strh->sh_offset = (Elf64_Off)(long)strtab - (Elf64_Off)(long)keh;
516: sh->sh_offset = (Elf64_Off)(long)symtab - (Elf64_Off)(long)keh;
517: memcpy(keh, eh, sizeof(Elf64_Ehdr));
518: keh->e_phoff = 0;
519: keh->e_shoff = sizeof(Elf64_Ehdr);
520: keh->e_phentsize = 0;
521: keh->e_phnum = 0;
522:
523: symptr[0] = (Elf64_Off)keh;
524: symptr[1] = (Elf64_Off)roundup((Elf64_Off)symend, sizeof(u_int64_t));
525:
526: return(0);
527:
528: }
CVSweb