Skip to content

Commit

Permalink
dmi: Let drivers walk the DMI table
Browse files Browse the repository at this point in the history
Let drivers walk the DMI table for their own needs. Some drivers need
data stored in OEM-specific DMI records for proper operation.

Signed-off-by: Jean Delvare <khali@linux-fr.org>
Signed-off-by: Mark M. Hoffman <mhoffman@lightlink.com>
  • Loading branch information
Jean Delvare authored and Mark M. Hoffman committed Feb 8, 2008
1 parent df92207 commit 7fce084
Show file tree
Hide file tree
Showing 2 changed files with 51 additions and 14 deletions.
62 changes: 48 additions & 14 deletions drivers/firmware/dmi_scan.c
Original file line number Diff line number Diff line change
Expand Up @@ -43,18 +43,12 @@ static char * __init dmi_string(const struct dmi_header *dm, u8 s)
* We have to be cautious here. We have seen BIOSes with DMI pointers
* pointing to completely the wrong place for example
*/
static int __init dmi_table(u32 base, int len, int num,
void (*decode)(const struct dmi_header *))
static void dmi_table(u8 *buf, int len, int num,
void (*decode)(const struct dmi_header *))
{
u8 *buf, *data;
u8 *data = buf;
int i = 0;

buf = dmi_ioremap(base, len);
if (buf == NULL)
return -1;

data = buf;

/*
* Stop when we see all the items the table claimed to have
* OR we run off the end of the table (also happens)
Expand All @@ -75,7 +69,23 @@ static int __init dmi_table(u32 base, int len, int num,
data += 2;
i++;
}
dmi_iounmap(buf, len);
}

static u32 dmi_base;
static u16 dmi_len;
static u16 dmi_num;

static int __init dmi_walk_early(void (*decode)(const struct dmi_header *))
{
u8 *buf;

buf = dmi_ioremap(dmi_base, dmi_len);
if (buf == NULL)
return -1;

dmi_table(buf, dmi_len, dmi_num, decode);

dmi_iounmap(buf, dmi_len);
return 0;
}

Expand Down Expand Up @@ -291,9 +301,9 @@ static int __init dmi_present(const char __iomem *p)

memcpy_fromio(buf, p, 15);
if ((memcmp(buf, "_DMI_", 5) == 0) && dmi_checksum(buf)) {
u16 num = (buf[13] << 8) | buf[12];
u16 len = (buf[7] << 8) | buf[6];
u32 base = (buf[11] << 24) | (buf[10] << 16) |
dmi_num = (buf[13] << 8) | buf[12];
dmi_len = (buf[7] << 8) | buf[6];
dmi_base = (buf[11] << 24) | (buf[10] << 16) |
(buf[9] << 8) | buf[8];

/*
Expand All @@ -305,7 +315,7 @@ static int __init dmi_present(const char __iomem *p)
buf[14] >> 4, buf[14] & 0xF);
else
printk(KERN_INFO "DMI present.\n");
if (dmi_table(base,len, num, dmi_decode) == 0)
if (dmi_walk_early(dmi_decode) == 0)
return 0;
}
return 1;
Expand Down Expand Up @@ -489,3 +499,27 @@ int dmi_get_year(int field)

return year;
}

/**
* dmi_walk - Walk the DMI table and get called back for every record
* @decode: Callback function
*
* Returns -1 when the DMI table can't be reached, 0 on success.
*/
int dmi_walk(void (*decode)(const struct dmi_header *))
{
u8 *buf;

if (!dmi_available)
return -1;

buf = ioremap(dmi_base, dmi_len);
if (buf == NULL)
return -1;

dmi_table(buf, dmi_len, dmi_num, decode);

iounmap(buf);
return 0;
}
EXPORT_SYMBOL_GPL(dmi_walk);
3 changes: 3 additions & 0 deletions include/linux/dmi.h
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ extern void dmi_scan_machine(void);
extern int dmi_get_year(int field);
extern int dmi_name_in_vendors(const char *str);
extern int dmi_available;
extern int dmi_walk(void (*decode)(const struct dmi_header *));

#else

Expand All @@ -89,6 +90,8 @@ static inline const struct dmi_device * dmi_find_device(int type, const char *na
static inline int dmi_get_year(int year) { return 0; }
static inline int dmi_name_in_vendors(const char *s) { return 0; }
#define dmi_available 0
static inline int dmi_walk(void (*decode)(const struct dmi_header *))
{ return -1; }

#endif

Expand Down

0 comments on commit 7fce084

Please sign in to comment.