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 /* 23 * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 #include <errno.h> 30 #include <kstat.h> 31 #include <limits.h> 32 #include <strings.h> 33 #include <unistd.h> 34 #include <fm/topo_mod.h> 35 #include <sys/fm/protocol.h> 36 37 #include <topo_error.h> 38 39 static int mem_enum(topo_mod_t *, tnode_t *, const char *, topo_instance_t, 40 topo_instance_t, void *); 41 static void mem_release(topo_mod_t *, tnode_t *); 42 static int mem_nvl2str(topo_mod_t *, tnode_t *, topo_version_t, nvlist_t *, 43 nvlist_t **); 44 static int mem_str2nvl(topo_mod_t *, tnode_t *, topo_version_t, nvlist_t *, 45 nvlist_t **); 46 static int mem_present(topo_mod_t *, tnode_t *, topo_version_t, nvlist_t *, 47 nvlist_t **); 48 static int mem_contains(topo_mod_t *, tnode_t *, topo_version_t, nvlist_t *, 49 nvlist_t **); 50 static int mem_unusable(topo_mod_t *, tnode_t *, topo_version_t, nvlist_t *, 51 nvlist_t **); 52 static int mem_expand(topo_mod_t *, tnode_t *, topo_version_t, nvlist_t *, 53 nvlist_t **); 54 55 #define MEM_VERSION TOPO_VERSION 56 57 static const topo_method_t mem_methods[] = { 58 { TOPO_METH_NVL2STR, TOPO_METH_NVL2STR_DESC, TOPO_METH_NVL2STR_VERSION, 59 TOPO_STABILITY_INTERNAL, mem_nvl2str }, 60 { TOPO_METH_STR2NVL, TOPO_METH_STR2NVL_DESC, TOPO_METH_STR2NVL_VERSION, 61 TOPO_STABILITY_INTERNAL, mem_str2nvl }, 62 { TOPO_METH_PRESENT, TOPO_METH_PRESENT_DESC, TOPO_METH_PRESENT_VERSION, 63 TOPO_STABILITY_INTERNAL, mem_present }, 64 { TOPO_METH_CONTAINS, TOPO_METH_CONTAINS_DESC, 65 TOPO_METH_CONTAINS_VERSION, TOPO_STABILITY_INTERNAL, mem_contains }, 66 { TOPO_METH_UNUSABLE, TOPO_METH_UNUSABLE_DESC, 67 TOPO_METH_UNUSABLE_VERSION, TOPO_STABILITY_INTERNAL, mem_unusable }, 68 { TOPO_METH_EXPAND, TOPO_METH_UNUSABLE_DESC, 69 TOPO_METH_EXPAND_VERSION, TOPO_STABILITY_INTERNAL, mem_expand }, 70 { NULL } 71 }; 72 73 static const topo_modinfo_t mem_info = 74 { "mem", MEM_VERSION, mem_enum, mem_release }; 75 76 void 77 mem_init(topo_mod_t *mod) 78 { 79 80 topo_mod_setdebug(mod, TOPO_DBG_ALL); 81 topo_mod_dprintf(mod, "initializing mem builtin\n"); 82 83 if (topo_mod_register(mod, &mem_info, NULL) != 0) { 84 topo_mod_dprintf(mod, "failed to register mem_info: " 85 "%s\n", topo_mod_errmsg(mod)); 86 return; 87 } 88 } 89 90 void 91 mem_fini(topo_mod_t *mod) 92 { 93 topo_mod_unregister(mod); 94 } 95 96 /*ARGSUSED*/ 97 static int 98 mem_enum(topo_mod_t *mod, tnode_t *pnode, const char *name, 99 topo_instance_t min, topo_instance_t max, void *arg) 100 { 101 (void) topo_method_register(mod, pnode, mem_methods); 102 103 return (0); 104 } 105 106 static void 107 mem_release(topo_mod_t *mod, tnode_t *node) 108 { 109 topo_method_unregister_all(mod, node); 110 } 111 112 /*ARGSUSED*/ 113 static int 114 mem_nvl2str(topo_mod_t *mod, tnode_t *node, topo_version_t version, 115 nvlist_t *in, nvlist_t **out) 116 { 117 const char *format; 118 nvlist_t *nvl; 119 uint64_t val; 120 char *buf, *unum; 121 size_t len; 122 int err; 123 124 if (topo_mod_nvalloc(mod, &nvl, NV_UNIQUE_NAME) != 0) 125 return (topo_mod_seterrno(mod, EMOD_FMRI_NVL)); 126 127 if (nvlist_lookup_string(in, FM_FMRI_MEM_UNUM, &unum) != 0) { 128 nvlist_free(nvl); 129 return (topo_mod_seterrno(mod, EMOD_FMRI_NVL)); 130 } 131 132 /* 133 * If we have a DIMM offset, include it in the string. If we have a 134 * PA then use that. Otherwise just format the unum element. 135 */ 136 if (nvlist_lookup_uint64(nvl, FM_FMRI_MEM_OFFSET, &val) == 0) { 137 format = FM_FMRI_SCHEME_MEM ":///%1$s/" 138 FM_FMRI_MEM_OFFSET "=%2$llx"; 139 } else if (nvlist_lookup_uint64(nvl, FM_FMRI_MEM_PHYSADDR, &val) == 0) { 140 format = FM_FMRI_SCHEME_MEM ":///%1$s/" 141 FM_FMRI_MEM_PHYSADDR "=%2$llx"; 142 } else 143 format = FM_FMRI_SCHEME_MEM ":///" "%1$s"; 144 145 /* 146 * If we have a well-formed unum we step over the hc:/// prefix 147 */ 148 if (strncmp(unum, "hc:///", 6) == 0) 149 unum += 6; 150 151 len = snprintf(NULL, 0, format, unum, val) + 1; 152 buf = topo_mod_zalloc(mod, len); 153 154 if (buf == NULL) { 155 nvlist_free(nvl); 156 return (topo_mod_seterrno(mod, EMOD_NOMEM)); 157 } 158 159 (void) snprintf(buf, len, format, unum, val); 160 err = nvlist_add_string(nvl, "fmri-string", buf); 161 topo_mod_free(mod, buf, len); 162 163 if (err != 0) { 164 nvlist_free(nvl); 165 return (topo_mod_seterrno(mod, EMOD_FMRI_NVL)); 166 } 167 168 *out = nvl; 169 return (0); 170 } 171 172 /*ARGSUSED*/ 173 static int 174 mem_str2nvl(topo_mod_t *mod, tnode_t *node, topo_version_t version, 175 nvlist_t *in, nvlist_t **out) 176 { 177 return (-1); 178 } 179 180 /*ARGSUSED*/ 181 static int 182 mem_present(topo_mod_t *mod, tnode_t *node, topo_version_t version, 183 nvlist_t *in, nvlist_t **out) 184 { 185 return (-1); 186 } 187 188 /*ARGSUSED*/ 189 static int 190 mem_contains(topo_mod_t *mod, tnode_t *node, topo_version_t version, 191 nvlist_t *in, nvlist_t **out) 192 { 193 return (-1); 194 } 195 196 /*ARGSUSED*/ 197 static int 198 mem_unusable(topo_mod_t *mod, tnode_t *node, topo_version_t version, 199 nvlist_t *in, nvlist_t **out) 200 { 201 return (-1); 202 } 203 204 /*ARGSUSED*/ 205 static int 206 mem_expand(topo_mod_t *mod, tnode_t *node, topo_version_t version, 207 nvlist_t *in, nvlist_t **out) 208 { 209 return (-1); 210 } 211