OSDN Git Service

Move nvme parsing to linux-nvme.c
authorPeter Jones <pjones@redhat.com>
Wed, 6 Jun 2018 20:43:30 +0000 (16:43 -0400)
committerPeter Jones <pmjones@gmail.com>
Fri, 8 Jun 2018 19:11:37 +0000 (15:11 -0400)
This won't actually *work* yet, because the infrastructure to use it
(replacing "struct disk_info") won't land for a few more patches.

Signed-off-by: Peter Jones <pjones@redhat.com>
src/linux-nvme.c [new file with mode: 0644]
src/linux.c
src/linux.h

diff --git a/src/linux-nvme.c b/src/linux-nvme.c
new file mode 100644 (file)
index 0000000..6d5196f
--- /dev/null
@@ -0,0 +1,170 @@
+/*
+ * libefiboot - library for the manipulation of EFI boot variables
+ * Copyright 2012-2018 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of the
+ * License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "fix_coverity.h"
+
+#include <errno.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <stdint.h>
+#include <unistd.h>
+
+#include "efiboot.h"
+
+/*
+ * support for NVMe devices
+ *
+ * /sys/dev/block/$major:$minor looks like:
+ * 259:0 -> ../../devices/pci0000:00/0000:00:1d.0/0000:05:00.0/nvme/nvme0/nvme0n1
+ * 259:1 -> ../../devices/pci0000:00/0000:00:1d.0/0000:05:00.0/nvme/nvme0/nvme0n1/nvme0n1p1
+ *
+ * /sys/dev/block/259:0/device looks like:
+ * device -> ../../nvme0
+ *
+ * /sys/dev/block/259:1/partition looks like:
+ * $ cat partition
+ * 1
+ *
+ * /sys/class/block/nvme0n1/eui looks like:
+ * $ cat /sys/class/block/nvme0n1/eui
+ * 00 25 38 53 5a 16 1d a9
+ */
+
+static ssize_t
+parse_nvme(struct device *dev, const char *current)
+{
+        int rc;
+        int32_t tosser0, tosser1, tosser2, ctrl_id, ns_id, partition;
+        uint8_t *filebuf = NULL;
+        int pos0 = 0, pos1 = 0;
+        char *spaces;
+
+        pos0 = strlen(current);
+        spaces = alloca(pos0+1);
+        memset(spaces, ' ', pos0+1);
+        spaces[pos0] = '\0';
+        pos0 = 0;
+
+        debug(DEBUG, "entry");
+
+        debug(DEBUG, "searching for nvme/nvme0/nvme0n1 or nvme/nvme0/nvme0n1/nvme0n1p1");
+        rc = sscanf(current, "nvme/nvme%d/nvme%dn%d%n/nvme%dn%dp%d%n",
+                    &tosser0, &ctrl_id, &ns_id, &pos0,
+                    &tosser1, &tosser2, &partition, &pos1);
+        debug(DEBUG, "current:\"%s\" rc:%d pos0:%d pos1:%d\n", current, rc, pos0, pos1);
+        arrow(DEBUG, spaces, 9, pos0, rc, 3);
+        arrow(DEBUG, spaces, 9, pos1, rc, 6);
+        /*
+         * If it isn't of that form, it's not one of our nvme devices.
+         */
+        if (rc != 3 && rc != 6)
+                return 0;
+
+        dev->nvme_info.ctrl_id = ctrl_id;
+        dev->nvme_info.ns_id = ns_id;
+        dev->nvme_info.has_eui = 0;
+        dev->interface_type = nvme;
+
+        if (rc == 6) {
+                if (dev->part == -1)
+                        dev->part = partition;
+
+                pos0 = pos1;
+        }
+
+        /*
+         * now fish the eui out of sysfs is there is one...
+         */
+        rc = read_sysfs_file(&filebuf,
+                             "class/block/nvme%dn%d/eui",
+                             ctrl_id, ns_id);
+        if ((rc < 0 && errno == ENOENT) || filebuf == NULL) {
+                rc = read_sysfs_file(&filebuf,
+                             "class/block/nvme%dn%d/device/eui",
+                             ctrl_id, ns_id);
+        }
+        if (rc >= 0 && filebuf != NULL) {
+                uint8_t eui[8];
+                if (rc < 23) {
+                        errno = EINVAL;
+                        return -1;
+                }
+                rc = sscanf((char *)filebuf,
+                            "%02hhx %02hhx %02hhx %02hhx "
+                            "%02hhx %02hhx %02hhx %02hhx",
+                            &eui[0], &eui[1], &eui[2], &eui[3],
+                            &eui[4], &eui[5], &eui[6], &eui[7]);
+                if (rc < 8) {
+                        errno = EINVAL;
+                        return -1;
+                }
+                dev->nvme_info.has_eui = 1;
+                memcpy(dev->nvme_info.eui, eui, sizeof(eui));
+        } else {
+                return -1;
+        }
+
+        return pos0;
+}
+
+static ssize_t
+dp_create_nvme(struct device *dev,
+               uint8_t *buf,  ssize_t size, ssize_t off)
+{
+        ssize_t sz;
+
+        debug(DEBUG, "entry");
+
+        sz = efidp_make_nvme(buf + off, size ? size - off : 0,
+                             dev->nvme_info.ns_id,
+                             dev->nvme_info.has_eui ? dev->nvme_info.eui
+                                                        : NULL);
+        return sz;
+}
+
+static char *
+make_part_name(struct device *dev)
+{
+        char *ret = NULL;
+        ssize_t rc;
+
+        if (dev->part < 1)
+                return NULL;
+
+        rc = asprintf(&ret, "%sp%d", dev->disk_name, dev->part);
+        if (rc < 0) {
+                efi_error("could not allocate memory");
+                return NULL;
+        }
+
+        return ret;
+}
+
+static enum interface_type nvme_iftypes[] = { nvme, unknown };
+
+struct dev_probe HIDDEN nvme_parser = {
+        .name = "nvme",
+        .iftypes = nvme_iftypes,
+        .flags = DEV_PROVIDES_HD,
+        .parse = parse_nvme,
+        .create = dp_create_nvme,
+        .make_part_name = make_part_name,
+};
+
index 2d72546..8aca0eb 100644 (file)
@@ -92,18 +92,6 @@ set_disk_and_part_name(struct disk_info *info)
                        if (rc < 0)
                                return -1;
                }
-       } else if (!strncmp(penultimate, "nvme", 4)) {
-               if (!info->disk_name) {
-                       info->disk_name = strdup(ultimate);
-                       if (!info->disk_name)
-                               return -1;
-               }
-               if (!info->part_name) {
-                       rc = asprintf(&info->part_name, "%sp%d",
-                                     info->disk_name, info->part);
-                       if (rc < 0)
-                               return -1;
-               }
        } else {
                if (!info->disk_name) {
                        info->disk_name = strdup(penultimate);
@@ -227,14 +215,6 @@ sysfs_test_pmem(const char *buf)
 }
 
 static int
-sysfs_test_nvme(const char *buf, ssize_t size)
-{
-       if (!strncmp(buf, "nvme/", MIN(size, 5)))
-               return 1;
-       return 0;
-}
-
-static int
 sysfs_test_sata(const char *buf, ssize_t size)
 {
        if (!strncmp(buf, "ata", MIN(size, 3)))
@@ -395,81 +375,6 @@ sysfs_parse_pmem(uint8_t *buf,  ssize_t size, ssize_t *off,
 }
 
 static ssize_t
-sysfs_parse_nvme(uint8_t *buf, ssize_t size, ssize_t *off,
-               const char *pbuf, ssize_t psize, ssize_t *poff,
-               struct disk_info *info)
-{
-       int rc;
-       int psz = 0;
-       uint8_t *filebuf = NULL;
-
-       *poff = 0;
-       *off = 0;
-
-       char *newpbuf;
-
-       newpbuf = strndupa(pbuf, psize+1);
-       if (!newpbuf)
-               return -1;
-       newpbuf[psize] = '\0';
-
-       int32_t tosser0;
-       int32_t ctrl_id;
-       int32_t ns_id;
-
-       /* buf is:
-        * nvme/nvme0/nvme0n1
-        */
-       rc = sscanf(newpbuf, "nvme/nvme%d/nvme%dn%d%n", &tosser0,
-                   &ctrl_id, &ns_id, &psz);
-       if (rc != 3)
-               return -1;
-       *poff += psz;
-
-       info->nvme_info.ctrl_id = ctrl_id;
-       info->nvme_info.ns_id = ns_id;
-       info->nvme_info.has_eui = 0;
-       info->interface_type = nvme;
-
-       /*
-        * now fish the eui out of sysfs is there is one...
-        */
-       rc = read_sysfs_file(&filebuf,
-                            "class/block/nvme%dn%d/eui",
-                            ctrl_id, ns_id);
-       if ((rc < 0 && errno == ENOENT) || filebuf == NULL) {
-               rc = read_sysfs_file(&filebuf,
-                            "class/block/nvme%dn%d/device/eui",
-                            ctrl_id, ns_id);
-       }
-       if (rc >= 0 && filebuf != NULL) {
-               uint8_t eui[8];
-               if (rc < 23) {
-                       errno = EINVAL;
-                       return -1;
-               }
-               rc = sscanf((char *)filebuf,
-                           "%02hhx %02hhx %02hhx %02hhx "
-                           "%02hhx %02hhx %02hhx %02hhx",
-                           &eui[0], &eui[1], &eui[2], &eui[3],
-                           &eui[4], &eui[5], &eui[6], &eui[7]);
-               if (rc < 8) {
-                       errno = EINVAL;
-                       return -1;
-               }
-               info->nvme_info.has_eui = 1;
-               memcpy(info->nvme_info.eui, eui, sizeof(eui));
-       }
-
-       *off = efidp_make_nvme(buf, size,
-                              info->nvme_info.ns_id,
-                              info->nvme_info.has_eui ? info->nvme_info.eui
-                                                      : NULL);
-       return *off;
-}
-
-
-static ssize_t
 sysfs_parse_sata(uint8_t *buf, ssize_t size, ssize_t *off,
                 const char *pbuf, ssize_t psize, ssize_t *poff,
                 struct disk_info *info)
@@ -883,26 +788,6 @@ make_blockdev_path(uint8_t *buf, ssize_t size, struct disk_info *info)
 
        }
 
-       /* /dev/nvme0n1 looks like:
-        * /sys/dev/block/259:0 -> ../../devices/pci0000:00/0000:00:1d.0/0000:05:00.0/nvme/nvme0/nvme0n1
-        */
-       if (!found) {
-               rc = sysfs_test_nvme(linkbuf+loff, PATH_MAX-off);
-               if (rc < 0)
-                       return -1;
-               else if (rc > 0) {
-                       ssize_t linksz;
-                       rc = sysfs_parse_nvme(buf+off, size?size-off:0, &sz,
-                                             linkbuf+loff, PATH_MAX-off,
-                                             &linksz, info);
-                       if (rc < 0)
-                               return -1;
-                       loff += linksz;
-                       off += sz;
-                       found = 1;
-               }
-       }
-
        /* /dev/sda as SATA looks like:
         * /sys/dev/block/8:0 -> ../../devices/pci0000:00/0000:00:1f.2/ata1/host0/target0:0:0/0:0:0:0/block/sda
         */
index c684617..0f836c3 100644 (file)
@@ -66,10 +66,10 @@ struct sata_info {
 };
 
 struct nvme_info {
-       int32_t ctrl_id;
-       int32_t ns_id;
-       int has_eui;
-       uint8_t eui[8];
+        int32_t ctrl_id;
+        int32_t ns_id;
+        int has_eui;
+        uint8_t eui[8];
 };
 
 struct disk_info {
@@ -259,6 +259,7 @@ extern ssize_t parse_scsi_link(const char *current, uint32_t *host,
 #define set_part(x, y) /* XXX remove later */
 
 /* device support implementations */
+extern struct dev_probe nvme_parser;
 extern struct dev_probe virtblk_parser;
 extern struct dev_probe i2o_parser;
 extern struct dev_probe scsi_parser;