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 <iomanip>
00024
00025 #include "SmbiosImpl.h"
00026
00027 #include "smbios/message.h"
00028
00029 using namespace smbiosLowlevel;
00030 using namespace std;
00031
00032 #define NOT_IMPLEMENTED { throw NotImplementedImpl(); }
00033
00034 namespace smbios
00035 {
00036 ISmbiosItem::~ISmbiosItem()
00037 {}
00038
00039 ISmbiosItem::ISmbiosItem()
00040 {}
00041
00042
00043
00044
00045 SmbiosItem::SmbiosItem (const SmbiosItem & source)
00046 : ISmbiosItem(), header (source.header), header_size(source.header_size)
00047 {
00048
00049
00050
00051 u8 *newSmbiosItem = new u8[ header_size ];
00052 memcpy (newSmbiosItem, source.header, header_size);
00053 header = reinterpret_cast<const smbios_structure_header *>(newSmbiosItem);
00054 }
00055
00056
00057
00058
00059 SmbiosItem::SmbiosItem (const smbios_structure_header *init_header)
00060 : ISmbiosItem(), header(init_header), header_size(0)
00061 {
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072 const u8 *nextStruct = reinterpret_cast<const u8 *>(header) + header->length ;
00073
00074
00075 while (*nextStruct || nextStruct[1])
00076 nextStruct++;
00077
00078
00079 nextStruct += 2;
00080
00081
00082
00083 header_size = nextStruct - reinterpret_cast<const u8 *>(header);
00084
00085
00086
00087
00088 u8 *newSmbiosItem = new u8[header_size];
00089 memcpy (newSmbiosItem, header, header_size);
00090 header = reinterpret_cast<const smbios_structure_header *>(newSmbiosItem);
00091 }
00092
00093 SmbiosItem::~SmbiosItem ()
00094 {
00095
00096 delete [] const_cast<u8 *>(reinterpret_cast<const u8 *>(header));
00097 header = 0;
00098 }
00099
00100
00101
00102
00103 static u32 force_u64_to_u32(u64 orig)
00104 {
00105
00106
00107 u32 *temp32 = reinterpret_cast<u32 *>(&orig);
00108 return *temp32;
00109 }
00110
00111
00112
00113
00114
00115
00116 const char *SmbiosItem::getStringByStringNumber (u8 which) const
00117 {
00118 const char *string_pointer = reinterpret_cast<const char *>(header);
00119
00120
00121
00122
00123
00124 if (!which)
00125 {
00126 throw StringUnavailableImpl(_("String does not exist."));
00127 }
00128
00129
00130
00131 if (!header)
00132 {
00133 InternalErrorImpl internalError;
00134 internalError.setMessageString(_("Not a valid header. header is zero."));
00135 throw internalError;
00136 }
00137
00138
00139
00140 string_pointer += header->length;
00141
00142 for (; which > 1; which--)
00143 {
00144 string_pointer += strlen (string_pointer);
00145 string_pointer++;
00146
00147
00148
00149
00150 const u8 *cur_loc = reinterpret_cast<const u8 *>(string_pointer);
00151 const u8 *base_loc = reinterpret_cast<const u8 *>(header);
00152 if( cur_loc >= base_loc + header_size)
00153 {
00154 ParseExceptionImpl parseException;
00155 parseException.setMessageString(_("Overflow while getting byte data at location: cur_loc >= base_loc + header_size\n cur_loc : %(cur_loc)i\n base_loc : %(base_loc)i\n header_size : %(header_size)i "));
00156 parseException.setParameter("cur_loc", force_u64_to_u32(reinterpret_cast<u64>(cur_loc)));
00157 parseException.setParameter("base_loc", force_u64_to_u32(reinterpret_cast<u64>(base_loc)));
00158 parseException.setParameter("header_size",static_cast<u32>(header_size));
00159 throw parseException;
00160 }
00161
00162
00163
00164
00165 if( ! *string_pointer )
00166 {
00167 throw StringUnavailableImpl(_("The string does not exist. Bad index caused this error"));
00168 }
00169 }
00170
00171 return string_pointer;
00172 }
00173
00174 const char *SmbiosItem::getString(unsigned int header_offset) const
00175 {
00176 DataOutOfBoundsImpl dataOutOfBounds;
00177
00178 if( header_offset >= getLength() )
00179 {
00180 dataOutOfBounds.setMessageString(_("Attempt to access string outside the length of header. offset : %(header_offset)i, header_length : %(header_length)i"));
00181 dataOutOfBounds.setParameter("header_offset",static_cast<int>(header_offset));
00182 dataOutOfBounds.setParameter("header_length",static_cast<int>(getLength()));
00183 throw dataOutOfBounds;
00184 }
00185
00186
00187 if (!header)
00188 {
00189 InternalErrorImpl().setMessageString(_("Not a valid header. header is zero."));
00190 throw InternalErrorImpl();
00191 }
00192
00193 return getStringByStringNumber ( (reinterpret_cast<const u8 *>(header))[header_offset]);
00194 }
00195
00196 std::auto_ptr<const ISmbiosItem> SmbiosItem::clone() const
00197 {
00198 return auto_ptr<const ISmbiosItem>(new SmbiosItem (*this));
00199 }
00200
00201 std::auto_ptr<ISmbiosItem> SmbiosItem::clone()
00202 {
00203 return auto_ptr<ISmbiosItem>(new SmbiosItem (*this));
00204 }
00205
00206 u8 SmbiosItem::getType () const
00207 {
00208 return header->type;
00209 }
00210
00211 u8 SmbiosItem::getLength () const
00212 {
00213 return header->length;
00214 }
00215
00216 u16 SmbiosItem::getHandle () const
00217 {
00218 return header->handle;
00219 }
00220
00221
00222
00223 u8 SmbiosItem::getU8 ( const std::string ) const NOT_IMPLEMENTED;
00224 u16 SmbiosItem::getU16( const std::string ) const NOT_IMPLEMENTED;
00225 u32 SmbiosItem::getU32( const std::string ) const NOT_IMPLEMENTED;
00226 u64 SmbiosItem::getU64( const std::string ) const NOT_IMPLEMENTED;
00227 const char *SmbiosItem::getString(const std::string ) const NOT_IMPLEMENTED;
00228 u32 SmbiosItem::getBitfield( const std::string, const std::string ) const NOT_IMPLEMENTED;
00229
00230 void checkItemBounds( size_t total_size, size_t length, size_t offset, size_t size)
00231 {
00232 DataOutOfBoundsImpl dataOutOfBounds;
00233 dataOutOfBounds.setParameter("offset",static_cast<int>(offset));
00234 dataOutOfBounds.setParameter("header_length",static_cast<int>(total_size));
00235
00236
00237 if( offset > length )
00238 {
00239 dataOutOfBounds.setMessageString(_("Attempt to access data outside the length of header. offset : %(offset)i, header_length : %(header_length)i"));
00240 throw dataOutOfBounds;
00241 }
00242
00243 if( offset + size < offset )
00244 {
00245 dataOutOfBounds.setMessageString(_("Attempt to access data outside the length of header. offset : %(offset)i, header_length : %(header_length)i"));
00246 throw dataOutOfBounds;
00247 }
00248
00249 if( offset + size > length )
00250 {
00251 dataOutOfBounds.setMessageString(_("Attempt to access data outside the length of header. offset : %(offset)i, header_length : %(header_length)i"));
00252 throw dataOutOfBounds;
00253 }
00254
00255 if( offset >= total_size )
00256
00257
00258
00259
00260 {
00261 dataOutOfBounds.setMessageString(_("Attempt to access data outside header buffer. Impossible situation! offset : %(offset)i, header_length : %(header_length)i"));
00262 throw dataOutOfBounds;
00263 }
00264
00265 }
00266
00267 void getData(const ISmbiosItem &item, u8 *data, unsigned int offset, unsigned int size)
00268 {
00269 for (unsigned int i=0; i< size; i++)
00270 {
00271 data[i] = item.getU8(offset +i);
00272 }
00273 }
00274
00275 u8 SmbiosItem::getU8 ( unsigned int offset ) const
00276 {
00277 checkItemBounds( header_size, header->length, offset, 1U );
00278 u8 byte1 = static_cast<u8>(reinterpret_cast<const u8 *>(header)[ offset + 0 ]);
00279 return byte1;
00280 }
00281
00282 u16 SmbiosItem::getU16 ( unsigned int offset ) const
00283 {
00284 u16 retval = 0;
00285 checkItemBounds(header_size, header->length, offset, sizeof(retval));
00286 getData(*this, reinterpret_cast<u8 *>(&retval), offset, sizeof(retval));
00287 return retval;
00288 }
00289
00290
00291 u32 SmbiosItem::getU32 ( unsigned int offset ) const
00292 {
00293 u32 retval = 0;
00294 checkItemBounds(header_size, header->length, offset, sizeof(retval));
00295 getData(*this, reinterpret_cast<u8 *>(&retval), offset, sizeof(retval));
00296 return retval;
00297 }
00298
00299 u64 SmbiosItem::getU64 ( unsigned int offset ) const
00300 {
00301 u64 retval = 0;
00302 checkItemBounds(header_size, header->length, offset, sizeof(retval));
00303 getData(*this, reinterpret_cast<u8 *>(&retval), offset, sizeof(retval));
00304 return retval;
00305 }
00306
00307 void checkBitfieldBounds( unsigned int bound, unsigned int lsb, unsigned int msb, DataOutOfBoundsImpl &doob )
00308 {
00309 if(lsb > bound || msb > bound)
00310 {
00311 doob.setMessageString(_("The total length of bit field is out of bounds. The largest accessible bit is %(bound)i. lsb: %(lsb)i , msb: %(msb)i"));
00312 doob.setParameter( "bound", bound );
00313 throw doob;
00314 }
00315 }
00316
00317
00318 u32 SmbiosItem::getBitfield ( unsigned int offset, unsigned int fieldLen, unsigned int lsb, unsigned int msb ) const
00319 {
00320 u64 bitfield = 0;
00321 DataOutOfBoundsImpl dataOutOfBounds;
00322
00323 dataOutOfBounds.setParameter("lsb",lsb);
00324 dataOutOfBounds.setParameter("msb",msb);
00325 dataOutOfBounds.setParameter("offset",static_cast<int>(offset));
00326 dataOutOfBounds.setParameter("header_length",static_cast<int>(header->length));
00327
00328 checkItemBounds( header_size, header->length, offset, fieldLen );
00329
00330
00331 if(msb <= lsb)
00332 {
00333 msb=lsb;
00334 }
00335
00336
00337 u64 bitlen = (msb-lsb) + 1;
00338 u64 mask = 0;
00339 for(u64 i=0;i<bitlen;i++)
00340 {
00341 mask = (mask << 1);
00342 mask |= 1;
00343 }
00344
00345 switch(fieldLen)
00346 {
00347 case FIELD_LEN_BYTE:
00348 checkBitfieldBounds( 7, lsb, msb, dataOutOfBounds);
00349 bitfield = getU8(offset);
00350 break;
00351 case FIELD_LEN_WORD:
00352 checkBitfieldBounds( 15, lsb, msb, dataOutOfBounds);
00353 bitfield = getU16(offset);
00354 break;
00355 case FIELD_LEN_DWORD:
00356 checkBitfieldBounds( 31, lsb, msb, dataOutOfBounds);
00357 bitfield = getU32(offset);
00358 break;
00359 case FIELD_LEN_QWORD:
00360 checkBitfieldBounds( 63, lsb, msb, dataOutOfBounds);
00361 bitfield = getU64(offset);
00362 break;
00363 default:
00364 dataOutOfBounds.setMessageString(_("Unsupported field length"));
00365 throw dataOutOfBounds;
00366 }
00367
00368 return static_cast<u32>((bitfield >> lsb) & mask);
00369 }
00370
00371 const u8 *SmbiosItem::getBufferCopy(size_t &size) const
00372 {
00373 size = header_size;
00374
00375 const u8 *newBuffer = new u8[ size ];
00376 memcpy (const_cast<u8 *>(newBuffer), header, size);
00377 return newBuffer;
00378 }
00379
00380 const size_t SmbiosItem::getBufferSize() const
00381 {
00382 return header_size;
00383 }
00384
00385 void SmbiosItem::fixup( const SmbiosWorkaroundTable *workaround ) const
00386 {
00387 u8 *buffer = const_cast<u8 *>(reinterpret_cast<const u8 *>(header));
00388 workaround->fixupItem( this, buffer, header_size );
00389 }
00390
00391 ostream & operator << (ostream & cout, const ISmbiosItem & item)
00392 {
00393 return item.streamify (cout);
00394 }
00395
00396 ostream & SmbiosItem::streamify (ostream & cout) const
00397 {
00398 if (header == 0)
00399 cout << "operator << on an uninitialized SmbiosItem!";
00400 else
00401 {
00402 std::ios::fmtflags old_opts = cout.flags ();
00403 cout << "Handle 0x" << hex << setfill ('0') <<
00404 setw (4) << getHandle () << endl;
00405 cout << "\tDMI type 0x" << static_cast<int>(getType()) << dec <<
00406 ", " << static_cast<int>(getLength()) << " bytes." <<
00407 endl;
00408 cout.flags (old_opts);
00409 }
00410 return cout;
00411 }
00412 }