1 /* $OpenBSD: boot.c,v 1.48 2019/04/10 19:41:03 florian Exp $ */ 2 3 /* 4 * Copyright (c) 2003 Dale Rahn 5 * Copyright (c) 1997,1998 Michael Shalayeff 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 19 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 * 29 */ 30 31 #include <sys/param.h> 32 #include <sys/reboot.h> 33 #include <sys/stat.h> 34 #include <libsa.h> 35 #include <lib/libsa/loadfile.h> 36 #include <lib/libkern/funcs.h> 37 38 #include <stand/boot/bootarg.h> 39 40 #include "cmd.h" 41 42 #ifndef KERNEL 43 #define KERNEL "/bsd" 44 #endif 45 46 char prog_ident[40]; 47 char *progname = "BOOT"; 48 49 extern const char version[]; 50 struct cmd_state cmd; 51 52 /* bootprompt can be set by MD code to avoid prompt first time round */ 53 int bootprompt = 1; 54 char *kernelfile = KERNEL; /* can be changed by MD code */ 55 int boottimeout = 5; /* can be changed by MD code */ 56 57 char rnddata[BOOTRANDOM_MAX]; 58 59 void 60 boot(dev_t bootdev) 61 { 62 int fd; 63 int try = 0, st; 64 uint64_t marks[MARK_MAX]; 65 66 machdep(); 67 68 snprintf(prog_ident, sizeof(prog_ident), 69 ">> OpenBSD/" MACHINE " %s %s", progname, version); 70 printf("%s\n", prog_ident); 71 72 devboot(bootdev, cmd.bootdev); 73 strlcpy(cmd.image, kernelfile, sizeof(cmd.image)); 74 cmd.boothowto = 0; 75 cmd.conf = "/etc/boot.conf"; 76 cmd.addr = (void *)DEFAULT_KERNEL_ADDRESS; 77 cmd.timeout = boottimeout; 78 79 if (upgrade()) { 80 strlcpy(cmd.image, "/bsd.upgrade", sizeof(cmd.image)); 81 printf("upgrade detected: switching to %s\n", cmd.image); 82 } 83 84 st = read_conf(); 85 86 #ifdef HIBERNATE 87 int bootdev_has_hibernate(void); 88 89 if (bootdev_has_hibernate()) { 90 strlcpy(cmd.image, "/bsd.booted", sizeof(cmd.image)); 91 printf("unhibernate detected: switching to %s\n", cmd.image); 92 } 93 #endif 94 95 if (!bootprompt) 96 snprintf(cmd.path, sizeof cmd.path, "%s:%s", 97 cmd.bootdev, cmd.image); 98 99 while (1) { 100 /* no boot.conf, or no boot cmd in there */ 101 if (bootprompt && st <= 0) { 102 do { 103 printf("boot> "); 104 } while(!getcmd()); 105 } 106 107 loadrandom(BOOTRANDOM, rnddata, sizeof(rnddata)); 108 #ifdef MDRANDOM 109 mdrandom(rnddata, sizeof(rnddata)); 110 #endif 111 #ifdef FWRANDOM 112 fwrandom(rnddata, sizeof(rnddata)); 113 #endif 114 115 st = 0; 116 bootprompt = 1; /* allow reselect should we fail */ 117 118 printf("booting %s: ", cmd.path); 119 marks[MARK_START] = (u_long)cmd.addr; 120 if ((fd = loadfile(cmd.path, marks, LOAD_ALL)) != -1) { 121 close(fd); 122 break; 123 } 124 125 kernelfile = KERNEL; 126 try++; 127 strlcpy(cmd.image, kernelfile, sizeof(cmd.image)); 128 printf(" failed(%d). will try %s\n", errno, kernelfile); 129 130 if (try < 2) { 131 if (cmd.timeout > 0) 132 cmd.timeout++; 133 } else { 134 if (cmd.timeout) 135 printf("Turning timeout off.\n"); 136 cmd.timeout = 0; 137 } 138 } 139 140 /* exec */ 141 run_loadfile(marks, cmd.boothowto); 142 } 143 144 void 145 loadrandom(char *name, char *buf, size_t buflen) 146 { 147 char path[MAXPATHLEN]; 148 struct stat sb; 149 int fd, i; 150 151 #define O_RDONLY 0 152 153 /* Extract the device name from the kernel we are loading. */ 154 for (i = 0; i < sizeof(cmd.path); i++) { 155 if (cmd.path[i] == ':') { 156 strlcpy(path, cmd.path, i + 1); 157 snprintf(path + i, sizeof(path) - i, ":%s", name); 158 break; 159 } else if (cmd.path[i] == '\0') { 160 snprintf(path, sizeof path, "%s:%s", 161 cmd.bootdev, name); 162 break; 163 } 164 } 165 166 fd = open(path, O_RDONLY); 167 if (fd == -1) { 168 if (errno != EPERM) 169 printf("cannot open %s: %s\n", path, strerror(errno)); 170 return; 171 } 172 if (fstat(fd, &sb) == -1 || 173 sb.st_uid != 0 || 174 (sb.st_mode & (S_IWOTH|S_IROTH))) 175 goto fail; 176 (void) read(fd, buf, buflen); 177 fail: 178 close(fd); 179 } 180