2 * Export SMBIOS/DMI info via sysfs to userspace
4 * Copyright 2007, Lennart Poettering
9 #include <linux/module.h>
10 #include <linux/kernel.h>
11 #include <linux/init.h>
12 #include <linux/dmi.h>
13 #include <linux/device.h>
14 #include <linux/autoconf.h>
16 #define DEFINE_DMI_ATTR(_name, _mode, _show) \
17 static struct device_attribute sys_dmi_##_name##_attr = \
18 __ATTR(_name, _mode, _show, NULL);
20 #define DEFINE_DMI_ATTR_WITH_SHOW(_name, _mode, _field) \
21 static ssize_t sys_dmi_##_name##_show(struct device *dev, \
22 struct device_attribute *attr, \
26 len = scnprintf(page, PAGE_SIZE, "%s\n", dmi_get_system_info(_field)); \
30 DEFINE_DMI_ATTR(_name, _mode, sys_dmi_##_name##_show);
32 DEFINE_DMI_ATTR_WITH_SHOW(bios_vendor
, 0444, DMI_BIOS_VENDOR
);
33 DEFINE_DMI_ATTR_WITH_SHOW(bios_version
, 0444, DMI_BIOS_VERSION
);
34 DEFINE_DMI_ATTR_WITH_SHOW(bios_date
, 0444, DMI_BIOS_DATE
);
35 DEFINE_DMI_ATTR_WITH_SHOW(sys_vendor
, 0444, DMI_SYS_VENDOR
);
36 DEFINE_DMI_ATTR_WITH_SHOW(product_name
, 0444, DMI_PRODUCT_NAME
);
37 DEFINE_DMI_ATTR_WITH_SHOW(product_version
, 0444, DMI_PRODUCT_VERSION
);
38 DEFINE_DMI_ATTR_WITH_SHOW(product_serial
, 0400, DMI_PRODUCT_SERIAL
);
39 DEFINE_DMI_ATTR_WITH_SHOW(product_uuid
, 0400, DMI_PRODUCT_UUID
);
40 DEFINE_DMI_ATTR_WITH_SHOW(board_vendor
, 0444, DMI_BOARD_VENDOR
);
41 DEFINE_DMI_ATTR_WITH_SHOW(board_name
, 0444, DMI_BOARD_NAME
);
42 DEFINE_DMI_ATTR_WITH_SHOW(board_version
, 0444, DMI_BOARD_VERSION
);
43 DEFINE_DMI_ATTR_WITH_SHOW(board_serial
, 0400, DMI_BOARD_SERIAL
);
44 DEFINE_DMI_ATTR_WITH_SHOW(board_asset_tag
, 0444, DMI_BOARD_ASSET_TAG
);
45 DEFINE_DMI_ATTR_WITH_SHOW(chassis_vendor
, 0444, DMI_CHASSIS_VENDOR
);
46 DEFINE_DMI_ATTR_WITH_SHOW(chassis_type
, 0444, DMI_CHASSIS_TYPE
);
47 DEFINE_DMI_ATTR_WITH_SHOW(chassis_version
, 0444, DMI_CHASSIS_VERSION
);
48 DEFINE_DMI_ATTR_WITH_SHOW(chassis_serial
, 0400, DMI_CHASSIS_SERIAL
);
49 DEFINE_DMI_ATTR_WITH_SHOW(chassis_asset_tag
, 0444, DMI_CHASSIS_ASSET_TAG
);
51 static void ascii_filter(char *d
, const char *s
)
53 /* Filter out characters we don't want to see in the modalias string */
55 if (*s
> ' ' && *s
< 127 && *s
!= ':')
61 static ssize_t
get_modalias(char *buffer
, size_t buffer_size
)
63 static const struct mafield
{
67 { "bvn", DMI_BIOS_VENDOR
},
68 { "bvr", DMI_BIOS_VERSION
},
69 { "bd", DMI_BIOS_DATE
},
70 { "svn", DMI_SYS_VENDOR
},
71 { "pn", DMI_PRODUCT_NAME
},
72 { "pvr", DMI_PRODUCT_VERSION
},
73 { "rvn", DMI_BOARD_VENDOR
},
74 { "rn", DMI_BOARD_NAME
},
75 { "rvr", DMI_BOARD_VERSION
},
76 { "cvn", DMI_CHASSIS_VENDOR
},
77 { "ct", DMI_CHASSIS_TYPE
},
78 { "cvr", DMI_CHASSIS_VERSION
},
84 const struct mafield
*f
;
86 strcpy(buffer
, "dmi");
87 p
= buffer
+ 3; left
= buffer_size
- 4;
89 for (f
= fields
; f
->prefix
&& left
> 0; f
++) {
93 c
= dmi_get_system_info(f
->field
);
97 t
= kmalloc(strlen(c
) + 1, GFP_KERNEL
);
101 l
= scnprintf(p
, left
, ":%s%s", f
->prefix
, t
);
111 return p
- buffer
+ 1;
114 static ssize_t
sys_dmi_modalias_show(struct device
*dev
,
115 struct device_attribute
*attr
, char *page
)
118 r
= get_modalias(page
, PAGE_SIZE
-1);
124 DEFINE_DMI_ATTR(modalias
, 0444, sys_dmi_modalias_show
);
126 static struct attribute
*sys_dmi_attributes
[DMI_STRING_MAX
+2];
128 static struct attribute_group sys_dmi_attribute_group
= {
129 .attrs
= sys_dmi_attributes
,
132 static struct attribute_group
* sys_dmi_attribute_groups
[] = {
133 &sys_dmi_attribute_group
,
137 static int dmi_dev_uevent(struct device
*dev
, char **envp
,
138 int num_envp
, char *buffer
, int buffer_size
)
140 strcpy(buffer
, "MODALIAS=");
141 get_modalias(buffer
+9, buffer_size
-9);
148 static struct class dmi_class
= {
150 .dev_release
= (void(*)(struct device
*)) kfree
,
151 .dev_uevent
= dmi_dev_uevent
,
154 static struct device
*dmi_dev
;
158 #define ADD_DMI_ATTR(_name, _field) \
159 if (dmi_get_system_info(_field)) \
160 sys_dmi_attributes[i++] = & sys_dmi_##_name##_attr.attr;
162 extern int dmi_available
;
164 static int __init
dmi_id_init(void)
171 /* Not necessarily all DMI fields are available on all
172 * systems, hence let's built an attribute table of just
173 * what's available */
175 ADD_DMI_ATTR(bios_vendor
, DMI_BIOS_VENDOR
);
176 ADD_DMI_ATTR(bios_version
, DMI_BIOS_VERSION
);
177 ADD_DMI_ATTR(bios_date
, DMI_BIOS_DATE
);
178 ADD_DMI_ATTR(sys_vendor
, DMI_SYS_VENDOR
);
179 ADD_DMI_ATTR(product_name
, DMI_PRODUCT_NAME
);
180 ADD_DMI_ATTR(product_version
, DMI_PRODUCT_VERSION
);
181 ADD_DMI_ATTR(product_serial
, DMI_PRODUCT_SERIAL
);
182 ADD_DMI_ATTR(product_uuid
, DMI_PRODUCT_UUID
);
183 ADD_DMI_ATTR(board_vendor
, DMI_BOARD_VENDOR
);
184 ADD_DMI_ATTR(board_name
, DMI_BOARD_NAME
);
185 ADD_DMI_ATTR(board_version
, DMI_BOARD_VERSION
);
186 ADD_DMI_ATTR(board_serial
, DMI_BOARD_SERIAL
);
187 ADD_DMI_ATTR(board_asset_tag
, DMI_BOARD_ASSET_TAG
);
188 ADD_DMI_ATTR(chassis_vendor
, DMI_CHASSIS_VENDOR
);
189 ADD_DMI_ATTR(chassis_type
, DMI_CHASSIS_TYPE
);
190 ADD_DMI_ATTR(chassis_version
, DMI_CHASSIS_VERSION
);
191 ADD_DMI_ATTR(chassis_serial
, DMI_CHASSIS_SERIAL
);
192 ADD_DMI_ATTR(chassis_asset_tag
, DMI_CHASSIS_ASSET_TAG
);
193 sys_dmi_attributes
[i
++] = &sys_dmi_modalias_attr
.attr
;
195 ret
= class_register(&dmi_class
);
199 dmi_dev
= kzalloc(sizeof(*dmi_dev
), GFP_KERNEL
);
202 goto fail_class_unregister
;
205 dmi_dev
->class = &dmi_class
;
206 strcpy(dmi_dev
->bus_id
, "id");
207 dmi_dev
->groups
= sys_dmi_attribute_groups
;
209 ret
= device_register(dmi_dev
);
211 goto fail_class_unregister
;
215 fail_class_unregister
:
217 class_unregister(&dmi_class
);
222 arch_initcall(dmi_id_init
);