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
smbios_test_fwinfo_mktable_common_fwinfo(smb_fwinfo_t * fw)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
smbios_test_fwinfo_mktable_common_fini(smbios_test_table_t * table)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
smbios_test_fwinfo_mktable_invlen_base(smbios_test_table_t * table)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
smbios_test_fwinfo_mktable_invlen_comps(smbios_test_table_t * table)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
smbios_test_fwinfo_mktable_nocomps(smbios_test_table_t * table)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
smbios_test_fwinfo_mktable_comps(smbios_test_table_t * table)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
smbios_test_fwinfo_verify_badtype(smbios_hdl_t * hdl)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
smbios_test_fwinfo_verify_invlen_base(smbios_hdl_t * hdl)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
smbios_test_fwinfo_verify_common(smbios_hdl_t * hdl,smbios_struct_t * sp,const smbios_fwinfo_t * fw)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
smbios_test_fwinfo_verify_nocomps(smbios_hdl_t * hdl)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
smbios_test_fwinfo_verify_invlen_comps(smbios_hdl_t * hdl)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
smbios_test_fwinfo_verify_comps(smbios_hdl_t * hdl)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%x", i,
420 				    comps[i]);
421 				ret = B_FALSE;
422 			}
423 		}
424 	}
425 
426 	smbios_info_fwinfo_comps_free(hdl, ncomps, comps);
427 
428 	return (ret);
429 }
430