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