2010-07-07 11:12:45 +00:00
|
|
|
From: Andreas Gruenbacher <agruen@suse.de>
|
|
|
|
Subject: Novell/external support flag in modules
|
|
|
|
Patch-mainline: Never, SLES feature
|
|
|
|
|
|
|
|
Upon module load, check if a module is supported, and set the
|
|
|
|
N (TAINT_NO_SUPPORT) or X (TAINT_EXTERNAL_SUPPORT) tail flags
|
|
|
|
for unsupported or externally suported modules.
|
|
|
|
|
|
|
|
Changes:
|
|
|
|
* Feb 21 2008 - jeffm
|
|
|
|
- 2.6.25 claimed -S and bumped the flags up a bit, modpost now uses -N
|
|
|
|
|
|
|
|
Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
|
|
|
|
|
|
|
|
---
|
|
|
|
|
2011-04-19 20:09:59 +00:00
|
|
|
Documentation/kernel-parameters.txt | 5 ++
|
2010-07-07 11:12:45 +00:00
|
|
|
Documentation/sysctl/kernel.txt | 12 ++++++
|
|
|
|
Makefile | 5 ++
|
2011-04-19 20:09:59 +00:00
|
|
|
include/linux/kernel.h | 9 ++++
|
|
|
|
include/linux/module.h | 1
|
|
|
|
kernel/ksysfs.c | 23 ++++++++++++
|
|
|
|
kernel/module.c | 65 ++++++++++++++++++++++++++++++++++++
|
|
|
|
kernel/panic.c | 9 ++++
|
2010-07-07 11:12:45 +00:00
|
|
|
kernel/sysctl.c | 9 ++++
|
|
|
|
scripts/Makefile.modpost | 4 +-
|
|
|
|
scripts/mod/modpost.c | 65 +++++++++++++++++++++++++++++++++++-
|
2011-04-19 20:09:59 +00:00
|
|
|
11 files changed, 205 insertions(+), 2 deletions(-)
|
2010-07-07 11:12:45 +00:00
|
|
|
|
|
|
|
--- a/Documentation/kernel-parameters.txt
|
|
|
|
+++ b/Documentation/kernel-parameters.txt
|
2011-04-19 20:09:59 +00:00
|
|
|
@@ -2504,6 +2504,11 @@ and is between 256 and 4096 characters.
|
|
|
|
[X86]
|
|
|
|
Set unknown_nmi_panic=1 early on boot.
|
2010-07-07 11:12:45 +00:00
|
|
|
|
|
|
|
+ unsupported Allow loading of unsupported kernel modules:
|
|
|
|
+ 0 = only allow supported modules,
|
|
|
|
+ 1 = warn when loading unsupported modules,
|
|
|
|
+ 2 = don't warn.
|
|
|
|
+
|
2011-04-19 20:09:59 +00:00
|
|
|
usbcore.autosuspend=
|
|
|
|
[USB] The autosuspend time delay (in seconds) used
|
|
|
|
for newly-detected USB devices (default 2). This
|
2010-07-07 11:12:45 +00:00
|
|
|
--- a/Documentation/sysctl/kernel.txt
|
|
|
|
+++ b/Documentation/sysctl/kernel.txt
|
2011-04-19 20:09:59 +00:00
|
|
|
@@ -491,6 +491,18 @@ can be ORed together:
|
2010-07-07 11:12:45 +00:00
|
|
|
instead of using the one provided by the hardware.
|
|
|
|
512 - A kernel warning has occurred.
|
|
|
|
1024 - A module from drivers/staging was loaded.
|
|
|
|
+ 0x40000000 - An unsupported kernel module was loaded.
|
|
|
|
+ 0x80000000 - An kernel module with external support was loaded.
|
|
|
|
+
|
|
|
|
+==============================================================
|
|
|
|
+
|
|
|
|
+unsupported:
|
|
|
|
+
|
|
|
|
+Allow to load unsupported kernel modules:
|
|
|
|
+
|
|
|
|
+ 0 - refuse to load unsupported modules,
|
|
|
|
+ 1 - warn when loading unsupported modules,
|
|
|
|
+ 2 - don't warn.
|
|
|
|
|
|
|
|
==============================================================
|
|
|
|
|
|
|
|
--- a/Makefile
|
|
|
|
+++ b/Makefile
|
2011-04-19 20:09:59 +00:00
|
|
|
@@ -362,6 +362,11 @@ KBUILD_AFLAGS_MODULE := -DMODULE
|
|
|
|
KBUILD_CFLAGS_MODULE := -DMODULE
|
|
|
|
KBUILD_LDFLAGS_MODULE := -T $(srctree)/scripts/module-common.lds
|
2010-07-07 11:12:45 +00:00
|
|
|
|
|
|
|
+# Warn about unsupported modules in kernels built inside Autobuild
|
|
|
|
+ifneq ($(wildcard /.buildenv),)
|
|
|
|
+CFLAGS += -DUNSUPPORTED_MODULES=2
|
|
|
|
+endif
|
|
|
|
+
|
|
|
|
# Read KERNELRELEASE from include/config/kernel.release (if it exists)
|
|
|
|
KERNELRELEASE = $(shell cat include/config/kernel.release 2> /dev/null)
|
|
|
|
KERNELVERSION = $(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
|
|
|
|
--- a/include/linux/kernel.h
|
|
|
|
+++ b/include/linux/kernel.h
|
2011-04-19 20:09:59 +00:00
|
|
|
@@ -222,8 +222,10 @@ extern int panic_timeout;
|
2010-07-07 11:12:45 +00:00
|
|
|
extern int panic_on_oops;
|
|
|
|
extern int panic_on_unrecovered_nmi;
|
|
|
|
extern int panic_on_io_nmi;
|
|
|
|
+extern int unsupported;
|
|
|
|
extern const char *print_tainted(void);
|
|
|
|
extern void add_taint(unsigned flag);
|
2011-04-19 20:09:59 +00:00
|
|
|
+extern void add_nonfatal_taint(unsigned flag);
|
2010-07-07 11:12:45 +00:00
|
|
|
extern int test_taint(unsigned flag);
|
2011-04-19 20:09:59 +00:00
|
|
|
extern unsigned long get_taint(void);
|
|
|
|
extern int root_mountflags;
|
|
|
|
@@ -251,6 +253,13 @@ extern enum system_states {
|
2010-07-07 11:12:45 +00:00
|
|
|
#define TAINT_CRAP 10
|
2011-04-19 20:09:59 +00:00
|
|
|
#define TAINT_FIRMWARE_WORKAROUND 11
|
2010-07-07 11:12:45 +00:00
|
|
|
|
|
|
|
+/*
|
|
|
|
+ * Take the upper bits to hopefully allow them
|
|
|
|
+ * to stay the same for more than one release.
|
|
|
|
+ */
|
|
|
|
+#define TAINT_NO_SUPPORT 30
|
|
|
|
+#define TAINT_EXTERNAL_SUPPORT 31
|
|
|
|
+
|
2011-04-19 20:09:59 +00:00
|
|
|
extern const char hex_asc[];
|
|
|
|
#define hex_asc_lo(x) hex_asc[((x) & 0x0f)]
|
|
|
|
#define hex_asc_hi(x) hex_asc[((x) & 0xf0) >> 4]
|
|
|
|
--- a/include/linux/module.h
|
|
|
|
+++ b/include/linux/module.h
|
|
|
|
@@ -410,6 +410,7 @@ struct module *__module_address(unsigned
|
|
|
|
bool is_module_address(unsigned long addr);
|
|
|
|
bool is_module_percpu_address(unsigned long addr);
|
|
|
|
bool is_module_text_address(unsigned long addr);
|
|
|
|
+const char *supported_printable(int taint);
|
|
|
|
|
|
|
|
static inline int within_module_core(unsigned long addr, struct module *mod)
|
|
|
|
{
|
|
|
|
--- a/kernel/ksysfs.c
|
|
|
|
+++ b/kernel/ksysfs.c
|
|
|
|
@@ -157,6 +157,28 @@ static struct bin_attribute notes_attr =
|
|
|
|
struct kobject *kernel_kobj;
|
|
|
|
EXPORT_SYMBOL_GPL(kernel_kobj);
|
|
|
|
|
|
|
|
+const char *supported_printable(int taint)
|
|
|
|
+{
|
|
|
|
+ int mask = TAINT_PROPRIETARY_MODULE|TAINT_NO_SUPPORT;
|
|
|
|
+ if ((taint & mask) == mask)
|
|
|
|
+ return "No, Proprietary and Unsupported modules are loaded";
|
|
|
|
+ else if (taint & TAINT_PROPRIETARY_MODULE)
|
|
|
|
+ return "No, Proprietary modules are loaded";
|
|
|
|
+ else if (taint & TAINT_NO_SUPPORT)
|
|
|
|
+ return "No, Unsupported modules are loaded";
|
|
|
|
+ else if (taint & TAINT_EXTERNAL_SUPPORT)
|
|
|
|
+ return "Yes, External";
|
|
|
|
+ else
|
|
|
|
+ return "Yes";
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static ssize_t supported_show(struct kobject *kobj,
|
|
|
|
+ struct kobj_attribute *attr, char *buf)
|
|
|
|
+{
|
|
|
|
+ return sprintf(buf, "%s\n", supported_printable(get_taint()));
|
|
|
|
+}
|
|
|
|
+KERNEL_ATTR_RO(supported);
|
|
|
|
+
|
|
|
|
static struct attribute * kernel_attrs[] = {
|
|
|
|
#if defined(CONFIG_HOTPLUG)
|
|
|
|
&uevent_seqnum_attr.attr,
|
|
|
|
@@ -171,6 +193,7 @@ static struct attribute * kernel_attrs[]
|
|
|
|
&kexec_crash_size_attr.attr,
|
|
|
|
&vmcoreinfo_attr.attr,
|
|
|
|
#endif
|
|
|
|
+ &supported_attr.attr,
|
|
|
|
NULL
|
|
|
|
};
|
2010-07-07 11:12:45 +00:00
|
|
|
|
|
|
|
--- a/kernel/module.c
|
|
|
|
+++ b/kernel/module.c
|
2011-04-19 20:09:59 +00:00
|
|
|
@@ -73,6 +73,20 @@
|
2010-07-07 11:12:45 +00:00
|
|
|
/* If this is set, the section belongs in the init part of the module */
|
|
|
|
#define INIT_OFFSET_MASK (1UL << (BITS_PER_LONG-1))
|
|
|
|
|
|
|
|
+/* Allow unsupported modules switch. */
|
|
|
|
+#ifdef UNSUPPORTED_MODULES
|
|
|
|
+int unsupported = UNSUPPORTED_MODULES;
|
|
|
|
+#else
|
|
|
|
+int unsupported = 2; /* don't warn when loading unsupported modules. */
|
|
|
|
+#endif
|
|
|
|
+
|
|
|
|
+static int __init unsupported_setup(char *str)
|
|
|
|
+{
|
|
|
|
+ get_option(&str, &unsupported);
|
|
|
|
+ return 1;
|
|
|
|
+}
|
|
|
|
+__setup("unsupported=", unsupported_setup);
|
|
|
|
+
|
2011-04-19 20:09:59 +00:00
|
|
|
/*
|
|
|
|
* Mutex protects:
|
|
|
|
* 1) List of modules (also safely readable with preempt_disable),
|
|
|
|
@@ -931,10 +945,36 @@ static struct module_attribute initstate
|
|
|
|
.show = show_initstate,
|
|
|
|
};
|
2010-07-07 11:12:45 +00:00
|
|
|
|
2011-04-19 20:09:59 +00:00
|
|
|
+static void setup_modinfo_supported(struct module *mod, const char *s)
|
|
|
|
+{
|
|
|
|
+ if (!s) {
|
|
|
|
+ mod->taints |= (1 << TAINT_NO_SUPPORT);
|
|
|
|
+ return;
|
2010-07-07 11:12:45 +00:00
|
|
|
+ }
|
2011-04-19 20:09:59 +00:00
|
|
|
+
|
|
|
|
+ if (strcmp(s, "external") == 0)
|
|
|
|
+ mod->taints |= (1 << TAINT_EXTERNAL_SUPPORT);
|
|
|
|
+ else if (strcmp(s, "yes"))
|
|
|
|
+ mod->taints |= (1 << TAINT_NO_SUPPORT);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static ssize_t show_modinfo_supported(struct module_attribute *mattr,
|
|
|
|
+ struct module *mod, char *buffer)
|
|
|
|
+{
|
|
|
|
+ return sprintf(buffer, "%s\n", supported_printable(mod->taints));
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static struct module_attribute modinfo_supported = {
|
|
|
|
+ .attr = { .name = "supported", .mode = 0444 },
|
|
|
|
+ .show = show_modinfo_supported,
|
|
|
|
+ .setup = setup_modinfo_supported,
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
static struct module_attribute *modinfo_attrs[] = {
|
|
|
|
&modinfo_version,
|
|
|
|
&modinfo_srcversion,
|
|
|
|
&initstate,
|
|
|
|
+ &modinfo_supported,
|
|
|
|
#ifdef CONFIG_MODULE_UNLOAD
|
|
|
|
&refcnt,
|
|
|
|
#endif
|
|
|
|
@@ -1476,6 +1516,26 @@ static int mod_sysfs_setup(struct module
|
|
|
|
add_sect_attrs(mod, info);
|
|
|
|
add_notes_attrs(mod, info);
|
|
|
|
|
|
|
|
+ /* We don't use add_taint() here because it also disables lockdep. */
|
|
|
|
+ if (mod->taints & (1 << TAINT_EXTERNAL_SUPPORT))
|
|
|
|
+ add_nonfatal_taint(TAINT_EXTERNAL_SUPPORT);
|
|
|
|
+ else if (mod->taints == (1 << TAINT_NO_SUPPORT)) {
|
2010-07-07 11:12:45 +00:00
|
|
|
+ if (unsupported == 0) {
|
|
|
|
+ printk(KERN_WARNING "%s: module not supported by "
|
|
|
|
+ "Novell, refusing to load. To override, echo "
|
|
|
|
+ "1 > /proc/sys/kernel/unsupported\n", mod->name);
|
|
|
|
+ err = -ENOEXEC;
|
|
|
|
+ goto free_hdr;
|
|
|
|
+ }
|
2011-04-19 20:09:59 +00:00
|
|
|
+ add_nonfatal_taint(TAINT_NO_SUPPORT);
|
2010-07-07 11:12:45 +00:00
|
|
|
+ if (unsupported == 1) {
|
2011-04-19 20:09:59 +00:00
|
|
|
+ printk(KERN_WARNING "%s: module is not supported by "
|
|
|
|
+ "Novell. Novell Technical Services may decline "
|
|
|
|
+ "your support request if it involves a kernel "
|
|
|
|
+ "fault.\n", mod->name);
|
2010-07-07 11:12:45 +00:00
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
2011-04-19 20:09:59 +00:00
|
|
|
kobject_uevent(&mod->mkobj.kobj, KOBJ_ADD);
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
@@ -3005,6 +3065,10 @@ static char *module_flags(struct module
|
2010-07-07 11:12:45 +00:00
|
|
|
buf[bx++] = 'F';
|
|
|
|
if (mod->taints & (1 << TAINT_CRAP))
|
|
|
|
buf[bx++] = 'C';
|
|
|
|
+ if (mod->taints & (1 << TAINT_NO_SUPPORT))
|
|
|
|
+ buf[bx++] = 'N';
|
|
|
|
+ if (mod->taints & (1 << TAINT_EXTERNAL_SUPPORT))
|
|
|
|
+ buf[bx++] = 'X';
|
|
|
|
/*
|
|
|
|
* TAINT_FORCED_RMMOD: could be added.
|
|
|
|
* TAINT_UNSAFE_SMP, TAINT_MACHINE_CHECK, TAINT_BAD_PAGE don't
|
2011-04-19 20:09:59 +00:00
|
|
|
@@ -3217,6 +3281,7 @@ void print_modules(void)
|
|
|
|
if (last_unloaded_module[0])
|
|
|
|
printk(" [last unloaded: %s]", last_unloaded_module);
|
|
|
|
printk("\n");
|
|
|
|
+ printk("Supported: %s\n", supported_printable(get_taint()));
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef CONFIG_MODVERSIONS
|
2010-07-07 11:12:45 +00:00
|
|
|
--- a/kernel/panic.c
|
|
|
|
+++ b/kernel/panic.c
|
2011-04-19 20:09:59 +00:00
|
|
|
@@ -174,6 +174,8 @@ static const struct tnt tnts[] = {
|
2010-07-07 11:12:45 +00:00
|
|
|
{ TAINT_WARN, 'W', ' ' },
|
|
|
|
{ TAINT_CRAP, 'C', ' ' },
|
2011-04-19 20:09:59 +00:00
|
|
|
{ TAINT_FIRMWARE_WORKAROUND, 'I', ' ' },
|
2010-07-07 11:12:45 +00:00
|
|
|
+ { TAINT_NO_SUPPORT, 'N', ' ' },
|
|
|
|
+ { TAINT_EXTERNAL_SUPPORT, 'X', ' ' },
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
2011-04-19 20:09:59 +00:00
|
|
|
@@ -191,6 +193,8 @@ static const struct tnt tnts[] = {
|
2010-07-07 11:12:45 +00:00
|
|
|
* 'W' - Taint on warning.
|
|
|
|
* 'C' - modules from drivers/staging are loaded.
|
2011-04-19 20:09:59 +00:00
|
|
|
* 'I' - Working around severe firmware bug.
|
2010-07-07 11:12:45 +00:00
|
|
|
+ * 'N' - Unsuported modules loaded.
|
|
|
|
+ * 'X' - Modules with external support loaded.
|
|
|
|
*
|
|
|
|
* The string is overwritten by the next call to print_tainted().
|
|
|
|
*/
|
2011-04-19 20:09:59 +00:00
|
|
|
@@ -226,6 +230,11 @@ unsigned long get_taint(void)
|
|
|
|
return tainted_mask;
|
|
|
|
}
|
|
|
|
|
|
|
|
+void add_nonfatal_taint(unsigned flag)
|
|
|
|
+{
|
|
|
|
+ set_bit(flag, &tainted_mask);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
void add_taint(unsigned flag)
|
|
|
|
{
|
|
|
|
/*
|
2010-07-07 11:12:45 +00:00
|
|
|
--- a/kernel/sysctl.c
|
|
|
|
+++ b/kernel/sysctl.c
|
2011-04-19 20:09:59 +00:00
|
|
|
@@ -664,6 +664,15 @@ static struct ctl_table kern_table[] = {
|
2010-07-07 11:12:45 +00:00
|
|
|
.extra1 = &pid_max_min,
|
|
|
|
.extra2 = &pid_max_max,
|
|
|
|
},
|
|
|
|
+#ifdef CONFIG_MODULES
|
|
|
|
+ {
|
|
|
|
+ .procname = "unsupported",
|
|
|
|
+ .data = &unsupported,
|
|
|
|
+ .maxlen = sizeof(int),
|
|
|
|
+ .mode = 0644,
|
|
|
|
+ .proc_handler = &proc_dointvec,
|
|
|
|
+ },
|
|
|
|
+#endif
|
|
|
|
{
|
|
|
|
.procname = "panic_on_oops",
|
|
|
|
.data = &panic_on_oops,
|
|
|
|
--- a/scripts/Makefile.modpost
|
|
|
|
+++ b/scripts/Makefile.modpost
|
|
|
|
@@ -81,7 +81,9 @@ modpost = scripts/mod/modpost
|
|
|
|
$(if $(KBUILD_EXTMOD),-o $(modulesymfile)) \
|
|
|
|
$(if $(CONFIG_DEBUG_SECTION_MISMATCH),,-S) \
|
|
|
|
$(if $(KBUILD_EXTMOD)$(KBUILD_MODPOST_WARN),-w) \
|
|
|
|
- $(if $(cross_build),-c)
|
|
|
|
+ $(if $(cross_build),-c) \
|
|
|
|
+ -N $(firstword $(wildcard $(dir $(MODVERDIR))/Module.supported \
|
|
|
|
+ $(objtree)/Module.supported /dev/null))
|
|
|
|
|
|
|
|
quiet_cmd_modpost = MODPOST $(words $(filter-out vmlinux FORCE, $^)) modules
|
|
|
|
cmd_modpost = $(modpost) -s
|
|
|
|
--- a/scripts/mod/modpost.c
|
|
|
|
+++ b/scripts/mod/modpost.c
|
2011-04-19 20:09:59 +00:00
|
|
|
@@ -1639,6 +1639,48 @@ static void check_sec_ref(struct module
|
2010-07-07 11:12:45 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
+void *supported_file;
|
|
|
|
+unsigned long supported_size;
|
|
|
|
+
|
|
|
|
+static const char *supported(struct module *mod)
|
|
|
|
+{
|
|
|
|
+ unsigned long pos = 0;
|
|
|
|
+ char *line;
|
|
|
|
+
|
|
|
|
+ /* In a first shot, do a simple linear scan. */
|
|
|
|
+ while ((line = get_next_line(&pos, supported_file,
|
|
|
|
+ supported_size))) {
|
|
|
|
+ const char *basename, *how = "yes";
|
|
|
|
+ char *l = line;
|
|
|
|
+
|
|
|
|
+ /* optional type-of-support flag */
|
|
|
|
+ for (l = line; *l != '\0'; l++) {
|
|
|
|
+ if (*l == ' ' || *l == '\t') {
|
|
|
|
+ *l = '\0';
|
|
|
|
+ how = l + 1;
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /* skip directory components */
|
|
|
|
+ if ((l = strrchr(line, '/')))
|
|
|
|
+ line = l + 1;
|
|
|
|
+ /* strip .ko extension */
|
|
|
|
+ l = line + strlen(line);
|
|
|
|
+ if (l - line > 3 && !strcmp(l-3, ".ko"))
|
|
|
|
+ *(l-3) = '\0';
|
|
|
|
+
|
|
|
|
+ /* skip directory components */
|
|
|
|
+ if ((basename = strrchr(mod->name, '/')))
|
|
|
|
+ basename++;
|
|
|
|
+ else
|
|
|
|
+ basename = mod->name;
|
|
|
|
+ if (!strcmp(basename, line))
|
|
|
|
+ return how;
|
|
|
|
+ }
|
|
|
|
+ return NULL;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
static void read_symbols(char *modname)
|
|
|
|
{
|
|
|
|
const char *symname;
|
2011-04-19 20:09:59 +00:00
|
|
|
@@ -1826,6 +1868,13 @@ static void add_staging_flag(struct buff
|
2010-07-07 11:12:45 +00:00
|
|
|
buf_printf(b, "\nMODULE_INFO(staging, \"Y\");\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
+static void add_supported_flag(struct buffer *b, struct module *mod)
|
|
|
|
+{
|
|
|
|
+ const char *how = supported(mod);
|
|
|
|
+ if (how)
|
|
|
|
+ buf_printf(b, "\nMODULE_INFO(supported, \"%s\");\n", how);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
/**
|
|
|
|
* Record CRCs for unresolved symbols
|
|
|
|
**/
|
2011-04-19 20:09:59 +00:00
|
|
|
@@ -1966,6 +2015,13 @@ static void write_if_changed(struct buff
|
2010-07-07 11:12:45 +00:00
|
|
|
fclose(file);
|
|
|
|
}
|
|
|
|
|
|
|
|
+static void read_supported(const char *fname)
|
|
|
|
+{
|
|
|
|
+ supported_file = grab_file(fname, &supported_size);
|
|
|
|
+ if (!supported_file)
|
|
|
|
+ ; /* ignore error */
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
/* parse Module.symvers file. line format:
|
|
|
|
* 0x12345678<tab>symbol<tab>module[[<tab>export]<tab>something]
|
|
|
|
**/
|
2011-04-19 20:09:59 +00:00
|
|
|
@@ -2059,12 +2115,13 @@ int main(int argc, char **argv)
|
2010-07-07 11:12:45 +00:00
|
|
|
struct buffer buf = { };
|
|
|
|
char *kernel_read = NULL, *module_read = NULL;
|
|
|
|
char *dump_write = NULL;
|
|
|
|
+ const char *supported = NULL;
|
|
|
|
int opt;
|
|
|
|
int err;
|
|
|
|
struct ext_sym_list *extsym_iter;
|
|
|
|
struct ext_sym_list *extsym_start = NULL;
|
|
|
|
|
|
|
|
- while ((opt = getopt(argc, argv, "i:I:e:cmsSo:awM:K:")) != -1) {
|
|
|
|
+ while ((opt = getopt(argc, argv, "i:I:e:cmsSo:awM:K:N:")) != -1) {
|
|
|
|
switch (opt) {
|
|
|
|
case 'i':
|
|
|
|
kernel_read = optarg;
|
2011-04-19 20:09:59 +00:00
|
|
|
@@ -2102,11 +2159,16 @@ int main(int argc, char **argv)
|
2010-07-07 11:12:45 +00:00
|
|
|
case 'w':
|
|
|
|
warn_unresolved = 1;
|
|
|
|
break;
|
|
|
|
+ case 'N':
|
|
|
|
+ supported = optarg;
|
|
|
|
+ break;
|
|
|
|
default:
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
+ if (supported)
|
|
|
|
+ read_supported(supported);
|
|
|
|
if (kernel_read)
|
|
|
|
read_dump(kernel_read, 1);
|
|
|
|
if (module_read)
|
2011-04-19 20:09:59 +00:00
|
|
|
@@ -2139,6 +2201,7 @@ int main(int argc, char **argv)
|
2010-07-07 11:12:45 +00:00
|
|
|
|
|
|
|
add_header(&buf, mod);
|
|
|
|
add_staging_flag(&buf, mod->name);
|
|
|
|
+ add_supported_flag(&buf, mod);
|
|
|
|
err |= add_versions(&buf, mod);
|
|
|
|
add_depends(&buf, mod, modules);
|
|
|
|
add_moddevtable(&buf, mod);
|