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>
15 struct dmi_device_attribute
{
16 struct device_attribute dev_attr
;
19 #define to_dmi_dev_attr(_dev_attr) \
20 container_of(_dev_attr, struct dmi_device_attribute, dev_attr)
22 static ssize_t
sys_dmi_field_show(struct device
*dev
,
23 struct device_attribute
*attr
,
26 int field
= to_dmi_dev_attr(attr
)->field
;
28 len
= scnprintf(page
, PAGE_SIZE
, "%s\n", dmi_get_system_info(field
));
33 #define DMI_ATTR(_name, _mode, _show, _field) \
34 { .dev_attr = __ATTR(_name, _mode, _show, NULL), \
37 #define DEFINE_DMI_ATTR_WITH_SHOW(_name, _mode, _field) \
38 static struct dmi_device_attribute sys_dmi_##_name##_attr = \
39 DMI_ATTR(_name, _mode, sys_dmi_field_show, _field);
41 DEFINE_DMI_ATTR_WITH_SHOW(bios_vendor
, 0444, DMI_BIOS_VENDOR
);
42 DEFINE_DMI_ATTR_WITH_SHOW(bios_version
, 0444, DMI_BIOS_VERSION
);
43 DEFINE_DMI_ATTR_WITH_SHOW(bios_date
, 0444, DMI_BIOS_DATE
);
44 DEFINE_DMI_ATTR_WITH_SHOW(sys_vendor
, 0444, DMI_SYS_VENDOR
);
45 DEFINE_DMI_ATTR_WITH_SHOW(product_name
, 0444, DMI_PRODUCT_NAME
);
46 DEFINE_DMI_ATTR_WITH_SHOW(product_version
, 0444, DMI_PRODUCT_VERSION
);
47 DEFINE_DMI_ATTR_WITH_SHOW(product_serial
, 0400, DMI_PRODUCT_SERIAL
);
48 DEFINE_DMI_ATTR_WITH_SHOW(product_uuid
, 0400, DMI_PRODUCT_UUID
);
49 DEFINE_DMI_ATTR_WITH_SHOW(board_vendor
, 0444, DMI_BOARD_VENDOR
);
50 DEFINE_DMI_ATTR_WITH_SHOW(board_name
, 0444, DMI_BOARD_NAME
);
51 DEFINE_DMI_ATTR_WITH_SHOW(board_version
, 0444, DMI_BOARD_VERSION
);
52 DEFINE_DMI_ATTR_WITH_SHOW(board_serial
, 0400, DMI_BOARD_SERIAL
);
53 DEFINE_DMI_ATTR_WITH_SHOW(board_asset_tag
, 0444, DMI_BOARD_ASSET_TAG
);
54 DEFINE_DMI_ATTR_WITH_SHOW(chassis_vendor
, 0444, DMI_CHASSIS_VENDOR
);
55 DEFINE_DMI_ATTR_WITH_SHOW(chassis_type
, 0444, DMI_CHASSIS_TYPE
);
56 DEFINE_DMI_ATTR_WITH_SHOW(chassis_version
, 0444, DMI_CHASSIS_VERSION
);
57 DEFINE_DMI_ATTR_WITH_SHOW(chassis_serial
, 0400, DMI_CHASSIS_SERIAL
);
58 DEFINE_DMI_ATTR_WITH_SHOW(chassis_asset_tag
, 0444, DMI_CHASSIS_ASSET_TAG
);
60 static void ascii_filter(char *d
, const char *s
)
62 /* Filter out characters we don't want to see in the modalias string */
64 if (*s
> ' ' && *s
< 127 && *s
!= ':')
70 static ssize_t
get_modalias(char *buffer
, size_t buffer_size
)
72 static const struct mafield
{
76 { "bvn", DMI_BIOS_VENDOR
},
77 { "bvr", DMI_BIOS_VERSION
},
78 { "bd", DMI_BIOS_DATE
},
79 { "svn", DMI_SYS_VENDOR
},
80 { "pn", DMI_PRODUCT_NAME
},
81 { "pvr", DMI_PRODUCT_VERSION
},
82 { "rvn", DMI_BOARD_VENDOR
},
83 { "rn", DMI_BOARD_NAME
},
84 { "rvr", DMI_BOARD_VERSION
},
85 { "cvn", DMI_CHASSIS_VENDOR
},
86 { "ct", DMI_CHASSIS_TYPE
},
87 { "cvr", DMI_CHASSIS_VERSION
},
93 const struct mafield
*f
;
95 strcpy(buffer
, "dmi");
96 p
= buffer
+ 3; left
= buffer_size
- 4;
98 for (f
= fields
; f
->prefix
&& left
> 0; f
++) {
102 c
= dmi_get_system_info(f
->field
);
106 t
= kmalloc(strlen(c
) + 1, GFP_KERNEL
);
110 l
= scnprintf(p
, left
, ":%s%s", f
->prefix
, t
);
120 return p
- buffer
+ 1;
123 static ssize_t
sys_dmi_modalias_show(struct device
*dev
,
124 struct device_attribute
*attr
, char *page
)
127 r
= get_modalias(page
, PAGE_SIZE
-1);
133 static struct device_attribute sys_dmi_modalias_attr
=
134 __ATTR(modalias
, 0444, sys_dmi_modalias_show
, NULL
);
136 static struct attribute
*sys_dmi_attributes
[DMI_STRING_MAX
+2];
138 static struct attribute_group sys_dmi_attribute_group
= {
139 .attrs
= sys_dmi_attributes
,
142 static struct attribute_group
* sys_dmi_attribute_groups
[] = {
143 &sys_dmi_attribute_group
,
147 static int dmi_dev_uevent(struct device
*dev
, struct kobj_uevent_env
*env
)
151 if (add_uevent_var(env
, "MODALIAS="))
153 len
= get_modalias(&env
->buf
[env
->buflen
- 1],
154 sizeof(env
->buf
) - env
->buflen
);
155 if (len
>= (sizeof(env
->buf
) - env
->buflen
))
161 static struct class dmi_class
= {
163 .dev_release
= (void(*)(struct device
*)) kfree
,
164 .dev_uevent
= dmi_dev_uevent
,
167 static struct device
*dmi_dev
;
171 #define ADD_DMI_ATTR(_name, _field) \
172 if (dmi_get_system_info(_field)) \
173 sys_dmi_attributes[i++] = &sys_dmi_##_name##_attr.dev_attr.attr;
175 /* In a separate function to keep gcc 3.2 happy - do NOT merge this in
177 static void __init
dmi_id_init_attr_table(void)
181 /* Not necessarily all DMI fields are available on all
182 * systems, hence let's built an attribute table of just
183 * what's available */
185 ADD_DMI_ATTR(bios_vendor
, DMI_BIOS_VENDOR
);
186 ADD_DMI_ATTR(bios_version
, DMI_BIOS_VERSION
);
187 ADD_DMI_ATTR(bios_date
, DMI_BIOS_DATE
);
188 ADD_DMI_ATTR(sys_vendor
, DMI_SYS_VENDOR
);
189 ADD_DMI_ATTR(product_name
, DMI_PRODUCT_NAME
);
190 ADD_DMI_ATTR(product_version
, DMI_PRODUCT_VERSION
);
191 ADD_DMI_ATTR(product_serial
, DMI_PRODUCT_SERIAL
);
192 ADD_DMI_ATTR(product_uuid
, DMI_PRODUCT_UUID
);
193 ADD_DMI_ATTR(board_vendor
, DMI_BOARD_VENDOR
);
194 ADD_DMI_ATTR(board_name
, DMI_BOARD_NAME
);
195 ADD_DMI_ATTR(board_version
, DMI_BOARD_VERSION
);
196 ADD_DMI_ATTR(board_serial
, DMI_BOARD_SERIAL
);
197 ADD_DMI_ATTR(board_asset_tag
, DMI_BOARD_ASSET_TAG
);
198 ADD_DMI_ATTR(chassis_vendor
, DMI_CHASSIS_VENDOR
);
199 ADD_DMI_ATTR(chassis_type
, DMI_CHASSIS_TYPE
);
200 ADD_DMI_ATTR(chassis_version
, DMI_CHASSIS_VERSION
);
201 ADD_DMI_ATTR(chassis_serial
, DMI_CHASSIS_SERIAL
);
202 ADD_DMI_ATTR(chassis_asset_tag
, DMI_CHASSIS_ASSET_TAG
);
203 sys_dmi_attributes
[i
++] = &sys_dmi_modalias_attr
.attr
;
206 static int __init
dmi_id_init(void)
213 dmi_id_init_attr_table();
215 ret
= class_register(&dmi_class
);
219 dmi_dev
= kzalloc(sizeof(*dmi_dev
), GFP_KERNEL
);
222 goto fail_class_unregister
;
225 dmi_dev
->class = &dmi_class
;
226 strcpy(dmi_dev
->bus_id
, "id");
227 dmi_dev
->groups
= sys_dmi_attribute_groups
;
229 ret
= device_register(dmi_dev
);
231 goto fail_class_unregister
;
235 fail_class_unregister
:
237 class_unregister(&dmi_class
);
242 arch_initcall(dmi_id_init
);