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
00025 #include "CmosRWImpl.h"
00026 #include "TokenImpl.h"
00027
00028
00029 #include "smbios/message.h"
00030
00031 using namespace std;
00032 using namespace cmos;
00033
00034 namespace smbios
00035 {
00036 static u8 byteChecksum(
00037 const ICmosRW *cmos, u32 start, u32 end,
00038 u32 indexPort, u32 dataPort );
00039 static u16 wordChecksum(
00040 const ICmosRW *cmos, u32 start, u32 end,
00041 u32 indexPort, u32 dataPort, bool complement );
00042 static u16 wordCrc(
00043 const ICmosRW *cmos, u32 start, u32 end,
00044 u32 indexPort, u32 dataPort );
00045
00046
00047
00048 CmosRWChecksumObserver::CmosRWChecksumObserver(
00049 string initDesc,
00050 ICmosRW *initCmos,
00051 int initCheckType, u32 initIndexPort, u32 initDataPort,
00052 u32 initStart, u32 initEnd, u32 initChecksumLocation )
00053 :
00054 IObserver(),
00055 description(initDesc),
00056 cmos(initCmos),
00057 checkType(initCheckType),
00058 indexPort(initIndexPort),
00059 dataPort(initDataPort),
00060 start(initStart),
00061 end(initEnd),
00062 checksumLocation(initChecksumLocation)
00063 {
00064 observer::IObservable *ob = dynamic_cast<observer::IObservable*>(cmos);
00065 if( ob )
00066 ob->attach(this);
00067 }
00068
00069
00070 CmosRWChecksumObserver::CmosRWChecksumObserver( const CmosRWChecksumObserver &source )
00071 :
00072 IObserver(),
00073 description(source.description),
00074 cmos(source.cmos),
00075 checkType(source.checkType),
00076 indexPort(source.indexPort),
00077 dataPort(source.dataPort),
00078 start(source.start),
00079 end(source.end),
00080 checksumLocation(source.checksumLocation)
00081 {
00082 observer::IObservable *ob = dynamic_cast<observer::IObservable*>(cmos);
00083 if( ob )
00084 ob->attach(this);
00085 }
00086
00087
00088 CmosRWChecksumObserver::~CmosRWChecksumObserver()
00089 {
00090 observer::IObservable *ob = dynamic_cast<observer::IObservable*>(cmos);
00091 if( ob )
00092 ob->detach(this);
00093 }
00094
00095 void CmosRWChecksumObserver::update( const observer::IObservable *whatChanged, void *doUpdate )
00096 {
00097 const ICmosRW *cmos = dynamic_cast<const ICmosRW *>(whatChanged);
00098
00099 const u8 *chksum = 0;
00100 u16 wordRetval = 0;
00101
00102
00103 u8 len = sizeof(wordRetval);
00104 chksum = reinterpret_cast<const u8 *>(&wordRetval);
00105
00106
00107 ostringstream ost;
00108 ost << hex ;
00109 ost << description << endl;
00110 ost << _("Checksum check for CMOS value does not match.") << endl;
00111 InvalidChecksumImpl invalidChecksum;
00112
00113
00114
00115 if( !(start || end || checksumLocation))
00116 return;
00117
00118 switch( checkType )
00119 {
00120 case CHECK_TYPE_BYTE_CHECKSUM:
00121 ost << _("SMBIOS-specified checksum type is Byte Checksum. Type %(byte_chksum_type)i") << endl;
00122
00123 wordRetval = byteChecksum(cmos, start, end, indexPort, dataPort);
00124 len = sizeof(u8);
00125 break;
00126 case CHECK_TYPE_WORD_CHECKSUM:
00127 ost << _("SMBIOS-specified checksum type is Word Checksum. Type %(word_chksum_type)i") << endl;
00128 wordRetval = wordChecksum(cmos, start, end, indexPort, dataPort, false);
00129 break;
00130 case CHECK_TYPE_WORD_CHECKSUM_N:
00131 ost << _("SMBIOS-specified checksum type is One's Complement Word Checksum. Type %(word_chksum_n_type)i") << endl;
00132 wordRetval = wordChecksum(cmos, start, end, indexPort, dataPort, true);
00133 break;
00134 case CHECK_TYPE_WORD_CRC:
00135 ost << _("SMBIOS-specified checksum type is Word CRC. Type %(word_crc_type)i") << endl;
00136 wordRetval = wordCrc(cmos, start, end, indexPort, dataPort);
00137 break;
00138 default:
00139 ostringstream chkost;
00140 chkost << hex;
00141 chkost << _("Unknown checksum type encountered: ");
00142 chkost << static_cast<int>(checkType);
00143 throw smbios::Exception<smbios::IException>( chkost.str() );
00144 }
00145
00146
00147
00148
00149
00150 if( !doUpdate || *static_cast<bool*>(doUpdate) )
00151 {
00152
00153 u32 actualChksum = 0;
00154 u32 calculatedChksum = 0;
00155 for( int i=0; i<len; ++i )
00156 {
00157 u8 byte = cmos->readByte(indexPort, dataPort, checksumLocation+i);
00158 actualChksum = (actualChksum << 8) | byte;
00159 calculatedChksum = calculatedChksum | (chksum[i] << (8*i));
00160 }
00161 if( actualChksum != calculatedChksum )
00162 {
00163 const cmos::Suppressable *o = dynamic_cast<const cmos::Suppressable *>(cmos);
00164 o->suppressNotification(true);
00165 for( int i=0; i<len; ++i )
00166 {
00167 cmos->writeByte(
00168 indexPort, dataPort,
00169 checksumLocation+i, chksum[len -i -1]);
00170 }
00171 o->resumeNotification(true);
00172 }
00173 }
00174 else
00175 {
00176 u32 actualChksum = 0;
00177 u32 calculatedChksum = 0;
00178 for( int i=0; i<len; ++i )
00179 {
00180 u8 byte = cmos->readByte(indexPort, dataPort, checksumLocation+i);
00181 actualChksum = (actualChksum << 8) | byte;
00182 calculatedChksum = calculatedChksum | (chksum[i] << (8*i));
00183 }
00184 if( actualChksum != calculatedChksum )
00185 {
00186 ost << _("Checking alternate checksum algorithm results.") << endl
00187 << _("Calculated (Type %(word_chksum_type)i) word checksum is: %(calc_word)i") << endl
00188 << _("Calculated (Type %(byte_chksum_type)i) byte checksum is: %(calc_byte)i") << endl
00189 << _("Calculated (Type %(word_crc_type)i) word crc is: %(calc_crc)i") << endl
00190 << _("Calculated (Type %(word_chksum_n_type)i) 1's complement word checksum is: %(calc_word_n)i") << endl
00191 << _("Actual data value is: %(actual)i") << endl
00192 << _("Calculated data value is: %(calc)i") << endl
00193 << _("Start: %(start)i") << endl
00194 << _("End: %(end)i") << endl
00195 << _("Checksum Loc: %(checksumLocation)i") << endl
00196 << _("Index Port: %(index)i") << endl
00197 << _("Data Port: %(data)i") << endl;
00198
00199 invalidChecksum.setParameter( "byte_chksum_type", CHECK_TYPE_BYTE_CHECKSUM );
00200 invalidChecksum.setParameter( "word_chksum_type", CHECK_TYPE_WORD_CHECKSUM );
00201 invalidChecksum.setParameter( "word_chksum_n_type", CHECK_TYPE_WORD_CHECKSUM_N );
00202 invalidChecksum.setParameter( "word_crc_type", CHECK_TYPE_WORD_CRC );
00203 invalidChecksum.setParameter("calc_byte", byteChecksum(cmos, start, end, indexPort, dataPort));
00204 invalidChecksum.setParameter("calc_word", wordChecksum(cmos, start, end, indexPort, dataPort, false));
00205 invalidChecksum.setParameter("calc_word_n", wordChecksum(cmos, start, end, indexPort, dataPort, true));
00206 invalidChecksum.setParameter("calc_crc", wordCrc(cmos, start, end, indexPort, dataPort));
00207 invalidChecksum.setParameter("actual", actualChksum);
00208 invalidChecksum.setParameter("calc", calculatedChksum);
00209 invalidChecksum.setParameter("start", start);
00210 invalidChecksum.setParameter("end", end);
00211 invalidChecksum.setParameter("checksumLocation", checksumLocation);
00212 invalidChecksum.setParameter("index", indexPort);
00213 invalidChecksum.setParameter("data", dataPort);
00214
00215 invalidChecksum.setMessageString( ost.str() );
00216 throw invalidChecksum;
00217 }
00218 }
00219 }
00220
00221
00222
00223
00224
00225
00226 static u8 byteChecksum(
00227 const ICmosRW *cmos, u32 start, u32 end,
00228 u32 indexPort, u32 dataPort )
00229 {
00230 u8 running_checksum=0;
00231
00232 for( u32 i = start; i <= end; i++)
00233 {
00234
00235 running_checksum = running_checksum + cmos->readByte( indexPort, dataPort, i );
00236 }
00237
00238 return static_cast<u8>(running_checksum);
00239 }
00240
00241
00242 static u16 wordChecksum(
00243 const ICmosRW *cmos, u32 start, u32 end,
00244 u32 indexPort, u32 dataPort, bool complement )
00245 {
00246 u16 running_checksum=0;
00247
00248 for( u32 i = start; i <= end; i++)
00249 {
00250
00251 running_checksum = running_checksum + cmos->readByte( indexPort, dataPort, i );
00252 }
00253
00254 if( complement )
00255 running_checksum = (~running_checksum) + 1;
00256 return running_checksum;
00257 }
00258
00259
00260 static u16 wordCrc(
00261 const ICmosRW *cmos, u32 start, u32 end,
00262 u32 indexPort, u32 dataPort )
00263 {
00264 u16 running_crc=0;
00265
00266 for( u32 i = start; i <= end; i++)
00267 {
00268 running_crc ^= cmos->readByte( indexPort, dataPort, i );
00269
00270 for( int j=0; j<7; j++ )
00271 {
00272 u16 temp = running_crc & 0x0001;
00273 running_crc >>= 1;
00274 if( temp != 0 )
00275 {
00276 running_crc |= 0x8000;
00277 running_crc ^= 0xA001;
00278 }
00279 }
00280 }
00281
00282 return running_crc;
00283 }
00284
00285 }
00286