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

Generated on Thu Jan 24 14:59:34 2008 for SMBIOS Library by  doxygen 1.5.4