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 46 - SMB_TYPE_STRPROP. 18 */ 19 20 #include "smbios_test.h" 21 22 static const char *smbios_fwinfo_name = "Sheikah Slate"; 23 static const char *smbios_fwinfo_vers = "1.3.1"; 24 static const char *smbios_fwinfo_id = "ganon"; 25 static const char *smbios_fwinfo_reldate = "2017-03-03"; 26 static const char *smbios_fwinfo_mfg = "The Goddess Hylia"; 27 static const char *smbios_fwinfo_lsv = "zelda"; 28 static const uint64_t smbios_fwinfo_size = 0xb0111b; 29 static const uint_t smbios_fwinfo_ncomps = 23; 30 static const uint8_t smbios_fwinfo_versid = 0x66; 31 32 static void 33 smbios_test_fwinfo_mktable_common_fwinfo(smb_fwinfo_t *fw) 34 { 35 fw->smbfwii_hdr.smbh_type = SMB_TYPE_FWINFO; 36 fw->smbfwii_hdr.smbh_len = sizeof (*fw); 37 fw->smbfwii_name = 1; 38 fw->smbfwii_vers = 2; 39 fw->smbfwii_vers_fmt = smbios_fwinfo_versid; 40 fw->smbfwii_id = 3; 41 fw->smbfwii_id_fmt = smbios_fwinfo_versid; 42 fw->smbfwii_reldate = 4; 43 fw->smbfwii_mfg = 5; 44 fw->smbfwii_lsv = 6; 45 fw->smbfwii_imgsz = htole64(smbios_fwinfo_size); 46 fw->smbfwii_chars = SMB_FWC_WP; 47 fw->smbfwii_state = SMB_FWS_UA_OFFLINE; 48 fw->smbfwii_ncomps = 0; 49 } 50 51 static void 52 smbios_test_fwinfo_mktable_common_fini(smbios_test_table_t *table) 53 { 54 smbios_test_table_append_string(table, smbios_fwinfo_name); 55 smbios_test_table_append_string(table, smbios_fwinfo_vers); 56 smbios_test_table_append_string(table, smbios_fwinfo_id); 57 smbios_test_table_append_string(table, smbios_fwinfo_reldate); 58 smbios_test_table_append_string(table, smbios_fwinfo_mfg); 59 smbios_test_table_append_string(table, smbios_fwinfo_lsv); 60 smbios_test_table_str_fini(table); 61 smbios_test_table_append_eot(table); 62 } 63 64 /* 65 * Generate a table that's too short to get basic info. 66 */ 67 boolean_t 68 smbios_test_fwinfo_mktable_invlen_base(smbios_test_table_t *table) 69 { 70 smb_header_t hdr; 71 72 hdr.smbh_type = SMB_TYPE_FWINFO; 73 hdr.smbh_len = sizeof (hdr); 74 75 (void) smbios_test_table_append(table, &hdr, sizeof (hdr)); 76 smbios_test_table_append_eot(table); 77 78 return (B_TRUE); 79 } 80 81 /* 82 * Generate a table where the table is too short for a specified number of 83 * components. 84 */ 85 boolean_t 86 smbios_test_fwinfo_mktable_invlen_comps(smbios_test_table_t *table) 87 { 88 smb_fwinfo_t fw; 89 90 smbios_test_fwinfo_mktable_common_fwinfo(&fw); 91 fw.smbfwii_ncomps = smbios_fwinfo_ncomps; 92 (void) smbios_test_table_append(table, &fw, sizeof (fw)); 93 smbios_test_fwinfo_mktable_common_fini(table); 94 95 return (B_TRUE); 96 } 97 98 boolean_t 99 smbios_test_fwinfo_mktable_nocomps(smbios_test_table_t *table) 100 { 101 smb_fwinfo_t fw; 102 103 smbios_test_fwinfo_mktable_common_fwinfo(&fw); 104 (void) smbios_test_table_append(table, &fw, sizeof (fw)); 105 smbios_test_fwinfo_mktable_common_fini(table); 106 107 return (B_TRUE); 108 } 109 110 boolean_t 111 smbios_test_fwinfo_mktable_comps(smbios_test_table_t *table) 112 { 113 smb_fwinfo_t fw; 114 115 smbios_test_fwinfo_mktable_common_fwinfo(&fw); 116 117 fw.smbfwii_hdr.smbh_len += smbios_fwinfo_ncomps * sizeof (uint16_t); 118 fw.smbfwii_ncomps = smbios_fwinfo_ncomps; 119 (void) smbios_test_table_append(table, &fw, sizeof (fw)); 120 121 for (uint_t i = 0; i < fw.smbfwii_ncomps; i++) { 122 uint16_t comp = 0x2300 + i; 123 124 smbios_test_table_append_raw(table, &comp, sizeof (comp)); 125 } 126 smbios_test_fwinfo_mktable_common_fini(table); 127 128 return (B_TRUE); 129 } 130 131 boolean_t 132 smbios_test_fwinfo_verify_badtype(smbios_hdl_t *hdl) 133 { 134 smbios_struct_t sp; 135 smbios_fwinfo_t fw; 136 137 if (smbios_lookup_type(hdl, SMB_TYPE_MEMDEVICE, &sp) == -1) { 138 warnx("failed to lookup SMBIOS memory device: %s", 139 smbios_errmsg(smbios_errno(hdl))); 140 return (B_FALSE); 141 } 142 143 if (smbios_info_fwinfo(hdl, sp.smbstr_id, &fw) != -1) { 144 warnx("accidentally parsed invalid fwinfo information as " 145 "valid"); 146 return (B_FALSE); 147 } 148 149 if (smbios_errno(hdl) != ESMB_TYPE) { 150 warnx("encountered wrong error for fwinfo, expected: " 151 "0x%x, found: 0x%x", ESMB_SHORT, smbios_errno(hdl)); 152 return (B_FALSE); 153 } 154 155 return (B_TRUE); 156 } 157 158 boolean_t 159 smbios_test_fwinfo_verify_invlen_base(smbios_hdl_t *hdl) 160 { 161 smbios_struct_t sp; 162 smbios_fwinfo_t fw; 163 164 if (smbios_lookup_type(hdl, SMB_TYPE_FWINFO, &sp) == -1) { 165 warnx("failed to lookup SMBIOS fwinfo: %s", 166 smbios_errmsg(smbios_errno(hdl))); 167 return (B_FALSE); 168 } 169 170 if (smbios_info_fwinfo(hdl, sp.smbstr_id, &fw) != -1) { 171 warnx("accidentally parsed invalid fwinfo information as " 172 "valid"); 173 return (B_FALSE); 174 } 175 176 if (smbios_errno(hdl) != ESMB_SHORT) { 177 warnx("encountered wrong error for fwinfo, expected: " 178 "0x%x, found: 0x%x", ESMB_SHORT, smbios_errno(hdl)); 179 return (B_FALSE); 180 } 181 182 return (B_TRUE); 183 } 184 185 static boolean_t 186 smbios_test_fwinfo_verify_common(smbios_hdl_t *hdl, smbios_struct_t *sp, 187 const smbios_fwinfo_t *fw) 188 { 189 boolean_t ret = B_TRUE; 190 smbios_info_t info; 191 192 if (strcmp(fw->smbfw_name, smbios_fwinfo_name) != 0) { 193 warnx("firmware inventory name mismatch, found %s", 194 fw->smbfw_name); 195 ret = B_FALSE; 196 } 197 198 if (strcmp(fw->smbfw_id, smbios_fwinfo_id) != 0) { 199 warnx("firmware inventory id mismatch, found %s", 200 fw->smbfw_id); 201 ret = B_FALSE; 202 } 203 204 if (strcmp(fw->smbfw_reldate, smbios_fwinfo_reldate) != 0) { 205 warnx("firmware inventory release date mismatch, found %s", 206 fw->smbfw_reldate); 207 ret = B_FALSE; 208 } 209 210 if (strcmp(fw->smbfw_lsv, smbios_fwinfo_lsv) != 0) { 211 warnx("firmware inventory lsv mismatch, found %s", 212 fw->smbfw_lsv); 213 ret = B_FALSE; 214 } 215 216 if (fw->smbfw_imgsz != smbios_fwinfo_size) { 217 warnx("firmware inventory size mismatch, found 0x%" PRIx64, 218 fw->smbfw_imgsz); 219 ret = B_FALSE; 220 } 221 222 if (fw->smbfw_chars != SMB_FWC_WP) { 223 warnx("firmware inventory chars mismatch, found 0x%x", 224 fw->smbfw_chars); 225 ret = B_FALSE; 226 } 227 228 if (fw->smbfw_state != SMB_FWS_UA_OFFLINE) { 229 warnx("firmware inventory state mismatch, found 0x%x", 230 fw->smbfw_state); 231 ret = B_FALSE; 232 } 233 234 if (fw->smbfw_vers_fmt != smbios_fwinfo_versid) { 235 warnx("firmware inventory version format mismatch, found 0x%x", 236 fw->smbfw_vers_fmt); 237 ret = B_FALSE; 238 } 239 240 if (fw->smbfw_id_fmt != smbios_fwinfo_versid) { 241 warnx("firmware inventory ID format mismatch, found 0x%x", 242 fw->smbfw_id_fmt); 243 ret = B_FALSE; 244 } 245 246 if (smbios_info_common(hdl, sp->smbstr_id, &info) == -1) { 247 warnx("failed to get firmware inventory common items: %s", 248 smbios_errmsg(smbios_errno(hdl))); 249 return (B_FALSE); 250 } 251 252 if (strcmp(info.smbi_manufacturer, smbios_fwinfo_mfg) != 0) { 253 warnx("firmware inventory manufacturer mismatch, found %s", 254 info.smbi_manufacturer); 255 ret = B_FALSE; 256 } 257 258 if (strcmp(info.smbi_version, smbios_fwinfo_vers) != 0) { 259 warnx("firmware inventory version mismatch, found %s", 260 info.smbi_version); 261 ret = B_FALSE; 262 } 263 264 return (ret); 265 } 266 267 boolean_t 268 smbios_test_fwinfo_verify_nocomps(smbios_hdl_t *hdl) 269 { 270 smbios_struct_t sp; 271 smbios_fwinfo_t fw; 272 uint_t ncomps; 273 smbios_fwinfo_comp_t *comps; 274 boolean_t ret = B_TRUE; 275 276 if (smbios_lookup_type(hdl, SMB_TYPE_FWINFO, &sp) == -1) { 277 warnx("failed to lookup SMBIOS fwinfo: %s", 278 smbios_errmsg(smbios_errno(hdl))); 279 return (B_FALSE); 280 } 281 282 if (smbios_info_fwinfo(hdl, sp.smbstr_id, &fw) == -1) { 283 warnx("failed to get firmware inventory: %s", 284 smbios_errmsg(smbios_errno(hdl))); 285 return (B_FALSE); 286 } 287 288 if (!smbios_test_fwinfo_verify_common(hdl, &sp, &fw)) { 289 ret = B_FALSE; 290 } 291 292 if (fw.smbfw_ncomps != 0) { 293 warnx("firmware inventory ncomps mismatch, found 0x%x", 294 fw.smbfw_ncomps); 295 ret = B_FALSE; 296 } 297 298 if (smbios_info_fwinfo_comps(hdl, sp.smbstr_id, &ncomps, &comps) != 0) { 299 warnx("failed to get components: %s", 300 smbios_errmsg(smbios_errno(hdl))); 301 ret = B_FALSE; 302 } 303 304 if (ncomps != 0) { 305 warnx("smbios_info_fwinfo_comps() returned wrong number of " 306 "comps: 0x%x", ncomps); 307 ret = B_FALSE; 308 } 309 310 if (comps != NULL) { 311 warnx("smbios_info_fwinfo_comps() gave a non-NULL comps " 312 "pointer: %p", comps); 313 ret = B_FALSE; 314 } 315 316 smbios_info_fwinfo_comps_free(hdl, ncomps, comps); 317 318 return (ret); 319 } 320 321 boolean_t 322 smbios_test_fwinfo_verify_invlen_comps(smbios_hdl_t *hdl) 323 { 324 smbios_struct_t sp; 325 smbios_fwinfo_t fw; 326 uint_t ncomps; 327 smbios_fwinfo_comp_t *comps; 328 boolean_t ret = B_TRUE; 329 330 if (smbios_lookup_type(hdl, SMB_TYPE_FWINFO, &sp) == -1) { 331 warnx("failed to lookup SMBIOS fwinfo: %s", 332 smbios_errmsg(smbios_errno(hdl))); 333 return (B_FALSE); 334 } 335 336 if (smbios_info_fwinfo(hdl, sp.smbstr_id, &fw) == -1) { 337 warnx("failed to get firmware inventory: %s", 338 smbios_errmsg(smbios_errno(hdl))); 339 return (B_FALSE); 340 } 341 342 if (!smbios_test_fwinfo_verify_common(hdl, &sp, &fw)) { 343 ret = B_FALSE; 344 } 345 346 if (fw.smbfw_ncomps != smbios_fwinfo_ncomps) { 347 warnx("firmware inventory ncomps mismatch, found 0x%x", 348 fw.smbfw_ncomps); 349 ret = B_FALSE; 350 } 351 352 if (smbios_info_fwinfo_comps(hdl, sp.smbstr_id, &ncomps, &comps) != 353 -1) { 354 warnx("accidentally parsed invalid fwinfo components as " 355 "valid"); 356 return (B_FALSE); 357 } 358 359 if (smbios_errno(hdl) != ESMB_SHORT) { 360 warnx("encountered wrong error for fwinfo comps, expected: " 361 "0x%x, found: 0x%x", ESMB_SHORT, smbios_errno(hdl)); 362 return (B_FALSE); 363 } 364 365 return (ret); 366 } 367 368 369 370 boolean_t 371 smbios_test_fwinfo_verify_comps(smbios_hdl_t *hdl) 372 { 373 smbios_struct_t sp; 374 smbios_fwinfo_t fw; 375 uint_t ncomps; 376 smbios_fwinfo_comp_t *comps; 377 boolean_t ret = B_TRUE; 378 379 if (smbios_lookup_type(hdl, SMB_TYPE_FWINFO, &sp) == -1) { 380 warnx("failed to lookup SMBIOS fwinfo: %s", 381 smbios_errmsg(smbios_errno(hdl))); 382 return (B_FALSE); 383 } 384 385 if (smbios_info_fwinfo(hdl, sp.smbstr_id, &fw) == -1) { 386 warnx("failed to get firmware inventory: %s", 387 smbios_errmsg(smbios_errno(hdl))); 388 return (B_FALSE); 389 } 390 391 if (!smbios_test_fwinfo_verify_common(hdl, &sp, &fw)) { 392 ret = B_FALSE; 393 } 394 395 if (fw.smbfw_ncomps != smbios_fwinfo_ncomps) { 396 warnx("firmware inventory ncomps mismatch, found 0x%x", 397 fw.smbfw_ncomps); 398 ret = B_FALSE; 399 } 400 401 if (smbios_info_fwinfo_comps(hdl, sp.smbstr_id, &ncomps, &comps) != 0) { 402 warnx("failed to get components: %s", 403 smbios_errmsg(smbios_errno(hdl))); 404 ret = B_FALSE; 405 } 406 407 if (ncomps != smbios_fwinfo_ncomps) { 408 warnx("smbios_info_fwinfo_comps() returned wrong number of " 409 "comps: 0x%x", ncomps); 410 ret = B_FALSE; 411 } 412 413 if (comps == NULL) { 414 warnx("smbios_info_fwinfo_comps() gave a NULL comps pointer"); 415 ret = B_FALSE; 416 } else { 417 for (uint_t i = 0; i < smbios_fwinfo_ncomps; i++) { 418 if (comps[i].smbfwe_id != 0x2300 + i) { 419 warnx("component id %u is wrong: 0x%" _PRIxID, 420 i, comps[i].smbfwe_id); 421 ret = B_FALSE; 422 } 423 } 424 } 425 426 smbios_info_fwinfo_comps_free(hdl, ncomps, comps); 427 428 return (ret); 429 } 430