2 * This file and its contents are supplied under the terms of the
3 * Common Development and Distribution License ("CDDL"), version 1.0.
4 * You may only use this file in accordance with the terms of version
7 * A full copy of the text of the CDDL should have accompanied this
8 * source. A copy of the CDDL is also available via the Internet at
9 * http://www.illumos.org/license/CDDL.
13 * Copyright (c) 2018, Joyent, Inc.
18 #include <fm/libtopo.h>
19 #include <fm/topo_mod.h>
23 #include <sys/fm/protocol.h>
27 typedef struct smb_enum_data
{
30 tnode_t
*sme_slotnode
;
31 topo_instance_t sme_slot_inst
;
32 topo_instance_t sme_slot_maxinst
;
33 smbios_info_t
*sme_smb_info
;
38 * This function serves two purposes. It filters out memory devices that
39 * don't have a formfactor that represents a reasonably modern DIMM-like
40 * device (and hence not a device we're interested in enumerating). It also
41 * converts the numeric SMBIOS type representation to a more generic TOPO dimm
44 * Caller must free the returned string.
47 distill_dimm_form(topo_mod_t
*mod
, smbios_memdevice_t
*smb_md
)
49 switch (smb_md
->smbmd_form
) {
51 return (topo_mod_strdup(mod
, TOPO_DIMM_SLOT_FORM_DIMM
));
52 case (SMB_MDFF_SODIMM
):
53 return (topo_mod_strdup(mod
, TOPO_DIMM_SLOT_FORM_SODIMM
));
54 case (SMB_MDFF_FBDIMM
):
55 return (topo_mod_strdup(mod
, TOPO_DIMM_SLOT_FORM_FBDIMM
));
57 topo_mod_dprintf(mod
, "skipping device with form factor 0x%x",
64 smbios2topotype(topo_mod_t
*mod
, uint8_t type
)
68 return (topo_mod_strdup(mod
, TOPO_DIMM_TYPE_DDR
));
70 case (SMB_MDT_DDR2FBDIMM
):
71 return (topo_mod_strdup(mod
, TOPO_DIMM_TYPE_DDR2
));
73 return (topo_mod_strdup(mod
, TOPO_DIMM_TYPE_DDR3
));
75 return (topo_mod_strdup(mod
, TOPO_DIMM_TYPE_DDR4
));
77 return (topo_mod_strdup(mod
, TOPO_DIMM_TYPE_LPDDR
));
78 case (SMB_MDT_LPDDR2
):
79 return (topo_mod_strdup(mod
, TOPO_DIMM_TYPE_LPDDR2
));
80 case (SMB_MDT_LPDDR3
):
81 return (topo_mod_strdup(mod
, TOPO_DIMM_TYPE_LPDDR3
));
82 case (SMB_MDT_LPDDR4
):
83 return (topo_mod_strdup(mod
, TOPO_DIMM_TYPE_LPDDR4
));
85 return (topo_mod_strdup(mod
, TOPO_DIMM_TYPE_UNKNOWN
));
90 is_valid_string(const char *str
)
92 if (strcmp(str
, SMB_DEFAULT1
) != 0 && strcmp(str
, SMB_DEFAULT2
) != 0 &&
93 strcmp(str
, SMB_DEFAULT3
) != 0 && strlen(str
) > 0)
100 smbios_make_slot(smb_enum_data_t
*smed
, smbios_memdevice_t
*smb_md
)
102 nvlist_t
*auth
, *fmri
;
104 topo_mod_t
*mod
= smed
->sme_mod
;
105 topo_pgroup_info_t pgi
;
108 if ((auth
= topo_mod_auth(mod
, smed
->sme_pnode
)) == NULL
) {
109 topo_mod_dprintf(mod
, "topo_mod_auth() failed: %s",
110 topo_mod_errmsg(mod
));
115 if ((fmri
= topo_mod_hcfmri(mod
, smed
->sme_pnode
, FM_HC_SCHEME_VERSION
,
116 SLOT
, smed
->sme_slot_inst
, NULL
, auth
, NULL
, NULL
, NULL
)) ==
119 topo_mod_dprintf(mod
, "topo_mod_hcfmri() failed: %s",
120 topo_mod_errmsg(mod
));
124 if ((slotnode
= topo_node_bind(mod
, smed
->sme_pnode
, SLOT
,
125 smed
->sme_slot_inst
, fmri
)) == NULL
) {
128 topo_mod_dprintf(mod
, "topo_node_bind() failed: %s",
129 topo_mod_errmsg(mod
));
136 /* Create authority and system pgroups */
137 topo_pgroup_hcset(slotnode
, auth
);
140 if (topo_node_label_set(slotnode
, (char *)smb_md
->smbmd_dloc
, &err
) !=
142 topo_mod_dprintf(mod
, "failed to set label on %s=%d: %s",
143 SLOT
, smed
->sme_slot_inst
, topo_strerror(err
));
144 (void) topo_mod_seterrno(mod
, err
);
147 if (topo_node_fru(smed
->sme_pnode
, &fmri
, NULL
, &err
) != 0 ||
148 topo_node_fru_set(slotnode
, fmri
, NULL
, &err
) != 0) {
149 topo_mod_dprintf(mod
, "failed to set FRU on %s=%d: %s", SLOT
,
150 smed
->sme_slot_inst
, topo_strerror(err
));
152 (void) topo_mod_seterrno(mod
, err
);
157 pgi
.tpi_name
= TOPO_PGROUP_SLOT
;
158 pgi
.tpi_namestab
= TOPO_STABILITY_PRIVATE
;
159 pgi
.tpi_datastab
= TOPO_STABILITY_PRIVATE
;
160 pgi
.tpi_version
= TOPO_VERSION
;
161 if (topo_pgroup_create(slotnode
, &pgi
, &err
) != 0 ||
162 topo_prop_set_uint32(slotnode
, TOPO_PGROUP_SLOT
,
163 TOPO_PROP_SLOT_TYPE
, TOPO_PROP_IMMUTABLE
, TOPO_SLOT_TYPE_DIMM
,
165 topo_mod_dprintf(mod
, "failed to create slot properties: %s",
167 (void) topo_mod_seterrno(mod
, err
);
171 pgi
.tpi_name
= TOPO_PGROUP_DIMM_SLOT
;
172 pgi
.tpi_namestab
= TOPO_STABILITY_PRIVATE
;
173 pgi
.tpi_datastab
= TOPO_STABILITY_PRIVATE
;
174 pgi
.tpi_version
= TOPO_VERSION
;
175 if (topo_pgroup_create(slotnode
, &pgi
, &err
) != 0 ||
176 topo_prop_set_string(slotnode
, TOPO_PGROUP_DIMM_SLOT
,
177 TOPO_PROP_DIMM_SLOT_FORM
, TOPO_PROP_IMMUTABLE
, smed
->sme_slot_form
,
179 topo_mod_dprintf(mod
, "failed to create slot properties: %s",
181 (void) topo_mod_seterrno(mod
, err
);
188 smbios_make_dimm(smb_enum_data_t
*smed
, smbios_memdevice_t
*smb_md
)
190 nvlist_t
*auth
, *fmri
;
191 smbios_info_t
*smb_info
= smed
->sme_smb_info
;
192 tnode_t
*slotnode
= smed
->sme_slotnode
;
193 tnode_t
*dimmnode
, *ret
= NULL
;
194 topo_mod_t
*mod
= smed
->sme_mod
;
195 topo_pgroup_info_t pgi
;
196 const char *part
= NULL
, *rev
= NULL
, *serial
= NULL
;
197 char *type
, *manuf
= NULL
, *prod
= NULL
, *asset
= NULL
, *loc
= NULL
;
200 if ((auth
= topo_mod_auth(mod
, slotnode
)) == NULL
) {
201 topo_mod_dprintf(mod
, "topo_mod_auth() failed: %s",
202 topo_mod_errmsg(mod
));
207 if (smed
->sme_smb_info
!= NULL
) {
208 if (is_valid_string(smb_info
->smbi_part
) == B_TRUE
)
209 part
= smb_info
->smbi_part
;
210 if (is_valid_string(smb_info
->smbi_version
) == B_TRUE
)
211 rev
= smb_info
->smbi_version
;
212 if (is_valid_string(smb_info
->smbi_serial
) == B_TRUE
)
213 serial
= smb_info
->smbi_serial
;
214 if (is_valid_string(smb_info
->smbi_manufacturer
) == B_TRUE
)
215 manuf
= topo_mod_clean_str(mod
,
216 smb_info
->smbi_manufacturer
);
217 if (is_valid_string(smb_info
->smbi_product
) == B_TRUE
)
218 prod
= topo_mod_clean_str(mod
, smb_info
->smbi_product
);
219 if (is_valid_string(smb_info
->smbi_asset
) == B_TRUE
)
220 asset
= topo_mod_clean_str(mod
, smb_info
->smbi_asset
);
221 if (is_valid_string(smb_info
->smbi_location
) == B_TRUE
)
222 loc
= topo_mod_clean_str(mod
, smb_info
->smbi_location
);
225 if ((fmri
= topo_mod_hcfmri(mod
, slotnode
, FM_HC_SCHEME_VERSION
,
226 DIMM
, 0, NULL
, auth
, part
, rev
, serial
)) == NULL
) {
228 topo_mod_dprintf(mod
, "topo_mod_hcfmri() failed: %s",
229 topo_mod_errmsg(mod
));
234 if (topo_node_range_create(mod
, slotnode
, DIMM
, 0, 0) < 0 ||
235 (dimmnode
= topo_node_bind(mod
, slotnode
, DIMM
, 0, fmri
)) ==
239 topo_mod_dprintf(mod
, "failed to bind dimm node: %s",
240 topo_mod_errmsg(mod
));
245 /* Create authority and system pgroups */
246 topo_pgroup_hcset(dimmnode
, auth
);
249 if (topo_node_fru_set(dimmnode
, fmri
, NULL
, &err
) != 0) {
250 topo_mod_dprintf(mod
, "failed to set FRU on %s: %s",
251 DIMM
, topo_strerror(err
));
253 (void) topo_mod_seterrno(mod
, err
);
258 if (topo_node_label_set(dimmnode
, (char *)smb_md
->smbmd_dloc
, &err
) !=
260 topo_mod_dprintf(mod
, "failed to set label on %s: %s",
261 DIMM
, topo_strerror(err
));
262 (void) topo_mod_seterrno(mod
, err
);
266 pgi
.tpi_name
= TOPO_PGROUP_DIMM_PROPS
;
267 pgi
.tpi_namestab
= TOPO_STABILITY_PRIVATE
;
268 pgi
.tpi_datastab
= TOPO_STABILITY_PRIVATE
;
269 pgi
.tpi_version
= TOPO_VERSION
;
270 if (topo_pgroup_create(dimmnode
, &pgi
, &err
) != 0) {
271 (void) topo_mod_seterrno(mod
, err
);
275 rc
+= topo_prop_set_uint64(dimmnode
, TOPO_PGROUP_DIMM_PROPS
, "size",
276 TOPO_PROP_IMMUTABLE
, smb_md
->smbmd_size
, &err
);
277 if (rc
== 0 && (type
= smbios2topotype(mod
, smb_md
->smbmd_type
)) !=
279 rc
+= topo_prop_set_string(dimmnode
, TOPO_PGROUP_DIMM_PROPS
,
280 "type", TOPO_PROP_IMMUTABLE
, type
, &err
);
281 topo_mod_strfree(mod
, type
);
283 if (rc
== 0 && smb_md
->smbmd_set
!= 0 && smb_md
->smbmd_set
!= 0xFF)
284 rc
+= topo_prop_set_uint32(dimmnode
, TOPO_PGROUP_DIMM_PROPS
,
285 "set", TOPO_PROP_IMMUTABLE
, smb_md
->smbmd_set
, &err
);
286 if (rc
== 0 && smb_md
->smbmd_rank
!= 0)
287 rc
+= topo_prop_set_uint32(dimmnode
, TOPO_PGROUP_DIMM_PROPS
,
288 "rank", TOPO_PROP_IMMUTABLE
, smb_md
->smbmd_rank
, &err
);
289 if (rc
== 0 && smb_md
->smbmd_clkspeed
!= 0)
290 rc
+= topo_prop_set_uint32(dimmnode
, TOPO_PGROUP_DIMM_PROPS
,
291 "configured-speed", TOPO_PROP_IMMUTABLE
,
292 smb_md
->smbmd_clkspeed
, &err
);
293 if (rc
== 0 && smb_md
->smbmd_speed
!= 0)
294 rc
+= topo_prop_set_uint32(dimmnode
, TOPO_PGROUP_DIMM_PROPS
,
295 "maximum-speed", TOPO_PROP_IMMUTABLE
, smb_md
->smbmd_speed
,
297 if (rc
== 0 && smb_md
->smbmd_maxvolt
!= 0)
298 rc
+= topo_prop_set_double(dimmnode
, TOPO_PGROUP_DIMM_PROPS
,
299 "maximum-voltage", TOPO_PROP_IMMUTABLE
,
300 (smb_md
->smbmd_maxvolt
/ 1000), &err
);
301 if (rc
== 0 && smb_md
->smbmd_minvolt
!= 0)
302 rc
+= topo_prop_set_double(dimmnode
, TOPO_PGROUP_DIMM_PROPS
,
303 "minimum-voltage", TOPO_PROP_IMMUTABLE
,
304 (smb_md
->smbmd_minvolt
/ 1000), &err
);
305 if (rc
== 0 && smb_md
->smbmd_confvolt
!= 0)
306 rc
+= topo_prop_set_double(dimmnode
, TOPO_PGROUP_DIMM_PROPS
,
307 "configured-voltage", TOPO_PROP_IMMUTABLE
,
308 (smb_md
->smbmd_confvolt
/ 1000), &err
);
309 if (rc
== 0 && manuf
!= NULL
)
310 rc
+= topo_prop_set_string(dimmnode
, TOPO_PGROUP_DIMM_PROPS
,
311 "manufacturer", TOPO_PROP_IMMUTABLE
, manuf
, &err
);
312 if (rc
== 0 && prod
!= NULL
)
313 rc
+= topo_prop_set_string(dimmnode
, TOPO_PGROUP_DIMM_PROPS
,
314 "product", TOPO_PROP_IMMUTABLE
, prod
, &err
);
315 if (rc
== 0 && asset
!= NULL
)
316 rc
+= topo_prop_set_string(dimmnode
, TOPO_PGROUP_DIMM_PROPS
,
317 "asset-tag", TOPO_PROP_IMMUTABLE
, asset
, &err
);
318 if (rc
== 0 && loc
!= NULL
)
319 rc
+= topo_prop_set_string(dimmnode
, TOPO_PGROUP_DIMM_PROPS
,
320 "location", TOPO_PROP_IMMUTABLE
, loc
, &err
);
323 topo_mod_dprintf(mod
, "error setting properties on %s node",
325 (void) topo_mod_seterrno(mod
, err
);
330 topo_mod_strfree(mod
, manuf
);
331 topo_mod_strfree(mod
, prod
);
332 topo_mod_strfree(mod
, asset
);
333 topo_mod_strfree(mod
, loc
);
338 smbios_enum_memory(smbios_hdl_t
*shp
, const smbios_struct_t
*sp
, void *arg
)
340 smbios_info_t smb_info
;
341 smbios_memdevice_t smb_md
;
342 smb_enum_data_t
*smed
= arg
;
343 topo_mod_t
*mod
= smed
->sme_mod
;
346 if (sp
->smbstr_type
!= SMB_TYPE_MEMDEVICE
)
349 if (smbios_info_memdevice(shp
, sp
->smbstr_id
, &smb_md
) != 0) {
350 topo_mod_dprintf(mod
, "libsmbios error");
351 return (topo_mod_seterrno(mod
, EMOD_UNKNOWN
));
355 * SMB_TYPE_MEMDEVICE records can also be used to represent memory
356 * that come in non-DIMM form factors. If we encounter something like
357 * that, then we skip over it.
359 if ((smed
->sme_slot_form
= distill_dimm_form(mod
, &smb_md
)) == NULL
)
362 if ((slotnode
= smbios_make_slot(smed
, &smb_md
)) == NULL
) {
363 topo_mod_dprintf(mod
, "failed to create %s node", SLOT
);
364 topo_mod_strfree(mod
, smed
->sme_slot_form
);
368 topo_mod_strfree(mod
, smed
->sme_slot_form
);
369 smed
->sme_slotnode
= slotnode
;
372 * A size of zero indicates that the DIMM slot is not populated, so
373 * we skip creating a child dimm node and return.
375 if (smb_md
.smbmd_size
== 0) {
376 smed
->sme_slot_inst
++;
380 if (smbios_info_common(shp
, sp
->smbstr_id
, &smb_info
) == 0)
381 smed
->sme_smb_info
= &smb_info
;
383 if (smbios_make_dimm(smed
, &smb_md
) == NULL
) {
384 topo_mod_dprintf(mod
, "failed to create %s node", DIMM
);
389 * If we've exceeded our max inst then return non-zero to cause
390 * the walk to terminate.
392 if (++smed
->sme_slot_inst
> smed
->sme_slot_maxinst
)
399 smbios_enum_motherboard(smbios_hdl_t
*shp
, smb_enum_data_t
*smed
)
402 smbios_bboard_t smb_mb
;
403 smbios_bios_t smb_bios
;
404 smbios_info_t smb_info
;
405 const char *part
= NULL
, *rev
= NULL
, *serial
= NULL
;
406 char *manuf
= NULL
, *prod
= NULL
, *asset
= NULL
;
407 char *bios_vendor
= NULL
, *bios_rev
= NULL
, *bios_reldate
= NULL
;
408 nvlist_t
*auth
, *fmri
;
409 topo_mod_t
*mod
= smed
->sme_mod
;
411 topo_pgroup_info_t pgi
;
414 if (smbios_lookup_type(shp
, SMB_TYPE_BASEBOARD
, &sp
) == 0 &&
415 smbios_info_bboard(shp
, sp
.smbstr_id
, &smb_mb
) == 0 &&
416 smbios_info_common(shp
, sp
.smbstr_id
, &smb_info
) == 0) {
417 if (is_valid_string(smb_info
.smbi_part
) == B_TRUE
)
418 part
= smb_info
.smbi_part
;
419 if (is_valid_string(smb_info
.smbi_version
) == B_TRUE
)
420 rev
= smb_info
.smbi_version
;
421 if (is_valid_string(smb_info
.smbi_serial
) == B_TRUE
)
422 serial
= smb_info
.smbi_serial
;
423 if (is_valid_string(smb_info
.smbi_manufacturer
) == B_TRUE
)
424 manuf
= topo_mod_clean_str(mod
,
425 smb_info
.smbi_manufacturer
);
426 if (is_valid_string(smb_info
.smbi_product
) == B_TRUE
)
427 prod
= topo_mod_clean_str(mod
, smb_info
.smbi_product
);
428 if (is_valid_string(smb_info
.smbi_asset
) == B_TRUE
)
429 asset
= topo_mod_clean_str(mod
, smb_info
.smbi_asset
);
431 if (smbios_lookup_type(shp
, SMB_TYPE_BIOS
, &sp
) == 0 &&
432 smbios_info_bios(shp
, &smb_bios
) == 0) {
433 if (is_valid_string(smb_bios
.smbb_vendor
) == B_TRUE
)
434 bios_vendor
= topo_mod_clean_str(mod
,
435 smb_bios
.smbb_vendor
);
436 if (is_valid_string(smb_bios
.smbb_version
) == B_TRUE
)
437 bios_rev
= topo_mod_clean_str(mod
,
438 smb_bios
.smbb_version
);
439 if (is_valid_string(smb_bios
.smbb_reldate
) == B_TRUE
)
440 bios_reldate
= topo_mod_clean_str(mod
,
441 smb_bios
.smbb_reldate
);
443 if ((auth
= topo_mod_auth(mod
, smed
->sme_pnode
)) == NULL
) {
444 topo_mod_dprintf(mod
, "topo_mod_auth() failed: %s",
445 topo_mod_errmsg(mod
));
450 if ((fmri
= topo_mod_hcfmri(mod
, NULL
, FM_HC_SCHEME_VERSION
,
451 MOTHERBOARD
, 0, NULL
, auth
, part
, rev
, serial
)) ==
454 topo_mod_dprintf(mod
, "topo_mod_hcfmri() failed: %s",
455 topo_mod_errmsg(mod
));
460 if ((mbnode
= topo_node_bind(mod
, smed
->sme_pnode
, MOTHERBOARD
, 0,
464 topo_mod_dprintf(mod
, "topo_node_bind() failed: %s",
465 topo_mod_errmsg(mod
));
470 /* Create authority and system pgroups */
471 topo_pgroup_hcset(mbnode
, auth
);
474 if (topo_node_fru_set(mbnode
, fmri
, NULL
, &err
) != 0) {
475 topo_mod_dprintf(mod
, "failed to set FRU on %s: %s",
476 MOTHERBOARD
, topo_strerror(err
));
478 (void) topo_mod_seterrno(mod
, err
);
484 if (topo_node_label_set(mbnode
, "MB", &err
) != 0) {
485 topo_mod_dprintf(mod
, "failed to set label on %s: %s",
486 MOTHERBOARD
, topo_strerror(err
));
487 (void) topo_mod_seterrno(mod
, err
);
491 pgi
.tpi_name
= TOPO_PGROUP_MOTHERBOARD
;
492 pgi
.tpi_namestab
= TOPO_STABILITY_PRIVATE
;
493 pgi
.tpi_datastab
= TOPO_STABILITY_PRIVATE
;
494 pgi
.tpi_version
= TOPO_VERSION
;
495 rc
= topo_pgroup_create(mbnode
, &pgi
, &err
);
497 if (rc
== 0 && manuf
!= NULL
)
498 rc
+= topo_prop_set_string(mbnode
, TOPO_PGROUP_MOTHERBOARD
,
499 TOPO_PROP_MB_MANUFACTURER
, TOPO_PROP_IMMUTABLE
, manuf
,
501 if (rc
== 0 && prod
!= NULL
)
502 rc
+= topo_prop_set_string(mbnode
, TOPO_PGROUP_MOTHERBOARD
,
503 TOPO_PROP_MB_PRODUCT
, TOPO_PROP_IMMUTABLE
, prod
, &err
);
504 if (rc
== 0 && asset
!= NULL
)
505 rc
+= topo_prop_set_string(mbnode
, TOPO_PGROUP_MOTHERBOARD
,
506 TOPO_PROP_MB_ASSET
, TOPO_PROP_IMMUTABLE
, asset
, &err
);
507 if (rc
== 0 && bios_vendor
!= NULL
)
508 rc
+= topo_prop_set_string(mbnode
, TOPO_PGROUP_MOTHERBOARD
,
509 TOPO_PROP_MB_FIRMWARE_VENDOR
, TOPO_PROP_IMMUTABLE
,
511 if (rc
== 0 && bios_rev
!= NULL
)
512 rc
+= topo_prop_set_string(mbnode
, TOPO_PGROUP_MOTHERBOARD
,
513 TOPO_PROP_MB_FIRMWARE_REV
, TOPO_PROP_IMMUTABLE
,
515 if (rc
== 0 && bios_reldate
!= NULL
)
516 rc
+= topo_prop_set_string(mbnode
, TOPO_PGROUP_MOTHERBOARD
,
517 TOPO_PROP_MB_FIRMWARE_RELDATE
, TOPO_PROP_IMMUTABLE
,
521 topo_mod_dprintf(mod
, "error setting properties on %s node",
523 (void) topo_mod_seterrno(mod
, err
);
527 topo_mod_strfree(mod
, manuf
);
528 topo_mod_strfree(mod
, prod
);
529 topo_mod_strfree(mod
, asset
);
530 topo_mod_strfree(mod
, bios_vendor
);
531 topo_mod_strfree(mod
, bios_rev
);
532 topo_mod_strfree(mod
, bios_reldate
);
538 * A system with a functional memory controller driver will have one mc device
539 * node per chip instance, starting at instance 0. The driver provides an
540 * ioctl interface for retrieving a snapshot of the system's memory topology.
541 * If we're able to issue this ioctl on one of the mc device nodes then we'll
542 * return B_TRUE, indicating that this system has a minimally functional memory
550 mc_snapshot_info_t mcs
;
552 if ((mc_fd
= open("/dev/mc/mc0", O_RDONLY
)) < 0)
555 if (ioctl(mc_fd
, MC_IOC_SNAPSHOT_INFO
, &mcs
) < 0) {
568 smbios_enum(topo_mod_t
*mod
, tnode_t
*rnode
, const char *name
,
569 topo_instance_t min
, topo_instance_t max
, void *arg
, void *unused
)
572 smb_enum_data_t smed
= { 0 };
574 if ((smbh
= topo_mod_smbios(mod
)) == NULL
) {
575 topo_mod_dprintf(mod
, "failed to get libsmbios handle");
576 return (topo_mod_seterrno(mod
, EMOD_UNKNOWN
));
579 smed
.sme_pnode
= rnode
;
580 smed
.sme_slot_inst
= min
;
581 smed
.sme_slot_maxinst
= max
;
584 * Currently we only support enumerating dimm-slot and dimm nodes, but
585 * this module could be expanded in the future to enumerate other
586 * hardware components from SMBIOS.
588 if (strcmp(name
, SLOT
) == 0) {
590 * If the system has a functional memory controller driver then
591 * we'll assume that it has responsibility for enumerating the
594 if (has_mc_driver() == B_TRUE
)
596 if (smbios_iter(smbh
, smbios_enum_memory
, &smed
) < 0)
599 } else if (strcmp(name
, MOTHERBOARD
) == 0) {
600 if (smbios_enum_motherboard(smbh
, &smed
) < 0)
604 topo_mod_dprintf(mod
, "smbios_enum() invoked for unsupported "
605 "node type: %s", name
);
606 return (topo_mod_seterrno(mod
, EMOD_UNKNOWN
));
611 const topo_modops_t smbios_ops
= { smbios_enum
, NULL
};
613 const topo_modinfo_t smbios_info
=
614 { "smbios", FM_FMRI_SCHEME_HC
, TOPO_VERSION
, &smbios_ops
};
618 _topo_init(topo_mod_t
*mod
, topo_version_t version
)
620 if (getenv("TOPOSMBIOSDEBUG") != NULL
)
621 topo_mod_setdebug(mod
);
623 if (topo_mod_register(mod
, &smbios_info
, TOPO_VERSION
) != 0) {
624 topo_mod_dprintf(mod
, "module registration failed: %s\n",
625 topo_mod_errmsg(mod
));
630 topo_mod_dprintf(mod
, "SMBIOS enumerator initialized\n");
635 _topo_fini(topo_mod_t
*mod
)
637 topo_mod_unregister(mod
);