| /*-␊ |
| * Copyright (c) 2005-2009 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.␊ |
| */␊ |
| ␊ |
| /*␊ |
| * Detect SMBIOS and export information about the SMBIOS into the␊ |
| * environment.␊ |
| *␊ |
| * System Management BIOS Reference Specification, v2.6 Final␊ |
| * http://www.dmtf.org/standards/published_documents/DSP0134_2.6.0.pdf␊ |
| */␊ |
| ␊ |
| /*␊ |
| * 2.1.1 SMBIOS Structure Table Entry Point␊ |
| *␊ |
| * "On non-EFI systems, 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. This entry point encapsulates an intermediate anchor␊ |
| * string that is used by some existing DMI browsers."␊ |
| */␊ |
| ␊ |
| #include "libsaio.h"␊ |
| #include "SMBIOS.h"␊ |
| #include "Platform.h"␊ |
| ␊ |
| static const char * const SMTAG = "_SM_";␊ |
| static const char* const DMITAG= "_DMI_";␊ |
| static struct SMBEntryPoint *getAddressOfSmbiosTable(void);␊ |
| #define SMBIOS_START 0xf0000␊ |
| #define SMBIOS_LENGTH 0x10000␊ |
| #define SMBIOS_STEP 0x10␊ |
| #define SMBIOS_SIG "_SM_"␊ |
| #define SMBIOS_DMI_SIG "_DMI_"␊ |
| ␊ |
| static struct SMBEntryPoint *getAddressOfSmbiosTable(void)␊ |
| #define SMBIOS_GET8(base, off) (*(uint8_t *)((base) + (off)))␊ |
| #define SMBIOS_GET16(base, off) (*(uint16_t *)((base) + (off)))␊ |
| #define SMBIOS_GET32(base, off) (*(uint32_t *)((base) + (off)))␊ |
| ␊ |
| #define SMBIOS_GETLEN(base) SMBIOS_GET8(base, 0x01)␊ |
| #define SMBIOS_GETSTR(base) ((base) + SMBIOS_GETLEN(base))␊ |
| ␊ |
| typedef char* caddr_t;␊ |
| ␊ |
| static uint8_t␊ |
| smbios_checksum(const caddr_t addr, const uint8_t len)␊ |
| {␊ |
| ␉struct SMBEntryPoint␉*smbios;␊ |
| ␉/* ␊ |
| ␉ * The logic is to start at 0xf0000 and end at 0xfffff iterating 16 bytes at a time looking␊ |
| ␉ * for the SMBIOS entry-point structure anchor (literal ASCII "_SM_").␊ |
| ␉ */␊ |
| ␉smbios = (struct SMBEntryPoint*) SMBIOS_RANGE_START;␊ |
| ␉while (smbios <= (struct SMBEntryPoint *)SMBIOS_RANGE_END)␊ |
| ␉{␊ |
| ␉␉if (COMPARE_DWORD(smbios->anchor, SMTAG) && ␊ |
| ␉␉␉COMPARE_DWORD(smbios->dmi.anchor, DMITAG) &&␊ |
| ␉␉␉smbios->dmi.anchor[4]==DMITAG[4] &&␊ |
| ␉␉␉checksum8(smbios, sizeof(struct SMBEntryPoint)) == 0)␊ |
| ␉ {␉␉␉␊ |
| ␉␉␉return ((void*)smbios);␊ |
| ␉ }␊ |
| ␉␉smbios = (struct SMBEntryPoint*) ( ((char*) smbios) + 16 );␊ |
| ␉}␊ |
| ␉printf("Error: Could not find original SMBIOS !!\n");␊ |
| ␉pause();␊ |
| ␉return NULL;␊ |
| ␉uint8_t sum;␊ |
| ␉int i;␊ |
| ␉␊ |
| ␉for (sum = 0, i = 0; i < len; i++)␊ |
| ␉␉sum += SMBIOS_GET8(addr, i);␊ |
| ␉return (sum);␊ |
| }␊ |
| ␊ |
| static caddr_t␊ |
| smbios_sigsearch(const caddr_t addr, const uint32_t len)␊ |
| {␊ |
| ␉caddr_t cp;␊ |
| ␉␊ |
| ␉/* Search on 16-byte boundaries. */␊ |
| ␉for (cp = addr; cp < addr + len; cp += SMBIOS_STEP)␊ |
| ␉␉if (strncmp(cp, SMBIOS_SIG, 4) == 0 &&␊ |
| ␉␉␉smbios_checksum(cp, SMBIOS_GET8(cp, 0x05)) == 0 &&␊ |
| ␉␉␉strncmp(cp + 0x10, SMBIOS_DMI_SIG, 5) == 0 &&␊ |
| ␉␉␉smbios_checksum(cp + 0x10, 0x0f) == 0)␊ |
| ␉␉␉return (cp);␊ |
| ␉return (NULL);␊ |
| }␊ |
| ␊ |
| struct SMBEntryPoint *getSmbiosOriginal()␊ |
| { ␉␊ |
| static struct SMBEntryPoint *orig = NULL; // cached␊ |
| static caddr_t smbios = NULL; // cached␊ |
| ␊ |
| if (orig == NULL)␊ |
| if (smbios == NULL)␊ |
| ␉{␊ |
| ␉␉orig = getAddressOfSmbiosTable();␉␉␊ |
| ␉␉/* Search signatures and validate checksums. */␊ |
| ␉␉smbios = smbios_sigsearch((caddr_t)ptov(SMBIOS_START), SMBIOS_LENGTH);␊ |
| ␉␉␊ |
| ␉␉if (orig)␊ |
| ␉␉if (smbios)␊ |
| ␉␉{␊ |
| ␉␉␉verbose("Found System Management BIOS (SMBIOS) table\n");␉␉␉␊ |
| ␉␉}␊ |
| ␊ |
| }␊ |
| return orig; ␊ |
| return (struct SMBEntryPoint *)smbios; ␊ |
| }␊ |
| ␊ |
| /* get product Name from original SMBIOS */␊ |