xref: /illumos-gate/usr/src/cmd/dcs/sparc/sun4u/rsrc_info.c (revision 581cede61ac9c14d8d4ea452562a567189eead78)
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 (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 #pragma ident	"%Z%%M%	%I%	%E% SMI"
27 
28 /*
29  * Routines for traversing and packing/unpacking the handle
30  * returned from ri_init.
31  */
32 
33 #include <stdlib.h>
34 #include <strings.h>
35 #include "rsrc_info.h"
36 #include "rsrc_info_impl.h"
37 
38 static int ap_list_pack(ri_ap_t *, char **, size_t *, int);
39 static int ap_list_unpack(char *, size_t, ri_ap_t **);
40 static int ap_pack(ri_ap_t *, char **, size_t *, int);
41 static int ap_unpack(char *, size_t, ri_ap_t *);
42 static int dev_list_pack(ri_dev_t *, char **, size_t *, int);
43 static int dev_list_unpack(char *, size_t, ri_dev_t **);
44 static int dev_pack(ri_dev_t *, char **, size_t *, int);
45 static int dev_unpack(char *, size_t, ri_dev_t *);
46 static int client_list_pack(ri_client_t *, char **, size_t *, int);
47 static int client_list_unpack(char *, size_t, ri_client_t **);
48 static int client_pack(ri_client_t *, char **, size_t *, int);
49 static int client_unpack(char *, size_t, ri_client_t *);
50 static int pack_add_byte_array(nvlist_t *, char *, nvlist_t *, int);
51 static int lookup_unpack_byte_array(nvlist_t *, char *, nvlist_t **);
52 static void ri_ap_free(ri_ap_t *);
53 
54 void
55 ri_fini(ri_hdl_t *hdl)
56 {
57 	ri_ap_t		*ap;
58 	ri_client_t	*client;
59 
60 	if (hdl == NULL)
61 		return;
62 
63 	while ((ap = hdl->aps) != NULL) {
64 		hdl->aps = ap->next;
65 		ri_ap_free(ap);
66 	}
67 	while ((client = hdl->cpu_cap_clients) != NULL) {
68 		hdl->cpu_cap_clients = client->next;
69 		ri_client_free(client);
70 	}
71 	while ((client = hdl->mem_cap_clients) != NULL) {
72 		hdl->mem_cap_clients = client->next;
73 		ri_client_free(client);
74 	}
75 	free(hdl);
76 }
77 
78 static void
79 ri_ap_free(ri_ap_t *ap)
80 {
81 	ri_dev_t	*dev;
82 
83 	assert(ap != NULL);
84 
85 	if (ap->conf_props != NULL)
86 		nvlist_free(ap->conf_props);
87 
88 	while ((dev = ap->cpus) != NULL) {
89 		ap->cpus = dev->next;
90 		ri_dev_free(dev);
91 	}
92 	while ((dev = ap->mems) != NULL) {
93 		ap->mems = dev->next;
94 		ri_dev_free(dev);
95 	}
96 	while ((dev = ap->ios) != NULL) {
97 		ap->ios = dev->next;
98 		ri_dev_free(dev);
99 	}
100 	free(ap);
101 }
102 
103 void
104 ri_dev_free(ri_dev_t *dev)
105 {
106 	ri_client_t	*client;
107 
108 	assert(dev != NULL);
109 
110 	nvlist_free(dev->conf_props);
111 	while ((client = dev->rcm_clients) != NULL) {
112 		dev->rcm_clients = client->next;
113 		ri_client_free(client);
114 	}
115 	free(dev);
116 }
117 
118 void
119 ri_client_free(ri_client_t *client)
120 {
121 	assert(client != NULL);
122 
123 	if (client->usg_props != NULL)
124 		nvlist_free(client->usg_props);
125 	if (client->v_props != NULL)
126 		nvlist_free(client->v_props);
127 	free(client);
128 }
129 
130 /*
131  * Pack everything contained in the handle up inside out.
132  */
133 int
134 ri_pack(ri_hdl_t *hdl, caddr_t *bufp, size_t *sizep, int encoding)
135 {
136 	nvlist_t	*nvl = NULL;
137 	char		*buf = NULL;
138 	size_t		size = 0;
139 
140 	if (bufp == NULL || sizep == NULL)
141 		return (RI_INVAL);
142 
143 	*sizep = 0;
144 	*bufp = NULL;
145 
146 	/*
147 	 * Check the handle. If it is NULL, there
148 	 * is nothing to pack, so we are done.
149 	 */
150 	if (hdl == NULL) {
151 		return (RI_SUCCESS);
152 	}
153 
154 	if (nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0) != 0) {
155 		dprintf((stderr, "nvlist_alloc fail\n", errno));
156 		goto fail;
157 	}
158 
159 	if (nvlist_add_int32(nvl, RI_HDL_FLAGS, hdl->flags) != 0) {
160 		dprintf((stderr, "nvlist_add_int32 fail\n"));
161 		goto fail;
162 	}
163 
164 	if (ap_list_pack(hdl->aps, &buf, &size, encoding) != 0 ||
165 	    nvlist_add_byte_array(nvl, RI_HDL_APS, (uchar_t *)buf, size) != 0) {
166 		goto fail;
167 	}
168 
169 	s_free(buf);
170 	if (client_list_pack(hdl->cpu_cap_clients, &buf, &size,
171 	    encoding) != 0 ||
172 	    nvlist_add_byte_array(nvl, RI_HDL_CPU_CAPS, (uchar_t *)buf,
173 	    size) != 0) {
174 		goto fail;
175 	}
176 
177 	s_free(buf);
178 	if (client_list_pack(hdl->mem_cap_clients, &buf, &size,
179 	    encoding) != 0 ||
180 	    nvlist_add_byte_array(nvl, RI_HDL_MEM_CAPS, (uchar_t *)buf,
181 	    size) != 0) {
182 		goto fail;
183 	}
184 
185 	s_free(buf);
186 	if (nvlist_pack(nvl, &buf, &size, encoding, 0) != 0) {
187 		dprintf((stderr, "nvlist_pack fail\n"));
188 		goto fail;
189 	}
190 
191 	nvlist_free(nvl);
192 	*bufp = buf;
193 	*sizep = size;
194 
195 	return (RI_SUCCESS);
196 
197 fail:
198 	s_free(buf);
199 	if (nvl != NULL)
200 		nvlist_free(nvl);
201 
202 	return (RI_FAILURE);
203 }
204 
205 /*
206  * Pack a list of attachment point handles.
207  */
208 static int
209 ap_list_pack(ri_ap_t *aplist, char **bufp, size_t *sizep, int encoding)
210 {
211 	nvlist_t	*nvl = NULL;
212 	char		*buf = NULL;
213 	size_t		size;
214 
215 	assert(bufp != NULL && sizep != NULL);
216 
217 	*sizep = 0;
218 	*bufp = NULL;
219 
220 	if (nvlist_alloc(&nvl, 0, 0) != 0) {
221 		dprintf((stderr, "nvlist_alloc fail\n"));
222 		return (-1);
223 	}
224 
225 	while (aplist != NULL) {
226 		s_free(buf);
227 		if (ap_pack(aplist, &buf, &size, encoding) != 0)
228 			goto fail;
229 
230 		if (nvlist_add_byte_array(nvl, RI_AP_T, (uchar_t *)buf,
231 		    size) != 0) {
232 			dprintf((stderr, "nvlist_add_byte_array fail "
233 			    "(%s)\n", RI_AP_T));
234 			goto fail;
235 		}
236 		aplist = aplist->next;
237 	}
238 
239 	s_free(buf);
240 	if (nvlist_pack(nvl, &buf, &size, encoding, 0) != 0) {
241 		dprintf((stderr, "nvlist_pack fail\n"));
242 		goto fail;
243 	}
244 
245 	nvlist_free(nvl);
246 	*bufp = buf;
247 	*sizep = size;
248 
249 	return (0);
250 
251 fail:
252 	s_free(buf);
253 	if (nvl != NULL)
254 		nvlist_free(nvl);
255 
256 	return (-1);
257 }
258 
259 /*
260  * Pack a list of ri_dev_t's.
261  */
262 static int
263 dev_list_pack(ri_dev_t *devlist, char **bufp, size_t *sizep, int encoding)
264 {
265 	nvlist_t	*nvl = NULL;
266 	char		*buf = NULL;
267 	size_t		size = 0;
268 
269 	assert(bufp != NULL && sizep != NULL);
270 
271 	*sizep = 0;
272 	*bufp = NULL;
273 
274 	if (nvlist_alloc(&nvl, 0, 0) != 0) {
275 		dprintf((stderr, "nvlist_alloc fail\n"));
276 		return (-1);
277 	}
278 
279 	while (devlist != NULL) {
280 		s_free(buf);
281 		if (dev_pack(devlist, &buf, &size, encoding) != 0)
282 			goto fail;
283 
284 		if (nvlist_add_byte_array(nvl, RI_DEV_T, (uchar_t *)buf,
285 		    size) != 0) {
286 			dprintf((stderr, "nvlist_add_byte_array fail "
287 			    "(%s)\n", RI_DEV_T));
288 			goto fail;
289 		}
290 		devlist = devlist->next;
291 	}
292 
293 	s_free(buf);
294 	if (nvlist_pack(nvl, &buf, &size, encoding, 0) != 0) {
295 		dprintf((stderr, "nvlist_pack fail\n"));
296 		goto fail;
297 	}
298 
299 	nvlist_free(nvl);
300 	*bufp = buf;
301 	*sizep = size;
302 
303 	return (0);
304 
305 fail:
306 	s_free(buf);
307 	if (nvl != NULL)
308 		nvlist_free(nvl);
309 
310 	return (-1);
311 }
312 
313 /*
314  * Pack a list of ri_client_t's.
315  */
316 static int
317 client_list_pack(ri_client_t *client_list, char **bufp, size_t *sizep,
318     int encoding)
319 {
320 	nvlist_t	*nvl = NULL;
321 	char		*buf = NULL;
322 	size_t		size = 0;
323 
324 	assert(bufp != NULL && sizep != NULL);
325 
326 	*sizep = 0;
327 	*bufp = NULL;
328 
329 	if (nvlist_alloc(&nvl, 0, 0) != 0) {
330 		dprintf((stderr, "nvlist_alloc fail\n"));
331 		return (-1);
332 	}
333 
334 	while (client_list != NULL) {
335 		s_free(buf);
336 		if (client_pack(client_list, &buf, &size, encoding) != 0)
337 			goto fail;
338 
339 		if (nvlist_add_byte_array(nvl, RI_CLIENT_T, (uchar_t *)buf,
340 		    size) != 0) {
341 			dprintf((stderr, "nvlist_add_byte_array fail "
342 			    "(%s)\n", RI_CLIENT_T));
343 			goto fail;
344 		}
345 		client_list = client_list->next;
346 	}
347 
348 	s_free(buf);
349 	if (nvlist_pack(nvl, &buf, &size, encoding, 0) != 0) {
350 		dprintf((stderr, "nvlist_pack fail\n"));
351 		goto fail;
352 	}
353 
354 	nvlist_free(nvl);
355 	*bufp = buf;
356 	*sizep = size;
357 
358 	return (0);
359 
360 fail:
361 	s_free(buf);
362 	if (nvl != NULL)
363 		nvlist_free(nvl);
364 
365 	return (-1);
366 }
367 
368 static int
369 ap_pack(ri_ap_t *ap, char **bufp, size_t *sizep, int encoding)
370 {
371 	nvlist_t	*nvl = NULL;
372 	char		*buf = NULL;
373 	size_t		size = 0;
374 
375 	if (nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0) != 0) {
376 		dprintf((stderr, "nvlist_alloc fail\n"));
377 		return (-1);
378 	}
379 
380 	if (pack_add_byte_array(ap->conf_props, RI_AP_PROPS, nvl,
381 	    encoding) != 0)
382 		goto fail;
383 
384 	if (dev_list_pack(ap->cpus, &buf, &size, encoding) != 0)
385 		goto fail;
386 
387 	if (nvlist_add_byte_array(nvl, RI_AP_CPUS, (uchar_t *)buf,
388 	    size) != 0) {
389 		dprintf((stderr, "nvlist_add_byte_array (%s)\n", RI_AP_CPUS));
390 		goto fail;
391 	}
392 
393 	s_free(buf);
394 	if (dev_list_pack(ap->mems, &buf, &size, encoding) != 0)
395 		goto fail;
396 
397 	if (nvlist_add_byte_array(nvl, RI_AP_MEMS, (uchar_t *)buf,
398 	    size) != 0) {
399 		dprintf((stderr, "nvlist_add_byte_array (%s)n", RI_AP_MEMS));
400 		goto fail;
401 	}
402 
403 	s_free(buf);
404 	if (dev_list_pack(ap->ios, &buf, &size, encoding) != 0)
405 		goto fail;
406 
407 	if (nvlist_add_byte_array(nvl, RI_AP_IOS, (uchar_t *)buf,
408 	    size) != 0) {
409 		dprintf((stderr, "nvlist_add_byte_array (%s)n", RI_AP_IOS));
410 		goto fail;
411 	}
412 
413 	s_free(buf);
414 	if (nvlist_pack(nvl, &buf, &size, encoding, 0) != 0) {
415 		dprintf((stderr, "nvlist_pack fail\n"));
416 		goto fail;
417 	}
418 
419 	nvlist_free(nvl);
420 	*bufp = buf;
421 	*sizep = size;
422 
423 	return (0);
424 
425 fail:
426 	s_free(buf);
427 	if (nvl != NULL)
428 		nvlist_free(nvl);
429 
430 	return (-1);
431 }
432 
433 static int
434 dev_pack(ri_dev_t *dev, char **bufp, size_t *sizep, int encoding)
435 {
436 	nvlist_t	*nvl = NULL;
437 	char		*buf = NULL;
438 	size_t		size = 0;
439 
440 	if (nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0) != 0) {
441 		dprintf((stderr, "nvlist_alloc fail\n"));
442 		return (-1);
443 	}
444 
445 	if (pack_add_byte_array(dev->conf_props, RI_DEV_PROPS, nvl,
446 	    encoding) != 0)
447 		goto fail;
448 
449 	if (client_list_pack(dev->rcm_clients, &buf, &size, encoding) != 0)
450 		goto fail;
451 
452 	if (nvlist_add_byte_array(nvl, RI_DEV_CLIENTS, (uchar_t *)buf,
453 	    size) != 0) {
454 		dprintf((stderr, "nvlist_add_byte_array (%s)n",
455 		    RI_DEV_CLIENTS));
456 		goto fail;
457 	}
458 
459 	s_free(buf);
460 	if (nvlist_pack(nvl, &buf, &size, encoding, 0) != 0) {
461 		dprintf((stderr, "nvlist_pack fail\n"));
462 		goto fail;
463 	}
464 
465 	nvlist_free(nvl);
466 	*bufp = buf;
467 	*sizep = size;
468 
469 	return (0);
470 
471 fail:
472 	s_free(buf);
473 	if (nvl != NULL)
474 		nvlist_free(nvl);
475 
476 	return (-1);
477 }
478 
479 static int
480 client_pack(ri_client_t *client, char **bufp, size_t *sizep, int encoding)
481 {
482 	nvlist_t	*nvl = NULL;
483 	char		*buf = NULL;
484 	size_t		size = 0;
485 
486 	if (nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0) != 0) {
487 		dprintf((stderr, "nvlist_alloc fail\n"));
488 		return (-1);
489 	}
490 
491 	if (pack_add_byte_array(client->usg_props, RI_CLIENT_USAGE_PROPS,
492 	    nvl, encoding) != 0) {
493 		goto fail;
494 	}
495 
496 	/*
497 	 * This will only be present if RI_VERBOSE was specified
498 	 * in the call to ri_init.
499 	 */
500 	if (client->v_props != NULL && pack_add_byte_array(client->v_props,
501 	    RI_CLIENT_VERB_PROPS, nvl, encoding) != 0) {
502 		goto fail;
503 	}
504 
505 	if (nvlist_pack(nvl, &buf, &size, encoding, 0) != 0) {
506 		dprintf((stderr, "nvlist_pack fail\n"));
507 		goto fail;
508 	}
509 
510 	nvlist_free(nvl);
511 	*bufp = buf;
512 	*sizep = size;
513 
514 	return (0);
515 
516 fail:
517 	s_free(buf);
518 	if (nvl != NULL)
519 		nvlist_free(nvl);
520 
521 	return (-1);
522 }
523 
524 /*
525  * Pack nvlist_t and add as byte array to another nvlist_t.
526  */
527 static int
528 pack_add_byte_array(nvlist_t *nvl_packme, char *name, nvlist_t *nvl,
529     int encoding)
530 {
531 	char	*buf = NULL;
532 	size_t	size = 0;
533 
534 	if (nvlist_pack(nvl_packme, &buf, &size, encoding, 0) != 0) {
535 		dprintf((stderr, "nvlist_pack fail (%s)\n", name));
536 		s_free(buf);
537 		return (-1);
538 	}
539 
540 	if (nvlist_add_byte_array(nvl, name, (uchar_t *)buf, size) != 0) {
541 		dprintf((stderr, "nvlist_add_byte_array fail (%s)\n", name));
542 		return (-1);
543 	}
544 
545 	s_free(buf);
546 	return (0);
547 }
548 
549 /*
550  * Unpack buf into ri_hdl_t.
551  */
552 int
553 ri_unpack(caddr_t buf, size_t size, ri_hdl_t **hdlp)
554 {
555 	ri_hdl_t	*ri_hdl = NULL;
556 	nvlist_t	*nvl = NULL;
557 
558 	if (hdlp == NULL)
559 		return (RI_INVAL);
560 
561 	*hdlp = NULL;
562 	if ((ri_hdl = calloc(1, sizeof (*ri_hdl))) == NULL) {
563 		dprintf((stderr, "calloc: %s\n", strerror(errno)));
564 		return (RI_FAILURE);
565 	}
566 
567 	if (nvlist_unpack(buf, size, &nvl, 0) != 0) {
568 		dprintf((stderr, "nvlist_unpack fail\n"));
569 		goto fail;
570 	}
571 
572 	if (nvlist_lookup_int32(nvl, RI_HDL_FLAGS, &ri_hdl->flags) != 0) {
573 		dprintf((stderr, "nvlist_lookup_int32 fail (%s)\n",
574 		    RI_HDL_FLAGS));
575 		goto fail;
576 	}
577 
578 	buf = NULL;
579 	size = 0;
580 	if (nvlist_lookup_byte_array(nvl, RI_HDL_APS, (uchar_t **)&buf,
581 	    (uint_t *)&size) != 0) {
582 		dprintf((stderr, "nvlist_lookup_int32 fail (%s)\n",
583 		    RI_HDL_APS));
584 		goto fail;
585 	}
586 
587 	if (ap_list_unpack(buf, size, &ri_hdl->aps) != 0)
588 		goto fail;
589 
590 	buf = NULL;
591 	size = 0;
592 	if (nvlist_lookup_byte_array(nvl, RI_HDL_CPU_CAPS, (uchar_t **)&buf,
593 	    (uint_t *)&size) != 0) {
594 		dprintf((stderr, "nvlist_lookup_byte_array fail (%s)\n",
595 		    RI_HDL_CPU_CAPS));
596 		goto fail;
597 	}
598 
599 	if (client_list_unpack(buf, size, &ri_hdl->cpu_cap_clients) != 0)
600 		goto fail;
601 
602 	buf = NULL;
603 	size = 0;
604 	if (nvlist_lookup_byte_array(nvl, RI_HDL_MEM_CAPS, (uchar_t **)&buf,
605 	    (uint_t *)&size) != 0) {
606 		dprintf((stderr, "nvlist_lookup_byte_array fail (%s)\n",
607 		    RI_HDL_MEM_CAPS));
608 		goto fail;
609 	}
610 
611 	if (client_list_unpack(buf, size, &ri_hdl->mem_cap_clients) != 0)
612 		goto fail;
613 
614 	*hdlp = ri_hdl;
615 
616 	return (0);
617 
618 fail:
619 	free(ri_hdl);
620 	if (nvl != NULL)
621 		nvlist_free(nvl);
622 
623 	return (-1);
624 }
625 
626 static int
627 ap_list_unpack(char *buf, size_t size, ri_ap_t **aps)
628 {
629 	nvpair_t	*nvp = NULL;
630 	nvlist_t	*nvl;
631 	ri_ap_t		*aplist = NULL;
632 	ri_ap_t		*prev = NULL;
633 	ri_ap_t		*tmp = NULL;
634 
635 	if (nvlist_unpack(buf, size, &nvl, 0) != 0) {
636 		dprintf((stderr, "nvlist_unpack fail\n"));
637 		return (-1);
638 	}
639 
640 	while ((nvp = nvlist_next_nvpair(nvl, nvp)) != NULL) {
641 		assert(strcmp(nvpair_name(nvp), RI_AP_T) == 0 &&
642 		    nvpair_type(nvp) == DATA_TYPE_BYTE_ARRAY);
643 
644 		if ((tmp = calloc(1, sizeof (*tmp))) == NULL) {
645 			dprintf((stderr, "calloc: %s\n", strerror(errno)));
646 			goto fail;
647 		}
648 
649 		buf = NULL;
650 		size = 0;
651 		if (nvpair_value_byte_array(nvp, (uchar_t **)&buf,
652 		    (uint_t *)&size) != 0) {
653 			dprintf((stderr, "nvpair_value_byte_array fail\n"));
654 			goto fail;
655 		}
656 
657 		if (ap_unpack(buf, size, tmp) != 0)
658 			goto fail;
659 
660 		if (aplist == NULL) {
661 			prev = aplist = tmp;
662 		} else {
663 			prev->next = tmp;
664 			prev = tmp;
665 		}
666 	}
667 
668 	nvlist_free(nvl);
669 	*aps = aplist;
670 
671 	return (0);
672 
673 fail:
674 	if (nvl != NULL)
675 		nvlist_free(nvl);
676 	if (aplist != NULL) {
677 		while ((tmp = aplist) != NULL) {
678 			aplist = aplist->next;
679 			ri_ap_free(tmp);
680 		}
681 	}
682 
683 	return (-1);
684 }
685 
686 static int
687 dev_list_unpack(char *buf, size_t size, ri_dev_t **devs)
688 {
689 	nvpair_t	*nvp = NULL;
690 	nvlist_t	*nvl;
691 	ri_dev_t	*devlist = NULL;
692 	ri_dev_t	*prev = NULL;
693 	ri_dev_t	*tmp = NULL;
694 
695 	if (nvlist_unpack(buf, size, &nvl, 0) != 0) {
696 		dprintf((stderr, "nvlist_unpack fail\n"));
697 		return (-1);
698 	}
699 
700 	while ((nvp = nvlist_next_nvpair(nvl, nvp)) != NULL) {
701 		assert(strcmp(nvpair_name(nvp), RI_DEV_T) == 0 &&
702 		    nvpair_type(nvp) == DATA_TYPE_BYTE_ARRAY);
703 
704 		if ((tmp = calloc(1, sizeof (*tmp))) == NULL) {
705 			dprintf((stderr, "calloc: %s\n", strerror(errno)));
706 			goto fail;
707 		}
708 
709 		if (nvpair_value_byte_array(nvp, (uchar_t **)&buf,
710 		    (uint_t *)&size) != 0) {
711 			dprintf((stderr, "nvpair_value_byte_array fail\n"));
712 			goto fail;
713 		}
714 
715 		if (dev_unpack(buf, size, tmp) != 0)
716 			goto fail;
717 
718 		if (devlist == NULL) {
719 			prev = devlist = tmp;
720 		} else {
721 			prev->next = tmp;
722 			prev = tmp;
723 		}
724 	}
725 
726 	nvlist_free(nvl);
727 	*devs = devlist;
728 
729 	return (0);
730 
731 fail:
732 	if (nvl != NULL)
733 		nvlist_free(nvl);
734 	if (devlist != NULL) {
735 		while ((tmp = devlist) != NULL) {
736 			devlist = devlist->next;
737 			ri_dev_free(tmp);
738 		}
739 	}
740 
741 	return (-1);
742 }
743 
744 static int
745 client_list_unpack(char *buf, size_t size, ri_client_t **clients)
746 {
747 	nvpair_t	*nvp = NULL;
748 	nvlist_t	*nvl;
749 	ri_client_t	*client_list = NULL;
750 	ri_client_t	*prev = NULL;
751 	ri_client_t	*tmp = NULL;
752 
753 	if (nvlist_unpack(buf, size, &nvl, 0) != 0) {
754 		dprintf((stderr, "nvlist_unpack fail\n"));
755 		return (-1);
756 	}
757 
758 	while ((nvp = nvlist_next_nvpair(nvl, nvp)) != NULL) {
759 		assert(strcmp(nvpair_name(nvp), RI_CLIENT_T) == 0);
760 		assert(nvpair_type(nvp) == DATA_TYPE_BYTE_ARRAY);
761 
762 		if ((tmp = calloc(1, sizeof (*tmp))) == NULL) {
763 			dprintf((stderr, "calloc: %s\n", strerror(errno)));
764 			goto fail;
765 		}
766 
767 		buf = NULL;
768 		size = 0;
769 		if (nvpair_value_byte_array(nvp, (uchar_t **)&buf,
770 		    (uint_t *)&size) != 0) {
771 			dprintf((stderr, "nvpair_value_byte_array fail\n"));
772 			goto fail;
773 		}
774 
775 		if (client_unpack(buf, size, tmp) != 0)
776 			goto fail;
777 
778 		if (client_list == NULL) {
779 			prev = client_list = tmp;
780 		} else {
781 			prev->next = tmp;
782 			prev = tmp;
783 		}
784 	}
785 
786 	nvlist_free(nvl);
787 	*clients = client_list;
788 
789 	return (0);
790 
791 fail:
792 	if (nvl != NULL)
793 		nvlist_free(nvl);
794 	if (client_list != NULL) {
795 		while ((tmp = client_list) != NULL) {
796 			client_list = client_list->next;
797 			ri_client_free(tmp);
798 		}
799 	}
800 
801 	return (-1);
802 }
803 
804 static int
805 client_unpack(char *buf, size_t size, ri_client_t *client)
806 {
807 	nvlist_t	*nvl;
808 
809 	if (nvlist_unpack(buf, size, &nvl, 0) != 0) {
810 		dprintf((stderr, "nvlist_unpack fail\n"));
811 		return (-1);
812 	}
813 
814 	if (lookup_unpack_byte_array(nvl, RI_CLIENT_USAGE_PROPS,
815 	    &client->usg_props) != 0) {
816 		nvlist_free(nvl);
817 		return (-1);
818 	}
819 
820 #ifdef DEBUG
821 	nvlist_print(stderr, client->usg_props);
822 #endif /* DEBUG */
823 
824 	/*
825 	 * Verbose properties for RCM clients only present if
826 	 * RI_VERBOSE was specified for ri_init.
827 	 */
828 	buf = NULL;
829 	size = 0;
830 	if (nvlist_lookup_byte_array(nvl, RI_CLIENT_VERB_PROPS,
831 	    (uchar_t **)&buf, (uint_t *)&size) == 0) {
832 		if (nvlist_unpack(buf, size, &client->v_props, 0) != 0) {
833 			dprintf((stderr, "nvlist_unpack fail (%s)\n",
834 			    RI_CLIENT_VERB_PROPS));
835 			nvlist_free(nvl);
836 			return (-1);
837 		}
838 	}
839 
840 	nvlist_free(nvl);
841 
842 	return (0);
843 }
844 
845 static int
846 dev_unpack(char *buf, size_t size, ri_dev_t *dev)
847 {
848 	nvlist_t	*nvl;
849 
850 	if (nvlist_unpack(buf, size, &nvl, 0) != 0) {
851 		dprintf((stderr, "nvlist_unpack fail\n"));
852 		return (-1);
853 	}
854 
855 	if (lookup_unpack_byte_array(nvl, RI_DEV_PROPS,
856 	    &dev->conf_props) != 0) {
857 		nvlist_free(nvl);
858 		return (-1);
859 	}
860 
861 #ifdef DEBUG
862 	nvlist_print(stderr, dev->conf_props);
863 #endif /* DEBUG */
864 
865 	if (nvlist_lookup_byte_array(nvl, RI_DEV_CLIENTS, (uchar_t **)&buf,
866 	    (uint_t *)&size) != 0) {
867 		dprintf((stderr, "nvlist_lookup_byte_array fail (%s)\n",
868 		    RI_DEV_CLIENTS));
869 		nvlist_free(nvl);
870 		return (-1);
871 	}
872 
873 	if (client_list_unpack(buf, size, &dev->rcm_clients) != 0) {
874 		nvlist_free(nvl);
875 		return (-1);
876 	}
877 
878 	nvlist_free(nvl);
879 
880 	return (0);
881 }
882 
883 static int
884 ap_unpack(char *buf, size_t size, ri_ap_t *ap)
885 {
886 	nvlist_t	*nvl;
887 
888 	if (nvlist_unpack(buf, size, &nvl, 0) != 0) {
889 		dprintf((stderr, "nvlist_unpack fail\n"));
890 		return (-1);
891 	}
892 
893 	if (lookup_unpack_byte_array(nvl, RI_AP_PROPS, &ap->conf_props) != 0) {
894 		nvlist_free(nvl);
895 		return (-1);
896 	}
897 
898 #ifdef DEBUG
899 	nvlist_print(stderr, ap->conf_props);
900 #endif /* DEBUG */
901 
902 	if (nvlist_lookup_byte_array(nvl, RI_AP_CPUS, (uchar_t **)&buf,
903 	    (uint_t *)&size) != 0) {
904 		dprintf((stderr, "nvlist_lookup_byte_array fail (%s)\n",
905 		    RI_AP_CPUS));
906 		nvlist_free(nvl);
907 		return (-1);
908 	}
909 
910 	if (dev_list_unpack(buf, size, &ap->cpus) != 0) {
911 		nvlist_free(nvl);
912 		return (-1);
913 	}
914 
915 	if (nvlist_lookup_byte_array(nvl, RI_AP_MEMS, (uchar_t **)&buf,
916 	    (uint_t *)&size) != 0) {
917 		dprintf((stderr, "nvlist_lookup_byte_array fail (%s)\n",
918 		    RI_AP_MEMS));
919 		nvlist_free(nvl);
920 		return (-1);
921 	}
922 
923 	if (dev_list_unpack(buf, size, &ap->mems) != 0) {
924 		nvlist_free(nvl);
925 		return (-1);
926 	}
927 
928 	if (nvlist_lookup_byte_array(nvl, RI_AP_IOS, (uchar_t **)&buf,
929 	    (uint_t *)&size) != 0) {
930 		dprintf((stderr, "nvlist_lookup_byte_array fail (%s)\n",
931 		    RI_AP_IOS));
932 		nvlist_free(nvl);
933 		return (-1);
934 	}
935 
936 	if (dev_list_unpack(buf, size, &ap->ios) != 0) {
937 		nvlist_free(nvl);
938 		return (-1);
939 	}
940 
941 	nvlist_free(nvl);
942 
943 	return (0);
944 }
945 
946 /*
947  * Lookup byte array in old nvlist_t and unpack into new nvlist_t.
948  */
949 static int
950 lookup_unpack_byte_array(nvlist_t *old_nvl, char *name, nvlist_t **new_nvl)
951 {
952 	char	*buf = NULL;
953 	size_t	size = 0;
954 
955 	if (nvlist_lookup_byte_array(old_nvl, name, (uchar_t **)&buf,
956 	    (uint_t *)&size) != 0) {
957 		dprintf((stderr, "nvlist_lookup_byte_array fail (%s)\n",
958 		    name));
959 		return (-1);
960 	}
961 
962 	if (nvlist_unpack(buf, size, new_nvl, 0) != 0) {
963 		dprintf((stderr, "nvlist_unpack fail (%s)\n", name));
964 		return (-1);
965 	}
966 
967 	return (0);
968 }
969 
970 ri_ap_t *
971 ri_ap_next(ri_hdl_t *hdl, ri_ap_t *ap)
972 {
973 	if (hdl == NULL) {
974 		errno = EINVAL;
975 		return (NULL);
976 	}
977 	return ((ap == NULL) ? hdl->aps : ap->next);
978 }
979 
980 nvlist_t *
981 ri_ap_conf_props(ri_ap_t *ap)
982 {
983 	if (ap == NULL) {
984 		errno = EINVAL;
985 		return (NULL);
986 	}
987 	return (ap->conf_props);
988 }
989 
990 ri_dev_t *
991 ri_cpu_next(ri_ap_t *ap, ri_dev_t *cpu)
992 {
993 	if (ap == NULL) {
994 		errno = EINVAL;
995 		return (NULL);
996 	}
997 	return ((cpu == NULL) ? ap->cpus : cpu->next);
998 }
999 
1000 ri_dev_t *
1001 ri_mem_next(ri_ap_t *ap, ri_dev_t *mem)
1002 {
1003 	if (ap == NULL) {
1004 		errno = EINVAL;
1005 		return (NULL);
1006 	}
1007 	return ((mem == NULL) ? ap->mems : mem->next);
1008 }
1009 
1010 ri_dev_t *
1011 ri_io_next(ri_ap_t *ap, ri_dev_t *io)
1012 {
1013 	if (ap == NULL) {
1014 		errno = EINVAL;
1015 		return (NULL);
1016 	}
1017 	return ((io == NULL) ? ap->ios : io->next);
1018 }
1019 
1020 ri_client_t *
1021 ri_client_next(ri_dev_t *dev, ri_client_t *rcm_client)
1022 {
1023 	if (dev == NULL) {
1024 		errno = EINVAL;
1025 		return (NULL);
1026 	}
1027 	return ((rcm_client == NULL) ? dev->rcm_clients : rcm_client->next);
1028 }
1029 
1030 nvlist_t *
1031 ri_dev_conf_props(ri_dev_t *dev)
1032 {
1033 	if (dev == NULL) {
1034 		errno = EINVAL;
1035 		return (NULL);
1036 	}
1037 	return (dev->conf_props);
1038 }
1039 
1040 nvlist_t *
1041 ri_client_usage_props(ri_client_t *rcm_client)
1042 {
1043 	if (rcm_client == NULL) {
1044 		errno = EINVAL;
1045 		return (NULL);
1046 	}
1047 	return (rcm_client->usg_props);
1048 }
1049 
1050 nvlist_t *
1051 ri_client_verbose_props(ri_client_t *rcm_client)
1052 {
1053 	if (rcm_client == NULL) {
1054 		errno = EINVAL;
1055 		return (NULL);
1056 	}
1057 	return (rcm_client->v_props);
1058 }
1059 
1060 ri_client_t *
1061 ri_cpu_cap_client_next(ri_hdl_t *hdl, ri_client_t *rcm_client)
1062 {
1063 	if (hdl == NULL) {
1064 		errno = EINVAL;
1065 		return (NULL);
1066 	}
1067 	return ((rcm_client == NULL) ? hdl->cpu_cap_clients : rcm_client->next);
1068 }
1069 
1070 ri_client_t *
1071 ri_mem_cap_client_next(ri_hdl_t *hdl, ri_client_t *rcm_client)
1072 {
1073 	if (hdl == NULL) {
1074 		errno = EINVAL;
1075 		return (NULL);
1076 	}
1077 	return ((rcm_client == NULL) ? hdl->mem_cap_clients : rcm_client->next);
1078 }
1079