[RFC PATCH] kexec-tools: Fix option/argument parsing
Matt Evans
matt at ozlabs.org
Thu May 13 04:14:32 EDT 2010
Hi,
In playing with kexec-tools I've noticed various problems with the argument
passing, meaning one has to be careful to use certain forms of arguments
and present them in a certain order.
The arguments end up being parsed three times, each getting more specific
than the last. main() looks for general args, arch_process_options() looks
for options common to all loaders for the arch, and then finally many
file_type load() methods check for options specific to that filetype.
As GNU getopt works, it re-orders the argv[] pushing any args it doesn't
recognise to the end. This includes arguments to valid options which
are simply not recognised the first time around.
For example, this does not work:
# ./kexec -l --append "init=/bin/foo" /boot/vmlinux
Cannot open `init=/bin/foo': No such file or directory
but this does:
# ./kexec -l --append="init=/bin/foo" /boot/vmlinux
<joy>
Using the --opt<space>arg variant results in the first non-option argument
in main() being "init=/bin/foo" which is then used as the kernel filename,
failing. Also, the order affects things in unintuitive ways:
# ./kexec -l /boot/vmlinux --append "init=/bin/foo"
<appears to load correctly, but command line appended with "/boot/vmlinux"!>
This behaviour is avoided by using the --opt= forms, but getopt does allow
both and hence the user can have a fairly frustrating experience. (Doing
something unexpected (ex. 3) is more annoying than an error exit (ex. 1)
in many cases.)
The fix presented here is to create a new #define to encapsulate all possible
options for an architecture build. The intention is that this set includes
all possible loaders' all possible options.
main() walks through the options and silently ignores any non-general
options (BUT respects that "--arg foo" should remain together, as
getopt_long() does now recognise it). arch_process_options() walks through
them again and responds to any arch-specific options, again ignoring but
respecting any non-arch options. Finally the loader may look for its
options, and find them in-order and present. Any outside of this combined
set are complained-about as usual.
So, comments please. Is this a reasonable way to do it or is there an
obvious better way I've missed? :-) So far I have been able to test on
x86(32,64) and ppc(32,64) but none of the others. :(
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 at 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 | 4 +-
30 files changed, 340 insertions(+), 98 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..a76539e 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..f4cf49f 100644
--- a/kexec/kexec.c
+++ b/kexec/kexec.c
@@ -1062,10 +1062,10 @@ 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();
--
1.6.3.3
More information about the kexec
mailing list