SMBIOS Library
SmbiosWorkaround.cpp
Go to the documentation of this file.
1 /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2  * vim:expandtab:autoindent:tabstop=4:shiftwidth=4:filetype=c:cindent:textwidth=0:
3  *
4  * Copyright (C) 2005 Dell Inc.
5  * by Michael Brown <Michael_E_Brown@dell.com>
6  * Licensed under the Open Software License version 2.1
7  *
8  * Alternatively, you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published
10  * by the Free Software Foundation; either version 2 of the License,
11  * or (at your option) any later version.
12 
13  * This program is distributed in the hope that it will be useful, but
14  * WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
16  * See the GNU General Public License for more details.
17  */
18 
19 #define LIBSMBIOS_SOURCE
20 #include "smbios/compat.h"
21 
22 #include <string.h>
23 
24 #include "SmbiosWorkaroundImpl.h"
25 #include "smbios/SmbiosDefs.h"
26 #include "SmbiosImpl.h"
27 
28 #include "StdWorkarounds.h"
29 
30 // message.h should be included last.
31 #include "smbios/message.h"
32 
33 using namespace std;
34 
35 // convenience function.
36 #define _X( expr ) do{ try { expr } catch( const std::exception & ){} }while(0)
37 
38 namespace smbios
39 {
40  SmbiosWorkaroundTable *SmbiosWorkaroundFactory::_tableInstance = 0;
41 
42  factory::TFactory<smbios::SmbiosWorkaroundFactory> *SmbiosWorkaroundFactory::getFactory()
43  {
44  // reinterpret_cast<...>(0) to ensure template parameter is correct
45  // this is a workaround for VC6 which cannot use explicit member template
46  // function initialization.
48  }
49 
50  SmbiosWorkaroundFactory::~SmbiosWorkaroundFactory() throw()
51  {
52  if( _tableInstance )
53  {
54  delete _tableInstance;
55  _tableInstance = 0;
56  }
57 
58  }
59 
60  SmbiosWorkaroundTable *SmbiosWorkaroundFactory::makeNew( const ISmbiosTable *table )
61  {
62  int systemId = 0;
63 
64  _X( systemId = getU8_FromItem( *(*table)[ Dell_Revisions_and_IDs ], 0x06 ); );
65  if( 0xFE == systemId )
66  _X(systemId = getU16_FromItem(*(*table)[ Dell_Revisions_and_IDs ], 0x08 ););
67 
68  const char * chBiosVersion = 0;
69 
70  std::string biosVersion = "";
71 
72  _X( chBiosVersion = getString_FromItem(*(*table)[ BIOS_Information ], 0x05 ); );
73 
74  if ( 0 != chBiosVersion )
75  biosVersion = chBiosVersion;
76 
77  const Workaround **thisSystemWA = 0;
78  for( int i=0; i < numSystemWorkarounds; ++i )
79  {
80  if( workaroundMasterList[i].system->systemId == systemId )
81  {
82  thisSystemWA = workaroundMasterList[i].workarounds;
83  break;
84  }
85  }
86 
87  return new SmbiosWorkaroundTable( table, thisSystemWA );
88  }
89 
90  SmbiosWorkaroundTable::SmbiosWorkaroundTable( const ISmbiosTable *, const Workaround **initWorkarounds )
91  : systemId(0), biosVersion(""), workaroundsForThisSystem(initWorkarounds)
92  {}
93 
95  {}
96 
97  static bool compare( int size, const ISmbiosItem *item, int offset, datatron data )
98  {
99  bool retval = false;
100  u8 *cmpPtr = new u8[size];
101 
102  try
103  {
104  item->getData(offset, cmpPtr, size);
105  if(0 == memcmp(cmpPtr, data.data, size))
106  retval = true;
107  }
108  catch(...)
109  {
110  delete [] cmpPtr;
111  cmpPtr = 0;
112  throw;
113  }
114 
115  delete [] cmpPtr;
116  cmpPtr = 0;
117 
118  return retval;
119  }
120 
121  static void fixupData( u8 *buf, size_t size, unsigned int offset, unsigned int len, datatron data )
122  {
123  InternalErrorImpl internalError;
124  if( offset > size )
125  {
126  internalError.setMessageString(_("Data overflow. Offset requested is larger than data size. offset: %(offset)i, data size: %(size)i"));
127  internalError.setParameter("offset",offset);
128  internalError.setParameter("size",static_cast<int>(size));
129  throw internalError;
130  }
131 
132  memcpy(&(buf[offset]), data.data, len);
133  //for(unsigned int i=0; i<len; i++)
134  //buf[offset + i] = data.data[i];
135  }
136 
137  static void doFixupItem( const Workaround *wa, const ISmbiosItem *item, u8 *buf, size_t bufSize )
138  {
139  int i = 0; //loop counter. workaround MSVC++ braindamage.
140 
141  // check all of the symptoms. If any symptom does not match, bail.
142  for( i=0; 0!=wa->symptoms[i].type; ++i )
143  {
144  bool ret = compare( wa->symptoms[i].fieldDataType, item, wa->symptoms[i].fieldOffset, wa->symptoms[i].data );
145  if( ! ret )
146  goto out;
147  }
148 
149  // All symptoms present if we got here.
150  //cout << "GOT HERE!" << flush;
151 
152  // apply all of the fixups.
153  for( i=0; 0!=wa->fixups[i].type; ++i )
154  {
155  fixupData(buf, bufSize, wa->fixups[i].fieldOffset, wa->fixups[i].fieldDataType, wa->fixups[i].data );
156  }
157 
158 out:
159  return;
160  }
161 
162  void SmbiosWorkaroundTable::fixupItem( const ISmbiosItem *item, u8 *buffer, size_t bufSize ) const
163  {
164  int i = 0; //declare i up here to work around braindamaged MSVC++ for()
165  // scoping violation.
166 
167  if( 0 == workaroundsForThisSystem )
168  goto out;
169 
170  // workaroundsForThisSystem is a NULL-terminated array
171  // of Workaround pointers.
172  for( i=0; 0 != workaroundsForThisSystem[i]; ++i )
173  {
174  if( workaroundsForThisSystem[i]->symptoms->type == item->getType() )
175  {
176  //cout << "-F-" << flush;
177  doFixupItem( workaroundsForThisSystem[i], item, buffer, bufSize );
178  }
179  }
180 
181 out:
182  return;
183  }
184 
185 }