mirror of
https://github.com/opnsense/src.git
synced 2026-06-14 19:20:18 -04:00
Add kexec-based Linux shim loader for use with the firmware petitboot
loader on PS3 and POWER8 systems. This is reasonably portable to other architectures, especially FDT-based ones, if similar features are useful elsewhere. Netboot support is missing for now and will be added in a future commit, at which time loader.ps3 will be garbage collected. Done at: Hackathon
This commit is contained in:
parent
855c46100d
commit
a4f7863238
15 changed files with 1694 additions and 1 deletions
|
|
@ -1,5 +1,5 @@
|
|||
# $FreeBSD$
|
||||
|
||||
SUBDIR= boot1.chrp ofw ps3 uboot
|
||||
SUBDIR= boot1.chrp kboot ofw ps3 uboot
|
||||
|
||||
.include <bsd.subdir.mk>
|
||||
|
|
|
|||
131
sys/boot/powerpc/kboot/Makefile
Normal file
131
sys/boot/powerpc/kboot/Makefile
Normal file
|
|
@ -0,0 +1,131 @@
|
|||
# $FreeBSD$
|
||||
|
||||
.include <src.opts.mk>
|
||||
MK_SSP= no
|
||||
|
||||
PROG= loader.kboot
|
||||
NEWVERSWHAT= "kboot loader" ${MACHINE_ARCH}
|
||||
BINDIR?= /boot
|
||||
INSTALLFLAGS= -b
|
||||
|
||||
# Architecture-specific loader code
|
||||
SRCS= conf.c metadata.c vers.c main.c ppc64_elf_freebsd.c
|
||||
SRCS+= host_syscall.S hostcons.c hostdisk.c kerneltramp.S kbootfdt.c
|
||||
SRCS+= ucmpdi2.c
|
||||
|
||||
LOADER_DISK_SUPPORT?= yes
|
||||
LOADER_UFS_SUPPORT?= yes
|
||||
LOADER_CD9660_SUPPORT?= yes
|
||||
LOADER_EXT2FS_SUPPORT?= yes
|
||||
LOADER_NET_SUPPORT?= yes
|
||||
LOADER_NFS_SUPPORT?= yes
|
||||
LOADER_TFTP_SUPPORT?= no
|
||||
LOADER_GZIP_SUPPORT?= yes
|
||||
LOADER_FDT_SUPPORT= yes
|
||||
LOADER_BZIP2_SUPPORT?= no
|
||||
|
||||
.if ${LOADER_DISK_SUPPORT} == "yes"
|
||||
CFLAGS+= -DLOADER_DISK_SUPPORT
|
||||
.endif
|
||||
.if ${LOADER_UFS_SUPPORT} == "yes"
|
||||
CFLAGS+= -DLOADER_UFS_SUPPORT
|
||||
.endif
|
||||
.if ${LOADER_CD9660_SUPPORT} == "yes"
|
||||
CFLAGS+= -DLOADER_CD9660_SUPPORT
|
||||
.endif
|
||||
.if ${LOADER_EXT2FS_SUPPORT} == "yes"
|
||||
CFLAGS+= -DLOADER_EXT2FS_SUPPORT
|
||||
.endif
|
||||
.if ${LOADER_GZIP_SUPPORT} == "yes"
|
||||
CFLAGS+= -DLOADER_GZIP_SUPPORT
|
||||
.endif
|
||||
.if ${LOADER_BZIP2_SUPPORT} == "yes"
|
||||
CFLAGS+= -DLOADER_BZIP2_SUPPORT
|
||||
.endif
|
||||
.if ${LOADER_NET_SUPPORT} == "yes"
|
||||
CFLAGS+= -DLOADER_NET_SUPPORT
|
||||
.endif
|
||||
.if ${LOADER_NFS_SUPPORT} == "yes"
|
||||
CFLAGS+= -DLOADER_NFS_SUPPORT
|
||||
.endif
|
||||
.if ${LOADER_TFTP_SUPPORT} == "yes"
|
||||
CFLAGS+= -DLOADER_TFTP_SUPPORT
|
||||
.endif
|
||||
.if ${LOADER_FDT_SUPPORT} == "yes"
|
||||
CFLAGS+= -I${.CURDIR}/../../fdt
|
||||
CFLAGS+= -I${.OBJDIR}/../../fdt
|
||||
CFLAGS+= -I${.CURDIR}/../../../contrib/libfdt
|
||||
CFLAGS+= -DLOADER_FDT_SUPPORT
|
||||
LIBFDT= ${.OBJDIR}/../../fdt/libfdt.a
|
||||
.endif
|
||||
|
||||
|
||||
.if ${MK_FORTH} != "no"
|
||||
# Enable BootForth
|
||||
BOOT_FORTH= yes
|
||||
CFLAGS+= -DBOOT_FORTH -I${.CURDIR}/../../ficl -I${.CURDIR}/../../ficl/powerpc
|
||||
LIBFICL= ${.OBJDIR}/../../ficl/libficl.a
|
||||
.endif
|
||||
|
||||
# Avoid the open-close-dance for every file access as some firmwares perform
|
||||
# an auto-negotiation on every open of the network interface and thus causes
|
||||
# netbooting to take horribly long.
|
||||
CFLAGS+= -DNETIF_OPEN_CLOSE_ONCE -mcpu=powerpc64
|
||||
|
||||
# Always add MI sources
|
||||
.PATH: ${.CURDIR}/../../common ${.CURDIR}/../../../libkern
|
||||
.include "${.CURDIR}/../../common/Makefile.inc"
|
||||
CFLAGS+= -I${.CURDIR}/../../common -I${.CURDIR}/../../..
|
||||
CFLAGS+= -I.
|
||||
|
||||
CLEANFILES+= vers.c loader.help
|
||||
|
||||
CFLAGS+= -Wall -ffreestanding -msoft-float -DAIM
|
||||
# load address. set in linker script
|
||||
RELOC?= 0x0
|
||||
CFLAGS+= -DRELOC=${RELOC}
|
||||
|
||||
LDFLAGS= -nostdlib -static -T ${.CURDIR}/ldscript.powerpc
|
||||
|
||||
# 64-bit bridge extensions
|
||||
CFLAGS+= -Wa,-mppc64bridge
|
||||
|
||||
# Pull in common loader code
|
||||
#.PATH: ${.CURDIR}/../../ofw/common
|
||||
#.include "${.CURDIR}/../../ofw/common/Makefile.inc"
|
||||
|
||||
# where to get libstand from
|
||||
LIBSTAND= ${.OBJDIR}/../../libstand32/libstand.a
|
||||
CFLAGS+= -I${.CURDIR}/../../../../lib/libstand/
|
||||
|
||||
DPADD= ${LIBFICL} ${LIBOFW} ${LIBFDT} ${LIBSTAND}
|
||||
LDADD= ${LIBFICL} ${LIBOFW} ${LIBFDT} ${LIBSTAND}
|
||||
|
||||
SC_DFLT_FONT=cp437
|
||||
|
||||
font.h:
|
||||
uudecode < /usr/share/syscons/fonts/${SC_DFLT_FONT}-8x16.fnt && file2c 'u_char dflt_font_16[16*256] = {' '};' < ${SC_DFLT_FONT}-8x16 > font.h && uudecode < /usr/share/syscons/fonts/${SC_DFLT_FONT}-8x14.fnt && file2c 'u_char dflt_font_14[14*256] = {' '};' < ${SC_DFLT_FONT}-8x14 >> font.h && uudecode < /usr/share/syscons/fonts/${SC_DFLT_FONT}-8x8.fnt && file2c 'u_char dflt_font_8[8*256] = {' '};' < ${SC_DFLT_FONT}-8x8 >> font.h
|
||||
|
||||
vers.c: ${.CURDIR}/../../common/newvers.sh ${.CURDIR}/version
|
||||
sh ${.CURDIR}/../../common/newvers.sh ${.CURDIR}/version ${NEWVERSWHAT}
|
||||
|
||||
loader.help: help.common help.kboot ${.CURDIR}/../../fdt/help.fdt
|
||||
cat ${.ALLSRC} | \
|
||||
awk -f ${.CURDIR}/../../common/merge_help.awk > ${.TARGET}
|
||||
|
||||
.PATH: ${.CURDIR}/../../forth
|
||||
FILES= loader.help loader.4th support.4th loader.conf
|
||||
FILES+= screen.4th frames.4th
|
||||
FILES+= beastie.4th brand.4th check-password.4th color.4th delay.4th
|
||||
FILES+= menu.4th menu-commands.4th menusets.4th shortcuts.4th version.4th
|
||||
FILESDIR_loader.conf= /boot/defaults
|
||||
|
||||
.if !exists(${DESTDIR}/boot/loader.rc)
|
||||
FILES+= loader.rc
|
||||
.endif
|
||||
|
||||
.if !exists(${DESTDIR}/boot/menu.rc)
|
||||
FILES+= menu.rc
|
||||
.endif
|
||||
|
||||
.include <bsd.prog.mk>
|
||||
121
sys/boot/powerpc/kboot/conf.c
Normal file
121
sys/boot/powerpc/kboot/conf.c
Normal file
|
|
@ -0,0 +1,121 @@
|
|||
/*-
|
||||
* Copyright (C) 1999 Michael Smith <msmith@freebsd.org>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <stand.h>
|
||||
#include "bootstrap.h"
|
||||
|
||||
#if defined(LOADER_NET_SUPPORT)
|
||||
#include "dev_net.h"
|
||||
#endif
|
||||
|
||||
extern struct devsw hostdisk;
|
||||
|
||||
/*
|
||||
* We could use linker sets for some or all of these, but
|
||||
* then we would have to control what ended up linked into
|
||||
* the bootstrap. So it's easier to conditionalise things
|
||||
* here.
|
||||
*
|
||||
* XXX rename these arrays to be consistent and less namespace-hostile
|
||||
*/
|
||||
|
||||
/* Exported for libstand */
|
||||
struct devsw *devsw[] = {
|
||||
#if defined(LOADER_DISK_SUPPORT) || defined(LOADER_CD9660_SUPPORT)
|
||||
&hostdisk,
|
||||
#endif
|
||||
#if defined(LOADER_NET_SUPPORT)
|
||||
&netdev,
|
||||
#endif
|
||||
NULL
|
||||
};
|
||||
|
||||
struct fs_ops *file_system[] = {
|
||||
#if defined(LOADER_UFS_SUPPORT)
|
||||
&ufs_fsops,
|
||||
#endif
|
||||
#if defined(LOADER_CD9660_SUPPORT)
|
||||
&cd9660_fsops,
|
||||
#endif
|
||||
#if defined(LOADER_EXT2FS_SUPPORT)
|
||||
&ext2fs_fsops,
|
||||
#endif
|
||||
#if defined(LOADER_NFS_SUPPORT)
|
||||
&nfs_fsops,
|
||||
#endif
|
||||
#if defined(LOADER_TFTP_SUPPORT)
|
||||
&tftp_fsops,
|
||||
#endif
|
||||
#if defined(LOADER_GZIP_SUPPORT)
|
||||
&gzipfs_fsops,
|
||||
#endif
|
||||
#if defined(LOADER_BZIP2_SUPPORT)
|
||||
&bzipfs_fsops,
|
||||
#endif
|
||||
NULL
|
||||
};
|
||||
|
||||
extern struct netif_driver kbootnet;
|
||||
|
||||
struct netif_driver *netif_drivers[] = {
|
||||
#if 0 /* XXX */
|
||||
#if defined(LOADER_NET_SUPPORT)
|
||||
&kbootnet,
|
||||
#endif
|
||||
#endif
|
||||
NULL,
|
||||
};
|
||||
|
||||
/* Exported for PowerPC only */
|
||||
/*
|
||||
* Sort formats so that those that can detect based on arguments
|
||||
* rather than reading the file go first.
|
||||
*/
|
||||
|
||||
extern struct file_format ppc_elf64;
|
||||
|
||||
struct file_format *file_formats[] = {
|
||||
&ppc_elf64,
|
||||
NULL
|
||||
};
|
||||
|
||||
/*
|
||||
* Consoles
|
||||
*/
|
||||
extern struct console hostconsole;
|
||||
|
||||
struct console *consoles[] = {
|
||||
&hostconsole,
|
||||
NULL
|
||||
};
|
||||
|
||||
/*
|
||||
* reloc - our load address
|
||||
*/
|
||||
vm_offset_t reloc = RELOC;
|
||||
1
sys/boot/powerpc/kboot/help.kboot
Normal file
1
sys/boot/powerpc/kboot/help.kboot
Normal file
|
|
@ -0,0 +1 @@
|
|||
$FreeBSD: user/nwhitehorn/kboot/powerpc/kboot/help.kboot 217044 2011-01-06 04:12:29Z nwhitehorn $
|
||||
67
sys/boot/powerpc/kboot/host_syscall.S
Normal file
67
sys/boot/powerpc/kboot/host_syscall.S
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
#include <machine/asm.h>
|
||||
|
||||
ENTRY(host_read)
|
||||
li %r0, 3 # SYS_read
|
||||
sc
|
||||
bso 1f
|
||||
blr
|
||||
1:
|
||||
li %r3, 0
|
||||
blr
|
||||
|
||||
|
||||
ENTRY(host_write)
|
||||
li %r0, 4 # SYS_write
|
||||
sc
|
||||
blr
|
||||
|
||||
ENTRY(host_seek)
|
||||
li %r0, 19 # SYS_lseek
|
||||
sc
|
||||
blr
|
||||
|
||||
ENTRY(host_open)
|
||||
li %r0, 5 # SYS_open
|
||||
sc
|
||||
bso 1f
|
||||
blr
|
||||
1:
|
||||
li %r3, 0
|
||||
blr
|
||||
|
||||
ENTRY(host_close)
|
||||
li %r0, 6 # SYS_close
|
||||
sc
|
||||
blr
|
||||
|
||||
ENTRY(host_mmap)
|
||||
li %r0, 90 # SYS_mmap
|
||||
sc
|
||||
blr
|
||||
|
||||
ENTRY(host_gettimeofday)
|
||||
li %r0, 78 # SYS_gettimeofday
|
||||
sc
|
||||
blr
|
||||
|
||||
ENTRY(host_select)
|
||||
li %r0, 142 # SYS_select
|
||||
sc
|
||||
blr
|
||||
|
||||
ENTRY(kexec_load)
|
||||
lis %r6,21 # KEXEC_ARCH_PPC64
|
||||
li %r0,268 # __NR_kexec_load
|
||||
sc
|
||||
blr
|
||||
|
||||
ENTRY(host_reboot)
|
||||
li %r0,88 # SYS_reboot
|
||||
sc
|
||||
blr
|
||||
|
||||
ENTRY(host_getdents)
|
||||
li %r0,141 # SYS_getdents
|
||||
sc
|
||||
blr
|
||||
|
||||
51
sys/boot/powerpc/kboot/host_syscall.h
Normal file
51
sys/boot/powerpc/kboot/host_syscall.h
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
/*-
|
||||
* Copyright (C) 2014 Nathan Whitehorn
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
||||
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#ifndef _HOST_SYSCALL_H
|
||||
#define _HOST_SYSCALL_H
|
||||
|
||||
#include <stand.h>
|
||||
|
||||
ssize_t host_read(int fd, void *buf, size_t nbyte);
|
||||
ssize_t host_write(int fd, const void *buf, size_t nbyte);
|
||||
ssize_t host_seek(int fd, int offset, int whence);
|
||||
int host_open(char *path, int flags, int mode);
|
||||
int host_close(int fd);
|
||||
void *host_mmap(void *addr, size_t len, int prot, int flags, int fd, int);
|
||||
#define host_getmem(size) host_mmap(0, size, 3 /* RW */, 0x22 /* ANON */, -1, 0);
|
||||
struct host_timeval {
|
||||
int tv_sec;
|
||||
int tv_usec;
|
||||
};
|
||||
int host_gettimeofday(struct host_timeval *a, void *b);
|
||||
int host_select(int nfds, long *readfds, long *writefds, long *exceptfds,
|
||||
struct host_timeval *timeout);
|
||||
int kexec_load(vm_offset_t start, int nsegs, void *segs);
|
||||
int host_reboot(int, int, int, void *);
|
||||
int host_getdents(int fd, void *dirp, int count);
|
||||
|
||||
#endif
|
||||
97
sys/boot/powerpc/kboot/hostcons.c
Normal file
97
sys/boot/powerpc/kboot/hostcons.c
Normal file
|
|
@ -0,0 +1,97 @@
|
|||
/*-
|
||||
* Copyright (C) 2014 Nathan Whitehorn
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
||||
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <sys/types.h>
|
||||
#include "bootstrap.h"
|
||||
#include "host_syscall.h"
|
||||
|
||||
static void hostcons_probe(struct console *cp);
|
||||
static int hostcons_init(int arg);
|
||||
static void hostcons_putchar(int c);
|
||||
static int hostcons_getchar();
|
||||
static int hostcons_poll();
|
||||
|
||||
struct console hostconsole = {
|
||||
"host",
|
||||
"Host Console",
|
||||
0,
|
||||
hostcons_probe,
|
||||
hostcons_init,
|
||||
hostcons_putchar,
|
||||
hostcons_getchar,
|
||||
hostcons_poll,
|
||||
};
|
||||
|
||||
static void
|
||||
hostcons_probe(struct console *cp)
|
||||
{
|
||||
|
||||
cp->c_flags |= C_PRESENTIN|C_PRESENTOUT;
|
||||
}
|
||||
|
||||
static int
|
||||
hostcons_init(int arg)
|
||||
{
|
||||
|
||||
/* XXX: set nonblocking */
|
||||
/* tcsetattr(~(ICANON | ECHO)) */
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static void
|
||||
hostcons_putchar(int c)
|
||||
{
|
||||
uint8_t ch = c;
|
||||
|
||||
host_write(1, &ch, 1);
|
||||
}
|
||||
|
||||
static int
|
||||
hostcons_getchar()
|
||||
{
|
||||
uint8_t ch;
|
||||
int rv;
|
||||
|
||||
rv = host_read(0, &ch, 1);
|
||||
if (rv == 1)
|
||||
return (ch);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
static int
|
||||
hostcons_poll()
|
||||
{
|
||||
struct host_timeval tv = {0,0};
|
||||
long fds = 1 << 0;
|
||||
int ret;
|
||||
|
||||
ret = host_select(32, &fds, NULL, NULL, &tv);
|
||||
return (ret > 0);
|
||||
}
|
||||
|
||||
126
sys/boot/powerpc/kboot/hostdisk.c
Normal file
126
sys/boot/powerpc/kboot/hostdisk.c
Normal file
|
|
@ -0,0 +1,126 @@
|
|||
/*-
|
||||
* Copyright (C) 2014 Nathan Whitehorn
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
||||
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <stdarg.h>
|
||||
#include "bootstrap.h"
|
||||
#include "host_syscall.h"
|
||||
|
||||
static int hostdisk_init(void);
|
||||
static int hostdisk_strategy(void *devdata, int flag, daddr_t dblk,
|
||||
size_t size, char *buf, size_t *rsize);
|
||||
static int hostdisk_open(struct open_file *f, ...);
|
||||
static int hostdisk_close(struct open_file *f);
|
||||
static int hostdisk_ioctl(struct open_file *f, u_long cmd, void *data);
|
||||
static void hostdisk_print(int verbose);
|
||||
|
||||
struct devsw hostdisk = {
|
||||
"s",
|
||||
DEVT_DISK,
|
||||
hostdisk_init,
|
||||
hostdisk_strategy,
|
||||
hostdisk_open,
|
||||
hostdisk_close,
|
||||
hostdisk_ioctl,
|
||||
hostdisk_print,
|
||||
};
|
||||
|
||||
static int
|
||||
hostdisk_init(void)
|
||||
{
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
hostdisk_strategy(void *devdata, int flag, daddr_t dblk, size_t size,
|
||||
char *buf, size_t *rsize)
|
||||
{
|
||||
struct devdesc *desc = devdata;
|
||||
daddr_t pos;
|
||||
int n;
|
||||
|
||||
pos = dblk * 512;
|
||||
|
||||
if (host_seek(desc->d_unit, pos, 0) < 0)
|
||||
return (EIO);
|
||||
n = host_read(desc->d_unit, buf, size);
|
||||
|
||||
if (n < 0)
|
||||
return (EIO);
|
||||
|
||||
*rsize = n;
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
hostdisk_open(struct open_file *f, ...)
|
||||
{
|
||||
struct devdesc *desc;
|
||||
char *path;
|
||||
va_list vl;
|
||||
|
||||
va_start(vl, f);
|
||||
desc = va_arg(vl, struct devdesc *);
|
||||
va_end(vl);
|
||||
|
||||
path = malloc(strlen((char *)(desc->d_opendata)) + 6);
|
||||
strcpy(path, "/dev/");
|
||||
strcat(path, (char *)(desc->d_opendata));
|
||||
|
||||
desc->d_unit = host_open(path, O_RDONLY, 0);
|
||||
free(path);
|
||||
|
||||
if (desc->d_unit <= 0)
|
||||
return (ENOENT);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
hostdisk_close(struct open_file *f)
|
||||
{
|
||||
struct devdesc *desc = f->f_devdata;
|
||||
|
||||
host_close(desc->d_unit);
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
hostdisk_ioctl(struct open_file *f, u_long cmd, void *data)
|
||||
{
|
||||
|
||||
return (EINVAL);
|
||||
}
|
||||
|
||||
static void
|
||||
hostdisk_print(int verbose)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
164
sys/boot/powerpc/kboot/kbootfdt.c
Normal file
164
sys/boot/powerpc/kboot/kbootfdt.c
Normal file
|
|
@ -0,0 +1,164 @@
|
|||
/*-
|
||||
* Copyright (C) 2014 Nathan Whitehorn
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
||||
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <fdt_platform.h>
|
||||
#include <libfdt.h>
|
||||
#include "bootstrap.h"
|
||||
#include "host_syscall.h"
|
||||
|
||||
static void
|
||||
add_node_to_fdt(void *buffer, const char *path, int fdt_offset)
|
||||
{
|
||||
int child_offset, fd, pfd, error, dentsize;
|
||||
char subpath[512];
|
||||
void *propbuf;
|
||||
ssize_t proplen;
|
||||
|
||||
struct host_dent {
|
||||
unsigned long d_fileno;
|
||||
unsigned long d_off;
|
||||
unsigned short d_reclen;
|
||||
char d_name[];
|
||||
/* uint8_t d_type; */
|
||||
};
|
||||
char dents[2048];
|
||||
struct host_dent *dent;
|
||||
int d_type;
|
||||
|
||||
fd = host_open(path, O_RDONLY, 0);
|
||||
while (1) {
|
||||
dentsize = host_getdents(fd, dents, sizeof(dents));
|
||||
if (dentsize <= 0)
|
||||
break;
|
||||
for (dent = (struct host_dent *)dents;
|
||||
(char *)dent < dents + dentsize;
|
||||
dent = (struct host_dent *)((void *)dent + dent->d_reclen)) {
|
||||
sprintf(subpath, "%s/%s", path, dent->d_name);
|
||||
if (strcmp(dent->d_name, ".") == 0 ||
|
||||
strcmp(dent->d_name, "..") == 0)
|
||||
continue;
|
||||
d_type = *((char *)(dent) + dent->d_reclen - 1);
|
||||
if (d_type == 4 /* DT_DIR */) {
|
||||
child_offset = fdt_add_subnode(buffer, fdt_offset,
|
||||
dent->d_name);
|
||||
if (child_offset < 0) {
|
||||
printf("Error %d adding node %s/%s, skipping\n",
|
||||
child_offset, path, dent->d_name);
|
||||
continue;
|
||||
}
|
||||
|
||||
add_node_to_fdt(buffer, subpath, child_offset);
|
||||
} else {
|
||||
propbuf = malloc(1024);
|
||||
proplen = 0;
|
||||
pfd = host_open(subpath, O_RDONLY, 0);
|
||||
if (pfd > 0) {
|
||||
proplen = host_read(pfd, propbuf, 1024);
|
||||
host_close(pfd);
|
||||
}
|
||||
error = fdt_setprop(buffer, fdt_offset, dent->d_name,
|
||||
propbuf, proplen);
|
||||
free(propbuf);
|
||||
if (error)
|
||||
printf("Error %d adding property %s to "
|
||||
"node %d\n", error, dent->d_name,
|
||||
fdt_offset);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
host_close(fd);
|
||||
}
|
||||
|
||||
/* Fix up wrong values added to the device tree by prom_init() in Linux */
|
||||
|
||||
static void
|
||||
fdt_linux_fixups(void *fdtp)
|
||||
{
|
||||
int offset, len;
|
||||
const void *prop;
|
||||
|
||||
/*
|
||||
* Remove /memory/available properties, which reflect long-gone OF
|
||||
* state
|
||||
*/
|
||||
|
||||
offset = fdt_path_offset(fdtp, "/memory@0");
|
||||
if (offset > 0) {
|
||||
fdt_delprop(fdtp, offset, "available");
|
||||
/*
|
||||
* XXX: add real available properties to reflect RTAS, etc.
|
||||
* reservations?
|
||||
*/
|
||||
}
|
||||
|
||||
/*
|
||||
* Patch up /chosen nodes so that the stored handles mean something,
|
||||
* where possible.
|
||||
*/
|
||||
offset = fdt_path_offset(fdtp, "/chosen");
|
||||
if (offset > 0) {
|
||||
fdt_delprop(fdtp, offset, "cpu"); /* This node not meaningful */
|
||||
|
||||
offset = fdt_path_offset(fdtp, "/chosen");
|
||||
prop = fdt_getprop(fdtp, offset, "linux,stdout-package", &len);
|
||||
if (prop != NULL) {
|
||||
fdt_setprop(fdtp, offset, "stdout", prop, len);
|
||||
offset = fdt_path_offset(fdtp, "/chosen");
|
||||
fdt_setprop(fdtp, offset, "stdin", prop, len);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
fdt_platform_load_dtb(void)
|
||||
{
|
||||
void *buffer;
|
||||
size_t buflen = 409600;
|
||||
|
||||
buffer = malloc(buflen);
|
||||
fdt_create_empty_tree(buffer, buflen);
|
||||
add_node_to_fdt(buffer, "/proc/device-tree",
|
||||
fdt_path_offset(buffer, "/"));
|
||||
fdt_linux_fixups(buffer);
|
||||
|
||||
fdt_pack(buffer);
|
||||
|
||||
fdt_load_dtb_addr(buffer);
|
||||
free(buffer);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
void
|
||||
fdt_platform_fixups(void)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
55
sys/boot/powerpc/kboot/kerneltramp.S
Normal file
55
sys/boot/powerpc/kboot/kerneltramp.S
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
/*
|
||||
* This is the analog to the kexec "purgatory" code
|
||||
*
|
||||
* The goal here is to call the actual kernel entry point with the arguments it
|
||||
* expects when kexec calls into it with no arguments. The value of the kernel
|
||||
* entry point and arguments r3-r7 are copied into the trampoline text (which
|
||||
* can be executed from any address) at bytes 8-32. kexec begins execution
|
||||
* of APs at 0x60 bytes past the entry point, executing in a copy relocated
|
||||
* to the absolute address 0x60. Here we implement a loop waiting on the release
|
||||
* of a lock by the kernel at 0x40.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <machine/asm.h>
|
||||
|
||||
.globl CNAME(kerneltramp),CNAME(szkerneltramp)
|
||||
CNAME(kerneltramp):
|
||||
mflr %r9
|
||||
bl 2f
|
||||
.space 24 /* branch address, r3-r7 */
|
||||
|
||||
. = kerneltramp + 0x40 /* AP spinlock */
|
||||
.long 0
|
||||
|
||||
. = kerneltramp + 0x60 /* AP entry point */
|
||||
li %r3,0x40
|
||||
1: lwz %r1,0(%r3)
|
||||
cmpwi %r1,0
|
||||
beq 1b
|
||||
|
||||
/* Jump into CPU reset */
|
||||
li %r0,0x100
|
||||
icbi 0,%r0
|
||||
isync
|
||||
sync
|
||||
ba 0x100
|
||||
|
||||
2: /* Continuation of 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)
|
||||
lwz %r5,12(%r8)
|
||||
lwz %r6,16(%r8)
|
||||
lwz %r7,20(%r8)
|
||||
bctr
|
||||
|
||||
endkerneltramp:
|
||||
|
||||
.data
|
||||
CNAME(szkerneltramp):
|
||||
.long endkerneltramp - CNAME(kerneltramp)
|
||||
111
sys/boot/powerpc/kboot/ldscript.powerpc
Normal file
111
sys/boot/powerpc/kboot/ldscript.powerpc
Normal file
|
|
@ -0,0 +1,111 @@
|
|||
/* $FreeBSD: user/nwhitehorn/kboot/powerpc/kboot/ldscript.powerpc 272888 2014-10-10 06:24:09Z bapt $ */
|
||||
|
||||
OUTPUT_FORMAT("elf32-powerpc-freebsd", "elf32-powerpc-freebsd",
|
||||
"elf32-powerpc-freebsd")
|
||||
OUTPUT_ARCH(powerpc:common)
|
||||
ENTRY(_start)
|
||||
SEARCH_DIR(/usr/lib);
|
||||
PROVIDE (__stack = 0);
|
||||
SECTIONS
|
||||
{
|
||||
/* Read-only sections, merged into text segment: */
|
||||
. = 0x100000;
|
||||
.text :
|
||||
{
|
||||
*(.text)
|
||||
/* .gnu.warning sections are handled specially by elf32.em. */
|
||||
*(.gnu.warning)
|
||||
*(.gnu.linkonce.t*)
|
||||
} =0
|
||||
_etext = .;
|
||||
.interp : { *(.interp) }
|
||||
.hash : { *(.hash) }
|
||||
.dynsym : { *(.dynsym) }
|
||||
.dynstr : { *(.dynstr) }
|
||||
.gnu.version : { *(.gnu.version) }
|
||||
.gnu.version_d : { *(.gnu.version_d) }
|
||||
.gnu.version_r : { *(.gnu.version_r) }
|
||||
.rela.text :
|
||||
{ *(.rela.text) *(.rela.gnu.linkonce.t*) }
|
||||
.rela.data :
|
||||
{ *(.rela.data) *(.rela.gnu.linkonce.d*) }
|
||||
.rela.rodata :
|
||||
{ *(.rela.rodata) *(.rela.gnu.linkonce.r*) }
|
||||
.rela.got : { *(.rela.got) }
|
||||
.rela.got1 : { *(.rela.got1) }
|
||||
.rela.got2 : { *(.rela.got2) }
|
||||
.rela.ctors : { *(.rela.ctors) }
|
||||
.rela.dtors : { *(.rela.dtors) }
|
||||
.rela.init : { *(.rela.init) }
|
||||
.rela.fini : { *(.rela.fini) }
|
||||
.rela.bss : { *(.rela.bss) }
|
||||
.rela.plt : { *(.rela.plt) }
|
||||
.rela.sbss : { *(.rela.sbss) }
|
||||
.rela.sbss2 : { *(.rela.sbss2) }
|
||||
.text :
|
||||
{
|
||||
*(.text)
|
||||
/* .gnu.warning sections are handled specially by elf32.em. */
|
||||
*(.gnu.warning)
|
||||
*(.gnu.linkonce.t*)
|
||||
} =0
|
||||
_etext = .;
|
||||
PROVIDE (etext = .);
|
||||
.init : { *(.init) } =0
|
||||
.fini : { *(.fini) } =0
|
||||
.rodata : { *(.rodata) *(.gnu.linkonce.r*) }
|
||||
.rodata1 : { *(.rodata1) }
|
||||
.sbss2 : { *(.sbss2) }
|
||||
/* Adjust the address for the data segment to the next page up. */
|
||||
. = ((. + 0x1000) & ~(0x1000 - 1));
|
||||
.data :
|
||||
{
|
||||
*(.data)
|
||||
*(.gnu.linkonce.d*)
|
||||
CONSTRUCTORS
|
||||
}
|
||||
.data1 : { *(.data1) }
|
||||
.got1 : { *(.got1) }
|
||||
.dynamic : { *(.dynamic) }
|
||||
/* Put .ctors and .dtors next to the .got2 section, so that the pointers
|
||||
get relocated with -mrelocatable. Also put in the .fixup pointers.
|
||||
The current compiler no longer needs this, but keep it around for 2.7.2 */
|
||||
PROVIDE (_GOT2_START_ = .);
|
||||
.got2 : { *(.got2) }
|
||||
PROVIDE (__CTOR_LIST__ = .);
|
||||
.ctors : { *(.ctors) }
|
||||
PROVIDE (__CTOR_END__ = .);
|
||||
PROVIDE (__DTOR_LIST__ = .);
|
||||
.dtors : { *(.dtors) }
|
||||
PROVIDE (__DTOR_END__ = .);
|
||||
PROVIDE (_FIXUP_START_ = .);
|
||||
.fixup : { *(.fixup) }
|
||||
PROVIDE (_FIXUP_END_ = .);
|
||||
PROVIDE (_GOT2_END_ = .);
|
||||
PROVIDE (_GOT_START_ = .);
|
||||
.got : { *(.got) }
|
||||
.got.plt : { *(.got.plt) }
|
||||
PROVIDE (_GOT_END_ = .);
|
||||
_edata = .;
|
||||
PROVIDE (edata = .);
|
||||
.sbss :
|
||||
{
|
||||
PROVIDE (__sbss_start = .);
|
||||
*(.sbss)
|
||||
*(.scommon)
|
||||
*(.dynsbss)
|
||||
PROVIDE (__sbss_end = .);
|
||||
}
|
||||
.plt : { *(.plt) }
|
||||
.bss :
|
||||
{
|
||||
PROVIDE (__bss_start = .);
|
||||
*(.dynbss)
|
||||
*(.bss)
|
||||
*(COMMON)
|
||||
}
|
||||
. = ALIGN(4096);
|
||||
_end = . ;
|
||||
PROVIDE (end = .);
|
||||
}
|
||||
|
||||
306
sys/boot/powerpc/kboot/main.c
Normal file
306
sys/boot/powerpc/kboot/main.c
Normal file
|
|
@ -0,0 +1,306 @@
|
|||
/*-
|
||||
* Copyright (C) 2010-2014 Nathan Whitehorn
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
||||
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <stand.h>
|
||||
#include <sys/param.h>
|
||||
#include <fdt_platform.h>
|
||||
|
||||
#define _KERNEL
|
||||
#include <machine/cpufunc.h>
|
||||
#include "bootstrap.h"
|
||||
#include "host_syscall.h"
|
||||
|
||||
struct arch_switch archsw;
|
||||
extern void *_end;
|
||||
|
||||
extern char bootprog_name[];
|
||||
extern char bootprog_rev[];
|
||||
extern char bootprog_date[];
|
||||
extern char bootprog_maker[];
|
||||
|
||||
int kboot_getdev(void **vdev, const char *devspec, const char **path);
|
||||
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);
|
||||
int kboot_setcurrdev(struct env_var *ev, int flags, const void *value);
|
||||
|
||||
extern int command_fdt_internal(int argc, char *argv[]);
|
||||
|
||||
int
|
||||
kboot_getdev(void **vdev, const char *devspec, const char **path)
|
||||
{
|
||||
int i;
|
||||
const char *devpath, *filepath;
|
||||
struct devsw *dv;
|
||||
struct devdesc *desc;
|
||||
|
||||
if (strchr(devspec, ':') != NULL) {
|
||||
devpath = devspec;
|
||||
filepath = strchr(devspec, ':') + 1;
|
||||
} else {
|
||||
devpath = getenv("currdev");
|
||||
filepath = devspec;
|
||||
}
|
||||
|
||||
for (i = 0; (dv = devsw[i]) != NULL; i++) {
|
||||
if (strncmp(dv->dv_name, devpath, strlen(dv->dv_name)) == 0)
|
||||
goto found;
|
||||
}
|
||||
return (ENOENT);
|
||||
|
||||
found:
|
||||
if (path != NULL && filepath != NULL)
|
||||
*path = filepath;
|
||||
else if (path != NULL)
|
||||
*path = strchr(devspec, ':') + 1;
|
||||
|
||||
if (vdev != NULL) {
|
||||
desc = malloc(sizeof(*desc));
|
||||
desc->d_dev = dv;
|
||||
desc->d_unit = 0;
|
||||
desc->d_opendata = strdup(devpath);
|
||||
*vdev = desc;
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, const char **argv)
|
||||
{
|
||||
void *heapbase;
|
||||
const size_t heapsize = 15*1024*1024;
|
||||
const char *bootdev = argv[1];
|
||||
|
||||
/*
|
||||
* Set the heap to one page after the end of the loader.
|
||||
*/
|
||||
heapbase = host_getmem(heapsize);
|
||||
setheap(heapbase, heapbase + heapsize);
|
||||
|
||||
/*
|
||||
* Set up console.
|
||||
*/
|
||||
cons_probe();
|
||||
|
||||
printf("Boot device: %s\n", bootdev);
|
||||
|
||||
archsw.arch_getdev = kboot_getdev;
|
||||
archsw.arch_copyin = kboot_copyin;
|
||||
archsw.arch_copyout = kboot_copyout;
|
||||
archsw.arch_readin = kboot_readin;
|
||||
archsw.arch_autoload = kboot_autoload;
|
||||
|
||||
printf("\n");
|
||||
printf("%s, Revision %s\n", bootprog_name, bootprog_rev);
|
||||
printf("(%s, %s)\n", bootprog_maker, bootprog_date);
|
||||
|
||||
setenv("currdev", bootdev, 1);
|
||||
setenv("loaddev", bootdev, 1);
|
||||
setenv("LINES", "24", 1);
|
||||
|
||||
interact(NULL); /* doesn't return */
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
void
|
||||
exit(int code)
|
||||
{
|
||||
/* XXX: host_exit */
|
||||
}
|
||||
|
||||
void
|
||||
delay(int usecs)
|
||||
{
|
||||
struct host_timeval tvi, tv;
|
||||
uint64_t ti, t;
|
||||
host_gettimeofday(&tvi, NULL);
|
||||
ti = tvi.tv_sec*1000000 + tvi.tv_usec;
|
||||
do {
|
||||
host_gettimeofday(&tv, NULL);
|
||||
t = tv.tv_sec*1000000 + tv.tv_usec;
|
||||
} while (t < ti + usecs);
|
||||
}
|
||||
|
||||
int
|
||||
getsecs()
|
||||
{
|
||||
struct host_timeval tv;
|
||||
host_gettimeofday(&tv, NULL);
|
||||
return (tv.tv_sec);
|
||||
}
|
||||
|
||||
time_t
|
||||
time(time_t *tloc)
|
||||
{
|
||||
time_t rv;
|
||||
|
||||
rv = getsecs();
|
||||
if (tloc != NULL)
|
||||
*tloc = rv;
|
||||
|
||||
return (rv);
|
||||
}
|
||||
|
||||
struct kexec_segment {
|
||||
void *buf;
|
||||
int bufsz;
|
||||
void *mem;
|
||||
int memsz;
|
||||
};
|
||||
|
||||
struct kexec_segment loaded_segments[128];
|
||||
int nkexec_segments = 0;
|
||||
|
||||
static ssize_t
|
||||
get_phys_buffer(vm_offset_t dest, const size_t len, void **buf)
|
||||
{
|
||||
int i = 0;
|
||||
const size_t segsize = 2*1024*1024;
|
||||
|
||||
for (i = 0; i < nkexec_segments; i++) {
|
||||
if (dest >= (vm_offset_t)loaded_segments[i].mem &&
|
||||
dest < (vm_offset_t)loaded_segments[i].mem +
|
||||
loaded_segments[i].memsz)
|
||||
goto out;
|
||||
}
|
||||
|
||||
loaded_segments[nkexec_segments].buf = host_getmem(segsize);
|
||||
loaded_segments[nkexec_segments].bufsz = segsize;
|
||||
loaded_segments[nkexec_segments].mem = (void *)rounddown2(dest,segsize);
|
||||
loaded_segments[nkexec_segments].memsz = segsize;
|
||||
i = nkexec_segments;
|
||||
nkexec_segments++;
|
||||
|
||||
out:
|
||||
*buf = loaded_segments[i].buf + (dest -
|
||||
(vm_offset_t)loaded_segments[i].mem);
|
||||
return (min(len,loaded_segments[i].bufsz - (dest -
|
||||
(vm_offset_t)loaded_segments[i].mem)));
|
||||
}
|
||||
|
||||
ssize_t
|
||||
kboot_copyin(const void *src, vm_offset_t dest, const size_t len)
|
||||
{
|
||||
ssize_t segsize, remainder;
|
||||
void *destbuf;
|
||||
|
||||
remainder = len;
|
||||
do {
|
||||
segsize = get_phys_buffer(dest, remainder, &destbuf);
|
||||
bcopy(src, destbuf, segsize);
|
||||
remainder -= segsize;
|
||||
src += segsize;
|
||||
dest += segsize;
|
||||
} while (remainder > 0);
|
||||
|
||||
return (len);
|
||||
}
|
||||
|
||||
ssize_t
|
||||
kboot_copyout(vm_offset_t src, void *dest, const size_t len)
|
||||
{
|
||||
ssize_t segsize, remainder;
|
||||
void *srcbuf;
|
||||
|
||||
remainder = len;
|
||||
do {
|
||||
segsize = get_phys_buffer(src, remainder, &srcbuf);
|
||||
bcopy(srcbuf, dest, segsize);
|
||||
remainder -= segsize;
|
||||
src += segsize;
|
||||
dest += segsize;
|
||||
} while (remainder > 0);
|
||||
|
||||
return (len);
|
||||
}
|
||||
|
||||
ssize_t
|
||||
kboot_readin(const int fd, vm_offset_t dest, const size_t len)
|
||||
{
|
||||
void *buf;
|
||||
size_t resid, chunk, get;
|
||||
ssize_t got;
|
||||
vm_offset_t p;
|
||||
|
||||
p = dest;
|
||||
|
||||
chunk = min(PAGE_SIZE, len);
|
||||
buf = malloc(chunk);
|
||||
if (buf == NULL) {
|
||||
printf("kboot_readin: buf malloc failed\n");
|
||||
return (0);
|
||||
}
|
||||
|
||||
for (resid = len; resid > 0; resid -= got, p += got) {
|
||||
get = min(chunk, resid);
|
||||
got = read(fd, buf, get);
|
||||
if (got <= 0) {
|
||||
if (got < 0)
|
||||
printf("kboot_readin: read failed\n");
|
||||
break;
|
||||
}
|
||||
|
||||
kboot_copyin(buf, p, got);
|
||||
}
|
||||
|
||||
free (buf);
|
||||
return (len - resid);
|
||||
}
|
||||
|
||||
int
|
||||
kboot_autoload(void)
|
||||
{
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
void
|
||||
_start(int argc, const char **argv, char **env)
|
||||
{
|
||||
register volatile void **sp asm("r1");
|
||||
main((int)sp[0], (const char **)&sp[1]);
|
||||
}
|
||||
|
||||
/*
|
||||
* Since proper fdt command handling function is defined in fdt_loader_cmd.c,
|
||||
* and declaring it as extern is in contradiction with COMMAND_SET() macro
|
||||
* (which uses static pointer), we're defining wrapper function, which
|
||||
* calls the proper fdt handling routine.
|
||||
*/
|
||||
static int
|
||||
command_fdt(int argc, char *argv[])
|
||||
{
|
||||
|
||||
return (command_fdt_internal(argc, argv));
|
||||
}
|
||||
|
||||
COMMAND_SET(fdt, "fdt", "flattened device tree handling", command_fdt);
|
||||
|
||||
343
sys/boot/powerpc/kboot/metadata.c
Normal file
343
sys/boot/powerpc/kboot/metadata.c
Normal file
|
|
@ -0,0 +1,343 @@
|
|||
/*-
|
||||
* Copyright (c) 1998 Michael Smith <msmith@freebsd.org>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* from: FreeBSD: src/sys/boot/sparc64/loader/metadata.c,v 1.6
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <stand.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/reboot.h>
|
||||
#include <sys/linker.h>
|
||||
#include <sys/boot.h>
|
||||
#include <fdt_platform.h>
|
||||
|
||||
#include <machine/metadata.h>
|
||||
|
||||
#include "bootstrap.h"
|
||||
|
||||
int
|
||||
md_getboothowto(char *kargs)
|
||||
{
|
||||
char *cp;
|
||||
int howto;
|
||||
int active;
|
||||
int i;
|
||||
|
||||
/* Parse kargs */
|
||||
howto = 0;
|
||||
if (kargs != NULL) {
|
||||
cp = kargs;
|
||||
active = 0;
|
||||
while (*cp != 0) {
|
||||
if (!active && (*cp == '-')) {
|
||||
active = 1;
|
||||
} else if (active)
|
||||
switch (*cp) {
|
||||
case 'a':
|
||||
howto |= RB_ASKNAME;
|
||||
break;
|
||||
case 'C':
|
||||
howto |= RB_CDROM;
|
||||
break;
|
||||
case 'd':
|
||||
howto |= RB_KDB;
|
||||
break;
|
||||
case 'D':
|
||||
howto |= RB_MULTIPLE;
|
||||
break;
|
||||
case 'm':
|
||||
howto |= RB_MUTE;
|
||||
break;
|
||||
case 'g':
|
||||
howto |= RB_GDB;
|
||||
break;
|
||||
case 'h':
|
||||
howto |= RB_SERIAL;
|
||||
break;
|
||||
case 'p':
|
||||
howto |= RB_PAUSE;
|
||||
break;
|
||||
case 'r':
|
||||
howto |= RB_DFLTROOT;
|
||||
break;
|
||||
case 's':
|
||||
howto |= RB_SINGLE;
|
||||
break;
|
||||
case 'v':
|
||||
howto |= RB_VERBOSE;
|
||||
break;
|
||||
default:
|
||||
active = 0;
|
||||
break;
|
||||
}
|
||||
cp++;
|
||||
}
|
||||
}
|
||||
/* get equivalents from the environment */
|
||||
for (i = 0; howto_names[i].ev != NULL; i++)
|
||||
if (getenv(howto_names[i].ev) != NULL)
|
||||
howto |= howto_names[i].mask;
|
||||
if (!strcmp(getenv("console"), "comconsole"))
|
||||
howto |= RB_SERIAL;
|
||||
if (!strcmp(getenv("console"), "nullconsole"))
|
||||
howto |= RB_MUTE;
|
||||
return(howto);
|
||||
}
|
||||
|
||||
/*
|
||||
* Copy the environment into the load area starting at (addr).
|
||||
* Each variable is formatted as <name>=<value>, with a single nul
|
||||
* separating each variable, and a double nul terminating the environment.
|
||||
*/
|
||||
vm_offset_t
|
||||
md_copyenv(vm_offset_t addr)
|
||||
{
|
||||
struct env_var *ep;
|
||||
|
||||
/* traverse the environment */
|
||||
for (ep = environ; ep != NULL; ep = ep->ev_next) {
|
||||
archsw.arch_copyin(ep->ev_name, addr, strlen(ep->ev_name));
|
||||
addr += strlen(ep->ev_name);
|
||||
archsw.arch_copyin("=", addr, 1);
|
||||
addr++;
|
||||
if (ep->ev_value != NULL) {
|
||||
archsw.arch_copyin(ep->ev_value, addr, strlen(ep->ev_value));
|
||||
addr += strlen(ep->ev_value);
|
||||
}
|
||||
archsw.arch_copyin("", addr, 1);
|
||||
addr++;
|
||||
}
|
||||
archsw.arch_copyin("", addr, 1);
|
||||
addr++;
|
||||
return(addr);
|
||||
}
|
||||
|
||||
/*
|
||||
* Copy module-related data into the load area, where it can be
|
||||
* used as a directory for loaded modules.
|
||||
*
|
||||
* Module data is presented in a self-describing format. Each datum
|
||||
* is preceded by a 32-bit identifier and a 32-bit size field.
|
||||
*
|
||||
* Currently, the following data are saved:
|
||||
*
|
||||
* MOD_NAME (variable) module name (string)
|
||||
* MOD_TYPE (variable) module type (string)
|
||||
* MOD_ARGS (variable) module parameters (string)
|
||||
* MOD_ADDR sizeof(vm_offset_t) module load address
|
||||
* MOD_SIZE sizeof(size_t) module size
|
||||
* MOD_METADATA (variable) type-specific metadata
|
||||
*/
|
||||
|
||||
static int align;
|
||||
|
||||
#define COPY32(v, a, c) { \
|
||||
u_int32_t x = (v); \
|
||||
if (c) \
|
||||
archsw.arch_copyin(&x, a, sizeof(x)); \
|
||||
a += sizeof(x); \
|
||||
}
|
||||
|
||||
#define MOD_STR(t, a, s, c) { \
|
||||
COPY32(t, a, c); \
|
||||
COPY32(strlen(s) + 1, a, c) \
|
||||
if (c) \
|
||||
archsw.arch_copyin(s, a, strlen(s) + 1);\
|
||||
a += roundup(strlen(s) + 1, align); \
|
||||
}
|
||||
|
||||
#define MOD_NAME(a, s, c) MOD_STR(MODINFO_NAME, a, s, c)
|
||||
#define MOD_TYPE(a, s, c) MOD_STR(MODINFO_TYPE, a, s, c)
|
||||
#define MOD_ARGS(a, s, c) MOD_STR(MODINFO_ARGS, a, s, c)
|
||||
|
||||
#define MOD_VAR(t, a, s, c) { \
|
||||
COPY32(t, a, c); \
|
||||
COPY32(sizeof(s), a, c); \
|
||||
if (c) \
|
||||
archsw.arch_copyin(&s, a, sizeof(s)); \
|
||||
a += roundup(sizeof(s), align); \
|
||||
}
|
||||
|
||||
#define MOD_ADDR(a, s, c) MOD_VAR(MODINFO_ADDR, a, s, c)
|
||||
#define MOD_SIZE(a, s, c) MOD_VAR(MODINFO_SIZE, a, s, c)
|
||||
|
||||
#define MOD_METADATA(a, mm, c) { \
|
||||
COPY32(MODINFO_METADATA | mm->md_type, a, c);\
|
||||
COPY32(mm->md_size, a, c); \
|
||||
if (c) \
|
||||
archsw.arch_copyin(mm->md_data, a, mm->md_size);\
|
||||
a += roundup(mm->md_size, align); \
|
||||
}
|
||||
|
||||
#define MOD_END(a, c) { \
|
||||
COPY32(MODINFO_END, a, c); \
|
||||
COPY32(0, a, c); \
|
||||
}
|
||||
|
||||
vm_offset_t
|
||||
md_copymodules(vm_offset_t addr, int kern64)
|
||||
{
|
||||
struct preloaded_file *fp;
|
||||
struct file_metadata *md;
|
||||
uint64_t scratch64;
|
||||
int c;
|
||||
|
||||
c = addr != 0;
|
||||
/* start with the first module on the list, should be the kernel */
|
||||
for (fp = file_findfile(NULL, NULL); fp != NULL; fp = fp->f_next) {
|
||||
|
||||
MOD_NAME(addr, fp->f_name, c); /* this field must come first */
|
||||
MOD_TYPE(addr, fp->f_type, c);
|
||||
if (fp->f_args)
|
||||
MOD_ARGS(addr, fp->f_args, c);
|
||||
if (kern64) {
|
||||
scratch64 = fp->f_addr;
|
||||
MOD_ADDR(addr, scratch64, c);
|
||||
scratch64 = fp->f_size;
|
||||
MOD_SIZE(addr, scratch64, c);
|
||||
} else {
|
||||
MOD_ADDR(addr, fp->f_addr, c);
|
||||
MOD_SIZE(addr, fp->f_size, c);
|
||||
}
|
||||
for (md = fp->f_metadata; md != NULL; md = md->md_next) {
|
||||
if (!(md->md_type & MODINFOMD_NOCOPY)) {
|
||||
MOD_METADATA(addr, md, c);
|
||||
}
|
||||
}
|
||||
}
|
||||
MOD_END(addr, c);
|
||||
return(addr);
|
||||
}
|
||||
|
||||
/*
|
||||
* Load the information expected by a powerpc kernel.
|
||||
*
|
||||
* - The 'boothowto' argument is constructed
|
||||
* - The 'bootdev' argument is constructed
|
||||
* - The kernel environment is copied into kernel space.
|
||||
* - Module metadata are formatted and placed in kernel space.
|
||||
*/
|
||||
int
|
||||
md_load_dual(char *args, vm_offset_t *modulep, vm_offset_t *dtb, int kern64)
|
||||
{
|
||||
struct preloaded_file *kfp;
|
||||
struct preloaded_file *xp;
|
||||
struct file_metadata *md;
|
||||
vm_offset_t kernend;
|
||||
vm_offset_t addr;
|
||||
vm_offset_t envp;
|
||||
vm_offset_t fdtp;
|
||||
vm_offset_t size;
|
||||
uint64_t scratch64;
|
||||
char *rootdevname;
|
||||
int howto;
|
||||
|
||||
align = kern64 ? 8 : 4;
|
||||
howto = md_getboothowto(args);
|
||||
|
||||
/*
|
||||
* Allow the environment variable 'rootdev' to override the supplied device
|
||||
* This should perhaps go to MI code and/or have $rootdev tested/set by
|
||||
* MI code before launching the kernel.
|
||||
*/
|
||||
rootdevname = getenv("rootdev");
|
||||
if (rootdevname == NULL)
|
||||
rootdevname = getenv("currdev");
|
||||
/* Try reading the /etc/fstab file to select the root device */
|
||||
getrootmount(rootdevname);
|
||||
|
||||
/* find the last module in the chain */
|
||||
addr = 0;
|
||||
for (xp = file_findfile(NULL, NULL); xp != NULL; xp = xp->f_next) {
|
||||
if (addr < (xp->f_addr + xp->f_size))
|
||||
addr = xp->f_addr + xp->f_size;
|
||||
}
|
||||
/* pad to a page boundary */
|
||||
addr = roundup(addr, PAGE_SIZE);
|
||||
|
||||
/* copy our environment */
|
||||
envp = addr;
|
||||
addr = md_copyenv(addr);
|
||||
|
||||
/* pad to a page boundary */
|
||||
addr = roundup(addr, PAGE_SIZE);
|
||||
|
||||
/* Copy out FDT */
|
||||
size = fdt_copy(addr);
|
||||
*dtb = fdtp = addr;
|
||||
addr = roundup(addr + size, PAGE_SIZE);
|
||||
|
||||
kernend = 0;
|
||||
kfp = file_findfile(NULL, kern64 ? "elf64 kernel" : "elf32 kernel");
|
||||
if (kfp == NULL)
|
||||
kfp = file_findfile(NULL, "elf kernel");
|
||||
if (kfp == NULL)
|
||||
panic("can't find kernel file");
|
||||
file_addmetadata(kfp, MODINFOMD_HOWTO, sizeof howto, &howto);
|
||||
if (kern64) {
|
||||
scratch64 = envp;
|
||||
file_addmetadata(kfp, MODINFOMD_ENVP, sizeof scratch64, &scratch64);
|
||||
scratch64 = fdtp;
|
||||
file_addmetadata(kfp, MODINFOMD_DTBP, sizeof scratch64, &scratch64);
|
||||
scratch64 = kernend;
|
||||
file_addmetadata(kfp, MODINFOMD_KERNEND, sizeof scratch64, &scratch64);
|
||||
} else {
|
||||
file_addmetadata(kfp, MODINFOMD_ENVP, sizeof envp, &envp);
|
||||
file_addmetadata(kfp, MODINFOMD_DTBP, sizeof fdtp, &fdtp);
|
||||
file_addmetadata(kfp, MODINFOMD_KERNEND, sizeof kernend, &kernend);
|
||||
}
|
||||
|
||||
*modulep = addr;
|
||||
size = md_copymodules(0, kern64);
|
||||
kernend = roundup(addr + size, PAGE_SIZE);
|
||||
|
||||
md = file_findmetadata(kfp, MODINFOMD_KERNEND);
|
||||
if (kern64) {
|
||||
scratch64 = kernend;
|
||||
bcopy(&scratch64, md->md_data, sizeof scratch64);
|
||||
} else {
|
||||
bcopy(&kernend, md->md_data, sizeof kernend);
|
||||
}
|
||||
|
||||
(void)md_copymodules(addr, kern64);
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
int
|
||||
md_load(char *args, vm_offset_t *modulep, vm_offset_t *dtb)
|
||||
{
|
||||
return (md_load_dual(args, modulep, dtb, 0));
|
||||
}
|
||||
|
||||
int
|
||||
md_load64(char *args, vm_offset_t *modulep, vm_offset_t *dtb)
|
||||
{
|
||||
return (md_load_dual(args, modulep, dtb, 1));
|
||||
}
|
||||
|
||||
114
sys/boot/powerpc/kboot/ppc64_elf_freebsd.c
Normal file
114
sys/boot/powerpc/kboot/ppc64_elf_freebsd.c
Normal file
|
|
@ -0,0 +1,114 @@
|
|||
/*-
|
||||
* Copyright (c) 2001 Benno Rice <benno@FreeBSD.org>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#define __ELF_WORD_SIZE 64
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/linker.h>
|
||||
|
||||
#include <machine/metadata.h>
|
||||
#include <machine/elf.h>
|
||||
|
||||
#include <stand.h>
|
||||
|
||||
#include "bootstrap.h"
|
||||
#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;
|
||||
extern void * loaded_segments;
|
||||
|
||||
int
|
||||
ppc64_elf_loadfile(char *filename, u_int64_t dest,
|
||||
struct preloaded_file **result)
|
||||
{
|
||||
int r;
|
||||
|
||||
r = __elfN(loadfile)(filename, dest, result);
|
||||
if (r != 0)
|
||||
return (r);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
ppc64_elf_exec(struct preloaded_file *fp)
|
||||
{
|
||||
struct file_metadata *fmp;
|
||||
vm_offset_t mdp, dtb;
|
||||
Elf_Ehdr *e;
|
||||
int error;
|
||||
uint32_t *trampoline;
|
||||
vm_offset_t trampolinebase = 96*1024*1024; /* XXX */
|
||||
|
||||
if ((fmp = file_findmetadata(fp, MODINFOMD_ELFHDR)) == NULL) {
|
||||
return(EFTYPE);
|
||||
}
|
||||
e = (Elf_Ehdr *)&fmp->md_data;
|
||||
|
||||
/* Handle function descriptor */
|
||||
trampoline = malloc(szkerneltramp);
|
||||
memcpy(trampoline, &kerneltramp, szkerneltramp);
|
||||
trampoline[2] = e->e_entry;
|
||||
trampoline[4] = 0; /* Phys. mem offset */
|
||||
trampoline[5] = 0; /* OF entry point */
|
||||
|
||||
if ((error = md_load64(fp->f_args, &mdp, &dtb)) != 0)
|
||||
return (error);
|
||||
|
||||
trampoline[3] = dtb;
|
||||
trampoline[6] = mdp;
|
||||
trampoline[7] = sizeof(mdp);
|
||||
printf("Kernel entry at %#jx ...\n", e->e_entry);
|
||||
|
||||
dev_cleanup();
|
||||
|
||||
archsw.arch_copyin(trampoline, trampolinebase, szkerneltramp);
|
||||
free(trampoline);
|
||||
|
||||
error = kexec_load(trampolinebase, nkexec_segments, &loaded_segments);
|
||||
if (error != 0)
|
||||
panic("kexec_load returned error: %d", error);
|
||||
error = host_reboot(0xfee1dead, 672274793,
|
||||
0x45584543 /* LINUX_REBOOT_CMD_KEXEC */, NULL);
|
||||
if (error != 0)
|
||||
panic("reboot returned error: %d", error);
|
||||
while (1) {}
|
||||
|
||||
panic("exec returned");
|
||||
}
|
||||
|
||||
struct file_format ppc_elf64 =
|
||||
{
|
||||
ppc64_elf_loadfile,
|
||||
ppc64_elf_exec
|
||||
};
|
||||
6
sys/boot/powerpc/kboot/version
Normal file
6
sys/boot/powerpc/kboot/version
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
$FreeBSD: user/nwhitehorn/kboot/powerpc/kboot/version 224106 2011-07-16 19:01:09Z nwhitehorn $
|
||||
|
||||
NOTE ANY CHANGES YOU MAKE TO THE BOOTBLOCKS HERE. The format of this
|
||||
file is important. Make sure the current version number is on line 6.
|
||||
|
||||
0.1: Initial kboot/PowerPC version.
|
||||
Loading…
Reference in a new issue