[PATCH] use SMBIOS tables on ARM for lscpu

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



ARM SBBR (Sever Base Boot Requirements) require SMBIOS tables, and
SMBIOS Type 4 describes the CPU manufacturer and model name (among other
details).  If SMBIOS Type 4 is present, use it to extract these strings.

Example output (before and after the patch) on an HP m400, Lenovo HR330A,
and HPE Apollo 70:

[root@hp-m400 ~]# /usr/bin/lscpu | grep -i -e vendor -e model -e stepping
Vendor ID:           APM
Model:               1
Model name:          X-Gene
Stepping:            0x0
[root@hp-m400 ~]# ./lscpu | grep -i -e vendor -e model -e stepping
Vendor ID:                       AppliedMicro
Model:                           1
Model name:                      X-Gene
Stepping:                        0x0

[root@lenovo-hr330a ~]# /usr/bin/lscpu | grep -i -e vendor -e model -e stepping
Vendor ID:           APM
Model:               2
Model name:          X-Gene
Stepping:            0x3
[root@lenovo-hr330a ~]# ./lscpu | grep -i -e vendor -e model -e stepping
Vendor ID:                       Ampere(TM)
Model:                           2
Model name:                      eMAG
Stepping:                        0x3

[root@hpe-apollo-70 ~]# /usr/bin/lscpu | grep -i -e vendor -e model -e stepping
Vendor ID:           Cavium
Model:               1
Model name:          ThunderX2 99xx
Stepping:            0x1
[root@hpe-apollo-70 ~]# ./lscpu | grep -i -e vendor -e model -e stepping
Vendor ID:                       Cavium Inc.
Model:                           1
Model name:                      Cavium ThunderX2(R) CPU CN9980 v2.1 @ 2.20GHz
Stepping:                        0x1

Signed-off-by: Jeffrey Bastian <jbastian@xxxxxxxxxx>
---
 sys-utils/lscpu-arm.c | 88 ++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 87 insertions(+), 1 deletion(-)

diff --git a/sys-utils/lscpu-arm.c b/sys-utils/lscpu-arm.c
index 270866191875..82cc23ca830c 100644
--- a/sys-utils/lscpu-arm.c
+++ b/sys-utils/lscpu-arm.c
@@ -22,7 +22,15 @@
  *  - Linux kernel: arch/armX/include/asm/cputype.h
  *  - GCC sources: config/arch/arch-cores.def
  *  - Ancient wisdom
+ *  - SMBIOS tables (if applicable)
  */
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
 #include "lscpu.h"
struct id_part {
@@ -202,7 +210,7 @@ static const struct hw_impl hw_implementer[] = {
     { -1,   unknown_part, "unknown" },
 };
-void arm_cpu_decode(struct lscpu_desc *desc)
+static void _arm_cpu_decode(struct lscpu_desc *desc)
 {
 	int j, impl, part;
 	const struct id_part *parts = NULL;
@@ -260,3 +268,81 @@ void arm_cpu_decode(struct lscpu_desc *desc)
 		desc->stepping = xstrdup(buf);
 	}
 }
+
+/* TODO: struct dmi_header, to_dmi_header() and dmi_string() are copied
+ * from lscpu-dmi.c.  Move them to a library?
+ */
+struct dmi_header
+{
+	uint8_t type;
+	uint8_t length;
+	uint16_t handle;
+	uint8_t *data;
+};
+
+static void to_dmi_header(struct dmi_header *h, uint8_t *data)
+{
+	h->type = data[0];
+	h->length = data[1];
+	memcpy(&h->handle, data + 2, sizeof(h->handle));
+	h->data = data;
+}
+
+static char *dmi_string(const struct dmi_header *dm, uint8_t s)
+{
+	char *bp = (char *)dm->data;
+
+	if (s == 0)
+		return NULL;
+
+	bp += dm->length;
+	while (s > 1 && *bp)
+	{
+		bp += strlen(bp);
+		bp++;
+		s--;
+	}
+
+	if (!*bp)
+		return NULL;
+
+	return bp;
+}
+
+#define _PATH_SYS_DMI_TYPE4	"/sys/firmware/dmi/entries/4-0/raw"
+#define PROC_MFR_OFFSET		0x07
+#define PROC_VERSION_OFFSET	0x10
+
+static void _arm_cpu_smbios(struct lscpu_desc *desc)
+{
+	uint8_t data[8192];
+	char buf[128];
+	struct dmi_header h;
+	int raw_fd = -1;
+
+	raw_fd = open(_PATH_SYS_DMI_TYPE4, O_RDONLY);
+	if (raw_fd == -1) {
+		return;
+	}
+	read(raw_fd, data, 8192);
+	close(raw_fd);
+
+	to_dmi_header(&h, data);
+
+	strncpy(buf, dmi_string(&h, data[PROC_MFR_OFFSET]), 127);
+	desc->vendor = xstrdup(buf);
+
+	strncpy(buf, dmi_string(&h, data[PROC_VERSION_OFFSET]), 127);
+	desc->modelname = xstrdup(buf);
+}
+
+void arm_cpu_decode(struct lscpu_desc *desc)
+{
+	/* use SMBIOS Type 4 data if available,
+	 * else fall back to manual decoding using the tables above */
+	if (access(_PATH_SYS_DMI_TYPE4, R_OK) != -1) {
+		_arm_cpu_smbios(desc);
+	} else {
+		_arm_cpu_decode(desc);
+	}
+}
--
2.26.2




[Index of Archives]     [Netdev]     [Ethernet Bridging]     [Linux Wireless]     [Kernel Newbies]     [Security]     [Linux for Hams]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux RAID]     [Linux Admin]     [Samba]

  Powered by Linux