Subversion Repositories Kolibri OS

Rev

Rev 5270 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

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