Some utils, like dmidecode and smbios, needs to access SMBIOS entry table area in order to get information like SMBIOS version, size, etc. Currently it's done via /dev/mem. But for situation when /dev/mem usage is disabled, the utils have to use dmi sysfs instead, which doesn't represent SMBIOS entry. So this patch series adds SMBIOS area to dmi sysfs in order to allow utils in question to work correctly with dmi sysfs.
Ivan Khoronzhuk (2): firmware: dmi_scan: add function to get SMBIOS entry area firmware: dmi-sysfs: add SMBIOS entry point area attribute
drivers/firmware/dmi-sysfs.c | 35 +++++++++++++++++++++++++++++++++++ drivers/firmware/dmi_scan.c | 43 +++++++++++++++++++++++++++++++++++++++++++ include/linux/dmi.h | 2 ++ 3 files changed, 80 insertions(+)
There are situations when code needs to access SMBIOS entry table area. For example, to pass it via sysfs to userspace when it's not allowed to get SMBIOS info via /dev/mem.
Signed-off-by: Ivan Khoronzhuk ivan.khoronzhuk@linaro.org --- drivers/firmware/dmi_scan.c | 43 +++++++++++++++++++++++++++++++++++++++++++ include/linux/dmi.h | 2 ++ 2 files changed, 45 insertions(+)
diff --git a/drivers/firmware/dmi_scan.c b/drivers/firmware/dmi_scan.c index ade4b51..174cf0b 100644 --- a/drivers/firmware/dmi_scan.c +++ b/drivers/firmware/dmi_scan.c @@ -113,6 +113,7 @@ static void dmi_table(u8 *buf, int len, int num, } }
+static phys_addr_t smbios_base; static phys_addr_t dmi_base; static u16 dmi_len; static u16 dmi_num; @@ -583,6 +584,7 @@ void __init dmi_scan_machine(void) dmi_early_unmap(p, 32);
if (!dmi_smbios3_present(buf)) { + smbios_base = efi.smbios3; dmi_available = 1; goto out; } @@ -601,6 +603,7 @@ void __init dmi_scan_machine(void) dmi_early_unmap(p, 32);
if (!dmi_present(buf)) { + smbios_base = efi.smbios; dmi_available = 1; goto out; } @@ -620,6 +623,11 @@ void __init dmi_scan_machine(void) for (q = p; q < p + 0x10000; q += 16) { memcpy_fromio(buf + 16, q, 16); if (!dmi_smbios3_present(buf) || !dmi_present(buf)) { + smbios_base = q - p + 0xF0000; + if (!memcmp(buf, "_SM_", 4) || + !memcmp(buf, "_SM3_", 5)) + smbios_base -= 16; + dmi_available = 1; dmi_early_unmap(p, 0x10000); goto out; @@ -943,3 +951,38 @@ void dmi_memdev_name(u16 handle, const char **bank, const char **device) } } EXPORT_SYMBOL_GPL(dmi_memdev_name); + +/** + * dmi_get_smbios_entry_area - copy SMBIOS entry point area to array. + * @entry - pointer on array to read area in, current max size is 32 bytes. + * + * returns -ENODATA if table is not available, otherwise returns actual + * size of SMBIOS entry point area. + */ +int dmi_get_smbios_entry_area(char *table) +{ + u8 *buf; + int size = 0; + + if (!dmi_initialized || !smbios_base) + return -ENODATA; + + buf = dmi_remap(smbios_base, 32); + + if (memcmp(buf, "_SM3_", 5) == 0) + size = buf[6]; + else if (memcmp(buf, "_SM_", 4) == 0) + size = buf[5]; + else if (memcmp(buf, "_DMI_", 5) == 0) + size = 15; + + memcpy(table, buf, size); + + dmi_unmap(buf); + + if (!size) + return -ENODATA; + + return size; +} +EXPORT_SYMBOL_GPL(dmi_get_smbios_entry_area); diff --git a/include/linux/dmi.h b/include/linux/dmi.h index f820f0a..f262d53 100644 --- a/include/linux/dmi.h +++ b/include/linux/dmi.h @@ -109,6 +109,7 @@ extern int dmi_walk(void (*decode)(const struct dmi_header *, void *), void *private_data); extern bool dmi_match(enum dmi_field f, const char *str); extern void dmi_memdev_name(u16 handle, const char **bank, const char **device); +extern int dmi_get_smbios_entry_area(char *table);
#else
@@ -140,6 +141,7 @@ static inline void dmi_memdev_name(u16 handle, const char **bank, const char **device) { } static inline const struct dmi_system_id * dmi_first_match(const struct dmi_system_id *list) { return NULL; } +static int dmi_get_smbios_entry_area(char *table) { return -ENODATA; }
#endif
Hello Ivan,
On 16 January 2015 at 17:56, Ivan Khoronzhuk ivan.khoronzhuk@linaro.org wrote:
There are situations when code needs to access SMBIOS entry table area. For example, to pass it via sysfs to userspace when it's not allowed to get SMBIOS info via /dev/mem.
Signed-off-by: Ivan Khoronzhuk ivan.khoronzhuk@linaro.org
drivers/firmware/dmi_scan.c | 43 +++++++++++++++++++++++++++++++++++++++++++ include/linux/dmi.h | 2 ++ 2 files changed, 45 insertions(+)
diff --git a/drivers/firmware/dmi_scan.c b/drivers/firmware/dmi_scan.c index ade4b51..174cf0b 100644 --- a/drivers/firmware/dmi_scan.c +++ b/drivers/firmware/dmi_scan.c @@ -113,6 +113,7 @@ static void dmi_table(u8 *buf, int len, int num, } }
+static phys_addr_t smbios_base; static phys_addr_t dmi_base;
If the kernel has managed to determine where the SMBIOS structure table is, and records the address in dmi_base, why are we still interested in the other stuff? Couldn't we just make dmi_base and dmi_len globals?
static u16 dmi_len; static u16 dmi_num; @@ -583,6 +584,7 @@ void __init dmi_scan_machine(void) dmi_early_unmap(p, 32);
if (!dmi_smbios3_present(buf)) {
smbios_base = efi.smbios3; dmi_available = 1; goto out; }
@@ -601,6 +603,7 @@ void __init dmi_scan_machine(void) dmi_early_unmap(p, 32);
if (!dmi_present(buf)) {
smbios_base = efi.smbios; dmi_available = 1; goto out; }
@@ -620,6 +623,11 @@ void __init dmi_scan_machine(void) for (q = p; q < p + 0x10000; q += 16) { memcpy_fromio(buf + 16, q, 16); if (!dmi_smbios3_present(buf) || !dmi_present(buf)) {
smbios_base = q - p + 0xF0000;
if (!memcmp(buf, "_SM_", 4) ||
!memcmp(buf, "_SM3_", 5))
smbios_base -= 16;
dmi_available = 1; dmi_early_unmap(p, 0x10000); goto out;
@@ -943,3 +951,38 @@ void dmi_memdev_name(u16 handle, const char **bank, const char **device) } } EXPORT_SYMBOL_GPL(dmi_memdev_name);
+/**
- dmi_get_smbios_entry_area - copy SMBIOS entry point area to array.
- @entry - pointer on array to read area in, current max size is 32 bytes.
- returns -ENODATA if table is not available, otherwise returns actual
- size of SMBIOS entry point area.
- */
+int dmi_get_smbios_entry_area(char *table) +{
u8 *buf;
int size = 0;
if (!dmi_initialized || !smbios_base)
return -ENODATA;
buf = dmi_remap(smbios_base, 32);
if (memcmp(buf, "_SM3_", 5) == 0)
size = buf[6];
else if (memcmp(buf, "_SM_", 4) == 0)
size = buf[5];
else if (memcmp(buf, "_DMI_", 5) == 0)
size = 15;
memcpy(table, buf, size);
dmi_unmap(buf);
if (!size)
return -ENODATA;
return size;
+} +EXPORT_SYMBOL_GPL(dmi_get_smbios_entry_area); diff --git a/include/linux/dmi.h b/include/linux/dmi.h index f820f0a..f262d53 100644 --- a/include/linux/dmi.h +++ b/include/linux/dmi.h @@ -109,6 +109,7 @@ extern int dmi_walk(void (*decode)(const struct dmi_header *, void *), void *private_data); extern bool dmi_match(enum dmi_field f, const char *str); extern void dmi_memdev_name(u16 handle, const char **bank, const char **device); +extern int dmi_get_smbios_entry_area(char *table);
#else
@@ -140,6 +141,7 @@ static inline void dmi_memdev_name(u16 handle, const char **bank, const char **device) { } static inline const struct dmi_system_id * dmi_first_match(const struct dmi_system_id *list) { return NULL; } +static int dmi_get_smbios_entry_area(char *table) { return -ENODATA; }
#endif
-- 1.9.1
Linaro-uefi mailing list Linaro-uefi@lists.linaro.org http://lists.linaro.org/mailman/listinfo/linaro-uefi
Hello Ard,
On 01/19/2015 06:06 PM, Ard Biesheuvel wrote:
Hello Ivan,
On 16 January 2015 at 17:56, Ivan Khoronzhuk ivan.khoronzhuk@linaro.org wrote:
There are situations when code needs to access SMBIOS entry table area. For example, to pass it via sysfs to userspace when it's not allowed to get SMBIOS info via /dev/mem.
Signed-off-by: Ivan Khoronzhuk ivan.khoronzhuk@linaro.org
drivers/firmware/dmi_scan.c | 43 +++++++++++++++++++++++++++++++++++++++++++ include/linux/dmi.h | 2 ++ 2 files changed, 45 insertions(+)
diff --git a/drivers/firmware/dmi_scan.c b/drivers/firmware/dmi_scan.c index ade4b51..174cf0b 100644 --- a/drivers/firmware/dmi_scan.c +++ b/drivers/firmware/dmi_scan.c @@ -113,6 +113,7 @@ static void dmi_table(u8 *buf, int len, int num, } }
+static phys_addr_t smbios_base; static phys_addr_t dmi_base;
If the kernel has managed to determine where the SMBIOS structure table is, and records the address in dmi_base, why are we still interested in the other stuff? Couldn't we just make dmi_base and dmi_len globals?
dmi_base and smbios_base are different addresses. dmi_base is the base address of dmi structure table
dmi_smbios is the base of SMBIOS entry table, that is like a pointer on a header for whole dmi talbe...
That's why a separate var was added.
static u16 dmi_len; static u16 dmi_num; @@ -583,6 +584,7 @@ void __init dmi_scan_machine(void) dmi_early_unmap(p, 32);
if (!dmi_smbios3_present(buf)) {
smbios_base = efi.smbios3; dmi_available = 1; goto out; }
@@ -601,6 +603,7 @@ void __init dmi_scan_machine(void) dmi_early_unmap(p, 32);
if (!dmi_present(buf)) {
smbios_base = efi.smbios; dmi_available = 1; goto out; }
@@ -620,6 +623,11 @@ void __init dmi_scan_machine(void) for (q = p; q < p + 0x10000; q += 16) { memcpy_fromio(buf + 16, q, 16); if (!dmi_smbios3_present(buf) || !dmi_present(buf)) {
smbios_base = q - p + 0xF0000;
if (!memcmp(buf, "_SM_", 4) ||
!memcmp(buf, "_SM3_", 5))
smbios_base -= 16;
dmi_available = 1; dmi_early_unmap(p, 0x10000); goto out;
@@ -943,3 +951,38 @@ void dmi_memdev_name(u16 handle, const char **bank, const char **device) } } EXPORT_SYMBOL_GPL(dmi_memdev_name);
+/**
- dmi_get_smbios_entry_area - copy SMBIOS entry point area to array.
- @entry - pointer on array to read area in, current max size is 32 bytes.
- returns -ENODATA if table is not available, otherwise returns actual
- size of SMBIOS entry point area.
- */
+int dmi_get_smbios_entry_area(char *table) +{
u8 *buf;
int size = 0;
if (!dmi_initialized || !smbios_base)
return -ENODATA;
buf = dmi_remap(smbios_base, 32);
if (memcmp(buf, "_SM3_", 5) == 0)
size = buf[6];
else if (memcmp(buf, "_SM_", 4) == 0)
size = buf[5];
else if (memcmp(buf, "_DMI_", 5) == 0)
size = 15;
memcpy(table, buf, size);
dmi_unmap(buf);
if (!size)
return -ENODATA;
return size;
+} +EXPORT_SYMBOL_GPL(dmi_get_smbios_entry_area); diff --git a/include/linux/dmi.h b/include/linux/dmi.h index f820f0a..f262d53 100644 --- a/include/linux/dmi.h +++ b/include/linux/dmi.h @@ -109,6 +109,7 @@ extern int dmi_walk(void (*decode)(const struct dmi_header *, void *), void *private_data); extern bool dmi_match(enum dmi_field f, const char *str); extern void dmi_memdev_name(u16 handle, const char **bank, const char **device); +extern int dmi_get_smbios_entry_area(char *table);
#else
@@ -140,6 +141,7 @@ static inline void dmi_memdev_name(u16 handle, const char **bank, const char **device) { } static inline const struct dmi_system_id * dmi_first_match(const struct dmi_system_id *list) { return NULL; } +static int dmi_get_smbios_entry_area(char *table) { return -ENODATA; }
#endif
-- 1.9.1
Linaro-uefi mailing list Linaro-uefi@lists.linaro.org http://lists.linaro.org/mailman/listinfo/linaro-uefi
On 19 January 2015 at 16:43, Ivan Khoronzhuk ivan.khoronzhuk@linaro.org wrote:
Hello Ard,
On 01/19/2015 06:06 PM, Ard Biesheuvel wrote:
Hello Ivan,
On 16 January 2015 at 17:56, Ivan Khoronzhuk ivan.khoronzhuk@linaro.org wrote:
There are situations when code needs to access SMBIOS entry table area. For example, to pass it via sysfs to userspace when it's not allowed to get SMBIOS info via /dev/mem.
Signed-off-by: Ivan Khoronzhuk ivan.khoronzhuk@linaro.org
drivers/firmware/dmi_scan.c | 43 +++++++++++++++++++++++++++++++++++++++++++ include/linux/dmi.h | 2 ++ 2 files changed, 45 insertions(+)
diff --git a/drivers/firmware/dmi_scan.c b/drivers/firmware/dmi_scan.c index ade4b51..174cf0b 100644 --- a/drivers/firmware/dmi_scan.c +++ b/drivers/firmware/dmi_scan.c @@ -113,6 +113,7 @@ static void dmi_table(u8 *buf, int len, int num, } }
+static phys_addr_t smbios_base; static phys_addr_t dmi_base;
If the kernel has managed to determine where the SMBIOS structure table is, and records the address in dmi_base, why are we still interested in the other stuff? Couldn't we just make dmi_base and dmi_len globals?
dmi_base and smbios_base are different addresses. dmi_base is the base address of dmi structure table
dmi_smbios is the base of SMBIOS entry table, that is like a pointer on a header for whole dmi talbe...
That's why a separate var was added.
OK, got it.
Then, could we perhaps just copy the 32 bytes into a global char[32] at scan time?
static u16 dmi_len; static u16 dmi_num; @@ -583,6 +584,7 @@ void __init dmi_scan_machine(void) dmi_early_unmap(p, 32);
if (!dmi_smbios3_present(buf)) {
smbios_base = efi.smbios3; dmi_available = 1; goto out; }
@@ -601,6 +603,7 @@ void __init dmi_scan_machine(void) dmi_early_unmap(p, 32);
if (!dmi_present(buf)) {
smbios_base = efi.smbios; dmi_available = 1; goto out; }
@@ -620,6 +623,11 @@ void __init dmi_scan_machine(void) for (q = p; q < p + 0x10000; q += 16) { memcpy_fromio(buf + 16, q, 16); if (!dmi_smbios3_present(buf) || !dmi_present(buf)) {
smbios_base = q - p + 0xF0000;
if (!memcmp(buf, "_SM_", 4) ||
!memcmp(buf, "_SM3_", 5))
smbios_base -= 16;
dmi_available = 1; dmi_early_unmap(p, 0x10000); goto out;
@@ -943,3 +951,38 @@ void dmi_memdev_name(u16 handle, const char **bank, const char **device) } } EXPORT_SYMBOL_GPL(dmi_memdev_name);
+/**
- dmi_get_smbios_entry_area - copy SMBIOS entry point area to array.
- @entry - pointer on array to read area in, current max size is 32
bytes.
- returns -ENODATA if table is not available, otherwise returns actual
- size of SMBIOS entry point area.
- */
+int dmi_get_smbios_entry_area(char *table) +{
u8 *buf;
int size = 0;
if (!dmi_initialized || !smbios_base)
return -ENODATA;
buf = dmi_remap(smbios_base, 32);
if (memcmp(buf, "_SM3_", 5) == 0)
size = buf[6];
else if (memcmp(buf, "_SM_", 4) == 0)
size = buf[5];
else if (memcmp(buf, "_DMI_", 5) == 0)
size = 15;
memcpy(table, buf, size);
dmi_unmap(buf);
if (!size)
return -ENODATA;
return size;
+} +EXPORT_SYMBOL_GPL(dmi_get_smbios_entry_area); diff --git a/include/linux/dmi.h b/include/linux/dmi.h index f820f0a..f262d53 100644 --- a/include/linux/dmi.h +++ b/include/linux/dmi.h @@ -109,6 +109,7 @@ extern int dmi_walk(void (*decode)(const struct dmi_header *, void *), void *private_data); extern bool dmi_match(enum dmi_field f, const char *str); extern void dmi_memdev_name(u16 handle, const char **bank, const char **device); +extern int dmi_get_smbios_entry_area(char *table);
#else
@@ -140,6 +141,7 @@ static inline void dmi_memdev_name(u16 handle, const char **bank, const char **device) { } static inline const struct dmi_system_id * dmi_first_match(const struct dmi_system_id *list) { return NULL; } +static int dmi_get_smbios_entry_area(char *table) { return -ENODATA; }
#endif
-- 1.9.1
Linaro-uefi mailing list Linaro-uefi@lists.linaro.org http://lists.linaro.org/mailman/listinfo/linaro-uefi
On 01/21/2015 11:02 AM, Ard Biesheuvel wrote:
On 19 January 2015 at 16:43, Ivan Khoronzhuk ivan.khoronzhuk@linaro.org wrote:
Hello Ard,
On 01/19/2015 06:06 PM, Ard Biesheuvel wrote:
Hello Ivan,
On 16 January 2015 at 17:56, Ivan Khoronzhuk ivan.khoronzhuk@linaro.org wrote:
There are situations when code needs to access SMBIOS entry table area. For example, to pass it via sysfs to userspace when it's not allowed to get SMBIOS info via /dev/mem.
Signed-off-by: Ivan Khoronzhuk ivan.khoronzhuk@linaro.org
drivers/firmware/dmi_scan.c | 43 +++++++++++++++++++++++++++++++++++++++++++ include/linux/dmi.h | 2 ++ 2 files changed, 45 insertions(+)
diff --git a/drivers/firmware/dmi_scan.c b/drivers/firmware/dmi_scan.c index ade4b51..174cf0b 100644 --- a/drivers/firmware/dmi_scan.c +++ b/drivers/firmware/dmi_scan.c @@ -113,6 +113,7 @@ static void dmi_table(u8 *buf, int len, int num, } }
+static phys_addr_t smbios_base; static phys_addr_t dmi_base;
If the kernel has managed to determine where the SMBIOS structure table is, and records the address in dmi_base, why are we still interested in the other stuff? Couldn't we just make dmi_base and dmi_len globals?
dmi_base and smbios_base are different addresses. dmi_base is the base address of dmi structure table
dmi_smbios is the base of SMBIOS entry table, that is like a pointer on a header for whole dmi talbe...
That's why a separate var was added.
OK, got it.
Then, could we perhaps just copy the 32 bytes into a global char[32] at scan time?
We could of-course. I thought about this also. But I just wanted to do it like dmi raw, when to get dmi table structure we remap/unmap dmi table each time.
static u16 dmi_len; static u16 dmi_num; @@ -583,6 +584,7 @@ void __init dmi_scan_machine(void) dmi_early_unmap(p, 32);
if (!dmi_smbios3_present(buf)) {
smbios_base = efi.smbios3; dmi_available = 1; goto out; }
@@ -601,6 +603,7 @@ void __init dmi_scan_machine(void) dmi_early_unmap(p, 32);
if (!dmi_present(buf)) {
smbios_base = efi.smbios; dmi_available = 1; goto out; }
@@ -620,6 +623,11 @@ void __init dmi_scan_machine(void) for (q = p; q < p + 0x10000; q += 16) { memcpy_fromio(buf + 16, q, 16); if (!dmi_smbios3_present(buf) || !dmi_present(buf)) {
smbios_base = q - p + 0xF0000;
if (!memcmp(buf, "_SM_", 4) ||
!memcmp(buf, "_SM3_", 5))
smbios_base -= 16;
dmi_available = 1; dmi_early_unmap(p, 0x10000); goto out;
@@ -943,3 +951,38 @@ void dmi_memdev_name(u16 handle, const char **bank, const char **device) } } EXPORT_SYMBOL_GPL(dmi_memdev_name);
+/**
- dmi_get_smbios_entry_area - copy SMBIOS entry point area to array.
- @entry - pointer on array to read area in, current max size is 32
bytes.
- returns -ENODATA if table is not available, otherwise returns actual
- size of SMBIOS entry point area.
- */
+int dmi_get_smbios_entry_area(char *table) +{
u8 *buf;
int size = 0;
if (!dmi_initialized || !smbios_base)
return -ENODATA;
buf = dmi_remap(smbios_base, 32);
if (memcmp(buf, "_SM3_", 5) == 0)
size = buf[6];
else if (memcmp(buf, "_SM_", 4) == 0)
size = buf[5];
else if (memcmp(buf, "_DMI_", 5) == 0)
size = 15;
memcpy(table, buf, size);
dmi_unmap(buf);
if (!size)
return -ENODATA;
return size;
+} +EXPORT_SYMBOL_GPL(dmi_get_smbios_entry_area); diff --git a/include/linux/dmi.h b/include/linux/dmi.h index f820f0a..f262d53 100644 --- a/include/linux/dmi.h +++ b/include/linux/dmi.h @@ -109,6 +109,7 @@ extern int dmi_walk(void (*decode)(const struct dmi_header *, void *), void *private_data); extern bool dmi_match(enum dmi_field f, const char *str); extern void dmi_memdev_name(u16 handle, const char **bank, const char **device); +extern int dmi_get_smbios_entry_area(char *table);
#else
@@ -140,6 +141,7 @@ static inline void dmi_memdev_name(u16 handle, const char **bank, const char **device) { } static inline const struct dmi_system_id * dmi_first_match(const struct dmi_system_id *list) { return NULL; } +static int dmi_get_smbios_entry_area(char *table) { return -ENODATA; }
#endif
-- 1.9.1
Linaro-uefi mailing list Linaro-uefi@lists.linaro.org http://lists.linaro.org/mailman/listinfo/linaro-uefi
On 21 January 2015 at 10:52, Ivan Khoronzhuk ivan.khoronzhuk@linaro.org wrote:
On 01/21/2015 11:02 AM, Ard Biesheuvel wrote:
On 19 January 2015 at 16:43, Ivan Khoronzhuk ivan.khoronzhuk@linaro.org wrote:
Hello Ard,
On 01/19/2015 06:06 PM, Ard Biesheuvel wrote:
Hello Ivan,
On 16 January 2015 at 17:56, Ivan Khoronzhuk ivan.khoronzhuk@linaro.org wrote:
There are situations when code needs to access SMBIOS entry table area. For example, to pass it via sysfs to userspace when it's not allowed to get SMBIOS info via /dev/mem.
Signed-off-by: Ivan Khoronzhuk ivan.khoronzhuk@linaro.org
drivers/firmware/dmi_scan.c | 43 +++++++++++++++++++++++++++++++++++++++++++ include/linux/dmi.h | 2 ++ 2 files changed, 45 insertions(+)
diff --git a/drivers/firmware/dmi_scan.c b/drivers/firmware/dmi_scan.c index ade4b51..174cf0b 100644 --- a/drivers/firmware/dmi_scan.c +++ b/drivers/firmware/dmi_scan.c @@ -113,6 +113,7 @@ static void dmi_table(u8 *buf, int len, int num, } }
+static phys_addr_t smbios_base; static phys_addr_t dmi_base;
If the kernel has managed to determine where the SMBIOS structure table is, and records the address in dmi_base, why are we still interested in the other stuff? Couldn't we just make dmi_base and dmi_len globals?
dmi_base and smbios_base are different addresses. dmi_base is the base address of dmi structure table
dmi_smbios is the base of SMBIOS entry table, that is like a pointer on a header for whole dmi talbe...
That's why a separate var was added.
OK, got it.
Then, could we perhaps just copy the 32 bytes into a global char[32] at scan time?
We could of-course. I thought about this also. But I just wanted to do it like dmi raw, when to get dmi table structure we rema p/unmap dmi table each time.
Actually, the most correct way would be to capture the header at the same time as the entries are populated. So fill the char[32] with a call from dmi_sysfs_init() and return this data every time the file is read.
static u16 dmi_len; static u16 dmi_num; @@ -583,6 +584,7 @@ void __init dmi_scan_machine(void) dmi_early_unmap(p, 32);
if (!dmi_smbios3_present(buf)) {
smbios_base = efi.smbios3; dmi_available = 1; goto out; }
@@ -601,6 +603,7 @@ void __init dmi_scan_machine(void) dmi_early_unmap(p, 32);
if (!dmi_present(buf)) {
smbios_base = efi.smbios; dmi_available = 1; goto out; }
@@ -620,6 +623,11 @@ void __init dmi_scan_machine(void) for (q = p; q < p + 0x10000; q += 16) { memcpy_fromio(buf + 16, q, 16); if (!dmi_smbios3_present(buf) || !dmi_present(buf)) {
smbios_base = q - p + 0xF0000;
if (!memcmp(buf, "_SM_", 4) ||
!memcmp(buf, "_SM3_", 5))
smbios_base -= 16;
dmi_available = 1; dmi_early_unmap(p, 0x10000); goto out;
@@ -943,3 +951,38 @@ void dmi_memdev_name(u16 handle, const char **bank, const char **device) } } EXPORT_SYMBOL_GPL(dmi_memdev_name);
+/**
- dmi_get_smbios_entry_area - copy SMBIOS entry point area to array.
- @entry - pointer on array to read area in, current max size is 32
bytes.
- returns -ENODATA if table is not available, otherwise returns
actual
- size of SMBIOS entry point area.
- */
+int dmi_get_smbios_entry_area(char *table) +{
u8 *buf;
int size = 0;
if (!dmi_initialized || !smbios_base)
return -ENODATA;
buf = dmi_remap(smbios_base, 32);
if (memcmp(buf, "_SM3_", 5) == 0)
size = buf[6];
else if (memcmp(buf, "_SM_", 4) == 0)
size = buf[5];
else if (memcmp(buf, "_DMI_", 5) == 0)
size = 15;
memcpy(table, buf, size);
dmi_unmap(buf);
if (!size)
return -ENODATA;
return size;
+} +EXPORT_SYMBOL_GPL(dmi_get_smbios_entry_area); diff --git a/include/linux/dmi.h b/include/linux/dmi.h index f820f0a..f262d53 100644 --- a/include/linux/dmi.h +++ b/include/linux/dmi.h @@ -109,6 +109,7 @@ extern int dmi_walk(void (*decode)(const struct dmi_header *, void *), void *private_data); extern bool dmi_match(enum dmi_field f, const char *str); extern void dmi_memdev_name(u16 handle, const char **bank, const char **device); +extern int dmi_get_smbios_entry_area(char *table);
#else
@@ -140,6 +141,7 @@ static inline void dmi_memdev_name(u16 handle, const char **bank, const char **device) { } static inline const struct dmi_system_id * dmi_first_match(const struct dmi_system_id *list) { return NULL; } +static int dmi_get_smbios_entry_area(char *table) { return -ENODATA; }
#endif
-- 1.9.1
Linaro-uefi mailing list Linaro-uefi@lists.linaro.org http://lists.linaro.org/mailman/listinfo/linaro-uefi
There are situations when code needs to access SMBIOS entry table area, but cannot use /dev/mem for this. As the table format is consistent only for a version, and can be changed, use binary attribute to give access to raw SMBIOS entry table area.
Signed-off-by: Ivan Khoronzhuk ivan.khoronzhuk@linaro.org --- drivers/firmware/dmi-sysfs.c | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+)
diff --git a/drivers/firmware/dmi-sysfs.c b/drivers/firmware/dmi-sysfs.c index e0f1cb3..c308b8b 100644 --- a/drivers/firmware/dmi-sysfs.c +++ b/drivers/firmware/dmi-sysfs.c @@ -646,6 +646,37 @@ static void cleanup_entry_list(void) } }
+static ssize_t smbios_entry_area_raw_read(struct file *filp, + struct kobject *kobj, + struct bin_attribute *bin_attr, + char *buf, loff_t pos, size_t count) +{ + ssize_t size; + unsigned char area[32]; + + size = dmi_get_smbios_entry_area(area); + if (size == -ENODATA) + return size; + + if (size > pos) + size -= pos; + else + return 0; + + if (count < size) + size = count; + + memcpy(buf, &area[pos], size); + + return size; +} + +static const struct bin_attribute smbios_entry_area_raw_attr = { + .size = 32, + .read = smbios_entry_area_raw_read, + .attr = {.name = "smbios_raw", .mode = 0400}, +}; + static int __init dmi_sysfs_init(void) { int error = -ENOMEM; @@ -656,6 +687,10 @@ static int __init dmi_sysfs_init(void) if (!dmi_kobj) goto err;
+ /* Create the raw binary file to access the entry area */ + if (sysfs_create_bin_file(dmi_kobj, &smbios_entry_area_raw_attr)) + goto err; + dmi_kset = kset_create_and_add("entries", NULL, dmi_kobj); if (!dmi_kset) goto err;
On 16 January 2015 at 17:56, Ivan Khoronzhuk ivan.khoronzhuk@linaro.org wrote:
There are situations when code needs to access SMBIOS entry table area, but cannot use /dev/mem for this. As the table format is consistent only for a version, and can be changed, use binary attribute to give access to raw SMBIOS entry table area.
So now we have a sysfs entry for the entry point, but still need /dev/mem to get at the actual data?
Signed-off-by: Ivan Khoronzhuk ivan.khoronzhuk@linaro.org
drivers/firmware/dmi-sysfs.c | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+)
diff --git a/drivers/firmware/dmi-sysfs.c b/drivers/firmware/dmi-sysfs.c index e0f1cb3..c308b8b 100644 --- a/drivers/firmware/dmi-sysfs.c +++ b/drivers/firmware/dmi-sysfs.c @@ -646,6 +646,37 @@ static void cleanup_entry_list(void) } }
+static ssize_t smbios_entry_area_raw_read(struct file *filp,
struct kobject *kobj,
struct bin_attribute *bin_attr,
char *buf, loff_t pos, size_t count)
+{
ssize_t size;
unsigned char area[32];
size = dmi_get_smbios_entry_area(area);
if (size == -ENODATA)
return size;
if (size > pos)
size -= pos;
else
return 0;
if (count < size)
size = count;
memcpy(buf, &area[pos], size);
return size;
+}
+static const struct bin_attribute smbios_entry_area_raw_attr = {
.size = 32,
.read = smbios_entry_area_raw_read,
.attr = {.name = "smbios_raw", .mode = 0400},
+};
static int __init dmi_sysfs_init(void) { int error = -ENOMEM; @@ -656,6 +687,10 @@ static int __init dmi_sysfs_init(void) if (!dmi_kobj) goto err;
/* Create the raw binary file to access the entry area */
if (sysfs_create_bin_file(dmi_kobj, &smbios_entry_area_raw_attr))
goto err;
dmi_kset = kset_create_and_add("entries", NULL, dmi_kobj); if (!dmi_kset) goto err;
-- 1.9.1
Linaro-uefi mailing list Linaro-uefi@lists.linaro.org http://lists.linaro.org/mailman/listinfo/linaro-uefi
On 19 January 2015 at 16:07, Ard Biesheuvel ard.biesheuvel@linaro.org wrote:
On 16 January 2015 at 17:56, Ivan Khoronzhuk ivan.khoronzhuk@linaro.org wrote:
There are situations when code needs to access SMBIOS entry table area, but cannot use /dev/mem for this. As the table format is consistent only for a version, and can be changed, use binary attribute to give access to raw SMBIOS entry table area.
So now we have a sysfs entry for the entry point, but still need /dev/mem to get at the actual data?
Ignore me, I was looking in the wrong place in /sys
So as I understand it, you need these patches to get at the payload of the entry point, i.e., the version number.
Could we instead export the version number directly, and not bother with recording and remapping the structure table? The version is already recorded in dmi_ver afaik,
On 01/19/2015 06:20 PM, Ard Biesheuvel wrote:
On 19 January 2015 at 16:07, Ard Biesheuvel ard.biesheuvel@linaro.org wrote:
On 16 January 2015 at 17:56, Ivan Khoronzhuk ivan.khoronzhuk@linaro.org wrote:
There are situations when code needs to access SMBIOS entry table area, but cannot use /dev/mem for this. As the table format is consistent only for a version, and can be changed, use binary attribute to give access to raw SMBIOS entry table area.
So now we have a sysfs entry for the entry point, but still need /dev/mem to get at the actual data?
Ignore me, I was looking in the wrong place in /sys
So as I understand it, you need these patches to get at the payload of the entry point, i.e., the version number.
The version number is not only var that can be required by utils. For example, dmidecode needs also print some additional info like phys address where dmitable is placed.
Also I don't sure how exactly next SMBIOS version will be changed. It can happen that some new data is available...and some old is removed. It's better to export it as raw data like it was done for dmi entries via raw attribute.
Could we instead export the version number directly, and not bother with recording and remapping the structure table? The version is already recorded in dmi_ver afaik,
dmi_ver is not only one var from SMBIOS entry table. It's better pass the whole entry table instead of each time modify the dmi sysfs interface when new SMBIOS version is issued.
On 19 January 2015 at 16:57, Ivan Khoronzhuk ivan.khoronzhuk@linaro.org wrote:
On 01/19/2015 06:20 PM, Ard Biesheuvel wrote:
On 19 January 2015 at 16:07, Ard Biesheuvel ard.biesheuvel@linaro.org wrote:
On 16 January 2015 at 17:56, Ivan Khoronzhuk ivan.khoronzhuk@linaro.org wrote:
There are situations when code needs to access SMBIOS entry table area, but cannot use /dev/mem for this. As the table format is consistent only for a version, and can be changed, use binary attribute to give access to raw SMBIOS entry table area.
So now we have a sysfs entry for the entry point, but still need /dev/mem to get at the actual data?
Ignore me, I was looking in the wrong place in /sys
So as I understand it, you need these patches to get at the payload of the entry point, i.e., the version number.
The version number is not only var that can be required by utils. For example, dmidecode needs also print some additional info like phys address where dmitable is placed.
Also I don't sure how exactly next SMBIOS version will be changed. It can happen that some new data is available...and some old is removed. It's better to export it as raw data like it was done for dmi entries via raw attribute.
OK.
Could we instead export the version number directly, and not bother with recording and remapping the structure table? The version is already recorded in dmi_ver afaik,
dmi_ver is not only one var from SMBIOS entry table. It's better pass the whole entry table instead of each time modify the dmi sysfs interface when new SMBIOS version is issued.
I think there is a number of things you can do to simplify this patch: - use the global char[32] i suggested in the other thread - move the create_bin_file call to after dmi_walk() so that it instantiates the sysfs entry only if (dmi_available) - use __BIN_ATTR_RO() instead of opencoding the struct initializers - the file size is fixed at 32 bytes, so the read call should return 32 bytes even if the payload of the header is smaller. - could we put it the header in /sys/firmware/dmi/raw/header perhaps?
Thanks, Ard.
On 01/21/2015 11:18 AM, Ard Biesheuvel wrote:
On 19 January 2015 at 16:57, Ivan Khoronzhuk ivan.khoronzhuk@linaro.org wrote:
On 01/19/2015 06:20 PM, Ard Biesheuvel wrote:
On 19 January 2015 at 16:07, Ard Biesheuvel ard.biesheuvel@linaro.org wrote:
On 16 January 2015 at 17:56, Ivan Khoronzhuk ivan.khoronzhuk@linaro.org wrote:
There are situations when code needs to access SMBIOS entry table area, but cannot use /dev/mem for this. As the table format is consistent only for a version, and can be changed, use binary attribute to give access to raw SMBIOS entry table area.
So now we have a sysfs entry for the entry point, but still need /dev/mem to get at the actual data?
Ignore me, I was looking in the wrong place in /sys
So as I understand it, you need these patches to get at the payload of the entry point, i.e., the version number.
The version number is not only var that can be required by utils. For example, dmidecode needs also print some additional info like phys address where dmitable is placed.
Also I don't sure how exactly next SMBIOS version will be changed. It can happen that some new data is available...and some old is removed. It's better to export it as raw data like it was done for dmi entries via raw attribute.
OK.
Could we instead export the version number directly, and not bother with recording and remapping the structure table? The version is already recorded in dmi_ver afaik,
dmi_ver is not only one var from SMBIOS entry table. It's better pass the whole entry table instead of each time modify the dmi sysfs interface when new SMBIOS version is issued.
I think there is a number of things you can do to simplify this patch:
- use the global char[32] i suggested in the other thread
Ok.
- move the create_bin_file call to after dmi_walk() so that it
instantiates the sysfs entry only if (dmi_available)
yes.
- use __BIN_ATTR_RO() instead of opencoding the struct initializers
In this case the following question will be reasonable: why we have different modes for "raw" attributes from entries kset and for "smbios_raw". __BIN_ATTR_RO assigns 0444.
- the file size is fixed at 32 bytes, so the read call should return
32 bytes even if the payload of the header is smaller.
Let it be.
PS: paranoid thought: ... return redundant data from kernel (security... who knows in what way it can be used)
- could we put it the header in /sys/firmware/dmi/raw/header perhaps?
In this case we need to create kset then attribute w/o visible reason. It be justified if we create smth like ./dmi/smbios/raw and ./dmi/smbios/version but currently I don't see reasons for that.
Thanks, Ard.
On 21 January 2015 at 11:53, Ivan Khoronzhuk ivan.khoronzhuk@linaro.org wrote:
On 01/21/2015 11:18 AM, Ard Biesheuvel wrote:
On 19 January 2015 at 16:57, Ivan Khoronzhuk ivan.khoronzhuk@linaro.org wrote:
On 01/19/2015 06:20 PM, Ard Biesheuvel wrote:
On 19 January 2015 at 16:07, Ard Biesheuvel ard.biesheuvel@linaro.org wrote:
On 16 January 2015 at 17:56, Ivan Khoronzhuk ivan.khoronzhuk@linaro.org wrote:
There are situations when code needs to access SMBIOS entry table area, but cannot use /dev/mem for this. As the table format is consistent only for a version, and can be changed, use binary attribute to give access to raw SMBIOS entry table area.
So now we have a sysfs entry for the entry point, but still need /dev/mem to get at the actual data?
Ignore me, I was looking in the wrong place in /sys
So as I understand it, you need these patches to get at the payload of the entry point, i.e., the version number.
The version number is not only var that can be required by utils. For example, dmidecode needs also print some additional info like phys address where dmitable is placed.
Also I don't sure how exactly next SMBIOS version will be changed. It can happen that some new data is available...and some old is removed. It's better to export it as raw data like it was done for dmi entries via raw attribute.
OK.
Could we instead export the version number directly, and not bother with recording and remapping the structure table? The version is already recorded in dmi_ver afaik,
dmi_ver is not only one var from SMBIOS entry table. It's better pass the whole entry table instead of each time modify the dmi sysfs interface when new SMBIOS version is issued.
I think there is a number of things you can do to simplify this patch:
- use the global char[32] i suggested in the other thread
Ok.
- move the create_bin_file call to after dmi_walk() so that it
instantiates the sysfs entry only if (dmi_available)
yes.
- use __BIN_ATTR_RO() instead of opencoding the struct initializers
In this case the following question will be reasonable: why we have different modes for "raw" attributes from entries kset and for "smbios_raw". __BIN_ATTR_RO assigns 0444.
Ah ok, I didn't notice that. I think 0400 is preferable.
- the file size is fixed at 32 bytes, so the read call should return
32 bytes even if the payload of the header is smaller.
Let it be.
Ehm, no
If stat() returns a file size of 32 bytes, read() should produce 32 bytes worth of data
You could drop the const from the struct bin_attribute and set the filesize dynamically if you like
PS: paranoid thought: ... return redundant data from kernel (security... who knows in what way it can be used)
Well, a static char[32] will be zero initialized, so if you make sure you don't memcpy() more that you need, we'll be fine.
- could we put it the header in /sys/firmware/dmi/raw/header perhaps?
In this case we need to create kset then attribute w/o visible reason. It be justified if we create smth like ./dmi/smbios/raw and ./dmi/smbios/version but currently I don't see reasons for that.
OK fair enough. Could we at least put 'header' in the name? 'smbios_raw" suggests it is the whole table.
On 01/21/2015 02:11 PM, Ard Biesheuvel wrote:
On 21 January 2015 at 11:53, Ivan Khoronzhuk ivan.khoronzhuk@linaro.org wrote:
On 01/21/2015 11:18 AM, Ard Biesheuvel wrote:
On 19 January 2015 at 16:57, Ivan Khoronzhuk ivan.khoronzhuk@linaro.org wrote:
On 01/19/2015 06:20 PM, Ard Biesheuvel wrote:
On 19 January 2015 at 16:07, Ard Biesheuvel ard.biesheuvel@linaro.org wrote:
On 16 January 2015 at 17:56, Ivan Khoronzhuk ivan.khoronzhuk@linaro.org wrote: > There are situations when code needs to access SMBIOS entry table > area, but cannot use /dev/mem for this. As the table format is > consistent only for a version, and can be changed, use binary > attribute to give access to raw SMBIOS entry table area. > So now we have a sysfs entry for the entry point, but still need /dev/mem to get at the actual data?
Ignore me, I was looking in the wrong place in /sys
So as I understand it, you need these patches to get at the payload of the entry point, i.e., the version number.
The version number is not only var that can be required by utils. For example, dmidecode needs also print some additional info like phys address where dmitable is placed.
Also I don't sure how exactly next SMBIOS version will be changed. It can happen that some new data is available...and some old is removed. It's better to export it as raw data like it was done for dmi entries via raw attribute.
OK.
Could we instead export the version number directly, and not bother with recording and remapping the structure table? The version is already recorded in dmi_ver afaik,
dmi_ver is not only one var from SMBIOS entry table. It's better pass the whole entry table instead of each time modify the dmi sysfs interface when new SMBIOS version is issued.
I think there is a number of things you can do to simplify this patch:
- use the global char[32] i suggested in the other thread
Ok.
- move the create_bin_file call to after dmi_walk() so that it
instantiates the sysfs entry only if (dmi_available)
yes.
- use __BIN_ATTR_RO() instead of opencoding the struct initializers
In this case the following question will be reasonable: why we have different modes for "raw" attributes from entries kset and for "smbios_raw". __BIN_ATTR_RO assigns 0444.
Ah ok, I didn't notice that. I think 0400 is preferable.
- the file size is fixed at 32 bytes, so the read call should return
32 bytes even if the payload of the header is smaller.
Let it be.
Ehm, no
If stat() returns a file size of 32 bytes, read() should produce 32 bytes worth of data
You could drop the const from the struct bin_attribute and set the filesize dynamically if you like
I thought that size is the maximum size of the binary attribute. And if I don't need to limit it, you can leave it 0, what means I have no maximum, as it was done for dmi "raw" attribute. What will return stat() in this case?
Let it return 32 bytes always, as there are no problems with this.
PS: paranoid thought: ... return redundant data from kernel (security... who knows in what way it can be used)
Well, a static char[32] will be zero initialized, so if you make sure you don't memcpy() more that you need, we'll be fine.
- could we put it the header in /sys/firmware/dmi/raw/header perhaps?
In this case we need to create kset then attribute w/o visible reason. It be justified if we create smth like ./dmi/smbios/raw and ./dmi/smbios/version but currently I don't see reasons for that.
OK fair enough. Could we at least put 'header' in the name? 'smbios_raw" suggests it is the whole table.
Ok, I'll name it smbios_raw_header. Thanks! I'll send new version soon.