18 #include <linux/kernel.h>
20 #include <linux/module.h>
21 #include <linux/types.h>
24 #include <linux/capability.h>
25 #include <linux/slab.h>
26 #include <linux/list.h>
29 #define MAX_ENTRY_TYPE 255
55 #define DMI_SYSFS_ATTR(_entry, _name) \
56 struct dmi_sysfs_attribute dmi_sysfs_attr_##_entry##_##_name = { \
57 .attr = {.name = __stringify(_name), .mode = 0400}, \
58 .show = dmi_sysfs_##_entry##_##_name, \
72 #define DMI_SYSFS_MAPPED_ATTR(_entry, _name) \
73 struct dmi_sysfs_mapped_attribute dmi_sysfs_attr_##_entry##_##_name = { \
74 .attr = {.name = __stringify(_name), .mode = 0400}, \
75 .show = dmi_sysfs_##_entry##_##_name, \
81 static void dmi_entry_free(
struct kobject *kobj)
106 return attr->
show(entry, buf);
109 static const struct sysfs_ops dmi_sysfs_attr_ops = {
110 .show = dmi_sysfs_attr_show,
124 static void find_dmi_entry_helper(
const struct dmi_header *dh,
131 if (dh->
type != entry->
dh.type)
164 .instance_countdown = entry->
instance,
169 ret =
dmi_walk(find_dmi_entry_helper, &data);
181 static size_t dmi_entry_length(
const struct dmi_header *dh)
183 const char *
p = (
const char *)dh;
190 return 2 + p - (
const char *)dh;
210 return attr->
show(entry, dh, data->
buf);
223 return find_dmi_entry(to_entry(kobj->
parent),
224 dmi_entry_attr_show_helper, &data);
227 static const struct sysfs_ops dmi_sysfs_specialize_attr_ops = {
228 .show = dmi_entry_attr_show,
237 #define DMI_SEL_ACCESS_METHOD_IO8 0x00
238 #define DMI_SEL_ACCESS_METHOD_IO2x8 0x01
239 #define DMI_SEL_ACCESS_METHOD_IO16 0x02
240 #define DMI_SEL_ACCESS_METHOD_PHYS32 0x03
241 #define DMI_SEL_ACCESS_METHOD_GPNV 0x04
266 #define DMI_SYSFS_SEL_FIELD(_field) \
267 static ssize_t dmi_sysfs_sel_##_field(struct dmi_sysfs_entry *entry, \
268 const struct dmi_header *dh, \
271 struct dmi_system_event_log sel; \
272 if (sizeof(sel) > dmi_entry_length(dh)) \
274 memcpy(&sel, dh, sizeof(sel)); \
275 return sprintf(buf, "%u\n", sel._field); \
277 static DMI_SYSFS_MAPPED_ATTR(sel, _field)
290 static struct attribute *dmi_sysfs_sel_attrs[] = {
291 &dmi_sysfs_attr_sel_area_length.attr,
292 &dmi_sysfs_attr_sel_header_start_offset.attr,
293 &dmi_sysfs_attr_sel_data_start_offset.attr,
294 &dmi_sysfs_attr_sel_access_method.attr,
295 &dmi_sysfs_attr_sel_status.attr,
296 &dmi_sysfs_attr_sel_change_token.attr,
297 &dmi_sysfs_attr_sel_access_method_address.attr,
298 &dmi_sysfs_attr_sel_header_format.attr,
299 &dmi_sysfs_attr_sel_type_descriptors_supported_count.attr,
300 &dmi_sysfs_attr_sel_per_log_type_descriptor_length.attr,
305 static struct kobj_type dmi_system_event_log_ktype = {
306 .release = dmi_entry_free,
307 .sysfs_ops = &dmi_sysfs_specialize_attr_ops,
308 .default_attrs = dmi_sysfs_sel_attrs,
322 outb((
u8)offset, sel->
io.index_addr);
323 ret =
inb(sel->
io.data_addr);
334 outb((
u8)offset, sel->
io.index_addr);
335 outb((
u8)(offset >> 8), sel->
io.index_addr + 1);
336 ret =
inb(sel->
io.data_addr);
348 ret =
inb(sel->
io.data_addr);
361 char *buf, loff_t
pos,
size_t count)
369 *(buf++) = io_reader(sel, pos++);
378 char *buf, loff_t pos,
size_t count)
387 while (count && pos < sel->area_length) {
389 *(buf++) =
readb(mapped + pos++);
404 if (
sizeof(sel) > dmi_entry_length(dh))
407 memcpy(&sel, dh,
sizeof(sel));
413 return dmi_sel_raw_read_io(entry, &sel, state->
buf,
416 return dmi_sel_raw_read_phys32(entry, &sel, state->
buf,
419 pr_info(
"dmi-sysfs: GPNV support missing.\n");
422 pr_info(
"dmi-sysfs: Unknown access method %02x\n",
430 char *buf, loff_t pos,
size_t count)
439 return find_dmi_entry(entry, dmi_sel_raw_read_helper, &state);
443 .attr = {.name =
"raw_event_log", .mode = 0400},
444 .read = dmi_sel_raw_read,
455 &dmi_system_event_log_ktype,
480 return sprintf(buf,
"%d\n", entry->
dh.length);
485 return sprintf(buf,
"%d\n", entry->
dh.handle);
490 return sprintf(buf,
"%d\n", entry->
dh.type);
511 static struct attribute *dmi_sysfs_entry_attrs[] = {
512 &dmi_sysfs_attr_entry_length.attr,
513 &dmi_sysfs_attr_entry_handle.attr,
514 &dmi_sysfs_attr_entry_type.attr,
515 &dmi_sysfs_attr_entry_instance.attr,
516 &dmi_sysfs_attr_entry_position.attr,
527 entry_length = dmi_entry_length(dh);
530 &state->
pos, dh, entry_length);
533 static ssize_t dmi_entry_raw_read(
struct file *filp,
536 char *buf, loff_t pos,
size_t count)
545 return find_dmi_entry(entry, dmi_entry_raw_read_helper, &state);
549 .attr = {.name =
"raw", .mode = 0400},
550 .read = dmi_entry_raw_read,
553 static void dmi_sysfs_entry_release(
struct kobject *kobj)
557 spin_lock(&entry_list_lock);
559 spin_unlock(&entry_list_lock);
563 static struct kobj_type dmi_sysfs_entry_ktype = {
564 .release = dmi_sysfs_entry_release,
565 .sysfs_ops = &dmi_sysfs_attr_ops,
566 .default_attrs = dmi_sysfs_entry_attrs,
569 static struct kobject *dmi_kobj;
570 static struct kset *dmi_kset;
596 memcpy(&entry->
dh, dh,
sizeof(*dh));
600 entry->
kobj.kset = dmi_kset;
610 spin_lock(&entry_list_lock);
612 spin_unlock(&entry_list_lock);
638 static void cleanup_entry_list(
void)
649 static int __init dmi_sysfs_init(
void)
664 error =
dmi_walk(dmi_sysfs_register_handle, &val);
676 cleanup_entry_list();
683 static void __exit dmi_sysfs_exit(
void)
685 pr_debug(
"dmi-sysfs: unloading.\n");
686 cleanup_entry_list();