From: "Randy.Dunlap" The SuSE kernels place their ikconfig info at /proc/config.gz: in a different place, and compressed. We thought it was a good idea to do it that way in 2.6 as well. - gzip the /proc config file, put it in /proc/config.gz; - Based on a SuSE patch by Oliver Xymoron , which was derived from a patch by Nicholas Leon - change /proc/ikconfig/built_with to /proc/config_build_info; - cleanup ikconfig init/exit entry points (static, __init, __exit); - Makefile help from Sam Ravnborg; init/Kconfig | 12 +++---- kernel/Makefile | 25 ++++++++++++++- kernel/configs.c | 85 ++++++++++++++++++++++-------------------------------- scripts/Makefile | 2 - scripts/bin2c.c | 27 +++++++++++++++++ scripts/mkconfigs | 8 +---- 6 files changed, 95 insertions(+), 64 deletions(-) diff -puN init/Kconfig~ikconfig-gzipped init/Kconfig --- 25/init/Kconfig~ikconfig-gzipped 2003-09-01 12:10:48.000000000 -0700 +++ 25-akpm/init/Kconfig 2003-09-01 12:10:48.000000000 -0700 @@ -126,24 +126,24 @@ config IKCONFIG This option enables the complete Linux kernel ".config" file contents, information on compiler used to build the kernel, kernel running when this kernel was built and kernel version - from Makefile to be saved in kernel. It provides documentation + from Makefile to be saved in the kernel. It provides documentation of which kernel options are used in a running kernel or in an on-disk kernel. This information can be extracted from the kernel image file with the script scripts/extract-ikconfig and used as input to rebuild the current kernel or to build another kernel. It can also be extracted from a running kernel by reading - /proc/ikconfig/config and /proc/ikconfig/built_with, if enabled. - /proc/ikconfig/config will list the configuration that was used - to build the kernel and /proc/ikconfig/built_with will list + /proc/config.gz and /proc/config_built_with, if enabled (below). + /proc/config.gz will list the configuration that was used + to build the kernel and /proc/config_built_with will list information on the compiler and host machine that was used to build the kernel. config IKCONFIG_PROC - bool "Enable access to .config through /proc/ikconfig" + bool "Enable access to .config through /proc/config.gz" depends on IKCONFIG && PROC_FS ---help--- This option enables access to kernel configuration file and build - information through /proc/ikconfig. + information through /proc/config.gz. menuconfig EMBEDDED diff -puN kernel/configs.c~ikconfig-gzipped kernel/configs.c --- 25/kernel/configs.c~ikconfig-gzipped 2003-09-01 12:10:48.000000000 -0700 +++ 25-akpm/kernel/configs.c 2003-09-01 12:10:48.000000000 -0700 @@ -23,6 +23,7 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +#include #include #include #include @@ -34,18 +35,20 @@ /**************************************************/ /* the actual current config file */ +/* This one is for extraction from the kernel binary file image. */ #include "ikconfig.h" #ifdef CONFIG_IKCONFIG_PROC +/* This is the data that can be read from /proc/config.gz. */ +#include "config_data.h" + /**************************************************/ /* globals and useful constants */ -static char *IKCONFIG_NAME = "ikconfig"; -static char *IKCONFIG_VERSION = "0.5"; +static char *IKCONFIG_VERSION = "0.6"; -static int ikconfig_current_size = 0; -static struct proc_dir_entry *ikconfig_dir, *current_config, *built_with; +static struct proc_dir_entry *current_config, *build_info; static int ikconfig_permission_current(struct inode *inode, int op, struct nameidata *nd) @@ -55,16 +58,16 @@ ikconfig_permission_current(struct inode } static ssize_t -ikconfig_output_current(struct file *file, char *buf, +ikconfig_read_current(struct file *file, char *buf, size_t len, loff_t * offset) { int i, limit; int cnt; - limit = (ikconfig_current_size > len) ? len : ikconfig_current_size; + limit = (kernel_config_data_size > len) ? len : kernel_config_data_size; for (i = file->f_pos, cnt = 0; - i < ikconfig_current_size && cnt < limit; i++, cnt++) { - if (put_user(ikconfig_config[i], buf + cnt)) + i < kernel_config_data_size && cnt < limit; i++, cnt++) { + if (put_user(kernel_config_data[i], buf + cnt)) return -EFAULT; } file->f_pos = i; @@ -75,7 +78,7 @@ static int ikconfig_open_current(struct inode *inode, struct file *file) { if (file->f_mode & FMODE_READ) { - inode->i_size = ikconfig_current_size; + inode->i_size = kernel_config_data_size; file->f_pos = 0; } return 0; @@ -88,7 +91,7 @@ ikconfig_close_current(struct inode *ino } static struct file_operations ikconfig_file_ops = { - .read = ikconfig_output_current, + .read = ikconfig_read_current, .open = ikconfig_open_current, .release = ikconfig_close_current, }; @@ -98,89 +101,71 @@ static struct inode_operations ikconfig_ }; /***************************************************/ -/* proc_read_built_with: let people read the info */ +/* proc_read_build_info: let people read the info */ /* we have on the tools used to build this kernel */ static int -proc_read_built_with(char *page, char **start, +proc_read_build_info(char *page, char **start, off_t off, int count, int *eof, void *data) { *eof = 1; return sprintf(page, "Kernel: %s\nCompiler: %s\nVersion_in_Makefile: %s\n", - ikconfig_built_with, LINUX_COMPILER, UTS_RELEASE); + ikconfig_build_info, LINUX_COMPILER, UTS_RELEASE); } /***************************************************/ /* ikconfig_init: start up everything we need to */ -int __init -ikconfig_init(void) +static int __init ikconfig_init(void) { int result = 0; - printk(KERN_INFO "ikconfig %s with /proc/ikconfig\n", + printk(KERN_INFO "ikconfig %s with /proc/config*\n", IKCONFIG_VERSION); - /* create the ikconfig directory */ - ikconfig_dir = proc_mkdir(IKCONFIG_NAME, NULL); - if (ikconfig_dir == NULL) { - result = -ENOMEM; - goto leave; - } - ikconfig_dir->owner = THIS_MODULE; - /* create the current config file */ - current_config = create_proc_entry("config", S_IFREG | S_IRUGO, - ikconfig_dir); + current_config = create_proc_entry("config.gz", S_IFREG | S_IRUGO, + &proc_root); if (current_config == NULL) { result = -ENOMEM; - goto leave2; + goto leave; } current_config->proc_iops = &ikconfig_inode_ops; current_config->proc_fops = &ikconfig_file_ops; current_config->owner = THIS_MODULE; - ikconfig_current_size = strlen(ikconfig_config); - current_config->size = ikconfig_current_size; + current_config->size = kernel_config_data_size; - /* create the "built with" file */ - built_with = create_proc_read_entry("built_with", 0444, ikconfig_dir, - proc_read_built_with, NULL); - if (built_with == NULL) { + /* create the "build_info" file */ + build_info = create_proc_read_entry("config_build_info", 0444, &proc_root, + proc_read_build_info, NULL); + if (build_info == NULL) { result = -ENOMEM; - goto leave3; + goto leave_gz; } - built_with->owner = THIS_MODULE; + build_info->owner = THIS_MODULE; goto leave; -leave3: +leave_gz: /* remove the file from proc */ - remove_proc_entry("config", ikconfig_dir); - -leave2: - /* remove the ikconfig directory */ - remove_proc_entry(IKCONFIG_NAME, NULL); + remove_proc_entry("config.gz", &proc_root); leave: return result; } /***************************************************/ -/* cleanup_ikconfig: clean up our mess */ +/* ikconfig_cleanup: clean up our mess */ -static void -cleanup_ikconfig(void) +static void __exit ikconfig_cleanup(void) { /* remove the files */ - remove_proc_entry("config", ikconfig_dir); - remove_proc_entry("built_with", ikconfig_dir); - - /* remove the ikconfig directory */ - remove_proc_entry(IKCONFIG_NAME, NULL); + remove_proc_entry("config.gz", &proc_root); + remove_proc_entry("config_build_info", &proc_root); } module_init(ikconfig_init); -module_exit(cleanup_ikconfig); +module_exit(ikconfig_cleanup); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Randy Dunlap"); diff -puN kernel/Makefile~ikconfig-gzipped kernel/Makefile --- 25/kernel/Makefile~ikconfig-gzipped 2003-09-01 12:10:48.000000000 -0700 +++ 25-akpm/kernel/Makefile 2003-09-01 12:10:48.000000000 -0700 @@ -19,6 +19,7 @@ obj-$(CONFIG_CPU_FREQ) += cpufreq.o obj-$(CONFIG_BSD_PROCESS_ACCT) += acct.o obj-$(CONFIG_COMPAT) += compat.o obj-$(CONFIG_IKCONFIG) += configs.o +obj-$(CONFIG_IKCONFIG_PROC) += configs.o ifneq ($(CONFIG_IA64),y) # According to Alan Modra , the -fno-omit-frame-pointer is @@ -29,12 +30,32 @@ ifneq ($(CONFIG_IA64),y) CFLAGS_sched.o := $(PROFILING) -fno-omit-frame-pointer endif +# configs.o uses generated files - dependecies must be listed explicitly +$(obj)/configs.o: $(obj)/ikconfig.h + +ifdef CONFIG_IKCONFIG_PROC +$(obj)/configs.o: $(obj)/config_data.h +endif + +# ikconfig.h contains all the selected config entries - generated +# from top-level Makefile and .config. Info from ikconfig.h can +# be extracted from the kernel binary. + quiet_cmd_ikconfig = IKCFG $@ cmd_ikconfig = $(CONFIG_SHELL) $< .config $(srctree)/Makefile > $@ targets += ikconfig.h - $(obj)/ikconfig.h: scripts/mkconfigs .config Makefile FORCE $(call if_changed,ikconfig) -$(obj)/configs.o: $(obj)/ikconfig.h +# config_data.h contains the same information as ikconfig.h but gzipped. +# Info from config_data can be extracted from /proc/config* +targets += config_data.gz +$(obj)/config_data.gz: .config FORCE + $(call if_changed,gzip) + +quiet_cmd_ikconfiggz = IKCFG $@ + cmd_ikconfiggz = cat $< | scripts/bin2c kernel_config_data > $@ +targets += config_data.h +$(obj)/config_data.h: $(obj)/config_data.gz FORCE + $(call if_changed,ikconfiggz) diff -puN /dev/null scripts/bin2c.c --- /dev/null 2002-08-30 16:31:37.000000000 -0700 +++ 25-akpm/scripts/bin2c.c 2003-09-01 12:10:48.000000000 -0700 @@ -0,0 +1,27 @@ +#include + +int main(int argc, char *argv[]) +{ + int ch, total=0; + + if (argc > 1) + printf("const char *%s %s=\n", + argv[1], argc > 2 ? argv[2] : ""); + + do { + printf("\t\""); + while ((ch = getchar()) != EOF) + { + total++; + printf("\\x%02x",ch); + if (total % 16 == 0) + break; + } + printf("\"\n"); + } while (ch != EOF); + + if (argc > 1) + printf("\t;\n\nconst int %s_size = %d;\n", argv[1], total); + + return 0; +} diff -puN scripts/Makefile~ikconfig-gzipped scripts/Makefile --- 25/scripts/Makefile~ikconfig-gzipped 2003-09-01 12:10:48.000000000 -0700 +++ 25-akpm/scripts/Makefile 2003-09-01 12:10:48.000000000 -0700 @@ -9,7 +9,7 @@ # conmakehash: Create arrays for initializing the kernel console tables host-progs := fixdep split-include conmakehash docproc kallsyms modpost \ - mk_elfconfig pnmtologo + mk_elfconfig pnmtologo bin2c always := $(host-progs) empty.o modpost-objs := modpost.o file2alias.o diff -puN scripts/mkconfigs~ikconfig-gzipped scripts/mkconfigs --- 25/scripts/mkconfigs~ikconfig-gzipped 2003-09-01 12:10:48.000000000 -0700 +++ 25-akpm/scripts/mkconfigs 2003-09-01 12:10:48.000000000 -0700 @@ -66,15 +66,13 @@ echo \ * */" -echo "static char *ikconfig_built_with =" +echo "#ifdef CONFIG_IKCONFIG_PROC" +echo "static char *ikconfig_build_info =" echo " \"`uname -s` `uname -r` `uname -v` `uname -m`\";" +echo "#endif" echo kernel_version $makefile -echo "#ifdef CONFIG_IKCONFIG_PROC" -echo "static char *ikconfig_config = " -echo "#else" echo "static char *ikconfig_config __initdata __attribute__((unused)) = " -echo "#endif" echo "\"CONFIG_BEGIN=n\\n\\" echo "`cat $config | sed 's/\"/\\\\\"/g' | grep "^#\? \?CONFIG_" | awk '{ print $0 "\\\\n\\\\" }' `" echo "CONFIG_END=n\\n\";" _