BTX problems

Jung-uk Kim jkim at FreeBSD.org
Mon Aug 22 17:19:52 GMT 2005


On Monday 22 August 2005 12:33 pm, Kenneth D. Merry wrote:
> On Mon, Aug 22, 2005 at 12:16:51 -0400, Jung-uk Kim wrote:
> > On Monday 22 August 2005 11:57 am, Kenneth D. Merry wrote:
> > > On Mon, Aug 22, 2005 at 11:37:25 -0400, Jung-uk Kim wrote:
> > > > On Saturday 20 August 2005 01:02 am, Kenneth D. Merry wrote:
> > > > > On Tue, Aug 16, 2005 at 13:39:48 -0400, John Baldwin wrote:
> > > > > > There haven't been a whole lot of changes.  My guess
> > > > > > would be the recently added smbios support.  You can
> > > > > > probably just comment out the call to smbios_detect() in
> > > > > > sys/boot/i386/loader/main.c as a simple test for that. 
> > > > > > It could also possibly be the multiple console support in
> > > > > > which case it would be easiest to just step your sys/boot
> > > > > > tree back using CVS.  The good news is that sys/boot is
> > > > > > largely self-contained so you can step it back while
> > > > > > keeping the rest of the tree up to date for testing
> > > > > > purposes at least.
> > > > >
> > > > > Thanks for the tips!
> > > > >
> > > > > Commenting out smbios_detect() did the trick.  The loader
> > > > > works fine after that.
> > > > >
> > > > > So now what?  Is there a way to fix it so it won't crash on
> > > > > my system?
> > > >
> > > > So, I guess I broke it, then.  Can you install
> > > > ports/sysutils/dmidecode and send me dmidecode output?
> > >
> > > Sure, here it is.
> >
> > Okay, it looks good so far.  Can you do:
> >
> > dd if=/dev/mem of=dmi.dat bs=1 count=1534 skip=984640
> > dd if=/dev/mem of=smbios.dat bs=1 count=65536 skip=983040
> >
> > and send me dmi.dat and smbios.dat, please?
>
> Here they are.

It's very strange.  It seems SM entry and DMI structures are all sane.  
I don't understand why it happens. :-( I just wrote a qucik-and-dirty 
userland wrapper for smbios.c, which is attached.

SMBIOS entry: 0x000f00a0
DMI structures: length = 1534, paddr = 0x000f0640, count = 49
smbios.bios.vendor="American Megatrends Inc."
smbios.bios.version="0700xx "
smbios.bios.reldate="11/14/2001"
smbios.system.maker="Supermicro"
smbios.system.product="P3TDE6"
smbios.system.version="1234567890"
smbios.planar.maker="Supermicro"
smbios.planar.product="P3TDE6"
smbios.planar.version="1234567890"
smbios.chassis.maker="Supermicro"
smbios.chassis.version="P3TDE6"

Is it possible that PTOV() is not working somehow???  I need help 
here.

Thanks,

Jung-uk Kim
-------------- next part --------------
/*-
 * Copyright (c) 2005 Jung-uk Kim <jkim at 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.
 */

#if 0
#include <sys/cdefs.h>
__FBSDID("$FreeBSD: src/sys/boot/i386/libi386/smbios.c,v 1.2 2005/07/27 19:11:10 jkim Exp $");

#include <stand.h>
#include <bootstrap.h>

#include "btxv86.h"
#else
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#endif

/*
 * 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);

#if 0
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;

	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);
}
#else
int main(void)
{
	int		smfd = -1, dmifd = -1, err = 0;
	u_int8_t	*smbios = NULL, *dmi = NULL, *addr = NULL;
	u_int8_t	*smp = NULL, *dmip = NULL;
	u_int16_t	i, length, count;
	u_int32_t	paddr;

	smfd = open("smbios.dat", O_RDONLY);
	if (smfd < 0) {
		printf("cannot open smbios.dat\n");
		err = -1;
		goto done;
	}
	smbios = calloc(1, SMBIOS_LENGTH);
	if (!smbios) {
		printf("cannot allocate smbios buffer\n");
		err = -2;
		goto done;
	}
	if (read(smfd, smbios, SMBIOS_LENGTH) < SMBIOS_LENGTH) {
		printf("cannot read smbios.dat\n");
		err = -3;
		goto done;
	}
	close(smfd);
		
	/* locate and validate the SMBIOS */
	smp = smbios_sigsearch(smbios, SMBIOS_LENGTH);
	if (smp == NULL) {
		printf("SMBIOS not found\n");
		err = -4;
		goto done;
	} else {
		printf("SMBIOS entry: 0x%08x\n", (u_int32_t)(smp - smbios) +
									SMBIOS_START);

		length = *(u_int16_t *)(smp + 0x16);	/* Structure Table Length */
		paddr = *(u_int32_t *)(smp + 0x18);	/* Structure Table Address */
		count = *(u_int16_t *)(smp + 0x1c);	/* No of SMBIOS Structures */

		printf("DMI structures: length = %u, paddr = 0x%08x, count = %u\n",
			length, paddr, count);
	}

	dmifd = open("dmi.dat", O_RDONLY);
	if (dmifd < 0) {
		printf("cannot open dmi.dat\n");
		err = -5;
		goto done;
	}
	dmi = calloc(1, length);
	if (!dmi) {
		printf("cannot allocate dmi buffer\n");
		err = -6;
		goto done;
	}
	if (read(dmifd, dmi, length) < length) {
		printf("cannot read dmi.dat\n");
		err = -7;
		goto done;
	}
	close(dmifd);

	for (dmip = addr = dmi, i = 0; dmip - addr < length && i < count; i++)
		dmip = smbios_parse_table(dmip);

done:
	if (smfd >= 0)
		close(smfd);
	if (smbios)
		free(smbios);
	if (dmifd >= 0)
		close(dmifd);
	if (dmi)
		free(dmi);
	return (err);
}
#endif

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("smbios.bios.vendor", dmi, 0x04);
		smbios_setenv("smbios.bios.version", dmi, 0x05);
		smbios_setenv("smbios.bios.reldate", dmi, 0x08);
		break;

	case 1:		/* Type 1: System */
		smbios_setenv("smbios.system.maker", dmi, 0x04);
		smbios_setenv("smbios.system.product", dmi, 0x05);
		smbios_setenv("smbios.system.version", dmi, 0x06);
		break;

	case 2:		/* Type 2: Base Board (or Module) */
		smbios_setenv("smbios.planar.maker", dmi, 0x04);
		smbios_setenv("smbios.planar.product", dmi, 0x05);
		smbios_setenv("smbios.planar.version", dmi, 0x06);
		break;

	case 3:		/* Type 3: System Enclosure or Chassis */
		smbios_setenv("smbios.chassis.maker", dmi, 0x04);
		smbios_setenv("smbios.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;
#if 0
	setenv(str, cp, 1);
#else
	printf("%s=\"%s\"\n", str, cp);
#endif
}

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);
}


More information about the freebsd-current mailing list