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 <cstring>
00024 #include <sstream>
00025 #include <iomanip>
00026
00027 #include "SmbiosXmlImpl.h"
00028 #include "StdSmbiosXml.h"
00029 #include "FactoryImpl2.h"
00030 #include "XmlUtils.h"
00031
00032
00033 #include "smbios/message.h"
00034
00035
00036 SETUP_XML_NAMESPACE
00037
00038 using namespace std;
00039 using namespace smbiosLowlevel;
00040 using namespace xmlutils;
00041
00042 #if defined(DEBUG_SMBIOSXML)
00043 # define DCOUT(line) do { cout << line; } while(0)
00044 # define DCERR(line) do { cerr << line; } while(0)
00045 #else
00046 # define DCOUT(line) do {} while(0)
00047 # define DCERR(line) do {} while(0)
00048 #endif
00049
00050 namespace smbios
00051 {
00052
00053
00054
00055 SmbiosXmlFactory::~SmbiosXmlFactory() throw()
00056 {}
00057
00058 class SmbiosXmlFactoryImpl: public SmbiosFactoryImpl
00059 {
00060 public:
00061 virtual ISmbiosTable *makeNew();
00062 SmbiosXmlFactoryImpl() : SmbiosFactoryImpl() {};
00063 virtual ~SmbiosXmlFactoryImpl() throw () {};
00064 };
00065
00066 SmbiosFactory *SmbiosXmlFactory::getFactory()
00067 {
00068
00069
00070
00071 return SmbiosFactoryImpl::getFactory(reinterpret_cast<SmbiosXmlFactoryImpl *>(0));
00072 }
00073
00074 ISmbiosTable *SmbiosXmlFactoryImpl::makeNew()
00075 {
00076
00077 bool strict = getParameterNum("strictValidation") ? 1 : 0;
00078
00079 SmbiosTableXml *table = 0;
00080
00081 std::vector<SmbiosStrategy *> strategies;
00082
00083 if (mode == AutoDetectMode)
00084 {
00085 strategies.push_back( new SmbiosMemoryStrategy(getParameterNum("offset")) );
00086 #ifdef LIBSMBIOS_PLATFORM_WIN32
00087 strategies.push_back( new SmbiosWinGetFirmwareTableStrategy() );
00088 strategies.push_back( new SmbiosWinWMIStrategy() );
00089 #endif
00090 }
00091 else if (mode == UnitTestMode)
00092 {
00093 strategies.push_back( new SmbiosMemoryStrategy(getParameterNum("offset")) );
00094 }
00095 else
00096 {
00097 throw NotImplementedImpl(_("Unknown smbios factory mode requested"));
00098 }
00099
00100
00101 table = new SmbiosTableXml(
00102 strategies,
00103 strict
00104 );
00105 table->setXmlFilePath( getParameterString("xmlFile") );
00106 table->initializeWorkaround();
00107 return table;
00108 }
00109
00110
00111
00112
00113
00114 DOMDocument *getSmbiosXmlDoc( DOMBuilder *parser, std::string &xmlFile )
00115 {
00116 DOMDocument *doc = 0;
00117
00118
00119 DCERR("Trying to parse file: '" << xmlFile << "'" << endl);
00120
00121 compatXmlReadFile(parser, doc, xmlFile.c_str());
00122
00123 if (!doc)
00124 {
00125 DCERR("Parse failed, no valid doc. Trying internal XML." << endl);
00126
00127 compatXmlReadMemory(parser, doc, stdXml, strlen(stdXml));
00128 }
00129
00130 if (!doc)
00131 {
00132 DCERR("Bad stuff... file parse failed and internal failed." << endl);
00133 throw ParseExceptionImpl("problem parsing xml file.");
00134 }
00135
00136 DCERR("Returning doc."<< endl);
00137 return doc;
00138 }
00139
00140 void validateSmbiosXmlDoc( DOMDocument *doc )
00141 {
00142 xmlNodePtr cur = xmlDocGetRootElement(doc);
00143
00144 if (cur == NULL)
00145 {
00146 fprintf(stderr,"empty document\n");
00147 xmlFreeDoc(doc);
00148 throw ParseExceptionImpl("problem parsing xml file. empty document.");
00149 }
00150
00151 if (xmlStrcmp(cur->name, reinterpret_cast<const xmlChar *>("STRUCTUREDEFS")))
00152 {
00153 fprintf(stderr,"document of the wrong type, root node != story");
00154 xmlFreeDoc(doc);
00155 throw ParseExceptionImpl("problem parsing xml file. root doc name not STRUCTUREDEFS.");
00156 }
00157 }
00158
00159 unsigned int parseLengthStr(string size)
00160 {
00161 if (size == "BYTE")
00162 return 1;
00163 else if (size == "WORD")
00164 return 2;
00165 else if (size == "DWORD")
00166 return 4;
00167 else if (size == "QWORD")
00168 return 8;
00169
00170 return strtol(size.c_str(), NULL, 0);
00171
00172
00173 }
00174
00175 void verifyElementAttr( const DOMElement *element, const string elementName, const string value )
00176 {
00177 string xmlValue = safeGetAttribute( element, elementName );
00178 if( value != xmlValue )
00179 throw ParseExceptionImpl("could not verify element attribute.");
00180 }
00181
00182
00183 void verifyElementAttr( const DOMElement *element, const string elementName, unsigned int size )
00184 {
00185 string xmlValue = safeGetAttribute( element, elementName );
00186 if( size != parseLengthStr(xmlValue) )
00187 throw ParseExceptionImpl("could not verify element attribute was correct size.");
00188 }
00189
00190 int getTypeForString( DOMDocument *doc, const string searchForDesc )
00191 {
00192
00193 DOMElement *elem = findElement( xmlDocGetRootElement(doc), "STRUCTURE", "description", searchForDesc );
00194
00195
00196 return strtol( safeGetAttribute( elem, "type" ).c_str(), 0, 0);
00197 }
00198
00199 const string getStringForType(const DOMDocument *doc, const int searchForType )
00200 {
00201
00202 DOMElement *elem = 0;
00203 try
00204 {
00205 elem = findElementWithNumericAttr( xmlDocGetRootElement(doc), "STRUCTURE", "type", searchForType);
00206 }
00207 catch(const NotFound &)
00208 {
00209 elem = findElement( xmlDocGetRootElement(doc), "STRUCTURE", "type", "unknown");
00210 }
00211
00212
00213 return safeGetAttribute( elem, "description");
00214 }
00215
00216
00217
00218
00219
00220
00221
00222
00223 SmbiosTableXml::SmbiosTableXml()
00224 : SmbiosTable(), xmlFile(""), parser(0), doc(0), xmlInitialized(false)
00225 {
00226 CHECK_VERSION_COMPAT;
00227 setXmlFilePath(xmlFile);
00228 }
00229
00230 SmbiosTableXml::SmbiosTableXml(std::vector<SmbiosStrategy *> initStrategyList, bool strictValidation)
00231 : SmbiosTable(initStrategyList, strictValidation), xmlFile(""), parser(0), doc(0), xmlInitialized(false)
00232 {
00233 CHECK_VERSION_COMPAT;
00234 setXmlFilePath(xmlFile);
00235 }
00236
00237
00238 SmbiosTableXml::~SmbiosTableXml()
00239 {
00240 if (parser)
00241 xmlFreeParser(parser);
00242
00243 if (doc)
00244 xmlFreeDoc(doc);
00245
00246 if( xmlInitialized )
00247 FiniXML();
00248 }
00249
00250
00251
00252
00253
00254
00255 void SmbiosTableXml::setXmlFilePath( std::string newFile )
00256 {
00257 try
00258 {
00259
00260 if( ! xmlInitialized )
00261 InitXML();
00262
00263 xmlInitialized = true;
00264
00265 DOMBuilder *newParser = getParser();
00266 DOMDocument *newdoc = getSmbiosXmlDoc( newParser, newFile );
00267 validateSmbiosXmlDoc( newdoc );
00268
00269
00270
00271 if (parser)
00272 xmlFreeParser(parser);
00273
00274 if (doc)
00275 xmlFreeDoc(doc);
00276
00277 parser = newParser;
00278 xmlFile = newFile;
00279 doc = newdoc;
00280 }
00281 catch(const exception &toCatch)
00282 {
00283 cerr << "Error during XML Initialization.\n"
00284 << " Exception message:"
00285 << toCatch.what() << endl;
00286 throw ParseExceptionImpl("XML initialization failed.");
00287 }
00288 }
00289
00290 const DOMDocument *SmbiosTableXml::getXmlDoc() const
00291 {
00292 return doc;
00293 }
00294
00295 int SmbiosTableXml::getTypeForString( const string searchForDesc ) const
00296 {
00297 return smbios::getTypeForString( doc, searchForDesc );
00298 }
00299
00300
00301 const string SmbiosTableXml::getStringForType( const int searchForType ) const
00302 {
00303 return smbios::getStringForType( doc, searchForType );
00304 }
00305
00306
00307
00308
00309 SmbiosTable::iterator SmbiosTableXml::operator[] (const string &searchFor)
00310 {
00311 int type = getTypeForString( searchFor );
00312 return SmbiosTable::iterator (this, type);
00313 }
00314
00315
00316
00317
00318 SmbiosTable::const_iterator SmbiosTableXml::operator[](const string &searchFor) const
00319 {
00320
00321 int type = getTypeForString( searchFor );
00322 return SmbiosTable::const_iterator (this, type);
00323 }
00324
00325
00326 static void getData_UsingXml(const ISmbiosItem &item, const string fieldName, void *out, size_t size )
00327 {
00328 DOMElement *element = 0;
00329
00330 smbios::ISmbiosTable *table =
00331 smbios::SmbiosFactory::getFactory()->getSingleton();
00332
00333 const SmbiosTableXml *tableXml = dynamic_cast<const SmbiosTableXml *>(table);
00334 if(!tableXml)
00335 throw NotImplementedImpl();
00336
00337 const DOMDocument *doc = tableXml->getXmlDoc();
00338
00339
00340 DOMElement *Structure = findElementWithNumericAttr( xmlDocGetRootElement(doc), "STRUCTURE", "type", item.getType() );
00341 element = findElement( Structure, "FIELD", "name", fieldName );
00342
00343
00344 verifyElementAttr( element, "length", size );
00345
00346
00347 item.getData( getNumberFromXmlAttr(element, "offset", 0), out, size );
00348 }
00349
00350 u8 getU8_FromItem(const ISmbiosItem &item, std::string field)
00351 {
00352 u8 retval = 0;
00353 getData_UsingXml(item, field, reinterpret_cast<u8 *>(&retval), sizeof(retval));
00354 return retval;
00355 }
00356
00357 u16 getU16_FromItem(const ISmbiosItem &item, std::string field)
00358 {
00359 u16 retval = 0;
00360 getData_UsingXml(item, field, reinterpret_cast<u8 *>(&retval), sizeof(retval));
00361 return retval;
00362 }
00363
00364 u32 getU32_FromItem(const ISmbiosItem &item, std::string field)
00365 {
00366 u32 retval = 0;
00367 getData_UsingXml(item, field, reinterpret_cast<u8 *>(&retval), sizeof(retval));
00368 return retval;
00369 }
00370
00371 u64 getU64_FromItem(const ISmbiosItem &item, std::string field)
00372 {
00373 u64 retval = 0;
00374 getData_UsingXml(item, field, reinterpret_cast<u8 *>(&retval), sizeof(retval));
00375 return retval;
00376 }
00377
00378 const char *getString_FromItem(const ISmbiosItem &item, std::string field)
00379 {
00380 DOMElement *element = 0;
00381
00382 smbios::ISmbiosTable *table =
00383 smbios::SmbiosFactory::getFactory()->getSingleton();
00384
00385 const SmbiosTableXml *tableXml = dynamic_cast<const SmbiosTableXml *>(table);
00386 if(!tableXml)
00387 throw NotImplementedImpl();
00388
00389 const DOMDocument *doc = tableXml->getXmlDoc();
00390
00391
00392 DOMElement *Structure = findElementWithNumericAttr( xmlDocGetRootElement(doc), "STRUCTURE", "type", item.getType() );
00393 element = findElement( Structure, "FIELD", "name", field );
00394
00395
00396 verifyElementAttr( element, "length", 1 );
00397
00398
00399 verifyElementAttr( element, "usage", "STRING" );
00400
00401
00402 return getString_FromItem(item, getNumberFromXmlAttr(element, "offset", 0) );
00403 }
00404
00405 void *getBits_FromItem(const ISmbiosItem &item, const string field, const string bitField, void *out)
00406 {
00407 DOMElement *bitElement = 0;
00408 DOMElement *fieldElement = 0;
00409
00410 smbios::ISmbiosTable *table =
00411 smbios::SmbiosFactory::getFactory()->getSingleton();
00412
00413 const SmbiosTableXml *tableXml = dynamic_cast<const SmbiosTableXml *>(table);
00414 if(!tableXml)
00415 throw NotImplementedImpl();
00416
00417 const DOMDocument *doc = tableXml->getXmlDoc();
00418
00419 try
00420 {
00421 DOMElement *Structure = findElementWithNumericAttr( xmlDocGetRootElement(doc), "STRUCTURE", "type", item.getType() );
00422 fieldElement = findElement( Structure, "FIELD", "name", field );
00423 bitElement = findElement( fieldElement, "BITS", "name", bitField );
00424 }
00425 catch (const NotFound & )
00426 {
00427 throw ParseExceptionImpl("could not fine bitfield name in xml file.");
00428 }
00429
00430
00431 return getBits_FromItem(item,
00432 getNumberFromXmlAttr(fieldElement, "offset", 0),
00433 out,
00434 getNumberFromXmlAttr(bitElement, "lsb", 0),
00435 getNumberFromXmlAttr(bitElement, "msb", 0)
00436 );
00437 }
00438
00439 void printStructureField( std::ostream &cout, const DOMNode *node, const ISmbiosItem &item )
00440 {
00441 std::ios::fmtflags old_opts = cout.flags ();
00442 try
00443 {
00444 unsigned int length = parseLengthStr(safeGetAttribute( node, "length" ));
00445 string strOffset = safeGetAttribute( node, "offset" );
00446 unsigned int offset = strtol( strOffset.c_str(), 0, 0 );
00447
00448 string usage = safeGetAttribute( node, "usage" );
00449 if (usage == "STRING")
00450 {
00451 try
00452 {
00453 cout << getString_FromItem(item, offset);
00454 }
00455 catch(const StringUnavailable &)
00456 {
00457 }
00458 }
00459 else
00460 {
00461 cout << hex << "0x";
00462 for(unsigned int i=0;i<length; i++)
00463 {
00464 cout << setfill('0') << setw(2) <<
00465 static_cast<int>(getU8_FromItem(item, offset + length - i - 1));
00466 }
00467 }
00468 }
00469 catch( const std::exception & )
00470 {
00471 cout.flags (old_opts);
00472 throw;
00473 }
00474 cout.flags (old_opts);
00475 }
00476
00477 std::ostream &SmbiosTableXml::streamify(ostream & cout) const
00478 {
00479 cout << "\nSMBIOS table " << endl;
00480 cout << "\tversion : ";
00481 cout << static_cast<int>(table_header.major_ver) << ".";
00482 cout << static_cast<int>(table_header.minor_ver) << endl;
00483 cout << hex ;
00484 cout << "\taddress : " << table_header.dmi.table_address << endl;
00485 cout << dec;
00486 cout << "\tlength : " << table_header.dmi.table_length << endl;
00487 cout << "\tnum structs: " << table_header.dmi.table_num_structs << endl;
00488 cout << endl;
00489
00490 SmbiosTable::const_iterator position = begin();
00491 while (position != end())
00492 {
00493 cout << *position << endl;
00494 ++position;
00495 }
00496 return cout;
00497 }
00498
00499
00500
00501
00502
00503
00504 std::ostream &toXmlString(const ISmbiosTable &table, ostream & cout)
00505 {
00506 UNREFERENCED_PARAMETER(table);
00507 cout << "XML output not yet supported in std lib." << endl;
00508 return cout;
00509 }
00510
00511 }