SMBIOS Library
System.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 "smbios/ISmbios.h"
25 #include "smbios/IToken.h"
26 #include "smbios/ISmi.h"
27 
28 #include "smbios/SystemInfo.h"
29 #include "smbios/IMemory.h"
30 #include "smbios/SmbiosDefs.h"
31 #include "ExceptionImpl.h"
32 #include "TokenLowLevel.h"
33 
34 #include "DellMagic.h"
35 
36 #include "smbios/version.h"
37 
38 // this always should be included last
39 #include "smbios/message.h"
40 
41 using namespace smbios;
42 using namespace cmos;
43 using namespace std;
44 
45 #if defined(DEBUG_SYSINFO)
46 # define DCOUT(line) do { cout << line; } while(0)
47 # define DCERR(line) do { cerr << line; } while(0)
48 #else
49 # define DCOUT(line) do {} while(0)
50 # define DCERR(line) do {} while(0)
51 #endif
52 
53 
55 
56 // so we don't have to change API, add new tryBiosPassword() function
57 // that sets this password. This password will silently be used by
58 // functions that need a password
59 static std::string biosPassword = "";
60 
61 static void stripString( char *str )
62 {
63  if(!str)
64  return;
65 
66  if(strlen(str) == 0)
67  return;
68 
69  size_t ch = strlen(str);
70  do
71  {
72  --ch;
73  if( ' ' == str[ch] )
74  str[ch] = '\0';
75  else
76  break;
77 
78  } while(ch);
79 }
80 
81 /***********************************************
82  * specialty functions to decode dell service tag
83  *
84  * note: funny naming for the following functions
85  * as they were copied from another project
86  **********************************************/
87 static unsigned char dell_decode_digit( char tagval )
88 {
89  // input == value from 0 - 0x1E
90  // output == ascii
91  // --> take value from range 0 - 0x1E and give ascii value
92  if( tagval > 0x19 )
93  tagval += 0x3C; /* V-Z, 0x1A-0x1E */
94  else if( tagval > 0x14 )
95  tagval += 0x3B; /* P-T, 0x15-0x19 */
96  else if( tagval > 0x0F )
97  tagval += 0x3A; /* J-N, 0x10-0x14 */
98  else if( tagval > 0x0C )
99  tagval += 0x39; /* F-H, 0x0D-0x0F */
100  else if( tagval > 0x09 )
101  tagval += 0x38; /* B-D, 0x0A-0x0C */
102  else
103  tagval += 0x30; /* 0-9, 0x00-0x09 */
104 
105  return tagval;
106 }
107 
108 // decodes tag in-place
109 static void dell_decode_service_tag( char *tag, int len )
110 {
111  // see encoding function for nice ascii art representation.
112  //
113  if( ((tag)[0] & (1<<7)) == (1<<7) )
114  {
115  char new_tag[SVC_TAG_LEN_MAX + 1] = {0,};
116 
117  // yuck.
118  new_tag[6] = dell_decode_digit( (tag[4] & 0x1F) );
119  new_tag[5] = dell_decode_digit( ((tag[3] & 0x03)<<3) | ((tag[4]>>5) & 0x07) );
120  new_tag[4] = dell_decode_digit( ((tag[3] & 0x7C)>>2) );
121  new_tag[3] = dell_decode_digit( (((tag[2] & 0x0F)<<1) | ((tag[3]>>7) & 0x01)) );
122  new_tag[2] = dell_decode_digit( (((tag[1] & 0x01)<<4) | ((tag[2]>>4) & 0xF)) & 0x1F);
123  new_tag[1] = dell_decode_digit( ((tag[1] & 0x3E)>>1) & 0x1F );
124  new_tag[0] = (tag[0] ^ (1<<7));
125 
126  memset(tag, 0, len);
127  strncpy(tag, new_tag, len < SVC_TAG_LEN_MAX ? len : SVC_TAG_LEN_MAX);
128  }
129 }
130 
131 static unsigned char dell_encode_digit( char ch )
132 {
133  // input == ascii
134  // output == value from 0 - 0x1E
135  // scale ascii value down to range 0-0x1E
136  // valid input ascii == Alphanumeric - vowels
137  // invalid input is converted to the char '0' (zero)
138  int uc = toupper(ch);
139  int retval = 0;
140  if ( uc >= '0' && uc <= '9' )
141  retval = uc - 0x30;
142  if ( uc >= 'B' && uc <= 'D' )
143  retval = uc - 0x38;
144  if ( uc >= 'F' && uc <= 'H' )
145  retval = uc - 0x39;
146  if ( uc >= 'J' && uc <= 'N' )
147  retval = uc - 0x3A;
148  if ( uc >= 'P' && uc <= 'T' )
149  retval = uc - 0x3B;
150  if ( uc >= 'V' && uc <= 'Z' )
151  retval = uc - 0x3C;
152  return static_cast<unsigned char>(retval);
153 }
154 
155 static void dell_encode_service_tag( char *tag, size_t len )
156 {
157  if (len <= SVC_TAG_CMOS_LEN_MAX)
158  return;
159 
160  // codes a 7-char value into 5 bytes
161  //
162  // byte byte byte byte byte
163  // 0 1 2 3 4
164  //|----|----| |----|----| |----|----| |----|----| |----|----|
165  // 1 0 0000 11 1112 2222 3333 3444 4455 5556 6666
166  // char0 char1 char2 char3 char4 char5 char6
167  //
168  // note: high bit set in byte0 to indicate coded tag.
169 
170  char tagToSet[SVC_TAG_LEN_MAX] = {0,};
171  memcpy(tagToSet, tag, len < SVC_TAG_LEN_MAX ? len : SVC_TAG_LEN_MAX );
172 
173  char newTagBuf[SVC_TAG_CMOS_LEN_MAX] = {0,};
174 
175  // char 0
176  newTagBuf[0] = tagToSet[0] | 1<<7;
177 
178  // char 1
179  newTagBuf[1] = dell_encode_digit(tagToSet[1]) << 1;
180 
181  // char 2
182  newTagBuf[1] = newTagBuf[1] | dell_encode_digit(tagToSet[2]) >> 4;
183  newTagBuf[2] = dell_encode_digit(tagToSet[2]) << 4;
184 
185  // char 3
186  newTagBuf[2] = newTagBuf[2] | dell_encode_digit(tagToSet[3]) >> 1;
187  newTagBuf[3] = dell_encode_digit(tagToSet[3]) << 7;
188 
189  // char 4
190  newTagBuf[3] = newTagBuf[3] | dell_encode_digit(tagToSet[4]) << 2;
191 
192  // char 5
193  newTagBuf[3] = newTagBuf[3] | dell_encode_digit(tagToSet[5]) >> 3;
194  newTagBuf[4] = dell_encode_digit(tagToSet[5]) << 5;
195 
196  // char 6
197  newTagBuf[4] = newTagBuf[4] | dell_encode_digit(tagToSet[6]);
198 
199  memset(tag, 0, len);
200  memcpy(tag, newTagBuf, len < SVC_TAG_CMOS_LEN_MAX ? len: SVC_TAG_CMOS_LEN_MAX);
201  return;
202 }
203 
204 
206 {
207  // LIBSMBIOS_RELEASE_VERSION is a macro defined by the build system
209 }
210 
211 void SMBIOSFreeMemory( const char *ptr )
212 {
213  delete [] const_cast<char *>(ptr);
214 }
215 
216 /* only for service/asset tags. */
217 static char *getTagFromSMI(u16 select)
218 {
219  u32 args[4] = {0,}, res[4] = {0,};
220  smi::doSimpleCallingInterfaceSmi(11, select, args, res);
221 
222  char *retval = new char[16];
223  memset(retval, '\0', 16);
224 
225  memcpy(retval, reinterpret_cast<u8 *>(&(res[1])), sizeof(res));
226 
227  for(size_t i=0; i<strlen(retval); i++)
228  if( static_cast<unsigned char>(retval[i]) == 0xFF ) retval[i] = '\0';
229 
230  return retval;
231 }
232 
233 /* only for service/asset tags. */
234 static void setTagUsingSMI(const char *newTag, u16 select)
235 {
236  u32 args[4] = {0,}, res[4] = {0,};
237  strncpy(reinterpret_cast<char *>(args), newTag, 12);
239  smi::doSimpleCallingInterfaceSmi(11, select, args, res);
240 }
241 
242 static char *getStringFromTable(unsigned int structure, unsigned int stringNumber)
243 {
244  const smbios::ISmbiosTable *table = 0;
246 
247  if (!table)
248  throw InternalErrorImpl();
249 
250  const char *tempval = 0;
251  tempval = getString_FromItem(*(*table)[structure], stringNumber);
252 
253  if(!tempval)
254  throw exception();
255 
256  size_t slen = strlen(tempval);
257  char *retval = new char[slen + 1];
258  strncpy(retval,tempval,slen);
259  retval[slen] = '\0';
260 
261  stripString(retval);
262  if ( ! strlen(retval ))
263  {
264  delete [] retval;
265  retval = 0;
266  throw exception(); // skip this one because returned string was all spaces.
267  }
268 
269  return retval;
270 }
271 
273 {
274  DCOUT( "in getServiceTagFromSysInfo()" << endl);
276 }
277 
279 {
280  DCOUT( "in getServiceTagFromSysEncl()" << endl);
282 }
283 
284 // not static so that unit tests can peek here. Not part of public API, though.
286 {
287  smbios::ITokenTable *table = 0;
289 
290  DCOUT( "in getServiceTagFromCMOSToken()" << endl);
291 
292  if (0 == table)
293  {
294  throw InternalErrorImpl();
295  }
296 
297  char *tempval = 0;
298  try
299  {
300  // Step 1: Get tag from CMOS
301  tempval = new char[SVC_TAG_LEN_MAX + 1];
302  memset(tempval, '\0', SVC_TAG_LEN_MAX + 1);
303  // will throw an exception if not found.
304  (*table)[Cmos_Service_Token]->getString(reinterpret_cast<u8*>(tempval), SVC_TAG_CMOS_LEN_MAX + 1);
305 
306  // Step 2: Decode 7-char tag from 5-char CMOS value
308 
309  // Step 3: Make sure checksum is good before returning value
310  u16 indexPort, dataPort;
311  u8 location;
312 
313  smbios::IToken *token = &(*((*table)[ Cmos_Service_Token ]));
314  dynamic_cast< smbios::ICmosToken * >(token)->getCMOSDetails( &indexPort, &dataPort, &location );
315 
316  u8 csum = 0;
318 
319  for( u32 i = 0; i < SVC_TAG_CMOS_LEN_MAX; i++)
320  {
321  // stupid stuff to avoid MVC++ .NET runtime exception check for cast to different size
322  csum = (csum + cmos->readByte( indexPort, dataPort, location + i )) & 0xFF;
323  }
324 
325  // stupid stuff to avoid MVC++ .NET runtime exception check for cast to different size
326  csum = (csum - cmos->readByte( indexPort, dataPort, location + SVC_TAG_CMOS_LEN_MAX )) & 0xFF;
327  if( csum ) // bad (should be zero)
328  throw "Bad checksum";
329  }
330  catch( ... )
331  {
332  delete [] tempval;
333  throw;
334  }
335 
336  return tempval;
337 }
338 
339 // not static so that unit tests can peek here. Not part of public API, though.
341 {
342  DCOUT( "in getServiceTagFromSMI()" << endl);
343  return getTagFromSMI( 2 ); /* Read service tag select code */
344 }
345 
346 // Code for getting the service tag from one of many locations
348 {
349  char *(*f_ptr)();
350 }
351 
352 /* try dynamic functions first to make sure we get current data. */
354  {&getServiceTagFromSMI,}, // SMI Token
355  {&getServiceTagFromCMOSToken,}, // CMOS Token
356  {&getServiceTagFromSysInfo,}, // SMBIOS System Information Item
357  {&getServiceTagFromSysEncl,}, // SMBIOS System Enclosure Item
358  };
359 
360 const char *SMBIOSGetServiceTag()
361 {
362  char *serviceTag = 0;
363  int numEntries =
365 
366  DCOUT( "numEntries: " << numEntries << endl);
367 
368  for (int i = 0; (i < numEntries) && (!serviceTag); ++i)
369  {
370  // eat exceptions from lowlevel functions and keep going.
371  try
372  {
373  DCOUT(" try #" << i << endl);
374  // first function to return non-zero id wins.
375  serviceTag = DellGetServiceTagFunctions[i].f_ptr ();
376  }
377  catch(const exception &e)
378  {
379  DCOUT(" Caught exception: " << e.what() << endl);
380  SysInfoException.setMessageString(e.what());
381  }
382  catch(...)
383  {
384  DCOUT(" Caught unknown exception" << endl);
385  SysInfoException.setMessageString( _("Unknown internal error occurred") );
386  }
387 
388  if(serviceTag)
389  DCOUT( " GOT TAG: -->" << serviceTag << "<--" << endl);
390  }
391  stripString(serviceTag);
392  return serviceTag;
393 }
394 
395 void setServiceTagUsingCMOSToken(const char *newTag, size_t len)
396 {
397  smbios::ITokenTable *table = 0;
399 
400  if (0 == table)
401  {
402  throw InternalErrorImpl();
403  }
404 
405  try
406  {
407  // don't want to modify user-supplied buffer, so copy new tag
408  // to our own buffer.
409  char codedTag[SVC_TAG_LEN_MAX + 1] = {0,}; // null padded
410  // copy (possibly oversize) user input to our buffer.
411  strncpy(codedTag, newTag, len < SVC_TAG_LEN_MAX ? len : SVC_TAG_LEN_MAX);
412  // encode in place, if necessary
413  dell_encode_service_tag(codedTag, len);
414  // will throw an exception if not found.
415 
416  // Step 1: set string: safe to use whole codedTag as it is guaranteed zero-padded
417  (*table)[Cmos_Service_Token]->setString(reinterpret_cast<const u8*>(codedTag), SVC_TAG_CMOS_LEN_MAX);
418 
419  // Step 2: reset checksum
420  u16 indexPort, dataPort;
421  u8 location;
422 
423  smbios::IToken *token = &(*((*table)[ Cmos_Service_Token ]));
424  dynamic_cast< smbios::ICmosToken * >(token)->getCMOSDetails( &indexPort, &dataPort, &location );
425 
426  u8 csum = 0;
428 
429  for( u32 i = 0; i < SVC_TAG_CMOS_LEN_MAX; i++)
430  {
431  // stupid stuff to avoid MVC++ .NET runtime exception check for cast to different size
432  csum = (csum + cmos->readByte( indexPort, dataPort, location + i )) & 0xFF;
433  }
434 
435  cmos->writeByte(
436  indexPort,
437  dataPort,
438  location + SVC_TAG_CMOS_LEN_MAX,
439  csum
440  );
441  }
442  catch( const smbios::IException & )
443  {
444  throw;
445  }
446 
447 }
448 
449 // Important note from the docs:
450 /* Only the manufacturing software that’s loading the service tag into the system should use this interface.
451  Some systems may return an error when the service tag has already been set (i.e. they prevent this function from changing the service tag once it has been set).
452  */
453 void setServiceTagUsingSMI(const char *newTag, size_t size)
454 {
455  (void) size; // avoid unused var warning.
456  setTagUsingSMI( newTag, 3 ); /* Write service tag select code */
457 }
458 
459 // Code for getting the service tag from one of many locations
461 {
462  void (*f_ptr)(const char *, size_t);
463 }
464 
466  {&setServiceTagUsingSMI,}, // SMBIOS System Information Item
467  {&setServiceTagUsingCMOSToken,}, // SMBIOS System Information Item
468  };
469 
470 int SMBIOSSetServiceTag(const char *password, const char *serviceTag, size_t len)
471 {
472  int retval = -1;
473  int numEntries =
475 
476  if(password)
477  biosPassword = password;
478 
479  for (int i = 0; (i < numEntries); ++i)
480  {
481  // eat exceptions from lowlevel functions and keep going.
482  try
483  {
484  // first function to return non-zero id wins.
485  DellSetServiceTagFunctions[i].f_ptr (serviceTag, len);
486  retval = 0;
487  }
488  catch(const smbios::IException &e)
489  {
490  SysInfoException.setMessageString(e.what());
491  }
492  catch(...)
493  {
494  SysInfoException.setMessageString( _("Unknown internal error occurred") );
495  }
496  }
497  return retval;
498 }
499 
501 {
503 }
504 
505 // not static so we can use it in unit test, but not part of public API.
506 // you have been warned.
508 {
509  smbios::ITokenTable *table = 0;
511 
512  if (0 == table)
513  {
514  throw InternalErrorImpl();
515  }
516 
517  u8 *tempval = 0;
518  try
519  {
520  tempval = new u8[ASSET_TAG_LEN_MAX + 1];
521  memset(tempval, '\0', ASSET_TAG_LEN_MAX + 1);
522  (*table)[Cmos_Asset_Token]->getString(tempval, ASSET_TAG_LEN_MAX + 1);
523 
524  // Step 3: Make sure checksum is good before returning value
525  u16 indexPort, dataPort;
526  u8 location;
527 
528  smbios::IToken *token = &(*((*table)[ Cmos_Asset_Token ]));
529  dynamic_cast< smbios::ICmosToken * >(token)->getCMOSDetails( &indexPort, &dataPort, &location );
530 
531  u8 csum = 0;
533 
534  for( u32 i = 0; i < ASSET_TAG_CMOS_LEN_MAX; i++)
535  {
536  // stupid stuff to avoid MVC++ .NET runtime exception check for cast to different size
537  csum = (csum + cmos->readByte( indexPort, dataPort, location + i )) & 0xFF;
538  }
539 
540  // stupid stuff to avoid MVC++ .NET runtime exception check for cast to different size
541  csum = (csum - cmos->readByte( indexPort, dataPort, location + ASSET_TAG_CMOS_LEN_MAX )) & 0xFF;
542  if( csum ) // bad (should be zero)
543  throw "Bad checksum";
544  }
545  catch (...)
546  {
547  delete [] tempval;
548  throw;
549  }
550 
551  return reinterpret_cast<char*>(tempval);
552 }
553 
555 {
556  return getTagFromSMI( 0 ); /* Read asset tag select code */
557 }
558 
559 // Code for getting the asset tag from one of many locations
561 {
562  char *(*f_ptr)();
563 }
564 
565 /* try dynamic functions first to make sure we get current data. */
567  {&getAssetTagFromSMI,}, // SMI
568  {&getAssetTagFromToken,}, // SMBIOS Token
569  {&getAssetTagFromSysEncl,}, // SMBIOS System Information Item
570  };
571 
572 const char *SMBIOSGetAssetTag()
573 {
574  char *assetTag = 0;
575  int numEntries =
576  sizeof (DellAssetTagFunctions) / sizeof (DellAssetTagFunctions[0]);
577 
578  for (int i = 0; (i < numEntries) && (!assetTag); ++i)
579  {
580  // eat exceptions from lowlevel functions and keep going.
581  try
582  {
583  // first function to return non-zero id wins.
584  assetTag = DellAssetTagFunctions[i].f_ptr ();
585  }
586  catch(const smbios::IException &e)
587  {
588  SysInfoException.setMessageString(e.what());
589  }
590  catch(...)
591  {
592  SysInfoException.setMessageString( _("Unknown internal error occurred") );
593  }
594  }
595  stripString(assetTag);
596  return assetTag;
597 }
598 
599 
600 
601 void setAssetTagUsingCMOSToken(const char *newTag, size_t len)
602 {
603  smbios::ITokenTable *table = 0;
605 
606  if (0 == table)
607  {
608  throw InternalErrorImpl();
609  }
610 
611  try
612  {
613  // Step 1: set string
614  (*table)[Cmos_Asset_Token]->setString(reinterpret_cast<const u8*>(newTag), len < ASSET_TAG_CMOS_LEN_MAX? len : ASSET_TAG_CMOS_LEN_MAX);
615 
616  // Step 2: reset checksum
617  u16 indexPort, dataPort;
618  u8 location;
619 
620  smbios::IToken *token = &(*((*table)[ Cmos_Asset_Token ]));
621  dynamic_cast< smbios::ICmosToken * >(token)->getCMOSDetails( &indexPort, &dataPort, &location );
622 
623  u8 csum = 0;
625 
626  for( u32 i = 0; i < ASSET_TAG_CMOS_LEN_MAX; i++)
627  {
628  // stupid stuff to avoid MVC++ .NET runtime exception check for cast to different size
629  csum = (csum + cmos->readByte( indexPort, dataPort, location + i )) & 0xFF;
630  }
631 
632  cmos->writeByte(
633  indexPort,
634  dataPort,
635  location + ASSET_TAG_CMOS_LEN_MAX,
636  csum
637  );
638  }
639  catch( const smbios::IException & )
640  {
641  throw;
642  }
643 
644 }
645 
646 void setAssetTagUsingSMI(const char *newTag, size_t size)
647 {
648  (void) size; // avoid unused var warning.
649  setTagUsingSMI( newTag, 1 ); /* Write asset tag select code */
650 }
651 
652 // Code for getting the service tag from one of many locations
654 {
655  void (*f_ptr)(const char *, size_t);
656  const char * desc;
657 }
658 
660  {&setAssetTagUsingSMI, "SMI"}, // SMBIOS System Information Item
661  {&setAssetTagUsingCMOSToken, "CMOS"}, // SMBIOS System Information Item
662  };
663 
664 int SMBIOSSetAssetTag(const char *password, const char *assetTag, size_t len)
665 {
666  int retval = -1;
667  int numEntries =
668  sizeof (DellSetAssetTagFunctions) / sizeof (DellSetAssetTagFunctions[0]);
669 
670  if(password)
671  biosPassword = password;
672 
673  for (int i = 0; (i < numEntries); ++i)
674  {
675  // eat exceptions from lowlevel functions and keep going.
676  try
677  {
678  // first function to return non-zero id wins.
679  DellSetAssetTagFunctions[i].f_ptr (assetTag, len);
680  retval = 0;
681  }
682  catch(const smbios::IException &e)
683  {
684  SysInfoException.setMessageString(e.what());
685  }
686  catch(...)
687  {
688  SysInfoException.setMessageString( _("Unknown internal error occurred") );
689  }
690  }
691  return retval;
692 }
693 
694 
696 {
698 }
699 
700 // Struct for getting the system name from one of many locations
702 {
703  char *(*f_ptr)();
704 }
705 
707  {&getSystemNameFromSysInfo,} // SMBIOS System Information Item
708  };
709 
710 const char *SMBIOSGetSystemName()
711 {
712  char *systemName= 0;
713  int numEntries =
714  sizeof (DellSystemNameFunctions) / sizeof (DellSystemNameFunctions[0]);
715 
716  for (int i = 0; (i < numEntries) && (!systemName); ++i)
717  {
718  // eat exceptions from lowlevel functions and keep going.
719  try
720  {
721  // first function to return non-zero id wins.
722  systemName = DellSystemNameFunctions[i].f_ptr ();
723  }
724  catch(const smbios::IException &e)
725  {
726  SysInfoException.setMessageString(e.what());
727  }
728  catch(...)
729  {
730  SysInfoException.setMessageString( _("Unknown internal error occurred") );
731  }
732  }
733 
734  stripString(systemName);
735  return systemName;
736 }
737 
738 // for Diamond only.
740 {
741  memory::IMemory *mem = 0;
742  u8 strBuf[DELL_SYSTEM_STRING_LEN] = { 0, };
743  u8 *biosVersion = 0;
744 
746 
747  if( 0 == mem )
748  throw InternalErrorImpl();
749 
750  // Step 1: Check that "Dell System" is present at the proper offset
752  if( strncmp( reinterpret_cast<char*>(strBuf), DELL_SYSTEM_STRING, DELL_SYSTEM_STRING_LEN ) == 0 )
754  {
755  biosVersion = new u8[4];
756  mem->fillBuffer(biosVersion, ID_BYTE_LOC_DIAMOND_1 + 1, 3);
757  biosVersion[3] = '\0';
758  }
759 
761  if( strncmp( reinterpret_cast<char*>(strBuf), DELL_SYSTEM_STRING, DELL_SYSTEM_STRING_LEN ) == 0 )
763  {
764  biosVersion = new u8[4];
765  mem->fillBuffer(biosVersion, ID_BYTE_LOC_DIAMOND_2 + 1, 3);
766  biosVersion[3] = '\0';
767  }
768 
769  return reinterpret_cast<char*>(biosVersion);
770 }
771 
773 {
775 }
776 
777 // Code for getting the service tag from one of many locations
779 {
780  char *(*f_ptr)();
781 }
785  };
786 
787 const char *SMBIOSGetBiosVersion()
788 {
789  char *systemName= 0;
790  int numEntries =
791  sizeof (DellBiosVersionFunctions) / sizeof (DellBiosVersionFunctions[0]);
792 
793  for (int i = 0; (i < numEntries) && (!systemName); ++i)
794  {
795  // eat exceptions from lowlevel functions and keep going.
796  try
797  {
798  // first function to return non-zero id wins.
799  systemName = DellBiosVersionFunctions[i].f_ptr ();
800  }
801  catch(const smbios::IException &e)
802  {
803  SysInfoException.setMessageString(e.what());
804  }
805  catch(...)
806  {
807  SysInfoException.setMessageString( _("Unknown internal error occurred") );
808  }
809  }
810 
811  stripString(systemName);
812  return systemName;
813 }
814 
815 
816 const char *SMBIOSGetVendorName()
817 {
818  char *retval = 0;
819 
820  try
821  {
823  }
824  catch(const smbios::IException &e)
825  {
826  SysInfoException.setMessageString(e.what());
827  }
828  catch(...)
829  {
830  SysInfoException.setMessageString( _("Unknown internal error occurred") );
831  }
832 
833  stripString(retval);
834  return retval;
835 }
836 
837 
839 {
840  int retval = 1;
841  try
842  {
844  smbios::ITokenTable *tokenTable = ttFactory->getSingleton();
845 
846  u8 tempData[2] = {0,0};
847  (*tokenTable)[ NvramByte1_Token ]->getString( tempData, 2 );
848  (*tokenTable)[ NvramByte2_Token ]->getString( tempData, 2 );
849  }
850  catch(const smbios::IException &e)
851  {
852  SysInfoException.setMessageString(e.what());
853  retval = 0;
854  }
855  catch(...)
856  {
857  SysInfoException.setMessageString( _("Unknown internal error occurred") );
858  }
859 
860  return retval;
861 }
862 
863 
864 // user =
865 // 0x0000 = DSA
866 // 0x8000 = OM Toolkit
867 // 0x9000 = open
868 // 0xA000 = open
869 // 0xB000 = open
870 // 0xC000 = open
871 // 0xD000 = open
872 // 0xE000 = open
873 // 0xF000 = expand to whole byte
875 {
876  u8 tempData[2] = {0,0};
877  int retval = 0;
878  try
879  {
881  smbios::ITokenTable *tokenTable = ttFactory->getSingleton();
882 
883  (*tokenTable)[ NvramByte1_Token ]->getString( tempData, 2 );
884  retval = *tempData;
885  (*tokenTable)[ NvramByte2_Token ]->getString( tempData, 2 );
886  retval |= (*tempData << 8);
887  }
888  catch(const smbios::IException &e)
889  {
890  SysInfoException.setMessageString(e.what());
891  }
892  catch(...)
893  {
894  SysInfoException.setMessageString( _("Unknown internal error occurred") );
895  }
896 
897  if( user == 0x0000 ) // DSA
898  {
899  if( (retval & 0x8000) != user )
900  {
901  retval = 0; // user doesn't match, return default
902  }
903  retval &= ~0x8000; // mask user bits
904  }
905  else
906  {
907  if ((user & 0xF000) == 0xF000 ) // probably will never be used
908  {
909  if( (retval & 0xFF00) != user )
910  {
911  retval = 0;// user doesn't match, return default
912  }
913  retval &= ~0xFF00; // mask user bits
914  }
915  else
916  {
917  if( (retval & 0xF000) != user ) // Toolkit (or users 0x9 - 0xE)
918  {
919  retval = 0;// user doesn't match, return default
920  }
921  retval &= ~0xF000; // mask user bits
922  }
923  }
924  return retval;
925 }
926 
927 void SMBIOSSetNvramStateBytes(int value, int user)
928 {
929  try
930  {
931  if ( user == 0x0000 ) // DSA
932  {
933  value &= ~0x8000; // mask user bits
934  value |= user; // set user
935  }
936  else if( (user & 0xF000) == 0xF000 )
937  {
938  value &= ~0xFF00; // mask user bits
939  value |= user; // set user
940  }
941  else
942  {
943  value &= ~0xF000; // mask user bits
944  value |= user; // set user
945  }
946 
948  smbios::ITokenTable *tokenTable = ttFactory->getSingleton();
949 
950  u8 *tempData = reinterpret_cast<u8*>(&value);
951  (*tokenTable)[ NvramByte1_Token ]->setString( tempData, 1 );
952  (*tokenTable)[ NvramByte2_Token ]->setString( tempData+1, 1 );
953  }
954  catch(const smbios::IException &e)
955  {
956  SysInfoException.setMessageString(e.what());
957  }
958  catch(...)
959  {
960  SysInfoException.setMessageString( _("Unknown internal error occurred") );
961  }
962  return;
963 }
964 
965 
966 static bool getUpOffsetAndFlag (up_info *up)
967 {
968  memory::IMemory *mem =
970 
971  up_info tempUP;
972  memset(&tempUP, 0, sizeof(tempUP));
973  int step_size = 16;
974 
975  unsigned int fp = 0xF0000;
976  bool found = false;
977  while( fp < (0xFFFFFUL - sizeof(tempUP)) )
978  {
979  mem->fillBuffer(
980  reinterpret_cast<u8 *>(&tempUP),
981  fp,
982  sizeof(tempUP)
983  );
984 
985  if ( 0 == memcmp( &(tempUP.anchor), "_UP_", 4))
986  {
987  found = true;
988  break;
989  }
990 
991  fp += step_size;
992  // for buggy BIOSen. If we don't find it on a paragraph boundary,
993  // start over and do byte-by-byte
994  if( step_size > 1 && fp >= (0xFFFFFUL - sizeof(tempUP)) )
995  {
996  step_size = 1;
997  fp = 0xF0000;
998  }
999  }
1000 
1001  if( found )
1002  memcpy( up, &tempUP, sizeof(tempUP) );
1003 
1004  return found;
1005 }
1006 
1007 static int upBootHelper(bool set
1008  =false, bool value=false)
1009 {
1010  // retval = 0: NO BOOT TO UP CAPABILITY
1011  // retval = 1 && set; set to value
1012  // retval = 2 && !set; UP not active
1013  // retval = 3 && !set; UP Active
1014  int retval = 0;
1015  const u8 *buf = 0;
1016 
1017  up_info up;
1018  memset( reinterpret_cast<u8*>(&up), 0, sizeof(up));
1019  try
1020  {
1021  bool found = getUpOffsetAndFlag( &up );
1022 
1023  if( !found )
1024  goto out;
1025 
1027  smbios::ITokenTable *tokenTable = ttFactory->getSingleton();
1028  size_t length;
1029  buf = (*tokenTable)[ NvramByte2_Token ]->getItemRef().getBufferCopy(length);
1030 
1031  const indexed_io_access_structure *io_struct =
1032  reinterpret_cast<const indexed_io_access_structure *>(buf);
1033 
1035 
1036  u8 byte = cmos->readByte( io_struct->indexPort, io_struct->dataPort, up.offset );
1037 
1038  if( set
1039  )
1040  {
1041  // default to set
1042  byte |= up.flag;
1043  retval = 1;
1044  if (!value) // clear
1045  {
1046  byte &= ~up.flag;
1047  }
1048  cmos->writeByte( io_struct->indexPort, io_struct->dataPort, up.offset, byte );
1049  }
1050  else
1051  {
1052  if( (byte & up.flag) == up.flag )
1053  retval = 3;
1054 
1055  if( (byte & up.flag) != up.flag )
1056  retval = 2;
1057  }
1058 
1059  }
1060  catch(const smbios::IException &e)
1061  {
1062  SysInfoException.setMessageString(e.what());
1063  }
1064  catch(...)
1065  {
1066  SysInfoException.setMessageString( _("Unknown internal error occurred") );
1067  }
1068 
1069  delete [] const_cast<u8 *>(buf);
1070  buf = 0;
1071 
1072 out:
1073  return retval;
1074 }
1075 
1077 {
1078  return upBootHelper();
1079 }
1080 
1082 {
1083  int retval = upBootHelper();
1084  retval -= 2;
1085  return retval;
1086 }
1087 
1088 void SMBIOSSetBootToUp(int state)
1089 {
1090  bool value = (state == 1) ? true: false;
1091  upBootHelper(true, value);
1092 }
1093 
1094 
1096 {
1097  int fmt=0;
1098  try
1099  {
1100  fmt = smi::getPasswordFormat();
1101  }
1102  catch(const exception &)
1103  {}
1104 
1105  return fmt;
1106 }
1107