coreboot-v2/util/kconfig/conf.c
<<
>>
Prefs
   1/*
   2 * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
   3 * Released under the terms of the GNU GPL v2.0.
   4 */
   5
   6#include <locale.h>
   7#include <ctype.h>
   8#include <stdio.h>
   9#include <stdlib.h>
  10#include <string.h>
  11#include <time.h>
  12#include <unistd.h>
  13#include <sys/stat.h>
  14
  15#define LKC_DIRECT_LINK
  16#include "lkc.h"
  17
  18static void conf(struct menu *menu);
  19static void check_conf(struct menu *menu);
  20
  21enum {
  22        ask_all,
  23        ask_new,
  24        ask_silent,
  25        set_default,
  26        set_yes,
  27        set_mod,
  28        set_no,
  29        set_random
  30} input_mode = ask_all;
  31char *defconfig_file;
  32
  33static int indent = 1;
  34static int valid_stdin = 1;
  35static int conf_cnt;
  36static char line[128];
  37static struct menu *rootEntry;
  38
  39static char nohelp_text[] = N_("Sorry, no help available for this option yet.\n");
  40
  41static const char *get_help(struct menu *menu)
  42{
  43        if (menu_has_help(menu))
  44                return _(menu_get_help(menu));
  45        else
  46                return nohelp_text;
  47}
  48
  49static void strip(char *str)
  50{
  51        char *p = str;
  52        int l;
  53
  54        while ((isspace(*p)))
  55                p++;
  56        l = strlen(p);
  57        if (p != str)
  58                memmove(str, p, l + 1);
  59        if (!l)
  60                return;
  61        p = str + l - 1;
  62        while ((isspace(*p)))
  63                *p-- = 0;
  64}
  65
  66static void check_stdin(void)
  67{
  68        if (!valid_stdin && input_mode == ask_silent) {
  69                printf(_("aborted!\n\n"));
  70                printf(_("Console input/output is redirected. "));
  71                printf(_("Run 'make oldconfig' to update configuration.\n\n"));
  72                exit(1);
  73        }
  74}
  75
  76static int conf_askvalue(struct symbol *sym, const char *def)
  77{
  78        enum symbol_type type = sym_get_type(sym);
  79        tristate val;
  80
  81        if (!sym_has_value(sym))
  82                printf(_("(NEW) "));
  83
  84        line[0] = '\n';
  85        line[1] = 0;
  86
  87        if (!sym_is_changable(sym)) {
  88                printf("%s\n", def);
  89                line[0] = '\n';
  90                line[1] = 0;
  91                return 0;
  92        }
  93
  94        switch (input_mode) {
  95        case set_no:
  96        case set_mod:
  97        case set_yes:
  98        case set_random:
  99                if (sym_has_value(sym)) {
 100                        printf("%s\n", def);
 101                        return 0;
 102                }
 103                break;
 104        case ask_new:
 105        case ask_silent:
 106                if (sym_has_value(sym)) {
 107                        printf("%s\n", def);
 108                        return 0;
 109                }
 110                check_stdin();
 111        case ask_all:
 112                fflush(stdout);
 113                fgets(line, 128, stdin);
 114                return 1;
 115        case set_default:
 116                printf("%s\n", def);
 117                return 1;
 118        default:
 119                break;
 120        }
 121
 122        switch (type) {
 123        case S_INT:
 124        case S_HEX:
 125        case S_STRING:
 126                printf("%s\n", def);
 127                return 1;
 128        default:
 129                ;
 130        }
 131        switch (input_mode) {
 132        case set_yes:
 133                if (sym_tristate_within_range(sym, yes)) {
 134                        line[0] = 'y';
 135                        line[1] = '\n';
 136                        line[2] = 0;
 137                        break;
 138                }
 139        case set_mod:
 140                if (type == S_TRISTATE) {
 141                        if (sym_tristate_within_range(sym, mod)) {
 142                                line[0] = 'm';
 143                                line[1] = '\n';
 144                                line[2] = 0;
 145                                break;
 146                        }
 147                } else {
 148                        if (sym_tristate_within_range(sym, yes)) {
 149                                line[0] = 'y';
 150                                line[1] = '\n';
 151                                line[2] = 0;
 152                                break;
 153                        }
 154                }
 155        case set_no:
 156                if (sym_tristate_within_range(sym, no)) {
 157                        line[0] = 'n';
 158                        line[1] = '\n';
 159                        line[2] = 0;
 160                        break;
 161                }
 162        case set_random:
 163                do {
 164                        val = (tristate)(rand() % 3);
 165                } while (!sym_tristate_within_range(sym, val));
 166                switch (val) {
 167                case no: line[0] = 'n'; break;
 168                case mod: line[0] = 'm'; break;
 169                case yes: line[0] = 'y'; break;
 170                }
 171                line[1] = '\n';
 172                line[2] = 0;
 173                break;
 174        default:
 175                break;
 176        }
 177        printf("%s", line);
 178        return 1;
 179}
 180
 181int conf_string(struct menu *menu)
 182{
 183        struct symbol *sym = menu->sym;
 184        const char *def;
 185
 186        while (1) {
 187                printf("%*s%s ", indent - 1, "", _(menu->prompt->text));
 188                printf("(%s) ", sym->name);
 189                def = sym_get_string_value(sym);
 190                if (sym_get_string_value(sym))
 191                        printf("[%s] ", def);
 192                if (!conf_askvalue(sym, def))
 193                        return 0;
 194                switch (line[0]) {
 195                case '\n':
 196                        break;
 197                case '?':
 198                        /* print help */
 199                        if (line[1] == '\n') {
 200                                printf("\n%s\n", get_help(menu));
 201                                def = NULL;
 202                                break;
 203                        }
 204                default:
 205                        line[strlen(line)-1] = 0;
 206                        def = line;
 207                }
 208                if (def && sym_set_string_value(sym, def))
 209                        return 0;
 210        }
 211}
 212
 213static int conf_sym(struct menu *menu)
 214{
 215        struct symbol *sym = menu->sym;
 216        int type;
 217        tristate oldval, newval;
 218
 219        while (1) {
 220                printf("%*s%s ", indent - 1, "", _(menu->prompt->text));
 221                if (sym->name)
 222                        printf("(%s) ", sym->name);
 223                type = sym_get_type(sym);
 224                putchar('[');
 225                oldval = sym_get_tristate_value(sym);
 226                switch (oldval) {
 227                case no:
 228                        putchar('N');
 229                        break;
 230                case mod:
 231                        putchar('M');
 232                        break;
 233                case yes:
 234                        putchar('Y');
 235                        break;
 236                }
 237                if (oldval != no && sym_tristate_within_range(sym, no))
 238                        printf("/n");
 239                if (oldval != mod && sym_tristate_within_range(sym, mod))
 240                        printf("/m");
 241                if (oldval != yes && sym_tristate_within_range(sym, yes))
 242                        printf("/y");
 243                if (menu_has_help(menu))
 244                        printf("/?");
 245                printf("] ");
 246                if (!conf_askvalue(sym, sym_get_string_value(sym)))
 247                        return 0;
 248                strip(line);
 249
 250                switch (line[0]) {
 251                case 'n':
 252                case 'N':
 253                        newval = no;
 254                        if (!line[1] || !strcmp(&line[1], "o"))
 255                                break;
 256                        continue;
 257                case 'm':
 258                case 'M':
 259                        newval = mod;
 260                        if (!line[1])
 261                                break;
 262                        continue;
 263                case 'y':
 264                case 'Y':
 265                        newval = yes;
 266                        if (!line[1] || !strcmp(&line[1], "es"))
 267                                break;
 268                        continue;
 269                case 0:
 270                        newval = oldval;
 271                        break;
 272                case '?':
 273                        goto help;
 274                default:
 275                        continue;
 276                }
 277                if (sym_set_tristate_value(sym, newval))
 278                        return 0;
 279help:
 280                printf("\n%s\n", get_help(menu));
 281        }
 282}
 283
 284static int conf_choice(struct menu *menu)
 285{
 286        struct symbol *sym, *def_sym;
 287        struct menu *child;
 288        int type;
 289        bool is_new;
 290
 291        sym = menu->sym;
 292        type = sym_get_type(sym);
 293        is_new = !sym_has_value(sym);
 294        if (sym_is_changable(sym)) {
 295                conf_sym(menu);
 296                sym_calc_value(sym);
 297                switch (sym_get_tristate_value(sym)) {
 298                case no:
 299                        return 1;
 300                case mod:
 301                        return 0;
 302                case yes:
 303                        break;
 304                }
 305        } else {
 306                switch (sym_get_tristate_value(sym)) {
 307                case no:
 308                        return 1;
 309                case mod:
 310                        printf("%*s%s\n", indent - 1, "", _(menu_get_prompt(menu)));
 311                        return 0;
 312                case yes:
 313                        break;
 314                }
 315        }
 316
 317        while (1) {
 318                int cnt, def;
 319
 320                printf("%*s%s\n", indent - 1, "", _(menu_get_prompt(menu)));
 321                def_sym = sym_get_choice_value(sym);
 322                cnt = def = 0;
 323                line[0] = 0;
 324                for (child = menu->list; child; child = child->next) {
 325                        if (!menu_is_visible(child))
 326                                continue;
 327                        if (!child->sym) {
 328                                printf("%*c %s\n", indent, '*', _(menu_get_prompt(child)));
 329                                continue;
 330                        }
 331                        cnt++;
 332                        if (child->sym == def_sym) {
 333                                def = cnt;
 334                                printf("%*c", indent, '>');
 335                        } else
 336                                printf("%*c", indent, ' ');
 337                        printf(" %d. %s", cnt, _(menu_get_prompt(child)));
 338                        if (child->sym->name)
 339                                printf(" (%s)", child->sym->name);
 340                        if (!sym_has_value(child->sym))
 341                                printf(_(" (NEW)"));
 342                        printf("\n");
 343                }
 344                printf(_("%*schoice"), indent - 1, "");
 345                if (cnt == 1) {
 346                        printf("[1]: 1\n");
 347                        goto conf_childs;
 348                }
 349                printf("[1-%d", cnt);
 350                if (menu_has_help(menu))
 351                        printf("?");
 352                printf("]: ");
 353                switch (input_mode) {
 354                case ask_new:
 355                case ask_silent:
 356                        if (!is_new) {
 357                                cnt = def;
 358                                printf("%d\n", cnt);
 359                                break;
 360                        }
 361                        check_stdin();
 362                case ask_all:
 363                        fflush(stdout);
 364                        fgets(line, 128, stdin);
 365                        strip(line);
 366                        if (line[0] == '?') {
 367                                printf("\n%s\n", get_help(menu));
 368                                continue;
 369                        }
 370                        if (!line[0])
 371                                cnt = def;
 372                        else if (isdigit(line[0]))
 373                                cnt = atoi(line);
 374                        else
 375                                continue;
 376                        break;
 377                case set_random:
 378                        if (is_new)
 379                                def = (rand() % cnt) + 1;
 380                case set_default:
 381                case set_yes:
 382                case set_mod:
 383                case set_no:
 384                        cnt = def;
 385                        printf("%d\n", cnt);
 386                        break;
 387                }
 388
 389        conf_childs:
 390                for (child = menu->list; child; child = child->next) {
 391                        if (!child->sym || !menu_is_visible(child))
 392                                continue;
 393                        if (!--cnt)
 394                                break;
 395                }
 396                if (!child)
 397                        continue;
 398                if (line[strlen(line) - 1] == '?') {
 399                        printf("\n%s\n", get_help(child));
 400                        continue;
 401                }
 402                sym_set_choice_value(sym, child->sym);
 403                for (child = child->list; child; child = child->next) {
 404                        indent += 2;
 405                        conf(child);
 406                        indent -= 2;
 407                }
 408                return 1;
 409        }
 410}
 411
 412static void conf(struct menu *menu)
 413{
 414        struct symbol *sym;
 415        struct property *prop;
 416        struct menu *child;
 417
 418        if (!menu_is_visible(menu))
 419                return;
 420
 421        sym = menu->sym;
 422        prop = menu->prompt;
 423        if (prop) {
 424                const char *prompt;
 425
 426                switch (prop->type) {
 427                case P_MENU:
 428                        if (input_mode == ask_silent && rootEntry != menu) {
 429                                check_conf(menu);
 430                                return;
 431                        }
 432                case P_COMMENT:
 433                        prompt = menu_get_prompt(menu);
 434                        if (prompt)
 435                                printf("%*c\n%*c %s\n%*c\n",
 436                                        indent, '*',
 437                                        indent, '*', _(prompt),
 438                                        indent, '*');
 439                default:
 440                        ;
 441                }
 442        }
 443
 444        if (!sym)
 445                goto conf_childs;
 446
 447        if (sym_is_choice(sym)) {
 448                conf_choice(menu);
 449                if (sym->curr.tri != mod)
 450                        return;
 451                goto conf_childs;
 452        }
 453
 454        switch (sym->type) {
 455        case S_INT:
 456        case S_HEX:
 457        case S_STRING:
 458                conf_string(menu);
 459                break;
 460        default:
 461                conf_sym(menu);
 462                break;
 463        }
 464
 465conf_childs:
 466        if (sym)
 467                indent += 2;
 468        for (child = menu->list; child; child = child->next)
 469                conf(child);
 470        if (sym)
 471                indent -= 2;
 472}
 473
 474static void check_conf(struct menu *menu)
 475{
 476        struct symbol *sym;
 477        struct menu *child;
 478
 479        if (!menu_is_visible(menu))
 480                return;
 481
 482        sym = menu->sym;
 483        if (sym && !sym_has_value(sym)) {
 484                if (sym_is_changable(sym) ||
 485                    (sym_is_choice(sym) && sym_get_tristate_value(sym) == yes)) {
 486                        if (!conf_cnt++)
 487                                printf(_("*\n* Restart config...\n*\n"));
 488                        rootEntry = menu_get_parent_menu(menu);
 489                        conf(rootEntry);
 490                }
 491        }
 492
 493        for (child = menu->list; child; child = child->next)
 494                check_conf(child);
 495}
 496
 497int main(int ac, char **av)
 498{
 499        int opt;
 500        const char *name;
 501        struct stat tmpstat;
 502
 503        setlocale(LC_ALL, "");
 504        bindtextdomain(PACKAGE, LOCALEDIR);
 505        textdomain(PACKAGE);
 506
 507        while ((opt = getopt(ac, av, "osdD:nmyrh")) != -1) {
 508                switch (opt) {
 509                case 'o':
 510                        input_mode = ask_new;
 511                        break;
 512                case 's':
 513                        input_mode = ask_silent;
 514                        valid_stdin = isatty(0) && isatty(1) && isatty(2);
 515                        break;
 516                case 'd':
 517                        input_mode = set_default;
 518                        break;
 519                case 'D':
 520                        input_mode = set_default;
 521                        defconfig_file = optarg;
 522                        break;
 523                case 'n':
 524                        input_mode = set_no;
 525                        break;
 526                case 'm':
 527                        input_mode = set_mod;
 528                        break;
 529                case 'y':
 530                        input_mode = set_yes;
 531                        break;
 532                case 'r':
 533                        input_mode = set_random;
 534                        srand(time(NULL));
 535                        break;
 536                case 'h':
 537                        printf(_("See README for usage info\n"));
 538                        exit(0);
 539                        break;
 540                default:
 541                        fprintf(stderr, _("See README for usage info\n"));
 542                        exit(1);
 543                }
 544        }
 545        if (ac == optind) {
 546                printf(_("%s: Kconfig file missing\n"), av[0]);
 547                exit(1);
 548        }
 549        name = av[optind];
 550        conf_parse(name);
 551        //zconfdump(stdout);
 552        switch (input_mode) {
 553        case set_default:
 554                if (!defconfig_file)
 555                        defconfig_file = conf_get_default_confname();
 556                if (conf_read(defconfig_file)) {
 557                        printf(_("***\n"
 558                                "*** Can't find default configuration \"%s\"!\n"
 559                                "***\n"), defconfig_file);
 560                        exit(1);
 561                }
 562                break;
 563        case ask_silent:
 564                if (stat(".config", &tmpstat)) {
 565                        printf(_("***\n"
 566                                "*** You have not yet configured coreboot!\n"
 567                                "*** (missing .config file)\n"
 568                                "***\n"
 569                                "*** Please run some configurator (e.g. \"make oldconfig\" or\n"
 570                                "*** \"make menuconfig\" or \"make xconfig\").\n"
 571                                "***\n"));
 572                        exit(1);
 573                }
 574        case ask_all:
 575        case ask_new:
 576                conf_read(NULL);
 577                break;
 578        case set_no:
 579        case set_mod:
 580        case set_yes:
 581        case set_random:
 582                name = getenv("KCONFIG_ALLCONFIG");
 583                if (name && !stat(name, &tmpstat)) {
 584                        conf_read_simple(name, S_DEF_USER);
 585                        break;
 586                }
 587                switch (input_mode) {
 588                case set_no:     name = "allno.config"; break;
 589                case set_mod:    name = "allmod.config"; break;
 590                case set_yes:    name = "allyes.config"; break;
 591                case set_random: name = "allrandom.config"; break;
 592                default: break;
 593                }
 594                if (!stat(name, &tmpstat))
 595                        conf_read_simple(name, S_DEF_USER);
 596                else if (!stat("all.config", &tmpstat))
 597                        conf_read_simple("all.config", S_DEF_USER);
 598                break;
 599        default:
 600                break;
 601        }
 602
 603        if (input_mode != ask_silent) {
 604                rootEntry = &rootmenu;
 605                conf(&rootmenu);
 606                if (input_mode == ask_all) {
 607                        input_mode = ask_silent;
 608                        valid_stdin = 1;
 609                }
 610        } else if (conf_get_changed()) {
 611                name = getenv("KCONFIG_NOSILENTUPDATE");
 612                if (name && *name) {
 613                        fprintf(stderr, _("\n*** coreboot configuration requires explicit update.\n\n"));
 614                        return 1;
 615                }
 616        } else
 617                goto skip_check;
 618
 619        do {
 620                conf_cnt = 0;
 621                check_conf(&rootmenu);
 622        } while (conf_cnt);
 623        if (conf_write(NULL)) {
 624                fprintf(stderr, _("\n*** Error during writing of the configuration.\n\n"));
 625                return 1;
 626        }
 627        if (conf_write_autoconf()) {
 628                fprintf(stderr, _("\n*** Error during writing of the configuration.\n\n"));
 629                return 1;
 630        }
 631skip_check:
 632        if (input_mode == ask_silent && conf_write_autoconf()) {
 633                fprintf(stderr, _("\n*** Error during writing of the configuration.\n\n"));
 634                return 1;
 635        }
 636
 637        return 0;
 638}
 639
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.