xref: /openbsd-src/sys/arch/arm64/dev/smbios.c (revision cad45e2ea1017ceb0aa58ce568e740475c2b24ed)
1*cad45e2eSkettenis /*	$OpenBSD: smbios.c,v 1.8 2022/10/29 20:35:50 kettenis Exp $	*/
23e97567cSkettenis /*
33e97567cSkettenis  * Copyright (c) 2006 Gordon Willem Klok <gklok@cogeco.ca>
43e97567cSkettenis  * Copyright (c) 2019 Mark Kettenis <kettenis@openbsd.org>
53e97567cSkettenis  *
63e97567cSkettenis  * Permission to use, copy, modify, and distribute this software for any
73e97567cSkettenis  * purpose with or without fee is hereby granted, provided that the above
83e97567cSkettenis  * copyright notice and this permission notice appear in all copies.
93e97567cSkettenis  *
103e97567cSkettenis  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
113e97567cSkettenis  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
123e97567cSkettenis  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
133e97567cSkettenis  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
143e97567cSkettenis  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
153e97567cSkettenis  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
163e97567cSkettenis  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
173e97567cSkettenis  */
183e97567cSkettenis 
193e97567cSkettenis #include <sys/param.h>
203e97567cSkettenis #include <sys/device.h>
213e97567cSkettenis #include <sys/malloc.h>
223e97567cSkettenis #include <sys/systm.h>
233e97567cSkettenis 
243e97567cSkettenis #include <machine/bus.h>
253e97567cSkettenis #include <machine/fdt.h>
263e97567cSkettenis #include <machine/smbiosvar.h>
273e97567cSkettenis 
283e97567cSkettenis #include <dev/ofw/fdt.h>
293e97567cSkettenis 
303e97567cSkettenis struct smbios_entry smbios_entry;
313e97567cSkettenis 
323e97567cSkettenis const char *smbios_uninfo[] = {
333e97567cSkettenis 	"System",
343e97567cSkettenis 	"Not ",
353e97567cSkettenis 	"To be",
363e97567cSkettenis 	"SYS-"
373e97567cSkettenis };
383e97567cSkettenis 
393e97567cSkettenis char smbios_bios_date[64];
401b5f5271Sjsg char smbios_board_vendor[64];
411b5f5271Sjsg char smbios_board_prod[64];
421b5f5271Sjsg char smbios_board_serial[64];
433e97567cSkettenis 
443e97567cSkettenis void smbios_info(char *);
453e97567cSkettenis char *fixstring(char *);
463e97567cSkettenis 
473e97567cSkettenis struct smbios_softc {
483e97567cSkettenis 	struct device	sc_dev;
493e97567cSkettenis 	bus_space_tag_t	sc_iot;
503e97567cSkettenis };
513e97567cSkettenis 
523e97567cSkettenis int	smbios_match(struct device *, void *, void *);
533e97567cSkettenis void	smbios_attach(struct device *, struct device *, void *);
543e97567cSkettenis 
559fdf0c62Smpi const struct cfattach smbios_ca = {
563e97567cSkettenis 	sizeof(struct device), smbios_match, smbios_attach
573e97567cSkettenis };
583e97567cSkettenis 
593e97567cSkettenis struct cfdriver smbios_cd = {
603e97567cSkettenis 	NULL, "smbios", DV_DULL
613e97567cSkettenis };
623e97567cSkettenis 
633e97567cSkettenis int
smbios_match(struct device * parent,void * match,void * aux)643e97567cSkettenis smbios_match(struct device *parent, void *match, void *aux)
653e97567cSkettenis {
663e97567cSkettenis 	struct fdt_attach_args *faa = aux;
673e97567cSkettenis 
683e97567cSkettenis 	return (strcmp(faa->fa_name, "smbios") == 0);
693e97567cSkettenis }
703e97567cSkettenis 
713e97567cSkettenis void
smbios_attach(struct device * parent,struct device * self,void * aux)723e97567cSkettenis smbios_attach(struct device *parent, struct device *self, void *aux)
733e97567cSkettenis {
743e97567cSkettenis 	struct smbios_softc *sc = (struct smbios_softc *)self;
753e97567cSkettenis 	struct fdt_attach_args *faa = aux;
763e97567cSkettenis 	struct smbios_struct_bios *sb;
773e97567cSkettenis 	struct smbtable bios;
783e97567cSkettenis 	char scratch[64];
79*cad45e2eSkettenis 	char sig[5];
803e97567cSkettenis 	char *sminfop;
813e97567cSkettenis 	bus_addr_t addr;
823e97567cSkettenis 	bus_size_t size;
833e97567cSkettenis 	bus_space_handle_t ioh;
84*cad45e2eSkettenis 
85*cad45e2eSkettenis 	sc->sc_iot = faa->fa_iot;
86*cad45e2eSkettenis 	if (bus_space_map(sc->sc_iot, faa->fa_reg[0].addr, sizeof(sig),
87*cad45e2eSkettenis 	    BUS_SPACE_MAP_LINEAR | BUS_SPACE_MAP_PREFETCHABLE, &ioh)) {
88*cad45e2eSkettenis 		printf(": can't map SMBIOS entry point structure\n");
89*cad45e2eSkettenis 		return;
90*cad45e2eSkettenis 	}
91*cad45e2eSkettenis 	bus_space_read_region_1(sc->sc_iot, ioh, 0, sig, sizeof(sig));
92*cad45e2eSkettenis 	bus_space_unmap(sc->sc_iot, ioh, sizeof(sig));
93*cad45e2eSkettenis 
94*cad45e2eSkettenis 	if (strncmp(sig, "_SM_", 4) == 0) {
95*cad45e2eSkettenis 		struct smbhdr *hdr;
963e97567cSkettenis 		uint8_t *p, checksum = 0;
973e97567cSkettenis 		int i;
983e97567cSkettenis 
993e97567cSkettenis 		if (bus_space_map(sc->sc_iot, faa->fa_reg[0].addr, sizeof(*hdr),
1003e97567cSkettenis 		    BUS_SPACE_MAP_LINEAR | BUS_SPACE_MAP_PREFETCHABLE, &ioh)) {
1013e97567cSkettenis 			printf(": can't map SMBIOS entry point structure\n");
1023e97567cSkettenis 			return;
1033e97567cSkettenis 		}
1043e97567cSkettenis 
1053e97567cSkettenis 		hdr = bus_space_vaddr(sc->sc_iot, ioh);
106*cad45e2eSkettenis 		if (hdr->len != sizeof(*hdr)) {
107*cad45e2eSkettenis 			bus_space_unmap(sc->sc_iot, ioh, sizeof(*hdr));
108*cad45e2eSkettenis 			printf("\n");
109*cad45e2eSkettenis 			return;
110*cad45e2eSkettenis 		}
1113e97567cSkettenis 		for (i = 0, p = (uint8_t *)hdr; i < hdr->len; i++)
1123e97567cSkettenis 			checksum += p[i];
113*cad45e2eSkettenis 		if (checksum != 0) {
114*cad45e2eSkettenis 			bus_space_unmap(sc->sc_iot, ioh, sizeof(*hdr));
115*cad45e2eSkettenis 			printf("\n");
116*cad45e2eSkettenis 			return;
117*cad45e2eSkettenis 		}
1183e97567cSkettenis 
119*cad45e2eSkettenis 		printf(": SMBIOS %d.%d", hdr->majrev, hdr->minrev);
120*cad45e2eSkettenis 
121*cad45e2eSkettenis 		smbios_entry.len = hdr->size;
122*cad45e2eSkettenis 		smbios_entry.mjr = hdr->majrev;
123*cad45e2eSkettenis 		smbios_entry.min = hdr->minrev;
124*cad45e2eSkettenis 		smbios_entry.count = hdr->count;
125*cad45e2eSkettenis 
126*cad45e2eSkettenis 		addr = hdr->addr;
127*cad45e2eSkettenis 		size = hdr->size;
128*cad45e2eSkettenis 		bus_space_unmap(sc->sc_iot, ioh, sizeof(*hdr));
129*cad45e2eSkettenis 	} else if (strncmp(sig, "_SM3_", 5) == 0) {
130*cad45e2eSkettenis 		struct smb3hdr *hdr;
131*cad45e2eSkettenis 		uint8_t *p, checksum = 0;
132*cad45e2eSkettenis 		int i;
133*cad45e2eSkettenis 
134*cad45e2eSkettenis 		if (bus_space_map(sc->sc_iot, faa->fa_reg[0].addr, sizeof(*hdr),
135*cad45e2eSkettenis 		    BUS_SPACE_MAP_LINEAR | BUS_SPACE_MAP_PREFETCHABLE, &ioh)) {
136*cad45e2eSkettenis 			printf(": can't map SMBIOS entry point structure\n");
137*cad45e2eSkettenis 			return;
138*cad45e2eSkettenis 		}
139*cad45e2eSkettenis 
140*cad45e2eSkettenis 		hdr = bus_space_vaddr(sc->sc_iot, ioh);
141*cad45e2eSkettenis 		if (hdr->len != sizeof(*hdr) || hdr->epr != 0x01) {
142*cad45e2eSkettenis 			bus_space_unmap(sc->sc_iot, ioh, sizeof(*hdr));
143*cad45e2eSkettenis 			printf("\n");
144*cad45e2eSkettenis 			return;
145*cad45e2eSkettenis 		}
146*cad45e2eSkettenis 		for (i = 0, p = (uint8_t *)hdr; i < hdr->len; i++)
147*cad45e2eSkettenis 			checksum += p[i];
148*cad45e2eSkettenis 		if (checksum != 0) {
149*cad45e2eSkettenis 			bus_space_unmap(sc->sc_iot, ioh, sizeof(*hdr));
150*cad45e2eSkettenis 			printf("\n");
151*cad45e2eSkettenis 			return;
152*cad45e2eSkettenis 		}
153*cad45e2eSkettenis 
154*cad45e2eSkettenis 		printf(": SMBIOS %d.%d.%d", hdr->majrev, hdr->minrev,
155*cad45e2eSkettenis 		    hdr->docrev);
1563e97567cSkettenis 
1573e97567cSkettenis 		smbios_entry.len = hdr->size;
1583e97567cSkettenis 		smbios_entry.mjr = hdr->majrev;
1593e97567cSkettenis 		smbios_entry.min = hdr->minrev;
1603e97567cSkettenis 		smbios_entry.count = -1;
1613e97567cSkettenis 
1623e97567cSkettenis 		addr = hdr->addr;
1633e97567cSkettenis 		size = hdr->size;
1643e97567cSkettenis 		bus_space_unmap(sc->sc_iot, ioh, sizeof(*hdr));
165*cad45e2eSkettenis 	} else {
166*cad45e2eSkettenis 		printf(": unsupported SMBIOS entry point\n");
167*cad45e2eSkettenis 		return;
168*cad45e2eSkettenis 	}
1693e97567cSkettenis 
1703e97567cSkettenis 	if (bus_space_map(sc->sc_iot, addr, size,
1713e97567cSkettenis 	    BUS_SPACE_MAP_LINEAR | BUS_SPACE_MAP_PREFETCHABLE, &ioh)) {
1723e97567cSkettenis 		printf(": can't map SMBIOS structure table\n");
1733e97567cSkettenis 		return;
1743e97567cSkettenis 	}
1753e97567cSkettenis 	smbios_entry.addr = bus_space_vaddr(sc->sc_iot, ioh);
1763e97567cSkettenis 
1773e97567cSkettenis 	bios.cookie = 0;
1783e97567cSkettenis 	if (smbios_find_table(SMBIOS_TYPE_BIOS, &bios)) {
1793e97567cSkettenis 		sb = bios.tblhdr;
1803e97567cSkettenis 		printf("\n%s:", sc->sc_dev.dv_xname);
1813e97567cSkettenis 		if ((smbios_get_string(&bios, sb->vendor,
1823e97567cSkettenis 		    scratch, sizeof(scratch))) != NULL)
1833e97567cSkettenis 			printf(" vendor %s",
1843e97567cSkettenis 			    fixstring(scratch));
1853e97567cSkettenis 		if ((smbios_get_string(&bios, sb->version,
1863e97567cSkettenis 		    scratch, sizeof(scratch))) != NULL)
1873e97567cSkettenis 			printf(" version \"%s\"",
1883e97567cSkettenis 			    fixstring(scratch));
1893e97567cSkettenis 		if ((smbios_get_string(&bios, sb->release,
1903e97567cSkettenis 		    scratch, sizeof(scratch))) != NULL) {
1913e97567cSkettenis 			sminfop = fixstring(scratch);
1923e97567cSkettenis 			if (sminfop != NULL) {
1933e97567cSkettenis 				strlcpy(smbios_bios_date,
1943e97567cSkettenis 				    sminfop,
1953e97567cSkettenis 				    sizeof(smbios_bios_date));
1963e97567cSkettenis 				printf(" date %s", sminfop);
1973e97567cSkettenis 			}
1983e97567cSkettenis 		}
1993e97567cSkettenis 
2003e97567cSkettenis 		smbios_info(sc->sc_dev.dv_xname);
2013e97567cSkettenis 	}
2023e97567cSkettenis 
203afcc1f65Skettenis 	bus_space_unmap(sc->sc_iot, ioh, size);
204afcc1f65Skettenis 
2053e97567cSkettenis 	printf("\n");
206afcc1f65Skettenis 	return;
2073e97567cSkettenis }
2083e97567cSkettenis 
2093e97567cSkettenis /*
2103e97567cSkettenis  * smbios_find_table() takes a caller supplied smbios struct type and
2113e97567cSkettenis  * a pointer to a handle (struct smbtable) returning one if the structure
2123e97567cSkettenis  * is successfully located and zero otherwise. Callers should take care
2133e97567cSkettenis  * to initialize the cookie field of the smbtable structure to zero before
2143e97567cSkettenis  * the first invocation of this function.
2153e97567cSkettenis  * Multiple tables of the same type can be located by repeatedly calling
2163e97567cSkettenis  * smbios_find_table with the same arguments.
2173e97567cSkettenis  */
2183e97567cSkettenis int
smbios_find_table(uint8_t type,struct smbtable * st)219f721f560Skettenis smbios_find_table(uint8_t type, struct smbtable *st)
2203e97567cSkettenis {
221f721f560Skettenis 	uint8_t *va, *end;
2223e97567cSkettenis 	struct smbtblhdr *hdr;
2233e97567cSkettenis 	int ret = 0, tcount = 1;
2243e97567cSkettenis 
2253e97567cSkettenis 	va = smbios_entry.addr;
2263e97567cSkettenis 	end = va + smbios_entry.len;
2273e97567cSkettenis 
2283e97567cSkettenis 	/*
2293e97567cSkettenis 	 * The cookie field of the smtable structure is used to locate
2303e97567cSkettenis 	 * multiple instances of a table of an arbitrary type. Following the
2313e97567cSkettenis 	 * successful location of a table, the type is encoded as bits 0:7 of
2323e97567cSkettenis 	 * the cookie value, the offset in terms of the number of structures
2333e97567cSkettenis 	 * preceding that referenced by the handle is encoded in bits 15:31.
2343e97567cSkettenis 	 */
2353e97567cSkettenis 	if ((st->cookie & 0xfff) == type && st->cookie >> 16) {
236f721f560Skettenis 		if ((uint8_t *)st->hdr >= va && (uint8_t *)st->hdr < end) {
2373e97567cSkettenis 			hdr = st->hdr;
2383e97567cSkettenis 			if (hdr->type == type) {
239f721f560Skettenis 				va = (uint8_t *)hdr + hdr->size;
2403e97567cSkettenis 				for (; va + 1 < end; va++)
2413e97567cSkettenis 					if (*va == 0 && *(va + 1) == 0)
2423e97567cSkettenis 						break;
2433e97567cSkettenis 				va += 2;
2443e97567cSkettenis 				tcount = st->cookie >> 16;
2453e97567cSkettenis 			}
2463e97567cSkettenis 		}
2473e97567cSkettenis 	}
248f721f560Skettenis 	for (; va + sizeof(struct smbtblhdr) < end &&
249f721f560Skettenis 	    tcount <= smbios_entry.count; tcount++) {
2503e97567cSkettenis 		hdr = (struct smbtblhdr *)va;
2513e97567cSkettenis 		if (hdr->type == type) {
2523e97567cSkettenis 			ret = 1;
2533e97567cSkettenis 			st->hdr = hdr;
2543e97567cSkettenis 			st->tblhdr = va + sizeof(struct smbtblhdr);
2553e97567cSkettenis 			st->cookie = (tcount + 1) << 16 | type;
2563e97567cSkettenis 			break;
2573e97567cSkettenis 		}
2583e97567cSkettenis 		if (hdr->type == SMBIOS_TYPE_EOT)
2593e97567cSkettenis 			break;
2603e97567cSkettenis 		va += hdr->size;
2613e97567cSkettenis 		for (; va + 1 < end; va++)
2623e97567cSkettenis 			if (*va == 0 && *(va + 1) == 0)
2633e97567cSkettenis 				break;
2643e97567cSkettenis 		va += 2;
2653e97567cSkettenis 	}
2663e97567cSkettenis 	return ret;
2673e97567cSkettenis }
2683e97567cSkettenis 
2693e97567cSkettenis char *
smbios_get_string(struct smbtable * st,uint8_t indx,char * dest,size_t len)270f721f560Skettenis smbios_get_string(struct smbtable *st, uint8_t indx, char *dest, size_t len)
2713e97567cSkettenis {
272f721f560Skettenis 	uint8_t *va, *end;
2733e97567cSkettenis 	char *ret = NULL;
2743e97567cSkettenis 	int i;
2753e97567cSkettenis 
276f721f560Skettenis 	va = (uint8_t *)st->hdr + st->hdr->size;
2773e97567cSkettenis 	end = smbios_entry.addr + smbios_entry.len;
2783e97567cSkettenis 	for (i = 1; va < end && i < indx && *va; i++)
2793e97567cSkettenis 		while (*va++)
2803e97567cSkettenis 			;
2813e97567cSkettenis 	if (i == indx) {
2823e97567cSkettenis 		if (va + len < end) {
2833e97567cSkettenis 			ret = dest;
2843e97567cSkettenis 			memcpy(ret, va, len);
2853e97567cSkettenis 			ret[len - 1] = '\0';
2863e97567cSkettenis 		}
2873e97567cSkettenis 	}
2883e97567cSkettenis 
2893e97567cSkettenis 	return ret;
2903e97567cSkettenis }
2913e97567cSkettenis 
2923e97567cSkettenis char *
fixstring(char * s)2933e97567cSkettenis fixstring(char *s)
2943e97567cSkettenis {
2953e97567cSkettenis 	char *p, *e;
2963e97567cSkettenis 	int i;
2973e97567cSkettenis 
2983e97567cSkettenis 	for (i = 0; i < nitems(smbios_uninfo); i++)
2993e97567cSkettenis 		if ((strncasecmp(s, smbios_uninfo[i],
3003e97567cSkettenis 		    strlen(smbios_uninfo[i]))) == 0)
3013e97567cSkettenis 			return NULL;
3023e97567cSkettenis 	/*
3033e97567cSkettenis 	 * Remove leading and trailing whitespace
3043e97567cSkettenis 	 */
3053e97567cSkettenis 	for (p = s; *p == ' '; p++)
3063e97567cSkettenis 		;
3073e97567cSkettenis 	/*
3083e97567cSkettenis 	 * Special case entire string is whitespace
3093e97567cSkettenis 	 */
3103e97567cSkettenis 	if (p == s + strlen(s))
3113e97567cSkettenis 		return NULL;
3123e97567cSkettenis 	for (e = s + strlen(s) - 1; e > s && *e == ' '; e--)
3133e97567cSkettenis 		;
3143e97567cSkettenis 	if (p > s || e < s + strlen(s) - 1) {
3153e97567cSkettenis 		memmove(s, p, e - p + 1);
3163e97567cSkettenis 		s[e - p + 1] = '\0';
3173e97567cSkettenis 	}
3183e97567cSkettenis 
3193e97567cSkettenis 	return s;
3203e97567cSkettenis }
3213e97567cSkettenis 
3223e97567cSkettenis void
smbios_info(char * str)3233e97567cSkettenis smbios_info(char *str)
3243e97567cSkettenis {
3253e97567cSkettenis 	char *sminfop, sminfo[64];
3263e97567cSkettenis 	struct smbtable stbl, btbl;
3273e97567cSkettenis 	struct smbios_sys *sys;
3283e97567cSkettenis 	struct smbios_board *board;
3293e97567cSkettenis 	int i, infolen, uuidf, havebb;
3303e97567cSkettenis 	char *p;
3313e97567cSkettenis 
3323e97567cSkettenis 	if (smbios_entry.mjr < 2)
3333e97567cSkettenis 		return;
3343e97567cSkettenis 	/*
3353e97567cSkettenis 	 * According to the spec the system table among others is required,
3363e97567cSkettenis 	 * if it is not we do not bother with this smbios implementation.
3373e97567cSkettenis 	 */
3383e97567cSkettenis 	stbl.cookie = btbl.cookie = 0;
3393e97567cSkettenis 	if (!smbios_find_table(SMBIOS_TYPE_SYSTEM, &stbl))
3403e97567cSkettenis 		return;
3413e97567cSkettenis 	havebb = smbios_find_table(SMBIOS_TYPE_BASEBOARD, &btbl);
3423e97567cSkettenis 
3433e97567cSkettenis 	sys = (struct smbios_sys *)stbl.tblhdr;
3441b5f5271Sjsg 	if (havebb) {
3453e97567cSkettenis 		board = (struct smbios_board *)btbl.tblhdr;
3461b5f5271Sjsg 
3471b5f5271Sjsg 		sminfop = NULL;
3481b5f5271Sjsg 		if ((p = smbios_get_string(&btbl, board->vendor,
3491b5f5271Sjsg 		    sminfo, sizeof(sminfo))) != NULL)
3501b5f5271Sjsg 			sminfop = fixstring(p);
3511b5f5271Sjsg 		if (sminfop)
3521b5f5271Sjsg 			strlcpy(smbios_board_vendor, sminfop,
3531b5f5271Sjsg 			    sizeof(smbios_board_vendor));
3541b5f5271Sjsg 
3551b5f5271Sjsg 		sminfop = NULL;
3561b5f5271Sjsg 		if ((p = smbios_get_string(&btbl, board->product,
3571b5f5271Sjsg 		    sminfo, sizeof(sminfo))) != NULL)
3581b5f5271Sjsg 			sminfop = fixstring(p);
3591b5f5271Sjsg 		if (sminfop)
3601b5f5271Sjsg 			strlcpy(smbios_board_prod, sminfop,
3611b5f5271Sjsg 			    sizeof(smbios_board_prod));
3621b5f5271Sjsg 
3631b5f5271Sjsg 		sminfop = NULL;
3641b5f5271Sjsg 		if ((p = smbios_get_string(&btbl, board->serial,
3651b5f5271Sjsg 		    sminfo, sizeof(sminfo))) != NULL)
3661b5f5271Sjsg 			sminfop = fixstring(p);
3671b5f5271Sjsg 		if (sminfop)
3681b5f5271Sjsg 			strlcpy(smbios_board_serial, sminfop,
3691b5f5271Sjsg 			    sizeof(smbios_board_serial));
3701b5f5271Sjsg 	}
3713e97567cSkettenis 	/*
372f721f560Skettenis 	 * Some smbios implementations have no system vendor or
373f721f560Skettenis 	 * product strings, some have very uninformative data which is
374f721f560Skettenis 	 * harder to work around and we must rely upon various
375f721f560Skettenis 	 * heuristics to detect this. In both cases we attempt to fall
376f721f560Skettenis 	 * back on the base board information in the perhaps naive
377f721f560Skettenis 	 * belief that motherboard vendors will supply this
3783e97567cSkettenis 	 * information.
3793e97567cSkettenis 	 */
3803e97567cSkettenis 	sminfop = NULL;
3813e97567cSkettenis 	if ((p = smbios_get_string(&stbl, sys->vendor, sminfo,
3823e97567cSkettenis 	    sizeof(sminfo))) != NULL)
3833e97567cSkettenis 		sminfop = fixstring(p);
3843e97567cSkettenis 	if (sminfop == NULL) {
3853e97567cSkettenis 		if (havebb) {
3863e97567cSkettenis 			if ((p = smbios_get_string(&btbl, board->vendor,
3873e97567cSkettenis 			    sminfo, sizeof(sminfo))) != NULL)
3883e97567cSkettenis 				sminfop = fixstring(p);
3893e97567cSkettenis 		}
3903e97567cSkettenis 	}
3913e97567cSkettenis 	if (sminfop) {
3923e97567cSkettenis 		infolen = strlen(sminfop) + 1;
3933e97567cSkettenis 		hw_vendor = malloc(infolen, M_DEVBUF, M_NOWAIT);
3943e97567cSkettenis 		if (hw_vendor)
3953e97567cSkettenis 			strlcpy(hw_vendor, sminfop, infolen);
3963e97567cSkettenis 		sminfop = NULL;
3973e97567cSkettenis 	}
3983e97567cSkettenis 	if ((p = smbios_get_string(&stbl, sys->product, sminfo,
3993e97567cSkettenis 	    sizeof(sminfo))) != NULL)
4003e97567cSkettenis 		sminfop = fixstring(p);
4013e97567cSkettenis 	if (sminfop == NULL) {
4023e97567cSkettenis 		if (havebb) {
4033e97567cSkettenis 			if ((p = smbios_get_string(&btbl, board->product,
4043e97567cSkettenis 			    sminfo, sizeof(sminfo))) != NULL)
4053e97567cSkettenis 				sminfop = fixstring(p);
4063e97567cSkettenis 		}
4073e97567cSkettenis 	}
4083e97567cSkettenis 	if (sminfop) {
4093e97567cSkettenis 		infolen = strlen(sminfop) + 1;
4103e97567cSkettenis 		hw_prod = malloc(infolen, M_DEVBUF, M_NOWAIT);
4113e97567cSkettenis 		if (hw_prod)
4123e97567cSkettenis 			strlcpy(hw_prod, sminfop, infolen);
4133e97567cSkettenis 		sminfop = NULL;
4143e97567cSkettenis 	}
4153e97567cSkettenis 	if (hw_vendor != NULL && hw_prod != NULL)
4163e97567cSkettenis 		printf("\n%s: %s %s", str, hw_vendor, hw_prod);
4173e97567cSkettenis 	if ((p = smbios_get_string(&stbl, sys->version, sminfo,
4183e97567cSkettenis 	    sizeof(sminfo))) != NULL)
4193e97567cSkettenis 		sminfop = fixstring(p);
4203e97567cSkettenis 	if (sminfop) {
4213e97567cSkettenis 		infolen = strlen(sminfop) + 1;
4223e97567cSkettenis 		hw_ver = malloc(infolen, M_DEVBUF, M_NOWAIT);
4233e97567cSkettenis 		if (hw_ver)
4243e97567cSkettenis 			strlcpy(hw_ver, sminfop, infolen);
4253e97567cSkettenis 		sminfop = NULL;
4263e97567cSkettenis 	}
4273e97567cSkettenis 	if ((p = smbios_get_string(&stbl, sys->serial, sminfo,
4283e97567cSkettenis 	    sizeof(sminfo))) != NULL)
4293e97567cSkettenis 		sminfop = fixstring(p);
4303e97567cSkettenis 	if (sminfop) {
4313e97567cSkettenis 		infolen = strlen(sminfop) + 1;
4323e97567cSkettenis 		for (i = 0; i < infolen - 1; i++)
4333e97567cSkettenis 			enqueue_randomness(sminfop[i]);
4343e97567cSkettenis 		hw_serial = malloc(infolen, M_DEVBUF, M_NOWAIT);
4353e97567cSkettenis 		if (hw_serial)
4363e97567cSkettenis 			strlcpy(hw_serial, sminfop, infolen);
4373e97567cSkettenis 	}
4383e97567cSkettenis 	if (smbios_entry.mjr > 2 || (smbios_entry.mjr == 2 &&
4393e97567cSkettenis 	    smbios_entry.min >= 1)) {
4403e97567cSkettenis 		/*
4413e97567cSkettenis 		 * If the uuid value is all 0xff the uuid is present but not
4423e97567cSkettenis 		 * set, if its all 0 then the uuid isn't present at all.
4433e97567cSkettenis 		 */
4443e97567cSkettenis 		uuidf = SMBIOS_UUID_NPRESENT|SMBIOS_UUID_NSET;
4453e97567cSkettenis 		for (i = 0; i < sizeof(sys->uuid); i++) {
4463e97567cSkettenis 			if (sys->uuid[i] != 0xff)
4473e97567cSkettenis 				uuidf &= ~SMBIOS_UUID_NSET;
4483e97567cSkettenis 			if (sys->uuid[i] != 0)
4493e97567cSkettenis 				uuidf &= ~SMBIOS_UUID_NPRESENT;
4503e97567cSkettenis 		}
4513e97567cSkettenis 
4523e97567cSkettenis 		if (uuidf & SMBIOS_UUID_NPRESENT)
4533e97567cSkettenis 			hw_uuid = NULL;
4543e97567cSkettenis 		else if (uuidf & SMBIOS_UUID_NSET)
4553e97567cSkettenis 			hw_uuid = "Not Set";
4563e97567cSkettenis 		else {
4573e97567cSkettenis 			for (i = 0; i < sizeof(sys->uuid); i++)
4583e97567cSkettenis 				enqueue_randomness(sys->uuid[i]);
4593e97567cSkettenis 			hw_uuid = malloc(SMBIOS_UUID_REPLEN, M_DEVBUF,
4603e97567cSkettenis 			    M_NOWAIT);
4613e97567cSkettenis 			if (hw_uuid) {
4623e97567cSkettenis 				snprintf(hw_uuid, SMBIOS_UUID_REPLEN,
4633e97567cSkettenis 				    SMBIOS_UUID_REP,
4643e97567cSkettenis 				    sys->uuid[0], sys->uuid[1], sys->uuid[2],
4653e97567cSkettenis 				    sys->uuid[3], sys->uuid[4], sys->uuid[5],
4663e97567cSkettenis 				    sys->uuid[6], sys->uuid[7], sys->uuid[8],
4673e97567cSkettenis 				    sys->uuid[9], sys->uuid[10], sys->uuid[11],
4683e97567cSkettenis 				    sys->uuid[12], sys->uuid[13], sys->uuid[14],
4693e97567cSkettenis 				    sys->uuid[15]);
4703e97567cSkettenis 			}
4713e97567cSkettenis 		}
4723e97567cSkettenis 	}
4733e97567cSkettenis }
474