Print this page
eeprom


 283         if (output) {
 284                 len = strlen(output) - 1;
 285                 if (output[len] == '\n')
 286                         output[len] = '\0';
 287         }
 288 
 289         ret = pclose(ptr);
 290         if (ret == -1) {
 291                 eeprom_error(PCLOSE_FAIL, cmdline, strerror(errno));
 292                 return (-1);
 293         }
 294 
 295         if (WIFEXITED(ret)) {
 296                 return (WEXITSTATUS(ret));
 297         } else {
 298                 eeprom_error(EXEC_FAIL, cmdline, ret);
 299                 return (-1);
 300         }
 301 }
 302 
 303 #define BOOTADM_STR     "bootadm: "
 304 
 305 /*
 306  * bootadm starts all error messages with "bootadm: ".
 307  * Add a note so users don't get confused on how they ran bootadm.
 308  */
 309 static void
 310 output_error_msg(const char *msg)
 311 {
 312         size_t len = sizeof (BOOTADM_STR) - 1;
 313 
 314         if (strncmp(msg, BOOTADM_STR, len) == 0) {
 315                 eeprom_error("error returned from %s\n", msg);
 316         } else if (msg[0] != '\0') {
 317                 eeprom_error("%s\n", msg);
 318         }
 319 }
 320 
 321 static char *
 322 get_bootadm_value(char *name, const int quiet)
 323 {
 324         char *ptr, *ret_str, *end_ptr, *orig_ptr;
 325         char output[BUFSIZ];
 326         int is_console, is_kernel = 0;
 327         size_t len;
 328 
 329         is_console = (strcmp(name, "console") == 0);
 330 
 331         if (strcmp(name, "boot-file") == 0) {
 332                 is_kernel = 1;
 333                 ptr = "/sbin/bootadm set-menu kernel 2>&1";
 334         } else if (is_console || (strcmp(name, "boot-args") == 0)) {
 335                 ptr = "/sbin/bootadm set-menu args 2>&1";
 336         } else {
 337                 eeprom_error("Unknown value in get_bootadm_value: %s\n", name);
 338                 return (NULL);
 339         }
 340 
 341         if (exec_cmd(ptr, output, BUFSIZ) != 0) {
 342                 if (quiet == 0) {
 343                         output_error_msg(output);
 344                 }
 345                 return (NULL);
 346         }
 347 
 348         if (is_console) {
 349                 if ((ptr = strstr(output, "console=")) == NULL) {
 350                         return (NULL);
 351                 }
 352                 ptr += strlen("console=");
 353 
 354                 /*
 355                  * -B may have comma-separated values.  It may also be
 356                  * followed by other flags.
 357                  */


 400                          * Since we removed the console setting, we no
 401                          * longer need the initial "-B "
 402                          */
 403                         orig_ptr = output + 3;
 404                 } else {
 405                         orig_ptr = output;
 406                 }
 407 
 408                 ret_str = strdup(orig_ptr);
 409                 if (ret_str == NULL)
 410                         eeprom_error(NO_MEM, strlen(orig_ptr) + 1);
 411                 return (ret_str);
 412         }
 413 }
 414 
 415 /*
 416  * If quiet is 1, print nothing if there is no value.  If quiet is 0, print
 417  * a message.  Return 1 if the value is printed, 0 otherwise.
 418  */
 419 static int
 420 print_bootadm_value(char *name, const int quiet)
 421 {
 422         int rv = 0;
 423         char *value = get_bootadm_value(name, quiet);
 424 
 425         if ((value != NULL) && (value[0] != '\0')) {
 426                 (void) printf("%s=%s\n", name, value);
 427                 rv = 1;
 428         } else if (quiet == 0) {
 429                 (void) printf("%s: data not available.\n", name);
 430         }
 431 
 432         if (value != NULL)
 433                 free(value);
 434         return (rv);
 435 }
 436 
 437 static void
 438 print_var(char *name, eplist_t *list)
 439 {
 440         benv_ent_t *p;
 441         char *bootcmd;
 442 
 443         /*
 444          * The console property is kept in both menu.lst and bootenv.rc.  The
 445          * menu.lst value takes precedence.
 446          */
 447         if (strcmp(name, "console") == 0) {
 448                 if (print_bootadm_value(name, 1) == 0) {
 449                         if ((p = get_var(name, list)) != NULL) {
 450                                 (void) printf("%s=%s\n", name, p->val ?
 451                                     p->val : "");
 452                         } else {
 453                                 (void) printf("%s: data not available.\n",
 454                                     name);
 455                         }
 456                 }
 457         } else if (strcmp(name, "bootcmd") == 0) {
 458                 bootcmd = getbootcmd();
 459                 (void) printf("%s=%s\n", name, bootcmd ? bootcmd : "");
 460         } else if ((strcmp(name, "boot-file") == 0) ||
 461             (strcmp(name, "boot-args") == 0)) {
 462                 (void) print_bootadm_value(name, 0);
 463         } else if ((p = get_var(name, list)) == NULL) {
 464                 (void) printf("%s: data not available.\n", name);
 465         } else {
 466                 (void) printf("%s=%s\n", name, p->val ? p->val : "");
 467         }
 468 }
 469 
 470 static void
 471 print_vars(eplist_t *list)
 472 {
 473         eplist_t *e;
 474         benv_ent_t *p;
 475         int console_printed = 0;
 476 
 477         /*
 478          * The console property is kept both in menu.lst and bootenv.rc.
 479          * The menu.lst value takes precedence, so try printing that one
 480          * first.
 481          */
 482         console_printed = print_bootadm_value("console", 1);
 483 
 484         for (e = list->next; e != list; e = e->next) {
 485                 p = (benv_ent_t *)e->item;
 486                 if (p->name != NULL) {
 487                         if (((strcmp(p->name, "console") == 0) &&
 488                             (console_printed == 1)) ||
 489                             ((strcmp(p->name, "boot-file") == 0) ||
 490                             (strcmp(p->name, "boot-args") == 0))) {
 491                                 /* handle these separately */
 492                                 continue;
 493                         }
 494                         (void) printf("%s=%s\n", p->name, p->val ? p->val : "");
 495                 }
 496         }
 497         (void) print_bootadm_value("boot-file", 1);
 498         (void) print_bootadm_value("boot-args", 1);
 499 }
 500 
 501 /*
 502  * Write a string to a file, quoted appropriately.  We use single
 503  * quotes to prevent any variable expansion.  Of course, we backslash-quote
 504  * any single quotes or backslashes.
 505  */
 506 static void
 507 put_quoted(FILE *fp, char *val)
 508 {
 509         (void) putc('\'', fp);
 510         while (*val) {
 511                 switch (*val) {
 512                 case '\'':
 513                 case '\\':
 514                         (void) putc('\\', fp);
 515                         /* FALLTHROUGH */
 516                 default:
 517                         (void) putc(*val, fp);
 518                         break;
 519                 }
 520                 val++;
 521         }
 522         (void) putc('\'', fp);
 523 }
 524 
 525 static void
 526 set_bootadm_var(char *name, char *value)
 527 {
 528         char buf[BUFSIZ];
 529         char output[BUFSIZ] = "";
 530         char *console, *args;
 531         int is_console;
 532 
 533         if (verbose) {
 534                 (void) printf("old:");
 535                 (void) print_bootadm_value(name, 0);
 536         }
 537 
 538         /*
 539          * For security, we single-quote whatever we run on the command line,
 540          * and we don't allow single quotes in the string.
 541          */
 542         if (strchr(value, '\'') != NULL) {
 543                 eeprom_error("Single quotes are not allowed "
 544                     "in the %s property.\n", name);
 545                 return;
 546         }
 547 
 548         is_console = (strcmp(name, "console") == 0);
 549         if (strcmp(name, "boot-file") == 0) {
 550                 (void) snprintf(buf, BUFSIZ, "/sbin/bootadm set-menu "
 551                     "kernel='%s' 2>&1", value);
 552         } else if (is_console || (strcmp(name, "boot-args") == 0)) {
 553                 if (is_console) {
 554                         args = get_bootadm_value("boot-args", 1);
 555                         console = value;
 556                 } else {
 557                         args = value;
 558                         console = get_bootadm_value("console", 1);
 559                 }
 560                 if (((args == NULL) || (args[0] == '\0')) &&
 561                     ((console == NULL) || (console[0] == '\0'))) {
 562                         (void) snprintf(buf, BUFSIZ, "/sbin/bootadm set-menu "
 563                             "args= 2>&1");
 564                 } else if ((args == NULL) || (args[0] == '\0')) {
 565                         (void) snprintf(buf, BUFSIZ, "/sbin/bootadm "
 566                             "set-menu args='-B console=%s' 2>&1",
 567                             console);
 568                 } else if ((console == NULL) || (console[0] == '\0')) {
 569                         (void) snprintf(buf, BUFSIZ, "/sbin/bootadm "
 570                             "set-menu args='%s' 2>&1", args);
 571                 } else if (strncmp(args, "-B ", 3) != 0) {
 572                         (void) snprintf(buf, BUFSIZ, "/sbin/bootadm "
 573                             "set-menu args='-B console=%s %s' 2>&1",
 574                             console, args);
 575                 } else {
 576                         (void) snprintf(buf, BUFSIZ, "/sbin/bootadm "
 577                             "set-menu args='-B console=%s,%s' 2>&1",
 578                             console, args + 3);
 579                 }
 580         } else {
 581                 eeprom_error("Unknown value in set_bootadm_value: %s\n", name);
 582                 return;
 583         }
 584 
 585         if (exec_cmd(buf, output, BUFSIZ) != 0) {
 586                 output_error_msg(output);
 587                 return;
 588         }
 589 
 590         if (verbose) {
 591                 (void) printf("new:");
 592                 (void) print_bootadm_value(name, 0);
 593         }
 594 }
 595 
 596 /*
 597  * Returns 1 if bootenv.rc was modified, 0 otherwise.
 598  */
 599 static int
 600 set_var(char *name, char *val, eplist_t *list)
 601 {
 602         benv_ent_t *p;
 603         int old_verbose;
 604 
 605         if (strcmp(name, "bootcmd") == 0)
 606                 return (0);
 607 
 608         if ((strcmp(name, "boot-file") == 0) ||
 609             (strcmp(name, "boot-args") == 0)) {
 610                 set_bootadm_var(name, val);
 611                 return (0);
 612         }
 613 
 614         /*
 615          * The console property is kept in two places: menu.lst and bootenv.rc.
 616          * Update them both.  We clear verbose to prevent duplicate messages.
 617          */
 618         if (strcmp(name, "console") == 0) {
 619                 old_verbose = verbose;
 620                 verbose = 0;
 621                 set_bootadm_var(name, val);
 622                 verbose = old_verbose;
 623         }
 624 
 625         if (verbose) {
 626                 (void) printf("old:");
 627                 print_var(name, list);
 628         }
 629 
 630         if ((p = get_var(name, list)) != NULL) {
 631                 free(p->val);
 632                 p->val = strdup(val);
 633         } else
 634                 add_bent(list, NULL, "setprop", name, val);
 635 
 636         if (verbose) {
 637                 (void) printf("new:");
 638                 print_var(name, list);
 639         }
 640         return (1);
 641 }




 283         if (output) {
 284                 len = strlen(output) - 1;
 285                 if (output[len] == '\n')
 286                         output[len] = '\0';
 287         }
 288 
 289         ret = pclose(ptr);
 290         if (ret == -1) {
 291                 eeprom_error(PCLOSE_FAIL, cmdline, strerror(errno));
 292                 return (-1);
 293         }
 294 
 295         if (WIFEXITED(ret)) {
 296                 return (WEXITSTATUS(ret));
 297         } else {
 298                 eeprom_error(EXEC_FAIL, cmdline, ret);
 299                 return (-1);
 300         }
 301 }
 302 
 303 #define GRUBADM_STR     "grubadm: "
 304 
 305 /*
 306  * grubadm starts all error messages with "grubadm: ".
 307  * Add a note so users don't get confused on how they ran grubadm.
 308  */
 309 static void
 310 output_error_msg(const char *msg)
 311 {
 312         size_t len = sizeof (GRUBADM_STR) - 1;
 313 
 314         if (strncmp(msg, GRUBADM_STR, len) == 0) {
 315                 eeprom_error("error returned from %s\n", msg);
 316         } else if (msg[0] != '\0') {
 317                 eeprom_error("%s\n", msg);
 318         }
 319 }
 320 
 321 static char *
 322 get_grubadm_value(char *name, const int quiet)
 323 {
 324         char *ptr, *ret_str, *end_ptr, *orig_ptr;
 325         char output[BUFSIZ];
 326         int is_console, is_kernel = 0;
 327         size_t len;
 328 
 329         is_console = (strcmp(name, "console") == 0);
 330 
 331         if (strcmp(name, "boot-file") == 0) {
 332                 is_kernel = 1;
 333                 ptr = "/sbin/grubadm --number -1 --get-kernel 2>&1";
 334         } else if (is_console || (strcmp(name, "boot-args") == 0)) {
 335                 ptr = "/sbin/grubadm --number -1 --get-opts 2>&1";
 336         } else {
 337                 eeprom_error("Unknown value in get_grubadm_value: %s\n", name);
 338                 return (NULL);
 339         }
 340 
 341         if (exec_cmd(ptr, output, BUFSIZ) != 0) {
 342                 if (quiet == 0) {
 343                         output_error_msg(output);
 344                 }
 345                 return (NULL);
 346         }
 347 
 348         if (is_console) {
 349                 if ((ptr = strstr(output, "console=")) == NULL) {
 350                         return (NULL);
 351                 }
 352                 ptr += strlen("console=");
 353 
 354                 /*
 355                  * -B may have comma-separated values.  It may also be
 356                  * followed by other flags.
 357                  */


 400                          * Since we removed the console setting, we no
 401                          * longer need the initial "-B "
 402                          */
 403                         orig_ptr = output + 3;
 404                 } else {
 405                         orig_ptr = output;
 406                 }
 407 
 408                 ret_str = strdup(orig_ptr);
 409                 if (ret_str == NULL)
 410                         eeprom_error(NO_MEM, strlen(orig_ptr) + 1);
 411                 return (ret_str);
 412         }
 413 }
 414 
 415 /*
 416  * If quiet is 1, print nothing if there is no value.  If quiet is 0, print
 417  * a message.  Return 1 if the value is printed, 0 otherwise.
 418  */
 419 static int
 420 print_grubadm_value(char *name, const int quiet)
 421 {
 422         int rv = 0;
 423         char *value = get_grubadm_value(name, quiet);
 424 
 425         if ((value != NULL) && (value[0] != '\0')) {
 426                 (void) printf("%s=%s\n", name, value);
 427                 rv = 1;
 428         } else if (quiet == 0) {
 429                 (void) printf("%s: data not available.\n", name);
 430         }
 431 
 432         if (value != NULL)
 433                 free(value);
 434         return (rv);
 435 }
 436 
 437 static void
 438 print_var(char *name, eplist_t *list)
 439 {
 440         benv_ent_t *p;
 441         char *bootcmd;
 442 
 443         /*
 444          * The console property is kept in both menu.lst and bootenv.rc.  The
 445          * menu.lst value takes precedence.
 446          */
 447         if (strcmp(name, "console") == 0) {
 448                 if (print_grubadm_value(name, 1) == 0) {
 449                         if ((p = get_var(name, list)) != NULL) {
 450                                 (void) printf("%s=%s\n", name, p->val ?
 451                                     p->val : "");
 452                         } else {
 453                                 (void) printf("%s: data not available.\n",
 454                                     name);
 455                         }
 456                 }
 457         } else if (strcmp(name, "bootcmd") == 0) {
 458                 bootcmd = getbootcmd();
 459                 (void) printf("%s=%s\n", name, bootcmd ? bootcmd : "");
 460         } else if ((strcmp(name, "boot-file") == 0) ||
 461             (strcmp(name, "boot-args") == 0)) {
 462                 (void) print_grubadm_value(name, 0);
 463         } else if ((p = get_var(name, list)) == NULL) {
 464                 (void) printf("%s: data not available.\n", name);
 465         } else {
 466                 (void) printf("%s=%s\n", name, p->val ? p->val : "");
 467         }
 468 }
 469 
 470 static void
 471 print_vars(eplist_t *list)
 472 {
 473         eplist_t *e;
 474         benv_ent_t *p;
 475         int console_printed = 0;
 476 
 477         /*
 478          * The console property is kept both in menu.lst and bootenv.rc.
 479          * The menu.lst value takes precedence, so try printing that one
 480          * first.
 481          */
 482         console_printed = print_grubadm_value("console", 1);
 483 
 484         for (e = list->next; e != list; e = e->next) {
 485                 p = (benv_ent_t *)e->item;
 486                 if (p->name != NULL) {
 487                         if (((strcmp(p->name, "console") == 0) &&
 488                             (console_printed == 1)) ||
 489                             ((strcmp(p->name, "boot-file") == 0) ||
 490                             (strcmp(p->name, "boot-args") == 0))) {
 491                                 /* handle these separately */
 492                                 continue;
 493                         }
 494                         (void) printf("%s=%s\n", p->name, p->val ? p->val : "");
 495                 }
 496         }
 497         (void) print_grubadm_value("boot-file", 1);
 498         (void) print_grubadm_value("boot-args", 1);
 499 }
 500 
 501 /*
 502  * Write a string to a file, quoted appropriately.  We use single
 503  * quotes to prevent any variable expansion.  Of course, we backslash-quote
 504  * any single quotes or backslashes.
 505  */
 506 static void
 507 put_quoted(FILE *fp, char *val)
 508 {
 509         (void) putc('\'', fp);
 510         while (*val) {
 511                 switch (*val) {
 512                 case '\'':
 513                 case '\\':
 514                         (void) putc('\\', fp);
 515                         /* FALLTHROUGH */
 516                 default:
 517                         (void) putc(*val, fp);
 518                         break;
 519                 }
 520                 val++;
 521         }
 522         (void) putc('\'', fp);
 523 }
 524 
 525 static void
 526 set_grubadm_var(char *name, char *value)
 527 {
 528         char buf[BUFSIZ];
 529         char output[BUFSIZ] = "";
 530         char *console, *args;
 531         int is_console;
 532 
 533         if (verbose) {
 534                 (void) printf("old:");
 535                 (void) print_grubadm_value(name, 0);
 536         }
 537 
 538         /*
 539          * For security, we single-quote whatever we run on the command line,
 540          * and we don't allow single quotes in the string.
 541          */
 542         if (strchr(value, '\'') != NULL) {
 543                 eeprom_error("Single quotes are not allowed "
 544                     "in the %s property.\n", name);
 545                 return;
 546         }
 547 
 548         is_console = (strcmp(name, "console") == 0);
 549         if (strcmp(name, "boot-file") == 0) {
 550                 (void) snprintf(buf, BUFSIZ, "/sbin/grubadm --number -1 "
 551                     "--set-kernel '%s' 2>&1", value);
 552         } else if (is_console || (strcmp(name, "boot-args") == 0)) {
 553                 if (is_console) {
 554                         args = get_grubadm_value("boot-args", 1);
 555                         console = value;
 556                 } else {
 557                         args = value;
 558                         console = get_grubadm_value("console", 1);
 559                 }
 560                 if (((args == NULL) || (args[0] == '\0')) &&
 561                     ((console == NULL) || (console[0] == '\0'))) {
 562                         (void) snprintf(buf, BUFSIZ, "/sbin/grubadm --number -1 "
 563                             "--set-opts '-B $ZFS_BOOTFS' 2>&1");
 564                 } else if ((args == NULL) || (args[0] == '\0')) {
 565                         (void) snprintf(buf, BUFSIZ, "/sbin/grubadm --number -1 "
 566                             "--set-opts '-B console=%s' 2>&1",
 567                             console);
 568                 } else if ((console == NULL) || (console[0] == '\0')) {
 569                         (void) snprintf(buf, BUFSIZ, "/sbin/grubadm --number -1 "
 570                             "--set-opts '%s' 2>&1", args);
 571                 } else if (strncmp(args, "-B ", 3) != 0) {
 572                         (void) snprintf(buf, BUFSIZ, "/sbin/grubadm --number -1 "
 573                             "--set-opts '-B console=%s %s' 2>&1",
 574                             console, args);
 575                 } else {
 576                         (void) snprintf(buf, BUFSIZ, "/sbin/grubadm --number -1 "
 577                             "--set-opts '-B console=%s,%s' 2>&1",
 578                             console, args + 3);
 579                 }
 580         } else {
 581                 eeprom_error("Unknown value in set_grubadm_value: %s\n", name);
 582                 return;
 583         }
 584 
 585         if (exec_cmd(buf, output, BUFSIZ) != 0) {
 586                 output_error_msg(output);
 587                 return;
 588         }
 589 
 590         if (verbose) {
 591                 (void) printf("new:");
 592                 (void) print_grubadm_value(name, 0);
 593         }
 594 }
 595 
 596 /*
 597  * Returns 1 if bootenv.rc was modified, 0 otherwise.
 598  */
 599 static int
 600 set_var(char *name, char *val, eplist_t *list)
 601 {
 602         benv_ent_t *p;
 603         int old_verbose;
 604 
 605         if (strcmp(name, "bootcmd") == 0)
 606                 return (0);
 607 
 608         if ((strcmp(name, "boot-file") == 0) ||
 609             (strcmp(name, "boot-args") == 0)) {
 610                 set_grubadm_var(name, val);
 611                 return (0);
 612         }
 613 
 614         /*
 615          * The console property is kept in two places: menu.lst and bootenv.rc.
 616          * Update them both.  We clear verbose to prevent duplicate messages.
 617          */
 618         if (strcmp(name, "console") == 0) {
 619                 old_verbose = verbose;
 620                 verbose = 0;
 621                 set_grubadm_var(name, val);
 622                 verbose = old_verbose;
 623         }
 624 
 625         if (verbose) {
 626                 (void) printf("old:");
 627                 print_var(name, list);
 628         }
 629 
 630         if ((p = get_var(name, list)) != NULL) {
 631                 free(p->val);
 632                 p->val = strdup(val);
 633         } else
 634                 add_bent(list, NULL, "setprop", name, val);
 635 
 636         if (verbose) {
 637                 (void) printf("new:");
 638                 print_var(name, list);
 639         }
 640         return (1);
 641 }