a4c8b30
diff -Naurp open-iscsi-2.0-870-rc1/utils/fwparam_ibft/fw_entry.c open-iscsi-2.0-870-rc1.work/utils/fwparam_ibft/fw_entry.c
a4c8b30
--- open-iscsi-2.0-870-rc1/utils/fwparam_ibft/fw_entry.c	2008-06-30 20:14:03.000000000 -0500
a4c8b30
+++ open-iscsi-2.0-870-rc1.work/utils/fwparam_ibft/fw_entry.c	2008-06-30 21:21:57.000000000 -0500
5a3872e
@@ -29,7 +29,8 @@ int fw_get_entry(struct boot_context *co
5a3872e
 
5a3872e
 	ret = fwparam_ppc(context, filepath);
5a3872e
 	if (ret)
5a3872e
-		ret = fwparam_ibft(context, filepath);
5a3872e
+		ret = fwparam_ibft_sysfs(context, filepath);
5a3872e
+
5a3872e
 	return ret;
5a3872e
 }
5a3872e
 
a4c8b30
diff -Naurp open-iscsi-2.0-870-rc1/utils/fwparam_ibft/fwparam_ibft.h open-iscsi-2.0-870-rc1.work/utils/fwparam_ibft/fwparam_ibft.h
a4c8b30
--- open-iscsi-2.0-870-rc1/utils/fwparam_ibft/fwparam_ibft.h	2008-06-30 20:14:03.000000000 -0500
a4c8b30
+++ open-iscsi-2.0-870-rc1.work/utils/fwparam_ibft/fwparam_ibft.h	2008-06-30 21:21:57.000000000 -0500
5a3872e
@@ -153,6 +153,7 @@ extern int dev_count;
5a3872e
 #define TARGET		"target"
5a3872e
 
5a3872e
 extern int fwparam_ibft(struct boot_context *context, const char *filepath);
5a3872e
+extern int fwparam_ibft_sysfs(struct boot_context *context,
5a3872e
+			const char *filepath);
5a3872e
 extern int fwparam_ppc(struct boot_context *context, const char *filepath);
5a3872e
-
5a3872e
 #endif /* FWPARAM_IBFT_H_ */
a4c8b30
diff -Naurp open-iscsi-2.0-870-rc1/utils/fwparam_ibft/fwparam_ibft_sysfs.c open-iscsi-2.0-870-rc1.work/utils/fwparam_ibft/fwparam_ibft_sysfs.c
a4c8b30
--- open-iscsi-2.0-870-rc1/utils/fwparam_ibft/fwparam_ibft_sysfs.c	1969-12-31 18:00:00.000000000 -0600
a4c8b30
+++ open-iscsi-2.0-870-rc1.work/utils/fwparam_ibft/fwparam_ibft_sysfs.c	2008-06-30 21:21:57.000000000 -0500
5a3872e
@@ -0,0 +1,271 @@
5a3872e
+/*
5a3872e
+ * Copyright (C) IBM Corporation. 2007
5a3872e
+ * Author: Konrad Rzeszutek <konradr@linux.vnet.ibm.com>
5a3872e
+ *
5a3872e
+ * This program is free software: you can redistribute it and/or modify
5a3872e
+ * it under the terms of the GNU General Public License as published by
5a3872e
+ * the Free Software Foundation, either version 2 of the License, or
5a3872e
+ * (at your option) any later version.
5a3872e
+ *
5a3872e
+ * This program is distributed in the hope that it will be useful,
5a3872e
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
5a3872e
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
5a3872e
+ * GNU General Public License for more details.
5a3872e
+ *
5a3872e
+ * You should have received a copy of the GNU General Public License
5a3872e
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
5a3872e
+ */
5a3872e
+
5a3872e
+#define  _XOPEN_SOURCE 500
5a3872e
+#include <ftw.h>
5a3872e
+#include <stdio.h>
5a3872e
+#include <stdlib.h>
5a3872e
+#include <string.h>
5a3872e
+#include <unistd.h>
5a3872e
+#include <fcntl.h>
5a3872e
+#include <errno.h>
5a3872e
+#include "fwparam_ibft.h"
5a3872e
+#include <fw_context.h>
5a3872e
+
5a3872e
+#define IBFT_MAX 255
5a3872e
+#define IBFT_SYSFS_ROOT "/sys/firmware/ibft/"
5a3872e
+
5a3872e
+static char *target_list[IBFT_MAX];
5a3872e
+static char *nic_list[IBFT_MAX];
5a3872e
+static int nic_cnt;
5a3872e
+static int tgt_cnt;
5a3872e
+
5a3872e
+/*
5a3872e
+ * Helper routines.
5a3872e
+ */
5a3872e
+static int file_exist(const char *file)
5a3872e
+{
5a3872e
+
5a3872e
+	struct stat bootpath_stat;
5a3872e
+
5a3872e
+	return !stat(file, &bootpath_stat);
5a3872e
+}
5a3872e
+
5a3872e
+static int read_file(const char *file, char **contents)
5a3872e
+{
5a3872e
+	int error, fd, bytes_read;
5a3872e
+	struct stat bootpath_stat;
5a3872e
+
5a3872e
+	error = stat(file, &bootpath_stat);
5a3872e
+	if (error < 0) {
5a3872e
+		fprintf(stderr, "(%s:%d) stat %s, %s\n", __FILE__, __LINE__,
5a3872e
+			file, strerror(errno));
5a3872e
+		return error;
5a3872e
+	}
5a3872e
+
5a3872e
+	*contents = malloc(bootpath_stat.st_size);
5a3872e
+	if (!*contents) {
5a3872e
+		error = ENOMEM;
5a3872e
+		fprintf(stderr, "(%s:%d) Could not allocate enough memory for "\
5a3872e
+			"%s: %s (%d)\n",
5a3872e
+			__FILE__, __LINE__, file, strerror(error), error);
5a3872e
+		return errno;
5a3872e
+	}
5a3872e
+
5a3872e
+	fd = open(file, O_RDONLY);
5a3872e
+	if (fd < 0) {
5a3872e
+		fprintf(stderr, "(%s:%d): Could not open %s: %s (%d)\n",
5a3872e
+			__FILE__, __LINE__, file, strerror(errno), errno);
5a3872e
+		free(*contents);
5a3872e
+		return errno;
5a3872e
+	}
5a3872e
+
5a3872e
+	bytes_read = read(fd, *contents, bootpath_stat.st_size);
5a3872e
+	close(fd);
5a3872e
+	if (bytes_read > bootpath_stat.st_size) {
5a3872e
+		fprintf(stderr, "(%s:%d) Read more data in than expected for "\
5a3872e
+			"%s: %s (%d)\n",
5a3872e
+			__FILE__, __LINE__, file, strerror(EIO), EIO);
5a3872e
+		free(*contents);
5a3872e
+		return errno;
5a3872e
+	}
5a3872e
+	/* chop() implementation */
5a3872e
+	if (*(*contents + (ssize_t)(bytes_read - 1))  == '\n')
5a3872e
+		*(*contents + (ssize_t) (bytes_read - 1)) = 0;
5a3872e
+
5a3872e
+	return 0;
5a3872e
+}
5a3872e
+
5a3872e
+static int read_data(const char *dir, const char *name, char *dst, ssize_t size)
5a3872e
+{
5a3872e
+	char *data = NULL;
5a3872e
+	char file[FILENAMESZ];
5a3872e
+	int rc = 0;
5a3872e
+
5a3872e
+	memset(file, 0, FILENAMESZ);
5a3872e
+	strncat(file, dir, FILENAMESZ);
5a3872e
+	strncat(file, name, FILENAMESZ);
5a3872e
+
5a3872e
+	if (file_exist(file))  {
5a3872e
+		rc = read_file(file, &data);
5a3872e
+		if (debug)
5a3872e
+			fprintf(stderr, "(%s:%d) Read from %s:[%s]\n",
5a3872e
+				__FILE__, __LINE__, file, data);
5a3872e
+		if (!rc)
5a3872e
+			memcpy(dst, data, size);
5a3872e
+		free(data);
5a3872e
+	}
5a3872e
+
5a3872e
+	return rc;
5a3872e
+}
5a3872e
+
5a3872e
+static int read_int_data(const char *dir, const char *name, int *dst)
5a3872e
+{
5a3872e
+	int rc = 0;
5a3872e
+	char contents[5]; /* The flag is a 1 byte value */
5a3872e
+
5a3872e
+	rc = read_data(dir, name, (char *)&contents, sizeof(contents));
5a3872e
+	if (!rc)
5a3872e
+		*dst = atoi(contents);
5a3872e
+
5a3872e
+	return rc;
5a3872e
+}
5a3872e
+
5a3872e
+/*
5a3872e
+ * Finds the etherrnetX and targetX under the sysfs directory.
5a3872e
+ */
5a3872e
+static int find_sysfs_dirs(const char *fpath, const struct stat *sb,
5a3872e
+			   int tflag, struct FTW *ftw)
5a3872e
+{
5a3872e
+	if (tflag == FTW_D &&
5a3872e
+		(strstr(fpath + ftw->base, "target")))
5a3872e
+			target_list[tgt_cnt++] = strdup(fpath);
5a3872e
+
5a3872e
+	if (tflag == FTW_D &&
5a3872e
+		(strstr(fpath + ftw->base, "ethernet")))
5a3872e
+			nic_list[nic_cnt++] = strdup(fpath);
5a3872e
+
5a3872e
+	return 0;
5a3872e
+}
5a3872e
+
5a3872e
+/*
5a3872e
+ * Routines to fill in the context values.
5a3872e
+ */
5a3872e
+static int fill_nic_context(const char *dir, struct boot_context *context)
5a3872e
+{
5a3872e
+	int rc = 0;
5a3872e
+
5a3872e
+	rc |= read_data(dir, "/mac", context->mac, sizeof(context->mac));
5a3872e
+	rc |= read_data(dir, "/vlan", context->vlan, sizeof(context->vlan));
5a3872e
+	rc |= read_data(dir, "/ip-addr", context->ipaddr,
5a3872e
+		sizeof(context->ipaddr));
5a3872e
+	rc |= read_data(dir, "/mask", context->mask, sizeof(context->mask));
5a3872e
+
5a3872e
+	return rc;
5a3872e
+}
5a3872e
+
5a3872e
+static int fill_initiator_context(const char *dir, struct boot_context *context)
5a3872e
+{
5a3872e
+	int rc = 0;
5a3872e
+
5a3872e
+	rc |= read_data(dir, "/initiator-name", context->initiatorname,
5a3872e
+		sizeof(context->initiatorname));
5a3872e
+	rc |= read_data(dir, "/isns-server", context->isid,
5a3872e
+		sizeof(context->isid));
5a3872e
+
5a3872e
+	return rc;
5a3872e
+}
5a3872e
+static int fill_tgt_context(const char *dir, struct boot_context *context)
5a3872e
+{
5a3872e
+	int rc = 0;
5a3872e
+
5a3872e
+	rc |= read_data(dir, "/target-name", context->targetname,
5a3872e
+		sizeof(context->targetname));
5a3872e
+	rc |= read_data(dir, "/ip-addr", context->target_ipaddr,
5a3872e
+		sizeof(context->target_ipaddr));
5a3872e
+	rc |= read_int_data(dir, "/port", &context->target_port);
5a3872e
+	rc |= read_data(dir, "/lun", context->lun,
5a3872e
+		sizeof(context->lun));
5a3872e
+	rc |= read_data(dir, "/chap-name", context->chap_name,
5a3872e
+		sizeof(context->chap_name));
5a3872e
+	rc |= read_data(dir, "/chap-secret", context->chap_password,
5a3872e
+		sizeof(context->chap_password));
5a3872e
+	rc |= read_data(dir, "/rev-chap-name", context->chap_name_in,
5a3872e
+		sizeof(context->chap_name_in));
5a3872e
+	rc |= read_data(dir, "/rev-chap-name-secret", context->chap_password_in,
5a3872e
+		sizeof(context->chap_password_in));
5a3872e
+
5a3872e
+	return 0;
5a3872e
+}
5a3872e
+
5a3872e
+#define IBFT_SYSFS_FLAG_NAME "/flags"
5a3872e
+#define IBFT_SYSFS_FLAG_FW_SEL_BOOT 2
5a3872e
+
5a3872e
+static int find_boot_flag(char *list[], ssize_t size, int *boot_idx)
5a3872e
+{
5a3872e
+	int rc = -1;
5a3872e
+	int i, flag = -1;
5a3872e
+
5a3872e
+	for (i = 0; i < size; i++, flag = -1) {
5a3872e
+		rc = read_int_data(list[i], IBFT_SYSFS_FLAG_NAME, &flag;;
5a3872e
+		if (flag & IBFT_SYSFS_FLAG_FW_SEL_BOOT) {
5a3872e
+			*boot_idx = i;
5a3872e
+			rc = 0;
5a3872e
+			break;
5a3872e
+		}
5a3872e
+
5a3872e
+	}
5a3872e
+
5a3872e
+	return rc;
5a3872e
+}
5a3872e
+
5a3872e
+static void deallocate_lists(void)
5a3872e
+{
5a3872e
+	int i;
5a3872e
+
5a3872e
+	for (i = 0; i < nic_cnt; i++)
5a3872e
+		free(nic_list[i]);
5a3872e
+
5a3872e
+	nic_cnt = 0;
5a3872e
+	for (i = 0; i < tgt_cnt; i++)
5a3872e
+		free(target_list[i]);
5a3872e
+
5a3872e
+	tgt_cnt = 0;
5a3872e
+
5a3872e
+}
5a3872e
+
5a3872e
+int fwparam_ibft_sysfs(struct boot_context *context, const char *filepath)
5a3872e
+{
5a3872e
+	char initiator_dir[FILENAMESZ];
5a3872e
+	char *root_sysfs = NULL;
5a3872e
+	int rc = 1;
5a3872e
+	int nic_idx = -1, tgt_idx = -1;
5a3872e
+
5a3872e
+	if (filepath)
5a3872e
+		root_sysfs = (char *)filepath;
5a3872e
+	else
5a3872e
+		root_sysfs = IBFT_SYSFS_ROOT;
5a3872e
+
5a3872e
+	memset(&initiator_dir, 0 , FILENAMESZ);
5a3872e
+	strncat(initiator_dir, root_sysfs, FILENAMESZ);
5a3872e
+	strncat(initiator_dir, "initiator", FILENAMESZ);
5a3872e
+
5a3872e
+	if (file_exist(initiator_dir)) {
5a3872e
+
5a3872e
+		/* Find the target's and the ethernet's */
5a3872e
+		rc = nftw(root_sysfs, find_sysfs_dirs, 20, 1);
5a3872e
+
5a3872e
+		/* Find wihch target and which ethernet have
5a3872e
+		the boot flag set. */
5a3872e
+		rc = find_boot_flag(nic_list, nic_cnt, &nic_idx);
5a3872e
+		if (rc)
5a3872e
+			goto free;
5a3872e
+
5a3872e
+		rc = find_boot_flag(target_list, tgt_cnt, &tgt_idx);
5a3872e
+		if (rc)
5a3872e
+			goto free;
5a3872e
+
5a3872e
+		/* Fill in the context values */
5a3872e
+		rc = fill_nic_context(nic_list[nic_idx], context);
5a3872e
+		rc |= fill_tgt_context(target_list[tgt_idx], context);
5a3872e
+		rc |= fill_initiator_context(initiator_dir, context);
5a3872e
+	}
5a3872e
+free:
5a3872e
+	deallocate_lists();
5a3872e
+	return rc;
5a3872e
+}
a4c8b30
diff -Naurp open-iscsi-2.0-870-rc1/utils/fwparam_ibft/Makefile open-iscsi-2.0-870-rc1.work/utils/fwparam_ibft/Makefile
a4c8b30
--- open-iscsi-2.0-870-rc1/utils/fwparam_ibft/Makefile	2008-06-30 20:14:03.000000000 -0500
a4c8b30
+++ open-iscsi-2.0-870-rc1.work/utils/fwparam_ibft/Makefile	2008-06-30 21:22:44.000000000 -0500
a4c8b30
@@ -22,7 +22,7 @@
5a3872e
 #
5a3872e
 
a4c8b30
 OBJS := fwparam_ibft.o fw_entry.o
a4c8b30
-OBJS += prom_lex.o prom_parse.tab.o fwparam_ppc.o
a4c8b30
+OBJS += prom_lex.o prom_parse.tab.o fwparam_ppc.o fwparam_ibft_sysfs.o
a4c8b30
 CLEANFILES = $(OBJS) *.output *~
a4c8b30
 
a4c8b30
 OPTFLAGS ?= -O2 -g -fPIC