Automatic MODULE_ALIAS() for DMI match tables.
This makes modpost handle MODULE_DEVICE_TABLE(dmi, xxxx). I had to change the string pointers in the match table to char arrays, and picked a size of 79 bytes almost at random -- do we need to make it bigger than that? I was a bit concerned about the 'bloat' this introduces into the match tables, but they should all be __initdata so it shouldn't matter too much. (Actually, modpost does go through the relocations and look at most of them; it wouldn't be impossible to make it handle string pointers -- but doesn't seem to be worth the effort, since they're __initdata). Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
This commit is contained in:
parent
9d5a9e7465
commit
d945b697d0
|
@ -2,29 +2,9 @@
|
|||
#define __DMI_H__
|
||||
|
||||
#include <linux/list.h>
|
||||
#include <linux/mod_devicetable.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_PRODUCT_SERIAL,
|
||||
DMI_PRODUCT_UUID,
|
||||
DMI_BOARD_VENDOR,
|
||||
DMI_BOARD_NAME,
|
||||
DMI_BOARD_VERSION,
|
||||
DMI_BOARD_SERIAL,
|
||||
DMI_BOARD_ASSET_TAG,
|
||||
DMI_CHASSIS_VENDOR,
|
||||
DMI_CHASSIS_TYPE,
|
||||
DMI_CHASSIS_VERSION,
|
||||
DMI_CHASSIS_SERIAL,
|
||||
DMI_CHASSIS_ASSET_TAG,
|
||||
DMI_STRING_MAX,
|
||||
};
|
||||
/* enum dmi_field is in mod_devicetable.h */
|
||||
|
||||
enum dmi_device_type {
|
||||
DMI_DEV_TYPE_ANY = 0,
|
||||
|
@ -48,23 +28,6 @@ struct dmi_header {
|
|||
u16 handle;
|
||||
};
|
||||
|
||||
/*
|
||||
* DMI callbacks for problem boards
|
||||
*/
|
||||
struct dmi_strmatch {
|
||||
u8 slot;
|
||||
char *substr;
|
||||
};
|
||||
|
||||
struct dmi_system_id {
|
||||
int (*callback)(const struct dmi_system_id *);
|
||||
const char *ident;
|
||||
struct dmi_strmatch matches[4];
|
||||
void *driver_data;
|
||||
};
|
||||
|
||||
#define DMI_MATCH(a, b) { a, b }
|
||||
|
||||
struct dmi_device {
|
||||
struct list_head list;
|
||||
int type;
|
||||
|
|
|
@ -388,5 +388,52 @@ struct i2c_device_id {
|
|||
__attribute__((aligned(sizeof(kernel_ulong_t))));
|
||||
};
|
||||
|
||||
/* dmi */
|
||||
enum dmi_field {
|
||||
DMI_NONE,
|
||||
DMI_BIOS_VENDOR,
|
||||
DMI_BIOS_VERSION,
|
||||
DMI_BIOS_DATE,
|
||||
DMI_SYS_VENDOR,
|
||||
DMI_PRODUCT_NAME,
|
||||
DMI_PRODUCT_VERSION,
|
||||
DMI_PRODUCT_SERIAL,
|
||||
DMI_PRODUCT_UUID,
|
||||
DMI_BOARD_VENDOR,
|
||||
DMI_BOARD_NAME,
|
||||
DMI_BOARD_VERSION,
|
||||
DMI_BOARD_SERIAL,
|
||||
DMI_BOARD_ASSET_TAG,
|
||||
DMI_CHASSIS_VENDOR,
|
||||
DMI_CHASSIS_TYPE,
|
||||
DMI_CHASSIS_VERSION,
|
||||
DMI_CHASSIS_SERIAL,
|
||||
DMI_CHASSIS_ASSET_TAG,
|
||||
DMI_STRING_MAX,
|
||||
};
|
||||
|
||||
struct dmi_strmatch {
|
||||
unsigned char slot;
|
||||
char substr[79];
|
||||
};
|
||||
|
||||
#ifndef __KERNEL__
|
||||
struct dmi_system_id {
|
||||
kernel_ulong_t callback;
|
||||
kernel_ulong_t ident;
|
||||
struct dmi_strmatch matches[4];
|
||||
kernel_ulong_t driver_data
|
||||
__attribute__((aligned(sizeof(kernel_ulong_t))));
|
||||
};
|
||||
#else
|
||||
struct dmi_system_id {
|
||||
int (*callback)(const struct dmi_system_id *);
|
||||
const char *ident;
|
||||
struct dmi_strmatch matches[4];
|
||||
void *driver_data;
|
||||
};
|
||||
#endif
|
||||
|
||||
#define DMI_MATCH(a, b) { a, b }
|
||||
|
||||
#endif /* LINUX_MOD_DEVICETABLE_H */
|
||||
|
|
|
@ -629,6 +629,59 @@ static int do_i2c_entry(const char *filename, struct i2c_device_id *id,
|
|||
return 1;
|
||||
}
|
||||
|
||||
static const struct dmifield {
|
||||
const char *prefix;
|
||||
int field;
|
||||
} dmi_fields[] = {
|
||||
{ "bvn", DMI_BIOS_VENDOR },
|
||||
{ "bvr", DMI_BIOS_VERSION },
|
||||
{ "bd", DMI_BIOS_DATE },
|
||||
{ "svn", DMI_SYS_VENDOR },
|
||||
{ "pn", DMI_PRODUCT_NAME },
|
||||
{ "pvr", DMI_PRODUCT_VERSION },
|
||||
{ "rvn", DMI_BOARD_VENDOR },
|
||||
{ "rn", DMI_BOARD_NAME },
|
||||
{ "rvr", DMI_BOARD_VERSION },
|
||||
{ "cvn", DMI_CHASSIS_VENDOR },
|
||||
{ "ct", DMI_CHASSIS_TYPE },
|
||||
{ "cvr", DMI_CHASSIS_VERSION },
|
||||
{ NULL, DMI_NONE }
|
||||
};
|
||||
|
||||
static void dmi_ascii_filter(char *d, const char *s)
|
||||
{
|
||||
/* Filter out characters we don't want to see in the modalias string */
|
||||
for (; *s; s++)
|
||||
if (*s > ' ' && *s < 127 && *s != ':')
|
||||
*(d++) = *s;
|
||||
|
||||
*d = 0;
|
||||
}
|
||||
|
||||
|
||||
static int do_dmi_entry(const char *filename, struct dmi_system_id *id,
|
||||
char *alias)
|
||||
{
|
||||
int i, j;
|
||||
|
||||
sprintf(alias, "dmi*");
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(dmi_fields); i++) {
|
||||
for (j = 0; j < 4; j++) {
|
||||
if (id->matches[j].slot &&
|
||||
id->matches[j].slot == dmi_fields[i].field) {
|
||||
sprintf(alias + strlen(alias), ":%s*",
|
||||
dmi_fields[i].prefix);
|
||||
dmi_ascii_filter(alias + strlen(alias),
|
||||
id->matches[j].substr);
|
||||
strcat(alias, "*");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
strcat(alias, ":");
|
||||
return 1;
|
||||
}
|
||||
/* Ignore any prefix, eg. some architectures prepend _ */
|
||||
static inline int sym_is(const char *symbol, const char *name)
|
||||
{
|
||||
|
@ -760,6 +813,10 @@ void handle_moddevtable(struct module *mod, struct elf_info *info,
|
|||
do_table(symval, sym->st_size,
|
||||
sizeof(struct i2c_device_id), "i2c",
|
||||
do_i2c_entry, mod);
|
||||
else if (sym_is(symname, "__mod_dmi_device_table"))
|
||||
do_table(symval, sym->st_size,
|
||||
sizeof(struct dmi_system_id), "dmi",
|
||||
do_dmi_entry, mod);
|
||||
free(zeros);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue