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 (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
24 */
25
26 /*
27 * Create Base Board (MB) topology node from SMBIOS Type 2 structure
28 */
29
30 #include <sys/types.h>
31 #include <strings.h>
32 #include <fm/topo_mod.h>
33 #include <fm/topo_hc.h>
34 #include <sys/systeminfo.h>
35 #include <sys/smbios_impl.h>
36 #include <sys/smbios.h>
37 #include <x86pi_impl.h>
38
39 /* base baoed type values to hc-canonical-name */
40 static const struct x86pi_bb_name {
41 int type;
42 const char *name;
43 } x86pi_bb_names[] = {
44 { SMB_BBT_SBLADE, "systemboard" },
45 { SMB_BBT_PROC, "cpuboard" },
46 { SMB_BBT_IO, "ioboard" },
47 { SMB_BBT_MEM, "memboard" },
48 { SMB_BBT_DAUGHTER, "systemboard" },
49 { SMB_BBT_MOTHER, "motherboard" },
50 { SMB_BBT_PROCMEM, "systemboard" },
51 { SMB_BBT_PROCIO, "systemboard" },
52 { SMB_BBT_INTER, "systemboard" },
53 { 0x00 }
54 };
55
56 tnode_t *
x86pi_gen_bboard(topo_mod_t * mod,tnode_t * t_parent,int smb_id,int instance,int psmb_id)57 x86pi_gen_bboard(topo_mod_t *mod, tnode_t *t_parent, int smb_id,
58 int instance, int psmb_id)
59 {
60 int rv;
61 smbios_info_t ip;
62 smbios_bboard_t bb;
63 smbios_struct_t sp;
64 x86pi_hcfmri_t bb_hcfmri;
65 tnode_t *bb_node;
66 const struct x86pi_bb_name *bbnp;
67 static int cpuboard = 0;
68 static int memboard = 0;
69 static int ioboard = 0;
70 static int systemboard = 0;
71 static int motherboard = 0;
72 char *f = "x86pi_gen_bboard";
73 smbios_hdl_t *shp;
74
75 topo_mod_dprintf(mod, "%s\n", f);
76
77 shp = topo_mod_smbios(mod);
78 if (shp == NULL) {
79 topo_mod_dprintf(mod, "%s: failed to load SMBIOS\n", f);
80 return (NULL);
81 }
82
83 /* SMBIOS Base Board struct */
84 rv = smbios_info_bboard(shp, smb_id, &bb);
85 if (rv != 0) {
86 topo_mod_dprintf(mod, "%s: smbios_info_bboard() failed\n", f);
87 return (NULL);
88 }
89 (void) smbios_lookup_id(shp, psmb_id, &sp);
90 if (sp.smbstr_type == SMB_TYPE_CHASSIS &&
91 bb.smbb_chassis != psmb_id) {
92 topo_mod_dprintf(mod, "%s: base board (%d) does not belong to "
93 "chassis (%d)\n", f, smb_id, psmb_id);
94 return (NULL);
95 }
96
97 /* SMBIOS Base Board strings */
98 rv = smbios_info_common(shp, smb_id, &ip);
99 if (rv != 0) {
100 return (NULL);
101 }
102
103 /*
104 * populate string entries
105 *
106 * We don't set "product" because it may contain characters
107 * unacceptable by fmri. topo_mod_auth() will set the product-id
108 * for us and call topo_cleanup_auth_str() when necessary.
109 */
110 bb_hcfmri.serial_number = x86pi_cleanup_smbios_str(mod,
111 ip.smbi_serial, 0);
112 bb_hcfmri.version = x86pi_cleanup_smbios_str(mod, ip.smbi_version, 0);
113 /* asset tag string contains the part number */
114 bb_hcfmri.part_number = x86pi_cleanup_smbios_str(mod,
115 ip.smbi_asset, 0);
116 bb_hcfmri.location = x86pi_cleanup_smbios_str(mod, ip.smbi_location, 0);
117
118 /* determine the hc-name */
119 for (bbnp = x86pi_bb_names; bbnp->type != 0x00; bbnp++) {
120 if (bbnp->type == bb.smbb_type) {
121 switch (bbnp->type) {
122 case SMB_BBT_PROC :
123 instance = cpuboard++;
124 break;
125 case SMB_BBT_IO :
126 instance = ioboard++;
127 break;
128 case SMB_BBT_MEM :
129 instance = memboard++;
130 break;
131 case SMB_BBT_MOTHER :
132 instance = motherboard++;
133 break;
134 default :
135 /*
136 * Enumerate any other baseboard type
137 * as systemboard.
138 *
139 * SMB_BBT_UNKNOWN
140 * SMB_BBT_OTHER
141 * SMB_BBT_SBLADE
142 * SMB_BBT_CSWITCH
143 * SMB_BBT_SMM
144 * SMB_BBT_DAUGHTER
145 * SMB_BBT_PROCMEM
146 * SMB_BBT_PROCIO
147 * SMB_BBT_INTER
148 */
149 instance = systemboard++;
150 break;
151 }
152 break;
153 }
154 }
155
156 bb_hcfmri.instance = instance;
157 if (bbnp->type != 0x00)
158 bb_hcfmri.hc_name = topo_mod_strdup(mod, bbnp->name);
159 else
160 bb_hcfmri.hc_name = topo_mod_strdup(mod, "NULL");
161
162 topo_mod_dprintf(mod, "%s: S/N (%s)\n", f, bb_hcfmri.serial_number);
163 topo_mod_dprintf(mod, "%s: version/N (%s)\n", f, bb_hcfmri.version);
164 topo_mod_dprintf(mod, "%s: Part/N (%s)\n", f, bb_hcfmri.part_number);
165 topo_mod_dprintf(mod, "%s: location (%s)\n", f, bb_hcfmri.location);
166 topo_mod_dprintf(mod, "%s: instance (%d)\n", f, bb_hcfmri.instance);
167 topo_mod_dprintf(mod, "%s: hc_name (%s)\n", f, bb_hcfmri.hc_name);
168
169 rv = x86pi_enum_generic(mod, &bb_hcfmri, t_parent, t_parent, &bb_node,
170 X86PI_ENUM_FRU);
171 if (rv != 0) {
172 topo_mod_dprintf(mod, "%s: failed to create tnode %d\n", f,
173 instance);
174 bb_node = NULL;
175 }
176
177 /* free up strings */
178 if (bb_hcfmri.hc_name != NULL) {
179 topo_mod_strfree(mod, (char *)bb_hcfmri.hc_name);
180 }
181 if (bb_hcfmri.part_number != NULL) {
182 topo_mod_strfree(mod, (char *)bb_hcfmri.part_number);
183 }
184 if (bb_hcfmri.serial_number != NULL) {
185 topo_mod_strfree(mod, (char *)bb_hcfmri.serial_number);
186 }
187 if (bb_hcfmri.version != NULL) {
188 topo_mod_strfree(mod, (char *)bb_hcfmri.version);
189 }
190 if (bb_hcfmri.location != NULL) {
191 topo_mod_strfree(mod, (char *)bb_hcfmri.location);
192 }
193
194 return (bb_node);
195 }
196
197
198 int
x86pi_bb_getchips(topo_mod_t * mod,int index,int nboards)199 x86pi_bb_getchips(topo_mod_t *mod, int index, int nboards)
200 {
201 id_t *cid;
202 int count;
203 int ncmp = 0;
204 smbios_struct_t sp;
205 smbs_cnt_t *smbc = NULL;
206 smbios_hdl_t *shp;
207
208 shp = topo_mod_smbios(mod);
209 if (shp == NULL)
210 return (ncmp);
211
212 cid = stypes[SMB_TYPE_BASEBOARD].ids[index].con_ids;
213 count = stypes[SMB_TYPE_BASEBOARD].ids[index].con_cnt;
214
215 for (int i = 0; i < count; i++) {
216 (void) smbios_lookup_id(shp, cid[i], &sp);
217 if (sp.smbstr_type == SMB_TYPE_PROCESSOR) {
218 ncmp++;
219 }
220 }
221
222 /*
223 * If there are missing SMB_TYPE_PROCESSOR structures
224 * contained within SMB_TYPE_BASEBOARD, and if the
225 * system has only one baseboard we enumerate
226 * all processors under it.
227 */
228 smbc = &stypes[SMB_TYPE_PROCESSOR];
229 smbc->type = SMB_TYPE_PROCESSOR;
230 x86pi_smb_strcnt(mod, smbc);
231
232 if (nboards == 1) {
233 if (ncmp != stypes[SMB_TYPE_PROCESSOR].count)
234 ncmp = stypes[SMB_TYPE_PROCESSOR].count;
235 } else {
236 if (ncmp == 0) {
237 topo_mod_dprintf(mod, "failed to get processors"
238 " (or) no processors are contained"
239 " within baseboard instance %d, unable to"
240 " enumerate chips\n", index);
241 }
242 }
243
244 return (ncmp);
245 }
246
247
248 id_t
x86pi_bb_topparent(topo_mod_t * mod,int index,tnode_t ** pnode,id_t * psmbid)249 x86pi_bb_topparent(topo_mod_t *mod, int index, tnode_t **pnode, id_t *psmbid)
250 {
251
252 id_t top_bb_smbid = -1;
253 id_t smb_id;
254 int bb_count, ch_count;
255 smbios_struct_t sp;
256 smbios_hdl_t *shp;
257
258 shp = topo_mod_smbios(mod);
259 if (shp == NULL)
260 return (top_bb_smbid);
261
262 smb_id = stypes[SMB_TYPE_BASEBOARD].ids[index].con_by_id;
263 (void) smbios_lookup_id(shp, smb_id, &sp);
264
265 if (sp.smbstr_type == SMB_TYPE_CHASSIS) {
266 top_bb_smbid = stypes[SMB_TYPE_BASEBOARD].ids[index].id;
267 *psmbid = smb_id;
268 ch_count = stypes[SMB_TYPE_CHASSIS].count;
269 for (int i = 0; i < ch_count; i++)
270 if (stypes[SMB_TYPE_CHASSIS].ids[i].id == *psmbid)
271 *pnode = stypes[SMB_TYPE_CHASSIS].ids[i].node;
272
273 return (top_bb_smbid);
274
275 } else if (sp.smbstr_type == SMB_TYPE_BASEBOARD) {
276 bb_count = stypes[SMB_TYPE_BASEBOARD].count;
277 for (int i = 0; i < bb_count; i++) {
278 if (stypes[SMB_TYPE_BASEBOARD].ids[i].id == smb_id) {
279 if (stypes[SMB_TYPE_BASEBOARD].ids[i].visited
280 == X86PI_VISITED) {
281 top_bb_smbid =
282 stypes[SMB_TYPE_BASEBOARD].\
283 ids[index].id;
284 *pnode =
285 stypes[SMB_TYPE_BASEBOARD].ids[i].\
286 node;
287 *psmbid =
288 stypes[SMB_TYPE_BASEBOARD].ids[i].\
289 id;
290 break;
291 }
292 top_bb_smbid = x86pi_bb_topparent(mod,
293 i, pnode, psmbid);
294 break;
295 }
296 }
297 }
298
299 return (top_bb_smbid);
300 }
301
302
303 id_t
x86pi_bb_chassis(topo_mod_t * mod,id_t bb_smbid)304 x86pi_bb_chassis(topo_mod_t *mod, id_t bb_smbid)
305 {
306 smbios_bboard_t bb;
307 int rv;
308 smbios_hdl_t *shp;
309
310 shp = topo_mod_smbios(mod);
311 if (shp == NULL)
312 return (-1);
313
314 rv = smbios_info_bboard(shp, bb_smbid, &bb);
315 if (rv != 0)
316 return (-1);
317
318 return (bb.smbb_chassis);
319 }
320
321
322 int
x86pi_bb_contains(topo_mod_t * mod)323 x86pi_bb_contains(topo_mod_t *mod)
324 {
325 int rv;
326 id_t smb_id;
327 smbios_bboard_t bb;
328 int bb_count = 0;
329 uint_t cont_cnt = 0;
330 smbios_struct_t sp;
331 smbios_hdl_t *shp;
332
333 shp = topo_mod_smbios(mod);
334 if (shp == NULL)
335 return (-1);
336
337 bb_count = stypes[SMB_TYPE_BASEBOARD].count;
338 for (int i = 0; i < bb_count; i++) {
339 smb_id = stypes[SMB_TYPE_BASEBOARD].ids[i].id;
340 /* SMBIOS Base Board struct */
341 rv = smbios_info_bboard(shp, smb_id, &bb);
342 if (rv != 0)
343 return (-1);
344 /* Set Baseboard - Chassis Relationship */
345 if (stypes[SMB_TYPE_BASEBOARD].ids[i].con_by_id == 0) {
346 stypes[SMB_TYPE_BASEBOARD].ids[i].con_by_id =
347 rv = x86pi_bb_chassis(mod, smb_id);
348 if (rv == -1) {
349 topo_mod_dprintf(mod, " failed to get"
350 " the chassis handle\n");
351 return (rv);
352 }
353 }
354
355 /* SMBIOS contained object handles */
356 cont_cnt = bb.smbb_contn;
357 if (cont_cnt > 0) {
358 id_t *cont_hdl;
359 uint16_t hdl;
360
361 /* allocate space for and get contained handles */
362 cont_hdl = topo_mod_alloc(mod, cont_cnt *
363 sizeof (id_t));
364 rv = smbios_info_contains(shp, smb_id, cont_cnt,
365 cont_hdl);
366 if (rv > SMB_CONT_MAX) {
367 topo_mod_free(mod, cont_hdl, cont_cnt *
368 sizeof (id_t));
369 return (-1);
370 }
371 cont_cnt = MIN(rv, cont_cnt);
372
373 /* attach contained handles */
374 stypes[SMB_TYPE_BASEBOARD].ids[i].con_cnt = cont_cnt;
375 for (int j = 0; j < cont_cnt; j++) {
376 hdl = (uint16_t)cont_hdl[j];
377 topo_mod_dprintf(mod, "id %d contained handle"
378 " %d: %d\n", i, j, hdl);
379 stypes[SMB_TYPE_BASEBOARD].ids[i].\
380 con_ids[j] = hdl;
381 (void) smbios_lookup_id(shp, hdl, &sp);
382 if (sp.smbstr_type == SMB_TYPE_BASEBOARD) {
383 for (int k = 0; k < bb_count; k++)
384 if (stypes[SMB_TYPE_BASEBOARD].\
385 ids[k].id == hdl)
386 stypes[\
387 SMB_TYPE_BASEBOARD\
388 ].ids[k].con_by_id =
389 smb_id;
390 }
391 }
392 topo_mod_free(mod, cont_hdl, cont_cnt * sizeof (id_t));
393 }
394 }
395 return (0);
396 }
397