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 <string.h>
00025
00026 #include "SmbiosImpl.h"
00027
00028
00029 #include "smbios/message.h"
00030
00031 using namespace smbiosLowlevel;
00032 using namespace std;
00033
00034 #if defined(DEBUG_SMBIOS)
00035 # define DCOUT(line) do { cout << line; } while(0)
00036 # define DCERR(line) do { cerr << line; } while(0)
00037 #else
00038 # define DCOUT(line) do {} while(0)
00039 # define DCERR(line) do {} while(0)
00040 #endif
00041
00042 namespace smbios
00043 {
00044
00045 ISmbiosTable::ISmbiosTable()
00046 {}
00047
00048 ISmbiosTable::~ISmbiosTable()
00049 {}
00050
00051
00052
00053 SmbiosTable::SmbiosTable ()
00054 : ISmbiosTable(), itemList(), initializing(true), strictValidationMode(false), workaround(0), smbiosBuffer (0)
00055 {
00056 memset (
00057 const_cast<smbios_table_entry_point *>(&table_header),
00058 0,
00059 sizeof (table_header)
00060 );
00061 }
00062
00063
00064 SmbiosTable::SmbiosTable(std::vector<SmbiosStrategy *> initStrategyList, bool strictValidation)
00065 :ISmbiosTable(), itemList(), initializing(true), strictValidationMode(strictValidation), workaround(0), smbiosBuffer (0), strategyList(initStrategyList)
00066 {
00067
00068 reReadTable();
00069 }
00070
00071
00072 SmbiosTable::~SmbiosTable ()
00073 {
00074 clearItemCache();
00075
00076 if (0 != smbiosBuffer)
00077 {
00078 memset ( const_cast<u8 *>(smbiosBuffer), 0, sizeof (*smbiosBuffer));
00079 delete [] const_cast<u8 *>(smbiosBuffer);
00080 smbiosBuffer = 0;
00081 }
00082
00083 memset (
00084 const_cast<smbios_table_entry_point *>(&table_header),
00085 0,
00086 sizeof (table_header)
00087 );
00088
00089 std::vector< SmbiosStrategy *>::iterator strategy;
00090 for( strategy = strategyList.begin(); strategy != strategyList.end(); ++strategy )
00091 {
00092 delete *strategy;
00093 }
00094 }
00095
00096 ISmbiosItem *SmbiosTable::getCachedItem( const void * itemPtr ) const
00097 {
00098 ISmbiosItem *ret = 0;
00099 if ((itemList.find (itemPtr) !=
00100 itemList.end ()))
00101 {
00102 if( 0 != itemList[itemPtr] )
00103 {
00104 ret = itemList[itemPtr];
00105 }
00106 else
00107 {
00108 throw InternalErrorImpl(_("No null pointers should ever leak into the itemList"));
00109 }
00110 }
00111 return ret;
00112 }
00113
00114 void SmbiosTable::cacheItem( const void *ptr, ISmbiosItem &newitem ) const
00115 {
00116
00117
00118
00119 pair < const void *, ISmbiosItem * >myPair (ptr, &newitem);
00120 itemList.insert (itemList.begin (), myPair);
00121 }
00122
00123 SmbiosTable::iterator SmbiosTable::begin ()
00124 {
00125 return SmbiosTable::iterator (this);
00126 }
00127
00128 SmbiosTable::const_iterator SmbiosTable::begin () const
00129 {
00130 return SmbiosTable::const_iterator (this);
00131 }
00132
00133 SmbiosTable::iterator SmbiosTable::end ()
00134 {
00135 return SmbiosTable::iterator ();
00136 }
00137
00138 SmbiosTable::const_iterator SmbiosTable::end ()const
00139 {
00140 return SmbiosTable::const_iterator ();
00141 }
00142
00143 SmbiosTable::iterator SmbiosTable::operator[] (const int type)
00144 {
00145 return SmbiosTable::iterator (this, type);
00146 }
00147
00148 SmbiosTable::const_iterator SmbiosTable::operator[](const int type) const
00149 {
00150 return SmbiosTable::const_iterator (this, type);
00151 }
00152
00153 SmbiosTable::iterator SmbiosTable::operator[] (const string &)
00154 {
00155 throw NotImplementedImpl(_("This is an enhanced function call that is not available in the base Smbios library. You must be using an enhanced library such as SmbiosXml to use this API"));
00156 }
00157
00158 SmbiosTable::const_iterator SmbiosTable::operator[](const string &) const
00159 {
00160 throw NotImplementedImpl(_("This is an enhanced function call that is not available in the base Smbios library. You must be using an enhanced library such as SmbiosXml to use this API"));
00161 }
00162
00163 void SmbiosTable::reReadTable()
00164 {
00165 bool gotTable = false;
00166
00167
00168
00169 if( ! initializing )
00170 clearItemCache();
00171
00172
00173
00174 DCERR("calling strategy code to read table" << endl);
00175 std::vector< SmbiosStrategy *>::iterator strategy;
00176 for( strategy = strategyList.begin(); strategy != strategyList.end(); ++strategy )
00177 {
00178 try
00179 {
00180 DCERR(" strategy: 0x" << hex << (int)(*strategy) << endl);
00181 if( (*strategy)->getSmbiosTable(&smbiosBuffer, &table_header, getStrictValidationMode()) )
00182 {
00183 DCERR(" RETURNED SUCCESS" << endl);
00184 gotTable = true;
00185 break;
00186 }
00187 }
00188 catch(...)
00189 {
00190
00191 }
00192 }
00193 DCERR("TABLE HEADER DUMP: " << endl << *this << endl);
00194 DCERR("TABLE BUFFER: 0x" << hex << (int)smbiosBuffer << endl);
00195
00196 if (! gotTable)
00197 {
00198
00199
00200 std::vector< SmbiosStrategy *>::iterator strategy;
00201 for( strategy = strategyList.begin(); strategy != strategyList.end(); ++strategy )
00202 {
00203 delete *strategy;
00204 }
00205 throw InternalErrorImpl(_("Could not instantiate SMBIOS table."));
00206 }
00207 }
00208
00209 void SmbiosTable::initializeWorkaround() const
00210 {
00211
00212
00213
00214
00215 const SmbiosWorkaroundTable *ptr = workaround.get();
00216 workaround.release();
00217 delete const_cast<SmbiosWorkaroundTable *>(ptr);
00218 std::auto_ptr<SmbiosWorkaroundTable> foo(
00219 SmbiosWorkaroundFactory::getFactory()->makeNew( this ));
00220 workaround = foo;
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233 clearItemCache();
00234
00235 initializing = false;
00236 }
00237
00238 void SmbiosTable::rawMode(bool m) const
00239 {
00240 initializing = m;
00241 }
00242
00243 void SmbiosTable::clearItemCache() const
00244 {
00245
00246 std::map < const void *, ISmbiosItem * >::iterator position;
00247 for (position = itemList.begin ();
00248 position != itemList.end (); ++position)
00249 {
00250 delete position->second;
00251 }
00252
00253 itemList.clear();
00254 }
00255
00256
00257 void SmbiosTable::setStrictValidationMode(bool mode) const
00258 {
00259 strictValidationMode = mode;
00260 }
00261
00262 bool SmbiosTable::getStrictValidationMode() const
00263 {
00264 return strictValidationMode;
00265 }
00266
00267
00268 ISmbiosItem &SmbiosTable::makeItem(
00269 const void *header) const
00270 {
00271 const smbios_structure_header *structure =
00272 reinterpret_cast<const smbios_structure_header *>(header);
00273 ISmbiosItem *item = new SmbiosItem( structure );
00274 if( ! initializing )
00275 {
00276 dynamic_cast<SmbiosItem*>(item)->fixup( workaround.get() );
00277 }
00278 return *item;
00279 }
00280
00281 const ISmbiosItem & SmbiosTable::getSmbiosItem (const u8 *current) const
00282 {
00283 return const_cast<SmbiosTable *>(this)->getSmbiosItem(current);
00284 }
00285
00286 ISmbiosItem & SmbiosTable::getSmbiosItem (const u8 *current)
00287 {
00288 if (0 == current)
00289 {
00290 throw ItemNotFoundImpl("Could not de-reference a null item");
00291 }
00292
00293 ISmbiosItem *item = this->getCachedItem( current );
00294 if ( 0 != item )
00295 return *(item);
00296
00297 ISmbiosItem &newitem = this->makeItem( current );
00298
00299 this->cacheItem( current, newitem );
00300
00301 return newitem;
00302 }
00303
00304 const u8 *SmbiosTable::nextSmbiosStruct (const u8* current) const
00305 {
00306 const smbios_structure_header *currStruct =
00307 reinterpret_cast<const smbios_structure_header *>(current);
00308 const u8 *data = 0;
00309
00310
00311 if (0 == smbiosBuffer || (currStruct && 0x7f == currStruct->type))
00312 goto out1;
00313
00314 data = smbiosBuffer;
00315
00316
00317 if (0 == currStruct)
00318 goto out1;
00319
00320
00321
00322
00323 data = reinterpret_cast<const u8 *>(currStruct) + currStruct->length;
00324
00325
00326
00327
00328
00329
00330
00331 while (((data - smbiosBuffer) < (table_header.dmi.table_length - 3)) && (*data || data[1]))
00332 data++;
00333
00334
00335 data += 2;
00336
00337
00338
00339
00340 if ( (data - smbiosBuffer) > (table_header.dmi.table_length - 4))
00341 {
00342
00343
00344 data = 0;
00345 goto out1;
00346 }
00347
00348 out1:
00349 return data;
00350 }
00351
00352
00353 int SmbiosTable::getNumberOfEntries () const
00354 {
00355 return table_header.dmi.table_num_structs;
00356 }
00357
00358 smbiosLowlevel::smbios_table_entry_point SmbiosTable::getTableEPS() const
00359 {
00360 return table_header;
00361 }
00362
00363 ostream & SmbiosTable::streamify(ostream & cout) const
00364 {
00365 cout << "\nSMBIOS table " << endl;
00366 cout << "\tversion : ";
00367 cout << static_cast<int>(table_header.major_ver) << ".";
00368 cout << static_cast<int>(table_header.minor_ver) << endl;
00369 cout << hex ;
00370 cout << "\taddress : " << table_header.dmi.table_address << endl;
00371 cout << dec;
00372 cout << "\tlength : " << table_header.dmi.table_length << endl;
00373 cout << "\tnum structs: " << table_header.dmi.table_num_structs << endl;
00374 cout << endl;
00375
00376 SmbiosTable::const_iterator position = begin();
00377 while (position != end())
00378 {
00379 cout << *position << endl;
00380 ++position;
00381 }
00382 return cout;
00383 }
00384
00385 ostream & operator << (ostream & cout, const ISmbiosTable & table)
00386 {
00387 table.streamify( cout );
00388 return cout;
00389 }
00390
00391 }