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 | ␊ |
62 | typedef char* caddr_t;␊ |
63 | ␊ |
64 | static uint8_t␊ |
65 | smbios_checksum(const caddr_t addr, const uint8_t len)␊ |
66 | {␊ |
67 | ␉uint8_t sum;␊ |
68 | ␉int i;␊ |
69 | ␉␊ |
70 | ␉for (sum = 0, i = 0; i < len; i++)␊ |
71 | ␉␉sum += SMBIOS_GET8(addr, i);␊ |
72 | ␉return (sum);␊ |
73 | }␊ |
74 | ␊ |
75 | static caddr_t␊ |
76 | smbios_sigsearch(const caddr_t addr, const uint32_t len)␊ |
77 | {␊ |
78 | ␉caddr_t cp;␊ |
79 | ␉␊ |
80 | ␉/* Search on 16-byte boundaries. */␊ |
81 | ␉for (cp = addr; cp < addr + len; cp += SMBIOS_STEP)␊ |
82 | ␉␉if (strncmp(cp, SMBIOS_SIG, 4) == 0 &&␊ |
83 | ␉␉␉smbios_checksum(cp, SMBIOS_GET8(cp, 0x05)) == 0 &&␊ |
84 | ␉␉␉strncmp(cp + 0x10, SMBIOS_DMI_SIG, 5) == 0 &&␊ |
85 | ␉␉␉smbios_checksum(cp + 0x10, 0x0f) == 0)␊ |
86 | ␉␉␉return (cp);␊ |
87 | ␉return (NULL);␊ |
88 | }␊ |
89 | ␊ |
90 | struct SMBEntryPoint *getSmbiosOriginal()␊ |
91 | { ␉␊ |
92 | static caddr_t smbios = NULL; // cached␊ |
93 | ␊ |
94 | if (smbios == NULL)␊ |
95 | ␉{␊ |
96 | ␉␉/* Search signatures and validate checksums. */␊ |
97 | ␉␉smbios = smbios_sigsearch((caddr_t)ptov(SMBIOS_START), SMBIOS_LENGTH);␊ |
98 | ␉␉␊ |
99 | ␉␉if (smbios)␊ |
100 | ␉␉{␊ |
101 | ␉␉␉verbose("Found System Management BIOS (SMBIOS) table\n");␉␉␉␊ |
102 | ␉␉}␊ |
103 | ␊ |
104 | }␊ |
105 | return (struct SMBEntryPoint *)smbios; ␊ |
106 | }␊ |
107 | ␊ |
108 | /* get product Name from original SMBIOS */␊ |
109 | char* readDefaultPlatformName(void)␊ |
110 | {␉␉␉␊ |
111 | ␉␊ |
112 | ␉SMBEntryPoint *eps = getSmbiosOriginal();␊ |
113 | ␉if (eps == NULL) return NULL;␊ |
114 | ␉␊ |
115 | ␉uint8_t *structPtr = (uint8_t *)eps->dmi.tableAddress;␊ |
116 | ␉SMBStructHeader *structHeader = (SMBStructHeader *)structPtr;␊ |
117 | ␉␊ |
118 | ␉for (;((eps->dmi.tableAddress + eps->dmi.tableLength) > ((uint32_t)(uint8_t *)structHeader + sizeof(SMBStructHeader)));)␊ |
119 | ␉{␊ |
120 | ␉␉switch (structHeader->type)␊ |
121 | ␉␉{␉␉␉␉␊ |
122 | ␉␉␉case kSMBTypeSystemInformation: ␊ |
123 | ␉␉␉{␊ |
124 | ␉␉␉␉uint8_t *stringPtr = (uint8_t *)structHeader + structHeader->length;␊ |
125 | ␉␉␉␉uint8_t field = ((SMBSystemInformation *)structHeader)->productName;␊ |
126 | ␉␉␉␉␊ |
127 | ␉␉␉␉if (!field)␊ |
128 | ␉␉␉␉␉return NULL;␊ |
129 | ␉␉␉␉␊ |
130 | ␉␉␉␉for (field--; field != 0 && strlen((char *)stringPtr) > 0; ␊ |
131 | ␉␉␉␉␉ field--, stringPtr = (uint8_t *)((uint32_t)stringPtr + strlen((char *)stringPtr) + 1));␊ |
132 | ␉␉␉␉␊ |
133 | ␉␉␉␉//DBG("original SMBIOS Product name: %s\n",(char *)stringPtr);␊ |
134 | ␉␉␉␉if (stringPtr)␊ |
135 | ␉␉␉␉␉return (char *)stringPtr;␊ |
136 | ␉␉␉␉else ␊ |
137 | ␉␉␉␉␉return NULL;␉␉␉␊ |
138 | ␉␉␉␉␊ |
139 | ␉␉␉␉break;␉␊ |
140 | ␉␉␉}␉␉␉␊ |
141 | ␉␉␉default:␊ |
142 | ␉␉␉␉break;␊ |
143 | ␉␉␉␉␊ |
144 | ␉␉}␊ |
145 | ␉␉␊ |
146 | ␉␉structPtr = (uint8_t *)((uint32_t)structHeader + structHeader->length);␊ |
147 | ␉␉for (; ((uint16_t *)structPtr)[0] != 0; structPtr++);␊ |
148 | ␉␉␊ |
149 | ␉␉if (((uint16_t *)structPtr)[0] == 0)␊ |
150 | ␉␉␉structPtr += 2;␊ |
151 | ␉␉␊ |
152 | ␉␉structHeader = (SMBStructHeader *)structPtr;␊ |
153 | ␉}␉␊ |
154 | ␉return NULL;␊ |
155 | }␊ |
156 | ␊ |
157 | /* get UUID or product Name from original SMBIOS, stripped version of kabyl's readSMBIOSInfo */␊ |
158 | int readSMBIOS(int value)␊ |
159 | {␉␉␉␊ |
160 | ␉␊ |
161 | ␉SMBEntryPoint *eps = getSmbiosOriginal();␊ |
162 | ␉if (eps == NULL) return 0;␊ |
163 | ␉␊ |
164 | ␉uint8_t *structPtr = (uint8_t *)eps->dmi.tableAddress;␊ |
165 | ␉SMBStructHeader *structHeader = (SMBStructHeader *)structPtr;␊ |
166 | ␉␊ |
167 | ␉for (;((eps->dmi.tableAddress + eps->dmi.tableLength) > ((uint32_t)(uint8_t *)structHeader + sizeof(SMBStructHeader)));)␊ |
168 | ␉{␊ |
169 | ␉␉switch (structHeader->type)␊ |
170 | ␉␉{␉␉␉␉␊ |
171 | ␉␉␉case kSMBTypeSystemInformation: ␊ |
172 | ␉␉␉{␊ |
173 | ␉␉␉␉switch (value) {␊ |
174 | ␉␉␉␉␉case theUUID:␊ |
175 | safe_set_env(envUUID,(uint32_t)((SMBSystemInformation *)structHeader)->uuid);␉␉␉␉␉␊ |
176 | ␉␉␉␉␉␉return 1;␊ |
177 | ␉␉␉␉␉␉break;␊ |
178 | ␉␉␉␉␉case thePlatformName:␊ |
179 | ␉␉␉␉␉{␊ |
180 | ␉␉␉␉␉␉uint8_t *stringPtr = (uint8_t *)structHeader + structHeader->length;␊ |
181 | ␉␉␉␉␉␉uint8_t field = ((SMBSystemInformation *)structHeader)->productName;␊ |
182 | ␉␉␉␉␉␉␊ |
183 | ␉␉␉␉␉␉if (!field)␊ |
184 | ␉␉␉␉␉␉␉return 0;␊ |
185 | ␉␉␉␉␉␉␊ |
186 | ␉␉␉␉␉␉for (field--; field != 0 && strlen((char *)stringPtr) > 0; ␊ |
187 | ␉␉␉␉␉␉␉ field--, stringPtr = (uint8_t *)((uint32_t)stringPtr + strlen((char *)stringPtr) + 1));␊ |
188 | ␉␉␉␉␉␉␊ |
189 | ␉␉␉␉␉␉//DBG("original SMBIOS Product name: %s\n",(char *)stringPtr);␊ |
190 | SetgPlatformName((char *)stringPtr);␊ |
191 | ␉␉␉␉␉␉if (GetgPlatformName()) return 1;␊ |
192 | ␉␉␉␉␉␉break;␊ |
193 | ␉␉␉␉␉}␊ |
194 | ␉␉␉␉␉default:␊ |
195 | ␉␉␉␉␉␉break;␊ |
196 | ␉␉␉␉}␉␉␉␉␊ |
197 | ␉␉␉␉␊ |
198 | ␉␉␉␉break;␉␊ |
199 | ␉␉␉}␊ |
200 | ␉␉␉case kSMBTypeBaseBoard:␊ |
201 | {␊ |
202 | ␉␉␉␉switch (value) {␊ |
203 | ␉␉␉␉␉case theProducBoard:␊ |
204 | ␉␉␉␉␉{␊ |
205 | ␉␉␉␉␉␉uint8_t *stringPtr = (uint8_t *)structHeader + structHeader->length;␊ |
206 | ␉␉␉␉␉␉uint8_t field = ((SMBBaseBoard *)structHeader)->product;␊ |
207 | ␉␉␉␉␉␉␊ |
208 | ␉␉␉␉␉␉if (!field)␊ |
209 | ␉␉␉␉␉␉␉return 0;␊ |
210 | ␉␉␉␉␉␉␊ |
211 | ␉␉␉␉␉␉for (field--; field != 0 && strlen((char *)stringPtr) > 0; ␊ |
212 | ␉␉␉␉␉␉␉ field--, stringPtr = (uint8_t *)((uint32_t)stringPtr + strlen((char *)stringPtr) + 1));␊ |
213 | ␉␉␉␉␉␉␊ |
214 | ␉␉␉␉␉␉Setgboardproduct((char *)stringPtr);␊ |
215 | ␉␉␉␉␉␉if (Getgboardproduct()) return 1;␊ |
216 | ␉␉␉␉␉␉break;␊ |
217 | ␉␉␉␉␉}␊ |
218 | ␉␉␉␉␉default:␊ |
219 | ␉␉␉␉␉␉break;␊ |
220 | ␉␉␉␉}␊ |
221 | ␉␉␉␉break;␊ |
222 | }␊ |
223 | ␉␉␉default:␊ |
224 | ␉␉␉␉break;␊ |
225 | ␉␉␉␉␊ |
226 | ␉␉}␊ |
227 | ␉␉␊ |
228 | ␉␉structPtr = (uint8_t *)((uint32_t)structHeader + structHeader->length);␊ |
229 | ␉␉for (; ((uint16_t *)structPtr)[0] != 0; structPtr++);␊ |
230 | ␉␉␊ |
231 | ␉␉if (((uint16_t *)structPtr)[0] == 0)␊ |
232 | ␉␉␉structPtr += 2;␊ |
233 | ␉␉␊ |
234 | ␉␉structHeader = (SMBStructHeader *)structPtr;␊ |
235 | ␉}␉␊ |
236 | ␉return 0;␊ |
237 | } |