Subversion Repositories Kolibri OS

Rev

Rev 5270 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1.  
  2. #include <linux/types.h>
  3. #include <linux/string.h>
  4. #include <linux/bug.h>
  5. #include <linux/module.h>
  6. #include <linux/ctype.h>
  7. #include <linux/dmi.h>
  8. #include <syscall.h>
  9.  
  10. #define pr_debug dbgprintf
  11. #define pr_info  printf
  12.  
  13. static void *dmi_alloc(unsigned len)
  14. {
  15.     return malloc(len);
  16. };
  17.  
  18. /*
  19.  * DMI stands for "Desktop Management Interface".  It is part
  20.  * of and an antecedent to, SMBIOS, which stands for System
  21.  * Management BIOS.  See further: http://www.dmtf.org/standards
  22.  */
  23. static const char dmi_empty_string[] = "        ";
  24.  
  25. static u16 dmi_ver;
  26. /*
  27.  * Catch too early calls to dmi_check_system():
  28.  */
  29. static int dmi_initialized;
  30.  
  31. /* DMI system identification string used during boot */
  32. static char dmi_ids_string[128];
  33.  
  34. static struct dmi_memdev_info {
  35.         const char *device;
  36.         const char *bank;
  37.         u16 handle;
  38. } *dmi_memdev;
  39. static int dmi_memdev_nr;
  40.  
  41. static const char * __init dmi_string_nosave(const struct dmi_header *dm, u8 s)
  42. {
  43.     const u8 *bp = ((u8 *) dm) + dm->length;
  44.  
  45.     if (s) {
  46.         s--;
  47.         while (s > 0 && *bp) {
  48.             bp += strlen(bp) + 1;
  49.             s--;
  50.         }
  51.  
  52.         if (*bp != 0) {
  53.             size_t len = strlen(bp)+1;
  54.             size_t cmp_len = len > 8 ? 8 : len;
  55.  
  56.             if (!memcmp(bp, dmi_empty_string, cmp_len))
  57.                 return dmi_empty_string;
  58.             return bp;
  59.         }
  60.     }
  61.  
  62.     return "";
  63. }
  64.  
  65. static const char * __init dmi_string(const struct dmi_header *dm, u8 s)
  66. {
  67.     const char *bp = dmi_string_nosave(dm, s);
  68.     char *str;
  69.     size_t len;
  70.  
  71.     if (bp == dmi_empty_string)
  72.         return dmi_empty_string;
  73.  
  74.     len = strlen(bp) + 1;
  75.     str = dmi_alloc(len);
  76.     if (str != NULL)
  77.         strcpy(str, bp);
  78.  
  79.     return str;
  80. }
  81.  
  82. /*
  83.  *      We have to be cautious here. We have seen BIOSes with DMI pointers
  84.  *      pointing to completely the wrong place for example
  85.  */
  86. static void dmi_table(u8 *buf, int len, int num,
  87.                       void (*decode)(const struct dmi_header *, void *),
  88.                       void *private_data)
  89. {
  90.         u8 *data = buf;
  91.         int i = 0;
  92.  
  93.         /*
  94.          *      Stop when we see all the items the table claimed to have
  95.          *      OR we run off the end of the table (also happens)
  96.          */
  97.         while ((i < num) && (data - buf + sizeof(struct dmi_header)) <= len) {
  98.                 const struct dmi_header *dm = (const struct dmi_header *)data;
  99.  
  100.                 /*
  101.                  *  We want to know the total length (formatted area and
  102.                  *  strings) before decoding to make sure we won't run off the
  103.                  *  table in dmi_decode or dmi_string
  104.                  */
  105.                 data += dm->length;
  106.                 while ((data - buf < len - 1) && (data[0] || data[1]))
  107.                         data++;
  108.                 if (data - buf < len - 1)
  109.                         decode(dm, private_data);
  110.                 data += 2;
  111.                 i++;
  112.         }
  113. }
  114.  
  115. static u32 dmi_base;
  116. static u16 dmi_len;
  117. static u16 dmi_num;
  118.  
  119. static int __init dmi_walk_early(void (*decode)(const struct dmi_header *,
  120.         void *))
  121. {
  122.         u8 *buf;
  123.  
  124.         buf = (u8*)MapIoMem(dmi_base, dmi_len, PG_SW);
  125.         if (buf == NULL)
  126.                 return -1;
  127.  
  128.         dmi_table(buf, dmi_len, dmi_num, decode, NULL);
  129.  
  130.         FreeKernelSpace(buf);
  131.  
  132.     return 0;
  133. }
  134.  
  135. static int __init dmi_checksum(const u8 *buf, u8 len)
  136. {
  137.     u8 sum = 0;
  138.     int a;
  139.  
  140.     for (a = 0; a < len; a++)
  141.         sum += buf[a];
  142.  
  143.     return sum == 0;
  144. }
  145.  
  146. static const char *dmi_ident[DMI_STRING_MAX];
  147. static LIST_HEAD(dmi_devices);
  148. int dmi_available;
  149.  
  150. /*
  151.  *  Save a DMI string
  152.  */
  153. static void __init dmi_save_ident(const struct dmi_header *dm, int slot,
  154.         int string)
  155. {
  156.     const char *d = (const char *) dm;
  157.     const char *p;
  158.  
  159.     if (dmi_ident[slot])
  160.         return;
  161.  
  162.     p = dmi_string(dm, d[string]);
  163.     if (p == NULL)
  164.         return;
  165.  
  166.     dmi_ident[slot] = p;
  167. }
  168.  
  169. static void __init dmi_save_uuid(const struct dmi_header *dm, int slot,
  170.         int index)
  171. {
  172.     const u8 *d = (u8 *) dm + index;
  173.     char *s;
  174.     int is_ff = 1, is_00 = 1, i;
  175.  
  176.     if (dmi_ident[slot])
  177.         return;
  178.  
  179.     for (i = 0; i < 16 && (is_ff || is_00); i++) {
  180.         if (d[i] != 0x00)
  181.             is_00 = 0;
  182.         if (d[i] != 0xFF)
  183.             is_ff = 0;
  184.     }
  185.  
  186.     if (is_ff || is_00)
  187.         return;
  188.  
  189.     s = dmi_alloc(16*2+4+1);
  190.     if (!s)
  191.         return;
  192.  
  193.     /*
  194.      * As of version 2.6 of the SMBIOS specification, the first 3 fields of
  195.      * the UUID are supposed to be little-endian encoded.  The specification
  196.      * says that this is the defacto standard.
  197.      */
  198.     if (dmi_ver >= 0x0206)
  199.         sprintf(s, "%pUL", d);
  200.     else
  201.         sprintf(s, "%pUB", d);
  202.  
  203.     dmi_ident[slot] = s;
  204. }
  205.  
  206. static void __init dmi_save_type(const struct dmi_header *dm, int slot,
  207.         int index)
  208. {
  209.     const u8 *d = (u8 *) dm + index;
  210.     char *s;
  211.  
  212.     if (dmi_ident[slot])
  213.         return;
  214.  
  215.     s = dmi_alloc(4);
  216.     if (!s)
  217.         return;
  218.  
  219.     sprintf(s, "%u", *d & 0x7F);
  220.     dmi_ident[slot] = s;
  221. }
  222.  
  223. static void __init dmi_save_one_device(int type, const char *name)
  224. {
  225.     struct dmi_device *dev;
  226.  
  227.     /* No duplicate device */
  228.     if (dmi_find_device(type, name, NULL))
  229.         return;
  230.  
  231.     dev = dmi_alloc(sizeof(*dev) + strlen(name) + 1);
  232.     if (!dev)
  233.         return;
  234.  
  235.     dev->type = type;
  236.     strcpy((char *)(dev + 1), name);
  237.     dev->name = (char *)(dev + 1);
  238.     dev->device_data = NULL;
  239.     list_add(&dev->list, &dmi_devices);
  240. }
  241.  
  242. static void __init dmi_save_devices(const struct dmi_header *dm)
  243. {
  244.     int i, count = (dm->length - sizeof(struct dmi_header)) / 2;
  245.  
  246.     for (i = 0; i < count; i++) {
  247.         const char *d = (char *)(dm + 1) + (i * 2);
  248.  
  249.         /* Skip disabled device */
  250.         if ((*d & 0x80) == 0)
  251.             continue;
  252.  
  253.         dmi_save_one_device(*d & 0x7f, dmi_string_nosave(dm, *(d + 1)));
  254.     }
  255. }
  256.  
  257. static void __init dmi_save_oem_strings_devices(const struct dmi_header *dm)
  258. {
  259.     int i, count = *(u8 *)(dm + 1);
  260.     struct dmi_device *dev;
  261.  
  262.     for (i = 1; i <= count; i++) {
  263.         const char *devname = dmi_string(dm, i);
  264.  
  265.         if (devname == dmi_empty_string)
  266.             continue;
  267.  
  268.         dev = dmi_alloc(sizeof(*dev));
  269.         if (!dev)
  270.             break;
  271.  
  272.         dev->type = DMI_DEV_TYPE_OEM_STRING;
  273.         dev->name = devname;
  274.         dev->device_data = NULL;
  275.  
  276.         list_add(&dev->list, &dmi_devices);
  277.     }
  278. }
  279.  
  280. static void __init dmi_save_ipmi_device(const struct dmi_header *dm)
  281. {
  282.         struct dmi_device *dev;
  283.         void *data;
  284.  
  285.         data = dmi_alloc(dm->length);
  286.         if (data == NULL)
  287.                 return;
  288.  
  289.         memcpy(data, dm, dm->length);
  290.  
  291.         dev = dmi_alloc(sizeof(*dev));
  292.         if (!dev)
  293.                 return;
  294.  
  295.         dev->type = DMI_DEV_TYPE_IPMI;
  296.         dev->name = "IPMI controller";
  297.         dev->device_data = data;
  298.  
  299.         list_add_tail(&dev->list, &dmi_devices);
  300. }
  301.  
  302. static void __init dmi_save_dev_onboard(int instance, int segment, int bus,
  303.                                         int devfn, const char *name)
  304. {
  305.         struct dmi_dev_onboard *onboard_dev;
  306.  
  307.         onboard_dev = dmi_alloc(sizeof(*onboard_dev) + strlen(name) + 1);
  308.         if (!onboard_dev)
  309.                 return;
  310.  
  311.         onboard_dev->instance = instance;
  312.         onboard_dev->segment = segment;
  313.         onboard_dev->bus = bus;
  314.         onboard_dev->devfn = devfn;
  315.  
  316.         strcpy((char *)&onboard_dev[1], name);
  317.         onboard_dev->dev.type = DMI_DEV_TYPE_DEV_ONBOARD;
  318.         onboard_dev->dev.name = (char *)&onboard_dev[1];
  319.         onboard_dev->dev.device_data = onboard_dev;
  320.  
  321.         list_add(&onboard_dev->dev.list, &dmi_devices);
  322. }
  323.  
  324. static void __init dmi_save_extended_devices(const struct dmi_header *dm)
  325. {
  326.         const u8 *d = (u8 *) dm + 5;
  327.  
  328.         /* Skip disabled device */
  329.         if ((*d & 0x80) == 0)
  330.                 return;
  331.  
  332.         dmi_save_dev_onboard(*(d+1), *(u16 *)(d+2), *(d+4), *(d+5),
  333.                              dmi_string_nosave(dm, *(d-1)));
  334.         dmi_save_one_device(*d & 0x7f, dmi_string_nosave(dm, *(d - 1)));
  335.  
  336. }
  337.  
  338. /*
  339.  *  Process a DMI table entry. Right now all we care about are the BIOS
  340.  *  and machine entries. For 2.5 we should pull the smbus controller info
  341.  *  out of here.
  342.  */
  343. static void __init dmi_decode(const struct dmi_header *dm, void *dummy)
  344. {
  345.     switch (dm->type) {
  346.     case 0:     /* BIOS Information */
  347.         dmi_save_ident(dm, DMI_BIOS_VENDOR, 4);
  348.         dmi_save_ident(dm, DMI_BIOS_VERSION, 5);
  349.         dmi_save_ident(dm, DMI_BIOS_DATE, 8);
  350.         break;
  351.     case 1:     /* System Information */
  352.         dmi_save_ident(dm, DMI_SYS_VENDOR, 4);
  353.         dmi_save_ident(dm, DMI_PRODUCT_NAME, 5);
  354.         dmi_save_ident(dm, DMI_PRODUCT_VERSION, 6);
  355.         dmi_save_ident(dm, DMI_PRODUCT_SERIAL, 7);
  356.         dmi_save_uuid(dm, DMI_PRODUCT_UUID, 8);
  357.         break;
  358.     case 2:     /* Base Board Information */
  359.         dmi_save_ident(dm, DMI_BOARD_VENDOR, 4);
  360.         dmi_save_ident(dm, DMI_BOARD_NAME, 5);
  361.         dmi_save_ident(dm, DMI_BOARD_VERSION, 6);
  362.         dmi_save_ident(dm, DMI_BOARD_SERIAL, 7);
  363.         dmi_save_ident(dm, DMI_BOARD_ASSET_TAG, 8);
  364.         break;
  365.     case 3:     /* Chassis Information */
  366.         dmi_save_ident(dm, DMI_CHASSIS_VENDOR, 4);
  367.         dmi_save_type(dm, DMI_CHASSIS_TYPE, 5);
  368.         dmi_save_ident(dm, DMI_CHASSIS_VERSION, 6);
  369.         dmi_save_ident(dm, DMI_CHASSIS_SERIAL, 7);
  370.         dmi_save_ident(dm, DMI_CHASSIS_ASSET_TAG, 8);
  371.         break;
  372.     case 10:    /* Onboard Devices Information */
  373.         dmi_save_devices(dm);
  374.         break;
  375.     case 11:    /* OEM Strings */
  376.         dmi_save_oem_strings_devices(dm);
  377.         break;
  378.     case 38:    /* IPMI Device Information */
  379.         dmi_save_ipmi_device(dm);
  380.         break;
  381.     case 41:    /* Onboard Devices Extended Information */
  382.         dmi_save_extended_devices(dm);
  383.     }
  384. }
  385.  
  386. static int __init print_filtered(char *buf, size_t len, const char *info)
  387. {
  388.         int c = 0;
  389.         const char *p;
  390.  
  391.         if (!info)
  392.                 return c;
  393.  
  394.         for (p = info; *p; p++)
  395.                 if (isprint(*p))
  396.                         c += scnprintf(buf + c, len - c, "%c", *p);
  397.                 else
  398.                         c += scnprintf(buf + c, len - c, "\\x%02x", *p & 0xff);
  399.         return c;
  400. }
  401.  
  402. static void __init dmi_format_ids(char *buf, size_t len)
  403. {
  404.     int c = 0;
  405.     const char *board;  /* Board Name is optional */
  406.  
  407.     c += print_filtered(buf + c, len - c,
  408.                 dmi_get_system_info(DMI_SYS_VENDOR));
  409.     c += scnprintf(buf + c, len - c, " ");
  410.     c += print_filtered(buf + c, len - c,
  411.                 dmi_get_system_info(DMI_PRODUCT_NAME));
  412.  
  413.     board = dmi_get_system_info(DMI_BOARD_NAME);
  414.     if (board) {
  415.         c += scnprintf(buf + c, len - c, "/");
  416.         c += print_filtered(buf + c, len - c, board);
  417.     }
  418.     c += scnprintf(buf + c, len - c, ", BIOS ");
  419.     c += print_filtered(buf + c, len - c,
  420.                 dmi_get_system_info(DMI_BIOS_VERSION));
  421.     c += scnprintf(buf + c, len - c, " ");
  422.     c += print_filtered(buf + c, len - c,
  423.                 dmi_get_system_info(DMI_BIOS_DATE));
  424. }
  425.  
  426. /*
  427.  * Check for DMI/SMBIOS headers in the system firmware image.  Any
  428.  * SMBIOS header must start 16 bytes before the DMI header, so take a
  429.  * 32 byte buffer and check for DMI at offset 16 and SMBIOS at offset
  430.  * 0.  If the DMI header is present, set dmi_ver accordingly (SMBIOS
  431.  * takes precedence) and return 0.  Otherwise return 1.
  432.  */
  433. static int __init dmi_present(const u8 *buf)
  434. {
  435.     int smbios_ver;
  436.  
  437.     if (memcmp(buf, "_SM_", 4) == 0 &&
  438.         buf[5] < 32 && dmi_checksum(buf, buf[5])) {
  439.         smbios_ver = (buf[6] << 8) + buf[7];
  440.  
  441.         /* Some BIOS report weird SMBIOS version, fix that up */
  442.         switch (smbios_ver) {
  443.         case 0x021F:
  444.         case 0x0221:
  445.             pr_debug("SMBIOS version fixup(2.%d->2.%d)\n",
  446.                  smbios_ver & 0xFF, 3);
  447.             smbios_ver = 0x0203;
  448.             break;
  449.         case 0x0233:
  450.             pr_debug("SMBIOS version fixup(2.%d->2.%d)\n", 51, 6);
  451.             smbios_ver = 0x0206;
  452.             break;
  453.         }
  454.     } else {
  455.         smbios_ver = 0;
  456.     }
  457.  
  458.     buf += 16;
  459.  
  460.     if (memcmp(buf, "_DMI_", 5) == 0 && dmi_checksum(buf, 15)) {
  461.         dmi_num = (buf[13] << 8) | buf[12];
  462.         dmi_len = (buf[7] << 8) | buf[6];
  463.         dmi_base = (buf[11] << 24) | (buf[10] << 16) |
  464.             (buf[9] << 8) | buf[8];
  465.  
  466.         if (dmi_walk_early(dmi_decode) == 0) {
  467.             if (smbios_ver) {
  468.                 dmi_ver = smbios_ver;
  469.                 pr_info("SMBIOS %d.%d present.\n",
  470.                        dmi_ver >> 8, dmi_ver & 0xFF);
  471.             } else {
  472.                 dmi_ver = (buf[14] & 0xF0) << 4 |
  473.                        (buf[14] & 0x0F);
  474.                 pr_info("Legacy DMI %d.%d present.\n",
  475.                        dmi_ver >> 8, dmi_ver & 0xFF);
  476.             }
  477.                         dmi_format_ids(dmi_ids_string, sizeof(dmi_ids_string));
  478.                         printk(KERN_DEBUG "DMI: %s\n", dmi_ids_string);
  479.             return 0;
  480.         }
  481.     }
  482.  
  483.     return 1;
  484. }
  485.  
  486. void __init dmi_scan_machine(void)
  487. {
  488.     char __iomem *p, *q;
  489.         char buf[32];
  490.  
  491.  
  492.  
  493.     p = (char*)0x800F0000;
  494.  
  495.     /*
  496.      * Iterate over all possible DMI header addresses q.
  497.      * Maintain the 32 bytes around q in buf.  On the
  498.      * first iteration, substitute zero for the
  499.      * out-of-range bytes so there is no chance of falsely
  500.      * detecting an SMBIOS header.
  501.      */
  502.     memset(buf, 0, 16);
  503.     for (q = p; q < p + 0x10000; q += 16) {
  504.         memcpy(buf + 16, q, 16);
  505.         if (!dmi_present(buf)) {
  506.             dmi_available = 1;
  507.             goto out;
  508.         }
  509.         memcpy(buf, buf + 16, 16);
  510.     }
  511.  error:
  512.     pr_info("DMI not present or invalid.\n");
  513.  out:
  514.     dmi_initialized = 1;
  515. }
  516.  
  517. /**
  518. /**
  519.  *      dmi_matches - check if dmi_system_id structure matches system DMI data
  520.  *      @dmi: pointer to the dmi_system_id structure to check
  521.  */
  522. static bool dmi_matches(const struct dmi_system_id *dmi)
  523. {
  524.         int i;
  525.  
  526.         WARN(!dmi_initialized, KERN_ERR "dmi check: not initialized yet.\n");
  527.  
  528.         for (i = 0; i < ARRAY_SIZE(dmi->matches); i++) {
  529.                 int s = dmi->matches[i].slot;
  530.                 if (s == DMI_NONE)
  531.                         break;
  532.                 if (dmi_ident[s]) {
  533.                         if (!dmi->matches[i].exact_match &&
  534.                             strstr(dmi_ident[s], dmi->matches[i].substr))
  535.                                 continue;
  536.                         else if (dmi->matches[i].exact_match &&
  537.                                  !strcmp(dmi_ident[s], dmi->matches[i].substr))
  538.                                 continue;
  539.                 }
  540.  
  541.                 /* No match */
  542.                 return false;
  543.         }
  544.         return true;
  545. }
  546.  
  547. /**
  548.  *      dmi_is_end_of_table - check for end-of-table marker
  549.  *      @dmi: pointer to the dmi_system_id structure to check
  550.  */
  551. static bool dmi_is_end_of_table(const struct dmi_system_id *dmi)
  552. {
  553.         return dmi->matches[0].slot == DMI_NONE;
  554. }
  555.  
  556. /**
  557.  *      dmi_check_system - check system DMI data
  558.  *      @list: array of dmi_system_id structures to match against
  559.  *              All non-null elements of the list must match
  560.  *              their slot's (field index's) data (i.e., each
  561.  *              list string must be a substring of the specified
  562.  *              DMI slot's string data) to be considered a
  563.  *              successful match.
  564.  *
  565.  *      Walk the blacklist table running matching functions until someone
  566.  *      returns non zero or we hit the end. Callback function is called for
  567.  *      each successful match. Returns the number of matches.
  568.  */
  569. int dmi_check_system(const struct dmi_system_id *list)
  570. {
  571.         int count = 0;
  572.         const struct dmi_system_id *d;
  573.  
  574.         for (d = list; !dmi_is_end_of_table(d); d++)
  575.                 if (dmi_matches(d)) {
  576.                         count++;
  577.                         if (d->callback && d->callback(d))
  578.                                 break;
  579.                 }
  580.  
  581.         return count;
  582. }
  583. EXPORT_SYMBOL(dmi_check_system);
  584.  
  585. /**
  586.  *  dmi_get_system_info - return DMI data value
  587.  *  @field: data index (see enum dmi_field)
  588.  *
  589.  *  Returns one DMI data value, can be used to perform
  590.  *  complex DMI data checks.
  591.  */
  592. const char *dmi_get_system_info(int field)
  593. {
  594.     return dmi_ident[field];
  595. }
  596. EXPORT_SYMBOL(dmi_get_system_info);
  597. /**
  598.  *      dmi_find_device - find onboard device by type/name
  599.  *      @type: device type or %DMI_DEV_TYPE_ANY to match all device types
  600.  *      @name: device name string or %NULL to match all
  601.  *      @from: previous device found in search, or %NULL for new search.
  602.  *
  603.  *      Iterates through the list of known onboard devices. If a device is
  604.  *      found with a matching @vendor and @device, a pointer to its device
  605.  *      structure is returned.  Otherwise, %NULL is returned.
  606.  *      A new search is initiated by passing %NULL as the @from argument.
  607.  *      If @from is not %NULL, searches continue from next device.
  608.  */
  609. const struct dmi_device *dmi_find_device(int type, const char *name,
  610.                                     const struct dmi_device *from)
  611. {
  612.         const struct list_head *head = from ? &from->list : &dmi_devices;
  613.         struct list_head *d;
  614.  
  615.         for (d = head->next; d != &dmi_devices; d = d->next) {
  616.                 const struct dmi_device *dev =
  617.                         list_entry(d, struct dmi_device, list);
  618.  
  619.                 if (((type == DMI_DEV_TYPE_ANY) || (dev->type == type)) &&
  620.                     ((name == NULL) || (strcmp(dev->name, name) == 0)))
  621.                         return dev;
  622.         }
  623.  
  624.         return NULL;
  625. }
  626. EXPORT_SYMBOL(dmi_find_device);
  627.