]> git.ipfire.org Git - thirdparty/util-linux.git/blobdiff - sys-utils/lscpu-virt.c
sys-utils: cleanup license lines, add SPDX
[thirdparty/util-linux.git] / sys-utils / lscpu-virt.c
index 9acc6bfd4df48e0cfd3e9502acb56578a35dd225..4d301271a339afc971b360c15a759a18f5f8aa9d 100644 (file)
@@ -1,3 +1,14 @@
+/*
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Copyright (C) 2008 Cai Qian <qcai@redhat.com>
+ * Copyright (C) 2008-2023 Karel Zak <kzak@redhat.com>
+ */
 #include <errno.h>
 #include <stdlib.h>
 #include <sys/types.h>
@@ -7,7 +18,21 @@
 #include <string.h>
 #include <stdio.h>
 
-#include "lscpu-api.h"
+#include "lscpu.h"
+
+#if (defined(__x86_64__) || defined(__i386__))
+# define INCLUDE_VMWARE_BDOOR
+#endif
+
+#ifdef INCLUDE_VMWARE_BDOOR
+# include <stdint.h>
+# include <signal.h>
+# include <strings.h>
+# include <setjmp.h>
+# ifdef HAVE_SYS_IO_H
+#  include <sys/io.h>
+# endif
+#endif
 
 /* Xen Domain feature flag used for /sys/hypervisor/properties/features */
 #define XENFEAT_supervisor_mode_kernel         3
@@ -38,7 +63,7 @@ static const int hv_graphics_pci[] = {
 #define WORD(x) (uint16_t)(*(const uint16_t *)(x))
 #define DWORD(x) (uint32_t)(*(const uint32_t *)(x))
 
-static void *get_mem_chunk(size_t base, size_t len, const char *devmem)
+void *get_mem_chunk(size_t base, size_t len, const char *devmem)
 {
        void *p = NULL;
        int fd;
@@ -65,62 +90,28 @@ nothing:
 static int hypervisor_from_dmi_table(uint32_t base, uint16_t len,
                                uint16_t num, const char *devmem)
 {
-       uint8_t *buf;
        uint8_t *data;
-       int i = 0;
-       char *vendor = NULL;
-       char *product = NULL;
-       char *manufacturer = NULL;
        int rc = VIRT_VENDOR_NONE;
+       struct dmi_info di;
 
-       data = buf = get_mem_chunk(base, len, devmem);
-       if (!buf)
-               goto done;
-
-        /* 4 is the length of an SMBIOS structure header */
-       while (i < num && data + 4 <= buf + len) {
-               uint8_t *next;
-               struct lscpu_dmi_header h;
-
-               to_dmi_header(&h, data);
-
-               /*
-                * If a short entry is found (less than 4 bytes), not only it
-                * is invalid, but we cannot reliably locate the next entry.
-                * Better stop at this point.
-                */
-               if (h.length < 4)
-                       goto done;
+       data = get_mem_chunk(base, len, devmem);
+       if (!data)
+               return rc;
 
-               /* look for the next handle */
-               next = data + h.length;
-               while (next - buf + 1 < len && (next[0] != 0 || next[1] != 0))
-                       next++;
-               next += 2;
-               switch (h.type) {
-                       case 0:
-                               vendor = dmi_string(&h, data[0x04]);
-                               break;
-                       case 1:
-                               manufacturer = dmi_string(&h, data[0x04]);
-                               product = dmi_string(&h, data[0x05]);
-                               break;
-                       default:
-                               break;
-               }
+       memset(&di, 0, sizeof(struct dmi_info));
+       rc = parse_dmi_table(len, num, data, &di);
+       if (rc < 0)
+               goto done;
 
-               data = next;
-               i++;
-       }
-       if (manufacturer && !strcmp(manufacturer, "innotek GmbH"))
+       if (di.manufacturer && !strcmp(di.manufacturer, "innotek GmbH"))
                rc = VIRT_VENDOR_INNOTEK;
-       else if (manufacturer && strstr(manufacturer, "HITACHI") &&
-                                       product && strstr(product, "LPAR"))
+       else if (di.manufacturer && strstr(di.manufacturer, "HITACHI") &&
+                                       di.product && strstr(di.product, "LPAR"))
                rc = VIRT_VENDOR_HITACHI;
-       else if (vendor && !strcmp(vendor, "Parallels"))
+       else if (di.vendor && !strcmp(di.vendor, "Parallels"))
                rc = VIRT_VENDOR_PARALLELS;
 done:
-       free(buf);
+       free(data);
        return rc;
 }
 
@@ -186,7 +177,10 @@ static int address_from_efi(size_t *address)
                        continue;
                *(addrp++) = '\0';
                if (strcmp(linebuf, "SMBIOS") == 0) {
+                       errno = 0;
                        *address = strtoul(addrp, NULL, 0);
+                       if (errno)
+                               continue;
                        ret = 0;
                        break;
                }
@@ -363,8 +357,9 @@ none:
 }
 
 #else /* ! (__x86_64__ || __i386__) */
-static void read_hypervisor_cpuid(void)
+static int read_hypervisor_cpuid(void)
 {
+       return 0;
 }
 #endif
 
@@ -411,17 +406,13 @@ static int read_hypervisor_powerpc(struct lscpu_cxt *cxt, int *type)
                   && ul_path_access(cxt->procfs, F_OK, "device-tree/hmc-managed?") == 0
                   && ul_path_access(cxt->procfs, F_OK, "device-tree/chosen/qemu,graphic-width") != 0) {
 
-               FILE *fd;
+               char buf[256];
                vendor = VIRT_VENDOR_PHYP;
                *type = VIRT_TYPE_PARA;
 
-               fd = ul_path_fopen(cxt->procfs, "r", "device-tree/ibm,partition-name");
-               if (fd) {
-                       char buf[256];
-                       if (fscanf(fd, "%255s", buf) == 1 && !strcmp(buf, "full"))
-                               *type = VIRT_TYPE_NONE;
-                       fclose(fd);
-               }
+               if (ul_path_scanf(cxt->procfs, "device-tree/ibm,partition-name", "%255s", buf) == 1 &&
+                   !strcmp(buf, "full"))
+                       *type = VIRT_TYPE_NONE;
 
        /* Qemu */
        } else if (is_devtree_compatible(cxt, "qemu,pseries")) {
@@ -567,9 +558,7 @@ struct lscpu_virt *lscpu_read_virtualization(struct lscpu_cxt *cxt)
                if (virt->vendor == VIRT_VENDOR_XEN) {
                        uint32_t features;
 
-                       fd = ul_prefix_fopen(cxt->prefix, "r", _PATH_SYS_HYP_FEATURES);
-
-                       if (fd && fscanf(fd, "%x", &features) == 1) {
+                       if (ul_path_scanf(cxt->rootfs, _PATH_SYS_HYP_FEATURES, "%x", &features) == 1) {
                                /* Xen PV domain */
                                if (features & XEN_FEATURES_PV_MASK)
                                        virt->type = VIRT_TYPE_PARA;
@@ -578,25 +567,18 @@ struct lscpu_virt *lscpu_read_virtualization(struct lscpu_cxt *cxt)
                                                                == XEN_FEATURES_PVH_MASK)
                                        virt->type = VIRT_TYPE_PARA;
                        }
-                       if (fd)
-                               fclose(fd);
                }
        } else if ((virt->vendor = read_hypervisor_powerpc(cxt, &virt->type))) {
                ;
 
        /* Xen para-virt or dom0 */
        } else if (ul_path_access(cxt->procfs, F_OK, "xen") == 0) {
+               char xenbuf[256];
                int dom0 = 0;
 
-               fd = ul_path_fopen(cxt->procfs, "r", "xen/capabilities");
-               if (fd) {
-                       char buf[256];
-
-                       if (fscanf(fd, "%255s", buf) == 1 &&
-                           !strcmp(buf, "control_d"))
-                               dom0 = 1;
-                       fclose(fd);
-               }
+               if (ul_path_scanf(cxt->procfs, "xen/capabilities", "%255s", xenbuf) == 1 &&
+                   !strcmp(xenbuf, "control_d"))
+                       dom0 = 1;
                virt->type = dom0 ? VIRT_TYPE_NONE : VIRT_TYPE_PARA;
                virt->vendor = VIRT_VENDOR_XEN;
 
@@ -682,6 +664,11 @@ done:
                                virt->hypervisor,
                                virt->vendor,
                                virt->type));
+
+       if (!virt->cpuflag && !virt->hypervisor && !virt->vendor && !virt->type) {
+               lscpu_free_virtualization(virt);
+               virt = NULL;
+       }
        return virt;
 }