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

SmbiosStrategy.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 <sstream>
00024 
00025 #include "smbios/IMemory.h"
00026 #include "SmbiosImpl.h"
00027 
00028 // message.h should be included last.
00029 #include "smbios/message.h"
00030 
00031 using namespace smbiosLowlevel;
00032 using namespace std;
00033 
00034 #if defined(DEBUG_SMBIOS_STRATEGY)
00035 #   define DCOUT(line) do { cout << line; } while(0)
00036 #   define DCERR(line) do { cerr << line; } while(0)
00037 #else
00038 #   define DCOUT(line) do {} while(0)
00039 #   define DCERR(line) do {} while(0)
00040 #endif
00041 
00042 namespace smbios
00043 {
00044     // validate the smbios table entry point
00045     bool validateTableEntryPoint(
00046         const smbiosLowlevel::smbios_table_entry_point *tempTEP,
00047         bool strict,
00048         ParseExceptionImpl &parseException
00049         )
00050     {
00051         // This code checks for the following:
00052         //       entry point structure checksum : As per the specs
00053         //       smbios major version : As per the specs
00054         //       Intermediate anchor string : As per the specs
00055         //
00056         // This code does not check the following:
00057         //      intermediate checksum: the main checksum covers the
00058         //      entire area
00059         //          and should be sufficient, plus there is a
00060         //          possibility for
00061         //          BIOS bugs in this area.
00062         //
00063         //      minor version: according to the spec, this parser should
00064         //      work
00065         //          with any change in minor version. The spec says this
00066         //          parser
00067         //          will break if major version changes, so we check
00068         //          that.
00069         //
00070 
00071         bool retval = true;
00072 
00073         u8 checksum = 0;
00074         const u8 *ptr = reinterpret_cast<const u8*>(tempTEP);
00075         // don't overrun tempTEP if BIOS is buggy... (note sizeof() test here)
00076         //      added especially to deal with buggy Intel BIOS.
00077         for( unsigned int i = 0; (i < static_cast<unsigned int>(tempTEP->eps_length)) && (i < sizeof(*tempTEP)); ++i )
00078         {
00079             // stupid stuff to avoid MVC++ .NET runtime exception check for cast to different size
00080             checksum = (checksum + ptr[i]) & 0xFF;
00081         }
00082 
00083         ostringstream oss;
00084         oss << _("validation of table entry point failed") << endl;
00085 
00086         if(memcmp(tempTEP->dmi_anchor,"_DMI_",5)!=0) // Checking intermediate anchor string
00087         {
00088             oss << _("Intermediate anchor string does not match. anchor string: %(dmi_anchor)s") << endl;
00089             retval = false;  // validation failed
00090         }
00091         if(checksum!=0x00) // Checking entry point structure checksum
00092         {
00093             oss << _("Checksum check for table entry point should be zero. checksum: %(checksum)i ") << endl;
00094             retval = false;  // validation failed
00095         }
00096         if(tempTEP->major_ver!=0x02)     // Checking smbios major version
00097         {
00098             oss << _("Major version of table entry point should be 2: %(major_version)i") << endl;
00099             retval = false;  // validation failed
00100         }
00101         // Entry Point Length field is at least 0x1f.
00102         if(tempTEP->eps_length < 0x0f)
00103         {
00104             oss << _("Entry Point Length field is at least 0x1f : %(eps_length)i") << endl;
00105             retval = false;  // validation failed
00106         }
00107 
00108         parseException.setParameter("dmi_anchor", reinterpret_cast<const char *>(tempTEP->dmi_anchor));
00109         parseException.setParameter("checksum", static_cast<int>(checksum));
00110         parseException.setParameter("major_version", static_cast<int>(tempTEP->major_ver));
00111         parseException.setParameter("eps_length", static_cast<int>(tempTEP->eps_length));
00112         parseException.setMessageString(oss.str());
00113 
00114         return strict ? retval : 1;
00115     }
00116 
00117 
00118 
00119 
00120 
00121     bool SmbiosMemoryStrategy::getSmbiosTable(const u8 **smbiosBuffer, smbiosLowlevel::smbios_table_entry_point *table_header, bool strict)
00122     {
00123         bool ret = false;
00124         try
00125         {
00126             // allocates no mem
00127             DCERR("trying SmbiosMemoryStrategy" << endl);
00128             getSmbiosTableHeader(table_header, strict);
00129 
00130             // allocates mem, but frees on exception
00131             getSmbiosTableBuf(smbiosBuffer, *table_header);
00132             if(smbiosBuffer)
00133                     ret = true;
00134         }
00135         catch(const exception &e)
00136         {
00137             UNREFERENCED_PARAMETER(e); // avoid unused var warning when !DEBUG
00138             DCERR("got Exception: " << e.what() << endl);
00139         }
00140 
00141         DCERR("  ret for SmbiosMemoryStrategy is: " << ret << endl);
00142         return ret;
00143     }
00144 
00145     void SmbiosMemoryStrategy::getSmbiosTableBuf(const u8 **smbiosBuffer, smbiosLowlevel::smbios_table_entry_point table_header)
00146     {
00147         memory::IMemory *mem = memory::MemoryFactory::getFactory()->getSingleton();
00148 
00149         // new throws exception, no need to test.
00150         u8 *newSmbiosBuffer = new u8[table_header.table_length];
00151         try
00152         {
00153             mem->fillBuffer( newSmbiosBuffer, table_header.table_address, table_header.table_length );
00154 
00155             //delete old one, if necessary
00156             if( 0 != *smbiosBuffer )
00157             {
00158                 memset (const_cast<u8 *>(*smbiosBuffer), 0, sizeof (**smbiosBuffer));
00159                 delete [] const_cast<u8 *>(*smbiosBuffer);
00160                 *smbiosBuffer = 0;
00161             }
00162         }
00163         catch(...)
00164         {
00165             delete [] newSmbiosBuffer;
00166             newSmbiosBuffer = 0;
00167             throw;
00168         }
00169 
00170         *smbiosBuffer = reinterpret_cast<const u8 *>(newSmbiosBuffer);
00171     }
00172 
00173     // allocates no memory, constructs no objects.
00174     // can raise an exception
00175     void SmbiosMemoryStrategy::getSmbiosTableHeader(smbiosLowlevel::smbios_table_entry_point *table_header, bool strict)
00176     {
00177         memory::IMemory *mem = memory::MemoryFactory::getFactory()->getSingleton();
00178 
00179         unsigned long fp = E_BLOCK_START;
00180         if( offset )
00181             fp = offset;
00182 
00183         ParseExceptionImpl parseException;
00184         if( offset )
00185         {
00186             DCERR("SmbiosMemoryStrategy::getSmbiosTableHeader() using hardcoded offset: " << hex << offset << endl);
00187             parseException.setMessageString(_("SMBIOS Header not found at offset: %(offsetValue)i"));
00188             parseException.setParameter("offsetValue",offset);
00189         }
00190         else
00191         {
00192             DCERR("SmbiosMemoryStrategy::getSmbiosTableHeader() Memory scan for smbios table." << endl);
00193             parseException.setMessageString(_("SMBIOS Header not found in search."));
00194         }
00195 
00196         smbios_table_entry_point tempTEP;
00197         memset(&tempTEP, 0, sizeof(tempTEP));
00198         while ( (fp + sizeof(tempTEP)) < F_BLOCK_END)
00199         {
00200             mem->fillBuffer(
00201                 reinterpret_cast<u8 *>(&tempTEP),
00202                 fp,
00203                 sizeof(tempTEP)
00204             );
00205 
00206             // search for promising looking headers
00207             if (memcmp (&tempTEP, "_SM_", 4) == 0)
00208             {
00209                 if(validateTableEntryPoint(&tempTEP, strict, parseException))
00210                 {
00211                     break;
00212                 }
00213             }
00214 
00215             // previous if() would have broken out if we have a valid
00216             // table header. if offset is set, then we are not supposed
00217             // to be scanning through memory. We didn't find a table,
00218             // so there is nothing to do but raise an exception.
00219             if (offset)
00220                 throw parseException; // previously set up.
00221 
00222             fp += 16;
00223         }
00224 
00225         // bad stuff happened if we got to here and fp > 0xFFFFFL
00226         if ((fp + sizeof(tempTEP)) >= F_BLOCK_END)
00227             throw parseException; // previously set up.
00228 
00229         // found it. set offset for future reference (no need to search.)
00230         offset = fp;
00231         memcpy( const_cast<smbios_table_entry_point *>(table_header), &tempTEP, sizeof(*table_header) );
00232     }
00233 }

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