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

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