f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby/*
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby * CDDL HEADER START
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby *
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby * The contents of this file are subject to the terms of the
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby * Common Development and Distribution License (the "License").
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby * You may not use this file except in compliance with the License.
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby *
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby * or http://www.opensolaris.org/os/licensing.
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby * See the License for the specific language governing permissions
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby * and limitations under the License.
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby *
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby * When distributing Covered Code, include this CDDL HEADER in each
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby * If applicable, add the following below this CDDL HEADER, with the
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby * fields enclosed by brackets "[]" replaced with your own identifying
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby * information: Portions Copyright [yyyy] [name of copyright owner]
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby *
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby * CDDL HEADER END
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby */
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby/*
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby */
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby#include <libnvpair.h>
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby#include <fm/topo_mod.h>
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby#include <sys/fm/protocol.h>
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby#include <sys/types.h>
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby#include <topo_method.h>
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby#include <topo_subr.h>
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby#include <sw.h>
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltbystatic int sw_fmri_nvl2str(topo_mod_t *, tnode_t *, topo_version_t,
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby nvlist_t *, nvlist_t **);
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltbystatic int sw_fmri_create(topo_mod_t *, tnode_t *, topo_version_t,
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby nvlist_t *, nvlist_t **);
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltbystatic const topo_method_t sw_methods[] = {
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby { TOPO_METH_NVL2STR, TOPO_METH_NVL2STR_DESC, TOPO_METH_NVL2STR_VERSION,
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby TOPO_STABILITY_INTERNAL, sw_fmri_nvl2str },
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby { TOPO_METH_FMRI, TOPO_METH_FMRI_DESC, TOPO_METH_FMRI_VERSION,
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby TOPO_STABILITY_INTERNAL, sw_fmri_create },
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby { NULL }
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby};
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltbystatic int sw_enum(topo_mod_t *, tnode_t *, const char *, topo_instance_t,
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby topo_instance_t, void *, void *);
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltbystatic void sw_release(topo_mod_t *, tnode_t *);
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltbystatic const topo_modops_t sw_ops =
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby { sw_enum, sw_release };
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltbystatic const topo_modinfo_t sw_info =
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby { "sw", FM_FMRI_SCHEME_SW, SW_VERSION, &sw_ops };
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltbyint
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltbysw_init(topo_mod_t *mod, topo_version_t version)
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby{
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby if (getenv("TOPOSWDEBUG"))
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby topo_mod_setdebug(mod);
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby topo_mod_dprintf(mod, "initializing sw builtin\n");
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby if (version != SW_VERSION)
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby return (topo_mod_seterrno(mod, EMOD_VER_NEW));
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby if (topo_mod_register(mod, &sw_info, TOPO_VERSION) != 0) {
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby topo_mod_dprintf(mod, "failed to register sw_info: "
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby "%s\n", topo_mod_errmsg(mod));
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby return (-1);
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby }
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby return (0);
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby}
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltbyvoid
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltbysw_fini(topo_mod_t *mod)
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby{
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby topo_mod_unregister(mod);
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby}
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltbystatic int
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltbysw_get_optl_string(nvlist_t *nvl, char *name, char **dest)
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby{
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby if (nvlist_lookup_string(nvl, name, dest) == 0) {
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby return (0);
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby } else {
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby *dest = NULL;
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby return (errno == ENOENT ? 0 : 1);
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby }
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby}
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltbystatic int
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltbysw_get_optl_int64(nvlist_t *nvl, char *name, int64_t *dest)
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby{
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby if (nvlist_lookup_int64(nvl, name, dest) == 0) {
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby return (0);
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby } else {
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby *dest = -1;
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby return (errno == ENOENT ? 0 : 1);
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby }
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby}
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltbystatic int
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltbysw_get_optl_nvlist(nvlist_t *nvl, char *name, nvlist_t **dest)
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby{
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby if (nvlist_lookup_nvlist(nvl, name, dest) == 0) {
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby return (0);
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby } else {
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby *dest = NULL;
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby return (errno == ENOENT ? 0 : 1);
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby }
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby}
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltbystatic int
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltbysw_add_optl_string(nvlist_t *nvl, char *name, char *val)
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby{
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby if (val)
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby return (nvlist_add_string(nvl, name, val) != 0);
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby else
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby return (0);
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby}
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby/*ARGSUSED*/
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltbystatic int
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltbysw_fmri_create(topo_mod_t *mod, tnode_t *node, topo_version_t version,
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby nvlist_t *in, nvlist_t **out)
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby{
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby nvlist_t *args, *fmri = NULL, *obj = NULL, *site = NULL, *ctxt = NULL;
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby topo_mod_errno_t moderr;
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby int err = 0;
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby char *obj_path, *obj_root;
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby nvlist_t *obj_pkg;
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby char *site_token, *site_module, *site_file, *site_func;
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby int64_t site_line;
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby char *ctxt_origin, *ctxt_execname, *ctxt_zone;
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby int64_t ctxt_pid, ctxt_ctid;
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby char **ctxt_stack;
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby uint_t ctxt_stackdepth;
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby if (version > TOPO_METH_FMRI_VERSION)
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby return (topo_mod_seterrno(mod, EMOD_VER_NEW));
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby if (nvlist_lookup_nvlist(in, TOPO_METH_FMRI_ARG_NVL, &args) != 0)
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby return (topo_mod_seterrno(mod, EMOD_METHOD_INVAL));
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby if (nvlist_lookup_string(args, "obj_path", &obj_path) != 0)
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby return (topo_mod_seterrno(mod, EMOD_NVL_INVAL));
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby err |= sw_get_optl_string(args, "obj_root", &obj_root);
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby err |= sw_get_optl_nvlist(args, "obj-pkg", &obj_pkg);
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby err |= sw_get_optl_string(args, "site_token", &site_token);
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby err |= sw_get_optl_string(args, "site_module", &site_module);
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby err |= sw_get_optl_string(args, "site_file", &site_file);
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby err |= sw_get_optl_string(args, "site_func", &site_func);
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby err |= sw_get_optl_int64(args, "site_line", &site_line);
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby err |= sw_get_optl_string(args, "ctxt_origin", &ctxt_origin);
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby err |= sw_get_optl_string(args, "ctxt_execname", &ctxt_execname);
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby err |= sw_get_optl_string(args, "ctxt_zone", &ctxt_zone);
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby err |= sw_get_optl_int64(args, "ctxt_pid", &ctxt_pid);
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby err |= sw_get_optl_int64(args, "ctxt_ctid", &ctxt_ctid);
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby if (nvlist_lookup_string_array(args, "stack", &ctxt_stack,
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby &ctxt_stackdepth) != 0) {
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby if (errno == ENOENT)
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby ctxt_stack = NULL;
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby else
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby err++;
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby }
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby if (err)
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby (void) topo_mod_seterrno(mod, EMOD_FMRI_NVL);
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby if (topo_mod_nvalloc(mod, &fmri, NV_UNIQUE_NAME) != 0 ||
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby topo_mod_nvalloc(mod, &obj, NV_UNIQUE_NAME) != 0) {
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby moderr = EMOD_NOMEM;
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby goto out;
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby }
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby /*
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby * Add standard FMRI members 'version' and 'scheme'.
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby */
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby err |= nvlist_add_uint8(fmri, FM_VERSION, FM_SW_SCHEME_VERSION);
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby err |= nvlist_add_string(fmri, FM_FMRI_SCHEME, FM_FMRI_SCHEME_SW);
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby /*
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby * Build up the 'object' nvlist.
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby */
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby err |= nvlist_add_string(obj, FM_FMRI_SW_OBJ_PATH, obj_path);
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby err |= sw_add_optl_string(obj, FM_FMRI_SW_OBJ_ROOT, obj_root);
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby if (obj_pkg)
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby err |= nvlist_add_nvlist(obj, FM_FMRI_SW_OBJ_PKG, obj_pkg);
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby /*
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby * Add 'object' to the fmri.
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby */
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby if (err == 0)
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby err |= nvlist_add_nvlist(fmri, FM_FMRI_SW_OBJ, obj);
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby if (err) {
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby moderr = EMOD_NOMEM;
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby goto out;
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby }
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby /*
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby * Do we have anything for a 'site' nvlist?
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby */
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby if (site_token == NULL && site_module == NULL && site_file == NULL &&
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby site_func == NULL && site_line == -1)
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby goto context;
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby /*
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby * Allocate and build 'site' nvlist.
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby */
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby if (topo_mod_nvalloc(mod, &site, NV_UNIQUE_NAME) != 0) {
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby moderr = EMOD_NOMEM;
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby goto out;
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby }
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby err |= sw_add_optl_string(site, FM_FMRI_SW_SITE_TOKEN, site_token);
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby err |= sw_add_optl_string(site, FM_FMRI_SW_SITE_MODULE, site_module);
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby err |= sw_add_optl_string(site, FM_FMRI_SW_SITE_FILE, site_file);
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby err |= sw_add_optl_string(site, FM_FMRI_SW_SITE_FUNC, site_func);
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby if ((site_token || site_module || site_file || site_func) &&
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby site_line != -1)
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby err |= nvlist_add_int64(site, FM_FMRI_SW_SITE_LINE, site_line);
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby /*
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby * Add 'site' to the fmri.
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby */
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby if (err == 0)
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby err |= nvlist_add_nvlist(fmri, FM_FMRI_SW_SITE, site);
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby if (err) {
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby moderr = EMOD_NOMEM;
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby goto out;
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby }
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltbycontext:
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby /*
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby * Do we have anything for a 'context' nvlist?
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby */
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby if (ctxt_origin || ctxt_execname || ctxt_zone ||
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby ctxt_pid != -1 || ctxt_ctid != -1 || ctxt_stack != NULL)
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby goto out;
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby /*
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby * Allocate and build 'context' nvlist.
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby */
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby if (topo_mod_nvalloc(mod, &ctxt, NV_UNIQUE_NAME) != 0) {
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby moderr = EMOD_NOMEM;
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby goto out;
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby }
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby err |= sw_add_optl_string(ctxt, FM_FMRI_SW_CTXT_ORIGIN, ctxt_origin);
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby err |= sw_add_optl_string(ctxt, FM_FMRI_SW_CTXT_EXECNAME,
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby ctxt_execname);
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby err |= sw_add_optl_string(ctxt, FM_FMRI_SW_CTXT_ZONE, ctxt_zone);
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby if (ctxt_pid != -1)
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby err |= nvlist_add_int64(ctxt, FM_FMRI_SW_CTXT_PID, ctxt_pid);
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby if (ctxt_ctid != -1)
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby err |= nvlist_add_int64(ctxt, FM_FMRI_SW_CTXT_CTID, ctxt_ctid);
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby if (ctxt_stack != NULL)
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby err |= nvlist_add_string_array(ctxt, FM_FMRI_SW_CTXT_STACK,
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby ctxt_stack, ctxt_stackdepth);
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby /*
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby * Add 'context' to the fmri.
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby */
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby if (err == 0)
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby err |= nvlist_add_nvlist(fmri, FM_FMRI_SW_CTXT, ctxt);
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby moderr = err ? EMOD_NOMEM : 0;
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltbyout:
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby if (moderr == 0)
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby *out = fmri;
aab83bb83be7342f6cfccaed8d5fe0b2f404855dJosef 'Jeff' Sipek else
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby nvlist_free(fmri);
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby
aab83bb83be7342f6cfccaed8d5fe0b2f404855dJosef 'Jeff' Sipek nvlist_free(obj);
aab83bb83be7342f6cfccaed8d5fe0b2f404855dJosef 'Jeff' Sipek nvlist_free(site);
aab83bb83be7342f6cfccaed8d5fe0b2f404855dJosef 'Jeff' Sipek nvlist_free(ctxt);
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby return (moderr == 0 ? 0 : topo_mod_seterrno(mod, moderr));
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby}
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby/*ARGSUSED*/
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltbystatic int
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltbysw_enum(topo_mod_t *mod, tnode_t *pnode, const char *name,
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby topo_instance_t min, topo_instance_t max, void *notused1, void *notused2)
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby{
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby (void) topo_method_register(mod, pnode, sw_methods);
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby return (0);
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby}
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltbystatic void
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltbysw_release(topo_mod_t *mod, tnode_t *node)
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby{
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby topo_method_unregister_all(mod, node);
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby}
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby/*
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby * Lookup a string in an nvlist. Possible return values:
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby * if 'required' is B_TRUE:
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby * 1 = found
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby * 0 = not found
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby * if 'required' is B_FALSE:
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby * 1 = found
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby * 0 = not found, but some error other than ENOENT encountered
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby * -1 = not found, with ENOENT
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby *
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby * So 0 is an error condition in both cases.
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby *
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby * In all "not found" cases, *valp is NULLed.
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby */
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltbystatic int
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltbylookup_string(nvlist_t *nvl, char *name, char **valp, boolean_t required)
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby{
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby int err;
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby err = nvlist_lookup_string(nvl, name, valp);
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby /*
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby * A return value of 1 always means "found"
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby */
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby if (err == 0)
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby return (1);
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby /*
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby * Failure to lookup for whatever reason NULLs valp
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby */
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby *valp = NULL;
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby /*
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby * Return 0 if not found but required, or optional but some error
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby * other than ENOENT was returned.
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby */
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby if (required == B_TRUE || err != ENOENT)
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby return (0);
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby /*
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby * Return -1 if not found but was optional (and got ENOENT).
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby */
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby return (-1);
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby}
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby/*ARGSUSED*/
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltbystatic int
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltbysw_fmri_nvl2str(topo_mod_t *mod, tnode_t *node, topo_version_t version,
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby nvlist_t *nvl, nvlist_t **out)
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby{
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby nvlist_t *object, *site = NULL, *anvl = NULL;
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby char *file, *func, *token;
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby uint8_t scheme_version;
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby char *path, *root;
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby nvlist_t *fmristr;
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby size_t buflen = 0;
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby int linevalid = 0;
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby char *buf = NULL;
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby ssize_t size = 0;
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby char linebuf[32];
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby int64_t line;
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby int pass;
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby int err;
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby if (version > TOPO_METH_NVL2STR_VERSION)
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby return (topo_mod_seterrno(mod, EMOD_VER_NEW));
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby if (nvlist_lookup_uint8(nvl, FM_VERSION, &scheme_version) != 0 ||
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby scheme_version > FM_SW_SCHEME_VERSION)
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby return (topo_mod_seterrno(mod, EMOD_FMRI_NVL));
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby /* Get authority, if present */
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby err = nvlist_lookup_nvlist(nvl, FM_FMRI_AUTHORITY, &anvl);
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby if (err != 0 && err != ENOENT)
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby return (topo_mod_seterrno(mod, EMOD_FMRI_NVL));
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby /*
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby * The 'object' nvlist is required. It must include the path,
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby * but the root is optional.
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby */
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby if (nvlist_lookup_nvlist(nvl, FM_FMRI_SW_OBJ, &object) != 0 ||
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby !lookup_string(object, FM_FMRI_SW_OBJ_PATH, &path, B_TRUE) ||
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby !lookup_string(object, FM_FMRI_SW_OBJ_ROOT, &root, B_FALSE))
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby return (topo_mod_seterrno(mod, EMOD_FMRI_NVL));
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby /* The 'site' nvlist is optional */
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby file = func = token = NULL;
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby linevalid = 0;
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby if ((err = nvlist_lookup_nvlist(nvl, FM_FMRI_SW_SITE, &site)) == 0) {
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby /*
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby * Prefer 'token' to file/func/line
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby */
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby if (lookup_string(site, FM_FMRI_SW_SITE_TOKEN, &token,
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby B_FALSE) <= 0) {
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby /*
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby * If no token then try file, func, line - but
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby * func and line are meaningless without file.
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby */
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby if (lookup_string(site, FM_FMRI_SW_SITE_FILE,
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby &file, B_FALSE) == 1) {
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby (void) lookup_string(site, FM_FMRI_SW_SITE_FUNC,
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby &func, B_FALSE);
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby if (nvlist_lookup_int64(site,
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby FM_FMRI_SW_SITE_LINE, &line) == 0)
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby linevalid = 1;
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby }
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby }
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby } else if (err != ENOENT) {
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby return (topo_mod_seterrno(mod, EMOD_FMRI_NVL));
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby }
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby /* On the first pass buf is NULL and size and buflen are 0 */
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby pass = 1;
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltbyagain:
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby /*
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby * sw://[<authority>]/
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby * [:root=<object.root]
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby * :path=<object.path>
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby * [#<fragment-identifier>]
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby *
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby * <fragment-identifier> is one of
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby *
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby * :token=<site.token>
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby * or
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby * :file=<site.file>[:func=<site.func>][:line=<site.line>]
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby */
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby /* sw:// */
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby topo_fmristr_build(&size, buf, buflen, FM_FMRI_SCHEME_SW,
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby NULL, "://");
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby /* authority, if any */
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby if (anvl != NULL) {
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby nvpair_t *apair;
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby char *aname, *aval;
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby for (apair = nvlist_next_nvpair(anvl, NULL);
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby apair != NULL; apair = nvlist_next_nvpair(anvl, apair)) {
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby if (nvpair_type(apair) != DATA_TYPE_STRING ||
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby nvpair_value_string(apair, &aval) != 0)
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby continue;
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby aname = nvpair_name(apair);
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby topo_fmristr_build(&size, buf, buflen, ":", NULL, NULL);
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby topo_fmristr_build(&size, buf, buflen, "=",
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby aname, aval);
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby }
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby }
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby /* separating slash */
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby topo_fmristr_build(&size, buf, buflen, "/", NULL, NULL);
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby /* :root=... */
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby if (root) {
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby topo_fmristr_build(&size, buf, buflen, root,
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby ":" FM_FMRI_SW_OBJ_ROOT "=", NULL);
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby }
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby /* :path=... */
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby topo_fmristr_build(&size, buf, buflen, path,
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby ":" FM_FMRI_SW_OBJ_PATH "=", NULL);
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby if (token) {
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby /* #:token=... */
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby topo_fmristr_build(&size, buf, buflen, token,
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby "#:" FM_FMRI_SW_SITE_TOKEN "=", NULL);
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby } else if (file) {
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby /* #:file=... */
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby topo_fmristr_build(&size, buf, buflen, file,
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby "#:" FM_FMRI_SW_SITE_FILE "=", NULL);
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby /* :func=... */
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby if (func) {
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby topo_fmristr_build(&size, buf, buflen, func,
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby ":" FM_FMRI_SW_SITE_FUNC "=", NULL);
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby }
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby /* :line=... */
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby if (linevalid) {
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby if (pass == 1)
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby (void) snprintf(linebuf, sizeof (linebuf),
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby "%lld", line);
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby topo_fmristr_build(&size, buf, buflen, linebuf,
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby ":" FM_FMRI_SW_SITE_LINE "=", NULL);
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby }
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby }
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby if (buf == NULL) {
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby if ((buf = topo_mod_alloc(mod, size + 1)) == NULL)
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby return (topo_mod_seterrno(mod, EMOD_NOMEM));
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby buflen = size + 1;
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby size = 0;
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby pass = 2;
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby goto again;
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby }
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby /*
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby * Construct the nvlist to return as the result.
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby */
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby if (topo_mod_nvalloc(mod, &fmristr, NV_UNIQUE_NAME) != 0) {
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby topo_mod_strfree(mod, buf);
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby return (topo_mod_seterrno(mod, EMOD_NOMEM));
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby }
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby if (nvlist_add_string(fmristr, "fmri-string", buf) != 0) {
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby topo_mod_strfree(mod, buf);
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby nvlist_free(fmristr);
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby return (topo_mod_seterrno(mod, EMOD_NOMEM));
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby }
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby topo_mod_strfree(mod, buf);
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby *out = fmristr;
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby return (0);
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby}