diff options
author | jkim <jkim@FreeBSD.org> | 2005-07-14 19:52:22 +0000 |
---|---|---|
committer | jkim <jkim@FreeBSD.org> | 2005-07-14 19:52:22 +0000 |
commit | 551446f627af0ed3afc5f879cb5cc40b2c02bd94 (patch) | |
tree | f4faafbd43a59d3e76e2a0ccb35fae3405e82646 /sys/boot | |
parent | 6a1d883879d0a43d5c1614ddea8a41b29f179fb1 (diff) | |
download | FreeBSD-src-551446f627af0ed3afc5f879cb5cc40b2c02bd94.zip FreeBSD-src-551446f627af0ed3afc5f879cb5cc40b2c02bd94.tar.gz |
Scan static SMBIOS structures and export the following environment
variables to loader:
hint.smbios.0.enabled "YES" when SMBIOS is detected
hint.smbios.0.bios.vendor BIOS vendor
hint.smbios.0.bios.version BIOS version
hint.smbios.0.bios.reldate BIOS release date
hint.smbios.0.system.maker System manufacturer
hint.smbios.0.system.product System product name
hint.smbios.0.system.version System version number
hint.smbios.0.planar.maker Base board manufacturer
hint.smbios.0.planar.product Base board product name
hint.smbios.0.planar.version Base board version number
hint.smbios.0.chassis.maker Enclosure manufacturer
hint.smbios.0.chassis.version Enclosure version
These strings can be used to detect hardware quirks and to set appropriate
flags. For example, Compaq R3000 series and some HP laptops require
hint.atkbd.0.flags="0x9"
to boot. See amd64/67745 for more detail.
Note: Please do not abuse this feature to resolve general problem when it
can be fixed programmatically. This must be used as a last resort.
PR: kern/81449
Approved by: anholt (mentor)
Diffstat (limited to 'sys/boot')
-rw-r--r-- | sys/boot/i386/libi386/Makefile | 2 | ||||
-rw-r--r-- | sys/boot/i386/libi386/libi386.h | 2 | ||||
-rw-r--r-- | sys/boot/i386/libi386/smbios.c | 176 | ||||
-rw-r--r-- | sys/boot/i386/loader/main.c | 3 |
4 files changed, 182 insertions, 1 deletions
diff --git a/sys/boot/i386/libi386/Makefile b/sys/boot/i386/libi386/Makefile index 2c388e3..baf8985 100644 --- a/sys/boot/i386/libi386/Makefile +++ b/sys/boot/i386/libi386/Makefile @@ -8,7 +8,7 @@ SRCS= biosacpi.c bioscd.c biosdisk.c biosmem.c biospnp.c \ comconsole.c devicename.c elf32_freebsd.c \ elf64_freebsd.c gatea20.c \ i386_copy.c i386_module.c nullconsole.c pxe.c pxetramp.s \ - time.c vidconsole.c amd64_tramp.S + smbios.c time.c vidconsole.c amd64_tramp.S BOOT_COMCONSOLE_PORT?= 0x3f8 CFLAGS+= -DCOMPORT=${BOOT_COMCONSOLE_PORT} diff --git a/sys/boot/i386/libi386/libi386.h b/sys/boot/i386/libi386/libi386.h index 7499576..c5d962a 100644 --- a/sys/boot/i386/libi386/libi386.h +++ b/sys/boot/i386/libi386/libi386.h @@ -99,6 +99,8 @@ int biospci_read_config(uint32_t locator, int offset, int width, uint32_t *val); void biosacpi_detect(); +void smbios_detect(); + void gateA20(void); int i386_autoload(void); diff --git a/sys/boot/i386/libi386/smbios.c b/sys/boot/i386/libi386/smbios.c new file mode 100644 index 0000000..e2e7081 --- /dev/null +++ b/sys/boot/i386/libi386/smbios.c @@ -0,0 +1,176 @@ +/*- + * Copyright (c) 2005 Jung-uk Kim <jkim@FreeBSD.org> + * 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 AUTHOR 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 AUTHOR 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. + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <stand.h> +#include <bootstrap.h> + +#include "btxv86.h" + +/* + * Detect SMBIOS and export information about the SMBIOS into the + * environment. + * + * System Management BIOS Reference Specification, v2.4 Final + * http://www.dmtf.org/standards/published_documents/DSP0134.pdf + */ + +/* + * Spec. 2.1.1 SMBIOS Structure Table Entry Point + * + * 'The SMBIOS Entry Point structure, described below, can be located by + * application software by searching for the anchor-string on paragraph + * (16-byte) boundaries within the physical memory address range + * 000F0000h to 000FFFFFh.' + */ +#define SMBIOS_START 0xf0000 +#define SMBIOS_LENGTH 0x10000 +#define SMBIOS_STEP 0x10 +#define SMBIOS_SIG "_SM_" +#define SMBIOS_DMI_SIG "_DMI_" + +static u_int8_t *smbios_parse_table(const u_int8_t *dmi); +static void smbios_setenv(const char *env, const u_int8_t *dmi, + const int offset); +static u_int8_t smbios_checksum(const u_int8_t *addr, const u_int8_t len); +static u_int8_t *smbios_sigsearch(const caddr_t addr, const u_int32_t len); + +void +smbios_detect(void) +{ + u_int8_t *smbios, *dmi, *addr; + u_int16_t i, length, count; + u_int32_t paddr; + + /* locate and validate the SMBIOS */ + smbios = smbios_sigsearch(PTOV(SMBIOS_START), SMBIOS_LENGTH); + if (smbios == NULL) + return; + + /* export values from the SMBIOS */ + setenv("hint.smbios.0.enabled", "YES", 1); + + length = *(u_int16_t *)(smbios + 0x16); /* Structure Table Length */ + paddr = *(u_int32_t *)(smbios + 0x18); /* Structure Table Address */ + count = *(u_int16_t *)(smbios + 0x1c); /* No of SMBIOS Structures */ + + for (dmi = addr = PTOV(paddr), i = 0; + dmi - addr < length && i < count; i++) + dmi = smbios_parse_table(dmi); +} + +static u_int8_t * +smbios_parse_table(const u_int8_t *dmi) +{ + u_int8_t *dp; + + switch(dmi[0]) { + case 0: /* Type 0: BIOS */ + smbios_setenv("hint.smbios.0.bios.vendor", dmi, 0x04); + smbios_setenv("hint.smbios.0.bios.version", dmi, 0x05); + smbios_setenv("hint.smbios.0.bios.reldate", dmi, 0x08); + break; + + case 1: /* Type 1: System */ + smbios_setenv("hint.smbios.0.system.maker", dmi, 0x04); + smbios_setenv("hint.smbios.0.system.product", dmi, 0x05); + smbios_setenv("hint.smbios.0.system.version", dmi, 0x06); + break; + + case 2: /* Type 2: Base Board (or Module) */ + smbios_setenv("hint.smbios.0.planar.maker", dmi, 0x04); + smbios_setenv("hint.smbios.0.planar.product", dmi, 0x05); + smbios_setenv("hint.smbios.0.planar.version", dmi, 0x06); + break; + + case 3: /* Type 3: System Enclosure or Chassis */ + smbios_setenv("hint.smbios.0.chassis.maker", dmi, 0x04); + smbios_setenv("hint.smbios.0.chassis.version", dmi, 0x06); + break; + + default: /* skip other types */ + break; + } + + /* find structure terminator */ + dp = (u_int8_t *)(dmi + dmi[1]); + while (dp[0] != 0 || dp[1] != 0) + dp++; + + return(dp + 2); +} + +static void +smbios_setenv(const char *str, const u_int8_t *dmi, const int offset) +{ + char *cp; + int i; + + /* skip undefined string */ + if (dmi[offset] == 0) + return; + + for (cp = (char *)(dmi + dmi[1]), i = 0; i < dmi[offset] - 1; i++) + cp += strlen(cp) + 1; + setenv(str, cp, 1); +} + +static u_int8_t +smbios_checksum(const u_int8_t *addr, const u_int8_t len) +{ + u_int8_t sum; + int i; + + for (sum = 0, i = 0; i < len; i++) + sum += addr[i]; + + return(sum); +} + +static u_int8_t * +smbios_sigsearch(const caddr_t addr, const u_int32_t len) +{ + caddr_t cp; + + /* search on 16-byte boundaries */ + for (cp = addr; cp - addr < len; cp += SMBIOS_STEP) { + /* compare signature, validate checksum */ + if (!strncmp(cp, SMBIOS_SIG, 4)) { + if (smbios_checksum(cp, *(cp + 0x05))) + continue; + if (strncmp(cp + 0x10, SMBIOS_DMI_SIG, 5)) + continue; + if (smbios_checksum(cp + 0x10, 0x0f)) + continue; + + return(cp); + } + } + + return(NULL); +} diff --git a/sys/boot/i386/loader/main.c b/sys/boot/i386/loader/main.c index 1e2f568..d8e61aa 100644 --- a/sys/boot/i386/loader/main.c +++ b/sys/boot/i386/loader/main.c @@ -144,6 +144,9 @@ main(void) /* detect ACPI for future reference */ biosacpi_detect(); + /* detect SMBIOS for future reference */ + smbios_detect(); + printf("\n"); printf("%s, Revision %s\n", bootprog_name, bootprog_rev); printf("(%s, %s)\n", bootprog_maker, bootprog_date); |