1 /* 2 * 3 * CDDL HEADER START 4 * 5 * The contents of this file are subject to the terms of the 6 * Common Development and Distribution License (the "License"). 7 * You may not use this file except in compliance with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 23 /* 24 * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. 25 */ 26 27 28 #include <stdio.h> 29 #include <stdlib.h> 30 #include <string.h> 31 #include <errno.h> 32 #include <ctype.h> 33 #include <alloca.h> 34 #include <limits.h> 35 #include <fm/topo_mod.h> 36 #include <sys/param.h> 37 #include <sys/systeminfo.h> 38 #include <sys/fm/protocol.h> 39 #include <sys/stat.h> 40 41 #include <topo_method.h> 42 #include <topo_subr.h> 43 #include <fmd.h> 44 45 static int fmd_enum(topo_mod_t *, tnode_t *, const char *, topo_instance_t, 46 topo_instance_t, void *, void *); 47 static void fmd_release(topo_mod_t *, tnode_t *); 48 static int fmd_fmri_nvl2str(topo_mod_t *, tnode_t *, topo_version_t, 49 nvlist_t *, nvlist_t **); 50 51 const topo_method_t fmd_methods[] = { 52 { TOPO_METH_NVL2STR, TOPO_METH_NVL2STR_DESC, TOPO_METH_NVL2STR_VERSION, 53 TOPO_STABILITY_INTERNAL, fmd_fmri_nvl2str }, 54 { NULL } 55 }; 56 57 static const topo_modops_t fmd_ops = 58 { fmd_enum, fmd_release }; 59 static const topo_modinfo_t fmd_info = 60 { FMD, FM_FMRI_SCHEME_FMD, FMD_VERSION, &fmd_ops }; 61 62 int 63 fmd_init(topo_mod_t *mod, topo_version_t version) 64 { 65 /* 66 * Turn on module debugging output 67 */ 68 if (getenv("TOPOFMDDEBUG")) 69 topo_mod_setdebug(mod); 70 71 topo_mod_dprintf(mod, "initializing fmd builtin\n"); 72 73 if (version != FMD_VERSION) 74 return (topo_mod_seterrno(mod, EMOD_VER_NEW)); 75 76 if (topo_mod_register(mod, &fmd_info, TOPO_VERSION) != 0) { 77 topo_mod_dprintf(mod, "failed to register fmd: " 78 "%s\n", topo_mod_errmsg(mod)); 79 return (-1); /* mod errno already set */ 80 } 81 82 return (0); 83 } 84 85 void 86 fmd_fini(topo_mod_t *mod) 87 { 88 topo_mod_unregister(mod); 89 } 90 91 92 /*ARGSUSED*/ 93 int 94 fmd_enum(topo_mod_t *mod, tnode_t *pnode, const char *name, topo_instance_t min, 95 topo_instance_t max, void *notused1, void *notused2) 96 { 97 /* 98 * Methods are registered, but there is no enumeration. Should 99 * enumeration be added be sure to cater for global vs non-global 100 * zones. 101 */ 102 (void) topo_method_register(mod, pnode, fmd_methods); 103 return (0); 104 } 105 106 /*ARGSUSED*/ 107 static void 108 fmd_release(topo_mod_t *mp, tnode_t *node) 109 { 110 topo_method_unregister_all(mp, node); 111 } 112 113 static ssize_t 114 fmri_nvl2str(nvlist_t *nvl, char *buf, size_t buflen) 115 { 116 char *name; 117 118 if (nvlist_lookup_string(nvl, FM_FMRI_FMD_NAME, &name) != 0) 119 return (0); 120 121 return (snprintf(buf, buflen, 122 "%s:///module/%s", FM_FMRI_SCHEME_FMD, name)); 123 } 124 125 /*ARGSUSED*/ 126 static int 127 fmd_fmri_nvl2str(topo_mod_t *mod, tnode_t *node, topo_version_t version, 128 nvlist_t *nvl, nvlist_t **out) 129 { 130 ssize_t len; 131 char *name = NULL; 132 nvlist_t *fmristr; 133 134 if (version > TOPO_METH_NVL2STR_VERSION) 135 return (topo_mod_seterrno(mod, EMOD_VER_NEW)); 136 137 if ((len = fmri_nvl2str(nvl, NULL, 0)) == 0 || 138 (name = topo_mod_alloc(mod, len + 1)) == NULL || 139 fmri_nvl2str(nvl, name, len + 1) == 0) { 140 if (name != NULL) 141 topo_mod_free(mod, name, len + 1); 142 return (topo_mod_seterrno(mod, EMOD_FMRI_NVL)); 143 } 144 145 if (topo_mod_nvalloc(mod, &fmristr, NV_UNIQUE_NAME) != 0) { 146 topo_mod_free(mod, name, len + 1); 147 return (topo_mod_seterrno(mod, EMOD_FMRI_NVL)); 148 } 149 if (nvlist_add_string(fmristr, "fmri-string", name) != 0) { 150 topo_mod_free(mod, name, len + 1); 151 nvlist_free(fmristr); 152 return (topo_mod_seterrno(mod, EMOD_FMRI_NVL)); 153 } 154 topo_mod_free(mod, name, len + 1); 155 *out = fmristr; 156 157 return (0); 158 } 159