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 3 - SMB_TYPE_CHASSIS.
18 */
19
20 #include "smbios_test.h"
21
22 static const char *smbios_chassis_mfg = "Shrina";
23 static const char *smbios_chassis_vers = "7R";
24 static const char *smbios_chassis_serial = "What's my number?";
25 static const char *smbios_chassis_asset = "lost";
26 static const char *smbios_chassis_sku = "Proud";
27 static const uint32_t smbios_chassis_oem = 0x36105997;
28 static const uint8_t smbios_chassis_uheight = 7;
29
30 boolean_t
smbios_test_chassis_mktable_invlen_base(smbios_test_table_t * table)31 smbios_test_chassis_mktable_invlen_base(smbios_test_table_t *table)
32 {
33 smb_header_t hdr;
34
35 hdr.smbh_type = SMB_TYPE_CHASSIS;
36 hdr.smbh_len = sizeof (hdr);
37
38 (void) smbios_test_table_append(table, &hdr, sizeof (hdr));
39 smbios_test_table_append_eot(table);
40
41 return (B_TRUE);
42 }
43
44 static void
smbios_test_chassis_mktable_fill_chassis(smb_chassis_t * ch)45 smbios_test_chassis_mktable_fill_chassis(smb_chassis_t *ch)
46 {
47 ch->smbch_hdr.smbh_type = SMB_TYPE_CHASSIS;
48 ch->smbch_hdr.smbh_len = sizeof (*ch);
49 ch->smbch_manufacturer = 1;
50 ch->smbch_type = SMB_CHT_LUNCHBOX;
51 ch->smbch_version = 2;
52 ch->smbch_serial = 3;
53 ch->smbch_asset = 4;
54 ch->smbch_bustate = SMB_CHST_SAFE;
55 ch->smbch_psstate = SMB_CHST_NONREC;
56 ch->smbch_thstate = SMB_CHST_WARNING;
57 ch->smbch_security = SMB_CHSC_NONE;
58 ch->smbch_oemdata = htole32(smbios_chassis_oem);
59 ch->smbch_uheight = smbios_chassis_uheight;
60 ch->smbch_cords = smbios_chassis_uheight - 1;
61 ch->smbch_cn = 0;
62 ch->smbch_cm = sizeof (smb_chassis_entry_t);
63 }
64
65 static void
smbios_test_chassis_mktable_fill_entries(smb_chassis_entry_t * ents)66 smbios_test_chassis_mktable_fill_entries(smb_chassis_entry_t *ents)
67 {
68 ents[0].smbce_type = SMB_TYPE_COOLDEV | (1 << 7);
69 ents[0].smbce_min = 1;
70 ents[0].smbce_max = 42;
71 ents[1].smbce_type = SMB_BBT_IO;
72 ents[1].smbce_min = 5;
73 ents[1].smbce_max = 123;
74 }
75
76 static void
smbios_test_chassis_mktable_append_strings(smbios_test_table_t * table)77 smbios_test_chassis_mktable_append_strings(smbios_test_table_t *table)
78 {
79 smbios_test_table_append_string(table, smbios_chassis_mfg);
80 smbios_test_table_append_string(table, smbios_chassis_vers);
81 smbios_test_table_append_string(table, smbios_chassis_serial);
82 smbios_test_table_append_string(table, smbios_chassis_asset);
83 }
84
85 /*
86 * This is an SMBIOS 2.4-esque table.
87 */
88 boolean_t
smbios_test_chassis_mktable_base(smbios_test_table_t * table)89 smbios_test_chassis_mktable_base(smbios_test_table_t *table)
90 {
91 smb_chassis_t ch;
92
93 smbios_test_chassis_mktable_fill_chassis(&ch);
94 (void) smbios_test_table_append(table, &ch, sizeof (ch));
95 smbios_test_chassis_mktable_append_strings(table);
96 smbios_test_table_str_fini(table);
97 smbios_test_table_append_eot(table);
98
99 return (B_TRUE);
100 }
101
102 boolean_t
smbios_test_chassis_mktable_comps(smbios_test_table_t * table)103 smbios_test_chassis_mktable_comps(smbios_test_table_t *table)
104 {
105 smb_chassis_t ch;
106 smb_chassis_entry_t ents[2];
107
108 smbios_test_chassis_mktable_fill_chassis(&ch);
109 smbios_test_chassis_mktable_fill_entries(ents);
110 ch.smbch_hdr.smbh_len += sizeof (ents);
111 ch.smbch_cn = 2;
112 (void) smbios_test_table_append(table, &ch, sizeof (ch));
113 smbios_test_table_append_raw(table, ents, sizeof (ents));
114 smbios_test_chassis_mktable_append_strings(table);
115 smbios_test_table_str_fini(table);
116 smbios_test_table_append_eot(table);
117
118 return (B_TRUE);
119 }
120
121 boolean_t
smbios_test_chassis_mktable_sku_nocomps(smbios_test_table_t * table)122 smbios_test_chassis_mktable_sku_nocomps(smbios_test_table_t *table)
123 {
124 smb_chassis_t ch;
125 const uint8_t sku_str = 5;
126
127 smbios_test_chassis_mktable_fill_chassis(&ch);
128 ch.smbch_hdr.smbh_len++;
129 (void) smbios_test_table_append(table, &ch, sizeof (ch));
130 smbios_test_table_append_raw(table, &sku_str, sizeof (sku_str));
131 smbios_test_chassis_mktable_append_strings(table);
132 smbios_test_table_append_string(table, smbios_chassis_sku);
133 smbios_test_table_str_fini(table);
134 smbios_test_table_append_eot(table);
135
136 return (B_TRUE);
137 }
138
139 boolean_t
smbios_test_chassis_mktable_sku(smbios_test_table_t * table)140 smbios_test_chassis_mktable_sku(smbios_test_table_t *table)
141 {
142 smb_chassis_t ch;
143 const uint8_t sku_str = 5;
144 smb_chassis_entry_t ents[2];
145
146 ch.smbch_cn = 2;
147
148 smbios_test_chassis_mktable_fill_chassis(&ch);
149 smbios_test_chassis_mktable_fill_entries(ents);
150 ch.smbch_hdr.smbh_len += sizeof (ents) + 1;
151 (void) smbios_test_table_append(table, &ch, sizeof (ch));
152 smbios_test_table_append_raw(table, &sku_str, sizeof (sku_str));
153 smbios_test_chassis_mktable_append_strings(table);
154 smbios_test_table_append_string(table, smbios_chassis_sku);
155 smbios_test_table_str_fini(table);
156 smbios_test_table_append_eot(table);
157
158 return (B_TRUE);
159 }
160
161 boolean_t
smbios_test_chassis_verify_invlen(smbios_hdl_t * hdl)162 smbios_test_chassis_verify_invlen(smbios_hdl_t *hdl)
163 {
164 smbios_struct_t sp;
165 smbios_chassis_t ch;
166
167 if (smbios_lookup_type(hdl, SMB_TYPE_CHASSIS, &sp) == -1) {
168 warnx("failed to lookup SMBIOS chassis: %s",
169 smbios_errmsg(smbios_errno(hdl)));
170 return (B_FALSE);
171 }
172
173 if (smbios_info_chassis(hdl, sp.smbstr_id, &ch) != -1) {
174 warnx("accidentally parsed invalid chassis as valid");
175 return (B_FALSE);
176 }
177
178 if (smbios_errno(hdl) != ESMB_SHORT) {
179 warnx("encountered wrong error for chassis, expected: "
180 "0x%x, found: 0x%x", ESMB_SHORT, smbios_errno(hdl));
181 return (B_FALSE);
182 }
183
184 return (B_TRUE);
185 }
186
187 static boolean_t
smbios_test_chassis_verify_common(smbios_hdl_t * hdl,smbios_struct_t * sp,smbios_chassis_t * ch)188 smbios_test_chassis_verify_common(smbios_hdl_t *hdl, smbios_struct_t *sp,
189 smbios_chassis_t *ch)
190 {
191 boolean_t ret = B_TRUE;
192 smbios_info_t info;
193
194 if (ch->smbc_oemdata != smbios_chassis_oem) {
195 warnx("chassis state mismatch, found unexpected oem data: 0x%x",
196 ch->smbc_oemdata);
197 ret = B_FALSE;
198 }
199
200 if (ch->smbc_lock != 0) {
201 warnx("chassis state mismatch, found unexpected lock: 0x%x",
202 ch->smbc_lock);
203 ret = B_FALSE;
204 }
205
206 if (ch->smbc_type != SMB_CHT_LUNCHBOX) {
207 warnx("chassis state mismatch, found unexpected type: 0x%x",
208 ch->smbc_type);
209 ret = B_FALSE;
210 }
211
212 if (ch->smbc_bustate != SMB_CHST_SAFE) {
213 warnx("chassis state mismatch, found unexpected boot state: "
214 "0x%x", ch->smbc_bustate);
215 ret = B_FALSE;
216 }
217
218 if (ch->smbc_psstate != SMB_CHST_NONREC) {
219 warnx("chassis state mismatch, found unexpected power state: "
220 "0x%x", ch->smbc_psstate);
221 ret = B_FALSE;
222 }
223
224 if (ch->smbc_thstate != SMB_CHST_WARNING) {
225 warnx("chassis state mismatch, found unexpected thermal state: "
226 "0x%x", ch->smbc_thstate);
227 ret = B_FALSE;
228 }
229
230 if (ch->smbc_security != SMB_CHSC_NONE) {
231 warnx("chassis state mismatch, found unexpected security "
232 "value: 0x%x", ch->smbc_security);
233 ret = B_FALSE;
234 }
235
236 if (ch->smbc_uheight != smbios_chassis_uheight) {
237 warnx("chassis state mismatch, found unexpected uheight value: "
238 "0x%x", ch->smbc_uheight);
239 ret = B_FALSE;
240 }
241
242 if (ch->smbc_cords != smbios_chassis_uheight - 1) {
243 warnx("chassis state mismatch, found unexpected cords value: "
244 "0x%x", ch->smbc_cords);
245 ret = B_FALSE;
246 }
247
248 if (ch->smbc_elemlen != sizeof (smb_chassis_entry_t)) {
249 warnx("chassis state mismatch, found unexpected elemlen value: "
250 "0x%x", ch->smbc_elemlen);
251 ret = B_FALSE;
252 }
253
254 if (smbios_info_common(hdl, sp->smbstr_id, &info) != 0) {
255 warnx("failed to get common chassis info: %s",
256 smbios_errmsg(smbios_errno(hdl)));
257 return (B_FALSE);
258 }
259
260 if (strcmp(info.smbi_manufacturer, smbios_chassis_mfg) != 0) {
261 warnx("chassis state mismatch, found unexpected mfg: "
262 "%s", info.smbi_manufacturer);
263 ret = B_FALSE;
264 }
265
266 if (strcmp(info.smbi_version, smbios_chassis_vers) != 0) {
267 warnx("chassis state mismatch, found unexpected version: %s",
268 info.smbi_version);
269 ret = B_FALSE;
270 }
271
272 if (strcmp(info.smbi_serial, smbios_chassis_serial) != 0) {
273 warnx("chassis state mismatch, found unexpected serial: %s",
274 info.smbi_serial);
275 ret = B_FALSE;
276 }
277
278 if (strcmp(info.smbi_asset, smbios_chassis_asset) != 0) {
279 warnx("chassis state mismatch, found unexpected asset: %s",
280 info.smbi_asset);
281 ret = B_FALSE;
282 }
283
284 return (ret);
285 }
286
287 boolean_t
smbios_test_chassis_verify_base(smbios_hdl_t * hdl)288 smbios_test_chassis_verify_base(smbios_hdl_t *hdl)
289 {
290 boolean_t ret = B_TRUE;
291 smbios_struct_t sp;
292 smbios_chassis_t ch;
293 smbios_chassis_entry_t *elts;
294 uint_t nelts;
295
296 if (smbios_lookup_type(hdl, SMB_TYPE_CHASSIS, &sp) == -1) {
297 warnx("failed to lookup SMBIOS chassis: %s",
298 smbios_errmsg(smbios_errno(hdl)));
299 return (B_FALSE);
300 }
301
302 if (smbios_info_chassis(hdl, sp.smbstr_id, &ch) == -1) {
303 warnx("failed to get chassis: %s",
304 smbios_errmsg(smbios_errno(hdl)));
305 return (B_FALSE);
306 }
307
308 if (!smbios_test_chassis_verify_common(hdl, &sp, &ch)) {
309 ret = B_FALSE;
310 }
311
312 if (ch.smbc_elems != 0) {
313 warnx("chassis state mismatch, found unexpected number of "
314 "elements: 0x%x", ch.smbc_elems);
315 ret = B_FALSE;
316 }
317
318 if (strcmp(ch.smbc_sku, "") != 0) {
319 warnx("chassis state mismatch, found unexpected sku: %s",
320 ch.smbc_sku);
321 ret = B_FALSE;
322 }
323
324 if (smbios_info_chassis_elts(hdl, sp.smbstr_id, &nelts, &elts) != 0) {
325 warnx("failed to get chassis elements: %s",
326 smbios_errmsg(smbios_errno(hdl)));
327 return (B_FALSE);
328 }
329
330 if (nelts != 0) {
331 warnx("chassis state mismatch, smbios_info_chassis_elts() "
332 "returned a non-zero number of entries: %u", nelts);
333 ret = B_FALSE;
334 }
335
336 if (elts != NULL) {
337 warnx("chassis state mismatch, smbios_info_chassis_elts() "
338 "returned a non-NULL pointer: %p", elts);
339 ret = B_FALSE;
340 }
341
342 return (ret);
343 }
344
345 boolean_t
smbios_test_chassis_verify_sku_nocomps(smbios_hdl_t * hdl)346 smbios_test_chassis_verify_sku_nocomps(smbios_hdl_t *hdl)
347 {
348 boolean_t ret = B_TRUE;
349 smbios_struct_t sp;
350 smbios_chassis_t ch;
351 smbios_chassis_entry_t *elts;
352 uint_t nelts;
353
354 if (smbios_lookup_type(hdl, SMB_TYPE_CHASSIS, &sp) == -1) {
355 warnx("failed to lookup SMBIOS chassis: %s",
356 smbios_errmsg(smbios_errno(hdl)));
357 return (B_FALSE);
358 }
359
360 if (smbios_info_chassis(hdl, sp.smbstr_id, &ch) == -1) {
361 warnx("failed to get chassis: %s",
362 smbios_errmsg(smbios_errno(hdl)));
363 return (B_FALSE);
364 }
365
366 if (!smbios_test_chassis_verify_common(hdl, &sp, &ch)) {
367 ret = B_FALSE;
368 }
369
370 if (ch.smbc_elems != 0) {
371 warnx("chassis state mismatch, found unexpected number of "
372 "elements: 0x%x", ch.smbc_elems);
373 ret = B_FALSE;
374 }
375
376 if (strcmp(ch.smbc_sku, smbios_chassis_sku) != 0) {
377 warnx("chassis state mismatch, found unexpected sku: %s",
378 ch.smbc_sku);
379 ret = B_FALSE;
380 }
381
382 if (smbios_info_chassis_elts(hdl, sp.smbstr_id, &nelts, &elts) != 0) {
383 warnx("failed to get chassis elements: %s",
384 smbios_errmsg(smbios_errno(hdl)));
385 return (B_FALSE);
386 }
387
388 if (nelts != 0) {
389 warnx("chassis state mismatch, smbios_info_chassis_elts() "
390 "returned a non-zero number of entries: %u", nelts);
391 ret = B_FALSE;
392 }
393
394 if (elts != NULL) {
395 warnx("chassis state mismatch, smbios_info_chassis_elts() "
396 "returned a non-NULL pointer: %p", elts);
397 ret = B_FALSE;
398 }
399
400
401 return (ret);
402 }
403
404 static boolean_t
smbios_test_chassis_verify_common_comps(smbios_hdl_t * hdl,smbios_struct_t * sp)405 smbios_test_chassis_verify_common_comps(smbios_hdl_t *hdl, smbios_struct_t *sp)
406 {
407 boolean_t ret = B_TRUE;
408 smbios_chassis_entry_t *elts;
409 uint_t nelts;
410
411 if (smbios_info_chassis_elts(hdl, sp->smbstr_id, &nelts, &elts) != 0) {
412 warnx("failed to get chassis elements: %s",
413 smbios_errmsg(smbios_errno(hdl)));
414 return (B_FALSE);
415 }
416
417 if (nelts != 2) {
418 warnx("chassis state mismatch, smbios_info_chassis_elts() "
419 "returned the wrong number of entries: %u", nelts);
420 return (B_FALSE);
421 }
422
423 if (elts[0].smbce_type != SMB_CELT_SMBIOS) {
424 warnx("chassis elts[0] type mismatch, found: %u",
425 elts[0].smbce_type);
426 ret = B_FALSE;
427 }
428
429 if (elts[0].smbce_elt != SMB_TYPE_COOLDEV) {
430 warnx("chassis elts[0] elt type mismatch, found: %u",
431 elts[0].smbce_elt);
432 ret = B_FALSE;
433 }
434
435 if (elts[0].smbce_min != 1) {
436 warnx("chassis elts[0] minimum number mismatch, found: %u",
437 elts[0].smbce_min);
438 ret = B_FALSE;
439 }
440
441 if (elts[0].smbce_max != 42) {
442 warnx("chassis elts[0] maximum number mismatch, found: %u",
443 elts[0].smbce_max);
444 ret = B_FALSE;
445 }
446
447 if (elts[1].smbce_type != SMB_CELT_BBOARD) {
448 warnx("chassis elts[1] type mismatch, found: %u",
449 elts[1].smbce_type);
450 ret = B_FALSE;
451 }
452
453 if (elts[1].smbce_elt != SMB_BBT_IO) {
454 warnx("chassis elts[1] elt type mismatch, found: %u",
455 elts[1].smbce_elt);
456 ret = B_FALSE;
457 }
458
459 if (elts[1].smbce_min != 5) {
460 warnx("chassis elts[1] minimum number mismatch, found: %u",
461 elts[1].smbce_min);
462 ret = B_FALSE;
463 }
464
465 if (elts[1].smbce_max != 123) {
466 warnx("chassis elts[1] maximum number mismatch, found: %u",
467 elts[1].smbce_max);
468 ret = B_FALSE;
469 }
470 return (ret);
471 }
472
473 boolean_t
smbios_test_chassis_verify_comps(smbios_hdl_t * hdl)474 smbios_test_chassis_verify_comps(smbios_hdl_t *hdl)
475 {
476 boolean_t ret = B_TRUE;
477 smbios_struct_t sp;
478 smbios_chassis_t ch;
479
480 if (smbios_lookup_type(hdl, SMB_TYPE_CHASSIS, &sp) == -1) {
481 warnx("failed to lookup SMBIOS chassis: %s",
482 smbios_errmsg(smbios_errno(hdl)));
483 return (B_FALSE);
484 }
485
486 if (smbios_info_chassis(hdl, sp.smbstr_id, &ch) == -1) {
487 warnx("failed to get chassis: %s",
488 smbios_errmsg(smbios_errno(hdl)));
489 return (B_FALSE);
490 }
491
492 if (!smbios_test_chassis_verify_common(hdl, &sp, &ch)) {
493 ret = B_FALSE;
494 }
495
496 if (ch.smbc_elems != 2) {
497 warnx("chassis state mismatch, found unexpected number of "
498 "elements: 0x%x", ch.smbc_elems);
499 ret = B_FALSE;
500 }
501
502 if (strcmp(ch.smbc_sku, "") != 0) {
503 warnx("chassis state mismatch, found unexpected sku: %s",
504 ch.smbc_sku);
505 ret = B_FALSE;
506 }
507
508 if (!smbios_test_chassis_verify_common_comps(hdl, &sp)) {
509 ret = B_FALSE;
510 }
511
512 return (ret);
513 }
514
515
516 boolean_t
smbios_test_chassis_verify_sku(smbios_hdl_t * hdl)517 smbios_test_chassis_verify_sku(smbios_hdl_t *hdl)
518 {
519 boolean_t ret = B_TRUE;
520 smbios_struct_t sp;
521 smbios_chassis_t ch;
522
523 if (smbios_lookup_type(hdl, SMB_TYPE_CHASSIS, &sp) == -1) {
524 warnx("failed to lookup SMBIOS chassis: %s",
525 smbios_errmsg(smbios_errno(hdl)));
526 return (B_FALSE);
527 }
528
529 if (smbios_info_chassis(hdl, sp.smbstr_id, &ch) == -1) {
530 warnx("failed to get chassis: %s",
531 smbios_errmsg(smbios_errno(hdl)));
532 return (B_FALSE);
533 }
534
535 if (!smbios_test_chassis_verify_common(hdl, &sp, &ch)) {
536 ret = B_FALSE;
537 }
538
539 if (ch.smbc_elems != 2) {
540 warnx("chassis state mismatch, found unexpected number of "
541 "elements: 0x%x", ch.smbc_elems);
542 ret = B_FALSE;
543 }
544
545 if (strcmp(ch.smbc_sku, smbios_chassis_sku) != 0) {
546 warnx("chassis state mismatch, found unexpected sku: %s",
547 ch.smbc_sku);
548 ret = B_FALSE;
549 }
550
551 if (!smbios_test_chassis_verify_common_comps(hdl, &sp)) {
552 ret = B_FALSE;
553 }
554
555 return (ret);
556 }
557