]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
lscpu: convert ARM decoding to new API
authorKarel Zak <kzak@redhat.com>
Thu, 14 May 2020 13:20:52 +0000 (15:20 +0200)
committerKarel Zak <kzak@redhat.com>
Fri, 13 Nov 2020 08:19:02 +0000 (09:19 +0100)
Signed-off-by: Karel Zak <kzak@redhat.com>
sys-utils/Makemodule.am
sys-utils/lscpu-api.h
sys-utils/lscpu-arm.c
sys-utils/lscpu-cputype.c
sys-utils/lscpu-virt.c
sys-utils/lscpu.h

index 15379aa9678c9572b3c0137024560ac624ec8cae..c0cdda728dfbf8c70b897f333d04342b4183a5b7 100644 (file)
@@ -403,6 +403,7 @@ check_PROGRAMS += test_cputype
 test_cputype_SOURCES = sys-utils/lscpu-cputype.c \
                       sys-utils/lscpu-cpu.c \
                       sys-utils/lscpu-virt.c \
+                      sys-utils/lscpu-arm.c \
                       sys-utils/lscpu-api.h
 test_cputype_CFLAGS = $(AM_CFLAGS) -DTEST_PROGRAM_CPUTYPE
 test_cputype_LDADD = $(LDADD) libcommon.la
index 9bbd18d2431c7e406f44473503a53cfa32dd7d7b..1d979e787de370b6994f551258b9d07165a21394 100644 (file)
@@ -191,9 +191,50 @@ int lscpu_add_cpu(struct lscpu_cxt *cxt,
                   struct lscpu_cputype *ct);
 int lscpu_cpus_apply_type(struct lscpu_cxt *cxt, struct lscpu_cputype *type);
 
+void lscpu_decode_arm(struct lscpu_cxt *cxt);
+
 struct lscpu_cxt *lscpu_new_context(void);
 void lscpu_free_context(struct lscpu_cxt *cxt);
 
 int lookup(char *line, char *pattern, char **value);
 
+/*
+ * Firmware stuff
+ */
+#define _PATH_SYS_DMI_TYPE4     "/sys/firmware/dmi/entries/4-0/raw"
+#define _PATH_SYS_DMI          "/sys/firmware/dmi/tables/DMI"
+
+struct lscpu_dmi_header
+{
+       uint8_t type;
+       uint8_t length;
+       uint16_t handle;
+       uint8_t *data;
+};
+
+static inline void to_dmi_header(struct lscpu_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 inline char *dmi_string(const struct lscpu_dmi_header *dm, uint8_t s)
+{
+       char *bp = (char *)dm->data;
+
+       if (!s || !bp)
+               return NULL;
+
+       bp += dm->length;
+       while (s > 1 && *bp) {
+               bp += strlen(bp);
+               bp++;
+               s--;
+       }
+
+       return !*bp ? NULL : bp;
+}
+
 #endif /* LSCPU_API_H */
index 20c7291e560ece134bcba60cce6e69e9dd75b401..de6a1537c347c3be3e7afe055991311e6d2a21c4 100644 (file)
  *  - 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"
+#include "lscpu-api.h"
 
 struct id_part {
     const int id;
@@ -216,72 +209,102 @@ static const struct hw_impl hw_implementer[] = {
     { -1,   unknown_part, "unknown" },
 };
 
-static void __arm_cpu_decode(struct lscpu_desc *desc)
+static int parse_id(const char *str)
 {
-       int j, impl = 0;
-       const struct id_part *parts = NULL;
-       char *end;
+       int id;
+       char *end = NULL;
 
-       if (desc->vendor && startswith(desc->vendor, "0x")) {
-               errno = 0;
-               impl = (int) strtol(desc->vendor, &end, 0);
-               if (errno || desc->vendor == end)
-                       return;
-       }
+       if (!str || strncmp(str, "0x",2) != 0)
+               return -EINVAL;
 
-       /* model and modelname */
-       if (impl && desc->model && startswith(desc->model, "0x")) {
-               int part;
+       errno = 0;
+       id = (int) strtol(str, &end, 0);
+       if (errno || str == end)
+               return -EINVAL;
 
-               errno = 0;
+       return id;
+}
 
-               part = (int) strtol(desc->model, &end, 0);
-               if (errno || desc->model == end)
-                       return;
+#define parse_implementer_id(_cxt)     (parse_id((_cxt)->vendor))
+#define parse_model_id(_cxt)           (parse_id((_cxt)->model))
+
+/*
+ * Use model and vendor IDs to decode to human readable names.
+ */
+static int arm_ids_decode(struct lscpu_cputype *ct)
+{
+       int impl, part, j;
+       const struct id_part *parts = NULL;
 
-               for (j = 0; hw_implementer[j].id != -1; j++) {
-                       if (hw_implementer[j].id == impl) {
-                               parts = hw_implementer[j].parts;
-                               desc->vendor = (char *) hw_implementer[j].name;
-                               break;
-                       }
+       impl = parse_implementer_id(ct);
+       if (impl <= 0)
+               return -EINVAL; /* no ARM or missing ID */
+
+       /* decode vendor */
+       for (j = 0; hw_implementer[j].id != -1; j++) {
+               if (hw_implementer[j].id == impl) {
+                       parts = hw_implementer[j].parts;
+                       free(ct->vendor);
+                       ct->vendor = xstrdup(hw_implementer[j].name);
+                       break;
                }
+       }
+
+       /* decode model */
+       if (!parts)
+               goto done;
 
-               if (parts == NULL)
-                       return;
+       part = parse_model_id(ct);
+       if (part <= 0)
+               goto done;
 
-               for (j = 0; parts[j].id != -1; j++) {
-                       if (parts[j].id == part) {
-                               desc->modelname = (char *) parts[j].name;
-                               break;
-                       }
+       for (j = 0; parts[j].id != -1; j++) {
+               if (parts[j].id == part) {
+                       free(ct->modelname);
+                       ct->modelname = xstrdup(parts[j].name);
+                       break;
                }
        }
+done:
+       return 0;
+}
 
-       /* Print out the rXpY string for ARM cores */
-       if (impl == 0x41 && desc->revision && desc->stepping) {
-               int revision, variant;
-               char buf[8];
+/* use "rXpY" string as stepping */
+static int arm_decode_rXpY(struct lscpu_cputype *ct)
+{
+       int impl, revision, variant;
+       char *end = NULL;
+       char buf[8];
 
-               errno = 0;
-               revision = (int) strtol(desc->revision, &end, 10);
-               if (errno || desc->revision == end)
-                       return;
+       impl = parse_implementer_id(ct);
 
-               errno = 0;
-               variant = (int) strtol(desc->stepping, &end, 0);
-               if (errno || desc->stepping == end)
-                       return;
+       if (impl != 0x41 || !ct->revision || !ct->stepping)
+               return -EINVAL;
 
-               snprintf(buf, sizeof(buf), "r%dp%d", variant, revision);
-               desc->stepping = xstrdup(buf);
-       }
+       errno = 0;
+       revision = (int) strtol(ct->revision, &end, 10);
+       if (errno || ct->revision == end)
+               return -EINVAL;
+
+       errno = 0;
+       variant = (int) strtol(ct->stepping, &end, 0);
+       if (errno || ct->stepping == end)
+               return -EINVAL;
+
+       snprintf(buf, sizeof(buf), "r%dp%d", variant, revision);
+       free(ct->stepping);
+       ct->stepping = xstrdup(buf);
+
+       return 0;
 }
 
 #define PROC_MFR_OFFSET                0x07
 #define PROC_VERSION_OFFSET    0x10
 
-static int __arm_cpu_smbios(struct lscpu_desc *desc)
+/*
+ * Use firmware to get human readable names
+ */
+static int arm_smbios_decode(struct lscpu_cputype *ct)
 {
        uint8_t data[8192];
        char buf[128], *str;
@@ -304,28 +327,37 @@ static int __arm_cpu_smbios(struct lscpu_desc *desc)
        str = dmi_string(&h, data[PROC_MFR_OFFSET]);
        if (str) {
                xstrncpy(buf, str, 127);
-               desc->vendor = xstrdup(buf);
+               ct->vendor = xstrdup(buf);
        }
 
        str = dmi_string(&h, data[PROC_VERSION_OFFSET]);
        if (str) {
                xstrncpy(buf, str, 127);
-               desc->modelname = xstrdup(buf);
+               ct->modelname = xstrdup(buf);
        }
 
        return 0;
 }
 
-void arm_cpu_decode(struct lscpu_desc *desc, struct lscpu_modifier *mod)
+static void arm_decode(struct lscpu_cxt *cxt, struct lscpu_cputype *ct)
 {
        int rc = -1;
 
-       /* use SMBIOS Type 4 data if available,
-        * else fall back to manual decoding using the tables above */
-       if (mod->system == SYSTEM_LIVE &&
-           access(_PATH_SYS_DMI_TYPE4, R_OK) == 0)
-               rc = __arm_cpu_smbios(desc);
-
+       /* use SMBIOS Type 4 data if available, else fall back to manual
+        * decoding using the tables above
+        */
+       if (!cxt->noalive && access(_PATH_SYS_DMI_TYPE4, R_OK) == 0)
+               rc = arm_smbios_decode(ct);
        if (rc)
-               __arm_cpu_decode(desc);
+               arm_ids_decode(ct);
+
+        arm_decode_rXpY(ct);
+}
+
+void lscpu_decode_arm(struct lscpu_cxt *cxt)
+{
+       size_t i;
+
+       for (i = 0; i < cxt->ncputypes; i++)
+               arm_decode(cxt, cxt->cputypes[i]);
 }
index dfa539b6ea5f7751cd039609616ba919c8f4c05d..632b5c4cfca0cb8f2144d9fcd31abd8ac43f791d 100644 (file)
@@ -343,6 +343,7 @@ static int cpuinfo_parse_line(      struct lscpu_cputype **ct,
                break;
        default:
                /* set value as a string and cleanup */
+               fprintf(stderr, "str=%s\n", str);
                strdup_to_offset(stru, pat->offset, v);
                data = (char **) ((char *) stru + pat->offset);
                rtrim_whitespace((unsigned char *) *data);
@@ -812,6 +813,7 @@ int main(int argc, char **argv)
        lscpu_read_extra(cxt);
        lscpu_read_vulnerabilities(cxt);
        lscpu_read_numas(cxt);
+       lscpu_decode_arm(cxt);
 
        cxt->virt = lscpu_read_virtualization(cxt);
 
index 501e4f8ebbe0d94f32f8e80807aac6cb588b2b21..56dc5c2ef0689a552fc4453ad676b4e38552630f 100644 (file)
@@ -9,8 +9,6 @@
 
 #include "lscpu-api.h"
 
-#define _PATH_SYS_DMI   "/sys/firmware/dmi/tables/DMI"
-
 /* Xen Domain feature flag used for /sys/hypervisor/properties/features */
 #define XENFEAT_supervisor_mode_kernel         3
 #define XENFEAT_mmu_pt_update_preserve_ad      5
@@ -40,14 +38,6 @@ static const int hv_graphics_pci[] = {
 #define WORD(x) (uint16_t)(*(const uint16_t *)(x))
 #define DWORD(x) (uint32_t)(*(const uint32_t *)(x))
 
-struct dmi_header
-{
-       uint8_t type;
-       uint8_t length;
-       uint16_t handle;
-       uint8_t *data;
-};
-
 static void *get_mem_chunk(size_t base, size_t len, const char *devmem)
 {
        void *p = NULL;
@@ -72,35 +62,6 @@ nothing:
        return NULL;
 }
 
-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;
-}
-
 static int hypervisor_from_dmi_table(uint32_t base, uint16_t len,
                                uint16_t num, const char *devmem)
 {
@@ -119,7 +80,7 @@ static int hypervisor_from_dmi_table(uint32_t base, uint16_t len,
         /* 4 is the length of an SMBIOS structure header */
        while (i < num && data + 4 <= buf + len) {
                uint8_t *next;
-               struct dmi_header h;
+               struct lscpu_dmi_header h;
 
                to_dmi_header(&h, data);
 
index 3de0abcce14a686ce93ed688f4b5ff1159f83d0b..04de84fee192f54c28da08c0255f46258a0796ef 100644 (file)
@@ -212,7 +212,6 @@ extern int read_hypervisor_dmi(void);
 extern void arm_cpu_decode(struct lscpu_desc *desc, struct lscpu_modifier *mod);
 
 #define _PATH_SYS_DMI          "/sys/firmware/dmi/tables/DMI"
-#define _PATH_SYS_DMI_TYPE4    "/sys/firmware/dmi/entries/4-0/raw"
 
 struct lscpu_dmi_header
 {