mirror of
https://github.com/Fishwaldo/Star64_linux.git
synced 2025-06-25 16:11:45 +00:00
Merge branch 'dmi-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jdelvare/staging
Pull DMI updates from Jean Delvare: "The most important change is the new sysfs interface to the DMI table, which will let user-space tools (such as dmidecode) access the table without relying on /dev/mem" * 'dmi-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jdelvare/staging: firmware: dmi: struct dmi_header should be packed firmware: dmi_scan: Coding style cleanups Documentation: ABI: sysfs-firmware-dmi: add -entries suffix to file name firmware: dmi_scan: add SBMIOS entry and DMI tables firmware: dmi_scan: Trim DMI table length before exporting it firmware: dmi_scan: Rename dmi_table to dmi_decode_table firmware: dmi: List my quilt tree firmware: dmi_scan: Only honor end-of-table for 64-bit tables
This commit is contained in:
commit
f7b08217c7
6 changed files with 143 additions and 31 deletions
|
@ -1,4 +1,4 @@
|
||||||
What: /sys/firmware/dmi/
|
What: /sys/firmware/dmi/entries/
|
||||||
Date: February 2011
|
Date: February 2011
|
||||||
Contact: Mike Waychison <mikew@google.com>
|
Contact: Mike Waychison <mikew@google.com>
|
||||||
Description:
|
Description:
|
22
Documentation/ABI/testing/sysfs-firmware-dmi-tables
Normal file
22
Documentation/ABI/testing/sysfs-firmware-dmi-tables
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
What: /sys/firmware/dmi/tables/
|
||||||
|
Date: April 2015
|
||||||
|
Contact: Ivan Khoronzhuk <ivan.khoronzhuk@globallogic.com>
|
||||||
|
Description:
|
||||||
|
The firmware provides DMI structures as a packed list of
|
||||||
|
data referenced by a SMBIOS table entry point. The SMBIOS
|
||||||
|
entry point contains general information, like SMBIOS
|
||||||
|
version, DMI table size, etc. The structure, content and
|
||||||
|
size of SMBIOS entry point is dependent on SMBIOS version.
|
||||||
|
The format of SMBIOS entry point and DMI structures
|
||||||
|
can be read in SMBIOS specification.
|
||||||
|
|
||||||
|
The dmi/tables provides raw SMBIOS entry point and DMI tables
|
||||||
|
through sysfs as an alternative to utilities reading them
|
||||||
|
from /dev/mem. The raw SMBIOS entry point and DMI table are
|
||||||
|
presented as binary attributes and are accessible via:
|
||||||
|
|
||||||
|
/sys/firmware/dmi/tables/smbios_entry_point
|
||||||
|
/sys/firmware/dmi/tables/DMI
|
||||||
|
|
||||||
|
The complete DMI information can be obtained using these two
|
||||||
|
tables.
|
|
@ -3337,6 +3337,8 @@ F: drivers/hwmon/dme1737.c
|
||||||
DMI/SMBIOS SUPPORT
|
DMI/SMBIOS SUPPORT
|
||||||
M: Jean Delvare <jdelvare@suse.de>
|
M: Jean Delvare <jdelvare@suse.de>
|
||||||
S: Maintained
|
S: Maintained
|
||||||
|
T: quilt http://jdelvare.nerim.net/devel/linux/jdelvare-dmi/
|
||||||
|
F: Documentation/ABI/testing/sysfs-firmware-dmi-tables
|
||||||
F: drivers/firmware/dmi-id.c
|
F: drivers/firmware/dmi-id.c
|
||||||
F: drivers/firmware/dmi_scan.c
|
F: drivers/firmware/dmi_scan.c
|
||||||
F: include/linux/dmi.h
|
F: include/linux/dmi.h
|
||||||
|
|
|
@ -566,7 +566,6 @@ static struct kobj_type dmi_sysfs_entry_ktype = {
|
||||||
.default_attrs = dmi_sysfs_entry_attrs,
|
.default_attrs = dmi_sysfs_entry_attrs,
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct kobject *dmi_kobj;
|
|
||||||
static struct kset *dmi_kset;
|
static struct kset *dmi_kset;
|
||||||
|
|
||||||
/* Global count of all instances seen. Only for setup */
|
/* Global count of all instances seen. Only for setup */
|
||||||
|
@ -648,17 +647,20 @@ static void cleanup_entry_list(void)
|
||||||
|
|
||||||
static int __init dmi_sysfs_init(void)
|
static int __init dmi_sysfs_init(void)
|
||||||
{
|
{
|
||||||
int error = -ENOMEM;
|
int error;
|
||||||
int val;
|
int val;
|
||||||
|
|
||||||
/* Set up our directory */
|
if (!dmi_kobj) {
|
||||||
dmi_kobj = kobject_create_and_add("dmi", firmware_kobj);
|
pr_err("dmi-sysfs: dmi entry is absent.\n");
|
||||||
if (!dmi_kobj)
|
error = -ENODATA;
|
||||||
goto err;
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
dmi_kset = kset_create_and_add("entries", NULL, dmi_kobj);
|
dmi_kset = kset_create_and_add("entries", NULL, dmi_kobj);
|
||||||
if (!dmi_kset)
|
if (!dmi_kset) {
|
||||||
|
error = -ENOMEM;
|
||||||
goto err;
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
val = 0;
|
val = 0;
|
||||||
error = dmi_walk(dmi_sysfs_register_handle, &val);
|
error = dmi_walk(dmi_sysfs_register_handle, &val);
|
||||||
|
@ -675,7 +677,6 @@ static int __init dmi_sysfs_init(void)
|
||||||
err:
|
err:
|
||||||
cleanup_entry_list();
|
cleanup_entry_list();
|
||||||
kset_unregister(dmi_kset);
|
kset_unregister(dmi_kset);
|
||||||
kobject_put(dmi_kobj);
|
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -685,8 +686,6 @@ static void __exit dmi_sysfs_exit(void)
|
||||||
pr_debug("dmi-sysfs: unloading.\n");
|
pr_debug("dmi-sysfs: unloading.\n");
|
||||||
cleanup_entry_list();
|
cleanup_entry_list();
|
||||||
kset_unregister(dmi_kset);
|
kset_unregister(dmi_kset);
|
||||||
kobject_del(dmi_kobj);
|
|
||||||
kobject_put(dmi_kobj);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
module_init(dmi_sysfs_init);
|
module_init(dmi_sysfs_init);
|
||||||
|
|
|
@ -10,6 +10,9 @@
|
||||||
#include <asm/dmi.h>
|
#include <asm/dmi.h>
|
||||||
#include <asm/unaligned.h>
|
#include <asm/unaligned.h>
|
||||||
|
|
||||||
|
struct kobject *dmi_kobj;
|
||||||
|
EXPORT_SYMBOL_GPL(dmi_kobj);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* DMI stands for "Desktop Management Interface". It is part
|
* DMI stands for "Desktop Management Interface". It is part
|
||||||
* of and an antecedent to, SMBIOS, which stands for System
|
* of and an antecedent to, SMBIOS, which stands for System
|
||||||
|
@ -20,6 +23,9 @@ static const char dmi_empty_string[] = " ";
|
||||||
static u32 dmi_ver __initdata;
|
static u32 dmi_ver __initdata;
|
||||||
static u32 dmi_len;
|
static u32 dmi_len;
|
||||||
static u16 dmi_num;
|
static u16 dmi_num;
|
||||||
|
static u8 smbios_entry_point[32];
|
||||||
|
static int smbios_entry_point_size;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Catch too early calls to dmi_check_system():
|
* Catch too early calls to dmi_check_system():
|
||||||
*/
|
*/
|
||||||
|
@ -80,7 +86,7 @@ static const char * __init dmi_string(const struct dmi_header *dm, u8 s)
|
||||||
* We have to be cautious here. We have seen BIOSes with DMI pointers
|
* We have to be cautious here. We have seen BIOSes with DMI pointers
|
||||||
* pointing to completely the wrong place for example
|
* pointing to completely the wrong place for example
|
||||||
*/
|
*/
|
||||||
static void dmi_table(u8 *buf,
|
static void dmi_decode_table(u8 *buf,
|
||||||
void (*decode)(const struct dmi_header *, void *),
|
void (*decode)(const struct dmi_header *, void *),
|
||||||
void *private_data)
|
void *private_data)
|
||||||
{
|
{
|
||||||
|
@ -89,9 +95,9 @@ static void dmi_table(u8 *buf,
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Stop when we have seen all the items the table claimed to have
|
* Stop when we have seen all the items the table claimed to have
|
||||||
* (SMBIOS < 3.0 only) OR we reach an end-of-table marker OR we run
|
* (SMBIOS < 3.0 only) OR we reach an end-of-table marker (SMBIOS
|
||||||
* off the end of the table (should never happen but sometimes does
|
* >= 3.0 only) OR we run off the end of the table (should never
|
||||||
* on bogus implementations.)
|
* happen but sometimes does on bogus implementations.)
|
||||||
*/
|
*/
|
||||||
while ((!dmi_num || i < dmi_num) &&
|
while ((!dmi_num || i < dmi_num) &&
|
||||||
(data - buf + sizeof(struct dmi_header)) <= dmi_len) {
|
(data - buf + sizeof(struct dmi_header)) <= dmi_len) {
|
||||||
|
@ -108,15 +114,24 @@ static void dmi_table(u8 *buf,
|
||||||
if (data - buf < dmi_len - 1)
|
if (data - buf < dmi_len - 1)
|
||||||
decode(dm, private_data);
|
decode(dm, private_data);
|
||||||
|
|
||||||
/*
|
|
||||||
* 7.45 End-of-Table (Type 127) [SMBIOS reference spec v3.0.0]
|
|
||||||
*/
|
|
||||||
if (dm->type == DMI_ENTRY_END_OF_TABLE)
|
|
||||||
break;
|
|
||||||
|
|
||||||
data += 2;
|
data += 2;
|
||||||
i++;
|
i++;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 7.45 End-of-Table (Type 127) [SMBIOS reference spec v3.0.0]
|
||||||
|
* For tables behind a 64-bit entry point, we have no item
|
||||||
|
* count and no exact table length, so stop on end-of-table
|
||||||
|
* marker. For tables behind a 32-bit entry point, we have
|
||||||
|
* seen OEM structures behind the end-of-table marker on
|
||||||
|
* some systems, so don't trust it.
|
||||||
|
*/
|
||||||
|
if (!dmi_num && dm->type == DMI_ENTRY_END_OF_TABLE)
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Trim DMI table length if needed */
|
||||||
|
if (dmi_len > data - buf)
|
||||||
|
dmi_len = data - buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
static phys_addr_t dmi_base;
|
static phys_addr_t dmi_base;
|
||||||
|
@ -125,16 +140,17 @@ static int __init dmi_walk_early(void (*decode)(const struct dmi_header *,
|
||||||
void *))
|
void *))
|
||||||
{
|
{
|
||||||
u8 *buf;
|
u8 *buf;
|
||||||
|
u32 orig_dmi_len = dmi_len;
|
||||||
|
|
||||||
buf = dmi_early_remap(dmi_base, dmi_len);
|
buf = dmi_early_remap(dmi_base, orig_dmi_len);
|
||||||
if (buf == NULL)
|
if (buf == NULL)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
dmi_table(buf, decode, NULL);
|
dmi_decode_table(buf, decode, NULL);
|
||||||
|
|
||||||
add_device_randomness(buf, dmi_len);
|
add_device_randomness(buf, dmi_len);
|
||||||
|
|
||||||
dmi_early_unmap(buf, dmi_len);
|
dmi_early_unmap(buf, orig_dmi_len);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -478,6 +494,8 @@ static int __init dmi_present(const u8 *buf)
|
||||||
if (memcmp(buf, "_SM_", 4) == 0 &&
|
if (memcmp(buf, "_SM_", 4) == 0 &&
|
||||||
buf[5] < 32 && dmi_checksum(buf, buf[5])) {
|
buf[5] < 32 && dmi_checksum(buf, buf[5])) {
|
||||||
smbios_ver = get_unaligned_be16(buf + 6);
|
smbios_ver = get_unaligned_be16(buf + 6);
|
||||||
|
smbios_entry_point_size = buf[5];
|
||||||
|
memcpy(smbios_entry_point, buf, smbios_entry_point_size);
|
||||||
|
|
||||||
/* Some BIOS report weird SMBIOS version, fix that up */
|
/* Some BIOS report weird SMBIOS version, fix that up */
|
||||||
switch (smbios_ver) {
|
switch (smbios_ver) {
|
||||||
|
@ -512,6 +530,9 @@ static int __init dmi_present(const u8 *buf)
|
||||||
pr_info("SMBIOS %d.%d present.\n",
|
pr_info("SMBIOS %d.%d present.\n",
|
||||||
dmi_ver >> 8, dmi_ver & 0xFF);
|
dmi_ver >> 8, dmi_ver & 0xFF);
|
||||||
} else {
|
} else {
|
||||||
|
smbios_entry_point_size = 15;
|
||||||
|
memcpy(smbios_entry_point, buf,
|
||||||
|
smbios_entry_point_size);
|
||||||
pr_info("Legacy DMI %d.%d present.\n",
|
pr_info("Legacy DMI %d.%d present.\n",
|
||||||
dmi_ver >> 8, dmi_ver & 0xFF);
|
dmi_ver >> 8, dmi_ver & 0xFF);
|
||||||
}
|
}
|
||||||
|
@ -533,11 +554,12 @@ static int __init dmi_smbios3_present(const u8 *buf)
|
||||||
{
|
{
|
||||||
if (memcmp(buf, "_SM3_", 5) == 0 &&
|
if (memcmp(buf, "_SM3_", 5) == 0 &&
|
||||||
buf[6] < 32 && dmi_checksum(buf, buf[6])) {
|
buf[6] < 32 && dmi_checksum(buf, buf[6])) {
|
||||||
dmi_ver = get_unaligned_be32(buf + 6);
|
dmi_ver = get_unaligned_be32(buf + 6) & 0xFFFFFF;
|
||||||
dmi_ver &= 0xFFFFFF;
|
|
||||||
dmi_num = 0; /* No longer specified */
|
dmi_num = 0; /* No longer specified */
|
||||||
dmi_len = get_unaligned_le32(buf + 12);
|
dmi_len = get_unaligned_le32(buf + 12);
|
||||||
dmi_base = get_unaligned_le64(buf + 16);
|
dmi_base = get_unaligned_le64(buf + 16);
|
||||||
|
smbios_entry_point_size = buf[6];
|
||||||
|
memcpy(smbios_entry_point, buf, smbios_entry_point_size);
|
||||||
|
|
||||||
if (dmi_walk_early(dmi_decode) == 0) {
|
if (dmi_walk_early(dmi_decode) == 0) {
|
||||||
pr_info("SMBIOS %d.%d.%d present.\n",
|
pr_info("SMBIOS %d.%d.%d present.\n",
|
||||||
|
@ -629,6 +651,71 @@ void __init dmi_scan_machine(void)
|
||||||
dmi_initialized = 1;
|
dmi_initialized = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static ssize_t raw_table_read(struct file *file, struct kobject *kobj,
|
||||||
|
struct bin_attribute *attr, char *buf,
|
||||||
|
loff_t pos, size_t count)
|
||||||
|
{
|
||||||
|
memcpy(buf, attr->private + pos, count);
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
static BIN_ATTR(smbios_entry_point, S_IRUSR, raw_table_read, NULL, 0);
|
||||||
|
static BIN_ATTR(DMI, S_IRUSR, raw_table_read, NULL, 0);
|
||||||
|
|
||||||
|
static int __init dmi_init(void)
|
||||||
|
{
|
||||||
|
struct kobject *tables_kobj;
|
||||||
|
u8 *dmi_table;
|
||||||
|
int ret = -ENOMEM;
|
||||||
|
|
||||||
|
if (!dmi_available) {
|
||||||
|
ret = -ENODATA;
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set up dmi directory at /sys/firmware/dmi. This entry should stay
|
||||||
|
* even after farther error, as it can be used by other modules like
|
||||||
|
* dmi-sysfs.
|
||||||
|
*/
|
||||||
|
dmi_kobj = kobject_create_and_add("dmi", firmware_kobj);
|
||||||
|
if (!dmi_kobj)
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
tables_kobj = kobject_create_and_add("tables", dmi_kobj);
|
||||||
|
if (!tables_kobj)
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
dmi_table = dmi_remap(dmi_base, dmi_len);
|
||||||
|
if (!dmi_table)
|
||||||
|
goto err_tables;
|
||||||
|
|
||||||
|
bin_attr_smbios_entry_point.size = smbios_entry_point_size;
|
||||||
|
bin_attr_smbios_entry_point.private = smbios_entry_point;
|
||||||
|
ret = sysfs_create_bin_file(tables_kobj, &bin_attr_smbios_entry_point);
|
||||||
|
if (ret)
|
||||||
|
goto err_unmap;
|
||||||
|
|
||||||
|
bin_attr_DMI.size = dmi_len;
|
||||||
|
bin_attr_DMI.private = dmi_table;
|
||||||
|
ret = sysfs_create_bin_file(tables_kobj, &bin_attr_DMI);
|
||||||
|
if (!ret)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
sysfs_remove_bin_file(tables_kobj,
|
||||||
|
&bin_attr_smbios_entry_point);
|
||||||
|
err_unmap:
|
||||||
|
dmi_unmap(dmi_table);
|
||||||
|
err_tables:
|
||||||
|
kobject_del(tables_kobj);
|
||||||
|
kobject_put(tables_kobj);
|
||||||
|
err:
|
||||||
|
pr_err("dmi: Firmware registration failed.\n");
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
subsys_initcall(dmi_init);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* dmi_set_dump_stack_arch_desc - set arch description for dump_stack()
|
* dmi_set_dump_stack_arch_desc - set arch description for dump_stack()
|
||||||
*
|
*
|
||||||
|
@ -897,7 +984,7 @@ int dmi_walk(void (*decode)(const struct dmi_header *, void *),
|
||||||
if (buf == NULL)
|
if (buf == NULL)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
dmi_table(buf, decode, private_data);
|
dmi_decode_table(buf, decode, private_data);
|
||||||
|
|
||||||
dmi_unmap(buf);
|
dmi_unmap(buf);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
#define __DMI_H__
|
#define __DMI_H__
|
||||||
|
|
||||||
#include <linux/list.h>
|
#include <linux/list.h>
|
||||||
|
#include <linux/kobject.h>
|
||||||
#include <linux/mod_devicetable.h>
|
#include <linux/mod_devicetable.h>
|
||||||
|
|
||||||
/* enum dmi_field is in mod_devicetable.h */
|
/* enum dmi_field is in mod_devicetable.h */
|
||||||
|
@ -74,7 +75,7 @@ struct dmi_header {
|
||||||
u8 type;
|
u8 type;
|
||||||
u8 length;
|
u8 length;
|
||||||
u16 handle;
|
u16 handle;
|
||||||
};
|
} __packed;
|
||||||
|
|
||||||
struct dmi_device {
|
struct dmi_device {
|
||||||
struct list_head list;
|
struct list_head list;
|
||||||
|
@ -93,6 +94,7 @@ struct dmi_dev_onboard {
|
||||||
int devfn;
|
int devfn;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
extern struct kobject *dmi_kobj;
|
||||||
extern int dmi_check_system(const struct dmi_system_id *list);
|
extern int dmi_check_system(const struct dmi_system_id *list);
|
||||||
const struct dmi_system_id *dmi_first_match(const struct dmi_system_id *list);
|
const struct dmi_system_id *dmi_first_match(const struct dmi_system_id *list);
|
||||||
extern const char * dmi_get_system_info(int field);
|
extern const char * dmi_get_system_info(int field);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue