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

System.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 #define LIBSMBIOS_SOURCE
00020 #include "smbios/ISmbios.h"
00021 #include "smbios/IToken.h"
00022 #include "smbios/ISmi.h"
00023 
00024 #include "smbios/SystemInfo.h"
00025 #include "smbios/IMemory.h"
00026 #include "smbios/SmbiosDefs.h"
00027 #include "ExceptionImpl.h"
00028 #include "TokenLowLevel.h"
00029 
00030 #include "DellMagic.h"
00031 
00032 #include "smbios/version.h"
00033 
00034 // this always should be included last
00035 #include "smbios/message.h"
00036 
00037 using namespace smbios;
00038 using namespace cmos;
00039 using namespace std;
00040 
00041 #if defined(DEBUG_SYSINFO)
00042 #   define DCOUT(line) do { cout << line; } while(0)
00043 #   define DCERR(line) do { cerr << line; } while(0)
00044 #else
00045 #   define DCOUT(line) do {} while(0)
00046 #   define DCERR(line) do {} while(0)
00047 #endif
00048 
00049 
00050 extern smbios::Exception<smbios::IException> SysInfoException;
00051 
00052 // so we don't have to change API, add new tryBiosPassword() function
00053 // that sets this password. This password will silently be used by
00054 // functions that need a password
00055 static std::string biosPassword = "";
00056 
00057 static void stripString( char *str )
00058 {
00059     if(!str)
00060         return;
00061 
00062     if(strlen(str) == 0)
00063         return;
00064 
00065     size_t ch = strlen(str); 
00066     do
00067     {
00068         --ch;
00069         if( ' ' == str[ch] )
00070             str[ch] = '\0';
00071         else
00072             break;
00073 
00074     } while(ch);
00075 }
00076 
00077 /***********************************************
00078  * specialty functions to decode dell service tag
00079  *
00080  * note: funny naming for the following functions
00081  *       as they were copied from another project
00082  **********************************************/
00083 static unsigned char dell_decode_digit( char tagval )
00084 {
00085     // input == value from 0 - 0x1E
00086     // output == ascii
00087     // --> take value from range 0 - 0x1E and give ascii value
00088     if( tagval > 0x19 )
00089         tagval += 0x3C;   /* V-Z, 0x1A-0x1E */
00090     else if( tagval > 0x14 )
00091         tagval += 0x3B;   /* P-T, 0x15-0x19 */
00092     else if( tagval > 0x0F )
00093         tagval += 0x3A;   /* J-N, 0x10-0x14 */
00094     else if( tagval > 0x0C )
00095         tagval += 0x39;   /* F-H, 0x0D-0x0F */
00096     else if( tagval > 0x09 )
00097         tagval += 0x38;   /* B-D, 0x0A-0x0C */
00098     else
00099         tagval += 0x30;   /* 0-9, 0x00-0x09 */
00100 
00101     return tagval;
00102 }
00103 
00104 // decodes tag in-place
00105 static void dell_decode_service_tag( char *tag, int len )
00106 {
00107     // see encoding function for nice ascii art representation.
00108     //
00109     if( ((tag)[0] & (1<<7)) == (1<<7) )
00110     {
00111         char new_tag[SVC_TAG_LEN_MAX + 1] = {0,};
00112 
00113         // yuck.
00114         new_tag[6] = dell_decode_digit( (tag[4] & 0x1F) );
00115         new_tag[5] = dell_decode_digit( ((tag[3] & 0x03)<<3) | ((tag[4]>>5) & 0x07) );
00116         new_tag[4] = dell_decode_digit( ((tag[3] & 0x7C)>>2) );
00117         new_tag[3] = dell_decode_digit( (((tag[2] & 0x0F)<<1) | ((tag[3]>>7) & 0x01)) );
00118         new_tag[2] = dell_decode_digit( (((tag[1] & 0x01)<<4) | ((tag[2]>>4) & 0xF)) & 0x1F);
00119         new_tag[1] = dell_decode_digit( ((tag[1] & 0x3E)>>1) & 0x1F );
00120         new_tag[0] = (tag[0] ^ (1<<7));
00121 
00122         memset(tag, 0, len);
00123         strncpy(tag, new_tag, len < SVC_TAG_LEN_MAX ? len : SVC_TAG_LEN_MAX);
00124     }
00125 }
00126 
00127 static unsigned char dell_encode_digit( char ch )
00128 {
00129     // input == ascii
00130     // output == value from 0 - 0x1E
00131     // scale ascii value down to range 0-0x1E
00132     // valid input ascii == Alphanumeric - vowels
00133     // invalid input is converted to the char '0' (zero)
00134     int uc = toupper(ch);
00135     int retval = 0;
00136     if ( uc >= '0' && uc <= '9' )
00137         retval = uc - 0x30;
00138     if ( uc >= 'B' && uc <= 'D' )
00139         retval = uc - 0x38;
00140     if ( uc >= 'F' && uc <= 'H' )
00141         retval = uc - 0x39;
00142     if ( uc >= 'J' && uc <= 'N' )
00143         retval = uc - 0x3A;
00144     if ( uc >= 'P' && uc <= 'T' )
00145         retval = uc - 0x3B;
00146     if ( uc >= 'V' && uc <= 'Z' )
00147         retval = uc - 0x3C;
00148     return static_cast<unsigned char>(retval);
00149 }
00150 
00151 static void dell_encode_service_tag( char *tag, size_t len )
00152 {
00153     if (len <= SVC_TAG_CMOS_LEN_MAX)
00154         return;
00155 
00156     // codes a 7-char value into 5 bytes
00157     //
00158     //    byte       byte        byte        byte         byte
00159     //     0           1           2           3           4
00160     //|----|----| |----|----| |----|----| |----|----| |----|----|
00161     // 1  0 0000     11 1112   2222 3333   3444 4455   5556 6666
00162     //     char0     char1  char2    char3  char4  char5    char6
00163     //
00164     // note: high bit set in byte0 to indicate coded tag.
00165 
00166     char tagToSet[SVC_TAG_LEN_MAX] = {0,};
00167     memcpy(tagToSet, tag, len < SVC_TAG_LEN_MAX ? len : SVC_TAG_LEN_MAX );
00168 
00169     char newTagBuf[SVC_TAG_CMOS_LEN_MAX] = {0,};
00170 
00171     // char 0
00172     newTagBuf[0] = tagToSet[0] | 1<<7;
00173 
00174     // char 1
00175     newTagBuf[1] = dell_encode_digit(tagToSet[1]) << 1;
00176 
00177     // char 2
00178     newTagBuf[1] = newTagBuf[1] | dell_encode_digit(tagToSet[2]) >> 4;
00179     newTagBuf[2] = dell_encode_digit(tagToSet[2]) << 4;
00180 
00181     // char 3
00182     newTagBuf[2] = newTagBuf[2] | dell_encode_digit(tagToSet[3]) >> 1;
00183     newTagBuf[3] = dell_encode_digit(tagToSet[3]) << 7;
00184 
00185     // char 4
00186     newTagBuf[3] = newTagBuf[3] | dell_encode_digit(tagToSet[4]) << 2;
00187 
00188     // char 5
00189     newTagBuf[3] = newTagBuf[3] | dell_encode_digit(tagToSet[5]) >> 3;
00190     newTagBuf[4] = dell_encode_digit(tagToSet[5]) << 5;
00191 
00192     // char 6
00193     newTagBuf[4] = newTagBuf[4] | dell_encode_digit(tagToSet[6]);
00194 
00195     memset(tag, 0, len);
00196     memcpy(tag, newTagBuf, len < SVC_TAG_CMOS_LEN_MAX ? len: SVC_TAG_CMOS_LEN_MAX);
00197     return;
00198 }
00199 
00200 
00201 const char *SMBIOSGetLibraryVersionString()
00202 {
00203     // LIBSMBIOS_RELEASE_VERSION is a macro defined by the build system
00204     return LIBSMBIOS_RELEASE_VERSION;
00205 }
00206 
00207 void SMBIOSFreeMemory( const char *ptr )
00208 {
00209     delete [] const_cast<char *>(ptr);
00210 }
00211 
00212 /* only for service/asset tags. */
00213 static char *getTagFromSMI(u16 select)
00214 {
00215     u32 args[4] = {0,}, res[4] = {0,};
00216     smi::doSimpleCallingInterfaceSmi(11, select, args, res);
00217 
00218     char *retval = new char[16];
00219     memset(retval, '\0', 16);
00220 
00221     memcpy(retval, reinterpret_cast<u8 *>(&(res[1])), sizeof(res));
00222 
00223     for(size_t i=0; i<strlen(retval); i++)
00224         if( static_cast<unsigned char>(retval[i]) == 0xFF ) retval[i] = '\0';
00225     
00226     return retval;
00227 }
00228 
00229 /* only for service/asset tags. */
00230 static void setTagUsingSMI(const char *newTag, u16 select)
00231 {
00232     u32 args[4] = {0,}, res[4] = {0,};
00233     strncpy(reinterpret_cast<char *>(args), newTag, 12);
00234     args[3] = smi::getAuthenticationKey(biosPassword);
00235     smi::doSimpleCallingInterfaceSmi(11, select, args, res);
00236 }
00237 
00238 static char *getStringFromTable(unsigned int structure, unsigned int stringNumber)
00239 {
00240     smbios::ISmbiosTable *table = 0;
00241     table = smbios::SmbiosFactory::getFactory()->getSingleton();
00242 
00243     if (!table)
00244         throw InternalErrorImpl();
00245 
00246     const char *tempval = 0;
00247     tempval = getString_FromItem(*(*table)[structure], stringNumber);
00248 
00249     if(!tempval)
00250         throw exception();
00251 
00252     size_t slen = strlen(tempval);
00253     char *retval = new char[slen + 1];
00254     strncpy(retval,tempval,slen);
00255     retval[slen] = '\0';
00256 
00257     stripString(retval);
00258     if ( ! strlen(retval ))
00259     {
00260         delete [] retval;
00261         retval = 0;
00262         throw exception(); // skip this one because returned string was all spaces. 
00263     }
00264 
00265     return retval;
00266 }
00267 
00268 static char *getServiceTagFromSysInfo()
00269 {
00270     DCOUT( "in getServiceTagFromSysInfo()" << endl);
00271     return getStringFromTable(System_Information, System_Information_Serial_Number_Offset);
00272 }
00273 
00274 static char *getServiceTagFromSysEncl()
00275 {
00276     DCOUT( "in getServiceTagFromSysEncl()" << endl);
00277     return getStringFromTable(System_Enclosure_or_Chassis, System_Enclosure_or_Chassis_Service_Offset);
00278 }
00279 
00280 // not static so that unit tests can peek here. Not part of public API, though.
00281 char *getServiceTagFromCMOSToken()
00282 {
00283     smbios::ITokenTable *table = 0;
00284     table = smbios::TokenTableFactory::getFactory()->getSingleton();
00285 
00286     DCOUT( "in getServiceTagFromCMOSToken()" << endl);
00287 
00288     if (0 == table)
00289     {
00290         throw InternalErrorImpl();
00291     }
00292 
00293     char *tempval = 0;
00294     try
00295     {
00296         // Step 1: Get tag from CMOS
00297         tempval = new char[SVC_TAG_LEN_MAX + 1];
00298         memset(tempval, '\0', SVC_TAG_LEN_MAX + 1);
00299         // will throw an exception if not found.
00300         (*table)[Cmos_Service_Token]->getString(reinterpret_cast<u8*>(tempval), SVC_TAG_CMOS_LEN_MAX + 1);
00301 
00302         // Step 2: Decode 7-char tag from 5-char CMOS value
00303         dell_decode_service_tag( tempval, SVC_TAG_LEN_MAX + 1 );
00304 
00305         // Step 3: Make sure checksum is good before returning value
00306         u16 indexPort, dataPort;
00307         u8  location;
00308 
00309         smbios::IToken *token = &(*((*table)[ Cmos_Service_Token ]));
00310         dynamic_cast< smbios::ICmosToken * >(token)->getCMOSDetails( &indexPort, &dataPort, &location );
00311 
00312         u8 csum = 0;
00313         ICmosRW *cmos = cmos::CmosRWFactory::getFactory()->getSingleton();
00314 
00315         for( u32 i = 0; i < SVC_TAG_CMOS_LEN_MAX; i++)
00316         {
00317             // stupid stuff to avoid MVC++ .NET runtime exception check for cast to different size
00318             csum = (csum + cmos->readByte( indexPort, dataPort, location + i )) & 0xFF;
00319         }
00320 
00321         // stupid stuff to avoid MVC++ .NET runtime exception check for cast to different size
00322         csum = (csum - cmos->readByte( indexPort, dataPort, location + SVC_TAG_CMOS_LEN_MAX )) & 0xFF;
00323         if( csum ) // bad (should be zero)
00324             throw "Bad checksum";
00325     }
00326     catch( ... )
00327     {
00328         delete [] tempval;
00329         throw;
00330     }
00331 
00332     return tempval;
00333 }
00334 
00335 // not static so that unit tests can peek here. Not part of public API, though.
00336 char *getServiceTagFromSMI()
00337 {
00338     DCOUT( "in getServiceTagFromSMI()" << endl);
00339     return getTagFromSMI( 2 ); /* Read service tag select code */
00340 }
00341 
00342 // Code for getting the service tag from one of many locations
00343 struct DellGetServiceTagFunctions
00344 {
00345     char *(*f_ptr)();
00346 }
00347 
00348 /* try dynamic functions first to make sure we get current data. */
00349 DellGetServiceTagFunctions[] = {
00350                                    {&getServiceTagFromSMI,},       // SMI Token
00351                                    {&getServiceTagFromCMOSToken,}, // CMOS Token
00352                                    {&getServiceTagFromSysInfo,},   // SMBIOS System Information Item
00353                                    {&getServiceTagFromSysEncl,},   // SMBIOS System Enclosure Item
00354                                };
00355 
00356 const char *SMBIOSGetServiceTag()
00357 {
00358     char *serviceTag = 0;
00359     int numEntries =
00360         sizeof (DellGetServiceTagFunctions) / sizeof (DellGetServiceTagFunctions[0]);
00361 
00362     DCOUT( "numEntries: " << numEntries << endl);
00363 
00364     for (int i = 0; (i < numEntries) && (!serviceTag); ++i)
00365     {
00366         // eat exceptions from lowlevel functions and keep going.
00367         try
00368         {
00369             DCOUT("  try #" << i << endl);
00370             // first function to return non-zero id wins.
00371             serviceTag = DellGetServiceTagFunctions[i].f_ptr ();
00372         }
00373         catch(const exception &e)
00374         {
00375             DCOUT("  Caught exception: " << e.what() << endl);
00376             SysInfoException.setMessageString(e.what());
00377         }
00378         catch(...)
00379         {
00380             DCOUT("  Caught unknown exception" << endl);
00381             SysInfoException.setMessageString( _("Unknown internal error occurred") );
00382         }
00383 
00384         if(serviceTag)
00385             DCOUT( "    GOT TAG: -->" << serviceTag << "<--" << endl);
00386     }
00387     stripString(serviceTag);
00388     return serviceTag;
00389 }
00390 
00391 void setServiceTagUsingCMOSToken(const char *newTag, size_t len)
00392 {
00393     smbios::ITokenTable *table = 0;
00394     table = smbios::TokenTableFactory::getFactory()->getSingleton();
00395 
00396     if (0 == table)
00397     {
00398         throw InternalErrorImpl();
00399     }
00400 
00401     try
00402     {
00403         // don't want to modify user-supplied buffer, so copy new tag
00404         // to our own buffer.
00405         char codedTag[SVC_TAG_LEN_MAX + 1] = {0,}; // null padded
00406         // copy (possibly oversize) user input to our buffer.
00407         strncpy(codedTag, newTag, len < SVC_TAG_LEN_MAX ? len : SVC_TAG_LEN_MAX);
00408         // encode in place, if necessary
00409         dell_encode_service_tag(codedTag, len);
00410         // will throw an exception if not found.
00411 
00412         // Step 1: set string: safe to use whole codedTag as it is guaranteed zero-padded
00413         (*table)[Cmos_Service_Token]->setString(reinterpret_cast<const u8*>(codedTag), SVC_TAG_CMOS_LEN_MAX);
00414 
00415         // Step 2: reset checksum
00416         u16 indexPort, dataPort;
00417         u8  location;
00418 
00419         smbios::IToken *token = &(*((*table)[ Cmos_Service_Token ]));
00420         dynamic_cast< smbios::ICmosToken * >(token)->getCMOSDetails( &indexPort, &dataPort, &location );
00421 
00422         u8 csum = 0;
00423         ICmosRW *cmos = cmos::CmosRWFactory::getFactory()->getSingleton();
00424 
00425         for( u32 i = 0; i < SVC_TAG_CMOS_LEN_MAX; i++)
00426         {
00427             // stupid stuff to avoid MVC++ .NET runtime exception check for cast to different size
00428             csum = (csum + cmos->readByte( indexPort, dataPort, location + i )) & 0xFF;
00429         }
00430 
00431         cmos->writeByte(
00432             indexPort,
00433             dataPort,
00434             location + SVC_TAG_CMOS_LEN_MAX,
00435             csum
00436         );
00437     }
00438     catch( const smbios::IException & )
00439     {
00440         throw;
00441     }
00442 
00443 }
00444 
00445 // Important note from the docs:
00446 /*  Only the manufacturing software that’s loading the service tag into the system should use this interface.
00447     Some systems may return an error when the service tag has already been set (i.e. they prevent this function from changing the service tag once it has been set).
00448     */
00449 void setServiceTagUsingSMI(const char *newTag, size_t size)
00450 {
00451     (void) size; // avoid unused var warning.
00452     setTagUsingSMI( newTag, 3 ); /* Write service tag select code */
00453 }
00454 
00455 // Code for getting the service tag from one of many locations
00456 struct DellSetServiceTagFunctions
00457 {
00458     void (*f_ptr)(const char *, size_t);
00459 }
00460 
00461 DellSetServiceTagFunctions[] = {
00462                                    {&setServiceTagUsingSMI,},   // SMBIOS System Information Item
00463                                    {&setServiceTagUsingCMOSToken,},   // SMBIOS System Information Item
00464                                };
00465 
00466 int SMBIOSSetServiceTag(const char *password, const char *serviceTag, size_t len)
00467 {
00468     int retval = -1;
00469     int numEntries =
00470         sizeof (DellSetServiceTagFunctions) / sizeof (DellSetServiceTagFunctions[0]);
00471 
00472     if(password)
00473         biosPassword = password;
00474 
00475     for (int i = 0; (i < numEntries); ++i)
00476     {
00477         // eat exceptions from lowlevel functions and keep going.
00478         try
00479         {
00480             // first function to return non-zero id wins.
00481             DellSetServiceTagFunctions[i].f_ptr (serviceTag, len);
00482             retval = 0;
00483         }
00484         catch(const smbios::IException &e)
00485         {
00486             SysInfoException.setMessageString(e.what());
00487         }
00488         catch(...)
00489         {
00490             SysInfoException.setMessageString( _("Unknown internal error occurred") );
00491         }
00492     }
00493     return retval;
00494 }
00495 
00496 static char *getAssetTagFromSysEncl()
00497 {
00498     return getStringFromTable(System_Enclosure_or_Chassis, System_Enclosure_or_Chassis_Asset_Offset);
00499 }
00500 
00501 // not static so we can use it in unit test, but not part of public API.
00502 // you have been warned.
00503 char *getAssetTagFromToken()
00504 {
00505     smbios::ITokenTable *table = 0;
00506     table = smbios::TokenTableFactory::getFactory()->getSingleton();
00507 
00508     if (0 == table)
00509     {
00510         throw InternalErrorImpl();
00511     }
00512 
00513     u8 *tempval = 0;
00514     try
00515     {
00516         tempval = new u8[ASSET_TAG_LEN_MAX + 1];
00517         memset(tempval, '\0', ASSET_TAG_LEN_MAX + 1);
00518         (*table)[Cmos_Asset_Token]->getString(tempval, ASSET_TAG_LEN_MAX + 1);
00519 
00520         // Step 3: Make sure checksum is good before returning value
00521         u16 indexPort, dataPort;
00522         u8  location;
00523 
00524         smbios::IToken *token = &(*((*table)[ Cmos_Asset_Token ]));
00525         dynamic_cast< smbios::ICmosToken * >(token)->getCMOSDetails( &indexPort, &dataPort, &location );
00526 
00527         u8 csum = 0;
00528         ICmosRW *cmos = cmos::CmosRWFactory::getFactory()->getSingleton();
00529 
00530         for( u32 i = 0; i < ASSET_TAG_CMOS_LEN_MAX; i++)
00531         {
00532             // stupid stuff to avoid MVC++ .NET runtime exception check for cast to different size
00533             csum = (csum + cmos->readByte( indexPort, dataPort, location + i )) & 0xFF;
00534         }
00535 
00536         // stupid stuff to avoid MVC++ .NET runtime exception check for cast to different size
00537         csum = (csum - cmos->readByte( indexPort, dataPort, location + ASSET_TAG_CMOS_LEN_MAX )) & 0xFF;
00538         if( csum ) // bad (should be zero)
00539             throw "Bad checksum";
00540     }
00541     catch (...)
00542     {
00543         delete [] tempval;
00544         throw;
00545     }
00546 
00547     return reinterpret_cast<char*>(tempval);
00548 }
00549 
00550 char *getAssetTagFromSMI()
00551 {
00552     return getTagFromSMI( 0 ); /* Read asset tag select code */
00553 }
00554 
00555 // Code for getting the asset tag from one of many locations
00556 struct DellAssetTagFunctions
00557 {
00558     char *(*f_ptr)();
00559 }
00560 
00561 /* try dynamic functions first to make sure we get current data. */
00562 DellAssetTagFunctions[] = {
00563                               {&getAssetTagFromSMI,},     // SMI
00564                               {&getAssetTagFromToken,},   // SMBIOS Token
00565                               {&getAssetTagFromSysEncl,}, // SMBIOS System Information Item
00566                           };
00567 
00568 const char *SMBIOSGetAssetTag()
00569 {
00570     char *assetTag = 0;
00571     int numEntries =
00572         sizeof (DellAssetTagFunctions) / sizeof (DellAssetTagFunctions[0]);
00573 
00574     for (int i = 0; (i < numEntries) && (!assetTag); ++i)
00575     {
00576         // eat exceptions from lowlevel functions and keep going.
00577         try
00578         {
00579             // first function to return non-zero id wins.
00580             assetTag = DellAssetTagFunctions[i].f_ptr ();
00581         }
00582         catch(const smbios::IException &e)
00583         {
00584             SysInfoException.setMessageString(e.what());
00585         }
00586         catch(...)
00587         {
00588             SysInfoException.setMessageString( _("Unknown internal error occurred") );
00589         }
00590     }
00591     stripString(assetTag);
00592     return assetTag;
00593 }
00594 
00595 
00596 
00597 void setAssetTagUsingCMOSToken(const char *newTag, size_t len)
00598 {
00599     smbios::ITokenTable *table = 0;
00600     table = smbios::TokenTableFactory::getFactory()->getSingleton();
00601 
00602     if (0 == table)
00603     {
00604         throw InternalErrorImpl();
00605     }
00606 
00607     try
00608     {
00609         // Step 1: set string
00610         (*table)[Cmos_Asset_Token]->setString(reinterpret_cast<const u8*>(newTag), len < ASSET_TAG_CMOS_LEN_MAX? len : ASSET_TAG_CMOS_LEN_MAX);
00611 
00612         // Step 2: reset checksum
00613         u16 indexPort, dataPort;
00614         u8  location;
00615 
00616         smbios::IToken *token = &(*((*table)[ Cmos_Asset_Token ]));
00617         dynamic_cast< smbios::ICmosToken * >(token)->getCMOSDetails( &indexPort, &dataPort, &location );
00618 
00619         u8 csum = 0;
00620         ICmosRW *cmos = cmos::CmosRWFactory::getFactory()->getSingleton();
00621 
00622         for( u32 i = 0; i < ASSET_TAG_CMOS_LEN_MAX; i++)
00623         {
00624             // stupid stuff to avoid MVC++ .NET runtime exception check for cast to different size
00625             csum = (csum + cmos->readByte( indexPort, dataPort, location + i )) & 0xFF;
00626         }
00627 
00628         cmos->writeByte(
00629             indexPort,
00630             dataPort,
00631             location + ASSET_TAG_CMOS_LEN_MAX,
00632             csum
00633         );
00634     }
00635     catch( const smbios::IException & )
00636     {
00637         throw;
00638     }
00639 
00640 }
00641 
00642 void setAssetTagUsingSMI(const char *newTag, size_t size)
00643 {
00644     (void) size; // avoid unused var warning.
00645     setTagUsingSMI( newTag, 1 ); /* Write asset tag select code */
00646 }
00647 
00648 // Code for getting the service tag from one of many locations
00649 struct DellSetAssetTagFunctions
00650 {
00651     void (*f_ptr)(const char *, size_t);
00652     const char * desc;
00653 }
00654 
00655 DellSetAssetTagFunctions[] = {
00656                                  {&setAssetTagUsingSMI, "SMI"},   // SMBIOS System Information Item
00657                                  {&setAssetTagUsingCMOSToken, "CMOS"},   // SMBIOS System Information Item
00658                              };
00659 
00660 int SMBIOSSetAssetTag(const char *password, const char *assetTag, size_t len)
00661 {
00662     int retval = -1;
00663     int numEntries =
00664         sizeof (DellSetAssetTagFunctions) / sizeof (DellSetAssetTagFunctions[0]);
00665 
00666     if(password)
00667         biosPassword = password;
00668 
00669     for (int i = 0; (i < numEntries); ++i)
00670     {
00671         // eat exceptions from lowlevel functions and keep going.
00672         try
00673         {
00674             // first function to return non-zero id wins.
00675             DellSetAssetTagFunctions[i].f_ptr (assetTag, len);
00676             retval = 0;
00677         }
00678         catch(const smbios::IException &e)
00679         {
00680             SysInfoException.setMessageString(e.what());
00681         }
00682         catch(...)
00683         {
00684             SysInfoException.setMessageString( _("Unknown internal error occurred") );
00685         }
00686     }
00687     return retval;
00688 }
00689 
00690 
00691 static char *getSystemNameFromSysInfo()
00692 {
00693     return getStringFromTable(System_Information, System_Information_Product_Name_Offset);
00694 }
00695 
00696 // Struct for getting the system name from one of many locations
00697 struct DellSystemNameFunctions
00698 {
00699     char *(*f_ptr)();
00700 }
00701 
00702 DellSystemNameFunctions[] = {
00703                                 {&getSystemNameFromSysInfo,}    // SMBIOS System Information Item
00704                             };
00705 
00706 const char *SMBIOSGetSystemName()
00707 {
00708     char *systemName= 0;
00709     int numEntries =
00710         sizeof (DellSystemNameFunctions) / sizeof (DellSystemNameFunctions[0]);
00711 
00712     for (int i = 0; (i < numEntries) && (!systemName); ++i)
00713     {
00714         // eat exceptions from lowlevel functions and keep going.
00715         try
00716         {
00717             // first function to return non-zero id wins.
00718             systemName = DellSystemNameFunctions[i].f_ptr ();
00719         }
00720         catch(const smbios::IException &e)
00721         {
00722             SysInfoException.setMessageString(e.what());
00723         }
00724         catch(...)
00725         {
00726             SysInfoException.setMessageString( _("Unknown internal error occurred") );
00727         }
00728     }
00729 
00730     stripString(systemName);
00731     return systemName;
00732 }
00733 
00734 // for Diamond only.
00735 static char *getBiosVersionFromOneByteStructForDiamond()
00736 {
00737     memory::IMemory *mem = 0;
00738     u8 strBuf[DELL_SYSTEM_STRING_LEN] = { 0, };
00739     u8 *biosVersion = 0;
00740 
00741     mem = memory::MemoryFactory::getFactory()->getSingleton();
00742 
00743     if( 0 == mem )
00744         throw InternalErrorImpl();
00745 
00746     // Step 1: Check that "Dell System" is present at the proper offset
00747     mem->fillBuffer( strBuf, DELL_SYSTEM_STRING_LOC_DIAMOND_1, DELL_SYSTEM_STRING_LEN - 1 );
00748     if( strncmp( reinterpret_cast<char*>(strBuf), DELL_SYSTEM_STRING, DELL_SYSTEM_STRING_LEN ) == 0 )
00749         if( SYSTEM_ID_DIAMOND == mem->getByte( ID_BYTE_LOC_DIAMOND_1 ) )
00750         {
00751             biosVersion = new u8[4];
00752             mem->fillBuffer(biosVersion, ID_BYTE_LOC_DIAMOND_1 + 1, 3);
00753             biosVersion[3] = '\0';
00754         }
00755 
00756     mem->fillBuffer( strBuf, DELL_SYSTEM_STRING_LOC_DIAMOND_2, DELL_SYSTEM_STRING_LEN - 1 );
00757     if( strncmp( reinterpret_cast<char*>(strBuf), DELL_SYSTEM_STRING, DELL_SYSTEM_STRING_LEN ) == 0 )
00758         if( SYSTEM_ID_DIAMOND == mem->getByte( ID_BYTE_LOC_DIAMOND_2 ) )
00759         {
00760             biosVersion = new u8[4];
00761             mem->fillBuffer(biosVersion, ID_BYTE_LOC_DIAMOND_2 + 1, 3);
00762             biosVersion[3] = '\0';
00763         }
00764 
00765     return reinterpret_cast<char*>(biosVersion);
00766 }
00767 
00768 static char *getBiosVersionFromSmbios()
00769 {
00770     return getStringFromTable(BIOS_Information, BIOS_Information_Version_Offset);
00771 }
00772 
00773 // Code for getting the service tag from one of many locations
00774 struct DellBiosVersionFunctions
00775 {
00776     char *(*f_ptr)();
00777 }
00778 DellBiosVersionFunctions[] = {
00779                                  {&getBiosVersionFromOneByteStructForDiamond,},    // Diamond
00780                                  {&getBiosVersionFromSmbios,}
00781                              };
00782 
00783 const char *SMBIOSGetBiosVersion()
00784 {
00785     char *systemName= 0;
00786     int numEntries =
00787         sizeof (DellBiosVersionFunctions) / sizeof (DellBiosVersionFunctions[0]);
00788 
00789     for (int i = 0; (i < numEntries) && (!systemName); ++i)
00790     {
00791         // eat exceptions from lowlevel functions and keep going.
00792         try
00793         {
00794             // first function to return non-zero id wins.
00795             systemName = DellBiosVersionFunctions[i].f_ptr ();
00796         }
00797         catch(const smbios::IException &e)
00798         {
00799             SysInfoException.setMessageString(e.what());
00800         }
00801         catch(...)
00802         {
00803             SysInfoException.setMessageString( _("Unknown internal error occurred") );
00804         }
00805     }
00806 
00807     stripString(systemName);
00808     return systemName;
00809 }
00810 
00811 
00812 const char *SMBIOSGetVendorName()
00813 {
00814     char *retval = 0;
00815 
00816     try
00817     {
00818         retval = getStringFromTable(System_Information, System_Information_Manufacturer_Offset);
00819     }
00820     catch(const smbios::IException &e)
00821     {
00822         SysInfoException.setMessageString(e.what());
00823     }
00824     catch(...)
00825     {
00826         SysInfoException.setMessageString( _("Unknown internal error occurred") );
00827     }
00828 
00829     stripString(retval);
00830     return retval;
00831 }
00832 
00833 
00834 int SMBIOSHasNvramStateBytes()
00835 {
00836     int retval = 1;
00837     try
00838     {
00839         smbios::TokenTableFactory *ttFactory = smbios::TokenTableFactory::getFactory() ;
00840         smbios::ITokenTable *tokenTable = ttFactory->getSingleton();
00841 
00842         u8 tempData[2] = {0,0};
00843         (*tokenTable)[ NvramByte1_Token  ]->getString( tempData, 2 );
00844         (*tokenTable)[ NvramByte2_Token  ]->getString( tempData, 2 );
00845     }
00846     catch(const smbios::IException &e)
00847     {
00848         SysInfoException.setMessageString(e.what());
00849         retval = 0;
00850     }
00851     catch(...)
00852     {
00853         SysInfoException.setMessageString( _("Unknown internal error occurred") );
00854     }
00855 
00856     return retval;
00857 }
00858 
00859 
00860 // user =
00861 //      0x0000 = DSA
00862 //      0x8000 = OM Toolkit
00863 //      0x9000 = open
00864 //      0xA000 = open
00865 //      0xB000 = open
00866 //      0xC000 = open
00867 //      0xD000 = open
00868 //      0xE000 = open
00869 //      0xF000 = expand to whole byte
00870 int SMBIOSGetNvramStateBytes( int user )
00871 {
00872     u8 tempData[2] = {0,0};
00873     int retval = 0;
00874     try
00875     {
00876         smbios::TokenTableFactory *ttFactory = smbios::TokenTableFactory::getFactory() ;
00877         smbios::ITokenTable *tokenTable = ttFactory->getSingleton();
00878 
00879         (*tokenTable)[ NvramByte1_Token  ]->getString( tempData, 2 );
00880         retval = *tempData;
00881         (*tokenTable)[ NvramByte2_Token  ]->getString( tempData, 2 );
00882         retval |= (*tempData << 8);
00883     }
00884     catch(const smbios::IException &e)
00885     {
00886         SysInfoException.setMessageString(e.what());
00887     }
00888     catch(...)
00889     {
00890         SysInfoException.setMessageString( _("Unknown internal error occurred") );
00891     }
00892 
00893     if( user == 0x0000 )  // DSA
00894     {
00895         if( (retval & 0x8000) != user )
00896         {
00897             retval = 0;  // user doesn't match, return default
00898         }
00899         retval &= ~0x8000; // mask user bits
00900     }
00901     else
00902     {
00903         if ((user & 0xF000) == 0xF000 ) // probably will never be used
00904         {
00905             if( (retval & 0xFF00) != user )
00906             {
00907                 retval = 0;// user doesn't match, return default
00908             }
00909             retval &= ~0xFF00; // mask user bits
00910         }
00911         else
00912         {
00913             if( (retval & 0xF000) != user ) // Toolkit (or users 0x9 - 0xE)
00914             {
00915                 retval = 0;// user doesn't match, return default
00916             }
00917             retval &= ~0xF000; // mask user bits
00918         }
00919     }
00920     return retval;
00921 }
00922 
00923 void SMBIOSSetNvramStateBytes(int value, int user)
00924 {
00925     try
00926     {
00927         if ( user == 0x0000 ) // DSA
00928         {
00929             value &= ~0x8000;  // mask user bits
00930             value |= user;     // set user
00931         }
00932         else if( (user & 0xF000) == 0xF000 )
00933         {
00934             value &= ~0xFF00;   // mask user bits
00935             value |= user;      // set user
00936         }
00937         else
00938         {
00939             value &= ~0xF000;   // mask user bits
00940             value |= user;      // set user
00941         }
00942 
00943         smbios::TokenTableFactory *ttFactory = smbios::TokenTableFactory::getFactory() ;
00944         smbios::ITokenTable *tokenTable = ttFactory->getSingleton();
00945 
00946         u8 *tempData = reinterpret_cast<u8*>(&value);
00947         (*tokenTable)[ NvramByte1_Token  ]->setString( tempData, 1 );
00948         (*tokenTable)[ NvramByte2_Token  ]->setString( tempData+1, 1 );
00949     }
00950     catch(const smbios::IException &e)
00951     {
00952         SysInfoException.setMessageString(e.what());
00953     }
00954     catch(...)
00955     {
00956         SysInfoException.setMessageString( _("Unknown internal error occurred") );
00957     }
00958     return;
00959 }
00960 
00961 
00962 static bool getUpOffsetAndFlag (up_info *up)
00963 {
00964     memory::IMemory *mem =
00965         memory::MemoryFactory::getFactory()->getSingleton();
00966 
00967     up_info tempUP;
00968     memset(&tempUP, 0, sizeof(tempUP));
00969     int step_size = 16;
00970 
00971     unsigned int fp = 0xF0000;
00972     bool found = false;
00973     while( fp < (0xFFFFFUL - sizeof(tempUP)) )
00974     {
00975         mem->fillBuffer(
00976             reinterpret_cast<u8 *>(&tempUP),
00977             fp,
00978             sizeof(tempUP)
00979         );
00980 
00981         if ( 0 == memcmp( &(tempUP.anchor), "_UP_", 4))
00982         {
00983             found = true;
00984             break;
00985         }
00986 
00987         fp += step_size;
00988         // for buggy BIOSen. If we don't find it on a paragraph boundary,
00989         // start over and do byte-by-byte
00990         if( step_size > 1 && fp >= (0xFFFFFUL - sizeof(tempUP)) )
00991         {
00992             step_size = 1;
00993             fp = 0xF0000;
00994         }
00995     }
00996 
00997     if( found )
00998         memcpy( up, &tempUP, sizeof(tempUP) );
00999 
01000     return found;
01001 }
01002 
01003 static int upBootHelper(bool set
01004                             =false, bool value=false)
01005 {
01006     // retval = 0: NO BOOT TO UP CAPABILITY
01007     // retval = 1 && set; set to value
01008     // retval = 2 && !set; UP not active
01009     // retval = 3 && !set; UP Active
01010     int retval = 0;
01011     const u8 *buf = 0;
01012 
01013     up_info up;
01014     memset( reinterpret_cast<u8*>(&up), 0, sizeof(up));
01015     try
01016     {
01017         bool found = getUpOffsetAndFlag( &up );
01018 
01019         if( !found )
01020             goto out;
01021 
01022         smbios::TokenTableFactory *ttFactory = smbios::TokenTableFactory::getFactory() ;
01023         smbios::ITokenTable *tokenTable = ttFactory->getSingleton();
01024         size_t length;
01025         buf = (*tokenTable)[ NvramByte2_Token  ]->getItemRef().getBufferCopy(length);
01026 
01027         const indexed_io_access_structure *io_struct =
01028             reinterpret_cast<const indexed_io_access_structure *>(buf);
01029 
01030         cmos::ICmosRW *cmos = cmos::CmosRWFactory::getFactory()->getSingleton();
01031 
01032         u8 byte = cmos->readByte( io_struct->indexPort, io_struct->dataPort, up.offset );
01033 
01034         if( set
01035               )
01036             {
01037                 // default to set
01038                 byte |= up.flag;
01039                 retval = 1;
01040                 if (!value) // clear
01041                 {
01042                     byte &= ~up.flag;
01043                 }
01044                 cmos->writeByte( io_struct->indexPort, io_struct->dataPort, up.offset, byte );
01045             }
01046         else
01047         {
01048             if( (byte & up.flag) == up.flag )
01049                 retval = 3;
01050 
01051             if( (byte & up.flag) != up.flag )
01052                 retval = 2;
01053         }
01054 
01055     }
01056     catch(const smbios::IException &e)
01057     {
01058         SysInfoException.setMessageString(e.what());
01059     }
01060     catch(...)
01061     {
01062         SysInfoException.setMessageString( _("Unknown internal error occurred") );
01063     }
01064 
01065     delete [] const_cast<u8 *>(buf);
01066     buf = 0;
01067 
01068 out:
01069     return retval;
01070 }
01071 
01072 int SMBIOSHasBootToUp()
01073 {
01074     return upBootHelper();
01075 }
01076 
01077 int SMBIOSGetBootToUp()
01078 {
01079     int retval = upBootHelper();
01080     retval -= 2;
01081     return retval;
01082 }
01083 
01084 void SMBIOSSetBootToUp(int state)
01085 {
01086     bool value = (state == 1) ? true: false;
01087     upBootHelper(true, value);
01088 }
01089 
01090 
01091 int SMBIOSGetSmiPasswordCoding()
01092 {
01093     int fmt=0;
01094     try
01095     {
01096         fmt = smi::getPasswordFormat();
01097     }
01098     catch(const exception &)
01099     {}
01100 
01101     return fmt;
01102 }
01103 

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