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 2019 Robert Mustacchi 14 */ 15 16 /* 17 * Basic testing of the SMBIOS 3.3 memory device extensions. We test these in a 18 * few different ways: 19 * 20 * 1. Using a 3.2 table with a 3.2 library to make sure we get the old fields. 21 * We also need to verify that we don't clobber memory in this case. 22 * 2. Using a 3.2 table with a 3.3 library to make sure we get the new fields. 23 * populated with the corresponding 3.2 values. 24 * 3. Using a 3.3 table with only the old values as valid. 25 * 4. Using a 3.3 table with both the old and new values as valid. 26 * memory. 27 */ 28 29 #include <stdlib.h> 30 #include "smbios_test.h" 31 32 static uint16_t smbios_memdevice_speed = 0xdeed; 33 static uint16_t smbios_memdevice_clkspeed = 0xf00f; 34 static uint32_t smbios_memdevice_extspeed = 0xbaddeed; 35 static uint32_t smbios_memdevice_extclkspeed = 0xbadf00f; 36 37 /* 38 * Fill in the basics of a single memory device. Callers need to fill in the 39 * speed, extspeed, clkspeed, and extclkspeed members. 40 */ 41 static void 42 smbios_test_memdevice_fill(smb_memdevice_t *mem) 43 { 44 mem->smbmdev_hdr.smbh_type = SMB_TYPE_MEMDEVICE; 45 mem->smbmdev_hdr.smbh_len = sizeof (smb_memdevice_t); 46 47 mem->smbmdev_array = 0xffff; 48 mem->smbmdev_error = htole16(0xfffe); 49 mem->smbmdev_twidth = 64; 50 mem->smbmdev_dwidth = 64; 51 mem->smbmdev_size = 0x7fff; 52 mem->smbmdev_form = SMB_MDFF_FBDIMM; 53 mem->smbmdev_set = 0; 54 mem->smbmdev_dloc = 0; 55 mem->smbmdev_bloc = 0; 56 mem->smbmdev_type = SMB_MDT_DDR4; 57 mem->smbmdev_manufacturer = 0; 58 mem->smbmdev_asset = 0; 59 mem->smbmdev_part = 0; 60 mem->smbmdev_attrs = 2; 61 mem->smbmdev_extsize = htole32(0x123456); 62 mem->smbmdev_minvolt = 0; 63 mem->smbmdev_maxvolt = 0; 64 mem->smbmdev_confvolt = 0; 65 mem->smbmdev_memtech = 0; 66 mem->smbmdev_opmode = 1 << 3; 67 mem->smbmdev_fwver = 0; 68 mem->smbmdev_modulemfgid = 0; 69 mem->smbmdev_moduleprodid = 0; 70 mem->smbmdev_memsysmfgid = 0; 71 mem->smbmdev_memsysprodid = 0; 72 mem->smbmdev_nvsize = htole64(UINT64_MAX); 73 mem->smbmdev_volsize = htole64(UINT64_MAX); 74 mem->smbmdev_cachesize = htole64(UINT64_MAX); 75 mem->smbmdev_logicalsize = htole64(UINT64_MAX); 76 } 77 78 boolean_t 79 smbios_test_memdevice_mktable_32(smbios_test_table_t *table) 80 { 81 smb_memdevice_t mem; 82 size_t len = 0x54; 83 84 smbios_test_memdevice_fill(&mem); 85 mem.smbmdev_speed = htole16(smbios_memdevice_speed); 86 mem.smbmdev_clkspeed = htole16(smbios_memdevice_clkspeed); 87 mem.smbmdev_extspeed = htole32(0); 88 mem.smbmdev_extclkspeed = htole32(0); 89 90 /* 91 * Because we're emulating an SMBIOS 3.2 table, we have to set it to the 92 * specification's defined size for that revision - 0x54. 93 */ 94 mem.smbmdev_hdr.smbh_len = len; 95 (void) smbios_test_table_append(table, &mem, len); 96 smbios_test_table_append_eot(table); 97 98 return (B_TRUE); 99 } 100 101 boolean_t 102 smbios_test_memdevice_mktable_33(smbios_test_table_t *table) 103 { 104 smb_memdevice_t mem; 105 106 smbios_test_memdevice_fill(&mem); 107 mem.smbmdev_speed = htole16(smbios_memdevice_speed); 108 mem.smbmdev_clkspeed = htole16(smbios_memdevice_clkspeed); 109 mem.smbmdev_extspeed = htole32(0); 110 mem.smbmdev_extclkspeed = htole32(0); 111 112 (void) smbios_test_table_append(table, &mem, sizeof (mem)); 113 smbios_test_table_append_eot(table); 114 115 return (B_TRUE); 116 } 117 118 boolean_t 119 smbios_test_memdevice_mktable_33ext(smbios_test_table_t *table) 120 { 121 smb_memdevice_t mem; 122 123 smbios_test_memdevice_fill(&mem); 124 mem.smbmdev_speed = htole16(0xffff); 125 mem.smbmdev_clkspeed = htole16(0xffff); 126 mem.smbmdev_extspeed = htole32(smbios_memdevice_extspeed); 127 mem.smbmdev_extclkspeed = htole32(smbios_memdevice_extclkspeed); 128 129 (void) smbios_test_table_append(table, &mem, sizeof (mem)); 130 smbios_test_table_append_eot(table); 131 132 return (B_TRUE); 133 } 134 135 static boolean_t 136 smbios_test_memdevice_verify_common(smbios_memdevice_t *mem) 137 { 138 boolean_t ret = B_TRUE; 139 140 if (mem->smbmd_dwidth != 64) { 141 warnx("found wrong dwidth: %u", mem->smbmd_dwidth); 142 ret = B_FALSE; 143 } 144 145 if (mem->smbmd_twidth != 64) { 146 warnx("found wrong twidth: %u", mem->smbmd_twidth); 147 ret = B_FALSE; 148 } 149 150 if (mem->smbmd_form != SMB_MDFF_FBDIMM) { 151 warnx("found wrong form: %u", mem->smbmd_form); 152 ret = B_FALSE; 153 } 154 155 if (mem->smbmd_size != 0x123456ULL * 1024 * 1024) { 156 warnx("found wrong size: %u", mem->smbmd_size); 157 ret = B_FALSE; 158 } 159 160 return (ret); 161 } 162 163 boolean_t 164 smbios_test_memdevice_verify_32(smbios_hdl_t *hdl) 165 { 166 smbios_struct_t sp; 167 smbios_memdevice_t mem; 168 boolean_t ret = B_TRUE; 169 uint64_t rval; 170 171 /* 172 * We expect that the SMBIOS 3.2 memory device values should not be 173 * touched here. As such we set them to a random value to verify and 174 * verify that it hasn't been set. 175 */ 176 arc4random_buf(&rval, sizeof (rval)); 177 mem.smbmd_extspeed = rval; 178 mem.smbmd_extclkspeed = rval; 179 180 if (smbios_lookup_type(hdl, SMB_TYPE_MEMDEVICE, &sp) == -1) { 181 warnx("failed to lookup SMBIOS memory device: %s", 182 smbios_errmsg(smbios_errno(hdl))); 183 return (B_FALSE); 184 } 185 186 if (smbios_info_memdevice(hdl, sp.smbstr_id, &mem) != 0) { 187 warnx("failed to get SMBIOS memory device info: %s", 188 smbios_errmsg(smbios_errno(hdl))); 189 return (B_FALSE); 190 } 191 192 if (mem.smbmd_extspeed != rval || mem.smbmd_extclkspeed != rval) { 193 warnx("smbios_memdevice_t had its memory cloberred!"); 194 return (B_FALSE); 195 } 196 197 if (!smbios_test_memdevice_verify_common(&mem)) { 198 return (B_FALSE); 199 } 200 201 if (mem.smbmd_speed != smbios_memdevice_speed) { 202 warnx("found wrong device speed: %u", mem.smbmd_speed); 203 ret = B_FALSE; 204 } 205 206 if (mem.smbmd_clkspeed != smbios_memdevice_clkspeed) { 207 warnx("found wrong device clkspeed: %u", mem.smbmd_clkspeed); 208 ret = B_FALSE; 209 } 210 211 return (ret); 212 } 213 214 /* 215 * This is a variant of smbios_test_memdevice_verify_32(), but instead of using 216 * an SMBIOS 3.2 library, we use an SMBIOS 3.3 handle. This means that we expect 217 * the extended values to be populated with the base values. 218 */ 219 boolean_t 220 smbios_test_memdevice_verify_32_33(smbios_hdl_t *hdl) 221 { 222 smbios_struct_t sp; 223 smbios_memdevice_t mem; 224 boolean_t ret = B_TRUE; 225 226 if (smbios_lookup_type(hdl, SMB_TYPE_MEMDEVICE, &sp) == -1) { 227 warnx("failed to lookup SMBIOS memory device: %s", 228 smbios_errmsg(smbios_errno(hdl))); 229 return (B_FALSE); 230 } 231 232 if (smbios_info_memdevice(hdl, sp.smbstr_id, &mem) != 0) { 233 warnx("failed to get SMBIOS memory device info: %s", 234 smbios_errmsg(smbios_errno(hdl))); 235 return (B_FALSE); 236 } 237 238 if (!smbios_test_memdevice_verify_common(&mem)) { 239 return (B_FALSE); 240 } 241 242 if (mem.smbmd_speed != smbios_memdevice_speed) { 243 warnx("found wrong device speed: %u", mem.smbmd_speed); 244 ret = B_FALSE; 245 } 246 247 if (mem.smbmd_clkspeed != smbios_memdevice_clkspeed) { 248 warnx("found wrong device clkspeed: %u", mem.smbmd_clkspeed); 249 ret = B_FALSE; 250 } 251 252 if (mem.smbmd_extspeed != smbios_memdevice_speed) { 253 warnx("found wrong device speed: %u", mem.smbmd_extspeed); 254 ret = B_FALSE; 255 } 256 257 if (mem.smbmd_extclkspeed != smbios_memdevice_clkspeed) { 258 warnx("found wrong device clkspeed: %u", mem.smbmd_extclkspeed); 259 ret = B_FALSE; 260 } 261 262 return (ret); 263 } 264 265 boolean_t 266 smbios_test_memdevice_verify_33(smbios_hdl_t *hdl) 267 { 268 smbios_struct_t sp; 269 smbios_memdevice_t mem; 270 boolean_t ret = B_TRUE; 271 272 if (smbios_lookup_type(hdl, SMB_TYPE_MEMDEVICE, &sp) == -1) { 273 warnx("failed to lookup SMBIOS memory device: %s", 274 smbios_errmsg(smbios_errno(hdl))); 275 return (B_FALSE); 276 } 277 278 if (smbios_info_memdevice(hdl, sp.smbstr_id, &mem) != 0) { 279 warnx("failed to get SMBIOS memory device info: %s", 280 smbios_errmsg(smbios_errno(hdl))); 281 return (B_FALSE); 282 } 283 284 if (!smbios_test_memdevice_verify_common(&mem)) { 285 return (B_FALSE); 286 } 287 288 if (mem.smbmd_speed != smbios_memdevice_speed) { 289 warnx("found wrong device speed: %u", mem.smbmd_speed); 290 ret = B_FALSE; 291 } 292 293 if (mem.smbmd_clkspeed != smbios_memdevice_clkspeed) { 294 warnx("found wrong device clkspeed: %u", mem.smbmd_clkspeed); 295 ret = B_FALSE; 296 } 297 298 if (mem.smbmd_extspeed != smbios_memdevice_speed) { 299 warnx("found wrong device speed: %u", mem.smbmd_extspeed); 300 ret = B_FALSE; 301 } 302 303 if (mem.smbmd_extclkspeed != smbios_memdevice_clkspeed) { 304 warnx("found wrong device clkspeed: %u", mem.smbmd_extclkspeed); 305 ret = B_FALSE; 306 } 307 308 return (ret); 309 } 310 311 boolean_t 312 smbios_test_memdevice_verify_33ext(smbios_hdl_t *hdl) 313 { 314 smbios_struct_t sp; 315 smbios_memdevice_t mem; 316 boolean_t ret = B_TRUE; 317 318 if (smbios_lookup_type(hdl, SMB_TYPE_MEMDEVICE, &sp) == -1) { 319 warnx("failed to lookup SMBIOS memory device: %s", 320 smbios_errmsg(smbios_errno(hdl))); 321 return (B_FALSE); 322 } 323 324 if (smbios_info_memdevice(hdl, sp.smbstr_id, &mem) != 0) { 325 warnx("failed to get SMBIOS memory device info: %s", 326 smbios_errmsg(smbios_errno(hdl))); 327 return (B_FALSE); 328 } 329 330 if (!smbios_test_memdevice_verify_common(&mem)) { 331 return (B_FALSE); 332 } 333 334 if (mem.smbmd_speed != 0xffff) { 335 warnx("found wrong device speed: %u", mem.smbmd_speed); 336 ret = B_FALSE; 337 } 338 339 if (mem.smbmd_clkspeed != 0xffff) { 340 warnx("found wrong device clkspeed: %u", mem.smbmd_clkspeed); 341 ret = B_FALSE; 342 } 343 344 if (mem.smbmd_extspeed != smbios_memdevice_extspeed) { 345 warnx("found wrong device speed: %u", mem.smbmd_extspeed); 346 ret = B_FALSE; 347 } 348 349 if (mem.smbmd_extclkspeed != smbios_memdevice_extclkspeed) { 350 warnx("found wrong device clkspeed: %u", mem.smbmd_extclkspeed); 351 ret = B_FALSE; 352 } 353 354 return (ret); 355 } 356