Subversion Repositories Kolibri OS

Rev

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