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

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