"Fossies" - the Fresh Open Source Software Archive

Member "dmidecode-3.2/vpddecode.c" (14 Sep 2018, 4842 Bytes) of package /linux/privat/dmidecode-3.2.tar.xz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "vpddecode.c" see the Fossies "Dox" file reference documentation and the last Fossies "Diffs" side-by-side code changes report: 2.12_vs_3.0.

    1 /*
    2  * IBM Vital Product Data decoder
    3  *
    4  *   Copyright (C) 2003-2007 Jean Delvare <jdelvare@suse.de>
    5  *
    6  *   This program is free software; you can redistribute it and/or modify
    7  *   it under the terms of the GNU General Public License as published by
    8  *   the Free Software Foundation; either version 2 of the License, or
    9  *   (at your option) any later version.
   10  *
   11  *   This program is distributed in the hope that it will be useful,
   12  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
   13  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   14  *   GNU General Public License for more details.
   15  *
   16  *   You should have received a copy of the GNU General Public License
   17  *   along with this program; if not, write to the Free Software
   18  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
   19  *
   20  *   For the avoidance of doubt the "preferred form" of this code is one which
   21  *   is in an open unpatent encumbered format. Where cryptographic key signing
   22  *   forms part of the process of creating an executable the information
   23  *   including keys needed to generate an equivalently functional executable
   24  *   are deemed to be part of the source code.
   25  *
   26  * References:
   27  *  - IBM "Using the BIOS Build ID to identify Thinkpad systems"
   28  *    Revision 2006-01-31
   29  *    http://www-307.ibm.com/pc/support/site.wss/MIGR-45120.html
   30  *
   31  * Notes:
   32  *  - Main part of the code is taken directly from biosdecode, with an
   33  *    additional command line interface and a few experimental features.
   34  */
   35 
   36 #include <stdio.h>
   37 #include <stdlib.h>
   38 #include <string.h>
   39 #include <unistd.h>
   40 
   41 #include "version.h"
   42 #include "config.h"
   43 #include "types.h"
   44 #include "util.h"
   45 #include "vpdopt.h"
   46 
   47 static void print_entry(const char *name, const u8 *p, size_t len)
   48 {
   49     size_t i;
   50 
   51     if (name != NULL)
   52         printf("%s: ", name);
   53     for (i = 0; i < len; i++)
   54     {
   55         /* ASCII filtering */
   56         if (p[i] >= 32 && p[i] < 127)
   57             printf("%c", p[i]);
   58         else if (p[i] != 0)
   59             printf(".");
   60     }
   61     printf("\n");
   62 }
   63 
   64 static void dump(const u8 *p, u8 len)
   65 {
   66     int done, i, min;
   67 
   68     for (done = 0; done < len; done += 16)
   69     {
   70         printf("%02X:", done);
   71         min = (len - done < 16) ? len - done : 16;
   72 
   73         /* As hexadecimal first */
   74         for (i = 0; i < min; i++)
   75             printf(" %02X", p[done + i]);
   76         for (; i < 16; i++) /* Complete line if needed */
   77             printf("   ");
   78         printf("     ");
   79 
   80         /* And now as text, with ASCII filtering */
   81         for (i = 0; i < min; i++)
   82             printf("%c", (p[done + i] >= 32 && p[done + i] < 127) ?
   83                 p[done + i] : '.');
   84         printf("\n");
   85     }
   86 }
   87 
   88 static int decode(const u8 *p)
   89 {
   90     if (p[5] < 0x30)
   91         return 0;
   92 
   93     /* XSeries have longer records, exact length seems to vary. */
   94     if (!(p[5] >= 0x45 && checksum(p, p[5]))
   95     /* Some Netvista seem to work with this. */
   96      && !(checksum(p, 0x30))
   97     /* The Thinkpad/Thinkcentre checksum does *not* include the first
   98        13 bytes. */
   99      && !(checksum(p + 0x0D, 0x30 - 0x0D)))
  100     {
  101         /* A few systems have a bad checksum (xSeries 325, 330, 335
  102            and 345 with early BIOS) but the record is otherwise
  103            valid. */
  104         if (!(opt.flags & FLAG_QUIET))
  105             printf("# Bad checksum!\n");
  106     }
  107 
  108     if (opt.string != NULL)
  109     {
  110         if (opt.string->offset + opt.string->len < p[5])
  111             print_entry(NULL, p + opt.string->offset,
  112                         opt.string->len);
  113         return 1;
  114     }
  115 
  116     print_entry("BIOS Build ID", p + 0x0D, 9);
  117     print_entry("Box Serial Number", p + 0x16, 7);
  118     print_entry("Motherboard Serial Number", p + 0x1D, 11);
  119     print_entry("Machine Type/Model", p + 0x28, 7);
  120 
  121     if (p[5] < 0x44)
  122         return 1;
  123 
  124     print_entry("BIOS Release Date", p + 0x30, 8);
  125     print_entry("Default Flash Image File Name", p + 0x38, 12);
  126 
  127     if (p[5] >= 0x46 && p[0x44] != 0x00)
  128     {
  129         printf("%s: %u\n", "BIOS Revision", p[0x44]);
  130     }
  131 
  132     return 1;
  133 }
  134 
  135 int main(int argc, char * const argv[])
  136 {
  137     u8 *buf;
  138     int found = 0;
  139     unsigned int fp;
  140 
  141     if (sizeof(u8) != 1)
  142     {
  143         fprintf(stderr, "%s: compiler incompatibility\n", argv[0]);
  144         exit(255);
  145     }
  146 
  147     /* Set default option values */
  148     opt.devmem = DEFAULT_MEM_DEV;
  149     opt.flags = 0;
  150 
  151     if (parse_command_line(argc, argv)<0)
  152         exit(2);
  153 
  154     if (opt.flags & FLAG_HELP)
  155     {
  156         print_help();
  157         return 0;
  158     }
  159 
  160     if (opt.flags & FLAG_VERSION)
  161     {
  162         printf("%s\n", VERSION);
  163         return 0;
  164     }
  165 
  166     if (!(opt.flags & FLAG_QUIET))
  167         printf("# vpddecode %s\n", VERSION);
  168 
  169     if ((buf = mem_chunk(0xF0000, 0x10000, opt.devmem)) == NULL)
  170         exit(1);
  171 
  172     for (fp = 0; fp <= 0xFFF0; fp += 4)
  173     {
  174         u8 *p = buf + fp;
  175 
  176         if (memcmp((char *)p, "\252\125VPD", 5) == 0
  177          && fp + p[5] - 1 <= 0xFFFF)
  178         {
  179             if (fp % 16 && !(opt.flags & FLAG_QUIET))
  180                 printf("# Unaligned address (%#x)\n",
  181                        0xf0000 + fp);
  182             if (opt.flags & FLAG_DUMP)
  183             {
  184                 dump(p, p[5]);
  185                 found++;
  186             }
  187             else
  188             {
  189                 if (decode(p))
  190                     found++;
  191             }
  192         }
  193     }
  194 
  195     free(buf);
  196 
  197     if (!found && !(opt.flags & FLAG_QUIET))
  198         printf("# No VPD structure found, sorry.\n");
  199 
  200     return 0;
  201 }