[PATCH v2] kexec-tools: Fix option/argument parsing

Matt Evans
2010-05-14T04:15:14Z

Hi,

v2 changes:
- Fixed ARM's multiline KEXEC_ALL_OPTIONS #define
- Removed opterr=0 from main()'s getopts_long() scan, and handle
unknown options in main() (as it now knows about all allowed opts).
Previously it relied on the file_type->load()er parsing & complaining
about unknown options; if the loader didn't parse them, no complaint.

Tested on x86, ppc and compile-tested on my new crisv32-axis-linux-gnu
crosscompiler :-)

Cheers,

Matt

---
The argument parsing is currently a bit broken as main()'s getopt_long()
knows nothing about either the architecture-specific options or, even
more specifically, the architecture-and-loader-specific options.

This patch introduces new #defines for all architectures,
KEXEC_ALL_OPTIONS and KEXEC_ALL_OPT_STR. These contain all possible
options for a given build, and the getopt_long() passes in main() and
arch_process_options() will now recognise arch- and loader-specific
options; these will not be re-ordered in argv[], there is no confusion
over which argv[] entry is the kernel filename, and using '--opt=foo' and
'--opt foo' both work.

All architectures have command line options (and #define OPT_BLAHs)
consolidated into their include/arch/option.h files. x86_64 builds
parts of i386/ as well, so now both share a single option.h file (with
a symlink).

Signed-off-by: Matt Evans <matt@ozlabs.org>
---
kexec/arch/alpha/include/arch/options.h | 9 +++++
kexec/arch/arm/include/arch/options.h | 29 +++++++++++++++++
kexec/arch/arm/kexec-zImage-arm.c | 3 +-
kexec/arch/cris/include/arch/options.h | 32 ++++++++++++++++--
kexec/arch/cris/kexec-elf-cris.c | 4 +-
kexec/arch/i386/include/arch/options.h | 51 ++++++++++++++++++++++++++++++
kexec/arch/i386/kexec-beoboot-x86.c | 3 +-
kexec/arch/i386/kexec-bzImage.c | 6 +--
kexec/arch/i386/kexec-elf-x86.c | 7 +---
kexec/arch/i386/kexec-multiboot-x86.c | 5 +--
kexec/arch/i386/kexec-x86.c | 4 +-
kexec/arch/ia64/include/arch/options.h | 33 ++++++++++++++++++-
kexec/arch/ia64/kexec-elf-ia64.c | 7 +---
kexec/arch/mips/include/arch/options.h | 27 +++++++++++++++-
kexec/arch/mips/kexec-elf-mips.c | 3 +-
kexec/arch/ppc/include/arch/options.h | 34 ++++++++++++++++++++
kexec/arch/ppc/kexec-dol-ppc.c | 4 +-
kexec/arch/ppc/kexec-elf-ppc.c | 7 +---
kexec/arch/ppc/kexec-uImage-ppc.c | 6 +--
kexec/arch/ppc64/include/arch/options.h | 37 ++++++++++++++++++++-
kexec/arch/ppc64/kexec-elf-ppc64.c | 12 ++++---
kexec/arch/ppc64/kexec-ppc64.c | 12 +++----
kexec/arch/s390/include/arch/options.h | 28 ++++++++++++++++-
kexec/arch/s390/kexec-image.c | 4 +--
kexec/arch/sh/include/arch/options.h | 26 +++++++++++++--
kexec/arch/sh/kexec-sh.c | 7 +++-
kexec/arch/x86_64/include/arch/options.h | 23 +-------------
kexec/arch/x86_64/kexec-elf-x86_64.c | 7 +---
kexec/arch/x86_64/kexec-x86_64.c | 4 +-
kexec/kexec.c | 6 ++--
30 files changed, 341 insertions(+), 99 deletions(-)
mode change 100644 => 120000 kexec/arch/x86_64/include/arch/options.h

diff --git a/kexec/arch/alpha/include/arch/options.h b/kexec/arch/alpha/include/arch/options.h
index 11557a4..a012c8a 100644
--- a/kexec/arch/alpha/include/arch/options.h
+++ b/kexec/arch/alpha/include/arch/options.h
@@ -3,9 +3,18 @@

#define OPT_ARCH_MAX (OPT_MAX+0)

+/* Options relevant to the architecture (excluding loader-specific ones),
+ * in this case none:
+ */
#define KEXEC_ARCH_OPTIONS \
KEXEC_OPTIONS \

#define KEXEC_ARCH_OPT_STR KEXEC_OPT_STR ""

+/* See the other architectures for details of these; Alpha has no
+ * loader-specific options yet.
+ */
+#define KEXEC_ALL_OPTIONS KEXEC_ARCH_OPTIONS
+#define KEXEC_ALL_OPT_STR KEXEC_ARCH_OPT_STR
+
#endif /* KEXEC_ARCH_ALPHA_OPTIONS_H */
diff --git a/kexec/arch/arm/include/arch/options.h b/kexec/arch/arm/include/arch/options.h
index 248230b..d89c91f 100644
--- a/kexec/arch/arm/include/arch/options.h
+++ b/kexec/arch/arm/include/arch/options.h
@@ -3,9 +3,38 @@

#define OPT_ARCH_MAX (OPT_MAX+0)

+#define OPT_APPEND 'a'
+#define OPT_RAMDISK 'r'
+
+/* Options relevant to the architecture (excluding loader-specific ones),
+ * in this case none:
+ */
#define KEXEC_ARCH_OPTIONS \
KEXEC_OPTIONS \

#define KEXEC_ARCH_OPT_STR KEXEC_OPT_STR ""

+/* The following two #defines list ALL of the options added by all of the
+ * architecture's loaders.
+ * o main() uses this complete list to scan for its options, ignoring
+ * arch-specific/loader-specific ones.
+ * o Then, arch_process_options() uses this complete list to scan for its
+ * options, ignoring general/loader-specific ones.
+ * o Then, the file_type[n].load re-scans for options, using
+ * KEXEC_ARCH_OPTIONS plus its loader-specific options subset.
+ * Any unrecognised options cause an error here.
+ *
+ * This is done so that main()'s/arch_process_options()'s getopt_long() calls
+ * don't choose a kernel filename from random arguments to options they don't
+ * recognise -- as they now recognise (if not act upon) all possible options.
+ */
+#define KEXEC_ALL_OPTIONS \
+ KEXEC_ARCH_OPTIONS \
+ { "command-line", 1, 0, OPT_APPEND }, \
+ { "append", 1, 0, OPT_APPEND }, \
+ { "initrd", 1, 0, OPT_RAMDISK }, \
+ { "ramdisk", 1, 0, OPT_RAMDISK },
+
+#define KEXEC_ALL_OPT_STR KEXEC_ARCH_OPT_STR "a:r:"
+
#endif /* KEXEC_ARCH_ARM_OPTIONS_H */
diff --git a/kexec/arch/arm/kexec-zImage-arm.c b/kexec/arch/arm/kexec-zImage-arm.c
index 1a446d9..e060f6e 100644
--- a/kexec/arch/arm/kexec-zImage-arm.c
+++ b/kexec/arch/arm/kexec-zImage-arm.c
@@ -219,8 +219,7 @@ int zImage_arm_load(int argc, char **argv, const char *buf, off_t len,
off_t ramdisk_length;
off_t ramdisk_offset;
int opt;
-#define OPT_APPEND 'a'
-#define OPT_RAMDISK 'r'
+ /* See options.h -- add any more there, too. */
static const struct option options[] = {
KEXEC_ARCH_OPTIONS
{ "command-line", 1, 0, OPT_APPEND },
diff --git a/kexec/arch/cris/include/arch/options.h b/kexec/arch/cris/include/arch/options.h
index bc5f706..1c1a029 100644
--- a/kexec/arch/cris/include/arch/options.h
+++ b/kexec/arch/cris/include/arch/options.h
@@ -1,11 +1,35 @@
-#ifndef KEXEC_ARCH_MIPS_OPTIONS_H
-#define KEXEC_ARCH_MIPS_OPTIONS_H
+#ifndef KEXEC_ARCH_CRIS_OPTIONS_H
+#define KEXEC_ARCH_CRIS_OPTIONS_H

-#define OPT_ARCH_MAX (OPT_MAX+0)
+#define OPT_ARCH_MAX (OPT_MAX+0)
+#define OPT_APPEND (OPT_ARCH_MAX+0)

+/* Options relevant to the architecture (excluding loader-specific ones),
+ * in this case none:
+ */
#define KEXEC_ARCH_OPTIONS \
KEXEC_OPTIONS \

#define KEXEC_ARCH_OPT_STR KEXEC_OPT_STR ""

-#endif /* KEXEC_ARCH_MIPS_OPTIONS_H */
+/* The following two #defines list ALL of the options added by all of the
+ * architecture's loaders.
+ * o main() uses this complete list to scan for its options, ignoring
+ * arch-specific/loader-specific ones.
+ * o Then, arch_process_options() uses this complete list to scan for its
+ * options, ignoring general/loader-specific ones.
+ * o Then, the file_type[n].load re-scans for options, using
+ * KEXEC_ARCH_OPTIONS plus its loader-specific options subset.
+ * Any unrecognised options cause an error here.
+ *
+ * This is done so that main()'s/arch_process_options()'s getopt_long() calls
+ * don't choose a kernel filename from random arguments to options they don't
+ * recognise -- as they now recognise (if not act upon) all possible options.
+ */
+#define KEXEC_ALL_OPTIONS \
+ KEXEC_ARCH_OPTIONS \
+ {"append", 1, 0, OPT_APPEND},
+
+#define KEXEC_ALL_OPT_STR KEXEC_ARCH_OPT_STR
+
+#endif /* KEXEC_ARCH_CRIS_OPTIONS_H */
diff --git a/kexec/arch/cris/kexec-elf-cris.c b/kexec/arch/cris/kexec-elf-cris.c
index 4b56a20..b48b7b3 100644
--- a/kexec/arch/cris/kexec-elf-cris.c
+++ b/kexec/arch/cris/kexec-elf-cris.c
@@ -40,8 +40,6 @@
#include <arch/options.h>
#include "kexec-cris.h"

-#define OPT_APPEND (OPT_ARCH_MAX+0)
-
int elf_cris_probe(const char *buf, off_t len)
{
struct mem_ehdr ehdr;
@@ -89,8 +87,10 @@ int elf_cris_load(int argc, char **argv, const char *buf, off_t len,
unsigned int regs[16];
} cris_regframe;

+ /* See options.h -- add any more there, too. */
static const struct option options[] = {
KEXEC_ARCH_OPTIONS
+ {"append", 1, 0, OPT_APPEND},
{ 0, 0, 0, 0 },
};

diff --git a/kexec/arch/i386/include/arch/options.h b/kexec/arch/i386/include/arch/options.h
index 0695f37..990527c 100644
--- a/kexec/arch/i386/include/arch/options.h
+++ b/kexec/arch/i386/include/arch/options.h
@@ -1,6 +1,15 @@
#ifndef KEXEC_ARCH_I386_OPTIONS_H
#define KEXEC_ARCH_I386_OPTIONS_H

+/*
+ *************************************************************************
+ * NOTE NOTE NOTE
+ * This file is included for i386 builds *and* x86_64 builds (which build
+ * both x86_64 and i386 loaders).
+ * It contains the combined set of options used by i386 and x86_64.
+ *************************************************************************
+ */
+
#define OPT_RESET_VGA (OPT_MAX+0)
#define OPT_SERIAL (OPT_MAX+1)
#define OPT_SERIAL_BAUD (OPT_MAX+2)
@@ -10,6 +19,18 @@
#define OPT_ELF64_CORE (OPT_MAX+6)
#define OPT_ARCH_MAX (OPT_MAX+7)

+#define OPT_APPEND (OPT_ARCH_MAX+0)
+#define OPT_REUSE_CMDLINE (OPT_ARCH_MAX+1)
+#define OPT_RAMDISK (OPT_ARCH_MAX+2)
+#define OPT_ARGS_ELF (OPT_ARCH_MAX+3)
+#define OPT_ARGS_LINUX (OPT_ARCH_MAX+4)
+#define OPT_ARGS_NONE (OPT_ARCH_MAX+5)
+#define OPT_CL (OPT_ARCH_MAX+6)
+#define OPT_MOD (OPT_ARCH_MAX+7)
+#define OPT_VGA (OPT_ARCH_MAX+8)
+#define OPT_REAL_MODE (OPT_ARCH_MAX+9)
+
+/* Options relevant to the architecture (excluding loader-specific ones): */
#define KEXEC_ARCH_OPTIONS \
KEXEC_OPTIONS \
{ "reset-vga", 0, 0, OPT_RESET_VGA }, \
@@ -22,5 +43,35 @@

#define KEXEC_ARCH_OPT_STR KEXEC_OPT_STR ""

+/* The following two #defines list ALL of the options added by all of the
+ * architecture's loaders.
+ * o main() uses this complete list to scan for its options, ignoring
+ * arch-specific/loader-specific ones.
+ * o Then, arch_process_options() uses this complete list to scan for its
+ * options, ignoring general/loader-specific ones.
+ * o Then, the file_type[n].load re-scans for options, using
+ * KEXEC_ARCH_OPTIONS plus its loader-specific options subset.
+ * Any unrecognised options cause an error here.
+ *
+ * This is done so that main()'s/arch_process_options()'s getopt_long() calls
+ * don't choose a kernel filename from random arguments to options they don't
+ * recognise -- as they now recognise (if not act upon) all possible options.
+ */
+#define KEXEC_ALL_OPTIONS \
+ KEXEC_ARCH_OPTIONS \
+ { "command-line", 1, NULL, OPT_APPEND }, \
+ { "append", 1, NULL, OPT_APPEND }, \
+ { "reuse-cmdline", 0, NULL, OPT_REUSE_CMDLINE }, \
+ { "initrd", 1, NULL, OPT_RAMDISK }, \
+ { "ramdisk", 1, NULL, OPT_RAMDISK }, \
+ { "args-elf", 0, NULL, OPT_ARGS_ELF }, \
+ { "args-linux", 0, NULL, OPT_ARGS_LINUX }, \
+ { "args-none", 0, NULL, OPT_ARGS_NONE }, \
+ { "debug", 0, NULL, OPT_DEBUG }, \
+ { "module", 1, 0, OPT_MOD }, \
+ { "real-mode", 0, NULL, OPT_REAL_MODE },
+
+#define KEXEC_ALL_OPT_STR KEXEC_ARCH_OPT_STR
+
#endif /* KEXEC_ARCH_I386_OPTIONS_H */

diff --git a/kexec/arch/i386/kexec-beoboot-x86.c b/kexec/arch/i386/kexec-beoboot-x86.c
index 27c5a2c..6d459ae 100644
--- a/kexec/arch/i386/kexec-beoboot-x86.c
+++ b/kexec/arch/i386/kexec-beoboot-x86.c
@@ -84,7 +84,8 @@ int beoboot_load(int argc, char **argv, const char *buf, off_t UNUSED(len),
int debug, real_mode_entry;
int opt;
int result;
-#define OPT_REAL_MODE (OPT_ARCH_MAX+0)
+
+ /* See options.h -- add any more there, too. */
static const struct option options[] = {
KEXEC_ARCH_OPTIONS
{ "debug", 0, 0, OPT_DEBUG },
diff --git a/kexec/arch/i386/kexec-bzImage.c b/kexec/arch/i386/kexec-bzImage.c
index 53a50b3..ae18689 100644
--- a/kexec/arch/i386/kexec-bzImage.c
+++ b/kexec/arch/i386/kexec-bzImage.c
@@ -341,10 +341,8 @@ int bzImage_load(int argc, char **argv, const char *buf, off_t len,
int debug, real_mode_entry;
int opt;
int result;
-#define OPT_APPEND (OPT_ARCH_MAX+0)
-#define OPT_REUSE_CMDLINE (OPT_ARCH_MAX+1)
-#define OPT_RAMDISK (OPT_ARCH_MAX+2)
-#define OPT_REAL_MODE (OPT_ARCH_MAX+3)
+
+ /* See options.h -- add any more there, too. */
static const struct option options[] = {
KEXEC_ARCH_OPTIONS
{ "debug", 0, 0, OPT_DEBUG },
diff --git a/kexec/arch/i386/kexec-elf-x86.c b/kexec/arch/i386/kexec-elf-x86.c
index 2cb9d11..2e9cf9a 100644
--- a/kexec/arch/i386/kexec-elf-x86.c
+++ b/kexec/arch/i386/kexec-elf-x86.c
@@ -99,13 +99,8 @@ int elf_x86_load(int argc, char **argv, const char *buf, off_t len,
#define ARG_STYLE_LINUX 1
#define ARG_STYLE_NONE 2
int opt;
-#define OPT_APPEND (OPT_ARCH_MAX+0)
-#define OPT_REUSE_CMDLINE (OPT_ARCH_MAX+1)
-#define OPT_RAMDISK (OPT_ARCH_MAX+2)
-#define OPT_ARGS_ELF (OPT_ARCH_MAX+3)
-#define OPT_ARGS_LINUX (OPT_ARCH_MAX+4)
-#define OPT_ARGS_NONE (OPT_ARCH_MAX+5)

+ /* See options.h -- add any more there, too. */
static const struct option options[] = {
KEXEC_ARCH_OPTIONS
{ "command-line", 1, NULL, OPT_APPEND },
diff --git a/kexec/arch/i386/kexec-multiboot-x86.c b/kexec/arch/i386/kexec-multiboot-x86.c
index 970de2a..23dab7b 100644
--- a/kexec/arch/i386/kexec-multiboot-x86.c
+++ b/kexec/arch/i386/kexec-multiboot-x86.c
@@ -157,10 +157,7 @@ int multiboot_x86_load(int argc, char **argv, const char *buf, off_t len,
uint32_t u;
int opt;
int modules, mod_command_line_space;
-#define OPT_CL (OPT_ARCH_MAX+0)
-#define OPT_REUSE_CMDLINE (OPT_ARCH_MAX+1)
-#define OPT_MOD (OPT_ARCH_MAX+2)
-#define OPT_VGA (OPT_ARCH_MAX+3)
+ /* See options.h -- add any more there, too. */
static const struct option options[] = {
KEXEC_ARCH_OPTIONS
{ "command-line", 1, 0, OPT_CL },
diff --git a/kexec/arch/i386/kexec-x86.c b/kexec/arch/i386/kexec-x86.c
index d33a14b..5c701aa 100644
--- a/kexec/arch/i386/kexec-x86.c
+++ b/kexec/arch/i386/kexec-x86.c
@@ -69,10 +69,10 @@ struct arch_options_t arch_options = {
int arch_process_options(int argc, char **argv)
{
static const struct option options[] = {
- KEXEC_ARCH_OPTIONS
+ KEXEC_ALL_OPTIONS
{ 0, 0, NULL, 0 },
};
- static const char short_options[] = KEXEC_ARCH_OPT_STR;
+ static const char short_options[] = KEXEC_ALL_OPT_STR;
int opt;
unsigned long value;
char *end;
diff --git a/kexec/arch/ia64/include/arch/options.h b/kexec/arch/ia64/include/arch/options.h
index 3053576..e8754ad 100644
--- a/kexec/arch/ia64/include/arch/options.h
+++ b/kexec/arch/ia64/include/arch/options.h
@@ -1,11 +1,42 @@
#ifndef KEXEC_ARCH_IA64_OPTIONS_H
#define KEXEC_ARCH_IA64_OPTIONS_H

-#define OPT_ARCH_MAX (OPT_MAX+0)
+#define OPT_ARCH_MAX (OPT_MAX+0)
+#define OPT_APPEND (OPT_ARCH_MAX+0)
+#define OPT_RAMDISK (OPT_ARCH_MAX+1)
+#define OPT_NOIO (OPT_ARCH_MAX+2)
+#define OPT_VMM (OPT_ARCH_MAX+3)

+/* Options relevant to the architecture (excluding loader-specific ones),
+ * in this case none:
+ */
#define KEXEC_ARCH_OPTIONS \
KEXEC_OPTIONS \

#define KEXEC_ARCH_OPT_STR KEXEC_OPT_STR ""

+/* The following two #defines list ALL of the options added by all of the
+ * architecture's loaders.
+ * o main() uses this complete list to scan for its options, ignoring
+ * arch-specific/loader-specific ones.
+ * o Then, arch_process_options() uses this complete list to scan for its
+ * options, ignoring general/loader-specific ones.
+ * o Then, the file_type[n].load re-scans for options, using
+ * KEXEC_ARCH_OPTIONS plus its loader-specific options subset.
+ * Any unrecognised options cause an error here.
+ *
+ * This is done so that main()'s/arch_process_options()'s getopt_long() calls
+ * don't choose a kernel filename from random arguments to options they don't
+ * recognise -- as they now recognise (if not act upon) all possible options.
+ */
+#define KEXEC_ALL_OPTIONS \
+ KEXEC_ARCH_OPTIONS \
+ {"command-line", 1, 0, OPT_APPEND}, \
+ {"append", 1, 0, OPT_APPEND}, \
+ {"initrd", 1, 0, OPT_RAMDISK}, \
+ {"noio", 0, 0, OPT_NOIO}, \
+ {"vmm", 1, 0, OPT_VMM}, \
+
+#define KEXEC_ALL_OPT_STR KEXEC_OPT_STR
+
#endif /* KEXEC_ARCH_IA64_OPTIONS_H */
diff --git a/kexec/arch/ia64/kexec-elf-ia64.c b/kexec/arch/ia64/kexec-elf-ia64.c
index 3bb5a4d..8da061e 100644
--- a/kexec/arch/ia64/kexec-elf-ia64.c
+++ b/kexec/arch/ia64/kexec-elf-ia64.c
@@ -45,11 +45,6 @@
#include "crashdump-ia64.h"
#include <arch/options.h>

-#define OPT_APPEND (OPT_ARCH_MAX+0)
-#define OPT_RAMDISK (OPT_ARCH_MAX+1)
-#define OPT_NOIO (OPT_ARCH_MAX+2)
-#define OPT_VMM (OPT_ARCH_MAX+3)
-
static const int probe_debug = 0;
extern unsigned long saved_efi_memmap_size;

@@ -136,6 +131,8 @@ int elf_ia64_load(int argc, char **argv, const char *buf, off_t len,
int result;
int opt;
char *efi_memmap_buf, *boot_param;
+
+ /* See options.h -- add any more there, too. */
static const struct option options[] = {
KEXEC_ARCH_OPTIONS
{"command-line", 1, 0, OPT_APPEND},
diff --git a/kexec/arch/mips/include/arch/options.h b/kexec/arch/mips/include/arch/options.h
index bc5f706..07b4f63 100644
--- a/kexec/arch/mips/include/arch/options.h
+++ b/kexec/arch/mips/include/arch/options.h
@@ -1,11 +1,36 @@
#ifndef KEXEC_ARCH_MIPS_OPTIONS_H
#define KEXEC_ARCH_MIPS_OPTIONS_H

-#define OPT_ARCH_MAX (OPT_MAX+0)
+#define OPT_ARCH_MAX (OPT_MAX+0)
+#define OPT_APPEND (OPT_ARCH_MAX+0)

+/* Options relevant to the architecture (excluding loader-specific ones),
+ * in this case none:
+ */
#define KEXEC_ARCH_OPTIONS \
KEXEC_OPTIONS \

#define KEXEC_ARCH_OPT_STR KEXEC_OPT_STR ""

+/* The following two #defines list ALL of the options added by all of the
+ * architecture's loaders.
+ * o main() uses this complete list to scan for its options, ignoring
+ * arch-specific/loader-specific ones.
+ * o Then, arch_process_options() uses this complete list to scan for its
+ * options, ignoring general/loader-specific ones.
+ * o Then, the file_type[n].load re-scans for options, using
+ * KEXEC_ARCH_OPTIONS plus its loader-specific options subset.
+ * Any unrecognised options cause an error here.
+ *
+ * This is done so that main()'s/arch_process_options()'s getopt_long() calls
+ * don't choose a kernel filename from random arguments to options they don't
+ * recognise -- as they now recognise (if not act upon) all possible options.
+ */
+#define KEXEC_ALL_OPTIONS \
+ KEXEC_ARCH_OPTIONS \
+ {"command-line", 1, 0, OPT_APPEND}, \
+ {"append", 1, 0, OPT_APPEND},
+
+#define KEXEC_ALL_OPT_STR KEXEC_ARCH_OPT_STR
+
#endif /* KEXEC_ARCH_MIPS_OPTIONS_H */
diff --git a/kexec/arch/mips/kexec-elf-mips.c b/kexec/arch/mips/kexec-elf-mips.c
index ce6bf0c..a9c865e 100644
--- a/kexec/arch/mips/kexec-elf-mips.c
+++ b/kexec/arch/mips/kexec-elf-mips.c
@@ -35,7 +35,6 @@ static const int probe_debug = 0;
#define BOOTLOADER "kexec"
#define MAX_COMMAND_LINE 256
#define UPSZ(X) ((sizeof(X) + 3) & ~3)
-#define OPT_APPEND (OPT_ARCH_MAX+0)
static char cmdline_buf[256] = "kexec ";

int elf_mips_probe(const char *buf, off_t len)
@@ -82,6 +81,8 @@ int elf_mips_load(int argc, char **argv, const char *buf, off_t len,
unsigned long cmdline_addr;
size_t i;
unsigned long bss_start = 0, bss_size = 0;
+
+ /* See options.h if adding any more options. */
static const struct option options[] = {
KEXEC_ARCH_OPTIONS
{"command-line", 1, 0, OPT_APPEND},
diff --git a/kexec/arch/ppc/include/arch/options.h b/kexec/arch/ppc/include/arch/options.h
index df14db5..f646ccc 100644
--- a/kexec/arch/ppc/include/arch/options.h
+++ b/kexec/arch/ppc/include/arch/options.h
@@ -3,9 +3,43 @@

#define OPT_ARCH_MAX (OPT_MAX+0)

+/* All 'local' loader options: */
+#define OPT_APPEND (OPT_ARCH_MAX+0)
+#define OPT_GAMECUBE (OPT_ARCH_MAX+1)
+#define OPT_DTB (OPT_ARCH_MAX+2)
+#define OPT_NODES (OPT_ARCH_MAX+3)
+
+/* Options relevant to the architecture (excluding loader-specific ones),
+ * in this case none:
+ */
#define KEXEC_ARCH_OPTIONS \
KEXEC_OPTIONS \

#define KEXEC_ARCH_OPT_STR KEXEC_OPT_STR ""

+/* The following two #defines list ALL of the options added by all of the
+ * architecture's loaders.
+ * o main() uses this complete list to scan for its options, ignoring
+ * arch-specific/loader-specific ones.
+ * o Then, arch_process_options() uses this complete list to scan for its
+ * options, ignoring general/loader-specific ones.
+ * o Then, the file_type[n].load re-scans for options, using
+ * KEXEC_ARCH_OPTIONS plus its loader-specific options subset.
+ * Any unrecognised options cause an error here.
+ *
+ * This is done so that main()'s/arch_process_options()'s getopt_long() calls
+ * don't choose a kernel filename from random arguments to options they don't
+ * recognise -- as they now recognise (if not act upon) all possible options.
+ */
+#define KEXEC_ALL_OPTIONS \
+ KEXEC_ARCH_OPTIONS \
+ {"command-line", 1, 0, OPT_APPEND},\
+ {"append", 1, 0, OPT_APPEND},\
+ {"gamecube", 1, 0, OPT_GAMECUBE},\
+ {"dtb", 1, 0, OPT_DTB},\
+ {"reuse-node", 1, 0, OPT_NODES},\
+ {"debug", 0, 0, OPT_DEBUG},
+
+#define KEXEC_ALL_OPT_STR KEXEC_OPT_STR
+
#endif /* KEXEC_ARCH_PPC_OPTIONS_H */
diff --git a/kexec/arch/ppc/kexec-dol-ppc.c b/kexec/arch/ppc/kexec-dol-ppc.c
index 83c122a..8de5293 100644
--- a/kexec/arch/ppc/kexec-dol-ppc.c
+++ b/kexec/arch/ppc/kexec-dol-ppc.c
@@ -335,8 +335,8 @@ int dol_ppc_load(int argc, char **argv, const char *buf, off_t UNUSED(len),
unsigned long lowest_start;
int i, j, k;
int opt;
-#define OPT_APPEND (OPT_ARCH_MAX+0)

+ /* See options.h -- add any more there, too. */
static const struct option options[] = {
KEXEC_ARCH_OPTIONS
{"debug", 0, 0, OPT_DEBUG},
@@ -344,7 +344,7 @@ int dol_ppc_load(int argc, char **argv, const char *buf, off_t UNUSED(len),
{"append", 1, 0, OPT_APPEND},
{0, 0, 0, 0},
};
- static const char short_options[] = KEXEC_ARCH_OPT_STR "d";
+ static const char short_options[] = KEXEC_ARCH_OPT_STR;

/*
* Parse the command line arguments
diff --git a/kexec/arch/ppc/kexec-elf-ppc.c b/kexec/arch/ppc/kexec-elf-ppc.c
index a54a5d5..cb2c07a 100644
--- a/kexec/arch/ppc/kexec-elf-ppc.c
+++ b/kexec/arch/ppc/kexec-elf-ppc.c
@@ -113,10 +113,7 @@ static void gamecube_hack_addresses(struct mem_ehdr *ehdr)
}
}

-#define OPT_APPEND (OPT_ARCH_MAX+0)
-#define OPT_GAMECUBE (OPT_ARCH_MAX+1)
-#define OPT_DTB (OPT_ARCH_MAX+2)
-#define OPT_NODES (OPT_ARCH_MAX+3)
+/* See options.h -- add any more there, too. */
static const struct option options[] = {
KEXEC_ARCH_OPTIONS
{"command-line", 1, 0, OPT_APPEND},
@@ -126,7 +123,7 @@ static const struct option options[] = {
{"reuse-node", 1, 0, OPT_NODES},
{0, 0, 0, 0},
};
-static const char short_options[] = KEXEC_ARCH_OPT_STR "d";
+static const char short_options[] = KEXEC_ARCH_OPT_STR;

void elf_ppc_usage(void)
{
diff --git a/kexec/arch/ppc/kexec-uImage-ppc.c b/kexec/arch/ppc/kexec-uImage-ppc.c
index 0a655a3..45cde2f 100644
--- a/kexec/arch/ppc/kexec-uImage-ppc.c
+++ b/kexec/arch/ppc/kexec-uImage-ppc.c
@@ -14,9 +14,7 @@
#include "fixup_dtb.h"
#include <kexec-uImage.h>

-#define OPT_APPEND (OPT_ARCH_MAX+0)
-#define OPT_DTB (OPT_ARCH_MAX+1)
-#define OPT_NODES (OPT_ARCH_MAX+2)
+/* See options.h -- add any more there, too. */
static const struct option options[] = {
KEXEC_ARCH_OPTIONS
{"command-line", 1, 0, OPT_APPEND},
@@ -25,7 +23,7 @@ static const struct option options[] = {
{"reuse-node", 1, 0, OPT_NODES},
{0, 0, 0, 0},
};
-static const char short_options[] = KEXEC_ARCH_OPT_STR "d";
+static const char short_options[] = KEXEC_ARCH_OPT_STR;

void uImage_ppc_usage(void)
{
diff --git a/kexec/arch/ppc64/include/arch/options.h b/kexec/arch/ppc64/include/arch/options.h
index 973cd4f..8f11c83 100644
--- a/kexec/arch/ppc64/include/arch/options.h
+++ b/kexec/arch/ppc64/include/arch/options.h
@@ -1,13 +1,46 @@
#ifndef KEXEC_ARCH_PPC64_OPTIONS_H
#define KEXEC_ARCH_PPC64_OPTIONS_H

-#define OPT_ARCH_MAX (OPT_MAX+0)
-#define OPT_ELF64_CORE (OPT_MAX+1)
+#define OPT_ELF64_CORE (OPT_MAX+0)
+#define OPT_ARCH_MAX (OPT_MAX+1)

+/* All 'local' loader options: */
+#define OPT_APPEND (OPT_ARCH_MAX+0)
+#define OPT_RAMDISK (OPT_ARCH_MAX+1)
+#define OPT_DEVICETREEBLOB (OPT_ARCH_MAX+2)
+#define OPT_ARGS_IGNORE (OPT_ARCH_MAX+3)
+
+/* Options relevant to the architecture (excluding loader-specific ones): */
#define KEXEC_ARCH_OPTIONS \
KEXEC_OPTIONS \
{ "elf64-core-headers", 0, 0, OPT_ELF64_CORE }, \

#define KEXEC_ARCH_OPT_STR KEXEC_OPT_STR ""

+/* The following two #defines list ALL of the options added by all of the
+ * architecture's loaders.
+ * o main() uses this complete list to scan for its options, ignoring
+ * arch-specific/loader-specific ones.
+ * o Then, arch_process_options() uses this complete list to scan for its
+ * options, ignoring general/loader-specific ones.
+ * o Then, the file_type[n].load re-scans for options, using
+ * KEXEC_ARCH_OPTIONS plus its loader-specific options subset.
+ * Any unrecognised options cause an error here.
+ *
+ * This is done so that main()'s/arch_process_options()'s getopt_long() calls
+ * don't choose a kernel filename from random arguments to options they don't
+ * recognise -- as they now recognise (if not act upon) all possible options.
+ */
+#define KEXEC_ALL_OPTIONS \
+ KEXEC_ARCH_OPTIONS \
+ { "command-line", 1, NULL, OPT_APPEND }, \
+ { "append", 1, NULL, OPT_APPEND }, \
+ { "ramdisk", 1, NULL, OPT_RAMDISK }, \
+ { "initrd", 1, NULL, OPT_RAMDISK }, \
+ { "devicetreeblob", 1, NULL, OPT_DEVICETREEBLOB }, \
+ { "args-linux", 0, NULL, OPT_ARGS_IGNORE },
+
+#define KEXEC_ALL_OPT_STR KEXEC_OPT_STR
+
+
#endif /* KEXEC_ARCH_PPC64_OPTIONS_H */
diff --git a/kexec/arch/ppc64/kexec-elf-ppc64.c b/kexec/arch/ppc64/kexec-elf-ppc64.c
index d65a5d5..ab6da7c 100644
--- a/kexec/arch/ppc64/kexec-elf-ppc64.c
+++ b/kexec/arch/ppc64/kexec-elf-ppc64.c
@@ -93,11 +93,7 @@ int elf_ppc64_load(int argc, char **argv, const char *buf, off_t len,
uint32_t my_run_at_load;
unsigned int slave_code[256/sizeof (unsigned int)], master_entry;

-#define OPT_APPEND (OPT_ARCH_MAX+0)
-#define OPT_RAMDISK (OPT_ARCH_MAX+1)
-#define OPT_DEVICETREEBLOB (OPT_ARCH_MAX+2)
-#define OPT_ARGS_IGNORE (OPT_ARCH_MAX+3)
-
+ /* See options.h -- add any more there, too. */
static const struct option options[] = {
KEXEC_ARCH_OPTIONS
{ "command-line", 1, NULL, OPT_APPEND },
@@ -347,5 +343,11 @@ int elf_ppc64_load(int argc, char **argv, const char *buf, off_t len,

void elf_ppc64_usage(void)
{
+ fprintf(stderr, " --command-line=<Command line> command line to append.\n");
+ fprintf(stderr, " --append=<Command line> same as --command-line.\n");
+ fprintf(stderr, " --ramdisk=<filename> Initial RAM disk.\n");
+ fprintf(stderr, " --initrd=<filename> same as --ramdisk.\n");
+ fprintf(stderr, " --devicetreeblob=<filename> Specify device tree blob file.\n");
+
fprintf(stderr, "elf support is still broken\n");
}
diff --git a/kexec/arch/ppc64/kexec-ppc64.c b/kexec/arch/ppc64/kexec-ppc64.c
index f9dc65b..48ea421 100644
--- a/kexec/arch/ppc64/kexec-ppc64.c
+++ b/kexec/arch/ppc64/kexec-ppc64.c
@@ -735,11 +735,6 @@ int file_types = sizeof(file_type) / sizeof(file_type[0]);

void arch_usage(void)
{
- fprintf(stderr, " --command-line=<Command line> command line to append.\n");
- fprintf(stderr, " --append=<Command line> same as --command-line.\n");
- fprintf(stderr, " --ramdisk=<filename> Initial RAM disk.\n");
- fprintf(stderr, " --initrd=<filename> same as --ramdisk.\n");
- fprintf(stderr, " --devicetreeblob=<filename> Specify device tree blob file.\n");
fprintf(stderr, " --elf64-core-headers Prepare core headers in ELF64 format\n");
}

@@ -749,11 +744,14 @@ struct arch_options_t arch_options = {

int arch_process_options(int argc, char **argv)
{
+ /* We look for all options so getopt_long doesn't start reordering
+ * argv[] before file_type[n].load() gets a look in.
+ */
static const struct option options[] = {
- KEXEC_ARCH_OPTIONS
+ KEXEC_ALL_OPTIONS
{ 0, 0, NULL, 0 },
};
- static const char short_options[] = KEXEC_ARCH_OPT_STR;
+ static const char short_options[] = KEXEC_ALL_OPT_STR;
int opt;

opterr = 0; /* Don't complain about unrecognized options here */
diff --git a/kexec/arch/s390/include/arch/options.h b/kexec/arch/s390/include/arch/options.h
index 2979617..b57539f 100644
--- a/kexec/arch/s390/include/arch/options.h
+++ b/kexec/arch/s390/include/arch/options.h
@@ -1,11 +1,37 @@
#ifndef KEXEC_ARCH_S390_OPTIONS_H
#define KEXEC_ARCH_S390_OPTIONS_H

-#define OPT_ARCH_MAX (OPT_MAX+0)
+#define OPT_ARCH_MAX (OPT_MAX+0)
+#define OPT_APPEND OPT_MAX+0
+#define OPT_RAMDISK OPT_MAX+1

+/* Options relevant to the architecture (excluding loader-specific ones),
+ * in this case none:
+ */
#define KEXEC_ARCH_OPTIONS \
KEXEC_OPTIONS \

#define KEXEC_ARCH_OPT_STR KEXEC_OPT_STR ""

+/* The following two #defines list ALL of the options added by all of the
+ * architecture's loaders.
+ * o main() uses this complete list to scan for its options, ignoring
+ * arch-specific/loader-specific ones.
+ * o Then, arch_process_options() uses this complete list to scan for its
+ * options, ignoring general/loader-specific ones.
+ * o Then, the file_type[n].load re-scans for options, using
+ * KEXEC_ARCH_OPTIONS plus its loader-specific options subset.
+ * Any unrecognised options cause an error here.
+ *
+ * This is done so that main()'s/arch_process_options()'s getopt_long() calls
+ * don't choose a kernel filename from random arguments to options they don't
+ * recognise -- as they now recognise (if not act upon) all possible options.
+ */
+#define KEXEC_ALL_OPTIONS \
+ KEXEC_ARCH_OPTIONS \
+ {"command-line", 1, 0, OPT_APPEND}, \
+ {"initrd", 1, 0, OPT_RAMDISK},
+
+#define KEXEC_ALL_OPT_STR KEXEC_ARCH_OPT_STR
+
#endif /* KEXEC_ARCH_S390_OPTIONS_H */
diff --git a/kexec/arch/s390/kexec-image.c b/kexec/arch/s390/kexec-image.c
index 13e550d..7ef8e29 100644
--- a/kexec/arch/s390/kexec-image.c
+++ b/kexec/arch/s390/kexec-image.c
@@ -19,9 +19,7 @@
#include <getopt.h>
#include "../../kexec.h"
#include "kexec-s390.h"
-
-#define OPT_APPEND OPT_MAX+0
-#define OPT_RAMDISK OPT_MAX+1
+#include <arch/options.h>

int
image_s390_load(int argc, char **argv, const char *kernel_buf,
diff --git a/kexec/arch/sh/include/arch/options.h b/kexec/arch/sh/include/arch/options.h
index e02960d..4bdd6a3 100644
--- a/kexec/arch/sh/include/arch/options.h
+++ b/kexec/arch/sh/include/arch/options.h
@@ -7,16 +7,36 @@
#define OPT_NBSD_HOWTO (OPT_ARCH_MAX+3)
#define OPT_NBSD_MROOT (OPT_ARCH_MAX+4)

-
+/* Options relevant to the architecture (excluding loader-specific ones): */
#define KEXEC_ARCH_OPTIONS \
KEXEC_OPTIONS \
{"command-line", 1, 0, OPT_APPEND}, \
{"append", 1, 0, OPT_APPEND}, \
{"empty-zero", 1, 0, OPT_APPEND}, \
{"howto", 1, 0, OPT_NBSD_HOWTO}, \
- {"miniroot", 1, 0, OPT_NBSD_MROOT}, \
-
+ {"miniroot", 1, 0, OPT_NBSD_MROOT},
+/* These options seem to be loader-specific rather than cris-specific, so
+ * ought to be moved to KEXEC_ALL_OPTIONS below and parsed in the relevant
+ * loader, e.g. kexec-netbsd-sh.c
+ */

#define KEXEC_ARCH_OPT_STR KEXEC_OPT_STR ""

+/* The following two #defines list ALL of the options added by all of the
+ * architecture's loaders.
+ * o main() uses this complete list to scan for its options, ignoring
+ * arch-specific/loader-specific ones.
+ * o Then, arch_process_options() uses this complete list to scan for its
+ * options, ignoring general/loader-specific ones.
+ * o Then, the file_type[n].load re-scans for options, using
+ * KEXEC_ARCH_OPTIONS plus its loader-specific options subset.
+ * Any unrecognised options cause an error here.
+ *
+ * This is done so that main()'s/arch_process_options()'s getopt_long() calls
+ * don't choose a kernel filename from random arguments to options they don't
+ * recognise -- as they now recognise (if not act upon) all possible options.
+ */
+#define KEXEC_ALL_OPTIONS KEXEC_ARCH_OPTIONS
+#define KEXEC_ALL_OPT_STR KEXEC_ARCH_OPT_STR
+
#endif /* KEXEC_ARCH_SH_OPTIONS_H */
diff --git a/kexec/arch/sh/kexec-sh.c b/kexec/arch/sh/kexec-sh.c
index 1ad3d38..4b21ee8 100644
--- a/kexec/arch/sh/kexec-sh.c
+++ b/kexec/arch/sh/kexec-sh.c
@@ -97,8 +97,13 @@ void arch_usage(void)

int arch_process_options(int argc, char **argv)
{
+ /* The common options amongst loaders (e.g. --append) should be read
+ * here, and the loader-specific options (e.g. NetBSD stuff) should
+ * then be re-parsed in the loader.
+ * (e.g. in kexec-netbsd-sh.c, for example.)
+ */
static const struct option options[] = {
- KEXEC_ARCH_OPTIONS
+ KEXEC_ALL_OPTIONS
{ 0, 0, NULL, 0 },
};
static const char short_options[] = KEXEC_ARCH_OPT_STR;
diff --git a/kexec/arch/x86_64/include/arch/options.h b/kexec/arch/x86_64/include/arch/options.h
deleted file mode 100644
index 75065b9..0000000
--- a/kexec/arch/x86_64/include/arch/options.h
+++ /dev/null
@@ -1,22 +0,0 @@
-#ifndef KEXEC_ARCH_X86_64_OPTIONS_H
-#define KEXEC_ARCH_X86_64_OPTIONS_H
-
-#define OPT_RESET_VGA (OPT_MAX+0)
-#define OPT_SERIAL (OPT_MAX+1)
-#define OPT_SERIAL_BAUD (OPT_MAX+2)
-#define OPT_CONSOLE_VGA (OPT_MAX+3)
-#define OPT_CONSOLE_SERIAL (OPT_MAX+4)
-#define OPT_ARCH_MAX (OPT_MAX+5)
-
-#define KEXEC_ARCH_OPTIONS \
- KEXEC_OPTIONS \
- { "reset-vga", 0, 0, OPT_RESET_VGA }, \
- { "serial", 1, 0, OPT_SERIAL }, \
- { "serial-baud", 1, 0, OPT_SERIAL_BAUD }, \
- { "console-vga", 0, 0, OPT_CONSOLE_VGA }, \
- { "console-serial", 0, 0, OPT_CONSOLE_SERIAL }, \
-
-#define KEXEC_ARCH_OPT_STR KEXEC_OPT_STR ""
-
-#endif /* KEXEC_ARCH_X86_64_OPTIONS_H */
-
diff --git a/kexec/arch/x86_64/include/arch/options.h b/kexec/arch/x86_64/include/arch/options.h
new file mode 120000
index 0000000..047b0f9
--- /dev/null
+++ b/kexec/arch/x86_64/include/arch/options.h
@@ -0,0 +1 @@
+../../../i386/include/arch/options.h
\ No newline at end of file
diff --git a/kexec/arch/x86_64/kexec-elf-x86_64.c b/kexec/arch/x86_64/kexec-elf-x86_64.c
index 20c7d77..a8204bc 100644
--- a/kexec/arch/x86_64/kexec-elf-x86_64.c
+++ b/kexec/arch/x86_64/kexec-elf-x86_64.c
@@ -98,13 +98,8 @@ int elf_x86_64_load(int argc, char **argv, const char *buf, off_t len,
#define ARG_STYLE_LINUX 1
#define ARG_STYLE_NONE 2
int opt;
-#define OPT_APPEND (OPT_ARCH_MAX+0)
-#define OPT_REUSE_CMDLINE (OPT_ARCH_MAX+1)
-#define OPT_RAMDISK (OPT_ARCH_MAX+2)
-#define OPT_ARGS_ELF (OPT_ARCH_MAX+3)
-#define OPT_ARGS_LINUX (OPT_ARCH_MAX+4)
-#define OPT_ARGS_NONE (OPT_ARCH_MAX+5)

+ /* See options.h and add any new options there too! */
static const struct option options[] = {
KEXEC_ARCH_OPTIONS
{ "command-line", 1, NULL, OPT_APPEND },
diff --git a/kexec/arch/x86_64/kexec-x86_64.c b/kexec/arch/x86_64/kexec-x86_64.c
index 49bfd36..a4f2d10 100644
--- a/kexec/arch/x86_64/kexec-x86_64.c
+++ b/kexec/arch/x86_64/kexec-x86_64.c
@@ -74,10 +74,10 @@ static struct {
int arch_process_options(int argc, char **argv)
{
static const struct option options[] = {
- KEXEC_ARCH_OPTIONS
+ KEXEC_ALL_OPTIONS
{ 0, 0, NULL, 0 },
};
- static const char short_options[] = KEXEC_ARCH_OPT_STR;
+ static const char short_options[] = KEXEC_ALL_OPT_STR;
int opt;
unsigned long value;
char *end;
diff --git a/kexec/kexec.c b/kexec/kexec.c
index e9a13a7..2d8258f 100644
--- a/kexec/kexec.c
+++ b/kexec/kexec.c
@@ -1062,17 +1062,17 @@ int main(int argc, char *argv[])
int result = 0;
int fileind;
static const struct option options[] = {
- KEXEC_ARCH_OPTIONS
+ KEXEC_ALL_OPTIONS
{ 0, 0, 0, 0},
};
- static const char short_options[] = KEXEC_OPT_STR;
+ static const char short_options[] = KEXEC_ALL_OPT_STR;

arch_init();

- opterr = 0; /* Don't complain about unrecognized options here */
while ((opt = getopt_long(argc, argv, short_options,
options, 0)) != -1) {
switch(opt) {
+ case '?':
case OPT_HELP:
usage();
return 0;
--
1.6.3.3