boot1.c revision 294721
11590Srgrimes/*- 21590Srgrimes * Copyright (c) 1998 Robert Nordier 31590Srgrimes * All rights reserved. 499821Sjoerg * Copyright (c) 2001 Robert Drehmel 599821Sjoerg * All rights reserved. 61590Srgrimes * 71590Srgrimes * Redistribution and use in source and binary forms are freely 81590Srgrimes * permitted provided that the above copyright notice and this 91590Srgrimes * paragraph and the following disclaimer are duplicated in all 101590Srgrimes * such forms. 111590Srgrimes * 121590Srgrimes * This software is provided "AS IS" and without any express or 131590Srgrimes * implied warranties, including, without limitation, the implied 141590Srgrimes * warranties of merchantability and fitness for a particular 151590Srgrimes * purpose. 161590Srgrimes */ 171590Srgrimes 181590Srgrimes#include <sys/cdefs.h> 191590Srgrimes__FBSDID("$FreeBSD: stable/10/sys/boot/powerpc/boot1.chrp/boot1.c 294721 2016-01-25 10:55:52Z smh $"); 201590Srgrimes 211590Srgrimes#include <sys/param.h> 221590Srgrimes#include <sys/dirent.h> 231590Srgrimes#include <machine/elf.h> 241590Srgrimes#include <machine/stdarg.h> 251590Srgrimes 261590Srgrimes#define _PATH_LOADER "/boot/loader" 271590Srgrimes#define _PATH_KERNEL "/boot/kernel/kernel" 281590Srgrimes 291590Srgrimes#define BSIZEMAX 16384 301590Srgrimes 311590Srgrimestypedef int putc_func_t(char c, void *arg); 321590Srgrimestypedef int32_t ofwh_t; 331590Srgrimes 3499821Sjoergstruct sp_data { 351590Srgrimes char *sp_buf; 3699821Sjoerg u_int sp_len; 3799821Sjoerg u_int sp_size; 38102247Sjohan}; 391590Srgrimes 4079535Srustatic const char digits[] = "0123456789abcdef"; 411590Srgrimes 421590Srgrimesstatic char bootpath[128]; 431590Srgrimesstatic char bootargs[128]; 441590Srgrimes 4568963Srustatic ofwh_t bootdev; 46102246Sjohan 47107276Srustatic struct fs fs; 4899377Sjohanstatic char blkbuf[BSIZEMAX]; 491590Srgrimesstatic unsigned int fsblks; 501590Srgrimes 5168963Srustatic uint32_t fs_off; 5299821Sjoerg 5399821Sjoergint main(int ac, char **av); 54131491Sru 55131491Srustatic void exit(int) __dead2; 5699821Sjoergstatic void load(const char *); 5799821Sjoergstatic int dskread(void *, u_int64_t, int); 5899821Sjoerg 5999821Sjoergstatic void usage(void); 6099821Sjoerg 6199821Sjoergstatic void bcopy(const void *src, void *dst, size_t len); 6299821Sjoergstatic void bzero(void *b, size_t len); 6399821Sjoerg 6499821Sjoergstatic int domount(const char *device, int quiet); 6599821Sjoerg 661590Srgrimesstatic void panic(const char *fmt, ...) __dead2; 6716385Sjoergstatic int printf(const char *fmt, ...); 681590Srgrimesstatic int putchar(char c, void *arg); 691590Srgrimesstatic int vprintf(const char *fmt, va_list ap); 701590Srgrimesstatic int vsnprintf(char *str, size_t sz, const char *fmt, va_list ap); 7199821Sjoerg 72100608Sjohanstatic int __printf(const char *fmt, putc_func_t *putc, void *arg, va_list ap); 73107276Srustatic int __putc(char c, void *arg); 7499821Sjoergstatic int __puts(const char *s, putc_func_t *putc, void *arg); 7599821Sjoergstatic int __sputc(char c, void *arg); 76131491Srustatic char *__uitoa(char *buf, u_int val, int base); 77131491Srustatic char *__ultoa(char *buf, u_long val, int base); 7899821Sjoerg 7999821Sjoergvoid __syncicache(void *, int); 8099821Sjoerg 8199821Sjoerg/* 8299821Sjoerg * Open Firmware interface functions 8399821Sjoerg */ 8499821Sjoergtypedef u_int32_t ofwcell_t; 8599821Sjoergtypedef u_int32_t u_ofwh_t; 8699821Sjoergtypedef int (*ofwfp_t)(void *); 8799821Sjoergofwfp_t ofw; /* the prom Open Firmware entry */ 88131491Sruofwh_t chosenh; 89131491Sru 9099821Sjoergvoid ofw_init(void *, int, int (*)(void *), char *, int); 9199821Sjoergstatic ofwh_t ofw_finddevice(const char *); 9299821Sjoergstatic ofwh_t ofw_open(const char *); 93131491Srustatic int ofw_close(ofwh_t); 94131491Srustatic int ofw_getprop(ofwh_t, const char *, void *, size_t); 9599821Sjoergstatic int ofw_setprop(ofwh_t, const char *, void *, size_t); 9699821Sjoergstatic int ofw_read(ofwh_t, void *, size_t); 9799821Sjoergstatic int ofw_write(ofwh_t, const void *, size_t); 98131491Srustatic int ofw_claim(void *virt, size_t len, u_int align); 99131491Srustatic int ofw_seek(ofwh_t, u_int64_t); 10099821Sjoergstatic void ofw_exit(void) __dead2; 10199821Sjoerg 102102246Sjohanofwh_t bootdevh; 103102246Sjohanofwh_t stdinh, stdouth; 10499821Sjoerg 10599821Sjoerg__asm(" \n\ 10699821Sjoerg .data \n\ 10799821Sjoerg .align 4 \n\ 10899821Sjoergstack: \n\ 10999821Sjoerg .space 16384 \n\ 11099821Sjoerg \n\ 11199821Sjoerg .text \n\ 11299821Sjoerg .globl _start \n\ 11399821Sjoerg_start: \n\ 11499821Sjoerg lis %r1,stack@ha \n\ 11599821Sjoerg addi %r1,%r1,stack@l \n\ 11699821Sjoerg addi %r1,%r1,8192 \n\ 11799821Sjoerg \n\ 11899821Sjoerg b ofw_init \n\ 11999821Sjoerg"); 12099821Sjoerg 12199821Sjoergvoid 12299821Sjoergofw_init(void *vpd, int res, int (*openfirm)(void *), char *arg, int argl) 12399821Sjoerg{ 12499821Sjoerg char *av[16]; 12599821Sjoerg char *p; 12699821Sjoerg int ac; 12799821Sjoerg 12899821Sjoerg ofw = openfirm; 129131491Sru 130131491Sru chosenh = ofw_finddevice("/chosen"); 131102246Sjohan ofw_getprop(chosenh, "stdin", &stdinh, sizeof(stdinh)); 13299821Sjoerg ofw_getprop(chosenh, "stdout", &stdouth, sizeof(stdouth)); 13399821Sjoerg ofw_getprop(chosenh, "bootargs", bootargs, sizeof(bootargs)); 13499821Sjoerg ofw_getprop(chosenh, "bootpath", bootpath, sizeof(bootpath)); 13599821Sjoerg 13699821Sjoerg bootargs[sizeof(bootargs) - 1] = '\0'; 13799821Sjoerg bootpath[sizeof(bootpath) - 1] = '\0'; 13899821Sjoerg 13999821Sjoerg p = bootpath; 14099821Sjoerg while (*p != '\0') { 14199821Sjoerg if (*p == ':') { 14299821Sjoerg *(++p) = '\0'; 14399821Sjoerg break; 14499821Sjoerg } 14599821Sjoerg p++; 14699821Sjoerg } 14799821Sjoerg 14899821Sjoerg ac = 0; 14999821Sjoerg p = bootargs; 15099821Sjoerg for (;;) { 15199821Sjoerg while (*p == ' ' && *p != '\0') 15299821Sjoerg p++; 15399821Sjoerg if (*p == '\0' || ac >= 16) 15499821Sjoerg break; 15599821Sjoerg av[ac++] = p; 15699821Sjoerg while (*p != ' ' && *p != '\0') 1571590Srgrimes p++; 15899821Sjoerg if (*p != '\0') 15999821Sjoerg *p++ = '\0'; 16099821Sjoerg } 16136057Sjkoshy 16216385Sjoerg exit(main(ac, av)); 1631590Srgrimes} 1641590Srgrimes 16568963Srustatic ofwh_t 16699970Scharnierofw_finddevice(const char *name) 16716385Sjoerg{ 16899821Sjoerg ofwcell_t args[] = { 16999821Sjoerg (ofwcell_t)"finddevice", 17099821Sjoerg 1, 17199821Sjoerg 1, 17299821Sjoerg (ofwcell_t)name, 17399821Sjoerg 0 17499821Sjoerg }; 17599821Sjoerg 17699821Sjoerg if ((*ofw)(args)) { 17799821Sjoerg printf("ofw_finddevice: name=\"%s\"\n", name); 17899821Sjoerg return (1); 17999821Sjoerg } 18099821Sjoerg return (args[4]); 18199821Sjoerg} 18299821Sjoerg 18399821Sjoergstatic int 18499821Sjoergofw_getprop(ofwh_t ofwh, const char *name, void *buf, size_t len) 185102246Sjohan{ 186102246Sjohan ofwcell_t args[] = { 187102246Sjohan (ofwcell_t)"getprop", 188102246Sjohan 4, 189102246Sjohan 1, 190102246Sjohan (u_ofwh_t)ofwh, 191 (ofwcell_t)name, 192 (ofwcell_t)buf, 193 len, 194 0 195 }; 196 197 if ((*ofw)(args)) { 198 printf("ofw_getprop: ofwh=0x%x buf=%p len=%u\n", 199 ofwh, buf, len); 200 return (1); 201 } 202 return (0); 203} 204 205static int 206ofw_setprop(ofwh_t ofwh, const char *name, void *buf, size_t len) 207{ 208 ofwcell_t args[] = { 209 (ofwcell_t)"setprop", 210 4, 211 1, 212 (u_ofwh_t)ofwh, 213 (ofwcell_t)name, 214 (ofwcell_t)buf, 215 len, 216 0 217 }; 218 219 if ((*ofw)(args)) { 220 printf("ofw_setprop: ofwh=0x%x buf=%p len=%u\n", 221 ofwh, buf, len); 222 return (1); 223 } 224 return (0); 225} 226 227static ofwh_t 228ofw_open(const char *path) 229{ 230 ofwcell_t args[] = { 231 (ofwcell_t)"open", 232 1, 233 1, 234 (ofwcell_t)path, 235 0 236 }; 237 238 if ((*ofw)(args)) { 239 printf("ofw_open: path=\"%s\"\n", path); 240 return (-1); 241 } 242 return (args[4]); 243} 244 245static int 246ofw_close(ofwh_t devh) 247{ 248 ofwcell_t args[] = { 249 (ofwcell_t)"close", 250 1, 251 0, 252 (u_ofwh_t)devh 253 }; 254 255 if ((*ofw)(args)) { 256 printf("ofw_close: devh=0x%x\n", devh); 257 return (1); 258 } 259 return (0); 260} 261 262static int 263ofw_claim(void *virt, size_t len, u_int align) 264{ 265 ofwcell_t args[] = { 266 (ofwcell_t)"claim", 267 3, 268 1, 269 (ofwcell_t)virt, 270 len, 271 align, 272 0, 273 0 274 }; 275 276 if ((*ofw)(args)) { 277 printf("ofw_claim: virt=%p len=%u\n", virt, len); 278 return (1); 279 } 280 281 return (0); 282} 283 284static int 285ofw_read(ofwh_t devh, void *buf, size_t len) 286{ 287 ofwcell_t args[] = { 288 (ofwcell_t)"read", 289 3, 290 1, 291 (u_ofwh_t)devh, 292 (ofwcell_t)buf, 293 len, 294 0 295 }; 296 297 if ((*ofw)(args)) { 298 printf("ofw_read: devh=0x%x buf=%p len=%u\n", devh, buf, len); 299 return (1); 300 } 301 return (0); 302} 303 304static int 305ofw_write(ofwh_t devh, const void *buf, size_t len) 306{ 307 ofwcell_t args[] = { 308 (ofwcell_t)"write", 309 3, 310 1, 311 (u_ofwh_t)devh, 312 (ofwcell_t)buf, 313 len, 314 0 315 }; 316 317 if ((*ofw)(args)) { 318 printf("ofw_write: devh=0x%x buf=%p len=%u\n", devh, buf, len); 319 return (1); 320 } 321 return (0); 322} 323 324static int 325ofw_seek(ofwh_t devh, u_int64_t off) 326{ 327 ofwcell_t args[] = { 328 (ofwcell_t)"seek", 329 3, 330 1, 331 (u_ofwh_t)devh, 332 off >> 32, 333 off, 334 0 335 }; 336 337 if ((*ofw)(args)) { 338 printf("ofw_seek: devh=0x%x off=0x%lx\n", devh, off); 339 return (1); 340 } 341 return (0); 342} 343 344static void 345ofw_exit(void) 346{ 347 ofwcell_t args[3]; 348 349 args[0] = (ofwcell_t)"exit"; 350 args[1] = 0; 351 args[2] = 0; 352 353 for (;;) 354 (*ofw)(args); 355} 356 357static void 358bcopy(const void *src, void *dst, size_t len) 359{ 360 const char *s = src; 361 char *d = dst; 362 363 while (len-- != 0) 364 *d++ = *s++; 365} 366 367static void 368memcpy(void *dst, const void *src, size_t len) 369{ 370 bcopy(src, dst, len); 371} 372 373static void 374bzero(void *b, size_t len) 375{ 376 char *p = b; 377 378 while (len-- != 0) 379 *p++ = 0; 380} 381 382static int 383strcmp(const char *s1, const char *s2) 384{ 385 for (; *s1 == *s2 && *s1; s1++, s2++) 386 ; 387 return ((u_char)*s1 - (u_char)*s2); 388} 389 390#include "ufsread.c" 391 392int 393main(int ac, char **av) 394{ 395 const char *path; 396 char bootpath_full[255]; 397 int i, len; 398 399 path = _PATH_LOADER; 400 for (i = 0; i < ac; i++) { 401 switch (av[i][0]) { 402 case '-': 403 switch (av[i][1]) { 404 default: 405 usage(); 406 } 407 break; 408 default: 409 path = av[i]; 410 break; 411 } 412 } 413 414 printf(" \n>> FreeBSD/powerpc Open Firmware boot block\n" 415 " Boot path: %s\n" 416 " Boot loader: %s\n", bootpath, path); 417 418 len = 0; 419 while (bootpath[len] != '\0') len++; 420 421 memcpy(bootpath_full,bootpath,len+1); 422 423 if (bootpath_full[len-1] == ':') { 424 for (i = 0; i < 16; i++) { 425 if (i < 10) { 426 bootpath_full[len] = i + '0'; 427 bootpath_full[len+1] = '\0'; 428 } else { 429 bootpath_full[len] = '1'; 430 bootpath_full[len+1] = i - 10 + '0'; 431 bootpath_full[len+2] = '\0'; 432 } 433 434 if (domount(bootpath_full,1) >= 0) 435 break; 436 437 if (bootdev > 0) 438 ofw_close(bootdev); 439 } 440 441 if (i >= 16) 442 panic("domount"); 443 } else { 444 if (domount(bootpath_full,0) == -1) 445 panic("domount"); 446 } 447 448 printf(" Boot volume: %s\n",bootpath_full); 449 ofw_setprop(chosenh, "bootargs", bootpath_full, len+2); 450 load(path); 451 return (1); 452} 453 454static void 455usage(void) 456{ 457 458 printf("usage: boot device [/path/to/loader]\n"); 459 exit(1); 460} 461 462static void 463exit(int code) 464{ 465 466 ofw_exit(); 467} 468 469static struct dmadat __dmadat; 470 471static int 472domount(const char *device, int quiet) 473{ 474 475 dmadat = &__dmadat; 476 if ((bootdev = ofw_open(device)) == -1) { 477 printf("domount: can't open device\n"); 478 return (-1); 479 } 480 if (fsread(0, NULL, 0)) { 481 if (!quiet) 482 printf("domount: can't read superblock\n"); 483 return (-1); 484 } 485 return (0); 486} 487 488static void 489load(const char *fname) 490{ 491 Elf32_Ehdr eh; 492 Elf32_Phdr ph; 493 caddr_t p; 494 ufs_ino_t ino; 495 int i; 496 497 if ((ino = lookup(fname)) == 0) { 498 printf("File %s not found\n", fname); 499 return; 500 } 501 if (fsread(ino, &eh, sizeof(eh)) != sizeof(eh)) { 502 printf("Can't read elf header\n"); 503 return; 504 } 505 if (!IS_ELF(eh)) { 506 printf("Not an ELF file\n"); 507 return; 508 } 509 for (i = 0; i < eh.e_phnum; i++) { 510 fs_off = eh.e_phoff + i * eh.e_phentsize; 511 if (fsread(ino, &ph, sizeof(ph)) != sizeof(ph)) { 512 printf("Can't read program header %d\n", i); 513 return; 514 } 515 if (ph.p_type != PT_LOAD) 516 continue; 517 fs_off = ph.p_offset; 518 p = (caddr_t)ph.p_vaddr; 519 ofw_claim(p,(ph.p_filesz > ph.p_memsz) ? 520 ph.p_filesz : ph.p_memsz,0); 521 if (fsread(ino, p, ph.p_filesz) != ph.p_filesz) { 522 printf("Can't read content of section %d\n", i); 523 return; 524 } 525 if (ph.p_filesz != ph.p_memsz) 526 bzero(p + ph.p_filesz, ph.p_memsz - ph.p_filesz); 527 __syncicache(p, ph.p_memsz); 528 } 529 ofw_close(bootdev); 530 (*(void (*)(void *, int, ofwfp_t, char *, int))eh.e_entry)(NULL, 0, 531 ofw,NULL,0); 532} 533 534static int 535dskread(void *buf, u_int64_t lba, int nblk) 536{ 537 /* 538 * The Open Firmware should open the correct partition for us. 539 * That means, if we read from offset zero on an open instance handle, 540 * we should read from offset zero of that partition. 541 */ 542 ofw_seek(bootdev, lba * DEV_BSIZE); 543 ofw_read(bootdev, buf, nblk * DEV_BSIZE); 544 return (0); 545} 546 547static void 548panic(const char *fmt, ...) 549{ 550 char buf[128]; 551 va_list ap; 552 553 va_start(ap, fmt); 554 vsnprintf(buf, sizeof buf, fmt, ap); 555 printf("panic: %s\n", buf); 556 va_end(ap); 557 558 exit(1); 559} 560 561static int 562printf(const char *fmt, ...) 563{ 564 va_list ap; 565 int ret; 566 567 va_start(ap, fmt); 568 ret = vprintf(fmt, ap); 569 va_end(ap); 570 return (ret); 571} 572 573static int 574putchar(char c, void *arg) 575{ 576 char buf; 577 578 if (c == '\n') { 579 buf = '\r'; 580 ofw_write(stdouth, &buf, 1); 581 } 582 buf = c; 583 ofw_write(stdouth, &buf, 1); 584 return (1); 585} 586 587static int 588vprintf(const char *fmt, va_list ap) 589{ 590 int ret; 591 592 ret = __printf(fmt, putchar, 0, ap); 593 return (ret); 594} 595 596static int 597vsnprintf(char *str, size_t sz, const char *fmt, va_list ap) 598{ 599 struct sp_data sp; 600 int ret; 601 602 sp.sp_buf = str; 603 sp.sp_len = 0; 604 sp.sp_size = sz; 605 ret = __printf(fmt, __sputc, &sp, ap); 606 return (ret); 607} 608 609static int 610__printf(const char *fmt, putc_func_t *putc, void *arg, va_list ap) 611{ 612 char buf[(sizeof(long) * 8) + 1]; 613 char *nbuf; 614 u_long ul; 615 u_int ui; 616 int lflag; 617 int sflag; 618 char *s; 619 int pad; 620 int ret; 621 int c; 622 623 nbuf = &buf[sizeof buf - 1]; 624 ret = 0; 625 while ((c = *fmt++) != 0) { 626 if (c != '%') { 627 ret += putc(c, arg); 628 continue; 629 } 630 lflag = 0; 631 sflag = 0; 632 pad = 0; 633reswitch: c = *fmt++; 634 switch (c) { 635 case '#': 636 sflag = 1; 637 goto reswitch; 638 case '%': 639 ret += putc('%', arg); 640 break; 641 case 'c': 642 c = va_arg(ap, int); 643 ret += putc(c, arg); 644 break; 645 case 'd': 646 if (lflag == 0) { 647 ui = (u_int)va_arg(ap, int); 648 if (ui < (int)ui) { 649 ui = -ui; 650 ret += putc('-', arg); 651 } 652 s = __uitoa(nbuf, ui, 10); 653 } else { 654 ul = (u_long)va_arg(ap, long); 655 if (ul < (long)ul) { 656 ul = -ul; 657 ret += putc('-', arg); 658 } 659 s = __ultoa(nbuf, ul, 10); 660 } 661 ret += __puts(s, putc, arg); 662 break; 663 case 'l': 664 lflag = 1; 665 goto reswitch; 666 case 'o': 667 if (lflag == 0) { 668 ui = (u_int)va_arg(ap, u_int); 669 s = __uitoa(nbuf, ui, 8); 670 } else { 671 ul = (u_long)va_arg(ap, u_long); 672 s = __ultoa(nbuf, ul, 8); 673 } 674 ret += __puts(s, putc, arg); 675 break; 676 case 'p': 677 ul = (u_long)va_arg(ap, void *); 678 s = __ultoa(nbuf, ul, 16); 679 ret += __puts("0x", putc, arg); 680 ret += __puts(s, putc, arg); 681 break; 682 case 's': 683 s = va_arg(ap, char *); 684 ret += __puts(s, putc, arg); 685 break; 686 case 'u': 687 if (lflag == 0) { 688 ui = va_arg(ap, u_int); 689 s = __uitoa(nbuf, ui, 10); 690 } else { 691 ul = va_arg(ap, u_long); 692 s = __ultoa(nbuf, ul, 10); 693 } 694 ret += __puts(s, putc, arg); 695 break; 696 case 'x': 697 if (lflag == 0) { 698 ui = va_arg(ap, u_int); 699 s = __uitoa(nbuf, ui, 16); 700 } else { 701 ul = va_arg(ap, u_long); 702 s = __ultoa(nbuf, ul, 16); 703 } 704 if (sflag) 705 ret += __puts("0x", putc, arg); 706 ret += __puts(s, putc, arg); 707 break; 708 case '0': case '1': case '2': case '3': case '4': 709 case '5': case '6': case '7': case '8': case '9': 710 pad = pad * 10 + c - '0'; 711 goto reswitch; 712 default: 713 break; 714 } 715 } 716 return (ret); 717} 718 719static int 720__sputc(char c, void *arg) 721{ 722 struct sp_data *sp; 723 724 sp = arg; 725 if (sp->sp_len < sp->sp_size) 726 sp->sp_buf[sp->sp_len++] = c; 727 sp->sp_buf[sp->sp_len] = '\0'; 728 return (1); 729} 730 731static int 732__puts(const char *s, putc_func_t *putc, void *arg) 733{ 734 const char *p; 735 int ret; 736 737 ret = 0; 738 for (p = s; *p != '\0'; p++) 739 ret += putc(*p, arg); 740 return (ret); 741} 742 743static char * 744__uitoa(char *buf, u_int ui, int base) 745{ 746 char *p; 747 748 p = buf; 749 *p = '\0'; 750 do 751 *--p = digits[ui % base]; 752 while ((ui /= base) != 0); 753 return (p); 754} 755 756static char * 757__ultoa(char *buf, u_long ul, int base) 758{ 759 char *p; 760 761 p = buf; 762 *p = '\0'; 763 do 764 *--p = digits[ul % base]; 765 while ((ul /= base) != 0); 766 return (p); 767} 768