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