1525 lines
41 KiB
Plaintext
1525 lines
41 KiB
Plaintext
diff --git a/utils/fwparam_ibft/Makefile b/utils/fwparam_ibft/Makefile
|
|
index ee090c1..673af53 100644
|
|
--- a/utils/fwparam_ibft/Makefile
|
|
+++ b/utils/fwparam_ibft/Makefile
|
|
@@ -1,3 +1,29 @@
|
|
+#
|
|
+# 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
|
|
+#
|
|
+# 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, write to the Free Software
|
|
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
|
+#
|
|
+# Copyright (C) IBM Corporation. 2007
|
|
+#
|
|
+# Authors: Patrick Mansfield <patmans@us.ibm.com>
|
|
+# Mike Anderson <andmike@us.ibm.com>
|
|
+# Doug Maxey <dwm@austin.ibm.com>
|
|
+#
|
|
+
|
|
+CC = $(CROSS_COMPILE)gcc
|
|
OPTFLAGS ?= -O2 -g
|
|
WARNFLAGS ?= -Wall -Wstrict-prototypes
|
|
CFLAGS += $(OPTFLAGS) $(WARNFLAGS)
|
|
@@ -5,7 +31,86 @@ PROGRAMS = fwparam_ibft
|
|
|
|
all: $(PROGRAMS)
|
|
|
|
-fwparam_ibft: fwparam_ibft.c fwparam_ibft.h
|
|
- $(CC) $(CFLAGS) $^ -o $@
|
|
-clean:
|
|
- rm -f *.o $(PROGRAMS)
|
|
+#
|
|
+# This tool currently only provides useful output on certain IBM
|
|
+# boxes with iboot capable firmware or BIOS on System x and System p. :)
|
|
+#
|
|
+
|
|
+OBJS :=
|
|
+
|
|
+# Allow cross compile by looking at the compiler, not the host.
|
|
+target_machine = $(ARCH)
|
|
+
|
|
+#
|
|
+# override compiler test for powerpc by defining DEBUG_IBFT=powerpc to
|
|
+# build with native compiler.
|
|
+#
|
|
+
|
|
+ifeq (ppc,$(findstring ppc,$(target_machine)))
|
|
+#
|
|
+# powerpc objects
|
|
+#
|
|
+OBJS += prom_lex.o prom_parse.tab.o fwparam_ppc_main.o
|
|
+GENFILES = prom_lex.c prom_parse.tab.c prom_parse.tab.h
|
|
+CLEANFILES = $(OBJS) $(GENFILES) *.output *~
|
|
+
|
|
+BISONFLAGS = -d
|
|
+FLEXFLAGS = -t
|
|
+# turn off #line number markers
|
|
+NOL = 0
|
|
+ifneq (0 ,$(NOL))
|
|
+ FLEXFLAGS += -L
|
|
+ BISONFLAGS += --no-lines
|
|
+endif # NOL
|
|
+
|
|
+ %.c : %.l
|
|
+ flex ${FLEXFLAGS} $< | perl -pe '/define YYLMAX/ && s{8192}{2048}' >$@
|
|
+
|
|
+ %.tab.c %.tab.h: %.y
|
|
+ bison ${BISONFLAGS} $<
|
|
+
|
|
+$(GENFILES): Makefile
|
|
+
|
|
+$(OBJS): prom_parse.tab.h prom_parse.h
|
|
+##########
|
|
+
|
|
+else
|
|
+ifeq (x86_64,$(target_machine))
|
|
+#
|
|
+# x86_64 objects
|
|
+#
|
|
+OBJS += fwparam_ibft.o
|
|
+CLEANFILES = $(OBJS) *~
|
|
+
|
|
+$(OBJS): Makefile fwparam_ibft.h
|
|
+##########
|
|
+
|
|
+
|
|
+else
|
|
+ifeq (86,$(findstring 86,$(target_machine)))
|
|
+#
|
|
+# x86 objects
|
|
+#
|
|
+OBJS += fwparam_ibft.o
|
|
+CLEANFILES = $(OBJS) *~
|
|
+
|
|
+$(OBJS): Makefile fwparam_ibft.h
|
|
+##########
|
|
+
|
|
+else
|
|
+#
|
|
+# compile a do nothing main here.
|
|
+#
|
|
+OBJS += fwparam_dummy.o
|
|
+##########
|
|
+
|
|
+endif
|
|
+endif
|
|
+endif
|
|
+
|
|
+$(PROGRAMS) : $(OBJS) Makefile
|
|
+ ${CC} -o $(PROGRAMS) $(OBJS)
|
|
+
|
|
+.PHONY : clean
|
|
+clean :
|
|
+ -rm -f $(PROGRAMS) $(CLEANFILES)
|
|
diff --git a/utils/fwparam_ibft/README-ppc b/utils/fwparam_ibft/README-ppc
|
|
new file mode 100644
|
|
index 0000000..f42d2c3
|
|
--- /dev/null
|
|
+++ b/utils/fwparam_ibft/README-ppc
|
|
@@ -0,0 +1,16 @@
|
|
+
|
|
+This is the second version of fwparam_ibft.
|
|
+
|
|
+This version of the tool enables a powerpc system that is capable of
|
|
+booting from an iSCSI device to extract the pertinent info about the
|
|
+connection. The functionality is as close an analogue as possible to
|
|
+the fwparam_ibft for IBM System x.
|
|
+
|
|
+This version of the tool parses the firmware property
|
|
+/proc/device-tree/chosen/bootpath by default when called with the -b
|
|
+flag, and prints the interesting data in a format that can be simply
|
|
+reparsed during boot.
|
|
+
|
|
+It can also use any file that properly describes the connection, in
|
|
+particular the /proc/device-tree/aliases/iscsi-disk? files.
|
|
+
|
|
diff --git a/utils/fwparam_ibft/fwparam_dummy.c b/utils/fwparam_ibft/fwparam_dummy.c
|
|
new file mode 100644
|
|
index 0000000..11a2efe
|
|
--- /dev/null
|
|
+++ b/utils/fwparam_ibft/fwparam_dummy.c
|
|
@@ -0,0 +1,23 @@
|
|
+/*
|
|
+ * 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, write to the Free Software
|
|
+ * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
|
|
+ * USA.
|
|
+ *
|
|
+ * Copyright (C) IBM Corporation, 2007
|
|
+ *
|
|
+ * Author: Doug Maxey <dwm@austin.ibm.com>
|
|
+ *
|
|
+ */
|
|
+
|
|
+int main (int argc, char **argv) {/* An exercise in minimalism. */ return 0;}
|
|
diff --git a/utils/fwparam_ibft/fwparam_ppc.c b/utils/fwparam_ibft/fwparam_ppc.c
|
|
new file mode 100644
|
|
index 0000000..8046370
|
|
--- /dev/null
|
|
+++ b/utils/fwparam_ibft/fwparam_ppc.c
|
|
@@ -0,0 +1,257 @@
|
|
+/*
|
|
+ * 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, write to the Free Software
|
|
+ * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
|
|
+ * USA.
|
|
+ *
|
|
+ * Copyright (C) IBM Corporation, 2007
|
|
+ *
|
|
+ * Author: Doug Maxey <dwm@austin.ibm.com>
|
|
+ *
|
|
+ */
|
|
+
|
|
+#include <sys/types.h>
|
|
+#include <sys/stat.h>
|
|
+#include <sys/mman.h>
|
|
+#include <stdio.h>
|
|
+#include <stdlib.h>
|
|
+#include <string.h>
|
|
+#include <unistd.h>
|
|
+#include <fcntl.h>
|
|
+#include <errno.h>
|
|
+
|
|
+char *progname;
|
|
+int debug;
|
|
+char default_file_name[] = "/proc/device-tree/choices/bootpath";
|
|
+char *filename = default_file_name;
|
|
+char *bootpath_val;
|
|
+char *mac_path;
|
|
+char *mac_val;
|
|
+int boot_selected_only;
|
|
+int bytes_read;
|
|
+char *device;
|
|
+char *iscsi;
|
|
+char *initiator_name;
|
|
+char *client_addr;
|
|
+char *subnet_mask;
|
|
+char *server_addr;
|
|
+char *server_name;
|
|
+char *port;
|
|
+char *lun;
|
|
+char *prefix;
|
|
+
|
|
+
|
|
+/*
|
|
+ * Prefix strings, for the "prefixN:NAME=value".
|
|
+ */
|
|
+#define NETWORK "network"
|
|
+#define INITIATOR "iscsi-initiator"
|
|
+#define TGT "target"
|
|
+#define MAC_FILE "/mac-address"
|
|
+
|
|
+void pr_param(const char *prefix, int instance, const char *item, char *param)
|
|
+{
|
|
+ char *val = strchr(param, '=') + 1;
|
|
+
|
|
+ fprintf(stdout, "%s%d:%s=%s ", prefix, instance, item, val);
|
|
+}
|
|
+
|
|
+int locate_print_mac(void)
|
|
+{
|
|
+ int error = 0;
|
|
+ char *dt = strdup(filename);
|
|
+ int mac_path_len = strlen(device) + strlen(MAC_FILE) + 2;
|
|
+ char *mac_file;
|
|
+ int mac_fd;
|
|
+
|
|
+ /*
|
|
+ * Get the device-tree top, and work from there.
|
|
+ */
|
|
+ mac_fd = strlen(filename);
|
|
+ mac_fd -= strlen("chosen/bootpath") + 1; /* back up this far */
|
|
+ dt[mac_fd] = 0;
|
|
+ mac_path_len += mac_fd;
|
|
+ mac_file = malloc(mac_path_len);
|
|
+ if (!mac_file) {
|
|
+ error = ENOMEM;
|
|
+ fprintf(stderr, "%s: malloc %s, %s\n", progname, filename,
|
|
+ strerror(errno));
|
|
+ goto lpm_bail;
|
|
+ }
|
|
+
|
|
+ snprintf(mac_file, mac_path_len, "%s%s%s", dt, device, MAC_FILE);
|
|
+ mac_fd = open(mac_file, O_RDONLY);
|
|
+ if (mac_fd < 0) {
|
|
+ error = errno;
|
|
+ fprintf(stderr, "%s: open %s, %s\n", progname, mac_file,
|
|
+ strerror(errno));
|
|
+ goto lpm_bail;
|
|
+ }
|
|
+
|
|
+ bytes_read = read(mac_fd, mac, 6);
|
|
+ if (bytes_read != 6) {
|
|
+ error = EIO;
|
|
+ fprintf(stderr, "%s: read %s, %s\n", progname, mac_file,
|
|
+ strerror(errno));
|
|
+ goto lpm_bail;
|
|
+ }
|
|
+ close(mac_fd);
|
|
+
|
|
+ fprintf(stdout, "%s0:HWADDR=%02x:%02x:%02x:%02x:%02x:%02x ", prefix,
|
|
+ mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
|
|
+
|
|
+lpm_bail:
|
|
+ return error;
|
|
+}
|
|
+
|
|
+int print_params(void)
|
|
+{
|
|
+ int error = 0;
|
|
+ char *pp; /* working pointer in the bootpath params. */
|
|
+#define pick(name) (name) = strtok(NULL, ","); \
|
|
+ if (!(name)) { error = __LINE__; goto ppb_bail; }
|
|
+
|
|
+ device = bootpath_val;
|
|
+ pp = strchr(bootpath_val, ':');
|
|
+
|
|
+ if (pp)
|
|
+ /* chop the string at the first colon. */
|
|
+ *pp++ = 0;
|
|
+ prefix = "iSCSI_INITIATOR_";
|
|
+
|
|
+ error = locate_print_mac();
|
|
+ if (error)
|
|
+ goto ppb_bail;
|
|
+
|
|
+ /*
|
|
+ * tokenize on the comma.
|
|
+ */
|
|
+
|
|
+ iscsi = strtok(pp, ",");
|
|
+ if (!(iscsi)) { error = __LINE__; goto ppb_bail; }
|
|
+
|
|
+ pick(initiator_name);
|
|
+ pick(client_addr);
|
|
+ pick(subnet_mask);
|
|
+ pick(server_addr);
|
|
+ pick(server_name);
|
|
+ pick(port);
|
|
+ pick(lun);
|
|
+
|
|
+ /* We have all the required strings. Now print them. */
|
|
+ pr_param(prefix, 0, "NAME", initiator_name);
|
|
+ pr_param(prefix, 0, "IPADDR", client_addr);
|
|
+ pr_param(prefix, 0, "MASK", subnet_mask);
|
|
+ prefix = "target";
|
|
+ pr_param(prefix, 0, "IPADDR", server_addr);
|
|
+ pr_param(prefix, 0, "PORT", port);
|
|
+ pr_param(prefix, 0, "LUN", lun);
|
|
+ pr_param(prefix, 0, "NAME", server_name);
|
|
+
|
|
+ puts("");
|
|
+ppb_bail:
|
|
+ return error;
|
|
+}
|
|
+
|
|
+int
|
|
+main (int argc, char **argv)
|
|
+{
|
|
+ int fd, option, ret;
|
|
+ struct stat bootpath_stat;
|
|
+
|
|
+ progname = argv[0];
|
|
+
|
|
+ /*
|
|
+ * For powerpc, our operations are fundamentally different.
|
|
+ * Where the x86 method searches memory, we look in the
|
|
+ * ppc procfs device-tree to obtain the data.
|
|
+ */
|
|
+ while (1) {
|
|
+ option = getopt(argc, argv, "f:m:s:e:vhb");
|
|
+ if (option == -1)
|
|
+ break;
|
|
+ switch (option) {
|
|
+ case 'b':
|
|
+ boot_selected_only = 1;
|
|
+ break;
|
|
+ case 'e':
|
|
+ break;
|
|
+ case 'f':
|
|
+ filename = optarg;
|
|
+ break;
|
|
+ case 's':
|
|
+ break;
|
|
+ case 'v':
|
|
+ debug++;
|
|
+ break;
|
|
+ default:
|
|
+ fprintf(stderr, "Unknown or bad option '%c'\n", option);
|
|
+ case 'h':
|
|
+ printf("Usage: %s OPTIONS\n"
|
|
+ "-b (x86 only) print only fw boot selected sections\n"
|
|
+ "-f file_to_search (default %s)\n"
|
|
+ "-s (x86 only) offset to start search\n"
|
|
+ "-e (x86 only) length of search\n"
|
|
+ "-v verbose\n",
|
|
+ progname, default_file_name);
|
|
+ exit(1);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if (debug)
|
|
+ fprintf(stderr, "%s: file:%s; debug:%d\n", progname, filename, debug);
|
|
+
|
|
+ ret = stat(filename, &bootpath_stat);
|
|
+ if (ret < 0) {
|
|
+ fprintf(stderr, "%s: stat %s, %s\n", progname, filename,
|
|
+ strerror(errno));
|
|
+ exit(errno);
|
|
+ }
|
|
+
|
|
+ bootpath_val = malloc(bootpath_stat.st_size);
|
|
+ if (!bootpath_val) {
|
|
+ fprintf(stderr, "%s: Could not open %s: %s (%d)\n",
|
|
+ progname, filename, strerror(ENOMEM), ENOMEM);
|
|
+ exit(ENOMEM);
|
|
+ }
|
|
+
|
|
+ fd = open(filename, O_RDONLY);
|
|
+ if (fd < 0) {
|
|
+ fprintf(stderr, "%s: Could not open %s: %s (%d)\n",
|
|
+ progname, filename, strerror(errno), errno);
|
|
+ exit(1);
|
|
+ }
|
|
+
|
|
+ bytes_read = read(fd, bootpath_val, bootpath_stat.st_size);
|
|
+ close(fd);
|
|
+ if (bytes_read != bootpath_stat.st_size) {
|
|
+ ret = EIO;
|
|
+ fprintf(stderr, "%s: Could not open %s: %s (%d)\n",
|
|
+ progname, filename, strerror(ret), ret);
|
|
+ exit(ret);
|
|
+ }
|
|
+
|
|
+ close(fd);
|
|
+
|
|
+ /*
|
|
+ * We should find *almost* everything we need in the bootpath,
|
|
+ * save the mac-address.
|
|
+ */
|
|
+ if (strstr(bootpath_val, "iscsi"))
|
|
+ ret = parse_print_params();
|
|
+ else
|
|
+ /* did not boot from iscsi! */
|
|
+ ret = 1;
|
|
+
|
|
+ exit(ret);
|
|
+}
|
|
diff --git a/utils/fwparam_ibft/fwparam_ppc_main.c b/utils/fwparam_ibft/fwparam_ppc_main.c
|
|
new file mode 100644
|
|
index 0000000..a004b04
|
|
--- /dev/null
|
|
+++ b/utils/fwparam_ibft/fwparam_ppc_main.c
|
|
@@ -0,0 +1,562 @@
|
|
+/*
|
|
+ * 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, write to the Free Software
|
|
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
|
+ *
|
|
+ * Copyright (C) IBM Corporation. 2007
|
|
+ * Author: Doug Maxey <dwm@austin.ibm.com>
|
|
+ *
|
|
+ */
|
|
+
|
|
+#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 "iscsi_obp.h"
|
|
+#include "prom_parse.h"
|
|
+
|
|
+void* yy_scan_string(const char *str);
|
|
+int yyparse(struct ofw_dev *ofwdev);
|
|
+
|
|
+#define BOOTPATH "/chosen/bootpath"
|
|
+#define DT_TOP "/proc/device-tree"
|
|
+#define MAC_FILE "/mac-address"
|
|
+#define LOCAL_MAC_FILE "/local-mac-address"
|
|
+
|
|
+char *progname;
|
|
+int debug;
|
|
+char default_devtree[] = DT_TOP;
|
|
+char *devtree = default_devtree;
|
|
+int devtree_len;
|
|
+char default_file_name[] = DT_TOP BOOTPATH;
|
|
+char *filename = default_file_name;
|
|
+char *bootpath_val;
|
|
+char *mac_path;
|
|
+char *mac_val;
|
|
+int boot_selected_only;
|
|
+int bytes_read;
|
|
+#define OFWDEV_MAX (10)
|
|
+struct ofw_dev *ofwdevs[OFWDEV_MAX];
|
|
+int dev_count;
|
|
+char *niclist[OFWDEV_MAX];
|
|
+int nic_count;
|
|
+
|
|
+/*
|
|
+ * Prefix strings, for the "prefixN:NAME=value".
|
|
+ */
|
|
+#define NETWORK "network"
|
|
+#define INITIATOR "iscsi-initiator"
|
|
+#define TARGET "target"
|
|
+
|
|
+void pr_param(const char *prefix, const char *name,
|
|
+ struct ofw_dev *dev, enum obp_param item)
|
|
+{
|
|
+ if (dev->param[item])
|
|
+ fprintf(stdout, " %s%s=%s", prefix, name, dev->param[item]->val);
|
|
+}
|
|
+
|
|
+char *find_devtree(const char *filename)
|
|
+{
|
|
+ char *devtree = strdup(filename);
|
|
+ char *chop_at;
|
|
+ struct stat dt_stat;
|
|
+ int error;
|
|
+
|
|
+ /*
|
|
+ * What is the path to the device-tree? The only valid
|
|
+ * directories to locate the property are under /aliases or
|
|
+ * /chosen.
|
|
+ */
|
|
+
|
|
+ chop_at = strstr(devtree, "/chosen");
|
|
+ if (!chop_at)
|
|
+ chop_at = strstr(devtree, "/aliases");
|
|
+
|
|
+ if (!chop_at) {
|
|
+ char *vdev = malloc(strlen(filename) + strlen("/vdevice") + 1);
|
|
+
|
|
+ /*
|
|
+ * test to see if there is /vdevice dir
|
|
+ */
|
|
+ sprintf(vdev, "%s%s", filename, "/vdevice");
|
|
+ error = stat(vdev, &dt_stat);
|
|
+ if (error)
|
|
+ devtree = NULL;
|
|
+ }
|
|
+ else
|
|
+ devtree[chop_at - devtree] = 0;
|
|
+
|
|
+ if (devtree)
|
|
+ devtree_len = strlen(devtree);
|
|
+
|
|
+ return devtree;
|
|
+}
|
|
+
|
|
+void print_mac(const char *prefix, struct ofw_dev *ofwdev)
|
|
+{
|
|
+ fprintf(stdout, " %sHWADDR=%02x:%02x:%02x:%02x:%02x:%02x ", prefix,
|
|
+ ofwdev->mac[0], ofwdev->mac[1], ofwdev->mac[2],
|
|
+ ofwdev->mac[3], ofwdev->mac[4], ofwdev->mac[5]);
|
|
+}
|
|
+
|
|
+/*
|
|
+ * Take the path to the property under chosen, and swizzle to make that
|
|
+ * the base for the device path discovered.
|
|
+ */
|
|
+int locate_mac(const char *devtree, struct ofw_dev *ofwdev)
|
|
+{
|
|
+ int error = 0;
|
|
+ int mac_path_len = strlen(ofwdev->dev_path) + strlen(MAC_FILE) + 2;
|
|
+ char *mac_file;
|
|
+ int mac_fd;
|
|
+
|
|
+ mac_path_len += strlen(devtree);
|
|
+ mac_file = malloc(mac_path_len);
|
|
+ if (!mac_file) {
|
|
+ error = ENOMEM;
|
|
+ fprintf(stderr, "%s: malloc %s, %s\n", progname, filename,
|
|
+ strerror(errno));
|
|
+ goto lpm_bail;
|
|
+ }
|
|
+
|
|
+ snprintf(mac_file, mac_path_len, "%s/%s%s", devtree, ofwdev->dev_path, MAC_FILE);
|
|
+ mac_fd = open(mac_file, O_RDONLY);
|
|
+ if (mac_fd < 0) {
|
|
+ error = errno;
|
|
+ fprintf(stderr, "%s: open %s, %s\n", progname, mac_file,
|
|
+ strerror(errno));
|
|
+ goto lpm_bail;
|
|
+ }
|
|
+
|
|
+ bytes_read = read(mac_fd, ofwdev->mac, 6);
|
|
+ if (bytes_read != 6) {
|
|
+ error = EIO;
|
|
+ fprintf(stderr, "%s: read %s, %s\n", progname, mac_file,
|
|
+ strerror(errno));
|
|
+ goto lpm_bail;
|
|
+ }
|
|
+ close(mac_fd);
|
|
+
|
|
+
|
|
+lpm_bail:
|
|
+ return error;
|
|
+}
|
|
+
|
|
+void print_initiator(const char *prefix, struct ofw_dev *ofwdev)
|
|
+{
|
|
+ pr_param(prefix, "ISNS", ofwdev, OBP_PARAM_ISNS);
|
|
+ pr_param(prefix, "SLP", ofwdev, OBP_PARAM_SLP);
|
|
+ pr_param(prefix, "NAME", ofwdev, OBP_PARAM_INAME);
|
|
+}
|
|
+
|
|
+void print_target(const char *prefix, struct ofw_dev *ofwdev)
|
|
+{
|
|
+ pr_param(prefix, "IPADDR", ofwdev, OBP_PARAM_SIADDR);
|
|
+ pr_param(prefix, "PORT", ofwdev, OBP_PARAM_IPORT);
|
|
+ pr_param(prefix, "LUN", ofwdev, OBP_PARAM_ILUN);
|
|
+ pr_param(prefix, "NAME", ofwdev, OBP_PARAM_ITNAME);
|
|
+ pr_param(prefix, "ISID", ofwdev, OBP_PARAM_ISID);
|
|
+
|
|
+ /*
|
|
+ * chap stuff is always associated with the target
|
|
+ */
|
|
+ pr_param(prefix, "CHAP_NAME", ofwdev, OBP_PARAM_ICHAPID);
|
|
+ pr_param(prefix, "CHAP_NAME", ofwdev, OBP_PARAM_ICHAPPW);
|
|
+ pr_param(prefix, "CHAP_NAME_IN", ofwdev, OBP_PARAM_CHAPID);
|
|
+ pr_param(prefix, "CHAP_PASSWORD_IN", ofwdev, OBP_PARAM_CHAPPW);
|
|
+}
|
|
+
|
|
+void print_nic(const char *prefix, struct ofw_dev *ofwdev)
|
|
+{
|
|
+ print_mac(prefix, ofwdev);
|
|
+
|
|
+ /*
|
|
+ * nic parameters
|
|
+ */
|
|
+ pr_param(prefix, "IPADDR", ofwdev, OBP_PARAM_CIADDR);
|
|
+ pr_param(prefix, "MASK", ofwdev, OBP_PARAM_SUBNET_MASK);
|
|
+}
|
|
+
|
|
+const char *obp_qual_set(struct ofw_dev *ofwdev, const char *qual)
|
|
+{
|
|
+ if (!strcmp("bootp", qual))
|
|
+ ofwdev->quals[ofwdev->qual_count++] = OBP_QUAL_BOOTP;
|
|
+ else if (!strcmp("ipv6", qual))
|
|
+ ofwdev->quals[ofwdev->qual_count++] = OBP_QUAL_IPV6;
|
|
+ else if (!strcmp("iscsi", qual)) {
|
|
+ ofwdev->type = OFW_DT_ISCSI;
|
|
+ ofwdev->quals[ofwdev->qual_count++] = OBP_QUAL_ISCSI;
|
|
+ }
|
|
+ else if (!strcmp("ping", qual))
|
|
+ ofwdev->quals[ofwdev->qual_count++] = OBP_QUAL_PING;
|
|
+ else
|
|
+ printf("%s: %s UNKNOWN\n", __func__, qual);
|
|
+ return qual;
|
|
+}
|
|
+
|
|
+void add_obp_parm(struct ofw_dev *ofwdev, enum obp_param parm, const char *str)
|
|
+{
|
|
+ int psz = sizeof(struct ofw_obp_param) + strlen(str);
|
|
+
|
|
+ ofwdev->param[parm] = malloc(psz);
|
|
+ if (ofwdev->param[parm] == NULL) {
|
|
+ printf("%s: ENOMEM!\n", __func__);
|
|
+ return;
|
|
+ }
|
|
+ memset(ofwdev->param[parm], 0, psz);
|
|
+ ofwdev->param[parm]->len = psz;
|
|
+ strcpy(ofwdev->param[parm]->val, str);
|
|
+}
|
|
+
|
|
+void obp_parm_addr(struct ofw_dev *ofwdev, const char *parm, const char *addr)
|
|
+{
|
|
+ if (!strcmp("ciaddr", parm))
|
|
+ add_obp_parm(ofwdev, OBP_PARAM_CIADDR, addr);
|
|
+ else if (!strcmp("dhcp", parm))
|
|
+ add_obp_parm(ofwdev, OBP_PARAM_DHCP, addr);
|
|
+ else if (!strcmp("giaddr", parm))
|
|
+ add_obp_parm(ofwdev, OBP_PARAM_GIADDR, addr);
|
|
+ else if (!strcmp("isns", parm))
|
|
+ add_obp_parm(ofwdev, OBP_PARAM_ISNS, addr);
|
|
+ else if (!strcmp("siaddr", parm))
|
|
+ add_obp_parm(ofwdev, OBP_PARAM_SIADDR, addr);
|
|
+ else if (!strcmp("slp", parm))
|
|
+ add_obp_parm(ofwdev, OBP_PARAM_SLP, addr);
|
|
+ else if (!strcmp("subnet-mask", parm))
|
|
+ add_obp_parm(ofwdev, OBP_PARAM_SUBNET_MASK, addr);
|
|
+ else
|
|
+ printf("%s: %s UNKNOWN\n", __func__, parm);
|
|
+}
|
|
+
|
|
+void obp_parm_iqn(struct ofw_dev *ofwdev, const char *parm, const char *iqn)
|
|
+{
|
|
+ if (!strcmp("itname", parm))
|
|
+ add_obp_parm(ofwdev, OBP_PARAM_ITNAME, iqn);
|
|
+ else if (!strcmp("iname", parm))
|
|
+ add_obp_parm(ofwdev, OBP_PARAM_INAME, iqn);
|
|
+ else
|
|
+ printf("%s: %s UNKNOWN\n", __func__, parm);
|
|
+}
|
|
+
|
|
+void obp_parm_hexnum(struct ofw_dev *ofwdev, const char *parm, const char *numstr)
|
|
+{
|
|
+ if (!strcmp("bootp-retries", parm))
|
|
+ add_obp_parm(ofwdev, OBP_PARAM_BOOTP_RETRIES, numstr);
|
|
+ else if (!strcmp("tftp-retries", parm))
|
|
+ add_obp_parm(ofwdev, OBP_PARAM_TFTP_RETRIES, numstr);
|
|
+ else if (!strcmp("iport", parm))
|
|
+ add_obp_parm(ofwdev, OBP_PARAM_IPORT, numstr);
|
|
+ else if (!strcmp("ilun", parm))
|
|
+ add_obp_parm(ofwdev, OBP_PARAM_ILUN, numstr);
|
|
+ else if (!strcmp("isid", parm))
|
|
+ add_obp_parm(ofwdev, OBP_PARAM_ISID, numstr);
|
|
+ else
|
|
+ printf("%s: %s UNKNOWN <%s>\n", __func__, parm, numstr);
|
|
+}
|
|
+
|
|
+void obp_parm_str(struct ofw_dev *ofwdev, const char *parm, const char *str)
|
|
+{
|
|
+ if (!strcmp("filename", parm))
|
|
+ add_obp_parm(ofwdev, OBP_PARAM_FILENAME, str);
|
|
+ else if (!strcmp("ichapid", parm))
|
|
+ add_obp_parm(ofwdev, OBP_PARAM_ICHAPID, str);
|
|
+ else if (!strcmp("ichappw", parm))
|
|
+ add_obp_parm(ofwdev, OBP_PARAM_ICHAPPW, str);
|
|
+ else if (!strcmp("chapid", parm))
|
|
+ add_obp_parm(ofwdev, OBP_PARAM_CHAPID, str);
|
|
+ else if (!strcmp("chappw", parm))
|
|
+ add_obp_parm(ofwdev, OBP_PARAM_CHAPPW, str);
|
|
+ else
|
|
+ printf("%s: %s UNKNOWN <%s>\n", __func__, parm, str);
|
|
+}
|
|
+
|
|
+void yyerror(struct ofw_dev *ofwdev, const char *msg)
|
|
+{
|
|
+ fprintf(stderr, "%s: error in <%s> at l%d.c%d\n", progname, ofwdev->prop_path,
|
|
+ yylloc.last_line, yylloc.last_column);
|
|
+}
|
|
+
|
|
+void dump_obp_params(struct ofw_dev **devs, int dev_count)
|
|
+{
|
|
+ static const char *param_name[] = {
|
|
+ "nada",
|
|
+ "blocksize",
|
|
+ "bootp-retries",
|
|
+ "target-chapid",
|
|
+ "target-chappwd",
|
|
+ "my-addr",
|
|
+ "dhcp",
|
|
+ "filename",
|
|
+ "gateway",
|
|
+ "my-chapid",
|
|
+ "my-chappwd",
|
|
+ "target-lun",
|
|
+ "target-name",
|
|
+ "target-port",
|
|
+ "target-isid",
|
|
+ "sns-server",
|
|
+ "my-name",
|
|
+ "server-addr",
|
|
+ "slp-server-addr",
|
|
+ "subnet-mask",
|
|
+ "tftp-retries",
|
|
+ "timeout"
|
|
+ };
|
|
+ int i, j;
|
|
+ struct ofw_dev *dev;
|
|
+ char prefix[42];
|
|
+
|
|
+ for (j = 0; j < dev_count; j++) {
|
|
+ sprintf(prefix, "instance%d:", j);
|
|
+ for (dev = devs[j], i = OBP_PARAM_BLKSIZE; i < OBP_PARAM_COUNT; i++) {
|
|
+ pr_param(prefix, param_name[i], dev, i);
|
|
+ putchar('\n');
|
|
+ }
|
|
+ }
|
|
+
|
|
+}
|
|
+
|
|
+int parse_params(const char *buf, struct ofw_dev *ofwdev)
|
|
+{
|
|
+ int error = 0;
|
|
+#if YYDEBUG
|
|
+ yydebug = 1;
|
|
+#endif
|
|
+
|
|
+
|
|
+ if (yy_scan_string(buf))
|
|
+ error = yyparse(ofwdev);
|
|
+
|
|
+ return error;
|
|
+}
|
|
+
|
|
+int find_file(const char *filename)
|
|
+{
|
|
+ int error, fd;
|
|
+ struct stat bootpath_stat;
|
|
+
|
|
+ error = stat(filename, &bootpath_stat);
|
|
+ if (error < 0) {
|
|
+ fprintf(stderr, "%s: stat %s, %s\n", progname, filename, strerror(errno));
|
|
+ exit(errno);
|
|
+ }
|
|
+
|
|
+ bootpath_val = malloc(bootpath_stat.st_size);
|
|
+ if (!bootpath_val) {
|
|
+ error = ENOMEM;
|
|
+ fprintf(stderr, "%s: Could not open %s: %s (%d)\n",
|
|
+ progname, filename, strerror(error), error);
|
|
+ exit(error);
|
|
+ }
|
|
+
|
|
+ fd = open(filename, O_RDONLY);
|
|
+ if (fd < 0) {
|
|
+ fprintf(stderr, "%s: Could not open %s: %s (%d)\n",
|
|
+ progname, filename, strerror(errno), errno);
|
|
+ exit(1);
|
|
+ }
|
|
+
|
|
+ bytes_read = read(fd, bootpath_val, bootpath_stat.st_size);
|
|
+ close(fd);
|
|
+ if (bytes_read != bootpath_stat.st_size) {
|
|
+ error = EIO;
|
|
+ fprintf(stderr, "%s: Could not open %s: %s (%d)\n",
|
|
+ progname, filename, strerror(error), error);
|
|
+ exit(error);
|
|
+ }
|
|
+
|
|
+ close(fd);
|
|
+
|
|
+ return 1;
|
|
+}
|
|
+
|
|
+static int find_nics(const char *fpath, const struct stat *sb, int tflag, struct FTW *ftw)
|
|
+{
|
|
+ if (tflag == FTW_D &&
|
|
+ (strstr(fpath + ftw->base, "iscsi-toe") ||
|
|
+ strstr(fpath + ftw->base, "ethernet"))) {
|
|
+
|
|
+ if (nic_count < OFWDEV_MAX) {
|
|
+ niclist[nic_count] = malloc(strlen(fpath) + 1);
|
|
+ niclist[nic_count++] = strdup(fpath + devtree_len);
|
|
+ }
|
|
+ }
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int find_initiator(const char *fpath, const struct stat *sb, int tflag, struct FTW *ftw)
|
|
+{
|
|
+ struct ofw_dev *dev;
|
|
+
|
|
+ if (tflag == FTW_F && (strstr(fpath + ftw->base, "iscsi-"))) {
|
|
+
|
|
+ if (dev_count < OFWDEV_MAX) {
|
|
+ ofwdevs[dev_count++] = dev = calloc(sizeof(struct ofw_dev), 1);
|
|
+ dev->prop_path = strdup(fpath + devtree_len);
|
|
+ }
|
|
+ }
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+int loop_devs(void)
|
|
+{
|
|
+ int error;
|
|
+ int i;
|
|
+ char prefix[256];
|
|
+
|
|
+ error = nftw(devtree, find_nics, 20, 0);
|
|
+ if (error)
|
|
+ return error;
|
|
+
|
|
+ snprintf(prefix, sizeof(prefix), "%s/%s", devtree, "aliases");
|
|
+ error = nftw(prefix, find_initiator, 20, 0);
|
|
+ if (error)
|
|
+ return error;
|
|
+
|
|
+ for (i = 0; i < dev_count; i++) {
|
|
+ snprintf(prefix, sizeof(prefix), "%s%s", devtree, ofwdevs[i]->prop_path);
|
|
+ if (find_file(prefix)) {
|
|
+ error = parse_params(bootpath_val, ofwdevs[i]);
|
|
+ if (!error)
|
|
+ error = locate_mac(devtree, ofwdevs[i]);
|
|
+
|
|
+ if (!error) {
|
|
+ snprintf(prefix, sizeof(prefix), "%s%d:", INITIATOR, i);
|
|
+ print_initiator(prefix, ofwdevs[i]);
|
|
+ snprintf(prefix, sizeof(prefix), "%s%d:", NETWORK, i);
|
|
+ print_nic(prefix, ofwdevs[i]);
|
|
+ snprintf(prefix, sizeof(prefix), "%s%d:", TARGET, i);
|
|
+ print_target(prefix, ofwdevs[i]);
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ if (!error)
|
|
+ putchar('\n');
|
|
+ return error;
|
|
+}
|
|
+
|
|
+int
|
|
+main(int argc, char **argv)
|
|
+{
|
|
+ int error, option;
|
|
+ char *prefix;
|
|
+
|
|
+
|
|
+ progname = argv[0];
|
|
+
|
|
+ /*
|
|
+ * For powerpc, our operations are fundamentally different.
|
|
+ *
|
|
+ * Where the x86 method searches memory, we look in the
|
|
+ * device-tree to obtain the data.
|
|
+ *
|
|
+ */
|
|
+ while (1) {
|
|
+ option = getopt(argc, argv, "be:f:hm:s:e:v");
|
|
+ if (option == -1)
|
|
+ break;
|
|
+ switch (option) {
|
|
+ case 'b':
|
|
+ boot_selected_only = 1;
|
|
+ break;
|
|
+ case 'e':
|
|
+ break;
|
|
+ case 'f':
|
|
+ filename = optarg;
|
|
+ break;
|
|
+ case 's':
|
|
+ break;
|
|
+ case 'v':
|
|
+ debug++;
|
|
+ break;
|
|
+ default:
|
|
+ fprintf(stderr, "Unknown or bad option '%c'\n", option);
|
|
+ case 'h':
|
|
+ printf("Usage: %s OPTIONS\n"
|
|
+ "-b print only fw boot selected sections\n"
|
|
+ "-f file_to_search (default %s)\n"
|
|
+ "-s (x86 only) offset to start search\n"
|
|
+ "-e (x86 only) length of search\n"
|
|
+ "-v verbose\n",
|
|
+ progname, default_file_name);
|
|
+ exit(1);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if (debug)
|
|
+ fprintf(stderr, "%s: file:%s; debug:%d\n", progname, filename, debug);
|
|
+
|
|
+ devtree = find_devtree(filename);
|
|
+ if (!devtree)
|
|
+ exit(2);
|
|
+
|
|
+
|
|
+ if (boot_selected_only) {
|
|
+ dev_count = find_file(filename);
|
|
+ if (dev_count < 1)
|
|
+ error = 3;
|
|
+ else {
|
|
+ if (debug)
|
|
+ printf("%s:\n%s\n\n", filename, bootpath_val);
|
|
+ /*
|
|
+ * We find *almost* everything we need in the
|
|
+ * bootpath, save the mac-address.
|
|
+ */
|
|
+
|
|
+ if (strstr(bootpath_val, "iscsi")) {
|
|
+ ofwdevs[0] = malloc(sizeof(struct ofw_dev));
|
|
+ if (!ofwdevs[0])
|
|
+ exit(ENOMEM);
|
|
+
|
|
+ error = parse_params(bootpath_val, ofwdevs[0]);
|
|
+ if (!error)
|
|
+ error = locate_mac(devtree, ofwdevs[0]);
|
|
+
|
|
+ }
|
|
+ else
|
|
+ /* yikes! we did not boot from iscsi. tsk, tsk. */
|
|
+ error = 1;
|
|
+
|
|
+ if (!error) {
|
|
+ prefix = "iSCSI_INITIATOR_";
|
|
+ print_initiator(prefix, ofwdevs[0]);
|
|
+ print_nic(prefix, ofwdevs[0]);
|
|
+ prefix = "iSCSI_TARGET_";
|
|
+ print_target(prefix, ofwdevs[0]);
|
|
+ putchar('\n');
|
|
+ }
|
|
+ }
|
|
+
|
|
+ }
|
|
+ else {
|
|
+ /*
|
|
+ * As we were *not* called with the -b flag, locate
|
|
+ * and loop over all the device-tree iscsi-toe and ethernet
|
|
+ * entries.
|
|
+ *
|
|
+ *
|
|
+ */
|
|
+ error = loop_devs();
|
|
+ }
|
|
+
|
|
+ if (debug)
|
|
+ dump_obp_params(ofwdevs, dev_count);
|
|
+
|
|
+
|
|
+ exit(error);
|
|
+}
|
|
diff --git a/utils/fwparam_ibft/iscsi_obp.h b/utils/fwparam_ibft/iscsi_obp.h
|
|
new file mode 100644
|
|
index 0000000..2f9c6b9
|
|
--- /dev/null
|
|
+++ b/utils/fwparam_ibft/iscsi_obp.h
|
|
@@ -0,0 +1,101 @@
|
|
+/*
|
|
+ * 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, write to the Free Software
|
|
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
|
+ *
|
|
+ * Copyright (C) IBM Corporation. 2007
|
|
+ * Author: Doug Maxey <dwm@austin.ibm.com>
|
|
+ *
|
|
+ */
|
|
+
|
|
+#ifndef ISCSI_OBP_H_
|
|
+#define ISCSI_OBP_H_
|
|
+
|
|
+enum ofw_dev_type {
|
|
+ OFW_DT_NONE,
|
|
+ OFW_DT_BLOCK,
|
|
+ OFW_DT_NETWORK,
|
|
+ OFW_DT_ISCSI,
|
|
+};
|
|
+
|
|
+enum obp_tftp_qual {
|
|
+ OBP_QUAL_NONE,
|
|
+ OBP_QUAL_BOOTP,
|
|
+ OBP_QUAL_IPV6,
|
|
+ OBP_QUAL_ISCSI,
|
|
+ OBP_QUAL_PING,
|
|
+ OBP_QUAL_COUNT, /* Numnber of defined OBP qualifiers */
|
|
+};
|
|
+
|
|
+enum obp_param {
|
|
+ /*
|
|
+ * Defined iscsi boot parameters.
|
|
+ */
|
|
+ OBP_PARAM_NONE,
|
|
+ OBP_PARAM_BLKSIZE, /* default is 512 */
|
|
+ OBP_PARAM_BOOTP_RETRIES, /* default 5 */
|
|
+ OBP_PARAM_CHAPID, /* target chap id */
|
|
+ OBP_PARAM_CHAPPW, /* target chap password */
|
|
+ OBP_PARAM_CIADDR, /* client (my) ip addr */
|
|
+ OBP_PARAM_DHCP, /* dhcp server address */
|
|
+ OBP_PARAM_FILENAME, /* boot filename */
|
|
+ OBP_PARAM_GIADDR, /* gateway addr */
|
|
+ OBP_PARAM_ICHAPID, /* initiator chapid */
|
|
+ OBP_PARAM_ICHAPPW, /* initiator chap password */
|
|
+ OBP_PARAM_ILUN, /* misnomer, really the target lun */
|
|
+ OBP_PARAM_INAME, /* initiator iqn */
|
|
+ OBP_PARAM_IPORT, /* initiator port, defaults to 3260 */
|
|
+ OBP_PARAM_ISID, /* session id */
|
|
+ OBP_PARAM_ISNS, /* sns server address */
|
|
+ OBP_PARAM_ITNAME, /* target iqn */
|
|
+ OBP_PARAM_SIADDR, /* iscsi server ip address. */
|
|
+ OBP_PARAM_SLP, /* slp server address */
|
|
+ OBP_PARAM_SUBNET_MASK,
|
|
+ OBP_PARAM_TFTP_RETRIES, /* default 5 */
|
|
+ OBP_PARAM_TIMEOUT, /* ping timeout period. */
|
|
+
|
|
+ OBP_PARAM_COUNT, /* number of defined OBP_PARAMs */
|
|
+};
|
|
+
|
|
+struct ofw_obp_param {
|
|
+ unsigned char len; /* length of value string. */
|
|
+ char val[1]; /* string value from the property */
|
|
+};
|
|
+
|
|
+struct ofw_dev {
|
|
+ char *prop_path; /* where we found these properties. */
|
|
+ enum ofw_dev_type type; /* known type of boot device. */
|
|
+ int qual_count; /* count of qualifiers. */
|
|
+ enum obp_tftp_qual quals[OBP_QUAL_COUNT];
|
|
+ struct ofw_obp_param *param[OBP_PARAM_COUNT];
|
|
+ int cfg_part; /* boot partition number. */
|
|
+ char *dev_path; /* path to this ofw device. */
|
|
+ unsigned char mac[6]; /* The binary mac address. */
|
|
+};
|
|
+
|
|
+#define OFW_DEV_INIT { \
|
|
+ .prop_path = NULL, \
|
|
+ .type = OFW_DT_NONE, \
|
|
+ .param = {0}, \
|
|
+ .dev_path = NULL, \
|
|
+ .cfg_part = -1 \
|
|
+ }
|
|
+
|
|
+const char *obp_qual_set(struct ofw_dev *ofwdev, const char *qual);
|
|
+void add_obp_parm(struct ofw_dev *ofwdev, enum obp_param parm, const char *str);
|
|
+void obp_parm_addr(struct ofw_dev *ofwdev, const char *parm, const char *addr);
|
|
+void obp_parm_iqn(struct ofw_dev *ofwdev, const char *parm, const char *iqn);
|
|
+void obp_parm_hexnum(struct ofw_dev *ofwdev, const char *parm, const char *numstr);
|
|
+void obp_parm_str(struct ofw_dev *ofwdev, const char *parm, const char *str);
|
|
+
|
|
+#endif /* ISCSI_OBP_H_ */
|
|
diff --git a/utils/fwparam_ibft/prom_lex.l b/utils/fwparam_ibft/prom_lex.l
|
|
new file mode 100644
|
|
index 0000000..3e17d98
|
|
--- /dev/null
|
|
+++ b/utils/fwparam_ibft/prom_lex.l
|
|
@@ -0,0 +1,93 @@
|
|
+/*
|
|
+ * Copyright (c) 2006 IBM Corporation.
|
|
+ * Doug Maxey <dwm@austin.ibm.com>
|
|
+ *
|
|
+ * 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, write to the Free Software
|
|
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
+ */
|
|
+
|
|
+/* definitions */
|
|
+%option array
|
|
+
|
|
+%{
|
|
+#include "prom_parse.h"
|
|
+
|
|
+#undef LEXDEBUG
|
|
+#ifdef LEXDEBUG
|
|
+#define dbg(a) dbgprint((a))
|
|
+#else
|
|
+#define dbg(a) do {} while (0)
|
|
+#endif /* LEXDEBUG */
|
|
+
|
|
+#define upval(d) \
|
|
+ dbg(#d); \
|
|
+ yylval.str[0] = 0; \
|
|
+ strcat(yylval.str, yytext); \
|
|
+ yylloc.first_column = yylloc.last_column; \
|
|
+ yylloc.last_column += yyleng; \
|
|
+ return d
|
|
+
|
|
+void dbgprint(const char *item) { fprintf(stderr, "%s: \"%s\" len=%d ", item, yytext, yyleng);}
|
|
+char *strcat(char *dest, const char *src);
|
|
+
|
|
+%}
|
|
+
|
|
+%option noyywrap
|
|
+%option never-interactive
|
|
+
|
|
+VDEVICE vdevice
|
|
+VDEVINST gscsi
|
|
+VDEVDEV dev
|
|
+VDEVRAW rawio
|
|
+ /* CHOSEN uses only boot related paths. */
|
|
+CHOSEN bootpath|bootargs|iscsi-bootargs|nas-bootdevice
|
|
+BUSNAME ata|i2c|ide|pci|sata|scsi|usb
|
|
+BOOTDEV cdrom|disk|ethernet|iscsi-(disk[0-9]|toe)|sd
|
|
+HEX4 [[:xdigit:]]{1,4}
|
|
+HEX16 [[:xdigit:]]{5,16}
|
|
+IPV4 [0-9]{1,3}(\.[0-9]{1,3}){3}
|
|
+IQN iqn\.[-[:alnum:]:.]{1,219}
|
|
+OBPQUAL bootp|ipv6|iscsi
|
|
+OBPPARM blksize|bootp-retries|chapid|chappw|ciaddr|dhcp|filename|giaddr|ichapid|ichappw|ilun|iname|iport|isid|isns|itname|siaddr|slp|subnet-mask|tftp-retries
|
|
+FILENAME \\[-[:alnum:]\\\.]{1,}
|
|
+
|
|
+%% /* rules */
|
|
+
|
|
+{CHOSEN} { upval(CHOSEN); }
|
|
+{VDEVICE} { upval(VDEVICE); }
|
|
+{VDEVINST} { upval(VDEVINST); }
|
|
+{VDEVDEV} { upval(VDEVDEV); }
|
|
+{VDEVRAW} { upval(VDEVRAW); }
|
|
+{OBPQUAL} { upval(OBPQUAL); }
|
|
+{BUSNAME} { upval(BUSNAME); }
|
|
+{IPV4} { upval(IPV4); }
|
|
+{IQN} { upval(IQN); }
|
|
+{BOOTDEV} { upval(BOOTDEV); }
|
|
+{OBPPARM} { upval(OBPPARM); }
|
|
+{HEX4} { upval(HEX4); }
|
|
+{HEX16} { upval(HEX16); }
|
|
+{FILENAME} { upval(FILENAME); }
|
|
+[ \t\n]+ { /* eat all whitespace. */
|
|
+ yylloc.first_column = yylloc.last_column;
|
|
+ yylloc.last_column += yyleng;
|
|
+}
|
|
+. { /* any other single char. */
|
|
+ dbg("??");
|
|
+ yylloc.first_column = yylloc.last_column;
|
|
+ yylloc.last_column += yyleng;
|
|
+ return *yytext;
|
|
+}
|
|
+
|
|
+<<EOF>> yyterminate();
|
|
+%% /* user code */
|
|
diff --git a/utils/fwparam_ibft/prom_parse.h b/utils/fwparam_ibft/prom_parse.h
|
|
new file mode 100644
|
|
index 0000000..d1145c9
|
|
--- /dev/null
|
|
+++ b/utils/fwparam_ibft/prom_parse.h
|
|
@@ -0,0 +1,41 @@
|
|
+/*
|
|
+ * 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, write to the Free Software
|
|
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
|
+ *
|
|
+ * Copyright (C) IBM Corporation. 2007
|
|
+ * Author: Doug Maxey <dwm@austin.ibm.com>
|
|
+ *
|
|
+ */
|
|
+
|
|
+#ifndef PROM_PARSE_H_
|
|
+#define PROM_PARSE_H_
|
|
+
|
|
+#include <stdlib.h>
|
|
+#include <string.h>
|
|
+#include "iscsi_obp.h"
|
|
+
|
|
+struct ofw_dev;
|
|
+void yyerror(struct ofw_dev *ofwdev, const char *msg);
|
|
+extern int yyleng;
|
|
+extern int yydebug;
|
|
+#include <stdio.h>
|
|
+extern FILE *yyin;
|
|
+extern char yytext[];
|
|
+int yylex(void);
|
|
+
|
|
+#define YY_NO_UNPUT 1 /* match this with %option never-interactive. */
|
|
+#include "prom_parse.tab.h"
|
|
+
|
|
+
|
|
+#endif /* PROM_PARSE_H_ */
|
|
diff --git a/utils/fwparam_ibft/prom_parse.y b/utils/fwparam_ibft/prom_parse.y
|
|
new file mode 100644
|
|
index 0000000..000198c
|
|
--- /dev/null
|
|
+++ b/utils/fwparam_ibft/prom_parse.y
|
|
@@ -0,0 +1,258 @@
|
|
+/*
|
|
+ * 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, write to the Free Software
|
|
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
|
+ *
|
|
+ * Copyright (C) IBM Corporation. 2007
|
|
+ * Author: Doug Maxey <dwm@austin.ibm.com>
|
|
+ *
|
|
+ */
|
|
+/* - DEFINITION section. */
|
|
+
|
|
+%{
|
|
+ /* literal block. include lines, decls, defns. */
|
|
+//#define YYDEBUG 1
|
|
+#if YYDEBUG
|
|
+#define DPRINT(fmt,...) printf(fmt,__VA_ARGS__)
|
|
+#else
|
|
+#define DPRINT(fmt,...) do {} while(0)
|
|
+#endif
|
|
+#include "prom_parse.h"
|
|
+#include "iscsi_obp.h"
|
|
+
|
|
+%}
|
|
+%union {
|
|
+ char str[256];
|
|
+}
|
|
+
|
|
+/* definitions. */
|
|
+%token <str> BUSNAME BOOTDEV
|
|
+%token <str> IPV4 IQN
|
|
+%token <str> OBPPARM OBPQUAL
|
|
+%token <str> HEX4 HEX16
|
|
+%token <str> VDEVICE VDEVINST VDEVDEV VDEVRAW
|
|
+%token <str> CHOSEN
|
|
+%token <str> FILENAME
|
|
+
|
|
+%type <str> devpath busses bus bootdev
|
|
+%type <str> disklabel diskpart
|
|
+%type <str> vdevice vdev_parms vdev_parm
|
|
+%type <str> obp_quals obp_qual obp_params obp_param
|
|
+%type <str> ipaddr ipv4 ipv6
|
|
+%type <str> hexpart hexseq
|
|
+
|
|
+%locations
|
|
+%parse-param {struct ofw_dev *ofwdev}
|
|
+
|
|
+%%
|
|
+
|
|
+devpath: '/' {
|
|
+ DPRINT("****rootonly: \"%s\"\n", "/");
|
|
+ }
|
|
+ | '/' busses bootdev {
|
|
+ DPRINT("****devpath busses:\n/%s/%s\n", $2, $3);
|
|
+ }
|
|
+ | '/' busses bootdev disklabel {
|
|
+ ofwdev->dev_path = malloc(strlen($<str>2) + strlen($<str>3) + 3);
|
|
+ sprintf(ofwdev->dev_path, "/%s/%s", $<str>2, $<str>3);
|
|
+ DPRINT("****devpath busses bootdev disklabel:\n/%s/%s%s\n", $2, $3, $4);
|
|
+ }
|
|
+ | '/' busses bootdev obp_quals obp_params {
|
|
+ ofwdev->dev_path = malloc(strlen($<str>2) + strlen($<str>3) + 3);
|
|
+ sprintf(ofwdev->dev_path, "/%s/%s", $<str>2, $<str>3);
|
|
+ DPRINT("****busses bootdev obp_quals obp_parms:\n/%s/%s:%s%s\n", $2, $3, $4, $5);
|
|
+ }
|
|
+ | '/' busses bootdev obp_quals obp_params disklabel {
|
|
+ ofwdev->dev_path = malloc(strlen($<str>2) + strlen($<str>3) + 3);
|
|
+ sprintf(ofwdev->dev_path, "/%s/%s", $<str>2, $<str>3);
|
|
+ DPRINT("****busses bootdev obp_quals obp_parms disklabel:\n/%s:%s%s%s\n", $2, $4, $5, $6);
|
|
+ }
|
|
+ | '/' vdevice bootdev vdev_parms obp_quals obp_params disklabel {
|
|
+ DPRINT("****vdevice bootdev obp_parms disklabel:\n/%s:%s%s%s%s\n", $2, $4, $5, $6, $7);
|
|
+ }
|
|
+ ;
|
|
+
|
|
+busses: bus {
|
|
+ strcpy($$, $1);
|
|
+ }
|
|
+ | busses '/' bus {
|
|
+ sprintf($$, "%s/%s", $<str>1, $<str>3);
|
|
+ }
|
|
+ ;
|
|
+
|
|
+bus: BUSNAME {
|
|
+ strcpy($$, $1);
|
|
+ }
|
|
+ | BUSNAME '@' HEX4 {
|
|
+ sprintf($$, "%s@%s", $<str>1, $<str>3);
|
|
+ }
|
|
+ | BUSNAME '@' HEX4 ',' HEX4 {
|
|
+ sprintf($$, "%s@%s,%s", $<str>1, $<str>3, $<str>5);
|
|
+ }
|
|
+ | BUSNAME '@' HEX16 {
|
|
+ sprintf($$, "%s@%s", $<str>1, $<str>3);
|
|
+ }
|
|
+ | BUSNAME ',' HEX4 '@' HEX16 {
|
|
+ sprintf($$, "%s,%s@%s", $<str>1, $<str>3, $<str>5);
|
|
+ }
|
|
+ ;
|
|
+
|
|
+
|
|
+bootdev: '/' BOOTDEV ':' {
|
|
+ sprintf($$, "/%s", $<str>2);
|
|
+ }
|
|
+ | '/' BOOTDEV '@' HEX4 ':' {
|
|
+ sprintf($$, "/%s@%s", $<str>2, $<str>4);
|
|
+ }
|
|
+ | '/' BOOTDEV '@' HEX4 ',' HEX4 ':' {
|
|
+ sprintf($$, "/%s@%s,%s", $<str>2, $<str>4, $<str>6);
|
|
+ }
|
|
+ ;
|
|
+
|
|
+vdevice: VDEVICE '/' VDEVINST {
|
|
+ sprintf($$, "%s/%s", $<str>1, $<str>3);
|
|
+ }
|
|
+ ;
|
|
+
|
|
+vdev_parms: ':' vdev_parm {
|
|
+ sprintf($$, ":%s", $<str>2);
|
|
+ }
|
|
+ | vdev_parms ',' vdev_parm {
|
|
+ sprintf($$, "%s,%s", $<str>1, $<str>3);
|
|
+ }
|
|
+ | vdev_parms ',' VDEVRAW {
|
|
+ sprintf($$, "%s,%s", $<str>1, $<str>3);
|
|
+ }
|
|
+ ;
|
|
+
|
|
+vdev_parm: VDEVDEV '=' CHOSEN {
|
|
+ sprintf($$, "%s=%s", $<str>1, $<str>3);
|
|
+ }
|
|
+ ;
|
|
+
|
|
+obp_params: ',' obp_param {
|
|
+ sprintf($$, ",%s", $2);
|
|
+ }
|
|
+ | obp_params ',' obp_param {
|
|
+ sprintf($$, "%s,%s", $<str>1, $<str>3);
|
|
+ }
|
|
+ | obp_params ',' disklabel {
|
|
+ sprintf($$, "%s,%s", $<str>1, $<str>3);
|
|
+ }
|
|
+ ;
|
|
+
|
|
+obp_param: HEX4 {
|
|
+ sprintf($$, "%s", $1);
|
|
+ }
|
|
+ | OBPPARM '=' HEX16 {
|
|
+ /* luns > 0 are the SAM-3+ hex representation. */
|
|
+ obp_parm_hexnum(ofwdev, $<str>1, $<str>3);
|
|
+ sprintf($$, "%s=%s", $<str>1, $<str>3);
|
|
+ }
|
|
+ | OBPPARM '=' ipaddr {
|
|
+ obp_parm_addr(ofwdev, $<str>1, $<str>3);
|
|
+ sprintf($$, "%s=%s", $<str>1, $<str>3);
|
|
+ }
|
|
+ | OBPPARM '=' IQN {
|
|
+ obp_parm_iqn(ofwdev, $<str>1, $<str>3);
|
|
+ sprintf($$, "%s=%s", $<str>1, $<str>3);
|
|
+ }
|
|
+ | OBPPARM '=' HEX4 {
|
|
+ obp_parm_hexnum(ofwdev, $<str>1, $<str>3);
|
|
+ sprintf($$, "%s=%s", $<str>1, $<str>3);
|
|
+ }
|
|
+ | OBPPARM '=' FILENAME {
|
|
+ obp_parm_str(ofwdev, $<str>1, $<str>3);
|
|
+ sprintf($$, "%s=%s", $<str>1, $<str>3);
|
|
+ }
|
|
+ ;
|
|
+
|
|
+obp_quals: obp_qual {
|
|
+ sprintf($$, "%s", $1);
|
|
+ }
|
|
+ | obp_quals ',' obp_qual {
|
|
+ sprintf($$, "%s,%s", $<str>1, $<str>3);
|
|
+ }
|
|
+ ;
|
|
+
|
|
+obp_qual: OBPQUAL {
|
|
+ sprintf($$, "%s", obp_qual_set(ofwdev, $<str>1));
|
|
+ }
|
|
+ | vdev_parm {
|
|
+ sprintf($$, "%s", $<str>1);
|
|
+ }
|
|
+ ;
|
|
+
|
|
+ipaddr: ipv4 {
|
|
+ sprintf($$, "%s", $<str>1);
|
|
+ }
|
|
+ | ipv6 {
|
|
+ sprintf($$, "%s", $<str>1);
|
|
+ }
|
|
+ ;
|
|
+
|
|
+ipv4: IPV4 {
|
|
+ sprintf($$, "%s", $1);
|
|
+ }
|
|
+ ;
|
|
+
|
|
+ipv6: hexpart {
|
|
+ sprintf($$, "%s", $1);
|
|
+ }
|
|
+ | hexpart ':' ipv4 {
|
|
+ sprintf($$, "%s:%s", $1, $3);
|
|
+ }
|
|
+ ;
|
|
+
|
|
+hexpart: hexseq {
|
|
+ sprintf($$, "%s", $1);
|
|
+ }
|
|
+ | hexpart "::" {
|
|
+ sprintf($$, "%s::", $<str>1);
|
|
+ }
|
|
+ | hexpart "::" hexseq {
|
|
+ sprintf($$, "%s::%s", $<str>1, $<str>3);
|
|
+ }
|
|
+ | "::" hexseq {
|
|
+ sprintf($$, "::%s", $<str>2);
|
|
+ }
|
|
+ ;
|
|
+
|
|
+hexseq: HEX4 {
|
|
+ sprintf($$, "%s", $1);
|
|
+ }
|
|
+ | hexseq ":" HEX4 {
|
|
+ sprintf($$, "%s:%s", $<str>1, $<str>3);
|
|
+ }
|
|
+ ;
|
|
+
|
|
+disklabel: diskpart {
|
|
+ sprintf($$, "%s", $<str>1);
|
|
+ }
|
|
+ | HEX4 diskpart {
|
|
+ sprintf($$, "%s%s", $<str>1, $<str>2);
|
|
+ }
|
|
+ | '@' HEX4 ',' HEX4 diskpart {
|
|
+ sprintf($$, "@%s,%s%s", $<str>2, $<str>4, $<str>5);
|
|
+ }
|
|
+ ;
|
|
+
|
|
+diskpart: ':' HEX4 {
|
|
+ sprintf($$, ":%s", $<str>2);
|
|
+ }
|
|
+ | ':' HEX4 ',' FILENAME {
|
|
+ sprintf($$, ":%s,%s", $<str>2, $<str>4);
|
|
+ }
|
|
+ ;
|
|
+
|
|
+%%
|