xref: /illumos-gate/usr/src/lib/fm/topo/modules/common/ipmi/ipmi_methods.c (revision f998c95e3b7029fe5f7542e115f7474ddb8024d7)
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 2008 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 <stdio.h>
30 #include <stdlib.h>
31 #include <stdarg.h>
32 #include <string.h>
33 #include <strings.h>
34 #include <libnvpair.h>
35 #include <sys/types.h>
36 #include <fm/topo_mod.h>
37 
38 #define	BUFSZ	128
39 
40 static char *
41 get_fmtstr(topo_mod_t *mod, nvlist_t *in)
42 {
43 	char *fmtstr;
44 	nvlist_t *args;
45 	int ret;
46 
47 	topo_mod_dprintf(mod, "get_fmtstr() called\n");
48 
49 	if ((ret = nvlist_lookup_nvlist(in, TOPO_PROP_ARGS, &args)) != 0) {
50 		topo_mod_dprintf(mod, "Failed to lookup 'args' list (%s)\n",
51 		    strerror(ret));
52 		(void) topo_mod_seterrno(mod, EMOD_NVL_INVAL);
53 		return (NULL);
54 	}
55 	if ((ret = nvlist_lookup_string(args, "format", &fmtstr)) != 0) {
56 		topo_mod_dprintf(mod, "Failed to lookup 'format' arg (%s)\n",
57 		    strerror(ret));
58 		(void) topo_mod_seterrno(mod, EMOD_NVL_INVAL);
59 		return (NULL);
60 	}
61 	return (fmtstr);
62 }
63 
64 static int
65 store_prop_val(topo_mod_t *mod, void *buf, char *propname, topo_type_t type,
66     nvlist_t **out)
67 {
68 	if (topo_mod_nvalloc(mod, out, NV_UNIQUE_NAME) != 0) {
69 		topo_mod_dprintf(mod, "Failed to allocate 'out' nvlist\n");
70 		return (topo_mod_seterrno(mod, EMOD_NOMEM));
71 	}
72 	if (nvlist_add_string(*out, TOPO_PROP_VAL_NAME, propname) != 0) {
73 		topo_mod_dprintf(mod, "Failed to set '%s'\n",
74 		    TOPO_PROP_VAL_NAME);
75 		nvlist_free(*out);
76 		return (topo_mod_seterrno(mod, EMOD_NVL_INVAL));
77 	}
78 	if (nvlist_add_uint32(*out, TOPO_PROP_VAL_TYPE, type)
79 	    != 0) {
80 		topo_mod_dprintf(mod, "Failed to set '%s'\n",
81 		    TOPO_PROP_VAL_TYPE);
82 		nvlist_free(*out);
83 		return (topo_mod_seterrno(mod, EMOD_NVL_INVAL));
84 	}
85 	if (type == TOPO_TYPE_STRING) {
86 		if (nvlist_add_string(*out, TOPO_PROP_VAL_VAL, (char *)buf)
87 		    != 0) {
88 			topo_mod_dprintf(mod, "Failed to set '%s'\n",
89 			    TOPO_PROP_VAL_VAL);
90 			nvlist_free(*out);
91 			return (topo_mod_seterrno(mod, EMOD_NVL_INVAL));
92 		}
93 	} else if (type == TOPO_TYPE_FMRI)
94 		if (nvlist_add_nvlist(*out, TOPO_PROP_VAL_VAL, (nvlist_t *)buf)
95 		    != 0) {
96 			topo_mod_dprintf(mod, "Failed to set '%s'\n",
97 			    TOPO_PROP_VAL_VAL);
98 			nvlist_free(*out);
99 			return (topo_mod_seterrno(mod, EMOD_NVL_INVAL));
100 		}
101 	return (0);
102 }
103 
104 /*
105  * This is a somewhat generic property method for labelling the PSU and fan
106  * FRU's that we're enumerating.  It takes the following three arguments:
107  *
108  * format:	a string containing a printf-like format with a two %d tokens
109  *              for the cpu and dimm slot label numbers, which this method
110  *              computes
111  *
112  *              i.e.: Fan %d
113  *
114  * offset:      a numeric offset that we'll number the FRU's from.  This is to
115  *              allow for the fact that some systems may number the FRU's
116  *              from zero while others may start from one
117  */
118 /* ARGSUSED */
119 int
120 ipmi_fru_label(topo_mod_t *mod, tnode_t *node, topo_version_t vers,
121     nvlist_t *in, nvlist_t **out)
122 {
123 	char *fmtstr, buf[BUFSZ];
124 	int ret;
125 	uint32_t offset;
126 	nvlist_t *args;
127 
128 	topo_mod_dprintf(mod, "ipmi_fru_label() called\n");
129 	if ((ret = nvlist_lookup_nvlist(in, TOPO_PROP_ARGS, &args)) != 0) {
130 		topo_mod_dprintf(mod, "Failed to lookup 'args' list (%s)\n",
131 		    strerror(ret));
132 		return (topo_mod_seterrno(mod, EMOD_NVL_INVAL));
133 	}
134 	if ((ret = nvlist_lookup_uint32(args, "offset", &offset)) != 0) {
135 		topo_mod_dprintf(mod, "Failed to lookup 'offset' arg (%s)\n",
136 		    strerror(ret));
137 		return (topo_mod_seterrno(mod, EMOD_NVL_INVAL));
138 	}
139 
140 	if ((fmtstr = get_fmtstr(mod, in)) == NULL) {
141 		topo_mod_dprintf(mod, "Failed to retrieve 'format' arg\n");
142 		/* topo errno already set */
143 		return (-1);
144 	}
145 
146 	/* LINTED: E_SEC_PRINTF_VAR_FMT */
147 	(void) snprintf(buf, BUFSZ, fmtstr,
148 	    (topo_node_instance(node) + offset));
149 
150 	if (store_prop_val(mod, (void *)buf, "label", TOPO_TYPE_STRING, out)
151 	    != 0) {
152 		topo_mod_dprintf(mod, "Failed to set label\n");
153 		/* topo errno already set */
154 		return (-1);
155 	}
156 
157 	return (0);
158 }
159 /*
160  * This is a somewhat generic property method for attaching a FRU fmri onto
161  * a power supply or fan based on the assumption that the FRU will either be
162  * the fan/psu itself or the parent node.
163  *
164  * entity:	either "self" or "parent"
165  */
166 /* ARGSUSED */
167 int
168 ipmi_fru_fmri(topo_mod_t *mod, tnode_t *node, topo_version_t vers,
169     nvlist_t *in, nvlist_t **out)
170 {
171 	char *entity;
172 	int ret, err;
173 	nvlist_t *args, *fru;
174 
175 	topo_mod_dprintf(mod, "ipmi_fru_fmri() called\n");
176 	if ((ret = nvlist_lookup_nvlist(in, TOPO_PROP_ARGS, &args)) != 0) {
177 		topo_mod_dprintf(mod, "Failed to lookup 'args' list (%s)\n",
178 		    strerror(ret));
179 		return (topo_mod_seterrno(mod, EMOD_NVL_INVAL));
180 	}
181 	if ((ret = nvlist_lookup_string(args, "entity", &entity)) != 0) {
182 		topo_mod_dprintf(mod, "Failed to lookup 'entity' arg (%s)\n",
183 		    strerror(ret));
184 		return (topo_mod_seterrno(mod, EMOD_NVL_INVAL));
185 	}
186 
187 	if (strcasecmp(entity, "self") == 0) {
188 		if (topo_node_resource(node, &fru, &err) != 0)
189 			return (-1);
190 	} else if (strcasecmp(entity, "parent") == 0) {
191 		if (topo_node_resource(topo_node_parent(node), &fru, &err) != 0)
192 			return (-1);
193 	} else {
194 		topo_mod_dprintf(mod, "Invalid 'entity' value\n");
195 		return (topo_mod_seterrno(mod, EMOD_NVL_INVAL));
196 	}
197 
198 	if (store_prop_val(mod, (void *)fru, "FRU", TOPO_TYPE_FMRI, out) != 0) {
199 		nvlist_free(fru);
200 		topo_mod_dprintf(mod, "Failed to set FRU\n");
201 		/* topo errno already set */
202 		return (-1);
203 	}
204 
205 	nvlist_free(fru);
206 
207 	return (0);
208 }
209