@@ -5197,7 +5197,7 @@ dmi_codes_major *find_dmiMajor(const struct dmi_header *h)
51975197 return NULL ;
51985198}
51995199
5200- static void dmi_table (Log_t * logp , int type , u32 base , u16 len , u16 num , u16 ver , const char * devmem , xmlNode * xmlnode )
5200+ static void dmi_table (Log_t * logp , int type , u32 base , u16 len , u16 num , u16 ver , const char * devmem , u32 flags , xmlNode * xmlnode )
52015201{
52025202 static u8 version_added = 0 ;
52035203 u8 * buf ;
@@ -5221,35 +5221,40 @@ static void dmi_table(Log_t *logp, int type, u32 base, u16 len, u16 num, u16 ver
52215221 info_n = NULL ;
52225222 }
52235223
5224- if ((buf = mem_chunk (logp , base , len , devmem )) == NULL ) {
5225- log_append (logp , LOGFL_NODUPS , LOG_WARNING , "Table is unreachable, sorry."
5226- #ifndef USE_MMAP
5227- "Try compiling dmidecode with -DUSE_MMAP."
5228- #endif
5229- );
5230- return ;
5231- }
5224+ if (flags & FLAG_NO_FILE_OFFSET ){
5225+ /*
5226+ * When reading from sysfs or from a dump file, the file may be
5227+ * shorter than announced. For SMBIOS v3 this is expcted, as we
5228+ * only know the maximum table size, not the actual table size.
5229+ * For older implementations (and for SMBIOS v3 too), this
5230+ * would be the result of the kernel truncating the table on
5231+ * parse error.
5232+ */
5233+ size_t size = len ;
5234+ buf = read_file (logp , flags & FLAG_NO_FILE_OFFSET ? 0 : base , & size , devmem );
5235+ if (num && size != (size_t )len ){
5236+ log_append (logp , LOGFL_NODUPS , LOG_WARNING , "Wrong DMI structures length: %i bytes announced, only %lu bytes available.\n" , len , (unsigned long )size );
5237+ }
5238+ len = size ;
5239+ } else {
5240+ buf = mem_chunk (logp , base , len , devmem );
5241+ }
5242+
5243+ if (ver > SUPPORTED_SMBIOS_VER ){
5244+ log_append (logp , LOGFL_NODUPS , LOG_WARNING , "# SMBIOS implementations newer than version %u.%u are not\n" , "# fully supported by this version of dmidecode.\n" , SUPPORTED_SMBIOS_VER >> 8 , SUPPORTED_SMBIOS_VER & 0xFF );
5245+ }
52325246
5233- if (ver > SUPPORTED_SMBIOS_VER ) {
5234- log_append (logp , LOGFL_NODUPS , LOG_WARNING ,
5235- "# SMBIOS implementations newer than version %u.%u are not\n"
5236- "# fully supported by this version of dmidecode.\n" ,
5237- SUPPORTED_SMBIOS_VER >> 8 , SUPPORTED_SMBIOS_VER & 0xFF );
5238- }
5239- // FIXME: This is hackerish ... rather try to avoid looping dmi_table() calls too much
52405247 if ( version_added == 0 ) {
52415248 dmixml_AddAttribute (xmlnode , "smbios_version" , "%u.%u" , ver >> 8 , ver & 0xFF );
52425249 version_added = 1 ;
52435250 }
52445251
5245- data = buf ;
5246- while (i < num && data + 4 <= buf + len ) { /* 4 is the length of an SMBIOS structure header */
5247-
5252+ data = buf ;
5253+ while (i < num && data + 4 <= buf + len ) { /* 4 is the length of an SMBIOS structure header */
52485254 u8 * next ;
52495255 struct dmi_header h ;
52505256
52515257 to_dmi_header (& h , data );
5252-
52535258 /*
52545259 ** If a short entry is found (less than 4 bytes), not only it
52555260 ** is invalid, but we cannot reliably locate the next entry.
@@ -5258,8 +5263,8 @@ static void dmi_table(Log_t *logp, int type, u32 base, u16 len, u16 num, u16 ver
52585263 */
52595264 if (h .length < 4 ) {
52605265 log_append (logp , LOGFL_NORMAL , LOG_WARNING ,
5261- "Invalid entry length (%i) for type %i. DMI table is broken! Stop." ,
5262- (unsigned int )h .length , type );
5266+ "Invalid entry length (%i) for type %i. DMI table is broken! Stop." ,
5267+ (unsigned int )h .length , type );
52635268 break ;
52645269 }
52655270
@@ -5278,7 +5283,6 @@ static void dmi_table(Log_t *logp, int type, u32 base, u16 len, u16 num, u16 ver
52785283 next ++ ;
52795284 }
52805285 next += 2 ;
5281-
52825286 xmlNode * handle_n = NULL ;
52835287 if ( h .type == type ) {
52845288 if (next - buf <= len ) {
@@ -5309,6 +5313,7 @@ static void dmi_table(Log_t *logp, int type, u32 base, u16 len, u16 num, u16 ver
53095313 dmixml_AddAttribute (handle_n , "length" , "%i" , (next - buf ));
53105314 dmixml_AddAttribute (handle_n , "expected_length" , "%i" , len );
53115315
5316+
53125317 log_append (logp , LOGFL_NODUPS , LOG_WARNING ,
53135318 "DMI/SMBIOS type 0x%02X is exceeding the expected buffer "
53145319 "size by %i bytes. Will not decode this entry." ,
@@ -5344,6 +5349,60 @@ static void dmi_table(Log_t *logp, int type, u32 base, u16 len, u16 num, u16 ver
53445349 free (buf );
53455350}
53465351
5352+ int _smbios3_decode_check (u8 * buf ){
5353+ int check = (!checksum (buf , buf [0x06 ])) ? 0 : 1 ;
5354+ return check ;
5355+ }
5356+
5357+ xmlNode * smbios3_decode_get_version (u8 * buf , const char * devmem )
5358+ {
5359+ int check = _smbios3_decode_check (buf );
5360+
5361+ xmlNode * data_n = xmlNewNode (NULL , (xmlChar * ) "DMIversion" );
5362+ assert ( data_n != NULL );
5363+
5364+ dmixml_AddAttribute (data_n , "type" , "SMBIOS" );
5365+
5366+ if (check == 1 ) {
5367+ u16 ver = (buf [0x07 ] << 16 ) + (buf [0x08 ] << 8 ) + buf [0x09 ];
5368+
5369+ dmixml_AddTextContent (data_n , "SMBIOS %i.%i.%i present" , buf [0x07 ], buf [0x08 ], buf [0x09 ]);
5370+ dmixml_AddAttribute (data_n , "version" , "%i.%i.%i" , buf [0x07 ], buf [0x08 ],buf [0x09 ]);
5371+ } else if (check == 0 ) {
5372+ dmixml_AddTextContent (data_n , "No SMBIOS nor DMI entry point found" );
5373+ dmixml_AddAttribute (data_n , "unknown" , "1" );
5374+ }
5375+ return data_n ;
5376+ }
5377+
5378+ int smbios3_decode (Log_t * logp , int type , u8 * buf , const char * devmem , u32 flags , xmlNode * xmlnode )
5379+ {
5380+ u32 ver ;
5381+ u64 offset ;
5382+
5383+ /* Don't let checksum run beyond the buffer */
5384+ if (buf [0x06 ] > 0x20 )
5385+ {
5386+ return 0 ;
5387+ }
5388+
5389+ int check = _smbios3_decode_check (buf );
5390+ if (check == 1 )
5391+ {
5392+ ver = (buf [0x07 ] << 16 ) + (buf [0x08 ] << 8 ) + buf [0x09 ];
5393+ offset = QWORD (buf + 0x10 );
5394+
5395+ if (!(flags & FLAG_NO_FILE_OFFSET ) && offset .h && sizeof (off_t ) < 8 )
5396+ {
5397+ return 0 ;
5398+ }
5399+
5400+ dmi_table (logp , type , ((off_t )offset .h << 32 ) | offset .l , DWORD (buf + 0x0C ), 0 , ver , devmem , flags | FLAG_STOP_AT_EOT , xmlnode );
5401+ }
5402+
5403+ return check ;
5404+ }
5405+
53475406int _smbios_decode_check (u8 * buf )
53485407{
53495408 int check = (!checksum (buf , buf [0x05 ]) || memcmp (buf + 0x10 , "_DMI_" , 5 ) != 0 ||
@@ -5370,7 +5429,8 @@ xmlNode *smbios_decode_get_version(u8 * buf, const char *devmem)
53705429 _M = 0 ;
53715430 switch (ver ) {
53725431 case 0x021F :
5373- _m = 31 ;
5432+ case 0x0221 :
5433+ _m = ver & 0xFF ;
53745434 _M = 3 ;
53755435 ver = 0x0203 ;
53765436 break ;
@@ -5396,7 +5456,7 @@ xmlNode *smbios_decode_get_version(u8 * buf, const char *devmem)
53965456 return data_n ;
53975457}
53985458
5399- int smbios_decode (Log_t * logp , int type , u8 * buf , const char * devmem , xmlNode * xmlnode )
5459+ int smbios_decode (Log_t * logp , int type , u8 * buf , const char * devmem , u32 flags , xmlNode * xmlnode )
54005460{
54015461 int check = _smbios_decode_check (buf );
54025462
@@ -5405,6 +5465,7 @@ int smbios_decode(Log_t *logp, int type, u8 *buf, const char *devmem, xmlNode *x
54055465
54065466 switch (ver ) {
54075467 case 0x021F :
5468+ case 0x0221 :
54085469 ver = 0x0203 ;
54095470 break ;
54105471 case 0x0233 :
@@ -5413,7 +5474,7 @@ int smbios_decode(Log_t *logp, int type, u8 *buf, const char *devmem, xmlNode *x
54135474 }
54145475 // printf(">>%d @ %d, %d<<\n", DWORD(buf+0x18), WORD(buf+0x16), WORD(buf+0x1C));
54155476 dmi_table (logp , type , DWORD (buf + 0x18 ), WORD (buf + 0x16 ), WORD (buf + 0x1C ), ver , devmem ,
5416- xmlnode );
5477+ flags , xmlnode );
54175478 }
54185479 return check ;
54195480}
@@ -5451,13 +5512,13 @@ xmlNode *legacy_decode_get_version(u8 * buf, const char *devmem)
54515512 return data_n ;
54525513}
54535514
5454- int legacy_decode (Log_t * logp , int type , u8 * buf , const char * devmem , xmlNode * xmlnode )
5515+ int legacy_decode (Log_t * logp , int type , u8 * buf , const char * devmem , u32 flags , xmlNode * xmlnode )
54555516{
54565517 int check = _legacy_decode_check (buf );
54575518
54585519 if (check == 1 )
54595520 dmi_table (logp , type , DWORD (buf + 0x08 ), WORD (buf + 0x06 ), WORD (buf + 0x0C ),
5460- ((buf [0x0E ] & 0xF0 ) << 4 ) + (buf [0x0E ] & 0x0F ), devmem , xmlnode );
5521+ ((buf [0x0E ] & 0xF0 ) << 4 ) + (buf [0x0E ] & 0x0F ), devmem , flags , xmlnode );
54615522 return check ;
54625523}
54635524
0 commit comments