Print this page
11630 remove checks for 64-bit capable hardware
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/psm/stand/boot/sparc/common/boot_plat.c
+++ new/usr/src/psm/stand/boot/sparc/common/boot_plat.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
↓ open down ↓ |
13 lines elided |
↑ open up ↑ |
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21 /*
22 22 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
23 23 * Use is subject to license terms.
24 + * Copyright 2019 Peter Tribbble.
24 25 */
25 26
26 27 #include <sys/param.h>
27 28 #include <sys/fcntl.h>
28 29 #include <sys/obpdefs.h>
29 30 #include <sys/reboot.h>
30 31 #include <sys/promif.h>
31 32 #include <sys/stat.h>
32 33 #include <sys/bootvfs.h>
33 34 #include <sys/platnames.h>
34 35 #include <sys/salib.h>
35 36 #include <sys/elf.h>
36 37 #include <sys/link.h>
37 38 #include <sys/auxv.h>
38 39 #include <sys/boot_policy.h>
39 40 #include <sys/boot_redirect.h>
40 41 #include <sys/bootconf.h>
41 42 #include <sys/boot.h>
42 43 #include "boot_plat.h"
43 44
44 45 #define SUCCESS 0
45 46 #define FAILURE -1
46 47
47 48 #define ISSPACE(c) (c == ' ' || c == '\t')
48 49 #define SKIP_WHITESPC(cp) while (*cp && ISSPACE(*cp)) cp++;
49 50
50 51
51 52 #ifdef DEBUG
52 53 int debug = 0;
53 54 #else
54 55 static const int debug = 0;
55 56 #endif
56 57
57 58 #define dprintf if (debug) printf
58 59
59 60 #ifdef DEBUG_LISTS
60 61 void print_memlist(struct memlist *av);
61 62 #endif
62 63
63 64 extern int (*readfile(int fd, int print))();
64 65 extern void kmem_init(void);
65 66 extern void *kmem_alloc(size_t, int);
66 67 extern void kmem_free(void *, size_t);
67 68 extern void get_boot_args(char *buf);
68 69 extern void setup_bootops(void);
69 70 extern struct bootops bootops;
70 71 extern void exitto(int (*entrypoint)());
71 72 extern void exitto64(int (*entrypoint)(), void *bootvec);
72 73
73 74 int openfile(char *filename);
74 75
75 76 char *default_name;
76 77 char *default_path;
77 78
78 79 int vac; /* virtual address cache type (none == 0) */
79 80 int is_sun4v; /* sun4u vs. sun4v */
80 81 int client_isLP64 = 1; /* SPARC clients are always LP64 */
81 82
82 83 extern bootplat_defaults_t sun4u_plat_defaults;
83 84 extern bootplat_defaults_t sun4v_plat_defaults;
84 85
85 86 /*
86 87 * filename is the name of the standalone we're going to execute.
87 88 */
88 89 char filename[MAXPATHLEN];
89 90
90 91 char * const defname = "kernel/sparcv9/unix";
91 92
92 93 /*
93 94 * We enable the cache by default
94 95 * but boot -n will leave it alone...
95 96 * that is, we use whatever state the PROM left it in.
96 97 */
97 98 char *mfg_name;
98 99 int cache_state = 1;
99 100 char filename2[MAXPATHLEN];
100 101
101 102 int boothowto = 0;
102 103 int verbosemode = 0;
103 104
104 105
105 106 /*
106 107 * Copy filename and bargs into v2args_buf, which will be exported as the
107 108 * boot-args boot property. We should probably warn the user if anything gets
108 109 * cut off.
109 110 */
110 111 void
111 112 set_client_bootargs(const char *filename, const char *bargs)
112 113 {
113 114 int i = 0;
114 115 const char *s;
115 116
116 117 s = filename;
117 118 while (*s != '\0' && i < V2ARGS_BUF_SZ - 1)
118 119 v2args_buf[i++] = *s++;
119 120
120 121 if (i >= V2ARGS_BUF_SZ - 2) {
121 122 /* Not enough room for a space and any of bargs. */
122 123 v2args_buf[i] = '\0';
123 124 return;
124 125 }
125 126
126 127 v2args_buf[i++] = ' ';
127 128
128 129 s = bargs;
129 130 while (*s != '\0' && i < V2ARGS_BUF_SZ - 1)
130 131 v2args_buf[i++] = *s++;
131 132
132 133 v2args_buf[i] = '\0';
133 134 }
134 135
135 136 /*
136 137 * The slice redirection file is used on the install CD
137 138 */
138 139 static int
139 140 read_redirect(char *redirect)
140 141 {
141 142 int fd;
142 143 char slicec;
143 144 size_t nread = 0;
144 145
145 146 if ((fd = open(BOOT_REDIRECT, O_RDONLY)) != -1) {
146 147 /*
147 148 * Read the character out of the file - this is the
148 149 * slice to use, in base 36.
149 150 */
150 151 nread = read(fd, &slicec, 1);
151 152 (void) close(fd);
152 153 if (nread == 1)
153 154 *redirect++ = slicec;
154 155 }
155 156 *redirect = '\0';
156 157
157 158 return (nread == 1);
158 159 }
159 160
160 161 void
161 162 post_mountroot(char *bootfile, char *redirect)
162 163 {
163 164 int (*go2)();
164 165 int fd;
165 166
166 167 /* Save the bootfile, just in case we need it again */
167 168 (void) strcpy(filename2, bootfile);
168 169
169 170 for (;;) {
170 171 if (boothowto & RB_ASKNAME) {
171 172 char tmpname[MAXPATHLEN];
172 173
173 174 printf("Enter filename [%s]: ", bootfile);
174 175 (void) cons_gets(tmpname, sizeof (tmpname));
175 176 if (tmpname[0] != '\0')
176 177 (void) strcpy(bootfile, tmpname);
177 178 }
178 179
179 180 if (boothowto & RB_HALT) {
180 181 printf("Boot halted.\n");
181 182 prom_enter_mon();
182 183 }
183 184
184 185 if ((fd = openfile(bootfile)) == FAILURE) {
185 186
186 187 /*
187 188 * There are many reasons why this might've
188 189 * happened .. but one of them is that we're
189 190 * on the installation CD, and we need to
190 191 * revector ourselves off to a different partition
191 192 * of the CD. Check for the redirection file.
192 193 */
193 194 if (redirect != NULL &&
194 195 read_redirect(redirect)) {
195 196 /* restore bootfile */
196 197 (void) strcpy(bootfile, filename2);
197 198 return;
198 199 /*NOTREACHED*/
199 200 }
200 201
201 202 printf("%s: cannot open %s\n", my_own_name, bootfile);
202 203 boothowto |= RB_ASKNAME;
203 204
204 205 /* restore bootfile */
205 206 (void) strcpy(bootfile, filename2);
206 207 continue;
207 208 }
208 209
209 210 if ((go2 = readfile(fd, boothowto & RB_VERBOSE)) !=
210 211 (int(*)()) -1) {
211 212 (void) close(fd);
212 213 } else {
213 214 printf("boot failed\n");
214 215 boothowto |= RB_ASKNAME;
215 216 continue;
216 217 }
217 218
218 219 if (boothowto & RB_HALT) {
219 220 printf("Boot halted before exit to 0x%p.\n",
220 221 (void *)go2);
221 222 prom_enter_mon();
222 223 }
223 224
224 225 my_own_name = bootfile;
225 226
226 227 dprintf("Calling exitto64(%p, %p)\n", (void *)go2,
227 228 (void *)elfbootvecELF64);
228 229 exitto64(go2, (void *)elfbootvecELF64);
229 230 }
230 231 }
231 232
232 233 /*ARGSUSED*/
233 234 static int
234 235 boot_open(char *pathname, void *arg)
235 236 {
236 237 dprintf("trying '%s'\n", pathname);
237 238 return (open(pathname, O_RDONLY));
238 239 }
239 240
240 241 /*
241 242 * Open the given filename, expanding to it's
242 243 * platform-dependent location if necessary.
243 244 *
244 245 * Boot supports OBP and IEEE1275.
245 246 *
246 247 * XXX: Move side effects out of this function!
247 248 */
248 249 int
249 250 openfile(char *filename)
250 251 {
251 252 static char *fullpath;
252 253 static int once;
253 254 int fd;
254 255
255 256 if (once == 0) {
256 257
257 258 ++once;
258 259
259 260 /*
260 261 * Setup exported 'boot' properties: 'mfg-name'.
261 262 * XXX: This shouldn't be a side effect of openfile().
262 263 */
263 264 if (mfg_name == NULL)
264 265 mfg_name = get_mfg_name();
265 266
266 267 fullpath = (char *)kmem_alloc(MAXPATHLEN, 0);
267 268 }
268 269
269 270 if (*filename == '/') {
270 271 (void) strcpy(fullpath, filename);
271 272 fd = boot_open(fullpath, NULL);
272 273 return (fd);
273 274 }
274 275
275 276 fd = open_platform_file(filename, boot_open, NULL, fullpath);
276 277 if (fd == -1)
277 278 return (-1);
278 279
279 280 /*
280 281 * Copy back the name we actually found
281 282 */
282 283 (void) strcpy(filename, fullpath);
283 284 return (fd);
284 285 }
285 286
286 287 /*
287 288 * Get the boot arguments from the PROM and split it into filename and
288 289 * options components.
289 290 *
290 291 * As per IEEE1275 and boot(1M), the boot arguments will have the syntax
291 292 * "[filename] [-options]". If filename is specified, it is copied into the
292 293 * first buffer. (Otherwise, the buffer is left alone.) The rest of the string
293 294 * is copied into the second buffer.
294 295 */
295 296 static void
296 297 init_bootargs(char *fname_buf, int fname_buf_sz, char *bargs_buf,
297 298 int bargs_buf_sz)
298 299 {
299 300 const char *tp = prom_bootargs();
300 301
301 302 if (!tp || *tp == '\0') {
302 303 *bargs_buf = '\0';
303 304 return;
304 305 }
305 306
306 307 SKIP_WHITESPC(tp);
307 308
308 309 /*
309 310 * If we don't have an option indicator, then we
310 311 * already have our filename prepended.
311 312 */
312 313 if (*tp && *tp != '-') {
313 314 int i;
314 315
315 316 /*
316 317 * Copy the filename into fname_buf.
317 318 */
318 319 for (i = 0; i < fname_buf_sz && *tp && !ISSPACE(*tp); ++i)
319 320 *fname_buf++ = *tp++;
320 321
321 322 if (i >= fname_buf_sz) {
322 323 printf("boot: boot filename too long!\n");
323 324 printf("boot halted.\n");
324 325 prom_enter_mon();
325 326 /*NOTREACHED*/
326 327 } else {
327 328 *fname_buf = '\0';
328 329 }
329 330
330 331 SKIP_WHITESPC(tp);
331 332 }
332 333
333 334 /* The rest of the line is the options. */
334 335 while (bargs_buf_sz > 1 && *tp) {
335 336 *bargs_buf++ = *tp++;
336 337 --bargs_buf_sz;
337 338 }
338 339 *bargs_buf = '\0';
339 340
340 341 if (bargs_buf_sz == 1) {
341 342 printf("boot: boot arguments too long!\n");
342 343 printf("boot halted.\n");
343 344 prom_enter_mon();
344 345 /*NOTREACHED*/
345 346 }
346 347 }
347 348
348 349 boolean_t
349 350 is_netdev(char *devpath)
350 351 {
351 352 pnode_t node = prom_finddevice(devpath);
352 353 char *options;
353 354
354 355 if ((node == OBP_NONODE) || (node == OBP_BADNODE))
355 356 return (B_FALSE);
356 357 if (prom_devicetype(node, "network") != 0)
357 358 return (B_TRUE);
358 359
359 360 /*
360 361 * For Infiniband, network device names will be of the
361 362 * format XXX/ib@0:port=1,pkey=1234,protocol=ip[,YYY] where
362 363 * XXX is typically /pci@8,700000/pci@1. The device_type
363 364 * property will be "ib".
364 365 */
365 366 if (prom_devicetype(node, "ib") != 0) {
366 367 options = prom_path_options(devpath);
367 368 if (options != NULL) {
368 369
369 370 #define SEARCHSTRING ",protocol=ip"
370 371 #define SEARCHSTRLEN strlen(SEARCHSTRING)
371 372
372 373 if (strstr(options, ",protocol=ip,") != NULL)
373 374 return (B_TRUE);
374 375 while ((options = strstr(options, SEARCHSTRING)) !=
375 376 NULL) {
376 377 char nextc;
377 378
378 379 nextc = options[SEARCHSTRLEN];
379 380 if ((nextc == ',') || (nextc == 0))
380 381 return (B_TRUE);
381 382 options += SEARCHSTRLEN;
382 383 }
383 384 }
384 385 }
385 386 return (B_FALSE);
386 387 }
387 388
388 389 /*
389 390 * Hook for modifying the OS boot path. This hook allows us to handle
390 391 * device arguments that the OS can't handle.
391 392 */
392 393 void
393 394 mangle_os_bootpath(char *bpath)
394 395 {
395 396 pnode_t node;
396 397 char *stripped_pathname;
397 398
398 399 node = prom_finddevice(bpath);
399 400 if (prom_devicetype(node, "network") == 0)
400 401 return;
401 402
402 403 /*
403 404 * The OS can't handle network device arguments
404 405 * eg: boot net:promiscuous,speed=100,duplex=full
405 406 * So, we remove any argument strings in the device
406 407 * pathname we hand off to the OS for network devices.
407 408 *
408 409 * Internally, within boot, bpath is used to access
409 410 * the device, but v2path (as the boot property "boot-path")
410 411 * is the pathname passed to the OS.
411 412 */
412 413
413 414 stripped_pathname = kmem_alloc(OBP_MAXPATHLEN, 0);
414 415 prom_strip_options(bpath, stripped_pathname);
415 416 v2path = stripped_pathname;
416 417 }
417 418
418 419 /*
419 420 * Given the boot path in the native firmware format use
420 421 * the redirection string to mutate the boot path to the new device.
421 422 * Fix up the 'v2path' so that it matches the new firmware path.
422 423 */
423 424 void
424 425 redirect_boot_path(char *bpath, char *redirect)
425 426 {
426 427 char slicec = *redirect;
427 428 char *p = bpath + strlen(bpath);
428 429
429 430 /*
430 431 * If the redirection character doesn't fall in this
431 432 * range, something went horribly wrong.
432 433 */
433 434 if (slicec < '0' || slicec > '7') {
434 435 printf("boot: bad redirection slice '%c'\n", slicec);
435 436 return;
436 437 }
437 438
438 439 /*
439 440 * Handle fully qualified OpenBoot pathname.
440 441 */
441 442 while (--p >= bpath && *p != '@' && *p != '/')
442 443 if (*p == ':')
443 444 break;
444 445 if (*p++ == ':') {
445 446 /*
↓ open down ↓ |
412 lines elided |
↑ open up ↑ |
446 447 * Convert slice number to partition 'letter'.
447 448 */
448 449 *p++ = 'a' + slicec - '0';
449 450 *p = '\0';
450 451 v2path = bpath;
451 452 return;
452 453 }
453 454 prom_panic("redirect_boot_path: mangled boot path!");
454 455 }
455 456
456 -#define PROM_VERS_MAX_LEN 64
457 -
458 457 void
459 458 system_check(void)
460 459 {
461 - char buf[PROM_VERS_MAX_LEN];
462 460 pnode_t n;
463 461 char arch[128];
464 462 size_t len;
465 463 bootplat_defaults_t *plat_defaults;
466 464
467 465 /*
468 466 * This is a sun4v machine iff the device_type property
469 467 * exists on the root node and has the value "sun4v".
470 468 * Some older sunfire proms do not have such a property.
471 469 */
472 470 is_sun4v = 0;
473 471 n = prom_rootnode();
474 472 len = prom_getproplen(n, "device_type");
475 473 if (len > 0 && len < sizeof (arch)) {
↓ open down ↓ |
4 lines elided |
↑ open up ↑ |
476 474 (void) prom_getprop(n, "device_type", arch);
477 475 arch[len] = '\0';
478 476 dprintf("device_type=%s\n", arch);
479 477 if (strcmp(arch, "sun4v") == 0) {
480 478 is_sun4v = 1;
481 479 }
482 480 } else {
483 481 dprintf("device_type: no such property, len=%d\n", (int)len);
484 482 }
485 483
486 - if (!is_sun4v && cpu_is_ultrasparc_1()) {
487 - printf("UltraSPARC I processors are not supported by this "
488 - "release of Solaris.\n");
489 - prom_exit_to_mon();
490 - }
491 -
492 484 /*
493 485 * Set up defaults per platform
494 486 */
495 487 plat_defaults = (is_sun4v) ?
496 488 &sun4v_plat_defaults : &sun4u_plat_defaults;
497 489
498 490 default_name = plat_defaults->plat_defaults_name;
499 491 default_path = plat_defaults->plat_defaults_path;
500 492 vac = plat_defaults->plat_defaults_vac;
501 493
502 494 dprintf("default_name: %s\n", default_name);
503 495 dprintf("default_path: %s\n", default_path);
504 496 dprintf("vac: %d\n", vac);
505 -
506 - if (prom_version_check(buf, PROM_VERS_MAX_LEN, NULL) != PROM_VER64_OK) {
507 - printf("The firmware on this system does not support the 64-bit"
508 - " OS.\n\tPlease upgrade to at least the following version:"
509 - "\n\n\t%s\n", buf);
510 - prom_exit_to_mon();
511 - }
512 497 }
513 498
514 499 /*
515 500 * Reads in the standalone (client) program and jumps to it. If this
516 501 * attempt fails, prints "boot failed" and returns to its caller.
517 502 *
518 503 * It will try to determine if it is loading a Unix file by
519 504 * looking at what should be the magic number. If it makes
520 505 * sense, it will use it; otherwise it jumps to the first
521 506 * address of the blocks that it reads in.
522 507 *
523 508 * This new boot program will open a file, read the ELF header,
524 509 * attempt to allocate and map memory at the location at which
525 510 * the client desires to be linked, and load the program at
526 511 * that point. It will then jump there.
527 512 */
528 513 /*ARGSUSED*/
529 514 int
530 515 main(void *cookie, char **argv, int argc)
531 516 {
532 517 /*
533 518 * bpath is the boot device path buffer.
534 519 * bargs is the boot arguments buffer.
535 520 */
536 521 static char bpath[OBP_MAXPATHLEN], bargs[OBP_MAXPATHLEN];
537 522 boolean_t user_specified_filename;
538 523
539 524 prom_init("boot", cookie);
540 525 fiximp();
541 526
542 527 system_check();
543 528
544 529 dprintf("\nboot: V%d /boot interface.\n", BO_VERSION);
545 530 #ifdef HALTBOOT
546 531 prom_enter_mon();
547 532 #endif /* HALTBOOT */
548 533
549 534 init_memlists();
550 535
551 536 #ifdef DEBUG_LISTS
552 537 dprintf("Physmem avail:\n");
553 538 if (debug) print_memlist(pfreelistp);
554 539 dprintf("Virtmem avail:\n");
555 540 if (debug) print_memlist(vfreelistp);
556 541 dprintf("Phys installed:\n");
557 542 if (debug) print_memlist(pinstalledp);
558 543 prom_enter_mon();
559 544 #endif /* DEBUG_LISTS */
560 545
561 546 /*
562 547 * Initialize the default filename (exported as "default-name" and
563 548 * used by kadb).
564 549 */
565 550 set_default_filename(defname);
566 551
567 552 /*
568 553 * Parse the arguments ASAP in case there are any flags which may
569 554 * affect execution.
570 555 */
571 556
572 557 /*
573 558 * filename is the path to the standalone. Initialize it to the empty
574 559 * string so we can tell whether the user specified it in the
575 560 * arguments.
576 561 */
577 562 filename[0] = '\0';
578 563
579 564 /*
580 565 * Fetch the boot arguments from the PROM and split the filename off
581 566 * if it's there.
582 567 */
583 568 init_bootargs(filename, sizeof (filename), bargs, sizeof (bargs));
584 569
585 570 /*
586 571 * kadb was delivered as a standalone, and as such, people got used to
587 572 * typing `boot kadb'. kmdb isn't a standalone - it is loaded by krtld
588 573 * as just another kernel module. For compatibility, though, when we
589 574 * see an attempt to `boot kadb' or `boot kmdb', we'll transform that
590 575 * into a `boot -k' (or equivalent).
591 576 */
592 577 if (strcmp(filename, "kmdb") == 0 || strcmp(filename, "kadb") == 0) {
593 578 boothowto |= RB_KMDB;
594 579 *filename = '\0'; /* let boot figure out which unix to use */
595 580 }
596 581
597 582 bootflags(bargs, sizeof (bargs));
598 583
599 584 user_specified_filename = (filename[0] != '\0');
600 585
601 586 /* Fetch the boot path from the PROM. */
602 587 (void) strncpy(bpath, prom_bootpath(), sizeof (bpath) - 1);
603 588 bpath[sizeof (bpath) - 1] = '\0';
604 589
605 590 dprintf("arch: %s\n", is_sun4v ? "sun4v" : "sun4u");
606 591 dprintf("bootpath: 0x%p %s\n", (void *)bpath, bpath);
607 592 dprintf("bootargs: 0x%p %s\n", (void *)bargs, bargs);
608 593 dprintf("filename: 0x%p %s\n", (void *)filename, filename);
609 594 dprintf("kernname: 0x%p %s\n", (void *)kernname, kernname);
610 595
611 596 /*
612 597 * *v2path will be exported to the standalone as the boot-path boot
613 598 * property.
614 599 */
615 600 v2path = bpath;
616 601
617 602 /*
618 603 * Our memory lists should be "up" by this time
619 604 */
620 605
621 606 setup_bootops();
622 607
623 608 /*
624 609 * If bpath is a network card, set v2path to a copy of bpath with the
625 610 * options stripped off.
626 611 */
627 612 mangle_os_bootpath(bpath);
628 613
629 614 /*
630 615 * Not necessary on sun4v as nvram is virtual
631 616 * and kept by the guest manager on the SP.
632 617 */
633 618 if (!is_sun4v) {
634 619 retain_nvram_page();
635 620 }
636 621
637 622 if (bootprog(bpath, bargs, user_specified_filename) == 0) {
638 623 post_mountroot(filename, NULL);
639 624 /*NOTREACHED*/
640 625 }
641 626
642 627 return (0);
643 628 }
↓ open down ↓ |
122 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX