From b75dcabd6c6c71d7cea64f78b06d18d9cda0ddd1 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Fri, 29 Jan 2010 11:40:38 +0100 Subject: modpost: members of *driver structs should not point to __init functions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Either the functions referred to in a driver struct should live in .devinit or the driver should be registered using platform_driver_probe (or equivalent for different driver types) with ->probe being NULL. Signed-off-by: Uwe Kleine-König --- scripts/mod/modpost.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c index 20923613467..713b62eed87 100644 --- a/scripts/mod/modpost.c +++ b/scripts/mod/modpost.c @@ -961,7 +961,7 @@ static int section_mismatch(const char *fromsec, const char *tosec) * Pattern 2: * Many drivers utilise a *driver container with references to * add, remove, probe functions etc. - * These functions may often be marked __init and we do not want to + * These functions may often be marked __devinit and we do not want to * warn here. * the pattern is identified by: * tosec = init or exit section -- cgit v1.2.3-18-g5258 From 4a31a229fb6cbbeabf5ca9a0dcb55d53ca052048 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Fri, 29 Jan 2010 12:04:26 +0100 Subject: modpost: define ALL_XXX{IN,EX}IT_SECTIONS MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Uwe Kleine-König --- scripts/mod/modpost.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c index 713b62eed87..dbab53a2e22 100644 --- a/scripts/mod/modpost.c +++ b/scripts/mod/modpost.c @@ -781,10 +781,13 @@ static void check_section(const char *modname, struct elf_info *elf, #define ALL_EXIT_TEXT_SECTIONS \ ".exit.text$", ".devexit.text$", ".cpuexit.text$", ".memexit.text$" -#define ALL_INIT_SECTIONS INIT_SECTIONS, DEV_INIT_SECTIONS, \ - CPU_INIT_SECTIONS, MEM_INIT_SECTIONS -#define ALL_EXIT_SECTIONS EXIT_SECTIONS, DEV_EXIT_SECTIONS, \ - CPU_EXIT_SECTIONS, MEM_EXIT_SECTIONS +#define ALL_XXXINIT_SECTIONS DEV_INIT_SECTIONS, CPU_INIT_SECTIONS, \ + MEM_INIT_SECTIONS +#define ALL_XXXEXIT_SECTIONS DEV_EXIT_SECTIONS, CPU_EXIT_SECTIONS, \ + MEM_EXIT_SECTIONS + +#define ALL_INIT_SECTIONS INIT_SECTIONS, ALL_XXXINIT_SECTIONS +#define ALL_EXIT_SECTIONS EXIT_SECTIONS, ALL_XXXEXIT_SECTIONS #define DATA_SECTIONS ".data$", ".data.rel$" #define TEXT_SECTIONS ".text$" @@ -876,7 +879,7 @@ const struct sectioncheck sectioncheck[] = { }, /* Do not reference init code/data from devinit/cpuinit/meminit code/data */ { - .fromsec = { DEV_INIT_SECTIONS, CPU_INIT_SECTIONS, MEM_INIT_SECTIONS, NULL }, + .fromsec = { ALL_XXXINIT_SECTIONS, NULL }, .tosec = { INIT_SECTIONS, NULL }, .mismatch = XXXINIT_TO_INIT, }, @@ -894,7 +897,7 @@ const struct sectioncheck sectioncheck[] = { }, /* Do not reference exit code/data from devexit/cpuexit/memexit code/data */ { - .fromsec = { DEV_EXIT_SECTIONS, CPU_EXIT_SECTIONS, MEM_EXIT_SECTIONS, NULL }, + .fromsec = { ALL_XXXEXIT_SECTIONS, NULL }, .tosec = { EXIT_SECTIONS, NULL }, .mismatch = XXXEXIT_TO_EXIT, }, -- cgit v1.2.3-18-g5258 From bbd3f4fb84f8c4a04f22c9c6dc119b0c4856c7d9 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Sat, 30 Jan 2010 16:35:47 +0100 Subject: modpost: give most mismatch constants a better name MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Uwe Kleine-König --- scripts/mod/modpost.c | 56 +++++++++++++++++++++++++-------------------------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c index dbab53a2e22..598d54a0fef 100644 --- a/scripts/mod/modpost.c +++ b/scripts/mod/modpost.c @@ -836,14 +836,14 @@ static const char *linker_symbols[] = enum mismatch { NO_MISMATCH, - TEXT_TO_INIT, - DATA_TO_INIT, - TEXT_TO_EXIT, - DATA_TO_EXIT, - XXXINIT_TO_INIT, - XXXEXIT_TO_EXIT, - INIT_TO_EXIT, - EXIT_TO_INIT, + TEXT_TO_ANY_INIT, + DATA_TO_ANY_INIT, + TEXT_TO_ANY_EXIT, + DATA_TO_ANY_EXIT, + XXXINIT_TO_SOME_INIT, + XXXEXIT_TO_SOME_EXIT, + ANY_INIT_TO_ANY_EXIT, + ANY_EXIT_TO_ANY_INIT, EXPORT_TO_INIT_EXIT, }; @@ -860,70 +860,70 @@ const struct sectioncheck sectioncheck[] = { { .fromsec = { TEXT_SECTIONS, NULL }, .tosec = { ALL_INIT_SECTIONS, NULL }, - .mismatch = TEXT_TO_INIT, + .mismatch = TEXT_TO_ANY_INIT, }, { .fromsec = { DATA_SECTIONS, NULL }, .tosec = { ALL_INIT_SECTIONS, NULL }, - .mismatch = DATA_TO_INIT, + .mismatch = DATA_TO_ANY_INIT, }, { .fromsec = { TEXT_SECTIONS, NULL }, .tosec = { ALL_EXIT_SECTIONS, NULL }, - .mismatch = TEXT_TO_EXIT, + .mismatch = TEXT_TO_ANY_EXIT, }, { .fromsec = { DATA_SECTIONS, NULL }, .tosec = { ALL_EXIT_SECTIONS, NULL }, - .mismatch = DATA_TO_EXIT, + .mismatch = DATA_TO_ANY_EXIT, }, /* Do not reference init code/data from devinit/cpuinit/meminit code/data */ { .fromsec = { ALL_XXXINIT_SECTIONS, NULL }, .tosec = { INIT_SECTIONS, NULL }, - .mismatch = XXXINIT_TO_INIT, + .mismatch = XXXINIT_TO_SOME_INIT, }, /* Do not reference cpuinit code/data from meminit code/data */ { .fromsec = { MEM_INIT_SECTIONS, NULL }, .tosec = { CPU_INIT_SECTIONS, NULL }, - .mismatch = XXXINIT_TO_INIT, + .mismatch = XXXINIT_TO_SOME_INIT, }, /* Do not reference meminit code/data from cpuinit code/data */ { .fromsec = { CPU_INIT_SECTIONS, NULL }, .tosec = { MEM_INIT_SECTIONS, NULL }, - .mismatch = XXXINIT_TO_INIT, + .mismatch = XXXINIT_TO_SOME_INIT, }, /* Do not reference exit code/data from devexit/cpuexit/memexit code/data */ { .fromsec = { ALL_XXXEXIT_SECTIONS, NULL }, .tosec = { EXIT_SECTIONS, NULL }, - .mismatch = XXXEXIT_TO_EXIT, + .mismatch = XXXEXIT_TO_SOME_EXIT, }, /* Do not reference cpuexit code/data from memexit code/data */ { .fromsec = { MEM_EXIT_SECTIONS, NULL }, .tosec = { CPU_EXIT_SECTIONS, NULL }, - .mismatch = XXXEXIT_TO_EXIT, + .mismatch = XXXEXIT_TO_SOME_EXIT, }, /* Do not reference memexit code/data from cpuexit code/data */ { .fromsec = { CPU_EXIT_SECTIONS, NULL }, .tosec = { MEM_EXIT_SECTIONS, NULL }, - .mismatch = XXXEXIT_TO_EXIT, + .mismatch = XXXEXIT_TO_SOME_EXIT, }, /* Do not use exit code/data from init code */ { .fromsec = { ALL_INIT_SECTIONS, NULL }, .tosec = { ALL_EXIT_SECTIONS, NULL }, - .mismatch = INIT_TO_EXIT, + .mismatch = ANY_INIT_TO_ANY_EXIT, }, /* Do not use init code/data from exit code */ { .fromsec = { ALL_EXIT_SECTIONS, NULL }, .tosec = { ALL_INIT_SECTIONS, NULL }, - .mismatch = EXIT_TO_INIT, + .mismatch = ANY_EXIT_TO_ANY_INIT, }, /* Do not export init/exit functions or data */ { @@ -1190,7 +1190,7 @@ static void report_sec_mismatch(const char *modname, enum mismatch mismatch, tosym, to_p); switch (mismatch) { - case TEXT_TO_INIT: + case TEXT_TO_ANY_INIT: fprintf(stderr, "The function %s%s() references\n" "the %s %s%s%s.\n" @@ -1200,7 +1200,7 @@ static void report_sec_mismatch(const char *modname, enum mismatch mismatch, to, sec2annotation(tosec), tosym, to_p, fromsym, sec2annotation(tosec), tosym); break; - case DATA_TO_INIT: { + case DATA_TO_ANY_INIT: { const char **s = symbol_white_list; fprintf(stderr, "The variable %s references\n" @@ -1214,14 +1214,14 @@ static void report_sec_mismatch(const char *modname, enum mismatch mismatch, fprintf(stderr, "\n"); break; } - case TEXT_TO_EXIT: + case TEXT_TO_ANY_EXIT: fprintf(stderr, "The function %s() references a %s in an exit section.\n" "Often the %s %s%s has valid usage outside the exit section\n" "and the fix is to remove the %sannotation of %s.\n", fromsym, to, to, tosym, to_p, sec2annotation(tosec), tosym); break; - case DATA_TO_EXIT: { + case DATA_TO_ANY_EXIT: { const char **s = symbol_white_list; fprintf(stderr, "The variable %s references\n" @@ -1235,8 +1235,8 @@ static void report_sec_mismatch(const char *modname, enum mismatch mismatch, fprintf(stderr, "\n"); break; } - case XXXINIT_TO_INIT: - case XXXEXIT_TO_EXIT: + case XXXINIT_TO_SOME_INIT: + case XXXEXIT_TO_SOME_EXIT: fprintf(stderr, "The %s %s%s%s references\n" "a %s %s%s%s.\n" @@ -1246,7 +1246,7 @@ static void report_sec_mismatch(const char *modname, enum mismatch mismatch, to, sec2annotation(tosec), tosym, to_p, tosym, fromsym, tosym); break; - case INIT_TO_EXIT: + case ANY_INIT_TO_ANY_EXIT: fprintf(stderr, "The %s %s%s%s references\n" "a %s %s%s%s.\n" @@ -1259,7 +1259,7 @@ static void report_sec_mismatch(const char *modname, enum mismatch mismatch, to, sec2annotation(tosec), tosym, to_p, sec2annotation(tosec), tosym, to_p); break; - case EXIT_TO_INIT: + case ANY_EXIT_TO_ANY_INIT: fprintf(stderr, "The %s %s%s%s references\n" "a %s %s%s%s.\n" -- cgit v1.2.3-18-g5258 From 0d2a636ee6c3b8c292fbaae05976fe1537b70958 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Sat, 30 Jan 2010 16:56:20 +0100 Subject: modpost: pass around const struct sectioncheck * instead of enum mismatch MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This prepares having a per-check whitelist of symbol names. Signed-off-by: Uwe Kleine-König --- scripts/mod/modpost.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c index 598d54a0fef..3f0380b8d8f 100644 --- a/scripts/mod/modpost.c +++ b/scripts/mod/modpost.c @@ -933,7 +933,8 @@ const struct sectioncheck sectioncheck[] = { } }; -static int section_mismatch(const char *fromsec, const char *tosec) +static const struct sectioncheck *section_mismatch( + const char *fromsec, const char *tosec) { int i; int elems = sizeof(sectioncheck) / sizeof(struct sectioncheck); @@ -942,10 +943,10 @@ static int section_mismatch(const char *fromsec, const char *tosec) for (i = 0; i < elems; i++) { if (match(fromsec, check->fromsec) && match(tosec, check->tosec)) - return check->mismatch; + return check; check++; } - return NO_MISMATCH; + return NULL; } /** @@ -1158,7 +1159,8 @@ static int is_function(Elf_Sym *sym) * Try to find symbols near it so user can find it. * Check whitelist before warning - it may be a false positive. */ -static void report_sec_mismatch(const char *modname, enum mismatch mismatch, +static void report_sec_mismatch(const char *modname, + const struct sectioncheck *mismatch, const char *fromsec, unsigned long long fromaddr, const char *fromsym, @@ -1189,7 +1191,7 @@ static void report_sec_mismatch(const char *modname, enum mismatch mismatch, modname, fromsec, fromaddr, from, fromsym, from_p, to, tosec, tosym, to_p); - switch (mismatch) { + switch (mismatch->mismatch) { case TEXT_TO_ANY_INIT: fprintf(stderr, "The function %s%s() references\n" @@ -1289,11 +1291,11 @@ static void check_section_mismatch(const char *modname, struct elf_info *elf, Elf_Rela *r, Elf_Sym *sym, const char *fromsec) { const char *tosec; - enum mismatch mismatch; + const struct sectioncheck *mismatch; tosec = sec_name(elf, sym->st_shndx); mismatch = section_mismatch(fromsec, tosec); - if (mismatch != NO_MISMATCH) { + if (mismatch) { Elf_Sym *to; Elf_Sym *from; const char *tosym; -- cgit v1.2.3-18-g5258 From fc2f7efadb755b020ad8fdf195515dacaf185e2d Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Sat, 30 Jan 2010 16:57:48 +0100 Subject: modpost: remove now unused NO_MISMATCH constant MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Uwe Kleine-König --- scripts/mod/modpost.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c index 3f0380b8d8f..a94bd10ad2d 100644 --- a/scripts/mod/modpost.c +++ b/scripts/mod/modpost.c @@ -835,7 +835,6 @@ static const char *linker_symbols[] = { "__init_begin", "_sinittext", "_einittext", NULL }; enum mismatch { - NO_MISMATCH, TEXT_TO_ANY_INIT, DATA_TO_ANY_INIT, TEXT_TO_ANY_EXIT, @@ -1280,8 +1279,6 @@ static void report_sec_mismatch(const char *modname, "Fix this by removing the %sannotation of %s " "or drop the export.\n", tosym, sec2annotation(tosec), sec2annotation(tosec), tosym); - case NO_MISMATCH: - /* To get warnings on missing members */ break; } fprintf(stderr, "\n"); -- cgit v1.2.3-18-g5258 From af92a82d0fec4dfd344b2ffd7a63e30f05c53938 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Sat, 30 Jan 2010 20:52:50 +0100 Subject: modpost: make symbol white list a per mismatch type variable MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Uwe Kleine-König --- scripts/mod/modpost.c | 49 +++++++++++++++++++++++++++++++------------------ 1 file changed, 31 insertions(+), 18 deletions(-) diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c index a94bd10ad2d..5dbe4db2bd4 100644 --- a/scripts/mod/modpost.c +++ b/scripts/mod/modpost.c @@ -817,18 +817,15 @@ static const char *data_sections[] = { DATA_SECTIONS, NULL }; /* symbols in .data that may refer to init/exit sections */ -static const char *symbol_white_list[] = -{ - "*driver", - "*_template", /* scsi uses *_template a lot */ - "*_timer", /* arm uses ops structures named _timer a lot */ - "*_sht", /* scsi also used *_sht to some extent */ - "*_ops", - "*_probe", - "*_probe_one", - "*_console", - NULL -}; +#define DEFAULT_SYMBOL_WHITE_LIST \ + "*driver", \ + "*_template", /* scsi uses *_template a lot */ \ + "*_timer", /* arm uses ops structures named _timer a lot */ \ + "*_sht", /* scsi also used *_sht to some extent */ \ + "*_ops", \ + "*_probe", \ + "*_probe_one", \ + "*_console" static const char *head_sections[] = { ".head.text*", NULL }; static const char *linker_symbols[] = @@ -850,6 +847,7 @@ struct sectioncheck { const char *fromsec[20]; const char *tosec[20]; enum mismatch mismatch; + const char *symbol_white_list[20]; }; const struct sectioncheck sectioncheck[] = { @@ -860,75 +858,88 @@ const struct sectioncheck sectioncheck[] = { .fromsec = { TEXT_SECTIONS, NULL }, .tosec = { ALL_INIT_SECTIONS, NULL }, .mismatch = TEXT_TO_ANY_INIT, + .symbol_white_list = { DEFAULT_SYMBOL_WHITE_LIST, NULL }, }, { .fromsec = { DATA_SECTIONS, NULL }, .tosec = { ALL_INIT_SECTIONS, NULL }, .mismatch = DATA_TO_ANY_INIT, + .symbol_white_list = { DEFAULT_SYMBOL_WHITE_LIST, NULL }, }, { .fromsec = { TEXT_SECTIONS, NULL }, .tosec = { ALL_EXIT_SECTIONS, NULL }, .mismatch = TEXT_TO_ANY_EXIT, + .symbol_white_list = { DEFAULT_SYMBOL_WHITE_LIST, NULL }, }, { .fromsec = { DATA_SECTIONS, NULL }, .tosec = { ALL_EXIT_SECTIONS, NULL }, .mismatch = DATA_TO_ANY_EXIT, + .symbol_white_list = { DEFAULT_SYMBOL_WHITE_LIST, NULL }, }, /* Do not reference init code/data from devinit/cpuinit/meminit code/data */ { .fromsec = { ALL_XXXINIT_SECTIONS, NULL }, .tosec = { INIT_SECTIONS, NULL }, .mismatch = XXXINIT_TO_SOME_INIT, + .symbol_white_list = { DEFAULT_SYMBOL_WHITE_LIST, NULL }, }, /* Do not reference cpuinit code/data from meminit code/data */ { .fromsec = { MEM_INIT_SECTIONS, NULL }, .tosec = { CPU_INIT_SECTIONS, NULL }, .mismatch = XXXINIT_TO_SOME_INIT, + .symbol_white_list = { DEFAULT_SYMBOL_WHITE_LIST, NULL }, }, /* Do not reference meminit code/data from cpuinit code/data */ { .fromsec = { CPU_INIT_SECTIONS, NULL }, .tosec = { MEM_INIT_SECTIONS, NULL }, .mismatch = XXXINIT_TO_SOME_INIT, + .symbol_white_list = { DEFAULT_SYMBOL_WHITE_LIST, NULL }, }, /* Do not reference exit code/data from devexit/cpuexit/memexit code/data */ { .fromsec = { ALL_XXXEXIT_SECTIONS, NULL }, .tosec = { EXIT_SECTIONS, NULL }, .mismatch = XXXEXIT_TO_SOME_EXIT, + .symbol_white_list = { DEFAULT_SYMBOL_WHITE_LIST, NULL }, }, /* Do not reference cpuexit code/data from memexit code/data */ { .fromsec = { MEM_EXIT_SECTIONS, NULL }, .tosec = { CPU_EXIT_SECTIONS, NULL }, .mismatch = XXXEXIT_TO_SOME_EXIT, + .symbol_white_list = { DEFAULT_SYMBOL_WHITE_LIST, NULL }, }, /* Do not reference memexit code/data from cpuexit code/data */ { .fromsec = { CPU_EXIT_SECTIONS, NULL }, .tosec = { MEM_EXIT_SECTIONS, NULL }, .mismatch = XXXEXIT_TO_SOME_EXIT, + .symbol_white_list = { DEFAULT_SYMBOL_WHITE_LIST, NULL }, }, /* Do not use exit code/data from init code */ { .fromsec = { ALL_INIT_SECTIONS, NULL }, .tosec = { ALL_EXIT_SECTIONS, NULL }, .mismatch = ANY_INIT_TO_ANY_EXIT, + .symbol_white_list = { DEFAULT_SYMBOL_WHITE_LIST, NULL }, }, /* Do not use init code/data from exit code */ { .fromsec = { ALL_EXIT_SECTIONS, NULL }, .tosec = { ALL_INIT_SECTIONS, NULL }, .mismatch = ANY_EXIT_TO_ANY_INIT, + .symbol_white_list = { DEFAULT_SYMBOL_WHITE_LIST, NULL }, }, /* Do not export init/exit functions or data */ { .fromsec = { "__ksymtab*", NULL }, .tosec = { INIT_SECTIONS, EXIT_SECTIONS, NULL }, - .mismatch = EXPORT_TO_INIT_EXIT + .mismatch = EXPORT_TO_INIT_EXIT, + .symbol_white_list = { DEFAULT_SYMBOL_WHITE_LIST, NULL }, } }; @@ -985,7 +996,8 @@ static const struct sectioncheck *section_mismatch( * refsymname = __init_begin, _sinittext, _einittext * **/ -static int secref_whitelist(const char *fromsec, const char *fromsym, +static int secref_whitelist(const struct sectioncheck *mismatch, + const char *fromsec, const char *fromsym, const char *tosec, const char *tosym) { /* Check for pattern 1 */ @@ -997,7 +1009,7 @@ static int secref_whitelist(const char *fromsec, const char *fromsym, /* Check for pattern 2 */ if (match(tosec, init_exit_sections) && match(fromsec, data_sections) && - match(fromsym, symbol_white_list)) + match(fromsym, mismatch->symbol_white_list)) return 0; /* Check for pattern 3 */ @@ -1202,7 +1214,7 @@ static void report_sec_mismatch(const char *modname, fromsym, sec2annotation(tosec), tosym); break; case DATA_TO_ANY_INIT: { - const char **s = symbol_white_list; + const char *const *s = mismatch->symbol_white_list; fprintf(stderr, "The variable %s references\n" "the %s %s%s%s\n" @@ -1223,7 +1235,7 @@ static void report_sec_mismatch(const char *modname, fromsym, to, to, tosym, to_p, sec2annotation(tosec), tosym); break; case DATA_TO_ANY_EXIT: { - const char **s = symbol_white_list; + const char *const *s = mismatch->symbol_white_list; fprintf(stderr, "The variable %s references\n" "the %s %s%s%s\n" @@ -1304,7 +1316,8 @@ static void check_section_mismatch(const char *modname, struct elf_info *elf, tosym = sym_name(elf, to); /* check whitelist - we may ignore it */ - if (secref_whitelist(fromsec, fromsym, tosec, tosym)) { + if (secref_whitelist(mismatch, + fromsec, fromsym, tosec, tosym)) { report_sec_mismatch(modname, mismatch, fromsec, r->r_offset, fromsym, is_function(from), tosec, tosym, -- cgit v1.2.3-18-g5258 From 0db252452378aa7a9e001a13226e1cd1dc61453d Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Sat, 30 Jan 2010 21:14:23 +0100 Subject: modpost: don't allow *driver to reference .init.* MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Uwe Kleine-König --- scripts/mod/modpost.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c index 5dbe4db2bd4..3318692e4e7 100644 --- a/scripts/mod/modpost.c +++ b/scripts/mod/modpost.c @@ -862,10 +862,19 @@ const struct sectioncheck sectioncheck[] = { }, { .fromsec = { DATA_SECTIONS, NULL }, - .tosec = { ALL_INIT_SECTIONS, NULL }, + .tosec = { ALL_XXXINIT_SECTIONS, NULL }, .mismatch = DATA_TO_ANY_INIT, .symbol_white_list = { DEFAULT_SYMBOL_WHITE_LIST, NULL }, }, +{ + .fromsec = { DATA_SECTIONS, NULL }, + .tosec = { INIT_SECTIONS, NULL }, + .mismatch = DATA_TO_ANY_INIT, + .symbol_white_list = { + "*_template", "*_timer", "*_sht", "*_ops", + "*_probe", "*_probe_one", "*_console", NULL + }, +}, { .fromsec = { TEXT_SECTIONS, NULL }, .tosec = { ALL_EXIT_SECTIONS, NULL }, -- cgit v1.2.3-18-g5258 From 4b024242e8a4e9679fa327ea03958b89f89096c9 Mon Sep 17 00:00:00 2001 From: Jiafu He Date: Thu, 17 Dec 2009 18:22:13 -0700 Subject: kbuild: Fix linking error built-in.o no such file or directory This patch fixes the link error "built-in.o: no such file or directory". The problem happens if "dirx/Makefile" contains only "obj-m += diry/ dirz/" and the empty "dirx/built-in.o" is missing. Adding $(subdir-m) into check for builtin-target fixes this error. Signed-off-by: Jiafu He Signed-off-by: Michal Marek --- scripts/Makefile.build | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/Makefile.build b/scripts/Makefile.build index 0b94d2fa3a8..e4deb73e9a8 100644 --- a/scripts/Makefile.build +++ b/scripts/Makefile.build @@ -82,7 +82,7 @@ ifneq ($(strip $(lib-y) $(lib-m) $(lib-n) $(lib-)),) lib-target := $(obj)/lib.a endif -ifneq ($(strip $(obj-y) $(obj-m) $(obj-n) $(obj-) $(lib-target)),) +ifneq ($(strip $(obj-y) $(obj-m) $(obj-n) $(obj-) $(subdir-m) $(lib-target)),) builtin-target := $(obj)/built-in.o endif -- cgit v1.2.3-18-g5258 From 84336466011c589b6af554f2f2f1fcfa1a5c1437 Mon Sep 17 00:00:00 2001 From: Roland McGrath Date: Mon, 21 Dec 2009 16:24:06 -0800 Subject: kconfig CROSS_COMPILE option This adds CROSS_COMPILE as a kconfig string so you can store it in .config. Then you can use plain "make" in the configured kernel build directory to do the right cross compilation without setting the command-line or environment variable every time. With this, you can set up different build directories for different kernel configurations, whether native or cross-builds, and then use the simple: make -C /build/dir M=module-source-dir idiom to build modules for any given target kernel, indicating which one by nothing but the build directory chosen. I tried a version that defaults the string with env="CROSS_COMPILE" so that in a "make oldconfig" with CROSS_COMPILE in the environment you can just hit return to store the way you're building it. But the kconfig prompt for strings doesn't give you any way to say you want an empty string instead of the default, so I punted that. Signed-off-by: Roland McGrath Cc: Sam Ravnborg Cc: Anibal Monsalve Salazar Cc: Steven Rostedt Cc: Michal Marek Signed-off-by: Andrew Morton Signed-off-by: Michal Marek --- Makefile | 3 +++ init/Kconfig | 8 ++++++++ 2 files changed, 11 insertions(+) diff --git a/Makefile b/Makefile index 394aec712c7..f9dc25cd9b2 100644 --- a/Makefile +++ b/Makefile @@ -183,11 +183,14 @@ SUBARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ \ # CROSS_COMPILE can be set on the command line # make CROSS_COMPILE=ia64-linux- # Alternatively CROSS_COMPILE can be set in the environment. +# A third alternative is to store a setting in .config so that plain +# "make" in the configured kernel build directory always uses that. # Default value for CROSS_COMPILE is not to prefix executables # Note: Some architectures assign CROSS_COMPILE in their arch/*/Makefile export KBUILD_BUILDHOST := $(SUBARCH) ARCH ?= $(SUBARCH) CROSS_COMPILE ?= +CROSS_COMPILE ?= $(CONFIG_CROSS_COMPILE:"%"=%) # Architecture as present in compile.h UTS_MACHINE := $(ARCH) diff --git a/init/Kconfig b/init/Kconfig index d95ca7cd5d4..313506d8be6 100644 --- a/init/Kconfig +++ b/init/Kconfig @@ -76,6 +76,14 @@ config INIT_ENV_ARG_LIMIT variables passed to init from the kernel command line. +config CROSS_COMPILE + string "Cross-compiler tool prefix" + help + Same as running 'make CROSS_COMPILE=prefix-' but stored for + default make runs in this kernel build directory. You don't + need to set this unless you want the configured kernel build + directory to select the cross-compiler automatically. + config LOCALVERSION string "Local version - append to kernel release" help -- cgit v1.2.3-18-g5258 From 5358db0b0e16470337c6ec08177deb3f68ed7673 Mon Sep 17 00:00:00 2001 From: Rabin Vincent Date: Tue, 5 Jan 2010 20:27:58 +0530 Subject: scripts: add ARM support to decodecode This patch adds support for decoding ARM oopses to scripts/decodecode. The following things are handled: - ARCH and CROSS_COMPILE environment variables are respected. - The Code: in x86 oopses is in bytes, while it is in either words (4 bytes) or halfwords for ARM. - Some versions of ARM objdump refuse to disassemble instructions generated by literal constants (".word 0x..."). The workaround is to strip the object file first. - The faulting instruction is marked (liked so) in ARM, but in x86. - ARM mnemonics may include characters such as [] which need to be escaped before being passed to sed for the "<- trapping instruction" substitution. Signed-off-by: Rabin Vincent Signed-off-by: Michal Marek --- scripts/decodecode | 48 +++++++++++++++++++++++++++++++++++------------- 1 file changed, 35 insertions(+), 13 deletions(-) diff --git a/scripts/decodecode b/scripts/decodecode index 4b00647814b..8b30cc36744 100755 --- a/scripts/decodecode +++ b/scripts/decodecode @@ -7,7 +7,7 @@ # AFLAGS=--32 decodecode < 386.oops cleanup() { - rm -f $T $T.s $T.o $T.oo $T.aa $T.aaa + rm -f $T $T.s $T.o $T.oo $T.aa $T.dis exit 1 } @@ -39,6 +39,29 @@ fi echo $code code=`echo $code | sed -e 's/.*Code: //'` +width=`expr index "$code" ' '` +width=$[($width-1)/2] +case $width in +1) type=byte ;; +2) type=2byte ;; +4) type=4byte ;; +esac + +disas() { + ${CROSS_COMPILE}as $AFLAGS -o $1.o $1.s &> /dev/null + + if [ "$ARCH" == "arm" ]; then + if [ $width == 2 ]; then + OBJDUMPFLAGS="-M force-thumb" + fi + + ${CROSS_COMPILE}strip $1.o + fi + + ${CROSS_COMPILE}objdump $OBJDUMPFLAGS -S $1.o | \ + grep -v "/tmp\|Disassembly\|\.text\|^$" &> $1.dis +} + marker=`expr index "$code" "\<"` if [ $marker -eq 0 ]; then marker=`expr index "$code" "\("` @@ -49,26 +72,25 @@ if [ $marker -ne 0 ]; then echo All code >> $T.oo echo ======== >> $T.oo beforemark=`echo "$code"` - echo -n " .byte 0x" > $T.s - echo $beforemark | sed -e 's/ /,0x/g' | sed -e 's///g' >> $T.s - as $AFLAGS -o $T.o $T.s &> /dev/null - objdump -S $T.o | grep -v "/tmp" | grep -v "Disassembly" | grep -v "\.text" | grep -v "^$" &> $T.ooo - cat $T.ooo >> $T.oo - rm -f $T.o $T.s $T.ooo + echo -n " .$type 0x" > $T.s + echo $beforemark | sed -e 's/ /,0x/g; s/[<>()]//g' >> $T.s + disas $T + cat $T.dis >> $T.oo + rm -f $T.o $T.s $T.dis # and fix code at-and-after marker code=`echo "$code" | cut -c$((${marker} + 1))-` fi echo Code starting with the faulting instruction > $T.aa echo =========================================== >> $T.aa -code=`echo $code | sed -e 's/ [<(]/ /;s/[>)] / /;s/ /,0x/g'` -echo -n " .byte 0x" > $T.s +code=`echo $code | sed -e 's/ [<(]/ /;s/[>)] / /;s/ /,0x/g; s/[>)]$//'` +echo -n " .$type 0x" > $T.s echo $code >> $T.s -as $AFLAGS -o $T.o $T.s &> /dev/null -objdump -S $T.o | grep -v "Disassembly" | grep -v "/tmp" | grep -v "\.text" | grep -v "^$" &> $T.aaa -cat $T.aaa >> $T.aa +disas $T +cat $T.dis >> $T.aa -faultline=`cat $T.aaa | head -1 | cut -d":" -f2` +faultline=`cat $T.dis | head -1 | cut -d":" -f2` +faultline=`echo "$faultline" | sed -e 's/\[/\\\[/g; s/\]/\\\]/g'` cat $T.oo | sed -e "s/\($faultline\)/\*\1 <-- trapping instruction/g" echo -- cgit v1.2.3-18-g5258 From da60fbbcb637b37b1d77a41886ae4e275422ca96 Mon Sep 17 00:00:00 2001 From: "Vadim Bendebury (вб)" Date: Sun, 20 Dec 2009 00:29:49 -0800 Subject: menuconfig: wrap long help lines Help text for certain config options is very extensive (the text includes the names of all other options the option in question depends on). Long lines are not wrapped, making it impossible to see the list without scrolling horizontally. This patch adds some logic which wraps help screen lines at word boundaries to prevent truncating. Tested by running ARCH=powerpc make menuconfig O=/tmp/build which shows that the long lines are now wrapped, and ARCH=powerpc make xconfig O=/tmp/build to demonstrate that it still compiles and operates as expected. Signed-off-by: Vadim Bendebury Signed-off-by: Michal Marek --- scripts/kconfig/expr.c | 27 +++++++++++++++++++++++++-- scripts/kconfig/lkc.h | 5 +++++ scripts/kconfig/mconf.c | 1 + scripts/kconfig/util.c | 2 ++ 4 files changed, 33 insertions(+), 2 deletions(-) diff --git a/scripts/kconfig/expr.c b/scripts/kconfig/expr.c index edd3f39a080..d83f2322893 100644 --- a/scripts/kconfig/expr.c +++ b/scripts/kconfig/expr.c @@ -1097,9 +1097,32 @@ void expr_fprint(struct expr *e, FILE *out) static void expr_print_gstr_helper(void *data, struct symbol *sym, const char *str) { - str_append((struct gstr*)data, str); + struct gstr *gs = (struct gstr*)data; + const char *sym_str = NULL; + + if (sym) + sym_str = sym_get_string_value(sym); + + if (gs->max_width) { + unsigned extra_length = strlen(str); + const char *last_cr = strrchr(gs->s, '\n'); + unsigned last_line_length; + + if (sym_str) + extra_length += 4 + strlen(sym_str); + + if (!last_cr) + last_cr = gs->s; + + last_line_length = strlen(gs->s) - (last_cr - gs->s); + + if ((last_line_length + extra_length) > gs->max_width) + str_append(gs, "\\\n"); + } + + str_append(gs, str); if (sym) - str_printf((struct gstr*)data, " [=%s]", sym_get_string_value(sym)); + str_printf(gs, " [=%s]", sym_str); } void expr_gstr_print(struct expr *e, struct gstr *gs) diff --git a/scripts/kconfig/lkc.h b/scripts/kconfig/lkc.h index f379b0bf8c9..e59dd0c5787 100644 --- a/scripts/kconfig/lkc.h +++ b/scripts/kconfig/lkc.h @@ -106,6 +106,11 @@ int file_write_dep(const char *name); struct gstr { size_t len; char *s; + /* + * when max_width is not zero long lines in string s (if any) get + * wrapped not to exceed the max_width value + */ + int max_width; }; struct gstr str_new(void); struct gstr str_assign(const char *s); diff --git a/scripts/kconfig/mconf.c b/scripts/kconfig/mconf.c index 8413cf38ed2..ac1e9dacde9 100644 --- a/scripts/kconfig/mconf.c +++ b/scripts/kconfig/mconf.c @@ -638,6 +638,7 @@ static void show_help(struct menu *menu) { struct gstr help = str_new(); + help.max_width = getmaxx(stdscr) - 10; menu_get_ext_help(menu, &help); show_helptext(_(menu_get_prompt(menu)), str_get(&help)); diff --git a/scripts/kconfig/util.c b/scripts/kconfig/util.c index b6b2a46af14..81c100d953e 100644 --- a/scripts/kconfig/util.c +++ b/scripts/kconfig/util.c @@ -78,6 +78,7 @@ struct gstr str_new(void) struct gstr gs; gs.s = malloc(sizeof(char) * 64); gs.len = 64; + gs.max_width = 0; strcpy(gs.s, "\0"); return gs; } @@ -88,6 +89,7 @@ struct gstr str_assign(const char *s) struct gstr gs; gs.s = strdup(s); gs.len = strlen(s) + 1; + gs.max_width = 0; return gs; } -- cgit v1.2.3-18-g5258 From c64152bfd0106807c8d3ddbe6d0928e14a64f7bb Mon Sep 17 00:00:00 2001 From: Alexander Beregalov Date: Thu, 7 Jan 2010 05:22:41 +0300 Subject: genksyms: close ref_file after use It is the last place when the file is read, so close it. Signed-off-by: Alexander Beregalov Signed-off-by: Michal Marek --- scripts/genksyms/genksyms.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/scripts/genksyms/genksyms.c b/scripts/genksyms/genksyms.c index af6b8363a2d..f99115ebe92 100644 --- a/scripts/genksyms/genksyms.c +++ b/scripts/genksyms/genksyms.c @@ -758,8 +758,10 @@ int main(int argc, char **argv) /* setlinebuf(debugfile); */ } - if (flag_reference) + if (flag_reference) { read_reference(ref_file); + fclose(ref_file); + } yyparse(); -- cgit v1.2.3-18-g5258 From 692d97c380c6dce2c35a04c5dcbce4e831a42fa0 Mon Sep 17 00:00:00 2001 From: "nir.tzachar@gmail.com" Date: Wed, 25 Nov 2009 12:28:43 +0200 Subject: kconfig: new configuration interface (nconfig) This patch was inspired by the kernel projects page, where an ncurses replacement for menuconfig was mentioned (by Sam Ravnborg). Building on menuconfig, this patch implements a more modern look interface using ncurses and ncurses' satellite libraries (menu, panel, form). The implementation does not depend on lxdialog, which is currently distributed with the kernel. Signed-off-by: Nir Tzachar Signed-off-by: Michal Marek --- scripts/kconfig/Makefile | 16 +- scripts/kconfig/lkc.h | 2 +- scripts/kconfig/lkc_proto.h | 3 +- scripts/kconfig/mconf.c | 13 - scripts/kconfig/menu.c | 16 +- scripts/kconfig/nconf.c | 1568 +++++++++++++++++++++++++++++++++++ scripts/kconfig/nconf.gui.c | 617 ++++++++++++++ scripts/kconfig/nconf.h | 95 +++ scripts/kconfig/zconf.tab.c_shipped | 2 +- scripts/kconfig/zconf.y | 2 +- 10 files changed, 2314 insertions(+), 20 deletions(-) create mode 100644 scripts/kconfig/nconf.c create mode 100644 scripts/kconfig/nconf.gui.c create mode 100644 scripts/kconfig/nconf.h diff --git a/scripts/kconfig/Makefile b/scripts/kconfig/Makefile index 999e8a7d5bf..75bdf5ae202 100644 --- a/scripts/kconfig/Makefile +++ b/scripts/kconfig/Makefile @@ -23,6 +23,9 @@ menuconfig: $(obj)/mconf config: $(obj)/conf $< $(Kconfig) +nconfig: $(obj)/nconf + $< $(Kconfig) + oldconfig: $(obj)/conf $< -o $(Kconfig) @@ -110,6 +113,7 @@ endif # Help text used by make help help: @echo ' config - Update current config utilising a line-oriented program' + @echo ' nconfig - Update current config utilising a ncurses menu based program' @echo ' menuconfig - Update current config utilising a menu based program' @echo ' xconfig - Update current config utilising a QT based front-end' @echo ' gconfig - Update current config utilising a GTK based front-end' @@ -137,6 +141,8 @@ HOST_EXTRACFLAGS += -DLOCALE # =========================================================================== # Shared Makefile for the various kconfig executables: # conf: Used for defconfig, oldconfig and related targets +# nconf: Used for the nconfig target. +# Utilizes ncurses # mconf: Used for the menuconfig target # Utilizes the lxdialog package # qconf: Used for the xconfig target @@ -149,11 +155,16 @@ lxdialog := lxdialog/checklist.o lxdialog/util.o lxdialog/inputbox.o lxdialog += lxdialog/textbox.o lxdialog/yesno.o lxdialog/menubox.o conf-objs := conf.o zconf.tab.o -mconf-objs := mconf.o zconf.tab.o $(lxdialog) +mconf-objs := mconf.o zconf.tab.o $(lxdialog) +nconf-objs := nconf.o zconf.tab.o nconf.gui.o kxgettext-objs := kxgettext.o zconf.tab.o hostprogs-y := conf qconf gconf kxgettext +ifeq ($(MAKECMDGOALS),nconfig) + hostprogs-y += nconf +endif + ifeq ($(MAKECMDGOALS),menuconfig) hostprogs-y += mconf endif @@ -177,7 +188,7 @@ endif clean-files := lkc_defs.h qconf.moc .tmp_qtcheck \ .tmp_gtkcheck zconf.tab.c lex.zconf.c zconf.hash.c gconf.glade.h -clean-files += mconf qconf gconf +clean-files += mconf qconf gconf nconf clean-files += config.pot linux.pot # Check that we have the required ncurses stuff installed for lxdialog (menuconfig) @@ -202,6 +213,7 @@ HOSTLOADLIBES_gconf = `pkg-config --libs gtk+-2.0 gmodule-2.0 libglade-2.0` HOSTCFLAGS_gconf.o = `pkg-config --cflags gtk+-2.0 gmodule-2.0 libglade-2.0` \ -D LKC_DIRECT_LINK +HOSTLOADLIBES_nconf = -lmenu -lpanel -lncurses $(obj)/qconf.o: $(obj)/.tmp_qtcheck ifeq ($(qconf-target),1) diff --git a/scripts/kconfig/lkc.h b/scripts/kconfig/lkc.h index e59dd0c5787..ce6549cdacc 100644 --- a/scripts/kconfig/lkc.h +++ b/scripts/kconfig/lkc.h @@ -84,7 +84,7 @@ void conf_set_all_new_symbols(enum conf_def_mode mode); void kconfig_load(void); /* menu.c */ -void menu_init(void); +void _menu_init(void); void menu_warn(struct menu *menu, const char *fmt, ...); struct menu *menu_add_menu(void); void menu_end_menu(void); diff --git a/scripts/kconfig/lkc_proto.h b/scripts/kconfig/lkc_proto.h index ffeb532b2cf..41e652a8d1f 100644 --- a/scripts/kconfig/lkc_proto.h +++ b/scripts/kconfig/lkc_proto.h @@ -17,7 +17,8 @@ P(menu_get_root_menu,struct menu *,(struct menu *menu)); P(menu_get_parent_menu,struct menu *,(struct menu *menu)); P(menu_has_help,bool,(struct menu *menu)); P(menu_get_help,const char *,(struct menu *menu)); -P(get_symbol_str,void,(struct gstr *r, struct symbol *sym)); +P(get_symbol_str, void, (struct gstr *r, struct symbol *sym)); +P(get_relations_str, struct gstr, (struct symbol **sym_arr)); P(menu_get_ext_help,void,(struct menu *menu, struct gstr *help)); /* symbol.c */ diff --git a/scripts/kconfig/mconf.c b/scripts/kconfig/mconf.c index ac1e9dacde9..a4a75190457 100644 --- a/scripts/kconfig/mconf.c +++ b/scripts/kconfig/mconf.c @@ -282,19 +282,6 @@ static void show_textbox(const char *title, const char *text, int r, int c); static void show_helptext(const char *title, const char *text); static void show_help(struct menu *menu); -static struct gstr get_relations_str(struct symbol **sym_arr) -{ - struct symbol *sym; - struct gstr res = str_new(); - int i; - - for (i = 0; sym_arr && (sym = sym_arr[i]); i++) - get_symbol_str(&res, sym); - if (!i) - str_append(&res, _("No matches found.\n")); - return res; -} - static char filename[PATH_MAX+1]; static void set_config_filename(const char *config_filename) { diff --git a/scripts/kconfig/menu.c b/scripts/kconfig/menu.c index 059a2465c57..21bfb3dbc87 100644 --- a/scripts/kconfig/menu.c +++ b/scripts/kconfig/menu.c @@ -38,7 +38,7 @@ static void prop_warn(struct property *prop, const char *fmt, ...) va_end(ap); } -void menu_init(void) +void _menu_init(void) { current_entry = current_menu = &rootmenu; last_entry_ptr = &rootmenu.list; @@ -515,6 +515,20 @@ void get_symbol_str(struct gstr *r, struct symbol *sym) str_append(r, "\n\n"); } +struct gstr get_relations_str(struct symbol **sym_arr) +{ + struct symbol *sym; + struct gstr res = str_new(); + int i; + + for (i = 0; sym_arr && (sym = sym_arr[i]); i++) + get_symbol_str(&res, sym); + if (!i) + str_append(&res, _("No matches found.\n")); + return res; +} + + void menu_get_ext_help(struct menu *menu, struct gstr *help) { struct symbol *sym = menu->sym; diff --git a/scripts/kconfig/nconf.c b/scripts/kconfig/nconf.c new file mode 100644 index 00000000000..8c56150a757 --- /dev/null +++ b/scripts/kconfig/nconf.c @@ -0,0 +1,1568 @@ +/* + * Copyright (C) 2008 Nir Tzachar can be built in, modularized or removed\n" +" { } can be built in or modularized (selected by other feature)\n" +" - - are selected by other feature,\n" +" XXX cannot be selected. use Symbol Info to find out why,\n" +"while *, M or whitespace inside braces means to build in, build as\n" +"a module or to exclude the feature respectively.\n" +"\n" +"To change any of these features, highlight it with the cursor\n" +"keys and press to build it in, to make it a module or\n" +" to removed it. You may also press the to cycle\n" +"through the available options (ie. Y->N->M->Y).\n" +"\n" +"Some additional keyboard hints:\n" +"\n" +"Menus\n" +"----------\n" +"o Use the Up/Down arrow keys (cursor keys) to highlight the item\n" +" you wish to change use or . Goto submenu by \n" +" pressing of . Use or to go back.\n" +" Submenus are designated by \"--->\".\n" +"\n" +" Shortcut: Press the option's highlighted letter (hotkey).\n" +" Pressing a hotkey more than once will sequence\n" +" through all visible items which use that hotkey.\n" +"\n" +" You may also use the and keys to scroll\n" +" unseen options into view.\n" +"\n" +"o To exit a menu use the just press or .\n" +"\n" +"o To get help with an item, press \n" +" Shortcut: Press or .\n" +"\n" +"\n" +"Radiolists (Choice lists)\n" +"-----------\n" +"o Use the cursor keys to select the option you wish to set and press\n" +" or the .\n" +"\n" +" Shortcut: Press the first letter of the option you wish to set then\n" +" press or .\n" +"\n" +"o To see available help for the item, press \n" +" Shortcut: Press or .\n" +"\n" +"\n" +"Data Entry\n" +"-----------\n" +"o Enter the requested information and press \n" +" If you are entering hexadecimal values, it is not necessary to\n" +" add the '0x' prefix to the entry.\n" +"\n" +"o For help, press .\n" +"\n" +"\n" +"Text Box (Help Window)\n" +"--------\n" +"o Use the cursor keys to scroll up/down/left/right. The VI editor\n" +" keys h,j,k,l function here as do for those\n" +" who are familiar with less and lynx.\n" +"\n" +"o Press , , , or to exit.\n" +"\n" +"\n" +"Alternate Configuration Files\n" +"-----------------------------\n" +"nconfig supports the use of alternate configuration files for\n" +"those who, for various reasons, find it necessary to switch\n" +"between different kernel configurations.\n" +"\n" +"At the end of the main menu you will find two options. One is\n" +"for saving the current configuration to a file of your choosing.\n" +"The other option is for loading a previously saved alternate\n" +"configuration.\n" +"\n" +"Even if you don't use alternate configuration files, but you\n" +"find during a nconfig session that you have completely messed\n" +"up your settings, you may use the \"Load Alternate...\" option to\n" +"restore your previously saved settings from \".config\" without\n" +"restarting nconfig.\n" +"\n" +"Other information\n" +"-----------------\n" +"If you use nconfig in an XTERM window make sure you have your\n" +"$TERM variable set to point to a xterm definition which supports color.\n" +"Otherwise, nconfig will look rather bad. nconfig will not\n" +"display correctly in a RXVT window because rxvt displays only one\n" +"intensity of color, bright.\n" +"\n" +"nconfig will display larger menus on screens or xterms which are\n" +"set to display more than the standard 25 row by 80 column geometry.\n" +"In order for this to work, the \"stty size\" command must be able to\n" +"display the screen's current row and column geometry. I STRONGLY\n" +"RECOMMEND that you make sure you do NOT have the shell variables\n" +"LINES and COLUMNS exported into your environment. Some distributions\n" +"export those variables via /etc/profile. Some ncurses programs can\n" +"become confused when those variables (LINES & COLUMNS) don't reflect\n" +"the true screen size.\n" +"\n" +"Optional personality available\n" +"------------------------------\n" +"If you prefer to have all of the kernel options listed in a single\n" +"menu, rather than the default multimenu hierarchy, run the nconfig\n" +"with NCONFIG_MODE environment variable set to single_menu. Example:\n" +"\n" +"make NCONFIG_MODE=single_menu nconfig\n" +"\n" +" will then unroll the appropriate category, or enfold it if it\n" +"is already unrolled.\n" +"\n" +"Note that this mode can eventually be a little more CPU expensive\n" +"(especially with a larger number of unrolled categories) than the\n" +"default mode.\n" +"\n"), +menu_no_f_instructions[] = N_( +" You do not have function keys support. Please follow the\n" +" following instructions:\n" +" Arrow keys navigate the menu.\n" +" or selects submenus --->.\n" +" Capital Letters are hotkeys.\n" +" Pressing includes, excludes, modularizes features.\n" +" Pressing SpaceBar toggles between the above options\n" +" Press or to go back one menu, \n" +" or for Help, for Search.\n" +" <1> is interchangable with , <2> with , etc.\n" +" Legend: [*] built-in [ ] excluded module < > module capable.\n" +" always leaves the current window\n"), +menu_instructions[] = N_( +" Arrow keys navigate the menu.\n" +" or selects submenus --->.\n" +" Capital Letters are hotkeys.\n" +" Pressing includes, excludes, modularizes features.\n" +" Pressing SpaceBar toggles between the above options\n" +" Press , or to go back one menu, \n" +" , or for Help, for Search.\n" +" <1> is interchangable with , <2> with , etc.\n" +" Legend: [*] built-in [ ] excluded module < > module capable.\n" +" always leaves the current window\n"), +radiolist_instructions[] = N_( +" Use the arrow keys to navigate this window or\n" +" press the hotkey of the item you wish to select\n" +" followed by the .\n" +" Press , or for additional information about this option.\n"), +inputbox_instructions_int[] = N_( +"Please enter a decimal value.\n" +"Fractions will not be accepted.\n" +"Press to accept, to cancel."), +inputbox_instructions_hex[] = N_( +"Please enter a hexadecimal value.\n" +"Press to accept, to cancel."), +inputbox_instructions_string[] = N_( +"Please enter a string value.\n" +"Press to accept, to cancel."), +setmod_text[] = N_( +"This feature depends on another which\n" +"has been configured as a module.\n" +"As a result, this feature will be built as a module."), +nohelp_text[] = N_( +"There is no help available for this kernel option.\n"), +load_config_text[] = N_( +"Enter the name of the configuration file you wish to load.\n" +"Accept the name shown to restore the configuration you\n" +"last retrieved. Leave blank to abort."), +load_config_help[] = N_( +"\n" +"For various reasons, one may wish to keep several different kernel\n" +"configurations available on a single machine.\n" +"\n" +"If you have saved a previous configuration in a file other than the\n" +"kernel's default, entering the name of the file here will allow you\n" +"to modify that configuration.\n" +"\n" +"If you are uncertain, then you have probably never used alternate\n" +"configuration files. You should therefor leave this blank to abort.\n"), +save_config_text[] = N_( +"Enter a filename to which this configuration should be saved\n" +"as an alternate. Leave blank to abort."), +save_config_help[] = N_( +"\n" +"For various reasons, one may wish to keep different kernel\n" +"configurations available on a single machine.\n" +"\n" +"Entering a file name here will allow you to later retrieve, modify\n" +"and use the current configuration as an alternate to whatever\n" +"configuration options you have selected at that time.\n" +"\n" +"If you are uncertain what all this means then you should probably\n" +"leave this blank.\n"), +search_help[] = N_( +"\n" +"Search for CONFIG_ symbols and display their relations.\n" +"Regular expressions are allowed.\n" +"Example: search for \"^FOO\"\n" +"Result:\n" +"-----------------------------------------------------------------\n" +"Symbol: FOO [ = m]\n" +"Prompt: Foo bus is used to drive the bar HW\n" +"Defined at drivers/pci/Kconfig:47\n" +"Depends on: X86_LOCAL_APIC && X86_IO_APIC || IA64\n" +"Location:\n" +" -> Bus options (PCI, PCMCIA, EISA, MCA, ISA)\n" +" -> PCI support (PCI [ = y])\n" +" -> PCI access mode ( [ = y])\n" +"Selects: LIBCRC32\n" +"Selected by: BAR\n" +"-----------------------------------------------------------------\n" +"o The line 'Prompt:' shows the text used in the menu structure for\n" +" this CONFIG_ symbol\n" +"o The 'Defined at' line tell at what file / line number the symbol\n" +" is defined\n" +"o The 'Depends on:' line tell what symbols needs to be defined for\n" +" this symbol to be visible in the menu (selectable)\n" +"o The 'Location:' lines tell where in the menu structure this symbol\n" +" is located\n" +" A location followed by a [ = y] indicate that this is a selectable\n" +" menu item - and current value is displayed inside brackets.\n" +"o The 'Selects:' line tell what symbol will be automatically\n" +" selected if this symbol is selected (y or m)\n" +"o The 'Selected by' line tell what symbol has selected this symbol\n" +"\n" +"Only relevant lines are shown.\n" +"\n\n" +"Search examples:\n" +"Examples: USB = > find all CONFIG_ symbols containing USB\n" +" ^USB => find all CONFIG_ symbols starting with USB\n" +" USB$ => find all CONFIG_ symbols ending with USB\n" +"\n"); + +struct mitem { + char str[256]; + char tag; + void *usrptr; + int is_hot; + int is_visible; +}; + +#define MAX_MENU_ITEMS 4096 +static int show_all_items; +static int indent; +static struct menu *current_menu; +static int child_count; +static int single_menu_mode; +/* the window in which all information appears */ +static WINDOW *main_window; +/* the largest size of the menu window */ +static int mwin_max_lines; +static int mwin_max_cols; +/* the window in which we show option buttons */ +static MENU *curses_menu; +static ITEM *curses_menu_items[MAX_MENU_ITEMS]; +static struct mitem k_menu_items[MAX_MENU_ITEMS]; +static int items_num; +static int global_exit; +/* the currently selected button */ +const char *current_instructions = menu_instructions; +/* this array is used to implement hot keys. it is updated in item_make and + * resetted in clean_items. It would be better to use a hash, but lets keep it + * simple... */ +#define MAX_SAME_KEY MAX_MENU_ITEMS +struct { + int count; + int ptrs[MAX_MENU_ITEMS]; +} hotkeys[1<<(sizeof(char)*8)]; + +static void conf(struct menu *menu); +static void conf_choice(struct menu *menu); +static void conf_string(struct menu *menu); +static void conf_load(void); +static void conf_save(void); +static void show_help(struct menu *menu); +static int do_exit(void); +static void setup_windows(void); + +typedef void (*function_key_handler_t)(int *key, struct menu *menu); +static void handle_f1(int *key, struct menu *current_item); +static void handle_f2(int *key, struct menu *current_item); +static void handle_f3(int *key, struct menu *current_item); +static void handle_f4(int *key, struct menu *current_item); +static void handle_f5(int *key, struct menu *current_item); +static void handle_f6(int *key, struct menu *current_item); +static void handle_f7(int *key, struct menu *current_item); +static void handle_f8(int *key, struct menu *current_item); + +struct function_keys { + const char *key_str; + const char *func; + function_key key; + function_key_handler_t handler; +}; + +static const int function_keys_num = 8; +struct function_keys function_keys[] = { + { + .key_str = "F1", + .func = "Help", + .key = F_HELP, + .handler = handle_f1, + }, + { + .key_str = "F2", + .func = "Symbol Info", + .key = F_SYMBOL, + .handler = handle_f2, + }, + { + .key_str = "F3", + .func = "Instructions", + .key = F_INSTS, + .handler = handle_f3, + }, + { + .key_str = "F4", + .func = "Config", + .key = F_CONF, + .handler = handle_f4, + }, + { + .key_str = "F5", + .func = "Back", + .key = F_BACK, + .handler = handle_f5, + }, + { + .key_str = "F6", + .func = "Save", + .key = F_SAVE, + .handler = handle_f6, + }, + { + .key_str = "F7", + .func = "Load", + .key = F_LOAD, + .handler = handle_f7, + }, + { + .key_str = "F8", + .func = "Exit", + .key = F_EXIT, + .handler = handle_f8, + }, +}; + +static void print_function_line(void) +{ + int i; + int offset = 1; + const int skip = 1; + + for (i = 0; i < function_keys_num; i++) { + wattrset(main_window, attributes[FUNCTION_HIGHLIGHT]); + mvwprintw(main_window, LINES-3, offset, + "%s", + function_keys[i].key_str); + wattrset(main_window, attributes[FUNCTION_TEXT]); + offset += strlen(function_keys[i].key_str); + mvwprintw(main_window, LINES-3, + offset, "%s", + function_keys[i].func); + offset += strlen(function_keys[i].func) + skip; + } + wattrset(main_window, attributes[NORMAL]); +} + +/* help */ +static void handle_f1(int *key, struct menu *current_item) +{ + show_scroll_win(main_window, + _("README"), _(nconf_readme)); + return; +} + +/* symbole help */ +static void handle_f2(int *key, struct menu *current_item) +{ + show_help(current_item); + return; +} + +/* instructions */ +static void handle_f3(int *key, struct menu *current_item) +{ + show_scroll_win(main_window, + _("Instructions"), + _(current_instructions)); + return; +} + +/* config */ +static void handle_f4(int *key, struct menu *current_item) +{ + int res = btn_dialog(main_window, + _("Show all symbols?"), + 2, + " ", + ""); + if (res == 0) + show_all_items = 1; + else if (res == 1) + show_all_items = 0; + + return; +} + +/* back */ +static void handle_f5(int *key, struct menu *current_item) +{ + *key = KEY_LEFT; + return; +} + +/* save */ +static void handle_f6(int *key, struct menu *current_item) +{ + conf_save(); + return; +} + +/* load */ +static void handle_f7(int *key, struct menu *current_item) +{ + conf_load(); + return; +} + +/* exit */ +static void handle_f8(int *key, struct menu *current_item) +{ + do_exit(); + return; +} + +/* return != 0 to indicate the key was handles */ +int process_special_keys(int *key, struct menu *menu) +{ + int i; + + if (*key == KEY_RESIZE) { + setup_windows(); + return 1; + } + + for (i = 0; i < function_keys_num; i++) { + if (*key == KEY_F(function_keys[i].key) || + *key == '0' + function_keys[i].key){ + function_keys[i].handler(key, menu); + return 1; + } + } + + return 0; +} + +static void clean_items(void) +{ + int i; + for (i = 0; curses_menu_items[i]; i++) + free_item(curses_menu_items[i]); + bzero(curses_menu_items, sizeof(curses_menu_items)); + bzero(k_menu_items, sizeof(k_menu_items)); + bzero(hotkeys, sizeof(hotkeys)); + items_num = 0; +} + +/* return the index of the next hot item, or -1 if no such item exists */ +int get_next_hot(int c) +{ + static int hot_index; + static int hot_char; + + if (c < 0 || c > 255 || hotkeys[c].count <= 0) + return -1; + + if (hot_char == c) { + hot_index = (hot_index+1)%hotkeys[c].count; + return hotkeys[c].ptrs[hot_index]; + } else { + hot_char = c; + hot_index = 0; + return hotkeys[c].ptrs[0]; + } +} + +/* can the char c be a hot key? no, if c is a common shortcut used elsewhere */ +int canbhot(char c) +{ + c = tolower(c); + return isalnum(c) && c != 'y' && c != 'm' && c != 'h' && + c != 'n' && c != '?'; +} + +/* check if str already contains a hot key. */ +int is_hot(int index) +{ + return k_menu_items[index].is_hot; +} + +/* find the first possible hot key, and mark it. + * index is the index of the item in the menu + * return 0 on success*/ +int make_hot(char *dest, int len, const char *org, int index) +{ + int position = -1; + int i; + int tmp; + int c; + int org_len = strlen(org); + + if (org == NULL || is_hot(index)) + return 1; + + /* make sure not to make hot keys out of markers. + * find where to start looking for a hot key + */ + i = 0; + /* skip white space */ + while (i < org_len && org[i] == ' ') + i++; + if (i == org_len) + return -1; + /* if encountering '(' or '<' or '[', find the match and look from there + **/ + if (org[i] == '[' || org[i] == '<' || org[i] == '(') { + i++; + for (; i < org_len; i++) + if (org[i] == ']' || org[i] == '>' || org[i] == ')') + break; + } + if (i == org_len) + return -1; + for (; i < org_len; i++) { + if (canbhot(org[i]) && org[i-1] != '<' && org[i-1] != '(') { + position = i; + break; + } + } + if (position == -1) + return 1; + + /* ok, char at org[position] should be a hot key to this item */ + c = tolower(org[position]); + tmp = hotkeys[c].count; + hotkeys[c].ptrs[tmp] = index; + hotkeys[c].count++; + /* + snprintf(dest, len, "%.*s(%c)%s", position, org, org[position], + &org[position+1]); + */ + /* make org[position] uppercase, and all leading letter small case */ + strncpy(dest, org, len); + for (i = 0; i < position; i++) + dest[i] = tolower(dest[i]); + dest[position] = toupper(dest[position]); + k_menu_items[index].is_hot = 1; + return 0; +} + +/* Make a new item. Add a hotkey mark in the first possible letter. + * As ncurses does not allow any attributes inside menue item, we mark the + * hot key as the first capitalized letter in the string */ +void item_make(struct menu *menu, char tag, const char *fmt, ...) +{ + va_list ap; + char tmp_str[256]; + + if (items_num > MAX_MENU_ITEMS-1) + return; + + bzero(&k_menu_items[items_num], sizeof(k_menu_items[0])); + k_menu_items[items_num].tag = tag; + k_menu_items[items_num].usrptr = menu; + if (menu != NULL) + k_menu_items[items_num].is_visible = + menu_is_visible(menu); + else + k_menu_items[items_num].is_visible = 1; + + va_start(ap, fmt); + vsnprintf(tmp_str, sizeof(tmp_str), fmt, ap); + if (!k_menu_items[items_num].is_visible) + memcpy(tmp_str, "XXX", 3); + va_end(ap); + if (make_hot( + k_menu_items[items_num].str, + sizeof(k_menu_items[items_num].str), tmp_str, items_num) != 0) + strncpy(k_menu_items[items_num].str, + tmp_str, + sizeof(k_menu_items[items_num].str)); + + curses_menu_items[items_num] = new_item( + k_menu_items[items_num].str, + k_menu_items[items_num].str); + set_item_userptr(curses_menu_items[items_num], + &k_menu_items[items_num]); + /* + if (!k_menu_items[items_num].is_visible) + item_opts_off(curses_menu_items[items_num], O_SELECTABLE); + */ + + items_num++; + curses_menu_items[items_num] = NULL; +} + +/* very hackish. adds a string to the last item added */ +void item_add_str(const char *fmt, ...) +{ + va_list ap; + int index = items_num-1; + char new_str[256]; + char tmp_str[256]; + + if (index < 0) + return; + + va_start(ap, fmt); + vsnprintf(new_str, sizeof(new_str), fmt, ap); + va_end(ap); + snprintf(tmp_str, sizeof(tmp_str), "%s%s", + k_menu_items[index].str, new_str); + if (make_hot(k_menu_items[index].str, + sizeof(k_menu_items[index].str), tmp_str, index) != 0) + strncpy(k_menu_items[index].str, + tmp_str, + sizeof(k_menu_items[index].str)); + + free_item(curses_menu_items[index]); + curses_menu_items[index] = new_item( + k_menu_items[index].str, + k_menu_items[index].str); + set_item_userptr(curses_menu_items[index], + &k_menu_items[index]); +} + +/* get the tag of the currently selected item */ +char item_tag(void) +{ + ITEM *cur; + struct mitem *mcur; + + cur = current_item(curses_menu); + if (cur == NULL) + return 0; + mcur = (struct mitem *) item_userptr(cur); + return mcur->tag; +} + +int curses_item_index(void) +{ + return item_index(current_item(curses_menu)); +} + +void *item_data(void) +{ + ITEM *cur; + struct mitem *mcur; + + cur = current_item(curses_menu); + mcur = (struct mitem *) item_userptr(cur); + return mcur->usrptr; + +} + +int item_is_tag(char tag) +{ + return item_tag() == tag; +} + +static char filename[PATH_MAX+1]; +static char menu_backtitle[PATH_MAX+128]; +const char *set_config_filename(const char *config_filename) +{ + int size; + struct symbol *sym; + + sym = sym_lookup("KERNELVERSION", 0); + sym_calc_value(sym); + size = snprintf(menu_backtitle, sizeof(menu_backtitle), + _("%s - Linux Kernel v%s Configuration"), + config_filename, sym_get_string_value(sym)); + if (size >= sizeof(menu_backtitle)) + menu_backtitle[sizeof(menu_backtitle)-1] = '\0'; + + size = snprintf(filename, sizeof(filename), "%s", config_filename); + if (size >= sizeof(filename)) + filename[sizeof(filename)-1] = '\0'; + return menu_backtitle; +} + +/* command = 0 is supress, 1 is restore */ +static void supress_stdout(int command) +{ + static FILE *org_stdout; + static FILE *org_stderr; + + if (command == 0) { + org_stdout = stdout; + org_stderr = stderr; + stdout = fopen("/dev/null", "a"); + stderr = fopen("/dev/null", "a"); + } else { + fclose(stdout); + fclose(stderr); + stdout = org_stdout; + stderr = org_stderr; + } +} + +/* return = 0 means we are successful. + * -1 means go on doing what you were doing + */ +static int do_exit(void) +{ + int res; + if (!conf_get_changed()) { + global_exit = 1; + return 0; + } + res = btn_dialog(main_window, + _("Do you wish to save your " + "new kernel configuration?\n" + " to cancel and resume nconfig."), + 2, + " ", + ""); + if (res == KEY_EXIT) { + global_exit = 0; + return -1; + } + + /* if we got here, the user really wants to exit */ + switch (res) { + case 0: + supress_stdout(0); + res = conf_write(filename); + supress_stdout(1); + if (res) + btn_dialog( + main_window, + _("Error during writing of the kernel " + "configuration.\n" + "Your kernel configuration " + "changes were NOT saved."), + 1, + ""); + else { + char buf[1024]; + snprintf(buf, 1024, + _("Configuration written to %s\n" + "End of Linux kernel configuration.\n" + "Execute 'make' to build the kernel or try" + " 'make help'."), filename); + btn_dialog( + main_window, + buf, + 1, + ""); + } + break; + default: + btn_dialog( + main_window, + _("Your kernel configuration changes were NOT saved."), + 1, + ""); + break; + } + global_exit = 1; + return 0; +} + + +static void search_conf(void) +{ + struct symbol **sym_arr; + struct gstr res; + char dialog_input_result[100]; + char *dialog_input; + int dres; +again: + dres = dialog_inputbox(main_window, + _("Search Configuration Parameter"), + _("Enter CONFIG_ (sub)string to search for " + "(with or without \"CONFIG\")"), + "", dialog_input_result, 99); + switch (dres) { + case 0: + break; + case 1: + show_scroll_win(main_window, + _("Search Configuration"), search_help); + goto again; + default: + return; + } + + /* strip CONFIG_ if necessary */ + dialog_input = dialog_input_result; + if (strncasecmp(dialog_input_result, "CONFIG_", 7) == 0) + dialog_input += 7; + + sym_arr = sym_re_search(dialog_input); + res = get_relations_str(sym_arr); + free(sym_arr); + show_scroll_win(main_window, + _("Search Results"), str_get(&res)); + str_free(&res); +} + + +static void build_conf(struct menu *menu) +{ + struct symbol *sym; + struct property *prop; + struct menu *child; + int type, tmp, doint = 2; + tristate val; + char ch; + + if (!menu || (!show_all_items && !menu_is_visible(menu))) + return; + + sym = menu->sym; + prop = menu->prompt; + if (!sym) { + if (prop && menu != current_menu) { + const char *prompt = menu_get_prompt(menu); + enum prop_type ptype; + ptype = menu->prompt ? menu->prompt->type : P_UNKNOWN; + switch (ptype) { + case P_MENU: + child_count++; + prompt = _(prompt); + if (single_menu_mode) { + item_make(menu, 'm', + "%s%*c%s", + menu->data ? "-->" : "++>", + indent + 1, ' ', prompt); + } else + item_make(menu, 'm', + " %*c%s --->", + indent + 1, + ' ', prompt); + + if (single_menu_mode && menu->data) + goto conf_childs; + return; + case P_COMMENT: + if (prompt) { + child_count++; + item_make(menu, ':', + " %*c*** %s ***", + indent + 1, ' ', + _(prompt)); + } + break; + default: + if (prompt) { + child_count++; + item_make(menu, ':', "---%*c%s", + indent + 1, ' ', + _(prompt)); + } + } + } else + doint = 0; + goto conf_childs; + } +