mchristi aadf696
diff --git a/include/fw_context.h b/include/fw_context.h
mchristi aadf696
index abdff42..770b41a 100644
mchristi aadf696
--- a/include/fw_context.h
mchristi aadf696
+++ b/include/fw_context.h
mchristi aadf696
@@ -54,6 +54,8 @@ struct boot_context {
mchristi aadf696
 	char mask[18];
mchristi aadf696
 	char lun[17];
mchristi aadf696
 	char vlan[15];
mchristi aadf696
+
mchristi aadf696
+	char scsi_host_name[64];
mchristi aadf696
 };
mchristi aadf696
 
mchristi aadf696
 extern int fw_get_entry(struct boot_context *context);
mchristi aadf696
diff --git a/usr/iface.c b/usr/iface.c
mchristi aadf696
index 27b59d0..9c74117 100644
mchristi aadf696
--- a/usr/iface.c
mchristi aadf696
+++ b/usr/iface.c
mchristi aadf696
@@ -778,31 +778,62 @@ void iface_link_ifaces(struct list_head *ifaces)
mchristi aadf696
 	iface_for_each_iface(ifaces, 1, &nr_found, iface_link);
mchristi aadf696
 }
mchristi aadf696
 
mchristi aadf696
-void iface_setup_from_boot_context(struct iface_rec *iface,
mchristi aadf696
+/**
mchristi aadf696
+ * iface_setup_from_boot_context - setup iface from boot context info
mchristi aadf696
+ * @iface: iface t setup
mchristi aadf696
+ * @context: boot context info
mchristi aadf696
+ *
mchristi aadf696
+ * Returns 1 if setup for offload.
mchristi aadf696
+ */
mchristi aadf696
+int iface_setup_from_boot_context(struct iface_rec *iface,
mchristi aadf696
 				   struct boot_context *context)
mchristi aadf696
 {
mchristi aadf696
 	if (strlen(context->initiatorname))
mchristi aadf696
 		strlcpy(iface->iname, context->initiatorname,
mchristi aadf696
 			sizeof(iface->iname));
mchristi aadf696
 
mchristi aadf696
-	if (strlen(context->iface)) {
mchristi aadf696
-		if (!net_get_transport_name_from_netdev(context->iface,
mchristi aadf696
-						iface->transport_name)) {
mchristi aadf696
-			/* set up for access through offload card */
mchristi aadf696
-			memset(iface->name, 0, sizeof(iface->name));
mchristi aadf696
-			snprintf(iface->name, sizeof(iface->name),
mchristi aadf696
-				 "%s.%s", iface->transport_name,
mchristi aadf696
-				 context->mac);
mchristi aadf696
-
mchristi aadf696
-			strlcpy(iface->netdev, context->iface,
mchristi aadf696
-				sizeof(iface->netdev));
mchristi aadf696
-			strlcpy(iface->hwaddress, context->mac,
mchristi aadf696
-				sizeof(iface->hwaddress));
mchristi aadf696
-			strlcpy(iface->ipaddress, context->ipaddr,
mchristi aadf696
-				sizeof(iface->ipaddress));
mchristi aadf696
+	if (strlen(context->scsi_host_name)) {
mchristi aadf696
+		struct iscsi_transport *t;
mchristi aadf696
+		uint32_t hostno;
mchristi aadf696
+
mchristi e81a583
+		if (sscanf(context->scsi_host_name, "iscsi_boot%u", &hostno) != 		    1) {
mchristi aadf696
+			log_error("Could not parse %s's host no.",
mchristi aadf696
+				  context->scsi_host_name);
mchristi aadf696
+			return 0;
mchristi aadf696
 		}
mchristi aadf696
-	}
mchristi aadf696
+		t = iscsi_sysfs_get_transport_by_hba(hostno);
mchristi aadf696
+		if (!t) {
mchristi aadf696
+			log_error("Could not get transport for %s. "
mchristi aadf696
+				  "Make sure the iSCSI driver is loaded.",
mchristi aadf696
+				  context->scsi_host_name);
mchristi aadf696
+			return 0;
mchristi aadf696
+		}
mchristi aadf696
+
mchristi aadf696
+		log_debug(3, "boot context has %s transport %s",
mchristi aadf696
+			  context->scsi_host_name, t->name);
mchristi aadf696
+		strcpy(iface->transport_name, t->name);
mchristi aadf696
+	} else if (strlen(context->iface) &&
mchristi aadf696
+		 (!net_get_transport_name_from_netdev(context->iface,
mchristi aadf696
+						iface->transport_name))) {
mchristi aadf696
+		log_debug(3, "boot context has netdev %s",
mchristi aadf696
+			  context->iface);
mchristi aadf696
+		strlcpy(iface->netdev, context->iface,
mchristi aadf696
+			sizeof(iface->netdev));
mchristi aadf696
+	} else
mchristi aadf696
+		return 0;
mchristi aadf696
+	/*
mchristi aadf696
+	 * set up for access through a offload card.
mchristi aadf696
+	 */
mchristi aadf696
+	memset(iface->name, 0, sizeof(iface->name));
mchristi aadf696
+	snprintf(iface->name, sizeof(iface->name), "%s.%s",
mchristi aadf696
+		 iface->transport_name, context->mac);
mchristi aadf696
+
mchristi aadf696
+	strlcpy(iface->hwaddress, context->mac,
mchristi aadf696
+		sizeof(iface->hwaddress));
mchristi aadf696
+	strlcpy(iface->ipaddress, context->ipaddr,
mchristi aadf696
+		sizeof(iface->ipaddress));
mchristi aadf696
 	log_debug(1, "iface " iface_fmt "\n", iface_str(iface));
mchristi aadf696
+	return 1;
mchristi aadf696
 }
mchristi aadf696
 
mchristi aadf696
 /**
mchristi aadf696
@@ -817,32 +848,24 @@ void iface_setup_from_boot_context(struct iface_rec *iface,
mchristi aadf696
 int iface_create_ifaces_from_boot_contexts(struct list_head *ifaces,
mchristi aadf696
 					   struct list_head *targets)
mchristi aadf696
 {
mchristi aadf696
-	char transport_name[ISCSI_TRANSPORT_NAME_MAXLEN];
mchristi aadf696
-	char iface_name[ISCSI_MAX_IFACE_LEN];
mchristi aadf696
 	struct boot_context *context;
mchristi aadf696
 	struct iface_rec *iface, *tmp_iface;
mchristi aadf696
 	int rc = 0;
mchristi aadf696
 
mchristi aadf696
 	list_for_each_entry(context, targets, list) {
mchristi aadf696
-		memset(transport_name, 0, ISCSI_TRANSPORT_NAME_MAXLEN);
mchristi aadf696
-
mchristi aadf696
-		if (net_get_transport_name_from_netdev(context->iface,
mchristi aadf696
-						       transport_name))
mchristi aadf696
-			continue;
mchristi aadf696
-
mchristi aadf696
-		/* offload + ibft support */
mchristi aadf696
-		memset(iface_name, 0, ISCSI_MAX_IFACE_LEN);
mchristi aadf696
-		snprintf(iface_name, ISCSI_MAX_IFACE_LEN,
mchristi aadf696
-			 "%s.%s", transport_name, context->mac);
mchristi aadf696
-
mchristi aadf696
 		rc = 0;
mchristi aadf696
-		iface = iface_alloc(iface_name, &rc);
mchristi aadf696
+		/* use dummy name. If valid it will get overwritten below */
mchristi aadf696
+		iface = iface_alloc(DEFAULT_IFACENAME, &rc);
mchristi aadf696
 		if (!iface) {
mchristi aadf696
 			log_error("Could not setup iface %s for boot\n",
mchristi aadf696
-				  iface_name);
mchristi aadf696
+				  context->iface);
mchristi aadf696
 			goto fail;
mchristi aadf696
 		}
mchristi aadf696
-		iface_setup_from_boot_context(iface, context);
mchristi aadf696
+		if (!iface_setup_from_boot_context(iface, context)) {
mchristi aadf696
+			/* no offload so forget it */
mchristi aadf696
+			free(iface);
mchristi aadf696
+			continue;
mchristi aadf696
+		}
mchristi aadf696
 
mchristi aadf696
 		rc = iface_conf_write(iface);
mchristi aadf696
 		if (rc) {
mchristi aadf696
diff --git a/usr/iface.h b/usr/iface.h
mchristi aadf696
index f948686..9f6d47e 100644
mchristi aadf696
--- a/usr/iface.h
mchristi aadf696
+++ b/usr/iface.h
mchristi aadf696
@@ -50,7 +50,7 @@ extern int iface_conf_write(struct iface_rec *iface);
mchristi aadf696
 extern int iface_conf_delete(struct iface_rec *iface);
mchristi aadf696
 extern int iface_is_valid(struct iface_rec *iface);
mchristi aadf696
 extern void iface_link_ifaces(struct list_head *ifaces);
mchristi aadf696
-extern void iface_setup_from_boot_context(struct iface_rec *iface,
mchristi aadf696
+extern int iface_setup_from_boot_context(struct iface_rec *iface,
mchristi aadf696
                                    struct boot_context *context);
mchristi aadf696
 extern int iface_create_ifaces_from_boot_contexts(struct list_head *ifaces,
mchristi aadf696
 						  struct list_head *targets);
mchristi aadf696
diff --git a/utils/fwparam_ibft/Makefile b/utils/fwparam_ibft/Makefile
mchristi aadf696
index b9e7988..ca07b76 100644
mchristi aadf696
--- a/utils/fwparam_ibft/Makefile
mchristi aadf696
+++ b/utils/fwparam_ibft/Makefile
mchristi aadf696
@@ -22,7 +22,7 @@
mchristi aadf696
 #
mchristi aadf696
 
mchristi aadf696
 SYSDEPS_OBJS = $(wildcard ../sysdeps/*.o)
mchristi aadf696
-OBJS := fw_entry.o fwparam_ibft_sysfs.o $(SYSDEPS_OBJS) ../../usr/iscsi_net_util.o
mchristi aadf696
+OBJS := fw_entry.o fwparam_sysfs.o $(SYSDEPS_OBJS) ../../usr/iscsi_net_util.o
mchristi aadf696
 OBJS += prom_lex.o prom_parse.tab.o fwparam_ppc.o
mchristi aadf696
 CLEANFILES = $(OBJS) *.output *~
mchristi aadf696
 
mchristi aadf696
diff --git a/utils/fwparam_ibft/fw_entry.c b/utils/fwparam_ibft/fw_entry.c
mchristi aadf696
index ae5d34a..bbdb6d2 100644
mchristi aadf696
--- a/utils/fwparam_ibft/fw_entry.c
mchristi aadf696
+++ b/utils/fwparam_ibft/fw_entry.c
mchristi aadf696
@@ -102,8 +102,7 @@ int fw_get_entry(struct boot_context *context)
mchristi aadf696
 
mchristi aadf696
 	ret = fwparam_ppc_boot_info(context);
mchristi aadf696
 	if (ret)
mchristi aadf696
-		ret = fwparam_ibft_sysfs_boot_info(context);
mchristi aadf696
-
mchristi aadf696
+		ret = fwparam_sysfs_boot_info(context);
mchristi aadf696
 	return ret;
mchristi aadf696
 }
mchristi aadf696
 
mchristi aadf696
@@ -124,8 +123,7 @@ int fw_get_targets(struct list_head *list)
mchristi aadf696
 
mchristi aadf696
 	ret = fwparam_ppc_get_targets(list);
mchristi aadf696
 	if (ret)
mchristi aadf696
-		ret = fwparam_ibft_sysfs_get_targets(list);
mchristi aadf696
-
mchristi aadf696
+		ret = fwparam_sysfs_get_targets(list);
mchristi aadf696
 	return ret;
mchristi aadf696
 }
mchristi aadf696
 
mchristi aadf696
diff --git a/utils/fwparam_ibft/fwparam.h b/utils/fwparam_ibft/fwparam.h
mchristi aadf696
index a79213b..32e4961 100644
mchristi aadf696
--- a/utils/fwparam_ibft/fwparam.h
mchristi aadf696
+++ b/utils/fwparam_ibft/fwparam.h
mchristi aadf696
@@ -24,8 +24,8 @@
mchristi aadf696
 
mchristi aadf696
 struct boot_context;
mchristi aadf696
 
mchristi aadf696
-int fwparam_ibft_sysfs_boot_info(struct boot_context *context);
mchristi aadf696
-int fwparam_ibft_sysfs_get_targets(struct list_head *list);
mchristi aadf696
+int fwparam_sysfs_boot_info(struct boot_context *context);
mchristi aadf696
+int fwparam_sysfs_get_targets(struct list_head *list);
mchristi aadf696
 int fwparam_ppc_boot_info(struct boot_context *context);
mchristi aadf696
 int fwparam_ppc_get_targets(struct list_head *list);
mchristi aadf696
 
mchristi aadf696
diff --git a/utils/fwparam_ibft/fwparam_sysfs.c b/utils/fwparam_ibft/fwparam_sysfs.c
mchristi aadf696
new file mode 100644
mchristi aadf696
index 0000000..9b73d1a
mchristi aadf696
--- /dev/null
mchristi aadf696
+++ b/utils/fwparam_ibft/fwparam_sysfs.c
mchristi aadf696
@@ -0,0 +1,484 @@
mchristi aadf696
+/*
mchristi aadf696
+ * Copyright (C) IBM Corporation. 2007
mchristi aadf696
+ * Author: Konrad Rzeszutek <konradr@linux.vnet.ibm.com>
mchristi aadf696
+ * Copyright (C) Red Hat, Inc.  All rights reserved. 2008 - 2010
mchristi aadf696
+ * Copyright (C) Mike Christie 2008 - 2010
mchristi aadf696
+ *
mchristi aadf696
+ * This program is free software: you can redistribute it and/or modify
mchristi aadf696
+ * it under the terms of the GNU General Public License as published by
mchristi aadf696
+ * the Free Software Foundation, either version 2 of the License, or
mchristi aadf696
+ * (at your option) any later version.
mchristi aadf696
+ *
mchristi aadf696
+ * This program is distributed in the hope that it will be useful,
mchristi aadf696
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
mchristi aadf696
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
mchristi aadf696
+ * GNU General Public License for more details.
mchristi aadf696
+ *
mchristi aadf696
+ * You should have received a copy of the GNU General Public License
mchristi aadf696
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
mchristi aadf696
+ */
mchristi aadf696
+
mchristi aadf696
+#define  _XOPEN_SOURCE 500
mchristi aadf696
+#define _SVID_SOURCE
mchristi aadf696
+#include <ftw.h>
mchristi aadf696
+#include <stdio.h>
mchristi aadf696
+#include <stdlib.h>
mchristi aadf696
+#include <string.h>
mchristi aadf696
+#include <unistd.h>
mchristi aadf696
+#include <fcntl.h>
mchristi aadf696
+#include <errno.h>
mchristi aadf696
+#include <dirent.h>
mchristi aadf696
+#include <sys/types.h>
mchristi aadf696
+#include <sys/stat.h>
mchristi aadf696
+
mchristi aadf696
+#include "sysfs.h"
mchristi aadf696
+#include "fw_context.h"
mchristi aadf696
+#include "fwparam.h"
mchristi aadf696
+#include "sysdeps.h"
mchristi aadf696
+#include "iscsi_net_util.h"
mchristi aadf696
+
mchristi aadf696
+#define ISCSI_BOOT_MAX		255
mchristi aadf696
+#define IBFT_SYSFS_ROOT		"/sys/firmware/ibft/"
mchristi aadf696
+#define IBFT_SUBSYS		"ibft"
mchristi aadf696
+
mchristi aadf696
+#define ISCSI_LLD_ROOT		"/sys/firmware/"
mchristi e81a583
+#define ISCSI_LLD_SUBSYS_PREFIX	"iscsi_boot"
mchristi aadf696
+
mchristi aadf696
+static char *target_list[ISCSI_BOOT_MAX];
mchristi aadf696
+static char *nic_list[ISCSI_BOOT_MAX];
mchristi aadf696
+static int nic_cnt;
mchristi aadf696
+static int tgt_cnt;
mchristi aadf696
+
mchristi aadf696
+static int file_exist(const char *file)
mchristi aadf696
+{
mchristi aadf696
+	struct stat bootpath_stat;
mchristi aadf696
+
mchristi aadf696
+	return !stat(file, &bootpath_stat);
mchristi aadf696
+}
mchristi aadf696
+
mchristi aadf696
+/*
mchristi aadf696
+ * Finds the etherrnetX and targetX under the sysfs directory.
mchristi aadf696
+ */
mchristi aadf696
+static int find_sysfs_dirs(const char *fpath, const struct stat *sb,
mchristi aadf696
+			   int tflag, struct FTW *ftw)
mchristi aadf696
+{
mchristi aadf696
+	if (tflag == FTW_D && (strstr(fpath + ftw->base, "target"))) {
mchristi aadf696
+		if (tgt_cnt == ISCSI_BOOT_MAX) {
mchristi aadf696
+			printf("Too many targets found in iSCSI boot data."
mchristi aadf696
+			       "Max number of targets %d\n", ISCSI_BOOT_MAX);
mchristi aadf696
+			return 0;
mchristi aadf696
+		}
mchristi aadf696
+		target_list[tgt_cnt++] = strdup(strstr(fpath, "target"));
mchristi aadf696
+	}
mchristi aadf696
+
mchristi aadf696
+	if (tflag == FTW_D && (strstr(fpath + ftw->base, "ethernet"))) {
mchristi aadf696
+		if (nic_cnt == ISCSI_BOOT_MAX) {
mchristi aadf696
+			printf("Too many nics found in iSCSI boot data."
mchristi aadf696
+			       "Max number of nics %d\n", ISCSI_BOOT_MAX);
mchristi aadf696
+			return 0;
mchristi aadf696
+		}
mchristi aadf696
+		nic_list[nic_cnt++] = strdup(strstr(fpath, "ethernet"));
mchristi aadf696
+	}
mchristi aadf696
+
mchristi aadf696
+	return 0;
mchristi aadf696
+}
mchristi aadf696
+ 
mchristi aadf696
+static int get_iface_from_device(char *id, struct boot_context *context)
mchristi aadf696
+{
mchristi aadf696
+	char dev_dir[FILENAMESZ];
mchristi aadf696
+	int rc = ENODEV;
mchristi aadf696
+	DIR *dirfd;
mchristi aadf696
+	struct dirent *dent;
mchristi aadf696
+
mchristi aadf696
+	memset(dev_dir, 0, FILENAMESZ);
mchristi aadf696
+	snprintf(dev_dir, FILENAMESZ, IBFT_SYSFS_ROOT"/%s/device", id);
mchristi aadf696
+
mchristi aadf696
+	if (!file_exist(dev_dir))
mchristi aadf696
+		return 0;
mchristi aadf696
+
mchristi aadf696
+	dirfd = opendir(dev_dir);
mchristi aadf696
+	if (!dirfd)
mchristi aadf696
+		return errno;
mchristi aadf696
+
mchristi aadf696
+	while ((dent = readdir(dirfd))) {
mchristi aadf696
+		if (!strcmp(dent->d_name, ".") || !strcmp(dent->d_name, "..") ||
mchristi aadf696
+		    strncmp(dent->d_name, "net:", 4))
mchristi aadf696
+			continue;
mchristi aadf696
+
mchristi aadf696
+		if (!strncmp(dent->d_name, "net:", 4)) {
mchristi aadf696
+			if ((strlen(dent->d_name) - 4) >
mchristi aadf696
+			    (sizeof(context->iface) - 1)) {
mchristi aadf696
+				rc = EINVAL;
mchristi aadf696
+				printf("Net device %s too big for iface "
mchristi aadf696
+				       "buffer.\n", dent->d_name);
mchristi aadf696
+				break;
mchristi aadf696
+			}
mchristi aadf696
+
mchristi aadf696
+			if (sscanf(dent->d_name, "net:%s", context->iface) != 1)
mchristi aadf696
+				rc = EINVAL;
mchristi aadf696
+			rc = 0;
mchristi aadf696
+			break;
mchristi aadf696
+		} else {
mchristi aadf696
+			printf("Could not read ethernet to net link.\n");
mchristi aadf696
+			rc = EOPNOTSUPP;
mchristi aadf696
+			break;
mchristi aadf696
+		}
mchristi aadf696
+	}
mchristi aadf696
+
mchristi aadf696
+	closedir(dirfd);
mchristi aadf696
+
mchristi aadf696
+	if (rc != ENODEV)
mchristi aadf696
+		return rc;
mchristi aadf696
+
mchristi aadf696
+	/* If not found try again with newer kernel networkdev sysfs layout */
mchristi aadf696
+	strlcat(dev_dir, "/net", FILENAMESZ);
mchristi aadf696
+
mchristi aadf696
+	if (!file_exist(dev_dir))
mchristi aadf696
+		return rc;
mchristi aadf696
+
mchristi aadf696
+	dirfd = opendir(dev_dir);
mchristi aadf696
+	if (!dirfd)
mchristi aadf696
+		return errno;
mchristi aadf696
+
mchristi aadf696
+	while ((dent = readdir(dirfd))) {
mchristi aadf696
+		if (!strcmp(dent->d_name, ".") || !strcmp(dent->d_name, ".."))
mchristi aadf696
+			continue;
mchristi aadf696
+
mchristi aadf696
+		/* Take the first "regular" directory entry */
mchristi aadf696
+		if (strlen(dent->d_name) > (sizeof(context->iface) - 1)) {
mchristi aadf696
+			rc = EINVAL;
mchristi aadf696
+			printf("Net device %s too big for iface buffer.\n",
mchristi aadf696
+			       dent->d_name);
mchristi aadf696
+			break;
mchristi aadf696
+		}
mchristi aadf696
+
mchristi aadf696
+		strcpy(context->iface, dent->d_name);
mchristi aadf696
+		rc = 0;
mchristi aadf696
+		break;
mchristi aadf696
+	}
mchristi aadf696
+
mchristi aadf696
+	closedir(dirfd);
mchristi aadf696
+	return rc;
mchristi aadf696
+}
mchristi aadf696
+
mchristi aadf696
+/*
mchristi aadf696
+ * Routines to fill in the context values.
mchristi aadf696
+ */
mchristi aadf696
+static int fill_nic_context(char *subsys, char *id,
mchristi aadf696
+			    struct boot_context *context)
mchristi aadf696
+{
mchristi aadf696
+	int rc;
mchristi aadf696
+
mchristi aadf696
+	rc = sysfs_get_str(id, subsys, "mac", context->mac,
mchristi aadf696
+			   sizeof(context->mac));
mchristi aadf696
+	if (rc)
mchristi aadf696
+		return rc;
mchristi aadf696
+
mchristi aadf696
+	/*
mchristi aadf696
+	 * Some offload cards like bnx2i use different MACs for the net and
mchristi aadf696
+	 * iscsi functions, so we have to follow the sysfs links.
mchristi aadf696
+	 *
mchristi aadf696
+	 * Other ibft implementations may not be tied to a pci function,
mchristi aadf696
+	 * so there will not be any device/net link, so we drop down to
mchristi aadf696
+	 * the MAC matching.
mchristi aadf696
+	 *
mchristi aadf696
+	 * And finally, some cards like be2iscsi and qla4xxx do not have
mchristi aadf696
+	 * any linux network subsys representation. These hosts will
mchristi aadf696
+	 * not have the ibft subsys. Instead the subsys is the scsi host
mchristi aadf696
+	 * number.
mchristi aadf696
+	 */
mchristi aadf696
+	if (!strcmp(IBFT_SUBSYS, subsys)) {
mchristi aadf696
+		rc = get_iface_from_device(id, context);
mchristi aadf696
+		if (rc) {
mchristi aadf696
+			rc = net_get_netdev_from_hwaddress(context->mac,
mchristi aadf696
+							   context->iface);
mchristi aadf696
+			if (rc)
mchristi aadf696
+				return rc;
mchristi aadf696
+		}
mchristi aadf696
+	} else
mchristi aadf696
+		strlcpy(context->scsi_host_name, subsys,
mchristi aadf696
+			sizeof(context->scsi_host_name));
mchristi aadf696
+
mchristi aadf696
+	sysfs_get_str(id, subsys, "ip-addr", context->ipaddr,
mchristi aadf696
+		      sizeof(context->ipaddr));
mchristi aadf696
+	sysfs_get_str(id, subsys, "vlan", context->vlan,
mchristi aadf696
+		      sizeof(context->vlan));
mchristi aadf696
+	sysfs_get_str(id, subsys, "subnet-mask", context->mask,
mchristi aadf696
+		      sizeof(context->mask));
mchristi aadf696
+	sysfs_get_str(id, subsys, "gateway", context->gateway,
mchristi aadf696
+		      sizeof(context->gateway));
mchristi aadf696
+	sysfs_get_str(id, subsys, "primary-dns", context->primary_dns,
mchristi aadf696
+		      sizeof(context->primary_dns));
mchristi aadf696
+	sysfs_get_str(id, subsys, "secondary-dns", context->secondary_dns,
mchristi aadf696
+		      sizeof(context->secondary_dns));
mchristi aadf696
+	sysfs_get_str(id, subsys, "dhcp", context->dhcp,
mchristi aadf696
+		      sizeof(context->dhcp));
mchristi aadf696
+	return 0;
mchristi aadf696
+}
mchristi aadf696
+
mchristi aadf696
+static void fill_initiator_context(char *subsys, struct boot_context *context)
mchristi aadf696
+{
mchristi aadf696
+	sysfs_get_str("initiator", subsys, "initiator-name",
mchristi aadf696
+		      context->initiatorname,
mchristi aadf696
+		      sizeof(context->initiatorname));
mchristi aadf696
+	sysfs_get_str("initiator", subsys, "isid", context->isid,
mchristi aadf696
+		      sizeof(context->isid));
mchristi aadf696
+}
mchristi aadf696
+static int fill_tgt_context(char *subsys, char *id,
mchristi aadf696
+			    struct boot_context *context)
mchristi aadf696
+{
mchristi aadf696
+	int rc;
mchristi aadf696
+
mchristi aadf696
+	rc = sysfs_get_str(id, subsys, "target-name", context->targetname,
mchristi aadf696
+			   sizeof(context->targetname));
mchristi aadf696
+	if (rc)
mchristi aadf696
+		return rc;
mchristi aadf696
+
mchristi aadf696
+	rc = sysfs_get_str(id, subsys, "ip-addr", context->target_ipaddr,
mchristi aadf696
+			   sizeof(context->target_ipaddr));
mchristi aadf696
+	if (rc)
mchristi aadf696
+		return rc;
mchristi aadf696
+
mchristi aadf696
+	/*
mchristi aadf696
+	 * We can live without the rest of they do not exist. If we
mchristi aadf696
+	 * failed to get them we will figure it out when we login.
mchristi aadf696
+	 */
mchristi aadf696
+	if (sysfs_get_int(id, subsys, "port", &context->target_port))
mchristi aadf696
+		context->target_port = ISCSI_LISTEN_PORT;
mchristi aadf696
+
mchristi aadf696
+	sysfs_get_str(id, subsys, "lun", context->lun,
mchristi aadf696
+		      sizeof(context->lun));
mchristi aadf696
+	sysfs_get_str(id, subsys, "chap-name", context->chap_name,
mchristi aadf696
+		      sizeof(context->chap_name));
mchristi aadf696
+	sysfs_get_str(id, subsys, "chap-secret", context->chap_password,
mchristi aadf696
+		      sizeof(context->chap_password));
mchristi aadf696
+	sysfs_get_str(id, subsys, "rev-chap-name", context->chap_name_in,
mchristi aadf696
+		      sizeof(context->chap_name_in));
mchristi aadf696
+	sysfs_get_str(id, subsys, "rev-chap-name-secret",
mchristi aadf696
+		      context->chap_password_in,
mchristi aadf696
+		      sizeof(context->chap_password_in));
mchristi aadf696
+	return 0;
mchristi aadf696
+}
mchristi aadf696
+
mchristi aadf696
+#define IBFT_SYSFS_FLAG_FW_SEL_BOOT 2
mchristi aadf696
+
mchristi aadf696
+static int find_boot_flag(char *subsys, char *list[], ssize_t size,
mchristi aadf696
+			  int *boot_idx)
mchristi aadf696
+{
mchristi aadf696
+	int rc = ENODEV;
mchristi aadf696
+	int i, flag = 0;
mchristi aadf696
+
mchristi aadf696
+	for (i = 0; i < size; i++, flag = -1) {
mchristi aadf696
+		rc = sysfs_get_int(list[i], subsys, "flags", &flag;;
mchristi aadf696
+		if (rc)
mchristi aadf696
+			continue;
mchristi aadf696
+
mchristi aadf696
+		if (flag & IBFT_SYSFS_FLAG_FW_SEL_BOOT) {
mchristi aadf696
+			*boot_idx = i;
mchristi aadf696
+			rc = 0;
mchristi aadf696
+			break;
mchristi aadf696
+		}
mchristi aadf696
+		rc = ENODEV;
mchristi aadf696
+		flag = 0;
mchristi aadf696
+
mchristi aadf696
+	}
mchristi aadf696
+
mchristi aadf696
+	return rc;
mchristi aadf696
+}
mchristi aadf696
+
mchristi aadf696
+static void deallocate_lists(void)
mchristi aadf696
+{
mchristi aadf696
+	int i;
mchristi aadf696
+
mchristi aadf696
+	for (i = 0; i < nic_cnt; i++)
mchristi aadf696
+		free(nic_list[i]);
mchristi aadf696
+
mchristi aadf696
+	nic_cnt = 0;
mchristi aadf696
+	for (i = 0; i < tgt_cnt; i++)
mchristi aadf696
+		free(target_list[i]);
mchristi aadf696
+
mchristi aadf696
+	tgt_cnt = 0;
mchristi aadf696
+
mchristi aadf696
+}
mchristi aadf696
+
mchristi aadf696
+static int get_boot_info(struct boot_context *context, char *rootdir,
mchristi aadf696
+			 char *subsys)
mchristi aadf696
+{
mchristi aadf696
+	char initiator_dir[FILENAMESZ];
mchristi aadf696
+	int rc = ENODEV;
mchristi aadf696
+	int nic_idx = -1, tgt_idx = -1;
mchristi aadf696
+
mchristi aadf696
+	memset(&initiator_dir, 0 , FILENAMESZ);
mchristi aadf696
+	snprintf(initiator_dir, FILENAMESZ, "%sinitiator", rootdir);
mchristi aadf696
+
mchristi aadf696
+	nic_cnt = 0;
mchristi aadf696
+	tgt_cnt = 0;
mchristi aadf696
+	if (file_exist(initiator_dir)) {
mchristi aadf696
+		/* Find the target's and the ethernet's */
mchristi aadf696
+		rc = nftw(rootdir, find_sysfs_dirs, 20, 1);
mchristi aadf696
+
mchristi aadf696
+		/* Find wihch target and which ethernet have
mchristi aadf696
+		the boot flag set. */
mchristi aadf696
+		rc = find_boot_flag(subsys, nic_list, nic_cnt, &nic_idx);
mchristi aadf696
+		if (rc)
mchristi aadf696
+			goto free;
mchristi aadf696
+
mchristi aadf696
+		rc = find_boot_flag(subsys, target_list, tgt_cnt, &tgt_idx);
mchristi aadf696
+		if (rc)
mchristi aadf696
+			goto free;
mchristi aadf696
+
mchristi aadf696
+		/* Fill in the context values */
mchristi aadf696
+		rc = fill_nic_context(subsys, nic_list[nic_idx], context);
mchristi aadf696
+		rc |= fill_tgt_context(subsys, target_list[tgt_idx], context);
mchristi aadf696
+		fill_initiator_context(subsys, context);
mchristi aadf696
+	}
mchristi aadf696
+free:
mchristi aadf696
+	deallocate_lists();
mchristi aadf696
+	return rc;
mchristi aadf696
+}
mchristi aadf696
+
mchristi aadf696
+int fwparam_sysfs_boot_info(struct boot_context *context)
mchristi aadf696
+{
mchristi aadf696
+	struct dirent *dent;
mchristi aadf696
+	DIR *dirfd;
mchristi aadf696
+	int rc = 0;
mchristi aadf696
+
mchristi aadf696
+	if (!get_boot_info(context, IBFT_SYSFS_ROOT, IBFT_SUBSYS))
mchristi aadf696
+		return 0;
mchristi aadf696
+	/*
mchristi aadf696
+	 * We could have multiple iscsi llds and each lld could have
mchristi aadf696
+	 * multiple targets/ethernet ports
mchristi aadf696
+	 */
mchristi aadf696
+	dirfd = opendir(ISCSI_LLD_ROOT);
mchristi aadf696
+	if (!dirfd)
mchristi aadf696
+		return errno;
mchristi aadf696
+
mchristi aadf696
+	while ((dent = readdir(dirfd))) {
mchristi aadf696
+		char lld_root[FILENAMESZ];
mchristi aadf696
+
mchristi aadf696
+		memset(&lld_root, 0 , FILENAMESZ);
mchristi aadf696
+
mchristi aadf696
+		if (!strcmp(dent->d_name, ".") || !strcmp(dent->d_name, ".."))
mchristi aadf696
+			continue;
mchristi aadf696
+
mchristi aadf696
+		if (strncmp(dent->d_name, ISCSI_LLD_SUBSYS_PREFIX, 10))
mchristi aadf696
+			continue;
mchristi aadf696
+
mchristi aadf696
+		snprintf(lld_root, FILENAMESZ, ISCSI_LLD_ROOT"%s",
mchristi aadf696
+			 dent->d_name);
mchristi aadf696
+		if (!get_boot_info(context, lld_root, dent->d_name))
mchristi aadf696
+			goto done;
mchristi aadf696
+	}
mchristi aadf696
+	rc = ENODEV;
mchristi aadf696
+done:
mchristi aadf696
+	closedir(dirfd);
mchristi aadf696
+	return rc;
mchristi aadf696
+}
mchristi aadf696
+
mchristi aadf696
+static int get_targets(struct list_head *list, char *rootdir, char *subsys)
mchristi aadf696
+{
mchristi aadf696
+	struct boot_context *context;
mchristi aadf696
+	int rc = 0, i, nic_idx, nic;
mchristi aadf696
+	char initiator_dir[FILENAMESZ];
mchristi aadf696
+
mchristi aadf696
+	memset(&initiator_dir, 0 , FILENAMESZ);
mchristi aadf696
+	snprintf(initiator_dir, FILENAMESZ, "%sinitiator", rootdir);
mchristi aadf696
+
mchristi aadf696
+	if (!file_exist(initiator_dir))
mchristi aadf696
+		return ENODEV;
mchristi aadf696
+
mchristi aadf696
+	nic_cnt = 0;
mchristi aadf696
+	tgt_cnt = 0;
mchristi aadf696
+
mchristi aadf696
+	/* Find the target's and the ethernet's */
mchristi aadf696
+	nftw(rootdir, find_sysfs_dirs, 20, 1);
mchristi aadf696
+	for (i = 0; i < tgt_cnt; i++) {
mchristi aadf696
+		context = calloc(1, sizeof(*context));
mchristi aadf696
+		if (!context) {
mchristi aadf696
+			rc = ENOMEM;
mchristi aadf696
+			break;
mchristi aadf696
+		}
mchristi aadf696
+
mchristi aadf696
+		rc = fill_tgt_context(subsys, target_list[i], context);
mchristi aadf696
+		if (rc)
mchristi aadf696
+			break;
mchristi aadf696
+
mchristi aadf696
+		rc = sysfs_get_int(target_list[i], subsys, "nic-assoc",
mchristi aadf696
+				   &nic_idx);
mchristi aadf696
+		if (rc)
mchristi aadf696
+			break;
mchristi aadf696
+
mchristi aadf696
+		for (nic = 0; nic < nic_cnt; nic++) {
mchristi aadf696
+			int id;
mchristi aadf696
+
mchristi aadf696
+			rc = sysfs_get_int(nic_list[nic], subsys, "index",
mchristi aadf696
+					   &id;;
mchristi aadf696
+			if (!rc && (id == nic_idx))
mchristi aadf696
+				break;
mchristi aadf696
+		}
mchristi aadf696
+
mchristi aadf696
+		if (nic == nic_cnt) {
mchristi aadf696
+			printf("Invalid nic-assoc of %d. Max id %d.\n",
mchristi aadf696
+			       nic_idx, nic_cnt);
mchristi aadf696
+			break;
mchristi aadf696
+		}
mchristi aadf696
+
mchristi aadf696
+		rc = fill_nic_context(subsys, nic_list[nic], context);
mchristi aadf696
+		if (rc)
mchristi aadf696
+			break;
mchristi aadf696
+
mchristi aadf696
+		fill_initiator_context(subsys, context);
mchristi aadf696
+		list_add_tail(&context->list, list);
mchristi aadf696
+	}
mchristi aadf696
+
mchristi aadf696
+	if (rc) {
mchristi aadf696
+		if (context)
mchristi aadf696
+			free(context);
mchristi aadf696
+		fw_free_targets(list);
mchristi aadf696
+	}
mchristi aadf696
+
mchristi aadf696
+	deallocate_lists();
mchristi aadf696
+	return rc;
mchristi aadf696
+}
mchristi aadf696
+
mchristi aadf696
+int fwparam_sysfs_get_targets(struct list_head *list)
mchristi aadf696
+{
mchristi aadf696
+	struct dirent *dent;
mchristi aadf696
+	DIR *dirfd;
mchristi aadf696
+	int rc = 0;
mchristi aadf696
+
mchristi aadf696
+	/* ibft only has one instance */
mchristi aadf696
+	get_targets(list, IBFT_SYSFS_ROOT, IBFT_SUBSYS);
mchristi aadf696
+	/*
mchristi aadf696
+	 * We could have multiple iscsi llds and each lld could have
mchristi aadf696
+	 * multiple targets/ethernet ports
mchristi aadf696
+	 */
mchristi aadf696
+	dirfd = opendir(ISCSI_LLD_ROOT);
mchristi aadf696
+	if (!dirfd) {
mchristi aadf696
+		rc = errno;
mchristi aadf696
+		goto done;
mchristi aadf696
+	}
mchristi aadf696
+
mchristi aadf696
+	while ((dent = readdir(dirfd))) {
mchristi aadf696
+		char lld_root[FILENAMESZ];
mchristi aadf696
+
mchristi aadf696
+		memset(&lld_root, 0 , FILENAMESZ);
mchristi aadf696
+
mchristi aadf696
+		if (!strcmp(dent->d_name, ".") || !strcmp(dent->d_name, ".."))
mchristi aadf696
+			continue;
mchristi aadf696
+
mchristi aadf696
+		if (strncmp(dent->d_name, ISCSI_LLD_SUBSYS_PREFIX, 10))
mchristi aadf696
+			continue;
mchristi aadf696
+
mchristi aadf696
+		snprintf(lld_root, FILENAMESZ, ISCSI_LLD_ROOT"%s",
mchristi aadf696
+			 dent->d_name);
mchristi aadf696
+		get_targets(list, lld_root, dent->d_name);
mchristi aadf696
+	}
mchristi aadf696
+	closedir(dirfd);
mchristi aadf696
+done:
mchristi aadf696
+	if (!rc && list_empty(list))
mchristi aadf696
+		rc = ENODEV;
mchristi aadf696
+	if (rc)
mchristi aadf696
+		fw_free_targets(list);
mchristi aadf696
+	return rc;
mchristi aadf696
+}
mchristi aadf696
-- 
mchristi aadf696
1.6.6.1
mchristi aadf696