Blame SOURCES/0055-sysfs-parsers-make-all-the-sys-block-link-parsers-wo.patch

b15ea1
From 4718694094647b981b74453445d000b0296b6544 Mon Sep 17 00:00:00 2001
b15ea1
From: Peter Jones <pjones@redhat.com>
b15ea1
Date: Tue, 15 Oct 2019 16:53:27 -0400
b15ea1
Subject: [PATCH 55/86] sysfs parsers: make all the /sys/block link parsers
b15ea1
 work the same way
b15ea1
b15ea1
Apparently I wrote some of these one way and some the other, and the one
b15ea1
special case where everything was "current+sz" instead of some form of
b15ea1
"current += pos; sz += pos; ...; return sz;" or the subtraction version.
b15ea1
b15ea1
Make them all the same, where possible.
b15ea1
b15ea1
Signed-off-by: Peter Jones <pjones@redhat.com>
b15ea1
---
b15ea1
 src/linux-acpi-root.c |  97 +++++++++--------
b15ea1
 src/linux-ata.c       |  10 +-
b15ea1
 src/linux-emmc.c      |  22 ++--
b15ea1
 src/linux-nvme.c      |  24 +++--
b15ea1
 src/linux-pci-root.c  |  17 +--
b15ea1
 src/linux-pci.c       |  28 +++--
b15ea1
 src/linux-pmem.c      |  22 ++--
b15ea1
 src/linux-sas.c       |   8 +-
b15ea1
 src/linux-sata.c      |  51 ++++-----
b15ea1
 src/linux-scsi.c      | 239 ++++++++++++++++++++++--------------------
b15ea1
 src/linux-soc-root.c  |  20 ++--
b15ea1
 src/linux-virtblk.c   |  15 +--
b15ea1
 12 files changed, 296 insertions(+), 257 deletions(-)
b15ea1
b15ea1
diff --git a/src/linux-acpi-root.c b/src/linux-acpi-root.c
b15ea1
index 8aa5c96cdb9..9154c950bb1 100644
b15ea1
--- a/src/linux-acpi-root.c
b15ea1
+++ b/src/linux-acpi-root.c
b15ea1
@@ -41,17 +41,16 @@
b15ea1
  *			    ^ root hub ^pci dev      ^pci dev     ^ blockdev stuff
b15ea1
  */
b15ea1
 static ssize_t
b15ea1
-parse_acpi_root(struct device *dev, const char *current, const char *root UNUSED)
b15ea1
+parse_acpi_root(struct device *dev, const char *path, const char *root UNUSED)
b15ea1
 {
b15ea1
+	const char *current = path;
b15ea1
 	int rc;
b15ea1
-	int pos = 0;
b15ea1
+	int pos0 = -1, pos1 = -1, pos2 = -1;
b15ea1
 	uint16_t pad0;
b15ea1
 	uint8_t pad1;
b15ea1
 	char *acpi_header = NULL;
b15ea1
 	char *colon;
b15ea1
 
b15ea1
-	const char *devpart = current;
b15ea1
-
b15ea1
 	debug("entry");
b15ea1
 
b15ea1
 	/*
b15ea1
@@ -61,23 +60,25 @@ parse_acpi_root(struct device *dev, const char *current, const char *root UNUSED
b15ea1
 	 * This is annoying because "/%04ms%h:%hhx/" won't bind from the right
b15ea1
 	 * side in sscanf.
b15ea1
 	 */
b15ea1
-	rc = sscanf(devpart, "../../devices/platform/%n", &pos;;
b15ea1
-	debug("devpart:\"%s\" rc:%d pos:%d", devpart, rc, pos);
b15ea1
-	dbgmk("         ", pos);
b15ea1
-	if (rc != 0 || pos < 1)
b15ea1
+	rc = sscanf(current, "../../devices/%nplatform/%n", &pos0, &pos1);
b15ea1
+	debug("current:'%s' rc:%d pos0:%d pos1:%d", current, rc, pos0, pos1);
b15ea1
+	dbgmk("         ", pos0, pos1);
b15ea1
+	if (rc != 0 || pos0 == -1 || pos1 == -1)
b15ea1
 		return 0;
b15ea1
-	devpart += pos;
b15ea1
+	current += pos1;
b15ea1
 
b15ea1
+	debug("searching for an ACPI string like A0000:00 or ACPI0000:00");
b15ea1
+	pos0 = 0;
b15ea1
 	/*
b15ea1
 	 * If it's too short to be A0000:00, it's not an ACPI string
b15ea1
 	 */
b15ea1
-	if (strlen(devpart) < 8)
b15ea1
+	if (strlen(current) < 8)
b15ea1
 		return 0;
b15ea1
 
b15ea1
-	colon = strchr(devpart, ':');
b15ea1
+	colon = strchr(current, ':');
b15ea1
 	if (!colon)
b15ea1
 		return 0;
b15ea1
-	pos = colon - devpart;
b15ea1
+	pos1 = colon - current;
b15ea1
 
b15ea1
 	/*
b15ea1
 	 * If colon doesn't point at something between one of these:
b15ea1
@@ -85,61 +86,71 @@ parse_acpi_root(struct device *dev, const char *current, const char *root UNUSED
b15ea1
 	 *	^ 5	    ^ 8
b15ea1
 	 * Then it's not an ACPI string.
b15ea1
 	 */
b15ea1
-	if (pos < 5 || pos > 8)
b15ea1
+	if (pos1 < 5 || pos1 > 8)
b15ea1
 		return 0;
b15ea1
 
b15ea1
-	dev->acpi_root.acpi_hid_str = strndup(devpart, pos + 1);
b15ea1
+	debug("current:'%s' rc:%d pos0:%d pos1:%d", current, rc, pos0, pos1);
b15ea1
+	dbgmk("         ", pos0, pos1);
b15ea1
+
b15ea1
+	dev->acpi_root.acpi_hid_str = strndup(current, pos1 + 1);
b15ea1
 	if (!dev->acpi_root.acpi_hid_str) {
b15ea1
 		efi_error("Could not allocate memory");
b15ea1
 		return -1;
b15ea1
 	}
b15ea1
-	dev->acpi_root.acpi_hid_str[pos] = 0;
b15ea1
-	debug("acpi_hid_str:\"%s\"", dev->acpi_root.acpi_hid_str);
b15ea1
+	dev->acpi_root.acpi_hid_str[pos1] = 0;
b15ea1
+	debug("acpi_hid_str:'%s'", dev->acpi_root.acpi_hid_str);
b15ea1
 
b15ea1
-	pos -= 4;
b15ea1
-	debug("devpart:\"%s\" rc:%d pos:%d", devpart, rc, pos);
b15ea1
-	dbgmk("         ", pos);
b15ea1
-	acpi_header = strndupa(devpart, pos);
b15ea1
+	/*
b15ea1
+	 * The string is like ACPI0000:00.
b15ea1
+	 *                    ^^^^
b15ea1
+	 * Here we're saying only this bit has been parsed, though we've
b15ea1
+	 * partially parsed up to the colon.
b15ea1
+	 */
b15ea1
+	pos1 -= 4;
b15ea1
+	acpi_header = strndupa(current, pos1);
b15ea1
 	if (!acpi_header)
b15ea1
 		return 0;
b15ea1
-	acpi_header[pos] = 0;
b15ea1
-	debug("devpart:\"%s\" acpi_header:\"%s\"", devpart, acpi_header);
b15ea1
-	devpart += pos;
b15ea1
+	acpi_header[pos1] = 0;
b15ea1
+	debug("acpi_header:'%s'", acpi_header);
b15ea1
 
b15ea1
 	/*
b15ea1
 	 * If we can't find these numbers, it's not an ACPI string
b15ea1
 	 */
b15ea1
-	rc = sscanf(devpart, "%hx:%hhx/%n", &pad0, &pad1, &pos;;
b15ea1
+	rc = sscanf(current+pos1, "%hx:%hhx/%n", &pad0, &pad1, &pos2);
b15ea1
 	if (rc != 2) {
b15ea1
-		efi_error("Could not parse ACPI path \"%s\"", devpart);
b15ea1
+		efi_error("Could not parse ACPI path \"%s\"", current);
b15ea1
 		return 0;
b15ea1
 	}
b15ea1
-	debug("devpart:\"%s\" parsed:%04hx:%02hhx pos:%d rc:%d",
b15ea1
-	      devpart, pad0, pad1, pos, rc);
b15ea1
-	dbgmk("         ", pos);
b15ea1
-
b15ea1
-	devpart += pos;
b15ea1
-
b15ea1
-	rc = parse_acpi_hid_uid(dev, "devices/platform/%s%04hX:%02hhX",
b15ea1
-				acpi_header, pad0, pad1);
b15ea1
-	debug("rc:%d acpi_header:%s pad0:%04hX pad1:%02hhX",
b15ea1
-	      rc, acpi_header, pad0, pad1);
b15ea1
-	if (rc < 0 && errno == ENOENT) {
b15ea1
-		rc = parse_acpi_hid_uid(dev, "devices/platform/%s%04hx:%02hhx",
b15ea1
-				acpi_header, pad0, pad1);
b15ea1
+	debug("current:'%s' rc:%d pos0:%d pos1:%d pos2:%d",
b15ea1
+	      current, rc, pos0, pos1, pos2);
b15ea1
+	dbgmk("         ", pos0, pos2);
b15ea1
+	current += pos2;
b15ea1
+
b15ea1
+	const char * const formats[] = {
b15ea1
+		"devices/platform/%s%04hX:%02hhX",
b15ea1
+		"devices/platform/%s%04hx:%02hhx",
b15ea1
+		NULL
b15ea1
+	};
b15ea1
+
b15ea1
+	for (unsigned int i = 0; formats[i]; i++) {
b15ea1
+		rc = parse_acpi_hid_uid(dev, formats[i],
b15ea1
+					acpi_header, pad0, pad1);
b15ea1
 		debug("rc:%d acpi_header:%s pad0:%04hx pad1:%02hhx",
b15ea1
 		      rc, acpi_header, pad0, pad1);
b15ea1
-	}
b15ea1
-	if (rc < 0) {
b15ea1
-		efi_error("Could not parse hid/uid");
b15ea1
-		return rc;
b15ea1
+		if (rc >= 0)
b15ea1
+			break;
b15ea1
+		if (errno != ENOENT) {
b15ea1
+			efi_error("Could not parse hid/uid");
b15ea1
+			return rc;
b15ea1
+		}
b15ea1
 	}
b15ea1
 	debug("Parsed HID:0x%08x UID:0x%"PRIx64" uidstr:\"%s\" path:\"%s\"",
b15ea1
 	      dev->acpi_root.acpi_hid, dev->acpi_root.acpi_uid,
b15ea1
 	      dev->acpi_root.acpi_uid_str,
b15ea1
 	      dev->acpi_root.acpi_cid_str);
b15ea1
 
b15ea1
-	return devpart - current;
b15ea1
+	debug("current:'%s' sz:%zd", current, current - path);
b15ea1
+	return current - path;
b15ea1
 }
b15ea1
 
b15ea1
 static ssize_t
b15ea1
diff --git a/src/linux-ata.c b/src/linux-ata.c
b15ea1
index b6a7c2dcf8a..a05a2feb8b9 100644
b15ea1
--- a/src/linux-ata.c
b15ea1
+++ b/src/linux-ata.c
b15ea1
@@ -1,6 +1,6 @@
b15ea1
 /*
b15ea1
  * libefiboot - library for the manipulation of EFI boot variables
b15ea1
- * Copyright 2012-2018 Red Hat, Inc.
b15ea1
+ * Copyright 2012-2019 Red Hat, Inc.
b15ea1
  *
b15ea1
  * This library is free software; you can redistribute it and/or
b15ea1
  * modify it under the terms of the GNU Lesser General Public License as
b15ea1
@@ -58,7 +58,7 @@ is_pata(struct device *dev)
b15ea1
  * 11:0 -> ../../devices/pci0000:00/0000:00:11.5/ata3/host2/target2:0:0/2:0:0:0/block/sr0
b15ea1
  */
b15ea1
 static ssize_t
b15ea1
-parse_ata(struct device *dev, const char *current, const char *root UNUSED)
b15ea1
+parse_ata(struct device *dev, const char *path, const char *root UNUSED)
b15ea1
 {
b15ea1
 	uint32_t scsi_host, scsi_bus, scsi_device, scsi_target;
b15ea1
 	uint64_t scsi_lun;
b15ea1
@@ -108,7 +108,7 @@ parse_ata(struct device *dev, const char *current, const char *root UNUSED)
b15ea1
 		return 0;
b15ea1
 	}
b15ea1
 
b15ea1
-	char *host = strstr(current, "/host");
b15ea1
+	char *host = strstr(path, "/host");
b15ea1
 	if (!host)
b15ea1
 		return -1;
b15ea1
 
b15ea1
@@ -125,10 +125,10 @@ parse_ata(struct device *dev, const char *current, const char *root UNUSED)
b15ea1
 	dev->ata_info.scsi_target = scsi_target;
b15ea1
 	dev->ata_info.scsi_lun = scsi_lun;
b15ea1
 
b15ea1
-	char *block = strstr(current, "/block/");
b15ea1
+	char *block = strstr(path, "/block/");
b15ea1
 	if (!block)
b15ea1
 		return -1;
b15ea1
-	return block + 1 - current;
b15ea1
+	return block + 1 - path;
b15ea1
 }
b15ea1
 
b15ea1
 static ssize_t
b15ea1
diff --git a/src/linux-emmc.c b/src/linux-emmc.c
b15ea1
index bcd061cb0b2..2b8ae64f0fb 100644
b15ea1
--- a/src/linux-emmc.c
b15ea1
+++ b/src/linux-emmc.c
b15ea1
@@ -24,6 +24,7 @@
b15ea1
 #include <fcntl.h>
b15ea1
 #include <inttypes.h>
b15ea1
 #include <stdint.h>
b15ea1
+#include <sys/param.h>
b15ea1
 #include <unistd.h>
b15ea1
 
b15ea1
 #include "efiboot.h"
b15ea1
@@ -45,20 +46,21 @@
b15ea1
  */
b15ea1
 
b15ea1
 static ssize_t
b15ea1
-parse_emmc(struct device *dev, const char *current, const char *root UNUSED)
b15ea1
+parse_emmc(struct device *dev, const char *path, const char *root UNUSED)
b15ea1
 {
b15ea1
+	const char * current = path;
b15ea1
 	int rc;
b15ea1
 	int32_t tosser0, tosser1, tosser2, tosser3, slot_id, partition;
b15ea1
-	int pos0 = 0, pos1 = 0;
b15ea1
+	int pos0 = -1, pos1 = -1, pos2 = -1;
b15ea1
 
b15ea1
 	debug("entry");
b15ea1
 
b15ea1
 	debug("searching for mmc_host/mmc0/mmc0:0001/block/mmcblk0 or mmc_host/mmc0/mmc0:0001/block/mmcblk0/mmcblk0p1");
b15ea1
-	rc = sscanf(current, "mmc_host/mmc%d/mmc%d:%d/block/mmcblk%d%n/mmcblk%dp%d%n",
b15ea1
-	            &tosser0, &tosser1, &tosser2, &slot_id,
b15ea1
-	            &pos0, &tosser3, &partition, &pos1);
b15ea1
-	debug("current:\"%s\" rc:%d pos0:%d pos1:%d\n", current, rc, pos0, pos1);
b15ea1
-	dbgmk("         ", pos0, pos1);
b15ea1
+	rc = sscanf(current, "%nmmc_host/mmc%d/mmc%d:%d/block/mmcblk%d%n/mmcblk%dp%d%n",
b15ea1
+	            &pos0, &tosser0, &tosser1, &tosser2, &slot_id,
b15ea1
+	            &pos1, &tosser3, &partition, &pos2);
b15ea1
+	debug("current:\"%s\" rc:%d pos0:%d pos1:%d pos2:%d\n", current, rc, pos0, pos1, pos2);
b15ea1
+	dbgmk("         ", pos0, MAX(pos1,pos2));
b15ea1
 	/*
b15ea1
 	 * If it isn't of that form, it's not one of our emmc devices.
b15ea1
 	 */
b15ea1
@@ -72,10 +74,12 @@ parse_emmc(struct device *dev, const char *current, const char *root UNUSED)
b15ea1
 	        if (dev->part == -1)
b15ea1
 	                dev->part = partition;
b15ea1
 
b15ea1
-	        pos0 = pos1;
b15ea1
+	        pos2 = pos1;
b15ea1
 	}
b15ea1
+	current += pos2;
b15ea1
 
b15ea1
-	return pos0;
b15ea1
+	debug("current:'%s' sz:%zd", current, current - path);
b15ea1
+	return current - path;
b15ea1
 }
b15ea1
 
b15ea1
 static ssize_t
b15ea1
diff --git a/src/linux-nvme.c b/src/linux-nvme.c
b15ea1
index 530259c38e6..b83c631119a 100644
b15ea1
--- a/src/linux-nvme.c
b15ea1
+++ b/src/linux-nvme.c
b15ea1
@@ -24,6 +24,7 @@
b15ea1
 #include <fcntl.h>
b15ea1
 #include <inttypes.h>
b15ea1
 #include <stdint.h>
b15ea1
+#include <sys/param.h>
b15ea1
 #include <unistd.h>
b15ea1
 
b15ea1
 #include "efiboot.h"
b15ea1
@@ -48,26 +49,29 @@
b15ea1
  */
b15ea1
 
b15ea1
 static ssize_t
b15ea1
-parse_nvme(struct device *dev, const char *current, const char *root UNUSED)
b15ea1
+parse_nvme(struct device *dev, const char *path, const char *root UNUSED)
b15ea1
 {
b15ea1
+	const char *current = path;
b15ea1
 	int rc;
b15ea1
 	int32_t tosser0, tosser1, tosser2, ctrl_id, ns_id, partition;
b15ea1
 	uint8_t *filebuf = NULL;
b15ea1
-	int pos0 = 0, pos1 = 0;
b15ea1
+	int pos0 = -1, pos1 = -1, pos2 = -1;
b15ea1
 
b15ea1
 	debug("entry");
b15ea1
 
b15ea1
 	debug("searching for nvme/nvme0/nvme0n1 or nvme/nvme0/nvme0n1/nvme0n1p1");
b15ea1
-	rc = sscanf(current, "nvme/nvme%d/nvme%dn%d%n/nvme%dn%dp%d%n",
b15ea1
-	            &tosser0, &ctrl_id, &ns_id, &pos0,
b15ea1
-	            &tosser1, &tosser2, &partition, &pos1);
b15ea1
-	debug("current:\"%s\" rc:%d pos0:%d pos1:%d\n", current, rc, pos0, pos1);
b15ea1
-	dbgmk("         ", pos0, pos1);
b15ea1
+	rc = sscanf(current, "%nnvme/nvme%d/nvme%dn%d%n/nvme%dn%dp%d%n",
b15ea1
+	            &pos0, &tosser0, &ctrl_id, &ns_id,
b15ea1
+		    &pos1, &tosser1, &tosser2, &partition, &pos2);
b15ea1
+	debug("current:\"%s\" rc:%d pos0:%d pos1:%d pos2:%d\n", current, rc, pos0, pos1, pos2);
b15ea1
+	dbgmk("         ", pos0, MAX(pos1,pos2));
b15ea1
 	/*
b15ea1
 	 * If it isn't of that form, it's not one of our nvme devices.
b15ea1
 	 */
b15ea1
 	if (rc != 3 && rc != 6)
b15ea1
 	        return 0;
b15ea1
+	if (rc == 3)
b15ea1
+		pos2 = pos1;
b15ea1
 
b15ea1
 	dev->nvme_info.ctrl_id = ctrl_id;
b15ea1
 	dev->nvme_info.ns_id = ns_id;
b15ea1
@@ -78,8 +82,9 @@ parse_nvme(struct device *dev, const char *current, const char *root UNUSED)
b15ea1
 	        if (dev->part == -1)
b15ea1
 	                dev->part = partition;
b15ea1
 
b15ea1
-	        pos0 = pos1;
b15ea1
+	        pos1 = pos2;
b15ea1
 	}
b15ea1
+	current += pos1;
b15ea1
 
b15ea1
 	/*
b15ea1
 	 * now fish the eui out of sysfs is there is one...
b15ea1
@@ -111,7 +116,8 @@ parse_nvme(struct device *dev, const char *current, const char *root UNUSED)
b15ea1
 	        memcpy(dev->nvme_info.eui, eui, sizeof(eui));
b15ea1
 	}
b15ea1
 
b15ea1
-	return pos0;
b15ea1
+	debug("current:'%s' sz:%zd", current, current - path);
b15ea1
+	return current - path;
b15ea1
 }
b15ea1
 
b15ea1
 static ssize_t
b15ea1
diff --git a/src/linux-pci-root.c b/src/linux-pci-root.c
b15ea1
index def8fdaa526..8cd3849b1db 100644
b15ea1
--- a/src/linux-pci-root.c
b15ea1
+++ b/src/linux-pci-root.c
b15ea1
@@ -41,13 +41,13 @@
b15ea1
  *
b15ea1
  */
b15ea1
 static ssize_t
b15ea1
-parse_pci_root(struct device *dev, const char *current, const char *root UNUSED)
b15ea1
+parse_pci_root(struct device *dev, const char *path, const char *root UNUSED)
b15ea1
 {
b15ea1
+	const char * current = path;
b15ea1
 	int rc;
b15ea1
-	int pos = 0;
b15ea1
+	int pos0 = -1, pos1 = -1;
b15ea1
 	uint16_t root_domain;
b15ea1
 	uint8_t root_bus;
b15ea1
-	const char *devpart = current;
b15ea1
 
b15ea1
 	debug("entry");
b15ea1
 
b15ea1
@@ -56,15 +56,15 @@ parse_pci_root(struct device *dev, const char *current, const char *root UNUSED)
b15ea1
 	 * pci0000:00/
b15ea1
 	 *    ^d   ^p
b15ea1
 	 */
b15ea1
-	rc = sscanf(devpart, "../../devices/pci%hx:%hhx/%n", &root_domain, &root_bus, &pos;;
b15ea1
-	debug("current:\"%s\" rc:%d pos:%d", devpart, rc, pos);
b15ea1
-	dbgmk("         ", pos);
b15ea1
+	rc = sscanf(current, "%n../../devices/pci%hx:%hhx/%n", &pos0, &root_domain, &root_bus, &pos1);
b15ea1
+	debug("current:'%s' rc:%d pos0:%d pos1:%d", current, rc, pos0, pos1);
b15ea1
+	dbgmk("         ", pos0, pos1);
b15ea1
 	/*
b15ea1
 	 * If we can't find that, it's not a PCI device.
b15ea1
 	 */
b15ea1
 	if (rc != 2)
b15ea1
 	        return 0;
b15ea1
-	devpart += pos;
b15ea1
+	current += pos1;
b15ea1
 
b15ea1
 	dev->pci_root.pci_domain = root_domain;
b15ea1
 	dev->pci_root.pci_bus = root_bus;
b15ea1
@@ -75,7 +75,8 @@ parse_pci_root(struct device *dev, const char *current, const char *root UNUSED)
b15ea1
 	        return -1;
b15ea1
 
b15ea1
 	errno = 0;
b15ea1
-	return devpart - current;
b15ea1
+	debug("current:'%s' sz:%zd\n", current, current - path);
b15ea1
+	return current - path;
b15ea1
 }
b15ea1
 
b15ea1
 static ssize_t
b15ea1
diff --git a/src/linux-pci.c b/src/linux-pci.c
b15ea1
index 4e7e636c463..2cd450bc470 100644
b15ea1
--- a/src/linux-pci.c
b15ea1
+++ b/src/linux-pci.c
b15ea1
@@ -43,11 +43,10 @@
b15ea1
  *
b15ea1
  */
b15ea1
 static ssize_t
b15ea1
-parse_pci(struct device *dev, const char *current, const char *root)
b15ea1
+parse_pci(struct device *dev, const char *path, const char *root)
b15ea1
 {
b15ea1
+	const char *current = path;
b15ea1
 	int rc;
b15ea1
-	int pos = 0;
b15ea1
-	const char *devpart = current;
b15ea1
 
b15ea1
 	debug("entry");
b15ea1
 
b15ea1
@@ -55,23 +54,22 @@ parse_pci(struct device *dev, const char *current, const char *root)
b15ea1
 	 * 0000:00:01.0/0000:01:00.0/
b15ea1
 	 *              ^d   ^b ^d ^f (of the last one in the series)
b15ea1
 	 */
b15ea1
-	while (*devpart) {
b15ea1
+	while (*current) {
b15ea1
 	        uint16_t domain;
b15ea1
 	        uint8_t bus, device, function;
b15ea1
 	        struct pci_dev_info *pci_dev;
b15ea1
 	        unsigned int i = dev->n_pci_devs;
b15ea1
 	        struct stat statbuf;
b15ea1
+		int pos0 = -1, pos1 = -1;
b15ea1
 
b15ea1
-	        debug("devpart is \"%s\"", devpart);
b15ea1
-	        pos = 0;
b15ea1
 	        debug("searching for 0000:00:00.0/");
b15ea1
-	        rc = sscanf(devpart, "%hx:%hhx:%hhx.%hhx/%n",
b15ea1
-	                    &domain, &bus, &device, &function, &pos;;
b15ea1
-	        debug("current:\"%s\" rc:%d pos:%d", devpart, rc, pos);
b15ea1
-		dbgmk("         ", pos);
b15ea1
+	        rc = sscanf(current, "%n%hx:%hhx:%hhx.%hhx/%n",
b15ea1
+	                    &pos0, &domain, &bus, &device, &function, &pos1);
b15ea1
+	        debug("current:'%s' rc:%d pos0:%d pos1:%d", current, rc, pos0, pos1);
b15ea1
+		dbgmk("         ", pos0, pos1);
b15ea1
 	        if (rc != 4)
b15ea1
 	                break;
b15ea1
-	        devpart += pos;
b15ea1
+	        current += pos1;
b15ea1
 
b15ea1
 	        debug("found pci domain %04hx:%02hhx:%02hhx.%02hhx",
b15ea1
 	              domain, bus, device, function);
b15ea1
@@ -88,13 +86,13 @@ parse_pci(struct device *dev, const char *current, const char *root)
b15ea1
 	        dev->pci_dev[i].pci_bus = bus;
b15ea1
 	        dev->pci_dev[i].pci_device = device;
b15ea1
 	        dev->pci_dev[i].pci_function = function;
b15ea1
-	        char *tmp = strndup(root, devpart-root+1);
b15ea1
+	        char *tmp = strndup(root, current-root+1);
b15ea1
 	        char *linkbuf = NULL;
b15ea1
 	        if (!tmp) {
b15ea1
 	                efi_error("could not allocate memory");
b15ea1
 	                return -1;
b15ea1
 	        }
b15ea1
-	        tmp[devpart - root] = '\0';
b15ea1
+	        tmp[current - root] = '\0';
b15ea1
 	        rc = sysfs_stat(&statbuf, "class/block/%s/driver", tmp);
b15ea1
 	        if (rc < 0 && errno == ENOENT) {
b15ea1
 	                debug("No driver link for /sys/class/block/%s", tmp);
b15ea1
@@ -115,8 +113,8 @@ parse_pci(struct device *dev, const char *current, const char *root)
b15ea1
 	        dev->n_pci_devs += 1;
b15ea1
 	}
b15ea1
 
b15ea1
-	debug("next:\"%s\"", devpart);
b15ea1
-	return devpart - current;
b15ea1
+	debug("current:'%s' sz:%zd\n", current, current - path);
b15ea1
+	return current - path;
b15ea1
 }
b15ea1
 
b15ea1
 static ssize_t
b15ea1
diff --git a/src/linux-pmem.c b/src/linux-pmem.c
b15ea1
index a11e1644094..e5de3264d03 100644
b15ea1
--- a/src/linux-pmem.c
b15ea1
+++ b/src/linux-pmem.c
b15ea1
@@ -70,12 +70,14 @@
b15ea1
  */
b15ea1
 
b15ea1
 static ssize_t
b15ea1
-parse_pmem(struct device *dev, const char *current, const char *root UNUSED)
b15ea1
+parse_pmem(struct device *dev, const char *path, const char *root UNUSED)
b15ea1
 {
b15ea1
+	const char *current = path;
b15ea1
 	uint8_t *filebuf = NULL;
b15ea1
 	uint8_t system, sysbus, acpi_id;
b15ea1
 	uint16_t pnp_id;
b15ea1
-	int ndbus, region, btt_region_id, btt_id, rc, pos;
b15ea1
+	int ndbus, region, btt_region_id, btt_id, rc;
b15ea1
+	int pos0 = -1, pos1 = -1;
b15ea1
 	char *namespace = NULL;
b15ea1
 
b15ea1
 	debug("entry");
b15ea1
@@ -95,20 +97,21 @@ parse_pmem(struct device *dev, const char *current, const char *root UNUSED)
b15ea1
 	}
b15ea1
 
b15ea1
 	/*
b15ea1
-	 * We're not actually using any of the values here except pos (our
b15ea1
+	 * We're not actually using any of the values here except pos1 (our
b15ea1
 	 * return value), but rather just being paranoid that this is the sort
b15ea1
 	 * of device we care about.
b15ea1
 	 *
b15ea1
 	 * 259:0 -> ../../devices/LNXSYSTM:00/LNXSYBUS:00/ACPI0012:00/ndbus0/region12/btt12.1/block/pmem12s
b15ea1
 	 */
b15ea1
 	rc = sscanf(current,
b15ea1
-	            "../../devices/LNXSYSTM:%hhx/LNXSYBUS:%hhx/ACPI%hx:%hhx/ndbus%d/region%d/btt%d.%d/%n",
b15ea1
-	            &system, &sysbus, &pnp_id, &acpi_id, &ndbus, &region,
b15ea1
-	            &btt_region_id, &btt_id, &pos;;
b15ea1
-	debug("current:\"%s\" rc:%d pos:%d", current, rc, pos);
b15ea1
-	dbgmk("         ", pos);
b15ea1
+	            "../../devices/%nLNXSYSTM:%hhx/LNXSYBUS:%hhx/ACPI%hx:%hhx/ndbus%d/region%d/btt%d.%d/%n",
b15ea1
+	            &pos0, &system, &sysbus, &pnp_id, &acpi_id, &ndbus,
b15ea1
+		    &region, &btt_region_id, &btt_id, &pos1);
b15ea1
+	debug("current:\"%s\" rc:%d pos0:%d pos1:%d", current, rc, pos0, pos1);
b15ea1
+	dbgmk("         ", pos0, pos1);
b15ea1
 	if (rc < 8)
b15ea1
 	        return 0;
b15ea1
+	current += pos1;
b15ea1
 
b15ea1
 	/*
b15ea1
 	 * but the UUID we really do need to have.
b15ea1
@@ -158,7 +161,8 @@ parse_pmem(struct device *dev, const char *current, const char *root UNUSED)
b15ea1
 
b15ea1
 	dev->interface_type = nd_pmem;
b15ea1
 
b15ea1
-	return pos;
b15ea1
+	debug("current:'%s' sz:%zd", current, current - path);
b15ea1
+	return current - path;
b15ea1
 }
b15ea1
 
b15ea1
 static ssize_t
b15ea1
diff --git a/src/linux-sas.c b/src/linux-sas.c
b15ea1
index f985deeaa3f..16f77d7259b 100644
b15ea1
--- a/src/linux-sas.c
b15ea1
+++ b/src/linux-sas.c
b15ea1
@@ -148,8 +148,9 @@ get_local_sas_address(uint64_t *sas_address, struct device *dev)
b15ea1
  * anywhere.
b15ea1
  */
b15ea1
 static ssize_t
b15ea1
-parse_sas(struct device *dev, const char *current, const char *root UNUSED)
b15ea1
+parse_sas(struct device *dev, const char *path, const char *root UNUSED)
b15ea1
 {
b15ea1
+	const char *current = path;
b15ea1
 	struct stat statbuf = { 0, };
b15ea1
 	int rc;
b15ea1
 	uint32_t scsi_host, scsi_bus, scsi_device, scsi_target;
b15ea1
@@ -172,6 +173,7 @@ parse_sas(struct device *dev, const char *current, const char *root UNUSED)
b15ea1
 	 */
b15ea1
 	if (pos < 0)
b15ea1
 	        return 0;
b15ea1
+	current += pos;
b15ea1
 
b15ea1
 	/*
b15ea1
 	 * Make sure it has the actual /SAS/ bits before we continue
b15ea1
@@ -236,7 +238,9 @@ parse_sas(struct device *dev, const char *current, const char *root UNUSED)
b15ea1
 	dev->scsi_info.scsi_target = scsi_target;
b15ea1
 	dev->scsi_info.scsi_lun = scsi_lun;
b15ea1
 	dev->interface_type = sas;
b15ea1
-	return pos;
b15ea1
+
b15ea1
+	debug("current:'%s' sz:%zd", current, current - path);
b15ea1
+	return current - path;
b15ea1
 }
b15ea1
 
b15ea1
 static ssize_t
b15ea1
diff --git a/src/linux-sata.c b/src/linux-sata.c
b15ea1
index f3a921c2f79..314a49c4337 100644
b15ea1
--- a/src/linux-sata.c
b15ea1
+++ b/src/linux-sata.c
b15ea1
@@ -138,15 +138,15 @@ sysfs_sata_get_port_info(uint32_t print_id, struct device *dev)
b15ea1
 }
b15ea1
 
b15ea1
 static ssize_t
b15ea1
-parse_sata(struct device *dev, const char *devlink, const char *root UNUSED)
b15ea1
+parse_sata(struct device *dev, const char *path, const char *root UNUSED)
b15ea1
 {
b15ea1
-	const char *current = devlink;
b15ea1
+	const char *current = path;
b15ea1
 	uint32_t print_id;
b15ea1
 	uint32_t scsi_bus, tosser0;
b15ea1
 	uint32_t scsi_device, tosser1;
b15ea1
 	uint32_t scsi_target, tosser2;
b15ea1
 	uint64_t scsi_lun, tosser3;
b15ea1
-	int pos = 0;
b15ea1
+	int pos0 = -1, pos1 = -1;
b15ea1
 	int rc;
b15ea1
 
b15ea1
 	debug("entry");
b15ea1
@@ -160,9 +160,9 @@ parse_sata(struct device *dev, const char *devlink, const char *root UNUSED)
b15ea1
 	 *    ^dev  ^host   x y z
b15ea1
 	 */
b15ea1
 	debug("searching for ata1/");
b15ea1
-	rc = sscanf(current, "ata%"PRIu32"/%n", &print_id, &pos;;
b15ea1
-	debug("current:\"%s\" rc:%d pos:%d\n", current, rc, pos);
b15ea1
-	dbgmk("         ", pos);
b15ea1
+	rc = sscanf(current, "%nata%"PRIu32"/%n", &pos0, &print_id, &pos1);
b15ea1
+	debug("current:'%s' rc:%d pos0:%d pos1:%d\n", current, rc, pos0, pos1);
b15ea1
+	dbgmk("         ", pos0, pos1);
b15ea1
 	/*
b15ea1
 	 * If we don't find this one, it isn't an ata device, so return 0 not
b15ea1
 	 * error.  Later errors mean it is an ata device, but we can't parse
b15ea1
@@ -170,36 +170,36 @@ parse_sata(struct device *dev, const char *devlink, const char *root UNUSED)
b15ea1
 	 */
b15ea1
 	if (rc != 1)
b15ea1
 	        return 0;
b15ea1
-	current += pos;
b15ea1
-	pos = 0;
b15ea1
+	current += pos1;
b15ea1
+	pos0 = pos1 = -1;
b15ea1
 
b15ea1
 	debug("searching for host0/");
b15ea1
-	rc = sscanf(current, "host%"PRIu32"/%n", &scsi_bus, &pos;;
b15ea1
-	debug("current:\"%s\" rc:%d pos:%d\n", current, rc, pos);
b15ea1
-	dbgmk("         ", pos);
b15ea1
+	rc = sscanf(current, "%nhost%"PRIu32"/%n", &pos0, &scsi_bus, &pos1);
b15ea1
+	debug("current:'%s' rc:%d pos0:%d pos1:%d\n", current, rc, pos0, pos1);
b15ea1
+	dbgmk("         ", pos0, pos1);
b15ea1
 	if (rc != 1)
b15ea1
 	        return -1;
b15ea1
-	current += pos;
b15ea1
-	pos = 0;
b15ea1
+	current += pos1;
b15ea1
+	pos0 = pos1 = -1;
b15ea1
 
b15ea1
 	debug("searching for target0:0:0:0/");
b15ea1
-	rc = sscanf(current, "target%"PRIu32":%"PRIu32":%"PRIu64"/%n",
b15ea1
-	            &scsi_device, &scsi_target, &scsi_lun, &pos;;
b15ea1
-	debug("current:\"%s\" rc:%d pos:%d\n", current, rc, pos);
b15ea1
-	dbgmk("         ", pos);
b15ea1
+	rc = sscanf(current, "%ntarget%"PRIu32":%"PRIu32":%"PRIu64"/%n",
b15ea1
+	            &pos0, &scsi_device, &scsi_target, &scsi_lun, &pos1);
b15ea1
+	debug("current:'%s' rc:%d pos0:%d pos1:%d\n", current, rc, pos0, pos1);
b15ea1
+	dbgmk("         ", pos0, pos1);
b15ea1
 	if (rc != 3)
b15ea1
 	        return -1;
b15ea1
-	current += pos;
b15ea1
-	pos = 0;
b15ea1
+	current += pos1;
b15ea1
+	pos0 = pos1 = -1;
b15ea1
 
b15ea1
 	debug("searching for 0:0:0:0/");
b15ea1
-	rc = sscanf(current, "%"PRIu32":%"PRIu32":%"PRIu32":%"PRIu64"/%n",
b15ea1
-	            &tosser0, &tosser1, &tosser2, &tosser3, &pos;;
b15ea1
-	debug("current:\"%s\" rc:%d pos:%d\n", current, rc, pos);
b15ea1
-	dbgmk("         ", pos);
b15ea1
+	rc = sscanf(current, "%n%"PRIu32":%"PRIu32":%"PRIu32":%"PRIu64"/%n",
b15ea1
+	            &pos0, &tosser0, &tosser1, &tosser2, &tosser3, &pos1);
b15ea1
+	debug("current:'%s' rc:%d pos0:%d pos1:%d\n", current, rc, pos0, pos1);
b15ea1
+	dbgmk("         ", pos0, pos1);
b15ea1
 	if (rc != 4)
b15ea1
 	        return -1;
b15ea1
-	current += pos;
b15ea1
+	current += pos1;
b15ea1
 
b15ea1
 	rc = sysfs_sata_get_port_info(print_id, dev);
b15ea1
 	if (rc < 0)
b15ea1
@@ -213,7 +213,8 @@ parse_sata(struct device *dev, const char *devlink, const char *root UNUSED)
b15ea1
 	if (dev->interface_type == unknown)
b15ea1
 	        dev->interface_type = sata;
b15ea1
 
b15ea1
-	return current - devlink;
b15ea1
+	debug("current:'%s' sz:%zd\n", current, current - path);
b15ea1
+	return current - path;
b15ea1
 }
b15ea1
 
b15ea1
 static ssize_t
b15ea1
diff --git a/src/linux-scsi.c b/src/linux-scsi.c
b15ea1
index 21fa0b7420c..7f68e03a1b0 100644
b15ea1
--- a/src/linux-scsi.c
b15ea1
+++ b/src/linux-scsi.c
b15ea1
@@ -24,6 +24,7 @@
b15ea1
 #include <fcntl.h>
b15ea1
 #include <inttypes.h>
b15ea1
 #include <stdint.h>
b15ea1
+#include <sys/param.h>
b15ea1
 #include <unistd.h>
b15ea1
 
b15ea1
 #include "efiboot.h"
b15ea1
@@ -36,15 +37,15 @@
b15ea1
  * helper for scsi formats...
b15ea1
  */
b15ea1
 ssize_t HIDDEN
b15ea1
-parse_scsi_link(const char *current, uint32_t *scsi_host,
b15ea1
+parse_scsi_link(const char *path, uint32_t *scsi_host,
b15ea1
 	        uint32_t *scsi_bus, uint32_t *scsi_device,
b15ea1
 	        uint32_t *scsi_target, uint64_t *scsi_lun,
b15ea1
 	        uint32_t *local_port_id, uint32_t *remote_port_id,
b15ea1
 	        uint32_t *remote_target_id)
b15ea1
 {
b15ea1
+	const char *current = path;
b15ea1
 	int rc;
b15ea1
-	int sz = 0;
b15ea1
-	int pos0 = 0, pos1 = 0;
b15ea1
+	int pos0 = -1, pos1 = -1, pos2 = -1;
b15ea1
 
b15ea1
 	debug("entry");
b15ea1
 	/*
b15ea1
@@ -99,13 +100,13 @@ parse_scsi_link(const char *current, uint32_t *scsi_host,
b15ea1
 	 * or host4/port-4:0:0
b15ea1
 	 */
b15ea1
 	debug("searching for host4/");
b15ea1
-	rc = sscanf(current, "host%d/%n", scsi_host, &pos0);
b15ea1
-	debug("current:\"%s\" rc:%d pos0:%d\n", current+sz, rc, pos0);
b15ea1
-	dbgmk("         ", pos0);
b15ea1
+	rc = sscanf(current, "%nhost%d/%n", scsi_host, &pos0, &pos1);
b15ea1
+	debug("current:'%s' rc:%d pos0:%d pos1:%d\n", current, rc, pos0, pos1);
b15ea1
+	dbgmk("         ", pos0, pos1);
b15ea1
 	if (rc != 1)
b15ea1
 	        return -1;
b15ea1
-	sz += pos0;
b15ea1
-	pos0 = 0;
b15ea1
+	current += pos1;
b15ea1
+	pos0 = pos1 = -1;
b15ea1
 
b15ea1
 	/*
b15ea1
 	 * We might have this next:
b15ea1
@@ -116,149 +117,154 @@ parse_scsi_link(const char *current, uint32_t *scsi_host,
b15ea1
 	 * port-2:0:2/end_device-2:0:2/target2:0:0/2:0:0:0/block/sda/sda1
b15ea1
 	 */
b15ea1
 	debug("searching for port-4:0 or port-4:0:0");
b15ea1
-	rc = sscanf(current+sz, "port-%d:%d%n:%d%n", &tosser0,
b15ea1
-	            &tosser1, &pos0, &tosser2, &pos1);
b15ea1
-	debug("current:\"%s\" rc:%d pos0:%d pos1:%d\n", current+sz, rc, pos0, pos1);
b15ea1
-	dbgmk("         ", pos0, pos1);
b15ea1
-	if (rc == 2 || rc == 3) {
b15ea1
-	        sz += pos0;
b15ea1
-	        pos0 = 0;
b15ea1
-	        if (local_port_id && rc == 2)
b15ea1
-	                *local_port_id = tosser1;
b15ea1
-	        if (remote_port_id && rc == 3)
b15ea1
-	                *remote_port_id = tosser2;
b15ea1
-
b15ea1
-	        if (current[sz] == '/')
b15ea1
-	                sz += 1;
b15ea1
-
b15ea1
-	        /*
b15ea1
-	         * We might have this next:
b15ea1
-	         * expander-2:0/port-2:0:2/end_device-2:0:2/target2:0:0/2:0:0:0/block/sda/sda1
b15ea1
-	         *                       ^ port id
b15ea1
-	         *                     ^ scsi target id
b15ea1
-	         *                   ^ host number
b15ea1
-	         *          ^ host number
b15ea1
-	         * We don't actually care about either number in expander-.../,
b15ea1
-	         * because they're replicated in all the other places.  We just need
b15ea1
-	         * to get past it.
b15ea1
-	         */
b15ea1
-	        debug("searching for expander-4:0/");
b15ea1
-	        rc = sscanf(current+sz, "expander-%d:%d/%n", &tosser0, &tosser1, &pos0);
b15ea1
-	        debug("current:\"%s\" rc:%d pos0:%d\n", current+sz, rc, pos0);
b15ea1
-		dbgmk("         ", pos0);
b15ea1
-	        if (rc == 2) {
b15ea1
-	                if (!remote_target_id) {
b15ea1
-	                        efi_error("Device is PHY is a remote target, but remote_target_id is NULL");
b15ea1
-	                        return -1;
b15ea1
-	                }
b15ea1
-	                *remote_target_id = tosser1;
b15ea1
-	                sz += pos0;
b15ea1
-	                pos0 = 0;
b15ea1
-
b15ea1
-	                /*
b15ea1
-	                 * if we have that, we should have a 3-part port next
b15ea1
-	                 */
b15ea1
-	                debug("searching for port-2:0:2/");
b15ea1
-	                rc = sscanf(current+sz, "port-%d:%d:%d/%n", &tosser0, &tosser1, &tosser2, &pos0);
b15ea1
-	                debug("current:\"%s\" rc:%d pos0:%d\n", current+sz, rc, pos0);
b15ea1
-			dbgmk("         ", pos0);
b15ea1
-	                if (rc != 3) {
b15ea1
-	                        efi_error("Couldn't parse port expander port string");
b15ea1
-	                        return -1;
b15ea1
-	                }
b15ea1
-	                sz += pos0;
b15ea1
-	        }
b15ea1
-	        pos0 = 0;
b15ea1
-
b15ea1
-	        /* next:
b15ea1
-	         *    /end_device-4:0
b15ea1
-	         * or /end_device-4:0:0
b15ea1
-	         * awesomely these are the exact same fields that go into port-blah,
b15ea1
-	         * but we don't care for now about any of them anyway.
b15ea1
-	         */
b15ea1
-	        debug("searching for end_device-4:0/ or end_device-4:0:0/");
b15ea1
-	        rc = sscanf(current + sz, "end_device-%d:%d%n", &tosser0, &tosser1, &pos0);
b15ea1
-	        debug("current:\"%s\" rc:%d pos0:%d\n", current+sz, rc, pos0);
b15ea1
-	        if (rc != 2)
b15ea1
-	                return -1;
b15ea1
-
b15ea1
-	        pos1 = 0;
b15ea1
-	        rc = sscanf(current + sz + pos0, ":%d%n", &tosser2, &pos1);
b15ea1
-	        if (rc != 0 && rc != 1)
b15ea1
-	                return -1;
b15ea1
-		dbgmk("         ", pos0, pos0+pos1);
b15ea1
-	        if (remote_port_id && rc == 1)
b15ea1
-	                *remote_port_id = tosser2;
b15ea1
-	        if (local_port_id && rc == 0)
b15ea1
-	                *local_port_id = tosser1;
b15ea1
-	        sz += pos0 + pos1;
b15ea1
-	        pos0 = pos1 = 0;
b15ea1
-
b15ea1
-	        if (current[sz] == '/')
b15ea1
-	                sz += 1;
b15ea1
+	rc = sscanf(current, "%nport-%d:%d%n:%d%n",
b15ea1
+		    &pos0, &tosser0, &tosser1, &pos1, &tosser2, &pos2);
b15ea1
+	debug("current:'%s' rc:%d pos0:%d pos1:%d pos2:%d\n", current, rc, pos0, pos1, pos2);
b15ea1
+	dbgmk("         ", pos0, MAX(pos1, pos2));
b15ea1
+	if (rc == 3) {
b15ea1
+		if (remote_port_id)
b15ea1
+			*remote_port_id = tosser2;
b15ea1
+		pos1 = pos2;
b15ea1
+	} else if (rc == 2) {
b15ea1
+		if (local_port_id)
b15ea1
+			*local_port_id = tosser1;
b15ea1
 	} else if (rc != 0) {
b15ea1
-	        return -1;
b15ea1
+		return -1;
b15ea1
+	} else {
b15ea1
+		pos1 = 0;
b15ea1
 	}
b15ea1
+	current += pos1;
b15ea1
+
b15ea1
+	if (current[0] == '/')
b15ea1
+		current += 1;
b15ea1
+	pos0 = pos1 = pos2 = -1;
b15ea1
+
b15ea1
+        /*
b15ea1
+         * We might have this next:
b15ea1
+         * expander-2:0/port-2:0:2/end_device-2:0:2/target2:0:0/2:0:0:0/block/sda/sda1
b15ea1
+         *                       ^ port id
b15ea1
+         *                     ^ scsi target id
b15ea1
+         *                   ^ host number
b15ea1
+         *          ^ host number
b15ea1
+         * We don't actually care about either number in expander-.../,
b15ea1
+         * because they're replicated in all the other places.  We just need
b15ea1
+         * to get past it.
b15ea1
+         */
b15ea1
+        debug("searching for expander-4:0/");
b15ea1
+        rc = sscanf(current, "%nexpander-%d:%d/%n", &pos0, &tosser0, &tosser1, &pos1);
b15ea1
+        debug("current:'%s' rc:%d pos0:%d pos1:%d\n", current, rc, pos0, pos1);
b15ea1
+	dbgmk("         ", pos0, pos1);
b15ea1
+        if (rc == 2) {
b15ea1
+                if (!remote_target_id) {
b15ea1
+                        efi_error("Device is PHY is a remote target, but remote_target_id is NULL");
b15ea1
+                        return -1;
b15ea1
+                }
b15ea1
+                *remote_target_id = tosser1;
b15ea1
+		current += pos1;
b15ea1
+		pos0 = pos1 = -1;
b15ea1
+
b15ea1
+                /*
b15ea1
+                 * if we have that, we should have a 3-part port next
b15ea1
+                 */
b15ea1
+                debug("searching for port-2:0:2/");
b15ea1
+                rc = sscanf(current, "%nport-%d:%d:%d/%n", &pos0, &tosser0, &tosser1, &tosser2, &pos1);
b15ea1
+                debug("current:'%s' rc:%d pos0:%d pos1:%d\n", current, rc, pos0, pos1);
b15ea1
+		dbgmk("         ", pos0, pos1);
b15ea1
+                if (rc != 3) {
b15ea1
+                        efi_error("Couldn't parse port expander port string");
b15ea1
+                        return -1;
b15ea1
+                }
b15ea1
+		current += pos1;
b15ea1
+        }
b15ea1
+	pos0 = pos1 = -1;
b15ea1
+
b15ea1
+        /* next:
b15ea1
+         *    /end_device-4:0
b15ea1
+         * or /end_device-4:0:0
b15ea1
+         * awesomely these are the exact same fields that go into port-blah,
b15ea1
+         * but we don't care for now about any of them anyway.
b15ea1
+         */
b15ea1
+        debug("searching for end_device-4:0/ or end_device-4:0:0/");
b15ea1
+        rc = sscanf(current, "%nend_device-%d:%d%n:%d%n",
b15ea1
+		    &pos0, &tosser0, &tosser1, &pos1, &tosser2, &pos2);
b15ea1
+        debug("current:'%s' rc:%d pos0:%d\n", current, rc, pos0);
b15ea1
+	dbgmk("         ", pos0, MAX(pos1, pos2));
b15ea1
+	if (rc == 3) {
b15ea1
+		if (remote_port_id)
b15ea1
+			*remote_port_id = tosser2;
b15ea1
+		pos1 = pos2;
b15ea1
+	} else if (rc == 2) {
b15ea1
+		if (local_port_id)
b15ea1
+			*local_port_id = tosser1;
b15ea1
+	} else {
b15ea1
+		pos1 = 0;
b15ea1
+	}
b15ea1
+	current += pos1;
b15ea1
+	pos0 = pos1 = pos2 = -1;
b15ea1
+
b15ea1
+        if (current[0] == '/')
b15ea1
+		current += 1;
b15ea1
 
b15ea1
 	/* now:
b15ea1
 	 * /target4:0:0/
b15ea1
 	 */
b15ea1
 	uint64_t tosser3;
b15ea1
 	debug("searching for target4:0:0/");
b15ea1
-	rc = sscanf(current + sz, "target%d:%d:%"PRIu64"/%n", &tosser0, &tosser1,
b15ea1
-	            &tosser3, &pos0);
b15ea1
-	debug("current:\"%s\" rc:%d pos0:%d\n", current+sz, rc, pos0);
b15ea1
-	dbgmk("         ", pos0);
b15ea1
+	rc = sscanf(current, "%ntarget%d:%d:%"PRIu64"/%n",
b15ea1
+		    &pos0, &tosser0, &tosser1, &tosser3, &pos1);
b15ea1
+	debug("current:'%s' rc:%d pos0:%d pos1:%d\n", current, rc, pos0, pos1);
b15ea1
+	dbgmk("         ", pos0, pos1);
b15ea1
 	if (rc != 3)
b15ea1
 	        return -1;
b15ea1
-	sz += pos0;
b15ea1
-	pos0 = 0;
b15ea1
+	current += pos1;
b15ea1
+	pos0 = pos1 = -1;
b15ea1
 
b15ea1
 	/* now:
b15ea1
 	 * %d:%d:%d:%llu/
b15ea1
 	 */
b15ea1
 	debug("searching for 4:0:0:0/");
b15ea1
-	rc = sscanf(current + sz, "%d:%d:%d:%"PRIu64"/%n",
b15ea1
-	            scsi_bus, scsi_device, scsi_target, scsi_lun, &pos0);
b15ea1
-	debug("current:\"%s\" rc:%d pos0:%d\n", current+sz, rc, pos0);
b15ea1
-	dbgmk("         ", pos0);
b15ea1
+	rc = sscanf(current, "%n%d:%d:%d:%"PRIu64"/%n",
b15ea1
+	            &pos0, scsi_bus, scsi_device, scsi_target, scsi_lun, &pos1);
b15ea1
+	debug("current:'%s' rc:%d pos0:%d pos1:%d\n", current, rc, pos0, pos1);
b15ea1
+	dbgmk("         ", pos0, pos1);
b15ea1
 	if (rc != 4)
b15ea1
 	        return -1;
b15ea1
-	sz += pos0;
b15ea1
+	current += pos1;
b15ea1
 
b15ea1
-	debug("returning %d", sz);
b15ea1
-	return sz;
b15ea1
+	debug("current:'%s' sz:%zd", current, current - path);
b15ea1
+	return current - path;
b15ea1
 }
b15ea1
 
b15ea1
 static ssize_t
b15ea1
-parse_scsi(struct device *dev, const char *current, const char *root UNUSED)
b15ea1
+parse_scsi(struct device *dev, const char *path, const char *root UNUSED)
b15ea1
 {
b15ea1
+	const char *current = path;
b15ea1
 	uint32_t scsi_host, scsi_bus, scsi_device, scsi_target;
b15ea1
 	uint64_t scsi_lun;
b15ea1
-	ssize_t sz;
b15ea1
-	int pos;
b15ea1
+	int pos0, pos1;
b15ea1
 	int rc;
b15ea1
 
b15ea1
 	debug("entry");
b15ea1
 
b15ea1
-	debug("searching for ../../../0:0:0:0");
b15ea1
-	rc = sscanf(dev->device, "../../../%d:%d:%d:%"PRIu64"%n",
b15ea1
+	debug("searching device for ../../../0:0:0:0");
b15ea1
+	pos0 = pos1 = -1;
b15ea1
+	rc = sscanf(dev->device, "../../../%n%d:%d:%d:%"PRIu64"%n",
b15ea1
+		    &pos0,
b15ea1
 	            &dev->scsi_info.scsi_bus,
b15ea1
 	            &dev->scsi_info.scsi_device,
b15ea1
 	            &dev->scsi_info.scsi_target,
b15ea1
 	            &dev->scsi_info.scsi_lun,
b15ea1
-	            &pos;;
b15ea1
-	debug("current:\"%s\" rc:%d pos:%d\n", dev->device, rc, pos);
b15ea1
-	dbgmk("         ", pos);
b15ea1
+	            &pos1);
b15ea1
+	debug("device:'%s' rc:%d pos0:%d pos1:%d\n", dev->device, rc, pos0, pos1);
b15ea1
+	dbgmk("        ", pos0, pos1);
b15ea1
 	if (rc != 4)
b15ea1
 	        return 0;
b15ea1
 
b15ea1
-	sz = parse_scsi_link(current, &scsi_host,
b15ea1
-	                      &scsi_bus, &scsi_device,
b15ea1
-	                      &scsi_target, &scsi_lun,
b15ea1
-	                      NULL, NULL, NULL);
b15ea1
-	if (sz < 0)
b15ea1
+	pos0 = parse_scsi_link(current, &scsi_host, &scsi_bus, &scsi_device,
b15ea1
+			       &scsi_target, &scsi_lun, NULL, NULL, NULL);
b15ea1
+	if (pos0 < 0)
b15ea1
 	        return 0;
b15ea1
+	current += pos0;
b15ea1
 
b15ea1
 	/*
b15ea1
 	 * SCSI disks can have up to 16 partitions, or 4 bits worth
b15ea1
@@ -281,7 +287,8 @@ parse_scsi(struct device *dev, const char *current, const char *root UNUSED)
b15ea1
 	        return -1;
b15ea1
 	}
b15ea1
 
b15ea1
-	return sz;
b15ea1
+	debug("current:'%s' sz:%zd\n", current, current - path);
b15ea1
+	return current - path;
b15ea1
 }
b15ea1
 
b15ea1
 static ssize_t
b15ea1
diff --git a/src/linux-soc-root.c b/src/linux-soc-root.c
b15ea1
index f4191dbd323..53686d614a0 100644
b15ea1
--- a/src/linux-soc-root.c
b15ea1
+++ b/src/linux-soc-root.c
b15ea1
@@ -38,23 +38,23 @@
b15ea1
  * I don't *think* the devicetree nodes stack.
b15ea1
  */
b15ea1
 static ssize_t
b15ea1
-parse_soc_root(struct device *dev UNUSED, const char *current, const char *root UNUSED)
b15ea1
+parse_soc_root(struct device *dev UNUSED, const char *path, const char *root UNUSED)
b15ea1
 {
b15ea1
+	const char *current = path;
b15ea1
 	int rc;
b15ea1
-	int pos = 0;
b15ea1
-	const char *devpart = current;
b15ea1
+	int pos0 = -1, pos1 = -1;
b15ea1
 
b15ea1
 	debug("entry");
b15ea1
 
b15ea1
-	rc = sscanf(devpart, "../../devices/platform/soc/%*[^/]/%n", &pos;;
b15ea1
-	if (rc != 0)
b15ea1
+	rc = sscanf(current, "../../devices/%nplatform/soc/%*[^/]/%n", &pos0, &pos1);
b15ea1
+	if (rc != 0 || pos0 == -1 || pos1 == -1)
b15ea1
 	        return 0;
b15ea1
-	debug("current:\"%s\" rc:%d pos:%d", current, rc, pos);
b15ea1
-	dbgmk("         ", pos);
b15ea1
-	devpart += pos;
b15ea1
-	debug("new position is \"%s\"", devpart);
b15ea1
+	debug("current:'%s' rc:%d pos0:%d pos1:%d", current, rc, pos0, pos1);
b15ea1
+	dbgmk("         ", pos0, pos1);
b15ea1
+	current += pos1;
b15ea1
 
b15ea1
-	return devpart - current;
b15ea1
+	debug("current:'%s' sz:%zd\n", current, current - path);
b15ea1
+	return current - path;
b15ea1
 }
b15ea1
 
b15ea1
 enum interface_type soc_root_iftypes[] = { soc_root, unknown };
b15ea1
diff --git a/src/linux-virtblk.c b/src/linux-virtblk.c
b15ea1
index e376e0480e6..fc87717ef96 100644
b15ea1
--- a/src/linux-virtblk.c
b15ea1
+++ b/src/linux-virtblk.c
b15ea1
@@ -45,18 +45,19 @@
b15ea1
  * But usually we just write the HD() entry, of course.
b15ea1
  */
b15ea1
 static ssize_t
b15ea1
-parse_virtblk(struct device *dev, const char *current, const char *root UNUSED)
b15ea1
+parse_virtblk(struct device *dev, const char *path, const char *root UNUSED)
b15ea1
 {
b15ea1
+	const char *current = path;
b15ea1
 	uint32_t tosser;
b15ea1
-	int pos = 0;
b15ea1
+	int pos0 = -1, pos1 = -1;
b15ea1
 	int rc;
b15ea1
 
b15ea1
 	debug("entry");
b15ea1
 
b15ea1
 	debug("searching for virtio0/");
b15ea1
-	rc = sscanf(current, "virtio%x/%n", &tosser, &pos;;
b15ea1
-	debug("current:\"%s\" rc:%d pos:%d\n", current, rc, pos);
b15ea1
-	dbgmk("         ", pos);
b15ea1
+	rc = sscanf(current, "%nvirtio%x/%n", &pos0, &tosser, &pos1);
b15ea1
+	debug("current:'%s' rc:%d pos0:%d pos1:%d\n", current, rc, pos0, pos1);
b15ea1
+	dbgmk("         ", pos0, pos1);
b15ea1
 	/*
b15ea1
 	 * If we couldn't find virtioX/ then it isn't a virtio device.
b15ea1
 	 */
b15ea1
@@ -64,8 +65,10 @@ parse_virtblk(struct device *dev, const char *current, const char *root UNUSED)
b15ea1
 	        return 0;
b15ea1
 
b15ea1
 	dev->interface_type = virtblk;
b15ea1
+	current += pos1;
b15ea1
 
b15ea1
-	return pos;
b15ea1
+	debug("current:'%s' sz:%zd\n", current, current - path);
b15ea1
+	return current - path;
b15ea1
 }
b15ea1
 
b15ea1
 enum interface_type virtblk_iftypes[] = { virtblk, unknown };
b15ea1
-- 
b15ea1
2.24.1
b15ea1