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 
36 static int ap_list_pack(ri_ap_t *, char **, size_t *, int);
37 static int ap_list_unpack(char *, size_t, ri_ap_t **);
38 static int ap_pack(ri_ap_t *, char **, size_t *, int);
39 static int ap_unpack(char *, size_t, ri_ap_t *);
40 static int dev_list_pack(ri_dev_t *, char **, size_t *, int);
41 static int dev_list_unpack(char *, size_t, ri_dev_t **);
42 static int dev_pack(ri_dev_t *, char **, size_t *, int);
43 static int dev_unpack(char *, size_t, ri_dev_t *);
44 static int client_list_pack(ri_client_t *, char **, size_t *, int);
45 static int client_list_unpack(char *, size_t, ri_client_t **);
46 static int client_pack(ri_client_t *, char **, size_t *, int);
47 static int client_unpack(char *, size_t, ri_client_t *);
48 static int pack_add_byte_array(nvlist_t *, char *, nvlist_t *, int);
49 static int lookup_unpack_byte_array(nvlist_t *, char *, nvlist_t **);
50 static void ri_ap_free(ri_ap_t *);
51 
52 void
ri_fini(ri_hdl_t * hdl)53 ri_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 
76 static void
ri_ap_free(ri_ap_t * ap)77 ri_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 
100 void
ri_dev_free(ri_dev_t * dev)101 ri_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 
115 void
ri_client_free(ri_client_t * client)116 ri_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  */
128 int
ri_pack(ri_hdl_t * hdl,caddr_t * bufp,size_t * sizep,int encoding)129 ri_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 
192 fail:
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  */
202 static int
ap_list_pack(ri_ap_t * aplist,char ** bufp,size_t * sizep,int encoding)203 ap_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 
245 fail:
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  */
255 static int
dev_list_pack(ri_dev_t * devlist,char ** bufp,size_t * sizep,int encoding)256 dev_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 
298 fail:
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  */
308 static int
client_list_pack(ri_client_t * client_list,char ** bufp,size_t * sizep,int encoding)309 client_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 
352 fail:
353 	s_free(buf);
354 	nvlist_free(nvl);
355 
356 	return (-1);
357 }
358 
359 static int
ap_pack(ri_ap_t * ap,char ** bufp,size_t * sizep,int encoding)360 ap_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 
416 fail:
417 	s_free(buf);
418 	nvlist_free(nvl);
419 
420 	return (-1);
421 }
422 
423 static int
dev_pack(ri_dev_t * dev,char ** bufp,size_t * sizep,int encoding)424 dev_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 
461 fail:
462 	s_free(buf);
463 	nvlist_free(nvl);
464 
465 	return (-1);
466 }
467 
468 static int
client_pack(ri_client_t * client,char ** bufp,size_t * sizep,int encoding)469 client_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 
505 fail:
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  */
515 static int
pack_add_byte_array(nvlist_t * nvl_packme,char * name,nvlist_t * nvl,int encoding)516 pack_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  */
540 int
ri_unpack(caddr_t buf,size_t size,ri_hdl_t ** hdlp)541 ri_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 
606 fail:
607 	free(ri_hdl);
608 	nvlist_free(nvl);
609 
610 	return (-1);
611 }
612 
613 static int
ap_list_unpack(char * buf,size_t size,ri_ap_t ** aps)614 ap_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 
660 fail:
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 
672 static int
dev_list_unpack(char * buf,size_t size,ri_dev_t ** devs)673 dev_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 
717 fail:
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 
729 static int
client_list_unpack(char * buf,size_t size,ri_client_t ** clients)730 client_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 
776 fail:
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 
788 static int
client_unpack(char * buf,size_t size,ri_client_t * client)789 client_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 
829 static int
dev_unpack(char * buf,size_t size,ri_dev_t * dev)830 dev_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 
867 static int
ap_unpack(char * buf,size_t size,ri_ap_t * ap)868 ap_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  */
933 static int
lookup_unpack_byte_array(nvlist_t * old_nvl,char * name,nvlist_t ** new_nvl)934 lookup_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 
954 ri_ap_t *
ri_ap_next(ri_hdl_t * hdl,ri_ap_t * ap)955 ri_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 
964 nvlist_t *
ri_ap_conf_props(ri_ap_t * ap)965 ri_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 
974 ri_dev_t *
ri_cpu_next(ri_ap_t * ap,ri_dev_t * cpu)975 ri_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 
984 ri_dev_t *
ri_mem_next(ri_ap_t * ap,ri_dev_t * mem)985 ri_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 
994 ri_dev_t *
ri_io_next(ri_ap_t * ap,ri_dev_t * io)995 ri_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 
1004 ri_client_t *
ri_client_next(ri_dev_t * dev,ri_client_t * rcm_client)1005 ri_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 
1014 nvlist_t *
ri_dev_conf_props(ri_dev_t * dev)1015 ri_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 
1024 nvlist_t *
ri_client_usage_props(ri_client_t * rcm_client)1025 ri_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 
1034 nvlist_t *
ri_client_verbose_props(ri_client_t * rcm_client)1035 ri_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 
1044 ri_client_t *
ri_cpu_cap_client_next(ri_hdl_t * hdl,ri_client_t * rcm_client)1045 ri_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 
1054 ri_client_t *
ri_mem_cap_client_next(ri_hdl_t * hdl,ri_client_t * rcm_client)1055 ri_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