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 2004 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 bsys_1275_call = (int (*)(void *))bop->bsys_1275_call; 85 args[0] = boot_ptr2cell("open"); 86 args[1] = 2; 87 args[2] = 1; 88 89 args[3] = boot_ptr2cell(name); 90 args[4] = boot_int2cell(flags); 91 (void) (bsys_1275_call)(args); 92 return (boot_cell2int(args[5])); 93 } 94 95 /* 96 * Implementation of the "read" boot service. 97 * 98 * Calling spec: 99 * args[0] Service name string 100 * args[1] #argument cells 101 * args[2] #result cells 102 * args[3] boot-opened file descriptor 103 * args[4] client's buffer 104 * args[5] size of read request 105 * args[6] Res0: returned result 106 * 107 */ 108 int 109 bop_read(struct bootops *bop, int fd, caddr_t buf, size_t size) 110 { 111 boot_cell_t args[7]; 112 int (*bsys_1275_call)(void *); 113 114 bsys_1275_call = (int (*)(void *))bop->bsys_1275_call; 115 args[0] = boot_ptr2cell("read"); 116 args[1] = 3; 117 args[2] = 1; 118 119 args[3] = boot_int2cell(fd); 120 args[4] = boot_ptr2cell(buf); 121 args[5] = boot_uint2cell(size); 122 (void) (bsys_1275_call)(args); 123 return (boot_cell2int(args[6])); 124 } 125 126 /* 127 * Implementation of the "seek" boot service. 128 * 129 * Calling spec: 130 * args[0] Service name string 131 * args[1] #argument cells 132 * args[2] #result cells 133 * args[3] boot-opened file descriptor 134 * args[4] offset hi XXX just use one cell for offset? 135 * args[5] offset lo 136 * args[6] Res0: returned result 137 */ 138 int 139 bop_seek(struct bootops *bop, int fd, off_t hi, off_t lo) 140 { 141 boot_cell_t args[7]; 142 int (*bsys_1275_call)(void *); 143 144 bsys_1275_call = (int (*)(void *))bop->bsys_1275_call; 145 args[0] = boot_ptr2cell("seek"); 146 args[1] = 3; 147 args[2] = 1; 148 149 args[3] = boot_int2cell(fd); 150 args[4] = boot_offt2cell(hi); 151 args[5] = boot_offt2cell(lo); 152 (void) (bsys_1275_call)(args); 153 return (boot_cell2int(args[6])); 154 } 155 156 /* 157 * Implementation of the "close" boot service. 158 * 159 * Calling spec: 160 * args[0] Service name string 161 * args[1] #argument cells 162 * args[2] #result cells 163 * args[3] boot-opened file descriptor 164 * args[4] Res0: returned result 165 */ 166 int 167 bop_close(struct bootops *bop, int fd) 168 { 169 boot_cell_t args[5]; 170 int (*bsys_1275_call)(void *); 171 172 bsys_1275_call = (int (*)(void *))bop->bsys_1275_call; 173 args[0] = boot_ptr2cell("close"); 174 args[1] = 1; 175 args[2] = 1; 176 177 args[3] = boot_int2cell(fd); 178 (void) (bsys_1275_call)(args); 179 return (boot_cell2int(args[4])); 180 } 181 182 /* 183 * Implementation of the "alloc" boot service. 184 * 185 * Calling spec: 186 * args[0] Service name string 187 * args[1] #argument cells 188 * args[2] #result cells 189 * args[3] virtual hint 190 * args[4] size to allocate 191 * args[5] alignment 192 * args[6] Res0: returned result 193 */ 194 caddr_t 195 bop_alloc(struct bootops *bop, caddr_t virthint, size_t size, int align) 196 { 197 boot_cell_t args[7]; 198 int (*bsys_1275_call)(void *); 199 200 bsys_1275_call = (int (*)(void *))bop->bsys_1275_call; 201 args[0] = boot_ptr2cell("alloc"); 202 args[1] = 3; 203 args[2] = 1; 204 205 args[3] = boot_ptr2cell(virthint); 206 args[4] = boot_size2cell(size); 207 args[5] = boot_int2cell(align); 208 (void) (bsys_1275_call)(args); 209 return ((caddr_t)boot_ptr2cell(args[6])); 210 } 211 212 /* 213 * Implementation of the "alloc_virt" boot service 214 * 215 * Calling spec: 216 * args[0] Service name string 217 * args[1] #argument cells 218 * args[2] #result cells 219 * args[3] virtual address 220 * args[4] size to allocate 221 * args[5] Resi: returned result 222 */ 223 caddr_t 224 bop_alloc_virt(struct bootops *bop, caddr_t virt, size_t size) 225 { 226 boot_cell_t args[6]; 227 int (*bsys_1275_call)(void *); 228 229 bsys_1275_call = (int (*)(void *))bop->bsys_1275_call; 230 args[0] = boot_ptr2cell("alloc_virt"); 231 args[1] = 2; 232 args[2] = 1; 233 234 args[3] = boot_ptr2cell(virt); 235 args[4] = boot_size2cell(size); 236 (void) (bsys_1275_call)(args); 237 return ((caddr_t)boot_ptr2cell(args[5])); 238 } 239 240 /* 241 * Implementation of the "free" boot service. 242 * 243 * Calling spec: 244 * args[0] Service name string 245 * args[1] #argument cells 246 * args[2] #result cells 247 * args[3] virtual hint 248 * args[4] size to free 249 * args[5] Res0: returned result 250 */ 251 /*ARGSUSED*/ 252 void 253 bop_free(struct bootops *bop, caddr_t virt, size_t size) 254 { 255 boot_cell_t args[6]; 256 int (*bsys_1275_call)(void *); 257 258 bsys_1275_call = (int (*)(void *))bop->bsys_1275_call; 259 args[0] = boot_ptr2cell("free"); 260 args[1] = 2; 261 args[2] = 1; 262 263 args[3] = boot_ptr2cell(virt); 264 args[4] = boot_size2cell(size); 265 (void) (bsys_1275_call)(args); 266 } 267 268 /* 269 * Implementation of the "map" boot service. 270 * 271 * Calling spec: 272 * args[0] Service name string 273 * args[1] #argument cells 274 * args[2] #result cells 275 * args[3] virtual address 276 * args[4] space of phys addr 277 * args[5] phys addr 278 * args[6] size 279 * args[7] Res0: returned result 280 */ 281 /*ARGSUSED*/ 282 caddr_t 283 bop_map(struct bootops *bop, caddr_t virt, int space, 284 caddr_t phys, size_t size) 285 { 286 boot_cell_t args[8]; 287 int (*bsys_1275_call)(void *); 288 289 bsys_1275_call = (int (*)(void *))bop->bsys_1275_call; 290 args[0] = boot_ptr2cell("map"); 291 args[1] = 3; 292 args[2] = 1; 293 294 args[3] = boot_ptr2cell(virt); 295 args[4] = boot_int2cell(space); 296 args[5] = boot_ptr2cell(phys); 297 args[6] = boot_size2cell(size); 298 (void) (bsys_1275_call)(args); 299 return ((caddr_t)boot_cell2ptr(args[7])); 300 } 301 302 /* 303 * Implementation of the "unmap" boot service. 304 * 305 * Calling spec: 306 * args[0] Service name string 307 * args[1] #argument cells 308 * args[2] #result cells 309 * args[3] virtual address 310 * args[4] size of chunk 311 * args[5] Res0: returned result 312 */ 313 /*ARGSUSED*/ 314 void 315 bop_unmap(struct bootops *bop, caddr_t virt, size_t size) 316 { 317 boot_cell_t args[6]; 318 int (*bsys_1275_call)(void *); 319 320 bsys_1275_call = (int (*)(void *))bop->bsys_1275_call; 321 args[0] = boot_ptr2cell("unmap"); 322 args[1] = 2; 323 args[2] = 1; 324 325 args[3] = boot_ptr2cell(virt); 326 args[4] = boot_size2cell(size); 327 (void) (bsys_1275_call)(args); 328 } 329 330 /* 331 * Implementation of the "quiesce" boot service. 332 * 333 * Calling spec: 334 * args[0] Service name string 335 * args[1] #argument cells 336 * args[2] #result cells 337 * args[3] Res0: returned result 338 */ 339 /*ARGSUSED*/ 340 void 341 bop_quiesce_io(struct bootops *bop) 342 { 343 boot_cell_t args[4]; 344 int (*bsys_1275_call)(void *); 345 346 bsys_1275_call = (int (*)(void *))bop->bsys_1275_call; 347 args[0] = boot_ptr2cell("quiesce"); 348 args[1] = 0; 349 args[2] = 1; 350 351 (void) (bsys_1275_call)(args); 352 } 353 354 /* 355 * Implementation of the "getproplen" boot service. 356 * 357 * Calling spec: 358 * args[0] Service name string 359 * args[1] #argument cells 360 * args[2] #result cells 361 * args[3] property name string 362 * args[4] Res0: returned result 363 */ 364 /*ARGSUSED*/ 365 int 366 bop_getproplen(struct bootops *bop, char *name) 367 { 368 boot_cell_t args[7]; 369 int (*bsys_1275_call)(void *); 370 371 bsys_1275_call = (int (*)(void *))bop->bsys_1275_call; 372 args[0] = boot_ptr2cell("getproplen"); 373 args[1] = 1; 374 args[2] = 1; 375 376 args[3] = boot_ptr2cell(name); 377 (void) (bsys_1275_call)(args); 378 return (boot_cell2int(args[4])); 379 } 380 381 /* 382 * Implementation of the "getprop" boot service. 383 * 384 * Calling spec: 385 * args[0] Service name string 386 * args[1] #argument cells 387 * args[2] #result cells 388 * args[3] property name string 389 * args[4] buffer pointer to hold value of the property 390 * args[5] Res0: returned result 391 */ 392 /*ARGSUSED*/ 393 int 394 bop_getprop(struct bootops *bop, char *name, void *value) 395 { 396 boot_cell_t args[6]; 397 int (*bsys_1275_call)(void *); 398 399 bsys_1275_call = (int (*)(void *))bop->bsys_1275_call; 400 args[0] = boot_ptr2cell("getprop"); 401 args[1] = 2; 402 args[2] = 1; 403 404 args[3] = boot_ptr2cell(name); 405 args[4] = boot_ptr2cell(value); 406 (void) (bsys_1275_call)(args); 407 return (boot_cell2int(args[5])); 408 } 409 410 /* 411 * Implementation of the "nextprop" boot service. 412 * 413 * Calling spec: 414 * args[0] Service name string 415 * args[1] #argument cells 416 * args[2] #result cells 417 * args[3] previous property name string 418 * args[4] Res0: returned result 419 */ 420 /*ARGSUSED*/ 421 char * 422 bop_nextprop(struct bootops *bop, char *prevprop) 423 { 424 boot_cell_t args[5]; 425 int (*bsys_1275_call)(void *); 426 427 bsys_1275_call = (int (*)(void *))bop->bsys_1275_call; 428 args[0] = boot_ptr2cell("nextprop"); 429 args[1] = 1; 430 args[2] = 1; 431 432 args[3] = boot_ptr2cell(prevprop); 433 (void) (bsys_1275_call)(args); 434 return ((char *)boot_cell2ptr(args[4])); 435 } 436 437 /* 438 * Implementation of the "puts" boot service. 439 * 440 * Calling spec: 441 * args[0] Service name string 442 * args[1] #argument cells 443 * args[2] #result cells 444 * args[3] string to print 445 */ 446 /*ARGSUSED*/ 447 void 448 bop_puts(struct bootops *bop, char *string) 449 { 450 boot_cell_t args[6]; 451 int (*bsys_1275_call)(void *); 452 void (*bsys_printf)(struct bootops *, char *, ...); 453 454 /* so new kernel, old boot can print a message before dying */ 455 if (!BOOTOPS_ARE_1275(bop)) { 456 bsys_printf = (void (*)(struct bootops *, char *, ...)) 457 (bop->bsys_printf); 458 (*bsys_printf)(bop, string); 459 return; 460 } 461 bsys_1275_call = (int (*)(void *))bop->bsys_1275_call; 462 args[0] = boot_ptr2cell("puts"); 463 args[1] = 1; 464 args[2] = 0; 465 466 args[3] = boot_ptr2cell(string); 467 (void) (bsys_1275_call)(args); 468 469 } 470 471 /* 472 * Implementation of the "putsarg" boot service. 473 * 474 * Calling spec: 475 * args[0] Service name string 476 * args[1] #argument cells 477 * args[2] #result cells 478 * args[3] string to print (with '%*' format) 479 * args[4] 64-bit thing to print 480 */ 481 /*ARGSUSED*/ 482 void 483 bop_putsarg(struct bootops *bop, const char *string, ...) 484 { 485 boot_cell_t args[6]; 486 int (*bsys_1275_call)(void *); 487 void (*bsys_printf)(struct bootops *, char *, ...); 488 va_list ap; 489 const char *fmt = string; 490 int ells = 0; 491 uint64_t arg; 492 493 /* 494 * We need to do the minimum printf-like stuff here to figure 495 * out the size of argument, if present. 496 */ 497 while (*fmt) { 498 if (*fmt++ != '%') 499 continue; 500 if (*fmt == '%') { 501 fmt++; 502 continue; 503 } 504 505 while (*fmt >= '0' && *fmt <= '9') 506 fmt++; 507 for (ells = 0; *fmt == 'l'; fmt++) 508 ells++; 509 va_start(ap, string); 510 switch (*fmt) { 511 case 's': 512 arg = (uint64_t)va_arg(ap, char *); 513 break; 514 case 'p': 515 arg = (uint64_t)va_arg(ap, void *); 516 break; 517 case 'd': 518 case 'D': 519 case 'x': 520 case 'X': 521 case 'u': 522 case 'U': 523 case 'o': 524 case 'O': 525 if (ells == 0) 526 arg = (uint64_t)va_arg(ap, uint_t); 527 else if (ells == 1) 528 arg = (uint64_t)va_arg(ap, ulong_t); 529 else 530 arg = (uint64_t)va_arg(ap, uint64_t); 531 break; 532 default: 533 arg = (uint64_t)va_arg(ap, uint_t); 534 break; 535 } 536 va_end(ap); 537 break; 538 } 539 540 /* so new kernel, old boot can print a message before dying */ 541 if (!BOOTOPS_ARE_1275(bop)) { 542 bsys_printf = (void (*)(struct bootops *, char *, ...)) 543 (bop->bsys_printf); 544 (*bsys_printf)(bop, (char *)string, arg); 545 return; 546 } 547 548 bsys_1275_call = (int (*)(void *))bop->bsys_1275_call; 549 args[0] = boot_ptr2cell("putsarg"); 550 args[1] = 2; 551 args[2] = 0; 552 args[3] = boot_ptr2cell(string); 553 args[4] = boot_uint642cell(arg); 554 555 (void) (bsys_1275_call)(args); 556 } 557 558 /* 559 * Implementation of the "mount" boot service. 560 * 561 * Calling spec: 562 * args[0] Service name string 563 * args[1] #argument cells 564 * args[2] #result cells 565 * args[3] pathname string 566 * args[4] Res0: returned result 567 */ 568 /*ARGSUSED*/ 569 int 570 bop_mountroot(struct bootops *bop, char *path) 571 { 572 boot_cell_t args[5]; 573 int (*bsys_1275_call)(void *); 574 575 bsys_1275_call = (int (*)(void *))bop->bsys_1275_call; 576 args[0] = boot_ptr2cell("mountroot"); 577 args[1] = 2; 578 args[2] = 1; 579 580 args[3] = boot_ptr2cell(path); 581 (void) (bsys_1275_call)(args); 582 return (boot_cell2int(args[4])); 583 } 584 585 /* 586 * Implementation of the "unmountroot" boot service. 587 * 588 * Calling spec: 589 * args[0] Service name string 590 * args[1] #argument cells 591 * args[2] #result cells 592 * args[3] Res0: returned result 593 */ 594 /*ARGSUSED*/ 595 int 596 bop_unmountroot(struct bootops *bop) 597 { 598 boot_cell_t args[4]; 599 int (*bsys_1275_call)(void *); 600 601 bsys_1275_call = (int (*)(void *))bop->bsys_1275_call; 602 args[0] = boot_ptr2cell("unmountroot"); 603 args[1] = 0; 604 args[2] = 1; 605 606 (void) (bsys_1275_call)(args); 607 return (boot_cell2int(args[3])); 608 } 609 610 /* 611 * Implementation of the "serviceavail" boot service. 612 * 613 * Calling spec: 614 * args[0] Service name string 615 * args[1] #argument cells 616 * args[2] #result cells 617 * args[3] name string of service to be tested for 618 * args[4] Res0: returned version number or 0 619 */ 620 /*ARGSUSED*/ 621 int 622 bop_serviceavail(struct bootops *bop, char *name) 623 { 624 boot_cell_t args[5]; 625 int (*bsys_1275_call)(void *) = 626 (int (*)(void *))bop->bsys_1275_call; 627 628 args[0] = boot_ptr2cell("serviceavail"); 629 args[1] = 1; 630 args[2] = 1; 631 632 args[3] = boot_ptr2cell(name); 633 (void) (bsys_1275_call)(args); 634 return (boot_cell2int(args[4])); 635 } 636 637 /* 638 * Implementation of the "fstat" boot service. 639 * 640 * Calling spec: 641 * args[0] Service name string 642 * args[1] #argument cells 643 * args[2] #result cells 644 * args[3] fd 645 * args[4] client's stat structure 646 */ 647 int 648 bop_fstat(struct bootops *bop, int fd, struct bootstat *st) 649 { 650 boot_cell_t args[6]; 651 int (*bsys_1275_call)(void *); 652 653 bsys_1275_call = (int (*)(void *))bop->bsys_1275_call; 654 args[0] = boot_ptr2cell("fstat"); 655 args[1] = 2; 656 args[2] = 1; 657 args[3] = boot_int2cell(fd); 658 args[4] = boot_ptr2cell(st); 659 (void) (bsys_1275_call)(args); 660 return (boot_cell2int(args[5])); 661 } 662 663 /* 664 * Implementation of the "enter_mon" boot service. 665 * 666 * Calling spec: 667 * args[0] Service name string 668 * args[1] #argument cells (0) 669 * args[2] #result cells (0) 670 */ 671 void 672 bop_enter_mon(struct bootops *bop) 673 { 674 boot_cell_t args[4]; 675 int (*bsys_1275_call)(void *); 676 677 bsys_1275_call = (int (*)(void *))bop->bsys_1275_call; 678 args[0] = boot_ptr2cell("enter_mon"); 679 args[1] = 0; 680 args[2] = 0; 681 (void) (bsys_1275_call)(args); 682 } 683