Signed-off-by: Stefan Reinauer <stepan@coresystems.de>
Acked-by: Jordan Crouse <jordan.crouse@amd.com>


git-svn-id: svn://svn.coreboot.org/coreboot/trunk@2736 2b7e53f0-3cfb-0310-b3e9-8179ed1497e1
diff --git a/util/lxbios/opts.c b/util/lxbios/opts.c
new file mode 100644
index 0000000..367678b
--- /dev/null
+++ b/util/lxbios/opts.c
@@ -0,0 +1,232 @@
+/*****************************************************************************\
+ * opts.c
+ * $Id: opts.c,v 1.2 2005/12/16 22:45:49 dsp_llnl Exp $
+ *****************************************************************************
+ *  Copyright (C) 2002-2005 The Regents of the University of California.
+ *  Produced at the Lawrence Livermore National Laboratory.
+ *  Written by Dave Peterson <dsp@llnl.gov> <dave_peterson@pobox.com>.
+ *  UCRL-CODE-2003-012
+ *  All rights reserved.
+ *
+ *  This file is part of lxbios, a utility for reading/writing LinuxBIOS
+ *  parameters and displaying information from the LinuxBIOS table.
+ *  For details, see <http://www.llnl.gov/linux/lxbios/>.
+ *
+ *  Please also read the file DISCLAIMER which is included in this software
+ *  distribution.
+ *
+ *  This program is free software; you can redistribute it and/or modify it
+ *  under the terms of the GNU General Public License (as published by the
+ *  Free Software Foundation) version 2, dated June 1991.
+ *
+ *  This program is distributed in the hope that it will be useful, but
+ *  WITHOUT ANY WARRANTY; without even the IMPLIED WARRANTY OF
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the terms and
+ *  conditions of the GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+\*****************************************************************************/
+
+#include "common.h"
+#include "opts.h"
+
+lxbios_op_info_t lxbios_op;
+
+lxbios_op_modifier_info_t lxbios_op_modifiers[LXBIOS_NUM_OP_MODIFIERS];
+
+static char * handle_optional_arg (int argc, char *argv[]);
+static void register_op (int *op_found, lxbios_op_t op, char op_param[]);
+static void register_op_modifier (lxbios_op_modifier_t mod, char mod_param[]);
+static void resolve_op_modifiers (void);
+static void sanity_check_args (void);
+
+static const char getopt_string[] = "-ab:B:c::de:hil::np:r:tvw:xX:y:Y";
+
+/****************************************************************************
+ * parse_lxbios_args
+ *
+ * Parse command line arguments.
+ ****************************************************************************/
+void parse_lxbios_args (int argc, char *argv[])
+ { lxbios_op_modifier_info_t *mod_info;
+   int i, op_found;
+   char c;
+
+   for (i = 0, mod_info = lxbios_op_modifiers;
+        i < LXBIOS_NUM_OP_MODIFIERS;
+        i++, mod_info++)
+    { mod_info->found = FALSE;
+      mod_info->found_seq = 0;
+      mod_info->param = NULL;
+    }
+
+   op_found = FALSE;
+   opterr = 0;
+
+   do
+    { switch (c = getopt(argc, argv, getopt_string))
+       { case 'a':
+            register_op(&op_found, LXBIOS_OP_CMOS_SHOW_ALL_PARAMS, NULL);
+            break;
+         case 'b':
+            register_op(&op_found, LXBIOS_OP_WRITE_CMOS_DUMP, optarg);
+            break;
+         case 'B':
+            register_op(&op_found, LXBIOS_OP_READ_CMOS_DUMP, optarg);
+            break;
+         case 'c':
+            register_op(&op_found, LXBIOS_OP_CMOS_CHECKSUM,
+                        handle_optional_arg(argc, argv));
+            break;
+         case 'd':
+            register_op(&op_found, LXBIOS_OP_LBTABLE_DUMP, NULL);
+            break;
+         case 'e':
+            register_op(&op_found, LXBIOS_OP_SHOW_PARAM_VALUES, optarg);
+            break;
+         case 'h':
+            register_op(&op_found, LXBIOS_OP_SHOW_USAGE, NULL);
+            break;
+         case 'i':
+            register_op(&op_found, LXBIOS_OP_CMOS_SET_PARAMS_STDIN, NULL);
+            break;
+         case 'l':
+            register_op(&op_found, LXBIOS_OP_LBTABLE_SHOW_INFO,
+                        handle_optional_arg(argc, argv));
+            break;
+         case 'n':
+            register_op_modifier(LXBIOS_MOD_SHOW_VALUE_ONLY, NULL);
+            break;
+         case 'p':
+            register_op(&op_found, LXBIOS_OP_CMOS_SET_PARAMS_FILE, optarg);
+            break;
+         case 'r':
+            register_op(&op_found, LXBIOS_OP_CMOS_SHOW_ONE_PARAM, optarg);
+            break;
+         case 't':
+            register_op_modifier(LXBIOS_MOD_USE_CMOS_OPT_TABLE, NULL);
+            break;
+         case 'v':
+            register_op(&op_found, LXBIOS_OP_SHOW_VERSION, NULL);
+            break;
+         case 'w':
+            register_op(&op_found, LXBIOS_OP_CMOS_SET_ONE_PARAM, optarg);
+            break;
+         case 'x':
+            register_op(&op_found, LXBIOS_OP_SHOW_CMOS_HEX_DUMP, NULL);
+            break;
+         case 'X':
+            register_op(&op_found, LXBIOS_OP_SHOW_CMOS_DUMPFILE, optarg);
+            break;
+         case 'y':
+            register_op_modifier(LXBIOS_MOD_USE_CMOS_LAYOUT_FILE, optarg);
+            break;
+         case 'Y':
+            register_op(&op_found, LXBIOS_OP_SHOW_LAYOUT, NULL);
+            break;
+         case -1:  /* no more command line args */
+            break;
+         case '?':  /* unknown option found */
+         case 1:  /* nonoption command line arg found */
+         default:
+            usage(stderr);
+            break;
+       }
+    }
+   while (c != -1);
+
+   if (!op_found)
+      usage(stderr);
+
+   resolve_op_modifiers();
+   sanity_check_args();
+ }
+
+/****************************************************************************
+ * handle_optional_arg
+ *
+ * Handle a command line option with an optional argument.
+ ****************************************************************************/
+static char * handle_optional_arg (int argc, char *argv[])
+ { char *arg;
+
+   if (optarg != NULL)
+    { /* optional arg is present and arg was specified as "-zarg" (with no
+       * whitespace between "z" and "arg"), where -z is the option and "arg"
+       * is the value of the optional arg
+       */
+      return optarg;
+    }
+
+   if ((argv[optind] == NULL) || (argv[optind][0] == '-'))
+      return NULL;
+
+   arg = argv[optind];  /* optional arg is present */
+
+   /* This call to getopt yields the optional arg we just found, which we want
+    * to skip.
+    */
+   getopt(argc, argv, getopt_string);
+
+   return arg;
+ }
+
+/****************************************************************************
+ * register_op
+ *
+ * Store the user's selection of which operation this program should perform.
+ ****************************************************************************/
+static void register_op (int *op_found, lxbios_op_t op, char op_param[])
+ { if (*op_found && (op != lxbios_op.op))
+      usage(stderr);
+
+   *op_found = TRUE;
+   lxbios_op.op = op;
+   lxbios_op.param = op_param;
+ }
+
+/****************************************************************************
+ * register_op_modifier
+ *
+ * Store information regarding an optional argument specified in addition to
+ * the user's selection of which operation this program should perform.
+ ****************************************************************************/
+static void register_op_modifier (lxbios_op_modifier_t mod, char mod_param[])
+ { static int found_seq = 0;
+   lxbios_op_modifier_info_t *mod_info;
+
+   mod_info = &lxbios_op_modifiers[mod];
+   mod_info->found = TRUE;
+   mod_info->found_seq = ++found_seq;
+   mod_info->param = mod_param;
+ }
+
+/****************************************************************************
+ * resolve_op_modifiers
+ *
+ * If the user specifies multiple arguments that conflict with each other,
+ * the last specified argument overrides previous conflicting arguments.
+ ****************************************************************************/
+static void resolve_op_modifiers (void)
+ { if (lxbios_op_modifiers[LXBIOS_MOD_USE_CMOS_LAYOUT_FILE].found &&
+       lxbios_op_modifiers[LXBIOS_MOD_USE_CMOS_OPT_TABLE].found)
+    { if (lxbios_op_modifiers[LXBIOS_MOD_USE_CMOS_LAYOUT_FILE].found_seq >
+          lxbios_op_modifiers[LXBIOS_MOD_USE_CMOS_OPT_TABLE].found_seq)
+         lxbios_op_modifiers[LXBIOS_MOD_USE_CMOS_OPT_TABLE].found = FALSE;
+      else
+         lxbios_op_modifiers[LXBIOS_MOD_USE_CMOS_LAYOUT_FILE].found = FALSE;
+    }
+ }
+
+/****************************************************************************
+ * sanity_check_args
+ *
+ * Perform sanity checking on command line arguments.
+ ****************************************************************************/
+static void sanity_check_args (void)
+ { if ((lxbios_op_modifiers[LXBIOS_MOD_SHOW_VALUE_ONLY].found) &&
+       (lxbios_op.op != LXBIOS_OP_CMOS_SHOW_ONE_PARAM))
+      usage(stderr);
+ }