On Sat, Sep 23, 2023 at 02:26:18PM +0000, Klemens Nanni wrote: > On Sat, Sep 23, 2023 at 01:11:32PM +0200, Mark Kettenis wrote: > > > Date: Thu, 21 Sep 2023 22:30:01 +0000 > > > From: Klemens Nanni <k...@openbsd.org> > > > > > > In comparison to MI boot which only cares about /bsd.upgrade's x bit, > > > powerpc64 rdboot just wants a regular file. > > > > > > Require and strip u+x before execution to prevent sysupgrade(8) loop. > > > I'm new to powerpc64 and can't think of a reason to be different. > > > > > > Feedback? Objection? OK? > > > > So there is a problem with this approach. Calling chmod() will mean > > the bootloader will change the filesystem. What happens if you're > > booting with a root filesystem that was not cleanly unmounted? > > Modifying a forcibly mounted filesystem may not be without risk. > > Isn't that already the case with chmo() /etc/random.seed? > > Can you explain how that is not a problem in other non-kernel boot loaders > using libsa's ufs2_open() instead of mount(2)?
chmod() through libsa's filesystem code modifies only the inode. Doing a mount-chmod-unmount cycle using the kernel triggers multiple writes to the filesystem. In the past, I have pondered if octeon (and powerpc64) bootcode should use libsa instead of replicating the MI boot code. I did not use libsa initially because the libsa and libc APIs differ, and I did not want to use custom system call stubs. The original octboot/kexec interface was not suitable for libsa use, either. However, the libsa and libc worlds can be reconciled with a trick. The libsa code is first compiled in standalone mode into a relinkable object ("saboot"). This object is then tweaked to avoid name conflicts with libc. Finally, the object is linked with glue code and libc into a proper rdboot executable that the kernel can run. Some have seen this before. diff --git a/sys/arch/octeon/stand/Makefile b/sys/arch/octeon/stand/Makefile index 498bd2809c6..4a86a8bef6b 100644 --- a/sys/arch/octeon/stand/Makefile +++ b/sys/arch/octeon/stand/Makefile @@ -1,5 +1,5 @@ # $OpenBSD: Makefile,v 1.4 2019/08/04 08:53:14 visa Exp $ -SUBDIR+= rdboot boot +SUBDIR+= saboot rdboot boot .include <bsd.subdir.mk> diff --git a/sys/arch/octeon/stand/Makefile.inc b/sys/arch/octeon/stand/Makefile.inc deleted file mode 100644 index 18d8470f888..00000000000 --- a/sys/arch/octeon/stand/Makefile.inc +++ /dev/null @@ -1,45 +0,0 @@ -# $OpenBSD: Makefile.inc,v 1.1 2013/06/05 01:02:29 jasper Exp $ - -BINDIR= /usr/mdec - -STANDALONE?= -D_STANDALONE - -.if ${MACHINE} == "octeon" -CPPFLAGS+= ${STANDALONE} -CPPFLAGS+= -I. -CFLAGS+= -fno-stack-protector -Wall -CFLAGS+= -fno-builtin-vprintf -fno-builtin-printf -fno-builtin-putchar -# Silence warnings -CFLAGS+= -fno-builtin-snprintf -CFLAGS+= -fno-builtin-memcpy -CFLAGS+= -fno-builtin-memcmp -CFLAGS+= -fno-builtin-memset -CFLAGS+= -fno-builtin-strncpy -CFLAGS+= -fno-builtin-strncmp -CFLAGS+= -fno-builtin-exit -SAABI= -mips3 -mno-abicalls -G 0 -fno-pic -fno-common -AS?= as -LD?= ld -.endif - -### Figure out what to use for libsa -LIBSADIR?= ${.CURDIR}/../libsa - -.if exists(${LIBSADIR}/${__objdir}) -LIBSAOBJDIR= ${LIBSADIR}/${__objdir} -.else -LIBSAOBJDIR= ${LIBSADIR} -.endif - -LIBSA= ${LIBSAOBJDIR}/libsa.a - -### Figure out what to use for libz -LIBZDIR?= ${.CURDIR}/../libz - -.if exists(${LIBZDIR}/${__objdir}) -LIBZOBJDIR= ${LIBZDIR}/${__objdir} -.else -LIBZOBJDIR= ${LIBZDIR} -.endif - -LIBZ= ${LIBZOBJDIR}/libz.a diff --git a/sys/arch/octeon/stand/libsa/Makefile b/sys/arch/octeon/stand/libsa/Makefile deleted file mode 100644 index 3b2961f25c0..00000000000 --- a/sys/arch/octeon/stand/libsa/Makefile +++ /dev/null @@ -1,51 +0,0 @@ -# $OpenBSD: Makefile,v 1.8 2019/10/29 02:55:52 deraadt Exp $ - -.include "${.CURDIR}/../Makefile.inc" - -LIB= sa - -.PATH: ${.CURDIR}/../../../../lib/libsa - -CLEANFILES += machine mips64 - -CFLAGS+= ${CEXTRAFLAGS} ${SAABI} -nostdinc -mno-abicalls -D_NO_ABICALLS \ - -fno-pie \ - -I${.CURDIR} -I${.CURDIR}/../include -I${.CURDIR}/../.. \ - -I${.CURDIR}/../../.. -I${.CURDIR}/../../../.. \ - -I${.CURDIR}/../../../../lib/libsa \ - -I${.OBJDIR} - -# stand routines -SRCS= alloc.c cons.c ctime.c exit.c getchar.c getfile.c getln.c globals.c \ - memcmp.c memcpy.c memmove.c memset.c printf.c putchar.c \ - snprintf.c strchr.c strcmp.c strerror.c strncmp.c strncpy.c strtol.c - -# io routines -SRCS+= close.c closeall.c dev.c disklabel.c dkcksum.c fstat.c ioctl.c \ - lseek.c open.c read.c readdir.c stat.c write.c - -#SRCS+= cread.c -#CPPFLAGS+= -D__INTERNAL_LIBSA_CREAD - -# boot filesystems -SRCS+= ufs.c cd9660.c - -CFLAGS+=-DNO_NET - -SRCS+= loadfile.c arc4.c - -${OBJS}: ${.CURDIR}/../Makefile.inc - -NOPROFILE= -NOPIC= - -.if !make(clean) && !make(cleandir) && !make(includes) && !make(obj) -.BEGIN: - @([ -h machine ] || ln -s ${.CURDIR}/../../include machine) - @([ -h mips64 ] || ln -s ${.CURDIR}/../../../mips64/include mips64) -CLEANFILES+= machine mips64 -.endif - -install: - -.include <bsd.lib.mk> diff --git a/sys/arch/octeon/stand/rdboot/Makefile b/sys/arch/octeon/stand/rdboot/Makefile index 841c363ed60..5833076c30b 100644 --- a/sys/arch/octeon/stand/rdboot/Makefile +++ b/sys/arch/octeon/stand/rdboot/Makefile @@ -4,16 +4,32 @@ NOMAN= .if ${MACHINE} == "octeon" PROG= rdboot -SRCS= cmd.c disk.c rdboot.c vars.c -LDADD+= -lutil -LDSTATIC+= -static -.else -NOPROG= -.endif -.PATH: ${S}/lib/libsa -#SRCS+= hexdump.c strtoll.c +S= ${.CURDIR}/../../../.. +BOOTDIR= ${S}/arch/octeon/stand/rdboot + +CFLAGS+= -Wall +CFLAGS+= -I${.CURDIR}/../saboot + +.PATH: ${BOOTDIR} +SRCS= rdboot.c unixcall.c install: +.if !make(clean) && !make(cleandir) && !make(includes) && !make(obj) +.BEGIN: + @([ -h machine ] || ln -s ${.CURDIR}/../../include machine) + @([ -h mips64 ] || ln -s ${.CURDIR}/../../../mips64/include mips64) +CLEANFILES+= machine mips64 +.endif + +SABOOT= ${.CURDIR}/../saboot/obj/saboot.elf + +${PROG}: ${OBJS} ${SABOOT} + ${CC} -static -o $@ ${SABOOT} ${OBJS} -lutil + +.else +NOPROG= +.endif + .include <bsd.prog.mk> diff --git a/sys/arch/octeon/stand/rdboot/cmd.c b/sys/arch/octeon/stand/rdboot/cmd.c deleted file mode 100644 index c9790bb8920..00000000000 --- a/sys/arch/octeon/stand/rdboot/cmd.c +++ /dev/null @@ -1,507 +0,0 @@ -/* $OpenBSD: cmd.c,v 1.3 2019/08/01 04:52:56 visa Exp $ */ - -/* - * Copyright (c) 1997-1999 Michael Shalayeff - * 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 THE REGENTS 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/param.h> -#include <sys/reboot.h> -#include <sys/select.h> -#include <sys/stat.h> - -#include <dirent.h> -#include <errno.h> -#include <fcntl.h> -#include <stdio.h> -#include <string.h> -#include <termios.h> -#include <unistd.h> - -#include "cmd.h" -#include "disk.h" - -static int Xboot(void); -static int Xecho(void); -static int Xhelp(void); -static int Xls(void); -static int Xnop(void); -static int Xreboot(void); -#ifdef MACHINE_CMD -static int Xmachine(void); -extern const struct cmd_table MACHINE_CMD[]; -#endif -extern int Xset(void); - -#ifdef CHECK_SKIP_CONF -extern int CHECK_SKIP_CONF(void); -#endif - -extern const struct cmd_table cmd_set[]; -const struct cmd_table cmd_table[] = { - {"#", CMDT_CMD, Xnop}, /* XXX must be first */ - {"boot", CMDT_CMD, Xboot}, - {"echo", CMDT_CMD, Xecho}, - {"help", CMDT_CMD, Xhelp}, - {"ls", CMDT_CMD, Xls}, -#ifdef MACHINE_CMD - {"machine",CMDT_MDC, Xmachine}, -#endif - {"reboot", CMDT_CMD, Xreboot}, - {"set", CMDT_SET, Xset}, - {NULL, 0}, -}; - -static void ls(const char *, struct stat *); -static int readline(char *, size_t, int); -char *nextword(char *); -static char *whatcmd(const struct cmd_table **ct, char *); -static char *qualify(char *); - -char cmd_buf[CMD_BUFF_SIZE]; - -int -getcmd(void) -{ - cmd.cmd = NULL; - - if (!readline(cmd_buf, sizeof(cmd_buf), cmd.timeout)) - cmd.cmd = cmd_table; - - return docmd(); -} - -int -read_conf(void) -{ - struct stat sb; - const char *path; - int fd, rc = 0; - -#ifdef CHECK_SKIP_CONF - if (CHECK_SKIP_CONF()) { - printf("boot.conf processing skipped at operator request\n"); - cmd.timeout = 0; - return -1; /* Pretend file wasn't found */ - } -#endif - - path = disk_open(qualify(cmd.conf)); - if (path == NULL) { - fprintf(stderr, "cannot open device for reading %s: %s\n", - cmd.conf, strerror(errno)); - return -1; - } - if ((fd = open(path, O_RDONLY)) == -1) { - if (errno != ENOENT && errno != ENXIO) { - fprintf(stderr, "%s: open(%s): %s\n", __func__, - cmd.path, strerror(errno)); - rc = 0; - } else - rc = -1; - goto out; - } - - (void) fstat(fd, &sb); - if (sb.st_uid || (sb.st_mode & 2)) { - fprintf(stderr, "non-secure %s, will not proceed\n", cmd.path); - rc = -1; - goto out; - } - - do { - char *p = cmd_buf; - - cmd.cmd = NULL; - do { - rc = read(fd, p, 1); - } while (rc > 0 && *p++ != '\n' && - (p-cmd_buf) < sizeof(cmd_buf)); - - if (rc < 0) { /* Error from read() */ - fprintf(stderr, "%s: %s\n", cmd.path, strerror(errno)); - break; - } - - if (rc == 0) { /* eof from read() */ - if (p != cmd_buf) { /* Line w/o trailing \n */ - *p = '\0'; - rc = docmd(); - break; - } - } else { /* rc > 0, read a char */ - p--; /* Get back to last character */ - - if (*p != '\n') { /* Line was too long */ - fprintf(stderr, "%s: line too long\n", - cmd.path); - - /* Don't want to run the truncated command */ - rc = -1; - } - *p = '\0'; - } - } while (rc > 0 && !(rc = docmd())); - -out: - if (fd != -1) - close(fd); - disk_close(); - return rc; -} - -int -docmd(void) -{ - char *p = NULL; - const struct cmd_table *ct = cmd_table, *cs; - - cmd.argc = 1; - if (cmd.cmd == NULL) { - - /* command */ - for (p = cmd_buf; *p == ' ' || *p == '\t'; p++) - ; - if (*p == '#' || *p == '\0') { /* comment or empty string */ -#ifdef DEBUG - printf("rem\n"); -#endif - return 0; - } - ct = cmd_table; - cs = NULL; - cmd.argv[cmd.argc] = p; /* in case it's shortcut boot */ - p = whatcmd(&ct, p); - if (ct == NULL) { - cmd.argc++; - ct = cmd_table; - } else if (ct->cmd_type == CMDT_SET && p != NULL) { - cs = cmd_set; -#ifdef MACHINE_CMD - } else if (ct->cmd_type == CMDT_MDC && p != NULL) { - cs = MACHINE_CMD; -#endif - } - - if (cs != NULL) { - p = whatcmd(&cs, p); - if (cs == NULL) { - printf("%s: syntax error\n", ct->cmd_name); - return 0; - } - ct = cs; - } - cmd.cmd = ct; - } - - cmd.argv[0] = ct->cmd_name; - while (p && cmd.argc+1 < sizeof(cmd.argv) / sizeof(cmd.argv[0])) { - cmd.argv[cmd.argc++] = p; - p = nextword(p); - } - cmd.argv[cmd.argc] = NULL; - - return (*cmd.cmd->cmd_exec)(); -} - -static char * -whatcmd(const struct cmd_table **ct, char *p) -{ - char *q; - int l; - - q = nextword(p); - - for (l = 0; p[l]; l++) - ; - - while ((*ct)->cmd_name != NULL && strncmp(p, (*ct)->cmd_name, l)) - (*ct)++; - - if ((*ct)->cmd_name == NULL) - *ct = NULL; - - return q; -} - -static int -readline(char *buf, size_t n, int to) -{ - struct termios saved_tio, tio; - struct timeval tv; - fd_set fdset; - char *p; - int timed_out = 0; -#ifdef DEBUG - extern int debug; -#endif - - /* Only do timeout if greater than 0 */ - if (to > 0) { - /* Switch to non-canonical mode for timeout detection. */ - tcgetattr(STDIN_FILENO, &saved_tio); - tio = saved_tio; - tio.c_lflag &= ~(ECHO | ICANON); - tcsetattr(STDIN_FILENO, TCSANOW, &tio); - - FD_ZERO(&fdset); - FD_SET(STDIN_FILENO, &fdset); - tv.tv_sec = to; - tv.tv_usec = 0; - if (select(STDIN_FILENO + 1, &fdset, NULL, NULL, &tv) == 0) - timed_out = 1; - - /* Restore canonical mode. */ - tcsetattr(STDIN_FILENO, TCSANOW, &saved_tio); - - if (timed_out) { - strlcpy(buf, "boot", 5); - putchar('\n'); - return strlen(buf); - } - } - - /* User has typed something. Turn off timeouts. */ - cmd.timeout = 0; - - if (fgets(buf, n, stdin) == NULL) - return 0; - - /* Strip trailing newline. */ - p = strchr(buf, '\n'); - if (p != NULL) - *p = '\0'; - - return strlen(buf); -} - -/* - * Search for spaces/tabs after the current word. If found, \0 the - * first one. Then pass a pointer to the first character of the - * next word, or NULL if there is no next word. - */ -char * -nextword(char *p) -{ - /* skip blanks */ - while (*p && *p != '\t' && *p != ' ') - p++; - if (*p) { - *p++ = '\0'; - while (*p == '\t' || *p == ' ') - p++; - } - if (*p == '\0') - p = NULL; - return p; -} - -static void -print_help(const struct cmd_table *ct) -{ - for (; ct->cmd_name != NULL; ct++) - printf(" %s", ct->cmd_name); - putchar('\n'); -} - -static int -Xhelp(void) -{ - printf("commands:"); - print_help(cmd_table); -#ifdef MACHINE_CMD - return Xmachine(); -#else - return 0; -#endif -} - -#ifdef MACHINE_CMD -static int -Xmachine(void) -{ - printf("machine:"); - print_help(MACHINE_CMD); - return 0; -} -#endif - -static int -Xecho(void) -{ - int i; - - for (i = 1; i < cmd.argc; i++) - printf("%s ", cmd.argv[i]); - putchar('\n'); - return 0; -} - -static int -Xls(void) -{ - struct stat sb; - const char *path; - DIR *dir; - struct dirent *dent; - int dirfd, oldcwd; - - path = disk_open(qualify(cmd.argv[1] ? cmd.argv[1] : "/.")); - if (path == NULL) - return 0; - - if (stat(path, &sb) < 0) { - printf("stat(%s): %s\n", cmd.path, strerror(errno)); - goto out; - } - - if ((sb.st_mode & S_IFMT) != S_IFDIR) - ls(path, &sb); - else { - oldcwd = open(".", O_RDONLY); - - dirfd = open(path, O_RDONLY); - if (dirfd < 0) { - printf("opendir(%s): %s\n", cmd.path, strerror(errno)); - close(oldcwd); - goto out; - } - if ((dir = fdopendir(dirfd)) < 0) { - printf("opendir(%s): %s\n", cmd.path, strerror(errno)); - close(dirfd); - close(oldcwd); - goto out; - } - fchdir(dirfd); - while ((dent = readdir(dir)) != NULL) { - if (fstatat(dirfd, dent->d_name, &sb, - AT_SYMLINK_NOFOLLOW) < 0) - printf("stat(%s): %s\n", dent->d_name, - strerror(errno)); - else - ls(dent->d_name, &sb); - } - closedir(dir); - - fchdir(oldcwd); - close(oldcwd); - } - -out: - disk_close(); - return 0; -} - -#define lsrwx(mode,s) \ - putchar ((mode) & S_IROTH? 'r' : '-'); \ - putchar ((mode) & S_IWOTH? 'w' : '-'); \ - putchar ((mode) & S_IXOTH? *(s): (s)[1]); - -static void -ls(const char *name, struct stat *sb) -{ - putchar("-fc-d-b---l-s-w-"[(sb->st_mode & S_IFMT) >> 12]); - lsrwx(sb->st_mode >> 6, (sb->st_mode & S_ISUID? "sS" : "x-")); - lsrwx(sb->st_mode >> 3, (sb->st_mode & S_ISGID? "sS" : "x-")); - lsrwx(sb->st_mode , (sb->st_mode & S_ISTXT? "tT" : "x-")); - - printf (" %u,%u\t%lu\t%s\n", sb->st_uid, sb->st_gid, - (u_long)sb->st_size, name); -} -#undef lsrwx - -int doboot = 1; - -static int -Xnop(void) -{ - if (doboot) { - doboot = 0; - return (Xboot()); - } - - return 0; -} - -static int -Xboot(void) -{ - if (cmd.argc > 1 && cmd.argv[1][0] != '-') { - qualify((cmd.argv[1]? cmd.argv[1]: cmd.image)); - if (bootparse(2)) - return 0; - } else { - if (bootparse(1)) - return 0; - snprintf(cmd.path, sizeof cmd.path, "%s:%s", - cmd.bootdev, cmd.image); - } - - return 1; -} - -/* - * Qualifies the path adding necessary dev - */ - -static char * -qualify(char *name) -{ - char *p; - - for (p = name; *p; p++) - if (*p == ':') - break; - if (*p == ':') - strlcpy(cmd.path, name, sizeof(cmd.path)); - else - snprintf(cmd.path, sizeof cmd.path, "%s:%s", - cmd.bootdev, name); - return cmd.path; -} - -static int -Xreboot(void) -{ - printf("Rebooting...\n"); - reboot(0); - return 0; /* just in case */ -} - -int -upgrade(void) -{ - struct stat sb; - const char *path; - int ret = 0; - - path = disk_open(qualify("/bsd.upgrade")); - if (path == NULL) - return 0; - if (stat(path, &sb) == 0 && S_ISREG(sb.st_mode)) - ret = 1; - disk_close(); - - return ret; -} diff --git a/sys/arch/octeon/stand/rdboot/cmd.h b/sys/arch/octeon/stand/rdboot/cmd.h deleted file mode 100644 index 1ffafde59ef..00000000000 --- a/sys/arch/octeon/stand/rdboot/cmd.h +++ /dev/null @@ -1,65 +0,0 @@ -/* $OpenBSD: cmd.h,v 1.1 2019/07/17 14:36:32 visa Exp $ */ - -/* - * Copyright (c) 1997 Michael Shalayeff - * 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 THE REGENTS 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. - * - */ - -#define CMD_BUFF_SIZE 133 -#define BOOTDEVLEN 1024 - -struct cmd_table { - char *cmd_name; - char cmd_type; -#define CMDT_CMD 0 -#define CMDT_VAR 1 -#define CMDT_SET 2 -#define CMDT_MDC 3 - int (*cmd_exec)(void); -}; - -struct cmd_state { - char bootdev[BOOTDEVLEN]; /* device */ - char image[MAXPATHLEN - 16]; /* image */ - unsigned char bootduid[8]; /* duid of root disk */ - int boothowto; /* howto */ - int hasduid; - char *conf; /* /etc/boot.conf normally */ - int timeout; - - char path[MAXPATHLEN]; /* buffer for pathname compose */ - const struct cmd_table *cmd; - int argc; - char *argv[8]; /* XXX i hope this is enough */ -}; -extern struct cmd_state cmd; - -int getcmd(void); -int read_conf(void); -int bootparse(int); -void boot(dev_t); - -int upgrade(void); -int docmd(void); /* No longer static: needed by regress test */ diff --git a/sys/arch/octeon/stand/rdboot/disk.c b/sys/arch/octeon/stand/rdboot/disk.c deleted file mode 100644 index eda089bc34f..00000000000 --- a/sys/arch/octeon/stand/rdboot/disk.c +++ /dev/null @@ -1,208 +0,0 @@ -/* $OpenBSD: disk.c,v 1.2 2020/05/26 13:30:47 visa Exp $ */ - -/* - * Copyright (c) 2019 Visa Hankala - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include <sys/types.h> -#include <sys/param.h> -#include <sys/disklabel.h> -#include <sys/dkio.h> -#include <sys/ioctl.h> -#include <sys/mount.h> -#include <sys/stat.h> -#include <sys/sysctl.h> - -#include <err.h> -#include <errno.h> -#include <fcntl.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> -#include <util.h> - -#include "cmd.h" - -int disk_proberoot(const char *); - -int mounted = 0; -int rdroot = -1; /* fd that points to the root of the ramdisk */ - -void -disk_init(void) -{ - char rootdevs[1024]; - char *devname, *disknames, *ptr; - size_t size; - int mib[2]; - - rdroot = open("/", O_RDONLY); - if (rdroot == -1) - err(1, "failed to open root directory fd"); - - if (strlen(cmd.bootdev) != 0) - return; - - mib[0] = CTL_HW; - mib[1] = HW_DISKNAMES; - size = 0; - if (sysctl(mib, 2, NULL, &size, NULL, 0) == -1) { - fprintf(stderr, "%s: cannot get hw.disknames: %s\n", __func__, - strerror(errno)); - return; - } - disknames = malloc(size); - if (disknames == NULL) { - fprintf(stderr, "%s: out of memory\n", __func__); - return; - } - if (sysctl(mib, 2, disknames, &size, NULL, 0) == -1) { - fprintf(stderr, "%s: cannot get hw.disknames: %s\n", __func__, - strerror(errno)); - free(disknames); - return; - } - - printf("probing disks\n"); - rootdevs[0] = '\0'; - ptr = disknames; - while ((devname = strsep(&ptr, ",")) != NULL) { - char *duid; - - duid = strchr(devname, ':'); - if (duid == NULL) - continue; - *duid++ = '\0'; - - /* Disk without a duid cannot be a root device. */ - if (strlen(duid) == 0) - continue; - - if (disk_proberoot(devname)) { - if (strlen(cmd.bootdev) == 0) { - snprintf(cmd.bootdev, sizeof(cmd.bootdev), - "%sa", devname); - } - (void)strlcat(rootdevs, " ", sizeof(rootdevs)); - (void)strlcat(rootdevs, devname, sizeof(rootdevs)); - } - } - if (strlen(rootdevs) != 0) - printf("available root devices:%s\n", rootdevs); - else - printf("no root devices found\n"); -} - -int -disk_proberoot(const char *devname) -{ - static const char *const names[] = { - "bin", "dev", "etc", "home", "mnt", "root", "sbin", "tmp", - "usr", "var", NULL - }; - struct ufs_args ffs_args; - struct stat st; - char path[32]; - int i, is_root = 1; - - snprintf(path, sizeof(path), "/dev/%sa", devname); - memset(&ffs_args, 0, sizeof(ffs_args)); - ffs_args.fspec = path; - if (mount(MOUNT_FFS, "/mnt", MNT_RDONLY, &ffs_args) == -1) - return 0; - for (i = 0; names[i] != NULL; i++) { - snprintf(path, sizeof(path), "/mnt/%s", names[i]); - if (stat(path, &st) == -1 || !S_ISDIR(st.st_mode)) { - is_root = 0; - break; - } - } - (void)unmount("/mnt", 0); - - return is_root; -} - -const char * -disk_open(const char *path) -{ - struct ufs_args ffs_args; - struct disklabel label; - char devname[32]; - char *devpath; - const char *ptr; - int fd; - - if (mounted) { - fprintf(stderr, "%s: cannot nest\n", __func__); - return NULL; - } - - ptr = strchr(path, ':'); - if (ptr != NULL) { - snprintf(devname, sizeof(devname), "%.*s", - (int)(ptr - path), path); - ptr++; /* skip ':' */ - } else { - strlcpy(devname, cmd.bootdev, sizeof(devname)); - ptr = path; - } - if (strlen(devname) == 0) { - fprintf(stderr, "no device specified\n"); - return NULL; - } - - cmd.hasduid = 0; - fd = opendev(devname, O_RDONLY, OPENDEV_BLCK, &devpath); - if (fd != -1) { - if (ioctl(fd, DIOCGDINFO, &label) != -1) { - memcpy(cmd.bootduid, label.d_uid, 8); - cmd.hasduid = 1; - } - close(fd); - } else { - fprintf(stderr, "failed to open device %s: %s\n", devname, - strerror(errno)); - return NULL; - } - - memset(&ffs_args, 0, sizeof(ffs_args)); - ffs_args.fspec = devpath; - if (mount(MOUNT_FFS, "/mnt", MNT_FORCE | MNT_NOATIME, - &ffs_args) == -1) { - fprintf(stderr, "failed to mount %s: %s\n", devpath, - strerror(errno)); - return NULL; - } - if (chroot("/mnt") == -1) { - fprintf(stderr, "failed to chroot: %s\n", strerror(errno)); - (void)unmount("/mnt", 0); - return NULL; - } - mounted = 1; - - return ptr; -} - -void -disk_close(void) -{ - if (mounted) { - (void)fchdir(rdroot); - (void)chroot("."); - mounted = 0; - (void)unmount("/mnt", 0); - } -} diff --git a/sys/arch/octeon/stand/rdboot/disk.h b/sys/arch/octeon/stand/rdboot/disk.h deleted file mode 100644 index ac0d1879bb0..00000000000 --- a/sys/arch/octeon/stand/rdboot/disk.h +++ /dev/null @@ -1,21 +0,0 @@ -/* $OpenBSD: disk.h,v 1.1 2019/07/17 14:36:32 visa Exp $ */ - -/* - * Copyright (c) 2019 Visa Hankala - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -void disk_init(void); -const char *disk_open(const char *); -void disk_close(void); diff --git a/sys/arch/octeon/stand/rdboot/rdboot.c b/sys/arch/octeon/stand/rdboot/rdboot.c index 850279c42a4..136d2c89003 100644 --- a/sys/arch/octeon/stand/rdboot/rdboot.c +++ b/sys/arch/octeon/stand/rdboot/rdboot.c @@ -1,9 +1,9 @@ /* $OpenBSD: rdboot.c,v 1.8 2020/12/09 18:10:19 krw Exp $ */ /* - * Copyright (c) 2019-2020 Visa Hankala + * Copyright (c) 2019-2022 Visa Hankala * - * Permission to use, copy, modify, and/or distribute this software for any + * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * @@ -19,10 +19,8 @@ #include <sys/types.h> #include <sys/param.h> #include <sys/ioctl.h> -#include <sys/mount.h> #include <sys/reboot.h> -#include <sys/select.h> -#include <sys/stat.h> +#include <sys/sysctl.h> #include <err.h> #include <errno.h> @@ -36,28 +34,25 @@ #include <util.h> #include <machine/octboot.h> -#include <machine/param.h> -#include "cmd.h" -#include "disk.h" +#define BOOTDEVLEN 1024 -#define DEVRANDOM "/dev/random" -#define BOOTRANDOM "/etc/random.seed" -#define BOOTRANDOM_MAX 256 /* no point being greater than RC4STATE */ -#define KERNEL "/bsd" +void findroot(char *, size_t); -int loadrandom(void); -void kexec(void); +void saboot_boot(int); +void saboot_cninit(void); +int saboot_proberoot(const char *); -struct cmd_state cmd; +char rootdev[32]; int octbootfd = -1; -const char version[] = "1.3"; + +extern unsigned char bootduid[]; +extern int bootduidvalid; int main(void) { - char rootdev[PATH_MAX]; - int fd, hasboot; + int fd; fd = open(_PATH_CONSOLE, O_RDWR); login_tty(fd); @@ -65,179 +60,140 @@ main(void) /* Keep stdout unbuffered to mimic ordinary bootblocks. */ setvbuf(stdout, NULL, _IONBF, 0); - printf(">> OpenBSD/" MACHINE " BOOT %s\n", version); - octbootfd = open("/dev/octboot", O_WRONLY); if (octbootfd == -1) err(1, "cannot open boot control device"); - memset(&cmd, 0, sizeof(cmd)); - cmd.boothowto = 0; - cmd.conf = "/etc/boot.conf"; - strlcpy(cmd.image, KERNEL, sizeof(cmd.image)); - cmd.timeout = 5; + saboot_cninit(); + saboot_boot(0); + reboot(RB_AUTOBOOT | RB_TIMEBAD); + + return 0; +} + +void +machdep(void) +{ if (ioctl(octbootfd, OBIOC_GETROOTDEV, rootdev) == -1) { - if (errno != ENOENT) + if (errno != ENOENT) { fprintf(stderr, "cannot get rootdev from kernel: %s\n", strerror(errno)); + } + findroot(rootdev, sizeof(rootdev)); } else { - snprintf(cmd.bootdev, sizeof(cmd.bootdev), "%s%sa", - rootdev, isduid(rootdev, OPENDEV_PART) ? "." : ""); + if (isduid(rootdev, OPENDEV_PART)) + (void)strlcat(rootdev, ".", sizeof(rootdev)); + (void)strlcat(rootdev, "a", sizeof(rootdev)); } +} - disk_init(); - - if (upgrade()) { - strlcpy(cmd.image, "/bsd.upgrade", sizeof(cmd.image)); - printf("upgrade detected: switching to %s\n", cmd.image); +void +findroot(char *rootdev, size_t rootdevlen) +{ + char rootdevs[1024]; + char devname[32]; + char *diskname, *disknames, *ptr; + size_t size; + int mib[2]; + + mib[0] = CTL_HW; + mib[1] = HW_DISKNAMES; + size = 0; + if (sysctl(mib, 2, NULL, &size, NULL, 0) == -1) { + fprintf(stderr, "%s: cannot get hw.disknames: %s\n", __func__, + strerror(errno)); + return; + } + disknames = malloc(size); + if (disknames == NULL) { + fprintf(stderr, "%s: out of memory\n", __func__); + return; + } + if (sysctl(mib, 2, disknames, &size, NULL, 0) == -1) { + fprintf(stderr, "%s: cannot get hw.disknames: %s\n", __func__, + strerror(errno)); + free(disknames); + return; } - hasboot = read_conf(); - - for (;;) { - if (hasboot <= 0) { - do { - printf("boot> "); - } while (!getcmd()); + printf("probing disks\n"); + rootdevs[0] = '\0'; + ptr = disknames; + while ((diskname = strsep(&ptr, ",")) != NULL) { + char *duid; + + duid = strchr(diskname, ':'); + if (duid == NULL) + continue; + *duid++ = '\0'; + + /* Disk without a duid cannot contain a root device. */ + if (strlen(duid) == 0) + continue; + + snprintf(devname, sizeof(devname), "%sa", diskname); + if (saboot_proberoot(devname)) { + if (strlen(rootdev) == 0) + (void)strlcpy(rootdev, devname, rootdevlen); + (void)strlcat(rootdevs, " ", sizeof(rootdevs)); + (void)strlcat(rootdevs, devname, sizeof(rootdevs)); } - - if (loadrandom() == 0) - cmd.boothowto |= RB_GOODRANDOM; - - kexec(); - - hasboot = 0; - strlcpy(cmd.image, KERNEL, sizeof(cmd.image)); - printf("will try %s\n", cmd.image); + } + if (strlen(rootdevs) != 0) { + printf("available root devices:%s\n", rootdevs); + } else { + printf("no root devices found\n"); + (void)strlcpy(rootdev, "sd0a", sizeof(rootdev)); } - return 0; + free(disknames); } -int -loadrandom(void) +void +devboot(dev_t dev, char *bootdev) { - char buf[BOOTRANDOM_MAX]; - struct stat sb; - int fd, ret = 0; - - /* Read the file from the device specified by the kernel path. */ - if (disk_open(cmd.path) == NULL) - return -1; - fd = open(BOOTRANDOM, O_RDONLY); - if (fd == -1) { - fprintf(stderr, "%s: cannot open %s: %s", __func__, BOOTRANDOM, - strerror(errno)); - disk_close(); - return -1; - } - if (fstat(fd, &sb) == 0) { - if (sb.st_mode & S_ISTXT) { - printf("NOTE: random seed is being reused.\n"); - ret = -1; - } - if (read(fd, buf, sizeof(buf)) != sizeof(buf)) - ret = -1; - fchmod(fd, sb.st_mode | S_ISTXT); - } else { - ret = -1; - } - close(fd); - disk_close(); - - /* - * Push the whole buffer to the entropy pool. - * The kernel will use the entropy on kexec(). - * It does not matter if some of the buffer content is uninitialized. - */ - fd = open(DEVRANDOM, O_WRONLY); - if (fd == -1) { - fprintf(stderr, "%s: cannot open %s: %s", __func__, - DEVRANDOM, strerror(errno)); - return -1; - } - write(fd, buf, sizeof(buf)); - close(fd); - return ret; + strlcpy(bootdev, rootdev, BOOTDEVLEN); } void -kexec(void) +_rtt(void) +{ + reboot(RB_AUTOBOOT | RB_TIMEBAD); +} + +void +hexdump(const void *addr, size_t size) +{ + /* Not worth it. There are better ways to study the system. */ + printf("not implemented\n"); +} + +int +ukexec(void *kimg, size_t klen, int howto) { struct octboot_kexec_args kargs; - struct stat sb; char boothowtostr[32]; char rootdev[32]; - char *kimg = NULL; - const char *path; - ssize_t n; - off_t pos; - int argc, fd = -1, ret; - - path = disk_open(cmd.path); - if (path == NULL) - return; - - fd = open(path, O_RDONLY); - if (fd == -1) - goto load_failed; - if (fstat(fd, &sb) == -1) - goto load_failed; - if (!S_ISREG(sb.st_mode) || sb.st_size == 0) { - errno = ENOEXEC; - goto load_failed; - } - - kimg = malloc(sb.st_size); - if (kimg == NULL) - goto load_failed; - - pos = 0; - while (pos < sb.st_size) { - n = read(fd, kimg + pos, sb.st_size - pos); - if (n == -1) - goto load_failed; - pos += n; - } - - close(fd); - disk_close(); + int argc = 0; memset(&kargs, 0, sizeof(kargs)); kargs.kimg = kimg; - kargs.klen = sb.st_size; - argc = 0; - if (cmd.boothowto != 0) { + kargs.klen = klen; + if (howto != 0) { snprintf(boothowtostr, sizeof(boothowtostr), "boothowto=%d", - cmd.boothowto); + howto); kargs.argv[argc++] = boothowtostr; } - if (cmd.hasduid) { + if (bootduidvalid) { snprintf(rootdev, sizeof(rootdev), "rootdev=%02x%02x%02x%02x%02x%02x%02x%02x", - cmd.bootduid[0], cmd.bootduid[1], - cmd.bootduid[2], cmd.bootduid[3], - cmd.bootduid[4], cmd.bootduid[5], - cmd.bootduid[6], cmd.bootduid[7]); + bootduid[0], bootduid[1], + bootduid[2], bootduid[3], + bootduid[4], bootduid[5], + bootduid[6], bootduid[7]); kargs.argv[argc++] = rootdev; } - printf("booting %s\n", cmd.path); - ret = ioctl(octbootfd, OBIOC_KEXEC, &kargs); - if (ret == -1) - fprintf(stderr, "failed to execute kernel %s: %s\n", - cmd.path, strerror(errno)); - else - fprintf(stderr, "kexec() returned unexpectedly\n"); - free(kimg); - return; - -load_failed: - fprintf(stderr, "failed to load kernel %s: %s\n", - cmd.path, strerror(errno)); - if (fd != -1) - close(fd); - disk_close(); - free(kimg); + return ioctl(octbootfd, OBIOC_KEXEC, &kargs); } diff --git a/sys/arch/octeon/stand/rdboot/unixcall.c b/sys/arch/octeon/stand/rdboot/unixcall.c new file mode 100644 index 00000000000..b4aa25c4cea --- /dev/null +++ b/sys/arch/octeon/stand/rdboot/unixcall.c @@ -0,0 +1,153 @@ +/* $OpenBSD$ */ + +/* + * Copyright (c) 2022 Visa Hankala + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <sys/types.h> +#include <sys/disklabel.h> +#include <sys/dkio.h> +#include <sys/ioctl.h> +#include <errno.h> +#include <fcntl.h> +#include <poll.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <termios.h> +#include <time.h> +#include <unistd.h> +#include <util.h> + +#include "unixcall.h" + +unsigned char bootduid[8]; +int bootduidvalid; + +time_t +getsecs(void) +{ + return time(NULL); +} + +void +ucninit(void) +{ + struct termios tio; + + tcgetattr(STDIN_FILENO, &tio); + cfmakeraw(&tio); + tio.c_iflag = ICRNL|IXANY; + tio.c_oflag = OPOST|ONLCR; + tio.c_cflag = CREAD|CS8|HUPCL; + tio.c_cc[VMIN] = 1; + tio.c_cc[VTIME] = 0; + tcsetattr(STDIN_FILENO, TCSANOW, &tio); +} + +int +ucngetc(int dopoll) +{ + struct pollfd pfd[1]; + int ret; + char b; + + pfd[0].fd = STDIN_FILENO; + pfd[0].events = POLLIN; + + for (;;) { + ret = poll(pfd, 1, dopoll ? 0 : -1); + if (dopoll) + return ret > 0; + if (ret > 0) { + if (read(STDIN_FILENO, &b, 1) < 1) + return -1; + return b; + } + } +} + +void +ucnputc(int c) +{ + char b = c; + + write(STDOUT_FILENO, &b, 1); +} + +int +udiskopen(const char *devname, int *pfd) +{ + struct disklabel label; + + if (*devname == '\0' || *devname == '/') + return ENODEV; + *pfd = opendev(devname, O_RDWR, 0, NULL); + if (*pfd == -1) + return errno; + + memset(bootduid, 0, sizeof(bootduid)); + bootduidvalid = 0; + if (ioctl(*pfd, DIOCGDINFO, &label) != -1) { + memcpy(bootduid, label.d_uid, sizeof(bootduid)); + bootduidvalid = 1; + } + + return 0; +} + +void +udiskclose(int fd) +{ + close(fd); +} + +int +udiskread(int fd, void *buf, size_t nbytes, off_t offset, size_t *rbytes) +{ + ssize_t n; + + n = pread(fd, buf, nbytes, offset); + if (n < 0) + return errno; + if (rbytes != NULL) + *rbytes = n; + return 0; +} + +int +udiskwrite(int fd, const void *buf, size_t nbytes, off_t offset, size_t *wbytes) +{ + ssize_t n; + + n = pwrite(fd, buf, nbytes, offset); + if (n < 0) + return errno; + if (wbytes != NULL) + *wbytes = n; + return 0; +} + +void * +umalloc(size_t size) +{ + return malloc(size); +} + +void +ufree(void *ptr) +{ + free(ptr); +} diff --git a/sys/arch/octeon/stand/rdboot/vars.c b/sys/arch/octeon/stand/rdboot/vars.c deleted file mode 100644 index 926c8a6cb16..00000000000 --- a/sys/arch/octeon/stand/rdboot/vars.c +++ /dev/null @@ -1,203 +0,0 @@ -/* $OpenBSD: vars.c,v 1.1 2019/07/17 14:36:32 visa Exp $ */ - -/* - * Copyright (c) 1998-2000 Michael Shalayeff - * 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 THE REGENTS 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 MIND, 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/param.h> -#include <sys/reboot.h> - -#include <limits.h> -#include <stdio.h> -#include <string.h> -#include <stdlib.h> - -#include "cmd.h" - -extern int debug; -int db_console = -1; - -static int Xdevice(void); -#ifdef DEBUG -static int Xdebug(void); -#endif -static int Xdb_console(void); -static int Ximage(void); -static int Xhowto(void); -static int Xtimeout(void); -int Xset(void); - -const struct cmd_table cmd_set[] = { - {"howto", CMDT_VAR, Xhowto}, -#ifdef DEBUG - {"debug", CMDT_VAR, Xdebug}, -#endif - {"device", CMDT_VAR, Xdevice}, - {"image", CMDT_VAR, Ximage}, - {"timeout",CMDT_VAR, Xtimeout}, - {"db_console", CMDT_VAR, Xdb_console}, - {NULL,0} -}; - -#ifdef DEBUG -static int -Xdebug(void) -{ - if (cmd.argc != 2) - printf( "o%s\n", debug? "n": "ff" ); - else - debug = (cmd.argv[1][0] == '0' || - (cmd.argv[1][0] == 'o' && cmd.argv[1][1] == 'f'))? - 0: 1; - return 0; -} -#endif - -int -Xdb_console(void) -{ - if (cmd.argc != 2) { - switch (db_console) { - case 0: - printf("off\n"); - break; - case 1: - printf("on\n"); - break; - default: - printf("unset\n"); - break; - } - } else { - if (strcmp(cmd.argv[1], "0") == 0 || - strcmp(cmd.argv[1], "off") == 0) - db_console = 0; - else if (strcmp(cmd.argv[1], "1") == 0 || - strcmp(cmd.argv[1], "on") == 0) - db_console = 1; - } - - return (0); -} - -static int -Xtimeout(void) -{ - if (cmd.argc != 2) - printf( "%d\n", cmd.timeout ); - else - cmd.timeout = (int)strtol( cmd.argv[1], (char **)NULL, 0 ); - return 0; -} - -/* called only w/ no arguments */ -int -Xset(void) -{ - const struct cmd_table *ct; - - printf("boot\n"); - for (ct = cmd_set; ct->cmd_name != NULL; ct++) { - printf("%s\t ", ct->cmd_name); - (*ct->cmd_exec)(); - } - return 0; -} - -static int -Xdevice(void) -{ - if (cmd.argc != 2) - printf("%s\n", cmd.bootdev); - else - strlcpy(cmd.bootdev, cmd.argv[1], sizeof(cmd.bootdev)); - return 0; -} - -static int -Ximage(void) -{ - if (cmd.argc != 2) - printf("%s\n", cmd.image); - else - strlcpy(cmd.image, cmd.argv[1], sizeof(cmd.image)); - return 0; -} - -static int -Xhowto(void) -{ - if (cmd.argc == 1) { - if (cmd.boothowto) { - putchar('-'); - if (cmd.boothowto & RB_ASKNAME) - putchar('a'); - if (cmd.boothowto & RB_CONFIG) - putchar('c'); - if (cmd.boothowto & RB_SINGLE) - putchar('s'); - if (cmd.boothowto & RB_KDB) - putchar('d'); - } - putchar('\n'); - } else - bootparse(1); - return 0; -} - -int -bootparse(int i) -{ - char *cp; - int howto = cmd.boothowto; - - for (; i < cmd.argc; i++) { - cp = cmd.argv[i]; - if (*cp == '-') { - while (*++cp) { - switch (*cp) { - case 'a': - howto |= RB_ASKNAME; - break; - case 'c': - howto |= RB_CONFIG; - break; - case 's': - howto |= RB_SINGLE; - break; - case 'd': - howto |= RB_KDB; - break; - default: - printf("howto: bad option: %c\n", *cp); - return 1; - } - } - } - } - cmd.boothowto = howto; - return 0; -} diff --git a/sys/arch/octeon/stand/saboot/Makefile b/sys/arch/octeon/stand/saboot/Makefile new file mode 100644 index 00000000000..73a328c8027 --- /dev/null +++ b/sys/arch/octeon/stand/saboot/Makefile @@ -0,0 +1,64 @@ +# $OpenBSD$ + +NOMAN= + +.if ${MACHINE} == "octeon" +PROG= saboot.elf + +NM?= nm +OBJCOPY?= objcopy + +S= ${.CURDIR}/../../../.. + +CFLAGS+= -Wall -ffreestanding -D_STANDALONE -nostdinc -fno-builtin +CFLAGS+= -I${.CURDIR} +CFLAGS+= -I${.OBJDIR} +CFLAGS+= -I${S} +CFLAGS+= -I${S}/lib/libsa + +LDFLAGS= -nostdlib + +SRCS= conf.c devopen.c loadfile.c saboot.c + +.PATH: ${S}/stand/boot +SRCS+= boot.c cmd.c vars.c + +.PATH: ${S}/lib/libsa +SRCS+= cons.c ctime.c exit.c getchar.c getfile.c getln.c globals.c \ + memcmp.c memcpy.c memmove.c memset.c printf.c putchar.c \ + snprintf.c strchr.c strcmp.c strerror.c strlen.c strncmp.c \ + strncpy.c strtol.c strtoll.c +SRCS+= close.c closeall.c dev.c disklabel.c dkcksum.c \ + fchmod.c fstat.c ioctl.c lseek.c open.c read.c readdir.c \ + stat.c write.c +SRCS+= arc4.c +SRCS+= ufs.c ufs2.c + +REMAP_OBJ= ${PROG}.tmp +CLEANFILES+= ${REMAP_OBJ} + +REMAP_LIST= ${PROG}.map +CLEANFILES+= ${REMAP_LIST} + +# Build a relocatable object. +# Add a prefix to the names of defined symbols so as to avoid name collisions +# when linking with libc in the next step. +${PROG}: ${OBJS} + ${CC} ${LDFLAGS} -r -o ${REMAP_OBJ} ${OBJS} + ${NM} -g ${REMAP_OBJ} | awk '$$1 != "U" && $$2 != "F" {printf("%s saboot_%s\n", $$3, $$3)}' > ${REMAP_LIST} + ${OBJCOPY} --redefine-syms=${REMAP_LIST} ${REMAP_OBJ} ${PROG} + +install: + +.if !make(clean) && !make(cleandir) && !make(includes) && !make(obj) +.BEGIN: + @([ -h machine ] || ln -s ${.CURDIR}/../../include machine) + @([ -h mips64 ] || ln -s ${.CURDIR}/../../../mips64/include mips64) +CLEANFILES+= machine mips64 +.endif + +.else +NOPROG= +.endif + +.include <bsd.prog.mk> diff --git a/sys/arch/octeon/stand/saboot/conf.c b/sys/arch/octeon/stand/saboot/conf.c new file mode 100644 index 00000000000..a4e21f775ad --- /dev/null +++ b/sys/arch/octeon/stand/saboot/conf.c @@ -0,0 +1,41 @@ +/* $OpenBSD$ */ + +/* + * Copyright (c) 2022 Visa Hankala + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <sys/param.h> +#include <dev/cons.h> + +#include "libsa.h" +#include <lib/libsa/ufs.h> +#include <lib/libsa/ufs2.h> + +const char version[] = "2.0"; + +struct fs_ops file_system[] = { + /* ufs filesystem */ + { ufs_open, ufs_close, ufs_read, ufs_write, + ufs_seek, ufs_stat, ufs_readdir, ufs_fchmod }, + { ufs2_open, ufs2_close, ufs2_read, ufs2_write, + ufs2_seek, ufs2_stat, ufs2_readdir, ufs2_fchmod }, +}; +int nfsys = nitems(file_system); + +struct consdev constab[] = { + { unix_cnprobe, unix_cninit, unix_cngetc, unix_cnputc }, + { NULL } +}; +struct consdev *cn_tab = constab; diff --git a/sys/arch/octeon/stand/saboot/devopen.c b/sys/arch/octeon/stand/saboot/devopen.c new file mode 100644 index 00000000000..ce378fe335c --- /dev/null +++ b/sys/arch/octeon/stand/saboot/devopen.c @@ -0,0 +1,89 @@ +/* $OpenBSD$ */ + +/* + * Copyright (c) 2022 Visa Hankala + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <sys/param.h> + +#include "libsa.h" +#include "unixcall.h" + +int diskstrategy(void *, int, daddr_t, size_t, void *, size_t *); +int diskclose(struct open_file *); + +static struct devsw disk = { + .dv_name = "disk", + .dv_strategy = diskstrategy, + .dv_close = diskclose, +}; + +int +diskstrategy(void *devdata, int rw, daddr_t bn, size_t reqcnt, + void *buf, size_t *cnt) +{ + off_t offs; + int error, fd; + + fd = (int)(intptr_t)devdata; + offs = bn * DEV_BSIZE; + switch (rw) { + case F_READ: + error = udiskread(fd, buf, reqcnt, offs, cnt); + break; + case F_WRITE: + error = udiskwrite(fd, buf, reqcnt, offs, cnt); + break; + default: + error = EINVAL; + break; + } + return error; +} + +int +diskclose(struct open_file *f) +{ + int fd = (int)(intptr_t)f->f_devdata; + + udiskclose(fd); + return 0; +} + +#define MAXDEVNAME 24 + +int +devopen(struct open_file *f, const char *fname, char **file) +{ + char devname[MAXDEVNAME]; + const char *ptr; + int error, fd; + + ptr = strchr(fname, ':'); + if (ptr == NULL) + return ENODEV; + if (ptr - fname >= sizeof(devname)) + return EINVAL; + memcpy(devname, fname, ptr - fname); + devname[ptr - fname] = '\0'; + + error = udiskopen(devname, &fd); + if (error != 0) + return error; + *file = (char *)(ptr + 1); + f->f_dev = &disk; + f->f_devdata = (void *)(intptr_t)fd; + return 0; +} diff --git a/sys/arch/octeon/stand/saboot/libsa.h b/sys/arch/octeon/stand/saboot/libsa.h new file mode 100644 index 00000000000..40fd48cb79e --- /dev/null +++ b/sys/arch/octeon/stand/saboot/libsa.h @@ -0,0 +1,30 @@ +/* $OpenBSD$ */ + +/* + * Copyright (c) 2022 Visa Hankala + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <lib/libsa/stand.h> + +#define DEFAULT_KERNEL_ADDRESS 0 + +void devboot(dev_t, char *); +void machdep(void); +void run_loadfile(uint64_t *, int); + +void unix_cnprobe(struct consdev *); +void unix_cninit(struct consdev *); +int unix_cngetc(dev_t); +void unix_cnputc(dev_t, int); diff --git a/sys/arch/octeon/stand/saboot/loadfile.c b/sys/arch/octeon/stand/saboot/loadfile.c new file mode 100644 index 00000000000..1d03e5330e4 --- /dev/null +++ b/sys/arch/octeon/stand/saboot/loadfile.c @@ -0,0 +1,115 @@ +/* $OpenBSD$ */ + +/* + * Copyright (c) 2022 Visa Hankala + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <sys/param.h> +#include <sys/exec_elf.h> + +#include <lib/libsa/stand.h> + +#include "unixcall.h" + +static void *kernbuf; +static size_t kernsize; + +int +loadfile(const char *fname, uint64_t *marks, int flags) +{ + struct stat sb; + char *buf = NULL; + size_t pos, size = 0; + ssize_t nread; + int fd; + + free(kernbuf, kernsize); + kernbuf = NULL; + kernsize = 0; + + fd = open(fname, O_RDONLY); + if (fd < 0) { + printf("cannot open %s: %s\n", fname, strerror(errno)); + return -1; + } + if (fstat(fd, &sb) < 0) { + printf("fstat(): %s\n", strerror(errno)); + goto fail; + } + size = sb.st_size; + if (size < sizeof(Elf_Ehdr)) { + printf("not ELF file\n"); + goto fail; + } + + buf = alloc(size); + if (buf == NULL) { + printf("cannot allocate %zu bytes: %s\n", size, + strerror(errno)); + goto fail; + } + + pos = 0; + while (pos < size) { + nread = read(fd, buf + pos, size - pos); + if (nread < 0) { + printf("read(): %s\n", fname, strerror(errno)); + goto fail; + } + if (nread == 0) { + printf("short read\n"); + goto fail; + } + pos += nread; + } + + /* + * Screen non-ELF files. + * More proper validation is done at kexec time. + */ + if (buf[0] != ELFMAG0 || buf[1] != ELFMAG1 || + buf[2] != ELFMAG2 || buf[3] != ELFMAG3) { + printf("not ELF file\n"); + goto fail; + } + + printf("loading done\n"); + + kernbuf = buf; + kernsize = size; + return fd; +fail: + free(buf, size); + close(fd); + return -1; +} + +void +run_loadfile(uint64_t *marks, int howto) +{ + if (kernbuf == NULL) { + printf("no kernel loaded\n"); + return; + } + + if (ukexec(kernbuf, kernsize, howto) == -1) + printf("kexec(): %s\n", strerror(errno)); + else + printf("kexec() returned unexpectedly\n"); + + free(kernbuf, kernsize); + kernbuf = NULL; + kernsize = 0; +} diff --git a/sys/arch/octeon/stand/saboot/saboot.c b/sys/arch/octeon/stand/saboot/saboot.c new file mode 100644 index 00000000000..5da6e8a9146 --- /dev/null +++ b/sys/arch/octeon/stand/saboot/saboot.c @@ -0,0 +1,101 @@ +/* $OpenBSD$ */ + +/* + * Copyright (c) 2022 Visa Hankala + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <sys/param.h> +#include <dev/cons.h> + +#include "libsa.h" +#include "unixcall.h" + +int +cnspeed(dev_t dev, int sp) +{ + return 115200; +} + +char * +ttyname(int fd) +{ + return "com0"; +} + +dev_t +ttydev(char *name) +{ + if (strcmp(name, "com0") != 0) + return NODEV; + return makedev(0, 0); +} + +void +unix_cnprobe(struct consdev *cn) +{ + cn->cn_pri = CN_HIGHPRI; +} + +void +unix_cninit(struct consdev *cn) +{ + ucninit(); +} + +int +unix_cngetc(dev_t dev) +{ + int dopoll = ((dev & 0x80) != 0); + + return ucngetc(dopoll); +} + +void +unix_cnputc(dev_t dev, int c) +{ + ucnputc(c); +} + +void * +alloc(unsigned int size) +{ + return umalloc(size); +} + +void +free(void *ptr, unsigned int size) +{ + ufree(ptr); +} + +int +proberoot(const char *devname) +{ + static const char *const names[] = { + "bin", "dev", "etc", "home", "mnt", "root", "sbin", "tmp", + "usr", "var", NULL + }; + struct stat st; + char path[32]; + int i; + + for (i = 0; names[i] != NULL; i++) { + snprintf(path, sizeof(path), "%s:%s", devname, names[i]); + if (stat(path, &st) == -1 || !S_ISDIR(st.st_mode)) + return 0; + } + + return 1; +} diff --git a/sys/arch/octeon/stand/saboot/unixcall.h b/sys/arch/octeon/stand/saboot/unixcall.h new file mode 100644 index 00000000000..83ba14d2430 --- /dev/null +++ b/sys/arch/octeon/stand/saboot/unixcall.h @@ -0,0 +1,31 @@ +/* $OpenBSD$ */ + +/* + * Copyright (c) 2022 Visa Hankala + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +void ucninit(void); +int ucngetc(int); +void ucnputc(int); + +int udiskopen(const char *, int *); +void udiskclose(int); +int udiskread(int, void *, size_t, off_t, size_t *); +int udiskwrite(int, const void *, size_t, off_t, size_t *); + +void ufree(void *); +void *umalloc(size_t); + +int ukexec(void *, size_t, int);