aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSam Ravnborg <sam@ravnborg.org>2010-07-31 17:35:34 -0400
committerMichal Marek <mmarek@suse.cz>2010-08-03 07:49:32 -0400
commit7cf3d73b4360e91b14326632ab1aeda4cb26308d (patch)
tree547bc52c631c9fb99ecd5c4be5ba25610505397a
parent49192f266ffa187bd7adaf5c2d881f85bd53e0ed (diff)
kconfig: add savedefconfig
savedefconfig will save a minimal config to a file named "defconfig". The config symbols are saved in the same order as they appear in the menu structure so it should be possible to map them to the relevant menus if desired. The implementation was tested against several minimal configs for arm which was created using brute-force. There was one regression related to default numbers which had their valid range further limited by another symbol. Sample: config FOO int "foo" default 4 config BAR int "bar" range 0 FOO If FOO is set to 3 then BAR cannot take a value higher than 3. But the current implementation will set BAR equal to 4. This is seldomly used and the final configuration is OK, and the fix was non-trivial. So it was documented in the code and left as is. Signed-off-by: Sam Ravnborg <sam@ravnborg.org> Acked-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de> Signed-off-by: Michal Marek <mmarek@suse.cz>
-rw-r--r--scripts/kconfig/Makefile6
-rw-r--r--scripts/kconfig/conf.c14
-rw-r--r--scripts/kconfig/confdata.c76
-rw-r--r--scripts/kconfig/lkc.h1
-rw-r--r--scripts/kconfig/lkc_proto.h1
-rw-r--r--scripts/kconfig/symbol.c74
6 files changed, 171 insertions, 1 deletions
diff --git a/scripts/kconfig/Makefile b/scripts/kconfig/Makefile
index 72973591c0f1..c0e459e2b014 100644
--- a/scripts/kconfig/Makefile
+++ b/scripts/kconfig/Makefile
@@ -90,11 +90,14 @@ PHONY += allnoconfig allyesconfig allmodconfig alldefconfig randconfig
90allnoconfig allyesconfig allmodconfig alldefconfig randconfig: $(obj)/conf 90allnoconfig allyesconfig allmodconfig alldefconfig randconfig: $(obj)/conf
91 $< --$@ $(Kconfig) 91 $< --$@ $(Kconfig)
92 92
93PHONY += listnewconfig oldnoconfig defconfig 93PHONY += listnewconfig oldnoconfig savedefconfig defconfig
94 94
95listnewconfig oldnoconfig: $(obj)/conf 95listnewconfig oldnoconfig: $(obj)/conf
96 $< --$@ $(Kconfig) 96 $< --$@ $(Kconfig)
97 97
98savedefconfig: $(obj)/conf
99 $< --$@=defconfig $(Kconfig)
100
98defconfig: $(obj)/conf 101defconfig: $(obj)/conf
99ifeq ($(KBUILD_DEFCONFIG),) 102ifeq ($(KBUILD_DEFCONFIG),)
100 $< --defconfig $(Kconfig) 103 $< --defconfig $(Kconfig)
@@ -118,6 +121,7 @@ help:
118 @echo ' localyesconfig - Update current config converting local mods to core' 121 @echo ' localyesconfig - Update current config converting local mods to core'
119 @echo ' silentoldconfig - Same as oldconfig, but quietly, additionally update deps' 122 @echo ' silentoldconfig - Same as oldconfig, but quietly, additionally update deps'
120 @echo ' defconfig - New config with default from ARCH supplied defconfig' 123 @echo ' defconfig - New config with default from ARCH supplied defconfig'
124 @echo ' savedefconfig - Save current config as ./defconfig (minimal config)'
121 @echo ' allnoconfig - New config where all options are answered with no' 125 @echo ' allnoconfig - New config where all options are answered with no'
122 @echo ' allyesconfig - New config where all options are accepted with yes' 126 @echo ' allyesconfig - New config where all options are accepted with yes'
123 @echo ' allmodconfig - New config selecting modules when possible' 127 @echo ' allmodconfig - New config selecting modules when possible'
diff --git a/scripts/kconfig/conf.c b/scripts/kconfig/conf.c
index c8bd33cb3bf7..010600ef58c0 100644
--- a/scripts/kconfig/conf.c
+++ b/scripts/kconfig/conf.c
@@ -30,6 +30,7 @@ enum input_mode {
30 alldefconfig, 30 alldefconfig,
31 randconfig, 31 randconfig,
32 defconfig, 32 defconfig,
33 savedefconfig,
33 listnewconfig, 34 listnewconfig,
34 oldnoconfig, 35 oldnoconfig,
35} input_mode = oldaskconfig; 36} input_mode = oldaskconfig;
@@ -444,6 +445,7 @@ static struct option long_opts[] = {
444 {"oldconfig", no_argument, NULL, oldconfig}, 445 {"oldconfig", no_argument, NULL, oldconfig},
445 {"silentoldconfig", no_argument, NULL, silentoldconfig}, 446 {"silentoldconfig", no_argument, NULL, silentoldconfig},
446 {"defconfig", optional_argument, NULL, defconfig}, 447 {"defconfig", optional_argument, NULL, defconfig},
448 {"savedefconfig", required_argument, NULL, savedefconfig},
447 {"allnoconfig", no_argument, NULL, allnoconfig}, 449 {"allnoconfig", no_argument, NULL, allnoconfig},
448 {"allyesconfig", no_argument, NULL, allyesconfig}, 450 {"allyesconfig", no_argument, NULL, allyesconfig},
449 {"allmodconfig", no_argument, NULL, allmodconfig}, 451 {"allmodconfig", no_argument, NULL, allmodconfig},
@@ -471,6 +473,7 @@ int main(int ac, char **av)
471 sync_kconfig = 1; 473 sync_kconfig = 1;
472 break; 474 break;
473 case defconfig: 475 case defconfig:
476 case savedefconfig:
474 defconfig_file = optarg; 477 defconfig_file = optarg;
475 break; 478 break;
476 case randconfig: 479 case randconfig:
@@ -526,6 +529,9 @@ int main(int ac, char **av)
526 exit(1); 529 exit(1);
527 } 530 }
528 break; 531 break;
532 case savedefconfig:
533 conf_read(NULL);
534 break;
529 case silentoldconfig: 535 case silentoldconfig:
530 case oldaskconfig: 536 case oldaskconfig:
531 case oldconfig: 537 case oldconfig:
@@ -591,6 +597,8 @@ int main(int ac, char **av)
591 case defconfig: 597 case defconfig:
592 conf_set_all_new_symbols(def_default); 598 conf_set_all_new_symbols(def_default);
593 break; 599 break;
600 case savedefconfig:
601 break;
594 case oldconfig: 602 case oldconfig:
595 case oldaskconfig: 603 case oldaskconfig:
596 rootEntry = &rootmenu; 604 rootEntry = &rootmenu;
@@ -622,6 +630,12 @@ int main(int ac, char **av)
622 fprintf(stderr, _("\n*** Error during update of the kernel configuration.\n\n")); 630 fprintf(stderr, _("\n*** Error during update of the kernel configuration.\n\n"));
623 return 1; 631 return 1;
624 } 632 }
633 } else if (input_mode == savedefconfig) {
634 if (conf_write_defconfig(defconfig_file)) {
635 fprintf(stderr, _("n*** Error while saving defconfig to: %s\n\n"),
636 defconfig_file);
637 return 1;
638 }
625 } else if (input_mode != listnewconfig) { 639 } else if (input_mode != listnewconfig) {
626 if (conf_write(NULL)) { 640 if (conf_write(NULL)) {
627 fprintf(stderr, _("\n*** Error during writing of the kernel configuration.\n\n")); 641 fprintf(stderr, _("\n*** Error during writing of the kernel configuration.\n\n"));
diff --git a/scripts/kconfig/confdata.c b/scripts/kconfig/confdata.c
index 583f6405f01d..f81f263b64f2 100644
--- a/scripts/kconfig/confdata.c
+++ b/scripts/kconfig/confdata.c
@@ -457,6 +457,82 @@ static void conf_write_symbol(struct symbol *sym, enum symbol_type type,
457 } 457 }
458} 458}
459 459
460/*
461 * Write out a minimal config.
462 * All values that has default values are skipped as this is redundant.
463 */
464int conf_write_defconfig(const char *filename)
465{
466 struct symbol *sym;
467 struct menu *menu;
468 FILE *out;
469
470 out = fopen(filename, "w");
471 if (!out)
472 return 1;
473
474 sym_clear_all_valid();
475
476 /* Traverse all menus to find all relevant symbols */
477 menu = rootmenu.list;
478
479 while (menu != NULL)
480 {
481 sym = menu->sym;
482 if (sym == NULL) {
483 if (!menu_is_visible(menu))
484 goto next_menu;
485 } else if (!sym_is_choice(sym)) {
486 sym_calc_value(sym);
487 if (!(sym->flags & SYMBOL_WRITE))
488 goto next_menu;
489 sym->flags &= ~SYMBOL_WRITE;
490 /* If we cannot change the symbol - skip */
491 if (!sym_is_changable(sym))
492 goto next_menu;
493 /* If symbol equals to default value - skip */
494 if (strcmp(sym_get_string_value(sym), sym_get_string_default(sym)) == 0)
495 goto next_menu;
496
497 /*
498 * If symbol is a choice value and equals to the
499 * default for a choice - skip.
500 * But only if value equal to "y".
501 */
502 if (sym_is_choice_value(sym)) {
503 struct symbol *cs;
504 struct symbol *ds;
505
506 cs = prop_get_symbol(sym_get_choice_prop(sym));
507 ds = sym_choice_default(cs);
508 if (sym == ds) {
509 if ((sym->type == S_BOOLEAN ||
510 sym->type == S_TRISTATE) &&
511 sym_get_tristate_value(sym) == yes)
512 goto next_menu;
513 }
514 }
515 conf_write_symbol(sym, sym->type, out, true);
516 }
517next_menu:
518 if (menu->list != NULL) {
519 menu = menu->list;
520 }
521 else if (menu->next != NULL) {
522 menu = menu->next;
523 } else {
524 while ((menu = menu->parent)) {
525 if (menu->next != NULL) {
526 menu = menu->next;
527 break;
528 }
529 }
530 }
531 }
532 fclose(out);
533 return 0;
534}
535
460int conf_write(const char *name) 536int conf_write(const char *name)
461{ 537{
462 FILE *out; 538 FILE *out;
diff --git a/scripts/kconfig/lkc.h b/scripts/kconfig/lkc.h
index 755b8190eb64..76db065ed72c 100644
--- a/scripts/kconfig/lkc.h
+++ b/scripts/kconfig/lkc.h
@@ -127,6 +127,7 @@ void sym_clear_all_valid(void);
127void sym_set_all_changed(void); 127void sym_set_all_changed(void);
128void sym_set_changed(struct symbol *sym); 128void sym_set_changed(struct symbol *sym);
129struct symbol *sym_choice_default(struct symbol *sym); 129struct symbol *sym_choice_default(struct symbol *sym);
130const char *sym_get_string_default(struct symbol *sym);
130struct symbol *sym_check_deps(struct symbol *sym); 131struct symbol *sym_check_deps(struct symbol *sym);
131struct property *prop_alloc(enum prop_type type, struct symbol *sym); 132struct property *prop_alloc(enum prop_type type, struct symbol *sym);
132struct symbol *prop_get_symbol(struct property *prop); 133struct symbol *prop_get_symbol(struct property *prop);
diff --git a/scripts/kconfig/lkc_proto.h b/scripts/kconfig/lkc_proto.h
index 7cadcad8233b..9a948c9ce44e 100644
--- a/scripts/kconfig/lkc_proto.h
+++ b/scripts/kconfig/lkc_proto.h
@@ -3,6 +3,7 @@
3P(conf_parse,void,(const char *name)); 3P(conf_parse,void,(const char *name));
4P(conf_read,int,(const char *name)); 4P(conf_read,int,(const char *name));
5P(conf_read_simple,int,(const char *name, int)); 5P(conf_read_simple,int,(const char *name, int));
6P(conf_write_defconfig,int,(const char *name));
6P(conf_write,int,(const char *name)); 7P(conf_write,int,(const char *name));
7P(conf_write_autoconf,int,(void)); 8P(conf_write_autoconf,int,(void));
8P(conf_get_changed,bool,(void)); 9P(conf_get_changed,bool,(void));
diff --git a/scripts/kconfig/symbol.c b/scripts/kconfig/symbol.c
index 0a013ab3ae27..e95718fea355 100644
--- a/scripts/kconfig/symbol.c
+++ b/scripts/kconfig/symbol.c
@@ -661,6 +661,80 @@ bool sym_set_string_value(struct symbol *sym, const char *newval)
661 return true; 661 return true;
662} 662}
663 663
664/*
665 * Find the default value associated to a symbol.
666 * For tristate symbol handle the modules=n case
667 * in which case "m" becomes "y".
668 * If the symbol does not have any default then fallback
669 * to the fixed default values.
670 */
671const char *sym_get_string_default(struct symbol *sym)
672{
673 struct property *prop;
674 struct symbol *ds;
675 const char *str;
676 tristate val;
677
678 sym_calc_visibility(sym);
679 sym_calc_value(modules_sym);
680 val = symbol_no.curr.tri;
681 str = symbol_empty.curr.val;
682
683 /* If symbol has a default value look it up */
684 prop = sym_get_default_prop(sym);
685 if (prop != NULL) {
686 switch (sym->type) {
687 case S_BOOLEAN:
688 case S_TRISTATE:
689 /* The visibility imay limit the value from yes => mod */
690 val = EXPR_AND(expr_calc_value(prop->expr), prop->visible.tri);
691 break;
692 default:
693 /*
694 * The following fails to handle the situation
695 * where a default value is further limited by
696 * the valid range.
697 */
698 ds = prop_get_symbol(prop);
699 if (ds != NULL) {
700 sym_calc_value(ds);
701 str = (const char *)ds->curr.val;
702 }
703 }
704 }
705
706 /* Handle select statements */
707 val = EXPR_OR(val, sym->rev_dep.tri);
708
709 /* transpose mod to yes if modules are not enabled */
710 if (val == mod)
711 if (!sym_is_choice_value(sym) && modules_sym->curr.tri == no)
712 val = yes;
713
714 /* transpose mod to yes if type is bool */
715 if (sym->type == S_BOOLEAN && val == mod)
716 val = yes;
717
718 switch (sym->type) {
719 case S_BOOLEAN:
720 case S_TRISTATE:
721 switch (val) {
722 case no: return "n";
723 case mod: return "m";
724 case yes: return "y";
725 }
726 case S_INT:
727 case S_HEX:
728 return str;
729 case S_STRING:
730 return str;
731 case S_OTHER:
732 case S_UNKNOWN:
733 break;
734 }
735 return "";
736}
737
664const char *sym_get_string_value(struct symbol *sym) 738const char *sym_get_string_value(struct symbol *sym)
665{ 739{
666 tristate val; 740 tristate val;