1 /* $OpenBSD: machdep.c,v 1.8 2014/07/13 09:26:08 jasper Exp $ */ 2 3 /* 4 * Copyright (c) 2010 Miodrag Vallat. 5 * 6 * Permission to use, copy, modify, and distribute this software for any 7 * purpose with or without fee is hereby granted, provided that the above 8 * copyright notice and this permission notice appear in all copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 */ 18 /* 19 * Copyright (c) 1998-2004 Michael Shalayeff 20 * All rights reserved. 21 * 22 * Redistribution and use in source and binary forms, with or without 23 * modification, are permitted provided that the following conditions 24 * are met: 25 * 1. Redistributions of source code must retain the above copyright 26 * notice, this list of conditions and the following disclaimer. 27 * 2. Redistributions in binary form must reproduce the above copyright 28 * notice, this list of conditions and the following disclaimer in the 29 * documentation and/or other materials provided with the distribution. 30 * 31 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 32 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 33 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 34 * IN NO EVENT SHALL THE AUTHOR OR HIS RELATIVES BE LIABLE FOR ANY DIRECT, 35 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 36 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 37 * SERVICES; LOSS OF MIND, USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 41 * THE POSSIBILITY OF SUCH DAMAGE. 42 */ 43 44 #include <sys/param.h> 45 #include <lib/libkern/libkern.h> 46 #include "libsa.h" 47 #include <machine/cpu.h> 48 #include <machine/pmon.h> 49 #include <stand/boot/cmd.h> 50 51 void gdium_abort(void); 52 int is_gdium; 53 int boot_rd; 54 55 extern int bootprompt; 56 57 /* 58 * Console 59 */ 60 61 int 62 cnspeed(dev_t dev, int sp) 63 { 64 return CONSPEED; 65 } 66 67 char * 68 ttyname(int fd) 69 { 70 return "pmon console"; 71 } 72 73 dev_t 74 ttydev(char *name) 75 { 76 /* we do not support any other console than pmon */ 77 return NODEV; 78 } 79 80 /* 81 * Configuration and device path aerobics 82 */ 83 84 /* 85 * Return the default boot device. 86 */ 87 void 88 devboot(dev_t dev, char *path) 89 { 90 const char *bootpath = NULL; 91 size_t bootpathlen = 0; /* gcc -Wall */ 92 const char *tmp; 93 int i; 94 95 /* 96 * If we are booting the initrd image, things are easy... 97 */ 98 99 if (dev != 0) { 100 strlcpy(path, "rd0a", BOOTDEVLEN); 101 return; 102 } 103 104 /* 105 * First, try to figure where we have been loaded from; we'll assume 106 * the default device to load the kernel from is the same. 107 * 108 * We may have been loaded in three different ways: 109 * - automatic load from `al' environment variable (similar to a 110 * `load' and `go' sequence). 111 * - manual `boot' command, with path on the commandline. 112 * - manual `load' and `go' commands, with no path on the commandline. 113 */ 114 115 if (pmon_argc > 0) { 116 tmp = (const char *)pmon_getarg(0); 117 if (tmp[0] != 'g') { 118 /* manual load */ 119 for (i = 1; i < pmon_argc; i++) { 120 tmp = (const char *)pmon_getarg(i); 121 if (tmp[0] != '-') { 122 bootpath = tmp; 123 break; 124 } 125 } 126 } else { 127 /* possible automatic load */ 128 bootpath = pmon_getenv("al"); 129 } 130 } 131 132 /* 133 * If the bootblocks have been loaded from the network, 134 * use the default disk. 135 */ 136 137 if (bootpath != NULL && strncmp(bootpath, "tftp://", 7) == 0) 138 bootpath = NULL; 139 140 /* 141 * Now extract the device name from the bootpath. 142 */ 143 144 if (bootpath != NULL) { 145 tmp = strchr(bootpath, '@'); 146 if (tmp == NULL) { 147 bootpath = NULL; 148 } else { 149 bootpath = tmp + 1; 150 tmp = strchr(bootpath, '/'); 151 if (tmp == NULL) { 152 bootpath = NULL; 153 } else { 154 bootpathlen = tmp - bootpath; 155 } 156 } 157 } 158 159 if (bootpath != NULL && bootpathlen >= 3) { 160 if (bootpathlen >= BOOTDEVLEN) 161 bootpathlen = BOOTDEVLEN - 1; 162 strncpy(path, bootpath, bootpathlen); 163 path[bootpathlen] = '\0'; 164 /* only add a partition letter if there is none */ 165 if (bootpath[bootpathlen - 1] >= '0' && 166 bootpath[bootpathlen - 1] <= '9') 167 strlcat(path, "a", BOOTDEVLEN); 168 } else { 169 strlcpy(path, "wd0a", BOOTDEVLEN); 170 } 171 } 172 173 /* 174 * Ugly (lack of) clock routines 175 */ 176 177 time_t 178 getsecs() 179 { 180 return 0; 181 } 182 183 /* 184 * Initialization 185 */ 186 187 void 188 machdep() 189 { 190 const char *envvar; 191 192 /* 193 * Since we can't have non-blocking input, we will try to 194 * autoload the kernel pointed to by the `bsd' environment 195 * variable, and fallback to interactive mode if the variable 196 * is empty or the load fails. 197 */ 198 199 if (boot_rd == 0) { 200 envvar = pmon_getenv("bsd"); 201 if (envvar != NULL) { 202 bootprompt = 0; 203 kernelfile = (char *)envvar; 204 } else { 205 if (is_gdium) 206 gdium_abort(); 207 } 208 } 209 } 210 211 int 212 main() 213 { 214 const char *envvar; 215 216 cninit(); 217 218 /* 219 * Figure out whether we are running on a Gdium system, which 220 * has an horribly castrated PMON. If we do, the best we can do 221 * is boot an initrd image. 222 */ 223 envvar = pmon_getenv("Version"); 224 if (envvar != NULL && strncmp(envvar, "Gdium", 5) == 0) 225 is_gdium = 1; 226 227 /* 228 * Check if we have a valid initrd loaded. 229 */ 230 231 envvar = pmon_getenv("rd"); 232 if (envvar != NULL && *envvar != '\0') 233 boot_rd = rd_isvalid(); 234 235 if (boot_rd != 0) 236 bootprompt = 0; 237 238 boot(boot_rd); 239 return 0; 240 } 241 242 void 243 gdium_abort() 244 { 245 /* Here's a nickel, kid. Get yourself a better firmware */ 246 printf("\n\nSorry, OpenBSD boot blocks do not work on Gdium, " 247 "because of dire firmware limitations.\n" 248 "Also, the firmware has reset the USB controller so you " 249 "will need to power cycle.\n" 250 "We would apologize for this inconvenience, but we have " 251 "no control about the firmware of your machine.\n\n"); 252 rd_invalidate(); 253 _rtt(); 254 } 255