Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #define LIBSMBIOS_SOURCE
00021 #include "smbios/compat.h"
00022
00023 #include <sstream>
00024 #include <string.h>
00025
00026 #include "smbios/IMemory.h"
00027 #include "SmbiosImpl.h"
00028
00029
00030 #include "smbios/message.h"
00031
00032 using namespace smbiosLowlevel;
00033 using namespace std;
00034
00035 #if defined(DEBUG_SMBIOS_STRATEGY)
00036 # define DCOUT(line) do { cout << line; } while(0)
00037 # define DCERR(line) do { cerr << line; } while(0)
00038 #else
00039 # define DCOUT(line) do {} while(0)
00040 # define DCERR(line) do {} while(0)
00041 #endif
00042
00043 namespace smbios
00044 {
00045
00046
00047 bool validateDMITableEntryPoint(
00048 const smbiosLowlevel::dmi_table_entry_point *tempTEP,
00049 bool strict,
00050 ParseExceptionImpl &parseException
00051 )
00052 {
00053
00054
00055
00056
00057 bool retval = true;
00058
00059 u8 checksum = 0;
00060 const u8 *ptr = reinterpret_cast<const u8*>(tempTEP);
00061
00062
00063 for( unsigned int i = 0; i < sizeof(*tempTEP); ++i )
00064 {
00065
00066 checksum = (checksum + ptr[i]) & 0xFF;
00067 }
00068
00069 ostringstream oss;
00070
00071 DCERR("_DMI_ anchor: " << tempTEP->anchor[0] << tempTEP->anchor[1] << tempTEP->anchor[2] << tempTEP->anchor[3] << tempTEP->anchor[4] << tempTEP->anchor[5] << endl);
00072 if(memcmp(tempTEP->anchor,"_DMI_",5)!=0)
00073 {
00074 oss << _("Intermediate anchor string does not match. anchor string: %(dmi_anchor)s") << endl;
00075 retval = false;
00076 }
00077
00078 DCERR("_DMI_ checksum: " << (int)checksum << endl);
00079 if(checksum)
00080 {
00081 oss << _("Checksum check for table entry point should be zero. checksum: %(dmi_checksum)i ") << endl;
00082 retval = false;
00083 }
00084
00085 parseException.setParameter("dmi_anchor", reinterpret_cast<const char *>(tempTEP->anchor));
00086 parseException.setParameter("dmi_checksum", static_cast<int>(checksum));
00087
00088 return retval;
00089 }
00090
00091
00092
00093
00094
00095 bool validateSmbiosTableEntryPoint(
00096 const smbiosLowlevel::smbios_table_entry_point *tempTEP,
00097 bool strict,
00098 ParseExceptionImpl &parseException
00099 )
00100 {
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121 bool retval = true;
00122
00123 u8 checksum = 0;
00124 const u8 *ptr = reinterpret_cast<const u8*>(tempTEP);
00125
00126
00127 for( unsigned int i = 0; (i < static_cast<unsigned int>(tempTEP->eps_length)) && (i < sizeof(*tempTEP)); ++i )
00128 {
00129
00130 checksum = (checksum + ptr[i]) & 0xFF;
00131 }
00132
00133 ostringstream oss;
00134 oss << _("validation of table entry point failed") << endl;
00135
00136 validateDMITableEntryPoint( &(tempTEP->dmi), strict, parseException );
00137
00138 DCERR("strict table checking: " << strict << endl);
00139
00140
00141 DCERR("_SM_ checksum: " << (int)checksum << endl);
00142
00143 if(checksum)
00144 {
00145 oss << _("Checksum check for table entry point should be zero. checksum: %(checksum)i ") << endl;
00146 retval = false;
00147 }
00148
00149 DCERR("major_ver: " << (int)tempTEP->major_ver << endl);
00150 if(tempTEP->major_ver!=0x02)
00151 {
00152 oss << _("Major version of table entry point should be 2: %(major_version)i") << endl;
00153 retval = false;
00154 }
00155
00156
00157 DCERR("eps_length: " << (int)tempTEP->eps_length << endl);
00158 if(tempTEP->eps_length < 0x0f)
00159 {
00160 oss << _("Entry Point Length field is at least 0x1f : %(eps_length)i") << endl;
00161 retval = false;
00162 }
00163
00164 parseException.setParameter("checksum", static_cast<int>(checksum));
00165 parseException.setParameter("major_version", static_cast<int>(tempTEP->major_ver));
00166 parseException.setParameter("eps_length", static_cast<int>(tempTEP->eps_length));
00167 parseException.setMessageString(oss.str());
00168
00169 return retval;
00170 }
00171
00172
00173
00174
00175
00176 bool SmbiosMemoryStrategy::getSmbiosTable(const u8 **smbiosBuffer, smbiosLowlevel::smbios_table_entry_point *table_header, bool strict)
00177 {
00178 bool ret = false;
00179 try
00180 {
00181
00182 DCERR("trying SmbiosMemoryStrategy" << endl);
00183 getSmbiosTableHeader(table_header, strict);
00184
00185
00186 getSmbiosTableBuf(smbiosBuffer, *table_header);
00187 if(smbiosBuffer)
00188 ret = true;
00189 }
00190 catch(const exception &e)
00191 {
00192 UNREFERENCED_PARAMETER(e);
00193 DCERR("got Exception: " << e.what() << endl);
00194 }
00195
00196 DCERR(" ret for SmbiosMemoryStrategy is: " << ret << endl);
00197 return ret;
00198 }
00199
00200 void SmbiosMemoryStrategy::getSmbiosTableBuf(const u8 **smbiosBuffer, smbiosLowlevel::smbios_table_entry_point table_header)
00201 {
00202 memory::IMemory *mem = memory::MemoryFactory::getFactory()->getSingleton();
00203
00204
00205 u8 *newSmbiosBuffer = new u8[table_header.dmi.table_length];
00206 try
00207 {
00208 mem->fillBuffer( newSmbiosBuffer, table_header.dmi.table_address, table_header.dmi.table_length );
00209
00210
00211 if( 0 != *smbiosBuffer )
00212 {
00213 memset (const_cast<u8 *>(*smbiosBuffer), 0, sizeof (**smbiosBuffer));
00214 delete [] const_cast<u8 *>(*smbiosBuffer);
00215 *smbiosBuffer = 0;
00216 }
00217 }
00218 catch(...)
00219 {
00220 delete [] newSmbiosBuffer;
00221 newSmbiosBuffer = 0;
00222 throw;
00223 }
00224
00225 *smbiosBuffer = reinterpret_cast<const u8 *>(newSmbiosBuffer);
00226 }
00227
00228
00229
00230 void SmbiosMemoryStrategy::getSmbiosTableHeader(smbiosLowlevel::smbios_table_entry_point *table_header, bool strict)
00231 {
00232 memory::IMemory *mem = memory::MemoryFactory::getFactory()->getSingleton();
00233
00234 unsigned long fp = E_BLOCK_START;
00235 if( offset )
00236 fp = offset;
00237
00238 ParseExceptionImpl parseException;
00239 if( offset )
00240 {
00241 DCERR("SmbiosMemoryStrategy::getSmbiosTableHeader() using hardcoded offset: " << hex << offset << endl);
00242 parseException.setMessageString(_("SMBIOS Header not found at offset: %(offsetValue)i"));
00243 parseException.setParameter("offsetValue",offset);
00244 }
00245 else
00246 {
00247 DCERR("SmbiosMemoryStrategy::getSmbiosTableHeader() Memory scan for smbios table." << endl);
00248 parseException.setMessageString(_("SMBIOS Header not found in search."));
00249 }
00250
00251
00252
00253
00254
00255
00256 mem->decReopenHint();
00257
00258 smbios_table_entry_point tempTEP;
00259 memset(&tempTEP, 0, sizeof(tempTEP));
00260 while ( (fp + sizeof(tempTEP)) < F_BLOCK_END)
00261 {
00262 mem->fillBuffer(
00263 reinterpret_cast<u8 *>(&tempTEP),
00264 fp,
00265 sizeof(tempTEP)
00266 );
00267
00268
00269
00270 if (memcmp (&tempTEP, "_DMI_", 5) == 0)
00271 {
00272 DCERR("Found _DMI_ anchor. Trying to parse legacy DMI structure." << endl);
00273 dmi_table_entry_point *dmiTEP = reinterpret_cast<dmi_table_entry_point *>(&tempTEP);
00274 memmove(&(tempTEP.dmi), &dmiTEP, sizeof(dmi_table_entry_point));
00275
00276 tempTEP.major_ver=2;
00277 tempTEP.minor_ver=0;
00278 if(validateDMITableEntryPoint(dmiTEP, strict, parseException))
00279 {
00280 DCERR("Found valid _DMI_ entry point at offset: " << fp << endl);
00281 break;
00282 }
00283 }
00284
00285
00286
00287 if (offset || (memcmp (&tempTEP, "_SM_", 4) == 0))
00288 {
00289
00290
00291
00292 DCERR("Found _SM_ anchor or using hardcoded offset. Trying to parse Smbios Entry Point." << endl);
00293 if(validateSmbiosTableEntryPoint(&tempTEP, strict, parseException))
00294 {
00295 DCERR("Found valid _SM_ entry point at offset: " << fp << endl);
00296 break;
00297 }
00298 }
00299
00300
00301
00302
00303
00304 if (offset)
00305 {
00306
00307 mem->incReopenHint();
00308 throw parseException;
00309 }
00310
00311 fp += 16;
00312 }
00313
00314
00315 mem->incReopenHint();
00316
00317
00318 if ((fp + sizeof(tempTEP)) >= F_BLOCK_END)
00319 throw parseException;
00320
00321
00322 offset = fp;
00323 memcpy( const_cast<smbios_table_entry_point *>(table_header), &tempTEP, sizeof(*table_header) );
00324 }
00325 }