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