xref: /illumos-gate/usr/src/cmd/boot/bootadm/bootadm.c (revision 23b5da0c)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5fbac2b2bSvikram  * Common Development and Distribution License (the "License").
6fbac2b2bSvikram  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
217c478bd9Sstevel@tonic-gate 
226debd3f5SAlexander Eremin /*
235f10ef69SYuri Pankov  * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
249adfa60dSMatthew Ahrens  * Copyright 2012 Milan Jurik. All rights reserved.
259adfa60dSMatthew Ahrens  * Copyright (c) 2015 by Delphix. All rights reserved.
262dc23587SToomas Soome  * Copyright 2016 Toomas Soome <tsoome@me.com>
272b987d42SAlexander Eremin  * Copyright 2017 Nexenta Systems, Inc.
285850749aSAndy Fiddaman  * Copyright 2018 OmniOS Community Edition (OmniOSce) Association.
296debd3f5SAlexander Eremin  */
306debd3f5SAlexander Eremin 
317c478bd9Sstevel@tonic-gate /*
327c478bd9Sstevel@tonic-gate  * bootadm(1M) is a new utility for managing bootability of
337c478bd9Sstevel@tonic-gate  * Solaris *Newboot* environments. It has two primary tasks:
3475383e32SAndy Fiddaman  *	- Allow end users to manage bootability of Newboot Solaris instances
357c478bd9Sstevel@tonic-gate  *	- Provide services to other subsystems in Solaris (primarily Install)
367c478bd9Sstevel@tonic-gate  */
377c478bd9Sstevel@tonic-gate 
387c478bd9Sstevel@tonic-gate /* Headers */
397c478bd9Sstevel@tonic-gate #include <stdio.h>
407c478bd9Sstevel@tonic-gate #include <errno.h>
417c478bd9Sstevel@tonic-gate #include <stdlib.h>
427c478bd9Sstevel@tonic-gate #include <string.h>
437c478bd9Sstevel@tonic-gate #include <unistd.h>
447c478bd9Sstevel@tonic-gate #include <sys/types.h>
457c478bd9Sstevel@tonic-gate #include <sys/stat.h>
4644da779fSWilliam Kucharski #include <alloca.h>
477c478bd9Sstevel@tonic-gate #include <stdarg.h>
487c478bd9Sstevel@tonic-gate #include <limits.h>
497c478bd9Sstevel@tonic-gate #include <signal.h>
507c478bd9Sstevel@tonic-gate #include <sys/wait.h>
517c478bd9Sstevel@tonic-gate #include <sys/mnttab.h>
52f904d32dSJerry Gilliam #include <sys/mntent.h>
537c478bd9Sstevel@tonic-gate #include <sys/statvfs.h>
547c478bd9Sstevel@tonic-gate #include <libnvpair.h>
557c478bd9Sstevel@tonic-gate #include <ftw.h>
567c478bd9Sstevel@tonic-gate #include <fcntl.h>
577c478bd9Sstevel@tonic-gate #include <strings.h>
582449e17fSsherrym #include <utime.h>
597c478bd9Sstevel@tonic-gate #include <sys/systeminfo.h>
607c478bd9Sstevel@tonic-gate #include <sys/dktp/fdisk.h>
6158091fd8Ssetje #include <sys/param.h>
62eb2bd662Svikram #include <dirent.h>
63eb2bd662Svikram #include <ctype.h>
64eb2bd662Svikram #include <libgen.h>
65e7cbe64fSgw #include <sys/sysmacros.h>
6648847494SEnrico Perla - Sun Microsystems #include <sys/elf.h>
67963390b4Svikram #include <libscf.h>
6848847494SEnrico Perla - Sun Microsystems #include <zlib.h>
6948847494SEnrico Perla - Sun Microsystems #include <sys/lockfs.h>
7048847494SEnrico Perla - Sun Microsystems #include <sys/filio.h>
716debd3f5SAlexander Eremin #include <libbe.h>
72fa0c327aSToomas Soome #include <deflt.h>
73e998e519SSheshadri Vasudevan #ifdef i386
74e998e519SSheshadri Vasudevan #include <libfdisk.h>
75e998e519SSheshadri Vasudevan #endif
76986fd29aSsetje 
7779c28b70SToomas Soome #if !defined(_OBP)
782449e17fSsherrym #include <sys/ucode.h>
792449e17fSsherrym #endif
807c478bd9Sstevel@tonic-gate 
817c478bd9Sstevel@tonic-gate #include <pwd.h>
827c478bd9Sstevel@tonic-gate #include <grp.h>
837c478bd9Sstevel@tonic-gate #include <device_info.h>
84eb2bd662Svikram #include <sys/vtoc.h>
85eb2bd662Svikram #include <sys/efi_partition.h>
8689c3ee43SGangadhar Mylapuram #include <regex.h>
877c478bd9Sstevel@tonic-gate #include <locale.h>
88c7c0ceafSToomas Soome #include <sys/mkdev.h>
897c478bd9Sstevel@tonic-gate 
90ae115bc7Smrj #include "bootadm.h"
917c478bd9Sstevel@tonic-gate 
927c478bd9Sstevel@tonic-gate #ifndef TEXT_DOMAIN
937c478bd9Sstevel@tonic-gate #define	TEXT_DOMAIN	"SUNW_OST_OSCMD"
947c478bd9Sstevel@tonic-gate #endif	/* TEXT_DOMAIN */
957c478bd9Sstevel@tonic-gate 
967c478bd9Sstevel@tonic-gate /* Type definitions */
977c478bd9Sstevel@tonic-gate 
987c478bd9Sstevel@tonic-gate /* Primary subcmds */
997c478bd9Sstevel@tonic-gate typedef enum {
1007c478bd9Sstevel@tonic-gate 	BAM_MENU = 3,
101c7c0ceafSToomas Soome 	BAM_ARCHIVE,
102c7c0ceafSToomas Soome 	BAM_INSTALL
1037c478bd9Sstevel@tonic-gate } subcmd_t;
1047c478bd9Sstevel@tonic-gate 
1057c478bd9Sstevel@tonic-gate #define	LINE_INIT	0	/* lineNum initial value */
1067c478bd9Sstevel@tonic-gate #define	ENTRY_INIT	-1	/* entryNum initial value */
1077c478bd9Sstevel@tonic-gate #define	ALL_ENTRIES	-2	/* selects all boot entries */
1087c478bd9Sstevel@tonic-gate 
1091a902ef8SHans Rosenfeld #define	PARTNO_NOTFOUND -1	/* Solaris partition not found */
1101a902ef8SHans Rosenfeld #define	PARTNO_EFI	-2	/* EFI partition table found */
1111a902ef8SHans Rosenfeld 
1127c478bd9Sstevel@tonic-gate #define	GRUB_DIR		"/boot/grub"
113963390b4Svikram #define	GRUB_STAGE2		GRUB_DIR "/stage2"
1147c478bd9Sstevel@tonic-gate #define	GRUB_MENU		"/boot/grub/menu.lst"
1157c478bd9Sstevel@tonic-gate #define	MENU_TMP		"/boot/grub/menu.lst.tmp"
116963390b4Svikram #define	GRUB_BACKUP_MENU	"/etc/lu/GRUB_backup_menu"
1171a96bf60SToomas Soome #define	RAMDISK_SPECIAL		"/devices/ramdisk"
11840541d5dSvikram #define	STUBBOOT		"/stubboot"
119eb2bd662Svikram #define	MULTIBOOT		"/platform/i86pc/multiboot"
120eb2bd662Svikram #define	GRUBSIGN_DIR		"/boot/grub/bootsign"
121eb2bd662Svikram #define	GRUBSIGN_BACKUP		"/etc/bootsign"
122eb2bd662Svikram #define	GRUBSIGN_UFS_PREFIX	"rootfs"
123eb2bd662Svikram #define	GRUBSIGN_ZFS_PREFIX	"pool_"
124eb2bd662Svikram #define	GRUBSIGN_LU_PREFIX	"BE_"
125eb2bd662Svikram #define	UFS_SIGNATURE_LIST	"/var/run/grub_ufs_signatures"
126eb2bd662Svikram #define	ZFS_LEGACY_MNTPT	"/tmp/bootadm_mnt_zfs_legacy"
127eb2bd662Svikram 
12875383e32SAndy Fiddaman /* SMF */
12975383e32SAndy Fiddaman #define	BOOT_ARCHIVE_FMRI	"system/boot-archive:default"
13075383e32SAndy Fiddaman #define	SCF_PG_CONFIG		"config"
13175383e32SAndy Fiddaman #define	SCF_PROPERTY_FORMAT	"format"
13275383e32SAndy Fiddaman 
133fa0c327aSToomas Soome /* BE defaults */
134fa0c327aSToomas Soome #define	BE_DEFAULTS		"/etc/default/be"
135fa0c327aSToomas Soome #define	BE_DFLT_BE_HAS_GRUB	"BE_HAS_GRUB="
136fa0c327aSToomas Soome 
137eb2bd662Svikram #define	BOOTADM_RDONLY_TEST	"BOOTADM_RDONLY_TEST"
1387c478bd9Sstevel@tonic-gate 
1397c478bd9Sstevel@tonic-gate /* lock related */
1407c478bd9Sstevel@tonic-gate #define	BAM_LOCK_FILE		"/var/run/bootadm.lock"
1417c478bd9Sstevel@tonic-gate #define	LOCK_FILE_PERMS		(S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH)
1427c478bd9Sstevel@tonic-gate 
143986fd29aSsetje #define	CREATE_RAMDISK		"boot/solaris/bin/create_ramdisk"
144986fd29aSsetje #define	CREATE_DISKMAP		"boot/solaris/bin/create_diskmap"
145986fd29aSsetje #define	EXTRACT_BOOT_FILELIST	"boot/solaris/bin/extract_boot_filelist"
1467c478bd9Sstevel@tonic-gate #define	GRUBDISK_MAP		"/var/run/solaris_grubdisk.map"
1477c478bd9Sstevel@tonic-gate 
148b610f78eSvikram #define	GRUB_slice		"/etc/lu/GRUB_slice"
149b610f78eSvikram #define	GRUB_root		"/etc/lu/GRUB_root"
150fbac2b2bSvikram #define	GRUB_fdisk		"/etc/lu/GRUB_fdisk"
151fbac2b2bSvikram #define	GRUB_fdisk_target	"/etc/lu/GRUB_fdisk_target"
152963390b4Svikram #define	FINDROOT_INSTALLGRUB	"/etc/lu/installgrub.findroot"
153963390b4Svikram #define	LULIB			"/usr/lib/lu/lulib"
154963390b4Svikram #define	LULIB_PROPAGATE_FILE	"lulib_propagate_file"
155963390b4Svikram #define	CKSUM			"/usr/bin/cksum"
156963390b4Svikram #define	LU_MENU_CKSUM		"/etc/lu/menu.cksum"
157963390b4Svikram #define	BOOTADM			"/sbin/bootadm"
158b610f78eSvikram 
159b610f78eSvikram #define	INSTALLGRUB		"/sbin/installgrub"
160b610f78eSvikram #define	STAGE1			"/boot/grub/stage1"
161b610f78eSvikram #define	STAGE2			"/boot/grub/stage2"
162b610f78eSvikram 
1632b987d42SAlexander Eremin #define	ETC_SYSTEM_DIR		"etc/system.d"
1642b987d42SAlexander Eremin #define	SELF_ASSEMBLY		"etc/system.d/.self-assembly"
1652b987d42SAlexander Eremin 
1667c478bd9Sstevel@tonic-gate /*
1677c478bd9Sstevel@tonic-gate  * Default file attributes
1687c478bd9Sstevel@tonic-gate  */
1697c478bd9Sstevel@tonic-gate #define	DEFAULT_DEV_MODE	0644	/* default permissions */
1707c478bd9Sstevel@tonic-gate #define	DEFAULT_DEV_UID		0	/* user root */
1717c478bd9Sstevel@tonic-gate #define	DEFAULT_DEV_GID		3	/* group sys */
1727c478bd9Sstevel@tonic-gate 
1737c478bd9Sstevel@tonic-gate /*
1747c478bd9Sstevel@tonic-gate  * Menu related
1757c478bd9Sstevel@tonic-gate  * menu_cmd_t and menu_cmds must be kept in sync
1767c478bd9Sstevel@tonic-gate  */
177ae115bc7Smrj char *menu_cmds[] = {
1787c478bd9Sstevel@tonic-gate 	"default",	/* DEFAULT_CMD */
1797c478bd9Sstevel@tonic-gate 	"timeout",	/* TIMEOUT_CMD */
1807c478bd9Sstevel@tonic-gate 	"title",	/* TITLE_CMD */
1817c478bd9Sstevel@tonic-gate 	"root",		/* ROOT_CMD */
1827c478bd9Sstevel@tonic-gate 	"kernel",	/* KERNEL_CMD */
183ae115bc7Smrj 	"kernel$",	/* KERNEL_DOLLAR_CMD */
1847c478bd9Sstevel@tonic-gate 	"module",	/* MODULE_CMD */
185ae115bc7Smrj 	"module$",	/* MODULE_DOLLAR_CMD */
1867c478bd9Sstevel@tonic-gate 	" ",		/* SEP_CMD */
1877c478bd9Sstevel@tonic-gate 	"#",		/* COMMENT_CMD */
188ae115bc7Smrj 	"chainloader",	/* CHAINLOADER_CMD */
189ae115bc7Smrj 	"args",		/* ARGS_CMD */
190eb2bd662Svikram 	"findroot",	/* FINDROOT_CMD */
19144da779fSWilliam Kucharski 	"bootfs",	/* BOOTFS_CMD */
1927c478bd9Sstevel@tonic-gate 	NULL
1937c478bd9Sstevel@tonic-gate };
1947c478bd9Sstevel@tonic-gate 
19575383e32SAndy Fiddaman char *bam_formats[] = {
19675383e32SAndy Fiddaman 	"hsfs",
19775383e32SAndy Fiddaman 	"ufs",
19875383e32SAndy Fiddaman 	"cpio",
19975383e32SAndy Fiddaman 	"ufs-nocompress",
20075383e32SAndy Fiddaman 	NULL
20175383e32SAndy Fiddaman };
20275383e32SAndy Fiddaman #define	BAM_FORMAT_UNSET -1
20375383e32SAndy Fiddaman #define	BAM_FORMAT_HSFS 0
20475383e32SAndy Fiddaman short bam_format = BAM_FORMAT_UNSET;
20575383e32SAndy Fiddaman 
2067c478bd9Sstevel@tonic-gate #define	OPT_ENTRY_NUM	"entry"
2077c478bd9Sstevel@tonic-gate 
2087c478bd9Sstevel@tonic-gate /*
209eb2bd662Svikram  * exec_cmd related
2107c478bd9Sstevel@tonic-gate  */
2117c478bd9Sstevel@tonic-gate typedef struct {
2127c478bd9Sstevel@tonic-gate 	line_t *head;
2137c478bd9Sstevel@tonic-gate 	line_t *tail;
2147c478bd9Sstevel@tonic-gate } filelist_t;
2157c478bd9Sstevel@tonic-gate 
2167c478bd9Sstevel@tonic-gate #define	BOOT_FILE_LIST	"boot/solaris/filelist.ramdisk"
2177c478bd9Sstevel@tonic-gate #define	ETC_FILE_LIST	"etc/boot/solaris/filelist.ramdisk"
2187c478bd9Sstevel@tonic-gate 
2197c478bd9Sstevel@tonic-gate #define	FILE_STAT	"boot/solaris/filestat.ramdisk"
2207c478bd9Sstevel@tonic-gate #define	FILE_STAT_TMP	"boot/solaris/filestat.ramdisk.tmp"
2217c478bd9Sstevel@tonic-gate #define	DIR_PERMS	(S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH)
2227c478bd9Sstevel@tonic-gate #define	FILE_STAT_MODE	(S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH)
2237c478bd9Sstevel@tonic-gate 
2244a9df875SEnrico Perla - Sun Microsystems #define	FILE_STAT_TIMESTAMP	"boot/solaris/timestamp.cache"
2254a9df875SEnrico Perla - Sun Microsystems 
2267c478bd9Sstevel@tonic-gate /* Globals */
227ae115bc7Smrj int bam_verbose;
228ae115bc7Smrj int bam_force;
229eb2bd662Svikram int bam_debug;
23075383e32SAndy Fiddaman int bam_skip_lock;
2317c478bd9Sstevel@tonic-gate static char *prog;
2327c478bd9Sstevel@tonic-gate static subcmd_t bam_cmd;
233c262cbbcSToomas Soome char *bam_root;
234c262cbbcSToomas Soome int bam_rootlen;
2357c478bd9Sstevel@tonic-gate static int bam_root_readonly;
236c262cbbcSToomas Soome int bam_alt_root;
23748847494SEnrico Perla - Sun Microsystems static int bam_extend = 0;
23848847494SEnrico Perla - Sun Microsystems static int bam_purge = 0;
2397c478bd9Sstevel@tonic-gate static char *bam_subcmd;
2407c478bd9Sstevel@tonic-gate static char *bam_opt;
2417c478bd9Sstevel@tonic-gate static char **bam_argv;
242c7c0ceafSToomas Soome static char *bam_pool;
2437c478bd9Sstevel@tonic-gate static int bam_argc;
2447c478bd9Sstevel@tonic-gate static int bam_check;
2455eea6091SEnrico Perla - Sun Microsystems static int bam_saved_check;
2467c478bd9Sstevel@tonic-gate static int bam_smf_check;
2477c478bd9Sstevel@tonic-gate static int bam_lock_fd = -1;
248e7cbe64fSgw static int bam_zfs;
249c7c0ceafSToomas Soome static int bam_mbr;
250c262cbbcSToomas Soome char rootbuf[PATH_MAX] = "/";
2512b987d42SAlexander Eremin static char self_assembly[PATH_MAX];
252b610f78eSvikram static int bam_update_all;
253d876c67dSjg static int bam_alt_platform;
254d876c67dSjg static char *bam_platform;
255cedc7e57SEnrico Perla - Sun Microsystems static char *bam_home_env = NULL;
2567c478bd9Sstevel@tonic-gate 
2577c478bd9Sstevel@tonic-gate /* function prototypes */
258986fd29aSsetje static void parse_args_internal(int, char *[]);
259986fd29aSsetje static void parse_args(int, char *argv[]);
260986fd29aSsetje static error_t bam_menu(char *, char *, int, char *[]);
261c7c0ceafSToomas Soome static error_t bam_install(char *, char *);
262986fd29aSsetje static error_t bam_archive(char *, char *);
2637c478bd9Sstevel@tonic-gate 
2647c478bd9Sstevel@tonic-gate static void bam_lock(void);
2657c478bd9Sstevel@tonic-gate static void bam_unlock(void);
2667c478bd9Sstevel@tonic-gate 
267986fd29aSsetje static int exec_cmd(char *, filelist_t *);
268986fd29aSsetje static error_t read_globals(menu_t *, char *, char *, int);
269eb2bd662Svikram static int menu_on_bootdisk(char *os_root, char *menu_root);
270986fd29aSsetje static menu_t *menu_read(char *);
271986fd29aSsetje static error_t menu_write(char *, menu_t *);
272986fd29aSsetje static void linelist_free(line_t *);
273986fd29aSsetje static void menu_free(menu_t *);
274986fd29aSsetje static void filelist_free(filelist_t *);
275986fd29aSsetje static error_t list2file(char *, char *, char *, line_t *);
276986fd29aSsetje static error_t list_entry(menu_t *, char *, char *);
27744da779fSWilliam Kucharski static error_t list_setting(menu_t *, char *, char *);
278986fd29aSsetje static error_t delete_all_entries(menu_t *, char *, char *);
279eb2bd662Svikram static error_t update_entry(menu_t *mp, char *menu_root, char *opt);
280eb2bd662Svikram static error_t update_temp(menu_t *mp, char *dummy, char *opt);
281986fd29aSsetje 
282c7c0ceafSToomas Soome static error_t install_bootloader(void);
283986fd29aSsetje static error_t update_archive(char *, char *);
284986fd29aSsetje static error_t list_archive(char *, char *);
285986fd29aSsetje static error_t update_all(char *, char *);
286986fd29aSsetje static error_t read_list(char *, filelist_t *);
287986fd29aSsetje static error_t set_option(menu_t *, char *, char *);
288986fd29aSsetje static error_t set_kernel(menu_t *, menu_cmd_t, char *, char *, size_t);
289eb2bd662Svikram static error_t get_kernel(menu_t *, menu_cmd_t, char *, size_t);
2902b987d42SAlexander Eremin static error_t build_etc_system_dir(char *);
291986fd29aSsetje static char *expand_path(const char *);
292986fd29aSsetje 
293986fd29aSsetje static long s_strtol(char *);
294986fd29aSsetje static int s_fputs(char *, FILE *);
295986fd29aSsetje 
2967c478bd9Sstevel@tonic-gate static int is_amd64(void);
29779755401Ssetje static char *get_machine(void);
2987c478bd9Sstevel@tonic-gate static void append_to_flist(filelist_t *, char *);
299eb2bd662Svikram static int ufs_add_to_sign_list(char *sign);
300963390b4Svikram static error_t synchronize_BE_menu(void);
3017c478bd9Sstevel@tonic-gate 
30279c28b70SToomas Soome #if !defined(_OBP)
3032449e17fSsherrym static void ucode_install();
3042449e17fSsherrym #endif
3052449e17fSsherrym 
3067c478bd9Sstevel@tonic-gate /* Menu related sub commands */
3077c478bd9Sstevel@tonic-gate static subcmd_defn_t menu_subcmds[] = {
308eb2bd662Svikram 	"set_option",		OPT_ABSENT,	set_option, 0,	/* PUB */
3091a97e40eSvikram 	"list_entry",		OPT_OPTIONAL,	list_entry, 1,	/* PUB */
3101a97e40eSvikram 	"delete_all_entries",	OPT_ABSENT,	delete_all_entries, 0, /* PVT */
3111a97e40eSvikram 	"update_entry",		OPT_REQ,	update_entry, 0, /* menu */
3121a97e40eSvikram 	"update_temp",		OPT_OPTIONAL,	update_temp, 0,	/* reboot */
313