00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include "smbios/compat.h"
00021
00022 #include <errno.h>
00023 #include <string.h>
00024 #include <iostream>
00025 #include <sstream>
00026 #include <iomanip>
00027
00028 #include "RbuImpl.h"
00029 #include "smbios/IToken.h"
00030 #include "smbios/SystemInfo.h"
00031
00032
00033 #include "smbios/message.h"
00034
00035 using namespace std;
00036
00037 namespace rbu
00038 {
00039
00040 RbuFactory::~RbuFactory() throw() {}
00041 RbuFactory::RbuFactory() {}
00042
00043 RbuFactory *RbuFactory::getFactory()
00044 {
00045
00046
00047
00048 return RbuFactoryImpl::getFactory(reinterpret_cast<RbuFactoryImpl *>(0));
00049 }
00050
00051 RbuFactoryImpl::~RbuFactoryImpl() throw() { }
00052 RbuFactoryImpl::RbuFactoryImpl() { }
00053 IRbuHdr *RbuFactoryImpl::makeNew(std::string filename)
00054 {
00055 return new RbuHdr( filename );
00056 }
00057
00058 IRbuHdr::IRbuHdr() {}
00059 IRbuHdr::~IRbuHdr() {}
00060
00061
00062 RbuHdr::RbuHdr( string filename ) : hdrFh(fopen(filename.c_str(), "rb"))
00063 {
00064 if(!hdrFh)
00065 {
00066 string errmsg = strerror(errno);
00067 throw HdrFileIOErrorImpl(errmsg);
00068 }
00069
00070 memset(&header, 0, sizeof(header));
00071 size_t bytesRead = fread(&header, 1, sizeof(header), hdrFh);
00072 if (bytesRead != sizeof(header))
00073 {
00074 fclose(hdrFh);
00075 hdrFh=0;
00076 throw InvalidHdrFileImpl("Couldnt read full header.");
00077 }
00078 fseek(hdrFh, 0, 0);
00079 if (
00080 header.headerId[0] == '$' &&
00081 header.headerId[1] == 'R' &&
00082 header.headerId[2] == 'B' &&
00083 header.headerId[3] == 'U'
00084 )
00085 {
00086 }
00087 else
00088 {
00089 fclose(hdrFh);
00090 hdrFh=0;
00091 throw InvalidHdrFileImpl("Did not pass header $RBU check.");
00092 }
00093
00094
00095 memset(sysIdList, 0, sizeof(sysIdList));
00096 for( unsigned int i=0; i < (sizeof(header.systemIdList)/sizeof(header.systemIdList[0])); ++i)
00097 {
00098 if(i >= static_cast<unsigned int>(NUM_SYS_ID_IN_HDR)) break;
00099
00100
00101 u32 val = header.systemIdList[i];
00102 u32 id = (val & 0xFF) | ((val & 0xF800) >> 3);
00103
00104 if(!id) break;
00105
00106 sysIdList[i] = id;
00107 }
00108 }
00109
00110 RbuHdr::~RbuHdr()
00111 {
00112 if(hdrFh)
00113 fclose(hdrFh);
00114 }
00115
00116 string RbuHdr::getBiosVersion() const
00117 {
00118 string ver("");
00119 if( header.headerMajorVer < 2 )
00120 {
00121 if( isalnum(header.biosVersion[0]) )
00122 ver = ver + header.biosVersion[0];
00123
00124 if( isalnum(header.biosVersion[1]) )
00125 ver = ver + header.biosVersion[1];
00126
00127 if( isalnum(header.biosVersion[2]) )
00128 ver = ver + header.biosVersion[2];
00129 }
00130 else
00131 {
00132 std::ostringstream rep;
00133 rep << static_cast<int>(header.biosVersion[0]) << "."
00134 << static_cast<int>(header.biosVersion[1]) << "."
00135 << static_cast<int>(header.biosVersion[2]);
00136 ver = rep.str();
00137 }
00138 return ver;
00139 }
00140
00141 void RbuHdr::getHdrVersion(unsigned int &major, unsigned int &minor) const
00142 {
00143 major = header.headerMajorVer;
00144 minor = header.headerMinorVer;
00145 }
00146
00147 const u32 * RbuHdr::getSystemIdList() const {return sysIdList;}
00148
00149
00150 void RbuHdr::doUpdate() const {}
00151
00152 bool checkSystemId(const IRbuHdr &hdr, u16 sysId )
00153 {
00154 const u32 *idList = hdr.getSystemIdList();
00155 for (const u32 *ptr = idList; *ptr; ++ptr)
00156 if( *ptr == sysId )
00157 return true;
00158
00159 return false;
00160 }
00161
00162 FILE *RbuHdr::getFh() const
00163 {
00164 return hdrFh;
00165 }
00166
00167 ostream & operator << (ostream & cout, const IRbuHdr & hdr)
00168 {
00169 return hdr.streamify (cout);
00170 }
00171
00172 ostream & RbuHdr::streamify( ostream &cout ) const
00173 {
00174 std::ios::fmtflags old_opts = cout.flags ();
00175 cout << "HeaderId : "
00176 << header.headerId[0]
00177 << header.headerId[1]
00178 << header.headerId[2]
00179 << header.headerId[3] << endl;
00180
00181 cout << "Header Length: " << static_cast<int>(header.headerLength) << endl;
00182 cout << "Header Major Ver: " << static_cast<int>(header.headerMajorVer) << endl;
00183 cout << "Header Minor Ver: " << static_cast<int>(header.headerMinorVer) << endl;
00184 cout << "Num Systems: " << static_cast<int>(header.numSystems) << endl;
00185
00186 cout << "Version: " << getBiosVersion() << endl;
00187
00188 char quickCheck[41] = {0};
00189 strncpy(quickCheck, header.quickCheck, 40);
00190 cout << "Quick Check: " << quickCheck << endl;
00191
00192 cout << "System ID List:" << hex;
00193
00194 for (const u32 *ptr = sysIdList; *ptr; ++ptr)
00195 cout << " 0x" << setfill ('0') << setw (4) << *ptr;
00196
00197 cout << endl << dec;
00198 cout.flags (old_opts);
00199
00200 return cout;
00201 }
00202
00203
00204 static string stringToLower(string in)
00205 {
00206 for(unsigned int i=0;i<in.length();i++)
00207 in[i] = tolower(in[i]);
00208
00209 return in;
00210 }
00211
00212 static int compareSamePrefixOldBiosVersion(std::string ver1, std::string ver2)
00213 {
00214 if(ver1 > ver2)
00215 return -1;
00216
00217 if(ver1 < ver2)
00218 return 1;
00219
00220
00221 return 0;
00222 }
00223
00224 static int compareOldBiosVersion(std::string ver1, std::string ver2)
00225 {
00226 if (ver1[0] == ver2[0])
00227 return compareSamePrefixOldBiosVersion(ver1, ver2);
00228
00229 if (tolower(ver1[0]) == 'a')
00230 return -1;
00231
00232 if (tolower(ver2[0]) == 'a')
00233 return 1;
00234
00235 if (tolower(ver1[0]) == 'x')
00236 return -1;
00237
00238 if (tolower(ver2[0]) == 'x')
00239 return 1;
00240
00241 if (tolower(ver1[0]) == 'p')
00242 return -1;
00243
00244 if (tolower(ver2[0]) == 'p')
00245 return 1;
00246
00247 if (ver1[0] > ver2[0])
00248 return -1;
00249
00250 return 1;
00251 }
00252
00253
00254 void splitNewVersion(std::string ver, unsigned int &maj, unsigned int &min, unsigned int &ext)
00255 {
00256 unsigned int verSplit[3] = {0,};
00257
00258 DCOUT("splitNewVersion( \""<< ver <<"\" )" << endl);
00259
00260 size_t start=0, end=0;
00261 for(int i=0; i<3; i++)
00262 {
00263 string verPart = "";
00264 end = ver.find('.', start);
00265 verPart.append(ver, start, end - start);
00266
00267 verSplit[i] = strtoul(verPart.c_str(), 0, 10);
00268 DCOUT("Start(" << start << ") End(" << end << ") verPart(\"" << verPart << "\") verSplit[" << i << "](" << verSplit[i] << ")" << endl);
00269
00270 if( end == string::npos )
00271 break;
00272
00273 start = end + 1;
00274 }
00275
00276 maj = verSplit[0];
00277 min = verSplit[1];
00278 ext = verSplit[2];
00279
00280 DCOUT("Return: (" << maj << ", " << min << ", " << ext << ")" << endl);
00281 }
00282
00283
00284 static int compareNewBiosVersion(std::string ver1, std::string ver2)
00285 {
00286 unsigned int maj1, min1, ext1;
00287 unsigned int maj2, min2, ext2;
00288 splitNewVersion( ver1, maj1, min1, ext1 );
00289 splitNewVersion( ver2, maj2, min2, ext2 );
00290
00291
00292 const unsigned int SPECIAL_VER_START = 90;
00293 if (maj1 >= SPECIAL_VER_START && maj2 < SPECIAL_VER_START)
00294 return 1;
00295 if (maj1 < SPECIAL_VER_START && maj2 >= SPECIAL_VER_START)
00296 return -1;
00297
00298 if (maj1 > maj2)
00299 return -1;
00300 if (maj1 < maj2)
00301 return 1;
00302
00303 if (min1 > min2)
00304 return -1;
00305 if (min1 < min2)
00306 return 1;
00307
00308 if (ext1 > ext2)
00309 return -1;
00310 if (ext1 < ext2)
00311 return 1;
00312
00313
00314 return 0;
00315 }
00316
00317
00318 int compareBiosVersion(std::string ver1, std::string ver2)
00319 {
00320 ver1 = stringToLower(ver1);
00321 ver2 = stringToLower(ver2);
00322
00323
00324 if(ver1 == ver2)
00325 return 0;
00326
00327
00328 if ( isalpha(ver1[0]) && isalpha(ver2[0]) )
00329 return compareOldBiosVersion(ver1, ver2);
00330
00331
00332 if ( ! isalpha(ver1[0]) && isalpha(ver2[0]) )
00333 return -1;
00334
00335
00336 if ( isalpha(ver1[0]) && !isalpha(ver2[0]) )
00337 return 1;
00338
00339 if ( ! isalpha(ver1[0]) && !isalpha(ver2[0]) )
00340 return compareNewBiosVersion(ver1, ver2);
00341
00342
00343 return 0;
00344 }
00345
00346
00347
00348
00349 packet_type getSupportedPacketType(void)
00350 {
00351 packet_type pt = pt_mono;
00352 try
00353 {
00354 smbios::SmbiosFactory *smbiosFactory = smbios::SmbiosFactory::getFactory();
00355 smbios::ISmbiosTable *table = smbiosFactory->getSingleton();
00356 smbios::ISmbiosItem &rbuStructure = *((*table)[RBU_SMBIOS_STRUCT]);
00357
00358 u8 byte = getU8_FromItem(rbuStructure, 0x0F);
00359 if( byte & 0x01 )
00360 pt = pt_packet;
00361 }
00362 catch(const smbios::DataOutOfBounds &)
00363 {
00364
00365
00366 }
00367 return pt;
00368 }
00369
00370 void activateRbuToken()
00371 {
00372 smbios::TokenTableFactory *ttFactory = smbios::TokenTableFactory::getFactory() ;
00373 smbios::ITokenTable *tokenTable = ttFactory->getSingleton();
00374 (*tokenTable)[ RBU_ACTIVATE ]->activate();
00375 }
00376
00377 void cancelRbuToken()
00378 {
00379 smbios::TokenTableFactory *ttFactory = smbios::TokenTableFactory::getFactory() ;
00380 smbios::ITokenTable *tokenTable = ttFactory->getSingleton();
00381 (*tokenTable)[ RBU_CANCEL ]->activate();
00382 }
00383
00384 void checksumPacket(rbu_packet *pkt, size_t size)
00385 {
00386 u16 *buf = reinterpret_cast<u16 *>(pkt);
00387 pkt->pktChksum = 0;
00388
00389 u16 csum = 0;
00390 for(size_t i=0; i<size/2; ++i)
00391 csum = csum + buf[i];
00392
00393 pkt->pktChksum = -csum;
00394 }
00395
00396 void createPacket(char *buffer, size_t bufSize, size_t imageSize)
00397 {
00398
00399 rbu_packet *pkt = reinterpret_cast<rbu_packet *>(buffer);
00400
00401 pkt->pktId = 0x4B505224;
00402 pkt->pktSize = bufSize / 1024;
00403 pkt->reserved1 = 0;
00404 pkt->hdrSize = 2;
00405 int datasize = bufSize - (16 * pkt->hdrSize);
00406
00407 pkt->reserved2 = 0;
00408 pkt->pktSetId = 0x12345678;
00409 pkt->pktNum = 0;
00410 pkt->totPkts = (imageSize/datasize) + ((imageSize % datasize) ? 1:0) + 1;
00411 pkt->pktVer = 1;
00412 pkt->pktChksum = 0;
00413
00414 checksumPacket(pkt, bufSize);
00415 }
00416 }