Main Page | Namespace List | Class Hierarchy | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

SmbiosTable.cpp

Go to the documentation of this file.
00001 /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
00002  * vim:expandtab:autoindent:tabstop=4:shiftwidth=4:filetype=c:cindent:textwidth=0:
00003  *
00004  * Copyright (C) 2005 Dell Inc.
00005  *  by Michael Brown <Michael_E_Brown@dell.com>
00006  * Licensed under the Open Software License version 2.1
00007  *
00008  * Alternatively, you can redistribute it and/or modify
00009  * it under the terms of the GNU General Public License as published
00010  * by the Free Software Foundation; either version 2 of the License,
00011  * or (at your option) any later version.
00012 
00013  * This program is distributed in the hope that it will be useful, but
00014  * WITHOUT ANY WARRANTY; without even the implied warranty of
00015  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
00016  * See the GNU General Public License for more details.
00017  */
00018 
00019 // compat header should always be first header if including system headers
00020 #define LIBSMBIOS_SOURCE
00021 #include "smbios/compat.h"
00022 
00023 #include <sstream>
00024 #include <string.h>
00025 
00026 #include "SmbiosImpl.h"
00027 
00028 // message.h should be included last.
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     // Regular CONSTRUCTOR   NOT ALLOWED!
00052     // This is marked "protected:" in the header (only to be used by derived classes)
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     // Regular Constructor
00064     SmbiosTable::SmbiosTable(std::vector<SmbiosStrategy *> initStrategyList, bool strictValidation)
00065             :ISmbiosTable(), itemList(), initializing(true), strictValidationMode(strictValidation), workaround(0), smbiosBuffer (0), strategyList(initStrategyList)
00066     {
00067         // clearItemCache(); // works fine if we call here.
00068         reReadTable(); // may throw
00069     }
00070 
00071     // DESTRUCTOR
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         // The following two lines are equivalent to:
00117         //table->itemList[current] = newitem;
00118         //  but are more efficient
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         // make sure there are no cached objects.
00167         // MSVC++ crashes here if you remove the if(). No idea why, works on
00168         // GCC.
00169         if( ! initializing )
00170             clearItemCache();
00171 
00172         // go through our strategies one-by-one and ask them if they can 
00173         // fulfill the request.
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                 // nil
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             // manually delete allocated stuff here because the destructor 
00199             // does not get called and this stuff will not be freed.
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         // crap code to work around compiler bugs in:
00212         //   -- gcc 2.96
00213         //   -- msvc++ 6.0
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         // after initializing the workaround object, go through and delete
00223         // all existing items.
00224         //
00225         // have to do this because items are possibly created with wrong
00226         // type. Types higher than SmbiosTableMemory
00227         // call this through constructor, and this call happens before
00228         // we enter the constructor for the higher level type.
00229         //
00230         // For example, if we are supposed to initializing an Xml Table,
00231         // The items here _should_ be SmbiosItemAccess objects, but instead
00232         // they turn out to be regular SmbiosItem objects.
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         // Delete everything in itemList
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         // clear the item list.
00253         itemList.clear();
00254     }
00255 
00256     // Restrict the validation of table entry point
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     // Get an Item
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         //If we are called on an uninitialized smbiosBuffer, return 0;
00311         if (0 == smbiosBuffer || (currStruct && 0x7f == currStruct->type))
00312             goto out1;
00313 
00314         data = smbiosBuffer;
00315 
00316         // currStruct == 0, that means we return the first struct
00317         if (0 == currStruct)
00318             goto out1;
00319 
00320         // start out at the end of the currStruct structure.
00321         // The only things that sits between us and the next struct
00322         // are the strings for the currStruct structure.
00323         data = reinterpret_cast<const u8 *>(currStruct) + currStruct->length;
00324 
00325         // skip past strings at the end of the formatted structure,
00326         // go until we hit double NULL "\0"
00327         // add a check to make sure we don't walk off the buffer end
00328         // for broken BIOSen.
00329         // The (3) is to take into account the deref at the end "data[0] ||
00330         // data[1]", and to take into account the "data += 2" on the next line.
00331         while (((data - smbiosBuffer) < (table_header.dmi.table_length - 3)) && (*data || data[1]))
00332             data++;
00333 
00334         // ok, skip past the actual double null.
00335         data += 2;
00336 
00337         // add code specifically to work around crap bios implementations
00338         // that do not have the _required_ 0x7f end-of-table entry
00339         //   note: (4) == sizeof a std header.
00340         if ( (data - smbiosBuffer) > (table_header.dmi.table_length - 4))
00341         {
00342             // really should output some nasty message here... This is very
00343             // broken
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 }

Generated on Tue Feb 26 14:39:00 2008 for SMBIOS Library by  doxygen 1.3.9.1