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 }