smbios.cc revision 11793
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 * Authors: Gabe Black 41 */ 42 43#include "arch/x86/bios/smbios.hh" 44 45#include "arch/x86/isa_traits.hh" 46#include "base/types.hh" 47#include "mem/port_proxy.hh" 48#include "params/X86SMBiosBiosInformation.hh" 49#include "params/X86SMBiosSMBiosStructure.hh" 50#include "params/X86SMBiosSMBiosTable.hh" 51#include "sim/byteswap.hh" 52 53using namespace std; 54 55const char X86ISA::SMBios::SMBiosTable::SMBiosHeader::anchorString[] = "_SM_"; 56const uint8_t X86ISA::SMBios::SMBiosTable:: 57 SMBiosHeader::formattedArea[] = {0,0,0,0,0}; 58const uint8_t X86ISA::SMBios::SMBiosTable:: 59 SMBiosHeader::entryPointLength = 0x1F; 60const uint8_t X86ISA::SMBios::SMBiosTable:: 61 SMBiosHeader::entryPointRevision = 0; 62const char X86ISA::SMBios::SMBiosTable:: 63 SMBiosHeader::IntermediateHeader::anchorString[] = "_DMI_"; 64 65template <class T> 66uint64_t 67composeBitVector(T vec) 68{ 69 uint64_t val = 0; 70 typename T::iterator vecIt; 71 for (vecIt = vec.begin(); vecIt != vec.end(); vecIt++) { 72 val |= (1 << (*vecIt)); 73 } 74 return val; 75} 76 77uint16_t 78X86ISA::SMBios::SMBiosStructure::writeOut(PortProxy& proxy, Addr addr) 79{ 80 proxy.writeBlob(addr, (uint8_t *)(&type), 1); 81 82 uint8_t length = getLength(); 83 proxy.writeBlob(addr + 1, (uint8_t *)(&length), 1); 84 85 uint16_t handleGuest = X86ISA::htog(handle); 86 proxy.writeBlob(addr + 2, (uint8_t *)(&handleGuest), 2); 87 88 return length + getStringLength(); 89} 90 91X86ISA::SMBios::SMBiosStructure::SMBiosStructure(Params * p, uint8_t _type) : 92 SimObject(p), type(_type), handle(0), stringFields(false) 93{} 94 95void 96X86ISA::SMBios::SMBiosStructure::writeOutStrings( 97 PortProxy& proxy, Addr addr) 98{ 99 std::vector<std::string>::iterator it; 100 Addr offset = 0; 101 102 const uint8_t nullTerminator = 0; 103 104 // If there are string fields but none of them are used, that's a 105 // special case which is handled by this if. 106 if (strings.size() == 0 && stringFields) { 107 proxy.writeBlob(addr + offset, (uint8_t *)(&nullTerminator), 1); 108 offset++; 109 } else { 110 for (it = strings.begin(); it != strings.end(); it++) { 111 proxy.writeBlob(addr + offset, 112 (uint8_t *)it->c_str(), it->length() + 1); 113 offset += it->length() + 1; 114 } 115 } 116 proxy.writeBlob(addr + offset, (uint8_t *)(&nullTerminator), 1); 117} 118 119int 120X86ISA::SMBios::SMBiosStructure::getStringLength() 121{ 122 int size = 0; 123 std::vector<std::string>::iterator it; 124 125 for (it = strings.begin(); it != strings.end(); it++) { 126 size += it->length() + 1; 127 } 128 129 return size + 1; 130} 131 132int 133X86ISA::SMBios::SMBiosStructure::addString(string & newString) 134{ 135 stringFields = true; 136 // If a string is empty, treat it as not existing. The index for empty 137 // strings is 0. 138 if (newString.length() == 0) 139 return 0; 140 strings.push_back(newString); 141 return strings.size(); 142} 143 144string 145X86ISA::SMBios::SMBiosStructure::readString(int n) 146{ 147 assert(n > 0 && n <= strings.size()); 148 return strings[n - 1]; 149} 150 151void 152X86ISA::SMBios::SMBiosStructure::setString(int n, std::string & newString) 153{ 154 assert(n > 0 && n <= strings.size()); 155 strings[n - 1] = newString; 156} 157 158X86ISA::SMBios::BiosInformation::BiosInformation(Params * p) : 159 SMBiosStructure(p, Type), 160 startingAddrSegment(p->starting_addr_segment), 161 romSize(p->rom_size), 162 majorVer(p->major), minorVer(p->minor), 163 embContFirmwareMajor(p->emb_cont_firmware_major), 164 embContFirmwareMinor(p->emb_cont_firmware_minor) 165 { 166 vendor = addString(p->vendor); 167 version = addString(p->version); 168 releaseDate = addString(p->release_date); 169 170 characteristics = composeBitVector(p->characteristics); 171 characteristicExtBytes = 172 composeBitVector(p->characteristic_ext_bytes); 173 } 174 175uint16_t 176X86ISA::SMBios::BiosInformation::writeOut(PortProxy& proxy, Addr addr) 177{ 178 uint8_t size = SMBiosStructure::writeOut(proxy, addr); 179 180 proxy.writeBlob(addr + 0x4, (uint8_t *)(&vendor), 1); 181 proxy.writeBlob(addr + 0x5, (uint8_t *)(&version), 1); 182 183 uint16_t startingAddrSegmentGuest = X86ISA::htog(startingAddrSegment); 184 proxy.writeBlob(addr + 0x6, (uint8_t *)(&startingAddrSegmentGuest), 2); 185 186 proxy.writeBlob(addr + 0x8, (uint8_t *)(&releaseDate), 1); 187 proxy.writeBlob(addr + 0x9, (uint8_t *)(&romSize), 1); 188 189 uint64_t characteristicsGuest = X86ISA::htog(characteristics); 190 proxy.writeBlob(addr + 0xA, (uint8_t *)(&characteristicsGuest), 8); 191 192 uint16_t characteristicExtBytesGuest = 193 X86ISA::htog(characteristicExtBytes); 194 proxy.writeBlob(addr + 0x12, (uint8_t *)(&characteristicExtBytesGuest), 2); 195 196 proxy.writeBlob(addr + 0x14, (uint8_t *)(&majorVer), 1); 197 proxy.writeBlob(addr + 0x15, (uint8_t *)(&minorVer), 1); 198 proxy.writeBlob(addr + 0x16, (uint8_t *)(&embContFirmwareMajor), 1); 199 proxy.writeBlob(addr + 0x17, (uint8_t *)(&embContFirmwareMinor), 1); 200 201 writeOutStrings(proxy, addr + getLength()); 202 203 return size; 204} 205 206X86ISA::SMBios::SMBiosTable::SMBiosTable(Params * p) : 207 SimObject(p), structures(p->structures) 208{ 209 smbiosHeader.majorVersion = p->major_version; 210 smbiosHeader.minorVersion = p->minor_version; 211 assert(p->major_version <= 9); 212 assert(p->minor_version <= 9); 213 smbiosHeader.intermediateHeader.smbiosBCDRevision = 214 (p->major_version << 4) | p->minor_version; 215} 216 217void 218X86ISA::SMBios::SMBiosTable::writeOut(PortProxy& proxy, Addr addr, 219 Addr &headerSize, Addr &structSize) 220{ 221 headerSize = 0x1F; 222 223 /* 224 * The main header 225 */ 226 uint8_t mainChecksum = 0; 227 228 proxy.writeBlob(addr, (uint8_t *)smbiosHeader.anchorString, 4); 229 for (int i = 0; i < 4; i++) 230 mainChecksum += smbiosHeader.anchorString[i]; 231 232 // The checksum goes here, but we're figuring it out as we go. 233 234 proxy.writeBlob(addr + 0x5, 235 (uint8_t *)(&smbiosHeader.entryPointLength), 1); 236 mainChecksum += smbiosHeader.entryPointLength; 237 proxy.writeBlob(addr + 0x6, 238 (uint8_t *)(&smbiosHeader.majorVersion), 1); 239 mainChecksum += smbiosHeader.majorVersion; 240 proxy.writeBlob(addr + 0x7, 241 (uint8_t *)(&smbiosHeader.minorVersion), 1); 242 mainChecksum += smbiosHeader.minorVersion; 243 // Maximum structure size goes here, but we'll figure it out later. 244 proxy.writeBlob(addr + 0xA, 245 (uint8_t *)(&smbiosHeader.entryPointRevision), 1); 246 mainChecksum += smbiosHeader.entryPointRevision; 247 proxy.writeBlob(addr + 0xB, 248 (uint8_t *)(&smbiosHeader.formattedArea), 5); 249 for (int i = 0; i < 5; i++) 250 mainChecksum += smbiosHeader.formattedArea[i]; 251 252 /* 253 * The intermediate header 254 */ 255 uint8_t intChecksum = 0; 256 257 proxy.writeBlob(addr + 0x10, 258 (uint8_t *)smbiosHeader.intermediateHeader.anchorString, 5); 259 for (int i = 0; i < 5; i++) 260 intChecksum += smbiosHeader.intermediateHeader.anchorString[i]; 261 262 // The checksum goes here, but we're figuring it out as we go. 263 // Then the length of the structure table which we'll find later 264 265 uint32_t tableAddrGuest = 266 X86ISA::htog(smbiosHeader.intermediateHeader.tableAddr); 267 proxy.writeBlob(addr + 0x18, (uint8_t *)(&tableAddrGuest), 4); 268 for (int i = 0; i < 4; i++) { 269 intChecksum += tableAddrGuest; 270 tableAddrGuest >>= 8; 271 } 272 273 uint16_t numStructs = X86ISA::gtoh(structures.size()); 274 proxy.writeBlob(addr + 0x1C, (uint8_t *)(&numStructs), 2); 275 for (int i = 0; i < 2; i++) { 276 intChecksum += numStructs; 277 numStructs >>= 8; 278 } 279 280 proxy.writeBlob(addr + 0x1E, 281 (uint8_t *)(&smbiosHeader.intermediateHeader.smbiosBCDRevision), 282 1); 283 intChecksum += smbiosHeader.intermediateHeader.smbiosBCDRevision; 284 285 /* 286 * Structure table 287 */ 288 289 Addr base = smbiosHeader.intermediateHeader.tableAddr; 290 Addr offset = 0; 291 uint16_t maxSize = 0; 292 std::vector<SMBiosStructure *>::iterator it; 293 for (it = structures.begin(); it != structures.end(); it++) { 294 uint16_t size = (*it)->writeOut(proxy, base + offset); 295 if (size > maxSize) 296 maxSize = size; 297 offset += size; 298 } 299 300 structSize = offset; 301 302 /* 303 * Header 304 */ 305 306 maxSize = X86ISA::htog(maxSize); 307 proxy.writeBlob(addr + 0x8, (uint8_t *)(&maxSize), 2); 308 for (int i = 0; i < 2; i++) { 309 mainChecksum += maxSize; 310 maxSize >>= 8; 311 } 312 313 // Set the checksum 314 mainChecksum = -mainChecksum; 315 proxy.writeBlob(addr + 0x4, (uint8_t *)(&mainChecksum), 1); 316 317 /* 318 * Intermediate header 319 */ 320 321 uint16_t tableSize = offset; 322 tableSize = X86ISA::htog(tableSize); 323 proxy.writeBlob(addr + 0x16, (uint8_t *)(&tableSize), 2); 324 for (int i = 0; i < 2; i++) { 325 intChecksum += tableSize; 326 tableSize >>= 8; 327 } 328 329 intChecksum = -intChecksum; 330 proxy.writeBlob(addr + 0x15, (uint8_t *)(&intChecksum), 1); 331} 332 333X86ISA::SMBios::BiosInformation * 334X86SMBiosBiosInformationParams::create() 335{ 336 return new X86ISA::SMBios::BiosInformation(this); 337} 338 339X86ISA::SMBios::SMBiosTable * 340X86SMBiosSMBiosTableParams::create() 341{ 342 return new X86ISA::SMBios::SMBiosTable(this); 343} 344