1 /*- 2 * Copyright (c) 1998 Robert Nordier 3 * All rights reserved. 4 * Copyright (c) 2001 Robert Drehmel 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms are freely 8 * permitted provided that the above copyright notice and this 9 * paragraph and the following disclaimer are duplicated in all 10 * such forms. 11 * 12 * This software is provided "AS IS" and without any express or 13 * implied warranties, including, without limitation, the implied 14 * warranties of merchantability and fitness for a particular 15 * purpose. 16 */ 17 18 #include <sys/param.h> 19 #include <sys/dirent.h> 20 #include <sys/endian.h> 21 #include <machine/elf.h> 22 #include <machine/stdarg.h> 23 #include <machine/md_var.h> 24 #include <ufs/ffs/fs.h> 25 26 #include "paths.h" 27 28 #define BSIZEMAX 16384 29 30 typedef int putc_func_t(char c, void *arg); 31 typedef int32_t ofwh_t; 32 33 struct sp_data { 34 char *sp_buf; 35 u_int sp_len; 36 u_int sp_size; 37 }; 38 39 static const char digits[] = "0123456789abcdef"; 40 41 static char bootpath[128]; 42 static char bootargs[128]; 43 44 static ofwh_t bootdev; 45 46 static struct fs fs; 47 static char blkbuf[BSIZEMAX]; 48 static unsigned int fsblks; 49 50 static uint32_t fs_off; 51 52 int main(int ac, char **av); 53 54 static void exit(int) __dead2; 55 static void load(const char *); 56 static int dskread(void *, uint64_t, int); 57 58 static void usage(void) __dead2; 59 60 static void bcopy(const void *src, void *dst, size_t len); 61 static void bzero(void *b, size_t len); 62 63 static int domount(const char *device, int quiet); 64 65 static void panic(const char *fmt, ...) __dead2; 66 static int printf(const char *fmt, ...); 67 static int putchar(char c, void *arg); 68 static int vprintf(const char *fmt, va_list ap); 69 static int vsnprintf(char *str, size_t sz, const char *fmt, va_list ap); 70 71 static int __printf(const char *fmt, putc_func_t *putc, void *arg, va_list ap); 72 static int __putc(char c, void *arg); 73 static int __puts(const char *s, putc_func_t *putc, void *arg); 74 static int __sputc(char c, void *arg); 75 static char *__uitoa(char *buf, u_int val, int base); 76 static char *__ultoa(char *buf, u_long val, int base); 77 78 /* 79 * Open Firmware interface functions 80 */ 81 typedef uint32_t ofwcell_t; 82 typedef uint32_t u_ofwh_t; 83 typedef int (*ofwfp_t)(ofwcell_t *); 84 ofwfp_t ofw; /* the prom Open Firmware entry */ 85 ofwh_t chosenh; 86 87 void ofw_init(void *, int, ofwfp_t, char *, int); 88 static ofwh_t ofw_finddevice(const char *); 89 static ofwh_t ofw_open(const char *); 90 static int ofw_close(ofwh_t); 91 static int ofw_getprop(ofwh_t, const char *, void *, size_t); 92 static int ofw_setprop(ofwh_t, const char *, void *, size_t); 93 static int ofw_read(ofwh_t, void *, size_t); 94 static int ofw_write(ofwh_t, const void *, size_t); 95 static int ofw_claim(void *virt, size_t len, u_int align); 96 static int ofw_seek(ofwh_t, uint64_t); 97 static void ofw_exit(void) __dead2; 98 99 ofwh_t bootdevh; 100 ofwh_t stdinh, stdouth; 101 102 /* 103 * Note about the entry point: 104 * 105 * For some odd reason, the first page of the load appears to have trouble 106 * when entering in LE. The first five instructions decode weirdly. 107 * I suspect it is some cache weirdness between the ELF headers and .text. 108 * 109 * Ensure we have a gap between the start of .text and the entry as a 110 * workaround. 111 */ 112 __asm(" \n\ 113 .data \n\ 114 .align 4 \n\ 115 stack: \n\ 116 .space 16384 \n\ 117 \n\ 118 .text \n\ 119 /* SLOF cache hack */ \n\ 120 .space 4096 \n\ 121 .globl _start \n\ 122 _start: \n\ 123 lis %r1,stack@ha \n\ 124 addi %r1,%r1,stack@l \n\ 125 addi %r1,%r1,8192 \n\ 126 \n\ 127 b ofw_init \n\ 128 "); 129 130 ofwfp_t realofw; 131 132 #if BYTE_ORDER == LITTLE_ENDIAN 133 /* 134 * Minimal endianness-swap trampoline for LE. 135 */ 136 __attribute__((naked)) int 137 ofwtramp(void *buf, ofwfp_t cb) 138 { 139 __asm(" \n\ 140 mflr %r0 \n\ 141 stw %r0, 4(%r1) \n\ 142 stwu %r1, -16(%r1) \n\ 143 stw %r30, 8(%r1) \n\ 144 /* Save current MSR for restoration post-call. */ \n\ 145 mfmsr %r30 \n\ 146 mr %r5, %r30 \n\ 147 /* Remove LE bit from MSR. */ \n\ 148 clrrwi %r5, %r5, 1 \n\ 149 mtsrr0 %r4 \n\ 150 mtsrr1 %r5 \n\ 151 bcl 20, 31, .+4 /* LOAD_LR_NIA */ \n\ 152 1: \n\ 153 mflr %r4 \n\ 154 addi %r4, %r4, (2f - 1b) \n\ 155 mtlr %r4 \n\ 156 /* Switch to BE and transfer control to OF entry */ \n\ 157 rfid \n\ 158 2: \n\ 159 /* Control is returned here, but in BE. */ \n\ 160 .long 0x05009f42 /* LOAD_LR_NIA */\n\ 161 /* 0: */\n\ 162 .long 0xa603db7f /* mtsrr1 %r30 */\n\ 163 .long 0xa602c87f /* mflr %r30 */\n\ 164 .long 0x1400de3b /* addi %r30, %r30, (1f - 0b) */\n\ 165 .long 0xa603da7f /* mtsrr0 %r30 */\n\ 166 .long 0x2400004c /* rfid */\n\ 167 /* 1: */\n\ 168 1: \n\ 169 /* Back to normal. Tidy up for return. */ \n\ 170 lwz %r30, 8(%r1) \n\ 171 lwz %r0, 20(%r1) \n\ 172 addi %r1, %r1, 16 \n\ 173 mtlr %r0 \n\ 174 blr \n\ 175 "); 176 } 177 178 /* 179 * Little-endian OFW entrypoint replacement. 180 * 181 * We are doing all the byteswapping in one place here to save space. 182 * This means instance handles will be byteswapped as well. 183 */ 184 int 185 call_ofw(ofwcell_t* buf) 186 { 187 int ret, i, ncells; 188 189 ncells = 3 + buf[1] + buf[2]; 190 for (i = 0; i < ncells; i++) 191 buf[i] = htobe32(buf[i]); 192 193 ret = (ofwtramp(buf, realofw)); 194 for (i = 0; i < ncells; i++) 195 buf[i] = be32toh(buf[i]); 196 return (ret); 197 } 198 #endif 199 200 void 201 ofw_init(void *vpd, int res, ofwfp_t openfirm, char *arg, int argl) 202 { 203 char *av[16]; 204 char *p; 205 int ac; 206 207 #if BYTE_ORDER == LITTLE_ENDIAN 208 realofw = openfirm; 209 ofw = call_ofw; 210 #else 211 realofw = ofw = openfirm; 212 #endif 213 214 chosenh = ofw_finddevice("/chosen"); 215 ofw_getprop(chosenh, "stdin", &stdinh, sizeof(stdinh)); 216 stdinh = be32toh(stdinh); 217 ofw_getprop(chosenh, "stdout", &stdouth, sizeof(stdouth)); 218 stdouth = be32toh(stdouth); 219 ofw_getprop(chosenh, "bootargs", bootargs, sizeof(bootargs)); 220 ofw_getprop(chosenh, "bootpath", bootpath, sizeof(bootpath)); 221 222 bootargs[sizeof(bootargs) - 1] = '\0'; 223 bootpath[sizeof(bootpath) - 1] = '\0'; 224 225 p = bootpath; 226 while (*p != '\0') { 227 /* Truncate partition ID */ 228 if (*p == ':') { 229 ofw_close(bootdev); 230 *(++p) = '\0'; 231 break; 232 } 233 p++; 234 } 235 236 ac = 0; 237 p = bootargs; 238 for (;;) { 239 while (*p == ' ' && *p != '\0') 240 p++; 241 if (*p == '\0' || ac >= 16) 242 break; 243 av[ac++] = p; 244 while (*p != ' ' && *p != '\0') 245 p++; 246 if (*p != '\0') 247 *p++ = '\0'; 248 } 249 250 exit(main(ac, av)); 251 } 252 253 static ofwh_t 254 ofw_finddevice(const char *name) 255 { 256 ofwcell_t args[] = { 257 (ofwcell_t)"finddevice", 258 1, 259 1, 260 (ofwcell_t)name, 261 0 262 }; 263 264 if ((*ofw)(args)) { 265 printf("ofw_finddevice: name=\"%s\"\n", name); 266 return (1); 267 } 268 return (args[4]); 269 } 270 271 static int 272 ofw_getprop(ofwh_t ofwh, const char *name, void *buf, size_t len) 273 { 274 ofwcell_t args[] = { 275 (ofwcell_t)"getprop", 276 4, 277 1, 278 (u_ofwh_t)ofwh, 279 (ofwcell_t)name, 280 (ofwcell_t)buf, 281 len, 282 0 283 }; 284 285 if ((*ofw)(args)) { 286 printf("ofw_getprop: ofwh=0x%x buf=%p len=%u\n", 287 ofwh, buf, len); 288 return (1); 289 } 290 return (0); 291 } 292 293 static int 294 ofw_setprop(ofwh_t ofwh, const char *name, void *buf, size_t len) 295 { 296 ofwcell_t args[] = { 297 (ofwcell_t)"setprop", 298 4, 299 1, 300 (u_ofwh_t)ofwh, 301 (ofwcell_t)name, 302 (ofwcell_t)buf, 303 len, 304 0 305 }; 306 307 if ((*ofw)(args)) { 308 printf("ofw_setprop: ofwh=0x%x buf=%p len=%u\n", 309 ofwh, buf, len); 310 return (1); 311 } 312 return (0); 313 } 314 315 static ofwh_t 316 ofw_open(const char *path) 317 { 318 ofwcell_t args[] = { 319 (ofwcell_t)"open", 320 1, 321 1, 322 (ofwcell_t)path, 323 0 324 }; 325 326 if ((*ofw)(args)) { 327 printf("ofw_open: path=\"%s\"\n", path); 328 return (-1); 329 } 330 return (args[4]); 331 } 332 333 static int 334 ofw_close(ofwh_t devh) 335 { 336 ofwcell_t args[] = { 337 (ofwcell_t)"close", 338 1, 339 0, 340 (u_ofwh_t)devh 341 }; 342 343 if ((*ofw)(args)) { 344 printf("ofw_close: devh=0x%x\n", devh); 345 return (1); 346 } 347 return (0); 348 } 349 350 static int 351 ofw_claim(void *virt, size_t len, u_int align) 352 { 353 ofwcell_t args[] = { 354 (ofwcell_t)"claim", 355 3, 356 1, 357 (ofwcell_t)virt, 358 len, 359 align, 360 0, 361 0 362 }; 363 364 if ((*ofw)(args)) { 365 printf("ofw_claim: virt=%p len=%u\n", virt, len); 366 return (1); 367 } 368 369 return (0); 370 } 371 372 static int 373 ofw_read(ofwh_t devh, void *buf, size_t len) 374 { 375 ofwcell_t args[] = { 376 (ofwcell_t)"read", 377 3, 378 1, 379 (u_ofwh_t)devh, 380 (ofwcell_t)buf, 381 len, 382 0 383 }; 384 385 if ((*ofw)(args)) { 386 printf("ofw_read: devh=0x%x buf=%p len=%u\n", devh, buf, len); 387 return (1); 388 } 389 return (0); 390 } 391 392 static int 393 ofw_write(ofwh_t devh, const void *buf, size_t len) 394 { 395 ofwcell_t args[] = { 396 (ofwcell_t)"write", 397 3, 398 1, 399 (u_ofwh_t)devh, 400 (ofwcell_t)buf, 401 len, 402 0 403 }; 404 405 if ((*ofw)(args)) { 406 printf("ofw_write: devh=0x%x buf=%p len=%u\n", devh, buf, len); 407 return (1); 408 } 409 return (0); 410 } 411 412 static int 413 ofw_seek(ofwh_t devh, uint64_t off) 414 { 415 ofwcell_t args[] = { 416 (ofwcell_t)"seek", 417 3, 418 1, 419 (u_ofwh_t)devh, 420 off >> 32, 421 off, 422 0 423 }; 424 425 if ((*ofw)(args)) { 426 printf("ofw_seek: devh=0x%x off=0x%lx\n", devh, off); 427 return (1); 428 } 429 return (0); 430 } 431 432 static void 433 ofw_exit(void) 434 { 435 ofwcell_t args[3]; 436 437 args[0] = (ofwcell_t)"exit"; 438 args[1] = 0; 439 args[2] = 0; 440 441 for (;;) 442 (*ofw)(args); 443 } 444 445 static void 446 bcopy(const void *src, void *dst, size_t len) 447 { 448 const char *s = src; 449 char *d = dst; 450 451 while (len-- != 0) 452 *d++ = *s++; 453 } 454 455 static void 456 memcpy(void *dst, const void *src, size_t len) 457 { 458 bcopy(src, dst, len); 459 } 460 461 static void 462 bzero(void *b, size_t len) 463 { 464 char *p = b; 465 466 while (len-- != 0) 467 *p++ = 0; 468 } 469 470 static int 471 strcmp(const char *s1, const char *s2) 472 { 473 for (; *s1 == *s2 && *s1; s1++, s2++) 474 ; 475 return ((u_char)*s1 - (u_char)*s2); 476 } 477 478 #include "ufsread.c" 479 480 int 481 main(int ac, char **av) 482 { 483 const char *path; 484 char bootpath_full[255]; 485 int i, len; 486 487 path = PATH_LOADER; 488 for (i = 0; i < ac; i++) { 489 switch (av[i][0]) { 490 case '-': 491 switch (av[i][1]) { 492 default: 493 usage(); 494 } 495 break; 496 default: 497 path = av[i]; 498 break; 499 } 500 } 501 502 printf(" \n>> FreeBSD/powerpc Open Firmware boot block\n" 503 " Boot path: %s\n" 504 " Boot loader: %s\n", bootpath, path); 505 506 len = 0; 507 while (bootpath[len] != '\0') len++; 508 509 memcpy(bootpath_full,bootpath,len+1); 510 511 if (bootpath_full[len-1] != ':') { 512 /* First try full volume */ 513 if (domount(bootpath_full,1) == 0) 514 goto out; 515 516 /* Add a : so that we try partitions if that fails */ 517 if (bootdev > 0) 518 ofw_close(bootdev); 519 bootpath_full[len] = ':'; 520 len += 1; 521 } 522 523 /* Loop through first 16 partitions to find a UFS one */ 524 for (i = 0; i < 16; i++) { 525 if (i < 10) { 526 bootpath_full[len] = i + '0'; 527 bootpath_full[len+1] = '\0'; 528 } else { 529 bootpath_full[len] = '1'; 530 bootpath_full[len+1] = i - 10 + '0'; 531 bootpath_full[len+2] = '\0'; 532 } 533 534 if (domount(bootpath_full,1) >= 0) 535 break; 536 537 if (bootdev > 0) 538 ofw_close(bootdev); 539 } 540 541 if (i >= 16) 542 panic("domount"); 543 544 out: 545 printf(" Boot volume: %s\n",bootpath_full); 546 ofw_setprop(chosenh, "bootargs", bootpath_full, len+2); 547 load(path); 548 return (1); 549 } 550 551 static void 552 usage(void) 553 { 554 555 printf("usage: boot device [/path/to/loader]\n"); 556 exit(1); 557 } 558 559 static void 560 exit(int code) 561 { 562 563 ofw_exit(); 564 } 565 566 static struct dmadat __dmadat; 567 568 static int 569 domount(const char *device, int quiet) 570 { 571 572 dmadat = &__dmadat; 573 if ((bootdev = ofw_open(device)) == -1) { 574 printf("domount: can't open device\n"); 575 return (-1); 576 } 577 if (fsread(0, NULL, 0)) { 578 if (!quiet) 579 printf("domount: can't read superblock\n"); 580 return (-1); 581 } 582 return (0); 583 } 584 585 static void 586 load(const char *fname) 587 { 588 Elf32_Ehdr eh; 589 Elf32_Phdr ph; 590 caddr_t p; 591 ufs_ino_t ino; 592 int i; 593 594 if ((ino = lookup(fname)) == 0) { 595 printf("File %s not found\n", fname); 596 return; 597 } 598 if (fsread(ino, &eh, sizeof(eh)) != sizeof(eh)) { 599 printf("Can't read elf header\n"); 600 return; 601 } 602 if (!IS_ELF(eh)) { 603 printf("Not an ELF file\n"); 604 return; 605 } 606 for (i = 0; i < eh.e_phnum; i++) { 607 fs_off = eh.e_phoff + i * eh.e_phentsize; 608 if (fsread(ino, &ph, sizeof(ph)) != sizeof(ph)) { 609 printf("Can't read program header %d\n", i); 610 return; 611 } 612 if (ph.p_type != PT_LOAD) 613 continue; 614 fs_off = ph.p_offset; 615 p = (caddr_t)ph.p_vaddr; 616 ofw_claim(p,(ph.p_filesz > ph.p_memsz) ? 617 ph.p_filesz : ph.p_memsz,0); 618 if (fsread(ino, p, ph.p_filesz) != ph.p_filesz) { 619 printf("Can't read content of section %d\n", i); 620 return; 621 } 622 if (ph.p_filesz != ph.p_memsz) 623 bzero(p + ph.p_filesz, ph.p_memsz - ph.p_filesz); 624 __syncicache(p, ph.p_memsz); 625 } 626 ofw_close(bootdev); 627 (*(void (*)(void *, int, ofwfp_t, char *, int))eh.e_entry)(NULL, 0, 628 realofw, NULL, 0); 629 } 630 631 static int 632 dskread(void *buf, uint64_t lba, int nblk) 633 { 634 /* 635 * The Open Firmware should open the correct partition for us. 636 * That means, if we read from offset zero on an open instance handle, 637 * we should read from offset zero of that partition. 638 */ 639 ofw_seek(bootdev, lba * DEV_BSIZE); 640 ofw_read(bootdev, buf, nblk * DEV_BSIZE); 641 return (0); 642 } 643 644 static void 645 panic(const char *fmt, ...) 646 { 647 char buf[128]; 648 va_list ap; 649 650 va_start(ap, fmt); 651 vsnprintf(buf, sizeof buf, fmt, ap); 652 printf("panic: %s\n", buf); 653 va_end(ap); 654 655 exit(1); 656 } 657 658 static int 659 printf(const char *fmt, ...) 660 { 661 va_list ap; 662 int ret; 663 664 va_start(ap, fmt); 665 ret = vprintf(fmt, ap); 666 va_end(ap); 667 return (ret); 668 } 669 670 static int 671 putchar(char c, void *arg) 672 { 673 char buf; 674 675 if (c == '\n') { 676 buf = '\r'; 677 ofw_write(stdouth, &buf, 1); 678 } 679 buf = c; 680 ofw_write(stdouth, &buf, 1); 681 return (1); 682 } 683 684 static int 685 vprintf(const char *fmt, va_list ap) 686 { 687 int ret; 688 689 ret = __printf(fmt, putchar, 0, ap); 690 return (ret); 691 } 692 693 static int 694 vsnprintf(char *str, size_t sz, const char *fmt, va_list ap) 695 { 696 struct sp_data sp; 697 int ret; 698 699 sp.sp_buf = str; 700 sp.sp_len = 0; 701 sp.sp_size = sz; 702 ret = __printf(fmt, __sputc, &sp, ap); 703 return (ret); 704 } 705 706 static int 707 __printf(const char *fmt, putc_func_t *putc, void *arg, va_list ap) 708 { 709 char buf[(sizeof(long) * 8) + 1]; 710 char *nbuf; 711 u_long ul; 712 u_int ui; 713 int lflag; 714 int sflag; 715 char *s; 716 int pad; 717 int ret; 718 int c; 719 720 nbuf = &buf[sizeof buf - 1]; 721 ret = 0; 722 while ((c = *fmt++) != 0) { 723 if (c != '%') { 724 ret += putc(c, arg); 725 continue; 726 } 727 lflag = 0; 728 sflag = 0; 729 pad = 0; 730 reswitch: c = *fmt++; 731 switch (c) { 732 case '#': 733 sflag = 1; 734 goto reswitch; 735 case '%': 736 ret += putc('%', arg); 737 break; 738 case 'c': 739 c = va_arg(ap, int); 740 ret += putc(c, arg); 741 break; 742 case 'd': 743 if (lflag == 0) { 744 ui = (u_int)va_arg(ap, int); 745 if (ui < (int)ui) { 746 ui = -ui; 747 ret += putc('-', arg); 748 } 749 s = __uitoa(nbuf, ui, 10); 750 } else { 751 ul = (u_long)va_arg(ap, long); 752 if (ul < (long)ul) { 753 ul = -ul; 754 ret += putc('-', arg); 755 } 756 s = __ultoa(nbuf, ul, 10); 757 } 758 ret += __puts(s, putc, arg); 759 break; 760 case 'l': 761 lflag = 1; 762 goto reswitch; 763 case 'o': 764 if (lflag == 0) { 765 ui = (u_int)va_arg(ap, u_int); 766 s = __uitoa(nbuf, ui, 8); 767 } else { 768 ul = (u_long)va_arg(ap, u_long); 769 s = __ultoa(nbuf, ul, 8); 770 } 771 ret += __puts(s, putc, arg); 772 break; 773 case 'p': 774 ul = (u_long)va_arg(ap, void *); 775 s = __ultoa(nbuf, ul, 16); 776 ret += __puts("0x", putc, arg); 777 ret += __puts(s, putc, arg); 778 break; 779 case 's': 780 s = va_arg(ap, char *); 781 ret += __puts(s, putc, arg); 782 break; 783 case 'u': 784 if (lflag == 0) { 785 ui = va_arg(ap, u_int); 786 s = __uitoa(nbuf, ui, 10); 787 } else { 788 ul = va_arg(ap, u_long); 789 s = __ultoa(nbuf, ul, 10); 790 } 791 ret += __puts(s, putc, arg); 792 break; 793 case 'x': 794 if (lflag == 0) { 795 ui = va_arg(ap, u_int); 796 s = __uitoa(nbuf, ui, 16); 797 } else { 798 ul = va_arg(ap, u_long); 799 s = __ultoa(nbuf, ul, 16); 800 } 801 if (sflag) 802 ret += __puts("0x", putc, arg); 803 ret += __puts(s, putc, arg); 804 break; 805 case '0': case '1': case '2': case '3': case '4': 806 case '5': case '6': case '7': case '8': case '9': 807 pad = pad * 10 + c - '0'; 808 goto reswitch; 809 default: 810 break; 811 } 812 } 813 return (ret); 814 } 815 816 static int 817 __sputc(char c, void *arg) 818 { 819 struct sp_data *sp; 820 821 sp = arg; 822 if (sp->sp_len < sp->sp_size) 823 sp->sp_buf[sp->sp_len++] = c; 824 sp->sp_buf[sp->sp_len] = '\0'; 825 return (1); 826 } 827 828 static int 829 __puts(const char *s, putc_func_t *putc, void *arg) 830 { 831 const char *p; 832 int ret; 833 834 ret = 0; 835 for (p = s; *p != '\0'; p++) 836 ret += putc(*p, arg); 837 return (ret); 838 } 839 840 static char * 841 __uitoa(char *buf, u_int ui, int base) 842 { 843 char *p; 844 845 p = buf; 846 *p = '\0'; 847 do 848 *--p = digits[ui % base]; 849 while ((ui /= base) != 0); 850 return (p); 851 } 852 853 static char * 854 __ultoa(char *buf, u_long ul, int base) 855 { 856 char *p; 857 858 p = buf; 859 *p = '\0'; 860 do 861 *--p = digits[ul % base]; 862 while ((ul /= base) != 0); 863 return (p); 864 } 865