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 2026 Oxide Computer Company
14 */
15
16 /*
17 * Tests for SMBIOS System, Type 1.
18 *
19 * We basically create three different types of tables. Those that mimic 2.0 and
20 * therefore stop short of the UUID. Those that mimic 2.1-2.3 which fall short
21 * of the family string. And those that have everything.
22 */
23
24 #include "smbios_test.h"
25
26 #include <sys/uuid.h>
27
28 static const char *sys_mfg = "manufacturer";
29 static const char *sys_product = "product";
30 static const char *sys_version = "version";
31 static const char *sys_serial = "serial";
32 static const uint8_t sys_uuid[UUID_LEN] = { 0x01, 0x02, 0x03, 0x4, 0x5, 0x6,
33 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe };
34 static const uint8_t sys_wakeup = 0x42;
35 static const char *sys_sku = "SKU";
36 static const char *sys_family = "family";
37
38 static void
smbios_test_system_mktable_common(smbios_test_table_t * table,size_t len)39 smbios_test_system_mktable_common(smbios_test_table_t *table, size_t len)
40 {
41 smb_system_t sys;
42
43 sys.smbsi_hdr.smbh_type = SMB_TYPE_SYSTEM;
44 sys.smbsi_hdr.smbh_len = len;
45
46 sys.smbsi_manufacturer = 1;
47 sys.smbsi_product = 2;
48 sys.smbsi_version = 3;
49 sys.smbsi_serial = 4;
50 (void) memcpy(sys.smbsi_uuid, sys_uuid, ARRAY_SIZE(sys_uuid));
51 sys.smbsi_wakeup = sys_wakeup;
52 sys.smbsi_sku = 5;
53 sys.smbsi_family = 6;
54
55 (void) smbios_test_table_append(table, &sys, len);
56 if (len > offsetof(smb_system_t, smbsi_manufacturer))
57 smbios_test_table_append_string(table, sys_mfg);
58 if (len > offsetof(smb_system_t, smbsi_product))
59 smbios_test_table_append_string(table, sys_product);
60 if (len > offsetof(smb_system_t, smbsi_version))
61 smbios_test_table_append_string(table, sys_version);
62 if (len > offsetof(smb_system_t, smbsi_serial))
63 smbios_test_table_append_string(table, sys_serial);
64 if (len > offsetof(smb_system_t, smbsi_sku))
65 smbios_test_table_append_string(table, sys_sku);
66 if (len > offsetof(smb_system_t, smbsi_family))
67 smbios_test_table_append_string(table, sys_family);
68 if (len > offsetof(smb_system_t, smbsi_manufacturer))
69 smbios_test_table_str_fini(table);
70 smbios_test_table_append_eot(table);
71 }
72
73 boolean_t
smbios_test_system_mktable_2p0(smbios_test_table_t * table)74 smbios_test_system_mktable_2p0(smbios_test_table_t *table)
75 {
76 smbios_test_system_mktable_common(table, offsetof(smb_system_t,
77 smbsi_uuid));
78 return (B_TRUE);
79 }
80
81 boolean_t
smbios_test_system_mktable_2p3(smbios_test_table_t * table)82 smbios_test_system_mktable_2p3(smbios_test_table_t *table)
83 {
84 smbios_test_system_mktable_common(table, offsetof(smb_system_t,
85 smbsi_family));
86 return (B_TRUE);
87 }
88
89 boolean_t
smbios_test_system_mktable(smbios_test_table_t * table)90 smbios_test_system_mktable(smbios_test_table_t *table)
91 {
92 smbios_test_system_mktable_common(table, sizeof (smb_system_t));
93 return (B_TRUE);
94 }
95
96 static boolean_t
smbios_test_system_verify_common(smbios_hdl_t * hdl,size_t len)97 smbios_test_system_verify_common(smbios_hdl_t *hdl, size_t len)
98 {
99 boolean_t ret = B_TRUE;
100 id_t id;
101 smbios_struct_t sp;
102 smbios_system_t sys;
103 smbios_info_t info;
104
105 if (smbios_lookup_type(hdl, SMB_TYPE_SYSTEM, &sp) == -1) {
106 warnx("failed to lookup SMBIOS system: %s",
107 smbios_errmsg(smbios_errno(hdl)));
108 return (B_FALSE);
109 }
110
111 id = smbios_info_system(hdl, &sys);
112 if (id < 0) {
113 warnx("failed to get system information: %s",
114 smbios_errmsg(smbios_errno(hdl)));
115 return (B_FALSE);
116 }
117
118 if (id != sp.smbstr_id) {
119 warnx("found mismatched IDs: smbios_info_system() returned 0x%"
120 _PRIxID ", but lookup gave us 0x%" _PRIxID, id,
121 sp.smbstr_id);
122 return (B_FALSE);
123 }
124
125 if (smbios_info_common(hdl, id, &info) != 0) {
126 warnx("failed to get system common information: %s",
127 smbios_errmsg(smbios_errno(hdl)));
128 return (B_FALSE);
129 }
130
131 /*
132 * Everything should always have a manufacturer, product, version, and
133 * serial.
134 */
135 if (strcmp(info.smbi_manufacturer, sys_mfg) != 0) {
136 warnx("found wrong manufacturer %s: expected %s",
137 info.smbi_manufacturer, sys_mfg);
138 ret = B_FALSE;
139 }
140
141 if (strcmp(info.smbi_product, sys_product) != 0) {
142 warnx("found wrong product %s: expected %s",
143 info.smbi_product, sys_product);
144 ret = B_FALSE;
145 }
146
147 if (strcmp(info.smbi_version, sys_version) != 0) {
148 warnx("found wrong version %s: expected %s",
149 info.smbi_version, sys_version);
150 ret = B_FALSE;
151 }
152
153 if (strcmp(info.smbi_serial, sys_serial) != 0) {
154 warnx("found wrong serial %s: expected %s",
155 info.smbi_serial, sys_serial);
156 ret = B_FALSE;
157 }
158
159 if (len >= offsetof(smb_system_t, smbsi_wakeup)) {
160 if (sys.smbs_uuidlen != ARRAY_SIZE(sys_uuid)) {
161 warnx("found wrong uuid length %u: expected %zu",
162 sys.smbs_uuidlen, ARRAY_SIZE(sys_uuid));
163 ret = B_FALSE;
164 }
165
166 if (sys.smbs_uuid == NULL) {
167 warnx("found unexpected NULL uuid pointer");
168 ret = B_FALSE;
169 }
170
171 if (sys.smbs_uuidlen == ARRAY_SIZE(sys_uuid) &&
172 sys.smbs_uuid != NULL && memcmp(sys.smbs_uuid,
173 sys_uuid, sizeof (sys_uuid)) != 0) {
174 warnx("encountered UUID mismatch");
175 ret = B_FALSE;
176 }
177 } else {
178 if (sys.smbs_uuid != NULL) {
179 warnx("found unexpected non-NULL uuid pointer");
180 ret = B_FALSE;
181 }
182
183 if (sys.smbs_uuidlen != 0) {
184 warnx("found unexpected non-zero uuid length: %u",
185 sys.smbs_uuidlen);
186 ret = B_FALSE;
187 }
188 }
189
190 if (len >= offsetof(smb_system_t, smbsi_sku)) {
191 if (sys.smbs_wakeup != sys_wakeup) {
192 warnx("found wrong wakeup 0x%x: expected 0x%x",
193 sys.smbs_wakeup, sys_wakeup);
194 ret = B_FALSE;
195 }
196 } else if (sys.smbs_wakeup != 0) {
197 warnx("found wrong wakeup 0x%x: expected none",
198 sys.smbs_wakeup);
199 ret = B_FALSE;
200 }
201
202 if (len >= offsetof(smb_system_t, smbsi_family)) {
203 if (strcmp(sys.smbs_sku, sys_sku) != 0) {
204 warnx("found wrong sku %s: expected %s",
205 sys.smbs_sku, sys_sku);
206 ret = B_FALSE;
207 }
208 } else if (strcmp(sys.smbs_sku, "") != 0) {
209 warnx("found wrong sku %s: expected none", sys.smbs_sku);
210 ret = B_FALSE;
211 }
212
213 if (len >= sizeof (smb_system_t)) {
214 if (strcmp(sys.smbs_family, sys_family) != 0) {
215 warnx("found wrong family %s: expected %s",
216 sys.smbs_family, sys_family);
217 ret = B_FALSE;
218 }
219 } else if (strcmp(sys.smbs_family, "") != 0) {
220 warnx("found wrong family %s: expected none", sys.smbs_family);
221 ret = B_FALSE;
222 }
223
224 return (ret);
225 }
226
227 boolean_t
smbios_test_system_verify_2p0(smbios_hdl_t * hdl)228 smbios_test_system_verify_2p0(smbios_hdl_t *hdl)
229 {
230 return (smbios_test_system_verify_common(hdl, offsetof(smb_system_t,
231 smbsi_uuid)));
232 }
233
234 boolean_t
smbios_test_system_verify_2p3(smbios_hdl_t * hdl)235 smbios_test_system_verify_2p3(smbios_hdl_t *hdl)
236 {
237 return (smbios_test_system_verify_common(hdl, offsetof(smb_system_t,
238 smbsi_family)));
239 }
240
241 boolean_t
smbios_test_system_verify(smbios_hdl_t * hdl)242 smbios_test_system_verify(smbios_hdl_t *hdl)
243 {
244 return (smbios_test_system_verify_common(hdl, sizeof (smb_system_t)));
245 }
246