00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
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
00027 #include "smbios/message.h"
00028
00029 using namespace std;
00030
00031
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
00041
00042
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;
00179
00180
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
00189
00190
00191
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;
00204
00205
00206 if( 0 == workaroundsForThisSystem )
00207 goto out;
00208
00209
00210
00211 for( i=0; 0 != workaroundsForThisSystem[i]; ++i )
00212 {
00213 if( workaroundsForThisSystem[i]->symptoms->type == item->getType() )
00214 {
00215
00216 doFixupItem( workaroundsForThisSystem[i], item, buffer, bufSize );
00217 }
00218 }
00219
00220 out:
00221 return;
00222 }
00223
00224 }