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, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 23 /* 24 * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 25 * Use is subject to license terms. 26 */ 27 28 #pragma ident "%Z%%M% %I% %E% SMI" 29 30 /* 31 * SMBIOS Information Routines 32 * 33 * The routines in this file are used to convert from the SMBIOS data format to 34 * a more reasonable and stable set of structures offered as part of our ABI. 35 * These functions take the general form: 36 * 37 * stp = smb_lookup_type(shp, foo); 38 * smb_foo_t foo; 39 * 40 * smb_info_bcopy(stp->smbst_hdr, &foo, sizeof (foo)); 41 * bzero(caller's struct); 42 * 43 * copy/convert foo members into caller's struct 44 * 45 * We copy the internal structure on to an automatic variable so as to avoid 46 * checks everywhere for structures that the BIOS has improperly truncated, and 47 * also to automatically handle the case of a structure that has been extended. 48 * When necessary, this code can use smb_gteq() to determine whether the SMBIOS 49 * data is of a particular revision that is supposed to contain a new field. 50 */ 51 52 #include <sys/smbios_impl.h> 53 54 /* 55 * A large number of SMBIOS structures contain a set of common strings used to 56 * describe a h/w component's serial number, manufacturer, etc. These fields 57 * helpfully have different names and offsets and sometimes aren't consistent. 58 * To simplify life for our clients, we factor these common things out into 59 * smbios_info_t, which can be retrieved for any structure. The following 60 * table describes the mapping from a given structure to the smbios_info_t. 61 */ 62 static const struct smb_infospec { 63 uint8_t is_type; /* structure type */ 64 uint8_t is_manu; /* manufacturer offset */ 65 uint8_t is_product; /* product name offset */ 66 uint8_t is_version; /* version offset */ 67 uint8_t is_serial; /* serial number offset */ 68 uint8_t is_asset; /* asset tag offset */ 69 uint8_t is_location; /* location string offset */ 70 uint8_t is_part; /* part number offset */ 71 } _smb_infospecs[] = { 72 { SMB_TYPE_SYSTEM, 73 offsetof(smb_system_t, smbsi_manufacturer), 74 offsetof(smb_system_t, smbsi_product), 75 offsetof(smb_system_t, smbsi_version), 76 offsetof(smb_system_t, smbsi_serial), 77 0, 78 0, 79 0 }, 80 { SMB_TYPE_BASEBOARD, 81 offsetof(smb_bboard_t, smbbb_manufacturer), 82 offsetof(smb_bboard_t, smbbb_product), 83 offsetof(smb_bboard_t, smbbb_version), 84 offsetof(smb_bboard_t, smbbb_serial), 85 offsetof(smb_bboard_t, smbbb_asset), 86 offsetof(smb_bboard_t, smbbb_location), 87 0 }, 88 { SMB_TYPE_CHASSIS, 89 offsetof(smb_chassis_t, smbch_manufacturer), 90 0, 91 offsetof(smb_chassis_t, smbch_version), 92 offsetof(smb_chassis_t, smbch_serial), 93 offsetof(smb_chassis_t, smbch_asset), 94 0, 95 0 }, 96 { SMB_TYPE_PROCESSOR, 97 offsetof(smb_processor_t, smbpr_manufacturer), 98 0, 99 offsetof(smb_processor_t, smbpr_version), 100 offsetof(smb_processor_t, smbpr_serial), 101 offsetof(smb_processor_t, smbpr_asset), 102 offsetof(smb_processor_t, smbpr_socket), 103 offsetof(smb_processor_t, smbpr_part) }, 104 { SMB_TYPE_CACHE, 105 0, 106 0, 107 0, 108 0, 109 0, 110 offsetof(smb_cache_t, smbca_socket), 111 0 }, 112 { SMB_TYPE_PORT, 113 0, 114 0, 115 0, 116 0, 117 0, 118 offsetof(smb_port_t, smbpo_iref), 119 0 }, 120 { SMB_TYPE_SLOT, 121 0, 122 0, 123 0, 124 0, 125 0, 126 offsetof(smb_slot_t, smbsl_name), 127 0 }, 128 { SMB_TYPE_MEMDEVICE, 129 offsetof(smb_memdevice_t, smbmdev_manufacturer), 130 0, 131 0, 132 offsetof(smb_memdevice_t, smbmdev_serial), 133 offsetof(smb_memdevice_t, smbmdev_asset), 134 offsetof(smb_memdevice_t, smbmdev_dloc), 135 offsetof(smb_memdevice_t, smbmdev_part) }, 136 { SMB_TYPE_POWERSUP, 137 offsetof(smb_powersup_t, smbpsup_manufacturer), 138 offsetof(smb_powersup_t, smbpsup_devname), 139 offsetof(smb_powersup_t, smbpsup_rev), 140 offsetof(smb_powersup_t, smbpsup_serial), 141 offsetof(smb_powersup_t, smbpsup_asset), 142 offsetof(smb_powersup_t, smbpsup_loc), 143 offsetof(smb_powersup_t, smbpsup_part) }, 144 { SMB_TYPE_EOT } 145 }; 146 147 static const char * 148 smb_info_strptr(const smb_struct_t *stp, uint8_t off, int *n) 149 { 150 const uint8_t *sp = (const uint8_t *)(uintptr_t)stp->smbst_hdr; 151 152 if (off != 0 && sp + off < stp->smbst_end) { 153 (*n)++; /* indicate success for caller */ 154 return (smb_strptr(stp, sp[off])); 155 } 156 157 return (smb_strptr(stp, 0)); 158 } 159 160 static void 161 smb_info_bcopy(const smb_header_t *hp, void *dst, size_t dstlen) 162 { 163 if (dstlen > hp->smbh_len) { 164 bcopy(hp, dst, hp->smbh_len); 165 bzero((char *)dst + hp->smbh_len, dstlen - hp->smbh_len); 166 } else 167 bcopy(hp, dst, dstlen); 168 } 169 170 void 171 smbios_info_smbios(smbios_hdl_t *shp, smbios_entry_t *ep) 172 { 173 bcopy(&shp->sh_ent, ep, sizeof (smbios_entry_t)); 174 } 175 176 int 177 smbios_info_common(smbios_hdl_t *shp, id_t id, smbios_info_t *ip) 178 { 179 const smb_struct_t *stp = smb_lookup_id(shp, id); 180 const struct smb_infospec *isp; 181 int n = 0; 182 183 if (stp == NULL) 184 return (-1); /* errno is set for us */ 185 186 for (isp = _smb_infospecs; isp->is_type != SMB_TYPE_EOT; isp++) { 187 if (isp->is_type == stp->smbst_hdr->smbh_type) 188 break; 189 } 190 191 ip->smbi_manufacturer = smb_info_strptr(stp, isp->is_manu, &n); 192 ip->smbi_product = smb_info_strptr(stp, isp->is_product, &n); 193 ip->smbi_version = smb_info_strptr(stp, isp->is_version, &n); 194 ip->smbi_serial = smb_info_strptr(stp, isp->is_serial, &n); 195 ip->smbi_asset = smb_info_strptr(stp, isp->is_asset, &n); 196 ip->smbi_location = smb_info_strptr(stp, isp->is_location, &n); 197 ip->smbi_part = smb_info_strptr(stp, isp->is_part, &n); 198 199 /* 200 * If we have a port with an empty internal reference designator string 201 * try using the external reference designator string instead. 202 */ 203 if (isp->is_type == SMB_TYPE_PORT && ip->smbi_location[0] == '\0') { 204 ip->smbi_location = smb_info_strptr(stp, 205 offsetof(smb_port_t, smbpo_eref), &n); 206 } 207 208 return (n ? 0 : smb_set_errno(shp, ESMB_NOINFO)); 209 } 210 211 id_t 212 smbios_info_bios(smbios_hdl_t *shp, smbios_bios_t *bp) 213 { 214 const smb_struct_t *stp = smb_lookup_type(shp, SMB_TYPE_BIOS); 215 const smb_bios_t *bip; 216 217 if (stp == NULL) 218 return (-1); /* errno is set for us */ 219 220 if (stp->smbst_hdr->smbh_len < sizeof (smb_bios_t) - sizeof (uint8_t)) 221 return (smb_set_errno(shp, ESMB_CORRUPT)); 222 223 bip = (smb_bios_t *)(uintptr_t)stp->smbst_hdr; 224 bzero(bp, sizeof (smbios_bios_t)); 225 226 bp->smbb_vendor = smb_strptr(stp, bip->smbbi_vendor); 227 bp->smbb_version = smb_strptr(stp, bip->smbbi_version); 228 bp->smbb_segment = bip->smbbi_segment; 229 bp->smbb_reldate = smb_strptr(stp, bip->smbbi_reldate); 230 bp->smbb_romsize = 64 * 1024 * ((uint32_t)bip->smbbi_romsize + 1); 231 bp->smbb_runsize = 16 * (0x10000 - (uint32_t)bip->smbbi_segment); 232 bp->smbb_cflags = bip->smbbi_cflags; 233 234 /* 235 * If one or more extension bytes are present, reset smbb_xcflags to 236 * point to them. Otherwise leave this member set to NULL. 237 */ 238 if (stp->smbst_hdr->smbh_len >= sizeof (smb_bios_t)) { 239 bp->smbb_xcflags = bip->smbbi_xcflags; 240 bp->smbb_nxcflags = stp->smbst_hdr->smbh_len - 241 sizeof (smb_bios_t) + 1; 242 243 if (bp->smbb_nxcflags > SMB_BIOSXB_ECFW_MIN && 244 smb_gteq(shp, SMB_VERSION_24)) { 245 bp->smbb_biosv.smbv_major = 246 bip->smbbi_xcflags[SMB_BIOSXB_BIOS_MAJ]; 247 bp->smbb_biosv.smbv_minor = 248 bip->smbbi_xcflags[SMB_BIOSXB_BIOS_MIN]; 249 bp->smbb_ecfwv.smbv_major = 250 bip->smbbi_xcflags[SMB_BIOSXB_ECFW_MAJ]; 251 bp->smbb_ecfwv.smbv_minor = 252 bip->smbbi_xcflags[SMB_BIOSXB_ECFW_MIN]; 253 } 254 } 255 256 return (stp->smbst_hdr->smbh_hdl); 257 } 258 259 id_t 260 smbios_info_system(smbios_hdl_t *shp, smbios_system_t *sip) 261 { 262 const smb_struct_t *stp = smb_lookup_type(shp, SMB_TYPE_SYSTEM); 263 smb_system_t si; 264 265 if (stp == NULL) 266 return (-1); /* errno is set for us */ 267 268 smb_info_bcopy(stp->smbst_hdr, &si, sizeof (si)); 269 bzero(sip, sizeof (smbios_system_t)); 270 271 sip->smbs_uuid = ((smb_system_t *)stp->smbst_hdr)->smbsi_uuid; 272 sip->smbs_uuidlen = sizeof (si.smbsi_uuid); 273 sip->smbs_wakeup = si.smbsi_wakeup; 274 sip->smbs_sku = smb_strptr(stp, si.smbsi_sku); 275 sip->smbs_family = smb_strptr(stp, si.smbsi_family); 276 277 return (stp->smbst_hdr->smbh_hdl); 278 } 279 280 int 281 smbios_info_bboard(smbios_hdl_t *shp, id_t id, smbios_bboard_t *bbp) 282 { 283 const smb_struct_t *stp = smb_lookup_id(shp, id); 284 smb_bboard_t bb; 285 286 if (stp == NULL) 287 return (-1); /* errno is set for us */ 288 289 if (stp->smbst_hdr->smbh_type != SMB_TYPE_BASEBOARD) 290 return (smb_set_errno(shp, ESMB_TYPE)); 291 292 smb_info_bcopy(stp->smbst_hdr, &bb, sizeof (bb)); 293 bzero(bbp, sizeof (smbios_bboard_t)); 294 295 /* 296 * At present, we do not provide support for the contained object 297 * handles portion of the Base Board structure, as none of the 2.3+ 298 * BIOSes commonly in use appear to implement it at present. 299 */ 300 bbp->smbb_chassis = bb.smbbb_chassis; 301 bbp->smbb_flags = bb.smbbb_flags; 302 bbp->smbb_type = bb.smbbb_type; 303 304 return (0); 305 } 306 307 int 308 smbios_info_chassis(smbios_hdl_t *shp, id_t id, smbios_chassis_t *chp) 309 { 310 const smb_struct_t *stp = smb_lookup_id(shp, id); 311 smb_chassis_t ch; 312 313 if (stp == NULL) 314 return (-1); /* errno is set for us */ 315 316 if (stp->smbst_hdr->smbh_type != SMB_TYPE_CHASSIS) 317 return (smb_set_errno(shp, ESMB_TYPE)); 318 319 smb_info_bcopy(stp->smbst_hdr, &ch, sizeof (ch)); 320 bzero(chp, sizeof (smbios_chassis_t)); 321 322 /* 323 * At present, we do not provide support for the contained object 324 * handles portion of the Chassis structure, as none of the 2.3+ 325 * BIOSes commonly in use appear to implement it at present. 326 */ 327 chp->smbc_oemdata = ch.smbch_oemdata; 328 chp->smbc_lock = (ch.smbch_type & SMB_CHT_LOCK) != 0; 329 chp->smbc_type = ch.smbch_type & ~SMB_CHT_LOCK; 330 chp->smbc_bustate = ch.smbch_bustate; 331 chp->smbc_psstate = ch.smbch_psstate; 332 chp->smbc_thstate = ch.smbch_thstate; 333 chp->smbc_security = ch.smbch_security; 334 chp->smbc_uheight = ch.smbch_uheight; 335 chp->smbc_cords = ch.smbch_cords; 336 chp->smbc_elems = ch.smbch_cn; 337 338 return (0); 339 } 340 341 int 342 smbios_info_processor(smbios_hdl_t *shp, id_t id, smbios_processor_t *pp) 343 { 344 const smb_struct_t *stp = smb_lookup_id(shp, id); 345 smb_processor_t p; 346 347 if (stp == NULL) 348 return (-1); /* errno is set for us */ 349 350 if (stp->smbst_hdr->smbh_type != SMB_TYPE_PROCESSOR) 351 return (smb_set_errno(shp, ESMB_TYPE)); 352 353 smb_info_bcopy(stp->smbst_hdr, &p, sizeof (p)); 354 bzero(pp, sizeof (smbios_processor_t)); 355 356 pp->smbp_cpuid = p.smbpr_cpuid; 357 pp->smbp_type = p.smbpr_type; 358 pp->smbp_family = p.smbpr_family; 359 pp->smbp_voltage = p.smbpr_voltage; 360 pp->smbp_maxspeed = p.smbpr_maxspeed; 361 pp->smbp_curspeed = p.smbpr_curspeed; 362 pp->smbp_status = p.smbpr_status; 363 pp->smbp_upgrade = p.smbpr_upgrade; 364 pp->smbp_l1cache = p.smbpr_l1cache; 365 pp->smbp_l2cache = p.smbpr_l2cache; 366 pp->smbp_l3cache = p.smbpr_l3cache; 367 368 return (0); 369 } 370 371 int 372 smbios_info_cache(smbios_hdl_t *shp, id_t id, smbios_cache_t *cap) 373 { 374 const smb_struct_t *stp = smb_lookup_id(shp, id); 375 smb_cache_t c; 376 377 if (stp == NULL) 378 return (-1); /* errno is set for us */ 379 380 if (stp->smbst_hdr->smbh_type != SMB_TYPE_CACHE) 381 return (smb_set_errno(shp, ESMB_TYPE)); 382 383 smb_info_bcopy(stp->smbst_hdr, &c, sizeof (c)); 384 bzero(cap, sizeof (smbios_cache_t)); 385 386 cap->smba_maxsize = SMB_CACHE_SIZE(c.smbca_maxsize); 387 cap->smba_size = SMB_CACHE_SIZE(c.smbca_size); 388 cap->smba_stype = c.smbca_stype; 389 cap->smba_ctype = c.smbca_ctype; 390 cap->smba_speed = c.smbca_speed; 391 cap->smba_etype = c.smbca_etype; 392 cap->smba_ltype = c.smbca_ltype; 393 cap->smba_assoc = c.smbca_assoc; 394 cap->smba_level = SMB_CACHE_CFG_LEVEL(c.smbca_config); 395 cap->smba_mode = SMB_CACHE_CFG_MODE(c.smbca_config); 396 cap->smba_location = SMB_CACHE_CFG_LOCATION(c.smbca_config); 397 398 if (SMB_CACHE_CFG_ENABLED(c.smbca_config)) 399 cap->smba_flags |= SMB_CAF_ENABLED; 400 401 if (SMB_CACHE_CFG_SOCKETED(c.smbca_config)) 402 cap->smba_flags |= SMB_CAF_SOCKETED; 403 404 return (0); 405 } 406 407 int 408 smbios_info_port(smbios_hdl_t *shp, id_t id, smbios_port_t *pop) 409 { 410 const smb_struct_t *stp = smb_lookup_id(shp, id); 411 smb_port_t p; 412 413 if (stp == NULL) 414 return (-1); /* errno is set for us */ 415 416 if (stp->smbst_hdr->smbh_type != SMB_TYPE_PORT) 417 return (smb_set_errno(shp, ESMB_TYPE)); 418 419 smb_info_bcopy(stp->smbst_hdr, &p, sizeof (p)); 420 bzero(pop, sizeof (smbios_port_t)); 421 422 pop->smbo_iref = smb_strptr(stp, p.smbpo_iref); 423 pop->smbo_eref = smb_strptr(stp, p.smbpo_eref); 424 425 pop->smbo_itype = p.smbpo_itype; 426 pop->smbo_etype = p.smbpo_etype; 427 pop->smbo_ptype = p.smbpo_ptype; 428 429 return (0); 430 } 431 432 int 433 smbios_info_slot(smbios_hdl_t *shp, id_t id, smbios_slot_t *sp) 434 { 435 const smb_struct_t *stp = smb_lookup_id(shp, id); 436 smb_slot_t s; 437 438 if (stp == NULL) 439 return (-1); /* errno is set for us */ 440 441 if (stp->smbst_hdr->smbh_type != SMB_TYPE_SLOT) 442 return (smb_set_errno(shp, ESMB_TYPE)); 443 444 smb_info_bcopy(stp->smbst_hdr, &s, sizeof (s)); 445 bzero(sp, sizeof (smbios_slot_t)); 446 447 sp->smbl_name = smb_strptr(stp, s.smbsl_name); 448 sp->smbl_type = s.smbsl_type; 449 sp->smbl_width = s.smbsl_width; 450 sp->smbl_usage = s.smbsl_usage; 451 sp->smbl_length = s.smbsl_length; 452 sp->smbl_id = s.smbsl_id; 453 sp->smbl_ch1 = s.smbsl_ch1; 454 sp->smbl_ch2 = s.smbsl_ch2; 455 456 return (0); 457 } 458 459 int 460 smbios_info_obdevs(smbios_hdl_t *shp, id_t id, int obc, smbios_obdev_t *obp) 461 { 462 const smb_struct_t *stp = smb_lookup_id(shp, id); 463 const smb_obdev_t *op; 464 int i, m, n; 465 466 if (stp == NULL) 467 return (-1); /* errno is set for us */ 468 469 if (stp->smbst_hdr->smbh_type != SMB_TYPE_OBDEVS) 470 return (smb_set_errno(shp, ESMB_TYPE)); 471 472 op = (smb_obdev_t *)((uintptr_t)stp->smbst_hdr + sizeof (smb_header_t)); 473 m = (stp->smbst_hdr->smbh_len - sizeof (smb_header_t)) / sizeof (*op); 474 n = MIN(m, obc); 475 476 for (i = 0; i < n; i++, op++, obp++) { 477 obp->smbd_name = smb_strptr(stp, op->smbob_name); 478 obp->smbd_type = op->smbob_type & ~SMB_OBT_ENABLED; 479 obp->smbd_enabled = (op->smbob_type & SMB_OBT_ENABLED) != 0; 480 } 481 482 return (m); 483 } 484 485 /* 486 * The implementation structures for OEMSTR, SYSCONFSTR, and LANG all use the 487 * first byte to indicate the size of a string table at the end of the record. 488 * Therefore, smbios_info_strtab() can be used to retrieve the table size and 489 * strings for any of these underlying record types. 490 */ 491 int 492 smbios_info_strtab(smbios_hdl_t *shp, id_t id, int argc, const char *argv[]) 493 { 494 const smb_struct_t *stp = smb_lookup_id(shp, id); 495 smb_strtab_t s; 496 int i, n; 497 498 if (stp == NULL) 499 return (-1); /* errno is set for us */ 500 501 if (stp->smbst_hdr->smbh_type != SMB_TYPE_OEMSTR && 502 stp->smbst_hdr->smbh_type != SMB_TYPE_SYSCONFSTR && 503 stp->smbst_hdr->smbh_type != SMB_TYPE_LANG) 504 return (smb_set_errno(shp, ESMB_TYPE)); 505 506 smb_info_bcopy(stp->smbst_hdr, &s, sizeof (s)); 507 n = MIN(s.smbtb_count, argc); 508 509 for (i = 0; i < n; i++) 510 argv[i] = smb_strptr(stp, i + 1); 511 512 return (s.smbtb_count); 513 } 514 515 id_t 516 smbios_info_lang(smbios_hdl_t *shp, smbios_lang_t *lp) 517 { 518 const smb_struct_t *stp = smb_lookup_type(shp, SMB_TYPE_LANG); 519 smb_lang_t l; 520 521 if (stp == NULL) 522 return (-1); /* errno is set for us */ 523 524 smb_info_bcopy(stp->smbst_hdr, &l, sizeof (l)); 525 bzero(lp, sizeof (smbios_lang_t)); 526 527 lp->smbla_cur = smb_strptr(stp, l.smblang_cur); 528 lp->smbla_fmt = l.smblang_flags & 1; 529 lp->smbla_num = l.smblang_num; 530 531 return (stp->smbst_hdr->smbh_hdl); 532 } 533 534 id_t 535 smbios_info_eventlog(smbios_hdl_t *shp, smbios_evlog_t *evp) 536 { 537 const smb_struct_t *stp = smb_lookup_type(shp, SMB_TYPE_EVENTLOG); 538 const smb_sel_t *sel; 539 size_t len; 540 541 if (stp == NULL) 542 return (-1); /* errno is set for us */ 543 544 if (stp->smbst_hdr->smbh_len < sizeof (smb_sel_t) - sizeof (uint8_t)) 545 return (smb_set_errno(shp, ESMB_CORRUPT)); 546 547 sel = (smb_sel_t *)(uintptr_t)stp->smbst_hdr; 548 len = stp->smbst_hdr->smbh_len - sizeof (smb_sel_t) + sizeof (uint8_t); 549 bzero(evp, sizeof (smbios_evlog_t)); 550 551 if (len < sel->smbsel_typec * sel->smbsel_typesz) 552 return (smb_set_errno(shp, ESMB_CORRUPT)); 553 554 evp->smbev_size = sel->smbsel_len; 555 evp->smbev_hdr = sel->smbsel_hdroff; 556 evp->smbev_data = sel->smbsel_dataoff; 557 evp->smbev_method = sel->smbsel_method; 558 evp->smbev_flags = sel->smbsel_status; 559 evp->smbev_format = sel->smbsel_format; 560 evp->smbev_token = sel->smbsel_token; 561 evp->smbev_addr.eva_addr = sel->smbsel_addr; 562 563 if (sel->smbsel_typesz == sizeof (smbios_evtype_t)) { 564 evp->smbev_typec = sel->smbsel_typec; 565 evp->smbev_typev = (void *)(uintptr_t)sel->smbsel_typev; 566 } 567 568 return (stp->smbst_hdr->smbh_hdl); 569 } 570 571 int 572 smbios_info_memarray(smbios_hdl_t *shp, id_t id, smbios_memarray_t *map) 573 { 574 const smb_struct_t *stp = smb_lookup_id(shp, id); 575 smb_memarray_t m; 576 577 if (stp == NULL) 578 return (-1); /* errno is set for us */ 579 580 if (stp->smbst_hdr->smbh_type != SMB_TYPE_MEMARRAY) 581 return (smb_set_errno(shp, ESMB_TYPE)); 582 583 smb_info_bcopy(stp->smbst_hdr, &m, sizeof (m)); 584 bzero(map, sizeof (smbios_memarray_t)); 585 586 map->smbma_location = m.smbmarr_loc; 587 map->smbma_use = m.smbmarr_use; 588 map->smbma_ecc = m.smbmarr_ecc; 589 map->smbma_ndevs = m.smbmarr_ndevs; 590 map->smbma_err = m.smbmarr_err; 591 592 if (m.smbmarr_cap != 0x80000000) 593 map->smbma_size = (uint64_t)m.smbmarr_cap * 1024; 594 else 595 map->smbma_size = 0; /* unknown */ 596 597 return (0); 598 } 599 600 int 601 smbios_info_memarrmap(smbios_hdl_t *shp, id_t id, smbios_memarrmap_t *map) 602 { 603 const smb_struct_t *stp = smb_lookup_id(shp, id); 604 smb_memarrmap_t m; 605 606 if (stp == NULL) 607 return (-1); /* errno is set for us */ 608 609 if (stp->smbst_hdr->smbh_type != SMB_TYPE_MEMARRAYMAP) 610 return (smb_set_errno(shp, ESMB_TYPE)); 611 612 smb_info_bcopy(stp->smbst_hdr, &m, sizeof (m)); 613 bzero(map, sizeof (smbios_memarrmap_t)); 614 615 map->smbmam_array = m.smbamap_array; 616 map->smbmam_width = m.smbamap_width; 617 map->smbmam_addr = (uint64_t)m.smbamap_start * 1024; 618 map->smbmam_size = (uint64_t) 619 (m.smbamap_end - m.smbamap_start + 1) * 1024; 620 621 return (0); 622 } 623 624 int 625 smbios_info_memdevice(smbios_hdl_t *shp, id_t id, smbios_memdevice_t *mdp) 626 { 627 const smb_struct_t *stp = smb_lookup_id(shp, id); 628 smb_memdevice_t m; 629 630 if (stp == NULL) 631 return (-1); /* errno is set for us */ 632 633 if (stp->smbst_hdr->smbh_type != SMB_TYPE_MEMDEVICE) 634 return (smb_set_errno(shp, ESMB_TYPE)); 635 636 smb_info_bcopy(stp->smbst_hdr, &m, sizeof (m)); 637 bzero(mdp, sizeof (smbios_memdevice_t)); 638 639 mdp->smbmd_array = m.smbmdev_array; 640 mdp->smbmd_error = m.smbmdev_error; 641 mdp->smbmd_twidth = m.smbmdev_twidth == 0xFFFF ? -1U : m.smbmdev_twidth; 642 mdp->smbmd_dwidth = m.smbmdev_dwidth == 0xFFFF ? -1U : m.smbmdev_dwidth; 643 644 if (mdp->smbmd_size != 0xFFFF) { 645 mdp->smbmd_size = (uint64_t)(m.smbmdev_size & ~SMB_MDS_KBYTES); 646 if (m.smbmdev_size & SMB_MDS_KBYTES) 647 mdp->smbmd_size *= 1024; 648 else 649 mdp->smbmd_size *= 1024 * 1024; 650 } else 651 mdp->smbmd_size = -1ULL; /* size unknown */ 652 653 mdp->smbmd_form = m.smbmdev_form; 654 mdp->smbmd_set = m.smbmdev_set; 655 mdp->smbmd_type = m.smbmdev_type; 656 mdp->smbmd_flags = m.smbmdev_flags; 657 mdp->smbmd_dloc = smb_strptr(stp, m.smbmdev_dloc); 658 mdp->smbmd_bloc = smb_strptr(stp, m.smbmdev_bloc); 659 660 if (m.smbmdev_speed != 0) 661 mdp->smbmd_speed = 1000 / m.smbmdev_speed; /* MHz -> nsec */ 662 663 return (0); 664 } 665 666 int 667 smbios_info_memdevmap(smbios_hdl_t *shp, id_t id, smbios_memdevmap_t *mdp) 668 { 669 const smb_struct_t *stp = smb_lookup_id(shp, id); 670 smb_memdevmap_t m; 671 672 if (stp == NULL) 673 return (-1); /* errno is set for us */ 674 675 if (stp->smbst_hdr->smbh_type != SMB_TYPE_MEMDEVICEMAP) 676 return (smb_set_errno(shp, ESMB_TYPE)); 677 678 smb_info_bcopy(stp->smbst_hdr, &m, sizeof (m)); 679 bzero(mdp, sizeof (smbios_memdevmap_t)); 680 681 mdp->smbmdm_device = m.smbdmap_device; 682 mdp->smbmdm_arrmap = m.smbdmap_array; 683 mdp->smbmdm_addr = (uint64_t)m.smbdmap_start * 1024; 684 mdp->smbmdm_size = (uint64_t) 685 (m.smbdmap_end - m.smbdmap_start + 1) * 1024; 686 mdp->smbmdm_rpos = m.smbdmap_rpos; 687 mdp->smbmdm_ipos = m.smbdmap_ipos; 688 mdp->smbmdm_idepth = m.smbdmap_idepth; 689 690 return (0); 691 } 692 693 id_t 694 smbios_info_hwsec(smbios_hdl_t *shp, smbios_hwsec_t *hsp) 695 { 696 const smb_struct_t *stp = smb_lookup_type(shp, SMB_TYPE_SECURITY); 697 smb_hwsec_t hs; 698 699 if (stp == NULL) 700 return (-1); /* errno is set for us */ 701 702 smb_info_bcopy(stp->smbst_hdr, &hs, sizeof (hs)); 703 bzero(hsp, sizeof (smbios_hwsec_t)); 704 705 hsp->smbh_pwr_ps = SMB_HWS_PWR_PS(hs.smbhs_settings); 706 hsp->smbh_kbd_ps = SMB_HWS_KBD_PS(hs.smbhs_settings); 707 hsp->smbh_adm_ps = SMB_HWS_ADM_PS(hs.smbhs_settings); 708 hsp->smbh_pan_ps = SMB_HWS_PAN_PS(hs.smbhs_settings); 709 710 return (stp->smbst_hdr->smbh_hdl); 711 } 712 713 id_t 714 smbios_info_boot(smbios_hdl_t *shp, smbios_boot_t *bp) 715 { 716 const smb_struct_t *stp = smb_lookup_type(shp, SMB_TYPE_BOOT); 717 const smb_boot_t *b = (smb_boot_t *)(uintptr_t)stp->smbst_hdr; 718 719 if (stp == NULL) 720 return (-1); /* errno is set for us */ 721 722 bzero(bp, sizeof (smbios_boot_t)); 723 724 bp->smbt_status = b->smbbo_status[0]; 725 bp->smbt_size = stp->smbst_hdr->smbh_len - sizeof (smb_boot_t); 726 bp->smbt_data = bp->smbt_size ? &b->smbbo_status[1] : NULL; 727 728 return (stp->smbst_hdr->smbh_hdl); 729 } 730 731 id_t 732 smbios_info_ipmi(smbios_hdl_t *shp, smbios_ipmi_t *ip) 733 { 734 const smb_struct_t *stp = smb_lookup_type(shp, SMB_TYPE_IPMIDEV); 735 smb_ipmi_t i; 736 737 if (stp == NULL) 738 return (-1); /* errno is set for us */ 739 740 smb_info_bcopy(stp->smbst_hdr, &i, sizeof (i)); 741 bzero(ip, sizeof (smbios_ipmi_t)); 742 743 ip->smbip_type = i.smbipm_type; 744 ip->smbip_vers.smbv_major = SMB_IPM_SPEC_MAJOR(i.smbipm_spec); 745 ip->smbip_vers.smbv_minor = SMB_IPM_SPEC_MINOR(i.smbipm_spec); 746 ip->smbip_i2c = i.smbipm_i2c; 747 ip->smbip_addr = i.smbipm_addr & ~SMB_IPM_ADDR_IO; 748 ip->smbip_intr = i.smbipm_intr; 749 750 if (i.smbipm_bus != (uint8_t)-1) 751 ip->smbip_bus = i.smbipm_bus; 752 else 753 ip->smbip_bus = -1u; 754 755 if (SMB_IPM_INFO_LSB(i.smbipm_info)) 756 ip->smbip_addr |= 1; /* turn on least-significant bit of addr */ 757 758 if (i.smbipm_addr & SMB_IPM_ADDR_IO) { 759 switch (SMB_IPM_INFO_REGS(i.smbipm_info)) { 760 case SMB_IPM_REGS_1B: 761 ip->smbip_regspacing = 1; 762 break; 763 case SMB_IPM_REGS_4B: 764 ip->smbip_regspacing = 4; 765 break; 766 case SMB_IPM_REGS_16B: 767 ip->smbip_regspacing = 16; 768 break; 769 default: 770 ip->smbip_regspacing = 1; 771 } 772 ip->smbip_flags |= SMB_IPMI_F_IOADDR; 773 } 774 775 if (SMB_IPM_INFO_ISPEC(i.smbipm_info)) 776 ip->smbip_flags |= SMB_IPMI_F_INTRSPEC; 777 778 if (SMB_IPM_INFO_IPOL(i.smbipm_info) == SMB_IPM_IPOL_HI) 779 ip->smbip_flags |= SMB_IPMI_F_INTRHIGH; 780 781 if (SMB_IPM_INFO_IMODE(i.smbipm_info) == SMB_IPM_IMODE_EDGE) 782 ip->smbip_flags |= SMB_IPMI_F_INTREDGE; 783 784 return (stp->smbst_hdr->smbh_hdl); 785 } 786