Right now the section is left in the kernel binary. The document is currently
not generated from the Makefile, so the curious user should perform:
$ objcopy -j __param_strings vmlinux -O binary foo
$ chmod a+x scripts/section2text.rb
$ cat foo | ./scripts/section2text.rb
And yeah, you need to install ruby to run the script.
The ruby script section2text.rb does some checks to see if MODULE_PARM_DESC()
is used without module_param(). You will find interesting typos.
Future work that extends this idea could include replacing __setup(name) with
__setup(name, descr). And storing the documentation somewhere to make it easy
for the end user to look up the generated parameter list from the boot loader.
/ magnus
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majo...@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
Signed-off-by: Magnus Damm <da...@opensource.se>
diff -urN linux-2.6.12-rc1/include/linux/init.h linux-2.6.12-rc1-autoparam/include/linux/init.h
--- linux-2.6.12-rc1/include/linux/init.h 2005-03-20 18:09:16.000000000 +0100
+++ linux-2.6.12-rc1-autoparam/include/linux/init.h 2005-03-20 22:24:14.393451896 +0100
@@ -125,7 +125,11 @@
__attribute_used__ \
__attribute__((__section__(".init.setup"))) \
__attribute__((aligned((sizeof(long))))) \
- = { __setup_str_##unique_id, fn, early }
+ = { __setup_str_##unique_id, fn, early }; \
+ static const char __setup_doc_##unique_id[] \
+ __attribute_used__ \
+ __attribute__((section("__param_strings"))) \
+ = str
#define __setup_null_param(str, unique_id) \
__setup_param(str, unique_id, NULL, 0)
diff -urN linux-2.6.12-rc1/include/linux/module.h linux-2.6.12-rc1-autoparam/include/linux/module.h
--- linux-2.6.12-rc1/include/linux/module.h 2005-03-20 18:20:18.000000000 +0100
+++ linux-2.6.12-rc1-autoparam/include/linux/module.h 2005-03-20 22:26:33.666279208 +0100
@@ -128,10 +128,18 @@
/* What your module does. */
#define MODULE_DESCRIPTION(_description) MODULE_INFO(description, _description)
+#ifdef MODULE
/* One for each parameter, describing how to use it. Some files do
multiple of these per line, so can't just use MODULE_INFO. */
#define MODULE_PARM_DESC(_parm, desc) \
__MODULE_INFO(parm, _parm, #_parm ":" desc)
+#else
+#define MODULE_PARM_DESC(_parm, desc) \
+ static const char __param_doc_desc_##_parm[] \
+ __attribute_used__ \
+ __attribute__((section("__param_strings"))) \
+ = __stringify(KBUILD_MODNAME) "." #_parm " () " desc
+#endif
#define MODULE_DEVICE_TABLE(type,name) \
MODULE_GENERIC_TABLE(type##_device,name)
diff -urN linux-2.6.12-rc1/include/linux/moduleparam.h linux-2.6.12-rc1-autoparam/include/linux/moduleparam.h
--- linux-2.6.12-rc1/include/linux/moduleparam.h 2005-03-20 18:20:18.000000000 +0100
+++ linux-2.6.12-rc1-autoparam/include/linux/moduleparam.h 2005-03-20 22:29:09.438598216 +0100
@@ -69,6 +69,12 @@
__attribute__ ((unused,__section__ ("__param"),aligned(sizeof(void *)))) \
= { __param_str_##name, perm, set, get, arg }
+#define module_param_doc(prefix, name, type) \
+ static const char __param_doc_##name[] \
+ __attribute_used__ \
+ __attribute__((section("__param_strings"))) \
+ = prefix #name " (" #type ")"
+
#define module_param_call(name, set, get, arg, perm) \
__module_param_call(MODULE_PARAM_PREFIX, name, set, get, arg, perm)
@@ -78,7 +84,8 @@
#define module_param_named(name, value, type, perm) \
param_check_##type(name, &(value)); \
module_param_call(name, param_set_##type, param_get_##type, &value, perm); \
- __MODULE_PARM_TYPE(name, #type)
+ __MODULE_PARM_TYPE(name, #type); \
+ module_param_doc(MODULE_PARAM_PREFIX, name, type)
#define module_param(name, type, perm) \
module_param_named(name, name, type, perm)
@@ -89,7 +96,8 @@
= { len, string }; \
module_param_call(name, param_set_copystring, param_get_string, \
&__param_string_##name, perm); \
- __MODULE_PARM_TYPE(name, "string")
+ __MODULE_PARM_TYPE(name, "string"); \
+ module_param_doc(MODULE_PARAM_PREFIX, name, type)
/* Called on module insert or kernel boot */
extern int parse_args(const char *name,
@@ -151,7 +159,8 @@
sizeof(array[0]), array }; \
module_param_call(name, param_array_set, param_array_get, \
&__param_arr_##name, perm); \
- __MODULE_PARM_TYPE(name, "array of " #type)
+ __MODULE_PARM_TYPE(name, "array of " #type); \
+ module_param_doc(MODULE_PARAM_PREFIX, name, type)
#define module_param_array(name, type, nump, perm) \
module_param_array_named(name, name, type, nump, perm)
Signed-off-by: Magnus Damm <da...@opensource.se>
diff -urN linux-2.6.12-rc1/net/unix/af_unix.c linux-2.6.12-rc1-autoparam/net/unix/af_unix.c
--- linux-2.6.12-rc1/net/unix/af_unix.c 2005-03-20 18:20:18.000000000 +0100
+++ linux-2.6.12-rc1-autoparam/net/unix/af_unix.c 2005-03-20 22:21:24.180328224 +0100
@@ -2080,6 +2080,8 @@
kmem_cache_destroy(unix_sk_cachep);
}
+#undef unix
+
module_init(af_unix_init);
module_exit(af_unix_exit);
Signed-off-by: Magnus Damm <da...@opensource.se>
diff -urN linux-2.6.12-rc1/drivers/ide/ide-disk.c linux-2.6.12-rc1-autoparam/drivers/ide/ide-disk.c
--- linux-2.6.12-rc1/drivers/ide/ide-disk.c 2005-03-20 18:20:16.000000000 +0100
+++ linux-2.6.12-rc1-autoparam/drivers/ide/ide-disk.c 2005-03-20 22:19:34.917938632 +0100
@@ -1179,6 +1179,8 @@
return ide_register_driver(&idedisk_driver);
}
+#undef ide_disk
+
module_init(idedisk_init);
module_exit(idedisk_exit);
MODULE_LICENSE("GPL");
diff -urN linux-2.6.12-rc1/drivers/ide/ide-floppy.c linux-2.6.12-rc1-autoparam/drivers/ide/ide-floppy.c
--- linux-2.6.12-rc1/drivers/ide/ide-floppy.c 2005-03-20 18:20:16.000000000 +0100
+++ linux-2.6.12-rc1-autoparam/drivers/ide/ide-floppy.c 2005-03-20 22:19:34.920938176 +0100
@@ -2117,6 +2117,8 @@
return 0;
}
+#undef ide_floppy
+
module_init(idefloppy_init);
module_exit(idefloppy_exit);
MODULE_LICENSE("GPL");
diff -urN linux-2.6.12-rc1/drivers/ide/ide-tape.c linux-2.6.12-rc1-autoparam/drivers/ide/ide-tape.c
--- linux-2.6.12-rc1/drivers/ide/ide-tape.c 2005-03-20 18:20:16.000000000 +0100
+++ linux-2.6.12-rc1-autoparam/drivers/ide/ide-tape.c 2005-03-20 22:19:34.944934528 +0100
@@ -4818,6 +4818,8 @@
return 0;
}
+#undef ide_tape
+
module_init(idetape_init);
module_exit(idetape_exit);
MODULE_ALIAS_CHARDEV_MAJOR(IDETAPE_MAJOR);
diff -urN linux-2.6.12-rc1/drivers/scsi/ide-scsi.c linux-2.6.12-rc1-autoparam/drivers/scsi/ide-scsi.c
--- linux-2.6.12-rc1/drivers/scsi/ide-scsi.c 2005-03-20 18:20:17.000000000 +0100
+++ linux-2.6.12-rc1-autoparam/drivers/scsi/ide-scsi.c 2005-03-20 22:19:34.946934224 +0100
@@ -1097,6 +1097,8 @@
ide_unregister_driver(&idescsi_driver);
}
+#undef ide_scsi
+
module_init(init_idescsi_module);
module_exit(exit_idescsi_module);
MODULE_LICENSE("GPL");
Signed-off-by: Magnus Damm <da...@opensource.se>
diff -urN linux-2.6.12-rc1/scripts/section2text.rb linux-2.6.12-rc1-autoparam/scripts/section2text.rb
--- linux-2.6.12-rc1/scripts/section2text.rb 1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.12-rc1-autoparam/scripts/section2text.rb 2005-03-20 22:53:10.847470760 +0100
@@ -0,0 +1,72 @@
+#!/usr/bin/env ruby
+
+param = {} # param[parametername] = [ type, description ]
+
+STDIN.read.split("\0").each do | x |
+ if x != ""
+ d = x.split
+ p = d.shift
+ t = d.shift
+
+ if d.length > 0
+ d = d.join(" ")
+ else
+ d = ""
+ end
+
+ if param[p]
+ if param[p][0] == "()"
+ param[p][0] = t
+ end
+ if param[p][1] == ""
+ param[p][1] = d
+ end
+ else
+ param[p] = [ t, d ]
+ end
+ end
+end
+
+bad = []
+
+param.keys.sort.each do | p |
+ t, d = param[p]
+
+ if t == "()"
+ bad << p
+ end
+end
+
+if bad != []
+ STDERR.puts "#{bad.length} error(s):"
+ bad.each do | p |
+ STDERR.puts "MODULE_PARM_DESC() on non-existing parameter \"#{p}\""
+ end
+ exit 1
+end
+
+param.keys.sort.each do | p |
+ t, d = param[p]
+
+ if not t
+ if p.index("=")
+ t = "(string)"
+ else
+ t = "(bool)"
+ end
+ end
+
+ if t == "()"
+ bad << p
+ else
+ puts "#{p} #{t}"
+ if d == ""
+ puts " Unknown"
+ else
+ puts " #{d}"
+ end
+ puts
+ end
+end
+
+exit 0
Signed-off-by: Magnus Damm <da...@opensource.se>
diff -urN linux-2.6.12-rc1/drivers/net/8139cp.c linux-2.6.12-rc1-autoparam/drivers/net/8139cp.c
--- linux-2.6.12-rc1/drivers/net/8139cp.c 2005-03-20 18:09:14.000000000 +0100
+++ linux-2.6.12-rc1-autoparam/drivers/net/8139cp.c 2005-03-20 22:47:41.504538496 +0100
@@ -94,13 +94,13 @@
MODULE_LICENSE("GPL");
static int debug = -1;
-MODULE_PARM (debug, "i");
+module_param (debug, int, 0);
MODULE_PARM_DESC (debug, "8139cp: bitmapped message enable number");
/* Maximum number of multicast addresses to filter (vs. Rx-all-multicast).
The RTL chips use a 64 element hash table based on the Ethernet CRC. */
static int multicast_filter_limit = 32;
-MODULE_PARM (multicast_filter_limit, "i");
+module_param (multicast_filter_limit, int, 0);
MODULE_PARM_DESC (multicast_filter_limit, "8139cp: maximum number of filtered multicast addresses");
#define PFX DRV_NAME ": "
diff -urN linux-2.6.12-rc1/drivers/net/eepro100.c linux-2.6.12-rc1-autoparam/drivers/net/eepro100.c
--- linux-2.6.12-rc1/drivers/net/eepro100.c 2005-03-20 18:20:16.000000000 +0100
+++ linux-2.6.12-rc1-autoparam/drivers/net/eepro100.c 2005-03-20 22:46:12.176118480 +0100
@@ -144,8 +144,8 @@
MODULE_PARM_DESC(congenb, "Enable congestion control (1)");
MODULE_PARM_DESC(txfifo, "Tx FIFO threshold in 4 byte units, (0-15)");
MODULE_PARM_DESC(rxfifo, "Rx FIFO threshold in 4 byte units, (0-15)");
-MODULE_PARM_DESC(txdmaccount, "Tx DMA burst length; 128 - disable (0-128)");
-MODULE_PARM_DESC(rxdmaccount, "Rx DMA burst length; 128 - disable (0-128)");
+MODULE_PARM_DESC(txdmacount, "Tx DMA burst length; 128 - disable (0-128)");
+MODULE_PARM_DESC(rxdmacount, "Rx DMA burst length; 128 - disable (0-128)");
MODULE_PARM_DESC(rx_copybreak, "copy breakpoint for copy-only-tiny-frames");
MODULE_PARM_DESC(max_interrupt_work, "maximum events handled per interrupt");
MODULE_PARM_DESC(multicast_filter_limit, "maximum number of filtered multicast addresses");
I think it's a great idea. A needed feature with simple implementation.
I like it.
>
> Right now the section is left in the kernel binary. The document is currently
> not generated from the Makefile, so the curious user should perform:
Any plans to make this a complete patch?
>
> $ objcopy -j __param_strings vmlinux -O binary foo
> $ chmod a+x scripts/section2text.rb
> $ cat foo | ./scripts/section2text.rb
>
> And yeah, you need to install ruby to run the script.
Attached a perl script, that has almost the same output. (I think
perl is more usual on linux machines)
>
> The ruby script section2text.rb does some checks to see if MODULE_PARM_DESC()
> is used without module_param(). You will find interesting typos.
>
> Future work that extends this idea could include replacing __setup(name) with
> __setup(name, descr). And storing the documentation somewhere to make it easy
> for the end user to look up the generated parameter list from the boot loader.
And kernel-parameters.txt will never again have obsoleted options :-)
Domen
Thanks! And together with the "disable built-in" patch we have a much
more user-friendly system...
> > Right now the section is left in the kernel binary. The document is currently
> > not generated from the Makefile, so the curious user should perform:
>
> Any plans to make this a complete patch?
Yes, if there is enough interest. I think autogenerating documents
from source code is the right way to do it, but I am not sure about
the disadvantages. Maybe someone could enlighten me? The latest patch
does not support obsolete MODULE_PARM() parameters - so I need to add
that to next release but that is no biggie.
> > $ objcopy -j __param_strings vmlinux -O binary foo
> > $ chmod a+x scripts/section2text.rb
> > $ cat foo | ./scripts/section2text.rb
> >
> > And yeah, you need to install ruby to run the script.
>
> Attached a perl script, that has almost the same output. (I think
> perl is more usual on linux machines)
Great, thanks! I prefer to do prototype hacking in ruby, but I realize
that "the magic duct tape language" is more suitable.. =)
Also, I am thinking of using a prefix with the parameter type to
determine the origin of the parameter, ie:
prefix "s:" means from __setup()
prefix "e:" means from early_param()
prefix "m:" means from module_param()
prefix "o:" means from obsolete MODULE_PARM()
Then I would like to let the script convert the types to a common set of types.
I thought about treating descriptions without parameters as errors,
and generate warnings about parameters without description. And to
reduce the amount of warnings I think it is a good idea to add a
SETUP_DESC() as suggested by Matt Domsch.
> > The ruby script section2text.rb does some checks to see if MODULE_PARM_DESC()
> > is used without module_param(). You will find interesting typos.
> >
> > Future work that extends this idea could include replacing __setup(name) with
> > __setup(name, descr). And storing the documentation somewhere to make it easy
> > for the end user to look up the generated parameter list from the boot loader.
>
> And kernel-parameters.txt will never again have obsoleted options :-)
Exactly! =)
/magnus