xref: /freebsd/stand/uboot/arch/powerpc/ppc64_elf_freebsd.c (revision 86077f4fd11070518a6d04eee7fdb93cbbfb1b52)
19dc70af8SWarner Losh /*-
29dc70af8SWarner Losh  * Copyright (c) 2001 Benno Rice <benno@FreeBSD.org>
39dc70af8SWarner Losh  * All rights reserved.
49dc70af8SWarner Losh  *
59dc70af8SWarner Losh  * Redistribution and use in source and binary forms, with or without
69dc70af8SWarner Losh  * modification, are permitted provided that the following conditions
79dc70af8SWarner Losh  * are met:
89dc70af8SWarner Losh  * 1. Redistributions of source code must retain the above copyright
99dc70af8SWarner Losh  *    notice, this list of conditions and the following disclaimer.
109dc70af8SWarner Losh  * 2. Redistributions in binary form must reproduce the above copyright
119dc70af8SWarner Losh  *    notice, this list of conditions and the following disclaimer in the
129dc70af8SWarner Losh  *    documentation and/or other materials provided with the distribution.
139dc70af8SWarner Losh  *
149dc70af8SWarner Losh  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
159dc70af8SWarner Losh  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
169dc70af8SWarner Losh  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
179dc70af8SWarner Losh  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
189dc70af8SWarner Losh  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
199dc70af8SWarner Losh  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
209dc70af8SWarner Losh  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
219dc70af8SWarner Losh  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
229dc70af8SWarner Losh  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
239dc70af8SWarner Losh  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
249dc70af8SWarner Losh  * SUCH DAMAGE.
259dc70af8SWarner Losh  */
269dc70af8SWarner Losh 
279dc70af8SWarner Losh #define __ELF_WORD_SIZE 64
289dc70af8SWarner Losh 
299dc70af8SWarner Losh #include <sys/param.h>
309dc70af8SWarner Losh #include <sys/linker.h>
319dc70af8SWarner Losh 
329dc70af8SWarner Losh #include <machine/metadata.h>
339dc70af8SWarner Losh #include <machine/elf.h>
349dc70af8SWarner Losh #include <machine/md_var.h>
359dc70af8SWarner Losh 
369dc70af8SWarner Losh #include <stand.h>
379dc70af8SWarner Losh 
389dc70af8SWarner Losh #include "bootstrap.h"
399dc70af8SWarner Losh #include "libuboot.h"
40335615c4SWarner Losh #include "modinfo.h"
419dc70af8SWarner Losh 
429dc70af8SWarner Losh int
ppc64_uboot_elf_loadfile(char * filename,uint64_t dest,struct preloaded_file ** result)439dc70af8SWarner Losh ppc64_uboot_elf_loadfile(char *filename, uint64_t dest,
449dc70af8SWarner Losh     struct preloaded_file **result)
459dc70af8SWarner Losh {
469dc70af8SWarner Losh 	int	r;
479dc70af8SWarner Losh 
489dc70af8SWarner Losh 	r = __elfN(loadfile)(filename, dest, result);
499dc70af8SWarner Losh 	if (r != 0)
509dc70af8SWarner Losh 		return (r);
519dc70af8SWarner Losh 
529dc70af8SWarner Losh 	/*
539dc70af8SWarner Losh 	 * No need to sync the icache for modules: this will
549dc70af8SWarner Losh 	 * be done by the kernel after relocation.
559dc70af8SWarner Losh 	 */
56*86077f4fSAhmad Khalifa 	if (!strcmp((*result)->f_type, md_kerntype))
579dc70af8SWarner Losh 		__syncicache((void *) (*result)->f_addr, (*result)->f_size);
589dc70af8SWarner Losh 	return (0);
599dc70af8SWarner Losh }
609dc70af8SWarner Losh 
619dc70af8SWarner Losh int
ppc64_uboot_elf_exec(struct preloaded_file * fp)629dc70af8SWarner Losh ppc64_uboot_elf_exec(struct preloaded_file *fp)
639dc70af8SWarner Losh {
649dc70af8SWarner Losh 	struct file_metadata	*fmp;
659dc70af8SWarner Losh 	vm_offset_t		mdp, dtbp;
669dc70af8SWarner Losh 	Elf_Ehdr		*e;
679dc70af8SWarner Losh 	int			error;
689dc70af8SWarner Losh 	void			(*entry)(void *);
699dc70af8SWarner Losh 
709dc70af8SWarner Losh 	if ((fmp = file_findmetadata(fp, MODINFOMD_ELFHDR)) == NULL) {
719dc70af8SWarner Losh 		return(EFTYPE);
729dc70af8SWarner Losh 	}
739dc70af8SWarner Losh 	e = (Elf_Ehdr *)&fmp->md_data;
749dc70af8SWarner Losh 
759dc70af8SWarner Losh 	/* Handle function descriptor for ELFv1 kernels */
769dc70af8SWarner Losh 	if ((e->e_flags & 3) == 2)
779dc70af8SWarner Losh 		entry = (void (*)(void*))(intptr_t)e->e_entry;
789dc70af8SWarner Losh 	else
799dc70af8SWarner Losh 		entry = *(void (*)(void*))(uint64_t *)(intptr_t)e->e_entry;
809dc70af8SWarner Losh 
819dc70af8SWarner Losh 	if ((error = md_load64(fp->f_args, &mdp, &dtbp)) != 0)
829dc70af8SWarner Losh 		return (error);
839dc70af8SWarner Losh 
849dc70af8SWarner Losh 	dev_cleanup();
859dc70af8SWarner Losh 	printf("Kernel args: %s\n", fp->f_args);
869dc70af8SWarner Losh 
879dc70af8SWarner Losh 	(*entry)((void *)mdp);
889dc70af8SWarner Losh 	panic("exec returned");
899dc70af8SWarner Losh }
909dc70af8SWarner Losh 
919dc70af8SWarner Losh struct file_format	uboot_elf64 =
929dc70af8SWarner Losh {
939dc70af8SWarner Losh 	ppc64_uboot_elf_loadfile,
949dc70af8SWarner Losh 	ppc64_uboot_elf_exec
959dc70af8SWarner Losh };
96