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 /* 28 * This module implements the PICL Interface used by PICL clients 29 * to access services of the PICL daemon 30 * 31 * Locking Strategy 32 * A single reader/writer lock (icl_lock) protects the access to the interface 33 * to the picl daemon, and the reference count, refcnt, variable. 34 * A reader lock is obtained to send a request to the daemon. 35 * A writer lock is obtained to initialize, reinitialize, or shutdown 36 * the interface. 37 */ 38 39 #include <stdio.h> 40 #include <stdlib.h> 41 #include <string.h> 42 #include <unistd.h> 43 #include <alloca.h> 44 #include <fcntl.h> 45 #include <libintl.h> 46 #include <errno.h> 47 #include <sys/mman.h> 48 #include <door.h> 49 #include <sys/door.h> 50 #include <sys/time.h> 51 #include <assert.h> 52 #include <synch.h> 53 #include <limits.h> 54 #include <picl.h> 55 #include "picl2door.h" 56 57 /* 58 * Module variables 59 */ 60 static int door_handle = -1; 61 static uint32_t refcnt = 0; 62 static rwlock_t picl_lock = DEFAULTRWLOCK; 63 64 static char *picl_errmsg[] = { 65 "No error", 66 "General system failure", 67 "Daemon not responding", 68 "Unknown PICL service", 69 "Session not initialized", 70 "Invalid arguments", 71 "Argument too big", 72 "Property not found", 73 "Not a table property handle", 74 "Not a node handle", 75 "Not a property handle", 76 "End of property list", 77 "Property already exists", 78 "Property not writable", 79 "Insufficient permissions", 80 "Invalid handle", 81 "Stale handle", 82 "Unsupported version", 83 "Wait timed out", 84 "Attempting to destroy before delete", 85 "PICL Tree is busy", 86 "Already has a parent", 87 "Property name is reserved", 88 "Invalid reference value", 89 "Continue tree walk", 90 "Terminate tree walk", 91 "Node not found", 92 "Not enough space available", 93 "Property not readable", 94 "Property value unavailable" 95 }; 96 97 #define N_ERRORS (sizeof (picl_errmsg)/sizeof (picl_errmsg[0])) 98 #define SEND_REQ_TRYCOUNT 1 99 100 /* 101 * This function sends the client request to the daemon using a door call. 102 * If door_handle is -1, it returns PICL_NOTINITIALIZED. 103 * If the door_call fails, it returns PICL_NORESPONSE. Otherwise, it 104 * checks the response from the daemon for error. If an error is returned 105 * this function returns the error code returned and unmaps any 106 * memory mapped by the door call. For successful results, the caller is 107 * responsible to unmap the mapped memory after retrieving the results. 108 * 109 * This function does not attempt to reinitialize the interface if the 110 * initial door_call fails. It is called from handshake() , shutdown() 111 * and trysend_req() routines. 112 */ 113 static int 114 post_req(door_arg_t *dargp, void *data_ptr, size_t data_size, 115 door_desc_t *desc_ptr, uint_t desc_num, void *rbuf, size_t rsize) 116 { 117 int err; 118 picl_service_t *ret; 119 int req_cnum; 120 121 req_cnum = ((picl_service_t *)data_ptr)->in.cnum; 122 dargp->data_ptr = data_ptr; 123 dargp->data_size = data_size; 124 dargp->desc_ptr = desc_ptr; 125 dargp->desc_num = desc_num; 126 dargp->rbuf = rbuf; 127 dargp->rsize = rsize; 128 129 if (door_call(door_handle, dargp) < 0) 130 return (PICL_NORESPONSE); 131 132 /*LINTED*/ 133 ret = (picl_service_t *)dargp->rbuf; 134 if (ret->in.cnum == req_cnum) 135 return (PICL_SUCCESS); 136 else if ((ret->in.cnum == PICL_CNUM_ERROR) && 137 (ret->ret_error.in_cnum == req_cnum)) 138 err = ret->ret_error.errnum; 139 else 140 err = PICL_UNKNOWNSERVICE; 141 if (dargp->rbuf != rbuf) 142 (void) munmap(dargp->rbuf, dargp->rsize); 143 return (err); 144 } 145 146 /* 147 * This function posts an INIT message to the daemon to 148 * verify communication channel. 149 */ 150 static int 151 handshake(void) 152 { 153 int err; 154 door_arg_t darg; 155 picl_reqinit_t req; 156 picl_retinit_t outargs; 157 158 req.cnum = PICL_CNUM_INIT; 159 req.clrev = PICL_VERSION_1; 160 161 if ((err = post_req(&darg, &req, sizeof (picl_reqinit_t), NULL, 162 0, &outargs, sizeof (picl_retinit_t))) != PICL_SUCCESS) 163 return (err); 164 165 if (darg.rbuf != (char *)&outargs) 166 (void) munmap(darg.rbuf, darg.rsize); 167 return (PICL_SUCCESS); 168 } 169 170 /* 171 * This function calls post_req() to make door_call and reinitializes 172 * the interface is post_req() fails. 173 */ 174 static int 175 trysend_req(door_arg_t *dargp, void *data_ptr, size_t data_size, 176 door_desc_t *desc_ptr, uint_t desc_num, void *rbuf, size_t rsize, 177 unsigned int trycount) 178 { 179 int err; 180 int write_locked; 181 182 write_locked = 0; 183 (void) rw_rdlock(&picl_lock); 184 if (refcnt == 0) { 185 (void) rw_unlock(&picl_lock); /* read unlock */ 186 return (PICL_NOTINITIALIZED); 187 } 188 189 while ((err = post_req(dargp, data_ptr, data_size, desc_ptr, desc_num, 190 rbuf, rsize)) == PICL_NORESPONSE) { 191 if (trycount == 0) /* no more retry */ 192 break; 193 194 if (write_locked == 1) { /* close and open door */ 195 (void) close(door_handle); 196 if ((door_handle = open(PICLD_DOOR, O_RDONLY)) < 0) { 197 err = PICL_NORESPONSE; 198 break; 199 } 200 --trycount; 201 continue; 202 } 203 /* 204 * Upgrade read to a write lock 205 */ 206 (void) rw_unlock(&picl_lock); 207 (void) rw_wrlock(&picl_lock); 208 209 /* 210 * if picl_shutdown happens during lock upgrade 211 */ 212 if (refcnt == 0) { 213 err = PICL_NOTINITIALIZED; 214 break; 215 } 216 write_locked = 1; 217 continue; 218 } 219 (void) rw_unlock(&picl_lock); /* read or write unlock */ 220 return (err); 221 } 222 223 /* 224 * Initialize the PICL interface 225 * Increment the reference count. 226 */ 227 int 228 picl_initialize(void) 229 { 230 int err; 231 232 (void) rw_wrlock(&picl_lock); 233 if (refcnt > 0) { /* previously initialized */ 234 err = handshake(); 235 if (err == PICL_SUCCESS) { 236 ++refcnt; 237 (void) rw_unlock(&picl_lock); /* write unlock */ 238 return (err); 239 } 240 if (err != PICL_NORESPONSE) { 241 (void) rw_unlock(&picl_lock); /* write unlock */ 242 return (err); 243 } 244 (void) close(door_handle); /* close bad door */ 245 } 246 247 /* 248 * Open picld door and initialize door_handle 249 */ 250 if ((door_handle = open(PICLD_DOOR, O_RDONLY)) < 0) { 251 (void) rw_unlock(&picl_lock); /* write unlock */ 252 return (PICL_NORESPONSE); 253 } 254 255 err = handshake(); 256 if (err != PICL_SUCCESS) 257 (void) close(door_handle); 258 else 259 ++refcnt; 260 (void) rw_unlock(&picl_lock); /* write unlock */ 261 return (err); 262 } 263 264 /* 265 * Shutdown the PICL interface 266 * Decrement the reference count and close the door_handle if refcnt is zero 267 */ 268 int 269 picl_shutdown(void) 270 { 271 int err; 272 door_arg_t darg; 273 picl_reqfini_t req_fini; 274 picl_retfini_t outargs; 275 276 (void) rw_wrlock(&picl_lock); /* write lock */ 277 if (refcnt == 0) { 278 (void) rw_unlock(&picl_lock); /* write unlock */ 279 return (PICL_NOTINITIALIZED); 280 } 281 req_fini.cnum = PICL_CNUM_FINI; 282 err = post_req(&darg, &req_fini, sizeof (picl_reqfini_t), 283 NULL, 0, &outargs, sizeof (picl_retfini_t)); 284 --refcnt; 285 if (refcnt == 0) 286 (void) close(door_handle); 287 (void) rw_unlock(&picl_lock); /* write unlock */ 288 if (err != PICL_SUCCESS) 289 return (err); 290 if (darg.rbuf != (char *)&outargs) 291 (void) munmap(darg.rbuf, darg.rsize); 292 return (PICL_SUCCESS); 293 } 294 295 /* 296 * This function waits for the specified number of seconds for a PICL 297 * tree refresh. 298 */ 299 int 300 picl_wait(unsigned int secs) 301 { 302 door_arg_t darg; 303 picl_reqwait_t req_wait; 304 picl_retwait_t outargs; 305 picl_service_t *ret; 306 int err; 307 308 req_wait.cnum = PICL_CNUM_WAIT; 309 req_wait.secs = secs; 310 err = trysend_req(&darg, &req_wait, sizeof (picl_reqwait_t), 311 NULL, 0, &outargs, sizeof (picl_retwait_t), SEND_REQ_TRYCOUNT); 312 if (err != PICL_SUCCESS) 313 return (err); 314 315 /*LINTED*/ 316 ret = (picl_service_t *)darg.rbuf; 317 err = ret->ret_wait.retcode; 318 if (darg.rbuf != (char *)&outargs) 319 (void) munmap(darg.rbuf, darg.rsize); 320 return (err); 321 } 322 323 /* 324 * This function copies the handle of the root node of the PICL tree into 325 * the buffer <rooth> 326 */ 327 int 328 picl_get_root(picl_nodehdl_t *rooth) 329 { 330 door_arg_t darg; 331 picl_reqroot_t req_root; 332 picl_retroot_t outargs; 333 picl_service_t *ret; 334 int err; 335 336 req_root.cnum = PICL_CNUM_GETROOT; 337 err = trysend_req(&darg, &req_root, sizeof (picl_reqroot_t), NULL, 338 0, &outargs, sizeof (picl_retroot_t), SEND_REQ_TRYCOUNT); 339 if (err != PICL_SUCCESS) 340 return (err); 341 /*LINTED*/ 342 ret = (picl_service_t *)darg.rbuf; 343 *rooth = ret->ret_root.rnode; 344 if (darg.rbuf != (char *)&outargs) 345 (void) munmap(darg.rbuf, darg.rsize); 346 return (PICL_SUCCESS); 347 } 348 349 /* 350 * This function copies the value of the property specified by its handle 351 * into the buffer <valbuf>. 352 */ 353 int 354 picl_get_propval(picl_prophdl_t proph, void *valbuf, size_t nbytes) 355 { 356 door_arg_t darg; 357 picl_reqattrval_t req_attrval; 358 picl_service_t *ret; 359 picl_retattrval_t *outargs; 360 int err; 361 362 req_attrval.cnum = PICL_CNUM_GETATTRVAL; 363 req_attrval.attr = proph; 364 req_attrval.bufsize = (uint32_t)nbytes; 365 if ((size_t)req_attrval.bufsize != nbytes) 366 return (PICL_VALUETOOBIG); 367 outargs = alloca(sizeof (picl_retattrval_t) + nbytes); 368 369 err = trysend_req(&darg, &req_attrval, sizeof (picl_reqattrval_t), 370 NULL, 0, outargs, sizeof (picl_retattrval_t) + nbytes, 371 SEND_REQ_TRYCOUNT); 372 if (err != PICL_SUCCESS) 373 return (err); 374 375 /*LINTED*/ 376 ret = (picl_service_t *)darg.rbuf; 377 if (ret->ret_attrval.nbytes > (uint32_t)nbytes) 378 err = PICL_VALUETOOBIG; 379 else 380 (void) memcpy(valbuf, ret->ret_attrval.ret_buf, 381 (size_t)ret->ret_attrval.nbytes); 382 if (darg.rbuf != (char *)outargs) 383 (void) munmap(darg.rbuf, darg.rsize); 384 return (err); 385 } 386 387 /* 388 * This function copies the value of the property specified by its 389 * name into the buffer <valbuf> 390 */ 391 int 392 picl_get_propval_by_name(picl_nodehdl_t nodeh, const char *propname, 393 void *valbuf, size_t nbytes) 394 { 395 door_arg_t darg; 396 picl_reqattrvalbyname_t req_attrvalbyname; 397 picl_service_t *ret; 398 picl_retattrvalbyname_t *outargs; 399 int err; 400 401 req_attrvalbyname.cnum = PICL_CNUM_GETATTRVALBYNAME; 402 req_attrvalbyname.nodeh = nodeh; 403 (void) strcpy(req_attrvalbyname.propname, propname); 404 req_attrvalbyname.bufsize = (uint32_t)nbytes; 405 if ((size_t)req_attrvalbyname.bufsize != nbytes) 406 return (PICL_VALUETOOBIG); 407 outargs = alloca(sizeof (picl_retattrvalbyname_t) + nbytes); 408 409 err = trysend_req(&darg, &req_attrvalbyname, 410 sizeof (picl_reqattrvalbyname_t), NULL, 0, outargs, 411 sizeof (picl_retattrvalbyname_t) + nbytes, SEND_REQ_TRYCOUNT); 412 if (err != PICL_SUCCESS) 413 return (err); 414 415 /*LINTED*/ 416 ret = (picl_service_t *)darg.rbuf; 417 if (ret->ret_attrvalbyname.nbytes > (uint32_t)nbytes) 418 err = PICL_VALUETOOBIG; 419 else 420 (void) memcpy(valbuf, ret->ret_attrvalbyname.ret_buf, 421 (size_t)ret->ret_attrvalbyname.nbytes); 422 if (darg.rbuf != (char *)outargs) 423 (void) munmap(darg.rbuf, darg.rsize); 424 return (err); 425 } 426 427 /* 428 * This function sets the value of the property specified by its 429 * handle with the value specified in <valbuf>. 430 */ 431 int 432 picl_set_propval(picl_prophdl_t proph, void *valbuf, size_t nbytes) 433 { 434 door_arg_t darg; 435 picl_reqsetattrval_t ret_setattrval; 436 picl_reqsetattrval_t *inargs; 437 int err; 438 439 if (nbytes >= (size_t)PICL_PROPSIZE_MAX) 440 return (PICL_VALUETOOBIG); 441 442 inargs = alloca(sizeof (picl_reqsetattrval_t) + nbytes); 443 inargs->cnum = PICL_CNUM_SETATTRVAL; 444 inargs->attr = proph; 445 inargs->bufsize = (uint32_t)nbytes; 446 if ((size_t)inargs->bufsize != nbytes) 447 return (PICL_VALUETOOBIG); 448 (void) memcpy(inargs->valbuf, valbuf, nbytes); 449 450 err = trysend_req(&darg, inargs, sizeof (picl_reqsetattrval_t) + 451 nbytes, NULL, 0, &ret_setattrval, 452 sizeof (picl_retsetattrval_t), SEND_REQ_TRYCOUNT); 453 if (err != PICL_SUCCESS) 454 return (err); 455 456 if (darg.rbuf != (char *)&ret_setattrval) 457 (void) munmap(darg.rbuf, darg.rsize); 458 return (PICL_SUCCESS); 459 } 460 461 /* 462 * This function sets the value of the property specified by its 463 * name with the value given in <valbuf> 464 */ 465 int 466 picl_set_propval_by_name(picl_nodehdl_t nodeh, const char *propname, 467 void *valbuf, size_t nbytes) 468 { 469 door_arg_t darg; 470 picl_retsetattrvalbyname_t ret_setattrvalbyname; 471 picl_reqsetattrvalbyname_t *inargs; 472 int err; 473 474 if (nbytes >= (size_t)PICL_PROPSIZE_MAX) 475 return (PICL_VALUETOOBIG); 476 477 inargs = alloca(sizeof (picl_reqsetattrvalbyname_t) + nbytes); 478 inargs->cnum = PICL_CNUM_SETATTRVALBYNAME; 479 inargs->nodeh = nodeh; 480 (void) strcpy(inargs->propname, propname); 481 inargs->bufsize = (uint32_t)nbytes; 482 if ((size_t)inargs->bufsize != nbytes) 483 return (PICL_VALUETOOBIG); 484 (void) memcpy(inargs->valbuf, valbuf, nbytes); 485 486 err = trysend_req(&darg, inargs, 487 sizeof (picl_reqsetattrvalbyname_t) + nbytes, NULL, 0, 488 &ret_setattrvalbyname, sizeof (picl_retsetattrvalbyname_t), 489 SEND_REQ_TRYCOUNT); 490 if (err != PICL_SUCCESS) 491 return (err); 492 493 if (darg.rbuf != (char *)&ret_setattrvalbyname) 494 (void) munmap(darg.rbuf, darg.rsize); 495 return (PICL_SUCCESS); 496 } 497 498 /* 499 * This function copies the information of the specified property 500 * into <pinfo> 501 */ 502 int 503 picl_get_propinfo(picl_prophdl_t proph, picl_propinfo_t *pinfo) 504 { 505 door_arg_t darg; 506 picl_reqattrinfo_t req_attrinfo; 507 picl_service_t *ret; 508 picl_retattrinfo_t outargs; 509 int err; 510 511 req_attrinfo.cnum = PICL_CNUM_GETATTRINFO; 512 req_attrinfo.attr = proph; 513 514 err = trysend_req(&darg, &req_attrinfo, 515 sizeof (picl_reqattrinfo_t), NULL, 0, &outargs, 516 sizeof (picl_retattrinfo_t), SEND_REQ_TRYCOUNT); 517 if (err != PICL_SUCCESS) 518 return (err); 519 520 /*LINTED*/ 521 ret = (picl_service_t *)darg.rbuf; 522 pinfo->type = ret->ret_attrinfo.type; 523 pinfo->accessmode = ret->ret_attrinfo.accessmode; 524 pinfo->size = (size_t)ret->ret_attrinfo.size; 525 (void) strcpy(pinfo->name, ret->ret_attrinfo.name); 526 if (darg.rbuf != (char *)&outargs) 527 (void) munmap(darg.rbuf, darg.rsize); 528 return (PICL_SUCCESS); 529 } 530 531 /* 532 * This function copies the handle of the first property of a node into 533 * <proph> 534 */ 535 int 536 picl_get_first_prop(picl_nodehdl_t nodeh, picl_prophdl_t *proph) 537 { 538 door_arg_t darg; 539 picl_reqfirstattr_t req_firstattr; 540 picl_service_t *ret; 541 picl_retfirstattr_t outargs; 542 int err; 543 544 req_firstattr.cnum = PICL_CNUM_GETFIRSTATTR; 545 req_firstattr.nodeh = nodeh; 546 547 err = trysend_req(&darg, &req_firstattr, 548 sizeof (picl_reqfirstattr_t), NULL, 0, &outargs, 549 sizeof (picl_retfirstattr_t), SEND_REQ_TRYCOUNT); 550 if (err != PICL_SUCCESS) 551 return (err); 552 553 /*LINTED*/ 554 ret = (picl_service_t *)darg.rbuf; 555 *proph = ret->ret_firstattr.attr; 556 if (darg.rbuf != (char *)&outargs) 557 (void) munmap(darg.rbuf, darg.rsize); 558 return (PICL_SUCCESS); 559 } 560 561 /* 562 * This function copies the handle of the next property in list 563 * into <nextprop>. 564 */ 565 int 566 picl_get_next_prop(picl_prophdl_t proph, picl_prophdl_t *nextprop) 567 { 568 door_arg_t darg; 569 picl_reqnextattr_t req_nextattr; 570 picl_service_t *ret; 571 picl_retnextattr_t outargs; 572 int err; 573 574 575 req_nextattr.cnum = PICL_CNUM_GETNEXTATTR; 576 req_nextattr.attr = proph; 577 578 err = trysend_req(&darg, &req_nextattr, 579 sizeof (picl_reqnextattr_t), NULL, 0, &outargs, 580 sizeof (picl_retnextattr_t), SEND_REQ_TRYCOUNT); 581 if (err != PICL_SUCCESS) 582 return (err); 583 584 /*LINTED*/ 585 ret = (picl_service_t *)darg.rbuf; 586 *nextprop = ret->ret_nextattr.nextattr; 587 if (darg.rbuf != (char *)&outargs) 588 (void) munmap(darg.rbuf, darg.rsize); 589 return (PICL_SUCCESS); 590 } 591 592 /* 593 * This function copies the handle of the property specified by its 594 * name into <proph>. 595 */ 596 int 597 picl_get_prop_by_name(picl_nodehdl_t nodeh, const char *name, 598 picl_prophdl_t *proph) 599 { 600 door_arg_t darg; 601 picl_reqattrbyname_t req_attrbyname; 602 picl_service_t *ret; 603 picl_retattrbyname_t outargs; 604 int err; 605 606 req_attrbyname.cnum = PICL_CNUM_GETATTRBYNAME; 607 req_attrbyname.nodeh = nodeh; 608 (void) strcpy(req_attrbyname.propname, name); 609 610 err = trysend_req(&darg, &req_attrbyname, 611 sizeof (picl_reqattrbyname_t), NULL, 0, &outargs, 612 sizeof (picl_retattrbyname_t), SEND_REQ_TRYCOUNT); 613 if (err != PICL_SUCCESS) 614 return (err); 615 616 /*LINTED*/ 617 ret = (picl_service_t *)darg.rbuf; 618 *proph = ret->ret_attrbyname.attr; 619 if (darg.rbuf != (char *)&outargs) 620 (void) munmap(darg.rbuf, darg.rsize); 621 return (PICL_SUCCESS); 622 } 623 624 /* 625 * This function copies the handle of the next property on the same 626 * row of the table into <rowproph>. 627 * When proph is the table handle, the handle of the property that is 628 * in first row and first column is copied. 629 */ 630 int 631 picl_get_next_by_row(picl_prophdl_t proph, picl_prophdl_t *rowproph) 632 { 633 door_arg_t darg; 634 picl_reqattrbyrow_t req_attrbyrow; 635 picl_service_t *ret; 636 picl_retattrbyrow_t outargs; 637 int err; 638 639 req_attrbyrow.cnum = PICL_CNUM_GETATTRBYROW; 640 req_attrbyrow.attr = proph; 641 642 err = trysend_req(&darg, &req_attrbyrow, 643 sizeof (picl_reqattrbyrow_t), NULL, 0, &outargs, 644 sizeof (picl_retattrbyrow_t), SEND_REQ_TRYCOUNT); 645 if (err != PICL_SUCCESS) 646 return (err); 647 648 /*LINTED*/ 649 ret = (picl_service_t *)darg.rbuf; 650 *rowproph = ret->ret_attrbyrow.rowattr; 651 if (darg.rbuf != (char *)&outargs) 652 (void) munmap(darg.rbuf, darg.rsize); 653 return (PICL_SUCCESS); 654 } 655 656 /* 657 * This function copies the handle of the next property on the same 658 * column of the table into <colproph>. 659 * When proph is the table handle, the handle of the property that is 660 * in the first row and first column is copied. 661 */ 662 int 663 picl_get_next_by_col(picl_prophdl_t proph, picl_prophdl_t *colproph) 664 { 665 door_arg_t darg; 666 picl_reqattrbycol_t req_attrbycol; 667 picl_service_t *ret; 668 picl_retattrbycol_t outargs; 669 int err; 670 671 req_attrbycol.cnum = PICL_CNUM_GETATTRBYCOL; 672 req_attrbycol.attr = proph; 673 674 err = trysend_req(&darg, (char *)&req_attrbycol, 675 sizeof (picl_reqattrbycol_t), NULL, 0, (char *)&outargs, 676 sizeof (picl_retattrbycol_t), SEND_REQ_TRYCOUNT); 677 if (err != PICL_SUCCESS) 678 return (err); 679 680 /*LINTED*/ 681 ret = (picl_service_t *)darg.rbuf; 682 *colproph = ret->ret_attrbycol.colattr; 683 if (darg.rbuf != (char *)&outargs) 684 (void) munmap(darg.rbuf, darg.rsize); 685 return (PICL_SUCCESS); 686 } 687 688 /* 689 * This function returns the picl error messages corresponding to the 690 * error number. 691 */ 692 char * 693 picl_strerror(int err) 694 { 695 if ((err < N_ERRORS) && (err >= 0)) { 696 return (gettext(picl_errmsg[err])); 697 } 698 return ((char *)NULL); 699 } 700 701 /* 702 * recursively visit all nodes 703 */ 704 static int 705 do_walk(picl_nodehdl_t rooth, const char *classname, 706 void *c_args, int (*callback_fn)(picl_nodehdl_t hdl, void *args)) 707 { 708 int err; 709 picl_nodehdl_t chdh; 710 char classval[PICL_CLASSNAMELEN_MAX]; 711 712 err = picl_get_propval_by_name(rooth, PICL_PROP_CHILD, &chdh, 713 sizeof (chdh)); 714 while (err == PICL_SUCCESS) { 715 err = picl_get_propval_by_name(chdh, PICL_PROP_CLASSNAME, 716 classval, sizeof (classval)); 717 if (err != PICL_SUCCESS) 718 return (err); 719 720 if ((classname == NULL) || (strcmp(classname, classval) == 0)) { 721 err = callback_fn(chdh, c_args); 722 if (err != PICL_WALK_CONTINUE) 723 return (err); 724 } 725 726 if ((err = do_walk(chdh, classname, c_args, callback_fn)) != 727 PICL_WALK_CONTINUE) 728 return (err); 729 730 err = picl_get_propval_by_name(chdh, PICL_PROP_PEER, &chdh, 731 sizeof (chdh)); 732 } 733 if (err == PICL_PROPNOTFOUND) /* end of a branch */ 734 return (PICL_WALK_CONTINUE); 735 return (err); 736 737 } 738 739 /* 740 * This function walks the tree by class and invokes the callback 741 * function on class name matches. 742 */ 743 int 744 picl_walk_tree_by_class(picl_nodehdl_t rooth, const char *classname, 745 void *c_args, int (*callback_fn)(picl_nodehdl_t hdl, void *args)) 746 { 747 int err; 748 749 if (callback_fn == NULL) 750 return (PICL_INVALIDARG); 751 err = do_walk(rooth, classname, c_args, callback_fn); 752 if ((err == PICL_WALK_CONTINUE) || (err == PICL_WALK_TERMINATE)) 753 return (PICL_SUCCESS); 754 return (err); 755 } 756 757 /* 758 * This function gets propinfo and prop handle of the named property 759 */ 760 int 761 picl_get_propinfo_by_name(picl_nodehdl_t nodeh, const char *prop_name, 762 picl_propinfo_t *pinfo, picl_prophdl_t *proph) 763 { 764 int err; 765 picl_prophdl_t tmpproph; 766 picl_propinfo_t tmppinfo; 767 768 err = picl_get_prop_by_name(nodeh, prop_name, &tmpproph); 769 if (err != PICL_SUCCESS) 770 return (err); 771 772 err = picl_get_propinfo(tmpproph, &tmppinfo); 773 if (err != PICL_SUCCESS) 774 return (err); 775 776 *proph = tmpproph; 777 *pinfo = tmppinfo; 778 return (PICL_SUCCESS); 779 } 780 781 int 782 picl_get_node_by_path(const char *piclpath, picl_nodehdl_t *nodeh) 783 { 784 door_arg_t darg; 785 picl_reqnodebypath_t req; 786 picl_retnodebypath_t out; 787 picl_service_t *ret; 788 int err; 789 790 req.cnum = PICL_CNUM_NODEBYPATH; 791 req.psize = PATH_MAX; 792 if (strlen(piclpath) >= PATH_MAX) 793 return (PICL_VALUETOOBIG); 794 (void) strncpy(req.pathbuf, piclpath, PATH_MAX); 795 796 err = trysend_req(&darg, &req, sizeof (req), NULL, 0, &out, 797 sizeof (out), SEND_REQ_TRYCOUNT); 798 if (err != PICL_SUCCESS) 799 return (err); 800 801 /*LINTED*/ 802 ret = (picl_service_t *)darg.rbuf; 803 *nodeh = ret->ret_nodebypath.nodeh; 804 if (darg.rbuf != (char *)&out) 805 (void) munmap(darg.rbuf, darg.rsize); 806 return (err); 807 } 808 809 int 810 picl_find_node(picl_nodehdl_t rooth, char *pname, picl_prop_type_t ptype, 811 void *pval, size_t valsize, picl_nodehdl_t *retnodeh) 812 { 813 door_arg_t darg; 814 picl_reqfindnode_t *req; 815 picl_service_t *ret; 816 picl_retfindnode_t out; 817 int err; 818 819 req = alloca(sizeof (picl_reqfindnode_t) + valsize); 820 req->cnum = PICL_CNUM_FINDNODE; 821 req->nodeh = rooth; 822 if (strlen(pname) >= PICL_PROPNAMELEN_MAX) 823 return (PICL_VALUETOOBIG); 824 (void) strncpy(req->propname, pname, PICL_PROPNAMELEN_MAX); 825 req->ptype = ptype; 826 req->valsize = (uint32_t)valsize; 827 if ((size_t)req->valsize != valsize) 828 return (PICL_VALUETOOBIG); 829 (void) memcpy(req->valbuf, pval, valsize); 830 831 err = trysend_req(&darg, req, sizeof (picl_reqfindnode_t) + valsize, 832 NULL, 0, &out, sizeof (out), SEND_REQ_TRYCOUNT); 833 if (err != PICL_SUCCESS) 834 return (err); 835 836 /*LINTED*/ 837 ret = (picl_service_t *)darg.rbuf; 838 *retnodeh = ret->ret_findnode.rnodeh; 839 if (darg.rbuf != (char *)&out) 840 (void) munmap(darg.rbuf, darg.rsize); 841 return (err); 842 } 843 844 int 845 picl_get_frutree_parent(picl_nodehdl_t devh, picl_nodehdl_t *fruh) 846 { 847 door_arg_t darg; 848 picl_reqfruparent_t req; 849 picl_retfruparent_t out; 850 picl_service_t *ret; 851 int err; 852 853 req.cnum = PICL_CNUM_FRUTREEPARENT; 854 req.devh = devh; 855 856 err = trysend_req(&darg, &req, sizeof (req), NULL, 0, &out, 857 sizeof (out), SEND_REQ_TRYCOUNT); 858 if (err != PICL_SUCCESS) 859 return (err); 860 861 /*LINTED*/ 862 ret = (picl_service_t *)darg.rbuf; 863 *fruh = ret->ret_fruparent.fruh; 864 if (darg.rbuf != (char *)&out) 865 (void) munmap(darg.rbuf, darg.rsize); 866 return (err); 867 } 868