[Debootloaders-devel] r164 - in trunk: . powerpc-ibm-utils powerpc-ibm-utils/cmds powerpc-ibm-utils/doc powerpc-ibm-utils/doc/nvram powerpc-ibm-utils/scripts

Aurélien GÉRÔME ag-guest at costa.debian.org
Mon Sep 25 09:08:45 UTC 2006


Author: ag-guest
Date: 2006-09-25 09:08:44 +0000 (Mon, 25 Sep 2006)
New Revision: 164

Added:
   trunk/powerpc-ibm-utils/
   trunk/powerpc-ibm-utils/COPYRIGHT
   trunk/powerpc-ibm-utils/Changelog
   trunk/powerpc-ibm-utils/Makefile
   trunk/powerpc-ibm-utils/README
   trunk/powerpc-ibm-utils/cmds/
   trunk/powerpc-ibm-utils/cmds/Makefile
   trunk/powerpc-ibm-utils/cmds/nvram.c
   trunk/powerpc-ibm-utils/cmds/nvram.h
   trunk/powerpc-ibm-utils/doc/
   trunk/powerpc-ibm-utils/doc/Makefile
   trunk/powerpc-ibm-utils/doc/bootlist.8
   trunk/powerpc-ibm-utils/doc/nvram/
   trunk/powerpc-ibm-utils/doc/nvram/Makefile
   trunk/powerpc-ibm-utils/doc/nvram/nvram.8
   trunk/powerpc-ibm-utils/doc/nvram/nvram.doxycfg
   trunk/powerpc-ibm-utils/doc/ofpathname.8
   trunk/powerpc-ibm-utils/doc/snap.8
   trunk/powerpc-ibm-utils/powerpc-utils.spec
   trunk/powerpc-ibm-utils/rules.mk
   trunk/powerpc-ibm-utils/scripts/
   trunk/powerpc-ibm-utils/scripts/Makefile
   trunk/powerpc-ibm-utils/scripts/bootlist
   trunk/powerpc-ibm-utils/scripts/ofpathname
   trunk/powerpc-ibm-utils/scripts/snap
Log:
Initial import of upstream tarball.


Added: trunk/powerpc-ibm-utils/COPYRIGHT
===================================================================
--- trunk/powerpc-ibm-utils/COPYRIGHT	                        (rev 0)
+++ trunk/powerpc-ibm-utils/COPYRIGHT	2006-09-25 09:08:44 UTC (rev 164)
@@ -0,0 +1,228 @@
+Common Public License - v 1.0 
+
+
+THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS COMMON
+PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF
+THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. 
+
+
+1. DEFINITIONS 
+
+"Contribution" means: 
+
+a) in the case of the initial Contributor, the initial code and
+documentation distributed under this Agreement, and
+b) in the case of each subsequent Contributor:
+i) changes to the Program, and
+ii) additions to the Program;
+where such changes and/or additions to the Program originate from and are
+distributed by that particular Contributor. A Contribution 'originates'
+from a Contributor if it was added to the Program by such Contributor
+itself or anyone acting on such Contributor's behalf. Contributions do
+not include additions to the Program which: (i) are separate modules of
+software distributed in conjunction with the Program under their own
+license agreement, and (ii) are not derivative works of the Program. 
+
+"Contributor" means any person or entity that distributes the Program. 
+
+
+"Licensed Patents " mean patent claims licensable by a Contributor which
+are necessarily infringed by the use or sale of its Contribution alone or
+when combined with the Program. 
+
+
+"Program" means the Contributions distributed in accordance with this
+Agreement. 
+
+
+"Recipient" means anyone who receives the Program under this Agreement,
+including all Contributors. 
+
+
+2. GRANT OF RIGHTS 
+
+a) Subject to the terms of this Agreement, each Contributor hereby grants
+Recipient a non-exclusive, worldwide, royalty-free copyright license to
+reproduce, prepare derivative works of, publicly display, publicly
+perform, distribute and sublicense the Contribution of such Contributor,
+if any, and such derivative works, in source code and object code form.
+b) Subject to the terms of this Agreement, each Contributor hereby grants
+Recipient a non-exclusive, worldwide, royalty-free patent license under
+Licensed Patents to make, use, sell, offer to sell, import and otherwise
+transfer the Contribution of such Contributor, if any, in source code and
+object code form. This patent license shall apply to the combination of
+the Contribution and the Program if, at the time the Contribution is
+added by the Contributor, such addition of the Contribution causes such
+combination to be covered by the Licensed Patents. The patent license
+shall not apply to any other combinations which include the Contribution.
+No hardware per se is licensed hereunder. 
+c) Recipient understands that although each Contributor grants the
+licenses to its Contributions set forth herein, no assurances are
+provided by any Contributor that the Program does not infringe the patent
+or other intellectual property rights of any other entity. Each
+Contributor disclaims any liability to Recipient for claims brought by
+any other entity based on infringement of intellectual property rights or
+otherwise. As a condition to exercising the rights and licenses granted
+hereunder, each Recipient hereby assumes sole responsibility to secure
+any other intellectual property rights needed, if any. For example, if a
+third party patent license is required to allow Recipient to distribute
+the Program, it is Recipient's responsibility to acquire that license
+before distributing the Program.
+d) Each Contributor represents that to its knowledge it has sufficient
+copyright rights in its Contribution, if any, to grant the copyright
+license set forth in this Agreement. 
+3. REQUIREMENTS 
+
+A Contributor may choose to distribute the Program in object code form
+under its own license agreement, provided that: 
+
+a) it complies with the terms and conditions of this Agreement; and
+b) its license agreement:
+i) effectively disclaims on behalf of all Contributors all warranties and
+conditions, express and implied, including warranties or conditions of
+title and non-infringement, and implied warranties or conditions of
+merchantability and fitness for a particular purpose; 
+ii) effectively excludes on behalf of all Contributors all liability for
+damages, including direct, indirect, special, incidental and
+consequential damages, such as lost profits; 
+iii) states that any provisions which differ from this Agreement are
+offered by that Contributor alone and not by any other party; and
+iv) states that source code for the Program is available from such
+Contributor, and informs licensees how to obtain it in a reasonable
+manner on or through a medium customarily used for software exchange. 
+When the Program is made available in source code form: 
+
+a) it must be made available under this Agreement; and 
+b) a copy of this Agreement must be included with each copy of the
+Program. 
+
+Contributors may not remove or alter any copyright notices contained
+within the Program. 
+
+
+Each Contributor must identify itself as the originator of its
+Contribution, if any, in a manner that reasonably allows subsequent
+Recipients to identify the originator of the Contribution. 
+
+
+4. COMMERCIAL DISTRIBUTION 
+
+Commercial distributors of software may accept certain responsibilities
+with respect to end users, business partners and the like. While this
+license is intended to facilitate the commercial use of the Program, the
+Contributor who includes the Program in a commercial product offering
+should do so in a manner which does not create potential liability for
+other Contributors. Therefore, if a Contributor includes the Program in a
+commercial product offering, such Contributor ("Commercial Contributor")
+hereby agrees to defend and indemnify every other Contributor
+("Indemnified Contributor") against any losses, damages and costs
+(collectively "Losses") arising from claims, lawsuits and other legal
+actions brought by a third party against the Indemnified Contributor to
+the extent caused by the acts or omissions of such Commercial Contributor
+in connection with its distribution of the Program in a commercial
+product offering. The obligations in this section do not apply to any
+claims or Losses relating to any actual or alleged intellectual property
+infringement. In order to qualify, an Indemnified Contributor must: a)
+promptly notify the Commercial Contributor in writing of such claim, and
+b) allow the Commercial Contributor to control, and cooperate with the
+Commercial Contributor in, the defense and any related settlement
+negotiations. The Indemnified Contributor may participate in any such
+claim at its own expense. 
+
+
+For example, a Contributor might include the Program in a commercial
+product offering, Product X. That Contributor is then a Commercial
+Contributor. If that Commercial Contributor then makes performance
+claims, or offers warranties related to Product X, those performance
+claims and warranties are such Commercial Contributor's responsibility
+alone. Under this section, the Commercial Contributor would have to
+defend claims against the other Contributors related to those performance
+claims and warranties, and if a court requires any other Contributor to
+pay any damages as a result, the Commercial Contributor must pay those
+damages. 
+
+
+5. NO WARRANTY 
+
+EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED
+ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER
+EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR
+CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A
+PARTICULAR PURPOSE. Each Recipient is solely responsible for determining
+the appropriateness of using and distributing the Program and assumes all
+risks associated with its exercise of rights under this Agreement,
+including but not limited to the risks and costs of program errors,
+compliance with applicable laws, damage to or loss of data, programs or
+equipment, and unavailability or interruption of operations. 
+
+
+6. DISCLAIMER OF LIABILITY 
+
+EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR
+ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING
+WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR
+DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
+HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 
+
+
+7. GENERAL 
+
+If any provision of this Agreement is invalid or unenforceable under
+applicable law, it shall not affect the validity or enforceability of the
+remainder of the terms of this Agreement, and without further action by
+the parties hereto, such provision shall be reformed to the minimum
+extent necessary to make such provision valid and enforceable. 
+
+
+If Recipient institutes patent litigation against a Contributor with
+respect to a patent applicable to software (including a cross-claim or
+counterclaim in a lawsuit), then any patent licenses granted by that
+Contributor to such Recipient under this Agreement shall terminate as of
+the date such litigation is filed. In addition, if Recipient institutes
+patent litigation against any entity (including a cross-claim or
+counterclaim in a lawsuit) alleging that the Program itself (excluding
+combinations of the Program with other software or hardware) infringes
+such Recipient's patent(s), then such Recipient's rights granted under
+Section 2(b) shall terminate as of the date such litigation is filed. 
+
+
+All Recipient's rights under this Agreement shall terminate if it fails
+to comply with any of the material terms or conditions of this Agreement
+and does not cure such failure in a reasonable period of time after
+becoming aware of such noncompliance. If all Recipient's rights under
+this Agreement terminate, Recipient agrees to cease use and distribution
+of the Program as soon as reasonably practicable. However, Recipient's
+obligations under this Agreement and any licenses granted by Recipient
+relating to the Program shall continue and survive. 
+
+
+Everyone is permitted to copy and distribute copies of this Agreement,
+but in order to avoid inconsistency the Agreement is copyrighted and may
+only be modified in the following manner. The Agreement Steward reserves
+the right to publish new versions (including revisions) of this Agreement
+from time to time. No one other than the Agreement Steward has the right
+to modify this Agreement. IBM is the initial Agreement Steward. IBM may
+assign the responsibility to serve as the Agreement Steward to a suitable
+separate entity. Each new version of the Agreement will be given a
+distinguishing version number. The Program (including Contributions) may
+always be distributed subject to the version of the Agreement under which
+it was received. In addition, after a new version of the Agreement is
+published, Contributor may elect to distribute the Program (including its
+Contributions) under the new version. Except as expressly stated in
+Sections 2(a) and 2(b) above, Recipient receives no rights or licenses to
+the intellectual property of any Contributor under this Agreement,
+whether expressly, by implication, estoppel or otherwise. All rights in
+the Program not expressly granted under this Agreement are reserved. 
+
+
+This Agreement is governed by the laws of the State of New York and the
+intellectual property laws of the United States of America. No party to
+this Agreement will bring a legal action under this Agreement more than
+one year after the cause of action arose. Each party waives its rights to
+a jury trial in any resulting litigation. 
+
+
+

Added: trunk/powerpc-ibm-utils/Changelog
===================================================================
--- trunk/powerpc-ibm-utils/Changelog	                        (rev 0)
+++ trunk/powerpc-ibm-utils/Changelog	2006-09-25 09:08:44 UTC (rev 164)
@@ -0,0 +1,20 @@
+Changelog for powerpc-utils-1.0.2
+=======================================
+    - Updated bootlist so that eth devices don't require any options
+
+Changelog for powerpc-utils-1.0.1
+=======================================
+    - ofpathanme: Updated the virtual disk number calculation for scsi 
+      devices.
+
+Changelog for powerpc-utils-1.0.0
+=======================================
+    - Added devball target for builds.
+
+Changelog for powerpc-utils-0.0.1
+=======================================
+    - Initial creation of powerpc-utils package.
+    - nvram command now defaults to the "common" partition.
+    - Corrected the parsing of optional ethernet args to the
+      bootlist command.
+

Added: trunk/powerpc-ibm-utils/Makefile
===================================================================
--- trunk/powerpc-ibm-utils/Makefile	                        (rev 0)
+++ trunk/powerpc-ibm-utils/Makefile	2006-09-25 09:08:44 UTC (rev 164)
@@ -0,0 +1,49 @@
+#
+# Makefile for powerpc-utils
+# 
+
+include rules.mk
+
+.SILENT:
+
+FILES = README COPYRIGHT
+SUBDIRS = cmds scripts doc
+
+TARBALL_FILES += $(FILES) Changelog
+
+all:
+	@echo "Building cmds files..."
+	@$(MAKE) -C cmds
+	@echo "Building scripts files..."
+	@$(MAKE) -C scripts
+	@echo "Building doc files..."
+	@$(MAKE) -C doc
+
+install: all
+	@$(call install_doc,$(FILES),$(DESTDIR))
+	@$(foreach d,$(SUBDIRS), $(MAKE) -C $d install;)
+
+uninstall: 
+	@$(call uninstall_doc,$(FILES),$(DESTDIR))
+	@$(foreach d,$(SUBDIRS), $(MAKE) -C $d uninstall;)
+
+rpm: all
+	@echo "Creating rpm..."
+	@export DESTDIR=$(SHIPDIR); $(MAKE) install
+	@$(RPM) -bb -v $(SPECFILE)
+	@rm -rf $(SHIPDIR)
+
+docs:
+	@$(MAKE) -C doc docs
+
+tarball: clean
+	@echo "Creating release tarball..."
+	@$(BUILD_TARBALL)
+
+devball: clean
+	@echo "Creating snapshot tarball..."
+	@$(BUILD_DEVBALL)
+
+clean:
+	@$(foreach d,$(SUBDIRS), $(MAKE) -C $d clean;)
+	@$(CLEAN) -rf $(SHIPDIR) $(TARBALL) $(DEVBALL) *~

Added: trunk/powerpc-ibm-utils/README
===================================================================
--- trunk/powerpc-ibm-utils/README	                        (rev 0)
+++ trunk/powerpc-ibm-utils/README	2006-09-25 09:08:44 UTC (rev 164)
@@ -0,0 +1,33 @@
+powerpc-utils package
+===================
+
+This package contains utilities intended for maintenance of powerpc platforms.
+All of these utilities must be run as root.
+
+Further documentation for each of these utilities is available in their
+corresponding man pages.
+
+snap:  system configuration snapshot
+----
+A script to gather significant system configuration information.  The
+script creates snap.tar.gz in the working directory; the contents of
+this file can be used for problem determination by servicers of the
+system.
+
+nvram:  NVRAM access utility
+-----
+A utility to view and format the contents of the system's non-volatile
+RAM, which contains configuration variables for Open Firmware and the
+system's Service Processor (if any), as well as error records and Vital
+Product Data (VPD).
+
+bootlist:  boot configuration utility
+--------
+A script to view and set the list of devices with which the system will
+attempt to boot.  Both the "normal" and "service" mode lists can be
+manipulated.
+
+ofpathname:  translate logical device names to OF names
+----------
+Used by bootlist to convert between Linux logical device names and Open
+Firmware names.

Added: trunk/powerpc-ibm-utils/cmds/Makefile
===================================================================
--- trunk/powerpc-ibm-utils/cmds/Makefile	                        (rev 0)
+++ trunk/powerpc-ibm-utils/cmds/Makefile	2006-09-25 09:08:44 UTC (rev 164)
@@ -0,0 +1,23 @@
+#
+# Makefile for powerpc-utils/cmds
+#
+
+include ../rules.mk
+
+CMDS = nvram 
+
+all: $(CMDS)
+
+nvram: nvram.o
+	@echo "LD $(WORK_DIR)/$@"
+	@$(CC) -o $@ $^ -ldl
+
+install: all
+	@$(call install_sbin,$(CMDS),$(DESTDIR))
+
+uninstall:
+	@$(call uninstall_sbin,$(CMDS),$(DESTDIR))
+
+clean:
+	@echo "Cleaning up $(WORK_DIR) files..."
+	@rm -f $(CMDS) *.o *~

Added: trunk/powerpc-ibm-utils/cmds/nvram.c
===================================================================
--- trunk/powerpc-ibm-utils/cmds/nvram.c	                        (rev 0)
+++ trunk/powerpc-ibm-utils/cmds/nvram.c	2006-09-25 09:08:44 UTC (rev 164)
@@ -0,0 +1,1649 @@
+/**
+ * @file nvram.c
+ * @brief nvram access utility for powerpc platforms.
+ */
+/**
+ * @mainpage nvram documentation
+ * @section Copyright
+ * Copyright (c) 2003, 2004, 2005 International Business Machines
+ * Common Public License Version 1.0 (see COPYRIGHT)
+ *
+ * @section Overview
+ * The nvram command is used to print and modify data stored in the 
+ * non-volatile RAM (NVRAM) on powerpc systems.  NVRAM on powerpc systems 
+ * is split into several partitions, each with their own format.  
+ *
+ * The print options allow you to view the available partitions in NVRAM
+ * and print their contents.
+ *
+ * The update options allow you to update certain partitions of NVRAM, 
+ * namely those containing name=value pairs.  On many systems, the 
+ * following NVRAM partitions contain data formatted as name=value pairs: 
+ * common, of-config, and ibm,setupcfg.
+ *
+ * @author Nathan Fontenot <nfont at austin.ibm.com>
+ * @author Michael Strosaker <strosake at us.ibm.com>
+ * @author Todd Inglett <tinglett at us.ibm.com>
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <ctype.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <time.h>
+#include <stdint.h>
+#include <dlfcn.h>
+#include <netinet/in.h> /* for ntohs */
+#include <glob.h>
+#include <getopt.h>
+
+#include "nvram.h"
+
+/**
+ * @var nvram_cmdname
+ * @brief name used to invoke thre nvram command (argv[0]) 
+ */
+char *nvram_cmdname;
+static int verbose;
+
+static struct option long_options[] = {
+    {"verbose", 		optional_argument, NULL, 'v'},
+    {"print-config",		optional_argument, NULL, 'o'},
+    {"print-vpd", 		optional_argument, NULL, 'V'},
+    {"print-all-vpd", 		optional_argument, NULL, 'W'},
+    {"print-err-log", 		no_argument, 	   NULL, 'e'},
+    {"print-event-scan", 	no_argument, 	   NULL, 'E'},
+    {"partitions", 		no_argument, 	   NULL, 'P'},
+    {"dump", 			required_argument, NULL, 'd'},
+    {"nvram-file", 		required_argument, NULL, 'n'},
+    {"nvram-size", 		required_argument, NULL, 's'},
+    {"update-config",		required_argument, NULL, 'u'},
+    {"help", 			no_argument, 	   NULL, 'h'},
+    {"partition",               required_argument, NULL, 'p'},
+    {0,0,0,0}
+};
+
+/**
+ * help
+ * @brief print the help/usage message for nvram
+ */
+static void 
+help(void)
+{
+    printf("nvram options:\n"
+    "  --print-config[=var]\n"
+    "          print value of a config variable, or print all variables in\n"
+    "          the specified (or all) partitions\n"
+    "  --update-config <var>=<value>\n"
+    "          update the config variable in the specified partition; the -p\n"
+    "          option must also be specified\n"
+    "  -p <partition>\n"
+    "          specify a partition; required with --update-config option,\n"
+    "          optional with --print-config option\n"
+    "  --print-vpd\n"
+    "          print VPD\n"
+    "  --print-all-vpd\n"
+    "          print VPD, including vendor specific data\n"
+    "  --print-err-log\n"
+    "          print checkstop error log\n"
+    "  --print-event-scan\n"
+    "          print event scan log\n"
+    "  --partitions\n"
+    "          print NVRAM paritition header info\n"
+    "  --dump <name>\n"
+    "          raw dump of partition (use --partitions to see names)\n"
+    "  --nvram-file <path>\n"
+    "          specify alternate nvram data file (default is /dev/nvram)\n"
+    "  --nvram-size\n"
+    "          specify size of nvram data (for repair operations)\n"
+    "  --verbose (-v)\n"
+    "          be (more) verbose\n"
+    "  --help\n"
+    "          print what you are reading right now.\n"
+    );
+}
+
+/**
+ * @def ERR_MSG
+ * @brief define to denote error messages
+ */
+#define ERR_MSG		0
+/**
+ * @def WARN_MSG
+ * @brief define to denote warning messages
+ */
+#define WARN_MSG	1
+/**
+ * @def MAXLINE
+ * @brief maximum line length
+ */
+#define MAXLINE		4096
+
+/**
+ * _msg
+ * @brief print a message to stderr with the specified prefix
+ *
+ * @param msg_type either ERR_MSG or WARN_MSG
+ * @param fmt formatted string a la printf()
+ * @param ap initialized varaiable arg list
+ */
+void
+_msg(int msg_type, const char *fmt, va_list ap)
+{
+    int	n;
+    char buf[MAXLINE];
+
+    n = sprintf(buf, "%s: %s", nvram_cmdname, 
+		(msg_type == WARN_MSG ? "WARNING: " : "ERROR: "));
+
+    vsprintf(buf + n, fmt, ap);
+
+    fflush(stderr);
+    fputs(buf, stderr);
+    fflush(NULL);
+}
+
+/**
+ * err_msg
+ * @brief print an error message to stderr
+ *
+ * @param fmt formatted string a la printf()
+ */
+void err_msg(const char *fmt, ...) __attribute__((format(printf, 1, 2)));
+void
+err_msg(const char *fmt, ...)
+{
+    va_list ap;
+    
+    va_start(ap, fmt);
+    _msg(ERR_MSG, fmt, ap);
+    va_end(ap);
+}
+
+/**
+ * warn_msg
+ * @brief print a warning message to stderr
+ *
+ * @param fmt formatted string a la printf()
+ */
+void warn_msg(const char *fmt, ...) __attribute__((format(printf, 1, 2)));
+void
+warn_msg(const char *fmt, ...)
+{
+    va_list ap;
+
+    va_start(ap, fmt);
+    _msg(WARN_MSG, fmt, ap);
+    va_end(ap);
+}
+
+/**
+ * resolve_of_node
+ * @brief resolve an Open Firmware node name
+ *
+ * In a device tree node with a single child, "foo at 0", all of the following
+ * names refer to that child: "foo at 0", "foo", "@0".
+ *
+ * @param parent fully-qualified path to the parent device node
+ * @param node the (possibly abbreviated) name of the child node
+ * @param nodelen length of the node parameter
+ * @param resolved pointer to return resolved node name in
+ * @return 0 if a suitable child can be found, and 'resolved' is a
+ * dynamically-allocated string containing the resolved node name.
+ * Otherwise, -1.
+ */
+static int
+resolve_of_node(const char *parent, const char *node, int nodelen,
+	    char **resolved)
+{
+    static char nodebuf[1024]; /* XXX hardcoded length */
+    struct stat sbuf;
+    glob_t pglob;
+    int rc;
+
+    *resolved = NULL;
+
+    snprintf(nodebuf, sizeof(nodebuf), "%s/%.*s", parent,
+	    nodelen, node);
+    rc = stat(nodebuf, &sbuf);
+    if (rc != -1) {
+	*resolved = malloc(nodelen+2);
+	snprintf(*resolved, nodelen+2, "/%.*s", nodelen, node);
+	goto out;
+    }
+    if (errno != ENOENT)
+	goto out; /* report unusual errors */
+
+    if (node[0] == '@') {
+	/* it's a unit address; glob for *@unitaddr */
+	snprintf(nodebuf, sizeof(nodebuf), "%s/*%.*s*", parent, nodelen, node);
+	rc = glob(nodebuf, 0, NULL, &pglob);
+	if (rc == 0) {
+	    if (pglob.gl_pathc > 1) {
+		err_msg("Ambiguous node name \"%.*s\"\n", nodelen, node);
+		while (pglob.gl_pathc) {
+		    free(pglob.gl_pathv[pglob.gl_pathc]);
+		    pglob.gl_pathc--;
+		}
+		goto out;
+	    }
+
+	    /* skip the leading fully-qualified path */
+	    *resolved = strdup(pglob.gl_pathv[0] + strlen(parent));
+	    free(pglob.gl_pathv[0]);
+	    goto out;
+	}
+    } else {
+	/* must be a node name; glob for node@* */
+	snprintf(nodebuf, sizeof(nodebuf), "%s/%.*s@*", parent, nodelen, node);
+	rc = glob(nodebuf, 0, NULL, &pglob);
+	if (rc == 0) {
+	    if (pglob.gl_pathc > 1) {
+		err_msg("Ambiguous node name \"%.*s\"\n", nodelen, node);
+		while (pglob.gl_pathc) {
+		    free(pglob.gl_pathv[pglob.gl_pathc]);
+		    pglob.gl_pathc--;
+		}
+		goto out;
+	    }
+
+	    /* skip the leading fully-qualified path */
+	    *resolved = strdup(pglob.gl_pathv[0] + strlen(parent));
+	    free(pglob.gl_pathv[0]);
+	    goto out;
+	}
+    }
+
+out:
+    if (*resolved != NULL)
+	return 0;
+    return -1;
+}
+
+/**
+ * open_of_path
+ * @brief open an Open Firmware path under DEVICE_TREE
+ *
+ * @param ofpath the path to open, such as "/pci/@d/mac-io/nvram/#bytes"
+ *
+ * An Open Firmware path may contain "shortcut" node names that are not present
+ * under /proc/device-tree. In the above example, we may need to open
+ * "pci at 80000000" instead of "pci".
+ *
+ * @return file descriptor to the opened node, or -1 on failure
+ */
+static int
+open_of_path(const char *ofpath)
+{
+    static char resolved_ofpath[1024]; /* XXX hardcoded length */
+    const char *node;
+    int fd = -1;
+    int rc = 0;
+
+    strcpy(resolved_ofpath, DEVICE_TREE);
+
+    while (ofpath) {
+	int nodelen;
+	char *resolved_node;
+
+	node = ofpath + 1;
+	ofpath = strchr(node + 1, '/');
+
+	nodelen = ofpath - node;
+	if (ofpath == NULL)
+	    nodelen = strlen(node);
+
+	rc = resolve_of_node(resolved_ofpath, node, nodelen, &resolved_node);
+	if (rc < 0)
+	    break;
+
+	strcat(resolved_ofpath, resolved_node);
+	free(resolved_node);
+    }
+
+    if (rc >= 0)
+	fd = open(resolved_ofpath, O_RDONLY);
+
+    return fd;
+}
+
+/**
+ * get_of_nvram_size
+ * @brief Get the size of nvram from the device tree
+ *
+ * Retrieve the size of nvram as specified by the Open Firmware
+ * device tree.  If this fails we return a default size of
+ * 1024 * 1024.
+ *
+ * @return size of nvram
+ */
+static int 
+get_of_nvram_size(void)
+{
+    char buf[1024] = NVRAM_DEFAULT "/#bytes";
+    int fd;
+    int size, len;
+
+    fd = open(buf, O_RDONLY);
+    if (fd == -1) {
+	/* Check the aliases directory */
+	struct stat sbuf;
+	int offset;
+
+        fd = open(NVRAM_ALIAS, O_RDONLY);
+	if (fd == -1) {
+	    err_msg("%s", "Could not determine nvram size from "
+		    NVRAM_ALIAS "\n");
+	    return DEFAULT_NVRAM_SZ;
+	}
+
+	if (fstat(fd, &sbuf) != 0) {
+	    err_msg("%s", "Could not determine nvram size from "
+		    NVRAM_ALIAS "\n");
+	    close(fd);
+	    return DEFAULT_NVRAM_SZ;
+	}
+
+	offset = read(fd, buf, sbuf.st_size - 1);
+	offset += sprintf(buf + offset, "%s", "/#bytes");
+	buf[offset] = '\0';
+
+	close(fd);
+	fd = open_of_path(buf);
+    }
+
+    if (fd == -1) {
+	warn_msg("cannot open nvram node \"%s\" in device tree: %s\n", buf,
+		strerror(errno));
+	close(fd);
+	return DEFAULT_NVRAM_SZ;
+    }
+    
+    len = read(fd, &size, sizeof(size));
+    close(fd);
+    
+    if (len != sizeof(size)) {
+	perror("got odd size for nvram node in device tree");
+	return DEFAULT_NVRAM_SZ;
+    }
+    
+    return size;
+}
+
+/**
+ * nvram_read
+ * @brief read in the contents of nvram
+ *
+ * @param nvram nvram struct to read data into
+ * @return 0 on success, !0 on failure
+ */
+int 
+nvram_read(struct nvram *nvram)
+{
+    int len, remaining;
+    char *p;
+
+    /* read in small chunks */
+    for (p = nvram->data, remaining = nvram->nbytes;
+           (len = read(nvram->fd, p, 512)) > 0;
+           p += len, remaining -= len) {
+           if (remaining <= 0) {
+               remaining = 0;
+               break;
+           }
+    }
+
+    if (len == -1) {
+        err_msg("cannot read \"%s\": %s\n", nvram->filename, strerror(errno));
+        return -1;
+    }
+   
+    /* If we are using the DEFAULT_NVRAM_SZ value we to do a small bit of
+     * fixup here.  All of the remaining code assumes that nbytes contains
+     * the actual size of nvram, not a guess-timated amount and bad things
+     * ensue if it is not correct.
+     */
+    if (nvram->nbytes == DEFAULT_NVRAM_SZ) {
+	    nvram->nbytes = nvram->nbytes - remaining;
+	    remaining = DEFAULT_NVRAM_SZ - (remaining + nvram->nbytes);
+    }
+
+    if (remaining) {
+	warn_msg("expected %d bytes, but only read %d!\n", 
+	    	 nvram->nbytes, nvram->nbytes - remaining);
+	/* preserve the given nbytes, but zero the rest in case someone cares */
+	memset(p, 0, remaining);
+    }
+
+    if (verbose)
+	printf("NVRAM size %d bytes\n", nvram->nbytes);
+
+    return 0;
+}
+
+/**
+ * checksum
+ * @brief calculate the checksum for a partition header
+ *
+ * @param p pointer to partition header
+ * @return calculated checksum
+ */
+static unsigned char 
+checksum(struct partition_header *p)
+{
+    unsigned int c_sum, c_sum2;
+    unsigned short *sp = (unsigned short *)p->name; /* assume 6 shorts */
+
+    c_sum = p->signature + p->length + sp[0] + sp[1] + sp[2] + sp[3] 
+	    		 + sp[4] + sp[5];
+
+    /* The sum probably may have spilled into the 3rd byte.  Fold it back. */
+    c_sum = ((c_sum & 0xffff) + (c_sum >> 16)) & 0xffff;
+
+    /* The sum cannot exceed 2 bytes.  Fold it into a checksum */
+    c_sum2 = (c_sum >> 8) + (c_sum << 8);
+    c_sum = ((c_sum + c_sum2) >> 8) & 0xff;
+    
+    return c_sum;
+}
+
+/**
+ * dump_raw_data
+ * @brief raw data dump of a partition.
+ * 
+ * Note that data_len must be a multiple of 16 bytes which makes
+ * for a cheap implementation.
+ *
+ * @param data pointer to data to be dumped
+ * @param data_len length of data buffer to be dumped
+ */
+void 
+dump_raw_data(char *data, int data_len)
+{
+    int i, j;
+    int offset = 0;
+    char *h, *a;
+    char *end = data + data_len;
+
+    h = a = data;
+    
+    while (h < end) {
+        printf("0x%08x  ", offset);
+	offset += 16;
+	
+	for (i = 0; i < 4; i++) {
+	    for (j = 0; j < 4; j++) {
+	        if (h <= end)
+	            printf("%02x", *h++);
+		else
+		    printf("  ");
+	    }
+	    printf(" ");
+	}
+	
+	printf("|");
+	
+        for (i = 0; i < 16; i++) {
+	    if (a <= end) {
+	        if ((*a >= ' ') && (*a <= '~'))
+		    printf("%c", *a);
+		else
+		    printf(".");
+		a++;
+	    } else
+	        printf(" ");
+	}
+	printf("|\n");
+    }
+}
+
+/**
+ * parse_of_common
+ * @brief parse a config definition
+ *
+ * Parse an Open Firmware common config definition which
+ * is of the form name=value and return its length.
+ *
+ * Note that the name will always be < 32 chars.  OF does
+ * not specify the max value length, but the value is binary
+ * and must be unquoted.  We assume 4k is enough.
+ *
+ * @param data pointer to start of raw data (NULL terminated)
+ * @param data_len length of remaining raw data
+ * @param outname buffer to write parsed name
+ * @param outval buffer to write parsed output value
+ * @return number of bytes parsed 
+ */
+int 
+parse_of_common(char *data, int data_len, char *outname, char *outval)
+{
+    char *p, *np;
+    char *p_end = data + data_len;
+
+    for (p = data, np = outname; *p && *p != '='; p++) {
+	*np++ = *p;
+	if (np - outname > 32)
+	    break;	/* don't overrun */
+	if (p >= p_end) {
+	    err_msg("partition corrupt:  ran off end parsing name\n");
+	    return 0;
+	}
+    }
+	
+    *np = '\0';
+    if (*p != '=') {
+	err_msg("corrupt data:  no = sign found or name > 31 chars\n");
+	return 0;
+    }
+    p++;
+	
+    /* Value needs to be unquoted */
+    for (np = outval; *p; p++) {
+	if (*p == (char)0xff) {
+	    char ch, num;
+	    p++;
+		
+	    if (p >= p_end) {
+		err_msg("partition corrupt: ran off end parsing "
+                        "quoted value\n");
+		return 0;
+	    }
+			
+	    num = *p & 0x7f;
+	    ch = (*p & 0x80) ? 0xff : 0;	/* hi bit chooses ff or 00. */
+	    if (np + num - outval > 4096)
+		break;	/* don't overrun */
+	
+	    /* repeat char */
+	    while (num > 0) {
+		*np++ = ch;
+		num--;
+	    }
+
+	} 
+        else {
+	    *np++ = *p;
+	    if (np - outval > 4096)
+		break;	/* don't overrun */
+	}
+	    
+	if (p >= p_end) {
+	    err_msg("partition corrupt:  ran off end parsing value\n");
+	    return 0;
+	} 
+    }
+
+    *np = '\0';
+    if (*p) {
+	err_msg("data value too long for this utility (>4k)\n");
+	return 0;
+	/* ToDo: recover */
+    }
+	
+    return p - data;
+}
+
+/**
+ * nvram_parse_partitions
+ * @brief fill in the nvram structure with data from nvram 
+ *
+ * Fill in the partition parts of the struct nvram.
+ * This makes handling partitions easier for the rest of the code.
+ *
+ * The spec says that partitions are made up of 16 byte blocks and
+ * the partition header must be 16 bytes.  We verify that here.
+ *
+ * @param nvram pointer to nvram struct to fill out
+ * @return 0 on success, !0 otherwise
+ */
+static int
+nvram_parse_partitions(struct nvram *nvram)
+{
+    char *nvram_end = nvram->data + nvram->nbytes;
+    char *p_start = nvram->data; 
+    struct partition_header *phead;
+    unsigned char c_sum;
+
+    if (sizeof(struct partition_header) != 16) {
+	err_msg("partition_header struct is not 16 bytes\n");
+	return -1;
+    }
+
+    while (p_start < nvram_end) {
+	phead = (struct partition_header *)p_start;
+	nvram->parts[nvram->nparts++] = phead;
+	c_sum = checksum(phead);
+	if (c_sum != phead->checksum)
+	    warn_msg("this partition checksum should be %02x!\n", c_sum);
+	p_start += phead->length * NVRAM_BLOCK_SIZE;
+    }
+
+    if (verbose)
+	printf("NVRAM contains %d partitions\n", nvram->nparts);
+
+    return 0;
+}
+
+/**
+ * nvram_find_fd_partition
+ * @brief Find a particular nvram partition using a file descriptor
+ *
+ * @param name name of the partition to find
+ * @param nvram pointer to nvram struct to search
+ * @return 0 on success, !0 otherwise
+ */
+static int
+nvram_find_fd_partition(struct nvram *nvram, char *name)
+{
+    struct partition_header	phead;
+    int				len;
+    int				found = 0;
+
+    if (lseek(nvram->fd, SEEK_SET, 0) == -1) {
+        err_msg("could not seek to beginning of file %s\n", nvram->filename);
+	return -1;
+    }
+    
+    while (! found) {
+        len = read(nvram->fd, &phead, sizeof(phead));
+	if (len == 0) { /* EOF */
+	    err_msg("could not find %s partition in %s\n", 
+	    	    name, nvram->filename);
+	    return -1;
+	} 
+        else if (len != sizeof(phead)) {
+	    err_msg("Invalid read from %s: %s\n", nvram->filename,
+	    	    strerror(errno));
+	    return -1;
+	}
+
+	if (! strncmp(phead.name, name, sizeof(phead.name)))
+	    found = 1;
+	else {
+	    int offset = phead.length * NVRAM_BLOCK_SIZE - len;
+	    if (lseek(nvram->fd, offset, SEEK_CUR) == -1) {
+	        err_msg("seek error in file %s: %s\n", nvram->filename,
+			strerror(errno));
+		return -1;
+	    }
+	}
+    }
+
+    if (! found) {
+        err_msg("could not find %s partition in %s\n", name, nvram->filename);
+	return -1;
+    }
+
+    /* we found the correct partition seek back to the beginning of it */
+    if (lseek(nvram->fd, -len, SEEK_CUR) == -1) {
+        err_msg("could not seek to %s partition\n", name);
+	return -1;
+    }
+
+    return 0;
+}
+	
+/**
+ * nvram_find_partition
+ * @brief Find a partition given a signature and name.
+ * 
+ * If signature is zero (invalid) it is not used for matching.
+ * If name is NULL it is ignored.
+ * start is the partition in which to resume a search (NULL starts at the first
+ * partition).
+ *
+ * @param signature partition signature to find
+ * @param name partition name to find
+ * @param start partition header to start search at
+ * @param nvram nvram struct to search
+ * @return pointer to partition header on success, NULL otherwise 
+ */
+static struct partition_header *
+nvram_find_partition(struct nvram *nvram, unsigned char signature, char *name, 
+		     struct partition_header *start)
+{
+    struct partition_header *phead;
+    int i;
+
+    /* Get starting partition.  This is not terribly efficient... */
+    if (start == NULL) {
+	i = 0;
+	if (verbose > 1)
+	    printf("find partition starts with zero\n");
+    } 
+    else {
+	for (i = 0; i < nvram->nparts; i++)
+	    if (nvram->parts[i] == start)
+		break;
+	i++;	/* start at next partition */
+	if (verbose > 1)
+	    printf("find partition starts with %d\n", i);
+    }
+
+    /* Search starting with partition i... */
+    while (i < nvram->nparts) {
+	phead = nvram->parts[i];
+	if (signature == '\0' || signature == phead->signature) {
+	    if (name == NULL 
+		|| strncmp(name, phead->name, sizeof(phead->name)) == 0) {
+		return phead;
+	    }
+	}
+	i++;
+    }
+	
+    return NULL;
+}
+
+/**
+ * print_partition_table
+ * @brief print a table of available partitions
+ *
+ * @param nvram nvram struct of partitions
+ */ 
+static void 
+print_partition_table(struct nvram *nvram)
+{
+    struct partition_header *phead;
+    int i = 0;
+
+    printf(" # Sig Chk  Len  Name\n");
+    for (i = 0; i < nvram->nparts; i++) {
+        phead = nvram->parts[i];
+    	printf("%2d  %02x  %02x  %04x %.12s\n", i, phead->signature, 
+	       phead->checksum, phead->length, phead->name);
+    }
+}
+
+/**
+ * getvalue
+ * @brief Copy a value into a buf.
+ * The first two bytes of the value is a length.
+ * Return pointer to byte after the value.
+ *
+ * @param p pointer to value to copy
+ * @param buf buffer to copy value into
+ * @return pointer past the copied value in p
+ */
+static char *
+getvalue(char *p, char *buf)
+{
+    int len = *p++;
+    len |= ((*p++) << 8);
+    memcpy(buf, p, len);
+    buf[len] = '\0';
+    return p+len;
+}
+
+/**
+ * getsmallvlaue
+ * @brief Copy a value into a buf.
+ * The first one bytes of the value is a length.
+ *
+ * @param p pointer to value to copy
+ * @param buf buffer to copy value into
+ * @return pointer past the copied value in p
+ */
+static char *
+getsmallvalue(char *p, char *buf)
+{
+    int len = *p++;
+    memcpy(buf, p, len);
+    buf[len] = '\0';
+    return p+len;
+}
+
+/**
+ * lookupfield
+ * @brief translate a VPD field to human readable string
+ *
+ * Lookup a VPD field name (always 2 chars) and return a human 
+ * readable string.
+ *
+ * @param p VPD field name
+ * @return pointer to human readable string on success, NULL otherwise
+ */
+static char *
+lookupfield(char *p)
+{
+    int i;
+
+    for (i = 0; (i < sizeof(descs) / sizeof(descs[0])); i++) {
+	if (strcmp(p, descs[i].name) == 0)
+	    return descs[i].desc;
+     }
+
+    return NULL;
+}
+
+/**
+ * printVPDfield
+ * @brief Format and print a VPD field and return a ptr to the next field. 
+ *
+ * @param p pointer to VPD field
+ * @param show_all verbosity level
+ * @return pointer to next VPD field
+ */
+static char *
+printVPDfield(char *p, int show_all)
+{
+    char field[3];
+    char value[256];
+    char *fname;
+
+    field[0] = p[0]; field[1] = p[1]; field[2] = 0;
+    p+=2;
+    p = getsmallvalue(p, value);
+    if ((fname = lookupfield(field)) != NULL)
+	printf("	%-20s %s\n", fname, value);
+    else if (show_all)
+	printf("	%-20s %s\n", field, value);
+
+    return p;
+}
+
+/**
+ * dump_vpd
+ * @brief Dump Vital Product Data
+ * 
+ * See Chapter 18: Expansion ROMs of the PCI spec.
+ *
+ * @param nvram nvram struct to retrieve VPD data from
+ * @param show_all verbosity level
+ */
+int 
+dump_vpd(struct nvram *nvram, int show_all)
+{
+    struct partition_header *phead;
+    char *p, *p_end;
+    char value[4096];
+
+    phead = nvram_find_partition(nvram, NVRAM_SIG_HW, "ibm,vpd", NULL);
+    if (!phead) {
+	err_msg("there is no ibm,vpd partition!\n");
+	return -1;
+    }
+
+    p = (char *)(phead + 1);
+    p_end = (char *)(phead + phead->length);
+	
+    while (*p && p < p_end) {
+	if (*p == (char)0x82) {	/* Identification string descriptor. */
+	    p++;
+	    p = getvalue(p, value);
+	    printf("%s\n", value);	/* print id string */
+	
+	    while (*p != 0x79) {	/* loop until VPD end tag */
+		int vpdlen;
+		char *vpd_endp;
+		p++;
+		vpdlen = *p++;
+		vpdlen |= ((*p++) << 8);
+		vpd_endp = p + vpdlen;
+		while (p < vpd_endp)
+		    p = printVPDfield(p, show_all);
+	    }
+		
+	    p++;
+	    /* printf("checksum byte=0x%x\n", *p); */
+	    p++;
+	} 
+        else if (*p == 0) {	/* end tag */
+	    break;
+	}
+    }
+	
+    if (*p && p < p_end) {
+	warn_msg("found unknown descriptor byte 0x%x\n", *p);
+    }
+
+    return 0;
+}
+
+/**
+ * dump_errlog
+ * @brief Dump ibm,err-log partition which contains checkstop info.
+ * 
+ * ToDo: this code needs more work.
+ * See IBM RPA (IBM internal use only -- sorry).
+ *
+ * @param nvram nvram struct to dump errlog from
+ * @return 0 on success, !0 otherwise
+ */
+int
+dump_errlog(struct nvram *nvram)
+{
+    struct partition_header *phead;
+    uint16_t *p, *p_end;    /* Note: data is organized into 16bit big 
+                             * endian (network byte order) */
+    int p_max;		/* max index to go out of bounds of the partition */
+    int i, cpu;
+    char checkstop_count;
+    int offset;
+    int num_cpus;
+    int num_memctrls;
+    int num_ioctrls;
+    uint16_t *sys_regs;	    /* System specific registers 
+                             * (e.g. bus arbitration chips, etc */
+    uint16_t *cpu_regs[MAX_CPUS+1];
+    uint16_t *memctrl_data;
+    uint16_t *ioctrl_data;
+
+    phead = nvram_find_partition(nvram, NVRAM_SIG_SP, "ibm,err-log", NULL);
+    if (!phead) {
+	err_msg("there is no ibm,err-log partition!\n");
+	return -1;
+    }
+	
+    p = (uint16_t *)(phead + 1);
+    p_end = (uint16_t *)(phead + phead->length);
+    p_max = p_end - p;	/* max in 16bit values */
+    if (p_max < 4) {
+	err_msg("Corrupt ibm,err-log partition in nvram\n");
+	return -1;
+    }
+	
+    /* index 0 is checkstop count (high byte), semaphores (low byte) */
+    i = 0;	/* index through short words */
+    checkstop_count = p[i] >> 8;
+    if (checkstop_count)
+	printf("Checkstops detected: %d\n", checkstop_count);
+    else
+	printf("No checkstops have been detected.\n");
+
+    /* index 1 is system specific register offset */
+    i++;
+    offset = ntohs(p[i])/2+1;
+    sys_regs = offset + i < p_max ? p + offset + i : 0;
+
+    /* index 2 is number of cpus */
+    i++;
+    num_cpus = ntohs(p[i]);
+    printf("CPUS: %d\n", num_cpus);
+
+    /* Next indexes are offsets to cpu specific regs */
+    for (cpu = 0; cpu < num_cpus; cpu++) {
+	i++;
+	if (cpu < MAX_CPUS) {
+	    offset = ntohs(p[i])/2+1;
+	    cpu_regs[cpu] = offset + i < p_max ? p + offset + i : 0;
+	}
+    }
+    
+    if (num_cpus > MAX_CPUS)
+	num_cpus = MAX_CPUS;	/* just in case... */
+
+    /* next index is number of memory controllers */
+    i++;
+    num_memctrls = ntohs(p[i]);
+    printf("Memory Controllers: %d\n", num_memctrls);
+
+    /* next index is offset of memory controller data */
+    i++;	/* ToDo: this may be a list of offsets...manual doesn't show 
+		   that but only 1 seems odd */
+    offset = ntohs(p[i])/2+1;
+    memctrl_data = offset + i < p_max ? p + offset + i : 0;
+
+    /* next index is number of I/O Subsystem controllers */
+    i++;
+    num_ioctrls = ntohs(p[i]);
+    printf("I/O Controllers: %d\n", num_ioctrls);
+
+    /* next index is offset of I/O Subsystem controller data */
+    i++;	/* ToDo: this may be a list of offsets...manual doesn't show 
+		   that but only 1 seems odd */
+    offset = ntohs(p[i])/2+1;
+    ioctrl_data = offset + i < p_max ? p + offset + i : 0;
+
+    /*** End of header ***/
+
+    /* Now dump sections collected by the header. */
+    if (sys_regs && num_cpus > 0) {
+	/* ToDo: what is the length of the data?  We dump until the 
+	   first cpu data. */
+	printf("System Specific Registers\n");
+	dump_raw_data((char *)sys_regs, cpu_regs[0] - sys_regs);
+    }
+
+    /* artificial "next cpu" data for length */
+    cpu_regs[num_cpus] = ioctrl_data;
+	
+    for (cpu = 0; cpu < num_cpus; cpu++) {
+	/*char buf[64];*/
+	int len;
+	/* ToDo: what is the length of the data?  We dump until the 
+	   next cpu data. */
+	len = cpu_regs[cpu+1] - cpu_regs[cpu];
+	printf("CPU %d Register Data (len=%x, offset=%x)\n", cpu, len, 
+		cpu_regs[cpu]-p);
+	if (len < 4096)	/* reasonable bound */
+	    dump_raw_data((char *)cpu_regs[cpu], len);
+    }
+
+    return 0;
+}
+
+/**
+ * dump_rtas_event_entry
+ * @brief Dump event-scan data.
+ *
+ * Note: This is really only valid for PAPR machines.  To ensure 
+ * the nvram command can run on all powerpc machines we dlopen the
+ * the librtasevent library to dump the rtas event.
+ *
+ * @param data pointer to rtas error to dump
+ * @param len length of data buffer
+ * @return 0 on success, !0 otherwise 
+ */
+int
+dump_rtas_event_entry(char *data, int len)
+{
+    void *rtas_event;
+    void *handle;
+    void *(*parse_rtas_event)();
+    void (*rtas_print_event)();
+    void (*cleanup_rtas_event)();
+
+    handle = dlopen("/usr/lib/librtasevent.so", RTLD_LAZY);
+    if (handle == NULL)
+        return 1;
+
+    parse_rtas_event = dlsym(handle, "parse_rtas_event");
+    if (parse_rtas_event == NULL) {
+        dlclose(handle);
+        return 1;
+    }
+
+    rtas_print_event = dlsym(handle, "rtas_print_event");
+    if (rtas_print_event == NULL) {
+        dlclose(handle);
+        return 1;
+    }
+
+    cleanup_rtas_event = dlsym(handle, "cleanup_rtas_event");
+    if (cleanup_rtas_event == NULL) {
+        dlclose(handle);
+        return 1;
+    }
+
+    rtas_event = parse_rtas_event(data, len);
+    if (rtas_event == NULL) {
+        dlclose(handle);
+        return 1;
+    }
+
+    rtas_print_event(stdout, rtas_event, 0);
+
+    cleanup_rtas_event(rtas_event);
+
+    dlclose(handle);
+    return 0;
+}
+
+/**
+ * dump_eventscanlog
+ * @brief Dump ibm,es-logs partition, which contains a service processor log
+ * 
+ * See IBM RPA (IBM internal use only -- sorry).
+ *
+ * @param nvram nvram struct to get eventscan log from 
+ * @return 0 on success, !0 otherwise
+ */
+int 
+dump_eventscanlog(struct nvram *nvram)
+{
+    struct partition_header *phead;
+    uint32_t *p, *p_end;	/* Note: data is organized into 32bit big 
+                                 * endian (network byte order) */
+    int p_max;		/* max index to go out of bounds of the partition */
+    int lognum;
+    int num_logs;
+    int rc;
+#define MAX_EVENTLOGS 100
+    uint32_t loghdr[MAX_EVENTLOGS+1];
+
+    phead = nvram_find_partition(nvram, NVRAM_SIG_SP, "ibm,es-logs", NULL);
+    if (!phead) {
+	err_msg("there is no ibm,es-logs partition!\n");
+	return -1;
+    } 
+	
+    p = (uint32_t *)(phead + 1);
+    p_end = (uint32_t *)(phead + phead->length);
+    p_max = p_end - p;	/* max in 32bit values */
+    if (p_max < 1) {
+	err_msg("Corrupt ibm,es-logs partition in nvram\n");
+	return -1;
+    }
+
+    num_logs = ntohl(*p);
+    printf("Number of Logs: %d\n", num_logs);
+
+    if (num_logs > MAX_EVENTLOGS) {
+	num_logs = MAX_EVENTLOGS;
+	warn_msg("limiting to %d log entries (program limit)\n", num_logs);
+    }
+    
+    if (num_logs > p_max-1) {
+	/* of course this leaves no room for log data 
+	   (i.e. corrupt partition) */
+	num_logs = p_max-1;
+	warn_msg("limiting to %d log entries (partition limit)\n", num_logs);
+    }
+	
+    for (lognum = 0; lognum < num_logs; lognum++) {
+	loghdr[lognum] = ntohl(p[lognum+1]);
+    }
+
+    /* artificial log entry (offset) to put a limit on the last log */
+    loghdr[num_logs] = p_max * sizeof(uint32_t);
+
+    for (lognum = 0; lognum < num_logs; lognum++) {
+	uint32_t hdr = loghdr[lognum];
+	int flags = (hdr >> 24) & 0xff;
+	int logtype = (hdr >> 16) & 0xff;
+	int start = hdr & 0xffff;
+	int end = loghdr[lognum+1] & 0xffff;
+	printf("Log Entry %d:  flags: 0x%02x  type: 0x%02x\n", lognum, 
+	       flags, logtype);
+	rc = dump_rtas_event_entry(((char *)p) + start, end - start);
+        if (rc) {
+            printf("==== Log %d ====\n", lognum);
+            dump_raw_data(((char *)p) + start, end - start);
+        }
+    }
+
+    return 0;
+}
+
+
+/**
+ * dump_raw_partition
+ * @brief Dump raw data of a partition.  Mainly for debugging.
+ *
+ * @param nvram nvram struct containing partition
+ * @param name name of partition to dump
+ * @return 0 on success, !0 otherwise
+ */
+int
+dump_raw_partition(struct nvram *nvram, char *name)
+{
+    struct partition_header *phead;
+
+    phead = nvram_find_partition(nvram, 0, name, NULL);
+    if (!phead) {
+	err_msg("there is no %s partition!\n", name);
+	return -1;
+    }
+    
+    dump_raw_data((char *)phead, phead->length * NVRAM_BLOCK_SIZE);
+
+    return 0;
+}
+
+/**
+ * print_of_config_part
+ * @brief Print the name/value pairs of a partition
+ *
+ * @param pname partition name containing name/value pairs
+ * @param nvram nvram struct containing partition to dump
+ * @return 0 on success, !0 otherwise
+ */
+static int
+print_of_config_part(struct nvram *nvram, char *pname)
+{
+    struct partition_header	*phead;
+    char	*data;
+    int		i;
+
+    phead = nvram_find_partition(nvram, 0, pname, NULL);
+    if (phead == NULL) 
+	return -1;
+
+    data = (char *)phead + sizeof(*phead);
+
+    printf("\"%s\" Partition\n", pname);
+    for (i = 0; i <= (strlen(pname) + 14); i++)
+	printf("-");
+    printf("\n");
+
+    while (*data != '\0') {
+        printf("%s\n", data);
+	data += strlen(data) + 1;
+    }
+
+    printf("\n");
+
+    return 0;
+}
+
+/* Print a single OF var...or all if "" is used */
+/**
+ * @var name_value_parts
+ * @brief List of partition names that contain name/value pairs
+ */
+/**
+ * @var num_name_value_parts
+ * @brief number of names in the name_vlaue_parts array
+ */
+static char	*name_value_parts[] = {
+    "common", "ibm,setupcfg", "of-config"
+};
+static int num_name_value_parts = 3;
+
+/**
+ * print_of_config
+ * @brief Print the contents of an Open Firmware config partition
+ *
+ * This will print the name/value pair for a specified Open
+ * Firmware config variable or print all of the name/value pairs
+ * in the partition if the name is NULL.
+ *
+ * @param config_var config variable to print
+ * @param pname partition name containing config_var
+ * @param nvram nvram struct containing pname
+ * @return 0 on success, !0 otherwise
+ */
+static int 
+print_of_config(struct nvram *nvram, char *config_var, char *pname)
+{
+    struct partition_header *phead;
+    char *data;
+    int  i, varlen;
+    int  rc = -1;
+
+    /* if config_var is NULL , print the data from the
+     * partition specified by pname or all of the
+     * name/value pair partitions if pname is NULL. 
+     */
+    if (config_var == NULL) {
+	if (pname == NULL) {
+            for (i = 0; i < num_name_value_parts; i++)
+	    	(void)print_of_config_part(nvram, name_value_parts[i]);
+	} 
+        else {
+	    for (i = 0; i < num_name_value_parts; i++) {
+	    	if (strcmp(pname, name_value_parts[i]) == 0) {
+	            (void)print_of_config_part(nvram, name_value_parts[i]);
+		    rc = 0;
+		}
+	    }
+	    if (rc)
+	    	err_msg("There is no Open Firmware \"%s\" partition!\n", pname);
+	}
+	return rc;
+    } 
+    
+    /* the config_var is a variable name */
+    varlen = strlen(config_var);
+
+    if (pname == NULL) {
+    	for (i = 0; i < num_name_value_parts; i++) {
+	    phead = nvram_find_partition(nvram, 0, name_value_parts[i], NULL);
+   	    if (phead == NULL) 
+		continue;
+
+	    data = (char *)phead + sizeof(*phead);
+
+	    while (*data != '\0') {
+	    	if ((data[varlen] == '=') && 
+		    strncmp(config_var, data, varlen) == 0) {
+    	            printf("%s\n", data + varlen + 1);
+		    rc = 0;
+		}
+	    	data += strlen(data) + 1;
+            }
+        }
+    } 
+    else {
+	phead = nvram_find_partition(nvram, 0, pname, NULL);
+	if (phead == NULL) {
+	    err_msg("There is no Open Firmware \"%s\" partition.\n", pname);
+	    return -1;
+	}
+
+	data = (char *)phead + sizeof(*phead);
+	while (*data != '\0') {
+	    if ((data[varlen] == '=') && 
+		strncmp(config_var, data, varlen) == 0) {
+		printf("%s\n", data + varlen + 1);
+		rc = 0;
+	    }
+	    data += strlen(data) + 1;
+	}
+    }
+
+    return rc;
+}
+
+/**
+ * update_config_var
+ * @brief Update an Open Firmware config variable in nvram
+ *
+ * This will attempt to update the value half of a name/value
+ * pair in the nvram config partition.  If the name/value pair
+ * is not found in the partition then the specified name/value pair
+ * is added to the end of the data in the partition.
+ *
+ * @param config_var OF config variable to update
+ * @param pname partition containing config_var
+ * @param nvram nvram struct containing pname
+ * @return 0 on success, !0 otherwise
+ */
+int
+update_of_config_var(struct nvram *nvram, char *config_var, char *pname)
+{
+    struct partition_header *phead, *new_phead;
+    char *data_offset;
+    char *new_part;
+    char *new_part_offset, *new_part_end;
+    char *tmp_offset;
+    int	config_name_len;
+    int	len, part_size, found = 0;
+
+    phead = nvram_find_partition(nvram, 0, pname, NULL);
+    if (phead == NULL) {
+        err_msg("there is no \"%s\" partition!\n", pname);
+	return -1;
+    }
+
+    part_size = phead->length * NVRAM_BLOCK_SIZE;
+    data_offset = (char *)((unsigned long)phead + sizeof(*phead));
+
+    new_part = malloc(part_size);
+    if (new_part == NULL) {
+        err_msg("cannot allocate space to update \"%s\" partition\n", pname);
+	return -1;
+    }
+
+    /* get the length of then name of the config variable we are updating */
+    config_name_len = strstr(config_var, "=") - config_var;
+    config_name_len++;
+    
+    /* now find this config variable in the partition */
+    while (*data_offset != '\0') {
+	if (strncmp(data_offset, config_var, config_name_len) == 0) {
+            found = 1;
+	    break;
+        }
+	else
+	    data_offset += strlen(data_offset) + 1;
+    }
+
+    if (!found) {
+        err_msg("cannot update %s\n"
+		"\tThe config var does not exist in the \"%s\" partition\n", 
+		config_var, pname);
+	free(new_part);
+	return -1;
+    }
+
+    /* Copy everything up to the config name we are modifying 
+     * to the new partition 
+     */
+    memcpy(new_part, phead, data_offset - (char *)phead);
+
+    /* make sure the new config var will fit into the partition and add it */
+    new_phead = (struct partition_header *)new_part;
+    new_part_offset = new_part + (data_offset - (char *)phead);
+    new_part_end = new_part + part_size;
+
+    if ((new_part_offset + strlen(config_var) + 1) >= new_part_end) {
+        err_msg("cannot update config var to\"%s\".\n"
+		"\tThere is not enough room in the \"%s\" partition\n", 
+		config_var, pname);
+	free(new_part);
+	return -1;
+    }
+
+    strncpy(new_part_offset, config_var, strlen(config_var));
+    new_part_offset += strlen(config_var);
+    *new_part_offset++ = '\0';
+
+    /* Find the end of the name/value pairs in the partition so we
+     * can copy them over to the new partition.
+     */
+    data_offset += strlen(data_offset) + 1;
+    tmp_offset = data_offset;
+    while (*data_offset != '\0') {
+    	data_offset += strlen(data_offset) + 1;
+    }
+
+    /* we should now be pointing to a double NULL, verify this */
+    if ((data_offset[-1] != '\0') && (data_offset[0] != '\0')) {
+        err_msg("the \"%s\" partition appears to be corrupt\n", pname);
+	free(new_part);
+	return -1;
+    }
+
+    /* go past double NULL */
+    data_offset++;
+
+    /* verify that this will fit into the new partition */
+    if ((new_part_offset + (data_offset - tmp_offset)) > new_part_end) {
+        err_msg("cannot update open firmware config var to \"%s\".\n"
+		"\tThere is not enough room in the \"%s\" partition\n", 
+		config_var, pname);
+	free(new_part);
+	return -1;
+    }
+
+    memcpy(new_part_offset, tmp_offset, data_offset - tmp_offset);
+
+    /* recalculate the checksum */
+    new_phead->checksum = checksum(new_phead);
+
+    /* seek the position in the /dev/nvram for the common partition */
+    if (nvram_find_fd_partition(nvram, new_phead->name) != 0) {
+    	free(new_part);
+	return -1;
+    }
+    
+    /* write the partition out to nvram */
+    len = write(nvram->fd, new_part, part_size);
+    if (len != part_size) {
+        err_msg("only wrote %d bytes of the \"%s\" partition back\n"
+		"\tto %s, expected to write %d bytes\n",
+		len, pname, nvram->filename, part_size);
+    }
+
+    free(new_part);
+    return 0;
+}
+
+int 
+main (int argc, char *argv[])
+{
+    struct nvram nvram;
+    struct stat sbuf;
+    int ret = 0; 
+    int	of_nvram_size;
+    int	option_index;
+    char *endp;
+    char *of_config_var = NULL;
+    int print_partitions = 0;
+    int print_vpd = 0;
+    int print_errlog = 0;
+    int print_event_scan = 0;
+    int	print_config_var = 0;
+    char *dump_name = NULL;
+    char *update_config_var = NULL;
+    char *config_pname = "common";
+
+    nvram_cmdname = argv[0];
+    if (argc == 1) {
+	help();
+	exit(1);
+    }
+
+    /* initialize nvram struct */
+    memset(&nvram, 0, sizeof(struct nvram));
+    nvram.fd = -1;
+	
+    for (;;) {
+	option_index = 0;
+	ret = getopt_long(argc, argv, "+v:p:", long_options, &option_index);
+	if (ret == -1)
+		break;
+	switch (ret) {
+	    case 'h':
+		help();
+		exit(0);
+	    case 'v':
+		verbose += (optarg ? atoi(optarg) : 1);
+		break;
+	    case 'd':	/* dump */
+		dump_name = optarg;
+		break;
+	    case 'n':	/* nvram-file */
+		nvram.filename = optarg;
+		break;
+	    case 'o':	/*print-config */
+		print_config_var = 1;
+		of_config_var = optarg;
+		break;
+	    case 'P':	/* partitions */
+		print_partitions = 1;
+		break;
+	    case 's':	/* nvram-size */
+		nvram.nbytes = strtoul(optarg, &endp, 10);
+		if (!*optarg || *endp) {
+		    err_msg("specify nvram-size as an integer\n");
+		    exit(1);
+		}
+		break;
+	    case 'V':	/* print-vpd */
+		print_vpd = 1;
+		break;
+	    case 'W':	/* print-all-vpd */
+		print_vpd = 2;
+		break;
+	    case 'e':	/* print-err-log */
+		print_errlog = 1;
+		break;
+	    case 'E':	/* print-event-scan */
+		print_event_scan = 1;
+		break;
+	    case 'u':	/* update-config */
+	        update_config_var = optarg;
+		break;
+	    case 'p':	/* update-config partition name */
+	        config_pname = optarg;
+		break;
+	    case '?':
+		exit(1);
+		break;
+	    default:
+		printf("huh?\n");
+		break;
+	}
+    }
+
+    if (optind < argc) {
+	    err_msg("Could not parse the option %s correctly.\n", 
+		    argv[optind]);
+	    help();
+	    exit(-1);
+    }
+
+    ret = 0;
+
+    if (nvram.filename) {
+        nvram.fd = open(nvram.filename, O_RDWR);
+        if (nvram.fd == -1) {
+	    err_msg("cannot open \"%s\": %s\n", 
+  		    nvram.filename, strerror(errno));
+              ret = -1;
+  	    goto err_exit;
+        }
+    } else {
+        nvram.filename = NVRAM_FILENAME1;
+        nvram.fd = open(nvram.filename, O_RDWR);
+        if (nvram.fd == -1) {
+	    int errno1 = errno;
+
+            nvram.filename = NVRAM_FILENAME2;
+            nvram.fd = open(nvram.filename, O_RDWR);
+            if (nvram.fd == -1) {
+                err_msg("cannot open \"%s\": %s\n", 
+                        NVRAM_FILENAME1, strerror(errno1));
+                err_msg("cannot open \"%s\": %s\n", 
+                        NVRAM_FILENAME2, strerror(errno));
+                ret = -1;
+                goto err_exit;
+            }
+        }
+    }
+
+    if (fstat(nvram.fd, &sbuf) < 0) {
+        err_msg("cannot stat %s: %s\n", nvram.filename, strerror(errno));
+	ret = -1;
+	goto err_exit;
+    }
+
+    of_nvram_size = get_of_nvram_size();
+    nvram.nbytes = sbuf.st_size ? sbuf.st_size : of_nvram_size;
+    if (nvram.nbytes != of_nvram_size) {
+	warn_msg("specified nvram size %d does not match this machine %d!\n", 
+		 nvram.nbytes, of_nvram_size);
+    }
+
+    nvram.data = malloc(nvram.nbytes);
+    if (nvram.data == NULL) {
+        err_msg("cannot allocate space for nvram of %d bytes\n", nvram.nbytes);
+    	ret = -1;
+	goto err_exit;
+    }
+
+    if (nvram_read(&nvram) != 0) {
+        ret = -1;
+        goto err_exit;
+    }
+
+    if (nvram_parse_partitions(&nvram) != 0) {
+        ret = -1;
+	goto err_exit;
+    }
+
+    if (print_partitions)
+	print_partition_table(&nvram);
+
+    if (update_config_var) {
+        if (config_pname == NULL) {
+	    err_msg("you must specify the partition name with the -p option\n"
+	    	    "\twhen using the --update-config option\n");
+	    goto err_exit;
+	}
+    	if (update_of_config_var(&nvram, update_config_var, config_pname) != 0) 
+	    ret = -1; 
+    }
+    if (print_config_var)
+	if (print_of_config(&nvram, of_config_var, config_pname) != 0)
+	    ret = -1;
+    if (print_vpd)
+	if (dump_vpd(&nvram, print_vpd == 2) != 0)
+	    ret = -1;
+    if (print_errlog)
+	if (dump_errlog(&nvram) != 0)
+	    ret = -1;
+    if (print_event_scan)
+	if (dump_eventscanlog(&nvram) != 0)
+	    ret = -1;
+    if (dump_name)
+	if (dump_raw_partition(&nvram, dump_name) != 0)
+	    ret = -1;
+   
+err_exit:   
+   if (nvram.data)
+	free(nvram.data);
+   if (nvram.fd != -1)
+   	close(nvram.fd);
+	
+   return ret;
+}

Added: trunk/powerpc-ibm-utils/cmds/nvram.h
===================================================================
--- trunk/powerpc-ibm-utils/cmds/nvram.h	                        (rev 0)
+++ trunk/powerpc-ibm-utils/cmds/nvram.h	2006-09-25 09:08:44 UTC (rev 164)
@@ -0,0 +1,111 @@
+/**
+ * @file nvram.h
+ * @brief nvram access utility for powerpc platforms.
+ *
+ * Copyright (c) 2003, 2004 International Business Machines
+ * Common Public License Version 1.0 (see COPYRIGHT)
+ *
+ * @author Nathan Fontenot <nfont at austin.ibm.com>
+ * @author Michael Strosaker <strosake at us.ibm.com>
+ * @author Todd Inglett <tinglett at us.ibm.com>
+ */
+
+#ifndef _DEV_NVRAM_H_
+#define _DEV_NVRAM_H_
+
+#define NVRAM_SIG_SP	0x02	/**< support processor signature */
+#define NVRAM_SIG_OF	0x50	/**< open firmware config signature */
+#define NVRAM_SIG_FW	0x51	/**< general firmware signature */
+#define NVRAM_SIG_HW	0x52	/**< hardware (VPD) signature */
+#define NVRAM_SIG_SYS	0x70	/**< system env vars signature */
+#define NVRAM_SIG_CFG	0x71	/**< config data signature */
+#define NVRAM_SIG_ELOG	0x72	/**< error log signature */
+#define NVRAM_SIG_VEND	0x7e	/**< vendor defined signature */
+#define NVRAM_SIG_FREE	0x7f	/**< Free space signature */
+#define NVRAM_SIG_OS	0xa0	/**< OS defined signature */
+
+/**
+ * @def printmap(ch)
+ * @brief dertermines if 'ch' is a printable character
+ */
+#define printmap(ch)	(isgraph(ch) ? (ch) : '.')
+
+#define NVRAM_BLOCK_SIZE	16
+#define NVRAM_FILENAME1		"/dev/nvram"
+#define NVRAM_FILENAME2		"/dev/misc/nvram"
+
+#define DEVICE_TREE "/proc/device-tree"
+#define NVRAM_DEFAULT DEVICE_TREE "/nvram"
+#define NVRAM_ALIAS DEVICE_TREE "/aliases/nvram"
+
+#define DEFAULT_NVRAM_SZ	(1024 * 1024)
+
+/**
+ * @def MAX_CPUS
+ * @brief maximum number of CPUS for errlog dumps
+ */
+#define MAX_CPUS 128
+
+/**
+ * @struct partition_header
+ * @brief nvram partition header data
+ */
+struct partition_header {
+    unsigned char	signature;  /**< partition signature */
+    unsigned char 	checksum;   /**< partition checksum */
+    unsigned short 	length;     /**< partition length */
+    char 		name[12];   /**< partition name */
+};
+
+/* Internal representation of NVRAM. */
+#define MAX_PARTITIONS 50
+/**
+ * @struct nvram
+ * @brief internal representation of nvram data
+ */
+struct nvram {
+    char 	*filename;		/**< original filename */
+    int		fd;			/**< file descriptor */
+    int 	nparts;			/**< number of partitions */
+    int 	nbytes;			/**< size of data in bytes.  This 
+                                         *   cannot be changed 
+                                         *   (i.e. hardware size) 
+					 */
+    struct partition_header *parts[MAX_PARTITIONS]; 
+                                        /**< partition header pointers 
+                                         *   into data 
+                                         */
+    char	*data;                  /**< nvram contents */
+};
+
+/**
+ * @var descs
+ * @brief Array of VPD field names and descriptions
+ */
+static struct { char *name; char *desc; } descs[] = {
+    {"PN", "Part Number"},
+    {"FN", "FRU Number"},
+    {"EC", "EC Level"},
+    {"MN", "Manufacture ID"},
+    {"SN", "Serial Number"},
+    {"LI", "Load ID"},
+    {"RL", "ROM Level"},
+    {"RM", "Alterable ROM Level"},
+    {"NA", "Network Address"},
+    {"DD", "Device Driver Level"},
+    {"DG", "Diagnostic Level"},
+    {"LL", "Loadable Microcode Level"},
+    {"VI", "Vendor ID/Device ID"},
+    {"FU", "Function Number"},
+    {"SI", "Subsystem Vendor ID/Device ID"},
+    {"VK", "Platform"},			/**< "RS6K" => VPD is present */
+    {"TM", "Model"},			/**< IBM specific? */
+    {"YL", "Location Code"},		/**< IBM specific? */
+    {"BR", "Brand"},			/**< IBM specific */
+    {"CI", "CEC ID"},			/**< IBM specific */
+    {"RD", "Rack ID"},			/**< IBM specific */
+    {"PA", "Op Panel Installed"},	/**< IBM specific */
+    {"NN", "Node Name"},		/**< IBM specific */
+};
+
+#endif

Added: trunk/powerpc-ibm-utils/doc/Makefile
===================================================================
--- trunk/powerpc-ibm-utils/doc/Makefile	                        (rev 0)
+++ trunk/powerpc-ibm-utils/doc/Makefile	2006-09-25 09:08:44 UTC (rev 164)
@@ -0,0 +1,28 @@
+#
+# Makefile for powerpc-utils/doc
+# 
+
+include ../rules.mk
+
+MANPAGES8 = snap.8 bootlist.8 ofpathname.8
+
+SUBDIRS = nvram
+
+all: $(MANPAGES8)
+	@$(foreach d,$(SUBDIRS), $(MAKE) -C $d;)
+
+install: all
+	@$(call install_man,$(MANPAGES8),$(DESTDIR))
+	@$(foreach d,$(SUBDIRS), $(MAKE) -C $d install;)
+
+uninstall:
+	@$(call uninstall_man,$(MANPAGES8),$(DESTDIR))
+	@$(foreach d,$(SUBDIRS), $(MAKE) -C $d uninstall;)
+
+docs:
+	@$(foreach d,$(SUBDIRS), $(MAKE) -C $d docs;)
+
+clean:	
+	@echo "Cleaning up $(WORK_DIR) files..."
+	@$(foreach d,$(SUBDIRS), $(MAKE) -C $d clean;)
+	@rm -f *~

Added: trunk/powerpc-ibm-utils/doc/bootlist.8
===================================================================
--- trunk/powerpc-ibm-utils/doc/bootlist.8	                        (rev 0)
+++ trunk/powerpc-ibm-utils/doc/bootlist.8	2006-09-25 09:08:44 UTC (rev 164)
@@ -0,0 +1,59 @@
+.\"
+.\" Copyright (C) 2004 International Business Machines
+.\" Nathan Fontenot <nfont at austin.ibm.com>
+.\"
+.TH BOOTLIST 8 "April 2004" Linux "Linux on Power Service Tools"
+.SH NAME
+bootlist - update and view the bootlist
+.SH SYNOPSIS
+.nf
+\fB/usr/sbin/bootlist \-m normal\fR|\fBservice\fR|\fBboth \fR[\fB-o\fR|\fB-r\fR] <\fIdev_list\fR>
+\fB/usr/sbin/bootlist \-m normal\fR|\fBservice\fR|\fBboth \fR[\fB-o\fR|\fB-r\fR] \fB-f \fIfile
+.fi
+.SH DESCRIPTION
+The bootlist command allows users to view and update the system bootlist
+stored in NVRAM for PowerPC-64 machines.  The bootlist entries can be
+specified as either logical device names or Open Firmware device path names.
+The bootlist will convert all names to Open Firmware device path names using
+\fIofpathname\fR when updating the bootlist.  Then uses the \fInvram\fR
+command to update NVRAM.  If a list of devices is specified, the boot list
+will be updated with the list provided.  If a list is not specified, the
+current boot list will be printed.
+.SH OPTIONS
+.TP
+\fB\-m normal\fR|\fBservice\fR|\fBboth
+Required; specify whether the normal or service mode boot list should be
+viewed/updated.  Specifying "both" will update the normal and service mode
+boot lists.
+.TP
+\fB\-o
+Display the current boot list entries as logical device names.
+.TP
+\fB\-r
+Display the current boot list entries as Open Firmware device path names
+(default).
+.TP
+\fB\-f \fIfile
+Read the bootlist device names from \fIfile\fR, one entry per line.
+.TP
+\fIdev_list
+A space-separated list of devices, specified as logical device names or OF
+device path names, depending on whether the \fB-o\fR or \fB-r\fR option is
+specified.
+.SH EXAMPLES
+.nf
+View the normal mode boot list as logical device names:
+
+    /usr/sbin/bootlist -o -m normal
+
+Update the service mode boot list:
+
+    /usr/sbin/bootlist -o -m service /dev/sda3 /dev/cdrom
+.fi
+.SH AUTHOR
+Written by Nathan Fontenot
+.SH "SEE ALSO"
+.BR ofpathname (8),
+.BR nvram (8)
+
+

Added: trunk/powerpc-ibm-utils/doc/nvram/Makefile
===================================================================
--- trunk/powerpc-ibm-utils/doc/nvram/Makefile	                        (rev 0)
+++ trunk/powerpc-ibm-utils/doc/nvram/Makefile	2006-09-25 09:08:44 UTC (rev 164)
@@ -0,0 +1,24 @@
+#
+# Makefile for powerpc-utils/doc/nvram
+# 
+
+include ../../rules.mk
+
+MANPAGE = nvram.8
+
+DOXYGEN_CFG = nvram.doxycfg
+
+all: $(MANPAGE)
+
+install: all
+	@$(call install_man,$(MANPAGE),$(DESTDIR))
+
+uninstall: 
+	@$(call uninstall_man,$(MANPAGE),$(DESTDIR))
+
+docs: $(DOXYGEN_CFG)
+	@echo "Creating $(WORK_DIR) doxygen docs..."
+	@$(DOXYGEN) $(DOXYGEN_CFG) >/dev/null
+
+clean: 
+	@rm -rf html latex *~

Added: trunk/powerpc-ibm-utils/doc/nvram/nvram.8
===================================================================
--- trunk/powerpc-ibm-utils/doc/nvram/nvram.8	                        (rev 0)
+++ trunk/powerpc-ibm-utils/doc/nvram/nvram.8	2006-09-25 09:08:44 UTC (rev 164)
@@ -0,0 +1,73 @@
+.\"
+.\" Copyright (C) 2002 - 2004 International Business Machines
+.\"
+.TH NVRAM 8 "May 2004" Linux "Linux on Power Service Tools"
+.SH NAME
+nvram \- format data stored in non-volatile RAM
+.SH SYNOPSIS
+.B /usr/sbin/nvram
+[ options ]
+.SH DESCRIPTION
+.I Nvram
+is used to print and modify data stored in the non-volatile RAM (NVRAM)
+on a PowerPC-64 system.  NVRAM on these systems is partitioned into data
+sections that each have their own format.  The print options to this
+command selects what to print and how to format it.
+
+.P
+The
+.I nvram 
+utility can also be used to update the data in certain NVRAM partitions of
+PowerPC-64 systems.
+.I Nvram
+can update the value of a name/value pair for NVRAM partitions formatted
+as a set of name=value pairs.  On many systems, the following NVRAM
+partitions contain data formatted as name=value pairs: common, of-config,
+and ibm,setupcfg.
+.SH OPTIONS
+.TP
+\fB\--print-config\fR[=\fIvar\fR]
+print value of a config variable, or print all variables in the specified
+(or all) partitions.
+.TP
+\fB\--update-config \fIname\fR=\fIvalue
+update the config variable in the specified partition; the -p option
+must also be specified..
+.TP
+\fB\-p \fIpartition
+specify a partition; required with the --update-config option, optional
+with the --print-config option.
+.TP
+\fB\--print-vpd
+print vital product data (VPD) collected by the system in NVRAM.
+This data may also be viewed with the lscfg(1) command directly from the
+devices.
+.TP
+\fB\--print-all-vpd
+print viral product data (VPD) collected by the system in NVRAM including
+vendor specific data.
+.TP
+\fB\--print-err-log
+print the checkstop error log generated by the service processor whenever
+the system checkstops.
+.TP
+\fB\--print-event-scan
+print the event scan log stored in NVRAM.
+.TP
+\fB\--partitions
+print the contents of all the NVRAM partition headers.
+.TP
+\fB\--nvram-file \fIpath
+read nvram data from a given file rather than /dev/nvram.  To capture NVRAM
+for later use, simply copy /dev/nvram into a file.
+.TP
+\fB\--verbose \fR(\fB-v\fR)
+be more verbose.
+.TP
+\fB\--help
+print usage information including other low level options useful for
+debugging nvram.
+.SH FILES
+/dev/nvram
+.SH AUTHOR
+Writtem by Todd Inglett, Nathan Fontenot, and Michael Strosaker

Added: trunk/powerpc-ibm-utils/doc/nvram/nvram.doxycfg
===================================================================
--- trunk/powerpc-ibm-utils/doc/nvram/nvram.doxycfg	                        (rev 0)
+++ trunk/powerpc-ibm-utils/doc/nvram/nvram.doxycfg	2006-09-25 09:08:44 UTC (rev 164)
@@ -0,0 +1,1153 @@
+# Doxyfile 1.3.8
+
+# This file describes the settings to be used by the documentation system
+# doxygen (www.doxygen.org) for a project
+#
+# All text after a hash (#) is considered a comment and will be ignored
+# The format is:
+#       TAG = value [value, ...]
+# For lists items can also be appended using:
+#       TAG += value [value, ...]
+# Values that contain spaces should be placed between quotes (" ")
+
+#---------------------------------------------------------------------------
+# Project related configuration options
+#---------------------------------------------------------------------------
+
+# The PROJECT_NAME tag is a single word (or a sequence of words surrounded 
+# by quotes) that should identify the project.
+
+PROJECT_NAME           = nvram
+
+# The PROJECT_NUMBER tag can be used to enter a project or revision number. 
+# This could be handy for archiving the generated documentation or 
+# if some version control system is used.
+
+PROJECT_NUMBER         = 
+
+# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) 
+# base path where the generated documentation will be put. 
+# If a relative path is entered, it will be relative to the location 
+# where doxygen was started. If left blank the current directory will be used.
+
+OUTPUT_DIRECTORY       = .
+
+# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create 
+# 4096 sub-directories (in 2 levels) under the output directory of each output 
+# format and will distribute the generated files over these directories. 
+# Enabling this option can be useful when feeding doxygen a huge amount of source 
+# files, where putting all generated files in the same directory would otherwise 
+# cause performance problems for the file system.
+
+CREATE_SUBDIRS         = NO
+
+# The OUTPUT_LANGUAGE tag is used to specify the language in which all 
+# documentation generated by doxygen is written. Doxygen will use this 
+# information to generate all constant output in the proper language. 
+# The default language is English, other supported languages are: 
+# Brazilian, Catalan, Chinese, Chinese-Traditional, Croatian, Czech, Danish, 
+# Dutch, Finnish, French, German, Greek, Hungarian, Italian, Japanese, 
+# Japanese-en (Japanese with English messages), Korean, Korean-en, Norwegian, 
+# Polish, Portuguese, Romanian, Russian, Serbian, Slovak, Slovene, Spanish, 
+# Swedish, and Ukrainian.
+
+OUTPUT_LANGUAGE        = English
+
+# This tag can be used to specify the encoding used in the generated output. 
+# The encoding is not always determined by the language that is chosen, 
+# but also whether or not the output is meant for Windows or non-Windows users. 
+# In case there is a difference, setting the USE_WINDOWS_ENCODING tag to YES 
+# forces the Windows encoding (this is the default for the Windows binary), 
+# whereas setting the tag to NO uses a Unix-style encoding (the default for 
+# all platforms other than Windows).
+
+USE_WINDOWS_ENCODING   = NO
+
+# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will 
+# include brief member descriptions after the members that are listed in 
+# the file and class documentation (similar to JavaDoc). 
+# Set to NO to disable this.
+
+BRIEF_MEMBER_DESC      = YES
+
+# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend 
+# the brief description of a member or function before the detailed description. 
+# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the 
+# brief descriptions will be completely suppressed.
+
+REPEAT_BRIEF           = NO 
+
+# This tag implements a quasi-intelligent brief description abbreviator 
+# that is used to form the text in various listings. Each string 
+# in this list, if found as the leading text of the brief description, will be 
+# stripped from the text and the result after processing the whole list, is used 
+# as the annotated text. Otherwise, the brief description is used as-is. If left 
+# blank, the following values are used ("$name" is automatically replaced with the 
+# name of the entity): "The $name class" "The $name widget" "The $name file" 
+# "is" "provides" "specifies" "contains" "represents" "a" "an" "the"
+
+ABBREVIATE_BRIEF       = 
+
+# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then 
+# Doxygen will generate a detailed section even if there is only a brief 
+# description.
+
+ALWAYS_DETAILED_SEC    = NO
+
+# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all inherited 
+# members of a class in the documentation of that class as if those members were 
+# ordinary class members. Constructors, destructors and assignment operators of 
+# the base classes will not be shown.
+
+INLINE_INHERITED_MEMB  = NO
+
+# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full 
+# path before files name in the file list and in the header files. If set 
+# to NO the shortest path that makes the file name unique will be used.
+
+FULL_PATH_NAMES        = YES
+
+# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag 
+# can be used to strip a user-defined part of the path. Stripping is 
+# only done if one of the specified strings matches the left-hand part of 
+# the path. The tag can be used to show relative paths in the file list. 
+# If left blank the directory from which doxygen is run is used as the 
+# path to strip.
+
+STRIP_FROM_PATH        = 
+
+# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of 
+# the path mentioned in the documentation of a class, which tells 
+# the reader which header file to include in order to use a class. 
+# If left blank only the name of the header file containing the class 
+# definition is used. Otherwise one should specify the include paths that 
+# are normally passed to the compiler using the -I flag.
+
+STRIP_FROM_INC_PATH    = 
+
+# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter 
+# (but less readable) file names. This can be useful is your file systems 
+# doesn't support long names like on DOS, Mac, or CD-ROM.
+
+SHORT_NAMES            = NO
+
+# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen 
+# will interpret the first line (until the first dot) of a JavaDoc-style 
+# comment as the brief description. If set to NO, the JavaDoc 
+# comments will behave just like the Qt-style comments (thus requiring an 
+# explicit @brief command for a brief description.
+
+JAVADOC_AUTOBRIEF      = NO
+
+# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen 
+# treat a multi-line C++ special comment block (i.e. a block of //! or /// 
+# comments) as a brief description. This used to be the default behaviour. 
+# The new default is to treat a multi-line C++ comment block as a detailed 
+# description. Set this tag to YES if you prefer the old behaviour instead.
+
+MULTILINE_CPP_IS_BRIEF = NO
+
+# If the DETAILS_AT_TOP tag is set to YES then Doxygen 
+# will output the detailed description near the top, like JavaDoc.
+# If set to NO, the detailed description appears after the member 
+# documentation.
+
+DETAILS_AT_TOP         = NO
+
+# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented 
+# member inherits the documentation from any documented member that it 
+# re-implements.
+
+INHERIT_DOCS           = YES
+
+# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC 
+# tag is set to YES, then doxygen will reuse the documentation of the first 
+# member in the group (if any) for the other members of the group. By default 
+# all members of a group must be documented explicitly.
+
+DISTRIBUTE_GROUP_DOC   = NO
+
+# The TAB_SIZE tag can be used to set the number of spaces in a tab. 
+# Doxygen uses this value to replace tabs by spaces in code fragments.
+
+TAB_SIZE               = 8
+
+# This tag can be used to specify a number of aliases that acts 
+# as commands in the documentation. An alias has the form "name=value". 
+# For example adding "sideeffect=\par Side Effects:\n" will allow you to 
+# put the command \sideeffect (or @sideeffect) in the documentation, which 
+# will result in a user-defined paragraph with heading "Side Effects:". 
+# You can put \n's in the value part of an alias to insert newlines.
+
+ALIASES                = 
+
+# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources 
+# only. Doxygen will then generate output that is more tailored for C. 
+# For instance, some of the names that are used will be different. The list 
+# of all members will be omitted, etc.
+
+OPTIMIZE_OUTPUT_FOR_C  = YES
+
+# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java sources 
+# only. Doxygen will then generate output that is more tailored for Java. 
+# For instance, namespaces will be presented as packages, qualified scopes 
+# will look different, etc.
+
+OPTIMIZE_OUTPUT_JAVA   = NO
+
+# Set the SUBGROUPING tag to YES (the default) to allow class member groups of 
+# the same type (for instance a group of public functions) to be put as a 
+# subgroup of that type (e.g. under the Public Functions section). Set it to 
+# NO to prevent subgrouping. Alternatively, this can be done per class using 
+# the \nosubgrouping command.
+
+SUBGROUPING            = NO
+
+#---------------------------------------------------------------------------
+# Build related configuration options
+#---------------------------------------------------------------------------
+
+# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in 
+# documentation are documented, even if no documentation was available. 
+# Private class members and static file members will be hidden unless 
+# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES
+
+EXTRACT_ALL            = YES
+
+# If the EXTRACT_PRIVATE tag is set to YES all private members of a class 
+# will be included in the documentation.
+
+EXTRACT_PRIVATE        = NO
+
+# If the EXTRACT_STATIC tag is set to YES all static members of a file 
+# will be included in the documentation.
+
+EXTRACT_STATIC         = YES 
+
+# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) 
+# defined locally in source files will be included in the documentation. 
+# If set to NO only classes defined in header files are included.
+
+EXTRACT_LOCAL_CLASSES  = YES
+
+# This flag is only useful for Objective-C code. When set to YES local 
+# methods, which are defined in the implementation section but not in 
+# the interface are included in the documentation. 
+# If set to NO (the default) only methods in the interface are included.
+
+EXTRACT_LOCAL_METHODS  = NO
+
+# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all 
+# undocumented members of documented classes, files or namespaces. 
+# If set to NO (the default) these members will be included in the 
+# various overviews, but no documentation section is generated. 
+# This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_MEMBERS     = NO
+
+# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all 
+# undocumented classes that are normally visible in the class hierarchy. 
+# If set to NO (the default) these classes will be included in the various 
+# overviews. This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_CLASSES     = NO
+
+# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all 
+# friend (class|struct|union) declarations. 
+# If set to NO (the default) these declarations will be included in the 
+# documentation.
+
+HIDE_FRIEND_COMPOUNDS  = NO
+
+# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any 
+# documentation blocks found inside the body of a function. 
+# If set to NO (the default) these blocks will be appended to the 
+# function's detailed documentation block.
+
+HIDE_IN_BODY_DOCS      = NO
+
+# The INTERNAL_DOCS tag determines if documentation 
+# that is typed after a \internal command is included. If the tag is set 
+# to NO (the default) then the documentation will be excluded. 
+# Set it to YES to include the internal documentation.
+
+INTERNAL_DOCS          = NO
+
+# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate 
+# file names in lower-case letters. If set to YES upper-case letters are also 
+# allowed. This is useful if you have classes or files whose names only differ 
+# in case and if your file system supports case sensitive file names. Windows 
+# and Mac users are advised to set this option to NO.
+
+CASE_SENSE_NAMES       = YES
+
+# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen 
+# will show members with their full class and namespace scopes in the 
+# documentation. If set to YES the scope will be hidden.
+
+HIDE_SCOPE_NAMES       = NO
+
+# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen 
+# will put a list of the files that are included by a file in the documentation 
+# of that file.
+
+SHOW_INCLUDE_FILES     = YES
+
+# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] 
+# is inserted in the documentation for inline members.
+
+INLINE_INFO            = YES
+
+# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen 
+# will sort the (detailed) documentation of file and class members 
+# alphabetically by member name. If set to NO the members will appear in 
+# declaration order.
+
+SORT_MEMBER_DOCS       = YES
+
+# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the 
+# brief documentation of file, namespace and class members alphabetically 
+# by member name. If set to NO (the default) the members will appear in 
+# declaration order.
+
+SORT_BRIEF_DOCS        = NO
+
+# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be 
+# sorted by fully-qualified names, including namespaces. If set to 
+# NO (the default), the class list will be sorted only by class name, 
+# not including the namespace part. 
+# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
+# Note: This option applies only to the class list, not to the 
+# alphabetical list.
+
+SORT_BY_SCOPE_NAME     = NO
+
+# The GENERATE_TODOLIST tag can be used to enable (YES) or 
+# disable (NO) the todo list. This list is created by putting \todo 
+# commands in the documentation.
+
+GENERATE_TODOLIST      = YES
+
+# The GENERATE_TESTLIST tag can be used to enable (YES) or 
+# disable (NO) the test list. This list is created by putting \test 
+# commands in the documentation.
+
+GENERATE_TESTLIST      = YES
+
+# The GENERATE_BUGLIST tag can be used to enable (YES) or 
+# disable (NO) the bug list. This list is created by putting \bug 
+# commands in the documentation.
+
+GENERATE_BUGLIST       = YES
+
+# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or 
+# disable (NO) the deprecated list. This list is created by putting 
+# \deprecated commands in the documentation.
+
+GENERATE_DEPRECATEDLIST= YES
+
+# The ENABLED_SECTIONS tag can be used to enable conditional 
+# documentation sections, marked by \if sectionname ... \endif.
+
+ENABLED_SECTIONS       = 
+
+# The MAX_INITIALIZER_LINES tag determines the maximum number of lines 
+# the initial value of a variable or define consists of for it to appear in 
+# the documentation. If the initializer consists of more lines than specified 
+# here it will be hidden. Use a value of 0 to hide initializers completely. 
+# The appearance of the initializer of individual variables and defines in the 
+# documentation can be controlled using \showinitializer or \hideinitializer 
+# command in the documentation regardless of this setting.
+
+MAX_INITIALIZER_LINES  = 30
+
+# Set the SHOW_USED_FILES tag to NO to disable the list of files generated 
+# at the bottom of the documentation of classes and structs. If set to YES the 
+# list will mention the files that were used to generate the documentation.
+
+SHOW_USED_FILES        = YES
+
+#---------------------------------------------------------------------------
+# configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+
+# The QUIET tag can be used to turn on/off the messages that are generated 
+# by doxygen. Possible values are YES and NO. If left blank NO is used.
+
+QUIET                  = NO
+
+# The WARNINGS tag can be used to turn on/off the warning messages that are 
+# generated by doxygen. Possible values are YES and NO. If left blank 
+# NO is used.
+
+WARNINGS               = YES
+
+# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings 
+# for undocumented members. If EXTRACT_ALL is set to YES then this flag will 
+# automatically be disabled.
+
+WARN_IF_UNDOCUMENTED   = YES
+
+# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for 
+# potential errors in the documentation, such as not documenting some 
+# parameters in a documented function, or documenting parameters that 
+# don't exist or using markup commands wrongly.
+
+WARN_IF_DOC_ERROR      = YES
+
+# The WARN_FORMAT tag determines the format of the warning messages that 
+# doxygen can produce. The string should contain the $file, $line, and $text 
+# tags, which will be replaced by the file and line number from which the 
+# warning originated and the warning text.
+
+WARN_FORMAT            = "$file:$line: $text"
+
+# The WARN_LOGFILE tag can be used to specify a file to which warning 
+# and error messages should be written. If left blank the output is written 
+# to stderr.
+
+WARN_LOGFILE           = 
+
+#---------------------------------------------------------------------------
+# configuration options related to the input files
+#---------------------------------------------------------------------------
+
+# The INPUT tag can be used to specify the files and/or directories that contain 
+# documented source files. You may enter file names like "myfile.cpp" or 
+# directories like "/usr/src/myproject". Separate the files or directories 
+# with spaces.
+
+INPUT                  = ../../cmds/nvram.c ../../cmds/nvram.h
+
+# If the value of the INPUT tag contains directories, you can use the 
+# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp 
+# and *.h) to filter out the source-files in the directories. If left 
+# blank the following patterns are tested: 
+# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx *.hpp 
+# *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm
+
+FILE_PATTERNS          = 
+
+# The RECURSIVE tag can be used to turn specify whether or not subdirectories 
+# should be searched for input files as well. Possible values are YES and NO. 
+# If left blank NO is used.
+
+RECURSIVE              = NO
+
+# The EXCLUDE tag can be used to specify files and/or directories that should 
+# excluded from the INPUT source files. This way you can easily exclude a 
+# subdirectory from a directory tree whose root is specified with the INPUT tag.
+
+EXCLUDE                = 
+
+# The EXCLUDE_SYMLINKS tag can be used select whether or not files or directories 
+# that are symbolic links (a Unix filesystem feature) are excluded from the input.
+
+EXCLUDE_SYMLINKS       = NO
+
+# If the value of the INPUT tag contains directories, you can use the 
+# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude 
+# certain files from those directories.
+
+EXCLUDE_PATTERNS       = 
+
+# The EXAMPLE_PATH tag can be used to specify one or more files or 
+# directories that contain example code fragments that are included (see 
+# the \include command).
+
+EXAMPLE_PATH           = 
+
+# If the value of the EXAMPLE_PATH tag contains directories, you can use the 
+# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp 
+# and *.h) to filter out the source-files in the directories. If left 
+# blank all files are included.
+
+EXAMPLE_PATTERNS       = 
+
+# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be 
+# searched for input files to be used with the \include or \dontinclude 
+# commands irrespective of the value of the RECURSIVE tag. 
+# Possible values are YES and NO. If left blank NO is used.
+
+EXAMPLE_RECURSIVE      = NO
+
+# The IMAGE_PATH tag can be used to specify one or more files or 
+# directories that contain image that are included in the documentation (see 
+# the \image command).
+
+IMAGE_PATH             = 
+
+# The INPUT_FILTER tag can be used to specify a program that doxygen should 
+# invoke to filter for each input file. Doxygen will invoke the filter program 
+# by executing (via popen()) the command <filter> <input-file>, where <filter> 
+# is the value of the INPUT_FILTER tag, and <input-file> is the name of an 
+# input file. Doxygen will then use the output that the filter program writes 
+# to standard output.  If FILTER_PATTERNS is specified, this tag will be 
+# ignored.
+
+INPUT_FILTER           = 
+
+# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern 
+# basis.  Doxygen will compare the file name with each pattern and apply the 
+# filter if there is a match.  The filters are a list of the form: 
+# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further 
+# info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER 
+# is applied to all files.
+
+FILTER_PATTERNS        = 
+
+# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using 
+# INPUT_FILTER) will be used to filter the input files when producing source 
+# files to browse (i.e. when SOURCE_BROWSER is set to YES).
+
+FILTER_SOURCE_FILES    = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to source browsing
+#---------------------------------------------------------------------------
+
+# If the SOURCE_BROWSER tag is set to YES then a list of source files will 
+# be generated. Documented entities will be cross-referenced with these sources. 
+# Note: To get rid of all source code in the generated output, make sure also 
+# VERBATIM_HEADERS is set to NO.
+
+SOURCE_BROWSER         = NO
+
+# Setting the INLINE_SOURCES tag to YES will include the body 
+# of functions and classes directly in the documentation.
+
+INLINE_SOURCES         = NO
+
+# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct 
+# doxygen to hide any special comment blocks from generated source code 
+# fragments. Normal C and C++ comments will always remain visible.
+
+STRIP_CODE_COMMENTS    = YES
+
+# If the REFERENCED_BY_RELATION tag is set to YES (the default) 
+# then for each documented function all documented 
+# functions referencing it will be listed.
+
+REFERENCED_BY_RELATION = YES
+
+# If the REFERENCES_RELATION tag is set to YES (the default) 
+# then for each documented function all documented entities 
+# called/used by that function will be listed.
+
+REFERENCES_RELATION    = YES
+
+# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen 
+# will generate a verbatim copy of the header file for each class for 
+# which an include is specified. Set to NO to disable this.
+
+VERBATIM_HEADERS       = YES
+
+#---------------------------------------------------------------------------
+# configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+
+# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index 
+# of all compounds will be generated. Enable this if the project 
+# contains a lot of classes, structs, unions or interfaces.
+
+ALPHABETICAL_INDEX     = NO
+
+# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then 
+# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns 
+# in which this list will be split (can be a number in the range [1..20])
+
+COLS_IN_ALPHA_INDEX    = 5
+
+# In case all classes in a project start with a common prefix, all 
+# classes will be put under the same header in the alphabetical index. 
+# The IGNORE_PREFIX tag can be used to specify one or more prefixes that 
+# should be ignored while generating the index headers.
+
+IGNORE_PREFIX          = 
+
+#---------------------------------------------------------------------------
+# configuration options related to the HTML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_HTML tag is set to YES (the default) Doxygen will 
+# generate HTML output.
+
+GENERATE_HTML          = YES
+
+# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. 
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
+# put in front of it. If left blank `html' will be used as the default path.
+
+HTML_OUTPUT            = html
+
+# The HTML_FILE_EXTENSION tag can be used to specify the file extension for 
+# each generated HTML page (for example: .htm,.php,.asp). If it is left blank 
+# doxygen will generate files with .html extension.
+
+HTML_FILE_EXTENSION    = .html
+
+# The HTML_HEADER tag can be used to specify a personal HTML header for 
+# each generated HTML page. If it is left blank doxygen will generate a 
+# standard header.
+
+HTML_HEADER            = 
+
+# The HTML_FOOTER tag can be used to specify a personal HTML footer for 
+# each generated HTML page. If it is left blank doxygen will generate a 
+# standard footer.
+
+HTML_FOOTER            = 
+
+# The HTML_STYLESHEET tag can be used to specify a user-defined cascading 
+# style sheet that is used by each HTML page. It can be used to 
+# fine-tune the look of the HTML output. If the tag is left blank doxygen 
+# will generate a default style sheet. Note that doxygen will try to copy 
+# the style sheet file to the HTML output directory, so don't put your own 
+# stylesheet in the HTML output directory as well, or it will be erased!
+
+HTML_STYLESHEET        = 
+
+# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, 
+# files or namespaces will be aligned in HTML using tables. If set to 
+# NO a bullet list will be used.
+
+HTML_ALIGN_MEMBERS     = YES
+
+# If the GENERATE_HTMLHELP tag is set to YES, additional index files 
+# will be generated that can be used as input for tools like the 
+# Microsoft HTML help workshop to generate a compressed HTML help file (.chm) 
+# of the generated HTML documentation.
+
+GENERATE_HTMLHELP      = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can 
+# be used to specify the file name of the resulting .chm file. You 
+# can add a path in front of the file if the result should not be 
+# written to the html output directory.
+
+CHM_FILE               = 
+
+# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can 
+# be used to specify the location (absolute path including file name) of 
+# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run 
+# the HTML help compiler on the generated index.hhp.
+
+HHC_LOCATION           = 
+
+# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag 
+# controls if a separate .chi index file is generated (YES) or that 
+# it should be included in the master .chm file (NO).
+
+GENERATE_CHI           = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag 
+# controls whether a binary table of contents is generated (YES) or a 
+# normal table of contents (NO) in the .chm file.
+
+BINARY_TOC             = NO
+
+# The TOC_EXPAND flag can be set to YES to add extra items for group members 
+# to the contents of the HTML help documentation and to the tree view.
+
+TOC_EXPAND             = NO
+
+# The DISABLE_INDEX tag can be used to turn on/off the condensed index at 
+# top of each HTML page. The value NO (the default) enables the index and 
+# the value YES disables it.
+
+DISABLE_INDEX          = NO
+
+# This tag can be used to set the number of enum values (range [1..20]) 
+# that doxygen will group on one line in the generated HTML documentation.
+
+ENUM_VALUES_PER_LINE   = 4
+
+# If the GENERATE_TREEVIEW tag is set to YES, a side panel will be
+# generated containing a tree-like index structure (just like the one that 
+# is generated for HTML Help). For this to work a browser that supports 
+# JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+, 
+# Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are 
+# probably better off using the HTML help feature.
+
+GENERATE_TREEVIEW      = NO
+
+# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be 
+# used to set the initial width (in pixels) of the frame in which the tree 
+# is shown.
+
+TREEVIEW_WIDTH         = 250
+
+#---------------------------------------------------------------------------
+# configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will 
+# generate Latex output.
+
+GENERATE_LATEX         = YES
+
+# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. 
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
+# put in front of it. If left blank `latex' will be used as the default path.
+
+LATEX_OUTPUT           = latex
+
+# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be 
+# invoked. If left blank `latex' will be used as the default command name.
+
+LATEX_CMD_NAME         = latex
+
+# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to 
+# generate index for LaTeX. If left blank `makeindex' will be used as the 
+# default command name.
+
+MAKEINDEX_CMD_NAME     = makeindex
+
+# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact 
+# LaTeX documents. This may be useful for small projects and may help to 
+# save some trees in general.
+
+COMPACT_LATEX          = NO
+
+# The PAPER_TYPE tag can be used to set the paper type that is used 
+# by the printer. Possible values are: a4, a4wide, letter, legal and 
+# executive. If left blank a4wide will be used.
+
+PAPER_TYPE             = a4wide
+
+# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX 
+# packages that should be included in the LaTeX output.
+
+EXTRA_PACKAGES         = 
+
+# The LATEX_HEADER tag can be used to specify a personal LaTeX header for 
+# the generated latex document. The header should contain everything until 
+# the first chapter. If it is left blank doxygen will generate a 
+# standard header. Notice: only use this tag if you know what you are doing!
+
+LATEX_HEADER           = 
+
+# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated 
+# is prepared for conversion to pdf (using ps2pdf). The pdf file will 
+# contain links (just like the HTML output) instead of page references 
+# This makes the output suitable for online browsing using a pdf viewer.
+
+PDF_HYPERLINKS         = NO
+
+# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of 
+# plain latex in the generated Makefile. Set this option to YES to get a 
+# higher quality PDF documentation.
+
+USE_PDFLATEX           = NO
+
+# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. 
+# command to the generated LaTeX files. This will instruct LaTeX to keep 
+# running if errors occur, instead of asking the user for help. 
+# This option is also used when generating formulas in HTML.
+
+LATEX_BATCHMODE        = NO
+
+# If LATEX_HIDE_INDICES is set to YES then doxygen will not 
+# include the index chapters (such as File Index, Compound Index, etc.) 
+# in the output.
+
+LATEX_HIDE_INDICES     = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the RTF output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output 
+# The RTF output is optimized for Word 97 and may not look very pretty with 
+# other RTF readers or editors.
+
+GENERATE_RTF           = NO
+
+# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. 
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
+# put in front of it. If left blank `rtf' will be used as the default path.
+
+RTF_OUTPUT             = rtf
+
+# If the COMPACT_RTF tag is set to YES Doxygen generates more compact 
+# RTF documents. This may be useful for small projects and may help to 
+# save some trees in general.
+
+COMPACT_RTF            = NO
+
+# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated 
+# will contain hyperlink fields. The RTF file will 
+# contain links (just like the HTML output) instead of page references. 
+# This makes the output suitable for online browsing using WORD or other 
+# programs which support those fields. 
+# Note: wordpad (write) and others do not support links.
+
+RTF_HYPERLINKS         = NO
+
+# Load stylesheet definitions from file. Syntax is similar to doxygen's 
+# config file, i.e. a series of assignments. You only have to provide 
+# replacements, missing definitions are set to their default value.
+
+RTF_STYLESHEET_FILE    = 
+
+# Set optional variables used in the generation of an rtf document. 
+# Syntax is similar to doxygen's config file.
+
+RTF_EXTENSIONS_FILE    = 
+
+#---------------------------------------------------------------------------
+# configuration options related to the man page output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_MAN tag is set to YES (the default) Doxygen will 
+# generate man pages
+
+GENERATE_MAN           = NO
+
+# The MAN_OUTPUT tag is used to specify where the man pages will be put. 
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
+# put in front of it. If left blank `man' will be used as the default path.
+
+MAN_OUTPUT             = man
+
+# The MAN_EXTENSION tag determines the extension that is added to 
+# the generated man pages (default is the subroutine's section .3)
+
+MAN_EXTENSION          = .3
+
+# If the MAN_LINKS tag is set to YES and Doxygen generates man output, 
+# then it will generate one additional man file for each entity 
+# documented in the real man page(s). These additional files 
+# only source the real man page, but without them the man command 
+# would be unable to find the correct page. The default is NO.
+
+MAN_LINKS              = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the XML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_XML tag is set to YES Doxygen will 
+# generate an XML file that captures the structure of 
+# the code including all documentation.
+
+GENERATE_XML           = NO
+
+# The XML_OUTPUT tag is used to specify where the XML pages will be put. 
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
+# put in front of it. If left blank `xml' will be used as the default path.
+
+XML_OUTPUT             = xml
+
+# The XML_SCHEMA tag can be used to specify an XML schema, 
+# which can be used by a validating XML parser to check the 
+# syntax of the XML files.
+
+XML_SCHEMA             = 
+
+# The XML_DTD tag can be used to specify an XML DTD, 
+# which can be used by a validating XML parser to check the 
+# syntax of the XML files.
+
+XML_DTD                = 
+
+# If the XML_PROGRAMLISTING tag is set to YES Doxygen will 
+# dump the program listings (including syntax highlighting 
+# and cross-referencing information) to the XML output. Note that 
+# enabling this will significantly increase the size of the XML output.
+
+XML_PROGRAMLISTING     = YES
+
+#---------------------------------------------------------------------------
+# configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will 
+# generate an AutoGen Definitions (see autogen.sf.net) file 
+# that captures the structure of the code including all 
+# documentation. Note that this feature is still experimental 
+# and incomplete at the moment.
+
+GENERATE_AUTOGEN_DEF   = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the Perl module output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_PERLMOD tag is set to YES Doxygen will 
+# generate a Perl module file that captures the structure of 
+# the code including all documentation. Note that this 
+# feature is still experimental and incomplete at the 
+# moment.
+
+GENERATE_PERLMOD       = NO
+
+# If the PERLMOD_LATEX tag is set to YES Doxygen will generate 
+# the necessary Makefile rules, Perl scripts and LaTeX code to be able 
+# to generate PDF and DVI output from the Perl module output.
+
+PERLMOD_LATEX          = NO
+
+# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be 
+# nicely formatted so it can be parsed by a human reader.  This is useful 
+# if you want to understand what is going on.  On the other hand, if this 
+# tag is set to NO the size of the Perl module output will be much smaller 
+# and Perl will parse it just the same.
+
+PERLMOD_PRETTY         = YES
+
+# The names of the make variables in the generated doxyrules.make file 
+# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. 
+# This is useful so different doxyrules.make files included by the same 
+# Makefile don't overwrite each other's variables.
+
+PERLMOD_MAKEVAR_PREFIX = 
+
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor   
+#---------------------------------------------------------------------------
+
+# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will 
+# evaluate all C-preprocessor directives found in the sources and include 
+# files.
+
+ENABLE_PREPROCESSING   = YES
+
+# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro 
+# names in the source code. If set to NO (the default) only conditional 
+# compilation will be performed. Macro expansion can be done in a controlled 
+# way by setting EXPAND_ONLY_PREDEF to YES.
+
+MACRO_EXPANSION        = NO
+
+# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES 
+# then the macro expansion is limited to the macros specified with the 
+# PREDEFINED and EXPAND_AS_PREDEFINED tags.
+
+EXPAND_ONLY_PREDEF     = NO
+
+# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files 
+# in the INCLUDE_PATH (see below) will be search if a #include is found.
+
+SEARCH_INCLUDES        = YES
+
+# The INCLUDE_PATH tag can be used to specify one or more directories that 
+# contain include files that are not input files but should be processed by 
+# the preprocessor.
+
+INCLUDE_PATH           = 
+
+# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard 
+# patterns (like *.h and *.hpp) to filter out the header-files in the 
+# directories. If left blank, the patterns specified with FILE_PATTERNS will 
+# be used.
+
+INCLUDE_FILE_PATTERNS  = 
+
+# The PREDEFINED tag can be used to specify one or more macro names that 
+# are defined before the preprocessor is started (similar to the -D option of 
+# gcc). The argument of the tag is a list of macros of the form: name 
+# or name=definition (no spaces). If the definition and the = are 
+# omitted =1 is assumed.
+
+PREDEFINED             = 
+
+# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then 
+# this tag can be used to specify a list of macro names that should be expanded. 
+# The macro definition that is found in the sources will be used. 
+# Use the PREDEFINED tag if you want to use a different macro definition.
+
+EXPAND_AS_DEFINED      = 
+
+# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then 
+# doxygen's preprocessor will remove all function-like macros that are alone 
+# on a line, have an all uppercase name, and do not end with a semicolon. Such 
+# function macros are typically used for boiler-plate code, and will confuse the 
+# parser if not removed.
+
+SKIP_FUNCTION_MACROS   = YES
+
+#---------------------------------------------------------------------------
+# Configuration::additions related to external references   
+#---------------------------------------------------------------------------
+
+# The TAGFILES option can be used to specify one or more tagfiles. 
+# Optionally an initial location of the external documentation 
+# can be added for each tagfile. The format of a tag file without 
+# this location is as follows: 
+#   TAGFILES = file1 file2 ... 
+# Adding location for the tag files is done as follows: 
+#   TAGFILES = file1=loc1 "file2 = loc2" ... 
+# where "loc1" and "loc2" can be relative or absolute paths or 
+# URLs. If a location is present for each tag, the installdox tool 
+# does not have to be run to correct the links.
+# Note that each tag file must have a unique name
+# (where the name does NOT include the path)
+# If a tag file is not located in the directory in which doxygen 
+# is run, you must also specify the path to the tagfile here.
+
+TAGFILES               = 
+
+# When a file name is specified after GENERATE_TAGFILE, doxygen will create 
+# a tag file that is based on the input files it reads.
+
+GENERATE_TAGFILE       = 
+
+# If the ALLEXTERNALS tag is set to YES all external classes will be listed 
+# in the class index. If set to NO only the inherited external classes 
+# will be listed.
+
+ALLEXTERNALS           = NO
+
+# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed 
+# in the modules index. If set to NO, only the current project's groups will 
+# be listed.
+
+EXTERNAL_GROUPS        = YES
+
+# The PERL_PATH should be the absolute path and name of the perl script 
+# interpreter (i.e. the result of `which perl').
+
+PERL_PATH              = /usr/bin/perl
+
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool   
+#---------------------------------------------------------------------------
+
+# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will 
+# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base or 
+# super classes. Setting the tag to NO turns the diagrams off. Note that this 
+# option is superseded by the HAVE_DOT option below. This is only a fallback. It is 
+# recommended to install and use dot, since it yields more powerful graphs.
+
+CLASS_DIAGRAMS         = YES
+
+# If set to YES, the inheritance and collaboration graphs will hide 
+# inheritance and usage relations if the target is undocumented 
+# or is not a class.
+
+HIDE_UNDOC_RELATIONS   = YES
+
+# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is 
+# available from the path. This tool is part of Graphviz, a graph visualization 
+# toolkit from AT&T and Lucent Bell Labs. The other options in this section 
+# have no effect if this option is set to NO (the default)
+
+HAVE_DOT               = NO
+
+# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen 
+# will generate a graph for each documented class showing the direct and 
+# indirect inheritance relations. Setting this tag to YES will force the 
+# the CLASS_DIAGRAMS tag to NO.
+
+CLASS_GRAPH            = YES
+
+# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen 
+# will generate a graph for each documented class showing the direct and 
+# indirect implementation dependencies (inheritance, containment, and 
+# class references variables) of the class with other documented classes.
+
+COLLABORATION_GRAPH    = YES
+
+# If the UML_LOOK tag is set to YES doxygen will generate inheritance and 
+# collaboration diagrams in a style similar to the OMG's Unified Modeling 
+# Language.
+
+UML_LOOK               = NO
+
+# If set to YES, the inheritance and collaboration graphs will show the 
+# relations between templates and their instances.
+
+TEMPLATE_RELATIONS     = NO
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT 
+# tags are set to YES then doxygen will generate a graph for each documented 
+# file showing the direct and indirect include dependencies of the file with 
+# other documented files.
+
+INCLUDE_GRAPH          = YES
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and 
+# HAVE_DOT tags are set to YES then doxygen will generate a graph for each 
+# documented header file showing the documented files that directly or 
+# indirectly include this file.
+
+INCLUDED_BY_GRAPH      = YES
+
+# If the CALL_GRAPH and HAVE_DOT tags are set to YES then doxygen will 
+# generate a call dependency graph for every global function or class method. 
+# Note that enabling this option will significantly increase the time of a run. 
+# So in most cases it will be better to enable call graphs for selected 
+# functions only using the \callgraph command.
+
+CALL_GRAPH             = NO
+
+# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen 
+# will graphical hierarchy of all classes instead of a textual one.
+
+GRAPHICAL_HIERARCHY    = YES
+
+# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images 
+# generated by dot. Possible values are png, jpg, or gif
+# If left blank png will be used.
+
+DOT_IMAGE_FORMAT       = png
+
+# The tag DOT_PATH can be used to specify the path where the dot tool can be 
+# found. If left blank, it is assumed the dot tool can be found on the path.
+
+DOT_PATH               = 
+
+# The DOTFILE_DIRS tag can be used to specify one or more directories that 
+# contain dot files that are included in the documentation (see the 
+# \dotfile command).
+
+DOTFILE_DIRS           = 
+
+# The MAX_DOT_GRAPH_WIDTH tag can be used to set the maximum allowed width 
+# (in pixels) of the graphs generated by dot. If a graph becomes larger than 
+# this value, doxygen will try to truncate the graph, so that it fits within 
+# the specified constraint. Beware that most browsers cannot cope with very 
+# large images.
+
+MAX_DOT_GRAPH_WIDTH    = 1024
+
+# The MAX_DOT_GRAPH_HEIGHT tag can be used to set the maximum allows height 
+# (in pixels) of the graphs generated by dot. If a graph becomes larger than 
+# this value, doxygen will try to truncate the graph, so that it fits within 
+# the specified constraint. Beware that most browsers cannot cope with very 
+# large images.
+
+MAX_DOT_GRAPH_HEIGHT   = 1024
+
+# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the 
+# graphs generated by dot. A depth value of 3 means that only nodes reachable 
+# from the root by following a path via at most 3 edges will be shown. Nodes that 
+# lay further from the root node will be omitted. Note that setting this option to 
+# 1 or 2 may greatly reduce the computation time needed for large code bases. Also 
+# note that a graph may be further truncated if the graph's image dimensions are 
+# not sufficient to fit the graph (see MAX_DOT_GRAPH_WIDTH and MAX_DOT_GRAPH_HEIGHT). 
+# If 0 is used for the depth value (the default), the graph is not depth-constrained.
+
+MAX_DOT_GRAPH_DEPTH    = 0
+
+# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will 
+# generate a legend page explaining the meaning of the various boxes and 
+# arrows in the dot generated graphs.
+
+GENERATE_LEGEND        = YES
+
+# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will 
+# remove the intermediate dot files that are used to generate 
+# the various graphs.
+
+DOT_CLEANUP            = YES
+
+#---------------------------------------------------------------------------
+# Configuration::additions related to the search engine   
+#---------------------------------------------------------------------------
+
+# The SEARCHENGINE tag specifies whether or not a search engine should be 
+# used. If set to NO the values of all tags below this one will be ignored.
+
+SEARCHENGINE           = NO

Added: trunk/powerpc-ibm-utils/doc/ofpathname.8
===================================================================
--- trunk/powerpc-ibm-utils/doc/ofpathname.8	                        (rev 0)
+++ trunk/powerpc-ibm-utils/doc/ofpathname.8	2006-09-25 09:08:44 UTC (rev 164)
@@ -0,0 +1,30 @@
+.\"
+.\" Copyright (C) 2004 International Business Machines
+.\" Nathan Fontenot <nfont at austin.ibm.com>
+.\"
+.TH OFPATHNAME 8 "April 2004" Linux "Linux on Power Service Tools"
+.SH NAME
+ofpathname \- translate between Open Firmware and logical device names
+.SH SYNOPSIS
+\fB/usr/sbin/ofpathname \fR[\fB-lq\fR] \fIname
+.SH DESCRIPTION
+.I Ofpathname
+provides the ability to translate logical device names to their Open Firmware
+device path names for PoowerPC-64 systems.  It can also translate an Open
+Firmware device path to its logical device name using the -l option.
+.SH OPTIONS
+.TP
+\fB\-l
+Translate the \fIname \fRparameter to the corresponding logical device name.
+.TP
+\fB\--quiet \fR(\fB\-q\fR)
+Do not report any failures, exit quietly.
+.TP
+\fB\--help \fR(\fB\-?\fR)
+print usage information.
+.SH AUTHOR
+Written by Nathan Fontenot
+.SH "SEE ALSO"
+.BR bootlist (8),
+.BR nvram (8)
+

Added: trunk/powerpc-ibm-utils/doc/snap.8
===================================================================
--- trunk/powerpc-ibm-utils/doc/snap.8	                        (rev 0)
+++ trunk/powerpc-ibm-utils/doc/snap.8	2006-09-25 09:08:44 UTC (rev 164)
@@ -0,0 +1,51 @@
+.\"
+.\" Copyright (C) 2002 - 2004 International Business Machines
+.\" Todd Inglett <tinglett at vnet.ibm.com>
+.\" Michael Strosaker <strosake at us.ibm.com>
+.\"
+.TH SNAP 8 "14 November 2003" Linux "Linux on Power Service Tools"
+.SH NAME
+snap \- generate a configuration snapshot for service
+.SH SYNOPSIS
+\fB/usr/sbin/snap \fR[\fB-ahv\fR] [\fB-d \fIdir\fR] [\fB-o \fIfile\fR]
+.SH DESCRIPTION
+The
+.I snap
+script copies several system status and config files and the output of
+several commands from the system into snap.tar.gz in the current directory.
+System servicers may ask that this be run in order collect data to diagnose
+a problem.
+
+.SH OPTIONS
+.TP
+.B \-a
+All data;  collect detailed information (more files and output).
+.TP
+\fB\-d \fIdir
+Specify the directory where files and ouput will be collected (default:
+/tmp/ibmsupt).
+.TP
+.B \-h
+Print a help message.
+.TP
+\fB\-o \fIfile
+Specify the output path and filename (.tar required, .tar.gz optional)
+(default: snap.tar.gz).
+.TP
+.B \-v
+verbose output
+
+.SH FILES
+These are some of the files that are archived:
+.P
+/var/log/messages
+.br
+/var/log/platform
+.br
+/var/log/scanoutlog.*
+.br
+/proc (select files)
+.br
+/dev/nvram
+.br
+/etc/yaboot.conf

Added: trunk/powerpc-ibm-utils/powerpc-utils.spec
===================================================================
--- trunk/powerpc-ibm-utils/powerpc-utils.spec	                        (rev 0)
+++ trunk/powerpc-ibm-utils/powerpc-utils.spec	2006-09-25 09:08:44 UTC (rev 164)
@@ -0,0 +1,29 @@
+%define name powerpc-utils
+%define version 1.0.2
+%define release 1
+Summary:	Utilities for PowerPC Platforms
+Name:		%{name}
+Version:	%{version}
+Release:	%{release}
+License:	IBM Common Public License (CPL)
+Group:		System Environment
+Source0:	N/A
+BuildRoot:	/tmp/%{name}-buildroot/
+Requires:	/bin/bash, /bin/sed, /usr/bin/perl
+
+%description
+Utilities for PowerPC Platforms.
+
+%files 
+%defattr(-,root,root)
+/usr/share/doc/packages/powerpc-utils/README
+/usr/share/doc/packages/powerpc-utils/COPYRIGHT
+/usr/sbin/nvram
+/usr/sbin/snap
+/usr/sbin/bootlist
+/usr/sbin/ofpathname
+/usr/share/man/man8/nvram.8
+/usr/share/man/man8/snap.8
+/usr/share/man/man8/bootlist.8
+/usr/share/man/man8/ofpathname.8
+

Added: trunk/powerpc-ibm-utils/rules.mk
===================================================================
--- trunk/powerpc-ibm-utils/rules.mk	                        (rev 0)
+++ trunk/powerpc-ibm-utils/rules.mk	2006-09-25 09:08:44 UTC (rev 164)
@@ -0,0 +1,206 @@
+#
+# Common Makefile definitions
+#
+
+PWD = $(shell echo `pwd`)
+INSTALL = /usr/bin/install
+
+DOXYGEN = `which doxygen`
+
+# Name of the rpm spec file
+SPECFILENAME = powerpc-utils.spec
+
+# resolves the root directory at which this build is occuring
+ROOT_DIR =                                              \
+        $(shell                                         \
+        while [[ `pwd` != "/" ]];                       \
+        do                                              \
+                if [[ -f `pwd`/$(SPECFILENAME) ]];      \
+                then                                    \
+                        echo `pwd`;                     \
+                        break;                          \
+                fi;                                     \
+                cd ..;                                  \
+        done;)
+
+# Full path to the rpm specfile
+SPECFILE = $(ROOT_DIR)/$(SPECFILENAME)
+
+# Find the correct command to build RPM's
+RPM =							\
+	$(shell						\
+	if [[ -a /bin/rpmbuild ]]; then			\
+		echo "/bin/rpmbuild";			\
+	elif [[ -a /usr/bin/rpmbuild ]]; then		\
+		echo "/usr/bin/rpmbuild";		\
+	elif [[ -a /bin/rpm ]]; then			\
+		echo "/bin/rpm";			\
+	elif [[ -a /usr/bin/rpm ]]; then		\
+		echo "/usr/bin/rpm";			\
+	else						\
+		echo "rpm seems to be non-existant";	\
+	fi;)
+
+# Pull the version, release and project name info from the spec file
+VERSION	:= $(shell echo `grep "define version" $(SPECFILE) | cut -d' ' -f3`)
+RELEASE	:= $(shell echo `grep "define release" $(SPECFILE) | cut -d' ' -f3`)
+PROJECT := $(shell echo `grep "define name" $(SPECFILE) | cut -d' ' -f3`)
+
+# Generate the Major, Minor and Revision numbers from the version
+VERSION_LIST := $(subst ., ,$(VERSION))
+MAJOR_NO := $(word 1,$(VERSION_LIST))
+MINOR_NO := $(word 2,$(VERSION_LIST))
+REVISION_NO := $(word 3,$(VERSION_LIST))
+
+# Set this if you want to install to a base directory other than /
+DESTDIR ?= 
+
+# Standard base directory names
+BIN_DIR = /usr/bin
+SBIN_DIR = /usr/sbin
+LIB_DIR = /usr/lib
+INC_DIR = /usr/include
+DOC_DIR = /usr/share/doc/packages/$(PROJECT)
+MAN_DIR = /usr/share/man/man8
+
+# Shipdir is where we put all the files to build an rpm
+SHIPDIR = /tmp/$(PROJECT)-buildroot
+
+# Source tarball name and build directory
+TARBALL = $(PROJECT)-$(VERSION).tar.gz
+TARBALL_FILES = Makefile rules.mk $(SPECFILENAME)
+TB_DIR = $(PROJECT)-$(VERSION)
+
+# Build a tarball of the source code
+BUILD_TARBALL =						\
+	$(shell						\
+	echo CVS > ./ignore;				\
+	mkdir $(TB_DIR);				\
+	cp -R $(SUBDIRS) $(TARBALL_FILES) $(TB_DIR);	\
+	tar -zcf $(TARBALL) -X ./ignore $(TB_DIR);	\
+	rm -rf ./ignore $(TB_DIR);)
+
+# Development snapshot builds
+DEVBALL = $(PROJECT)-$(VERSION)-`date +%Y%m%d`.tar.gz
+
+# Build a development snapshot of the source code
+BUILD_DEVBALL =						\
+	$(shell						\
+	echo CVS > ./ignore;				\
+	mkdir $(TB_DIR);				\
+	cp -R $(SUBDIRS) $(TARBALL_FILES) $(TB_DIR);	\
+	tar -zcf $(DEVBALL) -X ./ignore $(TB_DIR);	\
+	rm -rf ./ignore $(TB_DIR);)
+
+# Current build directory
+WORK_DIR = $(patsubst /%,%,$(subst $(ROOT_DIR),,$(PWD)))
+
+# You should always build with -Wall
+CFLAGS += -Wall
+
+# Uncomment this for debug builds
+CFLAGS += -g -DDEBUG 
+
+# If you wish to have a log of installed files, define the file here
+INSTALL_LOG ?= $(ROOT_DIR)/install.log
+
+#
+# install_files - Install file(s) in the given location
+#
+#  $1 - files to be installed
+#  $2 - permissions to install file with
+#  $3 - directory to install file to
+define install_files
+	$(INSTALL) -d -m 755 $3;
+	$(foreach f,$1,							\
+		echo "Installing $(patsubst /%,%,$(WORK_DIR)/$f)";	\
+		$(INSTALL) -m $2 $f $3;					\
+		$(if $(INSTALL_LOG),echo $3/$f >> $(INSTALL_LOG);,))
+endef
+
+#
+# The following are wrappers for calls to install_files for
+# installing files in known locations (i.e. /usr/bin).  The args
+# to each of the wrappers are the same.
+#
+#  $1 - files to be installed
+#  $2 - prefix to install path for the files
+#
+define install_bin
+	$(call install_files,$1,755,$2/$(BIN_DIR))
+endef
+
+define install_sbin
+	$(call install_files,$1,744,$2/$(SBIN_DIR))
+endef
+
+define install_lib
+	$(call install_files,$1,755,$2/$(LIB_DIR))
+endef
+
+define install_inc
+	$(call install_files,$1,644,$2/$(INC_DIR))
+endef
+
+define install_doc
+	$(call install_files,$1,644,$2/$(DOC_DIR))
+endef
+
+define install_man
+	$(call install_files,$1,644,$2/$(MAN_DIR))
+endef
+
+#
+# uninstall_files - Uninstall file(s)
+#
+#  $1 - files to be uninstalled
+#  $2 - the directory the files to uninstall live in
+define uninstall_files
+	$(foreach f,$1,							\
+		echo "Un-installing $(patsubst /%,%,$(WORK_DIR)/$f)";	\
+		rm -f $2/$f;) 
+endef
+
+#
+# The following are wrappers for calls to uninstall_files for
+# removing files in known locations (i.e. /usr/bin).  The args
+# to each of the wrappers are the same.
+#
+#  $1 - files to be uninstalled
+#  $2 - prefix to uninstall path for the files
+#
+define uninstall_bin
+	$(call uninstall_files,$1,$2/$(BIN_DIR))
+endef
+
+define uninstall_sbin
+	$(call uninstall_files,$1,$2/$(SBIN_DIR))
+endef
+
+define uninstall_lib
+	$(call uninstall_files,$1,$2/$(LIB_DIR))
+endef
+
+define uninstall_inc
+	$(call uninstall_files,$1,$2/$(INC_DIR))
+endef
+
+define uninstall_doc
+	$(call uninstall_files,$1,$2/$(DOC_DIR))
+endef
+
+define uninstall_man
+	$(call uninstall_files,$1,$2/$(MAN_DIR))
+endef
+
+
+# Define "CLEAN" as rm plus any files defined in this file that
+# the actual Makefile may not (or have to) know about
+CLEAN = /bin/rm -rf $(INSTALL_LOG) $(TB_DIR) *~
+
+# Default target for building object files
+%.o: %.c
+	@echo "CC $(WORK_DIR)/$@"
+	@$(CC) -c $(CFLAGS) $<
+
+

Added: trunk/powerpc-ibm-utils/scripts/Makefile
===================================================================
--- trunk/powerpc-ibm-utils/scripts/Makefile	                        (rev 0)
+++ trunk/powerpc-ibm-utils/scripts/Makefile	2006-09-25 09:08:44 UTC (rev 164)
@@ -0,0 +1,19 @@
+#
+# Makefile for powerpc-utils/scripts
+#
+
+include ../rules.mk
+
+SCRIPTS = snap bootlist ofpathname
+
+all: $(SCRIPTS)
+
+install: all
+	@$(call install_sbin,$(SCRIPTS),$(DESTDIR))
+
+uninstall:
+	@$(call uninstall_sbin,$(SCRIPTS),$(DESTDIR))
+
+clean:
+	@echo "Cleaning up $(WORK_DIR) files..."
+	@rm -f *~

Added: trunk/powerpc-ibm-utils/scripts/bootlist
===================================================================
--- trunk/powerpc-ibm-utils/scripts/bootlist	                        (rev 0)
+++ trunk/powerpc-ibm-utils/scripts/bootlist	2006-09-25 09:08:44 UTC (rev 164)
@@ -0,0 +1,331 @@
+#! /bin/bash
+# Copyright (c) 2004 International Business Machines
+# Common Public License Version 1.0 (see COPYRIGHT)
+#
+# bootlist - command to display and/or update the bootlist in nvram.
+#
+# author Nathan Fontenot <nfont at austin.ibm.com>
+#
+
+OFPATHNAME=/usr/sbin/ofpathname
+NVRAM=/usr/sbin/nvram
+
+#
+# usage
+# 
+usage()
+{
+    echo "Usage: $0 -m {normal|service|both} [-o] [-r]"
+    echo "             [-f <file>] [<device_list>]"
+    echo "View and update the system boot lists"
+    echo ""
+    echo "Required argument:"
+    echo "  -m {normal|service|both}"
+    echo "                   Specify the boot mode for boolist manipulation"
+    echo "Optional arguments:"
+    echo "  -o               Display bootlist entries as logical device names"
+    echo "  -r               Display bootlist entries as Open Firmware device"
+    echo "                   path names"
+    echo "  -f file          Read the boolist device names from file"
+    echo "  -?, --help       display this help information and exit"
+    echo "  <device_list>    a space-separated list of devices, specified as"
+    echo "                   logical device names or OF device path names,"
+    echo "                   depending on whether the -o or -r option is specified"
+    echo ""
+    echo "Additional optional arguments for ethernet devices:"
+    echo " bserver=<IP address of BOOTP server>"
+    echo " gateway=<IP address of gateway>"
+    echo " client=<IP address of the client>"
+    echo " speed=<Network adapter speed>, default=auto"
+    echo " duplex=<mode of the network adapter>, default=auto"
+    echo ""
+}
+
+#
+# update_eth_dev
+# When specifying an ethernet device for the bootlist we need to also get
+# the additional parameters for ethernet devices (i.e gateway, speed, ...)
+#
+# Please NOTE:  this routine does depend on global variables
+#
+update_eth_dev()
+{
+    local speed=auto
+    local duplex=auto
+    local bserver
+    local gateway
+    local client
+    local eth_index=$[$ctr]
+    local index=$[$ctr + 1]
+    local found=1
+
+    while [[ $found -eq 1 ]]; do
+	found=0
+        case ${LOGICAL_NAMES[$index]} in
+	    speed*)		speed=${LOGICAL_NAMES[$index]##*=}
+				found=1 ;;
+
+	    duplex*)		duplex=${LOGICAL_NAMES[$index]##*=}
+				found=1 ;;
+
+	    bserver*)	 	bserver=${LOGICAL_NAMES[$index]##*=}
+				found=1 ;;
+
+	    gateway*)		gateway=${LOGICAL_NAMES[$index]##*=}
+				found=1 ;;
+
+	    client*)		client=${LOGICAL_NAMES[$index]##*=}
+				found=1 ;;
+    	esac
+
+	if [[ $found -eq 1 ]]; then
+	    index=$[$index + 1]
+	    ctr=$[$ctr + 1]
+	fi
+    done
+
+    # if no additional option was specified, just use the full 
+    # path without options
+    if [[ -z $bserver && -z $gateway && -z $client ]]; then
+	OF_DEVPATH[$eth_index]=${OF_DEVPATH[$eth_index]}
+	return
+    fi
+
+    # Parameter Checking
+    if [[ -z $bserver || -z $gateway || -z $client ]]; then
+	echo "You must provide the IP Address for the BOOTP server, the"
+	echo "client, and the gateway when specifying an ethernet adapter"
+	usage
+	exit -1
+    fi
+
+    # update the ethernet device
+    OF_DEVPATH[$eth_index]=${OF_DEVPATH[$eth_index]}:speed=$speed,duplex=$duplex,$bserver,,$client,$gateway
+}
+
+#
+# parse_eth_info
+# Ethernet read from nvram (possibly) have additional data appended to 
+# them specifying the gateway, speed, ...
+#
+# $1 ethernet device name
+# $2 ethernet device data
+# 
+parse_eth_info()
+{
+    local eth_name=$1
+    local eth_info=${2##*:}
+
+    echo $eth_name
+
+    # first the speed
+    local item=${eth_info%%,*}
+    if [[ -n $item ]]; then
+	echo "    speed = ${item##*=}"
+    fi
+
+    # then the duplex
+    eth_info=${eth_info#*,}
+    item=${eth_info%%,*}
+    if [[ -n $item ]]; then
+	echo "    duplex = ${item##*=}"
+    fi
+
+    # then the BOOTP server
+    eth_info=${eth_info#*,}
+    item=${eth_info%%,*}
+    if [[ -n $item ]]; then
+	echo "    BOOTP Server: $item"
+    fi
+    
+    # then the Mask
+    eth_info=${eth_info#*,}
+    item=${eth_info%%,*}
+    if [[ -n $item ]]; then
+	echo "    Mask: $item"
+    fi
+    
+    # then the client
+    eth_info=${eth_info#*,}
+    item=${eth_info%%,*}
+    if [[ -n $item ]]; then
+	echo "    Client: $item"
+    fi
+    
+    # then the Gateway
+    eth_info=${eth_info#*,}
+    item=${eth_info%%,*}
+    if [[ -n $item ]]; then
+	echo "    Gateway: $item"
+    fi
+} 
+ 
+#
+# show_bootlist
+# Retrieve a bootlist from nvram and print its contents
+#
+# $1 bootlist to print
+# 
+show_bootlist()
+{
+    local devlist=$1
+    local i
+
+    for i in `$NVRAM --print-config=${devlist} | sed 's/ /\n/g'`; do
+	if [[ $TRANSLATE_NAMES = "yes" ]]; then
+	    name=`$OFPATHNAME -l $i`
+	    if [[ -z $name ]]; then
+	        echo "Could not translate $i to logical device name"
+	    else
+		case $name in
+		    eth*)   parse_eth_info $name $i ;;
+		       *)   echo $name ;; 
+	        esac
+	    fi
+	else
+	    echo $i
+	fi
+    done
+}
+
+#
+# Main
+#
+
+# make sure we can parse names
+if [[ ! -a $OFPATHNAME ]]; then
+    echo "no $OFPATHNAME!!!"
+fi
+
+# make sure we can update nvram
+if [[ ! -a $NVRAM ]]; then
+    echo "no $NVRAM!!!"
+fi
+
+BOOTLIST_MODE=unknown
+
+#
+# Parse the command line arguements and put them into two parallel
+# arrays, one to hold the logical device name and one to hold the 
+# corresponding open firmware device path.
+#
+typeset -i ctr=0
+
+while [[ -n $1 ]]; do
+    if [[ $1 = "-o" ]]; then
+        DISPLAY_BOOTLIST=yes
+	TRANSLATE_NAMES=yes
+    elif [[ $1 = "-r" ]]; then
+        DISPLAY_BOOTLIST=yes
+    elif [[ $1 = "-m" ]]; then
+        shift
+        if [[ ! -n $1 ]]; then
+            echo "did not specify \"normal\" or \"service\" mode with -m"
+            usage
+            exit -1
+        fi
+
+        if [[ $1 = "normal" ]]; then
+            BOOTLIST_MODE=boot-device
+        elif [[ $1 = "service" ]]; then
+            BOOTLIST_MODE=diag-device
+        elif [[ $1 = "both" ]]; then
+            BOOTLIST_MODE=$1
+        else
+            echo "invalid mode specified with -m; must be \"normal\", \"service\" or \"both\""
+            usage
+            exit -1
+        fi
+    elif [[ $1 = "-f" ]]; then
+        # get bootlist names from specified file
+	if [[ ! -a $2 ]]; then
+	    echo "file $2 does not exist"
+	fi
+
+        for i in `cat $2 2>/dev/null`; do
+	    LOGICAL_NAMES[$ctr]=$i
+	    ctr=$[$ctr + 1]
+	done
+	shift
+    elif [[ $1 = -* ]]; then
+    	# catch any illegal flags here
+	usage
+	exit -1
+    else
+        # add this element to the array
+	LOGICAL_NAMES[$ctr]=$1
+	ctr=$[$ctr + 1]
+    fi
+
+    shift
+done
+
+if [[ ${BOOTLIST_MODE} = "unknown" ]]; then
+    echo "The boot mode must be specified with the -m option"
+    usage
+    exit -1
+fi
+
+# Now we need to convert all of the logical device names to
+# open firmware device paths.
+if [[ ${#LOGICAL_NAMES[*]} -ne 0 ]]; then
+    ctr=0
+    while [[ $ctr -lt ${#LOGICAL_NAMES[*]} ]]; do
+        OF_DEVPATH[$ctr]=`$OFPATHNAME ${LOGICAL_NAMES[$ctr]}`
+        if [[ $? -ne 0 ]]; then
+	    # Assume the name is an OF pathname
+	    OF_DEVPATH[$ctr]=${LOGICAL_NAMES[$ctr]}
+        fi
+
+	# See if this is an ethernet adapter.  If so, the next entries
+	# may be parameters for the bootlist entry.
+	ethdev=${OF_DEVPATH[$ctr]##/*/}
+	ethdev=${ethdev%%@*}
+	if [[ $ethdev = "ethernet" ]]; then
+	    update_eth_dev
+	fi
+
+        # bootlist entries cannot exceed more than 255 chars
+        if [[ ${#OF_DEVPATH[$ctr]} -gt 255 ]]; then
+            echo "Bootlist entries cannot exceed 255 characters"
+            echo "${OF_DEVPATH[$ctr]}"
+            exit -1
+        fi
+
+        ctr=$[$ctr + 1]
+    done
+
+    # We cannot have a bootlist with more than five entries
+    if [[ ${#OF_DEVPATH[*]} -gt 5 ]]; then
+        echo "More than five entries cannot be specified in the bootlist"
+        exit -1
+    fi
+
+    # update the bootlist in nvram
+    if [[ $BOOTLIST_MODE = "both" ]]; then
+        $NVRAM --update-config "boot-device=${OF_DEVPATH[*]}" -pcommon
+        if [[ $? -ne 0 ]]; then
+            echo "Could not update service-mode bootlist"
+        fi
+
+        $NVRAM --update-config "diag-device=${OF_DEVPATH[*]}" -pcommon
+        if [[ $? -ne 0 ]]; then
+            echo "Could not update normal-mode bootlist"
+        fi
+    else
+        $NVRAM --update-config "${BOOTLIST_MODE}=${OF_DEVPATH[*]}" -pcommon
+        if [[ $? -ne 0 ]]; then
+            echo "Could not update bootlist!"
+        fi
+    fi
+fi
+
+# Display the bootlist if desired
+if [[ $DISPLAY_BOOTLIST = "yes" ]]; then
+    if [[ $BOOTLIST_MODE = "both" ]]; then
+	show_bootlist "boot-device"
+	show_bootlist "diag-device"
+    else
+	show_bootlist $BOOTLIST_MODE
+    fi
+fi


Property changes on: trunk/powerpc-ibm-utils/scripts/bootlist
___________________________________________________________________
Name: svn:executable
   + *

Added: trunk/powerpc-ibm-utils/scripts/ofpathname
===================================================================
--- trunk/powerpc-ibm-utils/scripts/ofpathname	                        (rev 0)
+++ trunk/powerpc-ibm-utils/scripts/ofpathname	2006-09-25 09:08:44 UTC (rev 164)
@@ -0,0 +1,587 @@
+#! /bin/bash
+
+# Copyright (c) 2004 International Business Machines
+# Common Public License Version 1.0 (see COPYRIGHT)
+#
+# Author Nathan Fontenot <nfont at austin.ibm.com>
+
+#
+# ofpathname - This utility provides a mechanism for converting a logical
+# device name to an open firmware device path, and vice versa.
+#
+# TODO: This script doesn't handle floppy drives and token ring devices,
+#       perhaps they should be added in at some point.
+#
+
+OFPATHNAME="ofpathname"
+VERSION="0.5"
+FIND=/usr/bin/find
+CAT=/bin/cat
+
+# Usage statemnet
+usage()
+{
+    echo "Usage: $OFPATHNAME [OPTION] DEVICE"
+    echo "Provide logical device names <==> Open Firmware Device Path Conversion"
+    echo ""
+    echo "Optional arguments."
+    echo "  -l               Convert Open Firmware device pathname to"
+    echo "                   logical device name."
+    echo "  -q, --quiet      do not report failures, exit quietly"
+    echo "  -V, --version    display version information and exit"         
+    echo "  -h, --help       display this help information and exit"
+    echo ""
+}
+
+show_version()
+{
+    echo "$OFPATHNAME: Version $VERSION"
+    echo "Written by: Nathan Fontenot"
+}
+
+# 
+# err
+# Common routine to print error messages for ofpathname.  Since most of the
+# error messages can be generated in multiple places, we put all the text
+# here to avoid errors in duplicating the messages.
+#
+# The first and only parameteris the error message number, all of which
+# are defined below as ERR_*.
+#
+ERR_NO_OFPATH=1
+ERR_NO_SYSFS=2
+ERR_NO_SYSFS_DEVINFO=3
+ERR_NOT_CONFIG=4
+ERR_NO_LOGDEV=5
+err()
+{
+    local emsg=$1
+    
+    if [[ -n $be_quiet ]]; then	
+        exit 1
+    fi
+
+    case $emsg in
+        1)  echo "$OFPATHNAME: Could not retrieve Open Firmware device path"
+            echo "            for logical device \"$DEVNAME_ARG\"." ;;
+	    
+        2)  echo "$OFPATHNAME: sysfs (/sys) is needed and does not appear"
+            echo "            to be mounted on this system." ;;
+	    
+        3)  echo "$OFPATHNAME: Could not find sysfs information for logical"
+            echo "            device \"$DEVNAME_ARG\"." ;;
+   
+        4)  echo "$OFPATHANME: Logical device \"$DEVNAME_ARG\" does not appear"
+            echo "            to be configured." ;;
+
+        5)  echo "$OFPATHNAME: Could not retrieve logical device name for"
+            echo "            Open Firmware path \"$DEVNAME_ARG\"."
+    esac
+
+    exit 1
+}
+
+#
+# get_link
+# return the directory path that a link points to.
+# The only parameter is the link name.
+#
+get_link()
+{
+    local ln_name=$1;
+    echo `ls -l $ln_name 2>/dev/null | awk -F"->" '{print $2}'`
+}
+
+#
+# get_hbtl
+# Given a path that ends in an HBTL (Host:Bus:Target ID:LUN), break it apart
+# into its constituent parts in the global vars HOST, BUS, TARGET and LUN
+#
+# #1 path ending in HBTL
+#
+get_hbtl()
+{
+    local hbtl
+
+    HBTL=${1##*/}
+    hbtl=$HBTL
+
+    HOST=${hbtl%%:*}
+    hbtl=${hbtl#*:}
+    BUS=${hbtl%%:*}
+    hbtl=${hbtl#*:}
+    ID=${hbtl%%:*}
+    ID=`echo "ibase=10;obase=16; $ID" | bc | tr "[:upper:]" "[:lower:]"`
+    LUN=${hbtl#*:}
+    LUN=`echo "ibase=10;obase=16; $LUN" | bc | tr "[:upper:]" "[:lower:]"`
+}
+
+#
+# get_vdisk_no
+# Given a path that ends in an HBTL, convert the HBTL values into a 
+# virtual disk number (not sure what the real terminology is for it).
+# To do the conversion, the HBTL (A:B:C:D) is split apart and 
+# calculated as;
+#     no = (0x8000 | B << 8 | C << 5 | D) * 1000000000000
+# 
+# $1 path ending in HBTL
+#
+get_vdisk_no()
+{
+    get_hbtl $1
+
+    local B C D
+    typeset -i B C D
+
+    B=$((0x$ID << 8))
+    C=$((0x$BUS << 5))
+    D=$((0x$LUN))
+
+    local vdiskno vdisk
+    typeset -i vdiskno
+    vdiskno=$((0x8000 | $B | $C | $D ))
+    vdisk=${vdiskno##-}
+
+    vdisk=`echo \`bc << END
+ibase=10
+obase=16
+$vdisk
+END\``
+
+    local extrazeroes="000000000000"
+    echo $vdisk$extrazeroes
+}
+
+#
+# goto_dir
+# This looks for a given file in a given directory or any parents of the 
+# given directory.
+#
+# $1 starting directory
+# $2 file to search for
+#  
+goto_dir()
+{
+    local start_dir=$1
+    local fname=$2
+    local found=0
+
+    cd $start_dir
+    while [[ $PWD != "/" ]]; do
+        ls 2>/dev/null | grep $fname >/dev/null 2>&1
+        if [[ $? -eq 0 ]]; then
+            found=1
+            break
+        fi
+        cd ..
+    done
+
+    if [[ $found -eq 0 ]]; then
+        err $ERR_NO_SYSFS_DEVINFO
+    fi
+}
+
+#
+# logical_to_ofpathname
+# Conversion for logical device name to an Open Firmware device path
+#
+logical_to_ofpathname()
+{
+    local is_cdrom
+
+    # follow any links to the real device name
+    while [[ -L $DEVNAME ]]; do
+        DEVNAME=`get_link $DEVNAME`
+    done
+    
+    while [[ -L /dev/$DEVNAME ]]; do
+        DEVNAME=`get_link /dev/$DEVNAME`
+    done
+
+    DEVICE=${DEVNAME##*/}
+    DEVNODE=${DEVICE%%[0-9]*}
+
+    # try to determine if this is a cdrom device
+    if [[ ${DEVNAME_ARG##*/} = cdrom ]]; then
+        is_cdrom=yes
+    elif [[ `get_link /dev/cdrom` = /dev/$DEVICE ]]; then
+        is_cdrom=yes
+    else
+        is_cdrom=no
+    fi
+
+    case $DEVICE in
+        eth*)       l2of_ethernet ;;
+        sd* | sr*)  l2of_scsi ;;
+        hd*)        l2of_ide ;;
+        fd*)        echo "no fd support yet" ;;
+    esac
+
+    if [[ -z $OF_PATH ]]; then
+        err $ERR_NO_OFPATH
+    fi
+
+    if [[ $is_cdrom = yes ]]; then
+        OF_PATH=$OFPATH:1\\ppc\\bootinfo.txt
+    fi
+
+    echo $OF_PATH
+}
+
+#
+# l2of_ide
+# Conversion routine for logical => OF path of ide devices
+#
+l2of_ide()
+{
+    cd /sys/block/$DEVICE
+    local link=`get_link "device"`
+    if [[ -z $link ]]; then 
+        err $ERR_NO_SYSFS_DEVINFO
+    fi
+    cd $link
+
+    # get the device number
+    local devdir=${PWD##/*/}
+    local channelno=${devdir%%\.*}
+    local devno=${devdir##*\.}
+
+    goto_dir $PWD "devspec"
+
+    OF_PATH=`$CAT $PWD/devspec`
+    if [[ -z $OF_PATH ]]; then
+        err $ERR_NO_OFPATH
+    fi
+
+    # PCI ATA controller nodes (found on some Macs) have one child per IDE
+    # channel.
+    case `$CAT "/proc/device-tree/$OF_PATH/device_type"` in
+        pci-ata | pci-ide)  OF_PATH=$OF_PATH/@$channelno ;;
+    esac
+
+    OF_PATH=$OF_PATH/disk@$devno
+}
+
+#
+# l2of_ethernet
+# Conversion routine for logical => OF path of ethernet devices
+#
+l2of_ethernet()
+{
+    local sysfs_eth=`$FIND /sys -name $DEVICE 2> /dev/null`
+    if [[ -z $sysfs_eth ]]; then
+        err $ERR_NOT_CONFIG
+    fi
+
+    OF_PATH=`$CAT $sysfs_eth/device/devspec`
+    if [[ -z $OF_PATH ]]; then
+        err $ERR_NO_OFPATH
+    fi
+}
+
+#
+# l2of_scsi
+# Converion routine for logical => OF path of scsi devices
+#
+l2of_scsi()
+{
+    local sysfs_sd=`$FIND /sys -name $DEVICE 2>/dev/null`
+    if [[ -z $sysfs_sd ]]; then
+        err $ERR_NOT_CONFIG
+    fi
+
+    # Move up directories until we find onew with a device link
+    goto_dir $sysfs_sd "device"
+
+    # follow the 'device' link
+    local link=`get_link "device"`
+    if [[ -z $link ]]; then 
+        err $ERR_NO_SYSFS_DEVINFO
+    fi
+
+    get_hbtl $link 
+    cd $link
+
+    # save the name of the current directory, we may need it later...
+    local device_dir=${PWD##/*/}
+
+    # move up directories until we find one with devspec information
+    goto_dir $PWD "devspec"
+
+    OF_PATH=`$CAT $PWD/devspec`
+    if [[ -z $OF_PATH ]]; then
+        err $ERR_NO_OFPATH
+    fi
+
+    local vdev=${OF_PATH%/*}
+
+    if [[ $vdev = "/vdevice" ]]; then
+        # get the v-device data
+        local i vdiskno
+        cd host*
+        cd target*
+        vdiskno=`get_vdisk_no $device_dir`
+
+        OF_PATH=$OF_PATH/disk\@$vdiskno
+
+    else
+        # make sure the "scsi" information is on the end of the path
+        local scsi_name=${OF_PATH##/*/}
+        scsi_name=${scsi_name%%@*}
+        if [[ $scsi_name != "scsi" ]]; then
+            scsi_name="scsi@$BUS"
+            OF_PATH=$OF_PATH/$scsi_name
+        fi
+
+        OF_PATH=$OF_PATH/sd@$ID,$LUN
+    fi
+}
+
+#
+# ofpathname_to_logical
+# Conversion for Open Firmware device paths to logical device names
+#
+ofpathname_to_logical()
+{
+    DEVPATH=${DEVNAME%/*}
+    DEVICE=${DEVNAME##/*/}
+    DEVTYPE=${DEVICE%\@*}
+
+    if [[ $DEVTYPE = "disk" && $DEVICE != ${DEVICE%:*} ]]; then
+        DEVTYPE=${DEVICE%:*}
+    fi
+
+    # Remove any possible cdrom data from DEVICE
+    if [[ ${DEVICE##*,} = "\ppc\bootinfo.txt" ||
+          ${DEVICE##*,} = \ppc\bootinfo.txt ]]; then
+        DEVICE=${DEVICE%,*}
+    fi
+
+    case $DEVTYPE in
+        sd*           )  of2l_scsi ;;
+        v-scsi | disk )  of2l_vscsi 
+                         if [[ -z $LOGICAL_DEVNAME && $DEVTYPE = disk ]]; then
+                             of2l_ide
+                          fi ;;
+        eth* | l-lan  )  of2l_ethernet ;;
+        disk*         )  of2l_ide ;;
+    esac
+
+    if [[ -z $LOGICAL_DEVNAME ]]; then
+        err $ERR_NO_LOGDEV
+    fi
+
+    # See if this device is the cdrom
+    if [[ `get_link "/dev/cdrom"` = $LOGICAL_DEVNAME ]]; then
+        LOGICAL_DEVNAME="cdrom"
+    fi
+
+    echo $LOGICAL_DEVNAME
+}
+
+#
+# of2l_ide
+# Conversion routine for OF path => logical name for ide devices
+#
+of2l_ide()
+{
+    local dir
+
+    for dir in `$FIND /sys/block -name hd*`; do
+        # get devno
+        local devno=${DEVICE##*@}
+        devno=${devno%%:*}
+
+        cd $dir
+        local link=`get_link "device"`
+        if [[ -n $link ]]; then 
+            cd $link
+
+            # see if this is the correct device
+            local this_devno=${PWD##*\.}
+            if [[ $devno -eq $this_devno ]]; then
+                goto_dir $PWD "devspec"
+                local devspec=`$CAT ./devspec 2>/dev/null`
+                
+                if [[ $devspec = $DEVPATH ]]; then
+                    LOGICAL_DEVNAME="${dir##*/}"
+                    break
+                fi
+            fi
+        fi
+    done
+}
+
+#
+# of2l_ethernet
+# Conversion routine for OF path => logical names of ethernet devices
+#
+of2l_ethernet()
+{
+    local dir
+
+    # strip off ip info if present
+    local devname=${DEVNAME%%:*}
+
+    for dir in `$FIND /sys/class/net -name eth*`; do
+        goto_dir $dir device
+
+        local link=`get_link "device"`
+        if [[ -z $link ]]; then 
+            err $ERR_NO_SYSFS_DEVINFO
+        fi
+
+        cd $link
+        local devspec=`$CAT ./devspec 2>/dev/null`
+ 
+        if [[ $devspec = $devname ]]; then
+            LOGICAL_DEVNAME="${dir##*/}"
+            return
+        fi
+    done
+}
+
+#
+# of2l_vscsi
+# Conversion routine for OF path => logical names of virtual scsi devices
+#
+of2l_vscsi()
+{
+    DEV_HBTL_NO=${DEVICE##*\@}
+
+    local dir
+    for dir in `$FIND /sys/block -name "s[dr]*"`; do
+        # go up to find directory with 'device' link
+        goto_dir $dir "device"
+
+        local link=`get_link "device"`	
+        if [[ -z $link ]]; then 
+            err $ERR_NO_SYSFS_DEVINFO
+        fi
+
+        local vdiskno=`get_vdisk_no $link`
+
+        cd $link	
+        if [[ $vdiskno = $DEV_HBTL_NO ]]; then
+            goto_dir $PWD "devspec"
+            local devspec=`$CAT ./devspec 2>/dev/null`
+            
+            if [[ $devspec = $DEVPATH ]]; then
+                LOGICAL_DEVNAME=${dir##/*/}
+                return
+            fi
+        fi
+    done
+}
+	
+#
+# of2l_scsi
+# Conversion routine for OF path => logical names of scsi devices
+#
+of2l_scsi()
+{
+    DEV_TARGET=${DEVICE##*\@}
+    DEV_TARGET=${DEV_TARGET%%,*}
+    DEV_LUN=${DEVICE##*,}
+
+    # At this point DEV_LUN may be in the form X:Y, we're only interested
+    # in the X component.         
+    DEV_LUN=${DEV_LUN%%:*}
+
+    local dir
+    for dir in `$FIND /sys/block -name s[dr]*`; do
+        # go up to find directory with 'device' link
+        goto_dir $dir "device"
+
+        local link=`get_link "device"`	
+        if [[ -z $link ]]; then 
+            err $ERR_NO_SYSFS_DEVINFO
+        fi
+
+        get_hbtl $link
+        cd $link
+
+        # save the name of the current directory, we may need it later...
+        local device_dir=${PWD##/*/}
+
+        if [[ $ID = $DEV_TARGET && $LUN = $DEV_LUN ]]; then
+            goto_dir $PWD "devspec"
+            local devspec=`$CAT ./devspec 2>/dev/null`
+            
+            if [[ $devspec = $DEVPATH ]]; then
+                LOGICAL_DEVNAME="${dir##*/}"
+                return
+            fi
+
+            local scsi_name=${devspec##/*/}
+            scsi_name=${scsi_name%%@*}
+
+            if [[ $scsi_name != "scsi" ]]; then
+                scsi_name="scsi@$BUS"
+                devspec=$devspec/$scsi_name
+
+                if [[ $devspec = $DEVPATH ]]; then
+                    LOGICAL_DEVNAME="${dir##*/}"
+                    return
+                fi
+            fi
+        fi
+    done
+}
+
+#
+# Main 
+#
+
+if [[ "$#" -eq 0 ]]; then
+    usage
+    exit 0
+fi
+
+# default: convert logical => OFpath
+do_of2l=0
+
+getopt -o "l:Vqh" -l "help,version,quiet" $@ > /dev/null 2>&1
+while [[ -n $1 ]]; do
+    case "$1" in
+        -l)             do_of2l=1 
+                        DEVNAME_ARG=$2
+                        shift ;;
+        
+        -V | --version) show_version 
+                        exit 0 ;;
+	
+        -q | --quiet)   be_quiet=1 ;;
+
+        -h | --help)    usage
+                        exit 0 ;;
+	*)              DEVNAME_ARG=$1 ;;
+    esac
+
+    shift
+done
+
+DEVNAME=$DEVNAME_ARG
+
+# double check device name
+if [[ -z $DEVNAME ]]; then
+    usage
+    exit 1
+fi
+
+# We need sysfs
+if [[ ! -d "/sys" ]]; then
+    err $ERR_NO_SYSFS
+    exit 1
+fi
+
+
+if [[ $do_of2l = "0" ]]; then
+    # logical devname => OF pathname
+    logical_to_ofpathname
+else
+    # OF pathnmae => logical devname
+    ofpathname_to_logical 
+fi
+
+exit 0


Property changes on: trunk/powerpc-ibm-utils/scripts/ofpathname
___________________________________________________________________
Name: svn:executable
   + *

Added: trunk/powerpc-ibm-utils/scripts/snap
===================================================================
--- trunk/powerpc-ibm-utils/scripts/snap	                        (rev 0)
+++ trunk/powerpc-ibm-utils/scripts/snap	2006-09-25 09:08:44 UTC (rev 164)
@@ -0,0 +1,345 @@
+#!/usr/bin/perl -w
+# Copyright (c) 2003, 2004 International Business Machines
+# Common Public License Version 1.0 (see COPYRIGHT)
+#
+# Author Todd Inglett <tinglett at us.ibm.com>
+# updates by Michael Strosaker <strosake at us.ibm.com>
+
+# Snapshot system config
+# Command-line parameters:
+#    a:       all data; collect detailed information (more files and output)
+#    d dir:   specify the directory where files and output will be collected
+#               (default: /tmp/ibmsupt)
+#    h:       print this help message
+#    o file:  specify the output file (.tar required, .tar.gz optional)
+#               (default: snap.tar.gz)
+#    v:       verbose output
+#
+#  Exit codes (view with "echo $?" immediately after running):
+#    0:  snap data was successfully captured
+#    1:  invalid command line
+#    2:  other fatal error
+
+use Getopt::Std;
+
+$outdir = "/tmp/ibmsupt";	# note NO trailing /
+$outfile = "snap.tar.gz";	# in the working dir.
+
+#  Files to include in all snaps
+ at snap_paths_general = (
+  "/var/log/messages",
+  "/var/log/platform",
+  "/var/log/scanoutlog.*",
+#  "/proc/bus/pci",	?? binary file
+  "/proc/cmdline",
+  "/proc/cpuinfo",
+#  "/proc/device-tree",  must summarize device-tree (a la dmpdt_chrp) instead of dumping whole thing
+  "/proc/devices",
+  "/proc/dma",
+  "/proc/filesystems",
+  "/proc/fs",
+  "/proc/ide",
+  "/proc/interrupts",
+  "/proc/iomem",
+  "/proc/ioports",
+  "/proc/loadavg",
+  "/proc/locks",
+  "/proc/mdstat",
+  "/proc/meminfo",
+  "/proc/misc",
+  "/proc/modules",
+  "/proc/mounts",
+  "/proc/net",
+  "/proc/partitions",
+  "/proc/pci",
+  "/proc/ppc64/lparcfg",
+  "/proc/ppc64/eeh",
+  "/proc/ppc64/pci",
+  "/proc/ppc64/systemcfg",
+  "/proc/scsi",
+  "/proc/slabinfo",
+  "/proc/stat",
+  "/proc/swaps",
+  "/proc/sys",
+  "/proc/sysvipc",
+  "/proc/uptime",
+  "/proc/version",
+  "/dev/nvram",
+  "/etc/fstab",
+  "/etc/raidtab",
+  "/etc/yaboot.conf",
+);
+
+#  Files to include in all snaps on SuSE systems
+ at snap_paths_general_SuSE = (
+  "/etc/SuSE-release",
+  "/var/log/boot.msg",
+);
+
+#  Files to include in all snaps on RedHat systems
+ at snap_paths_general_RedHat = (
+  "/etc/redhat-release",
+  "/var/log/dmesg",
+);
+
+#  Files to include only in detailed snaps (-a option)
+ at snap_paths_detailed = (
+  "/proc/tty",
+  "/etc/inittab",
+  "/proc/ppc64/paca",
+  "/proc/ppc64/naca",
+  "/proc/ppc64/pmc",
+  "/proc/ppc64/pcifr",
+);
+
+#  Command output to include in all snaps
+ at snap_commands_general = (
+  "lscfg -vp",
+  "ifconfig -a",
+);
+
+#  Command output to include only in detailed snaps (-a option)
+ at snap_commands_detailed = (
+  "rpm -qa",
+);
+  
+
+sub recurse_dir($);		# function prototype
+
+sub error {
+	my ($fatal, $message) = @_;
+
+	if ($fatal) {
+		print "$0: $message\n";
+		exit 2;
+	}
+	else {
+		if ($opt_v) {
+			print "$0: $message\n";
+		}
+	}
+}
+
+sub print_usage {
+	print "Usage: $0 [-ahv] [-d dir] [-o file]\n\n";
+	print "  Command-line parameters:\n";
+	print "    a:       all data; collect detailed information (more files and output)\n";
+	print "    d dir:   specify the directory where files and output will be collected\n"; 
+	print "               (default: /tmp/ibmsupt)\n";
+	print "    h:       print this help message\n";
+	print "    o file:  specify the output file (.tar required, .tar.gz optional)\n";
+	print "               (default: snap.tar.gz)\n";
+	print "    v:       verbose output\n\n";
+	print "  Exit codes (view with \"echo \$?\" immediately after running):\n";
+	print "    0:  snap data was successfully captured\n";
+	print "    1:  invalid command line\n";
+	print "    2:  other fatal error\n\n";
+}
+
+sub copy {
+	my ($source, $destination) = @_;
+	my ($dir, @path, $d, $blocksize, $buffer, $length);
+
+	#print "Copying $source...";
+
+	# Create directories, if necessary
+	$dir = substr $destination, 0, rindex($destination, "/");
+	if (!(-d $dir)) {
+		@path = split /\//, $dir;
+		if (substr($dir, 0, 1) eq "/") {	# remove leading /
+			shift @path;
+		}
+		$dir = "";
+		foreach $d (@path) {
+			$dir .= "/" . $d;
+			if (!(-d $dir)) {
+				if (!mkdir($dir, 0644)) {
+					error(0, "Cannot create directory: $dir");
+					return;
+				}
+			}
+		}
+	}
+
+	# Copy file
+	if (!open(SRC, "<$source")) {
+		error(0, "Cannot open file for reading: $source");
+		return;
+	}
+	binmode SRC;
+	if (!open(DST, ">$destination")) {
+		error(0, "Cannot open file for writing: $destination");
+		goto copy_out;
+	}
+	binmode DST;
+
+	$blocksize = (stat SRC)[11] || 16384;
+	while ($length = sysread SRC, $buffer, $blocksize) {
+		if (!defined $length) {
+			next if $! =~ /^Interrupted/;	# ^Z and fg
+			error(0, "System read error while reading $source: $!");
+			goto copy_out;
+		}
+		$offset = 0;
+		while ($length) {
+			if (!defined($written = syswrite DST, $buffer, $length, $offset)) {
+				error(0, "System write error while writing $destination: $!");
+				goto copy_out;
+			}
+			$length -= $written;
+			$offset += $written;
+		}
+	}
+
+copy_out:
+	#print "done.\n";
+	close SRC;
+	close DST;
+}
+
+sub recurse_dir ($) {
+	my ($dir) = @_;
+	my ($file) = "";
+	my (@contents) = ();
+
+	if (!opendir(DIR, $dir)) {
+		error(0, "Could not open directory $dir");
+		return;
+	}
+
+	@contents = readdir DIR;
+	closedir DIR;
+
+	foreach $file (@contents) {
+		if ($file eq "." or $file eq ".." or (-l "$dir/$file")) {
+			next;
+		}
+
+		if (-d "$dir/$file") {
+			recurse_dir "$dir/$file";
+		}
+		else {
+			copy "$dir/$file", $outdir."$dir/$file";
+		}
+	}
+}
+
+sub snap_paths {
+	my ($file, $dir, $search, @contents);
+
+	foreach $file (@_) {
+		if (-d $file) {
+			recurse_dir $file;
+		}
+		else {
+			# Check for wildcard (* in last character only)
+			if (substr($file, -1) eq "*") {
+				$dir = substr $file, 0, rindex($file, "/");
+				$search = substr $file, rindex($file, "/")+1, -1;
+
+				if (!opendir(DIR, $dir)) {
+					error(0, "Could not open directory $dir");
+					return;
+				}
+
+				@contents = readdir DIR;
+				closedir DIR;
+
+				foreach $file (@contents) {
+					if (substr($file, 0, length($search)) eq $search) {
+						copy "$dir/$file", $outdir."$dir/$file";
+					}
+				}
+			}
+			else {
+				copy $file, $outdir.$file;
+			}
+		}
+	}
+}
+
+sub snap_commands {
+	my ($path, @junk, @path, $filename, $command, $exit_value);
+
+	foreach $command (@_) {
+		# Retrieve the name of the binary to run (for output file name)
+		($path, @junk) = split / /, $command;
+		@path = reverse(split /\//, $path);
+		$filename = shift @path;
+
+		system("$command > $outdir/$filename.out 2>&1");
+		if ($exit_value = $? >> 8) {
+			error(0, "\"$command\" returned $exit_value");
+		}
+	}
+}
+
+$< == 0 or error(1, "Must be executed as root");
+
+$opt_a = 0;
+$opt_d = 0;
+$opt_h = 0;
+$opt_o = 0;
+$opt_v = 0;
+if (!getopts('ad:ho:v')) {
+	print_usage;
+	exit 1;
+}
+
+if ($opt_h) {
+	print_usage;
+	exit 0;
+}
+
+if ($opt_d) {
+	$outdir = $opt_d;
+	if ($outdir eq "/") {
+		error(1, "Cannot use / as the output directory");
+	}
+	if (substr($outdir, -1) eq "/") {
+		$outdir = substr $outdir, 0, -1;
+	}
+}
+if ($opt_o) {
+	if ($opt_o !~ /.tar/) {
+		print "$0: The filename provided, $opt_o, does not contain .tar;  using default filename $outfile\n";
+	}
+	else {
+		$outfile = $opt_o;
+	}
+}
+
+snap_paths(@snap_paths_general);
+
+# Check distro
+if (-e "/etc/SuSE-release") {
+	snap_paths(@snap_paths_general_SuSE);
+}
+elsif (-e "/etc/redhat-release") {
+	snap_paths(@snap_paths_general_RedHat);
+}
+
+# Run commands and capture output
+snap_commands(@snap_commands_general);
+
+# Gather detail files if requested (-a option)
+if ($opt_a) {
+	snap_paths(@snap_paths_detailed);
+	snap_commands(@snap_commands_detailed);
+}
+
+($basefile, $extension) = split /\.tar/, $outfile;
+
+system ("tar -cf $basefile.tar $outdir 2>/dev/null");
+
+if ($extension eq ".gz") {
+	system ("gzip -f $basefile.tar");
+}
+elsif ($extension eq "") { }
+else {
+	$outfile = "$basefile.tar";
+	print "$0: Unrecognized extension $extension\n";
+}
+
+print "output written to $outfile\n";
+exit 0;


Property changes on: trunk/powerpc-ibm-utils/scripts/snap
___________________________________________________________________
Name: svn:executable
   + *




More information about the Debootloaders-devel mailing list