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