• Main Page
  • Related Pages
  • Namespaces
  • Classes
  • Files
  • File List
  • File Members

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

Generated on Sun Aug 22 2010 14:38:30 for SMBIOS Library by  doxygen 1.7.1