diff options
author | Joel Sing <jsing@cvs.openbsd.org> | 2008-05-20 18:12:20 +0000 |
---|---|---|
committer | Joel Sing <jsing@cvs.openbsd.org> | 2008-05-20 18:12:20 +0000 |
commit | 86480375cdfab01471990bda620c046c8138c33b (patch) | |
tree | faecf41e96a8e63bece9e770e840b7aeccec2cac | |
parent | f4370fd03064afd7649f12473e875aaa94a3db9c (diff) |
Change the OpenBSD/sgi boot loader so that we use libsa loadfile(), rather
than rolling our own load functions.
tested jasper@, feedback and ok miod@
-rw-r--r-- | sys/arch/sgi/include/loadfile_machdep.h | 16 | ||||
-rw-r--r-- | sys/arch/sgi/stand/boot/Makefile | 9 | ||||
-rw-r--r-- | sys/arch/sgi/stand/boot/boot.c | 430 |
3 files changed, 38 insertions, 417 deletions
diff --git a/sys/arch/sgi/include/loadfile_machdep.h b/sys/arch/sgi/include/loadfile_machdep.h index d0e5940445b..01cdd5713bb 100644 --- a/sys/arch/sgi/include/loadfile_machdep.h +++ b/sys/arch/sgi/include/loadfile_machdep.h @@ -1,4 +1,4 @@ -/* $OpenBSD: loadfile_machdep.h,v 1.1 2004/08/06 21:12:19 pefo Exp $ */ +/* $OpenBSD: loadfile_machdep.h,v 1.2 2008/05/20 18:12:19 jsing Exp $ */ /* $NetBSD: loadfile_machdep.h,v 1.2 2001/10/31 17:20:49 thorpej Exp $ */ /*- @@ -37,15 +37,11 @@ * POSSIBILITY OF SUCH DAMAGE. */ -#ifndef _SGIMIPS_LOADFILE_MACHDEP_H_ -#define _SGIMIPS_LOADFILE_MACHDEP_H_ +#define BOOT_ELF +#define ELFSIZE 64 -#define BOOT_AOUT -#define BOOT_ECOFF -#define BOOT_ELF32 - -#define LOAD_KERNEL (LOAD_ALL & ~LOAD_TEXTA) -#define COUNT_KERNEL (COUNT_ALL & ~COUNT_TEXTA) +#define LOAD_KERNEL (LOAD_ALL & ~LOAD_TEXTA) +#define COUNT_KERNEL (COUNT_ALL & ~COUNT_TEXTA) #define LOADADDR(a) (((u_long)(a)) + offset) #define ALIGNENTRY(a) ((u_long)(a)) @@ -59,5 +55,3 @@ #define ALLOC(a) alloc(a) #define FREE(a, b) free(a, b) #define OKMAGIC(a) ((a) == OMAGIC) - -#endif /* !_SGIMIPS_LOADFILE_MACHDEP_H_ */ diff --git a/sys/arch/sgi/stand/boot/Makefile b/sys/arch/sgi/stand/boot/Makefile index 784d1c10570..e7b281e12c1 100644 --- a/sys/arch/sgi/stand/boot/Makefile +++ b/sys/arch/sgi/stand/boot/Makefile @@ -1,5 +1,4 @@ -# $OpenBSD: Makefile,v 1.9 2007/11/30 14:02:00 jsing Exp $ - +# $OpenBSD: Makefile,v 1.10 2008/05/20 18:12:19 jsing Exp $ PROG= boot NOMAN= noman @@ -17,12 +16,15 @@ LDFLAGS+= ${SALDFLAGS} -T ${.CURDIR}/ld.script -e __start S= ${.CURDIR}/../../../.. SRCS= start.S boot.c filesystem.c conf.c diskio.c arcbios.c strstr.c -CLEANFILES+= machine mips64 +.PATH: ${S}/lib/libsa +SRCS+= loadfile.c .PATH: ${S}/lib/libkern/arch/mips64 ${S}/lib/libkern SRCS+= strlcpy.c memcpy.c strlen.c strrchr.c strlcat.c ashrdi3.c strncmp.c \ strcmp.S udivdi3.c umoddi3.c qdivrem.c +CLEANFILES+= machine mips64 + .if !make(libdep) && !make(sadep) && !make(salibdir) && !make(obj) .BEGIN: @([ -h machine ] || ln -s ${.CURDIR}/../../include machine) @@ -33,7 +35,6 @@ ${PROG}: $(OBJS) $(LDADD) $(LD) $(LDFLAGS) -o boot $(OBJS) -L${LIBSADIR} ${LIBSA} \ -L${LIBZDIR} ${LIBZ} - install: install -c -m 555 -g bin -o bin ${PROG} ${DESTDIR}/usr/mdec diff --git a/sys/arch/sgi/stand/boot/boot.c b/sys/arch/sgi/stand/boot/boot.c index 4c9045e2108..7cab9da553b 100644 --- a/sys/arch/sgi/stand/boot/boot.c +++ b/sys/arch/sgi/stand/boot/boot.c @@ -1,4 +1,4 @@ -/* $OpenBSD: boot.c,v 1.10 2008/03/28 02:50:02 jsing Exp $ */ +/* $OpenBSD: boot.c,v 1.11 2008/05/20 18:12:19 jsing Exp $ */ /* * Copyright (c) 2004 Opsycon AB, www.opsycon.se. @@ -33,18 +33,12 @@ #include <stand.h> #include <mips64/arcbios.h> +#include <mips64/cpu.h> -void gets(char *); -ssize_t read(int, void *, size_t); -int close(int); +#include "loadfile.h" int main(int, char **); void dobootopts(int, char **); -Elf32_Addr loadfile(char *); -Elf32_Addr loadfile32(int, Elf32_Ehdr *); -Elf32_Addr loadfile64(int, Elf64_Ehdr *); -int loadsymtab32(int, Elf32_Ehdr *, int); -int loadsymtab64(int, Elf64_Ehdr *, int); enum { AUTO_NONE, @@ -57,40 +51,17 @@ enum { char *OSLoadPartition = NULL; char *OSLoadFilename = NULL; -unsigned long tablebase; - -static void * -readtable(int fd, int offs, void *base, int size, char *name, int flags) -{ - if (lseek(fd, offs, SEEK_SET) != offs || - read(fd, base, size) != size) { - printf("\nCannot read %s table!", name); - return (0); - } - return ((void *) base); -} - -static void * -gettable(int size, char *name, int flags, size_t align) -{ - long base; - - /* Put table after loaded code to support kernel DDB. */ - tablebase = roundup(tablebase, align); - base = tablebase; - tablebase += size; - return ((void *) base); -} - /* - * OpenBSD/sgi boot loader. + * OpenBSD/sgi Boot Loader. */ int main(int argc, char *argv[]) { + u_long marks[MARK_MAX]; + u_int64_t *esym; char line[1024]; - int i; - Elf32_Addr entry; + u_long entry; + int fd, i; dobootopts(argc, argv); if (OSLoadPartition != NULL) { @@ -108,9 +79,26 @@ main(int argc, char *argv[]) printf("Boot: %s\n", line); - entry = loadfile(line); - if (entry != NULL) - ((void (*)())entry)(argc, argv); + /* + * Load the kernel and symbol table. + */ + + marks[MARK_START] = 0; + if ((fd = loadfile(line, marks, LOAD_KERNEL | COUNT_KERNEL)) != -1) { + (void)close(fd); + + entry = marks[MARK_ENTRY]; +#ifdef __LP64__ + esym = (u_int64_t *)marks[MARK_END]; +#else +#undef KSEG0_BASE +#define KSEG0_BASE 0xffffffff80000000ULL + esym = (u_int64_t *)PHYS_TO_KSEG0(marks[MARK_END]); +#endif + + if (entry != NULL) + ((void (*)())entry)(argc, argv, esym); + } /* We failed to load the kernel. */ printf("Boot FAILED!\n"); @@ -166,365 +154,3 @@ dobootopts(int argc, char **argv) } } } - -/* - * Open 'filename', read in program and return the entry point or -1 if error. - */ -Elf32_Addr -loadfile(register char *fname) -{ - union { - Elf32_Ehdr eh32; - Elf64_Ehdr eh64; - } eh; - int fd; - Elf32_Addr entry = NULL; - - if ((fd = open(fname, 0)) < 0) { - printf("Cannot open file %s!\n", fname); - return (NULL); - } - - /* Read the ELF header and check that it IS an ELF header. */ - if (read(fd, (char *)&eh, sizeof(eh)) != sizeof(eh)) { - printf("Error: ELF header read error.\n"); - return (NULL); - } - if (!IS_ELF(eh.eh32)) { - printf("Not an ELF file.\n"); - return (NULL); - } - - /* Determine CLASS. */ - if (eh.eh32.e_ident[EI_CLASS] == ELFCLASS32) - entry = loadfile32(fd, (void *)&eh); - else if (eh.eh32.e_ident[EI_CLASS] == ELFCLASS64) - entry = loadfile64(fd, (void *)&eh); - else - printf("Unknown ELF class.\n"); - - return (entry); -} - -Elf32_Addr -loadfile32(int fd, Elf32_Ehdr *eh) -{ - char buf[4096]; - Elf32_Phdr *ph; - int i; - - ph = (Elf32_Phdr *) buf; - lseek(fd, eh->e_phoff, 0); - if (read(fd, (char *)ph, 4096) != 4096) { - printf("Unexpected EOF!\n"); - return (NULL); - } - - tablebase = 0; - printf("Loading ELF32 file\n"); - - for (i = 0; i < eh->e_phnum; i++, ph++) { - if (ph->p_type == PT_LOAD) { - lseek(fd, ph->p_offset, 0); - printf("0x%x:0x%x, ",(long)ph->p_paddr, (long)ph->p_filesz); - if (read(fd, (char *)ph->p_paddr, - ph->p_filesz) != ph->p_filesz) { - printf("Unexpected EOF!\n"); - return (NULL); - } - if (ph->p_memsz > ph->p_filesz) { - printf("Zero 0x%x:0x%x, ", - (long)(ph->p_paddr + ph->p_filesz), - (long)(ph->p_memsz - ph->p_filesz)); - bzero((void *)(ph->p_paddr + ph->p_filesz), - ph->p_memsz - ph->p_filesz); - } - if ((ph->p_paddr + ph->p_memsz) > tablebase) - tablebase = ph->p_paddr + ph->p_memsz; - } - } - memset((void *)tablebase, 0, 4096); - loadsymtab32(fd, eh, 0); - printf("Start at 0x%x\n", eh->e_entry); - return(eh->e_entry); -} - -Elf32_Addr -loadfile64(int fd, Elf64_Ehdr *eh) -{ - char buf[4096]; - Elf64_Phdr *ph; - int i; - - ph = (Elf64_Phdr *) buf; - lseek(fd, eh->e_phoff, 0); - if (read(fd, (char *)ph, 4096) != 4096) { - printf("Unexpected EOF!\n"); - return (NULL); - } - - tablebase = 0; - printf("Loading ELF64 file\n"); - - for (i = 0; i < eh->e_phnum; i++, ph++) { - if (ph->p_type == PT_LOAD) { - lseek(fd, ph->p_offset, 0); - printf("0x%llx:0x%llx, ",ph->p_paddr, ph->p_filesz); - if (read(fd, (char *)(long)ph->p_paddr, - ph->p_filesz) != ph->p_filesz) { - printf("Unexpected EOF!\n"); - return (NULL); - } - if (ph->p_memsz > ph->p_filesz) { - printf("Zero 0x%llx:0x%llx, ", - ph->p_paddr + ph->p_filesz, - ph->p_memsz - ph->p_filesz); - bzero((void *)(long)(ph->p_paddr + ph->p_filesz), - ph->p_memsz - ph->p_filesz); - } - if ((ph->p_paddr + ph->p_memsz) > tablebase) - tablebase = ph->p_paddr + ph->p_memsz; - } - } - memset((void *)tablebase, 0, 4096); - loadsymtab64(fd, eh, 0); - printf("Start at 0x%llx\n", eh->e_entry); - return(eh->e_entry); -} - -int -loadsymtab32(int fd, Elf32_Ehdr *eh, int flags) -{ - Elf32_Ehdr *keh; - Elf32_Shdr *shtab; - Elf32_Shdr *sh, *ksh, *shstrh, *strh; - Elf32_Sym *symtab; - int *symptr; - char *shstrtab, *strtab, *symend; - int i, nsym, offs, size; - - printf("Loading symbol table\n"); - size = eh->e_shnum * sizeof(Elf32_Shdr); - shtab = (Elf32_Shdr *) alloc(size); - if (lseek (fd, eh->e_shoff, SEEK_SET) != eh->e_shoff || - read (fd, shtab, size) != size) { - printf("Seek to section headers failed.\n"); - return (-1); - } - - tablebase = roundup(tablebase, sizeof(long)); - symptr = (int *)tablebase; - tablebase = roundup(tablebase, 4096); - keh = (Elf32_Ehdr *)tablebase; - tablebase += sizeof(Elf32_Ehdr); - tablebase = roundup(tablebase, sizeof(long)); - ksh = (Elf32_Shdr *)tablebase; - tablebase += roundup((sizeof(Elf32_Shdr) * eh->e_shnum), sizeof(long)); - memcpy(ksh, shtab, roundup((sizeof(Elf32_Shdr) * eh->e_shnum), sizeof(long))); - sh = ksh; - - shstrh = &sh[eh->e_shstrndx]; - - for (i = 0; i < eh->e_shnum; sh++, i++) { - if (sh->sh_type == SHT_SYMTAB) - break; - } - if (i >= eh->e_shnum) { - printf("No symbol table found!\n"); - return (-1); - } - - strh = &ksh[sh->sh_link]; - nsym = sh->sh_size / sh->sh_entsize; - offs = sh->sh_offset; - size = sh->sh_size; - - /* - * Allocate tables in correct order so that the kernel groks it. - * Then we read them in the order they are in the ELF file. - */ - shstrtab = gettable(shstrh->sh_size, "shstrtab", flags, sizeof(long)); - strtab = gettable(strh->sh_size, "strtab", flags, sizeof(long)); - symtab = gettable(size, "symtab", flags, sizeof(long)); - symend = (char *)symtab + size; - - do { - if(shstrh->sh_offset < offs && shstrh->sh_offset < strh->sh_offset) { -#if 0 - /* - * We would like to read the shstrtab from the file - * but since this table is located in front of the shtab - * it is already gone. We can't position backwards - * outside the current segment when using tftp. - * Instead we create the names we need in the string - * table because it can be reconstructed from the info - * we now have access to. - */ - if (!readtable (shstrh->sh_offset, (void *)shstrtab, - shstrh->sh_size, "shstring", flags)) - return(0); -#else - memset(shstrtab, 0, shstrh->sh_size); - strncpy(shstrtab + shstrh->sh_name, ".shstrtab", 10); - strncpy(shstrtab + strh->sh_name, ".strtab", 10); - strncpy(shstrtab + sh->sh_name, ".symtab", 10); -#endif - shstrh->sh_offset = 0x7fffffff; - } - - if (offs < strh->sh_offset && offs < shstrh->sh_offset) { - if (!(readtable(fd, offs, (void *)symtab, size, - "sym", flags))) - return (0); - offs = 0x7fffffff; - } - - if (strh->sh_offset < offs && strh->sh_offset < shstrh->sh_offset) { - if (!(readtable (fd, strh->sh_offset, (void *)strtab, - strh->sh_size, "string", flags))) - return (0); - strh->sh_offset = 0x7fffffff; - } - if (offs == 0x7fffffff && strh->sh_offset == 0x7fffffff && - shstrh->sh_offset == 0x7fffffff) - break; - } while (1); - - /* - * Update the kernel headers with the current info. - */ - shstrh->sh_offset = (Elf32_Off)shstrtab - (Elf32_Off)keh; - strh->sh_offset = (Elf32_Off)strtab - (Elf32_Off)keh; - sh->sh_offset = (Elf32_Off)symtab - (Elf32_Off)keh; - memcpy(keh, eh, sizeof(Elf32_Ehdr)); - keh->e_phoff = 0; - keh->e_shoff = sizeof(Elf32_Ehdr); - keh->e_phentsize = 0; - keh->e_phnum = 0; - - symptr[0] = (int)keh; - symptr[1] = roundup((int)symend, sizeof(int)); - - return(0); -} - -int -loadsymtab64(int fd, Elf64_Ehdr *eh, int flags) -{ - Elf64_Ehdr *keh; - Elf64_Shdr *shtab; - Elf64_Shdr *sh, *ksh, *shstrh, *strh; - Elf64_Sym *symtab; - u_int64_t *symptr; - char *shstrtab, *strtab, *symend; - int i, nsym; - Elf64_Xword size; - Elf64_Off offs; - - printf("Loading symbol table\n"); - size = eh->e_shnum * sizeof(Elf64_Shdr); - shtab = (Elf64_Shdr *) alloc(size); - if (lseek (fd, (int)eh->e_shoff, SEEK_SET) != (int)eh->e_shoff || - read (fd, shtab, size) != size) { - printf("Seek to section headers failed.\n"); - return (-1); - } - - tablebase = roundup(tablebase, sizeof(u_int64_t)); - symptr = (u_int64_t *)tablebase; - tablebase = roundup(tablebase, 4096); - keh = (Elf64_Ehdr *)tablebase; - tablebase += sizeof(Elf64_Ehdr); - tablebase = roundup(tablebase, sizeof(u_int64_t)); - ksh = (Elf64_Shdr *)tablebase; - tablebase += roundup((sizeof(Elf64_Shdr) * eh->e_shnum), sizeof(u_int64_t)); - memcpy(ksh, shtab, roundup((sizeof(Elf64_Shdr) * eh->e_shnum), - sizeof(u_int64_t))); - sh = ksh; - - shstrh = &sh[eh->e_shstrndx]; - - for (i = 0; i < eh->e_shnum; sh++, i++) { - if (sh->sh_type == SHT_SYMTAB) { - break; - } - } - if (i >= eh->e_shnum) { - printf("No symbol table found!\n"); - return (-1); - } - - strh = &ksh[sh->sh_link]; - nsym = sh->sh_size / sh->sh_entsize; - offs = sh->sh_offset; - size = sh->sh_size; - - /* - * Allocate tables in correct order so that the kernel groks it. - * Then we read them in the order they are in the ELF file. - */ - shstrtab = gettable(shstrh->sh_size, "shstrtab", flags, sizeof(u_int64_t)); - strtab = gettable(strh->sh_size, "strtab", flags, sizeof(u_int64_t)); - symtab = gettable(size, "symtab", flags, sizeof(u_int64_t)); - symend = (char *)symtab + size; - - do { - if(shstrh->sh_offset < offs && shstrh->sh_offset < strh->sh_offset) { -#if 0 - /* - * We would like to read the shstrtab from the file - * but since this table is located in front of the shtab - * it is already gone. We can't position backwards - * outside the current segment when using tftp. - * Instead we create the names we need in the string - * table because it can be reconstructed from the - * info we now have access to. - */ - if (!readtable (shstrh->sh_offset, (void *)shstrtab, - shstrh->sh_size, "shstring", flags)) - return (0); -#else - memset(shstrtab, 0, shstrh->sh_size); - strncpy(shstrtab + shstrh->sh_name, ".shstrtab", 10); - strncpy(shstrtab + strh->sh_name, ".strtab", 10); - strncpy(shstrtab + sh->sh_name, ".symtab", 10); -#endif - shstrh->sh_offset = 0x7fffffff; - } - - if (offs < strh->sh_offset && offs < shstrh->sh_offset) { - if (!(readtable(fd, offs, (void *)symtab, - size, "sym", flags))) - return (0); - offs = 0x7fffffff; - } - - if (strh->sh_offset < offs && strh->sh_offset < shstrh->sh_offset) { - if (!(readtable (fd, strh->sh_offset, (void *)strtab, - strh->sh_size, "string", flags))) { - return (0); - } - strh->sh_offset = 0x7fffffff; - } - if (offs == 0x7fffffff && strh->sh_offset == 0x7fffffff && - shstrh->sh_offset == 0x7fffffff) - break; - } while (1); - - /* - * Update the kernel headers with the current info. - */ - shstrh->sh_offset = (Elf64_Off)(long)shstrtab - (Elf64_Off)(long)keh; - strh->sh_offset = (Elf64_Off)(long)strtab - (Elf64_Off)(long)keh; - sh->sh_offset = (Elf64_Off)(long)symtab - (Elf64_Off)(long)keh; - memcpy(keh, eh, sizeof(Elf64_Ehdr)); - keh->e_phoff = 0; - keh->e_shoff = sizeof(Elf64_Ehdr); - keh->e_phentsize = 0; - keh->e_phnum = 0; - - symptr[0] = (Elf64_Off)keh; - symptr[1] = (Elf64_Off)roundup((Elf64_Off)symend, sizeof(u_int64_t)); - - return (0); -} |