[PATCH 0/5] autoparam

1 view
Skip to first unread message

Magnus Damm

unread,
Mar 20, 2005, 6:11:07 PM3/20/05
to linux-...@vger.kernel.org, Magnus Damm
Here are a set of patches that makes it possible to autogenerate kernel command
line documentation from the source code. The approach is rather straightforward
- the parameter name, the type and the description are stored in a section
called __param_strings. After vmlinux is built this section is extracted using
objcopy and a script is used to generate a primitive - but up to date -
document.

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/

Magnus Damm

unread,
Mar 20, 2005, 6:11:08 PM3/20/05
to linux-...@vger.kernel.org, Magnus Damm
The code of autoparam - modified include files. Stores parameter name, type
and description in a section called __param_strings.

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)

Magnus Damm

unread,
Mar 20, 2005, 6:15:20 PM3/20/05
to linux-...@vger.kernel.org, Magnus Damm
This is a quick fix that removes the "KBUILD_MODNAME -> unix -> 1" conflict.

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);

Magnus Damm

unread,
Mar 20, 2005, 6:15:19 PM3/20/05
to linux-...@vger.kernel.org, Magnus Damm
This patch contains quick fixes that prevents KBUILD_MODNAME conflicts.

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");

Magnus Damm

unread,
Mar 20, 2005, 6:19:21 PM3/20/05
to linux-...@vger.kernel.org, Magnus Damm
The quick ruby hack that generates text from the section data. The script
should probably be rewritten in some other languare to minimize dependencies.
Parameters without types are the result of MODULE_PARM_DESC typos or the use of
MODULE_PARM() instead of module_param() and are treated as errors.

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

Magnus Damm

unread,
Mar 20, 2005, 6:19:21 PM3/20/05
to linux-...@vger.kernel.org, Magnus Damm
Some module parameter fixes, errors reported by section2text.rb.

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");

Domen Puncer

unread,
Apr 10, 2005, 8:40:21 PM4/10/05
to Magnus Damm, linux-...@vger.kernel.org
On 21/03/05 00:06 +0100, Magnus Damm wrote:
> Here are a set of patches that makes it possible to autogenerate kernel command
> line documentation from the source code. The approach is rather straightforward
> - the parameter name, the type and the description are stored in a section
> called __param_strings. After vmlinux is built this section is extracted using
> objcopy and a script is used to generate a primitive - but up to date -
> document.

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

section2text.pl

Mister Exim

unread,
Apr 11, 2005, 6:18:43 AM4/11/05
to Magnus Damm, linux-...@vger.kernel.org
On 4/9/05, Domen Puncer <do...@coderock.org> wrote:
> On 21/03/05 00:06 +0100, Magnus Damm wrote:
> > Here are a set of patches that makes it possible to autogenerate kernel command
> > line documentation from the source code. The approach is rather straightforward
> > - the parameter name, the type and the description are stored in a section
> > called __param_strings. After vmlinux is built this section is extracted using
> > objcopy and a script is used to generate a primitive - but up to date -
> > document.
>
> I think it's a great idea. A needed feature with simple implementation.
> I like it.

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

Reply all
Reply to author
Forward
0 new messages