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 (c) 2018, Joyent, Inc. 14 * Copyright 2020 Oxide Computer Company 15 */ 16 17 /* 18 * Basic testing of the SMBIOS 3.2 Slot extensions. 19 */ 20 21 #include "smbios_test.h" 22 23 static const char *smbios_test_name = "The One Slot"; 24 static uint8_t smbios_slot_bus = 0x42; 25 static uint8_t smbios_slot_df = 0x23; 26 static uint8_t smbios_slot_info = 0x65; 27 static uint16_t smbios_slot_pitch = 0x12af; 28 29 static void 30 smbios_test_slot_fill(smb_slot_t *slot) 31 { 32 bzero(slot, sizeof (smb_slot_t)); 33 slot->smbsl_hdr.smbh_type = SMB_TYPE_SLOT; 34 slot->smbsl_hdr.smbh_len = sizeof (smb_slot_t); 35 slot->smbsl_name = 1; 36 slot->smbsl_type = SMB_SLT_PCIE3G16; 37 slot->smbsl_width = SMB_SLW_16X; 38 slot->smbsl_length = SMB_SLL_SHORT; 39 slot->smbsl_id = htole16(1); 40 slot->smbsl_ch1 = SMB_SLCH1_33V; 41 slot->smbsl_ch2 = SMB_SLCH2_PME; 42 slot->smbsl_sg = htole16(1); 43 slot->smbsl_bus = smbios_slot_bus; 44 slot->smbsl_df = smbios_slot_df; 45 slot->smbsl_dbw = SMB_SLW_16X; 46 } 47 48 boolean_t 49 smbios_test_slot_mktable(smbios_test_table_t *table) 50 { 51 smb_slot_t slot; 52 smb_slot_peer_t peers[2]; 53 const uint8_t endstring = 0; 54 55 smbios_test_slot_fill(&slot); 56 57 slot.smbsl_hdr.smbh_len += sizeof (peers); 58 slot.smbsl_npeers = 2; 59 60 peers[0].smbspb_group_no = htole16(1); 61 peers[0].smbspb_bus = 0x42; 62 peers[0].smbspb_df = 0x42; 63 peers[0].smbspb_width = SMB_SLW_8X; 64 65 peers[1].smbspb_group_no = htole16(1); 66 peers[1].smbspb_bus = 0x23; 67 peers[1].smbspb_df = 0x31; 68 peers[1].smbspb_width = SMB_SLW_8X; 69 70 (void) smbios_test_table_append(table, &slot, sizeof (slot)); 71 (void) smbios_test_table_append_raw(table, peers, sizeof (peers)); 72 (void) smbios_test_table_append_string(table, smbios_test_name); 73 (void) smbios_test_table_append_raw(table, &endstring, 74 sizeof (endstring)); 75 76 smbios_test_table_append_eot(table); 77 78 return (B_TRUE); 79 } 80 81 /* 82 * 3.4 introduced additional data after peers. This verison constructs a variant 83 * with no peers. 84 */ 85 boolean_t 86 smbios_test_slot_mktable_34_nopeers(smbios_test_table_t *table) 87 { 88 smb_slot_t slot; 89 smb_slot_cont_t cont; 90 const uint8_t endstring = 0; 91 92 smbios_test_slot_fill(&slot); 93 slot.smbsl_hdr.smbh_len = SMB_SLOT_CONT_START + sizeof (cont); 94 95 cont.smbsl_info = smbios_slot_info; 96 cont.smbsl_pwidth = SMB_SLW_32X; 97 cont.smbsl_pitch = htole16(smbios_slot_pitch); 98 99 (void) smbios_test_table_append(table, &slot, sizeof (slot)); 100 /* 101 * Append a raw zero to fill in the gaps that the peers would have had 102 * so the cont structure starts at the right offset. 103 */ 104 (void) smbios_test_table_append_raw(table, &endstring, 105 sizeof (endstring)); 106 (void) smbios_test_table_append_raw(table, &cont, sizeof (cont)); 107 (void) smbios_test_table_append_string(table, smbios_test_name); 108 (void) smbios_test_table_append_raw(table, &endstring, 109 sizeof (endstring)); 110 smbios_test_table_append_eot(table); 111 return (B_TRUE); 112 } 113 114 boolean_t 115 smbios_test_slot_mktable_34_peers(smbios_test_table_t *table) 116 { 117 smb_slot_t slot; 118 smb_slot_cont_t cont; 119 smb_slot_peer_t peers[1]; 120 const uint8_t endstring = 0; 121 122 smbios_test_slot_fill(&slot); 123 slot.smbsl_npeers = 1; 124 slot.smbsl_hdr.smbh_len = SMB_SLOT_CONT_START + 5 * slot.smbsl_npeers + 125 sizeof (cont); 126 127 peers[0].smbspb_group_no = htole16(1); 128 peers[0].smbspb_bus = 0x42; 129 peers[0].smbspb_df = 0x9a; 130 peers[0].smbspb_width = SMB_SLW_8X; 131 132 cont.smbsl_info = smbios_slot_info; 133 cont.smbsl_pwidth = SMB_SLW_32X; 134 cont.smbsl_pitch = htole16(smbios_slot_pitch); 135 136 (void) smbios_test_table_append(table, &slot, sizeof (slot)); 137 (void) smbios_test_table_append_raw(table, peers, sizeof (peers)); 138 (void) smbios_test_table_append_raw(table, &endstring, 139 sizeof (endstring)); 140 (void) smbios_test_table_append_raw(table, &cont, sizeof (cont)); 141 (void) smbios_test_table_append_string(table, smbios_test_name); 142 (void) smbios_test_table_append_raw(table, &endstring, 143 sizeof (endstring)); 144 smbios_test_table_append_eot(table); 145 return (B_TRUE); 146 } 147 148 149 static boolean_t 150 smbios_test_slot_common(smbios_slot_t *slot) 151 { 152 uint_t errs = 0; 153 154 if (strcmp(slot->smbl_name, smbios_test_name) != 0) { 155 warnx("slot name mismatch, expected %s, found %s", 156 smbios_test_name, slot->smbl_name); 157 errs++; 158 } 159 160 if (slot->smbl_type != SMB_SLT_PCIE3G16) { 161 warnx("incorrect slot type, found %u", slot->smbl_type); 162 errs++; 163 } 164 165 if (slot->smbl_width != SMB_SLW_16X) { 166 warnx("incorrect slot width, found %u", slot->smbl_width); 167 errs++; 168 } 169 170 if (slot->smbl_length != SMB_SLL_SHORT) { 171 warnx("incorrect slot length, found %u", slot->smbl_length); 172 errs++; 173 } 174 175 if (slot->smbl_dbw != SMB_SLW_16X) { 176 warnx("incorrect slot data bus width, found %u", 177 slot->smbl_dbw); 178 errs++; 179 } 180 181 if (slot->smbl_bus != smbios_slot_bus) { 182 warnx("incorrect slot bus id, found 0x%x\n", slot->smbl_bus); 183 } 184 185 if (slot->smbl_df != smbios_slot_df) { 186 warnx("incorrect slot df id, found 0x%x\n", slot->smbl_df); 187 } 188 189 if (errs > 0) { 190 return (B_FALSE); 191 } 192 193 return (B_TRUE); 194 } 195 196 boolean_t 197 smbios_test_slot_verify(smbios_hdl_t *hdl) 198 { 199 smbios_struct_t sp; 200 smbios_slot_t slot; 201 uint_t npeers; 202 smbios_slot_peer_t *peers; 203 uint_t errs = 0; 204 205 if (smbios_lookup_type(hdl, SMB_TYPE_SLOT, &sp) == -1) { 206 warnx("failed to lookup SMBIOS slot: %s", 207 smbios_errmsg(smbios_errno(hdl))); 208 return (B_FALSE); 209 } 210 211 if (smbios_info_slot(hdl, sp.smbstr_id, &slot) != 0) { 212 warnx("failed to get SMBIOS slot info: %s", 213 smbios_errmsg(smbios_errno(hdl))); 214 return (B_FALSE); 215 } 216 217 if (!smbios_test_slot_common(&slot)) { 218 errs++; 219 } 220 221 if (slot.smbl_npeers != 2) { 222 warnx("incorrect number of slot peers, found %u", 223 slot.smbl_npeers); 224 errs++; 225 } 226 227 if (smbios_info_slot_peers(hdl, sp.smbstr_id, &npeers, &peers) != 0) { 228 warnx("failed to get SMBIOS peer info: %s", 229 smbios_errmsg(smbios_errno(hdl))); 230 return (B_FALSE); 231 } 232 233 if (npeers != 2) { 234 warnx("got wrong number of slot peers: %u", npeers); 235 return (B_FALSE); 236 } 237 238 if (peers[0].smblp_group != 1) { 239 warnx("incorrect group for peer 0: %u", peers[0].smblp_group); 240 errs++; 241 } 242 243 if (peers[0].smblp_data_width != SMB_SLW_8X) { 244 warnx("incorrect data width for peer 0: %u", 245 peers[0].smblp_data_width); 246 errs++; 247 } 248 249 if (peers[0].smblp_device != (0x42 >> 3)) { 250 warnx("incorrect PCI device for peer 0: %u", 251 peers[0].smblp_device); 252 errs++; 253 } 254 255 if (peers[0].smblp_function != (0x42 & 0x7)) { 256 warnx("incorrect PCI function for peer 0: %u", 257 peers[0].smblp_function); 258 errs++; 259 } 260 261 if (peers[1].smblp_group != 1) { 262 warnx("incorrect group for peer 1: %u", peers[1].smblp_group); 263 errs++; 264 } 265 266 if (peers[1].smblp_device != (0x31 >> 3)) { 267 warnx("incorrect PCI device for peer 1: %u", 268 peers[1].smblp_device); 269 errs++; 270 } 271 272 if (peers[1].smblp_function != (0x31 & 0x7)) { 273 warnx("incorrect PCI function for peer 1: %u", 274 peers[1].smblp_function); 275 errs++; 276 } 277 278 if (peers[1].smblp_data_width != SMB_SLW_8X) { 279 warnx("incorrect data width for peer 1: %u", 280 peers[1].smblp_data_width); 281 errs++; 282 } 283 284 smbios_info_slot_peers_free(hdl, npeers, peers); 285 286 if (slot.smbl_info != 0) { 287 warnx("found wrong slot info: 0x%x", slot.smbl_info); 288 errs++; 289 } 290 291 if (slot.smbl_pwidth != 0) { 292 warnx("found wrong slot physical width: 0x%x", 293 slot.smbl_pwidth); 294 errs++; 295 } 296 297 if (slot.smbl_pitch != 0) { 298 warnx("found wrong slot pitch: 0x%x", slot.smbl_pitch); 299 errs++; 300 } 301 302 if (errs > 0) { 303 return (B_FALSE); 304 } 305 306 return (B_TRUE); 307 } 308 309 boolean_t 310 smbios_test_slot_verify_34_nopeers(smbios_hdl_t *hdl) 311 { 312 smbios_struct_t sp; 313 smbios_slot_t slot; 314 uint_t npeers; 315 smbios_slot_peer_t *peers; 316 uint_t errs = 0; 317 318 if (smbios_lookup_type(hdl, SMB_TYPE_SLOT, &sp) == -1) { 319 warnx("failed to lookup SMBIOS slot: %s", 320 smbios_errmsg(smbios_errno(hdl))); 321 return (B_FALSE); 322 } 323 324 if (smbios_info_slot(hdl, sp.smbstr_id, &slot) != 0) { 325 warnx("failed to get SMBIOS slot info: %s", 326 smbios_errmsg(smbios_errno(hdl))); 327 return (B_FALSE); 328 } 329 330 if (!smbios_test_slot_common(&slot)) { 331 errs++; 332 } 333 334 if (slot.smbl_npeers != 0) { 335 warnx("incorrect number of slot peers, found %u", 336 slot.smbl_npeers); 337 errs++; 338 } 339 340 if (smbios_info_slot_peers(hdl, sp.smbstr_id, &npeers, &peers) != 0) { 341 warnx("failed to get SMBIOS peer info: %s", 342 smbios_errmsg(smbios_errno(hdl))); 343 return (B_FALSE); 344 } 345 346 if (npeers != 0) { 347 warnx("got wrong number of slot peers: %u", npeers); 348 errs++; 349 } 350 351 if (peers != NULL) { 352 warnx("expected NULL peers pointer, but found %p", peers); 353 errs++; 354 } 355 356 smbios_info_slot_peers_free(hdl, npeers, peers); 357 358 if (slot.smbl_info != smbios_slot_info) { 359 warnx("found wrong slot info: 0x%x, expected 0x%x", 360 slot.smbl_info, smbios_slot_info); 361 errs++; 362 } 363 364 if (slot.smbl_pwidth != SMB_SLW_32X) { 365 warnx("found wrong slot physical width: 0x%x, expected 0x%x", 366 slot.smbl_pwidth, SMB_SLW_32X); 367 errs++; 368 } 369 370 if (slot.smbl_pitch != smbios_slot_pitch) { 371 warnx("found wrong slot pitch: 0x%x, expected 0x%x", 372 slot.smbl_pitch, smbios_slot_pitch); 373 errs++; 374 } 375 376 if (errs > 0) { 377 return (B_FALSE); 378 } 379 380 return (B_TRUE); 381 } 382 383 boolean_t 384 smbios_test_slot_verify_34_peers(smbios_hdl_t *hdl) 385 { 386 smbios_struct_t sp; 387 smbios_slot_t slot; 388 uint_t npeers; 389 smbios_slot_peer_t *peers; 390 uint_t errs = 0; 391 392 if (smbios_lookup_type(hdl, SMB_TYPE_SLOT, &sp) == -1) { 393 warnx("failed to lookup SMBIOS slot: %s", 394 smbios_errmsg(smbios_errno(hdl))); 395 return (B_FALSE); 396 } 397 398 if (smbios_info_slot(hdl, sp.smbstr_id, &slot) != 0) { 399 warnx("failed to get SMBIOS slot info: %s", 400 smbios_errmsg(smbios_errno(hdl))); 401 return (B_FALSE); 402 } 403 404 if (!smbios_test_slot_common(&slot)) { 405 errs++; 406 } 407 408 if (slot.smbl_npeers != 1) { 409 warnx("incorrect number of slot peers, found %u", 410 slot.smbl_npeers); 411 errs++; 412 } 413 414 if (smbios_info_slot_peers(hdl, sp.smbstr_id, &npeers, &peers) != 0) { 415 warnx("failed to get SMBIOS peer info: %s", 416 smbios_errmsg(smbios_errno(hdl))); 417 return (B_FALSE); 418 } 419 420 if (npeers != 1) { 421 warnx("got wrong number of slot peers: %u", npeers); 422 errs++; 423 } 424 425 if (peers[0].smblp_group != 1) { 426 warnx("incorrect group for peer 0: %u", peers[0].smblp_group); 427 errs++; 428 } 429 430 if (peers[0].smblp_data_width != SMB_SLW_8X) { 431 warnx("incorrect data width for peer 0: %u", 432 peers[0].smblp_data_width); 433 errs++; 434 } 435 436 if (peers[0].smblp_bus != 0x42) { 437 warnx("incorrect PCI bus for peer 0: %u", 438 peers[0].smblp_bus); 439 errs++; 440 } 441 442 if (peers[0].smblp_device != (0x9a >> 3)) { 443 warnx("incorrect PCI device for peer 0: %u", 444 peers[0].smblp_device); 445 errs++; 446 } 447 448 if (peers[0].smblp_function != (0x9a & 0x7)) { 449 warnx("incorrect PCI function for peer 0: %u", 450 peers[0].smblp_function); 451 errs++; 452 } 453 454 smbios_info_slot_peers_free(hdl, npeers, peers); 455 456 if (slot.smbl_info != smbios_slot_info) { 457 warnx("found wrong slot info: 0x%x, expected 0x%x", 458 slot.smbl_info, smbios_slot_info); 459 errs++; 460 } 461 462 if (slot.smbl_pwidth != SMB_SLW_32X) { 463 warnx("found wrong slot physical width: 0x%x, expected 0x%x", 464 slot.smbl_pwidth, SMB_SLW_32X); 465 errs++; 466 } 467 468 if (slot.smbl_pitch != smbios_slot_pitch) { 469 warnx("found wrong slot pitch: 0x%x, expected 0x%x", 470 slot.smbl_pitch, smbios_slot_pitch); 471 errs++; 472 } 473 474 if (errs > 0) { 475 return (B_FALSE); 476 } 477 478 return (B_TRUE); 479 } 480