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 2021 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 boolean_t 103 smbios_test_chassis_mktable_comps(smbios_test_table_t *table) 104 { 105 smb_chassis_t ch; 106 smb_chassis_entry_t ents[2]; 107 108 smbios_test_chassis_mktable_fill_chassis(&ch); 109 smbios_test_chassis_mktable_fill_entries(ents); 110 ch.smbch_hdr.smbh_len += sizeof (ents); 111 ch.smbch_cn = 2; 112 (void) smbios_test_table_append(table, &ch, sizeof (ch)); 113 smbios_test_table_append_raw(table, ents, sizeof (ents)); 114 smbios_test_chassis_mktable_append_strings(table); 115 smbios_test_table_str_fini(table); 116 smbios_test_table_append_eot(table); 117 118 return (B_TRUE); 119 } 120 121 boolean_t 122 smbios_test_chassis_mktable_sku_nocomps(smbios_test_table_t *table) 123 { 124 smb_chassis_t ch; 125 const uint8_t sku_str = 5; 126 127 smbios_test_chassis_mktable_fill_chassis(&ch); 128 ch.smbch_hdr.smbh_len++; 129 (void) smbios_test_table_append(table, &ch, sizeof (ch)); 130 smbios_test_table_append_raw(table, &sku_str, sizeof (sku_str)); 131 smbios_test_chassis_mktable_append_strings(table); 132 smbios_test_table_append_string(table, smbios_chassis_sku); 133 smbios_test_table_str_fini(table); 134 smbios_test_table_append_eot(table); 135 136 return (B_TRUE); 137 } 138 139 boolean_t 140 smbios_test_chassis_mktable_sku(smbios_test_table_t *table) 141 { 142 smb_chassis_t ch; 143 const uint8_t sku_str = 5; 144 smb_chassis_entry_t ents[2]; 145 146 ch.smbch_cn = 2; 147 148 smbios_test_chassis_mktable_fill_chassis(&ch); 149 smbios_test_chassis_mktable_fill_entries(ents); 150 ch.smbch_hdr.smbh_len += sizeof (ents) + 1; 151 (void) smbios_test_table_append(table, &ch, sizeof (ch)); 152 smbios_test_table_append_raw(table, &sku_str, sizeof (sku_str)); 153 smbios_test_chassis_mktable_append_strings(table); 154 smbios_test_table_append_string(table, smbios_chassis_sku); 155 smbios_test_table_str_fini(table); 156 smbios_test_table_append_eot(table); 157 158 return (B_TRUE); 159 } 160 161 boolean_t 162 smbios_test_chassis_verify_invlen(smbios_hdl_t *hdl) 163 { 164 smbios_struct_t sp; 165 smbios_chassis_t ch; 166 167 if (smbios_lookup_type(hdl, SMB_TYPE_CHASSIS, &sp) == -1) { 168 warnx("failed to lookup SMBIOS chassis: %s", 169 smbios_errmsg(smbios_errno(hdl))); 170 return (B_FALSE); 171 } 172 173 if (smbios_info_chassis(hdl, sp.smbstr_id, &ch) != -1) { 174 warnx("accidentally parsed invalid chassis as valid"); 175 return (B_FALSE); 176 } 177 178 if (smbios_errno(hdl) != ESMB_SHORT) { 179 warnx("encountered wrong error for chassis, expected: " 180 "0x%x, found: 0x%x", ESMB_SHORT, smbios_errno(hdl)); 181 return (B_FALSE); 182 } 183 184 return (B_TRUE); 185 } 186 187 static boolean_t 188 smbios_test_chassis_verify_common(smbios_hdl_t *hdl, smbios_struct_t *sp, 189 smbios_chassis_t *ch) 190 { 191 boolean_t ret = B_TRUE; 192 smbios_info_t info; 193 194 if (ch->smbc_oemdata != smbios_chassis_oem) { 195 warnx("chassis state mismatch, found unexpected oem data: 0x%x", 196 ch->smbc_oemdata); 197 ret = B_FALSE; 198 } 199 200 if (ch->smbc_lock != 0) { 201 warnx("chassis state mismatch, found unexpected lock: 0x%x", 202 ch->smbc_lock); 203 ret = B_FALSE; 204 } 205 206 if (ch->smbc_type != SMB_CHT_LUNCHBOX) { 207 warnx("chassis state mismatch, found unexpected type: 0x%x", 208 ch->smbc_type); 209 ret = B_FALSE; 210 } 211 212 if (ch->smbc_bustate != SMB_CHST_SAFE) { 213 warnx("chassis state mismatch, found unexpected boot state: " 214 "0x%x", ch->smbc_bustate); 215 ret = B_FALSE; 216 } 217 218 if (ch->smbc_psstate != SMB_CHST_NONREC) { 219 warnx("chassis state mismatch, found unexpected power state: " 220 "0x%x", ch->smbc_psstate); 221 ret = B_FALSE; 222 } 223 224 if (ch->smbc_thstate != SMB_CHST_WARNING) { 225 warnx("chassis state mismatch, found unexpected thermal state: " 226 "0x%x", ch->smbc_thstate); 227 ret = B_FALSE; 228 } 229 230 if (ch->smbc_security != SMB_CHSC_NONE) { 231 warnx("chassis state mismatch, found unexpected security " 232 "value: 0x%x", ch->smbc_security); 233 ret = B_FALSE; 234 } 235 236 if (ch->smbc_uheight != smbios_chassis_uheight) { 237 warnx("chassis state mismatch, found unexpected uheight value: " 238 "0x%x", ch->smbc_uheight); 239 ret = B_FALSE; 240 } 241 242 if (ch->smbc_cords != smbios_chassis_uheight - 1) { 243 warnx("chassis state mismatch, found unexpected cords value: " 244 "0x%x", ch->smbc_cords); 245 ret = B_FALSE; 246 } 247 248 if (ch->smbc_elemlen != sizeof (smb_chassis_entry_t)) { 249 warnx("chassis state mismatch, found unexpected elemlen value: " 250 "0x%x", ch->smbc_elemlen); 251 ret = B_FALSE; 252 } 253 254 if (smbios_info_common(hdl, sp->smbstr_id, &info) != 0) { 255 warnx("failed to get common chassis info: %s", 256 smbios_errmsg(smbios_errno(hdl))); 257 return (B_FALSE); 258 } 259 260 if (strcmp(info.smbi_manufacturer, smbios_chassis_mfg) != 0) { 261 warnx("chassis state mismatch, found unexpected mfg: " 262 "%s", info.smbi_manufacturer); 263 ret = B_FALSE; 264 } 265 266 if (strcmp(info.smbi_version, smbios_chassis_vers) != 0) { 267 warnx("chassis state mismatch, found unexpected version: %s", 268 info.smbi_version); 269 ret = B_FALSE; 270 } 271 272 if (strcmp(info.smbi_serial, smbios_chassis_serial) != 0) { 273 warnx("chassis state mismatch, found unexpected serial: %s", 274 info.smbi_serial); 275 ret = B_FALSE; 276 } 277 278 if (strcmp(info.smbi_asset, smbios_chassis_asset) != 0) { 279 warnx("chassis state mismatch, found unexpected asset: %s", 280 info.smbi_asset); 281 ret = B_FALSE; 282 } 283 284 return (ret); 285 } 286 287 boolean_t 288 smbios_test_chassis_verify_base(smbios_hdl_t *hdl) 289 { 290 boolean_t ret = B_TRUE; 291 smbios_struct_t sp; 292 smbios_chassis_t ch; 293 smbios_chassis_entry_t *elts; 294 uint_t nelts; 295 296 if (smbios_lookup_type(hdl, SMB_TYPE_CHASSIS, &sp) == -1) { 297 warnx("failed to lookup SMBIOS chassis: %s", 298 smbios_errmsg(smbios_errno(hdl))); 299 return (B_FALSE); 300 } 301 302 if (smbios_info_chassis(hdl, sp.smbstr_id, &ch) == -1) { 303 warnx("failed to get chassis: %s", 304 smbios_errmsg(smbios_errno(hdl))); 305 return (B_FALSE); 306 } 307 308 if (!smbios_test_chassis_verify_common(hdl, &sp, &ch)) { 309 ret = B_FALSE; 310 } 311 312 if (ch.smbc_elems != 0) { 313 warnx("chassis state mismatch, found unexpected number of " 314 "elements: 0x%x", ch.smbc_elems); 315 ret = B_FALSE; 316 } 317 318 if (strcmp(ch.smbc_sku, "") != 0) { 319 warnx("chassis state mismatch, found unexpected sku: %s", 320 ch.smbc_sku); 321 ret = B_FALSE; 322 } 323 324 if (smbios_info_chassis_elts(hdl, sp.smbstr_id, &nelts, &elts) != 0) { 325 warnx("failed to get chassis elements: %s", 326 smbios_errmsg(smbios_errno(hdl))); 327 return (B_FALSE); 328 } 329 330 if (nelts != 0) { 331 warnx("chassis state mismatch, smbios_info_chassis_elts() " 332 "returned a non-zero number of entries: %u", nelts); 333 ret = B_FALSE; 334 } 335 336 if (elts != NULL) { 337 warnx("chassis state mismatch, smbios_info_chassis_elts() " 338 "returned a non-NULL pointer: %p", elts); 339 ret = B_FALSE; 340 } 341 342 return (ret); 343 } 344 345 boolean_t 346 smbios_test_chassis_verify_sku_nocomps(smbios_hdl_t *hdl) 347 { 348 boolean_t ret = B_TRUE; 349 smbios_struct_t sp; 350 smbios_chassis_t ch; 351 smbios_chassis_entry_t *elts; 352 uint_t nelts; 353 354 if (smbios_lookup_type(hdl, SMB_TYPE_CHASSIS, &sp) == -1) { 355 warnx("failed to lookup SMBIOS chassis: %s", 356 smbios_errmsg(smbios_errno(hdl))); 357 return (B_FALSE); 358 } 359 360 if (smbios_info_chassis(hdl, sp.smbstr_id, &ch) == -1) { 361 warnx("failed to get chassis: %s", 362 smbios_errmsg(smbios_errno(hdl))); 363 return (B_FALSE); 364 } 365 366 if (!smbios_test_chassis_verify_common(hdl, &sp, &ch)) { 367 ret = B_FALSE; 368 } 369 370 if (ch.smbc_elems != 0) { 371 warnx("chassis state mismatch, found unexpected number of " 372 "elements: 0x%x", ch.smbc_elems); 373 ret = B_FALSE; 374 } 375 376 if (strcmp(ch.smbc_sku, smbios_chassis_sku) != 0) { 377 warnx("chassis state mismatch, found unexpected sku: %s", 378 ch.smbc_sku); 379 ret = B_FALSE; 380 } 381 382 if (smbios_info_chassis_elts(hdl, sp.smbstr_id, &nelts, &elts) != 0) { 383 warnx("failed to get chassis elements: %s", 384 smbios_errmsg(smbios_errno(hdl))); 385 return (B_FALSE); 386 } 387 388 if (nelts != 0) { 389 warnx("chassis state mismatch, smbios_info_chassis_elts() " 390 "returned a non-zero number of entries: %u", nelts); 391 ret = B_FALSE; 392 } 393 394 if (elts != NULL) { 395 warnx("chassis state mismatch, smbios_info_chassis_elts() " 396 "returned a non-NULL pointer: %p", elts); 397 ret = B_FALSE; 398 } 399 400 401 return (ret); 402 } 403 404 static boolean_t 405 smbios_test_chassis_verify_common_comps(smbios_hdl_t *hdl, smbios_struct_t *sp) 406 { 407 boolean_t ret = B_TRUE; 408 smbios_chassis_entry_t *elts; 409 uint_t nelts; 410 411 if (smbios_info_chassis_elts(hdl, sp->smbstr_id, &nelts, &elts) != 0) { 412 warnx("failed to get chassis elements: %s", 413 smbios_errmsg(smbios_errno(hdl))); 414 return (B_FALSE); 415 } 416 417 if (nelts != 2) { 418 warnx("chassis state mismatch, smbios_info_chassis_elts() " 419 "returned the wrong number of entries: %u", nelts); 420 return (B_FALSE); 421 } 422 423 if (elts[0].smbce_type != SMB_CELT_SMBIOS) { 424 warnx("chassis elts[0] type mismatch, found: %u", 425 elts[0].smbce_type); 426 ret = B_FALSE; 427 } 428 429 if (elts[0].smbce_elt != SMB_TYPE_COOLDEV) { 430 warnx("chassis elts[0] elt type mismatch, found: %u", 431 elts[0].smbce_elt); 432 ret = B_FALSE; 433 } 434 435 if (elts[0].smbce_min != 1) { 436 warnx("chassis elts[0] minimum number mismatch, found: %u", 437 elts[0].smbce_min); 438 ret = B_FALSE; 439 } 440 441 if (elts[0].smbce_max != 42) { 442 warnx("chassis elts[0] maximum number mismatch, found: %u", 443 elts[0].smbce_max); 444 ret = B_FALSE; 445 } 446 447 if (elts[1].smbce_type != SMB_CELT_BBOARD) { 448 warnx("chassis elts[1] type mismatch, found: %u", 449 elts[1].smbce_type); 450 ret = B_FALSE; 451 } 452 453 if (elts[1].smbce_elt != SMB_BBT_IO) { 454 warnx("chassis elts[1] elt type mismatch, found: %u", 455 elts[1].smbce_elt); 456 ret = B_FALSE; 457 } 458 459 if (elts[1].smbce_min != 5) { 460 warnx("chassis elts[1] minimum number mismatch, found: %u", 461 elts[1].smbce_min); 462 ret = B_FALSE; 463 } 464 465 if (elts[1].smbce_max != 123) { 466 warnx("chassis elts[1] maximum number mismatch, found: %u", 467 elts[1].smbce_max); 468 ret = B_FALSE; 469 } 470 return (ret); 471 } 472 473 boolean_t 474 smbios_test_chassis_verify_comps(smbios_hdl_t *hdl) 475 { 476 boolean_t ret = B_TRUE; 477 smbios_struct_t sp; 478 smbios_chassis_t ch; 479 480 if (smbios_lookup_type(hdl, SMB_TYPE_CHASSIS, &sp) == -1) { 481 warnx("failed to lookup SMBIOS chassis: %s", 482 smbios_errmsg(smbios_errno(hdl))); 483 return (B_FALSE); 484 } 485 486 if (smbios_info_chassis(hdl, sp.smbstr_id, &ch) == -1) { 487 warnx("failed to get chassis: %s", 488 smbios_errmsg(smbios_errno(hdl))); 489 return (B_FALSE); 490 } 491 492 if (!smbios_test_chassis_verify_common(hdl, &sp, &ch)) { 493 ret = B_FALSE; 494 } 495 496 if (ch.smbc_elems != 2) { 497 warnx("chassis state mismatch, found unexpected number of " 498 "elements: 0x%x", ch.smbc_elems); 499 ret = B_FALSE; 500 } 501 502 if (strcmp(ch.smbc_sku, "") != 0) { 503 warnx("chassis state mismatch, found unexpected sku: %s", 504 ch.smbc_sku); 505 ret = B_FALSE; 506 } 507 508 if (!smbios_test_chassis_verify_common_comps(hdl, &sp)) { 509 ret = B_FALSE; 510 } 511 512 return (ret); 513 } 514 515 516 boolean_t 517 smbios_test_chassis_verify_sku(smbios_hdl_t *hdl) 518 { 519 boolean_t ret = B_TRUE; 520 smbios_struct_t sp; 521 smbios_chassis_t ch; 522 523 if (smbios_lookup_type(hdl, SMB_TYPE_CHASSIS, &sp) == -1) { 524 warnx("failed to lookup SMBIOS chassis: %s", 525 smbios_errmsg(smbios_errno(hdl))); 526 return (B_FALSE); 527 } 528 529 if (smbios_info_chassis(hdl, sp.smbstr_id, &ch) == -1) { 530 warnx("failed to get chassis: %s", 531 smbios_errmsg(smbios_errno(hdl))); 532 return (B_FALSE); 533 } 534 535 if (!smbios_test_chassis_verify_common(hdl, &sp, &ch)) { 536 ret = B_FALSE; 537 } 538 539 if (ch.smbc_elems != 2) { 540 warnx("chassis state mismatch, found unexpected number of " 541 "elements: 0x%x", ch.smbc_elems); 542 ret = B_FALSE; 543 } 544 545 if (strcmp(ch.smbc_sku, smbios_chassis_sku) != 0) { 546 warnx("chassis state mismatch, found unexpected sku: %s", 547 ch.smbc_sku); 548 ret = B_FALSE; 549 } 550 551 if (!smbios_test_chassis_verify_common_comps(hdl, &sp)) { 552 ret = B_FALSE; 553 } 554 555 return (ret); 556 } 557