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