1 /* $NetBSD: boot.c,v 1.19 2002/06/09 19:21:08 matt Exp $ */ 2 /*- 3 * Copyright (c) 1982, 1986 The Regents of the University of California. 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 3. All advertising materials mentioning features or use of this software 15 * must display the following acknowledgement: 16 * This product includes software developed by the University of 17 * California, Berkeley and its contributors. 18 * 4. Neither the name of the University nor the names of its contributors 19 * may be used to endorse or promote products derived from this software 20 * without specific prior written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32 * SUCH DAMAGE. 33 * 34 * @(#)boot.c 7.15 (Berkeley) 5/4/91 35 */ 36 37 #include <sys/param.h> 38 #include <sys/reboot.h> 39 #include <sys/boot_flag.h> 40 #include "lib/libsa/stand.h" 41 #include "lib/libsa/loadfile.h" 42 #include "lib/libkern/libkern.h" 43 44 #define V750UCODE(x) ((x>>8)&255) 45 46 #include "machine/rpb.h" 47 48 #include "vaxstand.h" 49 50 /* 51 * Boot program... arguments passed in r10 and r11 determine 52 * whether boot stops to ask for system name and which device 53 * boot comes from. 54 */ 55 56 char line[100]; 57 int bootdev, debug; 58 extern unsigned opendev; 59 60 void usage(char *), boot(char *), halt(char *); 61 void Xmain(void); 62 void autoconf(void); 63 int getsecs(void); 64 int setjmp(int *); 65 int testkey(void); 66 void loadpcs(void); 67 68 const struct vals { 69 char *namn; 70 void (*func)(char *); 71 char *info; 72 } val[] = { 73 {"?", usage, "Show this help menu"}, 74 {"help", usage, "Same as '?'"}, 75 {"boot", boot, "Load and execute file"}, 76 {"halt", halt, "Halts the system"}, 77 {0, 0}, 78 }; 79 80 static struct { 81 char name[12]; 82 int quiet; 83 } filelist[] = { 84 { "netbsd.vax", 1 }, 85 { "netbsd", 0 }, 86 { "netbsd.gz", 0 }, 87 { "netbsd.old", 0 }, 88 { "gennetbsd", 0 }, 89 { "", 0 }, 90 }; 91 92 int jbuf[10]; 93 int sluttid, senast, skip, askname; 94 struct rpb bootrpb; 95 96 void 97 Xmain(void) 98 { 99 int io; 100 int j, nu; 101 u_long marks[MARK_MAX]; 102 extern const char bootprog_rev[], bootprog_date[]; 103 104 io = 0; 105 skip = 1; 106 autoconf(); 107 108 askname = bootrpb.rpb_bootr5 & RB_ASKNAME; 109 printf("\n\r>> NetBSD/vax boot [%s %s] <<\n", bootprog_rev, 110 bootprog_date); 111 printf(">> Press any key to abort autoboot "); 112 sluttid = getsecs() + 5; 113 senast = 0; 114 skip = 0; 115 setjmp(jbuf); 116 for (;;) { 117 nu = sluttid - getsecs(); 118 if (senast != nu) 119 printf("%c%d", 8, nu); 120 if (nu <= 0) 121 break; 122 senast = nu; 123 if ((j = (testkey() & 0177))) { 124 skip = 1; 125 if (j != 10 && j != 13) { 126 printf("\nPress '?' for help"); 127 askname = 1; 128 } 129 break; 130 } 131 } 132 skip = 1; 133 printf("\n"); 134 if (setjmp(jbuf)) 135 askname = 1; 136 137 /* First try to autoboot */ 138 if (askname == 0) { 139 int fileindex; 140 for (fileindex = 0; filelist[fileindex].name[0] != '\0'; 141 fileindex++) { 142 int err; 143 errno = 0; 144 if (!filelist[fileindex].quiet) 145 printf("> boot %s\n", filelist[fileindex].name); 146 marks[MARK_START] = 0; 147 err = loadfile(filelist[fileindex].name, marks, 148 LOAD_KERNEL|COUNT_KERNEL); 149 if (err == 0) { 150 machdep_start((char *)marks[MARK_ENTRY], 151 marks[MARK_NSYM], 152 (void *)marks[MARK_START], 153 (void *)marks[MARK_SYM], 154 (void *)marks[MARK_END]); 155 } 156 if (!filelist[fileindex].quiet) 157 printf("%s: boot failed: %s\n", 158 filelist[fileindex].name, strerror(errno)); 159 #if 0 /* Will hang VAX 4000 machines */ 160 if (testkey()) 161 break; 162 #endif 163 } 164 } 165 166 /* If any key pressed, go to conversational boot */ 167 for (;;) { 168 const struct vals *v = &val[0]; 169 char *c, *d; 170 171 printf("> "); 172 gets(line); 173 174 c = line; 175 while (*c == ' ') 176 c++; 177 178 if (c[0] == 0) 179 continue; 180 181 if ((d = index(c, ' '))) 182 *d++ = 0; 183 184 while (v->namn) { 185 if (strcmp(v->namn, c) == 0) 186 break; 187 v++; 188 } 189 if (v->namn) 190 (*v->func)(d); 191 else 192 printf("Unknown command: %s\n", c); 193 } 194 } 195 196 void 197 halt(char *hej) 198 { 199 asm("halt"); 200 } 201 202 void 203 boot(char *arg) 204 { 205 char *fn = "netbsd"; 206 int howto, fl, err; 207 u_long marks[MARK_MAX]; 208 209 if (arg) { 210 while (*arg == ' ') 211 arg++; 212 213 if (*arg != '-') { 214 fn = arg; 215 if ((arg = index(arg, ' '))) { 216 *arg++ = 0; 217 while (*arg == ' ') 218 arg++; 219 } else 220 goto load; 221 } 222 if (*arg != '-') { 223 fail: printf("usage: boot [filename] [-asdqv]\n"); 224 return; 225 } 226 227 howto = 0; 228 while (*++arg) { 229 fl = 0; 230 BOOT_FLAG(*arg, fl); 231 if (!fl) 232 goto fail; 233 howto |= fl; 234 } 235 bootrpb.rpb_bootr5 = howto; 236 } 237 load: 238 marks[MARK_START] = 0; 239 err = loadfile(fn, marks, LOAD_KERNEL|COUNT_KERNEL); 240 if (err == 0) { 241 machdep_start((char *)marks[MARK_ENTRY], 242 marks[MARK_NSYM], 243 (void *)marks[MARK_START], 244 (void *)marks[MARK_SYM], 245 (void *)marks[MARK_END]); 246 } 247 printf("Boot failed: %s\n", strerror(errno)); 248 } 249 250 /* 750 Patchable Control Store magic */ 251 252 #include "../include/mtpr.h" 253 #include "../include/cpu.h" 254 #include "../include/sid.h" 255 #define PCS_BITCNT 0x2000 /* number of patchbits */ 256 #define PCS_MICRONUM 0x400 /* number of ucode locs */ 257 #define PCS_PATCHADDR 0xf00000 /* start addr of patchbits */ 258 #define PCS_PCSADDR (PCS_PATCHADDR+0x8000) /* start addr of pcs */ 259 #define PCS_PATCHBIT (PCS_PATCHADDR+0xc000) /* patchbits enable reg */ 260 #define PCS_ENABLE 0xfff00000 /* enable bits for pcs */ 261 262 #define extzv(one, two, three,four) \ 263 ({ \ 264 asm __volatile ("extzv %0,%3,%1,%2" \ 265 : \ 266 : "g"(one),"m"(two),"mo>"(three),"g"(four)); \ 267 }) 268 269 270 void 271 loadpcs() 272 { 273 static int pcsdone = 0; 274 int mid = mfpr(PR_SID); 275 int i, j, *ip, *jp; 276 char pcs[100]; 277 char *cp; 278 279 if ((mid >> 24) != VAX_750 || ((mid >> 8) & 255) < 95 || pcsdone) 280 return; 281 printf("Updating 11/750 microcode: "); 282 for (cp = line; *cp; cp++) 283 if (*cp == ')' || *cp == ':') 284 break; 285 if (*cp) { 286 bcopy(line, pcs, 99); 287 pcs[99] = 0; 288 i = cp - line + 1; 289 } else 290 i = 0; 291 strcpy(pcs + i, "pcs750.bin"); 292 i = open(pcs, 0); 293 if (i < 0) { 294 printf("bad luck - missing pcs750.bin :-(\n"); 295 return; 296 } 297 /* 298 * We ask for more than we need to be sure we get only what we expect. 299 * After read: 300 * locs 0 - 1023 packed patchbits 301 * 1024 - 11264 packed microcode 302 */ 303 if (read(i, (char *)0, 23*512) != 22*512) { 304 printf("Error reading %s\n", pcs); 305 close(i); 306 return; 307 } 308 close(i); 309 310 /* 311 * Enable patchbit loading and load the bits one at a time. 312 */ 313 *((int *)PCS_PATCHBIT) = 1; 314 ip = (int *)PCS_PATCHADDR; 315 jp = (int *)0; 316 for (i=0; i < PCS_BITCNT; i++) { 317 extzv(i,*jp,*ip++,1); 318 } 319 *((int *)PCS_PATCHBIT) = 0; 320 321 /* 322 * Load PCS microcode 20 bits at a time. 323 */ 324 ip = (int *)PCS_PCSADDR; 325 jp = (int *)1024; 326 for (i=j=0; j < PCS_MICRONUM * 4; i+=20, j++) { 327 extzv(i,*jp,*ip++,20); 328 } 329 330 /* 331 * Enable PCS. 332 */ 333 i = *jp; /* get 1st 20 bits of microcode again */ 334 i &= 0xfffff; 335 i |= PCS_ENABLE; /* reload these bits with PCS enable set */ 336 *((int *)PCS_PCSADDR) = i; 337 338 mid = mfpr(PR_SID); 339 printf("new rev level=%d\n", V750UCODE(mid)); 340 pcsdone = 1; 341 } 342 343 void 344 usage(char *hej) 345 { 346 const struct vals *v = &val[0]; 347 348 printf("Commands:\n"); 349 while (v->namn) { 350 printf("%s\t%s\n", v->namn, v->info); 351 v++; 352 } 353 } 354