1 /* $OpenBSD: machdep.c,v 1.4 2010/04/03 19:13:27 miod 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 9600; 65 } 66 67 int 68 getchar() 69 { 70 int c = cngetc(); 71 72 if (c == '\r') 73 c = '\n'; 74 75 if ((c < ' ' && c != '\n') || c == '\177') 76 return c; 77 78 putchar(c); 79 80 return c; 81 } 82 83 int pch_pos; 84 85 void 86 putchar(int c) 87 { 88 switch (c) { 89 case '\177': /* DEL erases */ 90 cnputc('\b'); 91 cnputc(' '); 92 case '\b': 93 cnputc('\b'); 94 if (pch_pos) 95 pch_pos--; 96 break; 97 case '\t': 98 do 99 cnputc(' '); 100 while (++pch_pos % 8) ; 101 break; 102 case '\n': 103 case '\r': 104 cnputc(c); 105 pch_pos = 0; 106 break; 107 default: 108 cnputc(c); 109 pch_pos++; 110 break; 111 } 112 } 113 114 char * 115 ttyname(int fd) 116 { 117 return "pmon console"; 118 } 119 120 dev_t 121 ttydev(char *name) 122 { 123 /* we do not support any other console than pmon */ 124 return NODEV; 125 } 126 127 /* 128 * Configuration and device path aerobics 129 */ 130 131 /* 132 * Return the default boot device. 133 */ 134 void 135 devboot(dev_t dev, char *path) 136 { 137 const char *bootpath = NULL; 138 size_t bootpathlen = 0; /* gcc -Wall */ 139 const char *tmp; 140 int i; 141 142 /* 143 * If we are booting the initrd image, things are easy... 144 */ 145 146 if (dev != 0) { 147 strlcpy(path, "rd0a", BOOTDEVLEN); 148 return; 149 } 150 151 /* 152 * First, try to figure where we have been loaded from; we'll assume 153 * the default device to load the kernel from is the same. 154 * 155 * We may have been loaded in three different ways: 156 * - automatic load from `al' environment variable (similar to a 157 * `load' and `go' sequence). 158 * - manual `boot' command, with path on the commandline. 159 * - manual `load' and `go' commands, with no path on the commandline. 160 */ 161 162 if (pmon_argc > 0) { 163 tmp = (const char *)pmon_getarg(0); 164 if (tmp[0] != 'g') { 165 /* manual load */ 166 for (i = 1; i < pmon_argc; i++) { 167 tmp = (const char *)pmon_getarg(i); 168 if (tmp[0] != '-') { 169 bootpath = tmp; 170 break; 171 } 172 } 173 } else { 174 /* possible automatic load */ 175 bootpath = pmon_getenv("al"); 176 } 177 } 178 179 /* 180 * If the bootblocks have been loaded from the network, 181 * use the default disk. 182 */ 183 184 if (bootpath != NULL && strncmp(bootpath, "tftp://", 7) == 0) 185 bootpath = NULL; 186 187 /* 188 * Now extract the device name from the bootpath. 189 */ 190 191 if (bootpath != NULL) { 192 tmp = strchr(bootpath, '@'); 193 if (tmp == NULL) { 194 bootpath = NULL; 195 } else { 196 bootpath = tmp + 1; 197 tmp = strchr(bootpath, '/'); 198 if (tmp == NULL) { 199 bootpath = NULL; 200 } else { 201 bootpathlen = tmp - bootpath; 202 } 203 } 204 } 205 206 if (bootpath != NULL && bootpathlen >= 3) { 207 if (bootpathlen >= BOOTDEVLEN) 208 bootpathlen = BOOTDEVLEN - 1; 209 strncpy(path, bootpath, bootpathlen); 210 path[bootpathlen] = '\0'; 211 /* only add a partition letter if there is none */ 212 if (bootpath[bootpathlen - 1] >= '0' && 213 bootpath[bootpathlen - 1] <= '9') 214 strlcat(path, "a", BOOTDEVLEN); 215 } else { 216 strlcpy(path, "wd0a", BOOTDEVLEN); 217 } 218 } 219 220 /* 221 * Ugly (lack of) clock routines 222 */ 223 224 time_t 225 getsecs() 226 { 227 return 0; 228 } 229 230 /* 231 * Initialization 232 */ 233 234 void 235 machdep() 236 { 237 const char *envvar; 238 239 /* 240 * Since we can't have non-blocking input, we will try to 241 * autoload the kernel pointed to by the `bsd' environment 242 * variable, and fallback to interactive mode if the variable 243 * is empty or the load fails. 244 */ 245 246 if (boot_rd == 0) { 247 envvar = pmon_getenv("bsd"); 248 if (envvar != NULL) { 249 bootprompt = 0; 250 kernelfile = (char *)envvar; 251 } else { 252 if (is_gdium) 253 gdium_abort(); 254 } 255 } 256 } 257 258 int 259 main() 260 { 261 const char *envvar; 262 263 cninit(); 264 265 /* 266 * Figure out whether we are running on a Gdium system, which 267 * has an horribly castrated PMON. If we do, the best we can do 268 * is boot an initrd image. 269 */ 270 envvar = pmon_getenv("Version"); 271 if (envvar != NULL && strncmp(envvar, "Gdium", 5) == 0) 272 is_gdium = 1; 273 274 /* 275 * Check if we have a valid initrd loaded. 276 */ 277 278 envvar = pmon_getenv("rd"); 279 if (envvar != NULL && *envvar != '\0') 280 boot_rd = rd_isvalid(); 281 282 if (boot_rd != 0) 283 bootprompt = 0; 284 285 boot(boot_rd); 286 return 0; 287 } 288 289 void 290 gdium_abort() 291 { 292 /* Here's a nickel, kid. Get yourself a better firmware */ 293 printf("\n\nSorry, OpenBSD boot blocks do not work on Gdium, " 294 "because of dire firmware limitations.\n" 295 "Also, the firmware has reset the USB controller so you " 296 "will need to power cycle.\n" 297 "We would apologize for this incovenience, but we have " 298 "no control about the firmware of your machine.\n\n"); 299 rd_invalidate(); 300 _rtt(); 301 } 302