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

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

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