1176348Smarcel/*-
2176348Smarcel * Copyright (c) 2001 Benno Rice <benno@FreeBSD.org>
3176348Smarcel * Copyright (c) 2007 Semihalf, Rafal Jaworowski <raj@semihalf.com>
4176348Smarcel * All rights reserved.
5176348Smarcel *
6176348Smarcel * Redistribution and use in source and binary forms, with or without
7176348Smarcel * modification, are permitted provided that the following conditions
8176348Smarcel * are met:
9176348Smarcel * 1. Redistributions of source code must retain the above copyright
10176348Smarcel *    notice, this list of conditions and the following disclaimer.
11176348Smarcel * 2. Redistributions in binary form must reproduce the above copyright
12176348Smarcel *    notice, this list of conditions and the following disclaimer in the
13176348Smarcel *    documentation and/or other materials provided with the distribution.
14176348Smarcel *
15176348Smarcel * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16176348Smarcel * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17176348Smarcel * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18176348Smarcel * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19176348Smarcel * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20176348Smarcel * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21176348Smarcel * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22176348Smarcel * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23176348Smarcel * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24176348Smarcel * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25176348Smarcel * SUCH DAMAGE.
26176348Smarcel */
27176348Smarcel
28176348Smarcel#include <sys/cdefs.h>
29176348Smarcel__FBSDID("$FreeBSD$");
30176348Smarcel
31176348Smarcel#include <sys/param.h>
32176348Smarcel#include <sys/linker.h>
33176348Smarcel
34182723Sraj#include <machine/md_var.h>
35176348Smarcel#include <machine/metadata.h>
36176348Smarcel#include <machine/elf.h>
37176348Smarcel
38176348Smarcel#include <stand.h>
39176348Smarcel
40176348Smarcel#include "bootstrap.h"
41235694Skientzle#include "libuboot.h"
42176348Smarcel
43182723Srajextern vm_offset_t md_load(char *, vm_offset_t *);
44182723Sraj
45176348Smarcelint
46176348Smarcel__elfN(uboot_load)(char *filename, u_int64_t dest,
47176348Smarcel    struct preloaded_file **result)
48176348Smarcel{
49182723Sraj	int r;
50176348Smarcel
51176348Smarcel	r = __elfN(loadfile)(filename, dest, result);
52176348Smarcel	if (r != 0)
53176348Smarcel		return (r);
54176348Smarcel
55176348Smarcel#if defined(__powerpc__)
56176348Smarcel	/*
57176348Smarcel	 * No need to sync the icache for modules: this will
58176348Smarcel	 * be done by the kernel after relocation.
59176348Smarcel	 */
60176348Smarcel	if (!strcmp((*result)->f_type, "elf kernel"))
61176348Smarcel		__syncicache((void *) (*result)->f_addr, (*result)->f_size);
62176348Smarcel#endif
63176348Smarcel	return (0);
64176348Smarcel}
65176348Smarcel
66176348Smarcelint
67176348Smarcel__elfN(uboot_exec)(struct preloaded_file *fp)
68176348Smarcel{
69182723Sraj	struct file_metadata *fmp;
70182723Sraj	vm_offset_t mdp;
71182723Sraj	Elf_Ehdr *e;
72182723Sraj	int error;
73235694Skientzle	void (*entry)(void *);
74176348Smarcel
75182723Sraj	if ((fmp = file_findmetadata(fp, MODINFOMD_ELFHDR)) == NULL)
76176348Smarcel		return (EFTYPE);
77182723Sraj
78176348Smarcel	e = (Elf_Ehdr *)&fmp->md_data;
79176348Smarcel
80176348Smarcel	if ((error = md_load(fp->f_args, &mdp)) != 0)
81176348Smarcel		return (error);
82176348Smarcel
83235694Skientzle	entry = uboot_vm_translate(e->e_entry);
84235694Skientzle	printf("Kernel entry at 0x%x...\n", (unsigned)entry);
85176348Smarcel
86176348Smarcel	dev_cleanup();
87247200Skientzle	printf("Kernel args: %s\n", fp->f_args);
88176348Smarcel
89235694Skientzle	(*entry)((void *)mdp);
90176348Smarcel	panic("exec returned");
91176348Smarcel}
92176348Smarcel
93177152Sobrienstruct file_format uboot_elf = {
94176348Smarcel	__elfN(uboot_load),
95176348Smarcel	__elfN(uboot_exec)
96176348Smarcel};
97