#include <sys/param.h>
#include <sys/systm.h>
#include <sys/device.h>
#include <sys/errno.h>
#include <sys/malloc.h>
#include <sys/reboot.h>
#include <sys/extent.h>
#include <uvm/uvm_extern.h>
#include <sys/sysctl.h>
#include <dev/cons.h>
#include <stand/boot/bootarg.h>
#include <machine/conf.h>
#include <machine/gdt.h>
#include <machine/biosvar.h>
#include <machine/mpbiosvar.h>
#include <machine/smbiosvar.h>
#include <dev/isa/isareg.h>
#include <i386/isa/isa_machdep.h>
#include <dev/pci/pcivar.h>
#include "apm.h"
#include "acpi.h"
#include "mpbios.h"
#include "pcibios.h"
#include "pci.h"
#include "com.h"
#if NCOM > 0
#include <sys/termios.h>
#include <dev/ic/comvar.h>
#endif
#include "softraid.h"
#if NSOFTRAID > 0
#include <dev/softraidvar.h>
#endif
struct bios_softc {
struct device sc_dev;
vaddr_t bios32_service_va;
};
int biosprobe(struct device *, void *, void *);
void biosattach(struct device *, struct device *, void *);
int bios_print(void *, const char *);
char *fixstring(char *);
const struct cfattach bios_ca = {
sizeof(struct bios_softc), biosprobe, biosattach
};
struct cfdriver bios_cd = {
NULL, "bios", DV_DULL
};
extern dev_t bootdev;
#if NAPM > 0 || defined(DEBUG)
bios_apminfo_t *apm;
#endif
#if NPCI > 0
bios_pciinfo_t *bios_pciinfo;
#endif
bios_diskinfo_t *bios_diskinfo;
bios_memmap_t *bios_memmap;
struct bios_softc *bios_softc;
uint32_t bios_cksumlen;
struct bios32_entry bios32_entry;
struct smbios_entry smbios_entry;
#ifdef MULTIPROCESSOR
void *bios_smpinfo;
#endif
bios_bootmac_t *bios_bootmac;
#ifdef DDB
extern int db_console;
#endif
bios_ucode_t *bios_ucode;
void smbios_info(char*);
bios_diskinfo_t *bios_getdiskinfo(dev_t);
const char *smbios_uninfo[] = {
"System",
"Not ",
"To be",
"SYS-"
};
char smbios_bios_date[64];
char smbios_bios_version[64];
char smbios_board_vendor[64];
char smbios_board_prod[64];
char smbios_board_serial[64];
int
biosprobe(struct device *parent, void *match, void *aux)
{
struct bios_attach_args *bia = aux;
#ifdef BIOS_DEBUG
printf("%s%d: boot API ver %x, %x; args %p[%d]\n",
bia->ba_name, bios_cd.cd_ndevs,
bootapiver, BOOTARG_APIVER, bootargp, bootargc);
#endif
if (bios_cd.cd_ndevs || strcmp(bia->ba_name, bios_cd.cd_name))
return 0;
if (!(bootapiver & BAPIV_VECTOR) || bootargp == NULL)
return 0;
return 1;
}
void
biosattach(struct device *parent, struct device *self, void *aux)
{
struct bios_softc *sc = (struct bios_softc *)self;
#if (NPCI > 0 && NPCIBIOS > 0) || NAPM > 0
struct bios_attach_args *bia = aux;
#endif
struct smbios_struct_bios *sb;
struct smbtable bios;
volatile uint8_t *va;
char scratch[64], *str;
int flags, smbiosrev = 0, ncpu = 0, isa_hole_exec = 0;
#if NACPI > 0 || NAPM > 0
int usingacpi = 0;
#endif
bios_softc = sc;
flags = sc->sc_dev.dv_cfdata->cf_flags;
va = ISA_HOLE_VADDR(0xffff0);
printf(": date %c%c/%c%c/%c%c",
va[5], va[6], va[8], va[9], va[11], va[12]);
if (!(flags & BIOSF_BIOS32)) {
for (va = ISA_HOLE_VADDR(BIOS32_START);
va < (uint8_t *)ISA_HOLE_VADDR(BIOS32_END); va += 16) {
bios32_header_t h = (bios32_header_t)va;
uint8_t cksum;
int i;
if (h->signature != BIOS32_SIGNATURE)
continue;
for (cksum = 0, i = h->length * 16; i--; cksum += va[i])
;
if (cksum != 0)
continue;
if (h->entry <= BIOS32_START || h->entry >= BIOS32_END)
continue;
bios32_entry.segment = GSEL(GCODE_SEL, SEL_KPL);
bios32_entry.offset = (uint32_t)ISA_HOLE_VADDR(h->entry);
printf(", BIOS32 rev. %d @ 0x%x", h->rev, h->entry);
break;
}
}
if (!(flags & BIOSF_SMBIOS)) {
for (va = ISA_HOLE_VADDR(SMBIOS_START);
va < (uint8_t *)ISA_HOLE_VADDR(SMBIOS_END); va+= 16) {
struct smbhdr *sh = (struct smbhdr *)va;
char *sminfop;
uint8_t chksum;
vaddr_t eva;
paddr_t pa, end;
int i;
if (sh->sig != SMBIOS_SIGNATURE)
continue;
i = sh->len;
for (chksum = 0; i--; chksum += va[i])
;
if (chksum != 0)
continue;
va += 0x10;
if (!(va[0] == '_' && va[1] == 'D' && va[2] == 'M' &&
va[3] == 'I' && va[4] == '_'))
continue;
for (chksum = 0, i = 0xf; i--; chksum += va[i])
;
if (chksum != 0)
continue;
pa = trunc_page(sh->addr);
end = round_page(sh->addr + sh->size);
eva = (vaddr_t)km_alloc(end - pa, &kv_any,
&kp_none, &kd_nowait);
if (eva == 0)
break;
smbios_entry.addr = (uint8_t *)(eva +
(sh->addr & PGOFSET));
smbios_entry.len = sh->size;
smbios_entry.mjr = sh->majrev;
smbios_entry.min = sh->minrev;
smbios_entry.count = sh->count;
for (; pa < end; pa+= NBPG, eva+= NBPG)
pmap_kenter_pa(eva, pa, PROT_READ);
printf(", SMBIOS rev. %d.%d @ 0x%x (%hd entries)",
sh->majrev, sh->minrev, sh->addr, sh->count);
smbiosrev = sh->majrev * 100 + sh->minrev;
if (sh->minrev < 10)
smbiosrev = sh->majrev * 100 + sh->minrev * 10;
bios.cookie = 0;
if (smbios_find_table(SMBIOS_TYPE_BIOS, &bios)) {
sb = bios.tblhdr;
printf("\n%s:", sc->sc_dev.dv_xname);
if ((smbios_get_string(&bios, sb->vendor,
scratch, sizeof(scratch))) != NULL)
printf(" vendor %s",
fixstring(scratch));
if ((smbios_get_string(&bios, sb->version,
scratch, sizeof(scratch))) != NULL) {
sminfop = fixstring(scratch);
if (sminfop != NULL) {
strlcpy(smbios_bios_version,
sminfop,
sizeof(smbios_bios_version));
printf(" version \"%s\"",
sminfop);
}
}
if ((smbios_get_string(&bios, sb->release,
scratch, sizeof(scratch))) != NULL) {
sminfop = fixstring(scratch);
if (sminfop != NULL) {
strlcpy(smbios_bios_date,
sminfop,
sizeof(smbios_bios_date));
printf(" date %s", sminfop);
}
}
}
smbios_info(sc->sc_dev.dv_xname);
bzero(&bios, sizeof(bios));
while (smbios_find_table(SMBIOS_TYPE_PROCESSOR,&bios)) {
struct smbios_cpu *cpu = bios.tblhdr;
if (cpu->cpu_status & SMBIOS_CPUST_POPULATED) {
if (smbiosrev >= 250 &&
cpu->cpu_core_enabled)
ncpu += cpu->cpu_core_enabled;
else {
ncpu++;
if (cpu->cpu_id_edx & CPUID_HTT)
ncpu++;
}
}
}
break;
}
}
printf("\n");
if (!(flags & BIOSF_SMBIOS) && smbiosrev == 0) {
const char *signature = "Soekris Engineering";
for (va = ISA_HOLE_VADDR(SMBIOS_START);
va <= (uint8_t *)ISA_HOLE_VADDR(SMBIOS_END -
(strlen(signature) - 1)); va++)
if (!memcmp((uint8_t *)va, signature,
strlen(signature))) {
hw_vendor = malloc(strlen(signature) + 1,
M_DEVBUF, M_NOWAIT);
if (hw_vendor)
strlcpy(hw_vendor, signature,
strlen(signature) + 1);
va += strlen(signature);
break;
}
for (; hw_vendor &&
va <= (uint8_t *)ISA_HOLE_VADDR(SMBIOS_END - 6); va++)
if (!memcmp((uint8_t *)va, "net45xx", 7) ||
!memcmp((uint8_t *)va, "net4801", 7) ||
!memcmp((uint8_t *)va, "net5501", 7) ||
!memcmp((uint8_t *)va, "net6501", 7)) {
hw_prod = malloc(8, M_DEVBUF, M_NOWAIT);
if (hw_prod) {
memcpy(hw_prod, (uint8_t *)va, 7);
hw_prod[7] = '\0';
}
break;
}
}
#if NACPI > 0
#if NPCI > 0
if (smbiosrev >= 210 && pci_mode_detect() != 0)
#endif
{
struct bios_attach_args ba;
memset(&ba, 0, sizeof(ba));
ba.ba_name = "acpi";
ba.ba_func = 0x00;
ba.ba_iot = I386_BUS_SPACE_IO;
ba.ba_memt = I386_BUS_SPACE_MEM;
if (config_found(self, &ba, bios_print)) {
flags |= BIOSF_PCIBIOS;
usingacpi = 1;
}
}
#endif
#if NAPM > 0
if (usingacpi == 0 && apm && ncpu < 2 && smbiosrev < 240) {
struct bios_attach_args ba;
#if defined(DEBUG) || defined(APMDEBUG)
printf("apminfo: %x, code %x[%x]/%x[%x], data %x[%x], ept %x\n",
apm->apm_detail,
apm->apm_code32_base, apm->apm_code_len,
apm->apm_code16_base, apm->apm_code16_len,
apm->apm_data_base, apm->apm_data_len, apm->apm_entry);
#endif
ba.ba_name = "apm";
ba.ba_func = 0x15;
ba.ba_memt = bia->ba_memt;
ba.ba_iot = bia->ba_iot;
ba.ba_apmp = apm;
config_found(self, &ba, bios_print);
isa_hole_exec = 1;
}
#endif
#if NMPBIOS > 0
if (mpbios_probe(self)) {
struct bios_attach_args ba;
memset(&ba, 0, sizeof(ba));
ba.ba_name = "mpbios";
ba.ba_iot = I386_BUS_SPACE_IO;
ba.ba_memt = I386_BUS_SPACE_MEM;
config_found(self, &ba, bios_print);
}
#endif
#if NPCI > 0 && NPCIBIOS > 0
if (!(flags & BIOSF_PCIBIOS)) {
struct bios_attach_args ba;
ba.ba_name = "pcibios";
ba.ba_func = 0x1A;
ba.ba_memt = bia->ba_memt;
ba.ba_iot = bia->ba_iot;
config_found(self, &ba, bios_print);
}
#endif
if (!(flags & BIOSF_PROMSCAN)) {
volatile uint8_t *eva;
for (str = NULL, va = ISA_HOLE_VADDR(0xc0000),
eva = ISA_HOLE_VADDR(0xf0000);
va < eva; va += 512) {
extern struct extent *iomem_ex;
bios_romheader_t romh = (bios_romheader_t)va;
uint32_t off, len;
uint8_t cksum;
int i;
if (romh->signature != 0xaa55)
continue;
if (!romh->len || romh->len == 0xff)
continue;
len = romh->len * 512;
if (va + len > eva)
continue;
for (cksum = 0, i = len; i--; cksum += va[i])
;
off = 0xc0000 + (va - (uint8_t *)
ISA_HOLE_VADDR(0xc0000));
if (!str)
printf("%s: ROM list:",
str = sc->sc_dev.dv_xname);
printf(" 0x%05x/0x%x%s", off, len,
cksum? "!" : "");
if ((i = extent_alloc_region(iomem_ex,
(paddr_t)off, len, EX_NOWAIT)))
printf(":%d", i);
isa_hole_exec = 1;
va += len - 512;
}
if (str)
printf("\n");
}
if (!isa_hole_exec)
pmap_write_protect(pmap_kernel(), (vaddr_t)atdevbase,
(vaddr_t)atdevbase + IOM_SIZE, PROT_READ | PROT_WRITE);
}
void
bios_getopt(void)
{
bootarg_t *q;
bios_ddb_t *bios_ddb;
bios_bootduid_t *bios_bootduid;
bios_bootsr_t *bios_bootsr;
#ifdef BIOS_DEBUG
printf("bootargv:");
#endif
for(q = bootargp; q->ba_type != BOOTARG_END; q = q->ba_next) {
q->ba_next = (bootarg_t *)((caddr_t)q + q->ba_size);
switch (q->ba_type) {
case BOOTARG_MEMMAP:
bios_memmap = (bios_memmap_t *)q->ba_arg;
#ifdef BIOS_DEBUG
printf(" memmap %p", bios_memmap);
#endif
break;
case BOOTARG_DISKINFO:
bios_diskinfo = (bios_diskinfo_t *)q->ba_arg;
#ifdef BIOS_DEBUG
printf(" diskinfo %p", bios_diskinfo);
#endif
break;
#if NAPM > 0 || defined(DEBUG)
case BOOTARG_APMINFO:
#ifdef BIOS_DEBUG
printf(" apminfo %p", q->ba_arg);
#endif
apm = (bios_apminfo_t *)q->ba_arg;
break;
#endif
case BOOTARG_CKSUMLEN:
bios_cksumlen = *(uint32_t *)q->ba_arg;
#ifdef BIOS_DEBUG
printf(" cksumlen %d", bios_cksumlen);
#endif
break;
#if NPCI > 0
case BOOTARG_PCIINFO:
bios_pciinfo = (bios_pciinfo_t *)q->ba_arg;
#ifdef BIOS_DEBUG
printf(" pciinfo %p", bios_pciinfo);
#endif
break;
#endif
case BOOTARG_CONSDEV:
if (q->ba_size >= sizeof(bios_consdev_t) +
offsetof(bootarg_t, ba_arg)) {
bios_consdev_t *cdp =
(bios_consdev_t*)q->ba_arg;
#if NCOM > 0
static const int ports[] =
{ 0x3f8, 0x2f8, 0x3e8, 0x2e8 };
int unit = minor(cdp->consdev);
int consaddr = cdp->consaddr;
if (consaddr == -1 && unit >=0 &&
unit < (sizeof(ports)/sizeof(ports[0])))
consaddr = ports[unit];
if (major(cdp->consdev) == 8 &&
consaddr != -1) {
comconsunit = unit;
comconsaddr = consaddr;
comconsrate = cdp->conspeed;
comconsiot = I386_BUS_SPACE_IO;
cninit();
}
#endif
#ifdef BIOS_DEBUG
printf(" console 0x%x:%d",
cdp->consdev, cdp->conspeed);
#endif
}
break;
#ifdef MULTIPROCESSOR
case BOOTARG_SMPINFO:
bios_smpinfo = q->ba_arg;
printf(" smpinfo %p", bios_smpinfo);
break;
#endif
case BOOTARG_BOOTMAC:
bios_bootmac = (bios_bootmac_t *)q->ba_arg;
break;
case BOOTARG_DDB:
bios_ddb = (bios_ddb_t *)q->ba_arg;
#ifdef DDB
db_console = bios_ddb->db_console;
#endif
break;
case BOOTARG_BOOTDUID:
bios_bootduid = (bios_bootduid_t *)q->ba_arg;
bcopy(bios_bootduid, bootduid, sizeof(bootduid));
break;
case BOOTARG_BOOTSR:
bios_bootsr = (bios_bootsr_t *)q->ba_arg;
#if NSOFTRAID > 0
bcopy(&bios_bootsr->uuid, &sr_bootuuid,
sizeof(sr_bootuuid));
bcopy(&bios_bootsr->maskkey, &sr_bootkey,
sizeof(sr_bootkey));
#endif
explicit_bzero(bios_bootsr, sizeof(bios_bootsr_t));
break;
case BOOTARG_UCODE:
bios_ucode = (bios_ucode_t *)q->ba_arg;
break;
default:
#ifdef BIOS_DEBUG
printf(" unsupported arg (%d) %p", q->ba_type,
q->ba_arg);
#endif
break;
}
}
printf("\n");
}
int
bios_print(void *aux, const char *pnp)
{
struct bios_attach_args *ba = aux;
if (pnp)
printf("%s at %s function 0x%x",
ba->ba_name, pnp, ba->ba_func);
return (UNCONF);
}
int
bios32_service(uint32_t service, bios32_entry_t e, bios32_entry_info_t ei)
{
u_long pa, endpa;
vaddr_t va, sva;
uint32_t base, count, off, ent;
if (bios32_entry.offset == 0)
return 0;
base = 0;
__asm volatile("lcall *(%4)"
: "+a" (service), "+b" (base), "=c" (count), "=d" (off)
: "D" (&bios32_entry)
: "%esi", "cc", "memory");
if (service & 0xff)
return 0;
ent = base + off;
if (ent <= BIOS32_START || ent >= BIOS32_END)
return 0;
endpa = round_page(BIOS32_END);
sva = va = (vaddr_t)km_alloc(endpa, &kv_any, &kp_none, &kd_nowait);
if (va == 0)
return (0);
bios_softc->bios32_service_va = sva;
setgdt(GBIOS32_SEL, (caddr_t)va, BIOS32_END, SDT_MEMERA, SEL_KPL, 1, 0);
for (pa = trunc_page(BIOS32_START),
va += trunc_page(BIOS32_START);
pa < endpa; pa += NBPG, va += NBPG) {
pmap_enter(pmap_kernel(), va, pa,
PROT_READ | PROT_WRITE | PROT_EXEC,
PROT_READ | PROT_WRITE | PROT_EXEC | PMAP_WIRED);
if (pa >= trunc_page(base)) {
pmap_enter(pmap_kernel(), sva, pa,
PROT_READ | PROT_WRITE | PROT_EXEC,
PROT_READ | PROT_WRITE | PROT_EXEC | PMAP_WIRED);
sva += NBPG;
}
}
e->segment = GSEL(GBIOS32_SEL, SEL_KPL);
e->offset = (vaddr_t)ent;
ei->bei_base = base;
ei->bei_size = count;
ei->bei_entry = ent;
return 1;
}
void
bios32_cleanup(void)
{
u_long pa, size;
vaddr_t va;
size = round_page(BIOS32_END);
for (va = bios_softc->bios32_service_va;
va < bios_softc->bios32_service_va + size;
va += NBPG) {
if (pmap_extract(pmap_kernel(), va, &pa))
pmap_remove(pmap_kernel(), va, va + PAGE_SIZE);
}
km_free((void *)bios_softc->bios32_service_va, size,
&kv_any, &kp_none);
}
int
biosopen(dev_t dev, int flag, int mode, struct proc *p)
{
struct bios_softc *sc = bios_cd.cd_devs[0];
if (minor(dev))
return (ENXIO);
(void)sc;
return 0;
}
int
biosclose(dev_t dev, int flag, int mode, struct proc *p)
{
struct bios_softc *sc = bios_cd.cd_devs[0];
if (minor(dev))
return (ENXIO);
(void)sc;
return 0;
}
int
biosioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
{
struct bios_softc *sc = bios_cd.cd_devs[0];
if (minor(dev))
return (ENXIO);
switch (cmd) {
default:
return ENXIO;
}
(void)sc;
return 0;
}
int
bios_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp,
size_t newlen, struct proc *p)
{
bios_diskinfo_t *pdi;
int biosdev;
if (namelen != 1 && name[0] != BIOS_DISKINFO)
return (ENOTDIR);
if (!(bootapiver & BAPIV_VECTOR))
return EOPNOTSUPP;
switch (name[0]) {
case BIOS_DEV:
if ((pdi = bios_getdiskinfo(bootdev)) == NULL)
return ENXIO;
biosdev = pdi->bios_number;
return sysctl_rdint(oldp, oldlenp, newp, biosdev);
case BIOS_DISKINFO:
if (namelen != 2)
return ENOTDIR;
if ((pdi = bios_getdiskinfo(name[1])) == NULL)
return ENXIO;
return sysctl_rdstruct(oldp, oldlenp, newp, pdi, sizeof(*pdi));
case BIOS_CKSUMLEN:
return sysctl_rdint(oldp, oldlenp, newp, bios_cksumlen);
default:
return EOPNOTSUPP;
}
}
bios_diskinfo_t *
bios_getdiskinfo(dev_t dev)
{
bios_diskinfo_t *pdi;
if (bios_diskinfo == NULL)
return NULL;
for (pdi = bios_diskinfo; pdi->bios_number != -1; pdi++) {
if ((dev & B_MAGICMASK) == B_DEVMAGIC) {
if (pdi->bsd_dev == dev)
break;
} else {
if (pdi->bios_number == dev)
break;
}
}
if (pdi->bios_number == -1)
return NULL;
else
return pdi;
}
int
smbios_find_table(uint8_t type, struct smbtable *st)
{
uint8_t *va, *end;
struct smbtblhdr *hdr;
int ret = 0, tcount = 1;
va = smbios_entry.addr;
end = va + smbios_entry.len;
if ((st->cookie & 0xfff) == type && st->cookie >> 16) {
if ((uint8_t *)st->hdr >= va && (uint8_t *)st->hdr < end) {
hdr = st->hdr;
if (hdr->type == type) {
va = (uint8_t *)hdr + hdr->size;
for (; va + 1 < end; va++)
if (*va == 0 && *(va + 1) == 0)
break;
va += 2;
tcount = st->cookie >> 16;
}
}
}
for (; va + sizeof(struct smbtblhdr) < end &&
tcount <= smbios_entry.count; tcount++) {
hdr = (struct smbtblhdr *)va;
if (hdr->type == type) {
ret = 1;
st->hdr = hdr;
st->tblhdr = va + sizeof(struct smbtblhdr);
st->cookie = (tcount + 1) << 16 | type;
break;
}
if (hdr->type == SMBIOS_TYPE_EOT)
break;
va += hdr->size;
for (; va + 1 < end; va++)
if (*va == 0 && *(va + 1) == 0)
break;
va += 2;
}
return ret;
}
char *
smbios_get_string(struct smbtable *st, uint8_t indx, char *dest, size_t len)
{
uint8_t *va, *end;
char *ret = NULL;
int i;
va = (uint8_t *)st->hdr + st->hdr->size;
end = smbios_entry.addr + smbios_entry.len;
for (i = 1; va < end && i < indx && *va; i++)
while (*va++)
;
if (i == indx) {
if (va + len < end) {
ret = dest;
memcpy(ret, va, len);
ret[len - 1] = '\0';
}
}
return ret;
}
char *
fixstring(char *s)
{
char *p, *e;
int i;
for (i = 0; i < nitems(smbios_uninfo); i++)
if ((strncasecmp(s, smbios_uninfo[i],
strlen(smbios_uninfo[i]))) == 0)
return NULL;
for (p = s; *p == ' '; p++)
;
if (p == s + strlen(s))
return NULL;
for (e = s + strlen(s) - 1; e > s && *e == ' '; e--)
;
if (p > s || e < s + strlen(s) - 1) {
memmove(s, p, e - p + 1);
s[e - p + 1] = '\0';
}
return s;
}
void
smbios_info(char *str)
{
char *sminfop, sminfo[64];
struct smbtable stbl, btbl;
struct smbios_sys *sys;
struct smbios_board *board;
int i, infolen, uuidf, havebb;
char *p;
if (smbios_entry.mjr < 2)
return;
stbl.cookie = btbl.cookie = 0;
if (!smbios_find_table(SMBIOS_TYPE_SYSTEM, &stbl))
return;
havebb = smbios_find_table(SMBIOS_TYPE_BASEBOARD, &btbl);
sys = (struct smbios_sys *)stbl.tblhdr;
if (havebb) {
board = (struct smbios_board *)btbl.tblhdr;
sminfop = NULL;
if ((p = smbios_get_string(&btbl, board->vendor,
sminfo, sizeof(sminfo))) != NULL)
sminfop = fixstring(p);
if (sminfop)
strlcpy(smbios_board_vendor, sminfop,
sizeof(smbios_board_vendor));
sminfop = NULL;
if ((p = smbios_get_string(&btbl, board->product,
sminfo, sizeof(sminfo))) != NULL)
sminfop = fixstring(p);
if (sminfop)
strlcpy(smbios_board_prod, sminfop,
sizeof(smbios_board_prod));
sminfop = NULL;
if ((p = smbios_get_string(&btbl, board->serial,
sminfo, sizeof(sminfo))) != NULL)
sminfop = fixstring(p);
if (sminfop)
strlcpy(smbios_board_serial, sminfop,
sizeof(smbios_board_serial));
}
sminfop = NULL;
if ((p = smbios_get_string(&stbl, sys->vendor, sminfo,
sizeof(sminfo))) != NULL)
sminfop = fixstring(p);
if (sminfop == NULL) {
if (havebb) {
if ((p = smbios_get_string(&btbl, board->vendor,
sminfo, sizeof(sminfo))) != NULL)
sminfop = fixstring(p);
}
}
if (sminfop) {
infolen = strlen(sminfop) + 1;
hw_vendor = malloc(infolen, M_DEVBUF, M_NOWAIT);
if (hw_vendor)
strlcpy(hw_vendor, sminfop, infolen);
sminfop = NULL;
}
if ((p = smbios_get_string(&stbl, sys->product, sminfo,
sizeof(sminfo))) != NULL)
sminfop = fixstring(p);
if (sminfop == NULL) {
if (havebb) {
if ((p = smbios_get_string(&btbl, board->product,
sminfo, sizeof(sminfo))) != NULL)
sminfop = fixstring(p);
}
}
if (sminfop) {
infolen = strlen(sminfop) + 1;
hw_prod = malloc(infolen, M_DEVBUF, M_NOWAIT);
if (hw_prod)
strlcpy(hw_prod, sminfop, infolen);
sminfop = NULL;
}
if (hw_vendor != NULL && hw_prod != NULL)
printf("\n%s: %s %s", str, hw_vendor, hw_prod);
if ((p = smbios_get_string(&stbl, sys->version, sminfo,
sizeof(sminfo))) != NULL)
sminfop = fixstring(p);
if (sminfop) {
infolen = strlen(sminfop) + 1;
hw_ver = malloc(infolen, M_DEVBUF, M_NOWAIT);
if (hw_ver)
strlcpy(hw_ver, sminfop, infolen);
sminfop = NULL;
}
if ((p = smbios_get_string(&stbl, sys->serial, sminfo,
sizeof(sminfo))) != NULL)
sminfop = fixstring(p);
if (sminfop) {
infolen = strlen(sminfop) + 1;
for (i = 0; i < infolen - 1; i++)
enqueue_randomness(sminfop[i]);
hw_serial = malloc(infolen, M_DEVBUF, M_NOWAIT);
if (hw_serial)
strlcpy(hw_serial, sminfop, infolen);
}
if (smbios_entry.mjr > 2 || (smbios_entry.mjr == 2 &&
smbios_entry.min >= 1)) {
uuidf = SMBIOS_UUID_NPRESENT|SMBIOS_UUID_NSET;
for (i = 0; i < sizeof(sys->uuid); i++) {
if (sys->uuid[i] != 0xff)
uuidf &= ~SMBIOS_UUID_NSET;
if (sys->uuid[i] != 0)
uuidf &= ~SMBIOS_UUID_NPRESENT;
}
if (uuidf & SMBIOS_UUID_NPRESENT)
hw_uuid = NULL;
else if (uuidf & SMBIOS_UUID_NSET)
hw_uuid = "Not Set";
else {
for (i = 0; i < sizeof(sys->uuid); i++)
enqueue_randomness(sys->uuid[i]);
hw_uuid = malloc(SMBIOS_UUID_REPLEN, M_DEVBUF,
M_NOWAIT);
if (hw_uuid) {
snprintf(hw_uuid, SMBIOS_UUID_REPLEN,
SMBIOS_UUID_REP,
sys->uuid[0], sys->uuid[1], sys->uuid[2],
sys->uuid[3], sys->uuid[4], sys->uuid[5],
sys->uuid[6], sys->uuid[7], sys->uuid[8],
sys->uuid[9], sys->uuid[10], sys->uuid[11],
sys->uuid[12], sys->uuid[13], sys->uuid[14],
sys->uuid[15]);
}
}
}
}