aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/firmware/dmi_scan.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/firmware/dmi_scan.c')
-rw-r--r--drivers/firmware/dmi_scan.c78
1 files changed, 78 insertions, 0 deletions
diff --git a/drivers/firmware/dmi_scan.c b/drivers/firmware/dmi_scan.c
index 7fdf2868a276..5e0b770fdae5 100644
--- a/drivers/firmware/dmi_scan.c
+++ b/drivers/firmware/dmi_scan.c
@@ -10,6 +10,9 @@
10#include <asm/dmi.h> 10#include <asm/dmi.h>
11#include <asm/unaligned.h> 11#include <asm/unaligned.h>
12 12
13struct kobject *dmi_kobj;
14EXPORT_SYMBOL_GPL(dmi_kobj);
15
13/* 16/*
14 * DMI stands for "Desktop Management Interface". It is part 17 * DMI stands for "Desktop Management Interface". It is part
15 * of and an antecedent to, SMBIOS, which stands for System 18 * of and an antecedent to, SMBIOS, which stands for System
@@ -20,6 +23,9 @@ static const char dmi_empty_string[] = " ";
20static u32 dmi_ver __initdata; 23static u32 dmi_ver __initdata;
21static u32 dmi_len; 24static u32 dmi_len;
22static u16 dmi_num; 25static u16 dmi_num;
26static u8 smbios_entry_point[32];
27static int smbios_entry_point_size;
28
23/* 29/*
24 * Catch too early calls to dmi_check_system(): 30 * Catch too early calls to dmi_check_system():
25 */ 31 */
@@ -488,6 +494,8 @@ static int __init dmi_present(const u8 *buf)
488 if (memcmp(buf, "_SM_", 4) == 0 && 494 if (memcmp(buf, "_SM_", 4) == 0 &&
489 buf[5] < 32 && dmi_checksum(buf, buf[5])) { 495 buf[5] < 32 && dmi_checksum(buf, buf[5])) {
490 smbios_ver = get_unaligned_be16(buf + 6); 496 smbios_ver = get_unaligned_be16(buf + 6);
497 smbios_entry_point_size = buf[5];
498 memcpy(smbios_entry_point, buf, smbios_entry_point_size);
491 499
492 /* Some BIOS report weird SMBIOS version, fix that up */ 500 /* Some BIOS report weird SMBIOS version, fix that up */
493 switch (smbios_ver) { 501 switch (smbios_ver) {
@@ -522,6 +530,9 @@ static int __init dmi_present(const u8 *buf)
522 pr_info("SMBIOS %d.%d present.\n", 530 pr_info("SMBIOS %d.%d present.\n",
523 dmi_ver >> 8, dmi_ver & 0xFF); 531 dmi_ver >> 8, dmi_ver & 0xFF);
524 } else { 532 } else {
533 smbios_entry_point_size = 15;
534 memcpy(smbios_entry_point, buf,
535 smbios_entry_point_size);
525 pr_info("Legacy DMI %d.%d present.\n", 536 pr_info("Legacy DMI %d.%d present.\n",
526 dmi_ver >> 8, dmi_ver & 0xFF); 537 dmi_ver >> 8, dmi_ver & 0xFF);
527 } 538 }
@@ -548,6 +559,8 @@ static int __init dmi_smbios3_present(const u8 *buf)
548 dmi_num = 0; /* No longer specified */ 559 dmi_num = 0; /* No longer specified */
549 dmi_len = get_unaligned_le32(buf + 12); 560 dmi_len = get_unaligned_le32(buf + 12);
550 dmi_base = get_unaligned_le64(buf + 16); 561 dmi_base = get_unaligned_le64(buf + 16);
562 smbios_entry_point_size = buf[6];
563 memcpy(smbios_entry_point, buf, smbios_entry_point_size);
551 564
552 if (dmi_walk_early(dmi_decode) == 0) { 565 if (dmi_walk_early(dmi_decode) == 0) {
553 pr_info("SMBIOS %d.%d.%d present.\n", 566 pr_info("SMBIOS %d.%d.%d present.\n",
@@ -639,6 +652,71 @@ void __init dmi_scan_machine(void)
639 dmi_initialized = 1; 652 dmi_initialized = 1;
640} 653}
641 654
655static ssize_t raw_table_read(struct file *file, struct kobject *kobj,
656 struct bin_attribute *attr, char *buf,
657 loff_t pos, size_t count)
658{
659 memcpy(buf, attr->private + pos, count);
660 return count;
661}
662
663static BIN_ATTR(smbios_entry_point, S_IRUSR, raw_table_read, NULL, 0);
664static BIN_ATTR(DMI, S_IRUSR, raw_table_read, NULL, 0);
665
666static int __init dmi_init(void)
667{
668 struct kobject *tables_kobj;
669 u8 *dmi_table;
670 int ret = -ENOMEM;
671
672 if (!dmi_available) {
673 ret = -ENODATA;
674 goto err;
675 }
676
677 /*
678 * Set up dmi directory at /sys/firmware/dmi. This entry should stay
679 * even after farther error, as it can be used by other modules like
680 * dmi-sysfs.
681 */
682 dmi_kobj = kobject_create_and_add("dmi", firmware_kobj);
683 if (!dmi_kobj)
684 goto err;
685
686 tables_kobj = kobject_create_and_add("tables", dmi_kobj);
687 if (!tables_kobj)
688 goto err;
689
690 dmi_table = dmi_remap(dmi_base, dmi_len);
691 if (!dmi_table)
692 goto err_tables;
693
694 bin_attr_smbios_entry_point.size = smbios_entry_point_size;
695 bin_attr_smbios_entry_point.private = smbios_entry_point;
696 ret = sysfs_create_bin_file(tables_kobj, &bin_attr_smbios_entry_point);
697 if (ret)
698 goto err_unmap;
699
700 bin_attr_DMI.size = dmi_len;
701 bin_attr_DMI.private = dmi_table;
702 ret = sysfs_create_bin_file(tables_kobj, &bin_attr_DMI);
703 if (!ret)
704 return 0;
705
706 sysfs_remove_bin_file(tables_kobj,
707 &bin_attr_smbios_entry_point);
708 err_unmap:
709 dmi_unmap(dmi_table);
710 err_tables:
711 kobject_del(tables_kobj);
712 kobject_put(tables_kobj);
713 err:
714 pr_err("dmi: Firmware registration failed.\n");
715
716 return ret;
717}
718subsys_initcall(dmi_init);
719
642/** 720/**
643 * dmi_set_dump_stack_arch_desc - set arch description for dump_stack() 721 * dmi_set_dump_stack_arch_desc - set arch description for dump_stack()
644 * 722 *