Print this page
    
9250 remove xpv related code from bootadm
    
      
        | Split | Close | 
      | Expand all | 
      | Collapse all | 
    
    
          --- old/usr/src/cmd/boot/bootadm/bootadm_upgrade.c
          +++ new/usr/src/cmd/boot/bootadm/bootadm_upgrade.c
   1    1  /*
   2    2   * CDDL HEADER START
   3    3   *
   4    4   * The contents of this file are subject to the terms of the
   5    5   * Common Development and Distribution License (the "License").
   6    6   * You may not use this file except in compliance with the License.
   7    7   *
   8    8   * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9    9   * or http://www.opensolaris.org/os/licensing.
  10   10   * See the License for the specific language governing permissions
  11   11   * and limitations under the License.
  12   12   *
  13   13   * When distributing Covered Code, include this CDDL HEADER in each
  14   14   * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15   15   * If applicable, add the following below this CDDL HEADER, with the
  16   16   * fields enclosed by brackets "[]" replaced with your own identifying
  17   17   * information: Portions Copyright [yyyy] [name of copyright owner]
  18   18   *
  19   19   * CDDL HEADER END
  20   20   */
  21   21  /*
  22   22   * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  23   23   * Use is subject to license terms.
  24   24   * Copyright 2017 Toomas Soome <tsoome@me.com>
  25   25   */
  26   26  
  27   27  #include <stdio.h>
  28   28  #include <errno.h>
  29   29  #include <stdlib.h>
  30   30  #include <string.h>
  31   31  #include <unistd.h>
  32   32  #include <sys/types.h>
  33   33  #include <sys/stat.h>
  34   34  #include <limits.h>
  
    | ↓ open down ↓ | 34 lines elided | ↑ open up ↑ | 
  35   35  #include <fcntl.h>
  36   36  #include <strings.h>
  37   37  
  38   38  #include <sys/mman.h>
  39   39  #include <sys/elf.h>
  40   40  #include <sys/multiboot.h>
  41   41  
  42   42  #include "bootadm.h"
  43   43  
  44   44  direct_or_multi_t bam_direct = BAM_DIRECT_NOT_SET;
  45      -hv_t bam_is_hv = BAM_HV_UNKNOWN;
  46   45  findroot_t bam_is_findroot = BAM_FINDROOT_UNKNOWN;
  47   46  
  48   47  static void
  49   48  get_findroot_cap(const char *osroot)
  50   49  {
  51   50          FILE            *fp;
  52   51          char            path[PATH_MAX];
  53   52          char            buf[BAM_MAXLINE];
  54   53          struct stat     sb;
  55   54          int             dboot;
  56   55          int             error;
  57   56          int             ret;
  58   57          const char      *fcn = "get_findroot_cap()";
  59   58  
  60   59          (void) snprintf(path, sizeof (path), "%s/%s",
  61   60              osroot, "boot/grub/capability");
  62   61  
  63   62          if (stat(path, &sb) == -1) {
  64   63                  bam_is_findroot = BAM_FINDROOT_ABSENT;
  65   64                  BAM_DPRINTF(("%s: findroot capability absent\n", fcn));
  66   65                  return;
  67   66          }
  68   67  
  69   68          fp = fopen(path, "r");
  70   69          error = errno;
  71   70          INJECT_ERROR1("GET_CAP_FINDROOT_FOPEN", fp = NULL);
  72   71          if (fp == NULL) {
  73   72                  bam_error(_("failed to open file: %s: %s\n"), path,
  74   73                      strerror(error));
  75   74                  return;
  76   75          }
  77   76  
  78   77          dboot = 0;
  79   78          while (s_fgets(buf, sizeof (buf), fp) != NULL) {
  80   79                  if (strcmp(buf, "findroot") == 0) {
  81   80                          BAM_DPRINTF(("%s: findroot capability present\n", fcn));
  82   81                          bam_is_findroot = BAM_FINDROOT_PRESENT;
  83   82                  }
  84   83                  if (strcmp(buf, "dboot") == 0) {
  85   84                          BAM_DPRINTF(("%s: dboot capability present\n", fcn));
  86   85                          dboot = 1;
  87   86                  }
  88   87          }
  89   88  
  90   89          assert(dboot);
  91   90  
  92   91          if (bam_is_findroot == BAM_FINDROOT_UNKNOWN) {
  93   92                  bam_is_findroot = BAM_FINDROOT_ABSENT;
  94   93                  BAM_DPRINTF(("%s: findroot capability absent\n", fcn));
  95   94          }
  96   95  
  97   96          ret = fclose(fp);
  98   97          error = errno;
  99   98          INJECT_ERROR1("GET_CAP_FINDROOT_FCLOSE", ret = 1);
 100   99          if (ret != 0) {
 101  100                  bam_error(_("failed to close file: %s: %s\n"),
 102  101                      path, strerror(error));
 103  102          }
 104  103  }
 105  104  
 106  105  error_t
 107  106  get_boot_cap(const char *osroot)
 108  107  {
 109  108          char            fname[PATH_MAX];
 110  109          char            *image;
 111  110          uchar_t         *ident;
 112  111          uchar_t         class;
 113  112          int             fd;
 114  113          int             m;
 115  114          multiboot_header_t *mbh;
 116  115          struct stat     sb;
 117  116          int             error;
 118  117          const char      *fcn = "get_boot_cap()";
 119  118  
 120  119          if (is_sparc()) {
 121  120                  /* there is no non dboot sparc new-boot */
 122  121                  bam_direct = BAM_DIRECT_DBOOT;
 123  122                  BAM_DPRINTF(("%s: is sparc - always DBOOT\n", fcn));
 124  123                  return (BAM_SUCCESS);
 125  124          }
 126  125  
 127  126          /*
 128  127           * The install media can support both 64 and 32 bit boot
 129  128           * by using boot archive as ramdisk image. However, to save
 130  129           * the memory, the ramdisk may only have either 32 or 64
 131  130           * bit kernel files. To avoid error message about missing unix,
 132  131           * we should try both variants here and only complain if neither
 133  132           * is found. Since the 64-bit systems are more common, we start
 134  133           * from amd64.
 135  134           */
 136  135          class = ELFCLASS64;
 137  136          (void) snprintf(fname, PATH_MAX, "%s/%s", osroot,
 138  137              "platform/i86pc/kernel/amd64/unix");
 139  138          fd = open(fname, O_RDONLY);
 140  139          if (fd < 0) {
 141  140                  class = ELFCLASS32;
 142  141                  (void) snprintf(fname, PATH_MAX, "%s/%s", osroot,
 143  142                      "platform/i86pc/kernel/unix");
 144  143                  fd = open(fname, O_RDONLY);
 145  144          }
 146  145          error = errno;
 147  146          INJECT_ERROR1("GET_CAP_UNIX_OPEN", fd = -1);
 148  147          if (fd < 0) {
 149  148                  bam_error(_("failed to open file: %s: %s\n"), fname,
 150  149                      strerror(error));
 151  150                  return (BAM_ERROR);
 152  151          }
 153  152  
 154  153          /*
 155  154           * Verify that this is a sane unix at least 8192 bytes in length
 156  155           */
 157  156          if (fstat(fd, &sb) == -1 || sb.st_size < 8192) {
 158  157                  (void) close(fd);
 159  158                  bam_error(_("invalid or corrupted binary: %s\n"), fname);
 160  159                  return (BAM_ERROR);
 161  160          }
 162  161  
 163  162          /*
 164  163           * mmap the first 8K
 165  164           */
 166  165          image = mmap(NULL, 8192, PROT_READ, MAP_SHARED, fd, 0);
 167  166          error = errno;
 168  167          INJECT_ERROR1("GET_CAP_MMAP", image = MAP_FAILED);
 169  168          if (image == MAP_FAILED) {
 170  169                  bam_error(_("failed to mmap file: %s: %s\n"), fname,
 171  170                      strerror(error));
 172  171                  return (BAM_ERROR);
 173  172          }
 174  173  
 175  174          ident = (uchar_t *)image;
 176  175          if (ident[EI_MAG0] != ELFMAG0 || ident[EI_MAG1] != ELFMAG1 ||
 177  176              ident[EI_MAG2] != ELFMAG2 || ident[EI_MAG3] != ELFMAG3) {
 178  177                  bam_error(_("%s is not an ELF file.\n"), fname);
 179  178                  return (BAM_ERROR);
 180  179          }
 181  180          if (ident[EI_CLASS] != class) {
 182  181                  bam_error(_("%s is wrong ELF class 0x%x\n"), fname,
 183  182                      ident[EI_CLASS]);
 184  183                  return (BAM_ERROR);
 185  184          }
 186  185  
 187  186          /*
 188  187           * The GRUB multiboot header must be 32-bit aligned and completely
 189  188           * contained in the 1st 8K of the file.  If the unix binary has
 190  189           * a multiboot header, then it is a 'dboot' kernel.  Otherwise,
 191  190           * this kernel must be booted via multiboot -- we call this a
 192  191           * 'multiboot' kernel.
 193  192           */
 194  193          bam_direct = BAM_DIRECT_MULTIBOOT;
 195  194          for (m = 0; m < 8192 - sizeof (multiboot_header_t); m += 4) {
 196  195                  mbh = (void *)(image + m);
  
    | ↓ open down ↓ | 141 lines elided | ↑ open up ↑ | 
 197  196                  if (mbh->magic == MB_HEADER_MAGIC) {
 198  197                          BAM_DPRINTF(("%s: is DBOOT unix\n", fcn));
 199  198                          bam_direct = BAM_DIRECT_DBOOT;
 200  199                          break;
 201  200                  }
 202  201          }
 203  202          (void) munmap(image, 8192);
 204  203          (void) close(fd);
 205  204  
 206  205          INJECT_ERROR1("GET_CAP_MULTIBOOT", bam_direct = BAM_DIRECT_MULTIBOOT);
 207      -        if (bam_direct == BAM_DIRECT_DBOOT) {
 208      -                if (bam_is_hv == BAM_HV_PRESENT) {
 209      -                        BAM_DPRINTF(("%s: is xVM system\n", fcn));
 210      -                } else {
 211      -                        BAM_DPRINTF(("%s: is *NOT* xVM system\n", fcn));
 212      -                }
 213      -        } else {
      206 +        if (bam_direct != BAM_DIRECT_DBOOT) {
 214  207                  BAM_DPRINTF(("%s: is MULTIBOOT unix\n", fcn));
 215  208          }
 216  209  
 217  210          /* Not a fatal error if this fails */
 218  211          get_findroot_cap(osroot);
 219  212  
 220  213          BAM_DPRINTF(("%s: returning SUCCESS\n", fcn));
 221  214          return (BAM_SUCCESS);
 222  215  }
 223  216  
 224  217  #define INST_RELEASE    "var/sadm/system/admin/INST_RELEASE"
 225  218  
 226  219  /*
 227  220   * Return true if root has been bfu'ed.  bfu will blow away
 228  221   * var/sadm/system/admin/INST_RELEASE, so if it's still there, we can
 229  222   * assume the system has not been bfu'ed.
 230  223   */
 231  224  static int
 232  225  is_bfu_system(const char *root)
 233  226  {
 234  227          static int              is_bfu = -1;
 235  228          char                    path[PATH_MAX];
 236  229          struct stat             sb;
 237  230          const char              *fcn = "is_bfu_system()";
 238  231  
 239  232          if (is_bfu != -1) {
 240  233                  BAM_DPRINTF(("%s: already done bfu test. bfu is %s present\n",
 241  234                      fcn, is_bfu ? "" : "NOT"));
 242  235                  return (is_bfu);
 243  236          }
 244  237  
 245  238          (void) snprintf(path, sizeof (path), "%s/%s", root, INST_RELEASE);
 246  239          if (stat(path, &sb) != 0) {
 247  240                  is_bfu = 1;
 248  241                  BAM_DPRINTF(("%s: returning SUCCESS\n", fcn));
 249  242          } else {
 250  243                  is_bfu = 0;
 251  244                  BAM_DPRINTF(("%s: returning FAILURE\n", fcn));
 252  245          }
 253  246          return (is_bfu);
 254  247  }
 255  248  
 256  249  #define MENU_URL(root)  (is_bfu_system(root) ?          \
 257  250          "http://illumos.org/msg/SUNOS-8000-CF" :        \
 258  251          "http://illumos.org/msg/SUNOS-8000-AK")
 259  252  
 260  253  /*
 261  254   * Simply allocate a new line and copy in cmd + sep + arg
 262  255   */
 263  256  void
 264  257  update_line(line_t *linep)
 265  258  {
 266  259          size_t          size;
 267  260          const char      *fcn = "update_line()";
 268  261  
 269  262          BAM_DPRINTF(("%s: line before update: %s\n", fcn, linep->line));
 270  263          free(linep->line);
 271  264          size = strlen(linep->cmd) + strlen(linep->sep) + strlen(linep->arg) + 1;
 272  265          linep->line = s_calloc(1, size);
 273  266          (void) snprintf(linep->line, size, "%s%s%s", linep->cmd, linep->sep,
 274  267              linep->arg);
 275  268          BAM_DPRINTF(("%s: line after update: %s\n", fcn, linep->line));
 276  269  }
 277  270  
 278  271  static char *
 279  272  skip_wspace(char *ptr)
 280  273  {
 281  274          const char              *fcn = "skip_wspace()";
 282  275  
 283  276          INJECT_ERROR1("SKIP_WSPACE", ptr = NULL);
 284  277          if (ptr == NULL) {
 285  278                  BAM_DPRINTF(("%s: NULL ptr\n", fcn));
 286  279                  return (NULL);
 287  280          }
 288  281  
 289  282          BAM_DPRINTF(("%s: ptr on entry: %s\n", fcn, ptr));
 290  283          for (; *ptr != '\0'; ptr++) {
 291  284                  if ((*ptr != ' ') && (*ptr != '\t') &&
 292  285                      (*ptr != '\n'))
 293  286                          break;
 294  287          }
 295  288  
 296  289          ptr = (*ptr == '\0' ? NULL : ptr);
 297  290  
 298  291          BAM_DPRINTF(("%s: ptr on exit: %s\n", fcn, ptr ? ptr : "NULL"));
 299  292  
 300  293          return (ptr);
 301  294  }
 302  295  
 303  296  static char *
 304  297  rskip_bspace(char *bound, char *ptr)
 305  298  {
 306  299          const char              *fcn = "rskip_bspace()";
 307  300          assert(bound);
 308  301          assert(ptr);
 309  302          assert(bound <= ptr);
 310  303          assert(*bound != ' ' && *bound != '\t' && *bound != '\n');
 311  304  
 312  305          BAM_DPRINTF(("%s: ptr on entry: %s\n", fcn, ptr));
 313  306          for (; ptr > bound; ptr--) {
 314  307                  if (*ptr == ' ' || *ptr == '\t' || *ptr == '\n')
 315  308                          break;
 316  309          }
 317  310  
 318  311          BAM_DPRINTF(("%s: ptr on exit: %s\n", fcn, ptr));
 319  312          return (ptr);
 320  313  }
 321  314  
 322  315  /*
 323  316   * The parse_kernel_line function examines a menu.lst kernel line.  For
 324  317   * multiboot, this is:
 325  318   *
 326  319   * kernel <multiboot path> <flags1> <kernel path> <flags2>
 327  320   *
 328  321   * <multiboot path> is either /platform/i86pc/multiboot or /boot/multiboot
 329  322   *
 330  323   * <kernel path> may be missing, or may be any full or relative path to unix.
 331  324   *      We check for it by looking for a word ending in "/unix".  If it ends
 332  325   *      in "kernel/unix", we upgrade it to a 32-bit entry.  If it ends in
 333  326   *      "kernel/amd64/unix", we upgrade it to the default entry.  Otherwise,
 334  327   *      it's a custom kernel, and we skip it.
 335  328   *
 336  329   * <flags*> are anything that doesn't fit either of the above - these will be
 337  330   *      copied over.
 338  331   *
 339  332   * For direct boot, the defaults are
 340  333   *
 341  334   * kernel$ <kernel path> <flags>
 342  335   *
 343  336   * <kernel path> is one of:
 344  337   *      /platform/i86pc/kernel/$ISADIR/unix
 345  338   *      /boot/platform/i86pc/kernel/$ISADIR/unix
 346  339   *      /platform/i86pc/kernel/unix
 347  340   *      /platform/i86pc/kernel/amd64/unix
 348  341   *      /boot/platform/i86pc/kernel/unix
 349  342   *      /boot/platform/i86pc/kernel/amd64/unix
 350  343   *
 351  344   * If <kernel path> is any of the last four, the command may also be "kernel".
 352  345   *
 353  346   * <flags> is anything that isn't <kernel path>.
 354  347   *
 355  348   * This function is only called to convert a multiboot entry to a dboot entry
 356  349   *
 357  350   * For safety, we do one more check: if the kernel path starts with /boot,
 358  351   * we verify that the new kernel exists before changing it.  This is mainly
 359  352   * done for bfu, as it may cause the failsafe archives to be a different
 360  353   * boot architecture from the newly bfu'ed system.
 361  354   */
 362  355  static error_t
 363  356  cvt_kernel_line(line_t *line, const char *osroot, entry_t *entry)
 364  357  {
 365  358          char            path[PATH_MAX], path_64[PATH_MAX];
 366  359          char            linebuf[PATH_MAX];
 367  360          char            new_arg[PATH_MAX];
 368  361          struct stat     sb, sb_64;
 369  362          char            *old_ptr;
 370  363          char            *unix_ptr;
 371  364          char            *flags1_ptr;
 372  365          char            *flags2_ptr;
 373  366          const char      *fcn = "cvt_kernel_line()";
 374  367  
 375  368          BAM_DPRINTF(("%s: entered. args: %s %s\n", fcn, line->line, osroot));
 376  369  
 377  370          /*
 378  371           * We only convert multiboot to dboot and nothing else.
 379  372           */
 380  373          if (!(entry->flags & BAM_ENTRY_MULTIBOOT)) {
 381  374                  BAM_DPRINTF(("%s: not MULTIBOOT, not converting\n", fcn));
 382  375                  return (BAM_SUCCESS);
 383  376          }
 384  377  
 385  378          if (entry->flags & BAM_ENTRY_FAILSAFE) {
 386  379                  /*
 387  380                   * We're attempting to change failsafe to dboot.
 388  381                   * In the bfu case, we may not have a dboot failsafe
 389  382                   * kernel i.e. a "unix" under the "/boot" hierarchy.
 390  383                   * If so, just emit a message in verbose mode and
 391  384                   * return success.
 392  385                   */
 393  386                  BAM_DPRINTF(("%s: trying to convert failsafe to DBOOT\n", fcn));
 394  387                  (void) snprintf(path, PATH_MAX, "%s%s", osroot,
 395  388                      DIRECT_BOOT_FAILSAFE_32);
 396  389                  (void) snprintf(path_64, PATH_MAX, "%s%s", osroot,
 397  390                      DIRECT_BOOT_FAILSAFE_64);
 398  391                  if (stat(path, &sb) != 0 && stat(path_64, &sb_64) != 0) {
 399  392                          if (bam_verbose) {
 400  393                                  bam_error(_("bootadm -m upgrade run, but the "
 401  394                                      "failsafe archives have not been\nupdated. "
 402  395                                      "Not updating line %d\n"), line->lineNum);
 403  396                          }
 404  397                          BAM_DPRINTF(("%s: no FAILSAFE unix, not converting\n",
 405  398                              fcn));
 406  399                          return (BAM_SUCCESS);
 407  400                  }
 408  401          }
 409  402  
 410  403          /*
 411  404           * Make sure we have the correct cmd
 412  405           */
 413  406  
 414  407          free(line->cmd);
 415  408          line->cmd = s_strdup(menu_cmds[KERNEL_DOLLAR_CMD]);
 416  409          BAM_DPRINTF(("%s: converted kernel cmd to %s\n", fcn, line->cmd));
 417  410  
 418  411          assert(sizeof (linebuf) > strlen(line->arg) + 32);
 419  412          (void) strlcpy(linebuf, line->arg, sizeof (linebuf));
 420  413  
 421  414          old_ptr = strpbrk(linebuf, " \t\n");
 422  415          old_ptr = skip_wspace(old_ptr);
 423  416          if (old_ptr == NULL) {
 424  417                  /*
 425  418                   * only multiboot and nothing else
 426  419                   * i.e. flags1 = unix = flags2 = NULL
 427  420                   */
 428  421                  flags1_ptr = unix_ptr = flags2_ptr = NULL;
 429  422                  BAM_DPRINTF(("%s: NULL flags1, unix, flags2\n", fcn))
 430  423                  goto create;
 431  424          }
 432  425  
 433  426          /*
 434  427           *
 435  428           * old_ptr is either at "flags1" or "unix"
 436  429           */
 437  430          if ((unix_ptr = strstr(old_ptr, "/unix")) != NULL) {
 438  431  
 439  432                  /*
 440  433                   * There is a  unix.
 441  434                   */
 442  435                  BAM_DPRINTF(("%s: unix present\n", fcn));
 443  436  
 444  437                  /* See if there's a flags2 past unix */
 445  438                  flags2_ptr = unix_ptr + strlen("/unix");
 446  439                  flags2_ptr = skip_wspace(flags2_ptr);
 447  440                  if (flags2_ptr) {
 448  441                          BAM_DPRINTF(("%s: flags2 present: %s\n", fcn,
 449  442                              flags2_ptr));
 450  443                  } else {
 451  444                          BAM_DPRINTF(("%s: flags2 absent\n", fcn));
 452  445                  }
 453  446  
 454  447                  /* see if there is a flags1 before unix */
 455  448                  unix_ptr = rskip_bspace(old_ptr, unix_ptr);
 456  449  
 457  450                  if (unix_ptr == old_ptr) {
 458  451                          flags1_ptr = NULL;
 459  452                          BAM_DPRINTF(("%s: flags1 absent\n", fcn));
 460  453                  } else {
 461  454                          flags1_ptr = old_ptr;
 462  455                          *unix_ptr = '\0';
 463  456                          unix_ptr++;
 464  457                          BAM_DPRINTF(("%s: flags1 present: %s\n", fcn,
 465  458                              flags1_ptr));
 466  459                  }
 467  460  
 468  461          } else  {
 469  462                  /* There is no unix, there is only a bunch of flags */
 470  463                  flags1_ptr = old_ptr;
 471  464                  unix_ptr = flags2_ptr = NULL;
 472  465                  BAM_DPRINTF(("%s: flags1 present: %s, unix, flags2 absent\n",
 473  466                      fcn, flags1_ptr));
 474  467          }
 475  468  
 476  469          /*
 477  470           * With dboot, unix is fixed and is at the beginning. We need to
 478  471           * migrate flags1 and flags2
 479  472           */
 480  473  create:
 481  474          if (entry->flags & BAM_ENTRY_FAILSAFE) {
 482  475                  (void) snprintf(new_arg, sizeof (new_arg), "%s",
 483  476                      DIRECT_BOOT_FAILSAFE_KERNEL);
 484  477          } else {
 485  478                  (void) snprintf(new_arg, sizeof (new_arg), "%s",
 486  479                      DIRECT_BOOT_KERNEL);
 487  480          }
 488  481          BAM_DPRINTF(("%s: converted unix: %s\n", fcn, new_arg));
 489  482  
 490  483          if (flags1_ptr != NULL) {
 491  484                  (void) strlcat(new_arg, " ", sizeof (new_arg));
 492  485                  (void) strlcat(new_arg, flags1_ptr, sizeof (new_arg));
 493  486          }
 494  487  
 495  488          if (flags2_ptr != NULL) {
 496  489                  (void) strlcat(new_arg, " ", sizeof (new_arg));
 497  490                  (void) strlcat(new_arg, flags2_ptr, sizeof (new_arg));
 498  491          }
 499  492  
 500  493          BAM_DPRINTF(("%s: converted unix with flags : %s\n", fcn, new_arg));
 501  494  
 502  495          free(line->arg);
 503  496          line->arg = s_strdup(new_arg);
 504  497          update_line(line);
 505  498          BAM_DPRINTF(("%s: converted line is: %s\n", fcn, line->line));
 506  499          return (BAM_SUCCESS);
 507  500  }
 508  501  
 509  502  /*
 510  503   * Similar to above, except this time we're looking at a module line,
 511  504   * which is quite a bit simpler.
 512  505   *
 513  506   * Under multiboot, the archive line is:
 514  507   *
 515  508   * module /platform/i86pc/boot_archive
 516  509   *
 517  510   * Under directboot, the archive line is:
 518  511   *
 519  512   * module$ /platform/i86pc/$ISADIR/boot_archive
 520  513   *
 521  514   * which may be specified exactly as either of:
 522  515   *
 523  516   * module /platform/i86pc/boot_archive
 524  517   * module /platform/i86pc/amd64/boot_archive
 525  518   *
 526  519   * Under multiboot, the failsafe is:
 527  520   *
 528  521   * module /boot/x86.miniroot-safe
 529  522   *
 530  523   * Under dboot, the failsafe is:
 531  524   *
 532  525   * module$ /boot/$ISADIR/x86.miniroot-safe
 533  526   *
 534  527   * which may be specified exactly as either of:
 535  528   *
 536  529   * module /boot/x86.miniroot-safe
 537  530   * module /boot/amd64/x86.miniroot-safe
 538  531   */
 539  532  static error_t
 540  533  cvt_module_line(line_t *line, entry_t *entry)
 541  534  {
 542  535          const char              *fcn = "cvt_module_line()";
 543  536  
 544  537          BAM_DPRINTF(("%s: entered. arg: %s\n", fcn, line->line));
 545  538  
 546  539          /*
 547  540           * We only convert multiboot to dboot and nothing else
 548  541           */
 549  542          if (!(entry->flags & BAM_ENTRY_MULTIBOOT)) {
 550  543                  BAM_DPRINTF(("%s: not MULTIBOOT, not converting\n", fcn));
 551  544                  return (BAM_SUCCESS);
 552  545          }
 553  546  
 554  547          if (entry->flags & BAM_ENTRY_FAILSAFE) {
 555  548                  if (strcmp(line->arg, FAILSAFE_ARCHIVE) == 0) {
 556  549                          BAM_DPRINTF(("%s: failsafe module line needs no "
 557  550                              "conversion: %s\n", fcn, line->arg));
 558  551                          BAM_DPRINTF(("%s: returning SUCCESS\n", fcn));
 559  552                          return (BAM_SUCCESS);
 560  553                  }
 561  554          } else if (strcmp(line->arg, MULTIBOOT_ARCHIVE) != 0) {
 562  555                  bam_error(_("module command on line %d not recognized.\n"),
 563  556                      line->lineNum);
 564  557                  BAM_DPRINTF(("%s: returning FAILURE\n", fcn));
 565  558                  return (BAM_MSG);
 566  559          }
 567  560  
 568  561          free(line->cmd);
 569  562          free(line->arg);
 570  563          line->cmd = s_strdup(menu_cmds[MODULE_DOLLAR_CMD]);
 571  564  
 572  565          line->arg = s_strdup(entry->flags & BAM_ENTRY_FAILSAFE ?
 573  566              FAILSAFE_ARCHIVE : DIRECT_BOOT_ARCHIVE);
 574  567  
 575  568          update_line(line);
 576  569          BAM_DPRINTF(("%s: converted module line is: %s\n", fcn, line->line));
 577  570          BAM_DPRINTF(("%s: returning SUCCESS\n", fcn));
 578  571          return (BAM_SUCCESS);
 579  572  }
 580  573  
 581  574  static void
 582  575  bam_warn_hand_entries(menu_t *mp, char *osroot)
 583  576  {
 584  577          int             hand_num;
 585  578          int             hand_max;
 586  579          int             *hand_list;
 587  580          int             i;
 588  581          entry_t         *entry;
 589  582          const char      *fcn = "bam_warn_hand_entries()";
 590  583  
 591  584          if (bam_force) {
 592  585                  /*
 593  586                   * No warning needed, we are automatically converting
 594  587                   * the "hand" entries
 595  588                   */
 596  589                  BAM_DPRINTF(("%s: force specified, no warnings about hand "
 597  590                      "entries\n",  fcn));
 598  591                  return;
 599  592          }
 600  593  
 601  594          hand_num = 0;
 602  595          hand_max = BAM_ENTRY_NUM;
 603  596          hand_list = s_calloc(1, hand_max);
 604  597  
 605  598          for (entry = mp->entries; entry; entry = entry->next) {
 606  599                  if (entry->flags & (BAM_ENTRY_BOOTADM|BAM_ENTRY_LU))
 607  600                          continue;
 608  601                  BAM_DPRINTF(("%s: found hand entry #: %d\n", fcn,
 609  602                      entry->entryNum));
 610  603                  if (++hand_num > hand_max) {
 611  604                          hand_max *= 2;
 612  605                          hand_list = s_realloc(hand_list,
 613  606                              hand_max * sizeof (int));
 614  607                  }
 615  608                  hand_list[hand_num - 1] = entry->entryNum;
 616  609          }
 617  610  
 618  611          bam_error(_("bootadm(1M) will only upgrade GRUB menu entries added "
 619  612              "by \nbootadm(1M) or lu(1M). The following entries on %s will "
 620  613              "not be upgraded.\nFor details on manually updating entries, "
 621  614              "see %s\n"), osroot, MENU_URL(osroot));
 622  615          bam_print_stderr("Entry Number%s: ", (hand_num > 1) ?
 623  616              "s" : "");
 624  617          for (i = 0; i < hand_num; i++) {
 625  618                  bam_print_stderr("%d ", hand_list[i]);
 626  619          }
 627  620          bam_print_stderr("\n");
 628  621  }
 629  622  
 630  623  static entry_t *
 631  624  find_matching_entry(
 632  625          entry_t *estart,
 633  626          char *grubsign,
 634  627          char *grubroot,
 635  628          int root_opt)
 636  629  {
 637  630          entry_t         *entry;
 638  631          line_t          *line;
 639  632          char            opt[10];
 640  633          const char      *fcn = "find_matching_entry()";
 641  634  
 642  635          assert(grubsign);
 643  636          assert(root_opt == 0 || root_opt == 1);
 644  637  
 645  638          (void) snprintf(opt, sizeof (opt), "%d", root_opt);
 646  639          BAM_DPRINTF(("%s: entered. args: %s %s %s\n", fcn, grubsign,
 647  640              grubroot, opt));
 648  641  
 649  642          for (entry = estart; entry; entry = entry->next) {
 650  643  
 651  644                  if (!(entry->flags & (BAM_ENTRY_BOOTADM|BAM_ENTRY_LU)) &&
 652  645                      !bam_force) {
 653  646                          BAM_DPRINTF(("%s: skipping hand entry #: %d\n",
 654  647                              fcn, entry->entryNum));
 655  648                          continue;
 656  649                  }
 657  650  
 658  651                  if (entry->flags & BAM_ENTRY_ROOT) {
 659  652                          for (line = entry->start; line; line = line->next) {
 660  653                                  if (line->cmd == NULL || line->arg == NULL) {
 661  654                                          if (line == entry->end) {
 662  655                                                  BAM_DPRINTF(("%s: entry has "
 663  656                                                      "ended\n", fcn));
 664  657                                                  break;
 665  658                                          } else {
 666  659                                                  BAM_DPRINTF(("%s: skipping "
 667  660                                                      "NULL line\n", fcn));
 668  661                                                  continue;
 669  662                                          }
 670  663                                  }
 671  664                                  if (strcmp(line->cmd, menu_cmds[ROOT_CMD])
 672  665                                      == 0 && strcmp(line->arg, grubroot) == 0) {
 673  666                                          BAM_DPRINTF(("%s: found matching root "
 674  667                                              "line: %s,%s\n", fcn,
 675  668                                              line->line, grubsign));
 676  669                                          return (entry);
 677  670                                  }
 678  671                                  if (line == entry->end) {
 679  672                                          BAM_DPRINTF(("%s: entry has ended\n",
 680  673                                              fcn));
 681  674                                          break;
 682  675                                  }
 683  676                          }
 684  677                  } else if (entry->flags & BAM_ENTRY_FINDROOT) {
 685  678                          for (line = entry->start; line; line = line->next) {
 686  679                                  if (line->cmd == NULL || line->arg == NULL) {
 687  680                                          if (line == entry->end) {
 688  681                                                  BAM_DPRINTF(("%s: entry has "
 689  682                                                      "ended\n", fcn));
 690  683                                                  break;
 691  684                                          } else {
 692  685                                                  BAM_DPRINTF(("%s: skipping "
 693  686                                                      "NULL line\n", fcn));
 694  687                                                  continue;
 695  688                                          }
 696  689                                  }
 697  690                                  if (strcmp(line->cmd, menu_cmds[FINDROOT_CMD])
 698  691                                      == 0 && strcmp(line->arg, grubsign) == 0) {
 699  692                                          BAM_DPRINTF(("%s: found matching "
 700  693                                              "findroot line: %s,%s\n", fcn,
 701  694                                              line->line, grubsign));
 702  695                                          return (entry);
 703  696                                  }
 704  697                                  if (line == entry->end) {
 705  698                                          BAM_DPRINTF(("%s: entry has ended\n",
 706  699                                              fcn));
 707  700                                          break;
 708  701                                  }
 709  702                          }
 710  703                  } else if (root_opt) {
 711  704                          /* Neither root nor findroot */
 712  705                          BAM_DPRINTF(("%s: no root or findroot and root is "
 713  706                              "opt: %d\n", fcn, entry->entryNum));
 714  707                          return (entry);
 715  708                  }
 716  709          }
 717  710  
 718  711          BAM_DPRINTF(("%s: no matching entry found\n", fcn));
 719  712          return (NULL);
 720  713  }
 721  714  
 722  715  /*
 723  716   * The following is a set of routines that attempt to convert the
 724  717   * menu entries for the supplied osroot into a format compatible
 725  718   * with the GRUB installation on osroot.
 726  719   *
 727  720   * Each of these conversion routines make no assumptions about
 728  721   * the current state of the menu entry, it does its best to
 729  722   * convert the menu entry to the new state. In the process
 730  723   * we may either upgrade or downgrade.
 731  724   *
 732  725   * We don't make any heroic efforts at conversion. It is better
 733  726   * to be conservative and bail out at the first sign of error. We will
 734  727   * in such cases, point the user at the knowledge-base article
 735  728   * so that they can upgrade manually.
 736  729   */
 737  730  static error_t
 738  731  bam_add_findroot(menu_t *mp, char *grubsign, char *grubroot, int root_opt)
 739  732  {
 740  733          entry_t         *entry;
 741  734          line_t          *line;
 742  735          line_t          *newlp;
 743  736          int             update_num;
 744  737          char            linebuf[PATH_MAX];
 745  738          const char      *fcn = "bam_add_findroot()";
 746  739  
 747  740          update_num = 0;
 748  741  
 749  742          bam_print(_("converting entries to findroot...\n"));
 750  743  
 751  744          entry = find_matching_entry(mp->entries, grubsign, grubroot, root_opt);
 752  745          while (entry != NULL) {
 753  746                  if (entry->flags & BAM_ENTRY_FINDROOT) {
 754  747                          /* already converted */
 755  748                          BAM_DPRINTF(("%s: entry %d already converted to "
 756  749                              "findroot\n", fcn, entry->entryNum));
 757  750                          entry = find_matching_entry(entry->next, grubsign,
 758  751                              grubroot, root_opt);
 759  752                          continue;
 760  753                  }
 761  754                  for (line = entry->start; line; line = line->next) {
 762  755                          if (line->cmd == NULL || line->arg == NULL) {
 763  756                                  if (line == entry->end) {
 764  757                                          BAM_DPRINTF(("%s: entry has ended\n",
 765  758                                              fcn));
 766  759                                          break;
 767  760                                  } else {
 768  761                                          BAM_DPRINTF(("%s: skipping NULL line\n",
 769  762                                              fcn));
 770  763                                          continue;
 771  764                                  }
 772  765                          }
 773  766                          if (strcmp(line->cmd, menu_cmds[TITLE_CMD]) == 0) {
 774  767                                  newlp = s_calloc(1, sizeof (line_t));
 775  768                                  newlp->cmd = s_strdup(menu_cmds[FINDROOT_CMD]);
 776  769                                  newlp->sep = s_strdup(" ");
 777  770                                  newlp->arg = s_strdup(grubsign);
 778  771                                  (void) snprintf(linebuf, sizeof (linebuf),
 779  772                                      "%s%s%s", newlp->cmd, newlp->sep,
 780  773                                      newlp->arg);
 781  774                                  newlp->line = s_strdup(linebuf);
 782  775                                  bam_add_line(mp, entry, line, newlp);
 783  776                                  update_num = 1;
 784  777                                  entry->flags &= ~BAM_ENTRY_ROOT;
 785  778                                  entry->flags |= BAM_ENTRY_FINDROOT;
 786  779                                  BAM_DPRINTF(("%s: added findroot line: %s\n",
 787  780                                      fcn, newlp->line));
 788  781                                  line = newlp;
 789  782                          }
 790  783                          if (strcmp(line->cmd, menu_cmds[ROOT_CMD]) == 0) {
 791  784                                  BAM_DPRINTF(("%s: freeing root line: %s\n",
 792  785                                      fcn, line->line));
 793  786                                  unlink_line(mp, line);
 794  787                                  line_free(line);
 795  788                          }
 796  789                          if (line == entry->end) {
 797  790                                  BAM_DPRINTF(("%s: entry has ended\n", fcn));
 798  791                                  break;
 799  792                          }
 800  793                  }
 801  794                  entry = find_matching_entry(entry->next, grubsign, grubroot,
 802  795                      root_opt);
 803  796          }
 804  797  
  
    | ↓ open down ↓ | 581 lines elided | ↑ open up ↑ | 
 805  798          if (update_num) {
 806  799                  BAM_DPRINTF(("%s: updated numbering\n", fcn));
 807  800                  update_numbering(mp);
 808  801          }
 809  802  
 810  803          BAM_DPRINTF(("%s: returning SUCCESS\n", fcn));
 811  804          return (BAM_SUCCESS);
 812  805  }
 813  806  
 814  807  static error_t
 815      -bam_add_hv(menu_t *mp, char *grubsign, char *grubroot, int root_opt)
 816      -{
 817      -        entry_t         *entry;
 818      -        const char      *fcn = "bam_add_hv()";
 819      -
 820      -        bam_print(_("adding xVM entries...\n"));
 821      -
 822      -        entry = find_matching_entry(mp->entries, grubsign, grubroot, root_opt);
 823      -        while (entry != NULL) {
 824      -                if (entry->flags & BAM_ENTRY_HV) {
 825      -                        BAM_DPRINTF(("%s: entry %d already converted to "
 826      -                            "xvm HV\n", fcn, entry->entryNum));
 827      -                        return (BAM_SUCCESS);
 828      -                }
 829      -                entry = find_matching_entry(entry->next, grubsign, grubroot,
 830      -                    root_opt);
 831      -        }
 832      -
 833      -        (void) add_boot_entry(mp, NEW_HV_ENTRY, grubsign, XEN_MENU,
 834      -            XEN_KERNEL_MODULE_LINE, DIRECT_BOOT_ARCHIVE, NULL);
 835      -
 836      -        BAM_DPRINTF(("%s: added xVM HV entry via add_boot_entry()\n", fcn));
 837      -
 838      -        update_numbering(mp);
 839      -
 840      -        BAM_DPRINTF(("%s: returning SUCCESS\n", fcn));
 841      -
 842      -        return (BAM_SUCCESS);
 843      -}
 844      -
 845      -static error_t
 846  808  bam_add_dboot(
 847  809          menu_t *mp,
 848  810          char *osroot,
 849  811          char *grubsign,
 850  812          char *grubroot,
 851  813          int root_opt)
 852  814  {
 853  815          int             msg = 0;
 854  816          entry_t         *entry;
 855  817          line_t          *line;
 856  818          error_t         ret;
 857  819          const char      *fcn = "bam_add_dboot()";
 858  820  
 859  821          bam_print(_("converting entries to dboot...\n"));
 860  822  
 861  823          entry = find_matching_entry(mp->entries, grubsign, grubroot, root_opt);
 862  824          while (entry != NULL) {
 863  825                  for (line = entry->start; line; line = line->next) {
 864  826                          if (line->cmd == NULL || line->arg == NULL) {
 865  827                                  if (line == entry->end) {
 866  828                                          BAM_DPRINTF(("%s: entry has ended\n",
 867  829                                              fcn));
 868  830                                          break;
 869  831                                  } else {
 870  832                                          BAM_DPRINTF(("%s: skipping NULL line\n",
 871  833                                              fcn));
 872  834                                          continue;
 873  835                                  }
 874  836                          }
 875  837  
 876  838                          /*
 877  839                           * If we have a kernel$ command, assume it
 878  840                           * is dboot already.  If it is not a dboot
 879  841                           * entry, something funny is going on and
 880  842                           * we will leave it alone
 881  843                           */
 882  844                          if (strcmp(line->cmd, menu_cmds[KERNEL_CMD]) == 0) {
 883  845                                  ret = cvt_kernel_line(line, osroot, entry);
 884  846                                  INJECT_ERROR1("ADD_DBOOT_KERN_ERR",
 885  847                                      ret = BAM_ERROR);
 886  848                                  INJECT_ERROR1("ADD_DBOOT_KERN_MSG",
 887  849                                      ret = BAM_MSG);
 888  850                                  if (ret == BAM_ERROR) {
 889  851                                          BAM_DPRINTF(("%s: cvt_kernel_line() "
 890  852                                              "failed\n", fcn));
 891  853                                          return (ret);
 892  854                                  } else if (ret == BAM_MSG) {
 893  855                                          msg = 1;
 894  856                                          BAM_DPRINTF(("%s: BAM_MSG returned "
 895  857                                              "from cvt_kernel_line()\n", fcn));
 896  858                                  }
 897  859                          }
 898  860                          if (strcmp(line->cmd, menu_cmds[MODULE_CMD]) == 0) {
 899  861                                  ret = cvt_module_line(line, entry);
 900  862                                  INJECT_ERROR1("ADD_DBOOT_MOD_ERR",
 901  863                                      ret = BAM_ERROR);
 902  864                                  INJECT_ERROR1("ADD_DBOOT_MOD_MSG",
 903  865                                      ret = BAM_MSG);
 904  866                                  if (ret == BAM_ERROR) {
 905  867                                          BAM_DPRINTF(("%s: cvt_module_line() "
 906  868                                              "failed\n", fcn));
 907  869                                          return (ret);
 908  870                                  } else if (ret == BAM_MSG) {
 909  871                                          BAM_DPRINTF(("%s: BAM_MSG returned "
 910  872                                              "from cvt_module_line()\n", fcn));
 911  873                                          msg = 1;
 912  874                                  }
 913  875                          }
 914  876  
 915  877                          if (line == entry->end) {
 916  878                                  BAM_DPRINTF(("%s: entry has ended\n", fcn));
 917  879                                  break;
 918  880                          }
 919  881                  }
 920  882                  entry = find_matching_entry(entry->next, grubsign, grubroot,
 921  883                      root_opt);
 922  884          }
 923  885  
 924  886          ret = msg ? BAM_MSG : BAM_SUCCESS;
 925  887          BAM_DPRINTF(("%s: returning ret = %d\n", fcn, ret));
 926  888          return (ret);
 927  889  }
  
    | ↓ open down ↓ | 72 lines elided | ↑ open up ↑ | 
 928  890  
 929  891  /*ARGSUSED*/
 930  892  error_t
 931  893  upgrade_menu(menu_t *mp, char *osroot, char *menu_root)
 932  894  {
 933  895          char            *osdev;
 934  896          char            *grubsign;
 935  897          char            *grubroot;
 936  898          int             ret1;
 937  899          int             ret2;
 938      -        int             ret3;
 939  900          const char      *fcn = "upgrade_menu()";
 940  901  
 941  902          assert(osroot);
 942  903          assert(menu_root);
 943  904  
 944  905          BAM_DPRINTF(("%s: entered. args: %s %s\n", fcn, osroot, menu_root));
 945  906  
 946  907          /*
 947      -         * We only support upgrades. Xen may not be present
 948      -         * on smaller metaclusters so we don't check for that.
      908 +         * We only support upgrades.
 949  909           */
 950  910          if (bam_is_findroot != BAM_FINDROOT_PRESENT ||
 951  911              bam_direct != BAM_DIRECT_DBOOT) {
 952  912                  bam_error(_("automated downgrade of GRUB menu to older "
 953  913                      "version not supported.\n"));
 954  914                  return (BAM_ERROR);
 955  915          }
 956  916  
 957  917          /*
 958  918           * First get the GRUB signature
 959  919           */
 960  920          osdev = get_special(osroot);
 961  921          INJECT_ERROR1("UPGRADE_OSDEV", osdev = NULL);
 962  922          if (osdev == NULL) {
 963  923                  bam_error(_("cant find special file for mount-point %s\n"),
 964  924                      osroot);
 965  925                  return (BAM_ERROR);
 966  926          }
 967  927  
 968  928          grubsign = get_grubsign(osroot, osdev);
 969  929          INJECT_ERROR1("UPGRADE_GRUBSIGN", grubsign = NULL);
 970  930          if (grubsign == NULL) {
 971  931                  free(osdev);
 972  932                  bam_error(_("cannot find GRUB signature for %s\n"), osroot);
 973  933                  return (BAM_ERROR);
 974  934          }
 975  935  
 976  936          /* not fatal if we can't get grubroot */
 977  937          grubroot = get_grubroot(osroot, osdev, menu_root);
  
    | ↓ open down ↓ | 19 lines elided | ↑ open up ↑ | 
 978  938          INJECT_ERROR1("UPGRADE_GRUBROOT", grubroot = NULL);
 979  939  
 980  940          free(osdev);
 981  941  
 982  942          ret1 = bam_add_findroot(mp, grubsign,
 983  943              grubroot, root_optional(osroot, menu_root));
 984  944          INJECT_ERROR1("UPGRADE_ADD_FINDROOT", ret1 = BAM_ERROR);
 985  945          if (ret1 == BAM_ERROR)
 986  946                  goto abort;
 987  947  
 988      -        if (bam_is_hv == BAM_HV_PRESENT) {
 989      -                ret2 = bam_add_hv(mp, grubsign, grubroot,
 990      -                    root_optional(osroot, menu_root));
 991      -                INJECT_ERROR1("UPGRADE_ADD_HV", ret2 = BAM_ERROR);
 992      -                if (ret2 == BAM_ERROR)
 993      -                        goto abort;
 994      -        } else
 995      -                ret2 = BAM_SUCCESS;
 996      -
 997      -        ret3 = bam_add_dboot(mp, osroot, grubsign,
      948 +        ret2 = bam_add_dboot(mp, osroot, grubsign,
 998  949              grubroot, root_optional(osroot, menu_root));
 999      -        INJECT_ERROR1("UPGRADE_ADD_DBOOT", ret3 = BAM_ERROR);
1000      -        if (ret3 == BAM_ERROR)
      950 +        INJECT_ERROR1("UPGRADE_ADD_DBOOT", ret2 = BAM_ERROR);
      951 +        if (ret2 == BAM_ERROR)
1001  952                  goto abort;
1002  953  
1003      -        if (ret1 == BAM_MSG || ret2 == BAM_MSG || ret3 == BAM_MSG) {
      954 +        if (ret1 == BAM_MSG || ret2 == BAM_MSG) {
1004  955                  bam_error(_("one or more GRUB menu entries were not "
1005  956                      "automatically upgraded\nFor details on manually "
1006  957                      "updating entries, see %s\n"), MENU_URL(osroot));
1007  958          } else {
1008  959                  bam_warn_hand_entries(mp, osroot);
1009  960          }
1010  961  
1011  962          free(grubsign);
1012  963  
1013  964          BAM_DPRINTF(("%s: returning ret = %d\n", fcn, BAM_WRITE));
1014  965          return (BAM_WRITE);
1015  966  
1016  967  abort:
1017  968          free(grubsign);
1018  969          bam_error(_("error upgrading GRUB menu entries on %s. Aborting.\n"
1019  970              "For details on manually updating entries, see %s\n"), osroot,
1020  971              MENU_URL(osroot));
1021  972          return (BAM_ERROR);
1022  973  }
    
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX