SmbiosWorkaround.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 #define LIBSMBIOS_SOURCE
00020 #include "SmbiosWorkaroundImpl.h"
00021 #include "smbios/SmbiosDefs.h"
00022 #include "SmbiosImpl.h"
00023 
00024 #include "StdWorkarounds.h"
00025 
00026 // message.h should be included last.
00027 #include "smbios/message.h"
00028 
00029 using namespace std;
00030 
00031 // convenience function.
00032 #define _X( expr ) do{ try {  expr } catch( const std::exception & ){} }while(0)
00033 
00034 namespace smbios
00035 {
00036     SmbiosWorkaroundTable   *SmbiosWorkaroundFactory::_tableInstance = 0;
00037 
00038     factory::TFactory<smbios::SmbiosWorkaroundFactory> *SmbiosWorkaroundFactory::getFactory()
00039     {
00040         // reinterpret_cast<...>(0) to ensure template parameter is correct
00041         // this is a workaround for VC6 which cannot use explicit member template
00042         // function initialization.
00043         return factory::TFactory<SmbiosWorkaroundFactory>::getFactory(reinterpret_cast<factory::TFactory<SmbiosWorkaroundFactory> *>(0));
00044     }
00045 
00046     SmbiosWorkaroundFactory::~SmbiosWorkaroundFactory() throw()
00047     {
00048         if( _tableInstance )
00049         {
00050             delete _tableInstance;
00051             _tableInstance = 0;
00052         }
00053 
00054     }
00055 
00056     SmbiosWorkaroundTable *SmbiosWorkaroundFactory::makeNew( const ISmbiosTable *table )
00057     {
00058         int systemId = 0;
00059 
00060         _X( systemId = (*table)[ Dell_Revisions_and_IDs ]->getU8( 0x06 ); );
00061         if( 0xFE == systemId )
00062             _X(systemId = (*table)[ Dell_Revisions_and_IDs ]->getU16( 0x08 ););
00063 
00064         const char * chBiosVersion = 0;
00065 
00066         std::string biosVersion = "";
00067 
00068         _X( chBiosVersion = (*table)[ BIOS_Information ]->getString( 0x05  ); );
00069 
00070         if ( 0 != chBiosVersion )
00071             biosVersion = chBiosVersion;
00072 
00073         const Workaround **thisSystemWA = 0;
00074         for( int i=0; i < numSystemWorkarounds; ++i )
00075         {
00076             if( workaroundMasterList[i].system->systemId == systemId )
00077             {
00078                 thisSystemWA = workaroundMasterList[i].workarounds;
00079                 break;
00080             }
00081         }
00082 
00083         return new SmbiosWorkaroundTable( table, thisSystemWA );
00084     }
00085 
00086     SmbiosWorkaroundTable::SmbiosWorkaroundTable( const ISmbiosTable *, const Workaround **initWorkarounds )
00087             : systemId(0), biosVersion(""), workaroundsForThisSystem(initWorkarounds)
00088     {}
00089 
00090     SmbiosWorkaroundTable::~SmbiosWorkaroundTable()
00091     {}
00092 
00093     static bool compareU64( const ISmbiosItem *item, int offset, datatron data )
00094     {
00095         bool retval = false;
00096         u64 compareTo = item->getU64(offset);
00097         if( compareTo == data.dataU64 )
00098             retval = true;
00099         return retval;
00100     }
00101 
00102     static bool compareU32( const ISmbiosItem *item, int offset, datatron data )
00103     {
00104         bool retval = false;
00105         u32 compareTo = item->getU32(offset);
00106         if( compareTo == data.dataU32 )
00107             retval = true;
00108         return retval;
00109     }
00110 
00111     static bool compareU16( const ISmbiosItem *item, int offset, datatron data )
00112     {
00113         bool retval = false;
00114         u16 compareTo = item->getU16(offset);
00115         if( compareTo == data.dataU16 )
00116             retval = true;
00117         return retval;
00118     }
00119 
00120     static bool compareU8( const ISmbiosItem *item, int offset, datatron data )
00121     {
00122         bool retval = false;
00123         u8 compareTo = item->getU8(offset);
00124         if( compareTo == data.dataU8 )
00125             retval = true;
00126         return retval;
00127     }
00128 
00129     typedef bool (*compareFunction)(const ISmbiosItem *item, int offset, datatron data);
00130     struct
00131     {
00132         int type;
00133         compareFunction funct;
00134     }
00135     compareFunctions[] =
00136         {
00137             { TYPE_U8,  &compareU8  },
00138             { TYPE_U16, &compareU16 },
00139             { TYPE_U32, &compareU32 },
00140             { TYPE_U64, &compareU64 },
00141         };
00142 
00143     static bool compare( int type, const ISmbiosItem *item, int offset, datatron data )
00144     {
00145         compareFunction funct = 0;
00146         for( unsigned int i=0; i < (sizeof(compareFunctions)/sizeof(compareFunctions[0])); ++i )
00147         {
00148             if( compareFunctions[i].type == type )
00149                 funct = compareFunctions[i].funct;
00150         }
00151         if( funct == 0 )
00152         {
00153             InternalErrorImpl internalError(_("Compare function not found. Requested: %(type)i"));
00154             internalError.setParameter("type", type );
00155             throw internalError;
00156         }
00157 
00158         return funct( item, offset, data );
00159     }
00160 
00161     static void fixupData( u8 *buf, size_t size, unsigned int offset, unsigned int len, datatron data )
00162     {
00163         InternalErrorImpl internalError;
00164         if( offset > size )
00165         {
00166             internalError.setMessageString(_("Data overflow. Offset requested is larger than data size. offset: %(offset)i, data size: %(size)i"));
00167             internalError.setParameter("offset",offset);
00168             internalError.setParameter("size",static_cast<int>(size));
00169             throw internalError;
00170         }
00171 
00172         for(unsigned int i=0; i<len; i++)
00173             buf[offset + i] = data.data[i];
00174     }
00175 
00176     static void doFixupItem( const Workaround *wa, const ISmbiosItem *item, u8 *buf, size_t bufSize )
00177     {
00178         int i = 0;  //loop counter. workaround MSVC++ braindamage.
00179 
00180         // check all of the symptoms. If any symptom does not match, bail.
00181         for( i=0; 0!=wa->symptoms[i].type; ++i )
00182         {
00183             bool ret = compare( wa->symptoms[i].fieldDataType, item, wa->symptoms[i].fieldOffset, wa->symptoms[i].data );
00184             if( ! ret )
00185                 goto out;
00186         }
00187 
00188         // All symptoms present if we got here.
00189         //cout << "GOT HERE!" << flush;
00190 
00191         // apply all of the fixups.
00192         for( i=0; 0!=wa->fixups[i].type; ++i )
00193         {
00194             fixupData(buf, bufSize, wa->fixups[i].fieldOffset, wa->fixups[i].fieldDataType, wa->fixups[i].data );
00195         }
00196 
00197 out:
00198         return;
00199     }
00200 
00201     void SmbiosWorkaroundTable::fixupItem( const ISmbiosItem *item, u8 *buffer, size_t bufSize ) const
00202     {
00203         int i = 0; //declare i up here to work around braindamaged MSVC++ for()
00204         // scoping violation.
00205 
00206         if( 0 == workaroundsForThisSystem )
00207             goto out;
00208 
00209         // workaroundsForThisSystem is a NULL-terminated array
00210         // of Workaround pointers.
00211         for( i=0; 0 != workaroundsForThisSystem[i]; ++i )
00212         {
00213             if( workaroundsForThisSystem[i]->symptoms->type  == item->getType() )
00214             {
00215                 //cout << "-F-" << flush;
00216                 doFixupItem( workaroundsForThisSystem[i], item, buffer, bufSize );
00217             }
00218         }
00219 
00220 out:
00221         return;
00222     }
00223 
00224 }

Generated on Tue Jul 11 20:46:46 2006 for SMBIOS Library by  doxygen 1.4.7