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 2024 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 /*
103 * A variant of the base that doesn't include the element length becaue there
104 * are no elements.
105 */
106 boolean_t
smbios_test_chassis_mktable_part(smbios_test_table_t * table)107 smbios_test_chassis_mktable_part(smbios_test_table_t *table)
108 {
109 smb_chassis_t ch;
110 size_t len = offsetof(smb_chassis_t, smbch_cn);
111
112 smbios_test_chassis_mktable_fill_chassis(&ch);
113 ch.smbch_hdr.smbh_len = len;
114 (void) smbios_test_table_append(table, &ch, len);
115 smbios_test_chassis_mktable_append_strings(table);
116 smbios_test_table_str_fini(table);
117 smbios_test_table_append_eot(table);
118
119 return (B_TRUE);
120 }
121
122 boolean_t
smbios_test_chassis_mktable_comps(smbios_test_table_t * table)123 smbios_test_chassis_mktable_comps(smbios_test_table_t *table)
124 {
125 smb_chassis_t ch;
126 smb_chassis_entry_t ents[2];
127
128 smbios_test_chassis_mktable_fill_chassis(&ch);
129 smbios_test_chassis_mktable_fill_entries(ents);
130 ch.smbch_hdr.smbh_len += sizeof (ents);
131 ch.smbch_cn = 2;
132 (void) smbios_test_table_append(table, &ch, sizeof (ch));
133 smbios_test_table_append_raw(table, ents, sizeof (ents));
134 smbios_test_chassis_mktable_append_strings(table);
135 smbios_test_table_str_fini(table);
136 smbios_test_table_append_eot(table);
137
138 return (B_TRUE);
139 }
140
141 boolean_t
smbios_test_chassis_mktable_sku_nocomps(smbios_test_table_t * table)142 smbios_test_chassis_mktable_sku_nocomps(smbios_test_table_t *table)
143 {
144 smb_chassis_t ch;
145 const uint8_t sku_str = 5;
146
147 smbios_test_chassis_mktable_fill_chassis(&ch);
148 ch.smbch_hdr.smbh_len++;
149 (void) smbios_test_table_append(table, &ch, sizeof (ch));
150 smbios_test_table_append_raw(table, &sku_str, sizeof (sku_str));
151 smbios_test_chassis_mktable_append_strings(table);
152 smbios_test_table_append_string(table, smbios_chassis_sku);
153 smbios_test_table_str_fini(table);
154 smbios_test_table_append_eot(table);
155
156 return (B_TRUE);
157 }
158
159 boolean_t
smbios_test_chassis_mktable_sku(smbios_test_table_t * table)160 smbios_test_chassis_mktable_sku(smbios_test_table_t *table)
161 {
162 smb_chassis_t ch;
163 const uint8_t sku_str = 5;
164 smb_chassis_entry_t ents[2];
165
166 ch.smbch_cn = 2;
167
168 smbios_test_chassis_mktable_fill_chassis(&ch);
169 smbios_test_chassis_mktable_fill_entries(ents);
170 ch.smbch_hdr.smbh_len += sizeof (ents) + 1;
171 (void) smbios_test_table_append(table, &ch, sizeof (ch));
172 smbios_test_table_append_raw(table, &sku_str, sizeof (sku_str));
173 smbios_test_chassis_mktable_append_strings(table);
174 smbios_test_table_append_string(table, smbios_chassis_sku);
175 smbios_test_table_str_fini(table);
176 smbios_test_table_append_eot(table);
177
178 return (B_TRUE);
179 }
180
181 boolean_t
smbios_test_chassis_verify_invlen(smbios_hdl_t * hdl)182 smbios_test_chassis_verify_invlen(smbios_hdl_t *hdl)
183 {
184 smbios_struct_t sp;
185 smbios_chassis_t ch;
186
187 if (smbios_lookup_type(hdl, SMB_TYPE_CHASSIS, &sp) == -1) {
188 warnx("failed to lookup SMBIOS chassis: %s",
189 smbios_errmsg(smbios_errno(hdl)));
190 return (B_FALSE);
191 }
192
193 if (smbios_info_chassis(hdl, sp.smbstr_id, &ch) != -1) {
194 warnx("accidentally parsed invalid chassis as valid");
195 return (B_FALSE);
196 }
197
198 if (smbios_errno(hdl) != ESMB_SHORT) {
199 warnx("encountered wrong error for chassis, expected: "
200 "0x%x, found: 0x%x", ESMB_SHORT, smbios_errno(hdl));
201 return (B_FALSE);
202 }
203
204 return (B_TRUE);
205 }
206
207 static boolean_t
smbios_test_chassis_verify_common(smbios_hdl_t * hdl,smbios_struct_t * sp,smbios_chassis_t * ch)208 smbios_test_chassis_verify_common(smbios_hdl_t *hdl, smbios_struct_t *sp,
209 smbios_chassis_t *ch)
210 {
211 boolean_t ret = B_TRUE;
212 smbios_info_t info;
213
214 if (ch->smbc_oemdata != smbios_chassis_oem) {
215 warnx("chassis state mismatch, found unexpected oem data: 0x%x",
216 ch->smbc_oemdata);
217 ret = B_FALSE;
218 }
219
220 if (ch->smbc_lock != 0) {
221 warnx("chassis state mismatch, found unexpected lock: 0x%x",
222 ch->smbc_lock);
223 ret = B_FALSE;
224 }
225
226 if (ch->smbc_type != SMB_CHT_LUNCHBOX) {
227 warnx("chassis state mismatch, found unexpected type: 0x%x",
228 ch->smbc_type);
229 ret = B_FALSE;
230 }
231
232 if (ch->smbc_bustate != SMB_CHST_SAFE) {
233 warnx("chassis state mismatch, found unexpected boot state: "
234 "0x%x", ch->smbc_bustate);
235 ret = B_FALSE;
236 }
237
238 if (ch->smbc_psstate != SMB_CHST_NONREC) {
239 warnx("chassis state mismatch, found unexpected power state: "
240 "0x%x", ch->smbc_psstate);
241 ret = B_FALSE;
242 }
243
244 if (ch->smbc_thstate != SMB_CHST_WARNING) {
245 warnx("chassis state mismatch, found unexpected thermal state: "
246 "0x%x", ch->smbc_thstate);
247 ret = B_FALSE;
248 }
249
250 if (ch->smbc_security != SMB_CHSC_NONE) {
251 warnx("chassis state mismatch, found unexpected security "
252 "value: 0x%x", ch->smbc_security);
253 ret = B_FALSE;
254 }
255
256 if (ch->smbc_uheight != smbios_chassis_uheight) {
257 warnx("chassis state mismatch, found unexpected uheight value: "
258 "0x%x", ch->smbc_uheight);
259 ret = B_FALSE;
260 }
261
262 if (ch->smbc_cords != smbios_chassis_uheight - 1) {
263 warnx("chassis state mismatch, found unexpected cords value: "
264 "0x%x", ch->smbc_cords);
265 ret = B_FALSE;
266 }
267
268 if (smbios_info_common(hdl, sp->smbstr_id, &info) != 0) {
269 warnx("failed to get common chassis info: %s",
270 smbios_errmsg(smbios_errno(hdl)));
271 return (B_FALSE);
272 }
273
274 if (strcmp(info.smbi_manufacturer, smbios_chassis_mfg) != 0) {
275 warnx("chassis state mismatch, found unexpected mfg: "
276 "%s", info.smbi_manufacturer);
277 ret = B_FALSE;
278 }
279
280 if (strcmp(info.smbi_version, smbios_chassis_vers) != 0) {
281 warnx("chassis state mismatch, found unexpected version: %s",
282 info.smbi_version);
283 ret = B_FALSE;
284 }
285
286 if (strcmp(info.smbi_serial, smbios_chassis_serial) != 0) {
287 warnx("chassis state mismatch, found unexpected serial: %s",
288 info.smbi_serial);
289 ret = B_FALSE;
290 }
291
292 if (strcmp(info.smbi_asset, smbios_chassis_asset) != 0) {
293 warnx("chassis state mismatch, found unexpected asset: %s",
294 info.smbi_asset);
295 ret = B_FALSE;
296 }
297
298 return (ret);
299 }
300
301 boolean_t
smbios_test_chassis_verify_base(smbios_hdl_t * hdl)302 smbios_test_chassis_verify_base(smbios_hdl_t *hdl)
303 {
304 boolean_t ret = B_TRUE;
305 smbios_struct_t sp;
306 smbios_chassis_t ch;
307 smbios_chassis_entry_t *elts;
308 uint_t nelts;
309
310 if (smbios_lookup_type(hdl, SMB_TYPE_CHASSIS, &sp) == -1) {
311 warnx("failed to lookup SMBIOS chassis: %s",
312 smbios_errmsg(smbios_errno(hdl)));
313 return (B_FALSE);
314 }
315
316 if (smbios_info_chassis(hdl, sp.smbstr_id, &ch) == -1) {
317 warnx("failed to get chassis: %s",
318 smbios_errmsg(smbios_errno(hdl)));
319 return (B_FALSE);
320 }
321
322 if (!smbios_test_chassis_verify_common(hdl, &sp, &ch)) {
323 ret = B_FALSE;
324 }
325
326 if (ch.smbc_elems != 0) {
327 warnx("chassis state mismatch, found unexpected number of "
328 "elements: 0x%x", ch.smbc_elems);
329 ret = B_FALSE;
330 }
331
332 if (strcmp(ch.smbc_sku, "") != 0) {
333 warnx("chassis state mismatch, found unexpected sku: %s",
334 ch.smbc_sku);
335 ret = B_FALSE;
336 }
337
338 if (smbios_info_chassis_elts(hdl, sp.smbstr_id, &nelts, &elts) != 0) {
339 warnx("failed to get chassis elements: %s",
340 smbios_errmsg(smbios_errno(hdl)));
341 return (B_FALSE);
342 }
343
344 if (nelts != 0) {
345 warnx("chassis state mismatch, smbios_info_chassis_elts() "
346 "returned a non-zero number of entries: %u", nelts);
347 ret = B_FALSE;
348 }
349
350 if (elts != NULL) {
351 warnx("chassis state mismatch, smbios_info_chassis_elts() "
352 "returned a non-NULL pointer: %p", elts);
353 ret = B_FALSE;
354 }
355
356 return (ret);
357 }
358
359 boolean_t
smbios_test_chassis_verify_sku_nocomps(smbios_hdl_t * hdl)360 smbios_test_chassis_verify_sku_nocomps(smbios_hdl_t *hdl)
361 {
362 boolean_t ret = B_TRUE;
363 smbios_struct_t sp;
364 smbios_chassis_t ch;
365 smbios_chassis_entry_t *elts;
366 uint_t nelts;
367
368 if (smbios_lookup_type(hdl, SMB_TYPE_CHASSIS, &sp) == -1) {
369 warnx("failed to lookup SMBIOS chassis: %s",
370 smbios_errmsg(smbios_errno(hdl)));
371 return (B_FALSE);
372 }
373
374 if (smbios_info_chassis(hdl, sp.smbstr_id, &ch) == -1) {
375 warnx("failed to get chassis: %s",
376 smbios_errmsg(smbios_errno(hdl)));
377 return (B_FALSE);
378 }
379
380 if (!smbios_test_chassis_verify_common(hdl, &sp, &ch)) {
381 ret = B_FALSE;
382 }
383
384 if (ch.smbc_elems != 0) {
385 warnx("chassis state mismatch, found unexpected number of "
386 "elements: 0x%x", ch.smbc_elems);
387 ret = B_FALSE;
388 }
389
390 if (ch.smbc_elemlen != sizeof (smb_chassis_entry_t)) {
391 warnx("chassis state mismatch, found unexpected elemlen value: "
392 "0x%x", ch.smbc_elemlen);
393 ret = B_FALSE;
394 }
395
396 if (strcmp(ch.smbc_sku, smbios_chassis_sku) != 0) {
397 warnx("chassis state mismatch, found unexpected sku: %s",
398 ch.smbc_sku);
399 ret = B_FALSE;
400 }
401
402 if (smbios_info_chassis_elts(hdl, sp.smbstr_id, &nelts, &elts) != 0) {
403 warnx("failed to get chassis elements: %s",
404 smbios_errmsg(smbios_errno(hdl)));
405 return (B_FALSE);
406 }
407
408 if (nelts != 0) {
409 warnx("chassis state mismatch, smbios_info_chassis_elts() "
410 "returned a non-zero number of entries: %u", nelts);
411 ret = B_FALSE;
412 }
413
414 if (elts != NULL) {
415 warnx("chassis state mismatch, smbios_info_chassis_elts() "
416 "returned a non-NULL pointer: %p", elts);
417 ret = B_FALSE;
418 }
419
420
421 return (ret);
422 }
423
424 static boolean_t
smbios_test_chassis_verify_common_comps(smbios_hdl_t * hdl,smbios_struct_t * sp)425 smbios_test_chassis_verify_common_comps(smbios_hdl_t *hdl, smbios_struct_t *sp)
426 {
427 boolean_t ret = B_TRUE;
428 smbios_chassis_entry_t *elts;
429 uint_t nelts;
430
431 if (smbios_info_chassis_elts(hdl, sp->smbstr_id, &nelts, &elts) != 0) {
432 warnx("failed to get chassis elements: %s",
433 smbios_errmsg(smbios_errno(hdl)));
434 return (B_FALSE);
435 }
436
437 if (nelts != 2) {
438 warnx("chassis state mismatch, smbios_info_chassis_elts() "
439 "returned the wrong number of entries: %u", nelts);
440 return (B_FALSE);
441 }
442
443 if (elts[0].smbce_type != SMB_CELT_SMBIOS) {
444 warnx("chassis elts[0] type mismatch, found: %u",
445 elts[0].smbce_type);
446 ret = B_FALSE;
447 }
448
449 if (elts[0].smbce_elt != SMB_TYPE_COOLDEV) {
450 warnx("chassis elts[0] elt type mismatch, found: %u",
451 elts[0].smbce_elt);
452 ret = B_FALSE;
453 }
454
455 if (elts[0].smbce_min != 1) {
456 warnx("chassis elts[0] minimum number mismatch, found: %u",
457 elts[0].smbce_min);
458 ret = B_FALSE;
459 }
460
461 if (elts[0].smbce_max != 42) {
462 warnx("chassis elts[0] maximum number mismatch, found: %u",
463 elts[0].smbce_max);
464 ret = B_FALSE;
465 }
466
467 if (elts[1].smbce_type != SMB_CELT_BBOARD) {
468 warnx("chassis elts[1] type mismatch, found: %u",
469 elts[1].smbce_type);
470 ret = B_FALSE;
471 }
472
473 if (elts[1].smbce_elt != SMB_BBT_IO) {
474 warnx("chassis elts[1] elt type mismatch, found: %u",
475 elts[1].smbce_elt);
476 ret = B_FALSE;
477 }
478
479 if (elts[1].smbce_min != 5) {
480 warnx("chassis elts[1] minimum number mismatch, found: %u",
481 elts[1].smbce_min);
482 ret = B_FALSE;
483 }
484
485 if (elts[1].smbce_max != 123) {
486 warnx("chassis elts[1] maximum number mismatch, found: %u",
487 elts[1].smbce_max);
488 ret = B_FALSE;
489 }
490 return (ret);
491 }
492
493 boolean_t
smbios_test_chassis_verify_comps(smbios_hdl_t * hdl)494 smbios_test_chassis_verify_comps(smbios_hdl_t *hdl)
495 {
496 boolean_t ret = B_TRUE;
497 smbios_struct_t sp;
498 smbios_chassis_t ch;
499
500 if (smbios_lookup_type(hdl, SMB_TYPE_CHASSIS, &sp) == -1) {
501 warnx("failed to lookup SMBIOS chassis: %s",
502 smbios_errmsg(smbios_errno(hdl)));
503 return (B_FALSE);
504 }
505
506 if (smbios_info_chassis(hdl, sp.smbstr_id, &ch) == -1) {
507 warnx("failed to get chassis: %s",
508 smbios_errmsg(smbios_errno(hdl)));
509 return (B_FALSE);
510 }
511
512 if (!smbios_test_chassis_verify_common(hdl, &sp, &ch)) {
513 ret = B_FALSE;
514 }
515
516 if (ch.smbc_elems != 2) {
517 warnx("chassis state mismatch, found unexpected number of "
518 "elements: 0x%x", ch.smbc_elems);
519 ret = B_FALSE;
520 }
521
522 if (ch.smbc_elemlen != sizeof (smb_chassis_entry_t)) {
523 warnx("chassis state mismatch, found unexpected elemlen value: "
524 "0x%x", ch.smbc_elemlen);
525 ret = B_FALSE;
526 }
527
528 if (strcmp(ch.smbc_sku, "") != 0) {
529 warnx("chassis state mismatch, found unexpected sku: %s",
530 ch.smbc_sku);
531 ret = B_FALSE;
532 }
533
534 if (!smbios_test_chassis_verify_common_comps(hdl, &sp)) {
535 ret = B_FALSE;
536 }
537
538 return (ret);
539 }
540
541
542 boolean_t
smbios_test_chassis_verify_sku(smbios_hdl_t * hdl)543 smbios_test_chassis_verify_sku(smbios_hdl_t *hdl)
544 {
545 boolean_t ret = B_TRUE;
546 smbios_struct_t sp;
547 smbios_chassis_t ch;
548
549 if (smbios_lookup_type(hdl, SMB_TYPE_CHASSIS, &sp) == -1) {
550 warnx("failed to lookup SMBIOS chassis: %s",
551 smbios_errmsg(smbios_errno(hdl)));
552 return (B_FALSE);
553 }
554
555 if (smbios_info_chassis(hdl, sp.smbstr_id, &ch) == -1) {
556 warnx("failed to get chassis: %s",
557 smbios_errmsg(smbios_errno(hdl)));
558 return (B_FALSE);
559 }
560
561 if (!smbios_test_chassis_verify_common(hdl, &sp, &ch)) {
562 ret = B_FALSE;
563 }
564
565 if (ch.smbc_elems != 2) {
566 warnx("chassis state mismatch, found unexpected number of "
567 "elements: 0x%x", ch.smbc_elems);
568 ret = B_FALSE;
569 }
570
571 if (ch.smbc_elemlen != sizeof (smb_chassis_entry_t)) {
572 warnx("chassis state mismatch, found unexpected elemlen value: "
573 "0x%x", ch.smbc_elemlen);
574 ret = B_FALSE;
575 }
576
577 if (strcmp(ch.smbc_sku, smbios_chassis_sku) != 0) {
578 warnx("chassis state mismatch, found unexpected sku: %s",
579 ch.smbc_sku);
580 ret = B_FALSE;
581 }
582
583 if (!smbios_test_chassis_verify_common_comps(hdl, &sp)) {
584 ret = B_FALSE;
585 }
586
587 return (ret);
588 }
589