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

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