xref: /illumos-gate/usr/src/test/util-tests/tests/smbios/smbios.c (revision c94be9439c4f0773ef60e2cec21d548359cfea20)
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 (c) 2018, Joyent, Inc.
14  */
15 
16 /*
17  * Primordial SMBIOS test suite. At the moment, the purpose of this is just to
18  * test the recent SMBIOS 3.2 additions specific to the variable length slots.
19  * This should be evolved into a much fuller test suite.
20  */
21 
22 #include <umem.h>
23 #include "smbios_test.h"
24 
25 const char *
26 _umem_debug_init(void)
27 {
28 	return ("default,verbose");
29 }
30 
31 const char *
32 _umem_logging_init(void)
33 {
34 	return ("fail,contents");
35 }
36 
37 smbios_test_table_t *
38 smbios_test_table_init(smbios_entry_point_t type, uint_t version)
39 {
40 	smbios_test_table_t *table;
41 
42 	if (type != SMBIOS_ENTRY_POINT_30) {
43 		abort();
44 	}
45 
46 	table = umem_zalloc(sizeof (smbios_test_table_t), UMEM_DEFAULT);
47 	if (table == NULL) {
48 		return (NULL);
49 	}
50 
51 	table->stt_data = umem_zalloc(SMBIOS_TEST_ALLOC_SIZE, UMEM_DEFAULT);
52 	if (table->stt_data == NULL) {
53 		umem_free(table, sizeof (smbios_test_table_t));
54 		return (NULL);
55 	}
56 	table->stt_buflen = SMBIOS_TEST_ALLOC_SIZE;
57 	table->stt_type = type;
58 	table->stt_version = version;
59 	table->stt_nextid = 1;
60 
61 	return (table);
62 }
63 
64 static void *
65 smbios_test_table_append_common(smbios_test_table_t *table, const void *buf,
66     size_t len)
67 {
68 	void *start;
69 
70 	if (SIZE_MAX - table->stt_offset < len)
71 		abort();
72 
73 	if (len + table->stt_offset >= table->stt_buflen) {
74 		void *newbuf;
75 		size_t newlen = table->stt_buflen + SMBIOS_TEST_ALLOC_SIZE;
76 
77 		while (len + table->stt_offset >= newlen) {
78 			newlen += SMBIOS_TEST_ALLOC_SIZE;
79 		}
80 
81 		newbuf = umem_zalloc(newlen, UMEM_DEFAULT);
82 		if (newbuf == NULL) {
83 			err(EXIT_FAILURE, "failed to umem_zalloc for %lu bytes",
84 			    newlen);
85 		}
86 
87 		(void) memcpy(newbuf, table->stt_data, table->stt_buflen);
88 		umem_free(table->stt_data, table->stt_buflen);
89 		table->stt_data = newbuf;
90 		table->stt_buflen = newlen;
91 	}
92 
93 	start = (void *)((uintptr_t)table->stt_data + table->stt_offset);
94 	(void) memcpy(start, buf, len);
95 	table->stt_offset += len;
96 
97 	return (start);
98 }
99 
100 void
101 smbios_test_table_append_raw(smbios_test_table_t *table, const void *buf,
102     size_t len)
103 {
104 	(void) smbios_test_table_append_common(table, buf, len);
105 }
106 
107 void
108 smbios_test_table_append_string(smbios_test_table_t *table, const char *str)
109 {
110 	size_t len = strlen(str) + 1;
111 	(void) smbios_test_table_append_common(table, str, len);
112 }
113 
114 uint16_t
115 smbios_test_table_append(smbios_test_table_t *table, const void *buf,
116     size_t len)
117 {
118 	smb_header_t *hdr;
119 	uint16_t id;
120 
121 	hdr = smbios_test_table_append_common(table, buf, len);
122 	table->stt_nents++;
123 
124 	id = table->stt_nextid;
125 	hdr->smbh_hdl = htole16(table->stt_nextid);
126 	table->stt_nextid++;
127 
128 	return (id);
129 }
130 
131 void
132 smbios_test_table_append_eot(smbios_test_table_t *table)
133 {
134 	smb_header_t eot;
135 	uint8_t endstring = 0;
136 
137 	bzero(&eot, sizeof (eot));
138 	eot.smbh_type = SMB_TYPE_EOT;
139 	eot.smbh_len = 4;
140 	(void) smbios_test_table_append(table, &eot, sizeof (eot));
141 	(void) smbios_test_table_append_raw(table, &endstring,
142 	    sizeof (endstring));
143 	smbios_test_table_append_raw(table, &endstring,
144 	    sizeof (endstring));
145 	smbios_test_table_append_raw(table, &endstring,
146 	    sizeof (endstring));
147 
148 }
149 
150 static uint8_t
151 smbios_test_table_checksum(const uint8_t *buf, size_t len)
152 {
153 	uint8_t sum;
154 	size_t i;
155 
156 	for (i = 0, sum = 0; i < len; i++) {
157 		sum += buf[i];
158 	}
159 
160 	if (sum == 0)
161 		return (0);
162 
163 	return ((uint8_t)(0x100 - sum));
164 }
165 
166 static void
167 smbios_test_table_snapshot(smbios_test_table_t *table, smbios_entry_t **entryp,
168     void **bufp, size_t *lenp)
169 {
170 	smbios_30_entry_t *ent30;
171 
172 	switch (table->stt_type) {
173 	case SMBIOS_ENTRY_POINT_30:
174 		ent30 = &table->stt_entry.ep30;
175 
176 		(void) memcpy(ent30->smbe_eanchor, SMB3_ENTRY_EANCHOR,
177 		    sizeof (ent30->smbe_eanchor));
178 		ent30->smbe_ecksum = 0;
179 		ent30->smbe_elen = sizeof (*ent30);
180 		ent30->smbe_major = (table->stt_version >> 8) & 0xff;
181 		ent30->smbe_minor = table->stt_version & 0xff;
182 		ent30->smbe_docrev = 0;
183 		ent30->smbe_revision = 1;
184 		ent30->smbe_reserved = 0;
185 		ent30->smbe_stlen = htole32(table->stt_offset);
186 		ent30->smbe_staddr = htole64(P2ROUNDUP(sizeof (*ent30), 16));
187 
188 		ent30->smbe_ecksum = smbios_test_table_checksum((void *)ent30,
189 		    sizeof (*ent30));
190 		break;
191 	default:
192 		abort();
193 	}
194 
195 	*entryp = &table->stt_entry;
196 	*bufp = table->stt_data;
197 	*lenp = table->stt_offset;
198 }
199 
200 static void
201 smbios_test_table_fini(smbios_test_table_t *table)
202 {
203 	if (table == NULL) {
204 		return;
205 	}
206 
207 	if (table->stt_data != NULL) {
208 		umem_free(table->stt_data, table->stt_buflen);
209 	}
210 
211 	umem_free(table, sizeof (smbios_test_table_t));
212 }
213 
214 static const smbios_test_t smbios_tests[] = {
215 	{
216 	    .st_entry = SMBIOS_ENTRY_POINT_30,
217 	    .st_tvers = SMB_VERSION_32,
218 	    .st_libvers = SMB_VERSION,
219 	    .st_mktable = smbios_test_slot_mktable,
220 	    .st_canopen = B_TRUE,
221 	    .st_verify = smbios_test_slot_verify,
222 	    .st_desc = "slot tests"
223 	}, {
224 	    .st_entry = SMBIOS_ENTRY_POINT_30,
225 	    .st_tvers = SMB_VERSION,
226 	    .st_libvers = 0xffff,
227 	    .st_mktable = smbios_test_badvers_mktable,
228 	    .st_desc = "bad library version"
229 	}, {
230 	    .st_entry = SMBIOS_ENTRY_POINT_30,
231 	    .st_tvers = SMB_VERSION_32,
232 	    .st_libvers = SMB_VERSION_32,
233 	    .st_mktable = smbios_test_memdevice_mktable_32,
234 	    .st_canopen = B_TRUE,
235 	    .st_verify = smbios_test_memdevice_verify_32,
236 	    .st_desc = "memory device 3.2 / 3.2"
237 	}, {
238 	    .st_entry = SMBIOS_ENTRY_POINT_30,
239 	    .st_tvers = SMB_VERSION_32,
240 	    .st_libvers = SMB_VERSION_33,
241 	    .st_mktable = smbios_test_memdevice_mktable_32,
242 	    .st_canopen = B_TRUE,
243 	    .st_verify = smbios_test_memdevice_verify_32_33,
244 	    .st_desc = "memory device 3.2 / 3.3"
245 	}, {
246 	    .st_entry = SMBIOS_ENTRY_POINT_30,
247 	    .st_tvers = SMB_VERSION_33,
248 	    .st_libvers = SMB_VERSION_33,
249 	    .st_mktable = smbios_test_memdevice_mktable_33,
250 	    .st_canopen = B_TRUE,
251 	    .st_verify = smbios_test_memdevice_verify_33,
252 	    .st_desc = "memory device 3.3"
253 	}, {
254 	    .st_entry = SMBIOS_ENTRY_POINT_30,
255 	    .st_tvers = SMB_VERSION_33,
256 	    .st_libvers = SMB_VERSION_33,
257 	    .st_mktable = smbios_test_memdevice_mktable_33ext,
258 	    .st_canopen = B_TRUE,
259 	    .st_verify = smbios_test_memdevice_verify_33ext,
260 	    .st_desc = "memory device 3.3"
261 	}, {
262 	    .st_entry = SMBIOS_ENTRY_POINT_30,
263 	    .st_tvers = SMB_VERSION,
264 	    .st_libvers = SMB_VERSION,
265 	    .st_mktable = smbios_test_pinfo_mktable_amd64,
266 	    .st_canopen = B_TRUE,
267 	    .st_verify = smbios_test_pinfo_verify_amd64,
268 	    .st_desc = "processor additional information - amd64"
269 	}, {
270 	    .st_entry = SMBIOS_ENTRY_POINT_30,
271 	    .st_tvers = SMB_VERSION,
272 	    .st_libvers = SMB_VERSION,
273 	    .st_mktable = smbios_test_pinfo_mktable_riscv,
274 	    .st_canopen = B_TRUE,
275 	    .st_verify = smbios_test_pinfo_verify_riscv,
276 	    .st_desc = "processor additional information - riscv"
277 	}, {
278 	    .st_entry = SMBIOS_ENTRY_POINT_30,
279 	    .st_tvers = SMB_VERSION,
280 	    .st_libvers = SMB_VERSION,
281 	    .st_mktable = smbios_test_pinfo_mktable_invlen1,
282 	    .st_canopen = B_TRUE,
283 	    .st_verify = smbios_test_pinfo_verify_invlen1,
284 	    .st_desc = "processor additional information - bad table length 1"
285 	}, {
286 	    .st_entry = SMBIOS_ENTRY_POINT_30,
287 	    .st_tvers = SMB_VERSION,
288 	    .st_libvers = SMB_VERSION,
289 	    .st_mktable = smbios_test_pinfo_mktable_invlen2,
290 	    .st_canopen = B_TRUE,
291 	    .st_verify = smbios_test_pinfo_verify_invlen2,
292 	    .st_desc = "processor additional information - bad table length 2"
293 	}, {
294 	    .st_entry = SMBIOS_ENTRY_POINT_30,
295 	    .st_tvers = SMB_VERSION,
296 	    .st_libvers = SMB_VERSION,
297 	    .st_mktable = smbios_test_pinfo_mktable_invlen3,
298 	    .st_canopen = B_TRUE,
299 	    .st_verify = smbios_test_pinfo_verify_invlen3,
300 	    .st_desc = "processor additional information - bad table length 3"
301 	}, {
302 	    .st_entry = SMBIOS_ENTRY_POINT_30,
303 	    .st_tvers = SMB_VERSION,
304 	    .st_libvers = SMB_VERSION,
305 	    .st_mktable = smbios_test_pinfo_mktable_invlen4,
306 	    .st_canopen = B_TRUE,
307 	    .st_verify = smbios_test_pinfo_verify_invlen4,
308 	    .st_desc = "processor additional information - bad table length 4"
309 	}, {
310 	    .st_entry = SMBIOS_ENTRY_POINT_30,
311 	    .st_tvers = SMB_VERSION,
312 	    .st_libvers = SMB_VERSION,
313 	    .st_mktable = smbios_test_memdevice_mktable_32,
314 	    .st_canopen = B_TRUE,
315 	    .st_verify = smbios_test_pinfo_verify_badtype,
316 	    .st_desc = "processor additional information - bad type"
317 	},
318 
319 };
320 
321 static boolean_t
322 smbios_test_run_one(const smbios_test_t *test)
323 {
324 	smbios_test_table_t *table = NULL;
325 	smbios_hdl_t *hdl = NULL;
326 	void *buf;
327 	size_t len;
328 	smbios_entry_t *entry;
329 	int err = 0;
330 	boolean_t ret = B_FALSE;
331 
332 	table = smbios_test_table_init(test->st_entry, test->st_tvers);
333 	if (!test->st_mktable(table)) {
334 		goto out;
335 	}
336 
337 	smbios_test_table_snapshot(table, &entry, &buf, &len);
338 	hdl = smbios_bufopen(entry, buf, len, test->st_libvers, SMB_FL_DEBUG,
339 	    &err);
340 	if (test->st_canopen) {
341 		if (hdl == NULL) {
342 			warnx("failed to create table for test %s: %s",
343 			    test->st_desc, smbios_errmsg(err));
344 			goto out;
345 		}
346 	} else {
347 		if (hdl != NULL) {
348 			warnx("accidentally created table for test %s, "
349 			    "expected failure", test->st_desc);
350 		} else {
351 			ret = B_TRUE;
352 		}
353 		goto out;
354 	}
355 
356 	if (test->st_verify(hdl)) {
357 		ret = B_TRUE;
358 	}
359 
360 out:
361 	if (hdl != NULL) {
362 		smbios_close(hdl);
363 	}
364 
365 	if (table != NULL) {
366 		smbios_test_table_fini(table);
367 	}
368 
369 	if (ret) {
370 		(void) printf("TEST PASSED: %s\n", test->st_desc);
371 	} else {
372 		(void) printf("TEST FAILED: %s\n", test->st_desc);
373 	}
374 
375 	return (ret);
376 }
377 
378 int
379 main(void)
380 {
381 	int err = 0;
382 	size_t i;
383 
384 	for (i = 0; i < ARRAY_SIZE(smbios_tests); i++) {
385 		if (!smbios_test_run_one(&smbios_tests[i])) {
386 			err = 1;
387 		}
388 	}
389 
390 	return (err);
391 }
392