arch-x86: Stop "using namespace std"
[gem5.git] / src / arch / x86 / bios / smbios.cc
1 /*
2 * Copyright (c) 2008 The Hewlett-Packard Development Company
3 * All rights reserved.
4 *
5 * The license below extends only to copyright in the software and shall
6 * not be construed as granting a license to any other intellectual
7 * property including but not limited to intellectual property relating
8 * to a hardware implementation of the functionality of the software
9 * licensed hereunder. You may use the software subject to the license
10 * terms below provided that you ensure that this notice is replicated
11 * unmodified and in its entirety in all distributions of the software,
12 * modified or unmodified, in source code or in binary form.
13 *
14 * Copyright (c) 2008 The Regents of The University of Michigan
15 * All rights reserved.
16 *
17 * Redistribution and use in source and binary forms, with or without
18 * modification, are permitted provided that the following conditions are
19 * met: redistributions of source code must retain the above copyright
20 * notice, this list of conditions and the following disclaimer;
21 * redistributions in binary form must reproduce the above copyright
22 * notice, this list of conditions and the following disclaimer in the
23 * documentation and/or other materials provided with the distribution;
24 * neither the name of the copyright holders nor the names of its
25 * contributors may be used to endorse or promote products derived from
26 * this software without specific prior written permission.
27 *
28 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
29 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
30 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
31 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
32 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
33 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
34 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
35 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
36 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
37 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
38 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
39 */
40
41 #include "arch/x86/bios/smbios.hh"
42
43 #include "arch/x86/isa_traits.hh"
44 #include "base/types.hh"
45 #include "mem/port_proxy.hh"
46 #include "params/X86SMBiosBiosInformation.hh"
47 #include "params/X86SMBiosSMBiosStructure.hh"
48 #include "params/X86SMBiosSMBiosTable.hh"
49 #include "sim/byteswap.hh"
50
51 const char X86ISA::SMBios::SMBiosTable::SMBiosHeader::anchorString[] = "_SM_";
52 const uint8_t X86ISA::SMBios::SMBiosTable::
53 SMBiosHeader::formattedArea[] = {0,0,0,0,0};
54 const uint8_t X86ISA::SMBios::SMBiosTable::
55 SMBiosHeader::entryPointLength = 0x1F;
56 const uint8_t X86ISA::SMBios::SMBiosTable::
57 SMBiosHeader::entryPointRevision = 0;
58 const char X86ISA::SMBios::SMBiosTable::
59 SMBiosHeader::IntermediateHeader::anchorString[] = "_DMI_";
60
61 template <class T>
62 uint64_t
63 composeBitVector(T vec)
64 {
65 uint64_t val = 0;
66 typename T::iterator vecIt;
67 for (vecIt = vec.begin(); vecIt != vec.end(); vecIt++) {
68 val |= (1 << (*vecIt));
69 }
70 return val;
71 }
72
73 uint16_t
74 X86ISA::SMBios::SMBiosStructure::writeOut(PortProxy& proxy, Addr addr)
75 {
76 proxy.writeBlob(addr, &type, 1);
77
78 uint8_t length = getLength();
79 proxy.writeBlob(addr + 1, &length, 1);
80
81 uint16_t handleGuest = htole(handle);
82 proxy.writeBlob(addr + 2, &handleGuest, 2);
83
84 return length + getStringLength();
85 }
86
87 X86ISA::SMBios::SMBiosStructure::SMBiosStructure(
88 const Params &p, uint8_t _type) :
89 SimObject(p), type(_type), handle(0), stringFields(false)
90 {}
91
92 void
93 X86ISA::SMBios::SMBiosStructure::writeOutStrings(
94 PortProxy& proxy, Addr addr)
95 {
96 std::vector<std::string>::iterator it;
97 Addr offset = 0;
98
99 const uint8_t nullTerminator = 0;
100
101 // If there are string fields but none of them are used, that's a
102 // special case which is handled by this if.
103 if (strings.size() == 0 && stringFields) {
104 proxy.writeBlob(addr + offset, &nullTerminator, 1);
105 offset++;
106 } else {
107 for (it = strings.begin(); it != strings.end(); it++) {
108 proxy.writeBlob(addr + offset, it->c_str(), it->length() + 1);
109 offset += it->length() + 1;
110 }
111 }
112 proxy.writeBlob(addr + offset, &nullTerminator, 1);
113 }
114
115 int
116 X86ISA::SMBios::SMBiosStructure::getStringLength()
117 {
118 int size = 0;
119 std::vector<std::string>::iterator it;
120
121 for (it = strings.begin(); it != strings.end(); it++) {
122 size += it->length() + 1;
123 }
124
125 return size + 1;
126 }
127
128 int
129 X86ISA::SMBios::SMBiosStructure::addString(const std::string &new_string)
130 {
131 stringFields = true;
132 // If a string is empty, treat it as not existing. The index for empty
133 // strings is 0.
134 if (new_string.length() == 0)
135 return 0;
136 strings.push_back(new_string);
137 return strings.size();
138 }
139
140 std::string
141 X86ISA::SMBios::SMBiosStructure::readString(int n)
142 {
143 assert(n > 0 && n <= strings.size());
144 return strings[n - 1];
145 }
146
147 void
148 X86ISA::SMBios::SMBiosStructure::setString(
149 int n, const std::string &new_string)
150 {
151 assert(n > 0 && n <= strings.size());
152 strings[n - 1] = new_string;
153 }
154
155 X86ISA::SMBios::BiosInformation::BiosInformation(const Params &p) :
156 SMBiosStructure(p, Type),
157 startingAddrSegment(p.starting_addr_segment),
158 romSize(p.rom_size),
159 majorVer(p.major), minorVer(p.minor),
160 embContFirmwareMajor(p.emb_cont_firmware_major),
161 embContFirmwareMinor(p.emb_cont_firmware_minor)
162 {
163 vendor = addString(p.vendor);
164 version = addString(p.version);
165 releaseDate = addString(p.release_date);
166
167 characteristics = composeBitVector(p.characteristics);
168 characteristicExtBytes =
169 composeBitVector(p.characteristic_ext_bytes);
170 }
171
172 uint16_t
173 X86ISA::SMBios::BiosInformation::writeOut(PortProxy& proxy, Addr addr)
174 {
175 uint8_t size = SMBiosStructure::writeOut(proxy, addr);
176
177 proxy.writeBlob(addr + 0x4, &vendor, 1);
178 proxy.writeBlob(addr + 0x5, &version, 1);
179
180 uint16_t startingAddrSegmentGuest = htole(startingAddrSegment);
181 proxy.writeBlob(addr + 0x6, &startingAddrSegmentGuest, 2);
182
183 proxy.writeBlob(addr + 0x8, &releaseDate, 1);
184 proxy.writeBlob(addr + 0x9, &romSize, 1);
185
186 uint64_t characteristicsGuest = htole(characteristics);
187 proxy.writeBlob(addr + 0xA, &characteristicsGuest, 8);
188
189 uint16_t characteristicExtBytesGuest =
190 htole(characteristicExtBytes);
191 proxy.writeBlob(addr + 0x12, &characteristicExtBytesGuest, 2);
192
193 proxy.writeBlob(addr + 0x14, &majorVer, 1);
194 proxy.writeBlob(addr + 0x15, &minorVer, 1);
195 proxy.writeBlob(addr + 0x16, &embContFirmwareMajor, 1);
196 proxy.writeBlob(addr + 0x17, &embContFirmwareMinor, 1);
197
198 writeOutStrings(proxy, addr + getLength());
199
200 return size;
201 }
202
203 X86ISA::SMBios::SMBiosTable::SMBiosTable(const Params &p) :
204 SimObject(p), structures(p.structures)
205 {
206 smbiosHeader.majorVersion = p.major_version;
207 smbiosHeader.minorVersion = p.minor_version;
208 assert(p.major_version <= 9);
209 assert(p.minor_version <= 9);
210 smbiosHeader.intermediateHeader.smbiosBCDRevision =
211 (p.major_version << 4) | p.minor_version;
212 }
213
214 void
215 X86ISA::SMBios::SMBiosTable::writeOut(PortProxy& proxy, Addr addr,
216 Addr &headerSize, Addr &structSize)
217 {
218 headerSize = 0x1F;
219
220 /*
221 * The main header
222 */
223 uint8_t mainChecksum = 0;
224
225 proxy.writeBlob(addr, (uint8_t *)smbiosHeader.anchorString, 4);
226 for (int i = 0; i < 4; i++)
227 mainChecksum += smbiosHeader.anchorString[i];
228
229 // The checksum goes here, but we're figuring it out as we go.
230
231 proxy.writeBlob(addr + 0x5, &smbiosHeader.entryPointLength, 1);
232 mainChecksum += smbiosHeader.entryPointLength;
233 proxy.writeBlob(addr + 0x6, &smbiosHeader.majorVersion, 1);
234 mainChecksum += smbiosHeader.majorVersion;
235 proxy.writeBlob(addr + 0x7, &smbiosHeader.minorVersion, 1);
236 mainChecksum += smbiosHeader.minorVersion;
237 // Maximum structure size goes here, but we'll figure it out later.
238 proxy.writeBlob(addr + 0xA, &smbiosHeader.entryPointRevision, 1);
239 mainChecksum += smbiosHeader.entryPointRevision;
240 proxy.writeBlob(addr + 0xB, &smbiosHeader.formattedArea, 5);
241 for (int i = 0; i < 5; i++)
242 mainChecksum += smbiosHeader.formattedArea[i];
243
244 /*
245 * The intermediate header
246 */
247 uint8_t intChecksum = 0;
248
249 proxy.writeBlob(addr + 0x10,
250 smbiosHeader.intermediateHeader.anchorString, 5);
251 for (int i = 0; i < 5; i++)
252 intChecksum += smbiosHeader.intermediateHeader.anchorString[i];
253
254 // The checksum goes here, but we're figuring it out as we go.
255 // Then the length of the structure table which we'll find later
256
257 uint32_t tableAddrGuest =
258 htole(smbiosHeader.intermediateHeader.tableAddr);
259 proxy.writeBlob(addr + 0x18, &tableAddrGuest, 4);
260 for (int i = 0; i < 4; i++) {
261 intChecksum += tableAddrGuest;
262 tableAddrGuest >>= 8;
263 }
264
265 uint16_t numStructs = letoh(structures.size());
266 proxy.writeBlob(addr + 0x1C, &numStructs, 2);
267 for (int i = 0; i < 2; i++) {
268 intChecksum += numStructs;
269 numStructs >>= 8;
270 }
271
272 proxy.writeBlob(addr + 0x1E,
273 &smbiosHeader.intermediateHeader.smbiosBCDRevision, 1);
274 intChecksum += smbiosHeader.intermediateHeader.smbiosBCDRevision;
275
276 /*
277 * Structure table
278 */
279
280 Addr base = smbiosHeader.intermediateHeader.tableAddr;
281 Addr offset = 0;
282 uint16_t maxSize = 0;
283 std::vector<SMBiosStructure *>::iterator it;
284 for (it = structures.begin(); it != structures.end(); it++) {
285 uint16_t size = (*it)->writeOut(proxy, base + offset);
286 if (size > maxSize)
287 maxSize = size;
288 offset += size;
289 }
290
291 structSize = offset;
292
293 /*
294 * Header
295 */
296
297 maxSize = htole(maxSize);
298 proxy.writeBlob(addr + 0x8, &maxSize, 2);
299 for (int i = 0; i < 2; i++) {
300 mainChecksum += maxSize;
301 maxSize >>= 8;
302 }
303
304 // Set the checksum
305 mainChecksum = -mainChecksum;
306 proxy.writeBlob(addr + 0x4, &mainChecksum, 1);
307
308 /*
309 * Intermediate header
310 */
311
312 uint16_t tableSize = offset;
313 tableSize = htole(tableSize);
314 proxy.writeBlob(addr + 0x16, &tableSize, 2);
315 for (int i = 0; i < 2; i++) {
316 intChecksum += tableSize;
317 tableSize >>= 8;
318 }
319
320 intChecksum = -intChecksum;
321 proxy.writeBlob(addr + 0x15, &intChecksum, 1);
322 }