diff options
Diffstat (limited to 'usr/src/cmd/boot/bootadm/bootadm.c')
| -rw-r--r-- | usr/src/cmd/boot/bootadm/bootadm.c | 367 |
1 files changed, 207 insertions, 160 deletions
diff --git a/usr/src/cmd/boot/bootadm/bootadm.c b/usr/src/cmd/boot/bootadm/bootadm.c index 2ebc4e1b1e..ce2e154314 100644 --- a/usr/src/cmd/boot/bootadm/bootadm.c +++ b/usr/src/cmd/boot/bootadm/bootadm.c @@ -54,7 +54,8 @@ #include <sys/systeminfo.h> #include <sys/dktp/fdisk.h> #include <sys/param.h> -#if defined(__i386) + +#if !defined(_OPB) #include <sys/ucode.h> #endif @@ -108,8 +109,9 @@ typedef struct { #define BAM_LOCK_FILE "/var/run/bootadm.lock" #define LOCK_FILE_PERMS (S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH) -#define CREATE_RAMDISK "/boot/solaris/bin/create_ramdisk" -#define CREATE_DISKMAP "/boot/solaris/bin/create_diskmap" +#define CREATE_RAMDISK "boot/solaris/bin/create_ramdisk" +#define CREATE_DISKMAP "boot/solaris/bin/create_diskmap" +#define EXTRACT_BOOT_FILELIST "boot/solaris/bin/extract_boot_filelist" #define GRUBDISK_MAP "/var/run/solaris_grubdisk.map" #define GRUB_slice "/etc/lu/GRUB_slice" @@ -201,56 +203,51 @@ static char rootbuf[PATH_MAX] = "/"; static int bam_update_all; /* function prototypes */ -static void parse_args_internal(int argc, char *argv[]); -static void parse_args(int argc, char *argv[]); -static error_t bam_menu(char *subcmd, char *opt, int argc, char *argv[]); -static error_t bam_archive(char *subcmd, char *opt); +static void parse_args_internal(int, char *[]); +static void parse_args(int, char *argv[]); +static error_t bam_menu(char *, char *, int, char *[]); +static error_t bam_archive(char *, char *); -static void bam_print(char *format, ...); -static void bam_exit(int excode); +static void bam_print(char *, ...); +static void bam_exit(int); static void bam_lock(void); static void bam_unlock(void); -static int exec_cmd(char *cmdline, char *output, int64_t osize); -static error_t read_globals(menu_t *mp, char *menu_path, - char *globalcmd, int quiet); - -static menu_t *menu_read(char *menu_path); -static error_t menu_write(char *root, menu_t *mp); -static void linelist_free(line_t *start); -static void menu_free(menu_t *mp); -static void line_free(line_t *lp); -static void filelist_free(filelist_t *flistp); -static error_t list2file(char *root, char *tmp, - char *final, line_t *start); -static error_t list_entry(menu_t *mp, char *menu_path, char *opt); -static error_t delete_all_entries(menu_t *mp, char *menu_path, char *opt); -static error_t update_entry(menu_t *mp, char *root, char *opt); -static error_t update_temp(menu_t *mp, char *root, char *opt); - -static error_t update_archive(char *root, char *opt); -static error_t list_archive(char *root, char *opt); -static error_t update_all(char *root, char *opt); -static error_t read_list(char *root, filelist_t *flistp); -static error_t set_global(menu_t *mp, char *globalcmd, int val); -static error_t set_option(menu_t *mp, char *globalcmd, char *opt); -static error_t set_kernel(menu_t *mp, menu_cmd_t optnum, char *path, - char *buf, size_t bufsize); -static char *expand_path(const char *partial_path); - -static long s_strtol(char *str); -static int s_fputs(char *str, FILE *fp); - -static char *s_strdup(char *str); +static int exec_cmd(char *, filelist_t *); +static error_t read_globals(menu_t *, char *, char *, int); + +static menu_t *menu_read(char *); +static error_t menu_write(char *, menu_t *); +static void linelist_free(line_t *); +static void menu_free(menu_t *); +static void line_free(line_t *); +static void filelist_free(filelist_t *); +static error_t list2file(char *, char *, char *, line_t *); +static error_t list_entry(menu_t *, char *, char *); +static error_t delete_all_entries(menu_t *, char *, char *); +static error_t update_entry(menu_t *, char *, char *); +static error_t update_temp(menu_t *, char *, char *); + +static error_t update_archive(char *, char *); +static error_t list_archive(char *, char *); +static error_t update_all(char *, char *); +static error_t read_list(char *, filelist_t *); +static error_t set_global(menu_t *, char *, int); +static error_t set_option(menu_t *, char *, char *); +static error_t set_kernel(menu_t *, menu_cmd_t, char *, char *, size_t); +static char *expand_path(const char *); + +static long s_strtol(char *); +static int s_fputs(char *, FILE *); + +static char *s_strdup(char *); static int is_readonly(char *); static int is_amd64(void); +static int is_sun4u(void); +static int is_sun4v(void); static void append_to_flist(filelist_t *, char *); -#if defined(__sparc) -static void sparc_abort(void); -#endif - -#if defined(__i386) +#if !defined(_OPB) static void ucode_install(); #endif @@ -298,7 +295,7 @@ usage(void) (void) fprintf(stderr, "\t%s update-archive [-vn] [-R altroot]\n", prog); (void) fprintf(stderr, "\t%s list-archive [-R altroot]\n", prog); -#ifndef __sparc +#if !defined(_OPB) /* x86 only */ (void) fprintf(stderr, "\t%s set-menu [-R altroot] key=value\n", prog); (void) fprintf(stderr, "\t%s list-menu [-R altroot]\n", prog); @@ -327,21 +324,6 @@ main(int argc, char *argv[]) parse_args(argc, argv); -#if defined(__sparc) - /* - * There are only two valid invocations of bootadm - * on SPARC: - * - * - SPARC diskless server creating boot_archive for i386 clients - * - archive creation call during reboot of a SPARC system - * - * The latter should be a NOP - */ - if (bam_cmd != BAM_ARCHIVE) { - sparc_abort(); - } -#endif - switch (bam_cmd) { case BAM_MENU: ret = bam_menu(bam_subcmd, bam_opt, bam_argc, bam_argv); @@ -361,17 +343,6 @@ main(int argc, char *argv[]) return (0); } -#if defined(__sparc) - -static void -sparc_abort(void) -{ - bam_error(NOT_ON_SPARC); - bam_exit(1); -} - -#endif - /* * Equivalence of public and internal commands: * update-archive -- -a update @@ -738,7 +709,7 @@ mount_grub_slice(int *mnted, char **physlice, char **logslice, char **fs_type) (void) snprintf(cmd, sizeof (cmd), "/sbin/mount -F %s %s %s", fstype, dev, mntpt); - if (exec_cmd(cmd, NULL, 0) != 0) { + if (exec_cmd(cmd, NULL) != 0) { bam_error(MOUNT_FAILED, dev, fstype); if (rmdir(mntpt) != 0) { bam_error(RMDIR_FAILED, mntpt, strerror(errno)); @@ -791,7 +762,7 @@ umount_grub_slice( if (mnted) { (void) snprintf(cmd, sizeof (cmd), "/sbin/umount %s", mntpt); - if (exec_cmd(cmd, NULL, 0) != 0) { + if (exec_cmd(cmd, NULL) != 0) { bam_error(UMOUNT_FAILED, mntpt); } if (rmdir(mntpt) != 0) { @@ -853,7 +824,7 @@ use_stubboot(void) */ (void) snprintf(cmd, sizeof (cmd), "/sbin/mount %s", STUBBOOT); - if (exec_cmd(cmd, NULL, 0) != 0) { + if (exec_cmd(cmd, NULL) != 0) { bam_error(MOUNT_MNTPT_FAILED, STUBBOOT); return (NULL); } @@ -908,6 +879,16 @@ bam_menu(char *subcmd, char *opt, int largc, char *largv[]) struct stat sb; int mnted; /* set if we did a mount */ error_t (*f)(menu_t *mp, char *menu_path, char *opt); + char *rootpath; + + /* + * Menu sub-command only applies to GRUB (i.e. x86) + */ + rootpath = (bam_alt_root) ? bam_root : "/"; + if (!is_grub((const char *)rootpath)) { + bam_error(NOT_ON_SPARC); + return (BAM_ERROR); + } /* * Check arguments @@ -1033,16 +1014,6 @@ bam_archive( return (BAM_ERROR); } -#if defined(__sparc) - /* - * A NOP if called on SPARC during reboot - */ - if (strcmp(subcmd, "update_all") == 0) - return (BAM_SUCCESS); - else if (strcmp(subcmd, "update") != 0) - sparc_abort(); -#endif - ret = dboot_or_multiboot(rootbuf); if (ret != BAM_SUCCESS) return (ret); @@ -1060,7 +1031,7 @@ bam_archive( if (strcmp(subcmd, "update_all") == 0) bam_update_all = 1; -#if defined(__i386) +#if !defined(_OPB) ucode_install(bam_root); #endif @@ -1496,24 +1467,34 @@ check_flags_and_files(char *root) /* * If archive is missing, create archive */ - (void) snprintf(path, sizeof (path), "%s%s", root, - DIRECT_BOOT_ARCHIVE_32); + + if (is_sun4u()) + (void) snprintf(path, sizeof (path), "%s%s", root, + SUN4U__ARCHIVE); + else if (is_sun4v()) + (void) snprintf(path, sizeof (path), "%s%s", root, + SUN4V__ARCHIVE); + else { + if (bam_direct == BAM_DIRECT_DBOOT) { + (void) snprintf(path, sizeof (path), "%s%s", root, + DIRECT_BOOT_ARCHIVE_64); + if (stat(path, &sb) != 0) { + if (bam_verbose && !bam_check) + bam_print(UPDATE_ARCH_MISS, path); + walk_arg.need_update = 1; + return; + } + } + (void) snprintf(path, sizeof (path), "%s%s", root, + DIRECT_BOOT_ARCHIVE_32); + } + if (stat(path, &sb) != 0) { if (bam_verbose && !bam_check) bam_print(UPDATE_ARCH_MISS, path); walk_arg.need_update = 1; return; } - if (bam_direct == BAM_DIRECT_DBOOT) { - (void) snprintf(path, sizeof (path), "%s%s", root, - DIRECT_BOOT_ARCHIVE_64); - if (stat(path, &sb) != 0) { - if (bam_verbose && !bam_check) - bam_print(UPDATE_ARCH_MISS, path); - walk_arg.need_update = 1; - return; - } - } } static error_t @@ -1547,17 +1528,55 @@ read_one_list(char *root, filelist_t *flistp, char *filelist) static error_t read_list(char *root, filelist_t *flistp) { - int rval; + char path[PATH_MAX]; + char cmd[PATH_MAX]; + struct stat sb; + int n, rval; flistp->head = flistp->tail = NULL; /* - * Read current lists of files - only the first is mandatory + * build and check path to extract_boot_filelist.ksh */ - rval = read_one_list(root, flistp, BOOT_FILE_LIST); - if (rval != BAM_SUCCESS) - return (rval); - (void) read_one_list(root, flistp, ETC_FILE_LIST); + n = snprintf(path, sizeof (path), "%s%s", root, EXTRACT_BOOT_FILELIST); + if (n >= sizeof (path)) { + bam_error(NO_FLIST); + return (BAM_ERROR); + } + + /* + * If extract_boot_filelist is present, exec it, otherwise read + * the filelists directly, for compatibility with older images. + */ + if (stat(path, &sb) == 0) { + /* + * build arguments to exec extract_boot_filelist.ksh + */ + if (strlen(root) > 1) { + n = snprintf(cmd, sizeof (cmd), "%s -R %s /%s /%s", + path, root, BOOT_FILE_LIST, ETC_FILE_LIST); + } else { + n = snprintf(cmd, sizeof (cmd), "%s /%s /%s", + path, BOOT_FILE_LIST, ETC_FILE_LIST); + } + if (n >= sizeof (cmd)) { + bam_error(NO_FLIST); + return (BAM_ERROR); + } + if (exec_cmd(cmd, flistp) != 0) { + if (bam_debug) + bam_error(FLIST_FAIL, path, strerror(errno)); + return (BAM_ERROR); + } + } else { + /* + * Read current lists of files - only the first is mandatory + */ + rval = read_one_list(root, flistp, BOOT_FILE_LIST); + if (rval != BAM_SUCCESS) + return (rval); + (void) read_one_list(root, flistp, ETC_FILE_LIST); + } if (flistp->head == NULL) { bam_error(NO_FLIST); @@ -1678,9 +1697,14 @@ walk_list(char *root, filelist_t *flistp) line_t *lp; for (lp = flistp->head; lp; lp = lp->next) { + /* + * Don't follow symlinks. A symlink must refer to + * a file that would appear in the archive through + * a direct reference. This matches the archive + * construction behavior. + */ (void) snprintf(path, sizeof (path), "%s%s", root, lp->line); - /* XXX shouldn't we use FTW_MOUNT ? */ - if (nftw(path, cmpstat, 20, 0) == -1) { + if (nftw(path, cmpstat, 20, FTW_PHYS) == -1) { /* * Some files may not exist. * For example: etc/rtc_config on a x86 diskless system @@ -1849,15 +1873,6 @@ update_required(char *root) return (0); } - /* - * At this point we need an update - so save new stat data - * However, if only checking (-n), don't save new stat data. - */ - if (!bam_check) - savenew(root); - - clear_walk_args(); - return (1); } @@ -1871,7 +1886,7 @@ create_ramdisk(char *root) /* * Setup command args for create_ramdisk.ksh */ - (void) snprintf(path, sizeof (path), "%s%s", root, CREATE_RAMDISK); + (void) snprintf(path, sizeof (path), "%s/%s", root, CREATE_RAMDISK); if (stat(path, &sb) != 0) { bam_error(ARCH_EXEC_MISS, path, strerror(errno)); return (BAM_ERROR); @@ -1887,7 +1902,7 @@ create_ramdisk(char *root) } else (void) snprintf(cmdline, len, "%s", path); - if (exec_cmd(cmdline, NULL, 0) != 0) { + if (exec_cmd(cmdline, NULL) != 0) { bam_error(ARCHIVE_FAIL, cmdline); free(cmdline); return (BAM_ERROR); @@ -1895,22 +1910,10 @@ create_ramdisk(char *root) free(cmdline); /* - * Verify that the archive has been created + * The existence of the expected archives used to be + * verified here. This check is done in create_ramdisk as + * it needs to be in sync with the altroot operated upon. */ - (void) snprintf(path, sizeof (path), "%s%s", root, - DIRECT_BOOT_ARCHIVE_32); - if (stat(path, &sb) != 0) { - bam_error(ARCHIVE_NOT_CREATED, path); - return (BAM_ERROR); - } - if (bam_direct == BAM_DIRECT_DBOOT) { - (void) snprintf(path, sizeof (path), "%s%s", root, - DIRECT_BOOT_ARCHIVE_64); - if (stat(path, &sb) != 0) { - bam_error(ARCHIVE_NOT_CREATED, path); - return (BAM_ERROR); - } - } return (BAM_SUCCESS); } @@ -1986,27 +1989,39 @@ is_ramdisk(char *root) } static int -is_newboot(char *root) +is_boot_archive(char *root) { char path[PATH_MAX]; struct stat sb; /* - * We can't boot without MULTI_BOOT + * We can't create an archive without the create_ramdisk script */ - (void) snprintf(path, sizeof (path), "%s%s", root, MULTI_BOOT); + (void) snprintf(path, sizeof (path), "%s/%s", root, CREATE_RAMDISK); if (stat(path, &sb) == -1) { if (bam_verbose) bam_print(FILE_MISS, path); return (0); } + return (1); +} + +/* + * Need to call this for anything that operates on the GRUB menu + */ +int +is_grub(const char *root) +{ + char path[PATH_MAX]; + struct stat sb; + /* - * We can't generate archive without GRUB_DIR + * GRUB_DIR is required to modify the menu */ (void) snprintf(path, sizeof (path), "%s%s", root, GRUB_DIR); if (stat(path, &sb) == -1) { - if (bam_verbose) + if (bam_debug) bam_print(DIR_MISS, path); return (0); } @@ -2045,10 +2060,9 @@ update_archive(char *root, char *opt) assert(opt == NULL); /* - * root must belong to a GRUB boot OS, - * don't care on sparc except for diskless clients + * root must belong to a boot archive based OS, */ - if (!is_newboot(root)) { + if (!is_boot_archive(root)) { /* * Emit message only if not in context of update_all. * If in update_all, emit only if verbose flag is set. @@ -2103,6 +2117,14 @@ update_archive(char *root, char *opt) /* create the ramdisk */ ret = create_ramdisk(root); } + + /* if the archive is updated, save the new stat data */ + if (ret == 0 && walk_arg.new_nvlp != NULL) { + savenew(root); + } + + clear_walk_args(); + return (ret); } @@ -2120,7 +2142,7 @@ update_fdisk(void) GRUB_fdisk, GRUB_fdisk_target); bam_print(UPDATING_FDISK); - if (exec_cmd(cmd, NULL, 0) != 0) { + if (exec_cmd(cmd, NULL) != 0) { bam_error(FDISK_UPDATE_FAILED); } @@ -2178,7 +2200,7 @@ restore_grub_slice(void) (void) snprintf(cmd, sizeof (cmd), "%s %s %s %s", INSTALLGRUB, STAGE1, STAGE2, physlice); - if (exec_cmd(cmd, NULL, 0) != 0) { + if (exec_cmd(cmd, NULL) != 0) { bam_error(RESTORE_GRUB_FAILED); umount_grub_slice(mnted, mntpt, physlice, NULL, NULL); return; @@ -2194,7 +2216,7 @@ restore_grub_slice(void) (void) snprintf(cmd, sizeof (cmd), "/bin/cp %s %s", GRUB_backup_menu, menupath); - if (exec_cmd(cmd, NULL, 0) != 0) { + if (exec_cmd(cmd, NULL) != 0) { bam_error(RESTORE_MENU_FAILED, menupath); umount_grub_slice(mnted, mntpt, physlice, NULL, NULL); return; @@ -2211,6 +2233,7 @@ update_all(char *root, char *opt) struct stat sb; FILE *fp; char multibt[PATH_MAX]; + char creatram[PATH_MAX]; error_t ret = BAM_SUCCESS; int ret1, ret2; @@ -2239,7 +2262,7 @@ update_all(char *root, char *opt) } (void) snprintf(multibt, sizeof (multibt), "/sbin/mount -F lofs -o nosub / %s", LOFS_PATCH_MNT); - if (exec_cmd(multibt, NULL, 0) != 0) { + if (exec_cmd(multibt, NULL) != 0) { bam_error(MOUNT_FAILED, LOFS_PATCH_MNT, "lofs"); ret = BAM_ERROR; } @@ -2255,7 +2278,7 @@ update_all(char *root, char *opt) */ (void) snprintf(multibt, sizeof (multibt), "/sbin/umount %s", LOFS_PATCH_MNT); - if (exec_cmd(multibt, NULL, 0) != 0) { + if (exec_cmd(multibt, NULL) != 0) { bam_error(UMOUNT_FAILED, LOFS_PATCH_MNT); ret = BAM_ERROR; } @@ -2292,10 +2315,10 @@ update_all(char *root, char *opt) if (strcmp(mnt.mnt_mountp, "/") == 0) continue; - (void) snprintf(multibt, sizeof (multibt), "%s%s", - mnt.mnt_mountp, MULTI_BOOT); + (void) snprintf(creatram, sizeof (creatram), "%s/%s", + mnt.mnt_mountp, CREATE_RAMDISK); - if (stat(multibt, &sb) == -1) + if (stat(creatram, &sb) == -1) continue; /* @@ -3019,7 +3042,7 @@ open_diskmap(char *root) fp = fopen(GRUBDISK_MAP, "r"); if (fp == NULL) { (void) snprintf(cmd, sizeof (cmd), - "%s%s > /dev/null", root, CREATE_DISKMAP); + "%s/%s > /dev/null", root, CREATE_DISKMAP); (void) system(cmd); fp = fopen(GRUBDISK_MAP, "r"); } @@ -4341,12 +4364,11 @@ menu_free(menu_t *mp) * Any other value indicates an error */ static int -exec_cmd(char *cmdline, char *output, int64_t osize) +exec_cmd(char *cmdline, filelist_t *flistp) { char buf[BUFSIZ]; int ret; FILE *ptr; - size_t len; sigset_t set; void (*disp)(int); @@ -4407,14 +4429,12 @@ exec_cmd(char *cmdline, char *output, int64_t osize) * we can safely reap the exit status of the command * from the value returned by pclose() */ - while (fgets(buf, sizeof (buf), ptr) != NULL) { - /* if (bam_verbose) XXX */ - bam_print(PRINT_NO_NEWLINE, buf); - if (output && osize > 0) { - (void) snprintf(output, osize, "%s", buf); - len = strlen(buf); - output += len; - osize -= len; + while (s_fgets(buf, sizeof (buf), ptr) != NULL) { + if (flistp == NULL) { + /* s_fgets strips newlines, so insert them at the end */ + bam_print(PRINT, buf); + } else { + append_to_flist(flistp, buf); } } @@ -4551,6 +4571,33 @@ is_amd64(void) return (amd64); } +static int +is_sun4u(void) +{ + static int sun4u = 0; + char mbuf[257]; /* from sysinfo(2) manpage */ + + if (sysinfo(SI_MACHINE, mbuf, sizeof (mbuf)) > 0 && + strncmp(mbuf, "sun4u", strlen("sun4u")) == 0) + sun4u = 1; + + return (sun4u); +} + +static int +is_sun4v(void) +{ + static int sun4v = 0; + char mbuf[257]; /* from sysinfo(2) manpage */ + + if (sysinfo(SI_MACHINE, mbuf, sizeof (mbuf)) > 0 && + strncmp(mbuf, "sun4v", strlen("sun4v")) == 0) + sun4v = 1; + + return (sun4v); +} + + static void append_to_flist(filelist_t *flistp, char *s) { @@ -4565,7 +4612,7 @@ append_to_flist(filelist_t *flistp, char *s) flistp->tail = lp; } -#if defined(__i386) +#if !defined(_OPB) UCODE_VENDORS; |
