smbios.cc revision 5615:1c4b9b1aa500
11689SN/A/*
210333Smitch.hayenga@arm.com * Copyright (c) 2008 The Regents of The University of Michigan
37782Sminkyu.jeong@arm.com * All rights reserved.
47782Sminkyu.jeong@arm.com *
57782Sminkyu.jeong@arm.com * Redistribution and use in source and binary forms, with or without
67782Sminkyu.jeong@arm.com * modification, are permitted provided that the following conditions are
77782Sminkyu.jeong@arm.com * met: redistributions of source code must retain the above copyright
87782Sminkyu.jeong@arm.com * notice, this list of conditions and the following disclaimer;
97782Sminkyu.jeong@arm.com * redistributions in binary form must reproduce the above copyright
107782Sminkyu.jeong@arm.com * notice, this list of conditions and the following disclaimer in the
117782Sminkyu.jeong@arm.com * documentation and/or other materials provided with the distribution;
127782Sminkyu.jeong@arm.com * neither the name of the copyright holders nor the names of its
137782Sminkyu.jeong@arm.com * contributors may be used to endorse or promote products derived from
142326SN/A * this software without specific prior written permission.
151689SN/A *
161689SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
171689SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
181689SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
191689SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
201689SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
211689SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
221689SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
231689SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
241689SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
251689SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
261689SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
271689SN/A *
281689SN/A * Authors: Gabe Black
291689SN/A */
301689SN/A
311689SN/A/*
321689SN/A * Copyright (c) 2008 The Hewlett-Packard Development Company
331689SN/A * All rights reserved.
341689SN/A *
351689SN/A * Redistribution and use of this software in source and binary forms,
361689SN/A * with or without modification, are permitted provided that the
371689SN/A * following conditions are met:
381689SN/A *
392665Ssaidi@eecs.umich.edu * The software must be used only for Non-Commercial Use which means any
402665Ssaidi@eecs.umich.edu * use which is NOT directed to receiving any direct monetary
411689SN/A * compensation for, or commercial advantage from such use.  Illustrative
421689SN/A * examples of non-commercial use are academic research, personal study,
432292SN/A * teaching, education and corporate research & development.
442292SN/A * Illustrative examples of commercial use are distributing products for
451060SN/A * commercial advantage and providing services using the software for
461060SN/A * commercial advantage.
478230Snate@binkert.org *
481060SN/A * If you wish to use this software or functionality therein that may be
491461SN/A * covered by patents for commercial use, please contact:
501717SN/A *     Director of Intellectual Property Licensing
518229Snate@binkert.org *     Office of Strategy and Technology
522292SN/A *     Hewlett-Packard Company
538229Snate@binkert.org *     1501 Page Mill Road
548232Snate@binkert.org *     Palo Alto, California  94304
5510023Smatt.horsnell@ARM.com *
561060SN/A * Redistributions of source code must retain the above copyright notice,
578737Skoansin.tan@gmail.com * this list of conditions and the following disclaimer.  Redistributions
582292SN/A * in binary form must reproduce the above copyright notice, this list of
592292SN/A * conditions and the following disclaimer in the documentation and/or
602292SN/A * other materials provided with the distribution.  Neither the name of
612326SN/A * the COPYRIGHT HOLDER(s), HEWLETT-PACKARD COMPANY, nor the names of its
622326SN/A * contributors may be used to endorse or promote products derived from
632326SN/A * this software without specific prior written permission.  No right of
642326SN/A * sublicense is granted herewith.  Derivatives of the software and
652326SN/A * output created using the software may be prepared, but only for
662292SN/A * Non-Commercial Uses.  Derivatives of the software may be shared with
672326SN/A * others provided: (i) the others agree to abide by the list of
682326SN/A * conditions herein which includes the Non-Commercial Use restrictions;
692326SN/A * and (ii) such Derivatives of the software include the above copyright
702326SN/A * notice to acknowledge the contribution from this software where
712326SN/A * applicable, this list of conditions and the disclaimer below.
722326SN/A *
732326SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
742326SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
752326SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
762326SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
772326SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
782292SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
791681SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
802292SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
811060SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
821060SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
831060SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
841061SN/A *
851061SN/A * Authors: Gabe Black
862733Sktlim@umich.edu */
871060SN/A
881681SN/A#include "arch/x86/bios/smbios.hh"
891061SN/A#include "arch/x86/isa_traits.hh"
902292SN/A#include "mem/port.hh"
911060SN/A#include "params/X86SMBiosBiosInformation.hh"
921061SN/A#include "params/X86SMBiosSMBiosStructure.hh"
931061SN/A#include "params/X86SMBiosSMBiosTable.hh"
941061SN/A#include "sim/byteswap.hh"
951061SN/A#include "sim/host.hh"
961060SN/A
971060SN/Ausing namespace std;
982292SN/A
992292SN/Aconst char X86ISA::SMBios::SMBiosTable::SMBiosHeader::anchorString[] = "_SM_";
1002292SN/Aconst uint8_t X86ISA::SMBios::SMBiosTable::
1011060SN/A        SMBiosHeader::formattedArea[] = {0,0,0,0,0};
1022292SN/Aconst uint8_t X86ISA::SMBios::SMBiosTable::
1032292SN/A        SMBiosHeader::entryPointLength = 0x1F;
1042292SN/Aconst uint8_t X86ISA::SMBios::SMBiosTable::
1052292SN/A        SMBiosHeader::entryPointRevision = 0;
1062292SN/Aconst char X86ISA::SMBios::SMBiosTable::
1072292SN/A        SMBiosHeader::IntermediateHeader::anchorString[] = "_DMI_";
1081060SN/A
1091060SN/Atemplate <class T>
1101060SN/Auint64_t
1112292SN/AcomposeBitVector(T vec)
1121060SN/A{
1131060SN/A    uint64_t val = 0;
1141060SN/A    typename T::iterator vecIt;
1151060SN/A    for (vecIt = vec.begin(); vecIt != vec.end(); vecIt++) {
1161060SN/A        val |= (1 << (*vecIt));
1172292SN/A    }
1181060SN/A    return val;
1192292SN/A}
1202292SN/A
1212292SN/Auint16_t
1222292SN/AX86ISA::SMBios::SMBiosStructure::writeOut(FunctionalPort * port, Addr addr)
1232292SN/A{
1242292SN/A    port->writeBlob(addr, (uint8_t *)(&type), 1);
1251060SN/A
12610023Smatt.horsnell@ARM.com    uint8_t length = getLength();
12710023Smatt.horsnell@ARM.com    port->writeBlob(addr + 1, (uint8_t *)(&length), 1);
12810023Smatt.horsnell@ARM.com
12911246Sradhika.jagtap@ARM.com    uint16_t handleGuest = X86ISA::htog(handle);
13011246Sradhika.jagtap@ARM.com    port->writeBlob(addr + 2, (uint8_t *)(&handleGuest), 2);
13111246Sradhika.jagtap@ARM.com
13211246Sradhika.jagtap@ARM.com    return length + getStringLength();
13310023Smatt.horsnell@ARM.com}
1341060SN/A
1352292SN/AX86ISA::SMBios::SMBiosStructure::SMBiosStructure(Params * p, uint8_t _type) :
1365529Snate@binkert.org    SimObject(p), type(_type), handle(0), stringFields(false)
1371060SN/A{}
1382292SN/A
1392292SN/Avoid
1401062SN/AX86ISA::SMBios::SMBiosStructure::writeOutStrings(
1412292SN/A        FunctionalPort * port, Addr addr)
1422632Sstever@eecs.umich.edu{
1432632Sstever@eecs.umich.edu    std::vector<std::string>::iterator it;
14410023Smatt.horsnell@ARM.com    Addr offset = 0;
14510023Smatt.horsnell@ARM.com
14610023Smatt.horsnell@ARM.com    const uint8_t nullTerminator = 0;
1472292SN/A
1489427SAndreas.Sandberg@ARM.com    // If there are string fields but none of them are used, that's a
1492292SN/A    // special case which is handled by this if.
1502292SN/A    if (strings.size() == 0 && stringFields) {
1512632Sstever@eecs.umich.edu        port->writeBlob(addr + offset, (uint8_t *)(&nullTerminator), 1);
1522632Sstever@eecs.umich.edu        offset++;
1532292SN/A    } else {
1542632Sstever@eecs.umich.edu        for (it = strings.begin(); it != strings.end(); it++) {
1552632Sstever@eecs.umich.edu            port->writeBlob(addr + offset,
1562292SN/A                    (uint8_t *)it->c_str(), it->length() + 1);
1572632Sstever@eecs.umich.edu            offset += it->length() + 1;
1582632Sstever@eecs.umich.edu        }
1592292SN/A    }
1606221Snate@binkert.org    port->writeBlob(addr + offset, (uint8_t *)(&nullTerminator), 1);
1612632Sstever@eecs.umich.edu}
1622292SN/A
1632292SN/Aint
1642632Sstever@eecs.umich.eduX86ISA::SMBios::SMBiosStructure::getStringLength()
1659444SAndreas.Sandberg@ARM.com{
1669444SAndreas.Sandberg@ARM.com    int size = 0;
1672843Sktlim@umich.edu    std::vector<std::string>::iterator it;
1689444SAndreas.Sandberg@ARM.com
1699444SAndreas.Sandberg@ARM.com    for (it = strings.begin(); it != strings.end(); it++) {
1702632Sstever@eecs.umich.edu        size += it->length() + 1;
1712348SN/A    }
1722307SN/A
1732632Sstever@eecs.umich.edu    return size + 1;
1742292SN/A}
1756221Snate@binkert.org
1762107SN/Aint
1772292SN/AX86ISA::SMBios::SMBiosStructure::addString(string & newString)
1782632Sstever@eecs.umich.edu{
1792632Sstever@eecs.umich.edu    stringFields = true;
1802292SN/A    // If a string is empty, treat it as not existing. The index for empty
1812292SN/A    // strings is 0.
1822292SN/A    if (newString.length() == 0)
1832292SN/A        return 0;
1842292SN/A    strings.push_back(newString);
1852292SN/A    return strings.size();
1862292SN/A}
1872292SN/A
18810333Smitch.hayenga@arm.comstring
18910333Smitch.hayenga@arm.comX86ISA::SMBios::SMBiosStructure::readString(int n)
19010333Smitch.hayenga@arm.com{
19110333Smitch.hayenga@arm.com    assert(n > 0 && n <= strings.size());
19210333Smitch.hayenga@arm.com    return strings[n - 1];
19310333Smitch.hayenga@arm.com}
1942292SN/A
1952632Sstever@eecs.umich.eduvoid
1962632Sstever@eecs.umich.eduX86ISA::SMBios::SMBiosStructure::setString(int n, std::string & newString)
1972292SN/A{
1986221Snate@binkert.org    assert(n > 0 && n <= strings.size());
1992292SN/A    strings[n - 1] = newString;
2002292SN/A}
2012292SN/A
2022292SN/AX86ISA::SMBios::BiosInformation::BiosInformation(Params * p) :
2032292SN/A        SMBiosStructure(p, Type),
2042292SN/A        startingAddrSegment(p->starting_addr_segment),
2052292SN/A        romSize(p->rom_size),
2062292SN/A        majorVer(p->major), minorVer(p->minor),
2072292SN/A        embContFirmwareMajor(p->emb_cont_firmware_major),
2082292SN/A        embContFirmwareMinor(p->emb_cont_firmware_minor)
2092292SN/A    {
2102292SN/A        vendor = addString(p->vendor);
2112292SN/A        version = addString(p->version);
2122292SN/A        releaseDate = addString(p->release_date);
2132292SN/A
2142292SN/A        characteristics = composeBitVector(p->characteristics);
2152292SN/A        characteristicExtBytes =
2162292SN/A            composeBitVector(p->characteristic_ext_bytes);
2172292SN/A    }
2182292SN/A
2192292SN/Auint16_t
2202292SN/AX86ISA::SMBios::BiosInformation::writeOut(FunctionalPort * port, Addr addr)
2212292SN/A{
2222292SN/A    uint8_t size = SMBiosStructure::writeOut(port, addr);
2232292SN/A
2242292SN/A    port->writeBlob(addr + 0x4, (uint8_t *)(&vendor), 1);
2252292SN/A    port->writeBlob(addr + 0x5, (uint8_t *)(&version), 1);
2262292SN/A
2272292SN/A    uint16_t startingAddrSegmentGuest = X86ISA::htog(startingAddrSegment);
2282292SN/A    port->writeBlob(addr + 0x6, (uint8_t *)(&startingAddrSegmentGuest), 2);
2295557Sktlim@umich.edu
2306221Snate@binkert.org    port->writeBlob(addr + 0x8, (uint8_t *)(&releaseDate), 1);
2315557Sktlim@umich.edu    port->writeBlob(addr + 0x9, (uint8_t *)(&romSize), 1);
2327598Sminkyu.jeong@arm.com
2337598Sminkyu.jeong@arm.com    uint64_t characteristicsGuest = X86ISA::htog(characteristics);
2347598Sminkyu.jeong@arm.com    port->writeBlob(addr + 0xA, (uint8_t *)(&characteristicsGuest), 8);
2352632Sstever@eecs.umich.edu
2362292SN/A    uint16_t characteristicExtBytesGuest =
2372292SN/A        X86ISA::htog(characteristicExtBytes);
2382292SN/A    port->writeBlob(addr + 0x12, (uint8_t *)(&characteristicExtBytesGuest), 2);
2396221Snate@binkert.org
2402632Sstever@eecs.umich.edu    port->writeBlob(addr + 0x14, (uint8_t *)(&majorVer), 1);
2412292SN/A    port->writeBlob(addr + 0x15, (uint8_t *)(&minorVer), 1);
2422292SN/A    port->writeBlob(addr + 0x16, (uint8_t *)(&embContFirmwareMajor), 1);
2432292SN/A    port->writeBlob(addr + 0x17, (uint8_t *)(&embContFirmwareMinor), 1);
2446221Snate@binkert.org
2452292SN/A    writeOutStrings(port, addr + getLength());
2462292SN/A
2476221Snate@binkert.org    return size;
2482292SN/A}
2492292SN/A
2502292SN/AX86ISA::SMBios::SMBiosTable::SMBiosTable(Params * p) :
2512292SN/A    SimObject(p), structures(p->structures)
2526221Snate@binkert.org{
2532292SN/A    smbiosHeader.majorVersion = p->major_version;
2542292SN/A    smbiosHeader.minorVersion = p->minor_version;
2556221Snate@binkert.org    assert(p->major_version <= 9);
2562292SN/A    assert(p->minor_version <= 9);
2572292SN/A    smbiosHeader.intermediateHeader.smbiosBCDRevision =
2586221Snate@binkert.org        (p->major_version << 4) | p->minor_version;
2592292SN/A}
2602292SN/A
2612292SN/Avoid
2622292SN/AX86ISA::SMBios::SMBiosTable::writeOut(FunctionalPort * port, Addr addr,
2632292SN/A        Addr &headerSize, Addr &structSize)
2642632Sstever@eecs.umich.edu{
2652632Sstever@eecs.umich.edu    headerSize = 0x1F;
2662292SN/A
2672292SN/A    /*
2682292SN/A     * The main header
2692292SN/A     */
2702292SN/A    uint8_t mainChecksum = 0;
2712292SN/A
2722292SN/A    port->writeBlob(addr, (uint8_t *)smbiosHeader.anchorString, 4);
2732292SN/A    for (int i = 0; i < 4; i++)
2742292SN/A        mainChecksum += smbiosHeader.anchorString[i];
2752292SN/A
2762292SN/A    // The checksum goes here, but we're figuring it out as we go.
2772292SN/A
2782292SN/A    port->writeBlob(addr + 0x5,
2796221Snate@binkert.org            (uint8_t *)(&smbiosHeader.entryPointLength), 1);
2802292SN/A    mainChecksum += smbiosHeader.entryPointLength;
2812292SN/A    port->writeBlob(addr + 0x6,
2826221Snate@binkert.org            (uint8_t *)(&smbiosHeader.majorVersion), 1);
2832292SN/A    mainChecksum += smbiosHeader.majorVersion;
2842702Sktlim@umich.edu    port->writeBlob(addr + 0x7,
2856221Snate@binkert.org            (uint8_t *)(&smbiosHeader.minorVersion), 1);
2862702Sktlim@umich.edu    mainChecksum += smbiosHeader.minorVersion;
2872292SN/A    // Maximum structure size goes here, but we'll figure it out later.
2882292SN/A    port->writeBlob(addr + 0xA,
2891060SN/A            (uint8_t *)(&smbiosHeader.entryPointRevision), 1);
2901060SN/A    mainChecksum += smbiosHeader.entryPointRevision;
2912292SN/A    port->writeBlob(addr + 0xB,
2922292SN/A            (uint8_t *)(&smbiosHeader.formattedArea), 5);
2932292SN/A    for (int i = 0; i < 5; i++)
2942632Sstever@eecs.umich.edu        mainChecksum += smbiosHeader.formattedArea[i];
2951060SN/A
2961060SN/A    /*
2972348SN/A     * The intermediate header
2982301SN/A     */
2991062SN/A    uint8_t intChecksum = 0;
3002292SN/A
3012632Sstever@eecs.umich.edu    port->writeBlob(addr + 0x10,
3021062SN/A            (uint8_t *)smbiosHeader.intermediateHeader.anchorString, 5);
3032292SN/A    for (int i = 0; i < 5; i++)
3042292SN/A        intChecksum += smbiosHeader.intermediateHeader.anchorString[i];
3051060SN/A
3061060SN/A    // The checksum goes here, but we're figuring it out as we go.
3071060SN/A    // Then the length of the structure table which we'll find later
3081060SN/A
3091060SN/A    uint32_t tableAddrGuest =
3101060SN/A        X86ISA::htog(smbiosHeader.intermediateHeader.tableAddr);
3111060SN/A    port->writeBlob(addr + 0x18, (uint8_t *)(&tableAddrGuest), 4);
3121060SN/A    for (int i = 0; i < 4; i++) {
3131060SN/A        intChecksum += tableAddrGuest;
3141060SN/A        tableAddrGuest >>= 8;
3151060SN/A    }
3161060SN/A
3171060SN/A    uint16_t numStructs = X86ISA::gtoh(structures.size());
3181060SN/A    port->writeBlob(addr + 0x1C, (uint8_t *)(&numStructs), 2);
3191060SN/A    for (int i = 0; i < 2; i++) {
3201060SN/A        intChecksum += numStructs;
3211060SN/A        numStructs >>= 8;
3221060SN/A    }
3231060SN/A
3241060SN/A    port->writeBlob(addr + 0x1E,
3251060SN/A            (uint8_t *)(&smbiosHeader.intermediateHeader.smbiosBCDRevision),
3261060SN/A            1);
3271060SN/A    intChecksum += smbiosHeader.intermediateHeader.smbiosBCDRevision;
3281060SN/A
3291060SN/A    /*
3301060SN/A     * Structure table
3311060SN/A     */
3321060SN/A
3332292SN/A    Addr base = smbiosHeader.intermediateHeader.tableAddr;
3342292SN/A    Addr offset = 0;
3352292SN/A    uint16_t maxSize = 0;
3361060SN/A    std::vector<SMBiosStructure *>::iterator it;
3372292SN/A    for (it = structures.begin(); it != structures.end(); it++) {
3381060SN/A        uint16_t size = (*it)->writeOut(port, base + offset);
3392292SN/A        if (size > maxSize)
3402292SN/A            maxSize = size;
3412292SN/A        offset += size;
3421681SN/A    }
3432292SN/A
3442733Sktlim@umich.edu    structSize = offset;
3451060SN/A
3462292SN/A    /*
3472292SN/A     * Header
3482292SN/A     */
3492292SN/A
3502292SN/A    maxSize = X86ISA::htog(maxSize);
3512292SN/A    port->writeBlob(addr + 0x8, (uint8_t *)(&maxSize), 2);
3522292SN/A    for (int i = 0; i < 2; i++) {
3532292SN/A        mainChecksum += maxSize;
3542292SN/A        maxSize >>= 8;
3554329Sktlim@umich.edu    }
3564329Sktlim@umich.edu
3574329Sktlim@umich.edu    // Set the checksum
3584329Sktlim@umich.edu    mainChecksum = -mainChecksum;
3594329Sktlim@umich.edu    port->writeBlob(addr + 0x4, (uint8_t *)(&mainChecksum), 1);
3604329Sktlim@umich.edu
3614329Sktlim@umich.edu    /*
3624329Sktlim@umich.edu     * Intermediate header
3632292SN/A     */
3642292SN/A
3652292SN/A    uint16_t tableSize = offset;
3662292SN/A    tableSize = X86ISA::htog(tableSize);
3672292SN/A    port->writeBlob(addr + 0x16, (uint8_t *)(&tableSize), 2);
3681060SN/A    for (int i = 0; i < 2; i++) {
3692292SN/A        intChecksum += tableSize;
3702292SN/A        tableSize >>= 8;
3712292SN/A    }
3722292SN/A
3732292SN/A    intChecksum = -intChecksum;
3742292SN/A    port->writeBlob(addr + 0x15, (uint8_t *)(&intChecksum), 1);
3752292SN/A}
3762292SN/A
3779184Sandreas.hansson@arm.comX86ISA::SMBios::BiosInformation *
3789184Sandreas.hansson@arm.comX86SMBiosBiosInformationParams::create()
3791060SN/A{
3809184Sandreas.hansson@arm.com    return new X86ISA::SMBios::BiosInformation(this);
3819184Sandreas.hansson@arm.com}
3821060SN/A
3831060SN/AX86ISA::SMBios::SMBiosTable *
3849184Sandreas.hansson@arm.comX86SMBiosSMBiosTableParams::create()
3851060SN/A{
3861060SN/A    return new X86ISA::SMBios::SMBiosTable(this);
3871060SN/A}
3889184Sandreas.hansson@arm.com