diff options
author | Jayachandran C. <jchandra@FreeBSD.org> | 2011-07-16 17:22:01 +0000 |
---|---|---|
committer | Jayachandran C. <jchandra@FreeBSD.org> | 2011-07-16 17:22:01 +0000 |
commit | 578828c8d200a4610f18d4fcf00753175853eaa4 (patch) | |
tree | 0401aa1dab1f3e6c850f6b4852214727f7591e40 /sys | |
parent | 53b93f2f8acc25df7960a70b27ecb5aae33de31d (diff) | |
download | src-578828c8d200a4610f18d4fcf00753175853eaa4.tar.gz src-578828c8d200a4610f18d4fcf00753175853eaa4.zip |
Support compiling MIPS elf trampoline with a different ABI.
Allow changing the trampoline ABI with makeoptions, this will allow
us to have a trampoline with a different ABI from the kernel.
Useful in cases where we have to boot a 64 bit kernel from a
bootloader which supports only 32 bit or vice versa.
Approved by: bz(re), jmallett, imp
Notes
Notes:
svn path=/head/; revision=224105
Diffstat (limited to 'sys')
-rw-r--r-- | sys/conf/Makefile.mips | 21 | ||||
-rw-r--r-- | sys/mips/mips/elf_trampoline.c | 47 |
2 files changed, 45 insertions, 23 deletions
diff --git a/sys/conf/Makefile.mips b/sys/conf/Makefile.mips index 55d57e62b192..ab2b40ac8c76 100644 --- a/sys/conf/Makefile.mips +++ b/sys/conf/Makefile.mips @@ -50,7 +50,13 @@ HACK_EXTRA_FLAGS=-shared # is extremely poor, as well as -mno-abicalls to force no ABI usage. CFLAGS+=${EXTRA_FLAGS} $(ARCH_FLAGS) HACK_EXTRA_FLAGS+=${EXTRA_FLAGS} $(ARCH_FLAGS) -TRAMP_EXTRA_FLAGS=${EXTRA_FLAGS} $(ARCH_FLAGS) +TRAMP_ARCH_FLAGS?=$(ARCH_FLAGS) +TRAMP_EXTRA_FLAGS=${EXTRA_FLAGS} ${TRAMP_ARCH_FLAGS} +.if ${MACHINE_ARCH:Mmips64*} != "" +TRAMP_ELFSIZE=64 +.else +TRAMP_ELFSIZE=32 +.endif # XXX hardcoded kernel entry point ASM_CFLAGS+=${CFLAGS} -D_LOCORE -DLOCORE @@ -64,11 +70,12 @@ ${KERNEL_KO}.tramp.bin: ${KERNEL_KO} $S/$M/$M/elf_trampoline.c \ sed -e s/${KERNLOADADDR}/${TRAMPLOADADDR}/ -e s/" + SIZEOF_HEADERS"// \ ${LDSCRIPT_NAME} > ${LDSCRIPT_NAME}.tramp.noheader ${CC} -O -nostdlib -I. -I$S ${TRAMP_EXTRA_FLAGS} ${TRAMP_LDFLAGS} -Xlinker \ - -T -Xlinker ${LDSCRIPT_NAME}.tramp.noheader \ - -DKERNNAME="\"${KERNEL_KO}.tmp\"" $S/$M/$M/elf_trampoline.c \ - $S/$M/$M/inckern.S -o ${KERNEL_KO}.tramp.noheader - ${OBJCOPY} -S -O binary ${KERNEL_KO}.tramp.noheader \ - ${KERNEL_KO}.tramp.bin \ + -T -Xlinker ${LDSCRIPT_NAME}.tramp.noheader \ + -DKERNNAME="\"${KERNEL_KO}.tmp\"" -DELFSIZE=${TRAMP_ELFSIZE} \ + $S/$M/$M/elf_trampoline.c $S/$M/$M/inckern.S \ + -o ${KERNEL_KO}.tramp.elf + ${OBJCOPY} -S -O binary ${KERNEL_KO}.tramp.elf \ + ${KERNEL_KO}.tramp.bin %BEFORE_DEPEND @@ -83,7 +90,7 @@ ${KERNEL_KO}.tramp.bin: ${KERNEL_KO} $S/$M/$M/elf_trampoline.c \ %CLEAN CLEAN+= ${LDSCRIPT_NAME} ${LDSCRIPT_NAME}.tramp.noheader \ - ${KERNEL_KO}.tramp.noheader ${KERNEL_KO}.tramp.bin + ${KERNEL_KO}.tramp.elf ${KERNEL_KO}.tramp.bin ${LDSCRIPT_NAME}: $S/conf/${LDSCRIPT_NAME} sed s/KERNLOADADDR/${KERNLOADADDR}/g $S/conf/${LDSCRIPT_NAME} \ diff --git a/sys/mips/mips/elf_trampoline.c b/sys/mips/mips/elf_trampoline.c index 70aedebc167b..7d8324a733bf 100644 --- a/sys/mips/mips/elf_trampoline.c +++ b/sys/mips/mips/elf_trampoline.c @@ -27,7 +27,7 @@ __FBSDID("$FreeBSD$"); #include <machine/asm.h> #include <sys/param.h> -#ifdef __mips_n64 +#if ELFSIZE == 64 #include <sys/elf64.h> #else #include <sys/elf32.h> @@ -90,13 +90,19 @@ bzero(void *addr, size_t count) } /* + * Convert number to pointer, truncate on 64->32 case, sign extend + * in 32->64 case + */ +#define mkptr(x) ((void *)(intptr_t)(int)(x)) + +/* * Relocate PT_LOAD segements of kernel ELF image to their respective * virtual addresses and return entry point */ void * load_kernel(void * kstart) { -#ifdef __mips_n64 +#if ELFSIZE == 64 Elf64_Ehdr *eh; Elf64_Phdr phdr[64] /* XXX */; Elf64_Shdr shdr[64] /* XXX */; @@ -107,17 +113,19 @@ load_kernel(void * kstart) #endif int i, j; void *entry_point; - vm_offset_t lastaddr = 0; + vm_offset_t loadend = 0; + intptr_t lastaddr; int symtabindex = -1; int symstrindex = -1; + Elf_Size tmp; -#ifdef __mips_n64 +#if ELFSIZE == 64 eh = (Elf64_Ehdr *)kstart; #else eh = (Elf32_Ehdr *)kstart; #endif - entry_point = (void*)eh->e_entry; - memcpy(phdr, (void *)(kstart + eh->e_phoff ), + entry_point = mkptr(eh->e_entry); + memcpy(phdr, (void *)(kstart + eh->e_phoff), eh->e_phnum * sizeof(phdr[0])); memcpy(shdr, (void *)(kstart + eh->e_shoff), @@ -147,27 +155,31 @@ load_kernel(void * kstart) if (phdr[i].p_type != PT_LOAD) continue; - memcpy((void *)(phdr[i].p_vaddr), + memcpy(mkptr(phdr[i].p_vaddr), (void*)(kstart + phdr[i].p_offset), phdr[i].p_filesz); /* Clean space from oversized segments, eg: bss. */ if (phdr[i].p_filesz < phdr[i].p_memsz) - bzero((void *)(phdr[i].p_vaddr + phdr[i].p_filesz), + bzero(mkptr(phdr[i].p_vaddr + phdr[i].p_filesz), phdr[i].p_memsz - phdr[i].p_filesz); - if (lastaddr < phdr[i].p_vaddr + phdr[i].p_memsz) - lastaddr = phdr[i].p_vaddr + phdr[i].p_memsz; + if (loadend < phdr[i].p_vaddr + phdr[i].p_memsz) + loadend = phdr[i].p_vaddr + phdr[i].p_memsz; } /* Now grab the symbol tables. */ + lastaddr = (intptr_t)(int)loadend; if (symtabindex >= 0 && symstrindex >= 0) { - *(Elf_Size *)lastaddr = SYMTAB_MAGIC; + tmp = SYMTAB_MAGIC; + memcpy((void *)lastaddr, &tmp, sizeof(tmp)); lastaddr += sizeof(Elf_Size); - *(Elf_Size *)lastaddr = shdr[symtabindex].sh_size + + tmp = shdr[symtabindex].sh_size + shdr[symstrindex].sh_size + 2*sizeof(Elf_Size); + memcpy((void *)lastaddr, &tmp, sizeof(tmp)); lastaddr += sizeof(Elf_Size); /* .symtab size */ - *(Elf_Size *)lastaddr = shdr[symtabindex].sh_size; + tmp = shdr[symtabindex].sh_size; + memcpy((void *)lastaddr, &tmp, sizeof(tmp)); lastaddr += sizeof(shdr[symtabindex].sh_size); /* .symtab data */ memcpy((void*)lastaddr, @@ -176,16 +188,19 @@ load_kernel(void * kstart) lastaddr += shdr[symtabindex].sh_size; /* .strtab size */ - *(Elf_Size *)lastaddr = shdr[symstrindex].sh_size; + tmp = shdr[symstrindex].sh_size; + memcpy((void *)lastaddr, &tmp, sizeof(tmp)); lastaddr += sizeof(shdr[symstrindex].sh_size); /* .strtab data */ memcpy((void*)lastaddr, shdr[symstrindex].sh_offset + kstart, shdr[symstrindex].sh_size); - } else + } else { /* Do not take any chances */ - *(Elf_Size *)lastaddr = 0; + tmp = 0; + memcpy((void *)lastaddr, &tmp, sizeof(tmp)); + } return entry_point; } |