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 2009 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 /*
28  * Create a generic topology node.
29  */
30 #include <sys/types.h>
31 #include <strings.h>
32 #include <sys/fm/protocol.h>
33 #include <fm/topo_mod.h>
34 #include <fm/topo_hc.h>
35 #include <x86pi_impl.h>
36 
37 #define	_ENUM_NAME	"enum_generic"
38 #define	_FAC_PROV	"fac_prov_ipmi"
39 
40 /*
41  * Create a generic topo node based on the hcfmri strcuture passed in.
42  */
43 int
x86pi_enum_generic(topo_mod_t * mod,x86pi_hcfmri_t * hcfmri,tnode_t * t_bindparent,tnode_t * t_fmriparent,tnode_t ** t_node,int flag)44 x86pi_enum_generic(topo_mod_t *mod, x86pi_hcfmri_t *hcfmri,
45     tnode_t *t_bindparent, tnode_t *t_fmriparent, tnode_t **t_node, int flag)
46 {
47 	int		rv;
48 	int		err;
49 	nvlist_t	*out;
50 	nvlist_t	*fmri;
51 	nvlist_t	*auth;
52 
53 	topo_mod_dprintf(mod, "%s adding entry for type (%s)\n",
54 	    _ENUM_NAME, hcfmri->hc_name);
55 
56 	if (t_bindparent == NULL) {
57 		topo_mod_dprintf(mod,
58 		    "%s called with NULL parent for type %s\n",
59 		    _ENUM_NAME, hcfmri->hc_name);
60 		return (-1);
61 	}
62 
63 	/* Create the FMRI for this node */
64 	auth = topo_mod_auth(mod, t_bindparent);
65 	fmri = topo_mod_hcfmri(mod, t_fmriparent, FM_HC_SCHEME_VERSION,
66 	    hcfmri->hc_name, hcfmri->instance, NULL, auth,
67 	    hcfmri->part_number, hcfmri->version, hcfmri->serial_number);
68 
69 	nvlist_free(auth);
70 
71 	if (fmri == NULL) {
72 		topo_mod_dprintf(mod,
73 		    "%s failed to create %s fmri : %s\n", _ENUM_NAME,
74 		    hcfmri->hc_name, topo_strerror(topo_mod_errno(mod)));
75 		return (-1);
76 	}
77 
78 	rv = topo_node_range_create(mod, t_bindparent, hcfmri->hc_name, 0, 4);
79 	if (rv != 0 && topo_mod_errno(mod) != EMOD_NODE_DUP) {
80 		topo_mod_dprintf(mod, "%s range create failed for node %s\n",
81 		    _ENUM_NAME, hcfmri->hc_name);
82 	}
83 
84 	/* Bind this node to the parent */
85 	*t_node = x86pi_node_bind(mod, t_bindparent, hcfmri, fmri, flag);
86 	nvlist_free(fmri);
87 	if (*t_node == NULL) {
88 		topo_mod_dprintf(mod,
89 		    "%s failed to bind %s node instance %d: %s\n",
90 		    _ENUM_NAME, hcfmri->hc_name, hcfmri->instance,
91 		    topo_strerror(topo_mod_errno(mod)));
92 		return (-1);
93 	}
94 
95 	/* call IPMI facility provider to register fac methods */
96 	if (topo_mod_load(mod, _FAC_PROV, TOPO_VERSION) == NULL) {
97 		topo_mod_dprintf(mod,
98 		    "%s: Failed to load %s module: %s\n", _ENUM_NAME, _FAC_PROV,
99 		    topo_mod_errmsg(mod));
100 		return (-1);
101 	}
102 
103 	rv = topo_mod_enumerate(mod, *t_node, _FAC_PROV, _FAC_PROV, 0, 0, NULL);
104 	if (rv != 0) {
105 		topo_mod_dprintf(mod,
106 		    "%s: %s failed: %s\n", _ENUM_NAME, _FAC_PROV,
107 		    topo_mod_errmsg(mod));
108 		return (-1);
109 	}
110 
111 	/* invoke fac_prov_ipmi_enum method */
112 	if (topo_method_supported(*t_node, TOPO_METH_FAC_ENUM, 0)) {
113 		if (topo_method_invoke(*t_node, TOPO_METH_FAC_ENUM, 0, NULL,
114 		    &out, &err) != 0) {
115 			/* log the error and drive on */
116 			topo_mod_dprintf(mod,
117 			    "%s: TOPO_METH_FAC_ENUM failed\n", _ENUM_NAME);
118 		} else {
119 			fac_done = 1;
120 		}
121 	}
122 
123 	topo_mod_dprintf(mod, "%s added (%s) node\n", _ENUM_NAME,
124 	    topo_node_name(*t_node));
125 
126 	return (0);
127 }
128 
129 
130 tnode_t *
x86pi_node_bind(topo_mod_t * mod,tnode_t * t_parent,x86pi_hcfmri_t * hcfmri,nvlist_t * fmri,int flag)131 x86pi_node_bind(topo_mod_t *mod, tnode_t *t_parent, x86pi_hcfmri_t *hcfmri,
132     nvlist_t *fmri, int flag)
133 {
134 	int	result;
135 	tnode_t	*t_node;
136 	char	*f = "x86pi_node_bind";
137 
138 	if (t_parent == NULL) {
139 		topo_mod_dprintf(mod,
140 		    "%s: NULL parent for %s node instance %d\n",
141 		    f, hcfmri->hc_name, hcfmri->instance);
142 		return (NULL);
143 	}
144 
145 	/* Bind this node to the parent */
146 	t_node = topo_node_bind(mod, t_parent, hcfmri->hc_name,
147 	    hcfmri->instance, fmri);
148 	if (t_node == NULL) {
149 		topo_mod_dprintf(mod,
150 		    "%s: failed to bind %s node instance %d: %s\n",
151 		    f, hcfmri->hc_name, (uint32_t)hcfmri->instance,
152 		    topo_strerror(topo_mod_errno(mod)));
153 		return (NULL);
154 	}
155 	topo_mod_dprintf(mod, "%s: bound %s node instance %d type %s\n",
156 	    f, hcfmri->hc_name, hcfmri->instance, hcfmri->hc_name);
157 
158 	/*
159 	 * We have bound the node.  Now decorate it with an appropriate
160 	 * FRU and label (which may be inherited from the parent).
161 	 */
162 	result = x86pi_set_frufmri(mod, hcfmri, t_parent, t_node, flag);
163 	if (result != 0) {
164 		/*
165 		 * Though we have failed to set the FRU FMRI we still continue.
166 		 * The module errno is set by the called routine, so we report
167 		 * the problem and move on.
168 		 */
169 		topo_mod_dprintf(mod,
170 		    "%s: failed to set FRU FMRI for %s node\n",
171 		    f, hcfmri->hc_name);
172 	}
173 
174 	result = x86pi_set_label(mod, hcfmri->location, hcfmri->hc_name,
175 	    t_node);
176 	if (result != 0) {
177 		/*
178 		 * Though we have failed to set the label, we still continue.
179 		 * The module errno is set by the called routine, so we report
180 		 * the problem and move on.
181 		 */
182 		topo_mod_dprintf(mod, "%s: no label for %s node\n",
183 		    f, hcfmri->hc_name);
184 	}
185 
186 	result = x86pi_set_auth(mod, hcfmri, t_parent, t_node);
187 	if (result != 0) {
188 		/*
189 		 * Though we have failed to set the authority, we still
190 		 * continue. The module errno is set by the called routine, so
191 		 * we report the problem and move on.
192 		 */
193 		topo_mod_dprintf(mod,
194 		    "%s: no authority information for %s node\n",
195 		    f, hcfmri->hc_name);
196 	}
197 
198 	result = x86pi_set_system(mod, t_node);
199 	if (result != 0) {
200 		/*
201 		 * Though we have failed to set the system group, we still
202 		 * continue. The module errno is set by the called routine, so
203 		 * we report the problem and move on.
204 		 */
205 		topo_mod_dprintf(mod,
206 		    "%s: no system information for %s node\n",
207 		    f, hcfmri->hc_name);
208 	}
209 
210 	return (t_node);
211 }
212