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 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 /* use uintptr_t to suppress the gcc warning */ 457 bsys_printf = (void (*)(struct bootops *, char *, ...)) 458 (uintptr_t)bop->bsys_printf; 459 (*bsys_printf)(bop, string); 460 return; 461 } 462 bsys_1275_call = (int (*)(void *))bop->bsys_1275_call; 463 args[0] = boot_ptr2cell("puts"); 464 args[1] = 1; 465 args[2] = 0; 466 467 args[3] = boot_ptr2cell(string); 468 (void) (bsys_1275_call)(args); 469 470 } 471 472 /* 473 * Implementation of the "putsarg" boot service. 474 * 475 * Calling spec: 476 * args[0] Service name string 477 * args[1] #argument cells 478 * args[2] #result cells 479 * args[3] string to print (with '%*' format) 480 * args[4] 64-bit thing to print 481 */ 482 /*ARGSUSED*/ 483 void 484 bop_putsarg(struct bootops *bop, const char *string, ...) 485 { 486 boot_cell_t args[6]; 487 int (*bsys_1275_call)(void *); 488 void (*bsys_printf)(struct bootops *, char *, ...); 489 va_list ap; 490 const char *fmt = string; 491 int ells = 0; 492 uint64_t arg; 493 494 /* 495 * We need to do the minimum printf-like stuff here to figure 496 * out the size of argument, if present. 497 */ 498 while (*fmt) { 499 if (*fmt++ != '%') 500 continue; 501 if (*fmt == '%') { 502 fmt++; 503 continue; 504 } 505 506 while (*fmt >= '0' && *fmt <= '9') 507 fmt++; 508 for (ells = 0; *fmt == 'l'; fmt++) 509 ells++; 510 va_start(ap, string); 511 switch (*fmt) { 512 case 's': 513 arg = (uint64_t)va_arg(ap, char *); 514 break; 515 case 'p': 516 arg = (uint64_t)va_arg(ap, void *); 517 break; 518 case 'd': 519 case 'D': 520 case 'x': 521 case 'X': 522 case 'u': 523 case 'U': 524 case 'o': 525 case 'O': 526 if (ells == 0) 527 arg = (uint64_t)va_arg(ap, uint_t); 528 else if (ells == 1) 529 arg = (uint64_t)va_arg(ap, ulong_t); 530 else 531 arg = (uint64_t)va_arg(ap, uint64_t); 532 break; 533 default: 534 arg = (uint64_t)va_arg(ap, uint_t); 535 break; 536 } 537 va_end(ap); 538 break; 539 } 540 541 /* so new kernel, old boot can print a message before dying */ 542 if (!BOOTOPS_ARE_1275(bop)) { 543 /* use uintptr_t to suppress the gcc warning */ 544 bsys_printf = (void (*)(struct bootops *, char *, ...)) 545 (uintptr_t)bop->bsys_printf; 546 (*bsys_printf)(bop, (char *)string, arg); 547 return; 548 } 549 550 bsys_1275_call = (int (*)(void *))bop->bsys_1275_call; 551 args[0] = boot_ptr2cell("putsarg"); 552 args[1] = 2; 553 args[2] = 0; 554 args[3] = boot_ptr2cell(string); 555 args[4] = boot_uint642cell(arg); 556 557 (void) (bsys_1275_call)(args); 558 } 559 560 /* 561 * Implementation of the "mount" boot service. 562 * 563 * Calling spec: 564 * args[0] Service name string 565 * args[1] #argument cells 566 * args[2] #result cells 567 * args[3] pathname string 568 * args[4] Res0: returned result 569 */ 570 /*ARGSUSED*/ 571 int 572 bop_mountroot(struct bootops *bop, char *path) 573 { 574 boot_cell_t args[5]; 575 int (*bsys_1275_call)(void *); 576 577 bsys_1275_call = (int (*)(void *))bop->bsys_1275_call; 578 args[0] = boot_ptr2cell("mountroot"); 579 args[1] = 2; 580 args[2] = 1; 581 582 args[3] = boot_ptr2cell(path); 583 (void) (bsys_1275_call)(args); 584 return (boot_cell2int(args[4])); 585 } 586 587 /* 588 * Implementation of the "unmountroot" boot service. 589 * 590 * Calling spec: 591 * args[0] Service name string 592 * args[1] #argument cells 593 * args[2] #result cells 594 * args[3] Res0: returned result 595 */ 596 /*ARGSUSED*/ 597 int 598 bop_unmountroot(struct bootops *bop) 599 { 600 boot_cell_t args[4]; 601 int (*bsys_1275_call)(void *); 602 603 bsys_1275_call = (int (*)(void *))bop->bsys_1275_call; 604 args[0] = boot_ptr2cell("unmountroot"); 605 args[1] = 0; 606 args[2] = 1; 607 608 (void) (bsys_1275_call)(args); 609 return (boot_cell2int(args[3])); 610 } 611 612 /* 613 * Implementation of the "serviceavail" boot service. 614 * 615 * Calling spec: 616 * args[0] Service name string 617 * args[1] #argument cells 618 * args[2] #result cells 619 * args[3] name string of service to be tested for 620 * args[4] Res0: returned version number or 0 621 */ 622 /*ARGSUSED*/ 623 int 624 bop_serviceavail(struct bootops *bop, char *name) 625 { 626 boot_cell_t args[5]; 627 int (*bsys_1275_call)(void *) = 628 (int (*)(void *))bop->bsys_1275_call; 629 630 args[0] = boot_ptr2cell("serviceavail"); 631 args[1] = 1; 632 args[2] = 1; 633 634 args[3] = boot_ptr2cell(name); 635 (void) (bsys_1275_call)(args); 636 return (boot_cell2int(args[4])); 637 } 638 639 /* 640 * Implementation of the "fstat" boot service. 641 * 642 * Calling spec: 643 * args[0] Service name string 644 * args[1] #argument cells 645 * args[2] #result cells 646 * args[3] fd 647 * args[4] client's stat structure 648 */ 649 int 650 bop_fstat(struct bootops *bop, int fd, struct bootstat *st) 651 { 652 boot_cell_t args[6]; 653 int (*bsys_1275_call)(void *); 654 655 bsys_1275_call = (int (*)(void *))bop->bsys_1275_call; 656 args[0] = boot_ptr2cell("fstat"); 657 args[1] = 2; 658 args[2] = 1; 659 args[3] = boot_int2cell(fd); 660 args[4] = boot_ptr2cell(st); 661 (void) (bsys_1275_call)(args); 662 return (boot_cell2int(args[5])); 663 } 664 665 /* 666 * Implementation of the "enter_mon" boot service. 667 * 668 * Calling spec: 669 * args[0] Service name string 670 * args[1] #argument cells (0) 671 * args[2] #result cells (0) 672 */ 673 void 674 bop_enter_mon(struct bootops *bop) 675 { 676 boot_cell_t args[4]; 677 int (*bsys_1275_call)(void *); 678 679 bsys_1275_call = (int (*)(void *))bop->bsys_1275_call; 680 args[0] = boot_ptr2cell("enter_mon"); 681 args[1] = 0; 682 args[2] = 0; 683 (void) (bsys_1275_call)(args); 684 } 685