Blame SOURCES/0012-Move-ACPI-ID-parsing-to-a-shared-location.patch

36520b
From e2f68c8f9f4fab48f1ef3a4585932f757593fa92 Mon Sep 17 00:00:00 2001
36520b
From: Peter Jones <pjones@redhat.com>
36520b
Date: Wed, 20 Jun 2018 14:43:32 -0400
36520b
Subject: [PATCH 12/39] Move ACPI ID parsing to a shared location.
36520b
36520b
This is getting out of PCI because we have some other platforms that do
36520b
ACPI root parsing, but don't use the PCI roots.
36520b
36520b
Signed-off-by: Peter Jones <pjones@redhat.com>
36520b
---
36520b
 src/linux-acpi.c | 119 +++++++++++++++++++++++++++++++++++++++++++++++
36520b
 src/linux-pci.c  | 112 +++++---------------------------------------
36520b
 src/linux.c      |  11 ++++-
36520b
 src/linux.h      |  19 +++++---
36520b
 4 files changed, 152 insertions(+), 109 deletions(-)
36520b
 create mode 100644 src/linux-acpi.c
36520b
36520b
diff --git a/src/linux-acpi.c b/src/linux-acpi.c
36520b
new file mode 100644
36520b
index 00000000000..cb93a113ee2
36520b
--- /dev/null
36520b
+++ b/src/linux-acpi.c
36520b
@@ -0,0 +1,119 @@
36520b
+/*
36520b
+ * libefiboot - library for the manipulation of EFI boot variables
36520b
+ * Copyright 2012-2018 Red Hat, Inc.
36520b
+ *
36520b
+ * This library is free software; you can redistribute it and/or
36520b
+ * modify it under the terms of the GNU Lesser General Public License as
36520b
+ * published by the Free Software Foundation; either version 2.1 of the
36520b
+ * License, or (at your option) any later version.
36520b
+ *
36520b
+ * This library is distributed in the hope that it will be useful,
36520b
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
36520b
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
36520b
+ * Lesser General Public License for more details.
36520b
+ *
36520b
+ * You should have received a copy of the GNU Lesser General Public
36520b
+ * License along with this library; if not, see
36520b
+ * <http://www.gnu.org/licenses/>.
36520b
+ *
36520b
+ */
36520b
+
36520b
+#include "fix_coverity.h"
36520b
+
36520b
+#include <errno.h>
36520b
+#include <fcntl.h>
36520b
+#include <inttypes.h>
36520b
+#include <stdint.h>
36520b
+#include <unistd.h>
36520b
+
36520b
+#include "efiboot.h"
36520b
+
36520b
+int HIDDEN
36520b
+parse_acpi_hid_uid(struct device *dev, const char *fmt, ...)
36520b
+{
36520b
+        int rc;
36520b
+        char *path = NULL;
36520b
+        va_list ap;
36520b
+        char *fbuf = NULL;
36520b
+        uint16_t tmp16;
36520b
+        uint32_t acpi_hid = 0;
36520b
+        uint64_t acpi_uid_int = 0;
36520b
+
36520b
+        debug(DEBUG, "entry");
36520b
+
36520b
+        va_start(ap, fmt);
36520b
+        rc = vasprintfa(&path, fmt, ap);
36520b
+        va_end(ap);
36520b
+        debug(DEBUG, "path:%s rc:%d", path, rc);
36520b
+        if (rc < 0 || path == NULL)
36520b
+                return -1;
36520b
+
36520b
+        rc = read_sysfs_file(&fbuf, "%s/firmware_node/path", path);
36520b
+        if (rc > 0) {
36520b
+                size_t l = strlen(fbuf);
36520b
+                if (l > 1) {
36520b
+                        fbuf[l-1] = 0;
36520b
+                        dev->acpi_root.acpi_cid_str = strdup(fbuf);
36520b
+                        debug(DEBUG, "Setting ACPI root path to \"%s\"", fbuf);
36520b
+                }
36520b
+        }
36520b
+
36520b
+        rc = read_sysfs_file(&fbuf, "%s/firmware_node/hid", path);
36520b
+        if (rc < 0 || fbuf == NULL) {
36520b
+                efi_error("could not read %s/firmware_node/hid", path);
36520b
+                return -1;
36520b
+        }
36520b
+
36520b
+        rc = strlen(fbuf);
36520b
+        if (rc < 4) {
36520b
+hid_err:
36520b
+                efi_error("could not parse %s/firmware_node/hid", path);
36520b
+                return -1;
36520b
+        }
36520b
+        rc -= 4;
36520b
+
36520b
+        rc = sscanf((char *)fbuf + rc, "%04hx", &tmp16);
36520b
+        debug(DEBUG, "rc:%d hid:0x%08x\n", rc, tmp16);
36520b
+        if (rc != 1)
36520b
+                goto hid_err;
36520b
+
36520b
+        acpi_hid = EFIDP_EFI_PNP_ID(tmp16);
36520b
+
36520b
+        /*
36520b
+         * Apparently basically nothing can look up a PcieRoot() node,
36520b
+         * because they just check _CID.  So since _CID for the root pretty
36520b
+         * much always has to be PNP0A03 anyway, just use that no matter
36520b
+         * what.
36520b
+         */
36520b
+        if (acpi_hid == EFIDP_ACPI_PCIE_ROOT_HID)
36520b
+                acpi_hid = EFIDP_ACPI_PCI_ROOT_HID;
36520b
+        dev->acpi_root.acpi_hid = acpi_hid;
36520b
+        debug(DEBUG, "acpi root HID:0x%08x", acpi_hid);
36520b
+
36520b
+        errno = 0;
36520b
+        fbuf = NULL;
36520b
+        rc = read_sysfs_file(&fbuf, "%s/firmware_node/uid", path);
36520b
+        if ((rc <= 0 && errno != ENOENT) || fbuf == NULL) {
36520b
+                efi_error("could not read %s/firmware_node/uid", path);
36520b
+                return -1;
36520b
+        }
36520b
+        if (rc > 0) {
36520b
+                rc = sscanf((char *)fbuf, "%"PRIu64"\n", &acpi_uid_int);
36520b
+                if (rc == 1) {
36520b
+                        dev->acpi_root.acpi_uid = acpi_uid_int;
36520b
+                } else {
36520b
+                        /* kernel uses "%s\n" to print it, so there
36520b
+                         * should always be some value and a newline... */
36520b
+                        int l = strlen((char *)fbuf);
36520b
+                        if (l >= 1) {
36520b
+                                fbuf[l-1] = '\0';
36520b
+                                dev->acpi_root.acpi_uid_str = strdup(fbuf);
36520b
+                        }
36520b
+                }
36520b
+        }
36520b
+        debug(DEBUG, "acpi root UID:0x%"PRIx64" uidstr:\"%s\"",
36520b
+              dev->acpi_root.acpi_uid, dev->acpi_root.acpi_uid_str);
36520b
+
36520b
+        errno = 0;
36520b
+        return 0;
36520b
+}
36520b
diff --git a/src/linux-pci.c b/src/linux-pci.c
36520b
index 4fbd108e3ed..aa3e40c0f7c 100644
36520b
--- a/src/linux-pci.c
36520b
+++ b/src/linux-pci.c
36520b
@@ -37,21 +37,17 @@
36520b
  *                          ^ root hub ^device      ^device
36520b
  *
36520b
  * for network devices, we also get:
36520b
- * /sys/class/net/$IFACE -> ../../devices/$PCI_STUFF/net/$IFACE
36520b
+ * /sys/class/net/$IFACE -> ../../devices/$PCI_DEVICES/net/$IFACE
36520b
+ *
36520b
+ * In both cases our "current" pointer should be at $PCI_DEVICES.
36520b
  *
36520b
  */
36520b
 static ssize_t
36520b
-parse_pci(struct device *dev, const char *current, const char *root UNUSED)
36520b
+parse_pci(struct device *dev, const char *current, const char *root)
36520b
 {
36520b
         int rc;
36520b
         int pos;
36520b
-        uint16_t root_domain;
36520b
-        uint8_t root_bus;
36520b
-        uint32_t acpi_hid = 0;
36520b
-        uint64_t acpi_uid_int = 0;
36520b
         const char *devpart = current;
36520b
-        char *fbuf = NULL;
36520b
-        uint16_t tmp16 = 0;
36520b
         char *spaces;
36520b
 
36520b
         pos = strlen(current);
36520b
@@ -62,66 +58,6 @@ parse_pci(struct device *dev, const char *current, const char *root UNUSED)
36520b
 
36520b
         debug(DEBUG, "entry");
36520b
 
36520b
-        /*
36520b
-         * find the pci root domain and port; they basically look like:
36520b
-         * pci0000:00/
36520b
-         *    ^d   ^p
36520b
-         */
36520b
-        rc = sscanf(devpart, "../../devices/pci%hx:%hhx/%n", &root_domain, &root_bus, &pos;;
36520b
-        /*
36520b
-         * If we can't find that, it's not a PCI device.
36520b
-         */
36520b
-        if (rc != 2)
36520b
-                return 0;
36520b
-        devpart += pos;
36520b
-
36520b
-        dev->pci_root.pci_root_domain = root_domain;
36520b
-        dev->pci_root.pci_root_bus = root_bus;
36520b
-
36520b
-        rc = read_sysfs_file(&fbuf,
36520b
-                             "devices/pci%04hx:%02hhx/firmware_node/hid",
36520b
-                             root_domain, root_bus);
36520b
-        if (rc < 0 || fbuf == NULL)
36520b
-                return -1;
36520b
-
36520b
-        rc = sscanf((char *)fbuf, "PNP%hx", &tmp16);
36520b
-        if (rc != 1)
36520b
-                return -1;
36520b
-        acpi_hid = EFIDP_EFI_PNP_ID(tmp16);
36520b
-
36520b
-        /*
36520b
-         * Apparently basically nothing can look up a PcieRoot() node,
36520b
-         * because they just check _CID.  So since _CID for the root pretty
36520b
-         * much always has to be PNP0A03 anyway, just use that no matter
36520b
-         * what.
36520b
-         */
36520b
-        if (acpi_hid == EFIDP_ACPI_PCIE_ROOT_HID)
36520b
-                acpi_hid = EFIDP_ACPI_PCI_ROOT_HID;
36520b
-        dev->pci_root.pci_root_acpi_hid = acpi_hid;
36520b
-
36520b
-        errno = 0;
36520b
-        fbuf = NULL;
36520b
-        rc = read_sysfs_file(&fbuf,
36520b
-                             "devices/pci%04hx:%02hhx/firmware_node/uid",
36520b
-                             root_domain, root_bus);
36520b
-        if ((rc <= 0 && errno != ENOENT) || fbuf == NULL)
36520b
-                return -1;
36520b
-        if (rc > 0) {
36520b
-                rc = sscanf((char *)fbuf, "%"PRIu64"\n", &acpi_uid_int);
36520b
-                if (rc == 1) {
36520b
-                        dev->pci_root.pci_root_acpi_uid = acpi_uid_int;
36520b
-                } else {
36520b
-                        /* kernel uses "%s\n" to print it, so there
36520b
-                         * should always be some value and a newline... */
36520b
-                        int l = strlen((char *)fbuf);
36520b
-                        if (l >= 1) {
36520b
-                                fbuf[l-1] = '\0';
36520b
-                                dev->pci_root.pci_root_acpi_uid_str = fbuf;
36520b
-                        }
36520b
-                }
36520b
-        }
36520b
-        errno = 0;
36520b
-
36520b
         /* find the pci domain/bus/device/function:
36520b
          * 0000:00:01.0/0000:01:00.0/
36520b
          *              ^d   ^b ^d ^f (of the last one in the series)
36520b
@@ -136,7 +72,7 @@ parse_pci(struct device *dev, const char *current, const char *root UNUSED)
36520b
                 debug(DEBUG, "searching for 0000:00:00.0/");
36520b
                 rc = sscanf(devpart, "%hx:%hhx:%hhx.%hhx/%n",
36520b
                             &domain, &bus, &device, &function, &pos;;
36520b
-                debug(DEBUG, "current:\"%s\" rc:%d pos:%d\n", devpart, rc, pos);
36520b
+                debug(DEBUG, "current:\"%s\" rc:%d pos:%d", devpart, rc, pos);
36520b
                 arrow(DEBUG, spaces, 9, pos, rc, 3);
36520b
                 if (rc != 4)
36520b
                         break;
36520b
@@ -157,24 +93,26 @@ parse_pci(struct device *dev, const char *current, const char *root UNUSED)
36520b
                 dev->pci_dev[i].pci_bus = bus;
36520b
                 dev->pci_dev[i].pci_device = device;
36520b
                 dev->pci_dev[i].pci_function = function;
36520b
-                char *tmp = strndup(current, devpart-current+1);
36520b
+                char *tmp = strndup(root, devpart-root+1);
36520b
                 char *linkbuf = NULL;
36520b
                 if (!tmp) {
36520b
                         efi_error("could not allocate memory");
36520b
                         return -1;
36520b
                 }
36520b
-                tmp[devpart - current] = '\0';
36520b
+                tmp[devpart - root] = '\0';
36520b
                 rc = sysfs_readlink(&linkbuf, "class/block/%s/driver", tmp);
36520b
-                free(tmp);
36520b
                 if (rc < 0 || !linkbuf) {
36520b
-                        efi_error("Could not find driver for pci device");
36520b
+                        efi_error("Could not find driver for pci device %s", tmp);
36520b
+                        free(tmp);
36520b
                         return -1;
36520b
                 }
36520b
+                free(tmp);
36520b
                 dev->pci_dev[i].driverlink = strdup(linkbuf);
36520b
                 debug(DEBUG, "driver:%s\n", linkbuf);
36520b
                 dev->n_pci_devs += 1;
36520b
         }
36520b
 
36520b
+        debug(DEBUG, "next:\"%s\"", devpart);
36520b
         return devpart - current;
36520b
 }
36520b
 
36520b
@@ -186,34 +124,6 @@ dp_create_pci(struct device *dev,
36520b
 
36520b
         debug(DEBUG, "entry buf:%p size:%zd off:%zd", buf, size, off);
36520b
 
36520b
-        if (dev->pci_root.pci_root_acpi_uid_str) {
36520b
-                debug(DEBUG, "creating acpi_hid_ex dp hid:0x%08x uid:\"%s\"",
36520b
-                      dev->pci_root.pci_root_acpi_hid,
36520b
-                      dev->pci_root.pci_root_acpi_uid_str);
36520b
-                new = efidp_make_acpi_hid_ex(buf + off, size ? size - off : 0,
36520b
-                                            dev->pci_root.pci_root_acpi_hid,
36520b
-                                            0, 0, "",
36520b
-                                            dev->pci_root.pci_root_acpi_uid_str,
36520b
-                                            "");
36520b
-                if (new < 0) {
36520b
-                        efi_error("efidp_make_acpi_hid_ex() failed");
36520b
-                        return new;
36520b
-                }
36520b
-        } else {
36520b
-                debug(DEBUG, "creating acpi_hid dp hid:0x%08x uid:0x%0"PRIx64,
36520b
-                      dev->pci_root.pci_root_acpi_hid,
36520b
-                      dev->pci_root.pci_root_acpi_uid);
36520b
-                new = efidp_make_acpi_hid(buf + off, size ? size - off : 0,
36520b
-                                         dev->pci_root.pci_root_acpi_hid,
36520b
-                                         dev->pci_root.pci_root_acpi_uid);
36520b
-                if (new < 0) {
36520b
-                        efi_error("efidp_make_acpi_hid() failed");
36520b
-                        return new;
36520b
-                }
36520b
-        }
36520b
-        off += new;
36520b
-        sz += new;
36520b
-
36520b
         debug(DEBUG, "creating PCI device path nodes");
36520b
         for (unsigned int i = 0; i < dev->n_pci_devs; i++) {
36520b
                 debug(DEBUG, "creating PCI device path node %u", i);
36520b
diff --git a/src/linux.c b/src/linux.c
36520b
index ef560753481..9f3a22f7025 100644
36520b
--- a/src/linux.c
36520b
+++ b/src/linux.c
36520b
@@ -272,6 +272,13 @@ device_free(struct device *dev)
36520b
         if (dev->probes)
36520b
                 free(dev->probes);
36520b
 
36520b
+        if (dev->acpi_root.acpi_hid_str)
36520b
+                free(dev->acpi_root.acpi_hid_str);
36520b
+        if (dev->acpi_root.acpi_uid_str)
36520b
+                free(dev->acpi_root.acpi_uid_str);
36520b
+        if (dev->acpi_root.acpi_cid_str)
36520b
+                free(dev->acpi_root.acpi_cid_str);
36520b
+
36520b
         if (dev->interface_type == network) {
36520b
                 if (dev->ifname)
36520b
                         free(dev->ifname);
36520b
@@ -325,8 +332,8 @@ struct device HIDDEN
36520b
                 goto err;
36520b
         }
36520b
 
36520b
-        dev->pci_root.pci_root_domain = 0xffff;
36520b
-        dev->pci_root.pci_root_bus = 0xff;
36520b
+        dev->pci_root.pci_domain = 0xffff;
36520b
+        dev->pci_root.pci_bus = 0xff;
36520b
 
36520b
         if (S_ISBLK(dev->stat.st_mode)) {
36520b
                 dev->major = major(dev->stat.st_rdev);
36520b
diff --git a/src/linux.h b/src/linux.h
36520b
index 35951bb4d16..aa9e3d14a83 100644
36520b
--- a/src/linux.h
36520b
+++ b/src/linux.h
36520b
@@ -21,12 +21,18 @@
36520b
 #ifndef _EFIBOOT_LINUX_H
36520b
 #define _EFIBOOT_LINUX_H
36520b
 
36520b
+struct acpi_root_info {
36520b
+        uint32_t acpi_hid;
36520b
+        uint64_t acpi_uid;
36520b
+        uint32_t acpi_cid;
36520b
+        char *acpi_hid_str;
36520b
+        char *acpi_uid_str;
36520b
+        char *acpi_cid_str;
36520b
+};
36520b
+
36520b
 struct pci_root_info {
36520b
-        uint16_t pci_root_domain;
36520b
-        uint8_t pci_root_bus;
36520b
-        uint32_t pci_root_acpi_hid;
36520b
-        uint64_t pci_root_acpi_uid;
36520b
-        char *pci_root_acpi_uid_str;
36520b
+        uint16_t pci_domain;
36520b
+        uint8_t pci_bus;
36520b
 };
36520b
 
36520b
 struct pci_dev_info {
36520b
@@ -121,6 +127,7 @@ struct device {
36520b
                         char *disk_name;
36520b
                         char *part_name;
36520b
 
36520b
+                        struct acpi_root_info acpi_root;
36520b
                         struct pci_root_info pci_root;
36520b
                         unsigned int n_pci_devs;
36520b
                         struct pci_dev_info *pci_dev;
36520b
@@ -147,7 +154,7 @@ extern int HIDDEN set_disk_name(struct device *dev, const char * const fmt, ...)
36520b
 extern bool HIDDEN is_pata(struct device *dev);
36520b
 extern int HIDDEN make_blockdev_path(uint8_t *buf, ssize_t size,
36520b
                                      struct device *dev);
36520b
-
36520b
+extern int HIDDEN parse_acpi_hid_uid(struct device *dev, const char *fmt, ...);
36520b
 extern int HIDDEN eb_nvme_ns_id(int fd, uint32_t *ns_id);
36520b
 
36520b
 int HIDDEN get_sector_size(int filedes);
36520b
-- 
36520b
2.17.1
36520b