diff options
author | Tejun Heo <htejun@gmail.com> | 2009-08-16 08:02:36 -0400 |
---|---|---|
committer | Jeff Garzik <jgarzik@redhat.com> | 2009-09-08 21:17:48 -0400 |
commit | 3e5cd1f2576c720f1d0705fdd7ba64f27e8836b7 (patch) | |
tree | 631d41c950d2dc93c110ca86e779cb749c9a8987 | |
parent | 02c24fa87724bb3af969463cd74dc3b3feb24740 (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.c | 5 | ||||
-rw-r--r-- | drivers/acpi/blacklist.c | 5 | ||||
-rw-r--r-- | drivers/ata/ahci.c | 2 | ||||
-rw-r--r-- | drivers/firmware/dmi_scan.c | 76 | ||||
-rw-r--r-- | include/linux/dmi.h | 13 |
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 = { | |||
192 | static int __init pci_sanity_check(struct pci_raw_ops *o) | 192 | static 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 | ||
79 | static int __init blacklist_by_year(void) | 79 | static 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, | |||
568 | EXPORT_SYMBOL(dmi_find_device); | 568 | EXPORT_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 | */ |
576 | int dmi_get_year(int field) | 588 | bool 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; | ||
631 | out: | ||
632 | if (yearp) | ||
633 | *yearp = year; | ||
634 | if (monthp) | ||
635 | *monthp = month; | ||
636 | if (dayp) | ||
637 | *dayp = day; | ||
638 | return exists; | ||
599 | } | 639 | } |
600 | EXPORT_SYMBOL(dmi_get_year); | 640 | EXPORT_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); | |||
43 | extern const struct dmi_device * dmi_find_device(int type, const char *name, | 43 | extern const struct dmi_device * dmi_find_device(int type, const char *name, |
44 | const struct dmi_device *from); | 44 | const struct dmi_device *from); |
45 | extern void dmi_scan_machine(void); | 45 | extern void dmi_scan_machine(void); |
46 | extern int dmi_get_year(int field); | 46 | extern bool dmi_get_date(int field, int *yearp, int *monthp, int *dayp); |
47 | extern int dmi_name_in_vendors(const char *str); | 47 | extern int dmi_name_in_vendors(const char *str); |
48 | extern int dmi_name_in_serial(const char *str); | 48 | extern int dmi_name_in_serial(const char *str); |
49 | extern int dmi_available; | 49 | extern int dmi_available; |
@@ -58,7 +58,16 @@ static inline const char * dmi_get_system_info(int field) { return NULL; } | |||
58 | static inline const struct dmi_device * dmi_find_device(int type, const char *name, | 58 | static 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; } |
60 | static inline void dmi_scan_machine(void) { return; } | 60 | static inline void dmi_scan_machine(void) { return; } |
61 | static inline int dmi_get_year(int year) { return 0; } | 61 | static 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 | } | ||
62 | static inline int dmi_name_in_vendors(const char *s) { return 0; } | 71 | static inline int dmi_name_in_vendors(const char *s) { return 0; } |
63 | static inline int dmi_name_in_serial(const char *s) { return 0; } | 72 | static inline int dmi_name_in_serial(const char *s) { return 0; } |
64 | #define dmi_available 0 | 73 | #define dmi_available 0 |