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