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