diff options
author | Ingo Molnar <mingo@elte.hu> | 2009-09-15 12:18:15 +0200 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2009-09-15 12:18:15 +0200 |
commit | dca2d6ac09d9ef59ff46820d4f0c94b08a671202 (patch) | |
tree | fdec753b842dad09e3a4151954fab3eb5c43500d /drivers/firmware/dmi_scan.c | |
parent | d6a65dffb30d8636b1e5d4c201564ef401a246cf (diff) | |
parent | 18240904960a39e582ced8ba8ececb10b8c22dd3 (diff) |
Merge branch 'linus' into tracing/hw-breakpoints
Conflicts:
arch/x86/kernel/process_64.c
Semantic conflict fixed in:
arch/x86/kvm/x86.c
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'drivers/firmware/dmi_scan.c')
-rw-r--r-- | drivers/firmware/dmi_scan.c | 77 |
1 files changed, 59 insertions, 18 deletions
diff --git a/drivers/firmware/dmi_scan.c b/drivers/firmware/dmi_scan.c index 24c84ae8152..938100f14b1 100644 --- a/drivers/firmware/dmi_scan.c +++ b/drivers/firmware/dmi_scan.c @@ -568,35 +568,76 @@ const struct dmi_device * dmi_find_device(int type, const char *name, EXPORT_SYMBOL(dmi_find_device); /** - * dmi_get_year - Return year of a DMI date - * @field: data index (like dmi_get_system_info) + * dmi_get_date - parse a DMI date + * @field: data index (see enum dmi_field) + * @yearp: optional out parameter for the year + * @monthp: optional out parameter for the month + * @dayp: optional out parameter for the day * - * Returns -1 when the field doesn't exist. 0 when it is broken. + * The date field is assumed to be in the form resembling + * [mm[/dd]]/yy[yy] and the result is stored in the out + * parameters any or all of which can be omitted. + * + * If the field doesn't exist, all out parameters are set to zero + * and false is returned. Otherwise, true is returned with any + * invalid part of date set to zero. + * + * On return, year, month and day are guaranteed to be in the + * range of [0,9999], [0,12] and [0,31] respectively. */ -int dmi_get_year(int field) +bool dmi_get_date(int field, int *yearp, int *monthp, int *dayp) { - int year; - const char *s = dmi_get_system_info(field); + int year = 0, month = 0, day = 0; + bool exists; + const char *s, *y; + char *e; - if (!s) - return -1; - if (*s == '\0') - return 0; - s = strrchr(s, '/'); - if (!s) - return 0; + s = dmi_get_system_info(field); + exists = s; + if (!exists) + goto out; - s += 1; - year = simple_strtoul(s, NULL, 0); - if (year && year < 100) { /* 2-digit year */ + /* + * Determine year first. We assume the date string resembles + * mm/dd/yy[yy] but the original code extracted only the year + * from the end. Keep the behavior in the spirit of no + * surprises. + */ + y = strrchr(s, '/'); + if (!y) + goto out; + + y++; + year = simple_strtoul(y, &e, 10); + if (y != e && year < 100) { /* 2-digit year */ year += 1900; if (year < 1996) /* no dates < spec 1.0 */ year += 100; } + if (year > 9999) /* year should fit in %04d */ + year = 0; + + /* parse the mm and dd */ + month = simple_strtoul(s, &e, 10); + if (s == e || *e != '/' || !month || month > 12) { + month = 0; + goto out; + } - return year; + s = e + 1; + day = simple_strtoul(s, &e, 10); + if (s == y || s == e || *e != '/' || day > 31) + day = 0; +out: + if (yearp) + *yearp = year; + if (monthp) + *monthp = month; + if (dayp) + *dayp = day; + return exists; } -EXPORT_SYMBOL(dmi_get_year); +EXPORT_SYMBOL(dmi_get_date); /** * dmi_walk - Walk the DMI table and get called back for every record |