Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 23 May 2005 12:26:18 -0400
From:      Jung-uk Kim <jkim@niksun.com>
To:        John Baldwin <jhb@FreeBSD.org>
Cc:        "Matthew N. Dodd" <winter@jurai.net>, David O'Brien <obrien@FreeBSD.org>, freebsd-amd64@FreeBSD.org
Subject:   [PATCH] SMBIOS scan for loader (Was: Re: R3000Z Laptop Status)
Message-ID:  <200505231226.18856.jkim@niksun.com>
In-Reply-To: <200503211440.21752.jhb@FreeBSD.org>
References:  <2fd864e05032105366eaf8b2c@mail.gmail.com> <200503211411.58425.jkim@niksun.com> <200503211440.21752.jhb@FreeBSD.org>

next in thread | previous in thread | raw e-mail | index | archive | help

--Boundary-00=_qQgkC9ldWlyB+M7
Content-Type: text/plain;
  charset="iso-8859-1"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline

On Monday 21 March 2005 02:40 pm, John Baldwin wrote:
> On Monday 21 March 2005 02:11 pm, Jung-uk Kim wrote:
> > On Monday 21 March 2005 01:28 pm, Scott Long wrote:
> > > Astrodog wrote:
> > > >>>>>>>I was wondering if the R3000Z fixes have been committed
> > > >>>>>>> to the RELENG_5 branch, I don't see anything on the
> > > >>>>>>> lists about it. Should I expect 5.4 to work with the
> > > >>>>>>> R3000 line?
> > > >>>>>>
> > > >>>>>>Yes.  hint.atkbd.0.flags="0x9" is all you need now.  Try
> > > >>>>>> the latest snapshot and let us know.
> > > >>>>>>
> > > >>>>>>Thanks,
> > > >>>>>>
> > > >>>>>>Jung-uk Kim
> > > >>>>>
> > > >>>>>Is there any way that these systems can be detected at
> > > >>>>> runtime and have the work-arounds be automatically
> > > >>>>> activated?
> > > >>>>
> > > >>>>I believe DMI-based quirk table is the only way but we
> > > >>>> don't want to do that, right?
> > > >>>>
> > > >>>>Jung-uk Kim
> > > >>>>
> > > >>>>>Scott
> > > >>>
> > > >>>Well, it's gross, but it's not impossible to do.  Is there a
> > > >>>technical reason why we wouldn't want this?
> > > >>
> > > >>The only technical reason that I can think of is some systems
> > > >> (e. g., IBM e345 and e346 Opteron servers) have DMI
> > > >> structures in ACPI NVS area, which is not accessible from
> > > >> early stage.  If you want to do something like that, you
> > > >> will have to add gross hack in pmap.c to temporarily map it,
> > > >> I think.
> > > >>
> > > >>>Are there any alternatives, like detecting a signature in
> > > >>> ACPI, either a text string or a certain bit of ASL
> > > >>> bytecode?
> > > >>
> > > >>We already have the quirk for this broken BIOS.  However,
> > > >> keyboard probing happens way earlier to use this quirk. :-(
> > > >>
> > > >>Jung-uk Kim
> > > >>
> > > >>>Scott
> > > >
> > > > Something that came up originally, when this issue was first
> > > > noticed, was trying to figure out what, if any platforms,
> > > > would have problems if this was made to apply to all AMD64
> > > > machines, and use the flag to drive an opt-out. In as far as
> > > > I'm aware, no AMD64-based machines are effected if you just
> > > > "break" the keyboard test functionality, though I'm not
> > > > certain this is a path worth looking at, since its still a
> > > > bit ugly.
> > >
> > > My number 1 concern is that 5.4-RELEASE 'Just Works' when you
> > > load it onto a machine.  Undocumented and under-documented
> > > work-arounds are very hard to manage and don't help users that
> > > aren't intimately familiar with the problem.  This is a place
> > > where ("Alert!  Don the asbestos skivvies now!") adding an
> > > option to ("I'm warning you! Prepare for flamage!") beastie.4th
> > > might be a good idea.
> >
> > One possibility is adding DMI scan code in loader and passing
> > BIOS ID strings to kernel because loader can easily call BIOS
> > function calls. This won't require ugly hack in kernel space.
>
> I like this approach better.  We already provide hints to ACPI via
> the loader.

I had some time last week and wrote the patch.  This patch exports 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

If you think the information is excessive, you can comment them out.  
You can change the variable names if you don't like them. ;-)

Cheers,

Jung-uk Kim

* Postscript: Matthew,

http://www.freebsd.org/cgi/cvsweb.cgi/src/sys/i386/bios/smbios.c

has the wrong SMBIOS EPS structure.  According to 'System Management 
BIOS Reference Specification, v2.4 Final 
(http://www.dmtf.org/standards/published_documents/DSP0134.pdf)' page 
13-14, correct structure is something like this:

/*
 * SMBIOS Entry Point Structure
 */
struct smbios_eps {
	u_int8_t	Anchor[4];		/* '_SM_' */
	u_int8_t	Checksum;
	u_int8_t	Length;

	u_int8_t	SMBIOS_Major;
	u_int8_t	SMBIOS_Minor;
	u_int16_t	Max_Size;
	u_int8_t	Revision;
	u_int8_t	Formatted_Area[5];

	u_int8_t	Intermediate_Anchor[5];	/* '_DMI_' */
	u_int8_t	Intermediate_Checksum;

	u_int16_t	Structure_Table_Length;
	u_int32_t	Structure_Table_Address;
	u_int16_t	Structure_Count;

	u_int8_t	SMBIOS_BCD_Revision;
} __packed;

Just FYI...

--Boundary-00=_qQgkC9ldWlyB+M7
Content-Type: text/x-diff;
  charset="iso-8859-1";
  name="smbios.diff"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
	filename="smbios.diff"

Index: src/sys/boot/i386/libi386/Makefile
===================================================================
RCS file: /home/ncvs/src/sys/boot/i386/libi386/Makefile,v
retrieving revision 1.37
diff -u -r1.37 Makefile
--- src/sys/boot/i386/libi386/Makefile	24 Oct 2004 15:32:49 -0000	1.37
+++ src/sys/boot/i386/libi386/Makefile	23 May 2005 15:39:03 -0000
@@ -8,7 +8,7 @@
 	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}
Index: src/sys/boot/i386/libi386/libi386.h
===================================================================
RCS file: /home/ncvs/src/sys/boot/i386/libi386/libi386.h,v
retrieving revision 1.19
diff -u -r1.19 libi386.h
--- src/sys/boot/i386/libi386/libi386.h	22 Oct 2004 14:56:23 -0000	1.19
+++ src/sys/boot/i386/libi386/libi386.h	23 May 2005 15:39:03 -0000
@@ -99,6 +99,8 @@
 
 void	biosacpi_detect();
 
+void	smbios_detect();
+
 void	gateA20(void);
 
 int	i386_autoload(void);
--- src/sys/boot/i386/libi386/smbios.c	Mon May 23 11:38:29 2005
+++ src/sys/boot/i386/libi386/smbios.c	Fri May 20 21:50:45 2005
@@ -0,0 +1,176 @@
+/*-
+ * Copyright (c) 2005 Jung-uk Kim <jkim@niksun.com>
+ * 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 == 0)
+		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(0);
+}
Index: src/sys/boot/i386/loader/main.c
===================================================================
RCS file: /home/ncvs/src/sys/boot/i386/loader/main.c,v
retrieving revision 1.30
diff -u -r1.30 main.c
--- src/sys/boot/i386/loader/main.c	22 Oct 2004 14:57:28 -0000	1.30
+++ src/sys/boot/i386/loader/main.c	23 May 2005 15:39:04 -0000
@@ -140,6 +140,9 @@
     /* 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);

--Boundary-00=_qQgkC9ldWlyB+M7--



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200505231226.18856.jkim>