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