1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 /* 30 * Definitions of interfaces that provide services from the secondary 31 * boot program to its clients (primarily Solaris, krtld, kmdb and their 32 * successors.) This interface replaces the bootops (BOP) implementation 33 * as the interface to be called by boot clients. 34 * 35 */ 36 37 #include <sys/types.h> 38 #include <sys/reboot.h> 39 #include <sys/param.h> 40 #include <sys/varargs.h> 41 #include <sys/obpdefs.h> 42 #include <sys/promif.h> 43 #include <sys/bootconf.h> 44 #include <sys/bootstat.h> 45 46 /* 47 * Implementation of the "version" boot service. 48 * Return the compiled version number of this implementation. 49 * 50 * Note: An individual service can be tested for and versioned with 51 * bop_serviceavail(); 52 * 53 * Calling spec: 54 * args[0] Service name string 55 * args[1] #argument cells 56 * args[2] #result cells 57 * args[3] Res0: returned version number 58 */ 59 uint_t 60 bop_getversion(struct bootops *bop) 61 { 62 return (bop->bsys_version); 63 } 64 65 66 /* 67 * Implementation of the "open" boot service. 68 * 69 * Calling spec: 70 * args[0] Service name string 71 * args[1] #argument cells 72 * args[2] #result cells 73 * args[3] filename string 74 * args[4] flags 75 * args[5] Res0: returned result 76 * 77 */ 78 int 79 bop_open(struct bootops *bop, char *name, int flags) 80 { 81 boot_cell_t args[6]; 82 int (*bsys_1275_call)(void *); 83 84 /* use uintptr_t to suppress the gcc warning */ 85 bsys_1275_call = (int (*)(void *))(uintptr_t)bop->bsys_1275_call; 86 args[0] = boot_ptr2cell("open"); 87 args[1] = 2; 88 args[2] = 1; 89 90 args[3] = boot_ptr2cell(name); 91 args[4] = boot_int2cell(flags); 92 (void) (bsys_1275_call)(args); 93 return (boot_cell2int(args[5])); 94 } 95 96 /* 97 * Implementation of the "read" boot service. 98 * 99 * Calling spec: 100 * args[0] Service name string 101 * args[1] #argument cells 102 * args[2] #result cells 103 * args[3] boot-opened file descriptor 104 * args[4] client's buffer 105 * args[5] size of read request 106 * args[6] Res0: returned result 107 * 108 */ 109 int 110 bop_read(struct bootops *bop, int fd, caddr_t buf, size_t size) 111 { 112 boot_cell_t args[7]; 113 int (*bsys_1275_call)(void *); 114 115 /* use uintptr_t to suppress the gcc warning */ 116 bsys_1275_call = (int (*)(void *))(uintptr_t)bop->bsys_1275_call; 117 args[0] = boot_ptr2cell("read"); 118 args[1] = 3; 119 args[2] = 1; 120 121 args[3] = boot_int2cell(fd); 122 args[4] = boot_ptr2cell(buf); 123 args[5] = boot_uint2cell(size); 124 (void) (bsys_1275_call)(args); 125 return (boot_cell2int(args[6])); 126 } 127 128 /* 129 * Implementation of the "seek" boot service. 130 * 131 * Calling spec: 132 * args[0] Service name string 133 * args[1] #argument cells 134 * args[2] #result cells 135 * args[3] boot-opened file descriptor 136 * args[4] offset hi XXX just use one cell for offset? 137 * args[5] offset lo 138 * args[6] Res0: returned result 139 */ 140 int 141 bop_seek(struct bootops *bop, int fd, off_t hi, off_t lo) 142 { 143 boot_cell_t args[7]; 144 int (*bsys_1275_call)(void *); 145 146 /* use uintptr_t to suppress the gcc warning */ 147 bsys_1275_call = (int (*)(void *))(uintptr_t)bop->bsys_1275_call; 148 args[0] = boot_ptr2cell("seek"); 149 args[1] = 3; 150 args[2] = 1; 151 152 args[3] = boot_int2cell(fd); 153 args[4] = boot_offt2cell(hi); 154 args[5] = boot_offt2cell(lo); 155 (void) (bsys_1275_call)(args); 156 return (boot_cell2int(args[6])); 157 } 158 159 /* 160 * Implementation of the "close" boot service. 161 * 162 * Calling spec: 163 * args[0] Service name string 164 * args[1] #argument cells 165 * args[2] #result cells 166 * args[3] boot-opened file descriptor 167 * args[4] Res0: returned result 168 */ 169 int 170 bop_close(struct bootops *bop, int fd) 171 { 172 boot_cell_t args[5]; 173 int (*bsys_1275_call)(void *); 174 175 /* use uintptr_t to suppress the gcc warning */ 176 bsys_1275_call = (int (*)(void *))(uintptr_t)bop->bsys_1275_call; 177 args[0] = boot_ptr2cell("close"); 178 args[1] = 1; 179 args[2] = 1; 180 181 args[3] = boot_int2cell(fd); 182 (void) (bsys_1275_call)(args); 183 return (boot_cell2int(args[4])); 184 } 185 186 /* 187 * Implementation of the "alloc" boot service. 188 * 189 * Calling spec: 190 * args[0] Service name string 191 * args[1] #argument cells 192 * args[2] #result cells 193 * args[3] virtual hint 194 * args[4] size to allocate 195 * args[5] alignment 196 * args[6] Res0: returned result 197 */ 198 caddr_t 199 bop_alloc(struct bootops *bop, caddr_t virthint, size_t size, int align) 200 { 201 boot_cell_t args[7]; 202 int (*bsys_1275_call)(void *); 203 204 /* use uintptr_t to suppress the gcc warning */ 205 bsys_1275_call = (int (*)(void *))(uintptr_t)bop->bsys_1275_call; 206 args[0] = boot_ptr2cell("alloc"); 207 args[1] = 3; 208 args[2] = 1; 209 210 args[3] = boot_ptr2cell(virthint); 211 args[4] = boot_size2cell(size); 212 args[5] = boot_int2cell(align); 213 (void) (bsys_1275_call)(args); 214 return ((caddr_t)(uintptr_t)boot_ptr2cell((uintptr_t)args[6])); 215 } 216 217 /* 218 * Implementation of the "alloc_virt" boot service 219 * 220 * Calling spec: 221 * args[0] Service name string 222 * args[1] #argument cells 223 * args[2] #result cells 224 * args[3] virtual address 225 * args[4] size to allocate 226 * args[5] Resi: returned result 227 */ 228 caddr_t 229 bop_alloc_virt(struct bootops *bop, caddr_t virt, size_t size) 230 { 231 boot_cell_t args[6]; 232 int (*bsys_1275_call)(void *); 233 234 /* use uintptr_t to suppress the gcc warning */ 235 bsys_1275_call = (int (*)(void *))(uintptr_t)bop->bsys_1275_call; 236 args[0] = boot_ptr2cell("alloc_virt"); 237 args[1] = 2; 238 args[2] = 1; 239 240 args[3] = boot_ptr2cell(virt); 241 args[4] = boot_size2cell(size); 242 (void) (bsys_1275_call)(args); 243 return ((caddr_t)(uintptr_t)boot_ptr2cell((uintptr_t)args[5])); 244 } 245 246 /* 247 * Implementation of the "free" boot service. 248 * 249 * Calling spec: 250 * args[0] Service name string 251 * args[1] #argument cells 252 * args[2] #result cells 253 * args[3] virtual hint 254 * args[4] size to free 255 * args[5] Res0: returned result 256 */ 257 /*ARGSUSED*/ 258 void 259 bop_free(struct bootops *bop, caddr_t virt, size_t size) 260 { 261 boot_cell_t args[6]; 262 int (*bsys_1275_call)(void *); 263 264 /* use uintptr_t to suppress the gcc warning */ 265 bsys_1275_call = (int (*)(void *))(uintptr_t)bop->bsys_1275_call; 266 args[0] = boot_ptr2cell("free"); 267 args[1] = 2; 268 args[2] = 1; 269 270 args[3] = boot_ptr2cell(virt); 271 args[4] = boot_size2cell(size); 272 (void) (bsys_1275_call)(args); 273 } 274 275 /* 276 * Implementation of the "map" boot service. 277 * 278 * Calling spec: 279 * args[0] Service name string 280 * args[1] #argument cells 281 * args[2] #result cells 282 * args[3] virtual address 283 * args[4] space of phys addr 284 * args[5] phys addr 285 * args[6] size 286 * args[7] Res0: returned result 287 */ 288 /*ARGSUSED*/ 289 caddr_t 290 bop_map(struct bootops *bop, caddr_t virt, int space, 291 caddr_t phys, size_t size) 292 { 293 boot_cell_t args[8]; 294 int (*bsys_1275_call)(void *); 295 296 /* use uintptr_t to suppress the gcc warning */ 297 bsys_1275_call = (int (*)(void *))(uintptr_t)bop->bsys_1275_call; 298 args[0] = boot_ptr2cell("map"); 299 args[1] = 3; 300 args[2] = 1; 301 302 args[3] = boot_ptr2cell(virt); 303 args[4] = boot_int2cell(space); 304 args[5] = boot_ptr2cell(phys); 305 args[6] = boot_size2cell(size); 306 (void) (bsys_1275_call)(args); 307 return ((caddr_t)boot_cell2ptr(args[7])); 308 } 309 310 /* 311 * Implementation of the "unmap" boot service. 312 * 313 * Calling spec: 314 * args[0] Service name string 315 * args[1] #argument cells 316 * args[2] #result cells 317 * args[3] virtual address 318 * args[4] size of chunk 319 * args[5] Res0: returned result 320 */ 321 /*ARGSUSED*/ 322 void 323 bop_unmap(struct bootops *bop, caddr_t virt, size_t size) 324 { 325 boot_cell_t args[6]; 326 int (*bsys_1275_call)(void *); 327 328 /* use uintptr_t to suppress the gcc warning */ 329 bsys_1275_call = (int (*)(void *))(uintptr_t)bop->bsys_1275_call; 330 args[0] = boot_ptr2cell("unmap"); 331 args[1] = 2; 332 args[2] = 1; 333 334 args[3] = boot_ptr2cell(virt); 335 args[4] = boot_size2cell(size); 336 (void) (bsys_1275_call)(args); 337 } 338 339 /* 340 * Implementation of the "quiesce" boot service. 341 * 342 * Calling spec: 343 * args[0] Service name string 344 * args[1] #argument cells 345 * args[2] #result cells 346 * args[3] Res0: returned result 347 */ 348 /*ARGSUSED*/ 349 void 350 bop_quiesce_io(struct bootops *bop) 351 { 352 boot_cell_t args[4]; 353 int (*bsys_1275_call)(void *); 354 355 /* use uintptr_t to suppress the gcc warning */ 356 bsys_1275_call = (int (*)(void *))(uintptr_t)bop->bsys_1275_call; 357 args[0] = boot_ptr2cell("quiesce"); 358 args[1] = 0; 359 args[2] = 1; 360 361 (void) (bsys_1275_call)(args); 362 } 363 364 /* 365 * Implementation of the "getproplen" boot service. 366 * 367 * Calling spec: 368 * args[0] Service name string 369 * args[1] #argument cells 370 * args[2] #result cells 371 * args[3] property name string 372 * args[4] Res0: returned result 373 */ 374 /*ARGSUSED*/ 375 int 376 bop_getproplen(struct bootops *bop, char *name) 377 { 378 boot_cell_t args[7]; 379 int (*bsys_1275_call)(void *); 380 381 /* use uintptr_t to suppress the gcc warning */ 382 bsys_1275_call = (int (*)(void *))(uintptr_t)bop->bsys_1275_call; 383 args[0] = boot_ptr2cell("getproplen"); 384 args[1] = 1; 385 args[2] = 1; 386 387 args[3] = boot_ptr2cell(name); 388 (void) (bsys_1275_call)(args); 389 return (boot_cell2int(args[4])); 390 } 391 392 /* 393 * Implementation of the "getprop" boot service. 394 * 395 * Calling spec: 396 * args[0] Service name string 397 * args[1] #argument cells 398 * args[2] #result cells 399 * args[3] property name string 400 * args[4] buffer pointer to hold value of the property 401 * args[5] Res0: returned result 402 */ 403 /*ARGSUSED*/ 404 int 405 bop_getprop(struct bootops *bop, char *name, void *value) 406 { 407 boot_cell_t args[6]; 408 int (*bsys_1275_call)(void *); 409 410 /* use uintptr_t to suppress the gcc warning */ 411 bsys_1275_call = (int (*)(void *))(uintptr_t)bop->bsys_1275_call; 412 args[0] = boot_ptr2cell("getprop"); 413 args[1] = 2; 414 args[2] = 1; 415 416 args[3] = boot_ptr2cell(name); 417 args[4] = boot_ptr2cell(value); 418 (void) (bsys_1275_call)(args); 419 return (boot_cell2int(args[5])); 420 } 421 422 /* 423 * Implementation of the "nextprop" boot service. 424 * 425 * Calling spec: 426 * args[0] Service name string 427 * args[1] #argument cells 428 * args[2] #result cells 429 * args[3] previous property name string 430 * args[4] Res0: returned result 431 */ 432 /*ARGSUSED*/ 433 char * 434 bop_nextprop(struct bootops *bop, char *prevprop) 435 { 436 boot_cell_t args[5]; 437 int (*bsys_1275_call)(void *); 438 439 /* use uintptr_t to suppress the gcc warning */ 440 bsys_1275_call = (int (*)(void *))(uintptr_t)bop->bsys_1275_call; 441 args[0] = boot_ptr2cell("nextprop"); 442 args[1] = 1; 443 args[2] = 1; 444 445 args[3] = boot_ptr2cell(prevprop); 446 (void) (bsys_1275_call)(args); 447 return ((char *)boot_cell2ptr(args[4])); 448 } 449 450 /* 451 * Implementation of the "puts" boot service. 452 * 453 * Calling spec: 454 * args[0] Service name string 455 * args[1] #argument cells 456 * args[2] #result cells 457 * args[3] string to print 458 */ 459 /*ARGSUSED*/ 460 void 461 bop_puts(struct bootops *bop, char *string) 462 { 463 boot_cell_t args[6]; 464 int (*bsys_1275_call)(void *); 465 void (*bsys_printf)(struct bootops *, char *, ...); 466 467 /* so new kernel, old boot can print a message before dying */ 468 if (!BOOTOPS_ARE_1275(bop)) { 469 /* use uintptr_t to suppress the gcc warning */ 470 bsys_printf = (void (*)(struct bootops *, char *, ...)) 471 (uintptr_t)bop->bsys_printf; 472 (*bsys_printf)(bop, string); 473 return; 474 } 475 476 bsys_1275_call = (int (*)(void *))(uintptr_t)bop->bsys_1275_call; 477 args[0] = boot_ptr2cell("puts"); 478 args[1] = 1; 479 args[2] = 0; 480 481 args[3] = boot_ptr2cell(string); 482 (void) (bsys_1275_call)(args); 483 484 } 485 486 /* 487 * Implementation of the "putsarg" boot service. 488 * 489 * Calling spec: 490 * args[0] Service name string 491 * args[1] #argument cells 492 * args[2] #result cells 493 * args[3] string to print (with '%*' format) 494 * args[4] 64-bit thing to print 495 */ 496 /*ARGSUSED*/ 497 void 498 bop_putsarg(struct bootops *bop, const char *string, ...) 499 { 500 boot_cell_t args[6]; 501 int (*bsys_1275_call)(void *); 502 void (*bsys_printf)(struct bootops *, char *, ...); 503 va_list ap; 504 const char *fmt = string; 505 int ells = 0; 506 uint64_t arg; 507 508 /* 509 * We need to do the minimum printf-like stuff here to figure 510 * out the size of argument, if present. 511 */ 512 while (*fmt) { 513 if (*fmt++ != '%') 514 continue; 515 if (*fmt == '%') { 516 fmt++; 517 continue; 518 } 519 520 while (*fmt >= '0' && *fmt <= '9') 521 fmt++; 522 for (ells = 0; *fmt == 'l'; fmt++) 523 ells++; 524 va_start(ap, string); 525 switch (*fmt) { 526 case 's': 527 /* use uintptr_t to suppress the gcc warning */ 528 arg = (uint64_t)(uintptr_t)va_arg(ap, char *); 529 break; 530 case 'p': 531 arg = (uint64_t)(uintptr_t)va_arg(ap, void *); 532 break; 533 case 'd': 534 case 'D': 535 case 'x': 536 case 'X': 537 case 'u': 538 case 'U': 539 case 'o': 540 case 'O': 541 if (ells == 0) 542 arg = (uint64_t)va_arg(ap, uint_t); 543 else if (ells == 1) 544 arg = (uint64_t)va_arg(ap, ulong_t); 545 else 546 arg = (uint64_t)va_arg(ap, uint64_t); 547 break; 548 default: 549 arg = (uint64_t)va_arg(ap, uint_t); 550 break; 551 } 552 va_end(ap); 553 break; 554 } 555 556 /* so new kernel, old boot can print a message before dying */ 557 if (!BOOTOPS_ARE_1275(bop)) { 558 /* use uintptr_t to suppress the gcc warning */ 559 bsys_printf = (void (*)(struct bootops *, char *, ...)) 560 (uintptr_t)bop->bsys_printf; 561 (*bsys_printf)(bop, (char *)string, arg); 562 return; 563 } 564 565 bsys_1275_call = (int (*)(void *))(uintptr_t)bop->bsys_1275_call; 566 args[0] = boot_ptr2cell("putsarg"); 567 args[1] = 2; 568 args[2] = 0; 569 args[3] = boot_ptr2cell(string); 570 args[4] = boot_uint642cell(arg); 571 572 (void) (bsys_1275_call)(args); 573 } 574 575 /* 576 * Implementation of the "mount" boot service. 577 * 578 * Calling spec: 579 * args[0] Service name string 580 * args[1] #argument cells 581 * args[2] #result cells 582 * args[3] pathname string 583 * args[4] Res0: returned result 584 */ 585 /*ARGSUSED*/ 586 int 587 bop_mountroot(struct bootops *bop, char *path) 588 { 589 boot_cell_t args[5]; 590 int (*bsys_1275_call)(void *); 591 592 /* use uintptr_t to suppress the gcc warning */ 593 bsys_1275_call = (int (*)(void *))(uintptr_t)bop->bsys_1275_call; 594 args[0] = boot_ptr2cell("mountroot"); 595 args[1] = 2; 596 args[2] = 1; 597 598 args[3] = boot_ptr2cell(path); 599 (void) (bsys_1275_call)(args); 600 return (boot_cell2int(args[4])); 601 } 602 603 /* 604 * Implementation of the "unmountroot" boot service. 605 * 606 * Calling spec: 607 * args[0] Service name string 608 * args[1] #argument cells 609 * args[2] #result cells 610 * args[3] Res0: returned result 611 */ 612 /*ARGSUSED*/ 613 int 614 bop_unmountroot(struct bootops *bop) 615 { 616 boot_cell_t args[4]; 617 int (*bsys_1275_call)(void *); 618 619 /* use uintptr_t to suppress the gcc warning */ 620 bsys_1275_call = (int (*)(void *))(uintptr_t)bop->bsys_1275_call; 621 args[0] = boot_ptr2cell("unmountroot"); 622 args[1] = 0; 623 args[2] = 1; 624 625 (void) (bsys_1275_call)(args); 626 return (boot_cell2int(args[3])); 627 } 628 629 /* 630 * Implementation of the "serviceavail" boot service. 631 * 632 * Calling spec: 633 * args[0] Service name string 634 * args[1] #argument cells 635 * args[2] #result cells 636 * args[3] name string of service to be tested for 637 * args[4] Res0: returned version number or 0 638 */ 639 /*ARGSUSED*/ 640 int 641 bop_serviceavail(struct bootops *bop, char *name) 642 { 643 /* use uintptr_t to suppress the gcc warning */ 644 boot_cell_t args[5]; 645 int (*bsys_1275_call)(void *) = 646 (int (*)(void *))(uintptr_t)bop->bsys_1275_call; 647 648 args[0] = boot_ptr2cell("serviceavail"); 649 args[1] = 1; 650 args[2] = 1; 651 652 args[3] = boot_ptr2cell(name); 653 (void) (bsys_1275_call)(args); 654 return (boot_cell2int(args[4])); 655 } 656 657 /* 658 * Implementation of the "fstat" boot service. 659 * 660 * Calling spec: 661 * args[0] Service name string 662 * args[1] #argument cells 663 * args[2] #result cells 664 * args[3] fd 665 * args[4] client's stat structure 666 */ 667 int 668 bop_fstat(struct bootops *bop, int fd, struct bootstat *st) 669 { 670 boot_cell_t args[6]; 671 int (*bsys_1275_call)(void *); 672 673 /* use uintptr_t to suppress the gcc warning */ 674 bsys_1275_call = (int (*)(void *))(uintptr_t)bop->bsys_1275_call; 675 args[0] = boot_ptr2cell("fstat"); 676 args[1] = 2; 677 args[2] = 1; 678 args[3] = boot_int2cell(fd); 679 args[4] = boot_ptr2cell(st); 680 (void) (bsys_1275_call)(args); 681 return (boot_cell2int(args[5])); 682 } 683 684 /* 685 * Implementation of the "enter_mon" boot service. 686 * 687 * Calling spec: 688 * args[0] Service name string 689 * args[1] #argument cells (0) 690 * args[2] #result cells (0) 691 */ 692 void 693 bop_enter_mon(struct bootops *bop) 694 { 695 boot_cell_t args[4]; 696 int (*bsys_1275_call)(void *); 697 698 /* use uintptr_t to suppress the gcc warning */ 699 bsys_1275_call = (int (*)(void *))(uintptr_t)bop->bsys_1275_call; 700 args[0] = boot_ptr2cell("enter_mon"); 701 args[1] = 0; 702 args[2] = 0; 703 (void) (bsys_1275_call)(args); 704 } 705