1 /* 2 * This file and its contents are supplied under the terms of the 3 * Common Development and Distribution License ("CDDL"), version 1.0. 4 * You may only use this file in accordance with the terms of version 5 * 1.0 of the CDDL. 6 * 7 * A full copy of the text of the CDDL should have accompanied this 8 * source. A copy of the CDDL is also available via the Internet at 9 * http://www.illumos.org/license/CDDL. 10 */ 11 12 /* 13 * Copyright 2024 Oxide Computer Company 14 */ 15 16 /* 17 * Tests for SMBIOS Type 3 - SMB_TYPE_CHASSIS. 18 */ 19 20 #include "smbios_test.h" 21 22 static const char *smbios_chassis_mfg = "Shrina"; 23 static const char *smbios_chassis_vers = "7R"; 24 static const char *smbios_chassis_serial = "What's my number?"; 25 static const char *smbios_chassis_asset = "lost"; 26 static const char *smbios_chassis_sku = "Proud"; 27 static const uint32_t smbios_chassis_oem = 0x36105997; 28 static const uint8_t smbios_chassis_uheight = 7; 29 30 boolean_t 31 smbios_test_chassis_mktable_invlen_base(smbios_test_table_t *table) 32 { 33 smb_header_t hdr; 34 35 hdr.smbh_type = SMB_TYPE_CHASSIS; 36 hdr.smbh_len = sizeof (hdr); 37 38 (void) smbios_test_table_append(table, &hdr, sizeof (hdr)); 39 smbios_test_table_append_eot(table); 40 41 return (B_TRUE); 42 } 43 44 static void 45 smbios_test_chassis_mktable_fill_chassis(smb_chassis_t *ch) 46 { 47 ch->smbch_hdr.smbh_type = SMB_TYPE_CHASSIS; 48 ch->smbch_hdr.smbh_len = sizeof (*ch); 49 ch->smbch_manufacturer = 1; 50 ch->smbch_type = SMB_CHT_LUNCHBOX; 51 ch->smbch_version = 2; 52 ch->smbch_serial = 3; 53 ch->smbch_asset = 4; 54 ch->smbch_bustate = SMB_CHST_SAFE; 55 ch->smbch_psstate = SMB_CHST_NONREC; 56 ch->smbch_thstate = SMB_CHST_WARNING; 57 ch->smbch_security = SMB_CHSC_NONE; 58 ch->smbch_oemdata = htole32(smbios_chassis_oem); 59 ch->smbch_uheight = smbios_chassis_uheight; 60 ch->smbch_cords = smbios_chassis_uheight - 1; 61 ch->smbch_cn = 0; 62 ch->smbch_cm = sizeof (smb_chassis_entry_t); 63 } 64 65 static void 66 smbios_test_chassis_mktable_fill_entries(smb_chassis_entry_t *ents) 67 { 68 ents[0].smbce_type = SMB_TYPE_COOLDEV | (1 << 7); 69 ents[0].smbce_min = 1; 70 ents[0].smbce_max = 42; 71 ents[1].smbce_type = SMB_BBT_IO; 72 ents[1].smbce_min = 5; 73 ents[1].smbce_max = 123; 74 } 75 76 static void 77 smbios_test_chassis_mktable_append_strings(smbios_test_table_t *table) 78 { 79 smbios_test_table_append_string(table, smbios_chassis_mfg); 80 smbios_test_table_append_string(table, smbios_chassis_vers); 81 smbios_test_table_append_string(table, smbios_chassis_serial); 82 smbios_test_table_append_string(table, smbios_chassis_asset); 83 } 84 85 /* 86 * This is an SMBIOS 2.4-esque table. 87 */ 88 boolean_t 89 smbios_test_chassis_mktable_base(smbios_test_table_t *table) 90 { 91 smb_chassis_t ch; 92 93 smbios_test_chassis_mktable_fill_chassis(&ch); 94 (void) smbios_test_table_append(table, &ch, sizeof (ch)); 95 smbios_test_chassis_mktable_append_strings(table); 96 smbios_test_table_str_fini(table); 97 smbios_test_table_append_eot(table); 98 99 return (B_TRUE); 100 } 101 102 /* 103 * A variant of the base that doesn't include the element length becaue there 104 * are no elements. 105 */ 106 boolean_t 107 smbios_test_chassis_mktable_part(smbios_test_table_t *table) 108 { 109 smb_chassis_t ch; 110 size_t len = offsetof(smb_chassis_t, smbch_cn); 111 112 smbios_test_chassis_mktable_fill_chassis(&ch); 113 ch.smbch_hdr.smbh_len = len; 114 (void) smbios_test_table_append(table, &ch, len); 115 smbios_test_chassis_mktable_append_strings(table); 116 smbios_test_table_str_fini(table); 117 smbios_test_table_append_eot(table); 118 119 return (B_TRUE); 120 } 121 122 boolean_t 123 smbios_test_chassis_mktable_comps(smbios_test_table_t *table) 124 { 125 smb_chassis_t ch; 126 smb_chassis_entry_t ents[2]; 127 128 smbios_test_chassis_mktable_fill_chassis(&ch); 129 smbios_test_chassis_mktable_fill_entries(ents); 130 ch.smbch_hdr.smbh_len += sizeof (ents); 131 ch.smbch_cn = 2; 132 (void) smbios_test_table_append(table, &ch, sizeof (ch)); 133 smbios_test_table_append_raw(table, ents, sizeof (ents)); 134 smbios_test_chassis_mktable_append_strings(table); 135 smbios_test_table_str_fini(table); 136 smbios_test_table_append_eot(table); 137 138 return (B_TRUE); 139 } 140 141 boolean_t 142 smbios_test_chassis_mktable_sku_nocomps(smbios_test_table_t *table) 143 { 144 smb_chassis_t ch; 145 const uint8_t sku_str = 5; 146 147 smbios_test_chassis_mktable_fill_chassis(&ch); 148 ch.smbch_hdr.smbh_len++; 149 (void) smbios_test_table_append(table, &ch, sizeof (ch)); 150 smbios_test_table_append_raw(table, &sku_str, sizeof (sku_str)); 151 smbios_test_chassis_mktable_append_strings(table); 152 smbios_test_table_append_string(table, smbios_chassis_sku); 153 smbios_test_table_str_fini(table); 154 smbios_test_table_append_eot(table); 155 156 return (B_TRUE); 157 } 158 159 boolean_t 160 smbios_test_chassis_mktable_sku(smbios_test_table_t *table) 161 { 162 smb_chassis_t ch; 163 const uint8_t sku_str = 5; 164 smb_chassis_entry_t ents[2]; 165 166 ch.smbch_cn = 2; 167 168 smbios_test_chassis_mktable_fill_chassis(&ch); 169 smbios_test_chassis_mktable_fill_entries(ents); 170 ch.smbch_hdr.smbh_len += sizeof (ents) + 1; 171 (void) smbios_test_table_append(table, &ch, sizeof (ch)); 172 smbios_test_table_append_raw(table, &sku_str, sizeof (sku_str)); 173 smbios_test_chassis_mktable_append_strings(table); 174 smbios_test_table_append_string(table, smbios_chassis_sku); 175 smbios_test_table_str_fini(table); 176 smbios_test_table_append_eot(table); 177 178 return (B_TRUE); 179 } 180 181 boolean_t 182 smbios_test_chassis_verify_invlen(smbios_hdl_t *hdl) 183 { 184 smbios_struct_t sp; 185 smbios_chassis_t ch; 186 187 if (smbios_lookup_type(hdl, SMB_TYPE_CHASSIS, &sp) == -1) { 188 warnx("failed to lookup SMBIOS chassis: %s", 189 smbios_errmsg(smbios_errno(hdl))); 190 return (B_FALSE); 191 } 192 193 if (smbios_info_chassis(hdl, sp.smbstr_id, &ch) != -1) { 194 warnx("accidentally parsed invalid chassis as valid"); 195 return (B_FALSE); 196 } 197 198 if (smbios_errno(hdl) != ESMB_SHORT) { 199 warnx("encountered wrong error for chassis, expected: " 200 "0x%x, found: 0x%x", ESMB_SHORT, smbios_errno(hdl)); 201 return (B_FALSE); 202 } 203 204 return (B_TRUE); 205 } 206 207 static boolean_t 208 smbios_test_chassis_verify_common(smbios_hdl_t *hdl, smbios_struct_t *sp, 209 smbios_chassis_t *ch) 210 { 211 boolean_t ret = B_TRUE; 212 smbios_info_t info; 213 214 if (ch->smbc_oemdata != smbios_chassis_oem) { 215 warnx("chassis state mismatch, found unexpected oem data: 0x%x", 216 ch->smbc_oemdata); 217 ret = B_FALSE; 218 } 219 220 if (ch->smbc_lock != 0) { 221 warnx("chassis state mismatch, found unexpected lock: 0x%x", 222 ch->smbc_lock); 223 ret = B_FALSE; 224 } 225 226 if (ch->smbc_type != SMB_CHT_LUNCHBOX) { 227 warnx("chassis state mismatch, found unexpected type: 0x%x", 228 ch->smbc_type); 229 ret = B_FALSE; 230 } 231 232 if (ch->smbc_bustate != SMB_CHST_SAFE) { 233 warnx("chassis state mismatch, found unexpected boot state: " 234 "0x%x", ch->smbc_bustate); 235 ret = B_FALSE; 236 } 237 238 if (ch->smbc_psstate != SMB_CHST_NONREC) { 239 warnx("chassis state mismatch, found unexpected power state: " 240 "0x%x", ch->smbc_psstate); 241 ret = B_FALSE; 242 } 243 244 if (ch->smbc_thstate != SMB_CHST_WARNING) { 245 warnx("chassis state mismatch, found unexpected thermal state: " 246 "0x%x", ch->smbc_thstate); 247 ret = B_FALSE; 248 } 249 250 if (ch->smbc_security != SMB_CHSC_NONE) { 251 warnx("chassis state mismatch, found unexpected security " 252 "value: 0x%x", ch->smbc_security); 253 ret = B_FALSE; 254 } 255 256 if (ch->smbc_uheight != smbios_chassis_uheight) { 257 warnx("chassis state mismatch, found unexpected uheight value: " 258 "0x%x", ch->smbc_uheight); 259 ret = B_FALSE; 260 } 261 262 if (ch->smbc_cords != smbios_chassis_uheight - 1) { 263 warnx("chassis state mismatch, found unexpected cords value: " 264 "0x%x", ch->smbc_cords); 265 ret = B_FALSE; 266 } 267 268 if (smbios_info_common(hdl, sp->smbstr_id, &info) != 0) { 269 warnx("failed to get common chassis info: %s", 270 smbios_errmsg(smbios_errno(hdl))); 271 return (B_FALSE); 272 } 273 274 if (strcmp(info.smbi_manufacturer, smbios_chassis_mfg) != 0) { 275 warnx("chassis state mismatch, found unexpected mfg: " 276 "%s", info.smbi_manufacturer); 277 ret = B_FALSE; 278 } 279 280 if (strcmp(info.smbi_version, smbios_chassis_vers) != 0) { 281 warnx("chassis state mismatch, found unexpected version: %s", 282 info.smbi_version); 283 ret = B_FALSE; 284 } 285 286 if (strcmp(info.smbi_serial, smbios_chassis_serial) != 0) { 287 warnx("chassis state mismatch, found unexpected serial: %s", 288 info.smbi_serial); 289 ret = B_FALSE; 290 } 291 292 if (strcmp(info.smbi_asset, smbios_chassis_asset) != 0) { 293 warnx("chassis state mismatch, found unexpected asset: %s", 294 info.smbi_asset); 295 ret = B_FALSE; 296 } 297 298 return (ret); 299 } 300 301 boolean_t 302 smbios_test_chassis_verify_base(smbios_hdl_t *hdl) 303 { 304 boolean_t ret = B_TRUE; 305 smbios_struct_t sp; 306 smbios_chassis_t ch; 307 smbios_chassis_entry_t *elts; 308 uint_t nelts; 309 310 if (smbios_lookup_type(hdl, SMB_TYPE_CHASSIS, &sp) == -1) { 311 warnx("failed to lookup SMBIOS chassis: %s", 312 smbios_errmsg(smbios_errno(hdl))); 313 return (B_FALSE); 314 } 315 316 if (smbios_info_chassis(hdl, sp.smbstr_id, &ch) == -1) { 317 warnx("failed to get chassis: %s", 318 smbios_errmsg(smbios_errno(hdl))); 319 return (B_FALSE); 320 } 321 322 if (!smbios_test_chassis_verify_common(hdl, &sp, &ch)) { 323 ret = B_FALSE; 324 } 325 326 if (ch.smbc_elems != 0) { 327 warnx("chassis state mismatch, found unexpected number of " 328 "elements: 0x%x", ch.smbc_elems); 329 ret = B_FALSE; 330 } 331 332 if (strcmp(ch.smbc_sku, "") != 0) { 333 warnx("chassis state mismatch, found unexpected sku: %s", 334 ch.smbc_sku); 335 ret = B_FALSE; 336 } 337 338 if (smbios_info_chassis_elts(hdl, sp.smbstr_id, &nelts, &elts) != 0) { 339 warnx("failed to get chassis elements: %s", 340 smbios_errmsg(smbios_errno(hdl))); 341 return (B_FALSE); 342 } 343 344 if (nelts != 0) { 345 warnx("chassis state mismatch, smbios_info_chassis_elts() " 346 "returned a non-zero number of entries: %u", nelts); 347 ret = B_FALSE; 348 } 349 350 if (elts != NULL) { 351 warnx("chassis state mismatch, smbios_info_chassis_elts() " 352 "returned a non-NULL pointer: %p", elts); 353 ret = B_FALSE; 354 } 355 356 return (ret); 357 } 358 359 boolean_t 360 smbios_test_chassis_verify_sku_nocomps(smbios_hdl_t *hdl) 361 { 362 boolean_t ret = B_TRUE; 363 smbios_struct_t sp; 364 smbios_chassis_t ch; 365 smbios_chassis_entry_t *elts; 366 uint_t nelts; 367 368 if (smbios_lookup_type(hdl, SMB_TYPE_CHASSIS, &sp) == -1) { 369 warnx("failed to lookup SMBIOS chassis: %s", 370 smbios_errmsg(smbios_errno(hdl))); 371 return (B_FALSE); 372 } 373 374 if (smbios_info_chassis(hdl, sp.smbstr_id, &ch) == -1) { 375 warnx("failed to get chassis: %s", 376 smbios_errmsg(smbios_errno(hdl))); 377 return (B_FALSE); 378 } 379 380 if (!smbios_test_chassis_verify_common(hdl, &sp, &ch)) { 381 ret = B_FALSE; 382 } 383 384 if (ch.smbc_elems != 0) { 385 warnx("chassis state mismatch, found unexpected number of " 386 "elements: 0x%x", ch.smbc_elems); 387 ret = B_FALSE; 388 } 389 390 if (ch.smbc_elemlen != sizeof (smb_chassis_entry_t)) { 391 warnx("chassis state mismatch, found unexpected elemlen value: " 392 "0x%x", ch.smbc_elemlen); 393 ret = B_FALSE; 394 } 395 396 if (strcmp(ch.smbc_sku, smbios_chassis_sku) != 0) { 397 warnx("chassis state mismatch, found unexpected sku: %s", 398 ch.smbc_sku); 399 ret = B_FALSE; 400 } 401 402 if (smbios_info_chassis_elts(hdl, sp.smbstr_id, &nelts, &elts) != 0) { 403 warnx("failed to get chassis elements: %s", 404 smbios_errmsg(smbios_errno(hdl))); 405 return (B_FALSE); 406 } 407 408 if (nelts != 0) { 409 warnx("chassis state mismatch, smbios_info_chassis_elts() " 410 "returned a non-zero number of entries: %u", nelts); 411 ret = B_FALSE; 412 } 413 414 if (elts != NULL) { 415 warnx("chassis state mismatch, smbios_info_chassis_elts() " 416 "returned a non-NULL pointer: %p", elts); 417 ret = B_FALSE; 418 } 419 420 421 return (ret); 422 } 423 424 static boolean_t 425 smbios_test_chassis_verify_common_comps(smbios_hdl_t *hdl, smbios_struct_t *sp) 426 { 427 boolean_t ret = B_TRUE; 428 smbios_chassis_entry_t *elts; 429 uint_t nelts; 430 431 if (smbios_info_chassis_elts(hdl, sp->smbstr_id, &nelts, &elts) != 0) { 432 warnx("failed to get chassis elements: %s", 433 smbios_errmsg(smbios_errno(hdl))); 434 return (B_FALSE); 435 } 436 437 if (nelts != 2) { 438 warnx("chassis state mismatch, smbios_info_chassis_elts() " 439 "returned the wrong number of entries: %u", nelts); 440 return (B_FALSE); 441 } 442 443 if (elts[0].smbce_type != SMB_CELT_SMBIOS) { 444 warnx("chassis elts[0] type mismatch, found: %u", 445 elts[0].smbce_type); 446 ret = B_FALSE; 447 } 448 449 if (elts[0].smbce_elt != SMB_TYPE_COOLDEV) { 450 warnx("chassis elts[0] elt type mismatch, found: %u", 451 elts[0].smbce_elt); 452 ret = B_FALSE; 453 } 454 455 if (elts[0].smbce_min != 1) { 456 warnx("chassis elts[0] minimum number mismatch, found: %u", 457 elts[0].smbce_min); 458 ret = B_FALSE; 459 } 460 461 if (elts[0].smbce_max != 42) { 462 warnx("chassis elts[0] maximum number mismatch, found: %u", 463 elts[0].smbce_max); 464 ret = B_FALSE; 465 } 466 467 if (elts[1].smbce_type != SMB_CELT_BBOARD) { 468 warnx("chassis elts[1] type mismatch, found: %u", 469 elts[1].smbce_type); 470 ret = B_FALSE; 471 } 472 473 if (elts[1].smbce_elt != SMB_BBT_IO) { 474 warnx("chassis elts[1] elt type mismatch, found: %u", 475 elts[1].smbce_elt); 476 ret = B_FALSE; 477 } 478 479 if (elts[1].smbce_min != 5) { 480 warnx("chassis elts[1] minimum number mismatch, found: %u", 481 elts[1].smbce_min); 482 ret = B_FALSE; 483 } 484 485 if (elts[1].smbce_max != 123) { 486 warnx("chassis elts[1] maximum number mismatch, found: %u", 487 elts[1].smbce_max); 488 ret = B_FALSE; 489 } 490 return (ret); 491 } 492 493 boolean_t 494 smbios_test_chassis_verify_comps(smbios_hdl_t *hdl) 495 { 496 boolean_t ret = B_TRUE; 497 smbios_struct_t sp; 498 smbios_chassis_t ch; 499 500 if (smbios_lookup_type(hdl, SMB_TYPE_CHASSIS, &sp) == -1) { 501 warnx("failed to lookup SMBIOS chassis: %s", 502 smbios_errmsg(smbios_errno(hdl))); 503 return (B_FALSE); 504 } 505 506 if (smbios_info_chassis(hdl, sp.smbstr_id, &ch) == -1) { 507 warnx("failed to get chassis: %s", 508 smbios_errmsg(smbios_errno(hdl))); 509 return (B_FALSE); 510 } 511 512 if (!smbios_test_chassis_verify_common(hdl, &sp, &ch)) { 513 ret = B_FALSE; 514 } 515 516 if (ch.smbc_elems != 2) { 517 warnx("chassis state mismatch, found unexpected number of " 518 "elements: 0x%x", ch.smbc_elems); 519 ret = B_FALSE; 520 } 521 522 if (ch.smbc_elemlen != sizeof (smb_chassis_entry_t)) { 523 warnx("chassis state mismatch, found unexpected elemlen value: " 524 "0x%x", ch.smbc_elemlen); 525 ret = B_FALSE; 526 } 527 528 if (strcmp(ch.smbc_sku, "") != 0) { 529 warnx("chassis state mismatch, found unexpected sku: %s", 530 ch.smbc_sku); 531 ret = B_FALSE; 532 } 533 534 if (!smbios_test_chassis_verify_common_comps(hdl, &sp)) { 535 ret = B_FALSE; 536 } 537 538 return (ret); 539 } 540 541 542 boolean_t 543 smbios_test_chassis_verify_sku(smbios_hdl_t *hdl) 544 { 545 boolean_t ret = B_TRUE; 546 smbios_struct_t sp; 547 smbios_chassis_t ch; 548 549 if (smbios_lookup_type(hdl, SMB_TYPE_CHASSIS, &sp) == -1) { 550 warnx("failed to lookup SMBIOS chassis: %s", 551 smbios_errmsg(smbios_errno(hdl))); 552 return (B_FALSE); 553 } 554 555 if (smbios_info_chassis(hdl, sp.smbstr_id, &ch) == -1) { 556 warnx("failed to get chassis: %s", 557 smbios_errmsg(smbios_errno(hdl))); 558 return (B_FALSE); 559 } 560 561 if (!smbios_test_chassis_verify_common(hdl, &sp, &ch)) { 562 ret = B_FALSE; 563 } 564 565 if (ch.smbc_elems != 2) { 566 warnx("chassis state mismatch, found unexpected number of " 567 "elements: 0x%x", ch.smbc_elems); 568 ret = B_FALSE; 569 } 570 571 if (ch.smbc_elemlen != sizeof (smb_chassis_entry_t)) { 572 warnx("chassis state mismatch, found unexpected elemlen value: " 573 "0x%x", ch.smbc_elemlen); 574 ret = B_FALSE; 575 } 576 577 if (strcmp(ch.smbc_sku, smbios_chassis_sku) != 0) { 578 warnx("chassis state mismatch, found unexpected sku: %s", 579 ch.smbc_sku); 580 ret = B_FALSE; 581 } 582 583 if (!smbios_test_chassis_verify_common_comps(hdl, &sp)) { 584 ret = B_FALSE; 585 } 586 587 return (ret); 588 } 589