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 "../token/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     // ISmi functions
00047     //
00048     ISmi::ISmi()
00049     {}
00050 
00051     ISmi::~ISmi()
00052     {}
00053 
00054     IDellCallingInterfaceSmi::IDellCallingInterfaceSmi()
00055     {}
00056 
00057     IDellCallingInterfaceSmi::~IDellCallingInterfaceSmi()
00058     {}
00059 
00060     DellCallingInterfaceSmiImpl::DellCallingInterfaceSmiImpl(SmiStrategy *initStrategy)
00061             :  ISmi(), IDellCallingInterfaceSmi(), buffer(0), bufferSize(0), smiStrategy(initStrategy)
00062     {
00063         // this is the only place where we use 'real' sizeof(kernel_buf), 
00064         // everywhere else should use SIZEOF_KERNELBUF
00065         memset( &kernel_buf, 0, sizeof(kernel_buf) );
00066 
00067         memset( &smi_buf, 0, sizeof(smi_buf) );
00068         memset( &argIsAddress, 0, sizeof(argIsAddress) );
00069         memset( &argAddressOffset, 0, sizeof(argAddressOffset) );
00070 
00071         kernel_buf.magic = KERNEL_SMI_MAGIC_NUMBER;
00072         kernel_buf.ebx = 0;
00073         kernel_buf.ecx   = DELL_CALLINTF_SMI_MAGIC_NUMBER;
00074         kernel_buf.command_address = 0;
00075         kernel_buf.command_code = 0;
00076 
00077         /* default to "not handled" */
00078         smi_buf.cbRES1 = -3;
00079     }
00080 
00081     DellCallingInterfaceSmiImpl::~DellCallingInterfaceSmiImpl()
00082     {
00083         if(buffer)
00084         {
00085             delete [] buffer;
00086             buffer = 0;
00087             bufferSize = 0;
00088         }
00089     }
00090 
00091     void DellCallingInterfaceSmiImpl::setCommandIOMagic( u16 address, u8 code )
00092     {
00093         kernel_buf.command_address = address;
00094         kernel_buf.command_code = code;
00095     }
00096 
00097     u8 *DellCallingInterfaceSmiImpl::getBufferPtr()
00098     {
00099         return buffer;
00100     }
00101 
00102     void DellCallingInterfaceSmiImpl::setBufferSize(size_t newSize)
00103     {
00104         if ( bufferSize != newSize )
00105         {
00106             delete [] buffer;
00107             buffer = new u8[newSize];
00108             memset(buffer, 0, newSize);
00109 
00110             bufferSize=newSize;
00111         }
00112     }
00113 
00114     void DellCallingInterfaceSmiImpl::execute()
00115     {
00116         smiStrategy->lock()
00117         ;
00118         smiStrategy->setSize( SIZEOF_KERNELBUF + sizeof(smi_buf) + bufferSize );
00119 
00120         size_t baseAddr = smiStrategy->getPhysicalBufferBaseAddress();
00121         for( int i=0; i<4; i++)
00122             if( argIsAddress[i] )
00123                 smi_buf.inputArgs[i] = static_cast<u32>(baseAddr + SIZEOF_KERNELBUF + sizeof(smi_buf) + argAddressOffset[i]);
00124 
00125         smiStrategy->addInputBuffer(reinterpret_cast<u8 *>(&kernel_buf), SIZEOF_KERNELBUF);
00126         smiStrategy->addInputBuffer(reinterpret_cast<u8 *>(&smi_buf), sizeof(smi_buf));
00127         if(buffer)
00128             smiStrategy->addInputBuffer(buffer, bufferSize);
00129 
00130         smiStrategy->execute();
00131 
00132         smiStrategy->getResultBuffer(reinterpret_cast<u8 *>(&kernel_buf), SIZEOF_KERNELBUF);
00133         smiStrategy->getResultBuffer(reinterpret_cast<u8 *>(&smi_buf), sizeof(smi_buf));
00134         if(buffer)
00135             smiStrategy->getResultBuffer(reinterpret_cast<u8 *>(buffer), bufferSize);
00136 
00137         smiStrategy->finish();
00138 
00139         if( -3 == smi_buf.cbRES1 )
00140             throw UnhandledSmiImpl("Unhandled SMI call.");
00141 
00142         if( -2 == smi_buf.cbRES1 )
00143             throw UnsupportedSmiImpl("Unsupported SMI call.");
00144 
00145         if( -1 == smi_buf.cbRES1 )
00146             throw SmiExecutedWithErrorImpl("BIOS returned error for SMI call.");
00147     }
00148 
00149     void DellCallingInterfaceSmiImpl::setArgAsPhysicalAddress( u8 argNumber, u32 bufferOffset )
00150     {
00151         if( argNumber >= 4 )
00152             throw ParameterErrorImpl("Internal programming error. Argument must be in range 0..3");
00153 
00154         argIsAddress[argNumber] = true;
00155         argAddressOffset[argNumber] = bufferOffset;
00156     }
00157 
00158 
00159     void DellCallingInterfaceSmiImpl::setClass( u16 newClass )
00160     {
00161         smi_buf.smiClass = newClass;
00162     }
00163 
00164     void DellCallingInterfaceSmiImpl::setSelect( u16 newSelect )
00165     {
00166         smi_buf.smiSelect = newSelect;
00167     }
00168 
00169     void DellCallingInterfaceSmiImpl::setArg( u8 argNumber, u32 argValue )
00170     {
00171         if( argNumber >= 4 )
00172             throw ParameterErrorImpl("Internal programming error. Argument must be in range 0..3");
00173 
00174         smi_buf.inputArgs[ argNumber ] = argValue;
00175     }
00176 
00177     u32 DellCallingInterfaceSmiImpl::getRes( u8 resNumber ) const
00178     {
00179         if( resNumber >= 4 )
00180             throw ParameterErrorImpl("Internal programming error. Result request must be in range 0..3");
00181 
00182         return smi_buf.outputRes[resNumber];
00183     }
00184 
00185 
00186     /**************************************************************************
00187             HELPER FUNCTIONS  (Non-member functions)
00188      *************************************************************************/
00189 
00190     std::auto_ptr<smi::IDellCallingInterfaceSmi> setupCallingInterfaceSmi(u16 smiClass, u16 select, const u32 args[4])
00191     {
00192         smbios::ISmbiosTable *table = 0;
00193         table = smbios::SmbiosFactory::getFactory()->getSingleton();
00194 
00195         std::auto_ptr<smi::ISmi> smi = smi::SmiFactory::getFactory()->makeNew(smi::SmiFactory::DELL_CALLING_INTERFACE_SMI);
00196         smi::IDellCallingInterfaceSmi *ci = dynamic_cast<smi::IDellCallingInterfaceSmi *>(smi.get());
00197 
00198         size_t len = 0;
00199         const u8 *buf = 0;
00200         try
00201         {
00202             buf = (*table)[0xDA]->getBufferCopy(len);
00203             // have to take off the size of the optional structs or this is a false positive 
00204             // on some systems
00205             if( len < (sizeof(smbios::calling_interface_structure) - sizeof(smbios::calling_interface_token)) )
00206                 throw smbios::InternalErrorImpl("Internal error. Possible BIOS problem: length of 0xDA structure is too short.");
00207 
00208             const smbios::calling_interface_structure *struct_ptr = reinterpret_cast<const smbios::calling_interface_structure*>(buf);
00209             smi->setCommandIOMagic( struct_ptr->cmdIOAddress, struct_ptr->cmdIOCode );
00210             delete [] const_cast<u8 *>(buf);
00211         }
00212         catch(const smbios::DerefNullPointer &)
00213         {
00214             delete [] const_cast<u8 *>(buf);
00215             throw smbios::InternalErrorImpl("Internal error. It does not appear that this BIOS supports SMI (no 0xDA structure in SMBIOS).");
00216         }
00217         catch(...)
00218         {
00219             delete [] const_cast<u8 *>(buf);
00220             throw;
00221         }
00222 
00223         ci->setClass( smiClass );
00224         ci->setSelect( select );
00225         ci->setArg(0, args[0]);
00226         ci->setArg(1, args[1]);
00227         ci->setArg(2, args[2]);
00228         ci->setArg(3, args[3]);
00229 
00230         std::auto_ptr<smi::IDellCallingInterfaceSmi> retval(
00231             dynamic_cast<smi::IDellCallingInterfaceSmi *>(smi.get())
00232         );
00233         smi.release();
00234         return retval;
00235     }
00236 
00237     void doSimpleCallingInterfaceSmi(u16 smiClass, u16 select, const u32 args[4], u32 res[4])
00238     {
00239 
00240         std::auto_ptr<smi::IDellCallingInterfaceSmi> smi(
00241             setupCallingInterfaceSmi(smiClass, select, args));
00242 
00243         smi->execute();
00244 
00245         res[0] = smi->getRes(0);
00246         res[1] = smi->getRes(1);
00247         res[2] = smi->getRes(2);
00248         res[3] = smi->getRes(3);
00249     }
00250 
00251     /*
00252        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:
00253 
00254        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.
00255 
00256        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.
00257 
00258        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.
00259 
00260        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.
00261 
00262        */
00263     static bool getPasswordPropertiesII(u16 which, u8 &maxLen, u8 &minLen, u8 &props)
00264     {
00265         if( which != 9 && which != 10 )
00266             throw ParameterErrorImpl("Internal programming error. Argument must be either 9 or 10.");
00267 
00268         bool hasPw = false;
00269 
00270         u32 args[4] = {0,}, res[4] = {0,};
00271 
00272         // select 3 == get properties
00273         doSimpleCallingInterfaceSmi(which, 3, args, res);
00274 
00275         // byte 1 of res[1] shows password status. 0==password installed
00276         if( res[1] & 0xFF )
00277             goto out;
00278 
00279         DCERR( "getPasswordPropertiesII()" << hex << endl ); 
00280         DCERR( "res[0]: " << res[0] << endl);
00281         DCERR( "res[1]: " << res[1] << endl);
00282         DCERR( "res[2]: " << res[2] << endl);
00283         DCERR( "res[3]: " << res[3] << endl);
00284 
00285         hasPw = true;
00286         maxLen = static_cast<u8>((res[1] & 0x0000FF00) >> 8);
00287         minLen = static_cast<u8>((res[1] & 0x00FF0000) >> 16);
00288         props  = static_cast<u8>((res[1] & 0xFF000000) >> 24);
00289 
00290 out:
00291         return hasPw;
00292     }
00293 
00294     static u32 getAuthenticationKeyII(const string &password)
00295     {
00296         u32 authKey = 0;
00297 
00298         DCERR( "getAuthenticationKeyII()" << endl );
00299 
00300         u16 toCheck[2] = { class_admin_password, class_user_password };
00301         DCERR( "  trying auth keys" << endl);
00302 
00303         // try admin password first, then user password
00304         for( int i=0; i<2; i++ )
00305         {
00306             DCERR( "  trying class code: " << toCheck[i] << endl);
00307 
00308             u8 maxLen=0, minLen=0, props=0;
00309             // try next password type if no password set
00310             try
00311             {
00312                 if( ! getPasswordPropertiesII(toCheck[i], maxLen, minLen, props) )
00313                     continue;
00314             }
00315             catch( const exception & )
00316             {
00317                 // usually get here for unsupported SMI exception.
00318                 // in which case, it makes no sense to continue 
00319                 //DCERR( "  Caught something." << e.what() << endl);
00320                 continue;
00321             }
00322 
00323             DCERR("has a password." << hex << endl);
00324             DCERR( "  max len: " << (int)maxLen << endl);
00325             DCERR( "  min len: " << (int)minLen << endl);
00326             DCERR( "  props  : " << hex << props << endl);
00327 
00328             u32 args[4] = {0,};
00329             // select 4 == verify password
00330             std::auto_ptr<smi::IDellCallingInterfaceSmi> smi(setupCallingInterfaceSmi(toCheck[i], 4, args));
00331             smi->setBufferSize(maxLen);
00332             strncpy( reinterpret_cast<char*>(smi->getBufferPtr()), password.c_str(), maxLen);
00333             smi->setArgAsPhysicalAddress( 0, 0 );
00334             smi->execute();
00335 
00336             DCERR("after verify:"<< endl);
00337             DCERR("res[0]: " << smi->getRes(0) << endl; );
00338             DCERR("res[1]: " << smi->getRes(1) << endl; );
00339             DCERR("res[2]: " << smi->getRes(2) << endl; );
00340             DCERR("res[3]: " << smi->getRes(3) << endl; );
00341 
00342             if(! smi->getRes(0))
00343                 authKey = smi->getRes(1);
00344             else
00345                 throw PasswordVerificationFailedImpl("BIOS setup password enabled, but given password does not match.");
00346 
00347             // if this password is installed, no sense in checking the other, as it will not work.
00348             // highest priority password always takes precedence
00349             break;
00350         }
00351 
00352         return authKey;
00353     }
00354 
00355     u32 getAuthenticationKey(const string &password)
00356     {
00357         u32 authKey = 0;
00358 
00359         DCERR("getAuthenticationKey()" << endl);
00360 
00361         // try admin password first, then user password
00362         u16 toCheck[2] = { class_admin_password, class_user_password };
00363         DCERR("  trying auth keys" << endl);
00364 
00365         for( int i=0; i<2; i++ )
00366         {
00367             DCERR("    trying class code: " << toCheck[i] << endl);
00368             try
00369             {
00370                 u32 args[4] = {0,}, res[4] = {0,};
00371                 doSimpleCallingInterfaceSmi(toCheck[i], 0, args, res);
00372 
00373                 // no password of this type installed if res[0] == 0
00374                 if( res[0] != 0 )
00375                     continue;
00376             }
00377             catch(const SmiException &)
00378             {
00379                 // We should only get here under the following circumstances:
00380                 // - unsupported SMI call
00381                 // - unhandled SMI call
00382                 // - could not talk to dcdbas driver
00383                 continue;
00384             }
00385 
00386             // If we get here, that means a password of type toCheck[i]
00387             // is installed.
00388             //
00389             DCERR("      password installed" << endl);
00390 
00391             u32 args[4] = {0}, res[4] = {0,};
00392             strncpy(reinterpret_cast<char *>(args), password.c_str(), 2 * sizeof(u32));
00393 
00394             DCERR("    args are  : 0x" << args[0] << " 0x" << args[1] << " 0x" << args[2] << " 0x" << args[3] << endl);
00395 
00396             // if SMI above succeeded, this should to, no exception handling
00397             doSimpleCallingInterfaceSmi(toCheck[i], 1, args, res);
00398 
00399             if( res[0] == 0 )
00400                 authKey = res[1];
00401             else
00402                 throw PasswordVerificationFailedImpl("BIOS setup password enabled, but given password does not match.");
00403 
00404             // if this password is installed, no sense in checking the other, as it will not work.
00405             // highest priority password always takes precedence
00406             break;
00407         }
00408 
00409         // if this didn't work, try other method.
00410         if( ! authKey )
00411             authKey = getAuthenticationKeyII( password );
00412 
00413         return authKey;
00414     }
00415 
00416     password_format_enum getPasswordFormat()
00417     {
00418         password_format_enum format = PW_FORMAT_UNKNOWN;
00419 
00420         try
00421         {
00422             u32 args[4] = {0,}, res[4] = {0,};
00423             doSimpleCallingInterfaceSmi(class_admin_password, 0, args, res);
00424             format = PW_FORMAT_SCAN_CODE;
00425             goto out;
00426         }
00427         catch(const exception &)
00428         { }
00429 
00430         try
00431         {
00432             u32 args[4] = {0,}, res[4] = {0,};
00433             doSimpleCallingInterfaceSmi(class_user_password, 0, args, res);
00434             format = PW_FORMAT_SCAN_CODE;
00435             goto out;
00436         }
00437         catch(const exception &)
00438         { }
00439 
00440         try
00441         {
00442             u8 maxLen=0, minLen=0, props=0;
00443             getPasswordPropertiesII(class_admin_password, maxLen, minLen, props);
00444             format = PW_FORMAT_SCAN_CODE;
00445             if (props & 0x01)
00446                 format = PW_FORMAT_ASCII;
00447             goto out;
00448         }
00449         catch(const exception &)
00450         { }
00451 
00452         try
00453         {
00454             u8 maxLen=0, minLen=0, props=0;
00455             getPasswordPropertiesII(class_user_password, maxLen, minLen, props);
00456             format = PW_FORMAT_SCAN_CODE;
00457             if (props & 0x01)
00458                 format = PW_FORMAT_ASCII;
00459             goto out;
00460         }
00461         catch(const exception &)
00462         { }
00463 
00464 out:
00465         return format;
00466     }
00467 
00468     static u32 readSetting(u16 select, u32 location, u32 *minValue, u32 *maxValue)
00469     {
00470         u32 args[4] = {location, 0,}, res[4] = {0,};
00471         doSimpleCallingInterfaceSmi(0, select, args, res); // 0 == class code for setting/batter/ac/systemstatus
00472         if(minValue)
00473             *minValue = res[2];
00474         if(maxValue)
00475             *maxValue = res[3];
00476         return res[1]; // current value
00477     }
00478 
00479     u32 readNVStorage(u32 location, u32 *minValue, u32 *maxValue)
00480     {
00481         return readSetting(0, location, minValue, maxValue); // 0 = select code for nv storage
00482     }
00483 
00484     u32 readBatteryModeSetting(u32 location, u32 *minValue, u32 *maxValue)
00485     {
00486         return readSetting(1, location, minValue, maxValue); // 1 = select code for battery mode
00487     }
00488 
00489     u32 readACModeSetting(u32 location, u32 *minValue, u32 *maxValue)
00490     {
00491         return readSetting(2, location, minValue, maxValue); // 2 = select code for ac mode
00492     }
00493 
00494     u32 readSystemStatus(u32 *failingSensorHandle)
00495     {
00496         // 3 = select code for system status
00497         // 1st 0 == dummy location value
00498         // 2nd 0 == dummy max value pointer
00499         return readSetting(3, 0, failingSensorHandle, 0);
00500     }
00501 
00502 
00503     static u32 writeSetting(const std::string &password, u16 select, u32 location, u32 newValue, u32 *minValue, u32 *maxValue)
00504     {
00505         u32 args[4] = {location, newValue,}, res[4] = {0,};
00506 
00507         // go twice. Once without security key, once by trying password given.
00508         for(int i=0; i<2; i++)
00509         {
00510             try
00511             {
00512                 // 0 == class code for writing to setting/battery/ac/systemstatus
00513                 doSimpleCallingInterfaceSmi(1, select, args, res);
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                 args[2] = getAuthenticationKey(password);
00523             }
00524         }
00525 
00526         if(minValue)
00527             *minValue = res[2];
00528         if(maxValue)
00529             *maxValue = res[3];
00530         return res[1]; // current value
00531     }
00532 
00533     u32 writeNVStorage(const std::string &password, u32 location, u32 value, u32 *minValue, u32 *maxValue)
00534     {
00535         return writeSetting(password, 0, location, value, minValue, maxValue);
00536     }
00537 
00538     u32 writeBatteryModeSetting(const std::string &password, u32 location, u32 value, u32 *minValue, u32 *maxValue)
00539     {
00540         return writeSetting(password, 1, location, value, minValue, maxValue);
00541     }
00542 
00543     u32 writeACModeSetting(const std::string &password, u32 location, u32 value, u32 *minValue, u32 *maxValue)
00544     {
00545         return writeSetting(password, 2, location, value, minValue, maxValue);
00546     }
00547 
00548     void getDisplayType(u32 &type, u32 &resolution, u32 &memSizeX256kb)
00549     {
00550         u32 args[4] = {0,}, res[4] = {0,};
00551         doSimpleCallingInterfaceSmi(4, 0, args, res);
00552 
00553         type = (res[1] & 0x00FF);
00554         resolution = (res[1] & 0xFF00) >> 8;
00555         memSizeX256kb = res[2];
00556     }
00557 
00558     void getPanelResolution(u32 &horiz, u32 &vert)
00559     {
00560         u32 args[4] = {0,}, res[4] = {0,};
00561         doSimpleCallingInterfaceSmi(4, 1, args, res);
00562 
00563         horiz = (res[1] & 0x0000FFFF);
00564         vert  = (res[1] & 0xFFFF0000) >> 16;
00565     }
00566 
00567     void getActiveDisplays(u32 &bits)
00568     {
00569         u32 args[4] = {0,}, res[4] = {0,};
00570         doSimpleCallingInterfaceSmi(4, 2, args, res);
00571 
00572         bits = res[1];
00573     }
00574 
00575     void setActiveDisplays(u32 &bits)
00576     {
00577         u32 args[4] = {bits, 0,}, res[4] = {0,};
00578         doSimpleCallingInterfaceSmi(4, 3, args, res);
00579     }
00580 
00581     void getPropertyOwnershipTag(char *tagBuf, size_t size)
00582     {
00583         u32 args[4] = {0,};
00584         // class 20 == property tag
00585         std::auto_ptr<smi::IDellCallingInterfaceSmi> smi(setupCallingInterfaceSmi(20, 0, args));
00586         smi->setBufferSize(120); // 80 is max len, making sure it doesn't overflow now. :-)
00587         smi->setArgAsPhysicalAddress( 0, 0 );
00588         smi->execute();
00589         strncpy( tagBuf, reinterpret_cast<char*>(smi->getBufferPtr()), size < 80? size:80);
00590     }
00591 
00592     void setPropertyOwnershipTag(const string password, const char *newTag, size_t size)
00593     {
00594         u32 args[4] = {0,};
00595 
00596         for(int i=0; i<2; i++)
00597         {
00598             try
00599             {
00600                 // class 20 == property tag
00601                 std::auto_ptr<smi::IDellCallingInterfaceSmi> smi(setupCallingInterfaceSmi(20, 1, args));
00602                 smi->setBufferSize(120); // 80 is max len, making sure it doesn't overflow now. :-)
00603                 strncpy( reinterpret_cast<char*>(smi->getBufferPtr()), newTag, size < 80? size:80);
00604                 smi->setArgAsPhysicalAddress( 0, 0 );
00605                 smi->execute();
00606                 break;
00607             }
00608             catch(const SmiExecutedWithError &)
00609             {
00610                 // on second time through, just pass exception upwards.
00611                 if(i==1)
00612                     throw;
00613 
00614                 //cout << "Caught error. Might be bad password. Trying password: " << password << endl;
00615                 args[1] = getAuthenticationKey(password);
00616             }
00617         }
00618     }
00619 
00620 }

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