X86: Turn SMBios structures into simobjects.
authorGabe Black <gblack@eecs.umich.edu>
Fri, 10 Oct 2008 10:50:51 +0000 (03:50 -0700)
committerGabe Black <gblack@eecs.umich.edu>
Fri, 10 Oct 2008 10:50:51 +0000 (03:50 -0700)
configs/common/FSConfig.py
src/arch/x86/X86System.py
src/arch/x86/bios/SConscript
src/arch/x86/bios/SMBios.py [new file with mode: 0644]
src/arch/x86/bios/smbios.cc
src/arch/x86/bios/smbios.hh
src/arch/x86/system.cc
src/arch/x86/system.hh

index 8e2b0884c8652c066abdf5dce1e62b2e2c52de47..21d4311d0fa1bb500ceb9be98dc318023cbec54e 100644 (file)
@@ -185,6 +185,10 @@ def makeX86System(mem_mode, mdesc = None, self = None):
 
     self.intrctrl = IntrControl()
 
+    # Add in a Bios information structure.
+    structures = [X86SMBiosBiosInformation()]
+    self.smbios_table.structures = structures
+
 
 def makeLinuxX86System(mem_mode, mdesc = None):
     self = LinuxX86System()
index b4ec393c3956add1cbc7a50088f4277a8bbbf006..5fe69c709c2bb7ca2d6fb6142933af0dace4e083 100644 (file)
 
 from m5.params import *
 from E820 import X86E820Table, X86E820Entry
+from SMBios import X86SMBiosSMBiosTable
 from System import System
 
 class X86System(System):
     type = 'X86System'
+    smbios_table = Param.X86SMBiosSMBiosTable(
+            X86SMBiosSMBiosTable(), 'table of smbios/dmi information')
 
 class LinuxX86System(X86System):
     type = 'LinuxX86System'
index 1ec717b11740baca10304f137a70637199ae413b..cdb5f390f49dc4af1b3fb3f3b92080e8f0a8c69d 100644 (file)
@@ -65,4 +65,5 @@ if env['TARGET_ISA'] == 'x86':
         Source('e820.cc')
 
         # The DMI tables.
+        SimObject('SMBios.py')
        Source('smbios.cc')
diff --git a/src/arch/x86/bios/SMBios.py b/src/arch/x86/bios/SMBios.py
new file mode 100644 (file)
index 0000000..4947b28
--- /dev/null
@@ -0,0 +1,140 @@
+# Copyright (c) 2008 The Hewlett-Packard Development Company
+# All rights reserved.
+#
+# Redistribution and use of this software in source and binary forms,
+# with or without modification, are permitted provided that the
+# following conditions are met:
+#
+# The software must be used only for Non-Commercial Use which means any
+# use which is NOT directed to receiving any direct monetary
+# compensation for, or commercial advantage from such use.  Illustrative
+# examples of non-commercial use are academic research, personal study,
+# teaching, education and corporate research & development.
+# Illustrative examples of commercial use are distributing products for
+# commercial advantage and providing services using the software for
+# commercial advantage.
+#
+# If you wish to use this software or functionality therein that may be
+# covered by patents for commercial use, please contact:
+#     Director of Intellectual Property Licensing
+#     Office of Strategy and Technology
+#     Hewlett-Packard Company
+#     1501 Page Mill Road
+#     Palo Alto, California  94304
+#
+# Redistributions of source code must retain the above copyright notice,
+# this list of conditions and the following disclaimer.  Redistributions
+# in binary form must reproduce the above copyright notice, this list of
+# conditions and the following disclaimer in the documentation and/or
+# other materials provided with the distribution.  Neither the name of
+# the COPYRIGHT HOLDER(s), HEWLETT-PACKARD COMPANY, nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.  No right of
+# sublicense is granted herewith.  Derivatives of the software and
+# output created using the software may be prepared, but only for
+# Non-Commercial Uses.  Derivatives of the software may be shared with
+# others provided: (i) the others agree to abide by the list of
+# conditions herein which includes the Non-Commercial Use restrictions;
+# and (ii) such Derivatives of the software include the above copyright
+# notice to acknowledge the contribution from this software where
+# applicable, this list of conditions and the disclaimer below.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+# Authors: Gabe Black
+
+from m5.params import *
+from m5.SimObject import SimObject
+
+class X86SMBiosSMBiosStructure(SimObject):
+    type = 'X86SMBiosSMBiosStructure'
+    cxx_class = 'X86ISA::SMBios::SMBiosStructure'
+    abstract = True
+
+class Characteristic(Enum):
+    map = {'Unknown' : 2,
+           'Unsupported' : 3,
+           'ISA' : 4,
+           'MCA' : 5,
+           'EISA' : 6,
+           'PCI' : 7,
+           'PCMCIA' : 8,
+           'PnP' : 9,
+           'APM' : 10,
+           'Flash' : 11,
+           'Shadow' : 12,
+           'VL_Vesa' : 13,
+           'ESCD' : 14,
+           'CDBoot' : 15,
+           'SelectBoot' : 16,
+           'Socketed' : 17,
+           'PCMCIABoot' : 18,
+           'EDD' : 19,
+           'NEC9800' : 20,
+           'Toshiba' : 21,
+           'Floppy_5_25_360KB' : 22,
+           'Floppy_5_25_1_2MB' : 23,
+           'Floppy_3_5_720KB' : 24,
+           'Floppy_3_5_2_88MB' : 25,
+           'PrintScreen' : 26,
+           'Keyboard8024' : 27,
+           'Serial' : 28,
+           'Printer' : 29,
+           'CGA_Mono' : 30,
+           'NEC_PC_98' : 31
+    }
+
+class ExtCharacteristic(Enum):
+    map = {'ACPI' : 0,
+           'USBLegacy' : 1,
+           'AGP' : 2,
+           'I20Boot' : 3,
+           'LS_120Boot' : 4,
+           'ZIPBoot' : 5,
+           'FirewireBoot' : 6,
+           'SmartBattery' : 7,
+           'BootSpec' : 8,
+           'NetServiceBoot' : 9,
+           'TargetContent' : 10
+    }
+
+class X86SMBiosBiosInformation(X86SMBiosSMBiosStructure):
+    type = 'X86SMBiosBiosInformation'
+    cxx_class = 'X86ISA::SMBios::BiosInformation'
+
+    vendor = Param.String("", "vendor name string")
+    version = Param.String("", "version string")
+    starting_addr_segment = \
+        Param.UInt16(0, "segment location of bios starting address")
+    release_date = Param.String("06/08/2008", "release date")
+    rom_size = Param.UInt8(0, "rom size")
+    characteristics = VectorParam.Characteristic([],
+            "bios characteristic bit vector")
+    characteristic_ext_bytes = VectorParam.ExtCharacteristic([],
+            "extended bios characteristic bit vector")
+    major = Param.UInt8(0, "major version number")
+    minor = Param.UInt8(0, "minor version number")
+    emb_cont_firmware_major = Param.UInt8(0,
+            "embedded controller firmware major version number")
+
+    emb_cont_firmware_minor = Param.UInt8(0,
+            "embedded controller firmware minor version number")
+
+class X86SMBiosSMBiosTable(SimObject):
+    type = 'X86SMBiosSMBiosTable'
+    cxx_class = 'X86ISA::SMBios::SMBiosTable'
+
+    major_version = Param.UInt8(2, "major version number")
+    minor_version = Param.UInt8(5, "minor version number")
+
+    structures = VectorParam.X86SMBiosSMBiosStructure([], "smbios structures")
index de4a263b77ded3649e13febc655d9ce2df3d9729..95ade1e4d8b18b0d7e30083ed7e87de8a52cf30e 100644 (file)
 #include "arch/x86/bios/smbios.hh"
 #include "arch/x86/isa_traits.hh"
 #include "mem/port.hh"
+#include "params/X86SMBiosBiosInformation.hh"
+#include "params/X86SMBiosSMBiosStructure.hh"
+#include "params/X86SMBiosSMBiosTable.hh"
 #include "sim/byteswap.hh"
 #include "sim/host.hh"
 
+using namespace std;
+
 const char X86ISA::SMBios::SMBiosTable::SMBiosHeader::anchorString[] = "_SM_";
 const uint8_t X86ISA::SMBios::SMBiosTable::
         SMBiosHeader::formattedArea[] = {0,0,0,0,0};
@@ -101,6 +106,116 @@ const uint8_t X86ISA::SMBios::SMBiosTable::
 const char X86ISA::SMBios::SMBiosTable::
         SMBiosHeader::IntermediateHeader::anchorString[] = "_DMI_";
 
+template <class T>
+uint64_t
+composeBitVector(T vec)
+{
+    uint64_t val = 0;
+    typename T::iterator vecIt;
+    for (vecIt = vec.begin(); vecIt != vec.end(); vecIt++) {
+        val |= (1 << (*vecIt));
+    }
+    return val;
+}
+
+uint16_t
+X86ISA::SMBios::SMBiosStructure::writeOut(FunctionalPort * port, Addr addr)
+{
+    port->writeBlob(addr, (uint8_t *)(&type), 1);
+
+    uint8_t length = getLength();
+    port->writeBlob(addr + 1, (uint8_t *)(&length), 1);
+
+    uint16_t handleGuest = X86ISA::htog(handle);
+    port->writeBlob(addr + 2, (uint8_t *)(&handleGuest), 2);
+
+    return length + getStringLength();
+}
+
+X86ISA::SMBios::SMBiosStructure::SMBiosStructure(Params * p, uint8_t _type) :
+    SimObject(p), type(_type), handle(0), stringFields(false)
+{}
+
+void
+X86ISA::SMBios::SMBiosStructure::writeOutStrings(
+        FunctionalPort * port, Addr addr)
+{
+    std::vector<std::string>::iterator it;
+    Addr offset = 0;
+
+    const uint8_t nullTerminator = 0;
+
+    // If there are string fields but none of them are used, that's a
+    // special case which is handled by this if.
+    if (strings.size() == 0 && stringFields) {
+        port->writeBlob(addr + offset, (uint8_t *)(&nullTerminator), 1);
+        offset++;
+    } else {
+        for (it = strings.begin(); it != strings.end(); it++) {
+            port->writeBlob(addr + offset,
+                    (uint8_t *)it->c_str(), it->length() + 1);
+            offset += it->length() + 1;
+        }
+    }
+    port->writeBlob(addr + offset, (uint8_t *)(&nullTerminator), 1);
+}
+
+int
+X86ISA::SMBios::SMBiosStructure::getStringLength()
+{
+    int size = 0;
+    std::vector<std::string>::iterator it;
+
+    for (it = strings.begin(); it != strings.end(); it++) {
+        size += it->length() + 1;
+    }
+
+    return size + 1;
+}
+
+int
+X86ISA::SMBios::SMBiosStructure::addString(string & newString)
+{
+    stringFields = true;
+    // If a string is empty, treat it as not existing. The index for empty
+    // strings is 0.
+    if (newString.length() == 0)
+        return 0;
+    strings.push_back(newString);
+    return strings.size();
+}
+
+string
+X86ISA::SMBios::SMBiosStructure::readString(int n)
+{
+    assert(n > 0 && n <= strings.size());
+    return strings[n - 1];
+}
+
+void
+X86ISA::SMBios::SMBiosStructure::setString(int n, std::string & newString)
+{
+    assert(n > 0 && n <= strings.size());
+    strings[n - 1] = newString;
+}
+
+X86ISA::SMBios::BiosInformation::BiosInformation(Params * p) :
+        SMBiosStructure(p, Type),
+        startingAddrSegment(p->starting_addr_segment),
+        romSize(p->rom_size),
+        majorVer(p->major), minorVer(p->minor),
+        embContFirmwareMajor(p->emb_cont_firmware_major),
+        embContFirmwareMinor(p->emb_cont_firmware_minor)
+    {
+        vendor = addString(p->vendor);
+        version = addString(p->version);
+        releaseDate = addString(p->release_date);
+
+        characteristics = composeBitVector(p->characteristics);
+        characteristicExtBytes =
+            composeBitVector(p->characteristic_ext_bytes);
+    }
+
 uint16_t
 X86ISA::SMBios::BiosInformation::writeOut(FunctionalPort * port, Addr addr)
 {
@@ -122,8 +237,8 @@ X86ISA::SMBios::BiosInformation::writeOut(FunctionalPort * port, Addr addr)
         X86ISA::htog(characteristicExtBytes);
     port->writeBlob(addr + 0x12, (uint8_t *)(&characteristicExtBytesGuest), 2);
 
-    port->writeBlob(addr + 0x14, (uint8_t *)(&major), 1);
-    port->writeBlob(addr + 0x15, (uint8_t *)(&minor), 1);
+    port->writeBlob(addr + 0x14, (uint8_t *)(&majorVer), 1);
+    port->writeBlob(addr + 0x15, (uint8_t *)(&minorVer), 1);
     port->writeBlob(addr + 0x16, (uint8_t *)(&embContFirmwareMajor), 1);
     port->writeBlob(addr + 0x17, (uint8_t *)(&embContFirmwareMinor), 1);
 
@@ -132,9 +247,22 @@ X86ISA::SMBios::BiosInformation::writeOut(FunctionalPort * port, Addr addr)
     return size;
 }
 
+X86ISA::SMBios::SMBiosTable::SMBiosTable(Params * p) :
+    SimObject(p), structures(p->structures)
+{
+    smbiosHeader.majorVersion = p->major_version;
+    smbiosHeader.minorVersion = p->minor_version;
+    assert(p->major_version <= 9);
+    assert(p->minor_version <= 9);
+    smbiosHeader.intermediateHeader.smbiosBCDRevision =
+        (p->major_version << 4) | p->minor_version;
+}
+
 void
-X86ISA::SMBios::SMBiosTable::writeOut(FunctionalPort * port, Addr addr)
+X86ISA::SMBios::SMBiosTable::writeOut(FunctionalPort * port, Addr addr,
+        Addr &headerSize, Addr &structSize)
 {
+    headerSize = 0x1F;
 
     /*
      * The main header
@@ -205,14 +333,16 @@ X86ISA::SMBios::SMBiosTable::writeOut(FunctionalPort * port, Addr addr)
     Addr base = smbiosHeader.intermediateHeader.tableAddr;
     Addr offset = 0;
     uint16_t maxSize = 0;
-    std::vector<SMBiosStructure>::iterator it;
+    std::vector<SMBiosStructure *>::iterator it;
     for (it = structures.begin(); it != structures.end(); it++) {
-        uint16_t size = it->writeOut(port, base + offset);
+        uint16_t size = (*it)->writeOut(port, base + offset);
         if (size > maxSize)
             maxSize = size;
         offset += size;
     }
 
+    structSize = offset;
+
     /*
      * Header
      */
@@ -243,3 +373,15 @@ X86ISA::SMBios::SMBiosTable::writeOut(FunctionalPort * port, Addr addr)
     intChecksum = -intChecksum;
     port->writeBlob(addr + 0x15, (uint8_t *)(&intChecksum), 1);
 }
+
+X86ISA::SMBios::BiosInformation *
+X86SMBiosBiosInformationParams::create()
+{
+    return new X86ISA::SMBios::BiosInformation(this);
+}
+
+X86ISA::SMBios::SMBiosTable *
+X86SMBiosSMBiosTableParams::create()
+{
+    return new X86ISA::SMBios::SMBiosTable(this);
+}
index 8d3994fc7033448590380613688d7a4f46269f1a..1c50d0b48d1f1de8ac3651e0e07679cedc3b05e3 100644 (file)
 #include <string>
 #include <vector>
 
-#include "arch/x86/isa_traits.hh"
-#include "mem/port.hh"
-#include "sim/byteswap.hh"
+#include "enums/Characteristic.hh"
+#include "enums/ExtCharacteristic.hh"
 #include "sim/host.hh"
+#include "sim/sim_object.hh"
+
+class FunctionalPort;
+class X86SMBiosBiosInformationParams;
+class X86SMBiosSMBiosStructureParams;
+class X86SMBiosSMBiosTableParams;
 
 namespace X86ISA
 {
@@ -102,8 +107,11 @@ namespace X86ISA
 namespace SMBios
 {
 
-class SMBiosStructure
+class SMBiosStructure : public SimObject
 {
+  protected:
+    typedef X86SMBiosSMBiosStructureParams Params;
+
   public:
 
     virtual
@@ -126,73 +134,33 @@ class SMBiosStructure
         return 4;
     }
 
-    virtual uint16_t
-    writeOut(FunctionalPort * port, Addr addr)
-    {
-        port->writeBlob(addr, (uint8_t *)(&type), 1);
-
-        uint8_t length = getLength();
-        port->writeBlob(addr + 1, (uint8_t *)(&length), 1);
-
-        uint16_t handleGuest = X86ISA::htog(handle);
-        port->writeBlob(addr + 2, (uint8_t *)(&handleGuest), 2);
-
-        return length + getStringLength();
-    }
+    virtual uint16_t writeOut(FunctionalPort * port, Addr addr);
 
   protected:
-    std::vector<std::string> strings;
-
-    void writeOutStrings(FunctionalPort * port, Addr addr)
-    {
-        std::vector<std::string>::iterator it;
-        Addr offset = 0;
-
-        for (it = strings.begin(); it != strings.end(); it++) {
-            port->writeBlob(addr + offset,
-                    (uint8_t *)it->c_str(), it->length() + 1);
-            offset += it->length() + 1;
-        }
+    bool stringFields;
 
-        const uint8_t nullTerminator = 0;
-        port->writeBlob(addr + offset, (uint8_t *)(&nullTerminator), 1);
-    }
+    SMBiosStructure(Params * p, uint8_t _type);
 
-    int getStringLength()
-    {
-        int size = 0;
-        std::vector<std::string>::iterator it;
+    std::vector<std::string> strings;
 
-        for (it = strings.begin(); it != strings.end(); it++) {
-            size += it->length() + 1;
-        }
+    void writeOutStrings(FunctionalPort * port, Addr addr);
 
-        return size + 1;
-    }
+    int getStringLength();
 
   public:
 
-    int addString(std::string & newString)
-    {
-        strings.push_back(newString);
-        return strings.size();
-    }
-
-    std::string readString(int n)
-    {
-        assert(n > 0 && n <= strings.size());
-        return strings[n - 1];
-    }
-
-    void setString(int n, std::string & newString)
-    {
-        assert(n > 0 && n <= strings.size());
-        strings[n - 1] = newString;
-    }
+    int addString(std::string & newString);
+    std::string readString(int n);
+    void setString(int n, std::string & newString);
 };
 
 class BiosInformation : public SMBiosStructure
 {
+  protected:
+    const static uint8_t Type = 0;
+
+    typedef X86SMBiosBiosInformationParams Params;
+
   public:
     // Offset 04h, 1 byte
     uint8_t vendor;
@@ -211,21 +179,25 @@ class BiosInformation : public SMBiosStructure
     // Offset 12h, 2 bytes
     uint16_t characteristicExtBytes;
     // Offset 14h, 1 byte
-    uint8_t major;
+    uint8_t majorVer;
     // Offset 15h, 1 byte
-    uint8_t minor;
+    uint8_t minorVer;
     // Offset 16h, 1 byte
     uint8_t embContFirmwareMajor;
     // Offset 17h, 1 byte
     uint8_t embContFirmwareMinor;
 
+    BiosInformation(Params * p);
+
     uint8_t getLength() { return 0x18; }
     uint16_t writeOut(FunctionalPort * port, Addr addr);
 };
 
-class SMBiosTable
+class SMBiosTable : public SimObject
 {
-  public:
+  protected:
+    typedef X86SMBiosSMBiosTableParams Params;
+
     struct SMBiosHeader
     {
         SMBiosHeader()
@@ -281,9 +253,23 @@ class SMBiosTable
         } intermediateHeader;
     } smbiosHeader;
 
-    void writeOut(FunctionalPort * port, Addr addr);
+    std::vector<SMBiosStructure *> structures;
+
+  public:
+    SMBiosTable(Params * p);
+
+    Addr getTableAddr()
+    {
+        return smbiosHeader.intermediateHeader.tableAddr;
+    }
+
+    void setTableAddr(Addr addr)
+    {
+        smbiosHeader.intermediateHeader.tableAddr = addr;
+    }
 
-    std::vector<SMBiosStructure> structures;
+    void writeOut(FunctionalPort * port, Addr addr,
+            Addr &headerSize, Addr &structSize);
 };
 
 } //SMBios
index 48f34918d019d6c5f6aa256f4ab6fe3d68088fbc..9006ce22730e1b5226f8820faed8503fac13729f 100644 (file)
@@ -73,13 +73,8 @@ using namespace LittleEndianGuest;
 using namespace X86ISA;
 
 X86System::X86System(Params *p)
-    : System(p)
-{
-    smbiosTable = new X86ISA::SMBios::SMBiosTable;
-    smbiosTable->smbiosHeader.majorVersion = 2;
-    smbiosTable->smbiosHeader.minorVersion = 5;
-    smbiosTable->smbiosHeader.intermediateHeader.smbiosBCDRevision = 0x25;
-}
+    : System(p), smbiosTable(p->smbios_table)
+{}
 
 void
 X86System::startup()
@@ -236,27 +231,33 @@ X86System::startup()
 
     // We should now be in long mode. Yay!
 
+    Addr ebdaPos = 0xF0000;
+
+    Addr headerSize, structSize;
     //Write out the SMBios/DMI table
-    writeOutSMBiosTable(0xF0000);
+    writeOutSMBiosTable(ebdaPos, headerSize, structSize);
+    ebdaPos += (headerSize + structSize);
 }
 
 void
-X86System::writeOutSMBiosTable(Addr header, Addr table)
+X86System::writeOutSMBiosTable(Addr header,
+        Addr &headerSize, Addr &structSize, Addr table)
 {
     // Get a port to write the table and header to memory.
     FunctionalPort * physPort = threadContexts[0]->getPhysPort();
 
     // If the table location isn't specified, just put it after the header.
     // The header size as of the 2.5 SMBios specification is 0x1F bytes
-    if (!table) {
-        if (!smbiosTable->smbiosHeader.intermediateHeader.tableAddr)
-            smbiosTable->smbiosHeader.
-                intermediateHeader.tableAddr = header + 0x1F;
-    } else {
-        smbiosTable->smbiosHeader.intermediateHeader.tableAddr = table;
-    }
+    if (!table)
+        table = header + 0x1F;
+    smbiosTable->setTableAddr(table);
+
+    smbiosTable->writeOut(physPort, header, headerSize, structSize);
 
-    smbiosTable->writeOut(physPort, header);
+    // Do some bounds checking to make sure we at least didn't step on
+    // ourselves.
+    assert(header > table || header + headerSize <= table);
+    assert(table > header || table + structSize <= header);
 }
 
 
index 8a5483ebf2f923996884b485ff6f748fb85973f2..2120bc0909eb9e487247cdc31f427dac4b56728a 100644 (file)
@@ -96,7 +96,8 @@ class X86System : public System
 
     X86ISA::SMBios::SMBiosTable * smbiosTable;
 
-    void writeOutSMBiosTable(Addr header, Addr table = 0);
+    void writeOutSMBiosTable(Addr header,
+            Addr &headerSize, Addr &tableSize, Addr table = 0);
 
     const Params *params() const { return (const Params *)_params; }