usr/src/cmd/boot/bootadm/bootadm.c
changeset 6423 437422a29d3a
parent 6319 03c1299ed2bb
child 6448 dfd58b2129f6
equal deleted inserted replaced
6422:d51a10d738ba 6423:437422a29d3a
    52 #include <strings.h>
    52 #include <strings.h>
    53 #include <utime.h>
    53 #include <utime.h>
    54 #include <sys/systeminfo.h>
    54 #include <sys/systeminfo.h>
    55 #include <sys/dktp/fdisk.h>
    55 #include <sys/dktp/fdisk.h>
    56 #include <sys/param.h>
    56 #include <sys/param.h>
       
    57 #include <sys/sysmacros.h>
    57 
    58 
    58 #if !defined(_OPB)
    59 #if !defined(_OPB)
    59 #include <sys/ucode.h>
    60 #include <sys/ucode.h>
    60 #endif
    61 #endif
    61 
    62 
   195 static char **bam_argv;
   196 static char **bam_argv;
   196 static int bam_argc;
   197 static int bam_argc;
   197 static int bam_check;
   198 static int bam_check;
   198 static int bam_smf_check;
   199 static int bam_smf_check;
   199 static int bam_lock_fd = -1;
   200 static int bam_lock_fd = -1;
       
   201 static int bam_zfs;
   200 static char rootbuf[PATH_MAX] = "/";
   202 static char rootbuf[PATH_MAX] = "/";
   201 static int bam_update_all;
   203 static int bam_update_all;
   202 static int bam_alt_platform;
   204 static int bam_alt_platform;
   203 static char *bam_platform;
   205 static char *bam_platform;
   204 
   206 
   240 static long s_strtol(char *);
   242 static long s_strtol(char *);
   241 static int s_fputs(char *, FILE *);
   243 static int s_fputs(char *, FILE *);
   242 
   244 
   243 static char *s_strdup(char *);
   245 static char *s_strdup(char *);
   244 static int is_readonly(char *);
   246 static int is_readonly(char *);
       
   247 static int is_zfs(char *, char **);
   245 static int is_amd64(void);
   248 static int is_amd64(void);
   246 static int is_sun4u(void);
   249 static int is_sun4u(void);
   247 static int is_sun4v(void);
   250 static int is_sun4v(void);
   248 static void append_to_flist(filelist_t *, char *);
   251 static void append_to_flist(filelist_t *, char *);
   249 
   252 
   417 
   420 
   418 	/* Suppress error message from getopt */
   421 	/* Suppress error message from getopt */
   419 	opterr = 0;
   422 	opterr = 0;
   420 
   423 
   421 	error = 0;
   424 	error = 0;
   422 	while ((c = getopt(argc, argv, "a:d:fm:no:vCR:p:")) != -1) {
   425 	while ((c = getopt(argc, argv, "a:d:fm:no:vCR:p:Z")) != -1) {
   423 		switch (c) {
   426 		switch (c) {
   424 		case 'a':
   427 		case 'a':
   425 			if (bam_cmd) {
   428 			if (bam_cmd) {
   426 				error = 1;
   429 				error = 1;
   427 				bam_error(MULT_CMDS, c);
   430 				bam_error(MULT_CMDS, c);
   498 			    (strcmp(bam_platform, "sun4v") != 0)) {
   501 			    (strcmp(bam_platform, "sun4v") != 0)) {
   499 				error = 1;
   502 				error = 1;
   500 				bam_error(INVALID_PLAT, bam_platform);
   503 				bam_error(INVALID_PLAT, bam_platform);
   501 			}
   504 			}
   502 			break;
   505 			break;
       
   506 		case 'Z':
       
   507 			bam_zfs = 1;
       
   508 			break;
   503 		case '?':
   509 		case '?':
   504 			error = 1;
   510 			error = 1;
   505 			bam_error(BAD_OPT, optopt);
   511 			bam_error(BAD_OPT, optopt);
   506 			break;
   512 			break;
   507 		default :
   513 		default :
   891 bam_menu(char *subcmd, char *opt, int largc, char *largv[])
   897 bam_menu(char *subcmd, char *opt, int largc, char *largv[])
   892 {
   898 {
   893 	error_t ret;
   899 	error_t ret;
   894 	char menu_path[PATH_MAX];
   900 	char menu_path[PATH_MAX];
   895 	char path[PATH_MAX];
   901 	char path[PATH_MAX];
       
   902 	char full_menu_root[PATH_MAX];
   896 	menu_t *menu;
   903 	menu_t *menu;
   897 	char *mntpt, *menu_root, *logslice, *fstype;
   904 	char *mntpt, *menu_root, *logslice, *fstype, *grubSLICEpool, *pool;
   898 	struct stat sb;
   905 	struct stat sb;
   899 	int mnted;	/* set if we did a mount */
   906 	int mnted;	/* set if we did a mount */
   900 	error_t (*f)(menu_t *mp, char *menu_path, char *opt);
   907 	error_t (*f)(menu_t *mp, char *menu_path, char *opt);
   901 	char *rootpath;
   908 	char *rootpath;
   902 
   909 
   917 		return (BAM_ERROR);
   924 		return (BAM_ERROR);
   918 	}
   925 	}
   919 
   926 
   920 	mntpt = NULL;
   927 	mntpt = NULL;
   921 	mnted = 0;
   928 	mnted = 0;
   922 	logslice = fstype = NULL;
   929 	logslice = fstype = grubSLICEpool = pool = NULL;
   923 
   930 
   924 	/*
   931 	/*
   925 	 * Check for the menu.list file:
   932 	 * Check for the menu.list file:
   926 	 *
   933 	 *
   927 	 * 1. Check for a GRUB_slice file, be it on / or
   934 	 * 1. Check for a GRUB_slice file, be it on / or
   929 	 * 2. Use the alternate root, if given.
   936 	 * 2. Use the alternate root, if given.
   930 	 * 3. Check /stubboot
   937 	 * 3. Check /stubboot
   931 	 * 4. Use /
   938 	 * 4. Use /
   932 	 */
   939 	 */
   933 	if (bam_alt_root) {
   940 	if (bam_alt_root) {
   934 		(void) snprintf(path, sizeof (path), "%s%s", bam_root,
   941 		if (is_zfs(bam_root, &grubSLICEpool))
   935 		    GRUB_slice);
   942 			(void) snprintf(path, sizeof (path), "%s/%s%s",
       
   943 			    bam_root, grubSLICEpool, GRUB_slice);
       
   944 		else
       
   945 			(void) snprintf(path, sizeof (path), "%s%s",
       
   946 			    bam_root, GRUB_slice);
   936 	} else {
   947 	} else {
   937 		(void) snprintf(path, sizeof (path), "%s", GRUB_slice);
   948 		if (is_zfs(bam_root, &grubSLICEpool))
       
   949 			(void) snprintf(path, sizeof (path), "/%s%s",
       
   950 			    grubSLICEpool, GRUB_slice);
       
   951 		else
       
   952 			(void) snprintf(path, sizeof (path), "%s", GRUB_slice);
   938 	}
   953 	}
   939 
   954 
   940 	if (stat(path, &sb) == 0) {
   955 	if (stat(path, &sb) == 0) {
   941 		mntpt = mount_grub_slice(&mnted, NULL, &logslice, &fstype);
   956 		mntpt = mount_grub_slice(&mnted, NULL, &logslice, &fstype);
   942 		menu_root = mntpt;
   957 		menu_root = mntpt;
   951 	if (menu_root == NULL) {
   966 	if (menu_root == NULL) {
   952 		bam_error(CANNOT_LOCATE_GRUB_MENU);
   967 		bam_error(CANNOT_LOCATE_GRUB_MENU);
   953 		return (BAM_ERROR);
   968 		return (BAM_ERROR);
   954 	}
   969 	}
   955 
   970 
   956 	elide_trailing_slash(menu_root, menu_path, sizeof (menu_path));
   971 	/*
       
   972 	 * menu_root is the root file system of the boot environment being
       
   973 	 *    operated on.
       
   974 	 * full_menu_root is the location of the /boot/grub directory.
       
   975 	 *    With a ufs root, this is simply menu_root.  With a zfs
       
   976 	 *    root, it's <menu_root>/<poolname>
       
   977 	 */
       
   978 	elide_trailing_slash(menu_root, full_menu_root,
       
   979 	    sizeof (full_menu_root));
       
   980 
       
   981 	if (is_zfs(menu_root, &pool)) {
       
   982 		(void) strlcat(full_menu_root, "/", sizeof (full_menu_root));
       
   983 		(void) strlcat(full_menu_root, pool, sizeof (full_menu_root));
       
   984 	}
       
   985 
       
   986 	/*
       
   987 	 * menu_path is the directory that contains the menu.lst file
       
   988 	 */
       
   989 	(void) strlcpy(menu_path, full_menu_root, sizeof (menu_path));
   957 	(void) strlcat(menu_path, GRUB_MENU, sizeof (menu_path));
   990 	(void) strlcat(menu_path, GRUB_MENU, sizeof (menu_path));
   958 
   991 
   959 	/*
   992 	/*
   960 	 * If listing the menu, display the active menu
   993 	 * If listing the menu, display the active menu
   961 	 * location
   994 	 * location
   997 	    (strcmp(subcmd, "upgrade") == 0))
  1030 	    (strcmp(subcmd, "upgrade") == 0))
   998 		ret = f(menu, bam_root, opt);
  1031 		ret = f(menu, bam_root, opt);
   999 	else
  1032 	else
  1000 		ret = f(menu, menu_path, opt);
  1033 		ret = f(menu, menu_path, opt);
  1001 	if (ret == BAM_WRITE) {
  1034 	if (ret == BAM_WRITE) {
  1002 		ret = menu_write(menu_root, menu);
  1035 		ret = menu_write(full_menu_root, menu);
  1003 	}
  1036 	}
  1004 
  1037 
  1005 	menu_free(menu);
  1038 	menu_free(menu);
  1006 
  1039 
  1007 	umount_grub_slice(mnted, mntpt, NULL, logslice, fstype);
  1040 	umount_grub_slice(mnted, mntpt, NULL, logslice, fstype);
  1008 
  1041 
       
  1042 	if (grubSLICEpool)
       
  1043 		free(grubSLICEpool);
       
  1044 	if (pool)
       
  1045 		free(pool);
  1009 	return (ret);
  1046 	return (ret);
  1010 }
  1047 }
  1011 
  1048 
  1012 
  1049 
  1013 static error_t
  1050 static error_t
  2091 	}
  2128 	}
  2092 
  2129 
  2093 	return (0);
  2130 	return (0);
  2094 }
  2131 }
  2095 
  2132 
       
  2133 static int
       
  2134 is_zfs(char *root, char **poolname)
       
  2135 {
       
  2136 	struct statvfs64 vfs;
       
  2137 	FILE *fp;
       
  2138 	struct extmnttab mnt;
       
  2139 	dev_t devicenum;
       
  2140 	char *special = NULL;
       
  2141 	char *cp;
       
  2142 
       
  2143 	/* poolname can be null */
       
  2144 	if (poolname)
       
  2145 		*poolname = NULL;
       
  2146 
       
  2147 	if (statvfs64(root, &vfs) != 0) {
       
  2148 		if (bam_verbose)
       
  2149 			bam_error(STATVFS_FAIL, root, strerror(errno));
       
  2150 		return (0);
       
  2151 	}
       
  2152 
       
  2153 	if (strncmp(vfs.f_basetype, "zfs", strlen("zfs")) != 0)
       
  2154 		return (0);
       
  2155 
       
  2156 	if (poolname == NULL)
       
  2157 		return (1);
       
  2158 
       
  2159 	/*
       
  2160 	 * Now find the mnttab entry so that we can extract the
       
  2161 	 * pool name from the special device field.
       
  2162 	 */
       
  2163 	fp = fopen(MNTTAB, "r");
       
  2164 	if (fp == NULL) {
       
  2165 		bam_error(OPEN_FAIL, MNTTAB, strerror(errno));
       
  2166 		return (0);
       
  2167 	}
       
  2168 
       
  2169 	resetmnttab(fp);
       
  2170 
       
  2171 	while (getextmntent(fp, &mnt, sizeof (mnt)) == 0) {
       
  2172 		devicenum = makedevice(mnt.mnt_major, mnt.mnt_minor);
       
  2173 		if (devicenum == vfs.f_fsid) {
       
  2174 			special = s_strdup(mnt.mnt_special);
       
  2175 			if ((cp = strchr(special, '/')) != NULL)
       
  2176 				*cp = '\0';
       
  2177 			*poolname = s_strdup(special);
       
  2178 			break;
       
  2179 		}
       
  2180 	}
       
  2181 
       
  2182 	(void) fclose(fp);
       
  2183 
       
  2184 	if (special) {
       
  2185 		free(special);
       
  2186 		return (1);
       
  2187 	}
       
  2188 
       
  2189 	return (0);
       
  2190 }
       
  2191 
  2096 static error_t
  2192 static error_t
  2097 update_archive(char *root, char *opt)
  2193 update_archive(char *root, char *opt)
  2098 {
  2194 {
  2099 	error_t ret;
  2195 	error_t ret;
  2100 
  2196 
  3478 	}
  3574 	}
  3479 
  3575 
  3480 	/* add the entry for normal Solaris */
  3576 	/* add the entry for normal Solaris */
  3481 	if (bam_direct == BAM_DIRECT_DBOOT) {
  3577 	if (bam_direct == BAM_DIRECT_DBOOT) {
  3482 		entry = update_boot_entry(mp, title, grubdisk,
  3578 		entry = update_boot_entry(mp, title, grubdisk,
  3483 		    DIRECT_BOOT_KERNEL, NULL, DIRECT_BOOT_ARCHIVE,
  3579 		    (bam_zfs ? DIRECT_BOOT_KERNEL_ZFS : DIRECT_BOOT_KERNEL),
  3484 		    osroot == menu_root);
  3580 		    NULL, DIRECT_BOOT_ARCHIVE, osroot == menu_root);
  3485 		if ((entry != BAM_ERROR) && (bam_is_hv == BAM_HV_PRESENT)) {
  3581 		if ((entry != BAM_ERROR) && (bam_is_hv == BAM_HV_PRESENT)) {
  3486 			(void) update_boot_entry(mp, NEW_HV_ENTRY, grubdisk,
  3582 			(void) update_boot_entry(mp, NEW_HV_ENTRY, grubdisk,
  3487 			    XEN_MENU, KERNEL_MODULE_LINE, DIRECT_BOOT_ARCHIVE,
  3583 			    XEN_MENU, (bam_zfs ?
  3488 			    osroot == menu_root);
  3584 			    KERNEL_MODULE_LINE_ZFS : KERNEL_MODULE_LINE),
       
  3585 			    DIRECT_BOOT_ARCHIVE, osroot == menu_root);
  3489 		}
  3586 		}
  3490 	} else {
  3587 	} else {
  3491 		entry = update_boot_entry(mp, title, grubdisk, MULTI_BOOT,
  3588 		entry = update_boot_entry(mp, title, grubdisk, MULTI_BOOT,
  3492 		    NULL, MULTI_BOOT_ARCHIVE, osroot == menu_root);
  3589 		    NULL, MULTI_BOOT_ARCHIVE, osroot == menu_root);
  3493 	}
  3590 	}
  3501 
  3598 
  3502 		/* Figure out where the kernel line should point */
  3599 		/* Figure out where the kernel line should point */
  3503 		(void) snprintf(failsafe, sizeof (failsafe), "%s%s", osroot,
  3600 		(void) snprintf(failsafe, sizeof (failsafe), "%s%s", osroot,
  3504 		    DIRECT_BOOT_FAILSAFE_KERNEL);
  3601 		    DIRECT_BOOT_FAILSAFE_KERNEL);
  3505 		if (stat(failsafe, &sbuf) == 0) {
  3602 		if (stat(failsafe, &sbuf) == 0) {
  3506 			failsafe_kernel = DIRECT_BOOT_FAILSAFE_LINE;
  3603 			failsafe_kernel =
       
  3604 			    (bam_zfs ? DIRECT_BOOT_FAILSAFE_LINE_ZFS :
       
  3605 			    DIRECT_BOOT_FAILSAFE_LINE);
  3507 		} else {
  3606 		} else {
  3508 			(void) snprintf(failsafe, sizeof (failsafe), "%s%s",
  3607 			(void) snprintf(failsafe, sizeof (failsafe), "%s%s",
  3509 			    osroot, MULTI_BOOT_FAILSAFE);
  3608 			    osroot, MULTI_BOOT_FAILSAFE);
  3510 			if (stat(failsafe, &sbuf) == 0) {
  3609 			if (stat(failsafe, &sbuf) == 0) {
  3511 				failsafe_kernel = MULTI_BOOT_FAILSAFE_LINE;
  3610 				failsafe_kernel = MULTI_BOOT_FAILSAFE_LINE;