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

checksum.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 "CmosRWImpl.h"
00026 #include "TokenImpl.h"
00027 
00028 // message.h should be included last.
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     // REGULAR CONSTRUCTOR
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     // COPY CONSTRUCTOR
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     // DESTRUCTOR
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         // optimize for the common case
00103         u8 len = sizeof(wordRetval);
00104         chksum = reinterpret_cast<const u8 *>(&wordRetval);
00105 
00106         // set up for the case where we throw an exception
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         // All zeros indicates that this range is not checksummed
00114         // icky to keep vc.net /w4 happy
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             // works because we are little endian.
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         // if NULL parameter passed, or
00149         // if parameter not null and evaluates to TRUE
00150         if( !doUpdate || *static_cast<bool*>(doUpdate) )
00151         {
00152             // only write new checksum if it doesn't match what is already there
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     * Checksum functions
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             // not += to keep vc.net /w4 happy
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             // not += to keep vc.net /w4 happy
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 

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