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

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