Skip to content

Commit

Permalink
Automatic MODULE_ALIAS() for DMI match tables.
Browse files Browse the repository at this point in the history
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 <[email protected]>
  • Loading branch information
dwmw2 authored and David Woodhouse committed Oct 13, 2008
1 parent 9d5a9e7 commit d945b69
Show file tree
Hide file tree
Showing 3 changed files with 106 additions and 39 deletions.
41 changes: 2 additions & 39 deletions include/linux/dmi.h
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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;
Expand Down
47 changes: 47 additions & 0 deletions include/linux/mod_devicetable.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
57 changes: 57 additions & 0 deletions scripts/mod/file2alias.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand Down Expand Up @@ -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);
}

Expand Down

0 comments on commit d945b69

Please sign in to comment.