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 */ 15 16 /* 17 * Primordial SMBIOS test suite. At the moment, the purpose of this is just to 18 * test the recent SMBIOS 3.2 additions specific to the variable length slots. 19 * This should be evolved into a much fuller test suite. 20 */ 21 22 #include <umem.h> 23 #include "smbios_test.h" 24 25 const char * 26 _umem_debug_init(void) 27 { 28 return ("default,verbose"); 29 } 30 31 const char * 32 _umem_logging_init(void) 33 { 34 return ("fail,contents"); 35 } 36 37 smbios_test_table_t * 38 smbios_test_table_init(smbios_entry_point_t type, uint_t version) 39 { 40 smbios_test_table_t *table; 41 42 if (type != SMBIOS_ENTRY_POINT_30) { 43 abort(); 44 } 45 46 table = umem_zalloc(sizeof (smbios_test_table_t), UMEM_DEFAULT); 47 if (table == NULL) { 48 return (NULL); 49 } 50 51 table->stt_data = umem_zalloc(SMBIOS_TEST_ALLOC_SIZE, UMEM_DEFAULT); 52 if (table->stt_data == NULL) { 53 umem_free(table, sizeof (smbios_test_table_t)); 54 return (NULL); 55 } 56 table->stt_buflen = SMBIOS_TEST_ALLOC_SIZE; 57 table->stt_type = type; 58 table->stt_version = version; 59 table->stt_nextid = 1; 60 61 return (table); 62 } 63 64 static void * 65 smbios_test_table_append_common(smbios_test_table_t *table, const void *buf, 66 size_t len) 67 { 68 void *start; 69 70 if (SIZE_MAX - table->stt_offset < len) 71 abort(); 72 73 if (len + table->stt_offset >= table->stt_buflen) { 74 void *newbuf; 75 size_t newlen = table->stt_buflen + SMBIOS_TEST_ALLOC_SIZE; 76 77 while (len + table->stt_offset >= newlen) { 78 newlen += SMBIOS_TEST_ALLOC_SIZE; 79 } 80 81 newbuf = umem_zalloc(newlen, UMEM_DEFAULT); 82 if (newbuf == NULL) { 83 err(EXIT_FAILURE, "failed to umem_zalloc for %lu bytes", 84 newlen); 85 } 86 87 (void) memcpy(newbuf, table->stt_data, table->stt_buflen); 88 umem_free(table->stt_data, table->stt_buflen); 89 table->stt_data = newbuf; 90 table->stt_buflen = newlen; 91 } 92 93 start = (void *)((uintptr_t)table->stt_data + table->stt_offset); 94 (void) memcpy(start, buf, len); 95 table->stt_offset += len; 96 97 return (start); 98 } 99 100 void 101 smbios_test_table_append_raw(smbios_test_table_t *table, const void *buf, 102 size_t len) 103 { 104 (void) smbios_test_table_append_common(table, buf, len); 105 } 106 107 void 108 smbios_test_table_append_string(smbios_test_table_t *table, const char *str) 109 { 110 size_t len = strlen(str) + 1; 111 (void) smbios_test_table_append_common(table, str, len); 112 } 113 114 uint16_t 115 smbios_test_table_append(smbios_test_table_t *table, const void *buf, 116 size_t len) 117 { 118 smb_header_t *hdr; 119 uint16_t id; 120 121 hdr = smbios_test_table_append_common(table, buf, len); 122 table->stt_nents++; 123 124 id = table->stt_nextid; 125 hdr->smbh_hdl = htole16(table->stt_nextid); 126 table->stt_nextid++; 127 128 return (id); 129 } 130 131 void 132 smbios_test_table_append_eot(smbios_test_table_t *table) 133 { 134 smb_header_t eot; 135 uint8_t endstring = 0; 136 137 bzero(&eot, sizeof (eot)); 138 eot.smbh_type = SMB_TYPE_EOT; 139 eot.smbh_len = 4; 140 (void) smbios_test_table_append(table, &eot, sizeof (eot)); 141 (void) smbios_test_table_append_raw(table, &endstring, 142 sizeof (endstring)); 143 smbios_test_table_append_raw(table, &endstring, 144 sizeof (endstring)); 145 smbios_test_table_append_raw(table, &endstring, 146 sizeof (endstring)); 147 148 } 149 150 static uint8_t 151 smbios_test_table_checksum(const uint8_t *buf, size_t len) 152 { 153 uint8_t sum; 154 size_t i; 155 156 for (i = 0, sum = 0; i < len; i++) { 157 sum += buf[i]; 158 } 159 160 if (sum == 0) 161 return (0); 162 163 return ((uint8_t)(0x100 - sum)); 164 } 165 166 static void 167 smbios_test_table_snapshot(smbios_test_table_t *table, smbios_entry_t **entryp, 168 void **bufp, size_t *lenp) 169 { 170 smbios_30_entry_t *ent30; 171 172 switch (table->stt_type) { 173 case SMBIOS_ENTRY_POINT_30: 174 ent30 = &table->stt_entry.ep30; 175 176 (void) memcpy(ent30->smbe_eanchor, SMB3_ENTRY_EANCHOR, 177 sizeof (ent30->smbe_eanchor)); 178 ent30->smbe_ecksum = 0; 179 ent30->smbe_elen = sizeof (*ent30); 180 ent30->smbe_major = (table->stt_version >> 8) & 0xff; 181 ent30->smbe_minor = table->stt_version & 0xff; 182 ent30->smbe_docrev = 0; 183 ent30->smbe_revision = 1; 184 ent30->smbe_reserved = 0; 185 ent30->smbe_stlen = htole32(table->stt_offset); 186 ent30->smbe_staddr = htole64(P2ROUNDUP(sizeof (*ent30), 16)); 187 188 ent30->smbe_ecksum = smbios_test_table_checksum((void *)ent30, 189 sizeof (*ent30)); 190 break; 191 default: 192 abort(); 193 } 194 195 *entryp = &table->stt_entry; 196 *bufp = table->stt_data; 197 *lenp = table->stt_offset; 198 } 199 200 static void 201 smbios_test_table_fini(smbios_test_table_t *table) 202 { 203 if (table == NULL) { 204 return; 205 } 206 207 if (table->stt_data != NULL) { 208 umem_free(table->stt_data, table->stt_buflen); 209 } 210 211 umem_free(table, sizeof (smbios_test_table_t)); 212 } 213 214 static const smbios_test_t smbios_tests[] = { 215 { 216 .st_entry = SMBIOS_ENTRY_POINT_30, 217 .st_tvers = SMB_VERSION_32, 218 .st_libvers = SMB_VERSION, 219 .st_mktable = smbios_test_slot_mktable, 220 .st_canopen = B_TRUE, 221 .st_verify = smbios_test_slot_verify, 222 .st_desc = "slot tests" 223 }, { 224 .st_entry = SMBIOS_ENTRY_POINT_30, 225 .st_tvers = SMB_VERSION, 226 .st_libvers = 0xffff, 227 .st_mktable = smbios_test_badvers_mktable, 228 .st_desc = "bad library version" 229 }, { 230 .st_entry = SMBIOS_ENTRY_POINT_30, 231 .st_tvers = SMB_VERSION_32, 232 .st_libvers = SMB_VERSION_32, 233 .st_mktable = smbios_test_memdevice_mktable_32, 234 .st_canopen = B_TRUE, 235 .st_verify = smbios_test_memdevice_verify_32, 236 .st_desc = "memory device 3.2 / 3.2" 237 }, { 238 .st_entry = SMBIOS_ENTRY_POINT_30, 239 .st_tvers = SMB_VERSION_32, 240 .st_libvers = SMB_VERSION_33, 241 .st_mktable = smbios_test_memdevice_mktable_32, 242 .st_canopen = B_TRUE, 243 .st_verify = smbios_test_memdevice_verify_32_33, 244 .st_desc = "memory device 3.2 / 3.3" 245 }, { 246 .st_entry = SMBIOS_ENTRY_POINT_30, 247 .st_tvers = SMB_VERSION_33, 248 .st_libvers = SMB_VERSION_33, 249 .st_mktable = smbios_test_memdevice_mktable_33, 250 .st_canopen = B_TRUE, 251 .st_verify = smbios_test_memdevice_verify_33, 252 .st_desc = "memory device 3.3" 253 }, { 254 .st_entry = SMBIOS_ENTRY_POINT_30, 255 .st_tvers = SMB_VERSION_33, 256 .st_libvers = SMB_VERSION_33, 257 .st_mktable = smbios_test_memdevice_mktable_33ext, 258 .st_canopen = B_TRUE, 259 .st_verify = smbios_test_memdevice_verify_33ext, 260 .st_desc = "memory device 3.3" 261 }, { 262 .st_entry = SMBIOS_ENTRY_POINT_30, 263 .st_tvers = SMB_VERSION, 264 .st_libvers = SMB_VERSION, 265 .st_mktable = smbios_test_pinfo_mktable_amd64, 266 .st_canopen = B_TRUE, 267 .st_verify = smbios_test_pinfo_verify_amd64, 268 .st_desc = "processor additional information - amd64" 269 }, { 270 .st_entry = SMBIOS_ENTRY_POINT_30, 271 .st_tvers = SMB_VERSION, 272 .st_libvers = SMB_VERSION, 273 .st_mktable = smbios_test_pinfo_mktable_riscv, 274 .st_canopen = B_TRUE, 275 .st_verify = smbios_test_pinfo_verify_riscv, 276 .st_desc = "processor additional information - riscv" 277 }, { 278 .st_entry = SMBIOS_ENTRY_POINT_30, 279 .st_tvers = SMB_VERSION, 280 .st_libvers = SMB_VERSION, 281 .st_mktable = smbios_test_pinfo_mktable_invlen1, 282 .st_canopen = B_TRUE, 283 .st_verify = smbios_test_pinfo_verify_invlen1, 284 .st_desc = "processor additional information - bad table length 1" 285 }, { 286 .st_entry = SMBIOS_ENTRY_POINT_30, 287 .st_tvers = SMB_VERSION, 288 .st_libvers = SMB_VERSION, 289 .st_mktable = smbios_test_pinfo_mktable_invlen2, 290 .st_canopen = B_TRUE, 291 .st_verify = smbios_test_pinfo_verify_invlen2, 292 .st_desc = "processor additional information - bad table length 2" 293 }, { 294 .st_entry = SMBIOS_ENTRY_POINT_30, 295 .st_tvers = SMB_VERSION, 296 .st_libvers = SMB_VERSION, 297 .st_mktable = smbios_test_pinfo_mktable_invlen3, 298 .st_canopen = B_TRUE, 299 .st_verify = smbios_test_pinfo_verify_invlen3, 300 .st_desc = "processor additional information - bad table length 3" 301 }, { 302 .st_entry = SMBIOS_ENTRY_POINT_30, 303 .st_tvers = SMB_VERSION, 304 .st_libvers = SMB_VERSION, 305 .st_mktable = smbios_test_pinfo_mktable_invlen4, 306 .st_canopen = B_TRUE, 307 .st_verify = smbios_test_pinfo_verify_invlen4, 308 .st_desc = "processor additional information - bad table length 4" 309 }, { 310 .st_entry = SMBIOS_ENTRY_POINT_30, 311 .st_tvers = SMB_VERSION, 312 .st_libvers = SMB_VERSION, 313 .st_mktable = smbios_test_memdevice_mktable_32, 314 .st_canopen = B_TRUE, 315 .st_verify = smbios_test_pinfo_verify_badtype, 316 .st_desc = "processor additional information - bad type" 317 }, 318 319 }; 320 321 static boolean_t 322 smbios_test_run_one(const smbios_test_t *test) 323 { 324 smbios_test_table_t *table = NULL; 325 smbios_hdl_t *hdl = NULL; 326 void *buf; 327 size_t len; 328 smbios_entry_t *entry; 329 int err = 0; 330 boolean_t ret = B_FALSE; 331 332 table = smbios_test_table_init(test->st_entry, test->st_tvers); 333 if (!test->st_mktable(table)) { 334 goto out; 335 } 336 337 smbios_test_table_snapshot(table, &entry, &buf, &len); 338 hdl = smbios_bufopen(entry, buf, len, test->st_libvers, SMB_FL_DEBUG, 339 &err); 340 if (test->st_canopen) { 341 if (hdl == NULL) { 342 warnx("failed to create table for test %s: %s", 343 test->st_desc, smbios_errmsg(err)); 344 goto out; 345 } 346 } else { 347 if (hdl != NULL) { 348 warnx("accidentally created table for test %s, " 349 "expected failure", test->st_desc); 350 } else { 351 ret = B_TRUE; 352 } 353 goto out; 354 } 355 356 if (test->st_verify(hdl)) { 357 ret = B_TRUE; 358 } 359 360 out: 361 if (hdl != NULL) { 362 smbios_close(hdl); 363 } 364 365 if (table != NULL) { 366 smbios_test_table_fini(table); 367 } 368 369 if (ret) { 370 (void) printf("TEST PASSED: %s\n", test->st_desc); 371 } else { 372 (void) printf("TEST FAILED: %s\n", test->st_desc); 373 } 374 375 return (ret); 376 } 377 378 int 379 main(void) 380 { 381 int err = 0; 382 size_t i; 383 384 for (i = 0; i < ARRAY_SIZE(smbios_tests); i++) { 385 if (!smbios_test_run_one(&smbios_tests[i])) { 386 err = 1; 387 } 388 } 389 390 return (err); 391 } 392