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