101
102 typedef enum {
103 OPT_ABSENT = 0, /* No option */
104 OPT_REQ, /* option required */
105 OPT_OPTIONAL /* option may or may not be present */
106 } option_t;
107
108 typedef struct {
109 char *subcmd;
110 option_t option;
111 error_t (*handler)();
112 int unpriv; /* is this an unprivileged command */
113 } subcmd_defn_t;
114
115 #define LINE_INIT 0 /* lineNum initial value */
116 #define ENTRY_INIT -1 /* entryNum initial value */
117 #define ALL_ENTRIES -2 /* selects all boot entries */
118
119 #define GRUB_DIR "/boot/grub"
120 #define GRUB_STAGE2 GRUB_DIR "/stage2"
121 #define GRUB_MENU "/boot/grub/menu.lst"
122 #define MENU_TMP "/boot/grub/menu.lst.tmp"
123 #define GRUB_BACKUP_MENU "/etc/lu/GRUB_backup_menu"
124 #define RAMDISK_SPECIAL "/ramdisk"
125 #define STUBBOOT "/stubboot"
126 #define MULTIBOOT "/platform/i86pc/multiboot"
127 #define GRUBSIGN_DIR "/boot/grub/bootsign"
128 #define GRUBSIGN_BACKUP "/etc/bootsign"
129 #define GRUBSIGN_UFS_PREFIX "rootfs"
130 #define GRUBSIGN_ZFS_PREFIX "pool_"
131 #define GRUBSIGN_LU_PREFIX "BE_"
132 #define UFS_SIGNATURE_LIST "/var/run/grub_ufs_signatures"
133 #define ZFS_LEGACY_MNTPT "/tmp/bootadm_mnt_zfs_legacy"
134
135 #define BOOTADM_RDONLY_TEST "BOOTADM_RDONLY_TEST"
136
137 /* lock related */
138 #define BAM_LOCK_FILE "/var/run/bootadm.lock"
139 #define LOCK_FILE_PERMS (S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH)
140
141 #define CREATE_RAMDISK "boot/solaris/bin/create_ramdisk"
142 #define CREATE_DISKMAP "boot/solaris/bin/create_diskmap"
161 typedef enum zfs_mnted {
162 ZFS_MNT_ERROR = -1,
163 LEGACY_MOUNTED = 1,
164 LEGACY_ALREADY,
165 ZFS_MOUNTED,
166 ZFS_ALREADY
167 } zfs_mnted_t;
168
169 /*
170 * Default file attributes
171 */
172 #define DEFAULT_DEV_MODE 0644 /* default permissions */
173 #define DEFAULT_DEV_UID 0 /* user root */
174 #define DEFAULT_DEV_GID 3 /* group sys */
175
176 /*
177 * Menu related
178 * menu_cmd_t and menu_cmds must be kept in sync
179 */
180 char *menu_cmds[] = {
181 "default", /* DEFAULT_CMD */
182 "timeout", /* TIMEOUT_CMD */
183 "title", /* TITLE_CMD */
184 "root", /* ROOT_CMD */
185 "kernel", /* KERNEL_CMD */
186 "kernel$", /* KERNEL_DOLLAR_CMD */
187 "module", /* MODULE_CMD */
188 "module$", /* MODULE_DOLLAR_CMD */
189 " ", /* SEP_CMD */
190 "#", /* COMMENT_CMD */
191 "chainloader", /* CHAINLOADER_CMD */
192 "args", /* ARGS_CMD */
193 "findroot", /* FINDROOT_CMD */
194 "bootfs", /* BOOTFS_CMD */
195 NULL
196 };
197
198 #define OPT_ENTRY_NUM "entry"
199
200 /*
201 * exec_cmd related
202 */
203 typedef struct {
204 line_t *head;
205 line_t *tail;
206 } filelist_t;
207
208 #define BOOT_FILE_LIST "boot/solaris/filelist.ramdisk"
209 #define ETC_FILE_LIST "etc/boot/solaris/filelist.ramdisk"
210
211 #define FILE_STAT "boot/solaris/filestat.ramdisk"
212 #define FILE_STAT_TMP "boot/solaris/filestat.ramdisk.tmp"
213 #define DIR_PERMS (S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH)
214 #define FILE_STAT_MODE (S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH)
4673 }
4674
4675 return (BAM_SUCCESS);
4676 }
4677
4678 int
4679 add_boot_entry(menu_t *mp,
4680 char *title,
4681 char *findroot,
4682 char *kernel,
4683 char *mod_kernel,
4684 char *module,
4685 char *bootfs)
4686 {
4687 int lineNum;
4688 int entryNum;
4689 char linebuf[BAM_MAXLINE];
4690 menu_cmd_t k_cmd;
4691 menu_cmd_t m_cmd;
4692 const char *fcn = "add_boot_entry()";
4693
4694 assert(mp);
4695
4696 INJECT_ERROR1("ADD_BOOT_ENTRY_FINDROOT_NULL", findroot = NULL);
4697 if (findroot == NULL) {
4698 bam_error(NULL_FINDROOT);
4699 return (BAM_ERROR);
4700 }
4701
4702 if (title == NULL) {
4703 title = "Solaris"; /* default to Solaris */
4704 }
4705 if (kernel == NULL) {
4706 bam_error(SUBOPT_MISS, menu_cmds[KERNEL_CMD]);
4707 return (BAM_ERROR);
4708 }
4709 if (module == NULL) {
4710 if (bam_direct != BAM_DIRECT_DBOOT) {
4711 bam_error(SUBOPT_MISS, menu_cmds[MODULE_CMD]);
4712 return (BAM_ERROR);
4739 */
4740 (void) snprintf(linebuf, sizeof (linebuf), "%s%s",
4741 menu_cmds[COMMENT_CMD], BAM_BOOTADM_HDR);
4742 line_parser(mp, linebuf, &lineNum, &entryNum);
4743
4744 (void) snprintf(linebuf, sizeof (linebuf), "%s%s%s",
4745 menu_cmds[TITLE_CMD], menu_cmds[SEP_CMD], title);
4746 line_parser(mp, linebuf, &lineNum, &entryNum);
4747
4748 (void) snprintf(linebuf, sizeof (linebuf), "%s%s%s",
4749 menu_cmds[FINDROOT_CMD], menu_cmds[SEP_CMD], findroot);
4750 line_parser(mp, linebuf, &lineNum, &entryNum);
4751 BAM_DPRINTF((D_ADD_FINDROOT_NUM, fcn, lineNum, entryNum));
4752
4753 if (bootfs != NULL) {
4754 (void) snprintf(linebuf, sizeof (linebuf), "%s%s%s",
4755 menu_cmds[BOOTFS_CMD], menu_cmds[SEP_CMD], bootfs);
4756 line_parser(mp, linebuf, &lineNum, &entryNum);
4757 }
4758
4759 (void) snprintf(linebuf, sizeof (linebuf), "%s%s%s",
4760 menu_cmds[k_cmd], menu_cmds[SEP_CMD], kernel);
4761 line_parser(mp, linebuf, &lineNum, &entryNum);
4762
4763 if (mod_kernel != NULL) {
4764 (void) snprintf(linebuf, sizeof (linebuf), "%s%s%s",
4765 menu_cmds[m_cmd], menu_cmds[SEP_CMD], mod_kernel);
4766 line_parser(mp, linebuf, &lineNum, &entryNum);
4767 }
4768
4769 (void) snprintf(linebuf, sizeof (linebuf), "%s%s%s",
4770 menu_cmds[m_cmd], menu_cmds[SEP_CMD], module);
4771 line_parser(mp, linebuf, &lineNum, &entryNum);
4772
4773 (void) snprintf(linebuf, sizeof (linebuf), "%s%s",
4774 menu_cmds[COMMENT_CMD], BAM_BOOTADM_FTR);
4775 line_parser(mp, linebuf, &lineNum, &entryNum);
4776
4777 return (entryNum);
4778 }
4779
4780 error_t
4781 delete_boot_entry(menu_t *mp, int entryNum, int quiet)
4782 {
7095 (void) unlink(UFS_SIGNATURE_LIST);
7096 return (NULL);
7097 }
7098
7099 free(fstype);
7100
7101 if (bam_verbose)
7102 bam_print(GRUBSIGN_FOUND_OR_CREATED, sign, osdev);
7103
7104 fdiskpart = get_partition(osdev);
7105 INJECT_ERROR1("GET_GRUBSIGN_FDISK", fdiskpart = -1);
7106 if (fdiskpart == -1) {
7107 bam_error(FDISKPART_FAIL, osdev);
7108 free(sign);
7109 return (NULL);
7110 }
7111
7112 slice = strrchr(osdev, 's');
7113
7114 grubsign = s_calloc(1, MAXNAMELEN + 10);
7115 if (slice) {
7116 (void) snprintf(grubsign, MAXNAMELEN + 10, "(%s,%d,%c)",
7117 sign, fdiskpart, slice[1] + 'a' - '0');
7118 } else
7119 (void) snprintf(grubsign, MAXNAMELEN + 10, "(%s,%d)",
7120 sign, fdiskpart);
7121
7122 free(sign);
7123
7124 BAM_DPRINTF((D_GET_GRUBSIGN_SUCCESS, fcn, grubsign));
7125
7126 return (grubsign);
7127 }
7128
7129 static char *
7130 get_title(char *rootdir)
7131 {
7132 static char title[80];
7133 char *cp = NULL;
7134 char release[PATH_MAX];
7135 FILE *fp;
7136 const char *fcn = "get_title()";
7137
7138 /* open the /etc/release file */
7139 (void) snprintf(release, sizeof (release), "%s/etc/release", rootdir);
7140
7141 fp = fopen(release, "r");
7142 if (fp == NULL) {
7143 bam_error(OPEN_FAIL, release, strerror(errno));
7144 cp = NULL;
7145 goto out;
7146 }
7795 BAM_DPRINTF((D_MATCHED_TITLE, fcn, title));
7796 break;
7797 }
7798 BAM_DPRINTF((D_NOMATCH_TITLE, fcn, title, lp->arg));
7799 continue; /* check title only */
7800 }
7801
7802 lp = lp->next; /* advance to root line */
7803 if (lp == NULL) {
7804 continue;
7805 } else if (lp->cmd != NULL &&
7806 strcmp(lp->cmd, menu_cmds[FINDROOT_CMD]) == 0) {
7807 INJECT_ERROR1("FIND_BOOT_ENTRY_NULL_FINDROOT",
7808 findroot = NULL);
7809 if (findroot == NULL) {
7810 BAM_DPRINTF((D_NOMATCH_FINDROOT_NULL,
7811 fcn, lp->arg));
7812 continue;
7813 }
7814 /* findroot command found, try match */
7815 if (strcmp(lp->arg, findroot) != 0) {
7816 BAM_DPRINTF((D_NOMATCH_FINDROOT,
7817 fcn, findroot, lp->arg));
7818 continue;
7819 }
7820 BAM_DPRINTF((D_MATCHED_FINDROOT, fcn, findroot));
7821 lp = lp->next; /* advance to kernel line */
7822 } else if (lp->cmd != NULL &&
7823 strcmp(lp->cmd, menu_cmds[ROOT_CMD]) == 0) {
7824 INJECT_ERROR1("FIND_BOOT_ENTRY_NULL_ROOT", root = NULL);
7825 if (root == NULL) {
7826 BAM_DPRINTF((D_NOMATCH_ROOT_NULL,
7827 fcn, lp->arg));
7828 continue;
7829 }
7830 /* root cmd found, try match */
7831 if (strcmp(lp->arg, root) != 0) {
7832 BAM_DPRINTF((D_NOMATCH_ROOT,
7833 fcn, root, lp->arg));
7834 continue;
7835 }
7853 }
7854
7855 if (kernel &&
7856 (!check_cmd(lp->cmd, KERNEL_CMD, lp->arg, kernel))) {
7857 if (!(ent->flags & BAM_ENTRY_FAILSAFE) ||
7858 !(ent->flags & BAM_ENTRY_DBOOT) ||
7859 strcmp(kernel, DIRECT_BOOT_FAILSAFE_LINE) != 0)
7860 continue;
7861
7862 ent->flags |= BAM_ENTRY_UPGFSKERNEL;
7863
7864 }
7865 BAM_DPRINTF((D_KERNEL_MATCH, fcn, kernel, lp->arg));
7866
7867 /*
7868 * Check for matching module entry (failsafe or normal).
7869 * If it fails to match, we go around the loop again.
7870 * For xpv entries, there are two module lines, so we
7871 * do the check twice.
7872 */
7873 lp = lp->next; /* advance to module line */
7874 if (check_cmd(lp->cmd, MODULE_CMD, lp->arg, module) ||
7875 (((lp = lp->next) != NULL) &&
7876 check_cmd(lp->cmd, MODULE_CMD, lp->arg, module))) {
7877 /* match found */
7878 BAM_DPRINTF((D_MODULE_MATCH, fcn, module, lp->arg));
7879 break;
7880 }
7881
7882 if (strcmp(module, FAILSAFE_ARCHIVE) == 0 &&
7883 (strcmp(lp->prev->arg, FAILSAFE_ARCHIVE_32) == 0 ||
7884 strcmp(lp->prev->arg, FAILSAFE_ARCHIVE_64) == 0)) {
7885 ent->flags |= BAM_ENTRY_UPGFSMODULE;
7886 break;
7887 }
7888
7889 }
7890
7891 if (ent && entry_num) {
7892 *entry_num = i;
7894
7895 if (ent) {
7896 BAM_DPRINTF((D_RETURN_RET, fcn, i));
7897 } else {
7898 BAM_DPRINTF((D_RETURN_RET, fcn, BAM_ERROR));
7899 }
7900 return (ent);
7901 }
7902
7903 static int
7904 update_boot_entry(menu_t *mp, char *title, char *findroot, char *root,
7905 char *kernel, char *mod_kernel, char *module, int root_opt)
7906 {
7907 int i;
7908 int change_kernel = 0;
7909 entry_t *ent;
7910 line_t *lp;
7911 line_t *tlp;
7912 char linebuf[BAM_MAXLINE];
7913 const char *fcn = "update_boot_entry()";
7914
7915 /* note: don't match on title, it's updated on upgrade */
7916 ent = find_boot_entry(mp, NULL, kernel, findroot, root, module,
7917 root_opt, &i);
7918 if ((ent == NULL) && (bam_direct == BAM_DIRECT_DBOOT)) {
7919 /*
7920 * We may be upgrading a kernel from multiboot to
7921 * directboot. Look for a multiboot entry. A multiboot
7922 * entry will not have a findroot line.
7923 */
7924 ent = find_boot_entry(mp, NULL, "multiboot", NULL, root,
7925 MULTIBOOT_ARCHIVE, root_opt, &i);
7926 if (ent != NULL) {
7927 BAM_DPRINTF((D_UPGRADE_FROM_MULTIBOOT, fcn, root));
7928 change_kernel = 1;
7929 }
7930 } else if (ent) {
7931 BAM_DPRINTF((D_FOUND_FINDROOT, fcn, findroot));
7932 }
7933
7950
7951 tlp = lp; /* title line */
7952 lp = lp->next; /* root line */
7953
7954 /* if no root or findroot command, create a new line_t */
7955 if ((lp->cmd != NULL) && (strcmp(lp->cmd, menu_cmds[ROOT_CMD]) != 0 &&
7956 strcmp(lp->cmd, menu_cmds[FINDROOT_CMD]) != 0)) {
7957 lp = s_calloc(1, sizeof (line_t));
7958 bam_add_line(mp, ent, tlp, lp);
7959 } else {
7960 if (lp->cmd != NULL)
7961 free(lp->cmd);
7962
7963 free(lp->sep);
7964 free(lp->arg);
7965 free(lp->line);
7966 }
7967
7968 lp->cmd = s_strdup(menu_cmds[FINDROOT_CMD]);
7969 lp->sep = s_strdup(menu_cmds[SEP_CMD]);
7970 lp->arg = s_strdup(findroot);
7971 (void) snprintf(linebuf, sizeof (linebuf), "%s%s%s",
7972 menu_cmds[FINDROOT_CMD], menu_cmds[SEP_CMD], findroot);
7973 lp->line = s_strdup(linebuf);
7974 BAM_DPRINTF((D_ADDING_FINDROOT_LINE, fcn, findroot));
7975
7976 /* kernel line */
7977 lp = lp->next;
7978
7979 if (ent->flags & BAM_ENTRY_UPGFSKERNEL) {
7980 char *params = NULL;
7981
7982 params = strstr(lp->line, "-s");
7983 if (params != NULL)
7984 (void) snprintf(linebuf, sizeof (linebuf), "%s%s%s%s",
7985 menu_cmds[KERNEL_DOLLAR_CMD], menu_cmds[SEP_CMD],
7986 kernel, params+2);
7987 else
7988 (void) snprintf(linebuf, sizeof (linebuf), "%s%s%s",
7989 menu_cmds[KERNEL_DOLLAR_CMD], menu_cmds[SEP_CMD],
7990 kernel);
7991
7992 if (lp->cmd != NULL)
7993 free(lp->cmd);
7994
7995 free(lp->arg);
7996 free(lp->line);
7997 lp->cmd = s_strdup(menu_cmds[KERNEL_DOLLAR_CMD]);
7998 lp->arg = s_strdup(strstr(linebuf, "/"));
7999 lp->line = s_strdup(linebuf);
8000 ent->flags &= ~BAM_ENTRY_UPGFSKERNEL;
8001 BAM_DPRINTF((D_ADDING_KERNEL_DOLLAR, fcn, lp->prev->cmd));
8002 }
8003
8004 if (change_kernel) {
8005 /*
8006 * We're upgrading from multiboot to directboot.
8007 */
8008 if (lp->cmd != NULL &&
8009 strcmp(lp->cmd, menu_cmds[KERNEL_CMD]) == 0) {
8010 (void) snprintf(linebuf, sizeof (linebuf), "%s%s%s",
8011 menu_cmds[KERNEL_DOLLAR_CMD], menu_cmds[SEP_CMD],
8012 kernel);
8013 free(lp->cmd);
8014 free(lp->arg);
8015 free(lp->line);
8016 lp->cmd = s_strdup(menu_cmds[KERNEL_DOLLAR_CMD]);
8017 lp->arg = s_strdup(kernel);
8018 lp->line = s_strdup(linebuf);
8019 lp = lp->next;
8020 BAM_DPRINTF((D_ADDING_KERNEL_DOLLAR, fcn, kernel));
8021 }
8022 if (lp->cmd != NULL &&
8023 strcmp(lp->cmd, menu_cmds[MODULE_CMD]) == 0) {
8024 (void) snprintf(linebuf, sizeof (linebuf), "%s%s%s",
8025 menu_cmds[MODULE_DOLLAR_CMD], menu_cmds[SEP_CMD],
8026 module);
8027 free(lp->cmd);
8028 free(lp->arg);
8029 free(lp->line);
8030 lp->cmd = s_strdup(menu_cmds[MODULE_DOLLAR_CMD]);
8031 lp->arg = s_strdup(module);
8032 lp->line = s_strdup(linebuf);
8033 lp = lp->next;
8034 BAM_DPRINTF((D_ADDING_MODULE_DOLLAR, fcn, module));
8035 }
8036 }
8037
8038 /* module line */
8039 lp = lp->next;
8040
8929 sizeof (DIRECT_BOOT_KERNEL) - 1) == 0))) {
8930 kernelp = NULL;
8931 (void) delete_boot_entry(mp, entryNum, DBE_PRINTERR);
8932 restore_default_entry(mp, BAM_OLD_RC_DEF,
8933 mp->old_rc_default);
8934 mp->old_rc_default = NULL;
8935 rv = BAM_WRITE;
8936 BAM_DPRINTF((D_GET_SET_KERNEL_RESTORE_DEFAULT, fcn));
8937 goto done;
8938 }
8939
8940 if (optnum == KERNEL_CMD) {
8941 /*
8942 * At this point, we've already checked that old_args
8943 * and entryp are valid pointers. The "+ 2" is for
8944 * a space a the string termination character.
8945 */
8946 new_str_len = (sizeof (DIRECT_BOOT_KERNEL) - 1) +
8947 strlen(old_args) + 2;
8948 new_arg = s_calloc(1, new_str_len);
8949 (void) snprintf(new_arg, new_str_len, "%s %s",
8950 DIRECT_BOOT_KERNEL, old_args);
8951 free(kernelp->arg);
8952 kernelp->arg = new_arg;
8953
8954 /*
8955 * We have changed the kernel line, so we may need
8956 * to update the archive line as well.
8957 */
8958 set_archive_line(entryp, kernelp);
8959 BAM_DPRINTF((D_GET_SET_KERNEL_RESET_KERNEL_SET_ARG,
8960 fcn, kernelp->arg));
8961 } else {
8962 /*
8963 * We're resetting the boot args to nothing, so
8964 * we only need to copy the kernel. We've already
8965 * checked that the kernel is not the default.
8966 */
8967 new_arg = s_calloc(1, old_kernel_len + 1);
8968 (void) snprintf(new_arg, old_kernel_len + 1, "%s",
8969 kernelp->arg);
8970 free(kernelp->arg);
9091
9092 /*
9093 * There was already an bootenv entry which we need to edit.
9094 */
9095 if (optnum == KERNEL_CMD) {
9096 new_str_len = strlen(new_path) + strlen(old_args) + 2;
9097 new_arg = s_calloc(1, new_str_len);
9098 (void) snprintf(new_arg, new_str_len, "%s %s", new_path,
9099 old_args);
9100 free(kernelp->arg);
9101 kernelp->arg = new_arg;
9102
9103 /*
9104 * If we have changed the kernel line, we may need to update
9105 * the archive line as well.
9106 */
9107 set_archive_line(entryp, kernelp);
9108 BAM_DPRINTF((D_GET_SET_KERNEL_REPLACED_KERNEL_SAME_ARG, fcn,
9109 kernelp->arg));
9110 } else {
9111 new_str_len = old_kernel_len + strlen(path) + 8;
9112 new_arg = s_calloc(1, new_str_len);
9113 (void) strncpy(new_arg, kernelp->arg, old_kernel_len);
9114 (void) strlcat(new_arg, " ", new_str_len);
9115 (void) strlcat(new_arg, path, new_str_len);
9116 free(kernelp->arg);
9117 kernelp->arg = new_arg;
9118 BAM_DPRINTF((D_GET_SET_KERNEL_SAME_KERNEL_REPLACED_ARG, fcn,
9119 kernelp->arg));
9120 }
9121 rv = BAM_WRITE;
9122
9123 done:
9124 if ((rv == BAM_WRITE) && kernelp)
9125 update_line(kernelp);
9126 if (free_new_path)
9127 free(new_path);
9128 if (rv == BAM_WRITE) {
9129 BAM_DPRINTF((D_RETURN_SUCCESS, fcn));
9130 } else {
9131 BAM_DPRINTF((D_RETURN_FAILURE, fcn));
9132 }
9133 return (rv);
|
101
102 typedef enum {
103 OPT_ABSENT = 0, /* No option */
104 OPT_REQ, /* option required */
105 OPT_OPTIONAL /* option may or may not be present */
106 } option_t;
107
108 typedef struct {
109 char *subcmd;
110 option_t option;
111 error_t (*handler)();
112 int unpriv; /* is this an unprivileged command */
113 } subcmd_defn_t;
114
115 #define LINE_INIT 0 /* lineNum initial value */
116 #define ENTRY_INIT -1 /* entryNum initial value */
117 #define ALL_ENTRIES -2 /* selects all boot entries */
118
119 #define GRUB_DIR "/boot/grub"
120 #define GRUB_STAGE2 GRUB_DIR "/stage2"
121 #define GRUB_MENU "/boot/illumos.cfg"
122 #define MENU_TMP "/boot/illumos.cfg.tmp"
123 #define GRUB_BACKUP_MENU "/etc/lu/GRUB_backup_menu"
124 #define RAMDISK_SPECIAL "/ramdisk"
125 #define STUBBOOT "/stubboot"
126 #define MULTIBOOT "/platform/i86pc/multiboot"
127 #define GRUBSIGN_DIR "/boot/grub/bootsign"
128 #define GRUBSIGN_BACKUP "/etc/bootsign"
129 #define GRUBSIGN_UFS_PREFIX "rootfs"
130 #define GRUBSIGN_ZFS_PREFIX "pool_"
131 #define GRUBSIGN_LU_PREFIX "BE_"
132 #define UFS_SIGNATURE_LIST "/var/run/grub_ufs_signatures"
133 #define ZFS_LEGACY_MNTPT "/tmp/bootadm_mnt_zfs_legacy"
134
135 #define BOOTADM_RDONLY_TEST "BOOTADM_RDONLY_TEST"
136
137 /* lock related */
138 #define BAM_LOCK_FILE "/var/run/bootadm.lock"
139 #define LOCK_FILE_PERMS (S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH)
140
141 #define CREATE_RAMDISK "boot/solaris/bin/create_ramdisk"
142 #define CREATE_DISKMAP "boot/solaris/bin/create_diskmap"
161 typedef enum zfs_mnted {
162 ZFS_MNT_ERROR = -1,
163 LEGACY_MOUNTED = 1,
164 LEGACY_ALREADY,
165 ZFS_MOUNTED,
166 ZFS_ALREADY
167 } zfs_mnted_t;
168
169 /*
170 * Default file attributes
171 */
172 #define DEFAULT_DEV_MODE 0644 /* default permissions */
173 #define DEFAULT_DEV_UID 0 /* user root */
174 #define DEFAULT_DEV_GID 3 /* group sys */
175
176 /*
177 * Menu related
178 * menu_cmd_t and menu_cmds must be kept in sync
179 */
180 char *menu_cmds[] = {
181 "default_entry",/* DEFAULT_CMD */
182 "timeout", /* TIMEOUT_CMD */
183 "entry_name", /* TITLE_CMD */
184 "pool_uuid", /* ROOT_CMD */
185 "kernel_path$", /* KERNEL_CMD */
186 "kernel_path", /* KERNEL_DOLLAR_CMD */
187 "module$", /* MODULE_CMD */
188 "module", /* MODULE_DOLLAR_CMD */
189 "=", /* SEP_CMD */
190 "#", /* COMMENT_CMD */
191 "chainloader", /* CHAINLOADER_CMD */
192 "args", /* ARGS_CMD */
193 "pool_label", /* FINDROOT_CMD */
194 "dataset", /* BOOTFS_CMD */
195 "kernel_options",/* KERNEL_OPTIONS_CMD */
196 NULL
197 };
198
199 #define OPT_ENTRY_NUM "entry"
200
201 /*
202 * exec_cmd related
203 */
204 typedef struct {
205 line_t *head;
206 line_t *tail;
207 } filelist_t;
208
209 #define BOOT_FILE_LIST "boot/solaris/filelist.ramdisk"
210 #define ETC_FILE_LIST "etc/boot/solaris/filelist.ramdisk"
211
212 #define FILE_STAT "boot/solaris/filestat.ramdisk"
213 #define FILE_STAT_TMP "boot/solaris/filestat.ramdisk.tmp"
214 #define DIR_PERMS (S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH)
215 #define FILE_STAT_MODE (S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH)
4674 }
4675
4676 return (BAM_SUCCESS);
4677 }
4678
4679 int
4680 add_boot_entry(menu_t *mp,
4681 char *title,
4682 char *findroot,
4683 char *kernel,
4684 char *mod_kernel,
4685 char *module,
4686 char *bootfs)
4687 {
4688 int lineNum;
4689 int entryNum;
4690 char linebuf[BAM_MAXLINE];
4691 menu_cmd_t k_cmd;
4692 menu_cmd_t m_cmd;
4693 const char *fcn = "add_boot_entry()";
4694 char * options;
4695
4696 assert(mp);
4697
4698 INJECT_ERROR1("ADD_BOOT_ENTRY_FINDROOT_NULL", findroot = NULL);
4699 if (findroot == NULL) {
4700 bam_error(NULL_FINDROOT);
4701 return (BAM_ERROR);
4702 }
4703
4704 if (title == NULL) {
4705 title = "Solaris"; /* default to Solaris */
4706 }
4707 if (kernel == NULL) {
4708 bam_error(SUBOPT_MISS, menu_cmds[KERNEL_CMD]);
4709 return (BAM_ERROR);
4710 }
4711 if (module == NULL) {
4712 if (bam_direct != BAM_DIRECT_DBOOT) {
4713 bam_error(SUBOPT_MISS, menu_cmds[MODULE_CMD]);
4714 return (BAM_ERROR);
4741 */
4742 (void) snprintf(linebuf, sizeof (linebuf), "%s%s",
4743 menu_cmds[COMMENT_CMD], BAM_BOOTADM_HDR);
4744 line_parser(mp, linebuf, &lineNum, &entryNum);
4745
4746 (void) snprintf(linebuf, sizeof (linebuf), "%s%s%s",
4747 menu_cmds[TITLE_CMD], menu_cmds[SEP_CMD], title);
4748 line_parser(mp, linebuf, &lineNum, &entryNum);
4749
4750 (void) snprintf(linebuf, sizeof (linebuf), "%s%s%s",
4751 menu_cmds[FINDROOT_CMD], menu_cmds[SEP_CMD], findroot);
4752 line_parser(mp, linebuf, &lineNum, &entryNum);
4753 BAM_DPRINTF((D_ADD_FINDROOT_NUM, fcn, lineNum, entryNum));
4754
4755 if (bootfs != NULL) {
4756 (void) snprintf(linebuf, sizeof (linebuf), "%s%s%s",
4757 menu_cmds[BOOTFS_CMD], menu_cmds[SEP_CMD], bootfs);
4758 line_parser(mp, linebuf, &lineNum, &entryNum);
4759 }
4760
4761 options = strpbrk(kernel, " \t");
4762 if (options)
4763 *options++ = 0;
4764
4765 (void) snprintf(linebuf, sizeof (linebuf), "%s%s%s",
4766 menu_cmds[k_cmd], menu_cmds[SEP_CMD], kernel);
4767 line_parser(mp, linebuf, &lineNum, &entryNum);
4768
4769 if (options) {
4770 (void) snprintf(linebuf, sizeof (linebuf), "%s%s%s",
4771 menu_cmds[KERNEL_OPTIONS_CMD], menu_cmds[SEP_CMD], options);
4772 line_parser(mp, linebuf, &lineNum, &entryNum);
4773 }
4774
4775 if (mod_kernel != NULL) {
4776 (void) snprintf(linebuf, sizeof (linebuf), "%s%s%s",
4777 menu_cmds[m_cmd], menu_cmds[SEP_CMD], mod_kernel);
4778 line_parser(mp, linebuf, &lineNum, &entryNum);
4779 }
4780
4781 (void) snprintf(linebuf, sizeof (linebuf), "%s%s%s",
4782 menu_cmds[m_cmd], menu_cmds[SEP_CMD], module);
4783 line_parser(mp, linebuf, &lineNum, &entryNum);
4784
4785 (void) snprintf(linebuf, sizeof (linebuf), "%s%s",
4786 menu_cmds[COMMENT_CMD], BAM_BOOTADM_FTR);
4787 line_parser(mp, linebuf, &lineNum, &entryNum);
4788
4789 return (entryNum);
4790 }
4791
4792 error_t
4793 delete_boot_entry(menu_t *mp, int entryNum, int quiet)
4794 {
7107 (void) unlink(UFS_SIGNATURE_LIST);
7108 return (NULL);
7109 }
7110
7111 free(fstype);
7112
7113 if (bam_verbose)
7114 bam_print(GRUBSIGN_FOUND_OR_CREATED, sign, osdev);
7115
7116 fdiskpart = get_partition(osdev);
7117 INJECT_ERROR1("GET_GRUBSIGN_FDISK", fdiskpart = -1);
7118 if (fdiskpart == -1) {
7119 bam_error(FDISKPART_FAIL, osdev);
7120 free(sign);
7121 return (NULL);
7122 }
7123
7124 slice = strrchr(osdev, 's');
7125
7126 grubsign = s_calloc(1, MAXNAMELEN + 10);
7127 /* if (slice) {
7128 (void) snprintf(grubsign, MAXNAMELEN + 10, "(%s,%d,%c)",
7129 sign, fdiskpart, slice[1] + 'a' - '0');
7130 } else
7131 (void) snprintf(grubsign, MAXNAMELEN + 10, "(%s,%d)",
7132 sign, fdiskpart);*/
7133 grubsign = strdup(sign);
7134
7135 free(sign);
7136
7137 BAM_DPRINTF((D_GET_GRUBSIGN_SUCCESS, fcn, grubsign));
7138
7139 return (strchr(grubsign,'_') + 1);
7140 }
7141
7142 static char *
7143 get_title(char *rootdir)
7144 {
7145 static char title[80];
7146 char *cp = NULL;
7147 char release[PATH_MAX];
7148 FILE *fp;
7149 const char *fcn = "get_title()";
7150
7151 /* open the /etc/release file */
7152 (void) snprintf(release, sizeof (release), "%s/etc/release", rootdir);
7153
7154 fp = fopen(release, "r");
7155 if (fp == NULL) {
7156 bam_error(OPEN_FAIL, release, strerror(errno));
7157 cp = NULL;
7158 goto out;
7159 }
7808 BAM_DPRINTF((D_MATCHED_TITLE, fcn, title));
7809 break;
7810 }
7811 BAM_DPRINTF((D_NOMATCH_TITLE, fcn, title, lp->arg));
7812 continue; /* check title only */
7813 }
7814
7815 lp = lp->next; /* advance to root line */
7816 if (lp == NULL) {
7817 continue;
7818 } else if (lp->cmd != NULL &&
7819 strcmp(lp->cmd, menu_cmds[FINDROOT_CMD]) == 0) {
7820 INJECT_ERROR1("FIND_BOOT_ENTRY_NULL_FINDROOT",
7821 findroot = NULL);
7822 if (findroot == NULL) {
7823 BAM_DPRINTF((D_NOMATCH_FINDROOT_NULL,
7824 fcn, lp->arg));
7825 continue;
7826 }
7827 /* findroot command found, try match */
7828 if (strncmp(lp->arg, strchr(findroot, '_') + 1, strlen(lp->arg)) != 0) {
7829 BAM_DPRINTF((D_NOMATCH_FINDROOT,
7830 fcn, findroot, lp->arg));
7831 continue;
7832 }
7833 BAM_DPRINTF((D_MATCHED_FINDROOT, fcn, findroot));
7834 lp = lp->next; /* advance to kernel line */
7835 } else if (lp->cmd != NULL &&
7836 strcmp(lp->cmd, menu_cmds[ROOT_CMD]) == 0) {
7837 INJECT_ERROR1("FIND_BOOT_ENTRY_NULL_ROOT", root = NULL);
7838 if (root == NULL) {
7839 BAM_DPRINTF((D_NOMATCH_ROOT_NULL,
7840 fcn, lp->arg));
7841 continue;
7842 }
7843 /* root cmd found, try match */
7844 if (strcmp(lp->arg, root) != 0) {
7845 BAM_DPRINTF((D_NOMATCH_ROOT,
7846 fcn, root, lp->arg));
7847 continue;
7848 }
7866 }
7867
7868 if (kernel &&
7869 (!check_cmd(lp->cmd, KERNEL_CMD, lp->arg, kernel))) {
7870 if (!(ent->flags & BAM_ENTRY_FAILSAFE) ||
7871 !(ent->flags & BAM_ENTRY_DBOOT) ||
7872 strcmp(kernel, DIRECT_BOOT_FAILSAFE_LINE) != 0)
7873 continue;
7874
7875 ent->flags |= BAM_ENTRY_UPGFSKERNEL;
7876
7877 }
7878 BAM_DPRINTF((D_KERNEL_MATCH, fcn, kernel, lp->arg));
7879
7880 /*
7881 * Check for matching module entry (failsafe or normal).
7882 * If it fails to match, we go around the loop again.
7883 * For xpv entries, there are two module lines, so we
7884 * do the check twice.
7885 */
7886 lp = lp->next; /* advance to options line */
7887 lp = lp->next; /* advance to module line */
7888 if (check_cmd(lp->cmd, MODULE_CMD, lp->arg, module) ||
7889 (((lp = lp->next) != NULL) &&
7890 check_cmd(lp->cmd, MODULE_CMD, lp->arg, module))) {
7891 /* match found */
7892 BAM_DPRINTF((D_MODULE_MATCH, fcn, module, lp->arg));
7893 break;
7894 }
7895
7896 if (strcmp(module, FAILSAFE_ARCHIVE) == 0 &&
7897 (strcmp(lp->prev->arg, FAILSAFE_ARCHIVE_32) == 0 ||
7898 strcmp(lp->prev->arg, FAILSAFE_ARCHIVE_64) == 0)) {
7899 ent->flags |= BAM_ENTRY_UPGFSMODULE;
7900 break;
7901 }
7902
7903 }
7904
7905 if (ent && entry_num) {
7906 *entry_num = i;
7908
7909 if (ent) {
7910 BAM_DPRINTF((D_RETURN_RET, fcn, i));
7911 } else {
7912 BAM_DPRINTF((D_RETURN_RET, fcn, BAM_ERROR));
7913 }
7914 return (ent);
7915 }
7916
7917 static int
7918 update_boot_entry(menu_t *mp, char *title, char *findroot, char *root,
7919 char *kernel, char *mod_kernel, char *module, int root_opt)
7920 {
7921 int i;
7922 int change_kernel = 0;
7923 entry_t *ent;
7924 line_t *lp;
7925 line_t *tlp;
7926 char linebuf[BAM_MAXLINE];
7927 const char *fcn = "update_boot_entry()";
7928 char *label;
7929
7930 /* note: don't match on title, it's updated on upgrade */
7931 ent = find_boot_entry(mp, NULL, kernel, findroot, root, module,
7932 root_opt, &i);
7933 if ((ent == NULL) && (bam_direct == BAM_DIRECT_DBOOT)) {
7934 /*
7935 * We may be upgrading a kernel from multiboot to
7936 * directboot. Look for a multiboot entry. A multiboot
7937 * entry will not have a findroot line.
7938 */
7939 ent = find_boot_entry(mp, NULL, "multiboot", NULL, root,
7940 MULTIBOOT_ARCHIVE, root_opt, &i);
7941 if (ent != NULL) {
7942 BAM_DPRINTF((D_UPGRADE_FROM_MULTIBOOT, fcn, root));
7943 change_kernel = 1;
7944 }
7945 } else if (ent) {
7946 BAM_DPRINTF((D_FOUND_FINDROOT, fcn, findroot));
7947 }
7948
7965
7966 tlp = lp; /* title line */
7967 lp = lp->next; /* root line */
7968
7969 /* if no root or findroot command, create a new line_t */
7970 if ((lp->cmd != NULL) && (strcmp(lp->cmd, menu_cmds[ROOT_CMD]) != 0 &&
7971 strcmp(lp->cmd, menu_cmds[FINDROOT_CMD]) != 0)) {
7972 lp = s_calloc(1, sizeof (line_t));
7973 bam_add_line(mp, ent, tlp, lp);
7974 } else {
7975 if (lp->cmd != NULL)
7976 free(lp->cmd);
7977
7978 free(lp->sep);
7979 free(lp->arg);
7980 free(lp->line);
7981 }
7982
7983 lp->cmd = s_strdup(menu_cmds[FINDROOT_CMD]);
7984 lp->sep = s_strdup(menu_cmds[SEP_CMD]);
7985 label = s_strdup(strchr(findroot, '_') + 1);
7986 *(strchr(label,',')) = 0;
7987 lp->arg = s_strdup(label);
7988 (void) snprintf(linebuf, sizeof (linebuf), "%s%s%s",
7989 menu_cmds[FINDROOT_CMD], menu_cmds[SEP_CMD], label);
7990 lp->line = s_strdup(linebuf);
7991 free(label);
7992 BAM_DPRINTF((D_ADDING_FINDROOT_LINE, fcn, findroot));
7993
7994 /* kernel line */
7995 lp = lp->next;
7996
7997 if (ent->flags & BAM_ENTRY_UPGFSKERNEL) {
7998 char *params = NULL;
7999 char *opts = NULL;
8000
8001 opts = strpbrk(kernel, " \t");
8002 *opts++ = '\0';
8003 (void) snprintf(linebuf, sizeof (linebuf), "%s%s%s",
8004 menu_cmds[KERNEL_DOLLAR_CMD], menu_cmds[SEP_CMD],
8005 kernel);
8006
8007 if (lp->cmd != NULL)
8008 free(lp->cmd);
8009
8010 free(lp->arg);
8011 free(lp->line);
8012 lp->cmd = s_strdup(menu_cmds[KERNEL_DOLLAR_CMD]);
8013 lp->arg = s_strdup(strstr(linebuf, "/"));
8014 lp->line = s_strdup(linebuf);
8015 ent->flags &= ~BAM_ENTRY_UPGFSKERNEL;
8016 BAM_DPRINTF((D_ADDING_KERNEL_DOLLAR, fcn, lp->prev->cmd));
8017
8018 lp = lp->next;
8019 params = strstr(lp->arg, "-s");
8020 free(lp->arg);
8021 free(lp->line);
8022 if (params)
8023 (void) snprintf(linebuf, sizeof(linebuf), "%s%s%s -s",
8024 lp->cmd, menu_cmds[SEP_CMD],opts);
8025 else
8026 (void) snprintf(linebuf, sizeof(linebuf), "%s%s%s",
8027 lp->cmd, menu_cmds[SEP_CMD],opts);
8028 lp->line = s_strdup(linebuf);
8029 lp->arg = s_strdup(strchr(linebuf, '=') + 1);
8030 }
8031
8032 if (change_kernel) {
8033 char *opts = NULL;
8034 /*
8035 * We're upgrading from multiboot to directboot.
8036 */
8037 opts = strpbrk(kernel, " \t");
8038 *opts++ = '\0';
8039 if (lp->cmd != NULL &&
8040 strcmp(lp->cmd, menu_cmds[KERNEL_CMD]) == 0) {
8041 (void) snprintf(linebuf, sizeof (linebuf), "%s%s%s",
8042 menu_cmds[KERNEL_DOLLAR_CMD], menu_cmds[SEP_CMD],
8043 kernel);
8044 free(lp->cmd);
8045 free(lp->arg);
8046 free(lp->line);
8047 lp->cmd = s_strdup(menu_cmds[KERNEL_DOLLAR_CMD]);
8048 lp->arg = s_strdup(kernel);
8049 lp->line = s_strdup(linebuf);
8050 lp = lp->next;
8051 BAM_DPRINTF((D_ADDING_KERNEL_DOLLAR, fcn, kernel));
8052 (void) snprintf(linebuf, sizeof(linebuf), "%s%s%s",
8053 lp->cmd, menu_cmds[SEP_CMD],opts);
8054 free(lp->arg);
8055 free(lp->line);
8056 lp->line = s_strdup(linebuf);
8057 lp->arg = s_strdup(strchr(linebuf, '=') + 1);
8058 }
8059 if (lp->cmd != NULL &&
8060 strcmp(lp->cmd, menu_cmds[MODULE_CMD]) == 0) {
8061 (void) snprintf(linebuf, sizeof (linebuf), "%s%s%s",
8062 menu_cmds[MODULE_DOLLAR_CMD], menu_cmds[SEP_CMD],
8063 module);
8064 free(lp->cmd);
8065 free(lp->arg);
8066 free(lp->line);
8067 lp->cmd = s_strdup(menu_cmds[MODULE_DOLLAR_CMD]);
8068 lp->arg = s_strdup(module);
8069 lp->line = s_strdup(linebuf);
8070 lp = lp->next;
8071 BAM_DPRINTF((D_ADDING_MODULE_DOLLAR, fcn, module));
8072 }
8073 }
8074
8075 /* module line */
8076 lp = lp->next;
8077
8966 sizeof (DIRECT_BOOT_KERNEL) - 1) == 0))) {
8967 kernelp = NULL;
8968 (void) delete_boot_entry(mp, entryNum, DBE_PRINTERR);
8969 restore_default_entry(mp, BAM_OLD_RC_DEF,
8970 mp->old_rc_default);
8971 mp->old_rc_default = NULL;
8972 rv = BAM_WRITE;
8973 BAM_DPRINTF((D_GET_SET_KERNEL_RESTORE_DEFAULT, fcn));
8974 goto done;
8975 }
8976
8977 if (optnum == KERNEL_CMD) {
8978 /*
8979 * At this point, we've already checked that old_args
8980 * and entryp are valid pointers. The "+ 2" is for
8981 * a space a the string termination character.
8982 */
8983 new_str_len = (sizeof (DIRECT_BOOT_KERNEL) - 1) +
8984 strlen(old_args) + 2;
8985 new_arg = s_calloc(1, new_str_len);
8986 (void) snprintf(new_arg, new_str_len, "%s",
8987 DIRECT_BOOT_KERNEL);
8988 free(kernelp->arg);
8989 kernelp->arg = new_arg;
8990
8991 /*
8992 * We have changed the kernel line, so we may need
8993 * to update the archive line as well.
8994 */
8995 set_archive_line(entryp, kernelp);
8996 BAM_DPRINTF((D_GET_SET_KERNEL_RESET_KERNEL_SET_ARG,
8997 fcn, kernelp->arg));
8998 } else {
8999 /*
9000 * We're resetting the boot args to nothing, so
9001 * we only need to copy the kernel. We've already
9002 * checked that the kernel is not the default.
9003 */
9004 new_arg = s_calloc(1, old_kernel_len + 1);
9005 (void) snprintf(new_arg, old_kernel_len + 1, "%s",
9006 kernelp->arg);
9007 free(kernelp->arg);
9128
9129 /*
9130 * There was already an bootenv entry which we need to edit.
9131 */
9132 if (optnum == KERNEL_CMD) {
9133 new_str_len = strlen(new_path) + strlen(old_args) + 2;
9134 new_arg = s_calloc(1, new_str_len);
9135 (void) snprintf(new_arg, new_str_len, "%s %s", new_path,
9136 old_args);
9137 free(kernelp->arg);
9138 kernelp->arg = new_arg;
9139
9140 /*
9141 * If we have changed the kernel line, we may need to update
9142 * the archive line as well.
9143 */
9144 set_archive_line(entryp, kernelp);
9145 BAM_DPRINTF((D_GET_SET_KERNEL_REPLACED_KERNEL_SAME_ARG, fcn,
9146 kernelp->arg));
9147 } else {
9148 kernelp = kernelp->next;
9149 new_str_len = strlen(kernelp->arg) + strlen(path) + 8;
9150 new_arg = s_calloc(1, new_str_len);
9151 (void) strncpy(new_arg, kernelp->arg, strlen(kernelp->arg));
9152 (void) strlcat(new_arg, " ", new_str_len);
9153 (void) strlcat(new_arg, path, new_str_len);
9154 free(kernelp->arg);
9155 kernelp->arg = new_arg;
9156 BAM_DPRINTF((D_GET_SET_KERNEL_SAME_KERNEL_REPLACED_ARG, fcn,
9157 kernelp->arg));
9158 }
9159 rv = BAM_WRITE;
9160
9161 done:
9162 if ((rv == BAM_WRITE) && kernelp)
9163 update_line(kernelp);
9164 if (free_new_path)
9165 free(new_path);
9166 if (rv == BAM_WRITE) {
9167 BAM_DPRINTF((D_RETURN_SUCCESS, fcn));
9168 } else {
9169 BAM_DPRINTF((D_RETURN_FAILURE, fcn));
9170 }
9171 return (rv);
|