diff options
-rw-r--r-- | sys/boot/powerpc/kboot/conf.c | 4 | ||||
-rw-r--r-- | sys/boot/powerpc/kboot/kerneltramp.S | 2 | ||||
-rw-r--r-- | sys/boot/powerpc/kboot/main.c | 18 | ||||
-rw-r--r-- | sys/boot/powerpc/kboot/ppc64_elf_freebsd.c | 15 |
4 files changed, 29 insertions, 10 deletions
diff --git a/sys/boot/powerpc/kboot/conf.c b/sys/boot/powerpc/kboot/conf.c index 5338ced..104dd93 100644 --- a/sys/boot/powerpc/kboot/conf.c +++ b/sys/boot/powerpc/kboot/conf.c @@ -115,7 +115,3 @@ struct console *consoles[] = { NULL }; -/* - * reloc - our load address - */ -vm_offset_t reloc = RELOC; diff --git a/sys/boot/powerpc/kboot/kerneltramp.S b/sys/boot/powerpc/kboot/kerneltramp.S index 58b10b0..a394c95 100644 --- a/sys/boot/powerpc/kboot/kerneltramp.S +++ b/sys/boot/powerpc/kboot/kerneltramp.S @@ -9,6 +9,7 @@ * to the absolute address 0x60. Here we implement a loop waiting on the release * of a lock by the kernel at 0x40. * + * $FreeBSD$ */ #include <machine/asm.h> @@ -39,7 +40,6 @@ CNAME(kerneltramp): mflr %r8 mtlr %r9 lwz %r3,0(%r8) - ld %r3,0(%r3) /* Resolve function descriptor */ mtctr %r3 lwz %r3,4(%r8) lwz %r4,8(%r8) diff --git a/sys/boot/powerpc/kboot/main.c b/sys/boot/powerpc/kboot/main.c index 2189833..ec5ba6b 100644 --- a/sys/boot/powerpc/kboot/main.c +++ b/sys/boot/powerpc/kboot/main.c @@ -48,6 +48,7 @@ ssize_t kboot_copyin(const void *src, vm_offset_t dest, const size_t len); ssize_t kboot_copyout(vm_offset_t src, void *dest, const size_t len); ssize_t kboot_readin(const int fd, vm_offset_t dest, const size_t len); int kboot_autoload(void); +uint64_t kboot_loadaddr(u_int type, void *data, uint64_t addr); int kboot_setcurrdev(struct env_var *ev, int flags, const void *value); extern int command_fdt_internal(int argc, char *argv[]); @@ -116,6 +117,7 @@ main(int argc, const char **argv) archsw.arch_copyout = kboot_copyout; archsw.arch_readin = kboot_readin; archsw.arch_autoload = kboot_autoload; + archsw.arch_loadaddr = kboot_loadaddr; printf("\n"); printf("%s, Revision %s\n", bootprog_name, bootprog_rev); @@ -282,6 +284,22 @@ kboot_autoload(void) return (0); } +uint64_t +kboot_loadaddr(u_int type, void *data, uint64_t addr) +{ + /* + * Need to stay out of the way of Linux. /chosen/linux,kernel-end does + * a better job here, but use a fixed offset for now. + */ + + if (type == LOAD_ELF) + addr = roundup(addr, PAGE_SIZE); + else + addr += 64*1024*1024; /* Stay out of the way of Linux */ + + return (addr); +} + void _start(int argc, const char **argv, char **env) { diff --git a/sys/boot/powerpc/kboot/ppc64_elf_freebsd.c b/sys/boot/powerpc/kboot/ppc64_elf_freebsd.c index 2cb8017..3ee5e78 100644 --- a/sys/boot/powerpc/kboot/ppc64_elf_freebsd.c +++ b/sys/boot/powerpc/kboot/ppc64_elf_freebsd.c @@ -41,7 +41,6 @@ __FBSDID("$FreeBSD$"); #include "host_syscall.h" extern char end[]; -extern vm_offset_t reloc; /* From <arch>/conf.c */ extern void *kerneltramp; extern size_t szkerneltramp; extern int nkexec_segments; @@ -68,17 +67,22 @@ ppc64_elf_exec(struct preloaded_file *fp) Elf_Ehdr *e; int error; uint32_t *trampoline; - vm_offset_t trampolinebase = 96*1024*1024; /* XXX */ + uint64_t entry; + vm_offset_t trampolinebase; if ((fmp = file_findmetadata(fp, MODINFOMD_ELFHDR)) == NULL) { return(EFTYPE); } e = (Elf_Ehdr *)&fmp->md_data; + + /* Figure out where to put it */ + trampolinebase = archsw.arch_loadaddr(LOAD_RAW, NULL, 0); - /* Handle function descriptor */ + /* Set up interesting values in function descriptor */ trampoline = malloc(szkerneltramp); memcpy(trampoline, &kerneltramp, szkerneltramp); - trampoline[2] = e->e_entry; + archsw.arch_copyout(e->e_entry + elf64_relocation_offset, &entry, 8); + trampoline[2] = entry + elf64_relocation_offset; trampoline[4] = 0; /* Phys. mem offset */ trampoline[5] = 0; /* OF entry point */ @@ -88,7 +92,8 @@ ppc64_elf_exec(struct preloaded_file *fp) trampoline[3] = dtb; trampoline[6] = mdp; trampoline[7] = sizeof(mdp); - printf("Kernel entry at %#jx ...\n", e->e_entry); + printf("Kernel entry at %#jx (%#x) ...\n", e->e_entry, trampoline[2]); + printf("DTB at %#x, mdp at %#x\n", dtb, mdp); dev_cleanup(); |