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