00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #define LIBSMBIOS_SOURCE
00021 #include "smbios/compat.h"
00022
00023 #include <sstream>
00024 #include <iomanip>
00025
00026 #include "SmbiosXmlImpl_xerces.h"
00027 #include "StdSmbiosXml.h"
00028 #include "../common/FactoryImpl2.h"
00029 #include "../smbios/SmbiosImpl.h"
00030 #include "../common/XmlUtils.h"
00031
00032
00033 #include "smbios/message.h"
00034
00035 XERCES_CPP_NAMESPACE_USE;
00036 using namespace std;
00037 using namespace smbiosLowlevel;
00038 using namespace xmlutils;
00039
00040 namespace smbios
00041 {
00042
00043
00044
00045
00046 class SmbiosXmlFactoryImpl: public SmbiosFactoryImpl
00047 {
00048 public:
00049 virtual ISmbiosTable *makeNew();
00050 SmbiosXmlFactoryImpl() : SmbiosFactoryImpl() {};
00051 virtual ~SmbiosXmlFactoryImpl() throw () {};
00052 };
00053
00054 SmbiosFactory *SmbiosXmlFactory::getFactory()
00055 {
00056
00057
00058
00059 return SmbiosFactoryImpl::getFactory(reinterpret_cast<SmbiosXmlFactoryImpl *>(0));
00060 }
00061
00062 ISmbiosTable *SmbiosXmlFactoryImpl::makeNew()
00063 {
00064
00065 bool strict = getParameterNum("strictValidation") ? 1 : 0;
00066
00067 SmbiosTableXml *table = 0;
00068
00069 std::vector<SmbiosStrategy *> strategies;
00070
00071 if (mode == AutoDetectMode)
00072 {
00073 strategies.push_back( new SmbiosMemoryStrategy(getParameterNum("offset")) );
00074 #ifdef LIBSMBIOS_PLATFORM_WIN32
00075 strategies.push_back( new SmbiosWinGetFirmwareTableStrategy() );
00076 strategies.push_back( new SmbiosWinWMIStrategy() );
00077 #endif
00078 }
00079 else if (mode == UnitTestMode)
00080 {
00081 strategies.push_back( new SmbiosMemoryStrategy(getParameterNum("offset")) );
00082 }
00083 else
00084 {
00085 throw NotImplementedImpl(_("Unknown smbios factory mode requested"));
00086 }
00087
00088
00089 table = new SmbiosTableXml(
00090 strategies,
00091 strict
00092 );
00093 table->setXmlFilePath( getParameterString("xmlFile") );
00094 table->initializeWorkaround();
00095 return table;
00096 }
00097
00098
00099
00100
00101
00102 DOMDocument *getSmbiosXmlDoc( DOMBuilder *parser, std::string &xmlFile )
00103 {
00104 DOMDocument *doc = 0;
00105
00106 try
00107 {
00108 doc = parser->parseURI( xmlFile.c_str() );
00109 }
00110
00111
00112 catch( const std::exception & )
00113 {
00114 cerr << "Error during Xerces-c parsing.\n";
00115 cerr << "Falling back to builtin XML." << endl;
00116 }
00117
00118
00119 if( doc == 0 )
00120 {
00121 try
00122 {
00123
00124 size_t fileLen = strlen(stdXml);
00125 unsigned int *lenPtr = reinterpret_cast<unsigned int *>(&fileLen);
00126 MemBufInputSource* memBufIs = new MemBufInputSource(
00127 reinterpret_cast<const XMLByte*>(stdXml),
00128 *lenPtr,
00129 "standard_xml",
00130 false
00131 );
00132
00133
00134
00135 DOMInputSource* Is = new Wrapper4InputSource( memBufIs );
00136
00137 doc = parser->parse( *Is );
00138
00139 delete Is;
00140 }
00141
00142
00143 catch( const std::exception & )
00144 {
00145 cerr << "Error during Xerces-c parsing builin XML.\n";
00146 cerr << "This is really bad and probably not recoverable." << endl;
00147 throw ParseExceptionImpl("problem parsing xml file.");
00148 }
00149
00150 }
00151
00152 return doc;
00153 }
00154
00155 void validateSmbiosXmlDoc( DOMDocument *doc )
00156 {
00157 if( doc )
00158 {
00159 DOMElement *root = doc->getDocumentElement();
00160
00161
00162
00163
00164 string name = safeXMLChToString( root->getNodeName() );
00165 if ( ! (name == "STRUCTUREDEFS") )
00166 throw ParseExceptionImpl("problem parsing xml file. root doc name not STRUCTUREDEFS.");
00167 }
00168 }
00169
00170 unsigned int parseLengthStr(string size)
00171 {
00172 if (size == "BYTE")
00173 return 1;
00174 else if (size == "WORD")
00175 return 2;
00176 else if (size == "DWORD")
00177 return 4;
00178 else if (size == "QWORD")
00179 return 8;
00180
00181 return strtol(size.c_str(), NULL, 0);
00182
00183
00184 }
00185
00186 void verifyElementAttr( DOMElement *element, const string elementName, const string value )
00187 {
00188 string xmlValue = safeGetAttribute( element, elementName );
00189 if( value != xmlValue )
00190 throw ParseExceptionImpl("could not verify element attribute.");
00191 }
00192
00193
00194 void verifyElementAttr( DOMElement *element, const string elementName, unsigned int size )
00195 {
00196 string xmlValue = safeGetAttribute( element, elementName );
00197 if( size != parseLengthStr(xmlValue) )
00198 throw ParseExceptionImpl("could not verify element attribute was correct size.");
00199 }
00200
00201 int getTypeForString( DOMDocument *doc, const string searchForDesc )
00202 {
00203
00204 DOMElement *elem = findElement( doc->getDocumentElement(), "STRUCTURE", "description", searchForDesc );
00205
00206
00207 return strtol( safeGetAttribute( elem, "type" ).c_str(), 0, 0);
00208 }
00209
00210 const string getStringForType(const DOMDocument *doc, const int searchForType )
00211 {
00212
00213 DOMElement *elem = 0;
00214 try
00215 {
00216 elem = findElementWithNumericAttr( doc->getDocumentElement(), "STRUCTURE", "type", searchForType);
00217 }
00218 catch(const NotFound &)
00219 {
00220 elem = findElement( doc->getDocumentElement(), "STRUCTURE", "type", "unknown");
00221 }
00222
00223
00224 return safeGetAttribute( elem, "description");
00225 }
00226
00227
00228
00229
00230
00231
00232
00233
00234 SmbiosTableXml::SmbiosTableXml()
00235 : SmbiosTable(), xmlFile(""), parser(0), doc(0), xmlInitialized(false)
00236 {
00237 setXmlFilePath(xmlFile);
00238 }
00239
00240 SmbiosTableXml::SmbiosTableXml(std::vector<SmbiosStrategy *> initStrategyList, bool strictValidation)
00241 : SmbiosTable(initStrategyList, strictValidation), xmlFile(""), parser(0), doc(0), xmlInitialized(false)
00242 {
00243 setXmlFilePath(xmlFile);
00244 }
00245
00246
00247 SmbiosTableXml::~SmbiosTableXml()
00248 {
00249 if(parser)
00250 {
00251 parser->resetDocumentPool();
00252 parser->release();
00253 parser = 0;
00254 doc = 0;
00255 }
00256 if( xmlInitialized )
00257 XMLPlatformUtils::Terminate();
00258 }
00259
00260 ISmbiosItem &SmbiosTableXml::makeItem(const void *header) const
00261 {
00262
00263 const smbios_structure_header *structure =
00264 reinterpret_cast<const smbios_structure_header *>(header);
00265 SmbiosItemXml *item = new SmbiosItemXml( structure );
00266 item->setXmlFilePath( xmlFile, doc );
00267 if( ! initializing )
00268 {
00269 dynamic_cast<SmbiosItem*>(item)->fixup( workaround.get() );
00270 }
00271 return *item;
00272 }
00273
00274
00275
00276
00277
00278
00279 void SmbiosTableXml::setXmlFilePath( std::string newFile )
00280 {
00281 try
00282 {
00283
00284 if( ! xmlInitialized )
00285 XMLPlatformUtils::Initialize();
00286
00287 xmlInitialized = true;
00288
00289 DOMBuilder *newParser = getParser();
00290 DOMDocument *newdoc = getSmbiosXmlDoc( newParser, newFile );
00291 validateSmbiosXmlDoc( newdoc );
00292
00293
00294
00295
00296
00297 DOMBuilder *oldParser = parser;
00298
00299 parser = newParser;
00300 xmlFile = newFile;
00301 doc = newdoc;
00302
00303 if( oldParser )
00304 {
00305 oldParser->resetDocumentPool();
00306 oldParser->release();
00307 }
00308 }
00309 catch(const XMLException &toCatch)
00310 {
00311 cerr << "Error during Xerces-c Initialization.\n"
00312 << " Exception message:"
00313 << toCatch.getMessage() << endl;
00314 throw ParseExceptionImpl("xerces initialization failed.");
00315 }
00316 }
00317
00318 const DOMDocument *SmbiosTableXml::getXmlDoc() const
00319 {
00320 return doc;
00321 }
00322
00323 int SmbiosTableXml::getTypeForString( const string searchForDesc ) const
00324 {
00325 return smbios::getTypeForString( doc, searchForDesc );
00326 }
00327
00328
00329 const string SmbiosTableXml::getStringForType( const int searchForType ) const
00330 {
00331 return smbios::getStringForType( doc, searchForType );
00332 }
00333
00334
00335
00336
00337 SmbiosTable::iterator SmbiosTableXml::operator[] (const string &searchFor)
00338 {
00339 int type = getTypeForString( searchFor );
00340 return SmbiosTable::iterator (this, type);
00341 }
00342
00343
00344
00345
00346 SmbiosTable::const_iterator SmbiosTableXml::operator[](const string &searchFor) const
00347 {
00348
00349 int type = getTypeForString( searchFor );
00350 return SmbiosTable::const_iterator (this, type);
00351 }
00352
00353
00354
00355
00356
00357 void SmbiosItemXml::setXmlFilePath( const std::string newFile, XERCES_CPP_NAMESPACE_QUALIFIER DOMDocument *newDoc )
00358 {
00359 xmlFile = newFile;
00360 doc = newDoc;
00361 }
00362
00363 u8 SmbiosItemXml::getU8( const string fieldName ) const
00364 {
00365 DOMElement *element = 0;
00366
00367
00368 DOMElement *Structure = findElementWithNumericAttr( doc->getDocumentElement(), "STRUCTURE", "type", getType() );
00369 element = findElement( Structure, "FIELD", "name", fieldName );
00370
00371
00372 verifyElementAttr( element, "length", 1 );
00373
00374
00375 return SmbiosItem::getU8( getNumberFromXmlAttr(element, "offset", 0) );
00376 }
00377
00378 u16 SmbiosItemXml::getU16( const string fieldName ) const
00379 {
00380 DOMElement *element = 0;
00381
00382
00383 DOMElement *Structure = findElementWithNumericAttr( doc->getDocumentElement(), "STRUCTURE", "type", getType() );
00384 element = findElement( Structure, "FIELD", "name", fieldName );
00385
00386
00387 verifyElementAttr( element, "length", 2 );
00388
00389
00390 return SmbiosItem::getU16( getNumberFromXmlAttr(element, "offset", 0) );
00391 }
00392
00393 u32 SmbiosItemXml::getU32( const string fieldName ) const
00394 {
00395 DOMElement *element = 0;
00396
00397
00398 DOMElement *Structure = findElementWithNumericAttr( doc->getDocumentElement(), "STRUCTURE", "type", getType() );
00399 element = findElement( Structure, "FIELD", "name", fieldName );
00400
00401
00402 verifyElementAttr( element, "length", 4 );
00403
00404
00405 return SmbiosItem::getU32( getNumberFromXmlAttr(element, "offset", 0) );
00406 }
00407
00408 u64 SmbiosItemXml::getU64( const string fieldName ) const
00409 {
00410 DOMElement *element = 0;
00411
00412
00413 DOMElement *Structure = findElementWithNumericAttr( doc->getDocumentElement(), "STRUCTURE", "type", getType() );
00414 element = findElement( Structure, "FIELD", "name", fieldName );
00415
00416
00417 verifyElementAttr( element, "length", 8 );
00418
00419
00420 return SmbiosItem::getU64( getNumberFromXmlAttr(element, "offset", 0) );
00421 }
00422
00423 u32 SmbiosItemXml::getBitfield( const string field, const string bitField) const
00424 {
00425 DOMElement *bitElement = 0;
00426 DOMElement *fieldElement = 0;
00427
00428 try
00429 {
00430 DOMElement *Structure = findElementWithNumericAttr( doc->getDocumentElement(), "STRUCTURE", "type", getType() );
00431 fieldElement = findElement( Structure, "FIELD", "name", field );
00432 bitElement = findElement( fieldElement, "BITS", "name", bitField );
00433 }
00434 catch (const NotFound & )
00435 {
00436 throw ParseExceptionImpl("could not fine bitfield name in xml file.");
00437 }
00438
00439
00440 string length = safeGetAttribute( fieldElement, "length" );
00441 unsigned int lengthVal = 0;
00442 lengthVal = parseLengthStr(length);
00443
00444
00445 return SmbiosItem::getBitfield(
00446 getNumberFromXmlAttr(fieldElement, "offset", 0),
00447 lengthVal,
00448 getNumberFromXmlAttr(bitElement, "lsb", 0),
00449 getNumberFromXmlAttr(bitElement, "msb", 0)
00450 );
00451 }
00452
00453 const char* SmbiosItemXml::getString( const string fieldName ) const
00454 {
00455 DOMElement *element = 0;
00456
00457
00458 DOMElement *Structure = findElementWithNumericAttr( doc->getDocumentElement(), "STRUCTURE", "type", getType() );
00459 element = findElement( Structure, "FIELD", "name", fieldName );
00460
00461
00462 verifyElementAttr( element, "length", 1 );
00463
00464
00465 verifyElementAttr( element, "usage", "STRING" );
00466
00467
00468 return SmbiosItem::getString( getNumberFromXmlAttr(element, "offset", 0) );
00469 }
00470
00471 bool isBitSet(const ISmbiosItem *itemPtr, unsigned int offset, unsigned int bitToTest)
00472 {
00473 bool retval = false;
00474
00475 unsigned int byte = bitToTest / 8;
00476 u8 fieldValue = itemPtr->getU8( offset + byte );
00477 if (fieldValue & (1 << (bitToTest%8)))
00478 retval = true;
00479
00480 return retval;
00481 }
00482
00483
00484 void printStructureField( std::ostream &cout, const DOMNode *node, const ISmbiosItem &item )
00485 {
00486 std::ios::fmtflags old_opts = cout.flags ();
00487 try
00488 {
00489 unsigned int length = parseLengthStr(safeGetAttribute( node, "length" ));
00490 string strOffset = safeGetAttribute( node, "offset" );
00491 unsigned int offset = strtol( strOffset.c_str(), 0, 0 );
00492
00493 string usage = safeGetAttribute( node, "usage" );
00494 if (usage == "STRING")
00495 {
00496 try
00497 {
00498 cout << item.getString( offset );
00499 }
00500 catch(const StringUnavailable &)
00501 {
00502 }
00503 }
00504 else
00505 {
00506 cout << hex << "0x";
00507 for(unsigned int i=0;i<length; i++)
00508 {
00509 cout << setfill('0') << setw(2) <<
00510 static_cast<int>(item.getU8(offset + length - i - 1));
00511 }
00512 }
00513 }
00514 catch( const std::exception & )
00515 {
00516 cout.flags (old_opts);
00517 throw;
00518 }
00519 cout.flags (old_opts);
00520 }
00521
00522 std::ostream &SmbiosItemXml::streamify( std::ostream &cout ) const
00523 {
00524
00525 if( ! doc )
00526 return SmbiosItem::streamify(cout);
00527
00528 if (header == 0)
00529 {
00530
00531 cout << "operator << on an uninitialized SmbiosItem!";
00532 return cout;
00533 }
00534
00535 std::ios::fmtflags old_opts = cout.flags ();
00536
00537 DOMElement *Structure = 0;
00538 cout << "DMI BLOCK: " << flush;
00539 try
00540 {
00541 cout << smbios::getStringForType( doc, getType() ) << endl;;
00542 Structure = findElementWithNumericAttr( doc->getDocumentElement(), "STRUCTURE", "type", getType());
00543 }
00544 catch ( const NotFound & )
00545 {
00546 Structure = findElement(doc->getDocumentElement(), "STRUCTURE", "type", "unknown");
00547 }
00548
00549 XMLCh *tagName = X("FIELD");
00550 DOMNodeList *fieldList = Structure->getElementsByTagName(tagName);
00551 XMLString::release(&tagName);
00552
00553 if( !fieldList )
00554 return cout;
00555
00556 int length = fieldList->getLength();
00557 for( int index = 0; index < length; ++index )
00558 {
00559 DOMNode *node = fieldList->item( index );
00560 if( node->getNodeType() == DOMNode::ELEMENT_NODE )
00561 {
00562 ostringstream tmpBuf("");
00563 tmpBuf << "\t";
00564 tmpBuf << safeGetAttribute( node, "name" );
00565 tmpBuf << ": \t" ;
00566 try
00567 {
00568 printStructureField( tmpBuf, node, *this );
00569 }
00570 catch(const exception &)
00571 {
00572 continue;
00573 }
00574 cout << tmpBuf.str() << endl;
00575 }
00576 }
00577
00578 cout.flags (old_opts);
00579 return cout;
00580 }
00581
00582 std::ostream &SmbiosTableXml::streamify(ostream & cout) const
00583 {
00584 cout << "\nSMBIOS table " << endl;
00585 cout << "\tversion : ";
00586 cout << static_cast<int>(table_header.major_ver) << ".";
00587 cout << static_cast<int>(table_header.minor_ver) << endl;
00588 cout << hex ;
00589 cout << "\taddress : " << table_header.table_address << endl;
00590 cout << dec;
00591 cout << "\tlength : " << table_header.table_length << endl;
00592 cout << "\tnum structs: " << table_header.table_num_structs << endl;
00593 cout << endl;
00594
00595 SmbiosTable::const_iterator position = begin();
00596 while (position != end())
00597 {
00598 cout << *position << endl;
00599 ++position;
00600 }
00601 return cout;
00602 }
00603
00604
00605
00606
00607
00608
00609 std::ostream &toXmlString(const ISmbiosTable &table, ostream & cout)
00610 {
00611 UNREFERENCED_PARAMETER(table);
00612 cout << "XML output not yet supported in std lib." << endl;
00613 return cout;
00614 }
00615
00616 }