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

Smi.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 // compat header should always be first header if including system headers
00020 #define LIBSMBIOS_SOURCE
00021 #include "smbios/compat.h"
00022 
00023 //#include <iostream>
00024 
00025 #include "SmiImpl.h"
00026 #include "smbios/ISmbios.h"
00027 #include "smbios/IToken.h"
00028 #include "TokenLowLevel.h"
00029 
00030 using namespace std;
00031 
00032 #if defined(DEBUG_SMI)
00033 #   define DCOUT(line) do { cout << line; } while(0)
00034 #   define DCERR(line) do { cerr << line; } while(0)
00035 #else
00036 #   define DCOUT(line) do {} while(0)
00037 #   define DCERR(line) do {} while(0)
00038 #endif
00039 
00040 /* work around broken VC6 compiler */
00041 #define SIZEOF_KERNELBUF  (sizeof(kernel_buf) - sizeof(kernel_buf.command_buffer_start))
00042 
00043 namespace smi
00044 {
00045 
00046 
00047     //
00048     // ISmi functions
00049     //
00050     ISmi::ISmi()
00051     {}
00052 
00053     ISmi::~ISmi()
00054     {}
00055 
00056     IDellCallingInterfaceSmi::IDellCallingInterfaceSmi()
00057     {}
00058 
00059     IDellCallingInterfaceSmi::~IDellCallingInterfaceSmi()
00060     {}
00061 
00062     DellCallingInterfaceSmiImpl::DellCallingInterfaceSmiImpl(SmiStrategy *initStrategy)
00063             :  ISmi(), IDellCallingInterfaceSmi(), buffer(0), bufferSize(0), smiStrategy(initStrategy)
00064     {
00065         // this is the only place where we use 'real' sizeof(kernel_buf), 
00066         // everywhere else should use SIZEOF_KERNELBUF
00067         memset( &kernel_buf, 0, sizeof(kernel_buf) );
00068 
00069         memset( &smi_buf, 0, sizeof(smi_buf) );
00070         memset( &argIsAddress, 0, sizeof(argIsAddress) );
00071         memset( &argAddressOffset, 0, sizeof(argAddressOffset) );
00072 
00073         kernel_buf.magic = KERNEL_SMI_MAGIC_NUMBER;
00074         kernel_buf.ebx = 0;
00075         kernel_buf.ecx   = DELL_CALLINTF_SMI_MAGIC_NUMBER;
00076         kernel_buf.command_address = 0;
00077         kernel_buf.command_code = 0;
00078 
00079         /* default to "not handled" */
00080         smi_buf.cbRES1 = -3;
00081     }
00082 
00083     DellCallingInterfaceSmiImpl::~DellCallingInterfaceSmiImpl()
00084     {
00085         if(buffer)
00086         {
00087             delete [] buffer;
00088             buffer = 0;
00089             bufferSize = 0;
00090         }
00091     }
00092 
00093     void DellCallingInterfaceSmiImpl::setCommandIOMagic( u16 address, u8 code )
00094     {
00095         kernel_buf.command_address = address;
00096         kernel_buf.command_code = code;
00097     }
00098 
00099     u8 *DellCallingInterfaceSmiImpl::getBufferPtr()
00100     {
00101         return buffer;
00102     }
00103 
00104     void DellCallingInterfaceSmiImpl::setBufferSize(size_t newSize)
00105     {
00106         if ( bufferSize != newSize )
00107         {
00108             delete [] buffer;
00109             buffer = new u8[newSize];
00110             memset(buffer, 0, newSize);
00111 
00112             bufferSize=newSize;
00113         }
00114     }
00115 
00116     void DellCallingInterfaceSmiImpl::execute()
00117     {
00118         smiStrategy->lock()
00119         ;
00120         smiStrategy->setSize( SIZEOF_KERNELBUF + sizeof(smi_buf) + bufferSize );
00121 
00122         size_t baseAddr = smiStrategy->getPhysicalBufferBaseAddress();
00123         for( int i=0; i<4; i++)
00124             if( argIsAddress[i] )
00125                 smi_buf.inputArgs[i] = static_cast<u32>(baseAddr + SIZEOF_KERNELBUF + sizeof(smi_buf) + argAddressOffset[i]);
00126 
00127         smiStrategy->addInputBuffer(reinterpret_cast<u8 *>(&kernel_buf), SIZEOF_KERNELBUF);
00128         smiStrategy->addInputBuffer(reinterpret_cast<u8 *>(&smi_buf), sizeof(smi_buf));
00129         if(buffer)
00130             smiStrategy->addInputBuffer(buffer, bufferSize);
00131 
00132         smiStrategy->execute();
00133 
00134         smiStrategy->getResultBuffer(reinterpret_cast<u8 *>(&kernel_buf), SIZEOF_KERNELBUF);
00135         smiStrategy->getResultBuffer(reinterpret_cast<u8 *>(&smi_buf), sizeof(smi_buf));
00136         if(buffer)
00137             smiStrategy->getResultBuffer(reinterpret_cast<u8 *>(buffer), bufferSize);
00138 
00139         smiStrategy->finish();
00140 
00141         if( -6 == smi_buf.cbRES1 )
00142             throw SmiExceptionImpl("Output buffer not large enough.");
00143 
00144         if( -5 == smi_buf.cbRES1 )
00145             throw SmiExceptionImpl("Output buffer format error.");
00146 
00147         if( -3 == smi_buf.cbRES1 )
00148             throw UnhandledSmiImpl("Unhandled SMI call.");
00149 
00150         if( -2 == smi_buf.cbRES1 )
00151             throw UnsupportedSmiImpl("Unsupported SMI call.");
00152 
00153         if( -1 == smi_buf.cbRES1 )
00154             throw SmiExecutedWithErrorImpl("BIOS returned error for SMI call.");
00155     }
00156 
00157     void DellCallingInterfaceSmiImpl::setArgAsPhysicalAddress( u8 argNumber, u32 bufferOffset )
00158     {
00159         if( argNumber >= 4 )
00160             throw ParameterErrorImpl("Internal programming error. Argument must be in range 0..3");
00161 
00162         argIsAddress[argNumber] = true;
00163         argAddressOffset[argNumber] = bufferOffset;
00164     }
00165 
00166 
00167     void DellCallingInterfaceSmiImpl::setClass( u16 newClass )
00168     {
00169         smi_buf.smiClass = newClass;
00170     }
00171 
00172     void DellCallingInterfaceSmiImpl::setSelect( u16 newSelect )
00173     {
00174         smi_buf.smiSelect = newSelect;
00175     }
00176 
00177     void DellCallingInterfaceSmiImpl::setArg( u8 argNumber, u32 argValue )
00178     {
00179         if( argNumber >= 4 )
00180             throw ParameterErrorImpl("Internal programming error. Argument must be in range 0..3");
00181 
00182         smi_buf.inputArgs[ argNumber ] = argValue;
00183     }
00184 
00185     u32 DellCallingInterfaceSmiImpl::getRes( u8 resNumber ) const
00186     {
00187         if( resNumber >= 4 )
00188             throw ParameterErrorImpl("Internal programming error. Result request must be in range 0..3");
00189 
00190         return smi_buf.outputRes[resNumber];
00191     }
00192 
00193 
00194     /**************************************************************************
00195             HELPER FUNCTIONS  (Non-member functions)
00196      *************************************************************************/
00197 
00198     std::auto_ptr<smi::IDellCallingInterfaceSmi> setupCallingInterfaceSmi(u16 smiClass, u16 select, const u32 args[4])
00199     {
00200         smbios::ISmbiosTable *table = 0;
00201         table = smbios::SmbiosFactory::getFactory()->getSingleton();
00202 
00203         std::auto_ptr<smi::ISmi> smi = smi::SmiFactory::getFactory()->makeNew(smi::SmiFactory::DELL_CALLING_INTERFACE_SMI);
00204         smi::IDellCallingInterfaceSmi *ci = dynamic_cast<smi::IDellCallingInterfaceSmi *>(smi.get());
00205 
00206         ci->setClass( smiClass );
00207         ci->setSelect( select );
00208         ci->setArg(0, args[0]);
00209         ci->setArg(1, args[1]);
00210         ci->setArg(2, args[2]);
00211         ci->setArg(3, args[3]);
00212 
00213         std::auto_ptr<smi::IDellCallingInterfaceSmi> retval(
00214             dynamic_cast<smi::IDellCallingInterfaceSmi *>(smi.get())
00215         );
00216         smi.release();
00217         return retval;
00218     }
00219 
00220     void doSimpleCallingInterfaceSmi(u16 smiClass, u16 select, const u32 args[4], u32 res[4])
00221     {
00222 
00223         std::auto_ptr<smi::IDellCallingInterfaceSmi> smi(
00224             setupCallingInterfaceSmi(smiClass, select, args));
00225 
00226         smi->execute();
00227 
00228         res[0] = smi->getRes(0);
00229         res[1] = smi->getRes(1);
00230         res[2] = smi->getRes(2);
00231         res[3] = smi->getRes(3);
00232     }
00233 
00234     /*
00235        An application that will attempt to set information via any Security-Key-protected Calling Interface function must first acquire a proper Security Key.  It does this by performing the following steps:
00236 
00237        1.Check to see if an Administrator Password is set (Class 10, Selector 0 or 3). If yes, go to 2; otherwise, go to 3.
00238 
00239        2.Verify the Administrator Password (Class 10 Selector 1 or 4). If the password is verified (cbRES1 == 0), read the Security Key from cbRES2, and use it on subsequent set functions where it is required. If the password does not verify (cbRES1 == -1), repeat step 2 until it does verify; otherwise, subsequent set functions protected by the Administrator Password will be rejected by the BIOS if it supports the Security Key feature.
00240 
00241        3.Check to see if a User Password is set (Class 9, Selector 0 or 3). If yes, go to 4; otherwise, no Security Key will be needed to change data through the Calling Interface, and the caller can use any value at all for the Security Key when using any Security-Key-protected Calling Interface function.
00242 
00243        4.Verify the User Password (Class 9 Selector 1 or 4). If the password is verified (cbRES1 == 0), read the Security Key from cbRES2, and use it on subsequent set functions where it is required. If the password does not verify (cbRES1 == -1), repeat step 4 until it does verify; otherwise, subsequent set functions protected by the User Password will be rejected by the BIOS if it supports the Security Key feature.
00244 
00245        */
00246     static bool getPasswordPropertiesII(u16 which, u8 &maxLen, u8 &minLen, u8 &props)
00247     {
00248         if( which != 9 && which != 10 )
00249             throw ParameterErrorImpl("Internal programming error. Argument must be either 9 or 10.");
00250 
00251         bool hasPw = false;
00252 
00253         u32 args[4] = {0,}, res[4] = {0,};
00254 
00255         // select 3 == get properties
00256         doSimpleCallingInterfaceSmi(which, 3, args, res);
00257 
00258         // byte 1 of res[1] shows password status. 0==password installed
00259         if( res[1] & 0xFF )
00260             goto out;
00261 
00262         DCERR( "getPasswordPropertiesII()" << hex << endl ); 
00263         DCERR( "res[0]: " << res[0] << endl);
00264         DCERR( "res[1]: " << res[1] << endl);
00265         DCERR( "res[2]: " << res[2] << endl);
00266         DCERR( "res[3]: " << res[3] << endl);
00267 
00268         hasPw = true;
00269         maxLen = static_cast<u8>((res[1] & 0x0000FF00) >> 8);
00270         minLen = static_cast<u8>((res[1] & 0x00FF0000) >> 16);
00271         props  = static_cast<u8>((res[1] & 0xFF000000) >> 24);
00272 
00273 out:
00274         return hasPw;
00275     }
00276 
00277     static u32 getAuthenticationKeyII(const string &password)
00278     {
00279         u32 authKey = 0;
00280 
00281         DCERR( "getAuthenticationKeyII()" << endl );
00282 
00283         u16 toCheck[2] = { class_admin_password, class_user_password };
00284         DCERR( "  trying auth keys" << endl);
00285 
00286         // try admin password first, then user password
00287         for( int i=0; i<2; i++ )
00288         {
00289             DCERR( "  trying class code: " << toCheck[i] << endl);
00290 
00291             u8 maxLen=0, minLen=0, props=0;
00292             // try next password type if no password set
00293             try
00294             {
00295                 if( ! getPasswordPropertiesII(toCheck[i], maxLen, minLen, props) )
00296                     continue;
00297             }
00298             catch( const exception & )
00299             {
00300                 // usually get here for unsupported SMI exception.
00301                 // in which case, it makes no sense to continue 
00302                 //DCERR( "  Caught something." << e.what() << endl);
00303                 continue;
00304             }
00305 
00306             DCERR("has a password." << hex << endl);
00307             DCERR( "  max len: " << (int)maxLen << endl);
00308             DCERR( "  min len: " << (int)minLen << endl);
00309             DCERR( "  props  : " << hex << props << endl);
00310 
00311             u32 args[4] = {0,};
00312             // select 4 == verify password
00313             std::auto_ptr<smi::IDellCallingInterfaceSmi> smi(setupCallingInterfaceSmi(toCheck[i], 4, args));
00314             smi->setBufferSize(maxLen);
00315             strncpy( reinterpret_cast<char*>(smi->getBufferPtr()), password.c_str(), maxLen);
00316             smi->setArgAsPhysicalAddress( 0, 0 );
00317             smi->execute();
00318 
00319             DCERR("after verify:"<< endl);
00320             DCERR("res[0]: " << smi->getRes(0) << endl; );
00321             DCERR("res[1]: " << smi->getRes(1) << endl; );
00322             DCERR("res[2]: " << smi->getRes(2) << endl; );
00323             DCERR("res[3]: " << smi->getRes(3) << endl; );
00324 
00325             if(! smi->getRes(0))
00326                 authKey = smi->getRes(1);
00327             else
00328                 throw PasswordVerificationFailedImpl("BIOS setup password enabled, but given password does not match.");
00329 
00330             // if this password is installed, no sense in checking the other, as it will not work.
00331             // highest priority password always takes precedence
00332             break;
00333         }
00334 
00335         return authKey;
00336     }
00337 
00338     u32 getAuthenticationKey(const string &password)
00339     {
00340         u32 authKey = 0;
00341 
00342         DCERR("getAuthenticationKey(" << password << ")" << endl);
00343 
00344         // try admin password first, then user password
00345         u16 toCheck[2] = { class_admin_password, class_user_password };
00346         DCERR("  trying auth keys" << endl);
00347 
00348         for( int i=0; i<2; i++ )
00349         {
00350             DCERR("    trying class code: " << toCheck[i] << endl);
00351             try
00352             {
00353                 u32 args[4] = {0,}, res[4] = {0,};
00354                 doSimpleCallingInterfaceSmi(toCheck[i], 0, args, res);
00355 
00356                 // no password of this type installed if res[0] == 0
00357                 if( res[0] != 0 )
00358                     continue;
00359             }
00360             catch(const SmiException &)
00361             {
00362                 // We should only get here under the following circumstances:
00363                 // - unsupported SMI call
00364                 // - unhandled SMI call
00365                 // - could not talk to dcdbas driver
00366                 continue;
00367             }
00368 
00369             // If we get here, that means a password of type toCheck[i]
00370             // is installed.
00371             //
00372             DCERR("      password installed" << endl);
00373 
00374             u32 args[4] = {0}, res[4] = {0,};
00375             strncpy(reinterpret_cast<char *>(args), password.c_str(), 2 * sizeof(u32));
00376 
00377             DCERR("    args are  : 0x" << args[0] << " 0x" << args[1] << " 0x" << args[2] << " 0x" << args[3] << endl);
00378 
00379             // if SMI above succeeded, this should too, no exception handling
00380             doSimpleCallingInterfaceSmi(toCheck[i], 1, args, res);
00381 
00382             DCERR("    res was  : 0x" << res[0] << " 0x" << res[1] << " 0x" << res[2] << " 0x" << res[3] << endl);
00383             if( res[0] == 0 )
00384                 authKey = res[1];
00385             else
00386                 throw PasswordVerificationFailedImpl("BIOS setup password enabled, but given password does not match.");
00387 
00388             // if this password is installed, no sense in checking the other, as it will not work.
00389             // highest priority password always takes precedence
00390             break;
00391         }
00392 
00393         // if this didn't work, try other method.
00394         if( ! authKey )
00395             authKey = getAuthenticationKeyII( password );
00396 
00397         return authKey;
00398     }
00399 
00400     password_format_enum getPasswordFormat()
00401     {
00402         password_format_enum format = PW_FORMAT_UNKNOWN;
00403 
00404         try
00405         {
00406             u32 args[4] = {0,}, res[4] = {0,};
00407             doSimpleCallingInterfaceSmi(class_admin_password, 0, args, res);
00408             format = PW_FORMAT_SCAN_CODE;
00409             goto out;
00410         }
00411         catch(const exception &)
00412         { }
00413 
00414         try
00415         {
00416             u32 args[4] = {0,}, res[4] = {0,};
00417             doSimpleCallingInterfaceSmi(class_user_password, 0, args, res);
00418             format = PW_FORMAT_SCAN_CODE;
00419             goto out;
00420         }
00421         catch(const exception &)
00422         { }
00423 
00424         try
00425         {
00426             u8 maxLen=0, minLen=0, props=0;
00427             getPasswordPropertiesII(class_admin_password, maxLen, minLen, props);
00428             format = PW_FORMAT_SCAN_CODE;
00429             if (props & 0x01)
00430                 format = PW_FORMAT_ASCII;
00431             goto out;
00432         }
00433         catch(const exception &)
00434         { }
00435 
00436         try
00437         {
00438             u8 maxLen=0, minLen=0, props=0;
00439             getPasswordPropertiesII(class_user_password, maxLen, minLen, props);
00440             format = PW_FORMAT_SCAN_CODE;
00441             if (props & 0x01)
00442                 format = PW_FORMAT_ASCII;
00443             goto out;
00444         }
00445         catch(const exception &)
00446         { }
00447 
00448 out:
00449         return format;
00450     }
00451 
00452     static u32 readSetting(u16 select, u32 location, u32 *minValue, u32 *maxValue)
00453     {
00454         u32 args[4] = {location, 0,}, res[4] = {0,};
00455         doSimpleCallingInterfaceSmi(0, select, args, res); // 0 == class code for setting/batter/ac/systemstatus
00456         if(minValue)
00457             *minValue = res[2];
00458         if(maxValue)
00459             *maxValue = res[3];
00460         return res[1]; // current value
00461     }
00462 
00463     u32 readNVStorage(u32 location, u32 *minValue, u32 *maxValue)
00464     {
00465         return readSetting(0, location, minValue, maxValue); // 0 = select code for nv storage
00466     }
00467 
00468     u32 readBatteryModeSetting(u32 location, u32 *minValue, u32 *maxValue)
00469     {
00470         return readSetting(1, location, minValue, maxValue); // 1 = select code for battery mode
00471     }
00472 
00473     u32 readACModeSetting(u32 location, u32 *minValue, u32 *maxValue)
00474     {
00475         return readSetting(2, location, minValue, maxValue); // 2 = select code for ac mode
00476     }
00477 
00478     u32 readSystemStatus(u32 *failingSensorHandle)
00479     {
00480         // 3 = select code for system status
00481         // 1st 0 == dummy location value
00482         // 2nd 0 == dummy max value pointer
00483         return readSetting(3, 0, failingSensorHandle, 0);
00484     }
00485 
00486 
00487     static u32 writeSetting(const std::string &password, u16 select, u32 location, u32 newValue, u32 *minValue, u32 *maxValue)
00488     {
00489         u32 args[4] = {location, newValue,}, res[4] = {0,};
00490 
00491         // go twice. Once without security key, once by trying password given.
00492         for(int i=0; i<2; i++)
00493         {
00494             try
00495             {
00496                 // 0 == class code for writing to setting/battery/ac/systemstatus
00497                 DCERR("Try #" << i << " for writeSetting()" << endl);
00498                 DCERR("    args are  : 0x" << args[0] << " 0x" << args[1] << " 0x" << args[2] << " 0x" << args[3] << endl);
00499                 doSimpleCallingInterfaceSmi(1, select, args, res);
00500                 DCERR("    res was  : 0x" << res[0] << " 0x" << res[1] << " 0x" << res[2] << " 0x" << res[3] << endl);
00501                 break;
00502             }
00503             catch(const SmiExecutedWithError &)
00504             {
00505                 // on second time through, just pass exception upwards.
00506                 if(i==1)
00507                     throw;
00508 
00509                 DCERR("Executed with error, try password..." << endl);
00510                 args[2] = getAuthenticationKey(password);
00511             }
00512         }
00513 
00514         if(minValue)
00515             *minValue = res[2];
00516         if(maxValue)
00517             *maxValue = res[3];
00518         return res[1]; // current value
00519     }
00520 
00521     u32 writeNVStorage(const std::string &password, u32 location, u32 value, u32 *minValue, u32 *maxValue)
00522     {
00523         return writeSetting(password, 0, location, value, minValue, maxValue);
00524     }
00525 
00526     u32 writeBatteryModeSetting(const std::string &password, u32 location, u32 value, u32 *minValue, u32 *maxValue)
00527     {
00528         return writeSetting(password, 1, location, value, minValue, maxValue);
00529     }
00530 
00531     u32 writeACModeSetting(const std::string &password, u32 location, u32 value, u32 *minValue, u32 *maxValue)
00532     {
00533         return writeSetting(password, 2, location, value, minValue, maxValue);
00534     }
00535 
00536     void getDisplayType(u32 &type, u32 &resolution, u32 &memSizeX256kb)
00537     {
00538         u32 args[4] = {0,}, res[4] = {0,};
00539         doSimpleCallingInterfaceSmi(4, 0, args, res);
00540 
00541         type = (res[1] & 0x00FF);
00542         resolution = (res[1] & 0xFF00) >> 8;
00543         memSizeX256kb = res[2];
00544     }
00545 
00546     void getPanelResolution(u32 &horiz, u32 &vert)
00547     {
00548         u32 args[4] = {0,}, res[4] = {0,};
00549         doSimpleCallingInterfaceSmi(4, 1, args, res);
00550 
00551         horiz = (res[1] & 0x0000FFFF);
00552         vert  = (res[1] & 0xFFFF0000) >> 16;
00553     }
00554 
00555     void getActiveDisplays(u32 &bits)
00556     {
00557         u32 args[4] = {0,}, res[4] = {0,};
00558         doSimpleCallingInterfaceSmi(4, 2, args, res);
00559 
00560         bits = res[1];
00561     }
00562 
00563     void setActiveDisplays(u32 &bits)
00564     {
00565         u32 args[4] = {bits, 0,}, res[4] = {0,};
00566         doSimpleCallingInterfaceSmi(4, 3, args, res);
00567     }
00568 
00569     void getPropertyOwnershipTag(char *tagBuf, size_t size)
00570     {
00571         u32 args[4] = {0,};
00572         // class 20 == property tag
00573         std::auto_ptr<smi::IDellCallingInterfaceSmi> smi(setupCallingInterfaceSmi(20, 0, args));
00574         smi->setBufferSize(120); // 80 is max len, making sure it doesn't overflow now. :-)
00575         smi->setArgAsPhysicalAddress( 0, 0 );
00576         smi->execute();
00577         strncpy( tagBuf, reinterpret_cast<char*>(smi->getBufferPtr()), size < 80? size:80);
00578     }
00579 
00580     void setPropertyOwnershipTag(const string password, const char *newTag, size_t size)
00581     {
00582         u32 args[4] = {0,};
00583 
00584         for(int i=0; i<2; i++)
00585         {
00586             try
00587             {
00588                 // class 20 == property tag
00589                 std::auto_ptr<smi::IDellCallingInterfaceSmi> smi(setupCallingInterfaceSmi(20, 1, args));
00590                 smi->setBufferSize(120); // 80 is max len, making sure it doesn't overflow now. :-)
00591                 strncpy( reinterpret_cast<char*>(smi->getBufferPtr()), newTag, size < 80? size:80);
00592                 smi->setArgAsPhysicalAddress( 0, 0 );
00593                 smi->execute();
00594                 break;
00595             }
00596             catch(const SmiExecutedWithError &)
00597             {
00598                 // on second time through, just pass exception upwards.
00599                 if(i==1)
00600                     throw;
00601 
00602                 //cout << "Caught error. Might be bad password. Trying password: " << password << endl;
00603                 args[1] = getAuthenticationKey(password);
00604             }
00605         }
00606     }
00607 
00608 
00609     // token list for wireless tokens. Probably not the best place for this,
00610     // but until something better comes along...
00611     const int Bluetooth_Devices_Disable = 0x0153;  // docs appear to be wrong. They say 0x0152, but this looks backwards from reality
00612     const int Bluetooth_Devices_Enable = 0x0152;  // docs appear to be wrong. They say 0x0153, but this looks backwards from reality
00613     const int Cellular_Radio_Disable = 0x017B;
00614     const int Cellular_Radio_Enable = 0x017C;
00615     const int WiFi_Locator_Disable = 0x017D;
00616     const int WiFi_Locator_Enable = 0x017E;
00617     const int Wireless_LAN_Disable = 0x017F;
00618     const int Wireless_LAN_Enable = 0x0180;
00619     const int Wireless_Switch_Bluetooth_Control_Disable = 0x0181;
00620     const int Wireless_Switch_Bluetooth_Control_Enable = 0x0182;
00621     const int Wireless_Switch_Cellular_Control_Disable = 0x0183;
00622     const int Wireless_Switch_Cellular_Control_Enable = 0x0184;
00623     const int Wireless_Switch_Wireless_LAN_Control_Disable = 0x0185;
00624     const int Wireless_Switch_Wireless_LAN_Control_Enable = 0x0186;
00625     const int Radio_Transmission_Enable = 0x010c;
00626     const int Radio_Transmission_Disable = 0x010d;
00627     const int Wireless_Device_Disable = 0x0114;
00628     const int Wireless_Device_App_Control = 0x0115;
00629     const int Wireless_Device_App_Or_Hotkey_Control = 0x0116;
00630 
00631     // cbClass 17
00632     // cbSelect 11
00633     // WiFi Control
00634     // Entry/return values grouped by the value of cbARG1, byte0 which indicates the function to perform:
00635     // 0x1 = Set QuickSet Radio Disable Flag
00636     //  cbARG1, byte1    Radio ID value:
00637     //      0 Radio Status
00638     //      1 WLAN ID
00639     //      2 BT ID
00640     //      3 WWAN ID
00641     //  cbARG1, byte2   Flag bits:
00642     //      0 QuickSet disables radio (1)
00643     //      1-7 Reserved (0)
00644     //  cbRES1      Standard return codes (0, -1, -2)
00645     //  cbRES2      QuickSet (QS) radio disable bit map:
00646     //      0 QS disables WLAN
00647     //      1 QS disables BT
00648     //      2 QS disables WWAN
00649     //      3-31 Reserved (0)
00650     void wirelessRadioControl(bool enable, bool boot, bool runtime, int enable_token, int disable_token, int radioNum, std::string password)
00651     {
00652         if (boot)
00653             smbios::activateToken( (enable ?
00654                 enable_token :
00655                 disable_token),
00656                 password
00657                 );
00658         if (runtime)
00659         {
00660             if (enable && !smbios::isTokenActive(enable_token))
00661                 throw ConfigErrorImpl("boot time config disabled, runtime setting has no effect.");
00662 
00663             u32 disable = enable ? 0:1;
00664             u32 args[4] = {(1 | (static_cast<u32>(radioNum)<<8) | ((disable)<<16)), 0, 0, 0};
00665             u32 res[4] = {0,};
00666             doSimpleCallingInterfaceSmi(17, 11, args, res);
00667         }
00668     }
00669 
00670 
00671     static void switchControl(u32 whichConfig, u32 whichSwitch, bool enable)
00672     {
00673         std::auto_ptr<smi::ISmi> smi = smi::SmiFactory::getFactory()->makeNew(smi::SmiFactory::DELL_CALLING_INTERFACE_SMI);
00674         smi::IDellCallingInterfaceSmi *ci = dynamic_cast<smi::IDellCallingInterfaceSmi *>(smi.get());
00675         ci->setClass( 17 );  /* ? */
00676         ci->setSelect( 11 );  /* WiFi Control */
00677     
00678         // 0x2 = Wireless Switch Configuration
00679         //  cbARG1, byte1   Subcommand:
00680         //      0 Get config
00681         //      1 Set config
00682         //      2 Set WiFi locator enable/disable
00683         //  cbARG1,byte2    Switch settings (if byte 1==1):
00684         //      0 WLAN switch control (1)
00685         //      1 BT switch control (1)
00686         //      2 WWAN switch control (1)
00687         //      3-7 Reserved (0)
00688         //  cbARG1, byte2   Enable bits (if byte 1==2):
00689         //      0 Enable WiFi locator (1)
00690         //  cbRES1      Standard return codes (0, -1, -2)
00691         //  cbRES2      QuickSet radio disable bit map:
00692         //      0 WLAN controlled by switch (1)
00693         //      1 BT controlled by switch (1)
00694         //      2 WWAN controlled by switch (1)
00695         //      3-6 Reserved (0)
00696         //      7 Wireless switch config locked (1)
00697         //      8 WiFi locator enabled (1)
00698         //      9-14 Reserved (0)
00699         //      15 WiFi locator setting locked (1)
00700         //      16-31 Reserved (0)
00701         ci->setArg(smi::cbARG1, 0x2);
00702         ci->execute();
00703     
00704         u32 oldConfig = ci->getRes(smi::cbRES2);
00705         if (whichConfig == 1)
00706             oldConfig &= 0xFF;
00707         else if (whichConfig == 2)
00708             oldConfig = ((oldConfig>>8) & 0xFF);
00709     
00710         u32 newConfig = (oldConfig & ~whichSwitch) | ((enable?1:0) * whichSwitch);
00711         ci->setArg(smi::cbARG1, (0x2 | (whichConfig << 8) | (newConfig << 16)));
00712         ci->execute();
00713     }
00714     
00715     void wirelessSwitchControl(bool enable, bool boot, bool runtime, int enable_token, int disable_token, int switchNum, std::string password)
00716     {
00717         int intSwitchConfig = 0, intSwitchNum = 0;
00718         switch(switchNum)
00719         {
00720             case WLAN_SWITCH_CTL:
00721                 intSwitchConfig = 1;
00722                 intSwitchNum = 1;
00723                 break;
00724             case BLUETOOTH_SWITCH_CTL:
00725                 intSwitchConfig = 1;
00726                 intSwitchNum = 2;
00727                 break;
00728             case WWAN_SWITCH_CTL:
00729                 intSwitchConfig = 1;
00730                 intSwitchNum = 4;
00731                 break;
00732             case LOCATOR_SWITCH_CTL:
00733                 intSwitchConfig = 2;
00734                 intSwitchNum = 1;
00735                 break;
00736             default:
00737                 throw ParameterErrorImpl("Invalid switch number passed to wirelessSwitchControl()");
00738         }
00739         
00740         if (boot)
00741             smbios::activateToken( (enable ?
00742                 enable_token :
00743                 disable_token),
00744                 password
00745                 );
00746         if (runtime)
00747             switchControl(intSwitchConfig, intSwitchNum, enable);
00748     }
00749 
00750     radioStatusCode wirelessRadioStatus(radioNum which, std::ostream &cout, u32 defRes2)
00751     {
00752         radioStatusCode ret = STATUS_UNKNOWN;
00753         try
00754         {
00755             u32 args[4] = {0,}, res[4] ={0,};
00756             if (!defRes2)
00757                 smi::doSimpleCallingInterfaceSmi(17, 11, args, res);
00758             else
00759                 res[smi::cbRES2] = defRes2;
00760     
00761             int supported_bit=0, installed_bit=0, disabled_bit=0;
00762             string name;
00763             switch(which)
00764             {
00765                 case smi::WLAN_RADIO_NUM:
00766                     supported_bit = 2;
00767                     installed_bit = 8;
00768                     disabled_bit = 17;
00769                     name = "WLAN";
00770                     break;
00771                 case smi::BLUETOOTH_RADIO_NUM:
00772                     supported_bit = 3;
00773                     installed_bit = 9;
00774                     disabled_bit = 18;
00775                     name = "Bluetooth";
00776                     break;
00777                 case smi::WWAN_RADIO_NUM:
00778                     supported_bit = 4;
00779                     installed_bit = 10;
00780                     disabled_bit = 19;
00781                     name = "WWAN";
00782                     break;
00783             }
00784     
00785             cout << "Radio Status for " << name << ":" << endl;
00786             if (res[smi::cbRES2] & (1 << supported_bit))
00787             {
00788                 cout << "\t" << name << " supported" << endl;
00789                 cout << "\t" << name << " " << ((res[smi::cbRES2] & (1 << installed_bit)) ? "installed":"not installed") << endl;
00790                 cout << "\t" << name << " " << ((res[smi::cbRES2] & (1 << disabled_bit)) ? "disabled" : "enabled") << endl;
00791     
00792                 ret = STATUS_DISABLED;
00793                 if (!(res[smi::cbRES2] & (1 << installed_bit)))
00794                     ret = STATUS_NOT_PRESENT;
00795                 else if (!(res[smi::cbRES2] & (1 << disabled_bit)))
00796                     ret = STATUS_ENABLED;
00797             } else {
00798                 cout << "\t" << name << " not supported" << endl;
00799                 ret = STATUS_UNSUPPORTED;
00800         }
00801             cout << "\tStatus Code: " << ret << endl;
00802         } catch (smi::UnsupportedSmi &) {
00803             // this interface not available...
00804         }
00805         return ret;
00806     }
00807 
00808 }

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