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 if( doc )
00142 {
00143 DOMElement *root = xmlDocGetRootElement(doc);
00144
00145
00146
00147
00148 string name = safeXMLChToString( root->getNodeName() );
00149 if ( ! (name == "STRUCTUREDEFS") )
00150 throw ParseExceptionImpl("problem parsing xml file. root doc name not STRUCTUREDEFS.");
00151 }
00152 }
00153
00154 unsigned int parseLengthStr(string size)
00155 {
00156 if (size == "BYTE")
00157 return 1;
00158 else if (size == "WORD")
00159 return 2;
00160 else if (size == "DWORD")
00161 return 4;
00162 else if (size == "QWORD")
00163 return 8;
00164
00165 return strtol(size.c_str(), NULL, 0);
00166
00167
00168 }
00169
00170 void verifyElementAttr( const DOMElement *element, const string elementName, const string value )
00171 {
00172 string xmlValue = safeGetAttribute( element, elementName );
00173 if( value != xmlValue )
00174 throw ParseExceptionImpl("could not verify element attribute.");
00175 }
00176
00177
00178 void verifyElementAttr( const DOMElement *element, const string elementName, unsigned int size )
00179 {
00180 string xmlValue = safeGetAttribute( element, elementName );
00181 if( size != parseLengthStr(xmlValue) )
00182 throw ParseExceptionImpl("could not verify element attribute was correct size.");
00183 }
00184
00185 int getTypeForString( DOMDocument *doc, const string searchForDesc )
00186 {
00187
00188 DOMElement *elem = findElement( xmlDocGetRootElement(doc), "STRUCTURE", "description", searchForDesc );
00189
00190
00191 return strtol( safeGetAttribute( elem, "type" ).c_str(), 0, 0);
00192 }
00193
00194 const string getStringForType(const DOMDocument *doc, const int searchForType )
00195 {
00196
00197 DOMElement *elem = 0;
00198 try
00199 {
00200 elem = findElementWithNumericAttr( xmlDocGetRootElement(doc), "STRUCTURE", "type", searchForType);
00201 }
00202 catch(const NotFound &)
00203 {
00204 elem = findElement( xmlDocGetRootElement(doc), "STRUCTURE", "type", "unknown");
00205 }
00206
00207
00208 return safeGetAttribute( elem, "description");
00209 }
00210
00211
00212
00213
00214
00215
00216
00217
00218 SmbiosTableXml::SmbiosTableXml()
00219 : SmbiosTable(), xmlFile(""), parser(0), doc(0), xmlInitialized(false)
00220 {
00221 CHECK_VERSION_COMPAT;
00222 setXmlFilePath(xmlFile);
00223 }
00224
00225 SmbiosTableXml::SmbiosTableXml(std::vector<SmbiosStrategy *> initStrategyList, bool strictValidation)
00226 : SmbiosTable(initStrategyList, strictValidation), xmlFile(""), parser(0), doc(0), xmlInitialized(false)
00227 {
00228 CHECK_VERSION_COMPAT;
00229 setXmlFilePath(xmlFile);
00230 }
00231
00232
00233 SmbiosTableXml::~SmbiosTableXml()
00234 {
00235 if (parser)
00236 xmlFreeParser(parser);
00237
00238 if (doc)
00239 xmlFreeDoc(doc);
00240
00241 if( xmlInitialized )
00242 FiniXML();
00243 }
00244
00245
00246
00247
00248
00249
00250 void SmbiosTableXml::setXmlFilePath( std::string newFile )
00251 {
00252 try
00253 {
00254
00255 if( ! xmlInitialized )
00256 InitXML();
00257
00258 xmlInitialized = true;
00259
00260 DOMBuilder *newParser = getParser();
00261 DOMDocument *newdoc = getSmbiosXmlDoc( newParser, newFile );
00262 validateSmbiosXmlDoc( newdoc );
00263
00264
00265
00266 if (parser)
00267 xmlFreeParser(parser);
00268
00269 if (doc)
00270 xmlFreeDoc(doc);
00271
00272 parser = newParser;
00273 xmlFile = newFile;
00274 doc = newdoc;
00275 }
00276 catch(const exception &toCatch)
00277 {
00278 cerr << "Error during XML Initialization.\n"
00279 << " Exception message:"
00280 << toCatch.what() << endl;
00281 throw ParseExceptionImpl("XML initialization failed.");
00282 }
00283 }
00284
00285 const DOMDocument *SmbiosTableXml::getXmlDoc() const
00286 {
00287 return doc;
00288 }
00289
00290 int SmbiosTableXml::getTypeForString( const string searchForDesc ) const
00291 {
00292 return smbios::getTypeForString( doc, searchForDesc );
00293 }
00294
00295
00296 const string SmbiosTableXml::getStringForType( const int searchForType ) const
00297 {
00298 return smbios::getStringForType( doc, searchForType );
00299 }
00300
00301
00302
00303
00304 SmbiosTable::iterator SmbiosTableXml::operator[] (const string &searchFor)
00305 {
00306 int type = getTypeForString( searchFor );
00307 return SmbiosTable::iterator (this, type);
00308 }
00309
00310
00311
00312
00313 SmbiosTable::const_iterator SmbiosTableXml::operator[](const string &searchFor) const
00314 {
00315
00316 int type = getTypeForString( searchFor );
00317 return SmbiosTable::const_iterator (this, type);
00318 }
00319
00320
00321 static void getData_UsingXml(const ISmbiosItem &item, const string fieldName, void *out, size_t size )
00322 {
00323 DOMElement *element = 0;
00324
00325 smbios::ISmbiosTable *table =
00326 smbios::SmbiosFactory::getFactory()->getSingleton();
00327
00328 const SmbiosTableXml *tableXml = dynamic_cast<const SmbiosTableXml *>(table);
00329 if(!tableXml)
00330 throw NotImplementedImpl();
00331
00332 const DOMDocument *doc = tableXml->getXmlDoc();
00333
00334
00335 DOMElement *Structure = findElementWithNumericAttr( xmlDocGetRootElement(doc), "STRUCTURE", "type", item.getType() );
00336 element = findElement( Structure, "FIELD", "name", fieldName );
00337
00338
00339 verifyElementAttr( element, "length", size );
00340
00341
00342 item.getData( getNumberFromXmlAttr(element, "offset", 0), out, size );
00343 }
00344
00345 u8 getU8_FromItem(const ISmbiosItem &item, std::string field)
00346 {
00347 u8 retval = 0;
00348 getData_UsingXml(item, field, reinterpret_cast<u8 *>(&retval), sizeof(retval));
00349 return retval;
00350 }
00351
00352 u16 getU16_FromItem(const ISmbiosItem &item, std::string field)
00353 {
00354 u16 retval = 0;
00355 getData_UsingXml(item, field, reinterpret_cast<u8 *>(&retval), sizeof(retval));
00356 return retval;
00357 }
00358
00359 u32 getU32_FromItem(const ISmbiosItem &item, std::string field)
00360 {
00361 u32 retval = 0;
00362 getData_UsingXml(item, field, reinterpret_cast<u8 *>(&retval), sizeof(retval));
00363 return retval;
00364 }
00365
00366 u64 getU64_FromItem(const ISmbiosItem &item, std::string field)
00367 {
00368 u64 retval = 0;
00369 getData_UsingXml(item, field, reinterpret_cast<u8 *>(&retval), sizeof(retval));
00370 return retval;
00371 }
00372
00373 const char *getString_FromItem(const ISmbiosItem &item, std::string field)
00374 {
00375 DOMElement *element = 0;
00376
00377 smbios::ISmbiosTable *table =
00378 smbios::SmbiosFactory::getFactory()->getSingleton();
00379
00380 const SmbiosTableXml *tableXml = dynamic_cast<const SmbiosTableXml *>(table);
00381 if(!tableXml)
00382 throw NotImplementedImpl();
00383
00384 const DOMDocument *doc = tableXml->getXmlDoc();
00385
00386
00387 DOMElement *Structure = findElementWithNumericAttr( xmlDocGetRootElement(doc), "STRUCTURE", "type", item.getType() );
00388 element = findElement( Structure, "FIELD", "name", field );
00389
00390
00391 verifyElementAttr( element, "length", 1 );
00392
00393
00394 verifyElementAttr( element, "usage", "STRING" );
00395
00396
00397 return getString_FromItem(item, getNumberFromXmlAttr(element, "offset", 0) );
00398 }
00399
00400 void *getBits_FromItem(const ISmbiosItem &item, const string field, const string bitField, void *out)
00401 {
00402 DOMElement *bitElement = 0;
00403 DOMElement *fieldElement = 0;
00404
00405 smbios::ISmbiosTable *table =
00406 smbios::SmbiosFactory::getFactory()->getSingleton();
00407
00408 const SmbiosTableXml *tableXml = dynamic_cast<const SmbiosTableXml *>(table);
00409 if(!tableXml)
00410 throw NotImplementedImpl();
00411
00412 const DOMDocument *doc = tableXml->getXmlDoc();
00413
00414 try
00415 {
00416 DOMElement *Structure = findElementWithNumericAttr( xmlDocGetRootElement(doc), "STRUCTURE", "type", item.getType() );
00417 fieldElement = findElement( Structure, "FIELD", "name", field );
00418 bitElement = findElement( fieldElement, "BITS", "name", bitField );
00419 }
00420 catch (const NotFound & )
00421 {
00422 throw ParseExceptionImpl("could not fine bitfield name in xml file.");
00423 }
00424
00425
00426 return getBits_FromItem(item,
00427 getNumberFromXmlAttr(fieldElement, "offset", 0),
00428 out,
00429 getNumberFromXmlAttr(bitElement, "lsb", 0),
00430 getNumberFromXmlAttr(bitElement, "msb", 0)
00431 );
00432 }
00433
00434 void printStructureField( std::ostream &cout, const DOMNode *node, const ISmbiosItem &item )
00435 {
00436 std::ios::fmtflags old_opts = cout.flags ();
00437 try
00438 {
00439 unsigned int length = parseLengthStr(safeGetAttribute( node, "length" ));
00440 string strOffset = safeGetAttribute( node, "offset" );
00441 unsigned int offset = strtol( strOffset.c_str(), 0, 0 );
00442
00443 string usage = safeGetAttribute( node, "usage" );
00444 if (usage == "STRING")
00445 {
00446 try
00447 {
00448 cout << getString_FromItem(item, offset);
00449 }
00450 catch(const StringUnavailable &)
00451 {
00452 }
00453 }
00454 else
00455 {
00456 cout << hex << "0x";
00457 for(unsigned int i=0;i<length; i++)
00458 {
00459 cout << setfill('0') << setw(2) <<
00460 static_cast<int>(getU8_FromItem(item, offset + length - i - 1));
00461 }
00462 }
00463 }
00464 catch( const std::exception & )
00465 {
00466 cout.flags (old_opts);
00467 throw;
00468 }
00469 cout.flags (old_opts);
00470 }
00471
00472 std::ostream &SmbiosTableXml::streamify(ostream & cout) const
00473 {
00474 cout << "\nSMBIOS table " << endl;
00475 cout << "\tversion : ";
00476 cout << static_cast<int>(table_header.major_ver) << ".";
00477 cout << static_cast<int>(table_header.minor_ver) << endl;
00478 cout << hex ;
00479 cout << "\taddress : " << table_header.table_address << endl;
00480 cout << dec;
00481 cout << "\tlength : " << table_header.table_length << endl;
00482 cout << "\tnum structs: " << table_header.table_num_structs << endl;
00483 cout << endl;
00484
00485 SmbiosTable::const_iterator position = begin();
00486 while (position != end())
00487 {
00488 cout << *position << endl;
00489 ++position;
00490 }
00491 return cout;
00492 }
00493
00494
00495
00496
00497
00498
00499 std::ostream &toXmlString(const ISmbiosTable &table, ostream & cout)
00500 {
00501 UNREFERENCED_PARAMETER(table);
00502 cout << "XML output not yet supported in std lib." << endl;
00503 return cout;
00504 }
00505
00506 }