Chameleon

Chameleon Svn Source Tree

Root/branches/cparm/i386/libsaio/smbios.c

1/*-
2 * Copyright (c) 2005-2009 Jung-uk Kim <jkim@FreeBSD.org>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 */
26
27/*
28 * Detect SMBIOS and export information about the SMBIOS into the
29 * environment.
30 *
31 * System Management BIOS Reference Specification, v2.6 Final
32 * http://www.dmtf.org/standards/published_documents/DSP0134_2.6.0.pdf
33 */
34
35/*
36 * 2.1.1 SMBIOS Structure Table Entry Point
37 *
38 * "On non-EFI systems, the SMBIOS Entry Point structure, described below, can
39 * be located by application software by searching for the anchor-string on
40 * paragraph (16-byte) boundaries within the physical memory address range
41 * 000F0000h to 000FFFFFh. This entry point encapsulates an intermediate anchor
42 * string that is used by some existing DMI browsers."
43 */
44
45#include "libsaio.h"
46#include "SMBIOS.h"
47#include "Platform.h"
48
49#define SMBIOS_START 0xf0000
50#define SMBIOS_LENGTH 0x10000
51#define SMBIOS_STEP 0x10
52#define SMBIOS_SIG "_SM_"
53#define SMBIOS_DMI_SIG "_DMI_"
54
55#define SMBIOS_GET8(base, off) (*(uint8_t *)((base) + (off)))
56#define SMBIOS_GET16(base, off) (*(uint16_t *)((base) + (off)))
57#define SMBIOS_GET32(base, off) (*(uint32_t *)((base) + (off)))
58
59#define SMBIOS_GETLEN(base) SMBIOS_GET8(base, 0x01)
60#define SMBIOS_GETSTR(base) ((base) + SMBIOS_GETLEN(base))
61
62static uint8_t
63smbios_checksum(const caddr_t addr, const uint8_t len)
64{
65uint8_t sum;
66int i;
67
68for (sum = 0, i = 0; i < len; i++)
69sum += SMBIOS_GET8(addr, i);
70return (sum);
71}
72
73static caddr_t
74smbios_sigsearch(const caddr_t addr, const uint32_t len)
75{
76caddr_t cp;
77
78/* Search on 16-byte boundaries. */
79for (cp = addr; cp < addr + len; cp += SMBIOS_STEP)
80if (strncmp(cp, SMBIOS_SIG, 4) == 0 &&
81smbios_checksum(cp, SMBIOS_GET8(cp, 0x05)) == 0 &&
82strncmp(cp + 0x10, SMBIOS_DMI_SIG, 5) == 0 &&
83smbios_checksum(cp + 0x10, 0x0f) == 0)
84return (cp);
85return (NULL);
86}
87
88struct SMBEntryPoint *getSmbiosOriginal()
89{
90 static caddr_t smbios = NULL; // cached
91
92 if (smbios == NULL)
93{
94/* Search signatures and validate checksums. */
95smbios = smbios_sigsearch((caddr_t)ptov(SMBIOS_START), SMBIOS_LENGTH);
96
97if (smbios)
98{
99verbose("Found System Management BIOS (SMBIOS) table\n");
100}
101
102 }
103 return (struct SMBEntryPoint *)smbios;
104}
105
106/* get product Name from original SMBIOS */
107char* readDefaultPlatformName(void)
108{
109
110SMBEntryPoint *eps = getSmbiosOriginal();
111if (eps == NULL) return NULL;
112
113uint8_t *structPtr = (uint8_t *)eps->dmi.tableAddress;
114SMBStructHeader *structHeader = (SMBStructHeader *)structPtr;
115
116for (;((eps->dmi.tableAddress + eps->dmi.tableLength) > ((uint32_t)(uint8_t *)structHeader + sizeof(SMBStructHeader)));)
117{
118switch (structHeader->type)
119{
120case kSMBTypeSystemInformation:
121{
122uint8_t *stringPtr = (uint8_t *)structHeader + structHeader->length;
123uint8_t field = ((SMBSystemInformation *)structHeader)->productName;
124
125if (!field)
126return NULL;
127
128for (field--; field != 0 && strlen((char *)stringPtr) > 0;
129 field--, stringPtr = (uint8_t *)((uint32_t)stringPtr + strlen((char *)stringPtr) + 1));
130
131//DBG("original SMBIOS Product name: %s\n",(char *)stringPtr);
132if (stringPtr)
133return (char *)stringPtr;
134else
135return NULL;
136
137break;
138}
139default:
140break;
141
142}
143
144structPtr = (uint8_t *)((uint32_t)structHeader + structHeader->length);
145for (; ((uint16_t *)structPtr)[0] != 0; structPtr++);
146
147if (((uint16_t *)structPtr)[0] == 0)
148structPtr += 2;
149
150structHeader = (SMBStructHeader *)structPtr;
151}
152return NULL;
153}
154
155/* get UUID or product Name from original SMBIOS, stripped version of kabyl's readSMBIOSInfo */
156int readSMBIOS(int value)
157{
158
159SMBEntryPoint *eps = getSmbiosOriginal();
160if (eps == NULL) return 0;
161
162uint8_t *structPtr = (uint8_t *)eps->dmi.tableAddress;
163SMBStructHeader *structHeader = (SMBStructHeader *)structPtr;
164
165for (;((eps->dmi.tableAddress + eps->dmi.tableLength) > ((uint32_t)(uint8_t *)structHeader + sizeof(SMBStructHeader)));)
166{
167switch (structHeader->type)
168{
169case kSMBTypeSystemInformation:
170{
171switch (value) {
172case theUUID:
173 safe_set_env(envUUID,(uint32_t)((SMBSystemInformation *)structHeader)->uuid);
174return 1;
175break;
176case thePlatformName:
177{
178uint8_t *stringPtr = (uint8_t *)structHeader + structHeader->length;
179uint8_t field = ((SMBSystemInformation *)structHeader)->productName;
180
181if (!field)
182return 0;
183
184for (field--; field != 0 && strlen((char *)stringPtr) > 0;
185 field--, stringPtr = (uint8_t *)((uint32_t)stringPtr + strlen((char *)stringPtr) + 1)){};
186
187//DBG("original SMBIOS Product name: %s\n",(char *)stringPtr);
188 SetgPlatformName((char *)stringPtr);
189if (GetgPlatformName()) return 1;
190break;
191}
192default:
193break;
194}
195
196break;
197}
198case kSMBTypeBaseBoard:
199 {
200switch (value) {
201case theProducBoard:
202{
203uint8_t *stringPtr = (uint8_t *)structHeader + structHeader->length;
204uint8_t field = ((SMBBaseBoard *)structHeader)->product;
205
206if (!field)
207return 0;
208
209for (field--; field != 0 && strlen((char *)stringPtr) > 0;
210 field--, stringPtr = (uint8_t *)((uint32_t)stringPtr + strlen((char *)stringPtr) + 1));
211
212Setgboardproduct((char *)stringPtr);
213if (Getgboardproduct()) return 1;
214break;
215}
216default:
217break;
218}
219break;
220 }
221default:
222break;
223
224}
225
226structPtr = (uint8_t *)((uint32_t)structHeader + structHeader->length);
227for (; ((uint16_t *)structPtr)[0] != 0; structPtr++);
228
229if (((uint16_t *)structPtr)[0] == 0)
230structPtr += 2;
231
232structHeader = (SMBStructHeader *)structPtr;
233}
234return 0;
235}

Archive Download this file

Revision: 2182