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

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