diff options
author | Gordon Willem Klok <gwk@cvs.openbsd.org> | 2006-05-08 22:51:19 +0000 |
---|---|---|
committer | Gordon Willem Klok <gwk@cvs.openbsd.org> | 2006-05-08 22:51:19 +0000 |
commit | 43f20e0647ff9d1b9f6f333dca641dc01587e7ca (patch) | |
tree | 2749242ff1e683c88f4323fa995c1e5eeb99a750 /sys/arch | |
parent | b4b9ffec62bebe163253a5cefcea185cd4bbae23 (diff) |
Add smbios support for i386 and amd64, fix ipmi to use this new functionallity,
hook up some sysctls to add system vendor/product/version and UUID reporting.
"get it in" deraadt@
Diffstat (limited to 'sys/arch')
-rw-r--r-- | sys/arch/amd64/amd64/bios.c | 299 | ||||
-rw-r--r-- | sys/arch/amd64/amd64/mainbus.c | 19 | ||||
-rw-r--r-- | sys/arch/amd64/conf/GENERIC | 3 | ||||
-rw-r--r-- | sys/arch/amd64/conf/files.amd64 | 6 | ||||
-rw-r--r-- | sys/arch/amd64/include/biosvar.h | 4 | ||||
-rw-r--r-- | sys/arch/amd64/include/smbiosvar.h | 206 | ||||
-rw-r--r-- | sys/arch/i386/i386/bios.c | 40 | ||||
-rw-r--r-- | sys/arch/i386/include/biosvar.h | 4 | ||||
-rw-r--r-- | sys/arch/i386/include/smbiosvar.h | 206 |
9 files changed, 764 insertions, 23 deletions
diff --git a/sys/arch/amd64/amd64/bios.c b/sys/arch/amd64/amd64/bios.c new file mode 100644 index 00000000000..8d803aba448 --- /dev/null +++ b/sys/arch/amd64/amd64/bios.c @@ -0,0 +1,299 @@ +/* + * Copyright (c) 2006 Gordon Willem Klok <gklok@cogeco.ca> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/kernel.h> +#include <sys/device.h> +#include <sys/errno.h> +#include <sys/malloc.h> + +#include <uvm/uvm_extern.h> +#include <sys/sysctl.h> + +#include <machine/conf.h> +#include <machine/biosvar.h> +#include <machine/smbiosvar.h> + +#include <dev/isa/isareg.h> +#include <amd64/include/isa_machdep.h> + +struct bios_softc { + struct device sc_dev; +}; + +void smbios_info(char *); +int bios_match(struct device *, void *, void *); +void bios_attach(struct device *, struct device *, void *); + +struct cfattach bios_ca = { + sizeof(struct bios_softc), bios_match, bios_attach +}; + +struct cfdriver bios_cd = { + NULL, "bios", DV_DULL +}; + +struct smbios_entry smbios_entry; +/* + * used by hw_sysctl + */ +extern char *hw_vendor, *hw_prod, *hw_uuid, *hw_serial, *hw_ver; +const char * smbios_uninfo[] = { + "System", + "Not Specified" +}; + +int +bios_match(struct device *parent, void *match , void *aux) +{ + struct bios_attach_args *bia = aux; + /* only one */ + if (bios_cd.cd_ndevs || strcmp(bia->bios_dev, bios_cd.cd_name)) + return 0; + + return 1; +} + +void +bios_attach(struct device *parent, struct device *self, void *aux) +{ + struct bios_softc *sc = (struct bios_softc *)self; + vaddr_t va; + paddr_t pa, end; + u_int8_t *p; + + /* see if we have SMBIOS extentions */ + for (p = ISA_HOLE_VADDR(SMBIOS_START); + p < (u_int8_t *)ISA_HOLE_VADDR(SMBIOS_END); p+= 16) { + struct smbhdr * hdr = (struct smbhdr *)p; + u_int8_t chksum; + int i; + + if (hdr->sig != SMBIOS_SIGNATURE) + continue; + i = hdr->len; + for (chksum = 0; i--; chksum += p[i]) + ; + if (chksum != 0) + continue; + p += 0x10; + if (p[0] != '_' && p[1] != 'D' && p[2] != 'M' && + p[3] != 'I' && p[4] != '_') + continue; + for (chksum = 0, i = 0xf; i--; chksum += p[i]); + ; + if (chksum != 0) + continue; + + pa = trunc_page(hdr->addr); + end = round_page(hdr->addr + hdr->size); + va = uvm_km_valloc(kernel_map, end-pa); + if (va == 0) + break; + + smbios_entry.addr = (u_int8_t *)(va + (hdr->addr & PGOFSET)); + smbios_entry.len = hdr->size; + smbios_entry.mjr = hdr->majrev; + smbios_entry.min = hdr->minrev; + smbios_entry.count = hdr->count; + + for(; pa < end; pa+= NBPG, va+= NBPG) + pmap_kenter_pa(va, pa, VM_PROT_READ); + + printf(": SMBIOS rev. %d.%d @ 0x%lx (%d entries)", + hdr->majrev, hdr->minrev, hdr->addr, hdr->count); + smbios_info(sc->sc_dev.dv_xname); + break; + } + + printf("\n"); +} + +/* + * smbios_find_table() takes a caller supplied smbios struct type and + * a pointer to a handle (struct smbtable) returning one if the structure + * is sucessfully located and zero otherwise. Callers should take care + * to initilize the cookie field of the smbtable structure to zero before + * the first invocation of this function. + * Multiple tables of the same type can be located by repeadtly calling + * smbios_find_table with the same arguments. + */ +int +smbios_find_table(u_int8_t type, struct smbtable *st) +{ + u_int8_t *va, *end; + struct smbtblhdr *hdr; + int ret = 0, tcount = 1; + + va = smbios_entry.addr; + end = va + smbios_entry.len; + + /* + * The cookie field of the smtable structure is used to locate + * multiple instances of a table of an arbitrary type. Following the + * sucessful location of a table, the type is encoded as bits 0:7 of + * the cookie value, the offset in terms of the number of structures + * preceding that referenced by the handle is encoded in bits 15:31. + */ + if ((st->cookie & 0xfff) == type && st->cookie >> 16) { + if ((u_int8_t *)st->hdr >= va && (u_int8_t *)st->hdr < end) { + hdr = st->hdr; + if (hdr->type == type) { + va = (u_int8_t *) hdr + hdr->size; + for (; va + 1 < end; va++) + if (*va == NULL && *(va + 1) == NULL) + 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 == NULL && *(va + 1) == NULL) + break; + va+=2; + } + + return ret; +} + +char * +smbios_get_string(struct smbtable *st, u_int8_t indx) +{ + u_int8_t *va, *end; + char *ret = NULL; + int i; + + va = (u_int8_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) + ret = (char *) va; + + return ret; +} + +void +smbios_info(char * str) +{ + struct smbtable stbl, btbl; + struct smbios_sys *sys; + struct smbios_board *board; + int i, uuidf, havebb; + + if (smbios_entry.mjr < 2) + return; + /* + * According to the spec the system table among others are required to + * be present, if it is not we dont bother with this smbios + * implementation. + */ + 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; + /* + * Some smbios implementations have no system vendor or product strings, + * some have very uninformative data which is harder to work around + * and we must rely upon various heuristics to detect this. In both + * cases we attempt to fall back on the base board information in the + * perhaps naieve belief that motherboard vendors will supply this + * information. + */ + if ((hw_vendor = smbios_get_string(&stbl, sys->vendor)) != NULL) { + for (i = 0; i < sizeof(smbios_uninfo) / sizeof(smbios_uninfo[0]) + ; i++) { + if ((strncmp(hw_vendor, smbios_uninfo[i], + strlen(smbios_uninfo[i]))) == 0) { + if (havebb) + hw_vendor = smbios_get_string(&btbl, + board->vendor); + break; + } + } + } else + hw_vendor = smbios_get_string(&btbl, board->vendor); + if ((hw_prod = smbios_get_string(&stbl, sys->product)) != NULL) { + for (i = 0; i < sizeof(smbios_uninfo) / sizeof(smbios_uninfo[0]) + ; i++) { + if ((strncmp(hw_prod, smbios_uninfo[i], + strlen(smbios_uninfo[i]))) == 0) { + if (havebb) + hw_prod = smbios_get_string(&btbl, + board->product); + break; + } + } + } else + hw_prod = smbios_get_string(&btbl, board->product); + if (hw_vendor != NULL && hw_prod != NULL) + printf("\n%s: %s %s", str, hw_vendor, hw_prod); + hw_ver = smbios_get_string(&stbl, sys->version); + hw_serial = smbios_get_string(&stbl, sys->serial); + if (smbios_entry.mjr > 2 || (smbios_entry.mjr == 2 && + smbios_entry.min >= 1)) { + /* + * If the uuid value is all 0xff the uuid is present but not + * set, if its all 0 then the uuid isnt present at all. + */ + 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 { + 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]); + } + } + } +} diff --git a/sys/arch/amd64/amd64/mainbus.c b/sys/arch/amd64/amd64/mainbus.c index 42a3f8e38df..804a7c0308c 100644 --- a/sys/arch/amd64/amd64/mainbus.c +++ b/sys/arch/amd64/amd64/mainbus.c @@ -1,4 +1,4 @@ -/* $OpenBSD: mainbus.c,v 1.7 2006/04/14 21:33:56 marco Exp $ */ +/* $OpenBSD: mainbus.c,v 1.8 2006/05/08 22:51:17 gwk Exp $ */ /* $NetBSD: mainbus.c,v 1.1 2003/04/26 18:39:29 fvdl Exp $ */ /* @@ -46,6 +46,7 @@ #include "isa.h" #include "acpi.h" #include "ipmi.h" +#include "bios.h" #include <machine/cpuvar.h> #include <machine/i82093var.h> @@ -60,6 +61,10 @@ #include <dev/ipmivar.h> #endif +#if NBIOS > 0 +#include <machine/biosvar.h> +#endif + int mainbus_match(struct device *, void *, void *); void mainbus_attach(struct device *, struct device *, void *); @@ -85,6 +90,9 @@ union mainbus_attach_args { #if NIPMI > 0 struct ipmi_attach_args mba_iaa; #endif +#if NBIOS > 0 + struct bios_attach_args mba_bios; +#endif }; /* @@ -149,6 +157,15 @@ mainbus_attach(struct device *parent, struct device *self, void *aux) pci_mode = pci_mode_detect(); #endif +#if NBIOS > 0 + { + mba.mba_bios.bios_dev = "bios"; + mba.mba_bios.bios_iot = X86_BUS_SPACE_IO; + mba.mba_bios.bios_memt = X86_BUS_SPACE_MEM; + config_found(self, &mba.mba_bios, mainbus_print); + } +#endif + #if NACPI > 0 #if NPCI > 0 if (pci_mode != 0) diff --git a/sys/arch/amd64/conf/GENERIC b/sys/arch/amd64/conf/GENERIC index bab2525569c..800d51067c4 100644 --- a/sys/arch/amd64/conf/GENERIC +++ b/sys/arch/amd64/conf/GENERIC @@ -1,4 +1,4 @@ -# $OpenBSD: GENERIC,v 1.126 2006/05/08 04:15:02 brad Exp $ +# $OpenBSD: GENERIC,v 1.127 2006/05/08 22:51:18 gwk Exp $ # # For further information on compiling OpenBSD kernels, see the config(8) # man page. @@ -37,6 +37,7 @@ config bsd swap generic mainbus0 at root +bios0 at mainbus? cpu0 at mainbus? isa0 at mainbus0 isa0 at pcib? diff --git a/sys/arch/amd64/conf/files.amd64 b/sys/arch/amd64/conf/files.amd64 index 0b6cd58fa6a..ce1caf427b6 100644 --- a/sys/arch/amd64/conf/files.amd64 +++ b/sys/arch/amd64/conf/files.amd64 @@ -1,4 +1,4 @@ -# $OpenBSD: files.amd64,v 1.21 2006/03/22 21:16:00 kettenis Exp $ +# $OpenBSD: files.amd64,v 1.22 2006/05/08 22:51:18 gwk Exp $ maxpartitions 16 maxusers 2 16 128 @@ -73,6 +73,10 @@ device mainbus: isabus, pcibus, mainbus attach mainbus at root file arch/amd64/amd64/mainbus.c mainbus +device bios {} +attach bios at mainbus +file arch/amd64/amd64/bios.c bios needs-flag + define cpu {[apid = -1]} device cpu attach cpu at mainbus diff --git a/sys/arch/amd64/include/biosvar.h b/sys/arch/amd64/include/biosvar.h index b4bc59108bd..94a67ffad78 100644 --- a/sys/arch/amd64/include/biosvar.h +++ b/sys/arch/amd64/include/biosvar.h @@ -1,5 +1,5 @@ /* XXX - DSR */ -/* $OpenBSD: biosvar.h,v 1.5 2005/12/13 23:13:45 mickey Exp $ */ +/* $OpenBSD: biosvar.h,v 1.6 2006/05/08 22:51:18 gwk Exp $ */ /* * Copyright (c) 1997-1999 Michael Shalayeff @@ -42,6 +42,7 @@ #define BIOSF_BIOS32 0x0001 #define BIOSF_PCIBIOS 0x0002 #define BIOSF_PROMSCAN 0x0004 +#define BIOSF_SMBIOS 0x0006 /* BIOS media ID */ #define BIOSM_F320K 0xff /* floppy ds/sd 8 spt */ @@ -110,6 +111,7 @@ struct bios32_entry { ((a) | ((b) << 8) | ((c) << 16) | ((d) << 24)) #define BIOS32_SIGNATURE BIOS32_MAKESIG('_', '3', '2', '_') #define PCIBIOS_SIGNATURE BIOS32_MAKESIG('$', 'P', 'C', 'I') +#define SMBIOS_SIGNATURE BIOS32_MAKESIG('_', 'S', 'M', '_') /* * CTL_BIOS definitions. diff --git a/sys/arch/amd64/include/smbiosvar.h b/sys/arch/amd64/include/smbiosvar.h new file mode 100644 index 00000000000..5c9392c642e --- /dev/null +++ b/sys/arch/amd64/include/smbiosvar.h @@ -0,0 +1,206 @@ +/* + * Copyright (c) 2006 Gordon Willem Klok <gklok@cogeco.ca> + * Copyright (c) 2005 Jordan Hargrave + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +#ifndef _I386_SMBIOSVAR_ +#define _I386_SMBIOSVAR_ + +#define SMBIOS_START 0xf0000 +#define SMBIOS_END 0xfffff + +#define SMBIOS_UUID_NPRESENT 0x1 +#define SMBIOS_UUID_NSET 0x2 + +/* + * Section 3.5 of "UUIDs and GUIDs" found at + * http://www.opengroup.org/dce/info/draft-leach-uuids-guids-01.txt + * specifies the string repersentation of a UUID. + */ +#define SMBIOS_UUID_REP "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x" +#define SMBIOS_UUID_REPLEN 37 /* 16 zero padded values, 4 hyphens, 1 null */ + +struct smbios_entry { + u_int8_t mjr; + u_int8_t min; + u_int8_t *addr; + u_int16_t len; + u_int16_t count; +}; + +struct smbhdr { + u_int32_t sig; /* "_SM_" */ + u_int8_t checksum; /* Entry point checksum */ + u_int8_t len; /* Entry point structure length */ + u_int8_t majrev; /* Specification major revision */ + u_int8_t minrev; /* Specification minor revision */ + u_int16_t mss; /* Maximum Structure Size */ + u_int8_t epr; /* Entry Point Revision */ + u_int8_t fa[5]; /* value determined by EPR */ + u_int8_t sasig[5]; /* Secondary Anchor "_DMI_" */ + u_int8_t sachecksum; /* Secondary Checksum */ + u_int16_t size; /* Length of structure table in bytes */ + u_int32_t addr; /* Structure table address */ + u_int16_t count; /* Number of SMBIOS structures */ + u_int8_t rev; /* BCD revision */ +} __packed; + +struct smbtblhdr { + u_int8_t type; + u_int8_t size; + u_int16_t handle; +} __packed; + +struct smbtable { + struct smbtblhdr *hdr; + void *tblhdr; + u_int32_t cookie; +}; + +#define SMBIOS_TYPE_BIOS 0 +#define SMBIOS_TYPE_SYSTEM 1 +#define SMBIOS_TYPE_BASEBOARD 2 +#define SMBIOS_TYPE_ENCLOSURE 3 +#define SMBIOS_TYPE_PROCESSOR 4 +#define SMBIOS_TYPE_MEMCTRL 5 +#define SMBIOS_TYPE_MEMMOD 6 +#define SMBIOS_TYPE_CACHE 7 +#define SMBIOS_TYPE_PORT 8 +#define SMBIOS_TYPE_SLOTS 9 +#define SMBIOS_TYPE_OBD 10 +#define SMBIOS_TYPE_OEM 11 +#define SMBIOS_TYPE_SYSCONFOPT 12 +#define SMBIOS_TYPE_BIOSLANG 13 +#define SMBIOS_TYPE_GROUPASSOC 14 +#define SMBIOS_TYPE_SYSEVENTLOG 15 +#define SMBIOS_TYPE_PHYMEM 16 +#define SMBIOS_TYPE_MEMDEV 17 +#define SMBIOS_TYPE_ECCINFO32 18 +#define SMBIOS_TYPE_MEMMAPARRAYADDR 19 +#define SMBIOS_TYPE_MEMMAPDEVADDR 20 +#define SMBIOS_TYPE_INBUILTPOINT 21 +#define SMBIOS_TYPE_PORTBATT 22 +#define SMBIOS_TYPE_SYSRESET 23 +#define SMBIOS_TYPE_HWSECUIRTY 24 +#define SMBIOS_TYPE_PWRCTRL 25 +#define SMBIOS_TYPE_VOLTPROBE 26 +#define SMBIOS_TYPE_COOLING 27 +#define SMBIOS_TYPE_TEMPPROBE 28 +#define SMBIOS_TYPE_CURRENTPROBE 29 +#define SMBIOS_TYPE_OOB_REMOTEACCESS 30 +#define SMBIOS_TYPE_BIS 31 +#define SMBIOS_TYPE_SBI 32 +#define SMBIOS_TYPE_ECCINFO64 33 +#define SMBIOS_TYPE_MGMTDEV 34 +#define SMBIOS_TYPE_MGTDEVCOMP 35 +#define SMBIOS_TYPE_MGTDEVTHRESH 36 +#define SMBIOS_TYPE_MEMCHANNEL 37 +#define SMBIOS_TYPE_IPMIDEV 38 +#define SMBIOS_TYPE_SPS 39 +#define SMBIOS_TYPE_INACTIVE 126 +#define SMBIOS_TYPE_EOT 127 + +/* + * SMBIOS Structure Type 0 "BIOS Information" + * DMTF Specification DSP0134 Section: 3.3.1 p.g. 34 + */ +struct smbios_struct_bios { + u_int8_t vendor; /* string */ + u_int8_t version; /* string */ + u_int16_t startaddr; + u_int8_t release; /* string */ + u_int8_t romsize; + u_int64_t characteristics; + u_int32_t charext; + u_int8_t major_rel; + u_int8_t minor_rel; + u_int8_t ecf_mjr_rel; /* embedded controler firmware */ + u_int8_t ecf_min_rel; /* embedded controler firmware */ +} __packed; + +/* + * SMBIOS Structure Type 1 "System Information" + * DMTF Specification DSP0134 Section 3.3.2 p.g. 35 + */ + +struct smbios_sys { +/* SMBIOS spec 2.0+ */ + u_int8_t vendor; /* string */ + u_int8_t product; /* string */ + u_int8_t version; /* string */ + u_int8_t serial; /* string */ +/* SMBIOS spec 2.1+ */ + u_int8_t uuid[16]; + u_int8_t wakeup; +/* SMBIOS spec 2.4+ */ + u_int8_t sku; /* string */ + u_int8_t family; /* string */ +} __packed; + +/* + * SMBIOS Structure Type 2 "Base Board (Module) Information" + * DMTF Specification DSP0134 Section 3.3.3 p.g. 37 + */ +struct smbios_board { + u_int8_t vendor; /* string */ + u_int8_t product; /* string */ + u_int8_t version; /* string */ + u_int8_t serial; /* string */ + u_int8_t asset; /* stirng */ + u_int8_t feature; /* feature flags */ + u_int8_t location; /* location in chassis */ + u_int16_t handle; /* chassis handle */ + u_int8_t type; /* board type */ + u_int8_t noc; /* number of contained objects */ +} __packed; + +/* + * SMBIOS Structure Type 38 "IPMI Information" + * DMTF Specification DSP0134 Section 3.3.39 p.g. 91 + */ +struct smbios_ipmi { + u_int8_t smipmi_if_type; /* IPMI Interface Type */ + u_int8_t smipmi_if_rev; /* BCD IPMI Revision */ + u_int8_t smipmi_i2c_address; /* I2C address of BMC */ + u_int8_t smipmi_nvram_address; /* I2C address of NVRAM + * storage */ + u_int64_t smipmi_base_address; /* Base address of BMC (BAR + * format */ + u_int8_t smipmi_base_flags; /* Flags field: + * bit 7:6 : register spacing + * 00 = byte + * 01 = dword + * 02 = word + * bit 4 : Lower bit BAR + * bit 3 : IRQ valid + * bit 2 : N/A + * bit 1 : Interrupt polarity + * bit 0 : Interrupt trigger */ + u_int8_t smipmi_irq; /* IRQ if applicable */ +} __packed; + +int smbios_find_table(u_int8_t, struct smbtable *); +char * smbios_get_string(struct smbtable *, u_int8_t); + +#endif diff --git a/sys/arch/i386/i386/bios.c b/sys/arch/i386/i386/bios.c index e559d97caf7..95def0a01d5 100644 --- a/sys/arch/i386/i386/bios.c +++ b/sys/arch/i386/i386/bios.c @@ -1,4 +1,4 @@ -/* $OpenBSD: bios.c,v 1.62 2006/05/08 21:13:03 gwk Exp $ */ +/* $OpenBSD: bios.c,v 1.59 2006/05/08 22:51:18 gwk Exp $ */ /* * Copyright (c) 1997-2001 Michael Shalayeff @@ -91,7 +91,7 @@ u_int32_t bios_cksumlen; struct bios32_entry bios32_entry; struct smbios_entry smbios_entry; #ifdef MULTIPROCESSOR -void *bios_smpinfo; +void *bios_smpinfo; #endif void smbios_info(char*); @@ -103,8 +103,8 @@ bios_diskinfo_t *bios_getdiskinfo(dev_t); */ extern char *hw_vendor, *hw_prod, *hw_uuid, *hw_serial, *hw_ver; const char * smbios_uninfo[] = { - "System", - "Not Specified" + "System", + "Not Specified" }; @@ -160,7 +160,7 @@ biosattach(struct device *parent, struct device *self, void *aux) /* see if we have BIOS32 extensions */ if (!(flags & BIOSF_BIOS32)) { for (va = ISA_HOLE_VADDR(BIOS32_START); - va < (u_int8_t *)ISA_HOLE_VADDR(BIOS32_END); va += 16) { + va < (u_int8_t *)ISA_HOLE_VADDR(BIOS32_END); va += 16) { bios32_header_t h = (bios32_header_t)va; u_int8_t cksum; int i; @@ -184,7 +184,7 @@ biosattach(struct device *parent, struct device *self, void *aux) } } - /* see if we have SMBIOS extentions */ + /* see if we have SMBIOS extentions */ if (!(flags & BIOSF_SMBIOS)) { for (va = ISA_HOLE_VADDR(SMBIOS_START); va < (u_int8_t *)ISA_HOLE_VADDR(SMBIOS_END); va+= 16) { @@ -210,13 +210,13 @@ biosattach(struct device *parent, struct device *self, void *aux) if (chksum != 0) continue; - pa = trunc_page(sh->addr); + pa = trunc_page(sh->addr); end = round_page(sh->addr + sh->size); eva = uvm_km_valloc(kernel_map, end-pa); if (eva == 0) break; - smbios_entry.addr = (u_int8_t *)(eva + + smbios_entry.addr = (u_int8_t *)(eva + (sh->addr & PGOFSET)); smbios_entry.len = sh->size; smbios_entry.mjr = sh->majrev; @@ -225,10 +225,10 @@ biosattach(struct device *parent, struct device *self, void *aux) for (; pa < end; pa+= NBPG, eva+= NBPG) pmap_kenter_pa(eva, pa, VM_PROT_READ); - - printf(", SMBIOS rev. %d.%d @ 0x%lx (%d entries)", + + printf(", SMBIOS rev. %d.%d @ 0x%lx (%d entries)", sh->majrev, sh->minrev, sh->addr, sh->count); - + smbios_info(sc->sc_dev.dv_xname); break; } @@ -274,8 +274,8 @@ biosattach(struct device *parent, struct device *self, void *aux) volatile u_int8_t *eva; for (str = NULL, va = ISA_HOLE_VADDR(0xc0000), - eva = ISA_HOLE_VADDR(0xf0000); - va < eva; va += 512) { + eva = ISA_HOLE_VADDR(0xf0000); + va < eva; va += 512) { extern struct extent *iomem_ex; bios_romheader_t romh = (bios_romheader_t)va; u_int32_t off, len; @@ -452,8 +452,8 @@ bios32_service(u_int32_t service, bios32_entry_t e, bios32_entry_info_t ei) setgdt(slot, (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) { + va += trunc_page(BIOS32_START); + pa < endpa; pa += NBPG, va += NBPG) { pmap_enter(pmap_kernel(), va, pa, VM_PROT_READ | VM_PROT_WRITE, VM_PROT_READ | VM_PROT_WRITE | PMAP_WIRED); @@ -628,7 +628,7 @@ bios_getdiskinfo(dev_t dev) * smbios_find_table with the same arguments. */ int -smbios_find_table(u_int8_t type, struct smbtable *st) +smbios_find_table(u_int8_t type, struct smbtable *st) { u_int8_t *va, *end; struct smbtblhdr *hdr; @@ -660,6 +660,7 @@ smbios_find_table(u_int8_t type, struct smbtable *st) for (; va + sizeof(struct smbtblhdr) < end && tcount <= smbios_entry.count; tcount++) { hdr = (struct smbtblhdr *) va; + printf("SMBIOS (%d)@%p type: %d", tcount, va, hdr->type); if (hdr->type == type) { ret = 1; st->hdr = hdr; @@ -670,12 +671,15 @@ smbios_find_table(u_int8_t type, struct smbtable *st) if (hdr->type == SMBIOS_TYPE_EOT) break; va+= hdr->size; + printf(" size: %d strings@%p", hdr->size, va); for (; va + 1 < end; va++) if (*va == NULL && *(va + 1) == NULL) break; va+=2; + printf(" end@%p\n", va); } + printf("\n"); return ret; } @@ -698,7 +702,7 @@ smbios_get_string(struct smbtable *st, u_int8_t indx) } void -smbios_info(char * str) +smbios_info(char * str) { struct smbtable stbl, btbl; struct smbios_sys *sys; @@ -720,7 +724,7 @@ smbios_info(char * str) sys = (struct smbios_sys *)stbl.tblhdr; if (havebb) board = (struct smbios_board *)btbl.tblhdr; - /* + /* * Some smbios implementations have no system vendor or product strings, * some have very uninformative data which is harder to work around * and we must rely upon various heuristics to detect this. In both diff --git a/sys/arch/i386/include/biosvar.h b/sys/arch/i386/include/biosvar.h index dca4f99f7c5..fbf08a134f4 100644 --- a/sys/arch/i386/include/biosvar.h +++ b/sys/arch/i386/include/biosvar.h @@ -1,4 +1,4 @@ -/* $OpenBSD: biosvar.h,v 1.45 2005/11/22 12:51:01 mickey Exp $ */ +/* $OpenBSD: biosvar.h,v 1.46 2006/05/08 22:51:18 gwk Exp $ */ /* * Copyright (c) 1997-1999 Michael Shalayeff @@ -39,6 +39,7 @@ #define BIOSF_BIOS32 0x0001 #define BIOSF_PCIBIOS 0x0002 #define BIOSF_PROMSCAN 0x0004 +#define BIOSF_SMBIOS 0x0006 /* BIOS media ID */ #define BIOSM_F320K 0xff /* floppy ds/sd 8 spt */ @@ -107,6 +108,7 @@ struct bios32_entry { ((a) | ((b) << 8) | ((c) << 16) | ((d) << 24)) #define BIOS32_SIGNATURE BIOS32_MAKESIG('_', '3', '2', '_') #define PCIBIOS_SIGNATURE BIOS32_MAKESIG('$', 'P', 'C', 'I') +#define SMBIOS_SIGNATURE BIOS32_MAKESIG('_', 'S', 'M', '_') /* * CTL_BIOS definitions. diff --git a/sys/arch/i386/include/smbiosvar.h b/sys/arch/i386/include/smbiosvar.h new file mode 100644 index 00000000000..5c9392c642e --- /dev/null +++ b/sys/arch/i386/include/smbiosvar.h @@ -0,0 +1,206 @@ +/* + * Copyright (c) 2006 Gordon Willem Klok <gklok@cogeco.ca> + * Copyright (c) 2005 Jordan Hargrave + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +#ifndef _I386_SMBIOSVAR_ +#define _I386_SMBIOSVAR_ + +#define SMBIOS_START 0xf0000 +#define SMBIOS_END 0xfffff + +#define SMBIOS_UUID_NPRESENT 0x1 +#define SMBIOS_UUID_NSET 0x2 + +/* + * Section 3.5 of "UUIDs and GUIDs" found at + * http://www.opengroup.org/dce/info/draft-leach-uuids-guids-01.txt + * specifies the string repersentation of a UUID. + */ +#define SMBIOS_UUID_REP "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x" +#define SMBIOS_UUID_REPLEN 37 /* 16 zero padded values, 4 hyphens, 1 null */ + +struct smbios_entry { + u_int8_t mjr; + u_int8_t min; + u_int8_t *addr; + u_int16_t len; + u_int16_t count; +}; + +struct smbhdr { + u_int32_t sig; /* "_SM_" */ + u_int8_t checksum; /* Entry point checksum */ + u_int8_t len; /* Entry point structure length */ + u_int8_t majrev; /* Specification major revision */ + u_int8_t minrev; /* Specification minor revision */ + u_int16_t mss; /* Maximum Structure Size */ + u_int8_t epr; /* Entry Point Revision */ + u_int8_t fa[5]; /* value determined by EPR */ + u_int8_t sasig[5]; /* Secondary Anchor "_DMI_" */ + u_int8_t sachecksum; /* Secondary Checksum */ + u_int16_t size; /* Length of structure table in bytes */ + u_int32_t addr; /* Structure table address */ + u_int16_t count; /* Number of SMBIOS structures */ + u_int8_t rev; /* BCD revision */ +} __packed; + +struct smbtblhdr { + u_int8_t type; + u_int8_t size; + u_int16_t handle; +} __packed; + +struct smbtable { + struct smbtblhdr *hdr; + void *tblhdr; + u_int32_t cookie; +}; + +#define SMBIOS_TYPE_BIOS 0 +#define SMBIOS_TYPE_SYSTEM 1 +#define SMBIOS_TYPE_BASEBOARD 2 +#define SMBIOS_TYPE_ENCLOSURE 3 +#define SMBIOS_TYPE_PROCESSOR 4 +#define SMBIOS_TYPE_MEMCTRL 5 +#define SMBIOS_TYPE_MEMMOD 6 +#define SMBIOS_TYPE_CACHE 7 +#define SMBIOS_TYPE_PORT 8 +#define SMBIOS_TYPE_SLOTS 9 +#define SMBIOS_TYPE_OBD 10 +#define SMBIOS_TYPE_OEM 11 +#define SMBIOS_TYPE_SYSCONFOPT 12 +#define SMBIOS_TYPE_BIOSLANG 13 +#define SMBIOS_TYPE_GROUPASSOC 14 +#define SMBIOS_TYPE_SYSEVENTLOG 15 +#define SMBIOS_TYPE_PHYMEM 16 +#define SMBIOS_TYPE_MEMDEV 17 +#define SMBIOS_TYPE_ECCINFO32 18 +#define SMBIOS_TYPE_MEMMAPARRAYADDR 19 +#define SMBIOS_TYPE_MEMMAPDEVADDR 20 +#define SMBIOS_TYPE_INBUILTPOINT 21 +#define SMBIOS_TYPE_PORTBATT 22 +#define SMBIOS_TYPE_SYSRESET 23 +#define SMBIOS_TYPE_HWSECUIRTY 24 +#define SMBIOS_TYPE_PWRCTRL 25 +#define SMBIOS_TYPE_VOLTPROBE 26 +#define SMBIOS_TYPE_COOLING 27 +#define SMBIOS_TYPE_TEMPPROBE 28 +#define SMBIOS_TYPE_CURRENTPROBE 29 +#define SMBIOS_TYPE_OOB_REMOTEACCESS 30 +#define SMBIOS_TYPE_BIS 31 +#define SMBIOS_TYPE_SBI 32 +#define SMBIOS_TYPE_ECCINFO64 33 +#define SMBIOS_TYPE_MGMTDEV 34 +#define SMBIOS_TYPE_MGTDEVCOMP 35 +#define SMBIOS_TYPE_MGTDEVTHRESH 36 +#define SMBIOS_TYPE_MEMCHANNEL 37 +#define SMBIOS_TYPE_IPMIDEV 38 +#define SMBIOS_TYPE_SPS 39 +#define SMBIOS_TYPE_INACTIVE 126 +#define SMBIOS_TYPE_EOT 127 + +/* + * SMBIOS Structure Type 0 "BIOS Information" + * DMTF Specification DSP0134 Section: 3.3.1 p.g. 34 + */ +struct smbios_struct_bios { + u_int8_t vendor; /* string */ + u_int8_t version; /* string */ + u_int16_t startaddr; + u_int8_t release; /* string */ + u_int8_t romsize; + u_int64_t characteristics; + u_int32_t charext; + u_int8_t major_rel; + u_int8_t minor_rel; + u_int8_t ecf_mjr_rel; /* embedded controler firmware */ + u_int8_t ecf_min_rel; /* embedded controler firmware */ +} __packed; + +/* + * SMBIOS Structure Type 1 "System Information" + * DMTF Specification DSP0134 Section 3.3.2 p.g. 35 + */ + +struct smbios_sys { +/* SMBIOS spec 2.0+ */ + u_int8_t vendor; /* string */ + u_int8_t product; /* string */ + u_int8_t version; /* string */ + u_int8_t serial; /* string */ +/* SMBIOS spec 2.1+ */ + u_int8_t uuid[16]; + u_int8_t wakeup; +/* SMBIOS spec 2.4+ */ + u_int8_t sku; /* string */ + u_int8_t family; /* string */ +} __packed; + +/* + * SMBIOS Structure Type 2 "Base Board (Module) Information" + * DMTF Specification DSP0134 Section 3.3.3 p.g. 37 + */ +struct smbios_board { + u_int8_t vendor; /* string */ + u_int8_t product; /* string */ + u_int8_t version; /* string */ + u_int8_t serial; /* string */ + u_int8_t asset; /* stirng */ + u_int8_t feature; /* feature flags */ + u_int8_t location; /* location in chassis */ + u_int16_t handle; /* chassis handle */ + u_int8_t type; /* board type */ + u_int8_t noc; /* number of contained objects */ +} __packed; + +/* + * SMBIOS Structure Type 38 "IPMI Information" + * DMTF Specification DSP0134 Section 3.3.39 p.g. 91 + */ +struct smbios_ipmi { + u_int8_t smipmi_if_type; /* IPMI Interface Type */ + u_int8_t smipmi_if_rev; /* BCD IPMI Revision */ + u_int8_t smipmi_i2c_address; /* I2C address of BMC */ + u_int8_t smipmi_nvram_address; /* I2C address of NVRAM + * storage */ + u_int64_t smipmi_base_address; /* Base address of BMC (BAR + * format */ + u_int8_t smipmi_base_flags; /* Flags field: + * bit 7:6 : register spacing + * 00 = byte + * 01 = dword + * 02 = word + * bit 4 : Lower bit BAR + * bit 3 : IRQ valid + * bit 2 : N/A + * bit 1 : Interrupt polarity + * bit 0 : Interrupt trigger */ + u_int8_t smipmi_irq; /* IRQ if applicable */ +} __packed; + +int smbios_find_table(u_int8_t, struct smbtable *); +char * smbios_get_string(struct smbtable *, u_int8_t); + +#endif |