7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi/*
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * CDDL HEADER START
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi *
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * The contents of this file are subject to the terms of the
5f25dc2aa25a1742246574b0899ea47f941f0fbcgavinm * Common Development and Distribution License (the "License").
5f25dc2aa25a1742246574b0899ea47f941f0fbcgavinm * You may not use this file except in compliance with the License.
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi *
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * or http://www.opensolaris.org/os/licensing.
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * See the License for the specific language governing permissions
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * and limitations under the License.
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi *
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * When distributing Covered Code, include this CDDL HEADER in each
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * If applicable, add the following below this CDDL HEADER, with the
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * fields enclosed by brackets "[]" replaced with your own identifying
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * information: Portions Copyright [yyyy] [name of copyright owner]
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi *
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * CDDL HEADER END
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi */
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi/*
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi */
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
e5ba14ff435beeefdaa2e6649e175c74afe02c76stephh#include <ctype.h>
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi#include <errno.h>
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi#include <kstat.h>
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi#include <limits.h>
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi#include <strings.h>
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi#include <unistd.h>
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby#include <zone.h>
70818f5837509317d1f5dac4d82d7b5a2d547c29tsien#include <topo_error.h>
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi#include <fm/topo_mod.h>
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi#include <sys/fm/protocol.h>
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi#include <topo_method.h>
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi#include <mem.h>
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
70818f5837509317d1f5dac4d82d7b5a2d547c29tsien/*
70818f5837509317d1f5dac4d82d7b5a2d547c29tsien * platform specific mem module
70818f5837509317d1f5dac4d82d7b5a2d547c29tsien */
70818f5837509317d1f5dac4d82d7b5a2d547c29tsien#define PLATFORM_MEM_VERSION MEM_VERSION
70818f5837509317d1f5dac4d82d7b5a2d547c29tsien#define PLATFORM_MEM_NAME "platform-mem"
70818f5837509317d1f5dac4d82d7b5a2d547c29tsien
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindistatic int mem_enum(topo_mod_t *, tnode_t *, const char *, topo_instance_t,
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi topo_instance_t, void *, void *);
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindistatic void mem_release(topo_mod_t *, tnode_t *);
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindistatic int mem_nvl2str(topo_mod_t *, tnode_t *, topo_version_t, nvlist_t *,
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi nvlist_t **);
0eb822a1c0c2bea495647510b75f77f0e57633ebcindistatic int mem_fmri_create(topo_mod_t *, tnode_t *, topo_version_t,
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi nvlist_t *, nvlist_t **);
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindistatic const topo_method_t mem_methods[] = {
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi { TOPO_METH_NVL2STR, TOPO_METH_NVL2STR_DESC, TOPO_METH_NVL2STR_VERSION,
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi TOPO_STABILITY_INTERNAL, mem_nvl2str },
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi { TOPO_METH_FMRI, TOPO_METH_FMRI_DESC, TOPO_METH_FMRI_VERSION,
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi TOPO_STABILITY_INTERNAL, mem_fmri_create },
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi { NULL }
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi};
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
0eb822a1c0c2bea495647510b75f77f0e57633ebcindistatic const topo_modops_t mem_ops =
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi { mem_enum, mem_release };
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindistatic const topo_modinfo_t mem_info =
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi { "mem", FM_FMRI_SCHEME_MEM, MEM_VERSION, &mem_ops };
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
0eb822a1c0c2bea495647510b75f77f0e57633ebcindiint
0eb822a1c0c2bea495647510b75f77f0e57633ebcindimem_init(topo_mod_t *mod, topo_version_t version)
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi{
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi topo_mod_setdebug(mod);
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi topo_mod_dprintf(mod, "initializing mem builtin\n");
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi if (version != MEM_VERSION)
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi return (topo_mod_seterrno(mod, EMOD_VER_NEW));
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi if (topo_mod_register(mod, &mem_info, TOPO_VERSION) != 0) {
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi topo_mod_dprintf(mod, "failed to register mem_info: "
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi "%s\n", topo_mod_errmsg(mod));
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi return (-1); /* mod errno already set */
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi }
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi return (0);
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi}
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindivoid
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindimem_fini(topo_mod_t *mod)
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi{
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi topo_mod_unregister(mod);
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi}
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi/*ARGSUSED*/
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindistatic int
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindimem_enum(topo_mod_t *mod, tnode_t *pnode, const char *name,
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi topo_instance_t min, topo_instance_t max, void *notused1, void *notused2)
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi{
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby int isglobal = (getzoneid() == GLOBAL_ZONEID);
70818f5837509317d1f5dac4d82d7b5a2d547c29tsien topo_mod_t *nmp;
70818f5837509317d1f5dac4d82d7b5a2d547c29tsien
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby if (isglobal && (nmp = topo_mod_load(mod, PLATFORM_MEM_NAME,
70818f5837509317d1f5dac4d82d7b5a2d547c29tsien PLATFORM_MEM_VERSION)) == NULL) {
70818f5837509317d1f5dac4d82d7b5a2d547c29tsien if (topo_mod_errno(mod) == ETOPO_MOD_NOENT) {
70818f5837509317d1f5dac4d82d7b5a2d547c29tsien /*
70818f5837509317d1f5dac4d82d7b5a2d547c29tsien * There is no platform specific mem module.
70818f5837509317d1f5dac4d82d7b5a2d547c29tsien */
70818f5837509317d1f5dac4d82d7b5a2d547c29tsien (void) topo_method_register(mod, pnode, mem_methods);
70818f5837509317d1f5dac4d82d7b5a2d547c29tsien return (0);
70818f5837509317d1f5dac4d82d7b5a2d547c29tsien } else {
70818f5837509317d1f5dac4d82d7b5a2d547c29tsien /* Fail to load the module */
70818f5837509317d1f5dac4d82d7b5a2d547c29tsien topo_mod_dprintf(mod, "Failed to load module %s: %s",
70818f5837509317d1f5dac4d82d7b5a2d547c29tsien PLATFORM_MEM_NAME, topo_mod_errmsg(mod));
70818f5837509317d1f5dac4d82d7b5a2d547c29tsien return (-1);
70818f5837509317d1f5dac4d82d7b5a2d547c29tsien }
70818f5837509317d1f5dac4d82d7b5a2d547c29tsien }
70818f5837509317d1f5dac4d82d7b5a2d547c29tsien
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby if (isglobal && topo_mod_enumerate(nmp, pnode, PLATFORM_MEM_NAME, name,
70818f5837509317d1f5dac4d82d7b5a2d547c29tsien min, max, NULL) < 0) {
70818f5837509317d1f5dac4d82d7b5a2d547c29tsien topo_mod_dprintf(mod, "%s failed to enumerate: %s",
70818f5837509317d1f5dac4d82d7b5a2d547c29tsien PLATFORM_MEM_NAME, topo_mod_errmsg(mod));
70818f5837509317d1f5dac4d82d7b5a2d547c29tsien return (-1);
70818f5837509317d1f5dac4d82d7b5a2d547c29tsien }
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi (void) topo_method_register(mod, pnode, mem_methods);
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi return (0);
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi}
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindistatic void
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindimem_release(topo_mod_t *mod, tnode_t *node)
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi{
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi topo_method_unregister_all(mod, node);
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi}
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
e5ba14ff435beeefdaa2e6649e175c74afe02c76stephh/*
e5ba14ff435beeefdaa2e6649e175c74afe02c76stephh * Convert an input string to a URI escaped string and return the new string.
e5ba14ff435beeefdaa2e6649e175c74afe02c76stephh * RFC2396 Section 2.4 says that data must be escaped if it does not have a
e5ba14ff435beeefdaa2e6649e175c74afe02c76stephh * representation using an unreserved character, where an unreserved character
e5ba14ff435beeefdaa2e6649e175c74afe02c76stephh * is one that is either alphanumeric or one of the marks defined in S2.3.
e5ba14ff435beeefdaa2e6649e175c74afe02c76stephh */
e5ba14ff435beeefdaa2e6649e175c74afe02c76stephhstatic size_t
e5ba14ff435beeefdaa2e6649e175c74afe02c76stephhmem_fmri_uriescape(const char *s, const char *xmark, char *buf, size_t len)
e5ba14ff435beeefdaa2e6649e175c74afe02c76stephh{
e5ba14ff435beeefdaa2e6649e175c74afe02c76stephh static const char rfc2396_mark[] = "-_.!~*'()";
e5ba14ff435beeefdaa2e6649e175c74afe02c76stephh static const char hex_digits[] = "0123456789ABCDEF";
e5ba14ff435beeefdaa2e6649e175c74afe02c76stephh static const char empty_str[] = "";
e5ba14ff435beeefdaa2e6649e175c74afe02c76stephh
e5ba14ff435beeefdaa2e6649e175c74afe02c76stephh const char *p;
e5ba14ff435beeefdaa2e6649e175c74afe02c76stephh char c, *q;
e5ba14ff435beeefdaa2e6649e175c74afe02c76stephh size_t n = 0;
e5ba14ff435beeefdaa2e6649e175c74afe02c76stephh
e5ba14ff435beeefdaa2e6649e175c74afe02c76stephh if (s == NULL)
e5ba14ff435beeefdaa2e6649e175c74afe02c76stephh s = empty_str;
e5ba14ff435beeefdaa2e6649e175c74afe02c76stephh
e5ba14ff435beeefdaa2e6649e175c74afe02c76stephh if (xmark == NULL)
e5ba14ff435beeefdaa2e6649e175c74afe02c76stephh xmark = empty_str;
e5ba14ff435beeefdaa2e6649e175c74afe02c76stephh
e5ba14ff435beeefdaa2e6649e175c74afe02c76stephh for (p = s; (c = *p) != '\0'; p++) {
e5ba14ff435beeefdaa2e6649e175c74afe02c76stephh if (isalnum(c) || strchr(rfc2396_mark, c) || strchr(xmark, c))
e5ba14ff435beeefdaa2e6649e175c74afe02c76stephh n++; /* represent c as itself */
e5ba14ff435beeefdaa2e6649e175c74afe02c76stephh else
e5ba14ff435beeefdaa2e6649e175c74afe02c76stephh n += 3; /* represent c as escape */
e5ba14ff435beeefdaa2e6649e175c74afe02c76stephh }
e5ba14ff435beeefdaa2e6649e175c74afe02c76stephh
e5ba14ff435beeefdaa2e6649e175c74afe02c76stephh if (buf == NULL)
e5ba14ff435beeefdaa2e6649e175c74afe02c76stephh return (n);
e5ba14ff435beeefdaa2e6649e175c74afe02c76stephh
e5ba14ff435beeefdaa2e6649e175c74afe02c76stephh for (p = s, q = buf; (c = *p) != '\0' && q < buf + len; p++) {
e5ba14ff435beeefdaa2e6649e175c74afe02c76stephh if (isalnum(c) || strchr(rfc2396_mark, c) || strchr(xmark, c)) {
e5ba14ff435beeefdaa2e6649e175c74afe02c76stephh *q++ = c;
e5ba14ff435beeefdaa2e6649e175c74afe02c76stephh } else {
e5ba14ff435beeefdaa2e6649e175c74afe02c76stephh *q++ = '%';
e5ba14ff435beeefdaa2e6649e175c74afe02c76stephh *q++ = hex_digits[((uchar_t)c & 0xf0) >> 4];
e5ba14ff435beeefdaa2e6649e175c74afe02c76stephh *q++ = hex_digits[(uchar_t)c & 0xf];
e5ba14ff435beeefdaa2e6649e175c74afe02c76stephh }
e5ba14ff435beeefdaa2e6649e175c74afe02c76stephh }
e5ba14ff435beeefdaa2e6649e175c74afe02c76stephh
e5ba14ff435beeefdaa2e6649e175c74afe02c76stephh if (q == buf + len)
e5ba14ff435beeefdaa2e6649e175c74afe02c76stephh q--; /* len is too small: truncate output string */
e5ba14ff435beeefdaa2e6649e175c74afe02c76stephh
e5ba14ff435beeefdaa2e6649e175c74afe02c76stephh *q = '\0';
e5ba14ff435beeefdaa2e6649e175c74afe02c76stephh return (n);
e5ba14ff435beeefdaa2e6649e175c74afe02c76stephh}
e5ba14ff435beeefdaa2e6649e175c74afe02c76stephh
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi/*ARGSUSED*/
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindistatic int
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindimem_nvl2str(topo_mod_t *mod, tnode_t *node, topo_version_t version,
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi nvlist_t *in, nvlist_t **out)
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi{
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi const char *format;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi nvlist_t *nvl;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi uint64_t val;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi char *buf, *unum;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi size_t len;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi int err;
e5ba14ff435beeefdaa2e6649e175c74afe02c76stephh char *preunum, *escunum, *prefix;
e5ba14ff435beeefdaa2e6649e175c74afe02c76stephh ssize_t presz;
e5ba14ff435beeefdaa2e6649e175c74afe02c76stephh int i;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi if (topo_mod_nvalloc(mod, &nvl, NV_UNIQUE_NAME) != 0)
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi return (topo_mod_seterrno(mod, EMOD_FMRI_NVL));
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi if (nvlist_lookup_string(in, FM_FMRI_MEM_UNUM, &unum) != 0) {
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi nvlist_free(nvl);
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi return (topo_mod_seterrno(mod, EMOD_FMRI_NVL));
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi }
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi /*
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * If we have a DIMM offset, include it in the string. If we have a
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * PA then use that. Otherwise just format the unum element.
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi */
9dd0f810214fdc8e1af881a9a5c4b6927629ff9ecindi if (nvlist_lookup_uint64(in, FM_FMRI_MEM_OFFSET, &val) == 0) {
e5ba14ff435beeefdaa2e6649e175c74afe02c76stephh format = FM_FMRI_SCHEME_MEM ":///%1$s%2$s/"
e5ba14ff435beeefdaa2e6649e175c74afe02c76stephh FM_FMRI_MEM_OFFSET "=%3$llx";
9dd0f810214fdc8e1af881a9a5c4b6927629ff9ecindi } else if (nvlist_lookup_uint64(in, FM_FMRI_MEM_PHYSADDR, &val) == 0) {
e5ba14ff435beeefdaa2e6649e175c74afe02c76stephh format = FM_FMRI_SCHEME_MEM ":///%1$s%2$s/"
e5ba14ff435beeefdaa2e6649e175c74afe02c76stephh FM_FMRI_MEM_PHYSADDR "=%3$llx";
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi } else
e5ba14ff435beeefdaa2e6649e175c74afe02c76stephh format = FM_FMRI_SCHEME_MEM ":///%1$s%2$s";
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
8a40a695ee676a322b094e9afe5375567bfb51e3gavinm /*
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi * If we have a well-formed unum we step over the hc:// and
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi * authority prefix
8a40a695ee676a322b094e9afe5375567bfb51e3gavinm */
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi if (strncmp(unum, "hc://", 5) == 0) {
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi unum += 5;
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi unum = strchr(unum, '/');
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi ++unum;
e5ba14ff435beeefdaa2e6649e175c74afe02c76stephh prefix = "";
e5ba14ff435beeefdaa2e6649e175c74afe02c76stephh escunum = unum;
e5ba14ff435beeefdaa2e6649e175c74afe02c76stephh } else {
e5ba14ff435beeefdaa2e6649e175c74afe02c76stephh prefix = FM_FMRI_MEM_UNUM "=";
e5ba14ff435beeefdaa2e6649e175c74afe02c76stephh preunum = topo_mod_strdup(mod, unum);
e5ba14ff435beeefdaa2e6649e175c74afe02c76stephh presz = strlen(preunum) + 1;
e5ba14ff435beeefdaa2e6649e175c74afe02c76stephh
e5ba14ff435beeefdaa2e6649e175c74afe02c76stephh for (i = 0; i < presz - 1; i++) {
e5ba14ff435beeefdaa2e6649e175c74afe02c76stephh if (preunum[i] == ':' && preunum[i + 1] == ' ') {
e5ba14ff435beeefdaa2e6649e175c74afe02c76stephh bcopy(preunum + i + 2, preunum + i + 1,
e5ba14ff435beeefdaa2e6649e175c74afe02c76stephh presz - (i + 2));
e5ba14ff435beeefdaa2e6649e175c74afe02c76stephh } else if (preunum[i] == ' ') {
e5ba14ff435beeefdaa2e6649e175c74afe02c76stephh preunum[i] = ',';
e5ba14ff435beeefdaa2e6649e175c74afe02c76stephh }
e5ba14ff435beeefdaa2e6649e175c74afe02c76stephh }
e5ba14ff435beeefdaa2e6649e175c74afe02c76stephh
e5ba14ff435beeefdaa2e6649e175c74afe02c76stephh i = mem_fmri_uriescape(preunum, ":,/", NULL, 0);
e5ba14ff435beeefdaa2e6649e175c74afe02c76stephh escunum = topo_mod_alloc(mod, i + 1);
e5ba14ff435beeefdaa2e6649e175c74afe02c76stephh (void) mem_fmri_uriescape(preunum, ":,/", escunum, i + 1);
e5ba14ff435beeefdaa2e6649e175c74afe02c76stephh topo_mod_free(mod, preunum, presz);
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi }
8a40a695ee676a322b094e9afe5375567bfb51e3gavinm
e5ba14ff435beeefdaa2e6649e175c74afe02c76stephh len = snprintf(NULL, 0, format, prefix, escunum, val) + 1;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi buf = topo_mod_zalloc(mod, len);
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi if (buf == NULL) {
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi nvlist_free(nvl);
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi return (topo_mod_seterrno(mod, EMOD_NOMEM));
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi }
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
e5ba14ff435beeefdaa2e6649e175c74afe02c76stephh (void) snprintf(buf, len, format, prefix, escunum, val);
e5ba14ff435beeefdaa2e6649e175c74afe02c76stephh if (escunum != unum)
e5ba14ff435beeefdaa2e6649e175c74afe02c76stephh topo_mod_strfree(mod, escunum);
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi err = nvlist_add_string(nvl, "fmri-string", buf);
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi topo_mod_free(mod, buf, len);
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi if (err != 0) {
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi nvlist_free(nvl);
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi return (topo_mod_seterrno(mod, EMOD_FMRI_NVL));
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi }
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi *out = nvl;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi return (0);
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi}
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
0eb822a1c0c2bea495647510b75f77f0e57633ebcindistatic nvlist_t *
0eb822a1c0c2bea495647510b75f77f0e57633ebcindimem_fmri(topo_mod_t *mod, uint64_t pa, uint64_t offset, char *unum, int flags)
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi{
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi int err;
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi nvlist_t *asru;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi if (topo_mod_nvalloc(mod, &asru, NV_UNIQUE_NAME) != 0)
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi return (NULL);
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi /*
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi * If we have a well-formed unum we step over the hc:/// and
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi * authority prefix
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi */
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi if (strncmp(unum, "hc://", 5) == 0) {
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi char *tstr;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi tstr = strchr(unum, '/');
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi unum = ++tstr;
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi }
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi err = nvlist_add_uint8(asru, FM_VERSION, FM_MEM_SCHEME_VERSION);
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi err |= nvlist_add_string(asru, FM_FMRI_SCHEME, FM_FMRI_SCHEME_MEM);
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi err |= nvlist_add_string(asru, FM_FMRI_MEM_UNUM, unum);
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi if (flags & TOPO_MEMFMRI_PA)
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi err |= nvlist_add_uint64(asru, FM_FMRI_MEM_PHYSADDR, pa);
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi if (flags & TOPO_MEMFMRI_OFFSET)
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi err |= nvlist_add_uint64(asru, FM_FMRI_MEM_OFFSET, offset);
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi if (err != 0) {
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi nvlist_free(asru);
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi return (NULL);
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi }
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi return (asru);
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi}
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi/*ARGSUSED*/
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindistatic int
0eb822a1c0c2bea495647510b75f77f0e57633ebcindimem_fmri_create(topo_mod_t *mod, tnode_t *node, topo_version_t version,
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi nvlist_t *in, nvlist_t **out)
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi{
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi uint64_t pa = 0, offset = 0;
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi int flags = 0;
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi nvlist_t *asru;
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi char *unum;
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi if (nvlist_lookup_uint64(in, FM_FMRI_MEM_PHYSADDR, &pa) == 0)
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi flags |= TOPO_MEMFMRI_PA;
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi if (nvlist_lookup_uint64(in, FM_FMRI_MEM_OFFSET, &offset) == 0)
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi flags |= TOPO_MEMFMRI_OFFSET;
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi if (nvlist_lookup_string(in, FM_FMRI_MEM_UNUM, &unum) != 0)
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi return (topo_mod_seterrno(mod, EMOD_FMRI_MALFORM));
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi asru = mem_fmri(mod, pa, offset, unum, flags);
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi if (asru == NULL)
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi return (topo_mod_seterrno(mod, EMOD_FMRI_NVL));
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi *out = asru;
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi return (0);
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi}