Main Page | Namespace List | Class Hierarchy | Class List | 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 
00025 #include "SmbiosImpl.h"
00026 
00027 // message.h should be included last.
00028 #include "smbios/message.h"
00029 
00030 using namespace smbiosLowlevel;
00031 using namespace std;
00032 
00033 #if defined(DEBUG_SMBIOS)
00034 #   define DCOUT(line) do { cout << line; } while(0)
00035 #   define DCERR(line) do { cerr << line; } while(0)
00036 #else
00037 #   define DCOUT(line) do {} while(0)
00038 #   define DCERR(line) do {} while(0)
00039 #endif
00040 
00041 namespace smbios
00042 {
00043 
00044     ISmbiosTable::ISmbiosTable()
00045     {}
00046 
00047     ISmbiosTable::~ISmbiosTable()
00048     {}
00049 
00050     // Regular CONSTRUCTOR   NOT ALLOWED!
00051     // This is marked "protected:" in the header (only to be used by derived classes)
00052     SmbiosTable::SmbiosTable ()
00053             : ISmbiosTable(), itemList(), initializing(true), strictValidationMode(false), workaround(0), smbiosBuffer (0)
00054     {
00055         memset (
00056             const_cast<smbios_table_entry_point *>(&table_header),
00057             0,
00058             sizeof (table_header)
00059         );
00060     }
00061 
00062     // Regular Constructor
00063     SmbiosTable::SmbiosTable(std::vector<SmbiosStrategy *> initStrategyList, bool strictValidation)
00064             :ISmbiosTable(), itemList(), initializing(true), strictValidationMode(strictValidation), workaround(0), smbiosBuffer (0), strategyList(initStrategyList)
00065     {
00066         // clearItemCache(); // works fine if we call here.
00067         reReadTable(); // may throw
00068     }
00069 
00070     // DESTRUCTOR
00071     SmbiosTable::~SmbiosTable ()
00072     {
00073         clearItemCache();
00074 
00075         if (0 != smbiosBuffer)
00076         {
00077             memset ( const_cast<u8 *>(smbiosBuffer), 0, sizeof (*smbiosBuffer));
00078             delete [] const_cast<u8 *>(smbiosBuffer);
00079             smbiosBuffer = 0;
00080         }
00081 
00082         memset (
00083             const_cast<smbios_table_entry_point *>(&table_header),
00084             0,
00085             sizeof (table_header)
00086         );
00087 
00088         std::vector< SmbiosStrategy *>::iterator strategy;
00089         for( strategy = strategyList.begin(); strategy != strategyList.end(); ++strategy )
00090         {
00091             delete *strategy;
00092         }
00093     }
00094 
00095     ISmbiosItem *SmbiosTable::getCachedItem( const void * itemPtr ) const
00096     {
00097         ISmbiosItem *ret = 0;
00098         if ((itemList.find (itemPtr) !=
00099                 itemList.end ()))
00100         {
00101             if( 0 != itemList[itemPtr] )
00102             {
00103                 ret = itemList[itemPtr];
00104             }
00105             else
00106             {
00107                 throw InternalErrorImpl(_("No null pointers should ever leak into the itemList"));
00108             }
00109         }
00110         return ret;
00111     }
00112 
00113     void SmbiosTable::cacheItem( const void *ptr, ISmbiosItem &newitem ) const
00114     {
00115         // The following two lines are equivalent to:
00116         //table->itemList[current] = newitem;
00117         //  but are more efficient
00118         pair < const void *, ISmbiosItem * >myPair (ptr, &newitem);
00119         itemList.insert (itemList.begin (), myPair);
00120     }
00121 
00122     SmbiosTable::iterator SmbiosTable::begin ()
00123     {
00124         return SmbiosTable::iterator (this);
00125     }
00126 
00127     SmbiosTable::const_iterator SmbiosTable::begin () const
00128     {
00129         return SmbiosTable::const_iterator (this);
00130     }
00131 
00132     SmbiosTable::iterator SmbiosTable::end ()
00133     {
00134         return SmbiosTable::iterator ();
00135     }
00136 
00137     SmbiosTable::const_iterator SmbiosTable::end ()const
00138     {
00139         return SmbiosTable::const_iterator ();
00140     }
00141 
00142     SmbiosTable::iterator SmbiosTable::operator[] (const int type)
00143     {
00144         return SmbiosTable::iterator (this, type);
00145     }
00146 
00147     SmbiosTable::const_iterator SmbiosTable::operator[](const int type) const
00148     {
00149         return SmbiosTable::const_iterator (this, type);
00150     }
00151 
00152     SmbiosTable::iterator SmbiosTable::operator[] (const string &)
00153     {
00154         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"));
00155     }
00156 
00157     SmbiosTable::const_iterator SmbiosTable::operator[](const string &) const
00158     {
00159         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"));
00160     }
00161 
00162     void SmbiosTable::reReadTable()
00163     {
00164         bool gotTable = false;
00165         // make sure there are no cached objects.
00166         // MSVC++ crashes here if you remove the if(). No idea why, works on
00167         // GCC.
00168         if( ! initializing )
00169             clearItemCache();
00170 
00171         // go through our strategies one-by-one and ask them if they can 
00172         // fulfill the request.
00173         DCERR("calling strategy code to read table" << endl);
00174         std::vector< SmbiosStrategy *>::iterator strategy;
00175         for( strategy = strategyList.begin(); strategy != strategyList.end(); ++strategy )
00176         {
00177             try
00178             {
00179                 DCERR("  strategy: 0x" << hex << (int)(*strategy) << endl);
00180                 if( (*strategy)->getSmbiosTable(&smbiosBuffer, &table_header, getStrictValidationMode()) )
00181                 {
00182                     DCERR("    RETURNED SUCCESS" << endl);
00183                     gotTable = true;
00184                     break;
00185                 }
00186             }
00187             catch(...)
00188             {
00189                 // nil
00190             }
00191         }
00192         DCERR("TABLE HEADER DUMP: " << endl << *this << endl);
00193         DCERR("TABLE BUFFER: 0x" << hex << (int)smbiosBuffer << endl);
00194         
00195         if (! gotTable)
00196         {
00197             // manually delete allocated stuff here because the destructor 
00198             // does not get called and this stuff will not be freed.
00199             std::vector< SmbiosStrategy *>::iterator strategy;
00200             for( strategy = strategyList.begin(); strategy != strategyList.end(); ++strategy )
00201             {
00202                 delete *strategy;
00203             }
00204             throw InternalErrorImpl(_("Could not instantiate SMBIOS table."));
00205         }
00206     }
00207 
00208     void SmbiosTable::initializeWorkaround() const
00209     {
00210         // crap code to work around compiler bugs in:
00211         //   -- gcc 2.96
00212         //   -- msvc++ 6.0
00213         //
00214         const SmbiosWorkaroundTable *ptr = workaround.get();
00215         workaround.release();
00216         delete const_cast<SmbiosWorkaroundTable *>(ptr);
00217         std::auto_ptr<SmbiosWorkaroundTable> foo(
00218             SmbiosWorkaroundFactory::getFactory()->makeNew( this ));
00219         workaround = foo;
00220 
00221         // after initializing the workaround object, go through and delete
00222         // all existing items.
00223         //
00224         // have to do this because items are possibly created with wrong
00225         // type. Types higher than SmbiosTableMemory
00226         // call this through constructor, and this call happens before
00227         // we enter the constructor for the higher level type.
00228         //
00229         // For example, if we are supposed to initializing an Xml Table,
00230         // The items here _should_ be SmbiosItemAccess objects, but instead
00231         // they turn out to be regular SmbiosItem objects.
00232         clearItemCache();
00233 
00234         initializing = false;
00235     }
00236 
00237     void SmbiosTable::rawMode(bool m) const
00238     {
00239         initializing = m;
00240     }
00241 
00242     void SmbiosTable::clearItemCache() const
00243     {
00244         // Delete everything in itemList
00245         std::map < const void *, ISmbiosItem * >::iterator position;
00246         for (position = itemList.begin ();
00247                 position != itemList.end (); ++position)
00248         {
00249             delete position->second;
00250         }
00251         // clear the item list.
00252         itemList.clear();
00253     }
00254 
00255     // Restrict the validation of table entry point
00256     void SmbiosTable::setStrictValidationMode(bool mode) const
00257     {
00258         strictValidationMode = mode;
00259     }
00260 
00261     bool SmbiosTable::getStrictValidationMode() const
00262     {
00263         return strictValidationMode;
00264     }
00265 
00266     // Get an Item
00267     ISmbiosItem &SmbiosTable::makeItem(
00268         const void *header) const
00269     {
00270         const smbios_structure_header *structure =
00271             reinterpret_cast<const smbios_structure_header *>(header);
00272         ISmbiosItem *item = new SmbiosItem( structure );
00273         if( ! initializing )
00274         {
00275             dynamic_cast<SmbiosItem*>(item)->fixup( workaround.get() );
00276         }
00277         return *item;
00278     }
00279 
00280     const void *SmbiosTable::nextSmbiosStruct (const void* current) const
00281     {
00282         const smbios_structure_header *currStruct =
00283             reinterpret_cast<const smbios_structure_header *>(current);
00284         const u8 *data = 0;
00285 
00286         //If we are called on an uninitialized smbiosBuffer, return 0;
00287         if (0 == smbiosBuffer)
00288             goto out1;
00289 
00290         data = smbiosBuffer;
00291 
00292         // currStruct == 0, that means we return the first struct
00293         if (0 == currStruct)
00294             goto out1;
00295 
00296 
00297         // if currStruct struct is an end-of-table struct, stop.
00298         if (0x7f == currStruct->type)
00299         {
00300             data = 0;
00301             goto out1;
00302         }
00303 
00304         // start out at the end of the currStruct structure.
00305         // The only things that sits between us and the next struct
00306         // are the strings for the currStruct structure.
00307         data = reinterpret_cast<const u8 *>(currStruct) + currStruct->length;
00308 
00309         // skip past strings at the end of the formatted structure,
00310         // go until we hit double NULL "\0"
00311         // add a check to make sure we don't walk off the buffer end
00312         // for broken BIOSen.
00313         // The (3) is to take into account the deref at the end "data[0] ||
00314         // data[1]", and to take into account the "data += 2" on the next line.
00315         while (((data - smbiosBuffer) < (table_header.table_length - 3)) && (*data || data[1]))
00316             data++;
00317 
00318         // ok, skip past the actual double null.
00319         data += 2;
00320 
00321         // add code specifically to work around crap bios implementations
00322         // that do not have the _required_ 0x7f end-of-table entry
00323         //   note: (4) == sizeof a std header.
00324         if ( (data - smbiosBuffer) > (table_header.table_length - 4))
00325         {
00326             // really should output some nasty message here... This is very
00327             // broken
00328             data = 0;
00329             goto out1;
00330         }
00331 
00332 out1:
00333         return reinterpret_cast<const void *>(data);
00334     }
00335 
00336 
00337     int SmbiosTable::getNumberOfEntries () const
00338     {
00339         return table_header.table_num_structs;
00340     }
00341 
00342     smbiosLowlevel::smbios_table_entry_point SmbiosTable::getTableEPS() const
00343     {
00344         return table_header;
00345     }
00346 
00347     ostream & SmbiosTable::streamify(ostream & cout) const
00348     {
00349         cout << "\nSMBIOS table " << endl;
00350         cout << "\tversion    : ";
00351         cout << static_cast<int>(table_header.major_ver) << ".";
00352         cout << static_cast<int>(table_header.minor_ver) << endl;
00353         cout << hex ;
00354         cout << "\taddress    : " << table_header.table_address << endl;
00355         cout << dec;
00356         cout << "\tlength     : " << table_header.table_length << endl;
00357         cout << "\tnum structs: " << table_header.table_num_structs << endl;
00358         cout << endl;
00359 
00360         SmbiosTable::const_iterator position = begin();
00361         while (position != end())
00362         {
00363              cout << *position << endl;
00364             ++position;
00365         }
00366         return cout;
00367     }
00368 
00369     ostream & operator << (ostream & cout, const ISmbiosTable & table)
00370     {
00371         table.streamify( cout );
00372         return cout;
00373     }
00374 
00375 }

Generated on Wed Apr 11 16:25:10 2007 for SMBIOS Library by doxygen 1.3.5