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