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 "../common/ExceptionImpl.h"
00028 #include "../token/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     smbios::ISmbiosTable::iterator item;
00248     tempval = (*table)[structure]->getString(stringNumber);
00249 
00250     if(!tempval)
00251         throw exception();
00252 
00253     size_t slen = strlen(tempval);
00254     char *retval = new char[slen + 1];
00255     strncpy(retval,tempval,slen);
00256     retval[slen] = '\0';
00257 
00258     stripString(retval);
00259     if ( ! strlen(retval ))
00260     {
00261         delete [] retval;
00262         retval = 0;
00263         throw exception(); // skip this one because returned string was all spaces. 
00264     }
00265 
00266     return retval;
00267 }
00268 
00269 static char *getServiceTagFromSysInfo()
00270 {
00271     DCOUT( "in getServiceTagFromSysInfo()" << endl);
00272     return getStringFromTable(System_Information, System_Information_Serial_Number_Offset);
00273 }
00274 
00275 static char *getServiceTagFromSysEncl()
00276 {
00277     DCOUT( "in getServiceTagFromSysEncl()" << endl);
00278     return getStringFromTable(System_Enclosure_or_Chassis, System_Enclosure_or_Chassis_Service_Offset);
00279 }
00280 
00281 // not static so that unit tests can peek here. Not part of public API, though.
00282 char *getServiceTagFromCMOSToken()
00283 {
00284     smbios::ITokenTable *table = 0;
00285     table = smbios::TokenTableFactory::getFactory()->getSingleton();
00286 
00287     DCOUT( "in getServiceTagFromCMOSToken()" << endl);
00288 
00289     if (0 == table)
00290     {
00291         throw InternalErrorImpl();
00292     }
00293 
00294     char *tempval = 0;
00295     try
00296     {
00297         // Step 1: Get tag from CMOS
00298         tempval = new char[SVC_TAG_LEN_MAX + 1];
00299         memset(tempval, '\0', SVC_TAG_LEN_MAX + 1);
00300         // will throw an exception if not found.
00301         (*table)[Cmos_Service_Token]->getString(reinterpret_cast<u8*>(tempval), SVC_TAG_CMOS_LEN_MAX + 1);
00302 
00303         // Step 2: Decode 7-char tag from 5-char CMOS value
00304         dell_decode_service_tag( tempval, SVC_TAG_LEN_MAX + 1 );
00305 
00306         // Step 3: Make sure checksum is good before returning value
00307         u16 indexPort, dataPort;
00308         u8  location;
00309 
00310         smbios::IToken *token = &(*((*table)[ Cmos_Service_Token ]));
00311         dynamic_cast< smbios::ICmosToken * >(token)->getCMOSDetails( &indexPort, &dataPort, &location );
00312 
00313         u8 csum = 0;
00314         ICmosRW *cmos = cmos::CmosRWFactory::getFactory()->getSingleton();
00315 
00316         for( u32 i = 0; i < SVC_TAG_CMOS_LEN_MAX; i++)
00317         {
00318             // stupid stuff to avoid MVC++ .NET runtime exception check for cast to different size
00319             csum = (csum + cmos->readByte( indexPort, dataPort, location + i )) & 0xFF;
00320         }
00321 
00322         // stupid stuff to avoid MVC++ .NET runtime exception check for cast to different size
00323         csum = (csum - cmos->readByte( indexPort, dataPort, location + SVC_TAG_CMOS_LEN_MAX )) & 0xFF;
00324         if( csum ) // bad (should be zero)
00325             throw "Bad checksum";
00326     }
00327     catch( ... )
00328     {
00329         delete [] tempval;
00330         throw;
00331     }
00332 
00333     return tempval;
00334 }
00335 
00336 // not static so that unit tests can peek here. Not part of public API, though.
00337 char *getServiceTagFromSMI()
00338 {
00339     DCOUT( "in getServiceTagFromSMI()" << endl);
00340     return getTagFromSMI( 2 ); /* Read service tag select code */
00341 }
00342 
00343 // Code for getting the service tag from one of many locations
00344 struct DellGetServiceTagFunctions
00345 {
00346     char *(*f_ptr)();
00347 }
00348 
00349 /* try dynamic functions first to make sure we get current data. */
00350 DellGetServiceTagFunctions[] = {
00351                                    {&getServiceTagFromSMI,},       // SMI Token
00352                                    {&getServiceTagFromCMOSToken,}, // CMOS Token
00353                                    {&getServiceTagFromSysInfo,},   // SMBIOS System Information Item
00354                                    {&getServiceTagFromSysEncl,},   // SMBIOS System Enclosure Item
00355                                };
00356 
00357 const char *SMBIOSGetServiceTag()
00358 {
00359     char *serviceTag = 0;
00360     int numEntries =
00361         sizeof (DellGetServiceTagFunctions) / sizeof (DellGetServiceTagFunctions[0]);
00362 
00363     DCOUT( "numEntries: " << numEntries << endl);
00364 
00365     for (int i = 0; (i < numEntries) && (!serviceTag); ++i)
00366     {
00367         // eat exceptions from lowlevel functions and keep going.
00368         try
00369         {
00370             DCOUT("  try #" << i << endl);
00371             // first function to return non-zero id wins.
00372             serviceTag = DellGetServiceTagFunctions[i].f_ptr ();
00373         }
00374         catch(const exception &e)
00375         {
00376             DCOUT("  Caught exception: " << e.what() << endl);
00377             SysInfoException.setMessageString(e.what());
00378         }
00379         catch(...)
00380         {
00381             DCOUT("  Caught unknown exception" << endl);
00382             SysInfoException.setMessageString( _("Unknown internal error occurred") );
00383         }
00384 
00385         if(serviceTag)
00386             DCOUT( "    GOT TAG: -->" << serviceTag << "<--" << endl);
00387     }
00388     stripString(serviceTag);
00389     return serviceTag;
00390 }
00391 
00392 void setServiceTagUsingCMOSToken(const char *newTag, size_t len)
00393 {
00394     smbios::ITokenTable *table = 0;
00395     table = smbios::TokenTableFactory::getFactory()->getSingleton();
00396 
00397     if (0 == table)
00398     {
00399         throw InternalErrorImpl();
00400     }
00401 
00402     try
00403     {
00404         // don't want to modify user-supplied buffer, so copy new tag
00405         // to our own buffer.
00406         char codedTag[SVC_TAG_LEN_MAX + 1] = {0,}; // null padded
00407         // copy (possibly oversize) user input to our buffer.
00408         strncpy(codedTag, newTag, len < SVC_TAG_LEN_MAX ? len : SVC_TAG_LEN_MAX);
00409         // encode in place, if necessary
00410         dell_encode_service_tag(codedTag, len);
00411         // will throw an exception if not found.
00412 
00413         // Step 1: set string: safe to use whole codedTag as it is guaranteed zero-padded
00414         (*table)[Cmos_Service_Token]->setString(reinterpret_cast<const u8*>(codedTag), SVC_TAG_CMOS_LEN_MAX);
00415 
00416         // Step 2: reset checksum
00417         u16 indexPort, dataPort;
00418         u8  location;
00419 
00420         smbios::IToken *token = &(*((*table)[ Cmos_Service_Token ]));
00421         dynamic_cast< smbios::ICmosToken * >(token)->getCMOSDetails( &indexPort, &dataPort, &location );
00422 
00423         u8 csum = 0;
00424         ICmosRW *cmos = cmos::CmosRWFactory::getFactory()->getSingleton();
00425 
00426         for( u32 i = 0; i < SVC_TAG_CMOS_LEN_MAX; i++)
00427         {
00428             // stupid stuff to avoid MVC++ .NET runtime exception check for cast to different size
00429             csum = (csum + cmos->readByte( indexPort, dataPort, location + i )) & 0xFF;
00430         }
00431 
00432         cmos->writeByte(
00433             indexPort,
00434             dataPort,
00435             location + SVC_TAG_CMOS_LEN_MAX,
00436             csum
00437         );
00438     }
00439     catch( const smbios::IException & )
00440     {
00441         throw;
00442     }
00443 
00444 }
00445 
00446 // Important note from the docs:
00447 /*  Only the manufacturing software that’s loading the service tag into the system should use this interface.
00448     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).
00449     */
00450 void setServiceTagUsingSMI(const char *newTag, size_t size)
00451 {
00452     (void) size; // avoid unused var warning.
00453     setTagUsingSMI( newTag, 3 ); /* Write service tag select code */
00454 }
00455 
00456 // Code for getting the service tag from one of many locations
00457 struct DellSetServiceTagFunctions
00458 {
00459     void (*f_ptr)(const char *, size_t);
00460 }
00461 
00462 DellSetServiceTagFunctions[] = {
00463                                    {&setServiceTagUsingSMI,},   // SMBIOS System Information Item
00464                                    {&setServiceTagUsingCMOSToken,},   // SMBIOS System Information Item
00465                                };
00466 
00467 int SMBIOSSetServiceTag(const char *password, const char *serviceTag, size_t len)
00468 {
00469     int retval = -1;
00470     int numEntries =
00471         sizeof (DellSetServiceTagFunctions) / sizeof (DellSetServiceTagFunctions[0]);
00472 
00473     if(password)
00474         biosPassword = password;
00475 
00476     for (int i = 0; (i < numEntries); ++i)
00477     {
00478         // eat exceptions from lowlevel functions and keep going.
00479         try
00480         {
00481             // first function to return non-zero id wins.
00482             DellSetServiceTagFunctions[i].f_ptr (serviceTag, len);
00483             retval = 0;
00484         }
00485         catch(const smbios::IException &e)
00486         {
00487             SysInfoException.setMessageString(e.what());
00488         }
00489         catch(...)
00490         {
00491             SysInfoException.setMessageString( _("Unknown internal error occurred") );
00492         }
00493     }
00494     return retval;
00495 }
00496 
00497 static char *getAssetTagFromSysEncl()
00498 {
00499     return getStringFromTable(System_Enclosure_or_Chassis, System_Enclosure_or_Chassis_Asset_Offset);
00500 }
00501 
00502 static char *getAssetTagFromToken()
00503 {
00504     smbios::ITokenTable *table = 0;
00505     table = smbios::TokenTableFactory::getFactory()->getSingleton();
00506 
00507     if (0 == table)
00508     {
00509         throw InternalErrorImpl();
00510     }
00511 
00512     u8 *tempval = 0;
00513     try
00514     {
00515         tempval = new u8[ASSET_TAG_LEN_MAX + 1];
00516         memset(tempval, '\0', ASSET_TAG_LEN_MAX + 1);
00517         (*table)[Cmos_Asset_Token]->getString(tempval, ASSET_TAG_LEN_MAX + 1);
00518 
00519         // Step 3: Make sure checksum is good before returning value
00520         u16 indexPort, dataPort;
00521         u8  location;
00522 
00523         smbios::IToken *token = &(*((*table)[ Cmos_Asset_Token ]));
00524         dynamic_cast< smbios::ICmosToken * >(token)->getCMOSDetails( &indexPort, &dataPort, &location );
00525 
00526         u8 csum = 0;
00527         ICmosRW *cmos = cmos::CmosRWFactory::getFactory()->getSingleton();
00528 
00529         for( u32 i = 0; i < ASSET_TAG_CMOS_LEN_MAX; i++)
00530         {
00531             // stupid stuff to avoid MVC++ .NET runtime exception check for cast to different size
00532             csum = (csum + cmos->readByte( indexPort, dataPort, location + i )) & 0xFF;
00533         }
00534 
00535         // stupid stuff to avoid MVC++ .NET runtime exception check for cast to different size
00536         csum = (csum - cmos->readByte( indexPort, dataPort, location + ASSET_TAG_CMOS_LEN_MAX )) & 0xFF;
00537         if( csum ) // bad (should be zero)
00538             throw "Bad checksum";
00539     }
00540     catch (...)
00541     {
00542         delete [] tempval;
00543         throw;
00544     }
00545 
00546     return reinterpret_cast<char*>(tempval);
00547 }
00548 
00549 char *getAssetTagFromSMI()
00550 {
00551     return getTagFromSMI( 0 ); /* Read asset tag select code */
00552 }
00553 
00554 // Code for getting the asset tag from one of many locations
00555 struct DellAssetTagFunctions
00556 {
00557     char *(*f_ptr)();
00558 }
00559 
00560 /* try dynamic functions first to make sure we get current data. */
00561 DellAssetTagFunctions[] = {
00562                               {&getAssetTagFromSMI,},     // SMI
00563                               {&getAssetTagFromToken,},   // SMBIOS Token
00564                               {&getAssetTagFromSysEncl,}, // SMBIOS System Information Item
00565                           };
00566 
00567 const char *SMBIOSGetAssetTag()
00568 {
00569     char *assetTag = 0;
00570     int numEntries =
00571         sizeof (DellAssetTagFunctions) / sizeof (DellAssetTagFunctions[0]);
00572 
00573     for (int i = 0; (i < numEntries) && (!assetTag); ++i)
00574     {
00575         // eat exceptions from lowlevel functions and keep going.
00576         try
00577         {
00578             // first function to return non-zero id wins.
00579             assetTag = DellAssetTagFunctions[i].f_ptr ();
00580         }
00581         catch(const smbios::IException &e)
00582         {
00583             SysInfoException.setMessageString(e.what());
00584         }
00585         catch(...)
00586         {
00587             SysInfoException.setMessageString( _("Unknown internal error occurred") );
00588         }
00589     }
00590     stripString(assetTag);
00591     return assetTag;
00592 }
00593 
00594 
00595 
00596 void setAssetTagUsingCMOSToken(const char *newTag, size_t len)
00597 {
00598     smbios::ITokenTable *table = 0;
00599     table = smbios::TokenTableFactory::getFactory()->getSingleton();
00600 
00601     if (0 == table)
00602     {
00603         throw InternalErrorImpl();
00604     }
00605 
00606     try
00607     {
00608         // Step 1: set string
00609         (*table)[Cmos_Asset_Token]->setString(reinterpret_cast<const u8*>(newTag), len < ASSET_TAG_CMOS_LEN_MAX? len : ASSET_TAG_CMOS_LEN_MAX);
00610 
00611         // Step 2: reset checksum
00612         u16 indexPort, dataPort;
00613         u8  location;
00614 
00615         smbios::IToken *token = &(*((*table)[ Cmos_Asset_Token ]));
00616         dynamic_cast< smbios::ICmosToken * >(token)->getCMOSDetails( &indexPort, &dataPort, &location );
00617 
00618         u8 csum = 0;
00619         ICmosRW *cmos = cmos::CmosRWFactory::getFactory()->getSingleton();
00620 
00621         for( u32 i = 0; i < ASSET_TAG_CMOS_LEN_MAX; i++)
00622         {
00623             // stupid stuff to avoid MVC++ .NET runtime exception check for cast to different size
00624             csum = (csum + cmos->readByte( indexPort, dataPort, location + i )) & 0xFF;
00625         }
00626 
00627         cmos->writeByte(
00628             indexPort,
00629             dataPort,
00630             location + ASSET_TAG_CMOS_LEN_MAX,
00631             csum
00632         );
00633     }
00634     catch( const smbios::IException & )
00635     {
00636         throw;
00637     }
00638 
00639 }
00640 
00641 void setAssetTagUsingSMI(const char *newTag, size_t size)
00642 {
00643     (void) size; // avoid unused var warning.
00644     setTagUsingSMI( newTag, 1 ); /* Write asset tag select code */
00645 }
00646 
00647 // Code for getting the service tag from one of many locations
00648 struct DellSetAssetTagFunctions
00649 {
00650     void (*f_ptr)(const char *, size_t);
00651     const char * desc;
00652 }
00653 
00654 DellSetAssetTagFunctions[] = {
00655                                  {&setAssetTagUsingSMI, "SMI"},   // SMBIOS System Information Item
00656                                  {&setAssetTagUsingCMOSToken, "CMOS"},   // SMBIOS System Information Item
00657                              };
00658 
00659 int SMBIOSSetAssetTag(const char *password, const char *assetTag, size_t len)
00660 {
00661     int retval = -1;
00662     int numEntries =
00663         sizeof (DellSetAssetTagFunctions) / sizeof (DellSetAssetTagFunctions[0]);
00664 
00665     if(password)
00666         biosPassword = password;
00667 
00668     for (int i = 0; (i < numEntries); ++i)
00669     {
00670         // eat exceptions from lowlevel functions and keep going.
00671         try
00672         {
00673             // first function to return non-zero id wins.
00674             DellSetAssetTagFunctions[i].f_ptr (assetTag, len);
00675             retval = 0;
00676         }
00677         catch(const smbios::IException &e)
00678         {
00679             SysInfoException.setMessageString(e.what());
00680         }
00681         catch(...)
00682         {
00683             SysInfoException.setMessageString( _("Unknown internal error occurred") );
00684         }
00685     }
00686     return retval;
00687 }
00688 
00689 
00690 static char *getSystemNameFromSysInfo()
00691 {
00692     return getStringFromTable(System_Information, System_Information_Product_Name_Offset);
00693 }
00694 
00695 // Struct for getting the system name from one of many locations
00696 struct DellSystemNameFunctions
00697 {
00698     char *(*f_ptr)();
00699 }
00700 
00701 DellSystemNameFunctions[] = {
00702                                 {&getSystemNameFromSysInfo,}    // SMBIOS System Information Item
00703                             };
00704 
00705 const char *SMBIOSGetSystemName()
00706 {
00707     char *systemName= 0;
00708     int numEntries =
00709         sizeof (DellSystemNameFunctions) / sizeof (DellSystemNameFunctions[0]);
00710 
00711     for (int i = 0; (i < numEntries) && (!systemName); ++i)
00712     {
00713         // eat exceptions from lowlevel functions and keep going.
00714         try
00715         {
00716             // first function to return non-zero id wins.
00717             systemName = DellSystemNameFunctions[i].f_ptr ();
00718         }
00719         catch(const smbios::IException &e)
00720         {
00721             SysInfoException.setMessageString(e.what());
00722         }
00723         catch(...)
00724         {
00725             SysInfoException.setMessageString( _("Unknown internal error occurred") );
00726         }
00727     }
00728 
00729     stripString(systemName);
00730     return systemName;
00731 }
00732 
00733 // for Diamond only.
00734 static char *getBiosVersionFromOneByteStructForDiamond()
00735 {
00736     memory::IMemory *mem = 0;
00737     u8 strBuf[DELL_SYSTEM_STRING_LEN] = { 0, };
00738     u8 *biosVersion = 0;
00739 
00740     mem = memory::MemoryFactory::getFactory()->getSingleton();
00741 
00742     if( 0 == mem )
00743         throw InternalErrorImpl();
00744 
00745     // Step 1: Check that "Dell System" is present at the proper offset
00746     mem->fillBuffer( strBuf, DELL_SYSTEM_STRING_LOC_DIAMOND_1, DELL_SYSTEM_STRING_LEN - 1 );
00747     if( strncmp( reinterpret_cast<char*>(strBuf), DELL_SYSTEM_STRING, DELL_SYSTEM_STRING_LEN ) == 0 )
00748         if( SYSTEM_ID_DIAMOND == mem->getByte( ID_BYTE_LOC_DIAMOND_1 ) )
00749         {
00750             biosVersion = new u8[4];
00751             mem->fillBuffer(biosVersion, ID_BYTE_LOC_DIAMOND_1 + 1, 3);
00752             biosVersion[3] = '\0';
00753         }
00754 
00755     mem->fillBuffer( strBuf, DELL_SYSTEM_STRING_LOC_DIAMOND_2, DELL_SYSTEM_STRING_LEN - 1 );
00756     if( strncmp( reinterpret_cast<char*>(strBuf), DELL_SYSTEM_STRING, DELL_SYSTEM_STRING_LEN ) == 0 )
00757         if( SYSTEM_ID_DIAMOND == mem->getByte( ID_BYTE_LOC_DIAMOND_2 ) )
00758         {
00759             biosVersion = new u8[4];
00760             mem->fillBuffer(biosVersion, ID_BYTE_LOC_DIAMOND_2 + 1, 3);
00761             biosVersion[3] = '\0';
00762         }
00763 
00764     return reinterpret_cast<char*>(biosVersion);
00765 }
00766 
00767 static char *getBiosVersionFromSmbios()
00768 {
00769     return getStringFromTable(BIOS_Information, BIOS_Information_Version_Offset);
00770 }
00771 
00772 // Code for getting the service tag from one of many locations
00773 struct DellBiosVersionFunctions
00774 {
00775     char *(*f_ptr)();
00776 }
00777 DellBiosVersionFunctions[] = {
00778                                  {&getBiosVersionFromOneByteStructForDiamond,},    // Diamond
00779                                  {&getBiosVersionFromSmbios,}
00780                              };
00781 
00782 const char *SMBIOSGetBiosVersion()
00783 {
00784     char *systemName= 0;
00785     int numEntries =
00786         sizeof (DellBiosVersionFunctions) / sizeof (DellBiosVersionFunctions[0]);
00787 
00788     for (int i = 0; (i < numEntries) && (!systemName); ++i)
00789     {
00790         // eat exceptions from lowlevel functions and keep going.
00791         try
00792         {
00793             // first function to return non-zero id wins.
00794             systemName = DellBiosVersionFunctions[i].f_ptr ();
00795         }
00796         catch(const smbios::IException &e)
00797         {
00798             SysInfoException.setMessageString(e.what());
00799         }
00800         catch(...)
00801         {
00802             SysInfoException.setMessageString( _("Unknown internal error occurred") );
00803         }
00804     }
00805 
00806     stripString(systemName);
00807     return systemName;
00808 }
00809 
00810 
00811 const char *SMBIOSGetVendorName()
00812 {
00813     char *retval = 0;
00814 
00815     try
00816     {
00817         retval = getStringFromTable(System_Information, System_Information_Manufacturer_Offset);
00818     }
00819     catch(const smbios::IException &e)
00820     {
00821         SysInfoException.setMessageString(e.what());
00822     }
00823     catch(...)
00824     {
00825         SysInfoException.setMessageString( _("Unknown internal error occurred") );
00826     }
00827 
00828     stripString(retval);
00829     return retval;
00830 }
00831 
00832 
00833 int SMBIOSHasNvramStateBytes()
00834 {
00835     int retval = 1;
00836     try
00837     {
00838         smbios::TokenTableFactory *ttFactory = smbios::TokenTableFactory::getFactory() ;
00839         smbios::ITokenTable *tokenTable = ttFactory->getSingleton();
00840 
00841         u8 tempData[2] = {0,0};
00842         (*tokenTable)[ NvramByte1_Token  ]->getString( tempData, 2 );
00843         (*tokenTable)[ NvramByte2_Token  ]->getString( tempData, 2 );
00844     }
00845     catch(const smbios::IException &e)
00846     {
00847         SysInfoException.setMessageString(e.what());
00848         retval = 0;
00849     }
00850     catch(...)
00851     {
00852         SysInfoException.setMessageString( _("Unknown internal error occurred") );
00853     }
00854 
00855     return retval;
00856 }
00857 
00858 
00859 // user =
00860 //      0x0000 = DSA
00861 //      0x8000 = OM Toolkit
00862 //      0x9000 = open
00863 //      0xA000 = open
00864 //      0xB000 = open
00865 //      0xC000 = open
00866 //      0xD000 = open
00867 //      0xE000 = open
00868 //      0xF000 = expand to whole byte
00869 int SMBIOSGetNvramStateBytes( int user )
00870 {
00871     u8 tempData[2] = {0,0};
00872     int retval = 0;
00873     try
00874     {
00875         smbios::TokenTableFactory *ttFactory = smbios::TokenTableFactory::getFactory() ;
00876         smbios::ITokenTable *tokenTable = ttFactory->getSingleton();
00877 
00878         (*tokenTable)[ NvramByte1_Token  ]->getString( tempData, 2 );
00879         retval = *tempData;
00880         (*tokenTable)[ NvramByte2_Token  ]->getString( tempData, 2 );
00881         retval |= (*tempData << 8);
00882     }
00883     catch(const smbios::IException &e)
00884     {
00885         SysInfoException.setMessageString(e.what());
00886     }
00887     catch(...)
00888     {
00889         SysInfoException.setMessageString( _("Unknown internal error occurred") );
00890     }
00891 
00892     if( user == 0x0000 )  // DSA
00893     {
00894         if( (retval & 0x8000) != user )
00895         {
00896             retval = 0;  // user doesn't match, return default
00897         }
00898         retval &= ~0x8000; // mask user bits
00899     }
00900     else
00901     {
00902         if ((user & 0xF000) == 0xF000 ) // probably will never be used
00903         {
00904             if( (retval & 0xFF00) != user )
00905             {
00906                 retval = 0;// user doesn't match, return default
00907             }
00908             retval &= ~0xFF00; // mask user bits
00909         }
00910         else
00911         {
00912             if( (retval & 0xF000) != user ) // Toolkit (or users 0x9 - 0xE)
00913             {
00914                 retval = 0;// user doesn't match, return default
00915             }
00916             retval &= ~0xF000; // mask user bits
00917         }
00918     }
00919     return retval;
00920 }
00921 
00922 void SMBIOSSetNvramStateBytes(int value, int user)
00923 {
00924     try
00925     {
00926         if ( user == 0x0000 ) // DSA
00927         {
00928             value &= ~0x8000;  // mask user bits
00929             value |= user;     // set user
00930         }
00931         else if( (user & 0xF000) == 0xF000 )
00932         {
00933             value &= ~0xFF00;   // mask user bits
00934             value |= user;      // set user
00935         }
00936         else
00937         {
00938             value &= ~0xF000;   // mask user bits
00939             value |= user;      // set user
00940         }
00941 
00942         smbios::TokenTableFactory *ttFactory = smbios::TokenTableFactory::getFactory() ;
00943         smbios::ITokenTable *tokenTable = ttFactory->getSingleton();
00944 
00945         u8 *tempData = reinterpret_cast<u8*>(&value);
00946         (*tokenTable)[ NvramByte1_Token  ]->setString( tempData, 1 );
00947         (*tokenTable)[ NvramByte2_Token  ]->setString( tempData+1, 1 );
00948     }
00949     catch(const smbios::IException &e)
00950     {
00951         SysInfoException.setMessageString(e.what());
00952     }
00953     catch(...)
00954     {
00955         SysInfoException.setMessageString( _("Unknown internal error occurred") );
00956     }
00957     return;
00958 }
00959 
00960 
00961 static bool getUpOffsetAndFlag (up_info *up)
00962 {
00963     memory::IMemory *mem =
00964         memory::MemoryFactory::getFactory()->getSingleton();
00965 
00966     up_info tempUP;
00967     memset(&tempUP, 0, sizeof(tempUP));
00968     int step_size = 16;
00969 
00970     unsigned int fp = 0xF0000;
00971     bool found = false;
00972     while( fp < (0xFFFFFUL - sizeof(tempUP)) )
00973     {
00974         mem->fillBuffer(
00975             reinterpret_cast<u8 *>(&tempUP),
00976             fp,
00977             sizeof(tempUP)
00978         );
00979 
00980         if ( 0 == memcmp( &(tempUP.anchor), "_UP_", 4))
00981         {
00982             found = true;
00983             break;
00984         }
00985 
00986         fp += step_size;
00987         // for buggy BIOSen. If we don't find it on a paragraph boundary,
00988         // start over and do byte-by-byte
00989         if( step_size > 1 && fp >= (0xFFFFFUL - sizeof(tempUP)) )
00990         {
00991             step_size = 1;
00992             fp = 0xF0000;
00993         }
00994     }
00995 
00996     if( found )
00997         memcpy( up, &tempUP, sizeof(tempUP) );
00998 
00999     return found;
01000 }
01001 
01002 static int upBootHelper(bool set
01003                             =false, bool value=false)
01004 {
01005     // retval = 0: NO BOOT TO UP CAPABILITY
01006     // retval = 1 && set; set to value
01007     // retval = 2 && !set; UP not active
01008     // retval = 3 && !set; UP Active
01009     int retval = 0;
01010     const u8 *buf = 0;
01011 
01012     up_info up;
01013     memset( reinterpret_cast<u8*>(&up), 0, sizeof(up));
01014     try
01015     {
01016         bool found = getUpOffsetAndFlag( &up );
01017 
01018         if( !found )
01019             goto out;
01020 
01021         smbios::TokenTableFactory *ttFactory = smbios::TokenTableFactory::getFactory() ;
01022         smbios::ITokenTable *tokenTable = ttFactory->getSingleton();
01023         size_t length;
01024         buf = (*tokenTable)[ NvramByte2_Token  ]->getItemRef().getBufferCopy(length);
01025 
01026         const indexed_io_access_structure *io_struct =
01027             reinterpret_cast<const indexed_io_access_structure *>(buf);
01028 
01029         cmos::ICmosRW *cmos = cmos::CmosRWFactory::getFactory()->getSingleton();
01030 
01031         u8 byte = cmos->readByte( io_struct->indexPort, io_struct->dataPort, up.offset );
01032 
01033         if( set
01034               )
01035             {
01036                 // default to set
01037                 byte |= up.flag;
01038                 retval = 1;
01039                 if (!value) // clear
01040                 {
01041                     byte &= ~up.flag;
01042                 }
01043                 cmos->writeByte( io_struct->indexPort, io_struct->dataPort, up.offset, byte );
01044             }
01045         else
01046         {
01047             if( (byte & up.flag) == up.flag )
01048                 retval = 3;
01049 
01050             if( (byte & up.flag) != up.flag )
01051                 retval = 2;
01052         }
01053 
01054     }
01055     catch(const smbios::IException &e)
01056     {
01057         SysInfoException.setMessageString(e.what());
01058     }
01059     catch(...)
01060     {
01061         SysInfoException.setMessageString( _("Unknown internal error occurred") );
01062     }
01063 
01064     delete [] const_cast<u8 *>(buf);
01065     buf = 0;
01066 
01067 out:
01068     return retval;
01069 }
01070 
01071 int SMBIOSHasBootToUp()
01072 {
01073     return upBootHelper();
01074 }
01075 
01076 int SMBIOSGetBootToUp()
01077 {
01078     int retval = upBootHelper();
01079     retval -= 2;
01080     return retval;
01081 }
01082 
01083 void SMBIOSSetBootToUp(int state)
01084 {
01085     bool value = (state == 1) ? true: false;
01086     upBootHelper(true, value);
01087 }
01088 
01089 
01090 int SMBIOSGetSmiPasswordCoding()
01091 {
01092     int fmt=0;
01093     try
01094     {
01095         fmt = smi::getPasswordFormat();
01096     }
01097     catch(const exception &)
01098     {}
01099 
01100     return fmt;
01101 }
01102 

Generated on Tue Jul 11 20:46:46 2006 for SMBIOS Library by  doxygen 1.4.7