diff --git a/configs/common/FSConfig.py b/configs/common/FSConfig.py index 8e2b0884c..21d4311d0 100644 --- a/configs/common/FSConfig.py +++ b/configs/common/FSConfig.py @@ -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() diff --git a/src/arch/x86/X86System.py b/src/arch/x86/X86System.py index b4ec393c3..5fe69c709 100644 --- a/src/arch/x86/X86System.py +++ b/src/arch/x86/X86System.py @@ -55,10 +55,13 @@ 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' diff --git a/src/arch/x86/bios/SConscript b/src/arch/x86/bios/SConscript index 1ec717b11..cdb5f390f 100644 --- a/src/arch/x86/bios/SConscript +++ b/src/arch/x86/bios/SConscript @@ -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 index 000000000..4947b2854 --- /dev/null +++ b/src/arch/x86/bios/SMBios.py @@ -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") diff --git a/src/arch/x86/bios/smbios.cc b/src/arch/x86/bios/smbios.cc index de4a263b7..95ade1e4d 100644 --- a/src/arch/x86/bios/smbios.cc +++ b/src/arch/x86/bios/smbios.cc @@ -88,9 +88,14 @@ #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 +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::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::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; } -void -X86ISA::SMBios::SMBiosTable::writeOut(FunctionalPort * port, Addr addr) +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, + 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::iterator it; + std::vector::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); +} diff --git a/src/arch/x86/bios/smbios.hh b/src/arch/x86/bios/smbios.hh index 8d3994fc7..1c50d0b48 100644 --- a/src/arch/x86/bios/smbios.hh +++ b/src/arch/x86/bios/smbios.hh @@ -91,10 +91,15 @@ #include #include -#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: + bool stringFields; + + SMBiosStructure(Params * p, uint8_t _type); + std::vector strings; - void writeOutStrings(FunctionalPort * port, Addr addr) - { - std::vector::iterator it; - Addr offset = 0; + void writeOutStrings(FunctionalPort * port, Addr addr); - for (it = strings.begin(); it != strings.end(); it++) { - port->writeBlob(addr + offset, - (uint8_t *)it->c_str(), it->length() + 1); - offset += it->length() + 1; - } - - const uint8_t nullTerminator = 0; - port->writeBlob(addr + offset, (uint8_t *)(&nullTerminator), 1); - } - - int getStringLength() - { - int size = 0; - std::vector::iterator it; - - for (it = strings.begin(); it != strings.end(); it++) { - size += it->length() + 1; - } - - 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 structures; - std::vector structures; + public: + SMBiosTable(Params * p); + + Addr getTableAddr() + { + return smbiosHeader.intermediateHeader.tableAddr; + } + + void setTableAddr(Addr addr) + { + smbiosHeader.intermediateHeader.tableAddr = addr; + } + + void writeOut(FunctionalPort * port, Addr addr, + Addr &headerSize, Addr &structSize); }; } //SMBios diff --git a/src/arch/x86/system.cc b/src/arch/x86/system.cc index 48f34918d..9006ce227 100644 --- a/src/arch/x86/system.cc +++ b/src/arch/x86/system.cc @@ -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); + smbiosTable->writeOut(physPort, header, headerSize, structSize); + + // 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); } diff --git a/src/arch/x86/system.hh b/src/arch/x86/system.hh index 8a5483ebf..2120bc090 100644 --- a/src/arch/x86/system.hh +++ b/src/arch/x86/system.hh @@ -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; }