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 2015 OmniTI Computer Consulting, Inc. All rights reserved. 24 * Copyright 2019 Joyent, Inc. 25 * Copyright 2010 Sun Microsystems, Inc. All rights reserved. 26 * Use is subject to license terms. 27 */ 28 29 /* 30 * SMBIOS Information Routines 31 * 32 * The routines in this file are used to convert from the SMBIOS data format to 33 * a more reasonable and stable set of structures offered as part of our ABI. 34 * These functions take the general form: 35 * 36 * stp = smb_lookup_type(shp, foo); 37 * smb_foo_t foo; 38 * 39 * smb_info_bcopy(stp->smbst_hdr, &foo, sizeof (foo)); 40 * bzero(caller's struct); 41 * 42 * copy/convert foo members into caller's struct 43 * 44 * We copy the internal structure on to an automatic variable so as to avoid 45 * checks everywhere for structures that the BIOS has improperly truncated, and 46 * also to automatically handle the case of a structure that has been extended. 47 * When necessary, this code can use smb_gteq() to determine whether the SMBIOS 48 * data is of a particular revision that is supposed to contain a new field. 49 * 50 * Note, when trying to bzero the caller's struct you have to be careful about 51 * versions. One can only bzero the initial version that existed in illumos. In 52 * other words, if someone passes an older library handle that doesn't support a 53 * version you cannot assume that their structures have those additional members 54 * in them. Instead, a 'base' version is introduced for such types that have 55 * differences and instead we only bzero out the base version and then handle 56 * the additional members. In general, because all additional members will be 57 * assigned, there's no reason to zero them out unless they are arrays that 58 * won't be entirely filled in. 59 * 60 * Due to history, anything added after the update from version 2.4, in other 61 * words additions from or after '5094 Update libsmbios with recent items' 62 * (4e901881) is currently being used for this. While we don't allow software 63 * compiling against this to get an older form, this was the first major update 64 * and a good starting point for us to enforce this behavior which is useful for 65 * moving forward to making this more public. 66 */ 67 68 #include <sys/smbios_impl.h> 69 #include <sys/byteorder.h> 70 #include <sys/debug.h> 71 72 #ifdef _KERNEL 73 #include <sys/sunddi.h> 74 #else 75 #include <fcntl.h> 76 #include <unistd.h> 77 #include <string.h> 78 #endif 79 80 /* 81 * A large number of SMBIOS structures contain a set of common strings used to 82 * describe a h/w component's serial number, manufacturer, etc. These fields 83 * helpfully have different names and offsets and sometimes aren't consistent. 84 * To simplify life for our clients, we factor these common things out into 85 * smbios_info_t, which can be retrieved for any structure. The following 86 * table describes the mapping from a given structure to the smbios_info_t. 87 * Multiple SMBIOS stuctures' contained objects are also handled here. 88 */ 89 static const struct smb_infospec { 90 uint8_t is_type; /* structure type */ 91 uint8_t is_manu; /* manufacturer offset */ 92 uint8_t is_product; /* product name offset */ 93 uint8_t is_version; /* version offset */ 94 uint8_t is_serial; /* serial number offset */ 95 uint8_t is_asset; /* asset tag offset */ 96 uint8_t is_location; /* location string offset */ 97 uint8_t is_part; /* part number offset */ 98 uint8_t is_contc; /* contained count */ 99 uint8_t is_contsz; /* contained size */ 100 uint8_t is_contv; /* contained objects */ 101 } _smb_infospecs[] = { 102 { SMB_TYPE_SYSTEM, 103 offsetof(smb_system_t, smbsi_manufacturer), 104 offsetof(smb_system_t, smbsi_product), 105 offsetof(smb_system_t, smbsi_version), 106 offsetof(smb_system_t, smbsi_serial), 107 0, 108 0, 109 0, 110 0, 111 0, 112 0 }, 113 { SMB_TYPE_BASEBOARD, 114 offsetof(smb_bboard_t, smbbb_manufacturer), 115 offsetof(smb_bboard_t, smbbb_product), 116 offsetof(smb_bboard_t, smbbb_version), 117 offsetof(smb_bboard_t, smbbb_serial), 118 offsetof(smb_bboard_t, smbbb_asset), 119 offsetof(smb_bboard_t, smbbb_location), 120 0, 121 offsetof(smb_bboard_t, smbbb_cn), 122 SMB_CONT_WORD, 123 offsetof(smb_bboard_t, smbbb_cv) }, 124 { SMB_TYPE_CHASSIS, 125 offsetof(smb_chassis_t, smbch_manufacturer), 126 0, 127 offsetof(smb_chassis_t, smbch_version), 128 offsetof(smb_chassis_t, smbch_serial), 129 offsetof(smb_chassis_t, smbch_asset), 130 0, 131 0, 132 offsetof(smb_chassis_t, smbch_cn), 133 SMB_CONT_BYTE, 134 offsetof(smb_chassis_t, smbch_cv) }, 135 { SMB_TYPE_PROCESSOR, 136 offsetof(smb_processor_t, smbpr_manufacturer), 137 0, 138 offsetof(smb_processor_t, smbpr_version), 139 offsetof(smb_processor_t, smbpr_serial), 140 offsetof(smb_processor_t, smbpr_asset), 141 offsetof(smb_processor_t, smbpr_socket), 142 offsetof(smb_processor_t, smbpr_part), 143 0, 144 0, 145 0 }, 146 { SMB_TYPE_CACHE, 147 0, 148 0, 149 0, 150 0, 151 0, 152 offsetof(smb_cache_t, smbca_socket), 153 0, 154 0, 155 0, 156 0 }, 157 { SMB_TYPE_PORT, 158 0, 159 0, 160 0, 161 0, 162 0, 163 offsetof(smb_port_t, smbpo_iref), 164 0, 165 0, 166 0, 167 0 }, 168 { SMB_TYPE_SLOT, 169 0, 170 0, 171 0, 172 0, 173 0, 174 offsetof(smb_slot_t, smbsl_name), 175 0, 176 0, 177 0, 178 0 }, 179 { SMB_TYPE_MEMDEVICE, 180 offsetof(smb_memdevice_t, smbmdev_manufacturer), 181 0, 182 0, 183 offsetof(smb_memdevice_t, smbmdev_serial), 184 offsetof(smb_memdevice_t, smbmdev_asset), 185 offsetof(smb_memdevice_t, smbmdev_dloc), 186 offsetof(smb_memdevice_t, smbmdev_part), 187 0, 188 0, 189 0 }, 190 { SMB_TYPE_POWERSUP, 191 offsetof(smb_powersup_t, smbpsup_manufacturer), 192 offsetof(smb_powersup_t, smbpsup_devname), 193 offsetof(smb_powersup_t, smbpsup_rev), 194 offsetof(smb_powersup_t, smbpsup_serial), 195 offsetof(smb_powersup_t, smbpsup_asset), 196 offsetof(smb_powersup_t, smbpsup_loc), 197 offsetof(smb_powersup_t, smbpsup_part), 198 0, 199 0, 200 0 }, 201 { SMB_TYPE_BATTERY, 202 offsetof(smb_battery_t, smbbat_manufacturer), 203 offsetof(smb_battery_t, smbbat_devname), 204 0, 205 /* 206 * While the serial number is a part of the device, because of 207 * the fact that the battery has two different serial numbers, 208 * we don't include it here. 209 */ 210 0, 211 0, 212 offsetof(smb_battery_t, smbbat_loc), 213 0, 214 0, 215 0, 216 0 217 }, 218 { SMB_TYPE_EOT } 219 }; 220 221 static const char * 222 smb_info_strptr(const smb_struct_t *stp, uint8_t off, int *n) 223 { 224 const uint8_t *sp = (const uint8_t *)(uintptr_t)stp->smbst_hdr; 225 226 if (off != 0 && sp + off < stp->smbst_end) { 227 (*n)++; /* indicate success for caller */ 228 return (smb_strptr(stp, sp[off])); 229 } 230 231 return (smb_strptr(stp, 0)); 232 } 233 234 static void 235 smb_info_bcopy(const smb_header_t *hp, void *dst, size_t dstlen) 236 { 237 if (dstlen > hp->smbh_len) { 238 bcopy(hp, dst, hp->smbh_len); 239 bzero((char *)dst + hp->smbh_len, dstlen - hp->smbh_len); 240 } else 241 bcopy(hp, dst, dstlen); 242 } 243 244 smbios_entry_point_t 245 smbios_info_smbios(smbios_hdl_t *shp, smbios_entry_t *ep) 246 { 247 bcopy(&shp->sh_ent, ep, sizeof (smbios_entry_t)); 248 return (shp->sh_ent_type); 249 } 250 251 void 252 smbios_info_smbios_version(smbios_hdl_t *shp, smbios_version_t *v) 253 { 254 v->smbv_major = SMB_MAJOR(shp->sh_smbvers); 255 v->smbv_minor = SMB_MINOR(shp->sh_smbvers); 256 } 257 258 #ifndef _KERNEL 259 static char smbios_product_override[256]; 260 static boolean_t smbios_product_checked; 261 #endif 262 263 int 264 smbios_info_common(smbios_hdl_t *shp, id_t id, smbios_info_t *ip) 265 { 266 const smb_struct_t *stp = smb_lookup_id(shp, id); 267 const struct smb_infospec *isp; 268 int n = 0; 269 270 if (stp == NULL) 271 return (-1); /* errno is set for us */ 272 273 for (isp = _smb_infospecs; isp->is_type != SMB_TYPE_EOT; isp++) { 274 if (isp->is_type == stp->smbst_hdr->smbh_type) 275 break; 276 } 277 278 ip->smbi_manufacturer = smb_info_strptr(stp, isp->is_manu, &n); 279 ip->smbi_product = smb_info_strptr(stp, isp->is_product, &n); 280 ip->smbi_version = smb_info_strptr(stp, isp->is_version, &n); 281 ip->smbi_serial = smb_info_strptr(stp, isp->is_serial, &n); 282 ip->smbi_asset = smb_info_strptr(stp, isp->is_asset, &n); 283 ip->smbi_location = smb_info_strptr(stp, isp->is_location, &n); 284 ip->smbi_part = smb_info_strptr(stp, isp->is_part, &n); 285 286 /* 287 * This private file allows developers to experiment with reporting 288 * different platform strings from SMBIOS. It is not a supported 289 * mechanism in the long term, and does not work in the kernel. 290 */ 291 #ifndef _KERNEL 292 if (isp->is_type == SMB_TYPE_SYSTEM) { 293 if (!smbios_product_checked) { 294 int fd = open("/etc/smbios_product", O_RDONLY); 295 if (fd >= 0) { 296 (void) read(fd, smbios_product_override, 297 sizeof (smbios_product_override) - 1); 298 (void) close(fd); 299 } 300 smbios_product_checked = B_TRUE; 301 } 302 303 if (smbios_product_override[0] != '\0') 304 ip->smbi_product = smbios_product_override; 305 } 306 #endif 307 308 /* 309 * If we have a port with an empty internal reference designator string 310 * try using the external reference designator string instead. 311 */ 312 if (isp->is_type == SMB_TYPE_PORT && ip->smbi_location[0] == '\0') { 313 ip->smbi_location = smb_info_strptr(stp, 314 offsetof(smb_port_t, smbpo_eref), &n); 315 } 316 317 return (n ? 0 : smb_set_errno(shp, ESMB_NOINFO)); 318 } 319 320 /* 321 * Returns the actual number of contained objects. 322 * 323 * idc - number of contained objects 324 * idv - returned array of contained objects 325 */ 326 int 327 smbios_info_contains(smbios_hdl_t *shp, id_t id, uint_t idc, id_t *idv) 328 { 329 const smb_struct_t *stp = smb_lookup_id(shp, id); 330 const struct smb_infospec *isp; 331 id_t *cp; 332 uint_t size; 333 uint8_t cnt; 334 int i, n; 335 336 if (stp == NULL) { 337 return (-1); /* errno is set for us */ 338 } 339 340 for (isp = _smb_infospecs; isp->is_type != SMB_TYPE_EOT; isp++) { 341 if (isp->is_type == stp->smbst_hdr->smbh_type) 342 break; 343 } 344 if (isp->is_type == SMB_TYPE_EOT) 345 return (smb_set_errno(shp, ESMB_TYPE)); 346 347 size = isp->is_contsz; 348 cnt = *((uint8_t *)(uintptr_t)stp->smbst_hdr + isp->is_contc); 349 cp = (id_t *)((uintptr_t)stp->smbst_hdr + isp->is_contv); 350 351 n = MIN(cnt, idc); 352 for (i = 0; i < n; i++) { 353 if (size == SMB_CONT_WORD) 354 idv[i] = *((uint8_t *)(uintptr_t)cp + (i * 2)); 355 else if (size == SMB_CONT_BYTE) 356 idv[i] = *((uint8_t *)(uintptr_t)cp + (i * 3)); 357 else 358 return (smb_set_errno(shp, ESMB_INVAL)); 359 } 360 361 return (cnt); 362 } 363 364 id_t 365 smbios_info_bios(smbios_hdl_t *shp, smbios_bios_t *bp) 366 { 367 const smb_struct_t *stp = smb_lookup_type(shp, SMB_TYPE_BIOS); 368 const smb_bios_t *bip; 369 370 if (stp == NULL) 371 return (-1); /* errno is set for us */ 372 373 if (stp->smbst_hdr->smbh_len < sizeof (smb_bios_t) - sizeof (uint8_t)) 374 return (smb_set_errno(shp, ESMB_CORRUPT)); 375 376 bip = (smb_bios_t *)(uintptr_t)stp->smbst_hdr; 377 bzero(bp, sizeof (smb_base_bios_t)); 378 if (smb_libgteq(shp, SMB_VERSION_31)) { 379 bp->smbb_extromsize = 0; 380 } 381 382 bp->smbb_vendor = smb_strptr(stp, bip->smbbi_vendor); 383 bp->smbb_version = smb_strptr(stp, bip->smbbi_version); 384 bp->smbb_segment = bip->smbbi_segment; 385 bp->smbb_reldate = smb_strptr(stp, bip->smbbi_reldate); 386 bp->smbb_romsize = 64 * 1024 * ((uint32_t)bip->smbbi_romsize + 1); 387 bp->smbb_runsize = 16 * (0x10000 - (uint32_t)bip->smbbi_segment); 388 bp->smbb_cflags = bip->smbbi_cflags; 389 390 /* 391 * If one or more extension bytes are present, reset smbb_xcflags to 392 * point to them. Otherwise leave this member set to NULL. 393 */ 394 if (stp->smbst_hdr->smbh_len >= sizeof (smb_bios_t)) { 395 bp->smbb_xcflags = bip->smbbi_xcflags; 396 bp->smbb_nxcflags = stp->smbst_hdr->smbh_len - 397 sizeof (smb_bios_t) + 1; 398 399 if (bp->smbb_nxcflags > SMB_BIOSXB_ECFW_MIN && 400 smb_gteq(shp, SMB_VERSION_24)) { 401 bp->smbb_biosv.smbv_major = 402 bip->smbbi_xcflags[SMB_BIOSXB_BIOS_MAJ]; 403 bp->smbb_biosv.smbv_minor = 404 bip->smbbi_xcflags[SMB_BIOSXB_BIOS_MIN]; 405 bp->smbb_ecfwv.smbv_major = 406 bip->smbbi_xcflags[SMB_BIOSXB_ECFW_MAJ]; 407 bp->smbb_ecfwv.smbv_minor = 408 bip->smbbi_xcflags[SMB_BIOSXB_ECFW_MIN]; 409 } 410 411 if (bp->smbb_nxcflags > SMB_BIOSXB_EXTROM + 1 && 412 smb_gteq(shp, SMB_VERSION_31)) { 413 uint16_t val; 414 uint64_t rs; 415 416 /* 417 * Because of the fact that the extended size is a 418 * uint16_t and we'd need to define an explicit 419 * endian-aware way to access it, we don't include it in 420 * the number of extended flags below and thus subtract 421 * its size. 422 */ 423 bp->smbb_nxcflags -= sizeof (uint16_t); 424 bcopy(&bip->smbbi_xcflags[SMB_BIOSXB_EXTROM], &val, 425 sizeof (val)); 426 val = LE_16(val); 427 428 /* 429 * The upper two bits of the extended rom size are used 430 * to indicate whether the other 14 bits are in MB or 431 * GB. 432 */ 433 rs = SMB_BIOS_EXTROM_VALUE_MASK(val); 434 switch (SMB_BIOS_EXTROM_SHIFT_MASK(val)) { 435 case 0: 436 rs *= 1024ULL * 1024ULL; 437 break; 438 case 1: 439 rs *= 1024ULL * 1024ULL * 1024ULL; 440 break; 441 default: 442 rs = 0; 443 break; 444 } 445 446 if (smb_libgteq(shp, SMB_VERSION_31)) { 447 bp->smbb_extromsize = rs; 448 } 449 } 450 } 451 452 if (smb_libgteq(shp, SMB_VERSION_31) && bp->smbb_extromsize == 0) { 453 bp->smbb_extromsize = bp->smbb_romsize; 454 } 455 456 return (stp->smbst_hdr->smbh_hdl); 457 } 458 459 id_t 460 smbios_info_system(smbios_hdl_t *shp, smbios_system_t *sip) 461 { 462 const smb_struct_t *stp = smb_lookup_type(shp, SMB_TYPE_SYSTEM); 463 smb_system_t si; 464 465 if (stp == NULL) 466 return (-1); /* errno is set for us */ 467 468 smb_info_bcopy(stp->smbst_hdr, &si, sizeof (si)); 469 bzero(sip, sizeof (smbios_system_t)); 470 471 sip->smbs_uuid = ((smb_system_t *)stp->smbst_hdr)->smbsi_uuid; 472 sip->smbs_uuidlen = sizeof (si.smbsi_uuid); 473 sip->smbs_wakeup = si.smbsi_wakeup; 474 sip->smbs_sku = smb_strptr(stp, si.smbsi_sku); 475 sip->smbs_family = smb_strptr(stp, si.smbsi_family); 476 477 return (stp->smbst_hdr->smbh_hdl); 478 } 479 480 int 481 smbios_info_bboard(smbios_hdl_t *shp, id_t id, smbios_bboard_t *bbp) 482 { 483 const smb_struct_t *stp = smb_lookup_id(shp, id); 484 smb_bboard_t bb; 485 486 if (stp == NULL) 487 return (-1); /* errno is set for us */ 488 489 if (stp->smbst_hdr->smbh_type != SMB_TYPE_BASEBOARD) 490 return (smb_set_errno(shp, ESMB_TYPE)); 491 492 smb_info_bcopy(stp->smbst_hdr, &bb, sizeof (bb)); 493 bzero(bbp, sizeof (smbios_bboard_t)); 494 495 bbp->smbb_chassis = bb.smbbb_chassis; 496 bbp->smbb_flags = bb.smbbb_flags; 497 bbp->smbb_type = bb.smbbb_type; 498 bbp->smbb_contn = bb.smbbb_cn; 499 500 return (0); 501 } 502 503 int 504 smbios_info_chassis(smbios_hdl_t *shp, id_t id, smbios_chassis_t *chp) 505 { 506 const smb_struct_t *stp = smb_lookup_id(shp, id); 507 /* Length is measurable by one byte, so it'll be no more than 255. */ 508 uint8_t buf[256]; 509 smb_chassis_t *ch = (smb_chassis_t *)&buf[0]; 510 511 if (stp == NULL) 512 return (-1); /* errno is set for us */ 513 514 if (stp->smbst_hdr->smbh_type != SMB_TYPE_CHASSIS) 515 return (smb_set_errno(shp, ESMB_TYPE)); 516 517 smb_info_bcopy(stp->smbst_hdr, ch, sizeof (buf)); 518 bzero(chp, sizeof (smb_base_chassis_t)); 519 if (smb_libgteq(shp, SMB_VERSION_27)) { 520 bzero(chp->smbc_sku, sizeof (chp->smbc_sku)); 521 } 522 523 chp->smbc_oemdata = ch->smbch_oemdata; 524 chp->smbc_lock = (ch->smbch_type & SMB_CHT_LOCK) != 0; 525 chp->smbc_type = ch->smbch_type & ~SMB_CHT_LOCK; 526 chp->smbc_bustate = ch->smbch_bustate; 527 chp->smbc_psstate = ch->smbch_psstate; 528 chp->smbc_thstate = ch->smbch_thstate; 529 chp->smbc_security = ch->smbch_security; 530 chp->smbc_uheight = ch->smbch_uheight; 531 chp->smbc_cords = ch->smbch_cords; 532 chp->smbc_elems = ch->smbch_cn; 533 chp->smbc_elemlen = ch->smbch_cm; 534 535 if (smb_libgteq(shp, SMB_VERSION_27)) { 536 (void) strlcpy(chp->smbc_sku, SMB_CH_SKU(ch), 537 sizeof (chp->smbc_sku)); 538 } 539 540 return (0); 541 } 542 543 int 544 smbios_info_processor(smbios_hdl_t *shp, id_t id, smbios_processor_t *pp) 545 { 546 const smb_struct_t *stp = smb_lookup_id(shp, id); 547 smb_processor_t p; 548 549 if (stp == NULL) 550 return (-1); /* errno is set for us */ 551 552 if (stp->smbst_hdr->smbh_type != SMB_TYPE_PROCESSOR) 553 return (smb_set_errno(shp, ESMB_TYPE)); 554 555 smb_info_bcopy(stp->smbst_hdr, &p, sizeof (p)); 556 bzero(pp, sizeof (smb_base_processor_t)); 557 558 pp->smbp_cpuid = p.smbpr_cpuid; 559 pp->smbp_type = p.smbpr_type; 560 pp->smbp_family = p.smbpr_family; 561 pp->smbp_voltage = p.smbpr_voltage; 562 pp->smbp_maxspeed = p.smbpr_maxspeed; 563 pp->smbp_curspeed = p.smbpr_curspeed; 564 pp->smbp_status = p.smbpr_status; 565 pp->smbp_upgrade = p.smbpr_upgrade; 566 pp->smbp_l1cache = p.smbpr_l1cache; 567 pp->smbp_l2cache = p.smbpr_l2cache; 568 pp->smbp_l3cache = p.smbpr_l3cache; 569 570 if (smb_libgteq(shp, SMB_VERSION_25)) { 571 pp->smbp_corecount = p.smbpr_corecount; 572 pp->smbp_coresenabled = p.smbpr_coresenabled; 573 pp->smbp_threadcount = p.smbpr_threadcount; 574 pp->smbp_cflags = p.smbpr_cflags; 575 } 576 577 if (smb_libgteq(shp, SMB_VERSION_26)) { 578 if (pp->smbp_family == 0xfe) { 579 pp->smbp_family = p.smbpr_family2; 580 } 581 } 582 583 if (smb_libgteq(shp, SMB_VERSION_30)) { 584 if (pp->smbp_corecount == 0xff) { 585 pp->smbp_corecount = p.smbpr_corecount2; 586 } 587 if (pp->smbp_coresenabled == 0xff) { 588 pp->smbp_coresenabled = p.smbpr_coresenabled2; 589 } 590 if (pp->smbp_threadcount == 0xff) { 591 pp->smbp_threadcount = p.smbpr_threadcount2; 592 } 593 } 594 595 return (0); 596 } 597 598 int 599 smbios_info_cache(smbios_hdl_t *shp, id_t id, smbios_cache_t *cap) 600 { 601 const smb_struct_t *stp = smb_lookup_id(shp, id); 602 smb_cache_t c; 603 604 if (stp == NULL) 605 return (-1); /* errno is set for us */ 606 607 if (stp->smbst_hdr->smbh_type != SMB_TYPE_CACHE) 608 return (smb_set_errno(shp, ESMB_TYPE)); 609 610 smb_info_bcopy(stp->smbst_hdr, &c, sizeof (c)); 611 bzero(cap, sizeof (smb_base_cache_t)); 612 613 cap->smba_maxsize = SMB_CACHE_SIZE(c.smbca_maxsize); 614 cap->smba_size = SMB_CACHE_SIZE(c.smbca_size); 615 cap->smba_stype = c.smbca_stype; 616 cap->smba_ctype = c.smbca_ctype; 617 cap->smba_speed = c.smbca_speed; 618 cap->smba_etype = c.smbca_etype; 619 cap->smba_ltype = c.smbca_ltype; 620 cap->smba_assoc = c.smbca_assoc; 621 cap->smba_level = SMB_CACHE_CFG_LEVEL(c.smbca_config); 622 cap->smba_mode = SMB_CACHE_CFG_MODE(c.smbca_config); 623 cap->smba_location = SMB_CACHE_CFG_LOCATION(c.smbca_config); 624 625 if (SMB_CACHE_CFG_ENABLED(c.smbca_config)) 626 cap->smba_flags |= SMB_CAF_ENABLED; 627 628 if (SMB_CACHE_CFG_SOCKETED(c.smbca_config)) 629 cap->smba_flags |= SMB_CAF_SOCKETED; 630 631 if (smb_libgteq(shp, SMB_VERSION_31)) { 632 cap->smba_maxsize2 = SMB_CACHE_EXT_SIZE(c.smbca_maxsize2); 633 cap->smba_size2 = SMB_CACHE_EXT_SIZE(c.smbca_size2); 634 635 if (cap->smba_maxsize2 == 0) { 636 cap->smba_maxsize2 = cap->smba_maxsize; 637 } 638 639 if (cap->smba_size2 == 0) { 640 cap->smba_size2 = cap->smba_size; 641 } 642 } 643 644 return (0); 645 } 646 647 int 648 smbios_info_port(smbios_hdl_t *shp, id_t id, smbios_port_t *pop) 649 { 650 const smb_struct_t *stp = smb_lookup_id(shp, id); 651 smb_port_t p; 652 653 if (stp == NULL) 654 return (-1); /* errno is set for us */ 655 656 if (stp->smbst_hdr->smbh_type != SMB_TYPE_PORT) 657 return (smb_set_errno(shp, ESMB_TYPE)); 658 659 smb_info_bcopy(stp->smbst_hdr, &p, sizeof (p)); 660 bzero(pop, sizeof (smbios_port_t)); 661 662 pop->smbo_iref = smb_strptr(stp, p.smbpo_iref); 663 pop->smbo_eref = smb_strptr(stp, p.smbpo_eref); 664 665 pop->smbo_itype = p.smbpo_itype; 666 pop->smbo_etype = p.smbpo_etype; 667 pop->smbo_ptype = p.smbpo_ptype; 668 669 return (0); 670 } 671 672 int 673 smbios_info_slot(smbios_hdl_t *shp, id_t id, smbios_slot_t *sp) 674 { 675 const smb_struct_t *stp = smb_lookup_id(shp, id); 676 smb_slot_t s; 677 678 if (stp == NULL) 679 return (-1); /* errno is set for us */ 680 681 if (stp->smbst_hdr->smbh_type != SMB_TYPE_SLOT) 682 return (smb_set_errno(shp, ESMB_TYPE)); 683 684 smb_info_bcopy(stp->smbst_hdr, &s, sizeof (s)); 685 bzero(sp, sizeof (smb_base_slot_t)); 686 687 sp->smbl_name = smb_strptr(stp, s.smbsl_name); 688 sp->smbl_type = s.smbsl_type; 689 sp->smbl_width = s.smbsl_width; 690 sp->smbl_usage = s.smbsl_usage; 691 sp->smbl_length = s.smbsl_length; 692 sp->smbl_id = s.smbsl_id; 693 sp->smbl_ch1 = s.smbsl_ch1; 694 sp->smbl_ch2 = s.smbsl_ch2; 695 sp->smbl_sg = s.smbsl_sg; 696 sp->smbl_bus = s.smbsl_bus; 697 sp->smbl_df = s.smbsl_df; 698 699 if (smb_libgteq(shp, SMB_VERSION_32)) { 700 sp->smbl_dbw = s.smbsl_dbw; 701 sp->smbl_npeers = s.smbsl_npeers; 702 } 703 704 return (0); 705 } 706 707 void 708 smbios_info_slot_peers_free(smbios_hdl_t *shp, uint_t npeers, 709 smbios_slot_peer_t *peer) 710 { 711 size_t sz = npeers * sizeof (smbios_slot_peer_t); 712 713 if (npeers == 0) { 714 ASSERT3P(peer, ==, NULL); 715 return; 716 } 717 718 smb_free(peer, sz); 719 } 720 721 int 722 smbios_info_slot_peers(smbios_hdl_t *shp, id_t id, uint_t *npeers, 723 smbios_slot_peer_t **peerp) 724 { 725 const smb_struct_t *stp = smb_lookup_id(shp, id); 726 const smb_slot_t *slotp; 727 smbios_slot_peer_t *peer; 728 size_t minlen; 729 uint_t i; 730 731 if (stp == NULL) 732 return (-1); /* errno is set for us */ 733 734 slotp = (const smb_slot_t *)stp->smbst_hdr; 735 736 if (stp->smbst_hdr->smbh_type != SMB_TYPE_SLOT) 737 return (smb_set_errno(shp, ESMB_TYPE)); 738 739 if (stp->smbst_hdr->smbh_len <= offsetof(smb_slot_t, smbsl_npeers) || 740 slotp->smbsl_npeers == 0) { 741 *npeers = 0; 742 *peerp = NULL; 743 return (0); 744 } 745 746 /* 747 * Make sure that the size of the structure makes sense for the number 748 * of peers reported. 749 */ 750 minlen = slotp->smbsl_npeers * sizeof (smb_slot_peer_t) + 751 offsetof(smb_slot_t, smbsl_npeers); 752 if (stp->smbst_hdr->smbh_len < minlen) { 753 return (smb_set_errno(shp, ESMB_SHORT)); 754 } 755 756 if ((peer = smb_alloc(slotp->smbsl_npeers * 757 sizeof (smbios_slot_peer_t))) == NULL) { 758 return (smb_set_errno(shp, ESMB_NOMEM)); 759 } 760 761 for (i = 0; i < slotp->smbsl_npeers; i++) { 762 peer[i].smblp_group = slotp->smbsl_peers[i].smbspb_group_no; 763 peer[i].smblp_bus = slotp->smbsl_peers[i].smbspb_bus; 764 peer[i].smblp_device = slotp->smbsl_peers[i].smbspb_df >> 3; 765 peer[i].smblp_function = slotp->smbsl_peers[i].smbspb_df & 0x7; 766 peer[i].smblp_data_width = slotp->smbsl_peers[i].smbspb_width; 767 } 768 769 *npeers = slotp->smbsl_npeers; 770 *peerp = peer; 771 772 return (0); 773 } 774 775 int 776 smbios_info_obdevs_ext(smbios_hdl_t *shp, id_t id, smbios_obdev_ext_t *oep) 777 { 778 const smb_struct_t *stp = smb_lookup_id(shp, id); 779 smb_obdev_ext_t obe; 780 781 if (stp == NULL) 782 return (-1); /* errno is set for us */ 783 784 if (stp->smbst_hdr->smbh_type != SMB_TYPE_OBDEVEXT) 785 return (smb_set_errno(shp, ESMB_TYPE)); 786 787 smb_info_bcopy(stp->smbst_hdr, &obe, sizeof (obe)); 788 bzero(oep, sizeof (smbios_obdev_ext_t)); 789 790 oep->smboe_name = smb_strptr(stp, obe.smbobe_name); 791 oep->smboe_dtype = obe.smbobe_dtype; 792 oep->smboe_dti = obe.smbobe_dti; 793 oep->smboe_sg = obe.smbobe_sg; 794 oep->smboe_bus = obe.smbobe_bus; 795 oep->smboe_df = obe.smbobe_df; 796 797 return (0); 798 } 799 800 int 801 smbios_info_obdevs(smbios_hdl_t *shp, id_t id, int obc, smbios_obdev_t *obp) 802 { 803 const smb_struct_t *stp = smb_lookup_id(shp, id); 804 const smb_obdev_t *op; 805 int i, m, n; 806 807 if (stp == NULL) 808 return (-1); /* errno is set for us */ 809 810 if (stp->smbst_hdr->smbh_type != SMB_TYPE_OBDEVS) 811 return (smb_set_errno(shp, ESMB_TYPE)); 812 813 op = (smb_obdev_t *)((uintptr_t)stp->smbst_hdr + sizeof (smb_header_t)); 814 m = (stp->smbst_hdr->smbh_len - sizeof (smb_header_t)) / sizeof (*op); 815 n = MIN(m, obc); 816 817 for (i = 0; i < n; i++, op++, obp++) { 818 obp->smbd_name = smb_strptr(stp, op->smbob_name); 819 obp->smbd_type = op->smbob_type & ~SMB_OBT_ENABLED; 820 obp->smbd_enabled = (op->smbob_type & SMB_OBT_ENABLED) != 0; 821 } 822 823 return (m); 824 } 825 826 /* 827 * The implementation structures for OEMSTR, SYSCONFSTR, and LANG all use the 828 * first byte to indicate the size of a string table at the end of the record. 829 * Therefore, smbios_info_strtab() can be used to retrieve the table size and 830 * strings for any of these underlying record types. 831 */ 832 int 833 smbios_info_strtab(smbios_hdl_t *shp, id_t id, int argc, const char *argv[]) 834 { 835 const smb_struct_t *stp = smb_lookup_id(shp, id); 836 smb_strtab_t s; 837 int i, n; 838 839 if (stp == NULL) 840 return (-1); /* errno is set for us */ 841 842 if (stp->smbst_hdr->smbh_type != SMB_TYPE_OEMSTR && 843 stp->smbst_hdr->smbh_type != SMB_TYPE_SYSCONFSTR && 844 stp->smbst_hdr->smbh_type != SMB_TYPE_LANG) 845 return (smb_set_errno(shp, ESMB_TYPE)); 846 847 smb_info_bcopy(stp->smbst_hdr, &s, sizeof (s)); 848 n = MIN(s.smbtb_count, argc); 849 850 for (i = 0; i < n; i++) 851 argv[i] = smb_strptr(stp, i + 1); 852 853 return (s.smbtb_count); 854 } 855 856 id_t 857 smbios_info_lang(smbios_hdl_t *shp, smbios_lang_t *lp) 858 { 859 const smb_struct_t *stp = smb_lookup_type(shp, SMB_TYPE_LANG); 860 smb_lang_t l; 861 862 if (stp == NULL) 863 return (-1); /* errno is set for us */ 864 865 smb_info_bcopy(stp->smbst_hdr, &l, sizeof (l)); 866 bzero(lp, sizeof (smbios_lang_t)); 867 868 lp->smbla_cur = smb_strptr(stp, l.smblang_cur); 869 lp->smbla_fmt = l.smblang_flags & 1; 870 lp->smbla_num = l.smblang_num; 871 872 return (stp->smbst_hdr->smbh_hdl); 873 } 874 875 id_t 876 smbios_info_eventlog(smbios_hdl_t *shp, smbios_evlog_t *evp) 877 { 878 const smb_struct_t *stp = smb_lookup_type(shp, SMB_TYPE_EVENTLOG); 879 const smb_sel_t *sel; 880 size_t len; 881 882 if (stp == NULL) 883 return (-1); /* errno is set for us */ 884 885 if (stp->smbst_hdr->smbh_len < sizeof (smb_sel_t) - sizeof (uint8_t)) 886 return (smb_set_errno(shp, ESMB_CORRUPT)); 887 888 sel = (smb_sel_t *)(uintptr_t)stp->smbst_hdr; 889 len = stp->smbst_hdr->smbh_len - sizeof (smb_sel_t) + sizeof (uint8_t); 890 bzero(evp, sizeof (smbios_evlog_t)); 891 892 if (len < sel->smbsel_typec * sel->smbsel_typesz) 893 return (smb_set_errno(shp, ESMB_CORRUPT)); 894 895 evp->smbev_size = sel->smbsel_len; 896 evp->smbev_hdr = sel->smbsel_hdroff; 897 evp->smbev_data = sel->smbsel_dataoff; 898 evp->smbev_method = sel->smbsel_method; 899 evp->smbev_flags = sel->smbsel_status; 900 evp->smbev_format = sel->smbsel_format; 901 evp->smbev_token = sel->smbsel_token; 902 evp->smbev_addr.eva_addr = sel->smbsel_addr; 903 904 if (sel->smbsel_typesz == sizeof (smbios_evtype_t)) { 905 evp->smbev_typec = sel->smbsel_typec; 906 evp->smbev_typev = (void *)(uintptr_t)sel->smbsel_typev; 907 } 908 909 return (stp->smbst_hdr->smbh_hdl); 910 } 911 912 int 913 smbios_info_memarray(smbios_hdl_t *shp, id_t id, smbios_memarray_t *map) 914 { 915 const smb_struct_t *stp = smb_lookup_id(shp, id); 916 smb_memarray_t m; 917 918 if (stp == NULL) 919 return (-1); /* errno is set for us */ 920 921 if (stp->smbst_hdr->smbh_type != SMB_TYPE_MEMARRAY) 922 return (smb_set_errno(shp, ESMB_TYPE)); 923 924 smb_info_bcopy(stp->smbst_hdr, &m, sizeof (m)); 925 bzero(map, sizeof (smbios_memarray_t)); 926 927 map->smbma_location = m.smbmarr_loc; 928 map->smbma_use = m.smbmarr_use; 929 map->smbma_ecc = m.smbmarr_ecc; 930 map->smbma_ndevs = m.smbmarr_ndevs; 931 map->smbma_err = m.smbmarr_err; 932 933 if (m.smbmarr_cap != 0x80000000) 934 map->smbma_size = (uint64_t)m.smbmarr_cap * 1024; 935 else if (m.smbmarr_extcap != 0) 936 map->smbma_size = m.smbmarr_extcap; 937 else 938 map->smbma_size = 0; /* unknown */ 939 940 return (0); 941 } 942 943 int 944 smbios_info_memarrmap(smbios_hdl_t *shp, id_t id, smbios_memarrmap_t *map) 945 { 946 const smb_struct_t *stp = smb_lookup_id(shp, id); 947 smb_memarrmap_t m; 948 949 if (stp == NULL) 950 return (-1); /* errno is set for us */ 951 952 if (stp->smbst_hdr->smbh_type != SMB_TYPE_MEMARRAYMAP) 953 return (smb_set_errno(shp, ESMB_TYPE)); 954 955 smb_info_bcopy(stp->smbst_hdr, &m, sizeof (m)); 956 bzero(map, sizeof (smbios_memarrmap_t)); 957 958 map->smbmam_array = m.smbamap_array; 959 map->smbmam_width = m.smbamap_width; 960 961 if (m.smbamap_start != 0xFFFFFFFF && m.smbamap_end != 0xFFFFFFFF) { 962 map->smbmam_addr = (uint64_t)m.smbamap_start * 1024; 963 map->smbmam_size = (uint64_t) 964 (m.smbamap_end - m.smbamap_start + 1) * 1024; 965 } else if (m.smbamap_extstart != 0 && m.smbamap_extend != 0) { 966 map->smbmam_addr = m.smbamap_extstart; 967 map->smbmam_size = m.smbamap_extend - m.smbamap_extstart + 1; 968 } 969 970 return (0); 971 } 972 973 int 974 smbios_info_memdevice(smbios_hdl_t *shp, id_t id, smbios_memdevice_t *mdp) 975 { 976 const smb_struct_t *stp = smb_lookup_id(shp, id); 977 smb_memdevice_t m; 978 979 if (stp == NULL) 980 return (-1); /* errno is set for us */ 981 982 if (stp->smbst_hdr->smbh_type != SMB_TYPE_MEMDEVICE) 983 return (smb_set_errno(shp, ESMB_TYPE)); 984 985 smb_info_bcopy(stp->smbst_hdr, &m, sizeof (m)); 986 bzero(mdp, sizeof (smb_base_memdevice_t)); 987 988 mdp->smbmd_array = m.smbmdev_array; 989 mdp->smbmd_error = m.smbmdev_error; 990 mdp->smbmd_twidth = m.smbmdev_twidth == 0xFFFF ? -1U : m.smbmdev_twidth; 991 mdp->smbmd_dwidth = m.smbmdev_dwidth == 0xFFFF ? -1U : m.smbmdev_dwidth; 992 993 if (m.smbmdev_size == 0x7FFF) { 994 mdp->smbmd_size = (uint64_t)m.smbmdev_extsize; 995 mdp->smbmd_size *= 1024 * 1024; /* convert MB to bytes */ 996 } else if (m.smbmdev_size != 0xFFFF) { 997 mdp->smbmd_size = (uint64_t)(m.smbmdev_size & ~SMB_MDS_KBYTES); 998 if (m.smbmdev_size & SMB_MDS_KBYTES) 999 mdp->smbmd_size *= 1024; 1000 else 1001 mdp->smbmd_size *= 1024 * 1024; 1002 } else 1003 mdp->smbmd_size = -1ULL; /* size unknown */ 1004 1005 mdp->smbmd_form = m.smbmdev_form; 1006 mdp->smbmd_set = m.smbmdev_set; 1007 mdp->smbmd_type = m.smbmdev_type; 1008 mdp->smbmd_speed = m.smbmdev_speed; 1009 mdp->smbmd_flags = m.smbmdev_flags; 1010 mdp->smbmd_dloc = smb_strptr(stp, m.smbmdev_dloc); 1011 mdp->smbmd_bloc = smb_strptr(stp, m.smbmdev_bloc); 1012 1013 if (smb_libgteq(shp, SMB_VERSION_26)) { 1014 mdp->smbmd_rank = m.smbmdev_attrs & 0x0F; 1015 } 1016 1017 if (smb_libgteq(shp, SMB_VERSION_27)) { 1018 mdp->smbmd_clkspeed = m.smbmdev_clkspeed; 1019 } 1020 1021 if (smb_libgteq(shp, SMB_VERSION_28)) { 1022 mdp->smbmd_minvolt = m.smbmdev_minvolt; 1023 mdp->smbmd_maxvolt = m.smbmdev_maxvolt; 1024 mdp->smbmd_confvolt = m.smbmdev_confvolt; 1025 } 1026 1027 if (smb_libgteq(shp, SMB_VERSION_32)) { 1028 mdp->smbmd_memtech = m.smbmdev_memtech; 1029 mdp->smbmd_opcap_flags = m.smbmdev_opmode; 1030 mdp->smbmd_firmware_rev = smb_strptr(stp, 1031 m.smbmdev_fwver); 1032 mdp->smbmd_modmfg_id = m.smbmdev_modulemfgid; 1033 mdp->smbmd_modprod_id = m.smbmdev_moduleprodid; 1034 mdp->smbmd_cntrlmfg_id = m.smbmdev_memsysmfgid; 1035 mdp->smbmd_cntrlprod_id = m.smbmdev_memsysprodid; 1036 mdp->smbmd_nvsize = m.smbmdev_nvsize; 1037 mdp->smbmd_volatile_size = m.smbmdev_volsize; 1038 mdp->smbmd_cache_size = m.smbmdev_cachesize; 1039 mdp->smbmd_logical_size = m.smbmdev_logicalsize; 1040 } 1041 1042 if (smb_libgteq(shp, SMB_VERSION_33)) { 1043 if (m.smbmdev_speed == 0xffff) { 1044 mdp->smbmd_extspeed = m.smbmdev_extspeed; 1045 } else { 1046 mdp->smbmd_extspeed = m.smbmdev_speed; 1047 } 1048 1049 if (m.smbmdev_clkspeed == 0xffff) { 1050 mdp->smbmd_extclkspeed = m.smbmdev_extclkspeed; 1051 } else { 1052 mdp->smbmd_extclkspeed = m.smbmdev_clkspeed; 1053 } 1054 } 1055 1056 return (0); 1057 } 1058 1059 int 1060 smbios_info_memdevmap(smbios_hdl_t *shp, id_t id, smbios_memdevmap_t *mdp) 1061 { 1062 const smb_struct_t *stp = smb_lookup_id(shp, id); 1063 smb_memdevmap_t m; 1064 1065 if (stp == NULL) 1066 return (-1); /* errno is set for us */ 1067 1068 if (stp->smbst_hdr->smbh_type != SMB_TYPE_MEMDEVICEMAP) 1069 return (smb_set_errno(shp, ESMB_TYPE)); 1070 1071 smb_info_bcopy(stp->smbst_hdr, &m, sizeof (m)); 1072 bzero(mdp, sizeof (smbios_memdevmap_t)); 1073 1074 mdp->smbmdm_device = m.smbdmap_device; 1075 mdp->smbmdm_arrmap = m.smbdmap_array; 1076 mdp->smbmdm_rpos = m.smbdmap_rpos; 1077 mdp->smbmdm_ipos = m.smbdmap_ipos; 1078 mdp->smbmdm_idepth = m.smbdmap_idepth; 1079 1080 if (m.smbdmap_start != 0xFFFFFFFF && m.smbdmap_end != 0xFFFFFFFF) { 1081 mdp->smbmdm_addr = (uint64_t)m.smbdmap_start * 1024; 1082 mdp->smbmdm_size = (uint64_t) 1083 (m.smbdmap_end - m.smbdmap_start + 1) * 1024; 1084 } else if (m.smbdmap_extstart != 0 && m.smbdmap_extend != 0) { 1085 mdp->smbmdm_addr = m.smbdmap_extstart; 1086 mdp->smbmdm_size = m.smbdmap_extend - m.smbdmap_extstart + 1; 1087 } 1088 1089 return (0); 1090 } 1091 1092 id_t 1093 smbios_info_hwsec(smbios_hdl_t *shp, smbios_hwsec_t *hsp) 1094 { 1095 const smb_struct_t *stp = smb_lookup_type(shp, SMB_TYPE_SECURITY); 1096 smb_hwsec_t hs; 1097 1098 if (stp == NULL) 1099 return (-1); /* errno is set for us */ 1100 1101 smb_info_bcopy(stp->smbst_hdr, &hs, sizeof (hs)); 1102 bzero(hsp, sizeof (smbios_hwsec_t)); 1103 1104 hsp->smbh_pwr_ps = SMB_HWS_PWR_PS(hs.smbhs_settings); 1105 hsp->smbh_kbd_ps = SMB_HWS_KBD_PS(hs.smbhs_settings); 1106 hsp->smbh_adm_ps = SMB_HWS_ADM_PS(hs.smbhs_settings); 1107 hsp->smbh_pan_ps = SMB_HWS_PAN_PS(hs.smbhs_settings); 1108 1109 return (stp->smbst_hdr->smbh_hdl); 1110 } 1111 1112 id_t 1113 smbios_info_boot(smbios_hdl_t *shp, smbios_boot_t *bp) 1114 { 1115 const smb_struct_t *stp = smb_lookup_type(shp, SMB_TYPE_BOOT); 1116 const smb_boot_t *b; 1117 1118 if (stp == NULL) 1119 return (-1); /* errno is set for us */ 1120 1121 bzero(bp, sizeof (smbios_boot_t)); 1122 1123 b = (smb_boot_t *)(uintptr_t)stp->smbst_hdr; 1124 1125 bp->smbt_status = b->smbbo_status[0]; 1126 bp->smbt_size = stp->smbst_hdr->smbh_len - sizeof (smb_boot_t); 1127 bp->smbt_data = bp->smbt_size ? &b->smbbo_status[1] : NULL; 1128 1129 return (stp->smbst_hdr->smbh_hdl); 1130 } 1131 1132 id_t 1133 smbios_info_ipmi(smbios_hdl_t *shp, smbios_ipmi_t *ip) 1134 { 1135 const smb_struct_t *stp = smb_lookup_type(shp, SMB_TYPE_IPMIDEV); 1136 smb_ipmi_t i; 1137 1138 if (stp == NULL) 1139 return (-1); /* errno is set for us */ 1140 1141 smb_info_bcopy(stp->smbst_hdr, &i, sizeof (i)); 1142 bzero(ip, sizeof (smbios_ipmi_t)); 1143 1144 ip->smbip_type = i.smbipm_type; 1145 ip->smbip_vers.smbv_major = SMB_IPM_SPEC_MAJOR(i.smbipm_spec); 1146 ip->smbip_vers.smbv_minor = SMB_IPM_SPEC_MINOR(i.smbipm_spec); 1147 ip->smbip_i2c = i.smbipm_i2c; 1148 ip->smbip_addr = i.smbipm_addr & ~SMB_IPM_ADDR_IO; 1149 ip->smbip_intr = i.smbipm_intr; 1150 1151 if (i.smbipm_bus != (uint8_t)-1) 1152 ip->smbip_bus = i.smbipm_bus; 1153 else 1154 ip->smbip_bus = -1u; 1155 1156 if (SMB_IPM_INFO_LSB(i.smbipm_info)) 1157 ip->smbip_addr |= 1; /* turn on least-significant bit of addr */ 1158 1159 if (i.smbipm_addr & SMB_IPM_ADDR_IO) { 1160 switch (SMB_IPM_INFO_REGS(i.smbipm_info)) { 1161 case SMB_IPM_REGS_1B: 1162 ip->smbip_regspacing = 1; 1163 break; 1164 case SMB_IPM_REGS_4B: 1165 ip->smbip_regspacing = 4; 1166 break; 1167 case SMB_IPM_REGS_16B: 1168 ip->smbip_regspacing = 16; 1169 break; 1170 default: 1171 ip->smbip_regspacing = 1; 1172 } 1173 ip->smbip_flags |= SMB_IPMI_F_IOADDR; 1174 } 1175 1176 if (SMB_IPM_INFO_ISPEC(i.smbipm_info)) 1177 ip->smbip_flags |= SMB_IPMI_F_INTRSPEC; 1178 1179 if (SMB_IPM_INFO_IPOL(i.smbipm_info) == SMB_IPM_IPOL_HI) 1180 ip->smbip_flags |= SMB_IPMI_F_INTRHIGH; 1181 1182 if (SMB_IPM_INFO_IMODE(i.smbipm_info) == SMB_IPM_IMODE_EDGE) 1183 ip->smbip_flags |= SMB_IPMI_F_INTREDGE; 1184 1185 return (stp->smbst_hdr->smbh_hdl); 1186 } 1187 1188 static boolean_t 1189 smbios_has_oemstr(smbios_hdl_t *shp, const char *oemstr) 1190 { 1191 const smb_struct_t *stp = shp->sh_structs; 1192 smb_strtab_t s; 1193 int i, j; 1194 1195 for (i = 0; i < shp->sh_nstructs; i++, stp++) { 1196 if (stp->smbst_hdr->smbh_type != SMB_TYPE_OEMSTR) 1197 continue; 1198 1199 smb_info_bcopy(stp->smbst_hdr, &s, sizeof (s)); 1200 for (j = 0; j < s.smbtb_count; j++) 1201 if (strcmp(smb_strptr(stp, j + 1), oemstr) == 0) 1202 return (B_TRUE); 1203 } 1204 1205 return (B_FALSE); 1206 } 1207 1208 static const char * 1209 smb_serial_valid(const char *serial) 1210 { 1211 char buf[MAXNAMELEN]; 1212 int i = 0; 1213 1214 if (serial == NULL) 1215 return (NULL); 1216 1217 (void) strlcpy(buf, serial, sizeof (buf)); 1218 1219 while (buf[i] != '\0' && buf[i] == ' ') 1220 i++; 1221 1222 if (buf[i] == '\0' || strstr(buf, SMB_DEFAULT1) != NULL || 1223 strstr(buf, SMB_DEFAULT2) != NULL) 1224 return (NULL); 1225 1226 return (serial); 1227 } 1228 1229 /* 1230 * Get chassis SN or product SN 1231 */ 1232 static int 1233 smb_get_sn(smbios_hdl_t *shp, const char **psnp, const char **csnp) 1234 { 1235 const smb_struct_t *stp; 1236 smbios_info_t s1, s3; 1237 1238 if (psnp == NULL || csnp == NULL) 1239 return (smb_set_errno(shp, ESMB_INVAL)); 1240 1241 *psnp = *csnp = NULL; 1242 1243 /* 1244 * If SMBIOS meets Sun's PRMS requirements, retrieve product SN 1245 * from type 1 structure, and chassis SN from type 3 structure. 1246 * Otherwise return SN in type 1 structure as chassis SN. 1247 */ 1248 1249 /* Get type 1 SN */ 1250 if ((stp = smb_lookup_type(shp, SMB_TYPE_SYSTEM)) == NULL || 1251 smbios_info_common(shp, stp->smbst_hdr->smbh_hdl, &s1) == SMB_ERR) 1252 s1.smbi_serial = NULL; 1253 1254 /* Get type 3 SN */ 1255 if ((stp = smb_lookup_type(shp, SMB_TYPE_CHASSIS)) == NULL || 1256 smbios_info_common(shp, stp->smbst_hdr->smbh_hdl, &s3) == SMB_ERR) 1257 s3.smbi_serial = NULL; 1258 1259 if (smbios_has_oemstr(shp, SMB_PRMS1)) { 1260 *psnp = smb_serial_valid(s1.smbi_serial); 1261 *csnp = smb_serial_valid(s3.smbi_serial); 1262 } else { 1263 *csnp = smb_serial_valid(s1.smbi_serial); 1264 } 1265 1266 return (0); 1267 } 1268 1269 const char * 1270 smbios_psn(smbios_hdl_t *shp) 1271 { 1272 const char *psn, *csn; 1273 1274 return (smb_get_sn(shp, &psn, &csn) == SMB_ERR ? NULL : psn); 1275 } 1276 1277 const char * 1278 smbios_csn(smbios_hdl_t *shp) 1279 { 1280 const char *psn, *csn; 1281 1282 return (smb_get_sn(shp, &psn, &csn) == SMB_ERR ? NULL : csn); 1283 } 1284 1285 int 1286 smbios_info_extprocessor(smbios_hdl_t *shp, id_t id, 1287 smbios_processor_ext_t *epp) 1288 { 1289 const smb_struct_t *stp = smb_lookup_id(shp, id); 1290 smb_processor_ext_t *exp; 1291 1292 if (stp == NULL) 1293 return (-1); /* errno is set for us */ 1294 1295 if (stp->smbst_hdr->smbh_type != SUN_OEM_EXT_PROCESSOR) 1296 return (smb_set_errno(shp, ESMB_TYPE)); 1297 1298 exp = (smb_processor_ext_t *)(uintptr_t)stp->smbst_hdr; 1299 bzero(epp, sizeof (smbios_processor_ext_t)); 1300 1301 epp->smbpe_processor = exp->smbpre_processor; 1302 epp->smbpe_fru = exp->smbpre_fru; 1303 epp->smbpe_n = exp->smbpre_n; 1304 epp->smbpe_apicid = exp->smbpre_apicid; 1305 1306 return (0); 1307 } 1308 1309 int 1310 smbios_info_extport(smbios_hdl_t *shp, id_t id, smbios_port_ext_t *eportp) 1311 { 1312 const smb_struct_t *stp = smb_lookup_id(shp, id); 1313 smb_port_ext_t *ep; 1314 1315 if (stp == NULL) 1316 return (-1); /* errno is set for us */ 1317 1318 if (stp->smbst_hdr->smbh_type != SUN_OEM_EXT_PORT) 1319 return (smb_set_errno(shp, ESMB_TYPE)); 1320 1321 ep = (smb_port_ext_t *)(uintptr_t)stp->smbst_hdr; 1322 bzero(eportp, sizeof (smbios_port_ext_t)); 1323 1324 eportp->smbporte_chassis = ep->smbpoe_chassis; 1325 eportp->smbporte_port = ep->smbpoe_port; 1326 eportp->smbporte_dtype = ep->smbpoe_dtype; 1327 eportp->smbporte_devhdl = ep->smbpoe_devhdl; 1328 eportp->smbporte_phy = ep->smbpoe_phy; 1329 1330 return (0); 1331 } 1332 1333 int 1334 smbios_info_pciexrc(smbios_hdl_t *shp, id_t id, 1335 smbios_pciexrc_t *rcp) 1336 { 1337 const smb_struct_t *stp = smb_lookup_id(shp, id); 1338 smb_pciexrc_t rc; 1339 1340 if (stp == NULL) 1341 return (-1); /* errno is set for us */ 1342 1343 if (stp->smbst_hdr->smbh_type != SUN_OEM_PCIEXRC) 1344 return (smb_set_errno(shp, ESMB_TYPE)); 1345 1346 smb_info_bcopy(stp->smbst_hdr, &rc, sizeof (rc)); 1347 bzero(rcp, sizeof (smbios_pciexrc_t)); 1348 1349 rcp->smbpcie_bb = rc.smbpciexrc_bboard; 1350 rcp->smbpcie_bdf = rc.smbpciexrc_bdf; 1351 1352 return (0); 1353 } 1354 1355 int 1356 smbios_info_extmemarray(smbios_hdl_t *shp, id_t id, smbios_memarray_ext_t *emap) 1357 { 1358 const smb_struct_t *stp = smb_lookup_id(shp, id); 1359 smb_memarray_ext_t exma; 1360 1361 if (stp == NULL) 1362 return (-1); /* errno is set for us */ 1363 1364 if (stp->smbst_hdr->smbh_type != SUN_OEM_EXT_MEMARRAY) 1365 return (smb_set_errno(shp, ESMB_TYPE)); 1366 1367 smb_info_bcopy(stp->smbst_hdr, &exma, sizeof (exma)); 1368 bzero(emap, sizeof (smbios_memarray_ext_t)); 1369 1370 emap->smbmae_ma = exma.smbmarre_ma; 1371 emap->smbmae_comp = exma.smbmarre_component; 1372 emap->smbmae_bdf = exma.smbmarre_bdf; 1373 1374 return (0); 1375 } 1376 1377 int 1378 smbios_info_extmemdevice(smbios_hdl_t *shp, id_t id, 1379 smbios_memdevice_ext_t *emdp) 1380 { 1381 const smb_struct_t *stp = smb_lookup_id(shp, id); 1382 smb_memdevice_ext_t exmd; 1383 1384 if (stp == NULL) 1385 return (-1); /* errno is set for us */ 1386 1387 if (stp->smbst_hdr->smbh_type != SUN_OEM_EXT_MEMDEVICE) 1388 return (smb_set_errno(shp, ESMB_TYPE)); 1389 1390 smb_info_bcopy(stp->smbst_hdr, &exmd, sizeof (exmd)); 1391 bzero(emdp, sizeof (smbios_memdevice_ext_t)); 1392 1393 emdp->smbmdeve_md = exmd.smbmdeve_mdev; 1394 emdp->smbmdeve_drch = exmd.smbmdeve_dchan; 1395 emdp->smbmdeve_ncs = exmd.smbmdeve_ncs; 1396 emdp->smbmdeve_cs = exmd.smbmdeve_cs; 1397 1398 return (0); 1399 } 1400 1401 int 1402 smbios_info_powersup(smbios_hdl_t *shp, id_t id, smbios_powersup_t *psup) 1403 { 1404 const smb_struct_t *stp = smb_lookup_id(shp, id); 1405 smb_powersup_t psu; 1406 1407 if (stp == NULL) 1408 return (-1); /* errno is set for us */ 1409 1410 if (stp->smbst_hdr->smbh_type != SMB_TYPE_POWERSUP) 1411 return (smb_set_errno(shp, ESMB_TYPE)); 1412 1413 /* The minimum length required by the spec is 0x10. */ 1414 if (stp->smbst_hdr->smbh_len < 0x10) 1415 return (smb_set_errno(shp, ESMB_SHORT)); 1416 1417 bzero(psup, sizeof (*psup)); 1418 smb_info_bcopy(stp->smbst_hdr, &psu, sizeof (psu)); 1419 psup->smbps_group = psu.smbpsup_group; 1420 psup->smbps_maxout = psu.smbpsup_max; 1421 1422 if (SMB_PSU_CHARS_ISHOT(psu.smbpsup_char)) 1423 psup->smbps_flags |= SMB_POWERSUP_F_HOT; 1424 if (SMB_PSU_CHARS_ISPRES(psu.smbpsup_char)) 1425 psup->smbps_flags |= SMB_POWERSUP_F_PRESENT; 1426 if (SMB_PSU_CHARS_ISUNPLUG(psu.smbpsup_char)) 1427 psup->smbps_flags |= SMB_POWERSUP_F_UNPLUG; 1428 1429 psup->smbps_ivrs = SMB_PSU_CHARS_IVRS(psu.smbpsup_char); 1430 psup->smbps_status = SMB_PSU_CHARS_STATUS(psu.smbpsup_char); 1431 psup->smbps_pstype = SMB_PSU_CHARS_TYPE(psu.smbpsup_char); 1432 1433 if (stp->smbst_hdr->smbh_len >= 0x12) { 1434 psup->smbps_vprobe = psu.smbpsup_vprobe; 1435 } else { 1436 psup->smbps_vprobe = 0xffff; 1437 } 1438 1439 if (stp->smbst_hdr->smbh_len >= 0x14) { 1440 psup->smbps_cooldev = psu.smbpsup_cooldev; 1441 } else { 1442 psup->smbps_cooldev = 0xffff; 1443 } 1444 1445 if (stp->smbst_hdr->smbh_len >= 0x16) { 1446 psup->smbps_iprobe = psu.smbpsup_iprobe; 1447 } else { 1448 psup->smbps_iprobe = 0xffff; 1449 } 1450 1451 return (0); 1452 } 1453 1454 int 1455 smbios_info_vprobe(smbios_hdl_t *shp, id_t id, smbios_vprobe_t *vprobe) 1456 { 1457 const smb_struct_t *stp = smb_lookup_id(shp, id); 1458 smb_vprobe_t vp; 1459 1460 if (stp == NULL) 1461 return (-1); /* errno is set for us */ 1462 1463 if (stp->smbst_hdr->smbh_type != SMB_TYPE_VPROBE) 1464 return (smb_set_errno(shp, ESMB_TYPE)); 1465 1466 if (stp->smbst_hdr->smbh_len < SMB_VPROBE_MINLEN) 1467 return (smb_set_errno(shp, ESMB_SHORT)); 1468 1469 bzero(vprobe, sizeof (*vprobe)); 1470 smb_info_bcopy(stp->smbst_hdr, &vp, sizeof (vp)); 1471 vprobe->smbvp_description = smb_strptr(stp, vp.smbvpr_descr); 1472 vprobe->smbvp_location = SMB_VPROBE_LOCATION(vp.smbvpr_locstat); 1473 vprobe->smbvp_status = SMB_VPROBE_STATUS(vp.smbvpr_locstat); 1474 vprobe->smbvp_maxval = vp.smbvpr_maxval; 1475 vprobe->smbvp_minval = vp.smbvpr_minval; 1476 vprobe->smbvp_resolution = vp.smbvpr_resolution; 1477 vprobe->smbvp_tolerance = vp.smbvpr_tolerance; 1478 vprobe->smbvp_accuracy = vp.smbvpr_accuracy; 1479 1480 if (stp->smbst_hdr->smbh_len >= SMB_VPROBE_NOMINAL_MINLEN) { 1481 vprobe->smbvp_nominal = vp.smbvpr_nominal; 1482 } else { 1483 vprobe->smbvp_nominal = SMB_PROBE_UNKNOWN_VALUE; 1484 } 1485 1486 return (0); 1487 } 1488 1489 int 1490 smbios_info_cooldev(smbios_hdl_t *shp, id_t id, smbios_cooldev_t *cooldev) 1491 { 1492 const smb_struct_t *stp = smb_lookup_id(shp, id); 1493 smb_cooldev_t cd; 1494 1495 if (stp == NULL) 1496 return (-1); /* errno is set for us */ 1497 1498 if (stp->smbst_hdr->smbh_type != SMB_TYPE_COOLDEV) 1499 return (smb_set_errno(shp, ESMB_TYPE)); 1500 1501 if (stp->smbst_hdr->smbh_len < SMB_COOLDEV_MINLEN) 1502 return (smb_set_errno(shp, ESMB_SHORT)); 1503 1504 bzero(cooldev, sizeof (*cooldev)); 1505 smb_info_bcopy(stp->smbst_hdr, &cd, sizeof (cd)); 1506 cooldev->smbcd_tprobe = cd.smbcdev_tprobe; 1507 cooldev->smbcd_type = SMB_COOLDEV_TYPE(cd.smbcdev_typstat); 1508 cooldev->smbcd_status = SMB_COOLDEV_STATUS(cd.smbcdev_typstat); 1509 cooldev->smbcd_group = cd.smbcdev_group; 1510 cooldev->smbcd_oem = cd.smbcdev_oem; 1511 1512 if (stp->smbst_hdr->smbh_len >= SMB_COOLDEV_NOMINAL_MINLEN) { 1513 cooldev->smbcd_nominal = cd.smbcdev_nominal; 1514 } else { 1515 cooldev->smbcd_nominal = SMB_PROBE_UNKNOWN_VALUE; 1516 } 1517 1518 /* 1519 * The description field was added in SMBIOS version 2.7. The 1520 * SMB_TYPE_COOLDEV support was only added after all of the 2.7+ fields 1521 * were added in the spec. So while a user may request an older version, 1522 * we don't have to worry about old structures and just simply skip it 1523 * if they're not asking for it. 1524 */ 1525 if (smb_libgteq(shp, SMB_VERSION_27) && 1526 smb_gteq(shp, SMB_VERSION_27) && 1527 stp->smbst_hdr->smbh_len >= SMB_COOLDEV_DESCR_MINLEN) { 1528 cooldev->smbcd_descr = smb_strptr(stp, cd.smbcdev_descr); 1529 } else { 1530 cooldev->smbcd_descr = NULL; 1531 } 1532 1533 return (0); 1534 } 1535 1536 int 1537 smbios_info_tprobe(smbios_hdl_t *shp, id_t id, smbios_tprobe_t *tprobe) 1538 { 1539 const smb_struct_t *stp = smb_lookup_id(shp, id); 1540 smb_tprobe_t tp; 1541 1542 if (stp == NULL) 1543 return (-1); /* errno is set for us */ 1544 1545 if (stp->smbst_hdr->smbh_type != SMB_TYPE_TPROBE) 1546 return (smb_set_errno(shp, ESMB_TYPE)); 1547 1548 if (stp->smbst_hdr->smbh_len < SMB_TPROBE_MINLEN) 1549 return (smb_set_errno(shp, ESMB_SHORT)); 1550 1551 bzero(tprobe, sizeof (*tprobe)); 1552 smb_info_bcopy(stp->smbst_hdr, &tp, sizeof (tp)); 1553 tprobe->smbtp_description = smb_strptr(stp, tp.smbtpr_descr); 1554 tprobe->smbtp_location = SMB_TPROBE_LOCATION(tp.smbtpr_locstat); 1555 tprobe->smbtp_status = SMB_TPROBE_STATUS(tp.smbtpr_locstat); 1556 tprobe->smbtp_maxval = tp.smbtpr_maxval; 1557 tprobe->smbtp_minval = tp.smbtpr_minval; 1558 tprobe->smbtp_resolution = tp.smbtpr_resolution; 1559 tprobe->smbtp_tolerance = tp.smbtpr_tolerance; 1560 tprobe->smbtp_accuracy = tp.smbtpr_accuracy; 1561 1562 if (stp->smbst_hdr->smbh_len >= SMB_TPROBE_NOMINAL_MINLEN) { 1563 tprobe->smbtp_nominal = tp.smbtpr_nominal; 1564 } else { 1565 tprobe->smbtp_nominal = SMB_PROBE_UNKNOWN_VALUE; 1566 } 1567 1568 return (0); 1569 } 1570 1571 int 1572 smbios_info_iprobe(smbios_hdl_t *shp, id_t id, smbios_iprobe_t *iprobe) 1573 { 1574 const smb_struct_t *sip = smb_lookup_id(shp, id); 1575 smb_iprobe_t ip; 1576 1577 if (sip == NULL) 1578 return (-1); /* errno is set for us */ 1579 1580 if (sip->smbst_hdr->smbh_type != SMB_TYPE_IPROBE) 1581 return (smb_set_errno(shp, ESMB_TYPE)); 1582 1583 if (sip->smbst_hdr->smbh_len < SMB_IPROBE_MINLEN) 1584 return (smb_set_errno(shp, ESMB_SHORT)); 1585 1586 bzero(iprobe, sizeof (*iprobe)); 1587 smb_info_bcopy(sip->smbst_hdr, &ip, sizeof (ip)); 1588 iprobe->smbip_description = smb_strptr(sip, ip.smbipr_descr); 1589 iprobe->smbip_location = SMB_IPROBE_LOCATION(ip.smbipr_locstat); 1590 iprobe->smbip_status = SMB_IPROBE_STATUS(ip.smbipr_locstat); 1591 iprobe->smbip_maxval = ip.smbipr_maxval; 1592 iprobe->smbip_minval = ip.smbipr_minval; 1593 iprobe->smbip_resolution = ip.smbipr_resolution; 1594 iprobe->smbip_tolerance = ip.smbipr_tolerance; 1595 iprobe->smbip_accuracy = ip.smbipr_accuracy; 1596 1597 if (sip->smbst_hdr->smbh_len >= SMB_IPROBE_NOMINAL_MINLEN) { 1598 iprobe->smbip_nominal = ip.smbipr_nominal; 1599 } else { 1600 iprobe->smbip_nominal = SMB_PROBE_UNKNOWN_VALUE; 1601 } 1602 1603 return (0); 1604 } 1605 1606 int 1607 smbios_info_processor_info(smbios_hdl_t *shp, id_t id, 1608 smbios_processor_info_t *proc) 1609 { 1610 const smb_struct_t *stp = smb_lookup_id(shp, id); 1611 smb_processor_info_t pi; 1612 1613 if (stp == NULL) 1614 return (-1); /* errno is set for us */ 1615 1616 if (stp->smbst_hdr->smbh_type != SMB_TYPE_PROCESSOR_INFO) 1617 return (smb_set_errno(shp, ESMB_TYPE)); 1618 1619 if (stp->smbst_hdr->smbh_len < sizeof (pi)) 1620 return (smb_set_errno(shp, ESMB_SHORT)); 1621 1622 bzero(proc, sizeof (*proc)); 1623 smb_info_bcopy(stp->smbst_hdr, &pi, sizeof (pi)); 1624 1625 if (sizeof (pi) + pi.smbpai_len > stp->smbst_hdr->smbh_len) 1626 return (smb_set_errno(shp, ESMB_CORRUPT)); 1627 1628 proc->smbpi_processor = pi.smbpai_proc; 1629 proc->smbpi_ptype = pi.smbpai_type; 1630 1631 return (0); 1632 } 1633 1634 int 1635 smbios_info_processor_riscv(smbios_hdl_t *shp, id_t id, 1636 smbios_processor_info_riscv_t *riscv) 1637 { 1638 const smb_struct_t *stp = smb_lookup_id(shp, id); 1639 const smb_processor_info_t *proc; 1640 const smb_processor_info_riscv_t *rv; 1641 1642 if (stp->smbst_hdr->smbh_type != SMB_TYPE_PROCESSOR_INFO) { 1643 return (smb_set_errno(shp, ESMB_TYPE)); 1644 } 1645 1646 if (stp->smbst_hdr->smbh_len < sizeof (*proc)) { 1647 return (smb_set_errno(shp, ESMB_SHORT)); 1648 } 1649 1650 proc = (const smb_processor_info_t *)stp->smbst_hdr; 1651 if (sizeof (*proc) + proc->smbpai_len > stp->smbst_hdr->smbh_len) { 1652 return (smb_set_errno(shp, ESMB_CORRUPT)); 1653 } 1654 1655 switch (proc->smbpai_type) { 1656 case SMB_PROCINFO_T_RV32: 1657 case SMB_PROCINFO_T_RV64: 1658 case SMB_PROCINFO_T_RV128: 1659 break; 1660 default: 1661 return (smb_set_errno(shp, ESMB_TYPE)); 1662 } 1663 1664 if (stp->smbst_hdr->smbh_len < sizeof (*proc) + sizeof (*rv)) { 1665 return (smb_set_errno(shp, ESMB_SHORT)); 1666 } 1667 rv = (const smb_processor_info_riscv_t *)&proc->smbpai_data[0]; 1668 if (rv->smbpairv_len != sizeof (*rv)) { 1669 return (smb_set_errno(shp, ESMB_CORRUPT)); 1670 } 1671 1672 bcopy(rv->smbpairv_hartid, riscv->smbpirv_hartid, 1673 sizeof (riscv->smbpirv_hartid)); 1674 bcopy(rv->smbpairv_vendid, riscv->smbpirv_vendid, 1675 sizeof (riscv->smbpirv_vendid)); 1676 bcopy(rv->smbpairv_archid, riscv->smbpirv_archid, 1677 sizeof (riscv->smbpirv_archid)); 1678 bcopy(rv->smbpairv_machid, riscv->smbpirv_machid, 1679 sizeof (riscv->smbpirv_machid)); 1680 bcopy(rv->smbpairv_metdi, riscv->smbpirv_metdi, 1681 sizeof (riscv->smbpirv_metdi)); 1682 bcopy(rv->smbpairv_mitdi, riscv->smbpirv_mitdi, 1683 sizeof (riscv->smbpirv_mitdi)); 1684 riscv->smbpirv_isa = rv->smbpairv_isa; 1685 riscv->smbpirv_privlvl = rv->smbpairv_privlvl; 1686 riscv->smbpirv_boothart = rv->smbpairv_boot; 1687 riscv->smbpirv_xlen = rv->smbpairv_xlen; 1688 riscv->smbpirv_mxlen = rv->smbpairv_mxlen; 1689 riscv->smbpirv_sxlen = rv->smbpairv_sxlen; 1690 riscv->smbpirv_uxlen = rv->smbpairv_uxlen; 1691 1692 return (0); 1693 } 1694 1695 int 1696 smbios_info_pointdev(smbios_hdl_t *shp, id_t id, smbios_pointdev_t *pd) 1697 { 1698 const smb_struct_t *stp = smb_lookup_id(shp, id); 1699 smb_pointdev_t point; 1700 1701 if (stp->smbst_hdr->smbh_type != SMB_TYPE_POINTDEV) { 1702 return (smb_set_errno(shp, ESMB_TYPE)); 1703 } 1704 1705 if (stp->smbst_hdr->smbh_len < sizeof (point)) { 1706 return (smb_set_errno(shp, ESMB_SHORT)); 1707 } 1708 1709 bzero(pd, sizeof (*pd)); 1710 smb_info_bcopy(stp->smbst_hdr, &point, sizeof (point)); 1711 1712 pd->smbpd_type = point.smbpdev_type; 1713 pd->smbpd_iface = point.smbpdev_iface; 1714 pd->smbpd_nbuttons = point.smbpdev_nbuttons; 1715 1716 return (0); 1717 } 1718 1719 int 1720 smbios_info_battery(smbios_hdl_t *shp, id_t id, smbios_battery_t *bp) 1721 { 1722 const smb_struct_t *stp = smb_lookup_id(shp, id); 1723 smb_battery_t bat; 1724 1725 if (stp->smbst_hdr->smbh_type != SMB_TYPE_BATTERY) { 1726 return (smb_set_errno(shp, ESMB_TYPE)); 1727 } 1728 1729 if (stp->smbst_hdr->smbh_len < sizeof (bat)) { 1730 return (smb_set_errno(shp, ESMB_SHORT)); 1731 } 1732 1733 bzero(bp, sizeof (*bp)); 1734 smb_info_bcopy(stp->smbst_hdr, &bat, sizeof (bat)); 1735 1736 /* 1737 * This may be superseded by the SBDS data. 1738 */ 1739 if (bat.smbbat_date != 0) { 1740 bp->smbb_date = smb_strptr(stp, bat.smbbat_date); 1741 } else { 1742 bp->smbb_date = NULL; 1743 } 1744 1745 /* 1746 * This may be superseded by the SBDS data. 1747 */ 1748 if (bat.smbbat_serial != 0) { 1749 bp->smbb_serial = smb_strptr(stp, bat.smbbat_serial); 1750 } else { 1751 bp->smbb_serial = NULL; 1752 } 1753 1754 bp->smbb_chem = bat.smbbat_chem; 1755 bp->smbb_cap = bat.smbbat_cap; 1756 if (bat.smbbat_mult > 0) { 1757 bp->smbb_cap *= bat.smbbat_mult; 1758 } 1759 bp->smbb_volt = bat.smbbat_volt; 1760 bp->smbb_version = smb_strptr(stp, bat.smbbat_version); 1761 bp->smbb_err = bat.smbbat_err; 1762 bp->smbb_ssn = bat.smbbat_ssn; 1763 bp->smbb_syear = 1980 + (bat.smbbat_sdate >> 9); 1764 bp->smbb_smonth = (bat.smbbat_sdate >> 5) & 0xf; 1765 bp->smbb_sday = bat.smbbat_sdate & 0x1f; 1766 bp->smbb_schem = smb_strptr(stp, bat.smbbat_schem); 1767 bp->smbb_oemdata = bat.smbbat_oemdata; 1768 1769 return (0); 1770 } 1771