6335559: smbios utility reports bogus cache size information
6335549: prtdiag: can't get smbios tables on toshiba tecra s1 laptop
6335547: smbios intermediate checksum computation is broken, rejects valid 
smbios tables

See each bug's work around section for a suggested fix, with the exception of
CR 6335547 (see the attachment for a new suggested fix for 6335547).
This message posted from opensolaris.org
-------------- next part --------------
Diskless snv_22 client, ASUS A7V mainboard, bfu'ed to snv_23:

% prtdiag
prtdiag: failed to open SMBIOS: System does not export an SMBIOS table

/var/adm/messages:

Oct  8 20:05:17 moritz unix: [ID 672469 kern.info] SMBIOS not loaded (SMBIOS 
header checksum mismatch)

------------------------------------------------------------------------

open /dev/smbios fails with ENXIO, because in the kernel, ksmbios == NULL.

This happens in post_startup():

        ksmbios = smbios_open(NULL, SMB_VERSION, ksmbios_flags, NULL);


Root cause:

usr/src/common/smbios/smb_open.c function smbios_bufopen() computes an 
'isum' checksum like this:

    76  smbios_hdl_t *
    77  smbios_bufopen(const smbios_entry_t *ep, const void *buf, size_t len,
    78      int version, int flags, int *errp)
    79  {
   ...
   132                  for (p = (uchar_t *)ep->smbe_ianchor; p < q + sizeof 
(*ep); p++)
   133                          isum += *p;

The computed 'isum' checksum has a value != 0.

Problem is that the smbios entry structure has an odd length of 31 bytes, 
but the smbios_entry_t type definition is not 'packed' so that the compiler
works with an extra filler byte at the end and a sizeof(*ep) of 32 bytes.
One extra byte is included in the comupted checksum, the computed checksum
is bogus.

The smbios bios reference specification defines the intermediate checksum
as the sum of the values starting at offset 10h for 0Fh bytes (Solaris
sums 10h bytes).

------------------------------------------------------------------------

XXX Old suggested fix:
XXX 
XXX In usr/src/uts/common/sys/smbios.h, use #pragma pack(1) around the
XXX smbios_entry_t typedef.
XXX
XXX but this breaks smbios on a "Peacock Freeliner XP10" AMD laptop.

New suggested fix:

Don't rely on sizeof(smbios_entry_t) when computing/verifying the smbe_icksum.
Use the range of bytes [smbe_ianchor .. smbe_bcdrev] to compute/verify the
checksum.

*** usr/src/common/smbios/smb_open.c~   2005-10-10 19:14:20.155332000 +0200
--- usr/src/common/smbios/smb_open.c    2005-10-11 17:15:12.305958000 +0200
***************
*** 129,135 ****
                for (p = q; p < q + ep->smbe_elen; p++)
                        esum += *p;
  
!               for (p = (uchar_t *)ep->smbe_ianchor; p < q + sizeof (*ep); p++)
                        isum += *p;
  
                if (esum != 0 || isum != 0) {
--- 129,137 ----
                for (p = q; p < q + ep->smbe_elen; p++)
                        esum += *p;
  
!               for (p = (uchar_t *)ep->smbe_ianchor;
!                    p <= (uchar_t *)ep->smbe_bcdrev;
!                    p++)
                        isum += *p;
  
                if (esum != 0 || isum != 0) {
***************
*** 265,271 ****
  
        ep->smbe_ecksum = ep->smbe_icksum = 0;
  
!       for (p = (uchar_t *)ep->smbe_ianchor; p < q + sizeof (*ep); p++)
                isum += *p;
  
        ep->smbe_icksum = -isum;
--- 267,275 ----
  
        ep->smbe_ecksum = ep->smbe_icksum = 0;
  
!       for (p = (uchar_t *)ep->smbe_ianchor;
!            p <= (uchar_t *)ep->smbe_bcdrev;
!            p++)
                isum += *p;
  
        ep->smbe_icksum = -isum;

Reply via email to