1af28f636SEnrico Perla - Sun Microsystems /*
2af28f636SEnrico Perla - Sun Microsystems  * CDDL HEADER START
3af28f636SEnrico Perla - Sun Microsystems  *
4af28f636SEnrico Perla - Sun Microsystems  * The contents of this file are subject to the terms of the
5af28f636SEnrico Perla - Sun Microsystems  * Common Development and Distribution License (the "License").
6af28f636SEnrico Perla - Sun Microsystems  * You may not use this file except in compliance with the License.
7af28f636SEnrico Perla - Sun Microsystems  *
8af28f636SEnrico Perla - Sun Microsystems  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9af28f636SEnrico Perla - Sun Microsystems  * or http://www.opensolaris.org/os/licensing.
10af28f636SEnrico Perla - Sun Microsystems  * See the License for the specific language governing permissions
11af28f636SEnrico Perla - Sun Microsystems  * and limitations under the License.
12af28f636SEnrico Perla - Sun Microsystems  *
13af28f636SEnrico Perla - Sun Microsystems  * When distributing Covered Code, include this CDDL HEADER in each
14af28f636SEnrico Perla - Sun Microsystems  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15af28f636SEnrico Perla - Sun Microsystems  * If applicable, add the following below this CDDL HEADER, with the
16af28f636SEnrico Perla - Sun Microsystems  * fields enclosed by brackets "[]" replaced with your own identifying
17af28f636SEnrico Perla - Sun Microsystems  * information: Portions Copyright [yyyy] [name of copyright owner]
18af28f636SEnrico Perla - Sun Microsystems  *
19af28f636SEnrico Perla - Sun Microsystems  * CDDL HEADER END
20af28f636SEnrico Perla - Sun Microsystems  */
21af28f636SEnrico Perla - Sun Microsystems /*
22af28f636SEnrico Perla - Sun Microsystems  * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
2314d44f22SHans Rosenfeld  * Copyright 2012 Nexenta Systems, Inc. All rights reserved.
24af28f636SEnrico Perla - Sun Microsystems  */
25af28f636SEnrico Perla - Sun Microsystems 
26af28f636SEnrico Perla - Sun Microsystems #include <stdio.h>
27af28f636SEnrico Perla - Sun Microsystems #include <errno.h>
28af28f636SEnrico Perla - Sun Microsystems #include <unistd.h>
29af28f636SEnrico Perla - Sun Microsystems #include <fcntl.h>
30af28f636SEnrico Perla - Sun Microsystems #include <assert.h>
31af28f636SEnrico Perla - Sun Microsystems #include <locale.h>
32af28f636SEnrico Perla - Sun Microsystems #include <strings.h>
33af28f636SEnrico Perla - Sun Microsystems #include <sys/types.h>
34af28f636SEnrico Perla - Sun Microsystems #include <sys/stat.h>
35af28f636SEnrico Perla - Sun Microsystems #include <sys/multiboot.h>
36af28f636SEnrico Perla - Sun Microsystems #include <sys/sysmacros.h>
37af28f636SEnrico Perla - Sun Microsystems 
38af28f636SEnrico Perla - Sun Microsystems #include "installboot.h"
39*0c946d80SToomas Soome #include "../../common/bblk_einfo.h"
40*0c946d80SToomas Soome #include "../../common/boot_utils.h"
41*0c946d80SToomas Soome #include "../../common/mboot_extra.h"
42af28f636SEnrico Perla - Sun Microsystems 
43af28f636SEnrico Perla - Sun Microsystems #ifndef	TEXT_DOMAIN
44af28f636SEnrico Perla - Sun Microsystems #define	TEXT_DOMAIN	"SUNW_OST_OSCMD"
45af28f636SEnrico Perla - Sun Microsystems #endif
46af28f636SEnrico Perla - Sun Microsystems 
47af28f636SEnrico Perla - Sun Microsystems /*
48af28f636SEnrico Perla - Sun Microsystems  * SPARC bootblock installation:
49af28f636SEnrico Perla - Sun Microsystems  *
50af28f636SEnrico Perla - Sun Microsystems  * The bootblock resides in blocks 1 to 15 (disk label is at block 0).
51af28f636SEnrico Perla - Sun Microsystems  * The ZFS boot block is larger than what will fit into these first 7.5K so we
52af28f636SEnrico Perla - Sun Microsystems  * break it up and write the remaining portion into the ZFS provided boot block
53af28f636SEnrico Perla - Sun Microsystems  * region at offset 512K. If versioning is requested, we add a multiboot
54af28f636SEnrico Perla - Sun Microsystems  * header at the end of the bootblock, followed by the extra payload area and
55af28f636SEnrico Perla - Sun Microsystems  * place the extended information structure within the latter.
56af28f636SEnrico Perla - Sun Microsystems  */
57af28f636SEnrico Perla - Sun Microsystems 
58af28f636SEnrico Perla - Sun Microsystems static boolean_t	force_update = B_FALSE;
59af28f636SEnrico Perla - Sun Microsystems static boolean_t	do_getinfo = B_FALSE;
60af28f636SEnrico Perla - Sun Microsystems static boolean_t	do_version = B_FALSE;
61af28f636SEnrico Perla - Sun Microsystems static boolean_t	do_mirror_bblk = B_FALSE;
62af28f636SEnrico Perla - Sun Microsystems static boolean_t	strip = B_FALSE;
63af28f636SEnrico Perla - Sun Microsystems static boolean_t	verbose_dump = B_FALSE;
64af28f636SEnrico Perla - Sun Microsystems 
65af28f636SEnrico Perla - Sun Microsystems static char		*update_str;
66af28f636SEnrico Perla - Sun Microsystems static int		tgt_fs_type = TARGET_IS_UFS;
67af28f636SEnrico Perla - Sun Microsystems char			mboot_scan[MBOOT_SCAN_SIZE];
68af28f636SEnrico Perla - Sun Microsystems 
69af28f636SEnrico Perla - Sun Microsystems /* Function prototypes. */
70af28f636SEnrico Perla - Sun Microsystems static int read_bootblock_from_file(char *, ib_data_t *data);
71af28f636SEnrico Perla - Sun Microsystems static int read_bootblock_from_disk(int, ib_bootblock_t *);
72af28f636SEnrico Perla - Sun Microsystems static void add_bootblock_einfo(ib_bootblock_t *, char *);
73af28f636SEnrico Perla - Sun Microsystems static int prepare_bootblock(ib_data_t *, char *);
74af28f636SEnrico Perla - Sun Microsystems static int write_zfs_bootblock(ib_data_t *);
75af28f636SEnrico Perla - Sun Microsystems static int write_bootblock(ib_data_t *);
76af28f636SEnrico Perla - Sun Microsystems static int open_device(ib_device_t *);
77af28f636SEnrico Perla - Sun Microsystems static int init_device(ib_device_t *, char *);
78af28f636SEnrico Perla - Sun Microsystems static void cleanup_device(ib_device_t *);
79af28f636SEnrico Perla - Sun Microsystems static int commit_to_disk(ib_data_t *, char *);
80af28f636SEnrico Perla - Sun Microsystems static int handle_install(char *, char **);
81af28f636SEnrico Perla - Sun Microsystems static int handle_getinfo(char *, char **);
82af28f636SEnrico Perla - Sun Microsystems static int handle_mirror(char *, char **);
83af28f636SEnrico Perla - Sun Microsystems static boolean_t is_update_necessary(ib_data_t *, char *);
84af28f636SEnrico Perla - Sun Microsystems static int propagate_bootblock(ib_data_t *, ib_data_t *, char *);
85af28f636SEnrico Perla - Sun Microsystems static void usage(char *);
86af28f636SEnrico Perla - Sun Microsystems 
87af28f636SEnrico Perla - Sun Microsystems static int
read_bootblock_from_file(char * file,ib_data_t * data)88af28f636SEnrico Perla - Sun Microsystems read_bootblock_from_file(char *file, ib_data_t *data)
89af28f636SEnrico Perla - Sun Microsystems {
90af28f636SEnrico Perla - Sun Microsystems 	ib_device_t	*device = &data->device;
91af28f636SEnrico Perla - Sun Microsystems 	ib_bootblock_t	*bblock = &data->bootblock;
92af28f636SEnrico Perla - Sun Microsystems 	struct stat 	sb;
93af28f636SEnrico Perla - Sun Microsystems 	uint32_t	buf_size;
94af28f636SEnrico Perla - Sun Microsystems 	int		fd = -1;
95af28f636SEnrico Perla - Sun Microsystems 	int		retval = BC_ERROR;
96af28f636SEnrico Perla - Sun Microsystems 
97af28f636SEnrico Perla - Sun Microsystems 	assert(data != NULL);
98af28f636SEnrico Perla - Sun Microsystems 	assert(file != NULL);
99af28f636SEnrico Perla - Sun Microsystems 
100af28f636SEnrico Perla - Sun Microsystems 	fd = open(file, O_RDONLY);
101af28f636SEnrico Perla - Sun Microsystems 	if (fd == -1) {
102af28f636SEnrico Perla - Sun Microsystems 		BOOT_DEBUG("Error opening %s\n", file);
103af28f636SEnrico Perla - Sun Microsystems 		perror("open");
104af28f636SEnrico Perla - Sun Microsystems 		goto out;
105af28f636SEnrico Perla - Sun Microsystems 	}
106af28f636SEnrico Perla - Sun Microsystems 
107af28f636SEnrico Perla - Sun Microsystems 	if (fstat(fd, &sb) == -1) {
108af28f636SEnrico Perla - Sun Microsystems 		BOOT_DEBUG("Error getting information (stat) about %s", file);
109af28f636SEnrico Perla - Sun Microsystems 		perror("stat");
110af28f636SEnrico Perla - Sun Microsystems 		goto outfd;
111af28f636SEnrico Perla - Sun Microsystems 	}
112af28f636SEnrico Perla - Sun Microsystems 
113af28f636SEnrico Perla - Sun Microsystems 	bblock->file_size = sb.st_size;
114af28f636SEnrico Perla - Sun Microsystems 	BOOT_DEBUG("bootblock file size is %x\n", bblock->file_size);
115af28f636SEnrico Perla - Sun Microsystems 
116af28f636SEnrico Perla - Sun Microsystems 	/* UFS and HSFS bootblocks need to fit in the reserved 7.5K. */
117af28f636SEnrico Perla - Sun Microsystems 	if (!is_zfs(device->type)) {
118af28f636SEnrico Perla - Sun Microsystems 		buf_size = P2ROUNDUP(bblock->file_size, SECTOR_SIZE);
119af28f636SEnrico Perla - Sun Microsystems 		if (buf_size > BBLK_DATA_RSVD_SIZE) {
120af28f636SEnrico Perla - Sun Microsystems 			BOOT_DEBUG("boot block size is bigger than allowed\n");
121af28f636SEnrico Perla - Sun Microsystems 			goto outfd;
122af28f636SEnrico Perla - Sun Microsystems 		}
123af28f636SEnrico Perla - Sun Microsystems 	} else {
124af28f636SEnrico Perla - Sun Microsystems 		buf_size = P2ROUNDUP(bblock->file_size + SECTOR_SIZE,
125af28f636SEnrico Perla - Sun Microsystems 		    SECTOR_SIZE);
126af28f636SEnrico Perla - Sun Microsystems 		if (buf_size > BBLK_DATA_RSVD_SIZE + MBOOT_SCAN_SIZE) {
127af28f636SEnrico Perla - Sun Microsystems 			(void) fprintf(stderr, gettext("WARNING, bootblock size"
128af28f636SEnrico Perla - Sun Microsystems 			    " does not allow to place extended versioning "
129af28f636SEnrico Perla - Sun Microsystems 			    "information.. skipping\n"));
130af28f636SEnrico Perla - Sun Microsystems 			do_version = B_FALSE;
131af28f636SEnrico Perla - Sun Microsystems 		}
132af28f636SEnrico Perla - Sun Microsystems 	}
133af28f636SEnrico Perla - Sun Microsystems 
134af28f636SEnrico Perla - Sun Microsystems 	bblock->buf_size = buf_size;
135af28f636SEnrico Perla - Sun Microsystems 	BOOT_DEBUG("bootblock in-memory buffer size is %x\n",
136af28f636SEnrico Perla - Sun Microsystems 	    bblock->buf_size);
137af28f636SEnrico Perla - Sun Microsystems 
138af28f636SEnrico Perla - Sun Microsystems 	bblock->buf = malloc(buf_size);
139af28f636SEnrico Perla - Sun Microsystems 	if (bblock->buf == NULL) {
140af28f636SEnrico Perla - Sun Microsystems 		perror(gettext("Memory allocation failure"));
141af28f636SEnrico Perla - Sun Microsystems 		goto outbuf;
142af28f636SEnrico Perla - Sun Microsystems 	}
143af28f636SEnrico Perla - Sun Microsystems 	bblock->file = bblock->buf;
144af28f636SEnrico Perla - Sun Microsystems 
145af28f636SEnrico Perla - Sun Microsystems 	if (read(fd, bblock->file, bblock->file_size) != bblock->file_size) {
146af28f636SEnrico Perla - Sun Microsystems 		BOOT_DEBUG("Read from %s failed\n", file);
147af28f636SEnrico Perla - Sun Microsystems 		perror("read");
148af28f636SEnrico Perla - Sun Microsystems 		goto outfd;
149af28f636SEnrico Perla - Sun Microsystems 	}
150af28f636SEnrico Perla - Sun Microsystems 
151af28f636SEnrico Perla - Sun Microsystems 	/* If not on ZFS, we are done here. */
152af28f636SEnrico Perla - Sun Microsystems 	if (!is_zfs(device->type)) {
153af28f636SEnrico Perla - Sun Microsystems 		BOOT_DEBUG("Reading of the bootblock done\n");
154af28f636SEnrico Perla - Sun Microsystems 		retval = BC_SUCCESS;
155af28f636SEnrico Perla - Sun Microsystems 		goto outfd;
156af28f636SEnrico Perla - Sun Microsystems 	}
157af28f636SEnrico Perla - Sun Microsystems 	/*
158af28f636SEnrico Perla - Sun Microsystems 	 * We place the multiboot header right after the file, followed by
159af28f636SEnrico Perla - Sun Microsystems 	 * the extended information structure.
160af28f636SEnrico Perla - Sun Microsystems 	 */
161af28f636SEnrico Perla - Sun Microsystems 	bblock->mboot = (multiboot_header_t *)(bblock->file +
162af28f636SEnrico Perla - Sun Microsystems 	    P2ROUNDUP(bblock->file_size, 8));
163af28f636SEnrico Perla - Sun Microsystems 	bblock->extra = (char *)bblock->mboot + sizeof (multiboot_header_t);
164af28f636SEnrico Perla - Sun Microsystems 	BOOT_DEBUG("mboot at %p, extra at %p, buf=%p (size=%d)\n",
165af28f636SEnrico Perla - Sun Microsystems 	    bblock->mboot, bblock->extra, bblock->buf, bblock->buf_size);
166af28f636SEnrico Perla - Sun Microsystems 
167af28f636SEnrico Perla - Sun Microsystems 	(void) close(fd);
168af28f636SEnrico Perla - Sun Microsystems 	return (BC_SUCCESS);
169af28f636SEnrico Perla - Sun Microsystems 
170af28f636SEnrico Perla - Sun Microsystems outbuf:
171af28f636SEnrico Perla - Sun Microsystems 	(void) free(bblock->buf);
172af28f636SEnrico Perla - Sun Microsystems 	bblock->buf = NULL;
173af28f636SEnrico Perla - Sun Microsystems outfd:
174af28f636SEnrico Perla - Sun Microsystems 	(void) close(fd);
175af28f636SEnrico Perla - Sun Microsystems out:
176af28f636SEnrico Perla - Sun Microsystems 	return (retval);
177af28f636SEnrico Perla - Sun Microsystems }
178af28f636SEnrico Perla - Sun Microsystems 
179af28f636SEnrico Perla - Sun Microsystems static int
read_bootblock_from_disk(int dev_fd,ib_bootblock_t * bblock)180af28f636SEnrico Perla - Sun Microsystems read_bootblock_from_disk(int dev_fd, ib_bootblock_t *bblock)
181af28f636SEnrico Perla - Sun Microsystems {
182af28f636SEnrico Perla - Sun Microsystems 	char			*dest;
183af28f636SEnrico Perla - Sun Microsystems 	uint32_t		size;
184af28f636SEnrico Perla - Sun Microsystems 	uint32_t		buf_size;
185af28f636SEnrico Perla - Sun Microsystems 	uint32_t		mboot_off;
186af28f636SEnrico Perla - Sun Microsystems 	multiboot_header_t	*mboot;
187af28f636SEnrico Perla - Sun Microsystems 
188af28f636SEnrico Perla - Sun Microsystems 	assert(bblock != NULL);
189af28f636SEnrico Perla - Sun Microsystems 	assert(dev_fd != -1);
190af28f636SEnrico Perla - Sun Microsystems 
191af28f636SEnrico Perla - Sun Microsystems 	/*
192af28f636SEnrico Perla - Sun Microsystems 	 * The ZFS bootblock is divided in two parts, but the fake multiboot
193af28f636SEnrico Perla - Sun Microsystems 	 * header can only be in the second part (the one contained in the ZFS
194af28f636SEnrico Perla - Sun Microsystems 	 * reserved area).
195af28f636SEnrico Perla - Sun Microsystems 	 */
196af28f636SEnrico Perla - Sun Microsystems 	if (read_in(dev_fd, mboot_scan, sizeof (mboot_scan),
197af28f636SEnrico Perla - Sun Microsystems 	    BBLK_ZFS_EXTRA_OFF) != BC_SUCCESS) {
198af28f636SEnrico Perla - Sun Microsystems 		BOOT_DEBUG("Error reading ZFS reserved area\n");
199af28f636SEnrico Perla - Sun Microsystems 		perror("read");
200af28f636SEnrico Perla - Sun Microsystems 		return (BC_ERROR);
201af28f636SEnrico Perla - Sun Microsystems 	}
202af28f636SEnrico Perla - Sun Microsystems 
203af28f636SEnrico Perla - Sun Microsystems 	/* No multiboot means no chance of knowing bootblock size */
204af28f636SEnrico Perla - Sun Microsystems 	if (find_multiboot(mboot_scan, sizeof (mboot_scan), &mboot_off)
205af28f636SEnrico Perla - Sun Microsystems 	    != BC_SUCCESS) {
206af28f636SEnrico Perla - Sun Microsystems 		BOOT_DEBUG("Unable to find multiboot header\n");
207af28f636SEnrico Perla - Sun Microsystems 		return (BC_NOEXTRA);
208af28f636SEnrico Perla - Sun Microsystems 	}
209af28f636SEnrico Perla - Sun Microsystems 	mboot = (multiboot_header_t *)(mboot_scan + mboot_off);
210af28f636SEnrico Perla - Sun Microsystems 
211af28f636SEnrico Perla - Sun Microsystems 	/*
212af28f636SEnrico Perla - Sun Microsystems 	 * Currently, the amount of space reserved for extra information
213af28f636SEnrico Perla - Sun Microsystems 	 * is "fixed". We may have to scan for the terminating extra payload
214af28f636SEnrico Perla - Sun Microsystems 	 * in the future.
215af28f636SEnrico Perla - Sun Microsystems 	 */
216af28f636SEnrico Perla - Sun Microsystems 	size = mboot->load_end_addr - mboot->load_addr;
217af28f636SEnrico Perla - Sun Microsystems 	buf_size = P2ROUNDUP(size + SECTOR_SIZE, SECTOR_SIZE);
218af28f636SEnrico Perla - Sun Microsystems 	bblock->file_size = size;
219af28f636SEnrico Perla - Sun Microsystems 
220af28f636SEnrico Perla - Sun Microsystems 	bblock->buf = malloc(buf_size);
221af28f636SEnrico Perla - Sun Microsystems 	if (bblock->buf == NULL) {
222af28f636SEnrico Perla - Sun Microsystems 		BOOT_DEBUG("Unable to allocate enough memory to read"
223af28f636SEnrico Perla - Sun Microsystems 		    " the extra bootblock from the disk\n");
224af28f636SEnrico Perla - Sun Microsystems 		perror(gettext("Memory allocation failure"));
225af28f636SEnrico Perla - Sun Microsystems 		return (BC_ERROR);
226af28f636SEnrico Perla - Sun Microsystems 	}
227af28f636SEnrico Perla - Sun Microsystems 	bblock->buf_size = buf_size;
228af28f636SEnrico Perla - Sun Microsystems 
229af28f636SEnrico Perla - Sun Microsystems 	dest = bblock->buf;
230af28f636SEnrico Perla - Sun Microsystems 	size = BBLK_DATA_RSVD_SIZE;
231af28f636SEnrico Perla - Sun Microsystems 
232af28f636SEnrico Perla - Sun Microsystems 	if (read_in(dev_fd, dest, size, SECTOR_SIZE) != BC_SUCCESS) {
233af28f636SEnrico Perla - Sun Microsystems 		BOOT_DEBUG("Error reading first %d bytes of the bootblock\n",
234af28f636SEnrico Perla - Sun Microsystems 		    size);
235af28f636SEnrico Perla - Sun Microsystems 		(void) free(bblock->buf);
236af28f636SEnrico Perla - Sun Microsystems 		bblock->buf = NULL;
237af28f636SEnrico Perla - Sun Microsystems 		return (BC_ERROR);
238af28f636SEnrico Perla - Sun Microsystems 	}
239af28f636SEnrico Perla - Sun Microsystems 
240af28f636SEnrico Perla - Sun Microsystems 	dest += BBLK_DATA_RSVD_SIZE;
241af28f636SEnrico Perla - Sun Microsystems 	size = bblock->buf_size - BBLK_DATA_RSVD_SIZE;
242af28f636SEnrico Perla - Sun Microsystems 
243af28f636SEnrico Perla - Sun Microsystems 	if (read_in(dev_fd, dest, size, BBLK_ZFS_EXTRA_OFF) != BC_SUCCESS) {
244af28f636SEnrico Perla - Sun Microsystems 		BOOT_DEBUG("Error reading ZFS reserved area the second time\n");
245af28f636SEnrico Perla - Sun Microsystems 		(void) free(bblock->buf);
246af28f636SEnrico Perla - Sun Microsystems 		bblock->buf = NULL;
247af28f636SEnrico Perla - Sun Microsystems 		return (BC_ERROR);
248af28f636SEnrico Perla - Sun Microsystems 	}
249af28f636SEnrico Perla - Sun Microsystems 
250af28f636SEnrico Perla - Sun Microsystems 	/* Update pointers. */
251af28f636SEnrico Perla - Sun Microsystems 	bblock->file = bblock->buf;
252af28f636SEnrico Perla - Sun Microsystems 	bblock->mboot_off = mboot_off;
253af28f636SEnrico Perla - Sun Microsystems 	bblock->mboot = (multiboot_header_t *)(bblock->buf + bblock->mboot_off
254af28f636SEnrico Perla - Sun Microsystems 	    + BBLK_DATA_RSVD_SIZE);
255af28f636SEnrico Perla - Sun Microsystems 	bblock->extra = (char *)bblock->mboot + sizeof (multiboot_header_t);
25614d44f22SHans Rosenfeld 	bblock->extra_size = bblock->buf_size - bblock->mboot_off
25714d44f22SHans Rosenfeld 	    - BBLK_DATA_RSVD_SIZE - sizeof (multiboot_header_t);
258af28f636SEnrico Perla - Sun Microsystems 	return (BC_SUCCESS);
259af28f636SEnrico Perla - Sun Microsystems }
260af28f636SEnrico Perla - Sun Microsystems 
261af28f636SEnrico Perla - Sun Microsystems static boolean_t
is_update_necessary(ib_data_t * data,char * updt_str)262af28f636SEnrico Perla - Sun Microsystems is_update_necessary(ib_data_t *data, char *updt_str)
263af28f636SEnrico Perla - Sun Microsystems {
264af28f636SEnrico Perla - Sun Microsystems 	bblk_einfo_t	*einfo;
265af28f636SEnrico Perla - Sun Microsystems 	bblk_hs_t	bblock_hs;
266af28f636SEnrico Perla - Sun Microsystems 	ib_bootblock_t	bblock_disk;
267af28f636SEnrico Perla - Sun Microsystems 	ib_bootblock_t	*bblock_file = &data->bootblock;
268af28f636SEnrico Perla - Sun Microsystems 	ib_device_t	*device = &data->device;
269af28f636SEnrico Perla - Sun Microsystems 	int		dev_fd = device->fd;
270af28f636SEnrico Perla - Sun Microsystems 
271af28f636SEnrico Perla - Sun Microsystems 	assert(data != NULL);
272af28f636SEnrico Perla - Sun Microsystems 	assert(device->fd != -1);
273af28f636SEnrico Perla - Sun Microsystems 
274af28f636SEnrico Perla - Sun Microsystems 	/* Nothing to do if we are not updating a ZFS bootblock. */
275af28f636SEnrico Perla - Sun Microsystems 	if (!is_zfs(device->type))
276af28f636SEnrico Perla - Sun Microsystems 		return (B_TRUE);
277af28f636SEnrico Perla - Sun Microsystems 
278af28f636SEnrico Perla - Sun Microsystems 	bzero(&bblock_disk, sizeof (ib_bootblock_t));
279af28f636SEnrico Perla - Sun Microsystems 
280af28f636SEnrico Perla - Sun Microsystems 	if (read_bootblock_from_disk(dev_fd, &bblock_disk) != BC_SUCCESS) {
281af28f636SEnrico Perla - Sun Microsystems 		BOOT_DEBUG("Unable to read bootblock from %s\n", device->path);
282af28f636SEnrico Perla - Sun Microsystems 		return (B_TRUE);
283af28f636SEnrico Perla - Sun Microsystems 	}
284af28f636SEnrico Perla - Sun Microsystems 
28514d44f22SHans Rosenfeld 	einfo = find_einfo(bblock_disk.extra, bblock_disk.extra_size);
286af28f636SEnrico Perla - Sun Microsystems 	if (einfo == NULL) {
287af28f636SEnrico Perla - Sun Microsystems 		BOOT_DEBUG("No extended information available\n");
288af28f636SEnrico Perla - Sun Microsystems 		return (B_TRUE);
289af28f636SEnrico Perla - Sun Microsystems 	}
290af28f636SEnrico Perla - Sun Microsystems 
291af28f636SEnrico Perla - Sun Microsystems 	if (!do_version || updt_str == NULL) {
292af28f636SEnrico Perla - Sun Microsystems 		(void) fprintf(stdout, "WARNING: target device %s has a "
293af28f636SEnrico Perla - Sun Microsystems 		    "versioned bootblock that is going to be overwritten by a "
294af28f636SEnrico Perla - Sun Microsystems 		    "non versioned one\n", device->path);
295af28f636SEnrico Perla - Sun Microsystems 		return (B_TRUE);
296af28f636SEnrico Perla - Sun Microsystems 	}
297af28f636SEnrico Perla - Sun Microsystems 
298af28f636SEnrico Perla - Sun Microsystems 	if (force_update) {
299af28f636SEnrico Perla - Sun Microsystems 		BOOT_DEBUG("Forcing update of %s bootblock\n", device->path);
300af28f636SEnrico Perla - Sun Microsystems 		return (B_TRUE);
301af28f636SEnrico Perla - Sun Microsystems 	}
302af28f636SEnrico Perla - Sun Microsystems 
303af28f636SEnrico Perla - Sun Microsystems 	BOOT_DEBUG("Ready to check installed version vs %s\n", updt_str);
304af28f636SEnrico Perla - Sun Microsystems 
305af28f636SEnrico Perla - Sun Microsystems 	bblock_hs.src_buf = (unsigned char *)bblock_file->file;
306af28f636SEnrico Perla - Sun Microsystems 	bblock_hs.src_size = bblock_file->file_size;
307af28f636SEnrico Perla - Sun Microsystems 
308af28f636SEnrico Perla - Sun Microsystems 	return (einfo_should_update(einfo, &bblock_hs, updt_str));
309af28f636SEnrico Perla - Sun Microsystems }
310af28f636SEnrico Perla - Sun Microsystems 
311af28f636SEnrico Perla - Sun Microsystems static void
add_bootblock_einfo(ib_bootblock_t * bblock,char * updt_str)312af28f636SEnrico Perla - Sun Microsystems add_bootblock_einfo(ib_bootblock_t *bblock, char *updt_str)
313af28f636SEnrico Perla - Sun Microsystems {
314af28f636SEnrico Perla - Sun Microsystems 	bblk_hs_t	hs;
315af28f636SEnrico Perla - Sun Microsystems 	uint32_t	avail_space;
316af28f636SEnrico Perla - Sun Microsystems 
317af28f636SEnrico Perla - Sun Microsystems 	assert(bblock != NULL);
318af28f636SEnrico Perla - Sun Microsystems 
319af28f636SEnrico Perla - Sun Microsystems 	if (updt_str == NULL) {
320af28f636SEnrico Perla - Sun Microsystems 		BOOT_DEBUG("WARNING: no update string passed to "
321af28f636SEnrico Perla - Sun Microsystems 		    "add_bootblock_einfo()\n");
322af28f636SEnrico Perla - Sun Microsystems 		return;
323af28f636SEnrico Perla - Sun Microsystems 	}
324af28f636SEnrico Perla - Sun Microsystems 
325af28f636SEnrico Perla - Sun Microsystems 	/* Fill bootblock hashing source information. */
326af28f636SEnrico Perla - Sun Microsystems 	hs.src_buf = (unsigned char *)bblock->file;
327af28f636SEnrico Perla - Sun Microsystems 	hs.src_size = bblock->file_size;
328af28f636SEnrico Perla - Sun Microsystems 	/* How much space for the extended information structure? */
329af28f636SEnrico Perla - Sun Microsystems 	avail_space = bblock->buf_size - P2ROUNDUP(bblock->file_size, 8);
330af28f636SEnrico Perla - Sun Microsystems 	/* Place the extended information structure. */
331af28f636SEnrico Perla - Sun Microsystems 	add_einfo(bblock->extra, updt_str, &hs, avail_space);
332af28f636SEnrico Perla - Sun Microsystems }
333af28f636SEnrico Perla - Sun Microsystems 
334af28f636SEnrico Perla - Sun Microsystems 
335af28f636SEnrico Perla - Sun Microsystems static int
prepare_bootblock(ib_data_t * data,char * updt_str)336af28f636SEnrico Perla - Sun Microsystems prepare_bootblock(ib_data_t *data, char *updt_str)
337af28f636SEnrico Perla - Sun Microsystems {
338af28f636SEnrico Perla - Sun Microsystems 	ib_device_t		*device = &data->device;
339af28f636SEnrico Perla - Sun Microsystems 	ib_bootblock_t		*bblock = &data->bootblock;
340af28f636SEnrico Perla - Sun Microsystems 	multiboot_header_t	*mboot;
341af28f636SEnrico Perla - Sun Microsystems 
342af28f636SEnrico Perla - Sun Microsystems 	assert(data != NULL);
343af28f636SEnrico Perla - Sun Microsystems 
344af28f636SEnrico Perla - Sun Microsystems 	/* Nothing to do if we are not on ZFS. */
345af28f636SEnrico Perla - Sun Microsystems 	if (!is_zfs(device->type))
346af28f636SEnrico Perla - Sun Microsystems 		return (BC_SUCCESS);
347af28f636SEnrico Perla - Sun Microsystems 
348af28f636SEnrico Perla - Sun Microsystems 	/*
349af28f636SEnrico Perla - Sun Microsystems 	 * Write the fake multiboot structure followed by the extra information
350af28f636SEnrico Perla - Sun Microsystems 	 * data. Both mboot and extra pointers have already been filled up to
351af28f636SEnrico Perla - Sun Microsystems 	 * point to the right location in the buffer. We prepare the fake
352af28f636SEnrico Perla - Sun Microsystems 	 * multiboot regardless if versioning was requested or not because
353af28f636SEnrico Perla - Sun Microsystems 	 * we need it for mirroring support.
354af28f636SEnrico Perla - Sun Microsystems 	 */
355af28f636SEnrico Perla - Sun Microsystems 	assert(bblock->mboot != NULL);
356af28f636SEnrico Perla - Sun Microsystems 	assert(bblock->extra != NULL);
357af28f636SEnrico Perla - Sun Microsystems 
358af28f636SEnrico Perla - Sun Microsystems 	mboot = bblock->mboot;
359af28f636SEnrico Perla - Sun Microsystems 
360af28f636SEnrico Perla - Sun Microsystems 	mboot->magic = MB_HEADER_MAGIC;
361af28f636SEnrico Perla - Sun Microsystems 	mboot->flags = MB_HEADER_FLAGS_64;
362af28f636SEnrico Perla - Sun Microsystems 	mboot->checksum = -(mboot->flags + mboot->magic);
363af28f636SEnrico Perla - Sun Microsystems 	/*
364af28f636SEnrico Perla - Sun Microsystems 	 * Flags include the AOUT_KLUDGE and we use the extra members to specify
365af28f636SEnrico Perla - Sun Microsystems 	 * the size of the bootblock.
366af28f636SEnrico Perla - Sun Microsystems 	 */
367af28f636SEnrico Perla - Sun Microsystems 	mboot->header_addr = bblock->mboot_off;
368af28f636SEnrico Perla - Sun Microsystems 	mboot->load_addr = 0;
369af28f636SEnrico Perla - Sun Microsystems 	mboot->load_end_addr = bblock->file_size;
370af28f636SEnrico Perla - Sun Microsystems 
371af28f636SEnrico Perla - Sun Microsystems 	/*
372af28f636SEnrico Perla - Sun Microsystems 	 * Now that we have the mboot header in place, we can add the extended
373af28f636SEnrico Perla - Sun Microsystems 	 * versioning information. Since the multiboot header has been placed
374af28f636SEnrico Perla - Sun Microsystems 	 * after the file image, the hashing will still reflect the one of the
375af28f636SEnrico Perla - Sun Microsystems 	 * file on the disk.
376af28f636SEnrico Perla - Sun Microsystems 	 */
377af28f636SEnrico Perla - Sun Microsystems 	if (do_version)
378af28f636SEnrico Perla - Sun Microsystems 		add_bootblock_einfo(bblock, updt_str);
379af28f636SEnrico Perla - Sun Microsystems 
380af28f636SEnrico Perla - Sun Microsystems 	return (BC_SUCCESS);
381af28f636SEnrico Perla - Sun Microsystems }
382af28f636SEnrico Perla - Sun Microsystems 
383af28f636SEnrico Perla - Sun Microsystems static int
write_zfs_bootblock(ib_data_t * data)384af28f636SEnrico Perla - Sun Microsystems write_zfs_bootblock(ib_data_t *data)
385af28f636SEnrico Perla - Sun Microsystems {
386af28f636SEnrico Perla - Sun Microsystems 	ib_device_t	*device = &data->device;
387af28f636SEnrico Perla - Sun Microsystems 	ib_bootblock_t	*bblock = &data->bootblock;
388af28f636SEnrico Perla - Sun Microsystems 	char		*bufptr;
389af28f636SEnrico Perla - Sun Microsystems 	uint32_t	size;
390af28f636SEnrico Perla - Sun Microsystems 
391af28f636SEnrico Perla - Sun Microsystems 	assert(data != NULL);
392af28f636SEnrico Perla - Sun Microsystems 	assert(device->fd != -1);
393af28f636SEnrico Perla - Sun Microsystems 
394af28f636SEnrico Perla - Sun Microsystems 	/*
395af28f636SEnrico Perla - Sun Microsystems 	 * In the ZFS case we actually perform two different steps:
396af28f636SEnrico Perla - Sun Microsystems 	 * - write the first 15 blocks of the bootblock to the reserved disk
397af28f636SEnrico Perla - Sun Microsystems 	 *   blocks.
398af28f636SEnrico Perla - Sun Microsystems 	 * - write the remaining blocks in the ZFS reserved area at offset
399af28f636SEnrico Perla - Sun Microsystems 	 *   512K.
400af28f636SEnrico Perla - Sun Microsystems 	 */
401af28f636SEnrico Perla - Sun Microsystems 	bufptr = bblock->buf;
402af28f636SEnrico Perla - Sun Microsystems 	size = BBLK_DATA_RSVD_SIZE;
403af28f636SEnrico Perla - Sun Microsystems 
404af28f636SEnrico Perla - Sun Microsystems 	if (write_out(device->fd, bufptr, size, SECTOR_SIZE) != BC_SUCCESS) {
405af28f636SEnrico Perla - Sun Microsystems 		BOOT_DEBUG("Error writing first 15 blocks of %s\n",
406af28f636SEnrico Perla - Sun Microsystems 		    device->path);
407af28f636SEnrico Perla - Sun Microsystems 		perror("write");
408af28f636SEnrico Perla - Sun Microsystems 		return (BC_ERROR);
409af28f636SEnrico Perla - Sun Microsystems 	}
410af28f636SEnrico Perla - Sun Microsystems 
411af28f636SEnrico Perla - Sun Microsystems 	bufptr += BBLK_DATA_RSVD_SIZE;
412af28f636SEnrico Perla - Sun Microsystems 	size = bblock->buf_size - BBLK_DATA_RSVD_SIZE;
413af28f636SEnrico Perla - Sun Microsystems 
414af28f636SEnrico Perla - Sun Microsystems 	if (write_out(device->fd, bufptr, size, BBLK_ZFS_EXTRA_OFF)
415af28f636SEnrico Perla - Sun Microsystems 	    != BC_SUCCESS) {
416af28f636SEnrico Perla - Sun Microsystems 		BOOT_DEBUG("Error writing the second part of ZFS bootblock "
417af28f636SEnrico Perla - Sun Microsystems 		    "to %s at offset %d\n", device->path, BBLK_ZFS_EXTRA_OFF);
418af28f636SEnrico Perla - Sun Microsystems 		return (BC_ERROR);
419af28f636SEnrico Perla - Sun Microsystems 	}
420af28f636SEnrico Perla - Sun Microsystems 	return (BC_SUCCESS);
421af28f636SEnrico Perla - Sun Microsystems }
422af28f636SEnrico Perla - Sun Microsystems 
423af28f636SEnrico Perla - Sun Microsystems static int
write_bootblock(ib_data_t * data)424af28f636SEnrico Perla - Sun Microsystems write_bootblock(ib_data_t *data)
425af28f636SEnrico Perla - Sun Microsystems {
426af28f636SEnrico Perla - Sun Microsystems 	ib_device_t	*device = &data->device;
427af28f636SEnrico Perla - Sun Microsystems 	ib_bootblock_t	*bblock = &data->bootblock;
428af28f636SEnrico Perla - Sun Microsystems 	int		ret;
429af28f636SEnrico Perla - Sun Microsystems 
430af28f636SEnrico Perla - Sun Microsystems 	assert(data != NULL);
431af28f636SEnrico Perla - Sun Microsystems 
432af28f636SEnrico Perla - Sun Microsystems 	/*
433af28f636SEnrico Perla - Sun Microsystems 	 * If we are on UFS or HSFS we simply write out to the reserved
434af28f636SEnrico Perla - Sun Microsystems 	 * blocks (1 to 15) the boot block.
435af28f636SEnrico Perla - Sun Microsystems 	 */
436af28f636SEnrico Perla - Sun Microsystems 	if (!is_zfs(device->type)) {
437af28f636SEnrico Perla - Sun Microsystems 		if (write_out(device->fd, bblock->buf, bblock->buf_size,
438af28f636SEnrico Perla - Sun Microsystems 		    SECTOR_SIZE) != BC_SUCCESS) {
439af28f636SEnrico Perla - Sun Microsystems 			BOOT_DEBUG("Error writing bootblock to %s\n",
440af28f636SEnrico Perla - Sun Microsystems 			    device->path);
441af28f636SEnrico Perla - Sun Microsystems 			return (BC_ERROR);
442af28f636SEnrico Perla - Sun Microsystems 		} else {
443af28f636SEnrico Perla - Sun Microsystems 			return (BC_SUCCESS);
444af28f636SEnrico Perla - Sun Microsystems 		}
445af28f636SEnrico Perla - Sun Microsystems 	} else {
446af28f636SEnrico Perla - Sun Microsystems 		ret = write_zfs_bootblock(data);
447af28f636SEnrico Perla - Sun Microsystems 		return (ret);
448af28f636SEnrico Perla - Sun Microsystems 	}
449af28f636SEnrico Perla - Sun Microsystems }
450af28f636SEnrico Perla - Sun Microsystems 
451af28f636SEnrico Perla - Sun Microsystems static int
open_device(ib_device_t * device)452af28f636SEnrico Perla - Sun Microsystems open_device(ib_device_t *device)
453af28f636SEnrico Perla - Sun Microsystems {
454af28f636SEnrico Perla - Sun Microsystems 	struct stat	statbuf;
455af28f636SEnrico Perla - Sun Microsystems 
456af28f636SEnrico Perla - Sun Microsystems 	device->fd = open(device->path, O_RDWR);
457af28f636SEnrico Perla - Sun Microsystems 	if (device->fd == -1) {
458af28f636SEnrico Perla - Sun Microsystems 		BOOT_DEBUG("Unable to open %s\n", device->path);
459af28f636SEnrico Perla - Sun Microsystems 		perror("open");
460af28f636SEnrico Perla - Sun Microsystems 		return (BC_ERROR);
461af28f636SEnrico Perla - Sun Microsystems 	}
462af28f636SEnrico Perla - Sun Microsystems 
463af28f636SEnrico Perla - Sun Microsystems 	if (fstat(device->fd, &statbuf) != 0) {
464af28f636SEnrico Perla - Sun Microsystems 		BOOT_DEBUG("Unable to stat %s\n", device->path);
465af28f636SEnrico Perla - Sun Microsystems 		perror("stat");
466af28f636SEnrico Perla - Sun Microsystems 		(void) close(device->fd);
467af28f636SEnrico Perla - Sun Microsystems 		return (BC_ERROR);
468af28f636SEnrico Perla - Sun Microsystems 	}
469af28f636SEnrico Perla - Sun Microsystems 
470af28f636SEnrico Perla - Sun Microsystems 	if (S_ISCHR(statbuf.st_mode) == 0) {
471af28f636SEnrico Perla - Sun Microsystems 		(void) fprintf(stderr, gettext("%s: Not a character device\n"),
472af28f636SEnrico Perla - Sun Microsystems 		    device->path);
473af28f636SEnrico Perla - Sun Microsystems 		return (BC_ERROR);
474af28f636SEnrico Perla - Sun Microsystems 	}
475af28f636SEnrico Perla - Sun Microsystems 
476af28f636SEnrico Perla - Sun Microsystems 	return (BC_SUCCESS);
477af28f636SEnrico Perla - Sun Microsystems }
478af28f636SEnrico Perla - Sun Microsystems 
479af28f636SEnrico Perla - Sun Microsystems static int
init_device(ib_device_t * device,char * path)480af28f636SEnrico Perla - Sun Microsystems init_device(ib_device_t *device, char *path)
481af28f636SEnrico Perla - Sun Microsystems {
482af28f636SEnrico Perla - Sun Microsystems 	bzero(device, sizeof (*device));
483af28f636SEnrico Perla - Sun Microsystems 	device->fd = -1;
484af28f636SEnrico Perla - Sun Microsystems 
485af28f636SEnrico Perla - Sun Microsystems 	device->path = strdup(path);
486af28f636SEnrico Perla - Sun Microsystems 	if (path == NULL) {
487af28f636SEnrico Perla - Sun Microsystems 		perror(gettext("Memory allocation failure"));
488af28f636SEnrico Perla - Sun Microsystems 		return (BC_ERROR);
489af28f636SEnrico Perla - Sun Microsystems 	}
490af28f636SEnrico Perla - Sun Microsystems 
491af28f636SEnrico Perla - Sun Microsystems 	device->type = tgt_fs_type;
492af28f636SEnrico Perla - Sun Microsystems 	if (open_device(device) != BC_SUCCESS)
493af28f636SEnrico Perla - Sun Microsystems 		return (BC_ERROR);
494af28f636SEnrico Perla - Sun Microsystems 
495af28f636SEnrico Perla - Sun Microsystems 	return (BC_SUCCESS);
496af28f636SEnrico Perla - Sun Microsystems }
497af28f636SEnrico Perla - Sun Microsystems 
498af28f636SEnrico Perla - Sun Microsystems static void
cleanup_device(ib_device_t * device)499af28f636SEnrico Perla - Sun Microsystems cleanup_device(ib_device_t *device)
500af28f636SEnrico Perla - Sun Microsystems {
501af28f636SEnrico Perla - Sun Microsystems 	free(device->path);
502af28f636SEnrico Perla - Sun Microsystems 	bzero(device, sizeof (*device));
503af28f636SEnrico Perla - Sun Microsystems 
504af28f636SEnrico Perla - Sun Microsystems 	if (device->fd != -1)
505af28f636SEnrico Perla - Sun Microsystems 		(void) close(device->fd);
506af28f636SEnrico Perla - Sun Microsystems }
507af28f636SEnrico Perla - Sun Microsystems 
508af28f636SEnrico Perla - Sun Microsystems static void
cleanup_bootblock(ib_bootblock_t * bblock)509af28f636SEnrico Perla - Sun Microsystems cleanup_bootblock(ib_bootblock_t *bblock)
510af28f636SEnrico Perla - Sun Microsystems {
511af28f636SEnrico Perla - Sun Microsystems 	free(bblock->buf);
512af28f636SEnrico Perla - Sun Microsystems 	bzero(bblock, sizeof (ib_bootblock_t));
513af28f636SEnrico Perla - Sun Microsystems }
514af28f636SEnrico Perla - Sun Microsystems 
515af28f636SEnrico Perla - Sun Microsystems /*
516af28f636SEnrico Perla - Sun Microsystems  * Propagate the bootblock on the source disk to the destination disk and
517af28f636SEnrico Perla - Sun Microsystems  * version it with 'updt_str' in the process. Since we cannot trust any data
518af28f636SEnrico Perla - Sun Microsystems  * on the attaching disk, we do not perform any specific check on a potential
519af28f636SEnrico Perla - Sun Microsystems  * target extended information structure and we just blindly update.
520af28f636SEnrico Perla - Sun Microsystems  */
521af28f636SEnrico Perla - Sun Microsystems static int
propagate_bootblock(ib_data_t * src,ib_data_t * dest,char * updt_str)522af28f636SEnrico Perla - Sun Microsystems propagate_bootblock(ib_data_t *src, ib_data_t *dest, char *updt_str)
523af28f636SEnrico Perla - Sun Microsystems {
524af28f636SEnrico Perla - Sun Microsystems 	ib_bootblock_t	*src_bblock = &src->bootblock;
525af28f636SEnrico Perla - Sun Microsystems 	ib_bootblock_t	*dest_bblock = &dest->bootblock;
526af28f636SEnrico Perla - Sun Microsystems 	uint32_t	buf_size;
527af28f636SEnrico Perla - Sun Microsystems 
528af28f636SEnrico Perla - Sun Microsystems 	assert(src != NULL);
529af28f636SEnrico Perla - Sun Microsystems 	assert(dest != NULL);
530af28f636SEnrico Perla - Sun Microsystems 
531af28f636SEnrico Perla - Sun Microsystems 	cleanup_bootblock(dest_bblock);
532af28f636SEnrico Perla - Sun Microsystems 
533af28f636SEnrico Perla - Sun Microsystems 	if (updt_str != NULL) {
534af28f636SEnrico Perla - Sun Microsystems 		do_version = B_TRUE;
535af28f636SEnrico Perla - Sun Microsystems 	} else {
536af28f636SEnrico Perla - Sun Microsystems 		do_version = B_FALSE;
537af28f636SEnrico Perla - Sun Microsystems 	}
538af28f636SEnrico Perla - Sun Microsystems 
539af28f636SEnrico Perla - Sun Microsystems 	buf_size = src_bblock->file_size + SECTOR_SIZE;
540af28f636SEnrico Perla - Sun Microsystems 
541af28f636SEnrico Perla - Sun Microsystems 	dest_bblock->buf_size = P2ROUNDUP(buf_size, SECTOR_SIZE);
542af28f636SEnrico Perla - Sun Microsystems 	dest_bblock->buf = malloc(dest_bblock->buf_size);
543af28f636SEnrico Perla - Sun Microsystems 	if (dest_bblock->buf == NULL) {
544af28f636SEnrico Perla - Sun Microsystems 		perror(gettext("Memory Allocation Failure"));
545af28f636SEnrico Perla - Sun Microsystems 		return (BC_ERROR);
546af28f636SEnrico Perla - Sun Microsystems 	}
547af28f636SEnrico Perla - Sun Microsystems 	dest_bblock->file = dest_bblock->buf;
548af28f636SEnrico Perla - Sun Microsystems 	dest_bblock->file_size = src_bblock->file_size;
549af28f636SEnrico Perla - Sun Microsystems 	(void) memcpy(dest_bblock->file, src_bblock->file,
550af28f636SEnrico Perla - Sun Microsystems 	    dest_bblock->file_size);
551af28f636SEnrico Perla - Sun Microsystems 
552af28f636SEnrico Perla - Sun Microsystems 	dest_bblock->mboot = (multiboot_header_t *)(dest_bblock->file +
553af28f636SEnrico Perla - Sun Microsystems 	    P2ROUNDUP(dest_bblock->file_size, 8));
554af28f636SEnrico Perla - Sun Microsystems 	dest_bblock->extra = (char *)dest_bblock->mboot +
555af28f636SEnrico Perla - Sun Microsystems 	    sizeof (multiboot_header_t);
556af28f636SEnrico Perla - Sun Microsystems 
557af28f636SEnrico Perla - Sun Microsystems 	(void) fprintf(stdout, gettext("Propagating %s bootblock to %s\n"),
558af28f636SEnrico Perla - Sun Microsystems 	    src->device.path, dest->device.path);
559af28f636SEnrico Perla - Sun Microsystems 
560af28f636SEnrico Perla - Sun Microsystems 	return (commit_to_disk(dest, updt_str));
561af28f636SEnrico Perla - Sun Microsystems }
562af28f636SEnrico Perla - Sun Microsystems 
563af28f636SEnrico Perla - Sun Microsystems static int
commit_to_disk(ib_data_t * data,char * update_str)564af28f636SEnrico Perla - Sun Microsystems commit_to_disk(ib_data_t *data, char *update_str)
565af28f636SEnrico Perla - Sun Microsystems {
566af28f636SEnrico Perla - Sun Microsystems 	assert(data != NULL);
567af28f636SEnrico Perla - Sun Microsystems 
568af28f636SEnrico Perla - Sun Microsystems 	if (prepare_bootblock(data, update_str) != BC_SUCCESS) {
569af28f636SEnrico Perla - Sun Microsystems 		(void) fprintf(stderr, gettext("Error updating the bootblock "
570af28f636SEnrico Perla - Sun Microsystems 		    "image\n"));
571af28f636SEnrico Perla - Sun Microsystems 		return (BC_ERROR);
572af28f636SEnrico Perla - Sun Microsystems 	}
573af28f636SEnrico Perla - Sun Microsystems 
574af28f636SEnrico Perla - Sun Microsystems 	if (write_bootblock(data) != BC_SUCCESS) {
575af28f636SEnrico Perla - Sun Microsystems 		(void) fprintf(stderr, gettext("Error writing bootblock to "
576af28f636SEnrico Perla - Sun Microsystems 		    "disk\n"));
577af28f636SEnrico Perla - Sun Microsystems 		return (BC_ERROR);
578af28f636SEnrico Perla - Sun Microsystems 	}
579af28f636SEnrico Perla - Sun Microsystems 
580af28f636SEnrico Perla - Sun Microsystems 	return (BC_SUCCESS);
581af28f636SEnrico Perla - Sun Microsystems }
582af28f636SEnrico Perla - Sun Microsystems 
583af28f636SEnrico Perla - Sun Microsystems 
584af28f636SEnrico Perla - Sun Microsystems /*
585af28f636SEnrico Perla - Sun Microsystems  * Install a new bootblock on the given device. handle_install() expects argv
586af28f636SEnrico Perla - Sun Microsystems  * to contain 2 parameters (the target device path and the path to the
587af28f636SEnrico Perla - Sun Microsystems  * bootblock.
588af28f636SEnrico Perla - Sun Microsystems  *
589af28f636SEnrico Perla - Sun Microsystems  * Returns:	BC_SUCCESS - if the installation is successful
590af28f636SEnrico Perla - Sun Microsystems  *		BC_ERROR   - if the installation failed
591af28f636SEnrico Perla - Sun Microsystems  *		BC_NOUPDT  - if no installation was performed because the
592af28f636SEnrico Perla - Sun Microsystems  *		             version currently installed is more recent than the
593af28f636SEnrico Perla - Sun Microsystems  *			     supplied one.
594af28f636SEnrico Perla - Sun Microsystems  *
595af28f636SEnrico Perla - Sun Microsystems  */
596af28f636SEnrico Perla - Sun Microsystems static int
handle_install(char * progname,char ** argv)597af28f636SEnrico Perla - Sun Microsystems handle_install(char *progname, char **argv)
598af28f636SEnrico Perla - Sun Microsystems {
599af28f636SEnrico Perla - Sun Microsystems 	ib_data_t	install_data;
600af28f636SEnrico Perla - Sun Microsystems 	char		*bootblock = NULL;
601af28f636SEnrico Perla - Sun Microsystems 	char		*device_path = NULL;
602af28f636SEnrico Perla - Sun Microsystems 	int		ret = BC_ERROR;
603af28f636SEnrico Perla - Sun Microsystems 
604af28f636SEnrico Perla - Sun Microsystems 	bootblock = strdup(argv[0]);
605af28f636SEnrico Perla - Sun Microsystems 	device_path = strdup(argv[1]);
606af28f636SEnrico Perla - Sun Microsystems 
607af28f636SEnrico Perla - Sun Microsystems 	if (!device_path || !bootblock) {
608af28f636SEnrico Perla - Sun Microsystems 		(void) fprintf(stderr, gettext("Missing parameter"));
609af28f636SEnrico Perla - Sun Microsystems 		usage(progname);
610af28f636SEnrico Perla - Sun Microsystems 		goto out;
611af28f636SEnrico Perla - Sun Microsystems 	}
612af28f636SEnrico Perla - Sun Microsystems 
613af28f636SEnrico Perla - Sun Microsystems 	BOOT_DEBUG("device path: %s, bootblock file path: %s\n", device_path,
614af28f636SEnrico Perla - Sun Microsystems 	    bootblock);
615af28f636SEnrico Perla - Sun Microsystems 	bzero(&install_data, sizeof (ib_data_t));
616af28f636SEnrico Perla - Sun Microsystems 
617af28f636SEnrico Perla - Sun Microsystems 	if (init_device(&install_data.device, device_path) != BC_SUCCESS) {
618af28f636SEnrico Perla - Sun Microsystems 		(void) fprintf(stderr, gettext("Unable to open device %s\n"),
619af28f636SEnrico Perla - Sun Microsystems 		    device_path);
620af28f636SEnrico Perla - Sun Microsystems 		goto out;
621af28f636SEnrico Perla - Sun Microsystems 	}
622af28f636SEnrico Perla - Sun Microsystems 
623af28f636SEnrico Perla - Sun Microsystems 	if (read_bootblock_from_file(bootblock, &install_data) != BC_SUCCESS) {
624af28f636SEnrico Perla - Sun Microsystems 		(void) fprintf(stderr, gettext("Error reading %s\n"),
625af28f636SEnrico Perla - Sun Microsystems 		    bootblock);
626af28f636SEnrico Perla - Sun Microsystems 		goto out_dev;
627af28f636SEnrico Perla - Sun Microsystems 	}
628af28f636SEnrico Perla - Sun Microsystems 	/* Versioning is only supported for the ZFS bootblock. */
629af28f636SEnrico Perla - Sun Microsystems 	if (do_version && !is_zfs(install_data.device.type)) {
630af28f636SEnrico Perla - Sun Microsystems 		(void) fprintf(stderr, gettext("Versioning is only supported on"
631af28f636SEnrico Perla - Sun Microsystems 		    " ZFS... skipping.\n"));
632af28f636SEnrico Perla - Sun Microsystems 		do_version = B_FALSE;
633af28f636SEnrico Perla - Sun Microsystems 	}
634af28f636SEnrico Perla - Sun Microsystems 
635af28f636SEnrico Perla - Sun Microsystems 	/*
636af28f636SEnrico Perla - Sun Microsystems 	 * is_update_necessary() will take care of checking if versioning and/or
637af28f636SEnrico Perla - Sun Microsystems 	 * forcing the update have been specified. It will also emit a warning
638af28f636SEnrico Perla - Sun Microsystems 	 * if a non-versioned update is attempted over a versioned bootblock.
639af28f636SEnrico Perla - Sun Microsystems 	 */
640af28f636SEnrico Perla - Sun Microsystems 	if (!is_update_necessary(&install_data, update_str)) {
641af28f636SEnrico Perla - Sun Microsystems 		(void) fprintf(stderr, gettext("bootblock version installed "
642af28f636SEnrico Perla - Sun Microsystems 		    "on %s is more recent or identical\n"
643af28f636SEnrico Perla - Sun Microsystems 		    "Use -F to override or install without the -u option\n"),
644af28f636SEnrico Perla - Sun Microsystems 		    device_path);
645af28f636SEnrico Perla - Sun Microsystems 		ret = BC_NOUPDT;
646af28f636SEnrico Perla - Sun Microsystems 		goto out_dev;
647af28f636SEnrico Perla - Sun Microsystems 	}
648af28f636SEnrico Perla - Sun Microsystems 
649af28f636SEnrico Perla - Sun Microsystems 	BOOT_DEBUG("Ready to commit to disk\n");
650af28f636SEnrico Perla - Sun Microsystems 	ret = commit_to_disk(&install_data, update_str);
651af28f636SEnrico Perla - Sun Microsystems 
652af28f636SEnrico Perla - Sun Microsystems out_dev:
653af28f636SEnrico Perla - Sun Microsystems 	cleanup_device(&install_data.device);
654af28f636SEnrico Perla - Sun Microsystems out:
655af28f636SEnrico Perla - Sun Microsystems 	free(bootblock);
656af28f636SEnrico Perla - Sun Microsystems 	free(device_path);
657af28f636SEnrico Perla - Sun Microsystems 	return (ret);
658af28f636SEnrico Perla - Sun Microsystems }
659af28f636SEnrico Perla - Sun Microsystems 
660af28f636SEnrico Perla - Sun Microsystems /*
661af28f636SEnrico Perla - Sun Microsystems  * Retrieves from a device the extended information (einfo) associated to the
662af28f636SEnrico Perla - Sun Microsystems  * installed bootblock.
663af28f636SEnrico Perla - Sun Microsystems  * Expects one parameter, the device path, in the form: /dev/rdsk/c?[t?]d?s0.
664af28f636SEnrico Perla - Sun Microsystems  * Returns:
665af28f636SEnrico Perla - Sun Microsystems  *        - BC_SUCCESS (and prints out einfo contents depending on 'flags')
666af28f636SEnrico Perla - Sun Microsystems  *	  - BC_ERROR (on error)
667af28f636SEnrico Perla - Sun Microsystems  *        - BC_NOEINFO (no extended information available)
668af28f636SEnrico Perla - Sun Microsystems  */
669af28f636SEnrico Perla - Sun Microsystems static int
handle_getinfo(char * progname,char ** argv)670af28f636SEnrico Perla - Sun Microsystems handle_getinfo(char *progname, char **argv)
671af28f636SEnrico Perla - Sun Microsystems {
672af28f636SEnrico Perla - Sun Microsystems 
673af28f636SEnrico Perla - Sun Microsystems 	ib_data_t	data;
674af28f636SEnrico Perla - Sun Microsystems 	ib_bootblock_t	*bblock = &data.bootblock;
675af28f636SEnrico Perla - Sun Microsystems 	ib_device_t	*device = &data.device;
676af28f636SEnrico Perla - Sun Microsystems 	bblk_einfo_t	*einfo;
677af28f636SEnrico Perla - Sun Microsystems 	uint8_t		flags = 0;
678af28f636SEnrico Perla - Sun Microsystems 	uint32_t	size;
679af28f636SEnrico Perla - Sun Microsystems 	char		*device_path;
680af28f636SEnrico Perla - Sun Microsystems 	int		retval = BC_ERROR;
681af28f636SEnrico Perla - Sun Microsystems 	int		ret;
682af28f636SEnrico Perla - Sun Microsystems 
683af28f636SEnrico Perla - Sun Microsystems 	device_path = strdup(argv[0]);
684af28f636SEnrico Perla - Sun Microsystems 	if (!device_path) {
685af28f636SEnrico Perla - Sun Microsystems 		(void) fprintf(stderr, gettext("Missing parameter"));
686af28f636SEnrico Perla - Sun Microsystems 		usage(progname);
687af28f636SEnrico Perla - Sun Microsystems 		goto out;
688af28f636SEnrico Perla - Sun Microsystems 	}
689af28f636SEnrico Perla - Sun Microsystems 
690af28f636SEnrico Perla - Sun Microsystems 	bzero(&data, sizeof (ib_data_t));
691af28f636SEnrico Perla - Sun Microsystems 	BOOT_DEBUG("device path: %s\n", device_path);
692af28f636SEnrico Perla - Sun Microsystems 
693af28f636SEnrico Perla - Sun Microsystems 	if (init_device(device, device_path) != BC_SUCCESS) {
694af28f636SEnrico Perla - Sun Microsystems 		(void) fprintf(stderr, gettext("Unable to gather device "
695af28f636SEnrico Perla - Sun Microsystems 		    "information from %s\n"), device_path);
696af28f636SEnrico Perla - Sun Microsystems 		goto out_dev;
697af28f636SEnrico Perla - Sun Microsystems 	}
698af28f636SEnrico Perla - Sun Microsystems 
699af28f636SEnrico Perla - Sun Microsystems 	if (!is_zfs(device->type)) {
700af28f636SEnrico Perla - Sun Microsystems 		(void) fprintf(stderr, gettext("Versioning only supported on "
701af28f636SEnrico Perla - Sun Microsystems 		    "ZFS\n"));
702af28f636SEnrico Perla - Sun Microsystems 		goto out_dev;
703af28f636SEnrico Perla - Sun Microsystems 	}
704af28f636SEnrico Perla - Sun Microsystems 
705af28f636SEnrico Perla - Sun Microsystems 	ret = read_bootblock_from_disk(device->fd, bblock);
706af28f636SEnrico Perla - Sun Microsystems 	if (ret == BC_ERROR) {
707af28f636SEnrico Perla - Sun Microsystems 		(void) fprintf(stderr, gettext("Error reading bootblock from "
708af28f636SEnrico Perla - Sun Microsystems 		    "%s\n"), device_path);
709af28f636SEnrico Perla - Sun Microsystems 		goto out_dev;
710af28f636SEnrico Perla - Sun Microsystems 	}
711af28f636SEnrico Perla - Sun Microsystems 
712af28f636SEnrico Perla - Sun Microsystems 	if (ret == BC_NOEXTRA) {
713af28f636SEnrico Perla - Sun Microsystems 		BOOT_DEBUG("No multiboot header found on %s, unable "
714af28f636SEnrico Perla - Sun Microsystems 		    "to locate extra information area (old/non versioned "
715af28f636SEnrico Perla - Sun Microsystems 		    "bootblock?) \n", device_path);
716af28f636SEnrico Perla - Sun Microsystems 		(void) fprintf(stderr, gettext("No extended information "
717af28f636SEnrico Perla - Sun Microsystems 		    "found\n"));
718af28f636SEnrico Perla - Sun Microsystems 		retval = BC_NOEINFO;
719af28f636SEnrico Perla - Sun Microsystems 		goto out_dev;
720af28f636SEnrico Perla - Sun Microsystems 	}
721af28f636SEnrico Perla - Sun Microsystems 
72214d44f22SHans Rosenfeld 	einfo = find_einfo(bblock->extra, bblock->extra_size);
723af28f636SEnrico Perla - Sun Microsystems 	if (einfo == NULL) {
724af28f636SEnrico Perla - Sun Microsystems 		retval = BC_NOEINFO;
725af28f636SEnrico Perla - Sun Microsystems 		(void) fprintf(stderr, gettext("No extended information "
726af28f636SEnrico Perla - Sun Microsystems 		    "found\n"));
727af28f636SEnrico Perla - Sun Microsystems 		goto out_dev;
728af28f636SEnrico Perla - Sun Microsystems 	}
729af28f636SEnrico Perla - Sun Microsystems 
730af28f636SEnrico Perla - Sun Microsystems 	/* Print the extended information. */
731af28f636SEnrico Perla - Sun Microsystems 	if (strip)
732af28f636SEnrico Perla - Sun Microsystems 		flags |= EINFO_EASY_PARSE;
733af28f636SEnrico Perla - Sun Microsystems 	if (verbose_dump)
734af28f636SEnrico Perla - Sun Microsystems 		flags |= EINFO_PRINT_HEADER;
735af28f636SEnrico Perla - Sun Microsystems 
736af28f636SEnrico Perla - Sun Microsystems 	size = bblock->buf_size - P2ROUNDUP(bblock->file_size, 8) -
737af28f636SEnrico Perla - Sun Microsystems 	    sizeof (multiboot_header_t);
738af28f636SEnrico Perla - Sun Microsystems 	print_einfo(flags, einfo, size);
739af28f636SEnrico Perla - Sun Microsystems 	retval = BC_SUCCESS;
740af28f636SEnrico Perla - Sun Microsystems 
741af28f636SEnrico Perla - Sun Microsystems out_dev:
742af28f636SEnrico Perla - Sun Microsystems 	cleanup_device(&data.device);
743af28f636SEnrico Perla - Sun Microsystems out:
744af28f636SEnrico Perla - Sun Microsystems 	free(device_path);
745af28f636SEnrico Perla - Sun Microsystems 	return (retval);
746af28f636SEnrico Perla - Sun Microsystems 
747af28f636SEnrico Perla - Sun Microsystems }
748af28f636SEnrico Perla - Sun Microsystems 
749af28f636SEnrico Perla - Sun Microsystems /*
750af28f636SEnrico Perla - Sun Microsystems  * Attempt to mirror (propagate) the current bootblock over the attaching disk.
751af28f636SEnrico Perla - Sun Microsystems  *
752af28f636SEnrico Perla - Sun Microsystems  * Returns:
753af28f636SEnrico Perla - Sun Microsystems  *	- BC_SUCCESS (a successful propagation happened)
754af28f636SEnrico Perla - Sun Microsystems  *	- BC_ERROR (an error occurred)
755af28f636SEnrico Perla - Sun Microsystems  *	- BC_NOEXTRA (it is not possible to dump the current bootblock since
756af28f636SEnrico Perla - Sun Microsystems  *			there is no multiboot information)
757af28f636SEnrico Perla - Sun Microsystems  */
758af28f636SEnrico Perla - Sun Microsystems static int
handle_mirror(char * progname,char ** argv)759af28f636SEnrico Perla - Sun Microsystems handle_mirror(char *progname, char **argv)
760af28f636SEnrico Perla - Sun Microsystems {
761af28f636SEnrico Perla - Sun Microsystems 	ib_data_t	curr_data;
762af28f636SEnrico Perla - Sun Microsystems 	ib_data_t	attach_data;
763af28f636SEnrico Perla - Sun Microsystems 	ib_device_t	*curr_device = &curr_data.device;
764af28f636SEnrico Perla - Sun Microsystems 	ib_device_t	*attach_device = &attach_data.device;
765af28f636SEnrico Perla - Sun Microsystems 	ib_bootblock_t	*bblock_curr = &curr_data.bootblock;
766af28f636SEnrico Perla - Sun Microsystems 	ib_bootblock_t	*bblock_attach = &attach_data.bootblock;
767af28f636SEnrico Perla - Sun Microsystems 	bblk_einfo_t	*einfo_curr = NULL;
768af28f636SEnrico Perla - Sun Microsystems 	char		*curr_device_path;
769af28f636SEnrico Perla - Sun Microsystems 	char		*attach_device_path;
770af28f636SEnrico Perla - Sun Microsystems 	char		*updt_str = NULL;
771af28f636SEnrico Perla - Sun Microsystems 	int		retval = BC_ERROR;
772af28f636SEnrico Perla - Sun Microsystems 	int		ret;
773af28f636SEnrico Perla - Sun Microsystems 
774af28f636SEnrico Perla - Sun Microsystems 	curr_device_path = strdup(argv[0]);
775af28f636SEnrico Perla - Sun Microsystems 	attach_device_path = strdup(argv[1]);
776af28f636SEnrico Perla - Sun Microsystems 
777af28f636SEnrico Perla - Sun Microsystems 	if (!curr_device_path || !attach_device_path) {
778af28f636SEnrico Perla - Sun Microsystems 		(void) fprintf(stderr, gettext("Missing parameter"));
779af28f636SEnrico Perla - Sun Microsystems 		usage(progname);
780af28f636SEnrico Perla - Sun Microsystems 		goto out;
781af28f636SEnrico Perla - Sun Microsystems 	}
782af28f636SEnrico Perla - Sun Microsystems 	BOOT_DEBUG("Current device path is: %s, attaching device path is: "
783af28f636SEnrico Perla - Sun Microsystems 	    " %s\n", curr_device_path, attach_device_path);
784af28f636SEnrico Perla - Sun Microsystems 
785af28f636SEnrico Perla - Sun Microsystems 	bzero(&curr_data, sizeof (ib_data_t));
786af28f636SEnrico Perla - Sun Microsystems 	bzero(&attach_data, sizeof (ib_data_t));
787af28f636SEnrico Perla - Sun Microsystems 
788af28f636SEnrico Perla - Sun Microsystems 	if (tgt_fs_type != TARGET_IS_ZFS) {
789af28f636SEnrico Perla - Sun Microsystems 		(void) fprintf(stderr, gettext("Mirroring is only supported on "
790af28f636SEnrico Perla - Sun Microsystems 		    "ZFS\n"));
791af28f636SEnrico Perla - Sun Microsystems 		return (BC_ERROR);
792af28f636SEnrico Perla - Sun Microsystems 	}
793af28f636SEnrico Perla - Sun Microsystems 
794af28f636SEnrico Perla - Sun Microsystems 	if (init_device(curr_device, curr_device_path) != BC_SUCCESS) {
795af28f636SEnrico Perla - Sun Microsystems 		(void) fprintf(stderr, gettext("Unable to gather device "
796af28f636SEnrico Perla - Sun Microsystems 		    "information from %s (current device)\n"),
797af28f636SEnrico Perla - Sun Microsystems 		    curr_device_path);
798af28f636SEnrico Perla - Sun Microsystems 		goto out_currdev;
799af28f636SEnrico Perla - Sun Microsystems 	}
800af28f636SEnrico Perla - Sun Microsystems 
801af28f636SEnrico Perla - Sun Microsystems 	if (init_device(attach_device, attach_device_path) != BC_SUCCESS) {
802af28f636SEnrico Perla - Sun Microsystems 		(void) fprintf(stderr, gettext("Unable to gather device "
803af28f636SEnrico Perla - Sun Microsystems 		    "information from %s (attaching device)\n"),
804af28f636SEnrico Perla - Sun Microsystems 		    attach_device_path);
805af28f636SEnrico Perla - Sun Microsystems 		goto out_devs;
806af28f636SEnrico Perla - Sun Microsystems 	}
807af28f636SEnrico Perla - Sun Microsystems 
808af28f636SEnrico Perla - Sun Microsystems 	ret = read_bootblock_from_disk(curr_device->fd, bblock_curr);
809af28f636SEnrico Perla - Sun Microsystems 	if (ret == BC_ERROR) {
810af28f636SEnrico Perla - Sun Microsystems 		BOOT_DEBUG("Error reading bootblock from %s\n",
811af28f636SEnrico Perla - Sun Microsystems 		    curr_device->path);
812af28f636SEnrico Perla - Sun Microsystems 		retval = BC_ERROR;
813af28f636SEnrico Perla - Sun Microsystems 		goto out_devs;
814af28f636SEnrico Perla - Sun Microsystems 	}
815af28f636SEnrico Perla - Sun Microsystems 
816af28f636SEnrico Perla - Sun Microsystems 	if (ret == BC_NOEXTRA) {
817af28f636SEnrico Perla - Sun Microsystems 		BOOT_DEBUG("No multiboot header found on %s, unable to retrieve"
818af28f636SEnrico Perla - Sun Microsystems 		    " the bootblock\n", curr_device->path);
819af28f636SEnrico Perla - Sun Microsystems 		retval = BC_NOEXTRA;
820af28f636SEnrico Perla - Sun Microsystems 		goto out_devs;
821af28f636SEnrico Perla - Sun Microsystems 	}
822af28f636SEnrico Perla - Sun Microsystems 
82314d44f22SHans Rosenfeld 	einfo_curr = find_einfo(bblock_curr->extra, bblock_curr->extra_size);
824af28f636SEnrico Perla - Sun Microsystems 	if (einfo_curr != NULL)
825af28f636SEnrico Perla - Sun Microsystems 		updt_str = einfo_get_string(einfo_curr);
826af28f636SEnrico Perla - Sun Microsystems 
827af28f636SEnrico Perla - Sun Microsystems 	retval = propagate_bootblock(&curr_data, &attach_data, updt_str);
828af28f636SEnrico Perla - Sun Microsystems 	cleanup_bootblock(bblock_curr);
829af28f636SEnrico Perla - Sun Microsystems 	cleanup_bootblock(bblock_attach);
830af28f636SEnrico Perla - Sun Microsystems out_devs:
831af28f636SEnrico Perla - Sun Microsystems 	cleanup_device(attach_device);
832af28f636SEnrico Perla - Sun Microsystems out_currdev:
833af28f636SEnrico Perla - Sun Microsystems 	cleanup_device(curr_device);
834af28f636SEnrico Perla - Sun Microsystems out:
835af28f636SEnrico Perla - Sun Microsystems 	free(curr_device_path);
836af28f636SEnrico Perla - Sun Microsystems 	free(attach_device_path);
837af28f636SEnrico Perla - Sun Microsystems 	return (retval);
838af28f636SEnrico Perla - Sun Microsystems }
839af28f636SEnrico Perla - Sun Microsystems 
840af28f636SEnrico Perla - Sun Microsystems #define	USAGE_STRING	"Usage: %s [-h|-f|-F fstype|-u verstr] bootblk "       \
841af28f636SEnrico Perla - Sun Microsystems 			"raw-device\n"					       \
842af28f636SEnrico Perla - Sun Microsystems 			"\t%s [-e|-V] -i -F zfs raw-device\n"	               \
843af28f636SEnrico Perla - Sun Microsystems 			"\t%s -M -F zfs raw-device attach-raw-device\n"        \
844af28f636SEnrico Perla - Sun Microsystems 			"\tfstype is one of: 'ufs', 'hsfs' or 'zfs'\n"
845af28f636SEnrico Perla - Sun Microsystems 
846af28f636SEnrico Perla - Sun Microsystems #define	CANON_USAGE_STR	gettext(USAGE_STRING)
847af28f636SEnrico Perla - Sun Microsystems 
848af28f636SEnrico Perla - Sun Microsystems static void
usage(char * progname)849af28f636SEnrico Perla - Sun Microsystems usage(char *progname)
850af28f636SEnrico Perla - Sun Microsystems {
851af28f636SEnrico Perla - Sun Microsystems 	(void) fprintf(stdout, CANON_USAGE_STR, progname, progname, progname);
852af28f636SEnrico Perla - Sun Microsystems }
853af28f636SEnrico Perla - Sun Microsystems 
854af28f636SEnrico Perla - Sun Microsystems int
main(int argc,char ** argv)855af28f636SEnrico Perla - Sun Microsystems main(int argc, char **argv)
856af28f636SEnrico Perla - Sun Microsystems {
857af28f636SEnrico Perla - Sun Microsystems 	int	opt;
858af28f636SEnrico Perla - Sun Microsystems 	int	params = 2;
859af28f636SEnrico Perla - Sun Microsystems 	int	ret;
860af28f636SEnrico Perla - Sun Microsystems 	char	*progname;
861af28f636SEnrico Perla - Sun Microsystems 	char	**handle_args;
862af28f636SEnrico Perla - Sun Microsystems 
863af28f636SEnrico Perla - Sun Microsystems 	(void) setlocale(LC_ALL, "");
864af28f636SEnrico Perla - Sun Microsystems 	(void) textdomain(TEXT_DOMAIN);
865af28f636SEnrico Perla - Sun Microsystems 
866af28f636SEnrico Perla - Sun Microsystems 	while ((opt = getopt(argc, argv, "F:efiVMndhu:")) != EOF) {
867af28f636SEnrico Perla - Sun Microsystems 		switch (opt) {
868af28f636SEnrico Perla - Sun Microsystems 		case 'F':
869af28f636SEnrico Perla - Sun Microsystems 			if (strcmp(optarg, "ufs") == 0) {
870af28f636SEnrico Perla - Sun Microsystems 				tgt_fs_type = TARGET_IS_UFS;
871af28f636SEnrico Perla - Sun Microsystems 			} else if (strcmp(optarg, "hsfs") == 0) {
872af28f636SEnrico Perla - Sun Microsystems 				tgt_fs_type = TARGET_IS_HSFS;
873af28f636SEnrico Perla - Sun Microsystems 			} else if (strcmp(optarg, "zfs") == 0) {
874af28f636SEnrico Perla - Sun Microsystems 				tgt_fs_type = TARGET_IS_ZFS;
875af28f636SEnrico Perla - Sun Microsystems 			} else {
876af28f636SEnrico Perla - Sun Microsystems 				(void) fprintf(stderr, gettext("Wrong "
877af28f636SEnrico Perla - Sun Microsystems 				    "filesystem specified\n\n"));
878af28f636SEnrico Perla - Sun Microsystems 				usage(argv[0]);
879af28f636SEnrico Perla - Sun Microsystems 				exit(BC_ERROR);
880af28f636SEnrico Perla - Sun Microsystems 			}
881af28f636SEnrico Perla - Sun Microsystems 			break;
882af28f636SEnrico Perla - Sun Microsystems 		case 'e':
883af28f636SEnrico Perla - Sun Microsystems 			strip = B_TRUE;
884af28f636SEnrico Perla - Sun Microsystems 			break;
885af28f636SEnrico Perla - Sun Microsystems 		case 'f':
886af28f636SEnrico Perla - Sun Microsystems 			force_update = B_TRUE;
887af28f636SEnrico Perla - Sun Microsystems 			break;
888af28f636SEnrico Perla - Sun Microsystems 		case 'V':
889af28f636SEnrico Perla - Sun Microsystems 			verbose_dump = B_TRUE;
890af28f636SEnrico Perla - Sun Microsystems 			break;
891af28f636SEnrico Perla - Sun Microsystems 		case 'i':
892af28f636SEnrico Perla - Sun Microsystems 			do_getinfo = B_TRUE;
893af28f636SEnrico Perla - Sun Microsystems 			params = 1;
894af28f636SEnrico Perla - Sun Microsystems 			break;
895af28f636SEnrico Perla - Sun Microsystems 		case 'u':
896af28f636SEnrico Perla - Sun Microsystems 			do_version = B_TRUE;
897af28f636SEnrico Perla - Sun Microsystems 
898af28f636SEnrico Perla - Sun Microsystems 			update_str = malloc(strlen(optarg) + 1);
899af28f636SEnrico Perla - Sun Microsystems 			if (update_str == NULL) {
900af28f636SEnrico Perla - Sun Microsystems 				perror(gettext("Memory allocation failure"));
901af28f636SEnrico Perla - Sun Microsystems 				exit(BC_ERROR);
902af28f636SEnrico Perla - Sun Microsystems 			}
903af28f636SEnrico Perla - Sun Microsystems 			(void) strlcpy(update_str, optarg, strlen(optarg) + 1);
904af28f636SEnrico Perla - Sun Microsystems 			break;
905af28f636SEnrico Perla - Sun Microsystems 		case 'M':
906af28f636SEnrico Perla - Sun Microsystems 			do_mirror_bblk = B_TRUE;
907af28f636SEnrico Perla - Sun Microsystems 			break;
908af28f636SEnrico Perla - Sun Microsystems 		case 'h':
909af28f636SEnrico Perla - Sun Microsystems 			usage(argv[0]);
910af28f636SEnrico Perla - Sun Microsystems 			exit(BC_SUCCESS);
911af28f636SEnrico Perla - Sun Microsystems 			break;
912af28f636SEnrico Perla - Sun Microsystems 		case 'd':
913af28f636SEnrico Perla - Sun Microsystems 			boot_debug = B_TRUE;
914af28f636SEnrico Perla - Sun Microsystems 			break;
915af28f636SEnrico Perla - Sun Microsystems 		case 'n':
916af28f636SEnrico Perla - Sun Microsystems 			nowrite = B_TRUE;
917af28f636SEnrico Perla - Sun Microsystems 			break;
918af28f636SEnrico Perla - Sun Microsystems 		default:
919af28f636SEnrico Perla - Sun Microsystems 			/* fall through to process non-optional args */
920af28f636SEnrico Perla - Sun Microsystems 			break;
921af28f636SEnrico Perla - Sun Microsystems 		}
922af28f636SEnrico Perla - Sun Microsystems 	}
923af28f636SEnrico Perla - Sun Microsystems 
924af28f636SEnrico Perla - Sun Microsystems 	/* check arguments */
925af28f636SEnrico Perla - Sun Microsystems 	if (argc != optind + params) {
926af28f636SEnrico Perla - Sun Microsystems 		usage(argv[0]);
927af28f636SEnrico Perla - Sun Microsystems 		exit(BC_ERROR);
928af28f636SEnrico Perla - Sun Microsystems 	}
929af28f636SEnrico Perla - Sun Microsystems 	progname = argv[0];
930af28f636SEnrico Perla - Sun Microsystems 	handle_args = argv + optind;
931af28f636SEnrico Perla - Sun Microsystems 
932af28f636SEnrico Perla - Sun Microsystems 	/* check options. */
933af28f636SEnrico Perla - Sun Microsystems 	if (do_getinfo && do_mirror_bblk) {
934af28f636SEnrico Perla - Sun Microsystems 		(void) fprintf(stderr, gettext("Only one of -M and -i can be "
935af28f636SEnrico Perla - Sun Microsystems 		    "specified at the same time\n"));
936af28f636SEnrico Perla - Sun Microsystems 		usage(progname);
937af28f636SEnrico Perla - Sun Microsystems 		exit(BC_ERROR);
938af28f636SEnrico Perla - Sun Microsystems 	}
939af28f636SEnrico Perla - Sun Microsystems 
940af28f636SEnrico Perla - Sun Microsystems 	if (nowrite)
941af28f636SEnrico Perla - Sun Microsystems 		(void) fprintf(stdout, gettext("Dry run requested. Nothing will"
942af28f636SEnrico Perla - Sun Microsystems 		    " be written to disk.\n"));
943af28f636SEnrico Perla - Sun Microsystems 
944af28f636SEnrico Perla - Sun Microsystems 	if (do_getinfo) {
945af28f636SEnrico Perla - Sun Microsystems 		ret = handle_getinfo(progname, handle_args);
946af28f636SEnrico Perla - Sun Microsystems 	} else if (do_mirror_bblk) {
947af28f636SEnrico Perla - Sun Microsystems 		ret = handle_mirror(progname, handle_args);
948af28f636SEnrico Perla - Sun Microsystems 	} else {
949af28f636SEnrico Perla - Sun Microsystems 		ret = handle_install(progname, handle_args);
950af28f636SEnrico Perla - Sun Microsystems 	}
951af28f636SEnrico Perla - Sun Microsystems 	return (ret);
952af28f636SEnrico Perla - Sun Microsystems }
953