From: Andrey Panin This patch creates and exports 2 functions which can be used by the rest of kernel code to perform DMI data checks: - dmi_check_system() function checks system DMI data against given blacklist table and on each match runs corresponding callback function; - dmi_get_system_info() function returns DMI data value. Useful for people wanting more complex DMI data check than simple string match. Also filling unused match entries with NO_MATCH made optional, but existing NO_MATCH occurences are left intact, so people are free to continue dmi_scan.c patching without massive reject problems. Signed-off-by: Andrew Morton --- 25-akpm/arch/i386/kernel/dmi_scan.c | 111 +++++++++++++++++------------------- 25-akpm/include/linux/dmi.h | 47 +++++++++++++++ 2 files changed, 102 insertions(+), 56 deletions(-) diff -puN arch/i386/kernel/dmi_scan.c~export-dmi-check-functions arch/i386/kernel/dmi_scan.c --- 25/arch/i386/kernel/dmi_scan.c~export-dmi-check-functions 2004-06-17 22:36:11.123841592 -0700 +++ 25-akpm/arch/i386/kernel/dmi_scan.c 2004-06-17 22:36:11.129840680 -0700 @@ -10,6 +10,7 @@ #include #include #include +#include #include unsigned long dmi_broken; @@ -142,21 +143,6 @@ static int __init dmi_iterate(void (*dec return -1; } - -enum -{ - DMI_BIOS_VENDOR, - DMI_BIOS_VERSION, - DMI_BIOS_DATE, - DMI_SYS_VENDOR, - DMI_PRODUCT_NAME, - DMI_PRODUCT_VERSION, - DMI_BOARD_VENDOR, - DMI_BOARD_NAME, - DMI_BOARD_VERSION, - DMI_STRING_MAX -}; - static char *dmi_ident[DMI_STRING_MAX]; /* @@ -179,26 +165,11 @@ static void __init dmi_save_ident(struct } /* - * DMI callbacks for problem boards + * Ugly compatibility crap. */ - -struct dmi_strmatch -{ - u8 slot; - char *substr; -}; - -#define NONE 255 - -struct dmi_blacklist -{ - int (*callback)(struct dmi_blacklist *); - char *ident; - struct dmi_strmatch matches[4]; -}; - -#define NO_MATCH { NONE, NULL} -#define MATCH(a,b) { a, b } +#define dmi_blacklist dmi_system_id +#define NO_MATCH { DMI_NONE, NULL} +#define MATCH DMI_MATCH /* * Reboot options and system auto-detection code provided by @@ -1114,9 +1085,6 @@ static __initdata struct dmi_blacklist d static __init void dmi_check_blacklist(void) { - struct dmi_blacklist *d; - int i; - #ifdef CONFIG_ACPI_BOOT #define ACPI_BLACKLIST_CUTOFF_YEAR 2001 @@ -1138,25 +1106,7 @@ static __init void dmi_check_blacklist(v } } #endif - - d=&dmi_blacklist[0]; - while(d->callback) - { - for(i=0;i<4;i++) - { - int s = d->matches[i].slot; - if(s==NONE) - continue; - if(dmi_ident[s] && strstr(dmi_ident[s], d->matches[i].substr)) - continue; - /* No match */ - goto fail; - } - if(d->callback(d)) - return; -fail: - d++; - } + dmi_check_system(dmi_blacklist); } @@ -1223,3 +1173,52 @@ void __init dmi_scan_machine(void) } EXPORT_SYMBOL(is_unsafe_smbus); + + +/** + * dmi_check_system - check system DMI data + * @list: array of dmi_system_id structures to match against + * + * Walk the blacklist table running matching functions until someone + * returns non zero or we hit the end. Callback function is called for + * each successfull match. Returns the number of matches. + */ +int dmi_check_system(struct dmi_system_id *list) +{ + int i, count = 0; + struct dmi_system_id *d = list; + + while (d->ident) { + for (i = 0; i < ARRAY_SIZE(d->matches); i++) { + int s = d->matches[i].slot; + if (s == DMI_NONE) + continue; + if (dmi_ident[s] && strstr(dmi_ident[s], d->matches[i].substr)) + continue; + /* No match */ + goto fail; + } + if (d->callback && d->callback(d)) + break; + count++; +fail: d++; + } + + return count; +} + +EXPORT_SYMBOL(dmi_check_system); + +/** + * dmi_get_system_info - return DMI data value + * @field: data index (see enum dmi_filed) + * + * Returns one DMI data value, can be used to perform + * complex DMI data checks. + */ +char * dmi_get_system_info(int field) +{ + return dmi_ident[field]; +} + +EXPORT_SYMBOL(dmi_get_system_info); diff -puN /dev/null include/linux/dmi.h --- /dev/null 2003-09-15 06:40:47.000000000 -0700 +++ 25-akpm/include/linux/dmi.h 2004-06-17 22:36:11.129840680 -0700 @@ -0,0 +1,47 @@ +#ifndef __DMI_H__ +#define __DMI_H__ + +enum dmi_field { + DMI_NONE, + DMI_BIOS_VENDOR, + DMI_BIOS_VERSION, + DMI_BIOS_DATE, + DMI_SYS_VENDOR, + DMI_PRODUCT_NAME, + DMI_PRODUCT_VERSION, + DMI_BOARD_VENDOR, + DMI_BOARD_NAME, + DMI_BOARD_VERSION, + DMI_STRING_MAX, +}; + +/* + * DMI callbacks for problem boards + */ +struct dmi_strmatch { + u8 slot; + char *substr; +}; + +struct dmi_system_id { + int (*callback)(struct dmi_system_id *); + char *ident; + struct dmi_strmatch matches[4]; + void *driver_data; +}; + +#define DMI_MATCH(a,b) { a, b } + +#if defined(CONFIG_X86) && !defined(CONFIG_X86_64) + +extern int dmi_check_system(struct dmi_system_id *list); +extern char * dmi_get_system_info(int field); + +#else + +static inline int dmi_check_system(struct dmi_system_id *list) { return 0; } +static inline char * dmi_get_system_info(int field) { return NULL; } + +#endif + +#endif /* __DMI_H__ */ _