diff --git a/stand/kboot/Makefile b/stand/kboot/Makefile index aa5511d915a9..24ab77af66db 100644 --- a/stand/kboot/Makefile +++ b/stand/kboot/Makefile @@ -1,39 +1,39 @@ # $FreeBSD$ LOADER_CD9660_SUPPORT?= yes LOADER_MSDOS_SUPPORT?= no LOADER_EXT2FS_SUPPORT?= yes LOADER_UFS_SUPPORT?= yes LOADER_NET_SUPPORT?= yes LOADER_NFS_SUPPORT?= yes LOADER_TFTP_SUPPORT?= no LOADER_GZIP_SUPPORT?= yes LOADER_BZIP2_SUPPORT?= no .include PROG= loader.kboot NEWVERSWHAT= "kboot loader" ${MACHINE_ARCH} INSTALLFLAGS= -b # Architecture-specific loader code -SRCS= vers.c main.c hostcons.c hostdisk.c kbootfdt.c gfx_fb_stub.c +SRCS= vers.c main.c host_syscalls.c hostcons.c hostdisk.c kbootfdt.c gfx_fb_stub.c CFLAGS.gfx_fb_stub.c += -I${SRCTOP}/contrib/pnglite -I${SRCTOP}/sys/teken .include "${BOOTSRC}/fdt.mk" .PATH: ${.CURDIR}/arch/${MACHINE_ARCH} .include "${.CURDIR}/arch/${MACHINE_ARCH}/Makefile.inc" # Always add MI sources .include "${BOOTSRC}/loader.mk" .PATH: ${SYSDIR}/libkern CFLAGS+= -I${.CURDIR} -I${.CURDIR}/arch/${MACHINE_ARCH} CFLAGS+= -Wall DPADD= ${LDR_INTERP} ${LIBOFW} ${LIBFDT} ${LIBSA} LDADD= ${LDR_INTERP} ${LIBOFW} ${LIBFDT} ${LIBSA} .include diff --git a/stand/kboot/arch/powerpc64/host_syscall.S b/stand/kboot/arch/powerpc64/host_syscall.S index a5556aa1b2dc..729bc6baa082 100644 --- a/stand/kboot/arch/powerpc64/host_syscall.S +++ b/stand/kboot/arch/powerpc64/host_syscall.S @@ -1,88 +1,32 @@ -/* - * - * $FreeBSD$ - */ - #include -ENTRY(host_read) - li %r0, 3 # SYS_read - sc - bso 1f - blr -1: - li %r3, 0 - blr -END(host_read) - -ENTRY(host_write) - li %r0, 4 # SYS_write - sc - blr -END(host_write) - -ENTRY(host_llseek) - li %r0, 140 # SYS_llseek - sc - blr -END(host_llseek) - -ENTRY(host_open) - li %r0, 5 # SYS_open - sc - bso 1f - blr -1: - li %r3, 0 - blr -END(host_open) - -ENTRY(host_close) - li %r0, 6 # SYS_close - sc - blr -END(host_close) - -ENTRY(host_mmap) - li %r0, 90 # SYS_mmap - sc - blr -END(host_mmap) - -ENTRY(host_uname) - li %r0, 122 # SYS_uname - sc - blr -END(host_uname) - -ENTRY(host_gettimeofday) - li %r0, 78 # SYS_gettimeofday - sc - blr -END(host_gettimeofday) - -ENTRY(host_select) - li %r0, 142 # SYS_select - sc - blr -END(host_select) - -ENTRY(kexec_load) - lis %r6,21 # KEXEC_ARCH_PPC64 - li %r0,268 # __NR_kexec_load - sc - blr -END(kexec_load) - -ENTRY(host_reboot) - li %r0,88 # SYS_reboot - sc - blr -END(host_reboot) - -ENTRY(host_getdents) - li %r0,141 # SYS_getdents - sc - blr -END(host_getdents) - +/* + * Emulate the Linux system call interface. The system call number is set in + * %r0, and %r3 -> %r8 have the 6 system call arguments. errno is returned + * as a negative value, but we use it more as a flag something went wrong + * rather than using its value. + * + * Return value in %r3. If it is positive or < -4096, it's a successful + * system call. If it is between -1 and -4095 then it's an failed system + * call with -x as the errno. Errors from the kernel are signaled via the + * the 'so' bit, but we don't test that here at all. There are at most 6 + * arguments to system calls in Linux. + * + * We expose the raw system call result, rather than do the POSIX + * converion to -1 and setting errno. + * + * Note: The code this replaced used bso to set %r3 to 0 for the read and + * open system calls for reasons that are still under investigation. + */ +ENTRY(host_syscall) + mr %r0, %r3 /* SYS_ number in $r0 */ + mr %r3, %r4 /* arg2 -> 1 */ + mr %r4, %r5 /* arg3 -> 2 */ + mr %r5, %r6 /* arg4 -> 3 */ + mr %r6, %r7 /* arg5 -> 4 */ + mr %r7, %r8 /* arg6 -> 5 */ + mr %r8, %r9 /* arg7 -> 6 */ + sc + blr +/* Note: We're exposing the raw return value to the caller */ +END(host_syscall) diff --git a/stand/kboot/arch/powerpc64/syscall_nr.h b/stand/kboot/arch/powerpc64/syscall_nr.h new file mode 100644 index 000000000000..2854124153a2 --- /dev/null +++ b/stand/kboot/arch/powerpc64/syscall_nr.h @@ -0,0 +1,15 @@ +#define SYS_read 3 +#define SYS_write 4 +#define SYS_open 5 +#define SYS_close 6 +#define SYS_gettimeofday 78 +#define SYS_reboot 88 +#define SYS_mmap 90 +#define SYS_uname 120 +#define SYS_llseek 140 +#define SYS_getdents 141 +#define SYS_select 142 +#define __NR_kexec_load 268 + +#define KEXEC_ARCH_PPC64 21 +#define KEXEC_ARCH KEXEC_ARCH_PPC64 diff --git a/stand/kboot/host_syscall.h b/stand/kboot/host_syscall.h index 60b006e5dba4..f6f22a736d53 100644 --- a/stand/kboot/host_syscall.h +++ b/stand/kboot/host_syscall.h @@ -1,59 +1,61 @@ /*- * 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 +long host_syscall(int number, ...); + ssize_t host_read(int fd, void *buf, size_t nbyte); ssize_t host_write(int fd, const void *buf, size_t nbyte); int host_open(const char *path, int flags, int mode); ssize_t host_llseek(int fd, int32_t offset_high, int32_t offset_lo, uint64_t *result, int whence); int host_close(int fd); -void *host_mmap(void *addr, size_t len, int prot, int flags, int fd, int); +void *host_mmap(void *addr, size_t len, int prot, int flags, int fd, off_t off); #define host_getmem(size) host_mmap(0, size, 3 /* RW */, 0x22 /* ANON */, -1, 0); struct old_utsname { char sysname[65]; char nodename[65]; char release[65]; char version[65]; char machine[65]; }; int host_uname(struct old_utsname *); struct host_timeval { - int tv_sec; - int tv_usec; + time_t tv_sec; + long 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(uint32_t start, int nsegs, uint32_t segs); -int host_reboot(int, int, int, uint32_t); +int host_reboot(int, int, int, uintptr_t); int host_getdents(int fd, void *dirp, int count); #endif diff --git a/stand/kboot/host_syscalls.c b/stand/kboot/host_syscalls.c new file mode 100644 index 000000000000..53be0c166374 --- /dev/null +++ b/stand/kboot/host_syscalls.c @@ -0,0 +1,86 @@ +#include "host_syscall.h" +#include "syscall_nr.h" +#include + +ssize_t +host_read(int fd, void *buf, size_t nbyte) +{ + return host_syscall(SYS_read, fd, (uintptr_t)buf, nbyte); + /* XXX original overrode errors */ +} + +ssize_t +host_write(int fd, const void *buf, size_t nbyte) +{ + return host_syscall(SYS_write, fd, (uintptr_t)buf, nbyte); +} + +int +host_open(const char *path, int flags, int mode) +{ + return host_syscall(SYS_open, (uintptr_t)path, flags, mode); + /* XXX original overrode errors */ +} + +ssize_t +host_llseek(int fd, int32_t offset_high, int32_t offset_lo, uint64_t *result, int whence) +{ +#ifdef SYS_llseek + return host_syscall(SYS_llseek, fd, offset_high, offset_lo, (uintptr_t)result, whence); +#else + int64_t rv = host_syscall(SYS_lseek, fd, + (int64_t)((uint64_t)offset_high << 32 | (uint32_t)offset_lo), whence); + if (rv > 0) + *result = (uint64_t)rv; + return (rv); +#endif +} + +int +host_close(int fd) +{ + return host_syscall(SYS_close, fd); +} + +void * +host_mmap(void *addr, size_t len, int prot, int flags, int fd, off_t off) +{ + return (void *)host_syscall(SYS_mmap, (uintptr_t)addr, len, prot, flags, fd, off); +} + +int +host_uname(struct old_utsname *uts) +{ + return host_syscall(SYS_uname, (uintptr_t)uts); +} + +int +host_gettimeofday(struct host_timeval *a, void *b) +{ + return host_syscall(SYS_gettimeofday, (uintptr_t)a, (uintptr_t)b); +} + +int +host_select(int nfds, long *readfds, long *writefds, long *exceptfds, + struct host_timeval *timeout) +{ + return host_syscall(SYS_select, nfds, (uintptr_t)readfds, (uintptr_t)writefds, (uintptr_t)exceptfds, (uintptr_t)timeout, 0); +} + +int +kexec_load(uint32_t start, int nsegs, uint32_t segs) +{ + return host_syscall(__NR_kexec_load, start, nsegs, segs, KEXEC_ARCH << 16); +} + +int +host_reboot(int magic1, int magic2, int cmd, uintptr_t arg) +{ + return host_syscall(SYS_reboot, magic1, magic2, cmd, arg); +} + +int +host_getdents(int fd, void *dirp, int count) +{ + return host_syscall(SYS_getdents, fd, (uintptr_t)dirp, count); +}