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/slab.h>
16 struct dmi_device_attribute
{
17 struct device_attribute dev_attr
;
20 #define to_dmi_dev_attr(_dev_attr) \
21 container_of(_dev_attr, struct dmi_device_attribute, dev_attr)
23 static ssize_t
sys_dmi_field_show(struct device
*dev
,
24 struct device_attribute
*attr
,
27 int field
= to_dmi_dev_attr(attr
)->field
;
29 len
= scnprintf(page
, PAGE_SIZE
, "%s\n", dmi_get_system_info(field
));
34 #define DMI_ATTR(_name, _mode, _show, _field) \
35 { .dev_attr = __ATTR(_name, _mode, _show, NULL), \
38 #define DEFINE_DMI_ATTR_WITH_SHOW(_name, _mode, _field) \
39 static struct dmi_device_attribute sys_dmi_##_name##_attr = \
40 DMI_ATTR(_name, _mode, sys_dmi_field_show, _field);
42 DEFINE_DMI_ATTR_WITH_SHOW(bios_vendor
, 0444, DMI_BIOS_VENDOR
);
43 DEFINE_DMI_ATTR_WITH_SHOW(bios_version
, 0444, DMI_BIOS_VERSION
);
44 DEFINE_DMI_ATTR_WITH_SHOW(bios_date
, 0444, DMI_BIOS_DATE
);
45 DEFINE_DMI_ATTR_WITH_SHOW(sys_vendor
, 0444, DMI_SYS_VENDOR
);
46 DEFINE_DMI_ATTR_WITH_SHOW(product_name
, 0444, DMI_PRODUCT_NAME
);
47 DEFINE_DMI_ATTR_WITH_SHOW(product_version
, 0444, DMI_PRODUCT_VERSION
);
48 DEFINE_DMI_ATTR_WITH_SHOW(product_serial
, 0400, DMI_PRODUCT_SERIAL
);
49 DEFINE_DMI_ATTR_WITH_SHOW(product_uuid
, 0400, DMI_PRODUCT_UUID
);
50 DEFINE_DMI_ATTR_WITH_SHOW(board_vendor
, 0444, DMI_BOARD_VENDOR
);
51 DEFINE_DMI_ATTR_WITH_SHOW(board_name
, 0444, DMI_BOARD_NAME
);
52 DEFINE_DMI_ATTR_WITH_SHOW(board_version
, 0444, DMI_BOARD_VERSION
);
53 DEFINE_DMI_ATTR_WITH_SHOW(board_serial
, 0400, DMI_BOARD_SERIAL
);
54 DEFINE_DMI_ATTR_WITH_SHOW(board_asset_tag
, 0444, DMI_BOARD_ASSET_TAG
);
55 DEFINE_DMI_ATTR_WITH_SHOW(chassis_vendor
, 0444, DMI_CHASSIS_VENDOR
);
56 DEFINE_DMI_ATTR_WITH_SHOW(chassis_type
, 0444, DMI_CHASSIS_TYPE
);
57 DEFINE_DMI_ATTR_WITH_SHOW(chassis_version
, 0444, DMI_CHASSIS_VERSION
);
58 DEFINE_DMI_ATTR_WITH_SHOW(chassis_serial
, 0400, DMI_CHASSIS_SERIAL
);
59 DEFINE_DMI_ATTR_WITH_SHOW(chassis_asset_tag
, 0444, DMI_CHASSIS_ASSET_TAG
);
61 static void ascii_filter(char *d
, const char *s
)
63 /* Filter out characters we don't want to see in the modalias string */
65 if (*s
> ' ' && *s
< 127 && *s
!= ':')
71 static ssize_t
get_modalias(char *buffer
, size_t buffer_size
)
73 static const struct mafield
{
77 { "bvn", DMI_BIOS_VENDOR
},
78 { "bvr", DMI_BIOS_VERSION
},
79 { "bd", DMI_BIOS_DATE
},
80 { "svn", DMI_SYS_VENDOR
},
81 { "pn", DMI_PRODUCT_NAME
},
82 { "pvr", DMI_PRODUCT_VERSION
},
83 { "rvn", DMI_BOARD_VENDOR
},
84 { "rn", DMI_BOARD_NAME
},
85 { "rvr", DMI_BOARD_VERSION
},
86 { "cvn", DMI_CHASSIS_VENDOR
},
87 { "ct", DMI_CHASSIS_TYPE
},
88 { "cvr", DMI_CHASSIS_VERSION
},
94 const struct mafield
*f
;
96 strcpy(buffer
, "dmi");
97 p
= buffer
+ 3; left
= buffer_size
- 4;
99 for (f
= fields
; f
->prefix
&& left
> 0; f
++) {
103 c
= dmi_get_system_info(f
->field
);
107 t
= kmalloc(strlen(c
) + 1, GFP_KERNEL
);
111 l
= scnprintf(p
, left
, ":%s%s", f
->prefix
, t
);
121 return p
- buffer
+ 1;
124 static ssize_t
sys_dmi_modalias_show(struct device
*dev
,
125 struct device_attribute
*attr
, char *page
)
128 r
= get_modalias(page
, PAGE_SIZE
-1);
134 static struct device_attribute sys_dmi_modalias_attr
=
135 __ATTR(modalias
, 0444, sys_dmi_modalias_show
, NULL
);
137 static struct attribute
*sys_dmi_attributes
[DMI_STRING_MAX
+2];
139 static struct attribute_group sys_dmi_attribute_group
= {
140 .attrs
= sys_dmi_attributes
,
143 static const struct attribute_group
* sys_dmi_attribute_groups
[] = {
144 &sys_dmi_attribute_group
,
148 static int dmi_dev_uevent(struct device
*dev
, struct kobj_uevent_env
*env
)
152 if (add_uevent_var(env
, "MODALIAS="))
154 len
= get_modalias(&env
->buf
[env
->buflen
- 1],
155 sizeof(env
->buf
) - env
->buflen
);
156 if (len
>= (sizeof(env
->buf
) - env
->buflen
))
162 static struct class dmi_class
= {
164 .dev_release
= (void(*)(struct device
*)) kfree
,
165 .dev_uevent
= dmi_dev_uevent
,
168 static struct device
*dmi_dev
;
172 #define ADD_DMI_ATTR(_name, _field) \
173 if (dmi_get_system_info(_field)) \
174 sys_dmi_attributes[i++] = &sys_dmi_##_name##_attr.dev_attr.attr;
176 /* In a separate function to keep gcc 3.2 happy - do NOT merge this in
178 static void __init
dmi_id_init_attr_table(void)
182 /* Not necessarily all DMI fields are available on all
183 * systems, hence let's built an attribute table of just
184 * what's available */
186 ADD_DMI_ATTR(bios_vendor
, DMI_BIOS_VENDOR
);
187 ADD_DMI_ATTR(bios_version
, DMI_BIOS_VERSION
);
188 ADD_DMI_ATTR(bios_date
, DMI_BIOS_DATE
);
189 ADD_DMI_ATTR(sys_vendor
, DMI_SYS_VENDOR
);
190 ADD_DMI_ATTR(product_name
, DMI_PRODUCT_NAME
);
191 ADD_DMI_ATTR(product_version
, DMI_PRODUCT_VERSION
);
192 ADD_DMI_ATTR(product_serial
, DMI_PRODUCT_SERIAL
);
193 ADD_DMI_ATTR(product_uuid
, DMI_PRODUCT_UUID
);
194 ADD_DMI_ATTR(board_vendor
, DMI_BOARD_VENDOR
);
195 ADD_DMI_ATTR(board_name
, DMI_BOARD_NAME
);
196 ADD_DMI_ATTR(board_version
, DMI_BOARD_VERSION
);
197 ADD_DMI_ATTR(board_serial
, DMI_BOARD_SERIAL
);
198 ADD_DMI_ATTR(board_asset_tag
, DMI_BOARD_ASSET_TAG
);
199 ADD_DMI_ATTR(chassis_vendor
, DMI_CHASSIS_VENDOR
);
200 ADD_DMI_ATTR(chassis_type
, DMI_CHASSIS_TYPE
);
201 ADD_DMI_ATTR(chassis_version
, DMI_CHASSIS_VERSION
);
202 ADD_DMI_ATTR(chassis_serial
, DMI_CHASSIS_SERIAL
);
203 ADD_DMI_ATTR(chassis_asset_tag
, DMI_CHASSIS_ASSET_TAG
);
204 sys_dmi_attributes
[i
++] = &sys_dmi_modalias_attr
.attr
;
207 static int __init
dmi_id_init(void)
214 dmi_id_init_attr_table();
216 ret
= class_register(&dmi_class
);
220 dmi_dev
= kzalloc(sizeof(*dmi_dev
), GFP_KERNEL
);
223 goto fail_class_unregister
;
226 dmi_dev
->class = &dmi_class
;
227 dev_set_name(dmi_dev
, "id");
228 dmi_dev
->groups
= sys_dmi_attribute_groups
;
230 ret
= device_register(dmi_dev
);
232 goto fail_put_dmi_dev
;
239 fail_class_unregister
:
240 class_unregister(&dmi_class
);
245 arch_initcall(dmi_id_init
);