aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTejun Heo <htejun@gmail.com>2009-08-16 08:02:36 -0400
committerJeff Garzik <jgarzik@redhat.com>2009-09-08 21:17:48 -0400
commit3e5cd1f2576c720f1d0705fdd7ba64f27e8836b7 (patch)
tree631d41c950d2dc93c110ca86e779cb749c9a8987
parent02c24fa87724bb3af969463cd74dc3b3feb24740 (diff)
dmi: extend dmi_get_year() to dmi_get_date()
There are cases where full date information is required instead of just the year. Add month and day parsing to dmi_get_year() and rename it to dmi_get_date(). As the original function only required '/' followed by any number of parseable characters at the end of the string, keep that behavior to avoid upsetting existing users. The new function takes dates of format [mm[/dd]]/yy[yy]. Year, month and date are checked to be in the ranges of [1-9999], [1-12] and [1-31] respectively and any invalid or out-of-range component is returned as zero. The dummy implementation is updated accordingly but the return value is updated to indicate field not found which is consistent with how other dummy functions behave. Signed-off-by: Tejun Heo <tj@kernel.org> Signed-off-by: Jeff Garzik <jgarzik@redhat.com>
-rw-r--r--arch/x86/pci/direct.c5
-rw-r--r--drivers/acpi/blacklist.c5
-rw-r--r--drivers/ata/ahci.c2
-rw-r--r--drivers/firmware/dmi_scan.c76
-rw-r--r--include/linux/dmi.h13
5 files changed, 76 insertions, 25 deletions
diff --git a/arch/x86/pci/direct.c b/arch/x86/pci/direct.c
index bd13c3e4c6db..347d882b3bb3 100644
--- a/arch/x86/pci/direct.c
+++ b/arch/x86/pci/direct.c
@@ -192,13 +192,14 @@ struct pci_raw_ops pci_direct_conf2 = {
192static int __init pci_sanity_check(struct pci_raw_ops *o) 192static int __init pci_sanity_check(struct pci_raw_ops *o)
193{ 193{
194 u32 x = 0; 194 u32 x = 0;
195 int devfn; 195 int year, devfn;
196 196
197 if (pci_probe & PCI_NO_CHECKS) 197 if (pci_probe & PCI_NO_CHECKS)
198 return 1; 198 return 1;
199 /* Assume Type 1 works for newer systems. 199 /* Assume Type 1 works for newer systems.
200 This handles machines that don't have anything on PCI Bus 0. */ 200 This handles machines that don't have anything on PCI Bus 0. */
201 if (dmi_get_year(DMI_BIOS_DATE) >= 2001) 201 dmi_get_date(DMI_BIOS_DATE, &year, NULL, NULL);
202 if (year >= 2001)
202 return 1; 203 return 1;
203 204
204 for (devfn = 0; devfn < 0x100; devfn++) { 205 for (devfn = 0; devfn < 0x100; devfn++) {
diff --git a/drivers/acpi/blacklist.c b/drivers/acpi/blacklist.c
index f6baa77deefb..0c4ca4d318b3 100644
--- a/drivers/acpi/blacklist.c
+++ b/drivers/acpi/blacklist.c
@@ -78,9 +78,10 @@ static struct acpi_blacklist_item acpi_blacklist[] __initdata = {
78 78
79static int __init blacklist_by_year(void) 79static int __init blacklist_by_year(void)
80{ 80{
81 int year = dmi_get_year(DMI_BIOS_DATE); 81 int year;
82
82 /* Doesn't exist? Likely an old system */ 83 /* Doesn't exist? Likely an old system */
83 if (year == -1) { 84 if (!dmi_get_date(DMI_BIOS_DATE, &year, NULL, NULL)) {
84 printk(KERN_ERR PREFIX "no DMI BIOS year, " 85 printk(KERN_ERR PREFIX "no DMI BIOS year, "
85 "acpi=force is required to enable ACPI\n" ); 86 "acpi=force is required to enable ACPI\n" );
86 return 1; 87 return 1;
diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c
index be4c39f8ab81..147b9be3b4d2 100644
--- a/drivers/ata/ahci.c
+++ b/drivers/ata/ahci.c
@@ -2679,7 +2679,7 @@ static bool ahci_asus_m2a_vm_32bit_only(struct pci_dev *pdev)
2679 * different versions. 2679 * different versions.
2680 */ 2680 */
2681 date = dmi_get_system_info(DMI_BIOS_DATE); 2681 date = dmi_get_system_info(DMI_BIOS_DATE);
2682 year = dmi_get_year(DMI_BIOS_DATE); 2682 dmi_get_date(DMI_BIOS_DATE, &year, NULL, NULL);
2683 if (date && strlen(date) >= 10 && date[2] == '/' && date[5] == '/' && 2683 if (date && strlen(date) >= 10 && date[2] == '/' && date[5] == '/' &&
2684 (year > 2007 || 2684 (year > 2007 ||
2685 (year == 2007 && strncmp(date, cutoff_mmdd, 5) >= 0))) 2685 (year == 2007 && strncmp(date, cutoff_mmdd, 5) >= 0)))
diff --git a/drivers/firmware/dmi_scan.c b/drivers/firmware/dmi_scan.c
index 531e621677ce..938100f14b16 100644
--- a/drivers/firmware/dmi_scan.c
+++ b/drivers/firmware/dmi_scan.c
@@ -568,36 +568,76 @@ const struct dmi_device * dmi_find_device(int type, const char *name,
568EXPORT_SYMBOL(dmi_find_device); 568EXPORT_SYMBOL(dmi_find_device);
569 569
570/** 570/**
571 * dmi_get_year - Return year of a DMI date 571 * dmi_get_date - parse a DMI date
572 * @field: data index (like dmi_get_system_info) 572 * @field: data index (see enum dmi_field)
573 * @yearp: optional out parameter for the year
574 * @monthp: optional out parameter for the month
575 * @dayp: optional out parameter for the day
573 * 576 *
574 * Returns -1 when the field doesn't exist. 0 when it is broken. 577 * The date field is assumed to be in the form resembling
578 * [mm[/dd]]/yy[yy] and the result is stored in the out
579 * parameters any or all of which can be omitted.
580 *
581 * If the field doesn't exist, all out parameters are set to zero
582 * and false is returned. Otherwise, true is returned with any
583 * invalid part of date set to zero.
584 *
585 * On return, year, month and day are guaranteed to be in the
586 * range of [0,9999], [0,12] and [0,31] respectively.
575 */ 587 */
576int dmi_get_year(int field) 588bool dmi_get_date(int field, int *yearp, int *monthp, int *dayp)
577{ 589{
578 int year; 590 int year = 0, month = 0, day = 0;
579 const char *s = dmi_get_system_info(field); 591 bool exists;
592 const char *s, *y;
580 char *e; 593 char *e;
581 594
582 if (!s) 595 s = dmi_get_system_info(field);
583 return -1; 596 exists = s;
584 if (*s == '\0') 597 if (!exists)
585 return 0; 598 goto out;
586 s = strrchr(s, '/');
587 if (!s)
588 return 0;
589 599
590 s += 1; 600 /*
591 year = simple_strtoul(s, &e, 10); 601 * Determine year first. We assume the date string resembles
592 if (s != e && year < 100) { /* 2-digit year */ 602 * mm/dd/yy[yy] but the original code extracted only the year
603 * from the end. Keep the behavior in the spirit of no
604 * surprises.
605 */
606 y = strrchr(s, '/');
607 if (!y)
608 goto out;
609
610 y++;
611 year = simple_strtoul(y, &e, 10);
612 if (y != e && year < 100) { /* 2-digit year */
593 year += 1900; 613 year += 1900;
594 if (year < 1996) /* no dates < spec 1.0 */ 614 if (year < 1996) /* no dates < spec 1.0 */
595 year += 100; 615 year += 100;
596 } 616 }
617 if (year > 9999) /* year should fit in %04d */
618 year = 0;
619
620 /* parse the mm and dd */
621 month = simple_strtoul(s, &e, 10);
622 if (s == e || *e != '/' || !month || month > 12) {
623 month = 0;
624 goto out;
625 }
597 626
598 return year; 627 s = e + 1;
628 day = simple_strtoul(s, &e, 10);
629 if (s == y || s == e || *e != '/' || day > 31)
630 day = 0;
631out:
632 if (yearp)
633 *yearp = year;
634 if (monthp)
635 *monthp = month;
636 if (dayp)
637 *dayp = day;
638 return exists;
599} 639}
600EXPORT_SYMBOL(dmi_get_year); 640EXPORT_SYMBOL(dmi_get_date);
601 641
602/** 642/**
603 * dmi_walk - Walk the DMI table and get called back for every record 643 * dmi_walk - Walk the DMI table and get called back for every record
diff --git a/include/linux/dmi.h b/include/linux/dmi.h
index bb5489c82c99..a8a3e1ac281d 100644
--- a/include/linux/dmi.h
+++ b/include/linux/dmi.h
@@ -43,7 +43,7 @@ extern const char * dmi_get_system_info(int field);
43extern const struct dmi_device * dmi_find_device(int type, const char *name, 43extern const struct dmi_device * dmi_find_device(int type, const char *name,
44 const struct dmi_device *from); 44 const struct dmi_device *from);
45extern void dmi_scan_machine(void); 45extern void dmi_scan_machine(void);
46extern int dmi_get_year(int field); 46extern bool dmi_get_date(int field, int *yearp, int *monthp, int *dayp);
47extern int dmi_name_in_vendors(const char *str); 47extern int dmi_name_in_vendors(const char *str);
48extern int dmi_name_in_serial(const char *str); 48extern int dmi_name_in_serial(const char *str);
49extern int dmi_available; 49extern int dmi_available;
@@ -58,7 +58,16 @@ static inline const char * dmi_get_system_info(int field) { return NULL; }
58static inline const struct dmi_device * dmi_find_device(int type, const char *name, 58static inline const struct dmi_device * dmi_find_device(int type, const char *name,
59 const struct dmi_device *from) { return NULL; } 59 const struct dmi_device *from) { return NULL; }
60static inline void dmi_scan_machine(void) { return; } 60static inline void dmi_scan_machine(void) { return; }
61static inline int dmi_get_year(int year) { return 0; } 61static inline bool dmi_get_date(int field, int *yearp, int *monthp, int *dayp)
62{
63 if (yearp)
64 *yearp = 0;
65 if (monthp)
66 *monthp = 0;
67 if (dayp)
68 *dayp = 0;
69 return false;
70}
62static inline int dmi_name_in_vendors(const char *s) { return 0; } 71static inline int dmi_name_in_vendors(const char *s) { return 0; }
63static inline int dmi_name_in_serial(const char *s) { return 0; } 72static inline int dmi_name_in_serial(const char *s) { return 0; }
64#define dmi_available 0 73#define dmi_available 0