Mike,

I've added the bug-fixes and the missing functionality you put in RHEL5.2 to 
make this
one check-in. But if you would like me to split it out in two posts: initial 
code and
bugfix I would be more than happy to do this.

This patch parses the kernel exposing the iBFT information via the sysfs entry.
Here is the git commit from the kernel.org:

commit 138fe4e069798d9aa948a5402ff15e58f483ee4e
Author: Konrad Rzeszutek <[EMAIL PROTECTED]>
Date:   Wed Apr 9 19:50:41 2008 -0700

    Firmware: add iSCSI iBFT Support
    
    Add /sysfs/firmware/ibft/[initiator|targetX|ethernetX] directories along 
with
    text properties which export the the iSCSI Boot Firmware Table (iBFT)
    structure.
    
    What is iSCSI Boot Firmware Table?  It is a mechanism for the iSCSI tools to
    extract from the machine NICs the iSCSI connection information so that they
    can automagically mount the iSCSI share/target.  Currently the iSCSI
    information is hard-coded in the initrd.  The /sysfs entries are read-only
    one-name-and-value fields.
    
    The usual set of data exposed is:
    
    # for a in `find /sys/firmware/ibft/ -type f -print`; do  echo -n "$a: ";  
cat $a; done
    /sys/firmware/ibft/target0/target-name: 
iqn.2007.com.intel-sbx44:storage-10gb
    /sys/firmware/ibft/target0/nic-assoc: 0
    /sys/firmware/ibft/target0/chap-type: 0
    /sys/firmware/ibft/target0/lun: 00000000
    /sys/firmware/ibft/target0/port: 3260
    /sys/firmware/ibft/target0/ip-addr: 192.168.79.116
    /sys/firmware/ibft/target0/flags: 3
    /sys/firmware/ibft/target0/index: 0
    /sys/firmware/ibft/ethernet0/mac: 00:11:25:9d:8b:01
    /sys/firmware/ibft/ethernet0/vlan: 0
    /sys/firmware/ibft/ethernet0/gateway: 192.168.79.254
    /sys/firmware/ibft/ethernet0/origin: 0
    /sys/firmware/ibft/ethernet0/subnet-mask: 255.255.252.0
    /sys/firmware/ibft/ethernet0/ip-addr: 192.168.77.41
    /sys/firmware/ibft/ethernet0/flags: 7
    /sys/firmware/ibft/ethernet0/index: 0
    /sys/firmware/ibft/initiator/initiator-name: 
iqn.2007-07.com:konrad.initiator
    /sys/firmware/ibft/initiator/flags: 3
    /sys/firmware/ibft/initiator/index: 0



 Makefile             |    3 
 fw_entry.c           |    3 
 fwparam_ibft.h       |    3 
 fwparam_ibft_sysfs.c |  330 +++++++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 336 insertions(+), 3 deletions(-)


 Signed-off-by:  Konrad Rzeszutek <[EMAIL PROTECTED]>


diff --git a/utils/fwparam_ibft/Makefile b/utils/fwparam_ibft/Makefile
index 6d7d00a..71d27a9 100644
--- a/utils/fwparam_ibft/Makefile
+++ b/utils/fwparam_ibft/Makefile
@@ -20,8 +20,7 @@
 #          Doug Maxey <[EMAIL PROTECTED]>
 #          "Prasanna Mumbai" <[EMAIL PROTECTED]>
 #
-
-OBJS := fwparam_ibft.o fw_entry.o
+OBJS := fwparam_ibft.o fw_entry.o fwparam_ibft_sysfs.o
 OBJS += prom_lex.o prom_parse.tab.o fwparam_ppc.o
 CLEANFILES = $(OBJS) *.output *~
 
diff --git a/utils/fwparam_ibft/fw_entry.c b/utils/fwparam_ibft/fw_entry.c
index 915bbb7..e575da4 100644
--- a/utils/fwparam_ibft/fw_entry.c
+++ b/utils/fwparam_ibft/fw_entry.c
@@ -29,7 +29,10 @@ int fw_get_entry(struct boot_context *context, const char 
*filepath)
 
        ret = fwparam_ppc(context, filepath);
        if (ret)
+               ret = fwparam_ibft_sysfs(context, filepath);
+       if (ret)
                ret = fwparam_ibft(context, filepath);
+
        return ret;
 }
 
diff --git a/utils/fwparam_ibft/fwparam_ibft.h 
b/utils/fwparam_ibft/fwparam_ibft.h
index 90ecb17..0eed9cd 100644
--- a/utils/fwparam_ibft/fwparam_ibft.h
+++ b/utils/fwparam_ibft/fwparam_ibft.h
@@ -153,6 +153,7 @@ extern int dev_count;
 #define TARGET         "target"
 
 extern int fwparam_ibft(struct boot_context *context, const char *filepath);
+extern int fwparam_ibft_sysfs(struct boot_context *context,
+                       const char *filepath);
 extern int fwparam_ppc(struct boot_context *context, const char *filepath);
-
 #endif /* FWPARAM_IBFT_H_ */
diff --git a/utils/fwparam_ibft/fwparam_ibft_sysfs.c 
b/utils/fwparam_ibft/fwparam_ibft_sysfs.c
new file mode 100644
index 0000000..004a1ea
--- /dev/null
+++ b/utils/fwparam_ibft/fwparam_ibft_sysfs.c
@@ -0,0 +1,330 @@
+/*
+ * Copyright (C) IBM Corporation. 2007
+ * Copyright (C) Konrad Rzeszutek, 2008
+ * Author: Konrad Rzeszutek <[EMAIL PROTECTED]>
+ *
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#define  _XOPEN_SOURCE 500
+#include <ftw.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <dirent.h>
+#include <fw_context.h>
+#include <sys/types.h>
+
+#include "fwparam_ibft.h"
+
+#define IBFT_MAX 255
+#define IBFT_SYSFS_ROOT "/sys/firmware/ibft/"
+#define IBFT_SYSFS_DE
+
+static char *target_list[IBFT_MAX];
+static char *nic_list[IBFT_MAX];
+static int nic_cnt;
+static int tgt_cnt;
+
+/*
+ * Helper routines.
+ */
+static int file_exist(const char *file)
+{
+
+       struct stat bootpath_stat;
+
+       return !stat(file, &bootpath_stat);
+}
+
+static int read_file(const char *file, char **contents)
+{
+       int error, fd, bytes_read;
+       struct stat bootpath_stat;
+
+       error = stat(file, &bootpath_stat);
+       if (error < 0) {
+               fprintf(stderr, "(%s:%d) stat %s, %s\n", __FILE__, __LINE__,
+                       file, strerror(errno));
+               return error;
+       }
+
+       *contents = malloc(bootpath_stat.st_size);
+       if (!*contents) {
+               error = ENOMEM;
+               fprintf(stderr, "(%s:%d) Could not allocate enough memory for "\
+                       "%s: %s (%d)\n",
+                       __FILE__, __LINE__, file, strerror(error), error);
+               return errno;
+       }
+
+       fd = open(file, O_RDONLY);
+       if (fd < 0) {
+               fprintf(stderr, "(%s:%d): Could not open %s: %s (%d)\n",
+                       __FILE__, __LINE__, file, strerror(errno), errno);
+               free(*contents);
+               return errno;
+       }
+
+       bytes_read = read(fd, *contents, bootpath_stat.st_size);
+       close(fd);
+       if (bytes_read > bootpath_stat.st_size) {
+               fprintf(stderr, "(%s:%d) Read more data in than expected for "\
+                       "%s: %s (%d)\n",
+                       __FILE__, __LINE__, file, strerror(EIO), EIO);
+               free(*contents);
+               return errno;
+       }
+       /* chop() implementation */
+       if (*(*contents + (ssize_t)(bytes_read - 1))  == '\n')
+               *(*contents + (ssize_t) (bytes_read - 1)) = 0;
+
+       return 0;
+}
+
+static int read_data(const char *dir, const char *name, char *dst, ssize_t 
size)
+{
+       char *data = NULL;
+       char file[FILENAMESZ];
+       int rc = 0;
+
+       memset(file, 0, FILENAMESZ);
+       strncat(file, dir, FILENAMESZ);
+       strncat(file, name, FILENAMESZ);
+
+       if (file_exist(file))  {
+               rc = read_file(file, &data);
+               if (debug)
+                       fprintf(stderr, "(%s:%d) Read from %s:[%s]\n",
+                               __FILE__, __LINE__, file, data);
+               if (!rc)
+                       memcpy(dst, data, size);
+               free(data);
+       }
+
+       return rc;
+}
+
+static int read_int_data(const char *dir, const char *name, int *dst)
+{
+       int rc = 0;
+       char contents[5]; /* The flag is a 1 byte value */
+
+       rc = read_data(dir, name, (char *)&contents, sizeof(contents));
+       if (!rc)
+               *dst = atoi(contents);
+
+       return rc;
+}
+
+/*
+ * Finds the etherrnetX and targetX under the sysfs directory.
+ */
+static int find_sysfs_dirs(const char *fpath, const struct stat *sb,
+                          int tflag, struct FTW *ftw)
+{
+       if (tflag == FTW_D &&
+               (strstr(fpath + ftw->base, "target")))
+                       target_list[tgt_cnt++] = strdup(fpath);
+
+       if (tflag == FTW_D &&
+               (strstr(fpath + ftw->base, "ethernet")))
+                       nic_list[nic_cnt++] = strdup(fpath);
+
+       return 0;
+}
+
+static int get_iface_from_device(const char *eth_dir,
+                                struct boot_context *context)
+{
+       char dev_dir[FILENAMESZ];
+       int rc = ENODEV;
+       DIR *dirfd;
+       struct dirent *dent;
+
+       memset(dev_dir, 0, FILENAMESZ);
+       strncat(dev_dir, eth_dir, FILENAMESZ);
+       strncat(dev_dir, "/device", FILENAMESZ);
+
+       if (!file_exist(dev_dir))
+               return 0;
+
+       dirfd = opendir(dev_dir);
+       if (!dirfd)
+               return errno;
+
+       while ((dent = readdir(dirfd))) {
+               if (!strcmp(dent->d_name, ".") || !strcmp(dent->d_name, ".."))
+                       continue;
+
+               if (strncmp(dent->d_name, "net:", 4))
+                       continue;
+
+               if ((strlen(dent->d_name) - 4) > (sizeof(context->iface) - 1)) {
+                       rc = EINVAL;
+                       printf("Net device %s too bug for iface buffer.\n",
+                              dent->d_name);
+                       break;
+               }
+
+               if (sscanf(dent->d_name, "net:%s", context->iface) != 1)
+                       rc = EINVAL;
+               rc = 0;
+               break;
+       }
+
+       return rc;
+}
+
+/*
+ * Routines to fill in the context values.
+ */
+static int fill_nic_context(const char *dir, struct boot_context *context)
+{
+       int rc = 0;
+
+       rc |= read_data(dir, "/mac", context->mac, sizeof(context->mac));
+       rc |= read_data(dir, "/vlan", context->vlan, sizeof(context->vlan));
+       rc |= read_data(dir, "/ip-addr", context->ipaddr,
+               sizeof(context->ipaddr));
+       rc |= read_data(dir, "/subnet-mask", context->mask,
+                       sizeof(context->mask));
+       rc |= read_data(dir, "/gateway", context->gateway,
+                       sizeof(context->gateway));
+       rc |= read_data(dir, "/primary-dns", context->primary_dns,
+                       sizeof(context->primary_dns));
+       rc |= read_data(dir, "/secondary-dns", context->secondary_dns,
+                       sizeof(context->secondary_dns));
+       rc |= read_data(dir, "/dhcp", context->dhcp, sizeof(context->dhcp));
+
+       rc |= get_iface_from_device(dir, context);
+
+       return rc;
+}
+
+static int fill_initiator_context(const char *dir, struct boot_context 
*context)
+{
+       int rc = 0;
+
+       rc |= read_data(dir, "/initiator-name", context->initiatorname,
+               sizeof(context->initiatorname));
+       rc |= read_data(dir, "/isns-server", context->isid,
+               sizeof(context->isid));
+
+       return rc;
+}
+static int fill_tgt_context(const char *dir, struct boot_context *context)
+{
+       int rc = 0;
+
+       rc |= read_data(dir, "/target-name", context->targetname,
+               sizeof(context->targetname));
+       rc |= read_data(dir, "/ip-addr", context->target_ipaddr,
+               sizeof(context->target_ipaddr));
+       rc |= read_int_data(dir, "/port", &context->target_port);
+       rc |= read_data(dir, "/lun", context->lun,
+               sizeof(context->lun));
+       rc |= read_data(dir, "/chap-name", context->chap_name,
+               sizeof(context->chap_name));
+       rc |= read_data(dir, "/chap-secret", context->chap_password,
+               sizeof(context->chap_password));
+       rc |= read_data(dir, "/rev-chap-name", context->chap_name_in,
+               sizeof(context->chap_name_in));
+       rc |= read_data(dir, "/rev-chap-name-secret", context->chap_password_in,
+               sizeof(context->chap_password_in));
+
+       return 0;
+}
+
+#define IBFT_SYSFS_FLAG_NAME "/flags"
+#define IBFT_SYSFS_FLAG_FW_SEL_BOOT 2
+
+static int find_boot_flag(char *list[], ssize_t size, int *boot_idx)
+{
+       int rc = -1;
+       int i, flag = 0;
+
+       for (i = 0; i < size; i++, flag = -1) {
+               rc = read_int_data(list[i], IBFT_SYSFS_FLAG_NAME, &flag);
+               if (flag & IBFT_SYSFS_FLAG_FW_SEL_BOOT) {
+                       *boot_idx = i;
+                       rc = 0;
+                       break;
+               }
+               rc = -1;
+               flag = 0;
+
+       }
+
+       return rc;
+}
+
+static void deallocate_lists(void)
+{
+       int i;
+
+       for (i = 0; i < nic_cnt; i++)
+               free(nic_list[i]);
+
+       nic_cnt = 0;
+       for (i = 0; i < tgt_cnt; i++)
+               free(target_list[i]);
+
+       tgt_cnt = 0;
+
+}
+
+int fwparam_ibft_sysfs(struct boot_context *context, const char *filepath)
+{
+       char initiator_dir[FILENAMESZ];
+       char *root_sysfs = NULL;
+       int rc = 1;
+       int nic_idx = -1, tgt_idx = -1;
+
+       if (filepath)
+               root_sysfs = (char *)filepath;
+       else
+               root_sysfs = IBFT_SYSFS_ROOT;
+
+       memset(&initiator_dir, 0 , FILENAMESZ);
+       strncat(initiator_dir, root_sysfs, FILENAMESZ);
+       strncat(initiator_dir, "initiator", FILENAMESZ);
+
+       if (file_exist(initiator_dir)) {
+
+               /* Find the target's and the ethernet's */
+               rc = nftw(root_sysfs, find_sysfs_dirs, 20, 1);
+
+               /* Find which target and ethernet have the boot flag set. */
+               rc = find_boot_flag(nic_list, nic_cnt, &nic_idx);
+               if (rc)
+                       goto free;
+
+               rc = find_boot_flag(target_list, tgt_cnt, &tgt_idx);
+               if (rc)
+                       goto free;
+
+               /* Fill in the context values */
+               rc = fill_nic_context(nic_list[nic_idx], context);
+               rc |= fill_tgt_context(target_list[tgt_idx], context);
+               rc |= fill_initiator_context(initiator_dir, context);
+       }
+free:
+       deallocate_lists();
+       return rc;
+}

--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"open-iscsi" group.
To post to this group, send email to open-iscsi@googlegroups.com
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at http://groups.google.com/group/open-iscsi
-~----------~----~----~----~------~----~------~--~---

Reply via email to