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
5d33344bbSsy25831 * Common Development and Distribution License (the "License").
6d33344bbSsy25831 * 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 /*
22af28f636SEnrico Perla - Sun Microsystems * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
2333f5ff17SMilan Jurik * Copyright 2012 Milan Jurik. All rights reserved.
241a902ef8SHans Rosenfeld * Copyright 2015 Nexenta Systems, Inc. All rights reserved.
25*cc641e8dSToomas Soome * Copyright 2016 Toomas Soome <tsoome@me.com>
267c478bd9Sstevel@tonic-gate */
277c478bd9Sstevel@tonic-gate
287c478bd9Sstevel@tonic-gate #include <stdio.h>
297c478bd9Sstevel@tonic-gate #include <stdlib.h>
307c478bd9Sstevel@tonic-gate #include <libgen.h>
317c478bd9Sstevel@tonic-gate #include <malloc.h>
327c478bd9Sstevel@tonic-gate #include <string.h>
337c478bd9Sstevel@tonic-gate #include <fcntl.h>
347c478bd9Sstevel@tonic-gate #include <unistd.h>
357c478bd9Sstevel@tonic-gate #include <strings.h>
36af28f636SEnrico Perla - Sun Microsystems #include <libintl.h>
37af28f636SEnrico Perla - Sun Microsystems #include <locale.h>
38af28f636SEnrico Perla - Sun Microsystems #include <errno.h>
39af28f636SEnrico Perla - Sun Microsystems #include <libfdisk.h>
40af28f636SEnrico Perla - Sun Microsystems #include <stdarg.h>
41af28f636SEnrico Perla - Sun Microsystems #include <assert.h>
42af28f636SEnrico Perla - Sun Microsystems
437c478bd9Sstevel@tonic-gate #include <sys/mount.h>
447c478bd9Sstevel@tonic-gate #include <sys/mnttab.h>
457c478bd9Sstevel@tonic-gate #include <sys/dktp/fdisk.h>
46d33344bbSsy25831 #include <sys/dkio.h>
47d33344bbSsy25831 #include <sys/vtoc.h>
48af28f636SEnrico Perla - Sun Microsystems #include <sys/types.h>
49af28f636SEnrico Perla - Sun Microsystems #include <sys/stat.h>
50af28f636SEnrico Perla - Sun Microsystems #include <sys/multiboot.h>
51af28f636SEnrico Perla - Sun Microsystems #include <sys/sysmacros.h>
521a902ef8SHans Rosenfeld #include <sys/efi_partition.h>
531a902ef8SHans Rosenfeld
541a902ef8SHans Rosenfeld #include <libnvpair.h>
551a902ef8SHans Rosenfeld #include <libfstyp.h>
567c478bd9Sstevel@tonic-gate
577c478bd9Sstevel@tonic-gate #include "message.h"
58af28f636SEnrico Perla - Sun Microsystems #include "installgrub.h"
59af28f636SEnrico Perla - Sun Microsystems #include "./../common/bblk_einfo.h"
60af28f636SEnrico Perla - Sun Microsystems #include "./../common/boot_utils.h"
61af28f636SEnrico Perla - Sun Microsystems #include "./../common/mboot_extra.h"
6221ba817cSToomas Soome #include "getresponse.h"
637c478bd9Sstevel@tonic-gate
647c478bd9Sstevel@tonic-gate #ifndef TEXT_DOMAIN
657c478bd9Sstevel@tonic-gate #define TEXT_DOMAIN "SUNW_OST_OSCMD"
667c478bd9Sstevel@tonic-gate #endif
677c478bd9Sstevel@tonic-gate
68af28f636SEnrico Perla - Sun Microsystems /*
69af28f636SEnrico Perla - Sun Microsystems * Variables to track installgrub desired mode of operation.
70af28f636SEnrico Perla - Sun Microsystems * 'nowrite' and 'boot_debug' come from boot_common.h.
71af28f636SEnrico Perla - Sun Microsystems */
72af28f636SEnrico Perla - Sun Microsystems static boolean_t write_mbr = B_FALSE;
73af28f636SEnrico Perla - Sun Microsystems static boolean_t force_mbr = B_FALSE;
74af28f636SEnrico Perla - Sun Microsystems static boolean_t force_update = B_FALSE;
75af28f636SEnrico Perla - Sun Microsystems static boolean_t do_getinfo = B_FALSE;
76af28f636SEnrico Perla - Sun Microsystems static boolean_t do_version = B_FALSE;
77af28f636SEnrico Perla - Sun Microsystems static boolean_t do_mirror_bblk = B_FALSE;
78af28f636SEnrico Perla - Sun Microsystems static boolean_t strip = B_FALSE;
79af28f636SEnrico Perla - Sun Microsystems static boolean_t verbose_dump = B_FALSE;
807c478bd9Sstevel@tonic-gate
81af28f636SEnrico Perla - Sun Microsystems /* Installing the bootblock is the default operation. */
82af28f636SEnrico Perla - Sun Microsystems static boolean_t do_install = B_TRUE;
837c478bd9Sstevel@tonic-gate
84af28f636SEnrico Perla - Sun Microsystems /* Versioning string, if present. */
85af28f636SEnrico Perla - Sun Microsystems static char *update_str;
867c478bd9Sstevel@tonic-gate
87af28f636SEnrico Perla - Sun Microsystems /*
88af28f636SEnrico Perla - Sun Microsystems * Temporary buffer to store the first 32K of data looking for a multiboot
89af28f636SEnrico Perla - Sun Microsystems * signature.
90af28f636SEnrico Perla - Sun Microsystems */
91af28f636SEnrico Perla - Sun Microsystems char mboot_scan[MBOOT_SCAN_SIZE];
927ce76caaSEnrico Perla - Sun Microsystems
93af28f636SEnrico Perla - Sun Microsystems /* Function prototypes. */
94af28f636SEnrico Perla - Sun Microsystems static void check_options(char *);
95af28f636SEnrico Perla - Sun Microsystems static int handle_install(char *, char **);
96af28f636SEnrico Perla - Sun Microsystems static int handle_mirror(char *, char **);
97af28f636SEnrico Perla - Sun Microsystems static int handle_getinfo(char *, char **);
98af28f636SEnrico Perla - Sun Microsystems static int commit_to_disk(ig_data_t *, char *);
99af28f636SEnrico Perla - Sun Microsystems static int init_device(ig_device_t *, char *path);
100af28f636SEnrico Perla - Sun Microsystems static void cleanup_device(ig_device_t *);
101af28f636SEnrico Perla - Sun Microsystems static void cleanup_stage2(ig_stage2_t *);
102af28f636SEnrico Perla - Sun Microsystems static int get_start_sector(ig_device_t *);
103af28f636SEnrico Perla - Sun Microsystems static int get_disk_fd(ig_device_t *device);
104af28f636SEnrico Perla - Sun Microsystems static int get_raw_partition_fd(ig_device_t *);
105af28f636SEnrico Perla - Sun Microsystems static char *get_raw_partition_path(ig_device_t *);
106af28f636SEnrico Perla - Sun Microsystems static boolean_t gather_stage2_from_dev(ig_data_t *);
107af28f636SEnrico Perla - Sun Microsystems static int propagate_bootblock(ig_data_t *, ig_data_t *, char *);
108af28f636SEnrico Perla - Sun Microsystems static int find_x86_bootpar(struct mboot *, int *, uint32_t *);
109af28f636SEnrico Perla - Sun Microsystems static int copy_stage2_to_pcfs(ig_data_t *);
110af28f636SEnrico Perla - Sun Microsystems static int write_stage2(ig_data_t *);
111af28f636SEnrico Perla - Sun Microsystems static int write_stage1(ig_data_t *);
1127c478bd9Sstevel@tonic-gate static void usage(char *);
113af28f636SEnrico Perla - Sun Microsystems static int read_stage1_from_file(char *, ig_data_t *);
114af28f636SEnrico Perla - Sun Microsystems static int read_stage2_from_file(char *, ig_data_t *);
115af28f636SEnrico Perla - Sun Microsystems static int read_stage1_from_disk(int, char *);
1161a902ef8SHans Rosenfeld static int read_stage2_from_disk(int, ig_stage2_t *, int);
117af28f636SEnrico Perla - Sun Microsystems static int prepare_stage1(ig_data_t *);
118af28f636SEnrico Perla - Sun Microsystems static int prepare_stage2(ig_data_t *, char *);
119af28f636SEnrico Perla - Sun Microsystems static void prepare_fake_multiboot(ig_stage2_t *);
120af28f636SEnrico Perla - Sun Microsystems static void add_stage2_einfo(ig_stage2_t *, char *updt_str);
121af28f636SEnrico Perla - Sun Microsystems static boolean_t is_update_necessary(ig_data_t *, char *);
1227c478bd9Sstevel@tonic-gate
123342440ecSPrasad Singamsetty extern int read_stage2_blocklist(int, unsigned int *);
1247c478bd9Sstevel@tonic-gate
1257c478bd9Sstevel@tonic-gate int
main(int argc,char * argv[])1267c478bd9Sstevel@tonic-gate main(int argc, char *argv[])
1277c478bd9Sstevel@tonic-gate {
128af28f636SEnrico Perla - Sun Microsystems int opt;
129af28f636SEnrico Perla - Sun Microsystems int params = 3;
130af28f636SEnrico Perla - Sun Microsystems int ret;
131af28f636SEnrico Perla - Sun Microsystems char **handle_args;
132af28f636SEnrico Perla - Sun Microsystems char *progname;
1337c478bd9Sstevel@tonic-gate
1347c478bd9Sstevel@tonic-gate (void) setlocale(LC_ALL, "");
1357c478bd9Sstevel@tonic-gate (void) textdomain(TEXT_DOMAIN);
13621ba817cSToomas Soome if (init_yes() < 0) {
13721ba817cSToomas Soome (void) fprintf(stderr, gettext(ERR_MSG_INIT_YES),
13821ba817cSToomas Soome strerror(errno));
13921ba817cSToomas Soome exit(BC_ERROR);
14021ba817cSToomas Soome }
1417c478bd9Sstevel@tonic-gate
142af28f636SEnrico Perla - Sun Microsystems /*
143af28f636SEnrico Perla - Sun Microsystems * retro-compatibility: installing the bootblock is the default
144af28f636SEnrico Perla - Sun Microsystems * and there is no switch for it.
145af28f636SEnrico Perla - Sun Microsystems */
146af28f636SEnrico Perla - Sun Microsystems do_install = B_TRUE;
147af28f636SEnrico Perla - Sun Microsystems
148af28f636SEnrico Perla - Sun Microsystems while ((opt = getopt(argc, argv, "dVMFfmneiu:")) != EOF) {
1497c478bd9Sstevel@tonic-gate switch (opt) {
1507c478bd9Sstevel@tonic-gate case 'm':
151af28f636SEnrico Perla - Sun Microsystems write_mbr = B_TRUE;
1527c478bd9Sstevel@tonic-gate break;
1537c478bd9Sstevel@tonic-gate case 'n':
154af28f636SEnrico Perla - Sun Microsystems nowrite = B_TRUE;
1557c478bd9Sstevel@tonic-gate break;
1567c478bd9Sstevel@tonic-gate case 'f':
157af28f636SEnrico Perla - Sun Microsystems force_mbr = B_TRUE;
1587c478bd9Sstevel@tonic-gate break;
1597ce76caaSEnrico Perla - Sun Microsystems case 'i':
160af28f636SEnrico Perla - Sun Microsystems do_getinfo = B_TRUE;
161af28f636SEnrico Perla - Sun Microsystems do_install = B_FALSE;
1627ce76caaSEnrico Perla - Sun Microsystems params = 1;
1637ce76caaSEnrico Perla - Sun Microsystems break;
164af28f636SEnrico Perla - Sun Microsystems case 'V':
165af28f636SEnrico Perla - Sun Microsystems verbose_dump = B_TRUE;
1667ce76caaSEnrico Perla - Sun Microsystems break;
167af28f636SEnrico Perla - Sun Microsystems case 'd':
168af28f636SEnrico Perla - Sun Microsystems boot_debug = B_TRUE;
169af28f636SEnrico Perla - Sun Microsystems break;
170af28f636SEnrico Perla - Sun Microsystems case 'F':
171af28f636SEnrico Perla - Sun Microsystems force_update = B_TRUE;
172af28f636SEnrico Perla - Sun Microsystems break;
173af28f636SEnrico Perla - Sun Microsystems case 'e':
174af28f636SEnrico Perla - Sun Microsystems strip = B_TRUE;
175af28f636SEnrico Perla - Sun Microsystems break;
176af28f636SEnrico Perla - Sun Microsystems case 'M':
177af28f636SEnrico Perla - Sun Microsystems do_mirror_bblk = B_TRUE;
178af28f636SEnrico Perla - Sun Microsystems do_install = B_FALSE;
179af28f636SEnrico Perla - Sun Microsystems params = 2;
180af28f636SEnrico Perla - Sun Microsystems break;
181af28f636SEnrico Perla - Sun Microsystems case 'u':
182af28f636SEnrico Perla - Sun Microsystems do_version = B_TRUE;
183af28f636SEnrico Perla - Sun Microsystems
184af28f636SEnrico Perla - Sun Microsystems update_str = malloc(strlen(optarg) + 1);
185af28f636SEnrico Perla - Sun Microsystems if (update_str == NULL) {
186af28f636SEnrico Perla - Sun Microsystems (void) fprintf(stderr, gettext("Unable to "
187af28f636SEnrico Perla - Sun Microsystems "allocate memory\n"));
188af28f636SEnrico Perla - Sun Microsystems exit(BC_ERROR);
189af28f636SEnrico Perla - Sun Microsystems }
190af28f636SEnrico Perla - Sun Microsystems (void) strlcpy(update_str, optarg, strlen(optarg) + 1);
1917ce76caaSEnrico Perla - Sun Microsystems break;
1927c478bd9Sstevel@tonic-gate default:
1937c478bd9Sstevel@tonic-gate /* fall through to process non-optional args */
1947c478bd9Sstevel@tonic-gate break;
1957c478bd9Sstevel@tonic-gate }
1967c478bd9Sstevel@tonic-gate }
1977c478bd9Sstevel@tonic-gate
1987c478bd9Sstevel@tonic-gate /* check arguments */
1997ce76caaSEnrico Perla - Sun Microsystems if (argc != optind + params) {
2007c478bd9Sstevel@tonic-gate usage(argv[0]);
201af28f636SEnrico Perla - Sun Microsystems exit(BC_ERROR);
2027c478bd9Sstevel@tonic-gate }
2037c478bd9Sstevel@tonic-gate
204af28f636SEnrico Perla - Sun Microsystems /*
205af28f636SEnrico Perla - Sun Microsystems * clean up options (and bail out if an unrecoverable combination is
206af28f636SEnrico Perla - Sun Microsystems * requested.
207af28f636SEnrico Perla - Sun Microsystems */
208af28f636SEnrico Perla - Sun Microsystems progname = argv[0];
209af28f636SEnrico Perla - Sun Microsystems check_options(progname);
210af28f636SEnrico Perla - Sun Microsystems handle_args = argv + optind;
211af28f636SEnrico Perla - Sun Microsystems
212af28f636SEnrico Perla - Sun Microsystems if (nowrite)
2137c478bd9Sstevel@tonic-gate (void) fprintf(stdout, DRY_RUN);
214af28f636SEnrico Perla - Sun Microsystems
215af28f636SEnrico Perla - Sun Microsystems if (do_getinfo) {
216af28f636SEnrico Perla - Sun Microsystems ret = handle_getinfo(progname, handle_args);
217af28f636SEnrico Perla - Sun Microsystems } else if (do_mirror_bblk) {
218af28f636SEnrico Perla - Sun Microsystems ret = handle_mirror(progname, handle_args);
219af28f636SEnrico Perla - Sun Microsystems } else {
220af28f636SEnrico Perla - Sun Microsystems ret = handle_install(progname, handle_args);
221af28f636SEnrico Perla - Sun Microsystems }
222af28f636SEnrico Perla - Sun Microsystems return (ret);
2237c478bd9Sstevel@tonic-gate }
2247c478bd9Sstevel@tonic-gate
225af28f636SEnrico Perla - Sun Microsystems #define MEANINGLESS_OPT gettext("%s specified but meaningless, ignoring\n")
226af28f636SEnrico Perla - Sun Microsystems static void
check_options(char * progname)227af28f636SEnrico Perla - Sun Microsystems check_options(char *progname)
2287c478bd9Sstevel@tonic-gate {
229af28f636SEnrico Perla - Sun Microsystems if (do_getinfo && do_mirror_bblk) {
230af28f636SEnrico Perla - Sun Microsystems (void) fprintf(stderr, gettext("Only one of -M and -i can be "
231af28f636SEnrico Perla - Sun Microsystems "specified at the same time\n"));
232af28f636SEnrico Perla - Sun Microsystems usage(progname);
233af28f636SEnrico Perla - Sun Microsystems exit(BC_ERROR);
234af28f636SEnrico Perla - Sun Microsystems }
235af28f636SEnrico Perla - Sun Microsystems
236af28f636SEnrico Perla - Sun Microsystems if (do_mirror_bblk) {
237af28f636SEnrico Perla - Sun Microsystems /*
238af28f636SEnrico Perla - Sun Microsystems * -u and -F may actually reflect a user intent that is not
239af28f636SEnrico Perla - Sun Microsystems * correct with this command (mirror can be interpreted
240af28f636SEnrico Perla - Sun Microsystems * "similar" to install. Emit a message and continue.
241af28f636SEnrico Perla - Sun Microsystems * -e and -V have no meaning, be quiet here and only report the
242af28f636SEnrico Perla - Sun Microsystems * incongruence if a debug output is requested.
243af28f636SEnrico Perla - Sun Microsystems */
244af28f636SEnrico Perla - Sun Microsystems if (do_version) {
245af28f636SEnrico Perla - Sun Microsystems (void) fprintf(stderr, MEANINGLESS_OPT, "-u");
246af28f636SEnrico Perla - Sun Microsystems do_version = B_FALSE;
247af28f636SEnrico Perla - Sun Microsystems }
248af28f636SEnrico Perla - Sun Microsystems if (force_update) {
249af28f636SEnrico Perla - Sun Microsystems (void) fprintf(stderr, MEANINGLESS_OPT, "-F");
250af28f636SEnrico Perla - Sun Microsystems force_update = B_FALSE;
251af28f636SEnrico Perla - Sun Microsystems }
252af28f636SEnrico Perla - Sun Microsystems if (strip || verbose_dump) {
253af28f636SEnrico Perla - Sun Microsystems BOOT_DEBUG(MEANINGLESS_OPT, "-e|-V");
254af28f636SEnrico Perla - Sun Microsystems strip = B_FALSE;
255af28f636SEnrico Perla - Sun Microsystems verbose_dump = B_FALSE;
256af28f636SEnrico Perla - Sun Microsystems }
257af28f636SEnrico Perla - Sun Microsystems }
258af28f636SEnrico Perla - Sun Microsystems
259af28f636SEnrico Perla - Sun Microsystems if (do_getinfo) {
260af28f636SEnrico Perla - Sun Microsystems if (write_mbr || force_mbr || do_version || force_update) {
261af28f636SEnrico Perla - Sun Microsystems BOOT_DEBUG(MEANINGLESS_OPT, "-m|-f|-u|-F");
262af28f636SEnrico Perla - Sun Microsystems write_mbr = force_mbr = do_version = B_FALSE;
263af28f636SEnrico Perla - Sun Microsystems force_update = B_FALSE;
264af28f636SEnrico Perla - Sun Microsystems }
265af28f636SEnrico Perla - Sun Microsystems }
266af28f636SEnrico Perla - Sun Microsystems }
267af28f636SEnrico Perla - Sun Microsystems
268af28f636SEnrico Perla - Sun Microsystems /*
269af28f636SEnrico Perla - Sun Microsystems * Install a new stage1/stage2 pair on the specified device. handle_install()
270af28f636SEnrico Perla - Sun Microsystems * expects argv to contain 3 parameters (the path to stage1, the path to stage2,
271af28f636SEnrico Perla - Sun Microsystems * the target device).
272af28f636SEnrico Perla - Sun Microsystems *
273af28f636SEnrico Perla - Sun Microsystems * Returns: BC_SUCCESS - if the installation is successful
274af28f636SEnrico Perla - Sun Microsystems * BC_ERROR - if the installation failed
275af28f636SEnrico Perla - Sun Microsystems * BC_NOUPDT - if no installation was performed because the GRUB
276af28f636SEnrico Perla - Sun Microsystems * version currently installed is more recent than the
277af28f636SEnrico Perla - Sun Microsystems * supplied one.
278af28f636SEnrico Perla - Sun Microsystems *
279af28f636SEnrico Perla - Sun Microsystems */
280af28f636SEnrico Perla - Sun Microsystems static int
handle_install(char * progname,char ** argv)281af28f636SEnrico Perla - Sun Microsystems handle_install(char *progname, char **argv)
282af28f636SEnrico Perla - Sun Microsystems {
283af28f636SEnrico Perla - Sun Microsystems ig_data_t install_data;
284af28f636SEnrico Perla - Sun Microsystems char *stage1_path = NULL;
285af28f636SEnrico Perla - Sun Microsystems char *stage2_path = NULL;
286af28f636SEnrico Perla - Sun Microsystems char *device_path = NULL;
287af28f636SEnrico Perla - Sun Microsystems int ret = BC_ERROR;
288af28f636SEnrico Perla - Sun Microsystems
289af28f636SEnrico Perla - Sun Microsystems stage1_path = strdup(argv[0]);
290af28f636SEnrico Perla - Sun Microsystems stage2_path = strdup(argv[1]);
291af28f636SEnrico Perla - Sun Microsystems device_path = strdup(argv[2]);
292af28f636SEnrico Perla - Sun Microsystems
293af28f636SEnrico Perla - Sun Microsystems bzero(&install_data, sizeof (ig_data_t));
294af28f636SEnrico Perla - Sun Microsystems
295af28f636SEnrico Perla - Sun Microsystems if (!stage1_path || !stage2_path || !device_path) {
296af28f636SEnrico Perla - Sun Microsystems (void) fprintf(stderr, gettext("Missing parameter"));
297af28f636SEnrico Perla - Sun Microsystems usage(progname);
298af28f636SEnrico Perla - Sun Microsystems goto out;
299af28f636SEnrico Perla - Sun Microsystems }
300af28f636SEnrico Perla - Sun Microsystems
301af28f636SEnrico Perla - Sun Microsystems BOOT_DEBUG("stage1 path: %s, stage2 path: %s, device: %s\n",
302af28f636SEnrico Perla - Sun Microsystems stage1_path, stage2_path, device_path);
303af28f636SEnrico Perla - Sun Microsystems
304af28f636SEnrico Perla - Sun Microsystems if (init_device(&install_data.device, device_path) != BC_SUCCESS) {
305af28f636SEnrico Perla - Sun Microsystems (void) fprintf(stderr, gettext("Unable to gather device "
306af28f636SEnrico Perla - Sun Microsystems "information for %s\n"), device_path);
307af28f636SEnrico Perla - Sun Microsystems goto out;
308af28f636SEnrico Perla - Sun Microsystems }
309af28f636SEnrico Perla - Sun Microsystems
310af28f636SEnrico Perla - Sun Microsystems /* read in stage1 and stage2. */
311af28f636SEnrico Perla - Sun Microsystems if (read_stage1_from_file(stage1_path, &install_data) != BC_SUCCESS) {
312af28f636SEnrico Perla - Sun Microsystems (void) fprintf(stderr, gettext("Error opening %s\n"),
313af28f636SEnrico Perla - Sun Microsystems stage1_path);
314af28f636SEnrico Perla - Sun Microsystems goto out_dev;
315af28f636SEnrico Perla - Sun Microsystems }
316af28f636SEnrico Perla - Sun Microsystems
317af28f636SEnrico Perla - Sun Microsystems if (read_stage2_from_file(stage2_path, &install_data) != BC_SUCCESS) {
318af28f636SEnrico Perla - Sun Microsystems (void) fprintf(stderr, gettext("Error opening %s\n"),
319af28f636SEnrico Perla - Sun Microsystems stage2_path);
320af28f636SEnrico Perla - Sun Microsystems goto out_dev;
321af28f636SEnrico Perla - Sun Microsystems }
322af28f636SEnrico Perla - Sun Microsystems
323af28f636SEnrico Perla - Sun Microsystems /* We do not support versioning on PCFS. */
324af28f636SEnrico Perla - Sun Microsystems if (is_bootpar(install_data.device.type) && do_version)
325af28f636SEnrico Perla - Sun Microsystems do_version = B_FALSE;
326af28f636SEnrico Perla - Sun Microsystems
327af28f636SEnrico Perla - Sun Microsystems /*
328af28f636SEnrico Perla - Sun Microsystems * is_update_necessary() will take care of checking if versioning and/or
329af28f636SEnrico Perla - Sun Microsystems * forcing the update have been specified. It will also emit a warning
330af28f636SEnrico Perla - Sun Microsystems * if a non-versioned update is attempted over a versioned bootblock.
331af28f636SEnrico Perla - Sun Microsystems */
332af28f636SEnrico Perla - Sun Microsystems if (!is_update_necessary(&install_data, update_str)) {
333af28f636SEnrico Perla - Sun Microsystems (void) fprintf(stderr, gettext("GRUB version installed "
334af28f636SEnrico Perla - Sun Microsystems "on %s is more recent or identical\n"
335af28f636SEnrico Perla - Sun Microsystems "Use -F to override or install without the -u option\n"),
336af28f636SEnrico Perla - Sun Microsystems device_path);
337af28f636SEnrico Perla - Sun Microsystems ret = BC_NOUPDT;
338af28f636SEnrico Perla - Sun Microsystems goto out_dev;
339af28f636SEnrico Perla - Sun Microsystems }
340af28f636SEnrico Perla - Sun Microsystems /*
341af28f636SEnrico Perla - Sun Microsystems * We get here if:
342af28f636SEnrico Perla - Sun Microsystems * - the installed GRUB version is older than the one about to be
343af28f636SEnrico Perla - Sun Microsystems * installed.
344af28f636SEnrico Perla - Sun Microsystems * - no versioning string has been passed through the command line.
345af28f636SEnrico Perla - Sun Microsystems * - a forced update is requested (-F).
346af28f636SEnrico Perla - Sun Microsystems */
347af28f636SEnrico Perla - Sun Microsystems BOOT_DEBUG("Ready to commit to disk\n");
348af28f636SEnrico Perla - Sun Microsystems ret = commit_to_disk(&install_data, update_str);
349af28f636SEnrico Perla - Sun Microsystems
350af28f636SEnrico Perla - Sun Microsystems out_dev:
351af28f636SEnrico Perla - Sun Microsystems cleanup_device(&install_data.device);
352af28f636SEnrico Perla - Sun Microsystems out:
353af28f636SEnrico Perla - Sun Microsystems free(stage1_path);
354af28f636SEnrico Perla - Sun Microsystems free(stage2_path);
355af28f636SEnrico Perla - Sun Microsystems free(device_path);
356af28f636SEnrico Perla - Sun Microsystems return (ret);
357af28f636SEnrico Perla - Sun Microsystems }
358af28f636SEnrico Perla - Sun Microsystems
359af28f636SEnrico Perla - Sun Microsystems /*
360af28f636SEnrico Perla - Sun Microsystems * Retrieves from a device the extended information (einfo) associated to the
361af28f636SEnrico Perla - Sun Microsystems * installed stage2.
362af28f636SEnrico Perla - Sun Microsystems * Expects one parameter, the device path, in the form: /dev/rdsk/c?[t?]d?s0.
363af28f636SEnrico Perla - Sun Microsystems * Returns:
364af28f636SEnrico Perla - Sun Microsystems * - BC_SUCCESS (and prints out einfo contents depending on 'flags')
365af28f636SEnrico Perla - Sun Microsystems * - BC_ERROR (on error)
366af28f636SEnrico Perla - Sun Microsystems * - BC_NOEINFO (no extended information available)
367af28f636SEnrico Perla - Sun Microsystems */
368af28f636SEnrico Perla - Sun Microsystems static int
handle_getinfo(char * progname,char ** argv)369af28f636SEnrico Perla - Sun Microsystems handle_getinfo(char *progname, char **argv)
370af28f636SEnrico Perla - Sun Microsystems {
371af28f636SEnrico Perla - Sun Microsystems ig_data_t data;
372af28f636SEnrico Perla - Sun Microsystems ig_stage2_t *stage2 = &data.stage2;
373af28f636SEnrico Perla - Sun Microsystems ig_device_t *device = &data.device;
374af28f636SEnrico Perla - Sun Microsystems bblk_einfo_t *einfo;
375af28f636SEnrico Perla - Sun Microsystems uint8_t flags = 0;
376af28f636SEnrico Perla - Sun Microsystems uint32_t size;
377af28f636SEnrico Perla - Sun Microsystems char *device_path;
378af28f636SEnrico Perla - Sun Microsystems int retval = BC_ERROR;
379af28f636SEnrico Perla - Sun Microsystems int ret;
380af28f636SEnrico Perla - Sun Microsystems
381af28f636SEnrico Perla - Sun Microsystems device_path = strdup(argv[0]);
382af28f636SEnrico Perla - Sun Microsystems if (!device_path) {
383af28f636SEnrico Perla - Sun Microsystems (void) fprintf(stderr, gettext("Missing parameter"));
384af28f636SEnrico Perla - Sun Microsystems usage(progname);
385af28f636SEnrico Perla - Sun Microsystems goto out;
386af28f636SEnrico Perla - Sun Microsystems }
387af28f636SEnrico Perla - Sun Microsystems
388af28f636SEnrico Perla - Sun Microsystems bzero(&data, sizeof (ig_data_t));
389af28f636SEnrico Perla - Sun Microsystems BOOT_DEBUG("device path: %s\n", device_path);
390af28f636SEnrico Perla - Sun Microsystems
391af28f636SEnrico Perla - Sun Microsystems if (init_device(device, device_path) != BC_SUCCESS) {
392af28f636SEnrico Perla - Sun Microsystems (void) fprintf(stderr, gettext("Unable to gather device "
393af28f636SEnrico Perla - Sun Microsystems "information for %s\n"), device_path);
394af28f636SEnrico Perla - Sun Microsystems goto out_dev;
395af28f636SEnrico Perla - Sun Microsystems }
396af28f636SEnrico Perla - Sun Microsystems
397af28f636SEnrico Perla - Sun Microsystems if (is_bootpar(device->type)) {
398af28f636SEnrico Perla - Sun Microsystems (void) fprintf(stderr, gettext("Versioning not supported on "
399af28f636SEnrico Perla - Sun Microsystems "PCFS\n"));
400af28f636SEnrico Perla - Sun Microsystems goto out_dev;
401af28f636SEnrico Perla - Sun Microsystems }
402af28f636SEnrico Perla - Sun Microsystems
4031a902ef8SHans Rosenfeld ret = read_stage2_from_disk(device->part_fd, stage2, device->type);
404af28f636SEnrico Perla - Sun Microsystems if (ret == BC_ERROR) {
405af28f636SEnrico Perla - Sun Microsystems (void) fprintf(stderr, gettext("Error reading stage2 from "
406af28f636SEnrico Perla - Sun Microsystems "%s\n"), device_path);
407af28f636SEnrico Perla - Sun Microsystems goto out_dev;
408af28f636SEnrico Perla - Sun Microsystems }
409af28f636SEnrico Perla - Sun Microsystems
410af28f636SEnrico Perla - Sun Microsystems if (ret == BC_NOEXTRA) {
411af28f636SEnrico Perla - Sun Microsystems (void) fprintf(stdout, gettext("No multiboot header found on "
412af28f636SEnrico Perla - Sun Microsystems "%s, unable to locate extra information area\n"),
413af28f636SEnrico Perla - Sun Microsystems device_path);
414af28f636SEnrico Perla - Sun Microsystems retval = BC_NOEINFO;
415af28f636SEnrico Perla - Sun Microsystems goto out_dev;
416af28f636SEnrico Perla - Sun Microsystems }
417af28f636SEnrico Perla - Sun Microsystems
41814d44f22SHans Rosenfeld einfo = find_einfo(stage2->extra, stage2->extra_size);
419af28f636SEnrico Perla - Sun Microsystems if (einfo == NULL) {
420af28f636SEnrico Perla - Sun Microsystems retval = BC_NOEINFO;
421af28f636SEnrico Perla - Sun Microsystems (void) fprintf(stderr, gettext("No extended information "
422af28f636SEnrico Perla - Sun Microsystems "found\n"));
423af28f636SEnrico Perla - Sun Microsystems goto out_dev;
424af28f636SEnrico Perla - Sun Microsystems }
425af28f636SEnrico Perla - Sun Microsystems
426af28f636SEnrico Perla - Sun Microsystems /* Print the extended information. */
427af28f636SEnrico Perla - Sun Microsystems if (strip)
428af28f636SEnrico Perla - Sun Microsystems flags |= EINFO_EASY_PARSE;
429af28f636SEnrico Perla - Sun Microsystems if (verbose_dump)
430af28f636SEnrico Perla - Sun Microsystems flags |= EINFO_PRINT_HEADER;
431af28f636SEnrico Perla - Sun Microsystems
432af28f636SEnrico Perla - Sun Microsystems size = stage2->buf_size - P2ROUNDUP(stage2->file_size, 8);
433af28f636SEnrico Perla - Sun Microsystems print_einfo(flags, einfo, size);
434af28f636SEnrico Perla - Sun Microsystems retval = BC_SUCCESS;
435af28f636SEnrico Perla - Sun Microsystems
436af28f636SEnrico Perla - Sun Microsystems out_dev:
437af28f636SEnrico Perla - Sun Microsystems cleanup_device(&data.device);
438af28f636SEnrico Perla - Sun Microsystems out:
439af28f636SEnrico Perla - Sun Microsystems free(device_path);
440af28f636SEnrico Perla - Sun Microsystems return (retval);
441af28f636SEnrico Perla - Sun Microsystems }
442af28f636SEnrico Perla - Sun Microsystems
443af28f636SEnrico Perla - Sun Microsystems /*
444af28f636SEnrico Perla - Sun Microsystems * Attempt to mirror (propagate) the current stage2 over the attaching disk.
445af28f636SEnrico Perla - Sun Microsystems *
446af28f636SEnrico Perla - Sun Microsystems * Returns:
447af28f636SEnrico Perla - Sun Microsystems * - BC_SUCCESS (a successful propagation happened)
448af28f636SEnrico Perla - Sun Microsystems * - BC_ERROR (an error occurred)
449af28f636SEnrico Perla - Sun Microsystems * - BC_NOEXTRA (it is not possible to dump the current bootblock since
450af28f636SEnrico Perla - Sun Microsystems * there is no multiboot information)
451af28f636SEnrico Perla - Sun Microsystems */
452af28f636SEnrico Perla - Sun Microsystems static int
handle_mirror(char * progname,char ** argv)453af28f636SEnrico Perla - Sun Microsystems handle_mirror(char *progname, char **argv)
454af28f636SEnrico Perla - Sun Microsystems {
455af28f636SEnrico Perla - Sun Microsystems ig_data_t curr_data;
456af28f636SEnrico Perla - Sun Microsystems ig_data_t attach_data;
457af28f636SEnrico Perla - Sun Microsystems ig_device_t *curr_device = &curr_data.device;
458af28f636SEnrico Perla - Sun Microsystems ig_device_t *attach_device = &attach_data.device;
459af28f636SEnrico Perla - Sun Microsystems ig_stage2_t *stage2_curr = &curr_data.stage2;
460af28f636SEnrico Perla - Sun Microsystems ig_stage2_t *stage2_attach = &attach_data.stage2;
461af28f636SEnrico Perla - Sun Microsystems bblk_einfo_t *einfo_curr = NULL;
462af28f636SEnrico Perla - Sun Microsystems char *curr_device_path;
463af28f636SEnrico Perla - Sun Microsystems char *attach_device_path;
464af28f636SEnrico Perla - Sun Microsystems char *updt_str = NULL;
465af28f636SEnrico Perla - Sun Microsystems int retval = BC_ERROR;
466af28f636SEnrico Perla - Sun Microsystems int ret;
467af28f636SEnrico Perla - Sun Microsystems
468af28f636SEnrico Perla - Sun Microsystems curr_device_path = strdup(argv[0]);
469af28f636SEnrico Perla - Sun Microsystems attach_device_path = strdup(argv[1]);
470af28f636SEnrico Perla - Sun Microsystems
471af28f636SEnrico Perla - Sun Microsystems if (!curr_device_path || !attach_device_path) {
472af28f636SEnrico Perla - Sun Microsystems (void) fprintf(stderr, gettext("Missing parameter"));
473af28f636SEnrico Perla - Sun Microsystems usage(progname);
474af28f636SEnrico Perla - Sun Microsystems goto out;
475af28f636SEnrico Perla - Sun Microsystems }
476af28f636SEnrico Perla - Sun Microsystems BOOT_DEBUG("Current device path is: %s, attaching device path is: "
477af28f636SEnrico Perla - Sun Microsystems " %s\n", curr_device_path, attach_device_path);
478af28f636SEnrico Perla - Sun Microsystems
479af28f636SEnrico Perla - Sun Microsystems bzero(&curr_data, sizeof (ig_data_t));
480af28f636SEnrico Perla - Sun Microsystems bzero(&attach_data, sizeof (ig_data_t));
481af28f636SEnrico Perla - Sun Microsystems
482af28f636SEnrico Perla - Sun Microsystems if (init_device(curr_device, curr_device_path) != BC_SUCCESS) {
483af28f636SEnrico Perla - Sun Microsystems (void) fprintf(stderr, gettext("Unable to gather device "
484af28f636SEnrico Perla - Sun Microsystems "information for %s (current device)\n"), curr_device_path);
485af28f636SEnrico Perla - Sun Microsystems goto out_currdev;
486af28f636SEnrico Perla - Sun Microsystems }
487af28f636SEnrico Perla - Sun Microsystems
488af28f636SEnrico Perla - Sun Microsystems if (init_device(attach_device, attach_device_path) != BC_SUCCESS) {
489af28f636SEnrico Perla - Sun Microsystems (void) fprintf(stderr, gettext("Unable to gather device "
490af28f636SEnrico Perla - Sun Microsystems "information for %s (attaching device)\n"),
491af28f636SEnrico Perla - Sun Microsystems attach_device_path);
492af28f636SEnrico Perla - Sun Microsystems goto out_devs;
493af28f636SEnrico Perla - Sun Microsystems }
494af28f636SEnrico Perla - Sun Microsystems
495af28f636SEnrico Perla - Sun Microsystems if (is_bootpar(curr_device->type) || is_bootpar(attach_device->type)) {
496af28f636SEnrico Perla - Sun Microsystems (void) fprintf(stderr, gettext("boot block mirroring is not "
497af28f636SEnrico Perla - Sun Microsystems "supported on PCFS\n"));
498af28f636SEnrico Perla - Sun Microsystems goto out_devs;
499af28f636SEnrico Perla - Sun Microsystems }
500af28f636SEnrico Perla - Sun Microsystems
5011a902ef8SHans Rosenfeld ret = read_stage2_from_disk(curr_device->part_fd, stage2_curr,
5021a902ef8SHans Rosenfeld curr_device->type);
503af28f636SEnrico Perla - Sun Microsystems if (ret == BC_ERROR) {
504af28f636SEnrico Perla - Sun Microsystems BOOT_DEBUG("Error reading first stage2 blocks from %s\n",
505af28f636SEnrico Perla - Sun Microsystems curr_device->path);
506af28f636SEnrico Perla - Sun Microsystems retval = BC_ERROR;
507af28f636SEnrico Perla - Sun Microsystems goto out_devs;
508af28f636SEnrico Perla - Sun Microsystems }
509af28f636SEnrico Perla - Sun Microsystems
510af28f636SEnrico Perla - Sun Microsystems if (ret == BC_NOEXTRA) {
511af28f636SEnrico Perla - Sun Microsystems BOOT_DEBUG("No multiboot header found on %s, unable to grab "
512af28f636SEnrico Perla - Sun Microsystems "stage2\n", curr_device->path);
513af28f636SEnrico Perla - Sun Microsystems retval = BC_NOEXTRA;
514af28f636SEnrico Perla - Sun Microsystems goto out_devs;
515af28f636SEnrico Perla - Sun Microsystems }
516af28f636SEnrico Perla - Sun Microsystems
51714d44f22SHans Rosenfeld einfo_curr = find_einfo(stage2_curr->extra, stage2_curr->extra_size);
518af28f636SEnrico Perla - Sun Microsystems if (einfo_curr != NULL)
519af28f636SEnrico Perla - Sun Microsystems updt_str = einfo_get_string(einfo_curr);
520af28f636SEnrico Perla - Sun Microsystems
521af28f636SEnrico Perla - Sun Microsystems write_mbr = B_TRUE;
522af28f636SEnrico Perla - Sun Microsystems force_mbr = B_TRUE;
523af28f636SEnrico Perla - Sun Microsystems retval = propagate_bootblock(&curr_data, &attach_data, updt_str);
524af28f636SEnrico Perla - Sun Microsystems cleanup_stage2(stage2_curr);
525af28f636SEnrico Perla - Sun Microsystems cleanup_stage2(stage2_attach);
526af28f636SEnrico Perla - Sun Microsystems
527af28f636SEnrico Perla - Sun Microsystems out_devs:
528af28f636SEnrico Perla - Sun Microsystems cleanup_device(attach_device);
529af28f636SEnrico Perla - Sun Microsystems out_currdev:
530af28f636SEnrico Perla - Sun Microsystems cleanup_device(curr_device);
531af28f636SEnrico Perla - Sun Microsystems out:
532af28f636SEnrico Perla - Sun Microsystems free(curr_device_path);
533af28f636SEnrico Perla - Sun Microsystems free(attach_device_path);
534af28f636SEnrico Perla - Sun Microsystems return (retval);
535af28f636SEnrico Perla - Sun Microsystems }
536af28f636SEnrico Perla - Sun Microsystems
537af28f636SEnrico Perla - Sun Microsystems static int
commit_to_disk(ig_data_t * install,char * updt_str)538af28f636SEnrico Perla - Sun Microsystems commit_to_disk(ig_data_t *install, char *updt_str)
539af28f636SEnrico Perla - Sun Microsystems {
540af28f636SEnrico Perla - Sun Microsystems assert(install != NULL);
541af28f636SEnrico Perla - Sun Microsystems /*
542af28f636SEnrico Perla - Sun Microsystems * vanilla stage1 and stage2 need to be updated at runtime.
543af28f636SEnrico Perla - Sun Microsystems * Update stage2 before stage1 because stage1 needs to know the first
544af28f636SEnrico Perla - Sun Microsystems * sector stage2 will be written to.
545af28f636SEnrico Perla - Sun Microsystems */
546af28f636SEnrico Perla - Sun Microsystems if (prepare_stage2(install, updt_str) != BC_SUCCESS) {
547af28f636SEnrico Perla - Sun Microsystems (void) fprintf(stderr, gettext("Error building stage2\n"));
548af28f636SEnrico Perla - Sun Microsystems return (BC_ERROR);
549af28f636SEnrico Perla - Sun Microsystems }
550af28f636SEnrico Perla - Sun Microsystems if (prepare_stage1(install) != BC_SUCCESS) {
551af28f636SEnrico Perla - Sun Microsystems (void) fprintf(stderr, gettext("Error building stage1\n"));
552af28f636SEnrico Perla - Sun Microsystems return (BC_ERROR);
553af28f636SEnrico Perla - Sun Microsystems }
554af28f636SEnrico Perla - Sun Microsystems
555af28f636SEnrico Perla - Sun Microsystems /* Write stage2 out to disk. */
556af28f636SEnrico Perla - Sun Microsystems if (write_stage2(install) != BC_SUCCESS) {
557af28f636SEnrico Perla - Sun Microsystems (void) fprintf(stderr, gettext("Error writing stage2 to "
558af28f636SEnrico Perla - Sun Microsystems "disk\n"));
559af28f636SEnrico Perla - Sun Microsystems return (BC_ERROR);
560af28f636SEnrico Perla - Sun Microsystems }
561af28f636SEnrico Perla - Sun Microsystems
562af28f636SEnrico Perla - Sun Microsystems /* Write stage1 to disk and, if requested, to the MBR. */
563af28f636SEnrico Perla - Sun Microsystems if (write_stage1(install) != BC_SUCCESS) {
564af28f636SEnrico Perla - Sun Microsystems (void) fprintf(stderr, gettext("Error writing stage1 to "
565af28f636SEnrico Perla - Sun Microsystems "disk\n"));
566af28f636SEnrico Perla - Sun Microsystems return (BC_ERROR);
567af28f636SEnrico Perla - Sun Microsystems }
568af28f636SEnrico Perla - Sun Microsystems
569af28f636SEnrico Perla - Sun Microsystems return (BC_SUCCESS);
570af28f636SEnrico Perla - Sun Microsystems }
571af28f636SEnrico Perla - Sun Microsystems
572af28f636SEnrico Perla - Sun Microsystems /*
573af28f636SEnrico Perla - Sun Microsystems * Propagate the bootblock on the source disk to the destination disk and
574af28f636SEnrico Perla - Sun Microsystems * version it with 'updt_str' in the process. Since we cannot trust any data
575af28f636SEnrico Perla - Sun Microsystems * on the attaching disk, we do not perform any specific check on a potential
576af28f636SEnrico Perla - Sun Microsystems * target extended information structure and we just blindly update.
577af28f636SEnrico Perla - Sun Microsystems */
578af28f636SEnrico Perla - Sun Microsystems static int
propagate_bootblock(ig_data_t * source,ig_data_t * target,char * updt_str)579af28f636SEnrico Perla - Sun Microsystems propagate_bootblock(ig_data_t *source, ig_data_t *target, char *updt_str)
580af28f636SEnrico Perla - Sun Microsystems {
581af28f636SEnrico Perla - Sun Microsystems ig_device_t *src_device = &source->device;
582af28f636SEnrico Perla - Sun Microsystems ig_device_t *dest_device = &target->device;
583af28f636SEnrico Perla - Sun Microsystems ig_stage2_t *src_stage2 = &source->stage2;
584af28f636SEnrico Perla - Sun Microsystems ig_stage2_t *dest_stage2 = &target->stage2;
585af28f636SEnrico Perla - Sun Microsystems uint32_t buf_size;
586af28f636SEnrico Perla - Sun Microsystems int retval;
587af28f636SEnrico Perla - Sun Microsystems
588af28f636SEnrico Perla - Sun Microsystems assert(source != NULL);
589af28f636SEnrico Perla - Sun Microsystems assert(target != NULL);
590af28f636SEnrico Perla - Sun Microsystems
591af28f636SEnrico Perla - Sun Microsystems /* read in stage1 from the source disk. */
592af28f636SEnrico Perla - Sun Microsystems if (read_stage1_from_disk(src_device->part_fd, target->stage1_buf)
593af28f636SEnrico Perla - Sun Microsystems != BC_SUCCESS)
594af28f636SEnrico Perla - Sun Microsystems return (BC_ERROR);
595af28f636SEnrico Perla - Sun Microsystems
596af28f636SEnrico Perla - Sun Microsystems /* Prepare target stage2 for commit_to_disk. */
597af28f636SEnrico Perla - Sun Microsystems cleanup_stage2(dest_stage2);
598af28f636SEnrico Perla - Sun Microsystems
599af28f636SEnrico Perla - Sun Microsystems if (updt_str != NULL)
600af28f636SEnrico Perla - Sun Microsystems do_version = B_TRUE;
601af28f636SEnrico Perla - Sun Microsystems else
602af28f636SEnrico Perla - Sun Microsystems do_version = B_FALSE;
603af28f636SEnrico Perla - Sun Microsystems
604af28f636SEnrico Perla - Sun Microsystems buf_size = src_stage2->file_size + SECTOR_SIZE;
605af28f636SEnrico Perla - Sun Microsystems
606af28f636SEnrico Perla - Sun Microsystems dest_stage2->buf_size = P2ROUNDUP(buf_size, SECTOR_SIZE);
607af28f636SEnrico Perla - Sun Microsystems dest_stage2->buf = malloc(dest_stage2->buf_size);
608af28f636SEnrico Perla - Sun Microsystems if (dest_stage2->buf == NULL) {
609af28f636SEnrico Perla - Sun Microsystems perror(gettext("Memory allocation failed"));
610af28f636SEnrico Perla - Sun Microsystems return (BC_ERROR);
611af28f636SEnrico Perla - Sun Microsystems }
612af28f636SEnrico Perla - Sun Microsystems dest_stage2->file = dest_stage2->buf;
613af28f636SEnrico Perla - Sun Microsystems dest_stage2->file_size = src_stage2->file_size;
614af28f636SEnrico Perla - Sun Microsystems memcpy(dest_stage2->file, src_stage2->file, dest_stage2->file_size);
615af28f636SEnrico Perla - Sun Microsystems dest_stage2->extra = dest_stage2->buf +
616af28f636SEnrico Perla - Sun Microsystems P2ROUNDUP(dest_stage2->file_size, 8);
617af28f636SEnrico Perla - Sun Microsystems
618af28f636SEnrico Perla - Sun Microsystems /* If we get down here we do have a mboot structure. */
619af28f636SEnrico Perla - Sun Microsystems assert(src_stage2->mboot);
620af28f636SEnrico Perla - Sun Microsystems
621af28f636SEnrico Perla - Sun Microsystems dest_stage2->mboot_off = src_stage2->mboot_off;
622af28f636SEnrico Perla - Sun Microsystems dest_stage2->mboot = (multiboot_header_t *)(dest_stage2->buf +
623af28f636SEnrico Perla - Sun Microsystems dest_stage2->mboot_off);
624af28f636SEnrico Perla - Sun Microsystems
625af28f636SEnrico Perla - Sun Microsystems (void) fprintf(stdout, gettext("Propagating %s stage1/stage2 to %s\n"),
626af28f636SEnrico Perla - Sun Microsystems src_device->path, dest_device->path);
627af28f636SEnrico Perla - Sun Microsystems retval = commit_to_disk(target, updt_str);
628af28f636SEnrico Perla - Sun Microsystems
629af28f636SEnrico Perla - Sun Microsystems return (retval);
630af28f636SEnrico Perla - Sun Microsystems }
631af28f636SEnrico Perla - Sun Microsystems
632af28f636SEnrico Perla - Sun Microsystems /*
633af28f636SEnrico Perla - Sun Microsystems * open the device and fill the various members of ig_device_t.
634af28f636SEnrico Perla - Sun Microsystems */
635af28f636SEnrico Perla - Sun Microsystems static int
init_device(ig_device_t * device,char * path)636af28f636SEnrico Perla - Sun Microsystems init_device(ig_device_t *device, char *path)
637af28f636SEnrico Perla - Sun Microsystems {
6381a902ef8SHans Rosenfeld struct dk_gpt *vtoc;
6391a902ef8SHans Rosenfeld fstyp_handle_t fhdl;
6401a902ef8SHans Rosenfeld const char *fident;
6411a902ef8SHans Rosenfeld
642af28f636SEnrico Perla - Sun Microsystems bzero(device, sizeof (*device));
643af28f636SEnrico Perla - Sun Microsystems device->part_fd = -1;
644af28f636SEnrico Perla - Sun Microsystems device->disk_fd = -1;
645af28f636SEnrico Perla - Sun Microsystems device->path_p0 = NULL;
646af28f636SEnrico Perla - Sun Microsystems
647af28f636SEnrico Perla - Sun Microsystems device->path = strdup(path);
648af28f636SEnrico Perla - Sun Microsystems if (device->path == NULL) {
649af28f636SEnrico Perla - Sun Microsystems perror(gettext("Memory allocation failed"));
650af28f636SEnrico Perla - Sun Microsystems return (BC_ERROR);
651af28f636SEnrico Perla - Sun Microsystems }
652af28f636SEnrico Perla - Sun Microsystems
653af28f636SEnrico Perla - Sun Microsystems if (strstr(device->path, "diskette")) {
654af28f636SEnrico Perla - Sun Microsystems (void) fprintf(stderr, gettext("installing GRUB to a floppy "
655af28f636SEnrico Perla - Sun Microsystems "disk is no longer supported\n"));
656af28f636SEnrico Perla - Sun Microsystems return (BC_ERROR);
657af28f636SEnrico Perla - Sun Microsystems }
658af28f636SEnrico Perla - Sun Microsystems
659af28f636SEnrico Perla - Sun Microsystems /* Detect if the target device is a pcfs partition. */
660af28f636SEnrico Perla - Sun Microsystems if (strstr(device->path, "p0:boot"))
661af28f636SEnrico Perla - Sun Microsystems device->type = IG_DEV_X86BOOTPAR;
662af28f636SEnrico Perla - Sun Microsystems
663af28f636SEnrico Perla - Sun Microsystems if (get_disk_fd(device) != BC_SUCCESS)
664af28f636SEnrico Perla - Sun Microsystems return (BC_ERROR);
665af28f636SEnrico Perla - Sun Microsystems
666af28f636SEnrico Perla - Sun Microsystems /* read in the device boot sector. */
667af28f636SEnrico Perla - Sun Microsystems if (read(device->disk_fd, device->boot_sector, SECTOR_SIZE)
668af28f636SEnrico Perla - Sun Microsystems != SECTOR_SIZE) {
669af28f636SEnrico Perla - Sun Microsystems (void) fprintf(stderr, gettext("Error reading boot sector\n"));
670af28f636SEnrico Perla - Sun Microsystems perror("read");
671af28f636SEnrico Perla - Sun Microsystems return (BC_ERROR);
672af28f636SEnrico Perla - Sun Microsystems }
673af28f636SEnrico Perla - Sun Microsystems
674*cc641e8dSToomas Soome if (efi_alloc_and_read(device->disk_fd, &vtoc) >= 0) {
6751a902ef8SHans Rosenfeld device->type = IG_DEV_EFI;
6761a902ef8SHans Rosenfeld efi_free(vtoc);
6771a902ef8SHans Rosenfeld }
6781a902ef8SHans Rosenfeld
679af28f636SEnrico Perla - Sun Microsystems if (get_raw_partition_fd(device) != BC_SUCCESS)
680af28f636SEnrico Perla - Sun Microsystems return (BC_ERROR);
681af28f636SEnrico Perla - Sun Microsystems
6829348d232SHans Rosenfeld if (is_efi(device->type)) {
6831a902ef8SHans Rosenfeld if (fstyp_init(device->part_fd, 0, NULL, &fhdl) != 0)
6841a902ef8SHans Rosenfeld return (BC_ERROR);
6851a902ef8SHans Rosenfeld
6861a902ef8SHans Rosenfeld if (fstyp_ident(fhdl, "zfs", &fident) != 0) {
6871a902ef8SHans Rosenfeld fstyp_fini(fhdl);
6889348d232SHans Rosenfeld (void) fprintf(stderr, gettext("Booting of EFI labeled "
6899348d232SHans Rosenfeld "disks is only supported with ZFS\n"));
6901a902ef8SHans Rosenfeld return (BC_ERROR);
6911a902ef8SHans Rosenfeld }
6921a902ef8SHans Rosenfeld fstyp_fini(fhdl);
6939348d232SHans Rosenfeld }
6941a902ef8SHans Rosenfeld
695af28f636SEnrico Perla - Sun Microsystems if (get_start_sector(device) != BC_SUCCESS)
696af28f636SEnrico Perla - Sun Microsystems return (BC_ERROR);
697af28f636SEnrico Perla - Sun Microsystems
698af28f636SEnrico Perla - Sun Microsystems return (BC_SUCCESS);
699af28f636SEnrico Perla - Sun Microsystems }
700af28f636SEnrico Perla - Sun Microsystems
701af28f636SEnrico Perla - Sun Microsystems static void
cleanup_device(ig_device_t * device)702af28f636SEnrico Perla - Sun Microsystems cleanup_device(ig_device_t *device)
703af28f636SEnrico Perla - Sun Microsystems {
704af28f636SEnrico Perla - Sun Microsystems if (device->path)
705af28f636SEnrico Perla - Sun Microsystems free(device->path);
706af28f636SEnrico Perla - Sun Microsystems if (device->path_p0)
707af28f636SEnrico Perla - Sun Microsystems free(device->path_p0);
708af28f636SEnrico Perla - Sun Microsystems
709af28f636SEnrico Perla - Sun Microsystems if (device->part_fd != -1)
710af28f636SEnrico Perla - Sun Microsystems (void) close(device->part_fd);
711af28f636SEnrico Perla - Sun Microsystems if (device->disk_fd != -1)
712af28f636SEnrico Perla - Sun Microsystems (void) close(device->disk_fd);
713af28f636SEnrico Perla - Sun Microsystems
714af28f636SEnrico Perla - Sun Microsystems bzero(device, sizeof (ig_device_t));
715af28f636SEnrico Perla - Sun Microsystems device->part_fd = -1;
716af28f636SEnrico Perla - Sun Microsystems device->disk_fd = -1;
717af28f636SEnrico Perla - Sun Microsystems }
718af28f636SEnrico Perla - Sun Microsystems
719af28f636SEnrico Perla - Sun Microsystems static void
cleanup_stage2(ig_stage2_t * stage2)720af28f636SEnrico Perla - Sun Microsystems cleanup_stage2(ig_stage2_t *stage2)
721af28f636SEnrico Perla - Sun Microsystems {
722af28f636SEnrico Perla - Sun Microsystems if (stage2->buf)
723af28f636SEnrico Perla - Sun Microsystems free(stage2->buf);
724af28f636SEnrico Perla - Sun Microsystems bzero(stage2, sizeof (ig_stage2_t));
725af28f636SEnrico Perla - Sun Microsystems }
726af28f636SEnrico Perla - Sun Microsystems
727af28f636SEnrico Perla - Sun Microsystems static int
get_start_sector(ig_device_t * device)728af28f636SEnrico Perla - Sun Microsystems get_start_sector(ig_device_t *device)
729af28f636SEnrico Perla - Sun Microsystems {
7307fc5d2a4SVikram Hegde uint32_t secnum = 0, numsec = 0;
7317fc5d2a4SVikram Hegde int i, pno, rval, log_part = 0;
7327c478bd9Sstevel@tonic-gate struct mboot *mboot;
7337c478bd9Sstevel@tonic-gate struct ipart *part;
734aa1b14e7SSheshadri Vasudevan ext_part_t *epp;
7357fc5d2a4SVikram Hegde struct part_info dkpi;
7367fc5d2a4SVikram Hegde struct extpart_info edkpi;
7377c478bd9Sstevel@tonic-gate
7381a902ef8SHans Rosenfeld if (is_efi(device->type)) {
7391a902ef8SHans Rosenfeld struct dk_gpt *vtoc;
7401a902ef8SHans Rosenfeld
741*cc641e8dSToomas Soome if (efi_alloc_and_read(device->disk_fd, &vtoc) < 0)
7421a902ef8SHans Rosenfeld return (BC_ERROR);
7431a902ef8SHans Rosenfeld
7441a902ef8SHans Rosenfeld device->start_sector = vtoc->efi_parts[device->slice].p_start;
7451a902ef8SHans Rosenfeld /* GPT doesn't use traditional slice letters */
7461a902ef8SHans Rosenfeld device->slice = 0xff;
7471a902ef8SHans Rosenfeld device->partition = 0;
7481a902ef8SHans Rosenfeld
7491a902ef8SHans Rosenfeld efi_free(vtoc);
7501a902ef8SHans Rosenfeld goto found_part;
7511a902ef8SHans Rosenfeld }
7521a902ef8SHans Rosenfeld
753af28f636SEnrico Perla - Sun Microsystems mboot = (struct mboot *)device->boot_sector;
7547c478bd9Sstevel@tonic-gate
755af28f636SEnrico Perla - Sun Microsystems if (is_bootpar(device->type)) {
756af28f636SEnrico Perla - Sun Microsystems if (find_x86_bootpar(mboot, &pno, &secnum) != BC_SUCCESS) {
757af28f636SEnrico Perla - Sun Microsystems (void) fprintf(stderr, NOBOOTPAR);
758af28f636SEnrico Perla - Sun Microsystems return (BC_ERROR);
759af28f636SEnrico Perla - Sun Microsystems } else {
760af28f636SEnrico Perla - Sun Microsystems device->start_sector = secnum;
761af28f636SEnrico Perla - Sun Microsystems device->partition = pno;
7627fc5d2a4SVikram Hegde goto found_part;
7637fc5d2a4SVikram Hegde }
764d33344bbSsy25831 }
765d33344bbSsy25831
766aa1b14e7SSheshadri Vasudevan /*
767af28f636SEnrico Perla - Sun Microsystems * Search for Solaris fdisk partition
768d33344bbSsy25831 * Get the solaris partition information from the device
769d33344bbSsy25831 * and compare the offset of S2 with offset of solaris partition
770d33344bbSsy25831 * from fdisk partition table.
771d33344bbSsy25831 */
772af28f636SEnrico Perla - Sun Microsystems if (ioctl(device->part_fd, DKIOCEXTPARTINFO, &edkpi) < 0) {
773af28f636SEnrico Perla - Sun Microsystems if (ioctl(device->part_fd, DKIOCPARTINFO, &dkpi) < 0) {
774d33344bbSsy25831 (void) fprintf(stderr, PART_FAIL);
775af28f636SEnrico Perla - Sun Microsystems return (BC_ERROR);
776342440ecSPrasad Singamsetty } else {
777342440ecSPrasad Singamsetty edkpi.p_start = dkpi.p_start;
778342440ecSPrasad Singamsetty }
779d33344bbSsy25831 }
780d33344bbSsy25831
781d33344bbSsy25831 for (i = 0; i < FD_NUMPART; i++) {
782d33344bbSsy25831 part = (struct ipart *)mboot->parts + i;
783d33344bbSsy25831
784d33344bbSsy25831 if (part->relsect == 0) {
785d33344bbSsy25831 (void) fprintf(stderr, BAD_PART, i);
786af28f636SEnrico Perla - Sun Microsystems return (BC_ERROR);
787d33344bbSsy25831 }
788aa1b14e7SSheshadri Vasudevan
789342440ecSPrasad Singamsetty if (edkpi.p_start >= part->relsect &&
790342440ecSPrasad Singamsetty edkpi.p_start < (part->relsect + part->numsect)) {
791d33344bbSsy25831 /* Found the partition */
7927c478bd9Sstevel@tonic-gate break;
793d33344bbSsy25831 }
7947c478bd9Sstevel@tonic-gate }
7957c478bd9Sstevel@tonic-gate
7967fc5d2a4SVikram Hegde if (i == FD_NUMPART) {
7977fc5d2a4SVikram Hegde /* No solaris fdisk partitions (primary or logical) */
7987fc5d2a4SVikram Hegde (void) fprintf(stderr, NOSOLPAR);
799af28f636SEnrico Perla - Sun Microsystems return (BC_ERROR);
8007c478bd9Sstevel@tonic-gate }
8017c478bd9Sstevel@tonic-gate
8027fc5d2a4SVikram Hegde /*
8037fc5d2a4SVikram Hegde * We have found a Solaris fdisk partition (primary or extended)
8047fc5d2a4SVikram Hegde * Handle the simple case first: Solaris in a primary partition
8057fc5d2a4SVikram Hegde */
8067fc5d2a4SVikram Hegde if (!fdisk_is_dos_extended(part->systid)) {
807af28f636SEnrico Perla - Sun Microsystems device->start_sector = part->relsect;
808af28f636SEnrico Perla - Sun Microsystems device->partition = i;
8097fc5d2a4SVikram Hegde goto found_part;
8107fc5d2a4SVikram Hegde }
8117fc5d2a4SVikram Hegde
8127fc5d2a4SVikram Hegde /*
8137fc5d2a4SVikram Hegde * Solaris in a logical partition. Find that partition in the
8147fc5d2a4SVikram Hegde * extended part.
8157fc5d2a4SVikram Hegde */
816af28f636SEnrico Perla - Sun Microsystems if ((rval = libfdisk_init(&epp, device->path_p0, NULL, FDISK_READ_DISK))
8177fc5d2a4SVikram Hegde != FDISK_SUCCESS) {
8187fc5d2a4SVikram Hegde switch (rval) {
8197fc5d2a4SVikram Hegde /*
8206cb5747bSSharath M Srinivasan * The first 3 cases are not an error per-se, just that
8217fc5d2a4SVikram Hegde * there is no Solaris logical partition
8227fc5d2a4SVikram Hegde */
8237fc5d2a4SVikram Hegde case FDISK_EBADLOGDRIVE:
8247fc5d2a4SVikram Hegde case FDISK_ENOLOGDRIVE:
8256cb5747bSSharath M Srinivasan case FDISK_EBADMAGIC:
8267fc5d2a4SVikram Hegde (void) fprintf(stderr, NOSOLPAR);
827af28f636SEnrico Perla - Sun Microsystems return (BC_ERROR);
8287fc5d2a4SVikram Hegde case FDISK_ENOVGEOM:
8297fc5d2a4SVikram Hegde (void) fprintf(stderr, NO_VIRT_GEOM);
830af28f636SEnrico Perla - Sun Microsystems return (BC_ERROR);
8317fc5d2a4SVikram Hegde case FDISK_ENOPGEOM:
8327fc5d2a4SVikram Hegde (void) fprintf(stderr, NO_PHYS_GEOM);
833af28f636SEnrico Perla - Sun Microsystems return (BC_ERROR);
8347fc5d2a4SVikram Hegde case FDISK_ENOLGEOM:
8357fc5d2a4SVikram Hegde (void) fprintf(stderr, NO_LABEL_GEOM);
836af28f636SEnrico Perla - Sun Microsystems return (BC_ERROR);
8377fc5d2a4SVikram Hegde default:
8387fc5d2a4SVikram Hegde (void) fprintf(stderr, LIBFDISK_INIT_FAIL);
839af28f636SEnrico Perla - Sun Microsystems return (BC_ERROR);
8407fc5d2a4SVikram Hegde }
8417fc5d2a4SVikram Hegde }
8427fc5d2a4SVikram Hegde
8437fc5d2a4SVikram Hegde rval = fdisk_get_solaris_part(epp, &pno, &secnum, &numsec);
8446cb5747bSSharath M Srinivasan libfdisk_fini(&epp);
8457fc5d2a4SVikram Hegde if (rval != FDISK_SUCCESS) {
8467fc5d2a4SVikram Hegde /* No solaris logical partition */
8477fc5d2a4SVikram Hegde (void) fprintf(stderr, NOSOLPAR);
848af28f636SEnrico Perla - Sun Microsystems return (BC_ERROR);
8497fc5d2a4SVikram Hegde }
8507fc5d2a4SVikram Hegde
851af28f636SEnrico Perla - Sun Microsystems device->start_sector = secnum;
852af28f636SEnrico Perla - Sun Microsystems device->partition = pno - 1;
8537fc5d2a4SVikram Hegde log_part = 1;
8547fc5d2a4SVikram Hegde
8557fc5d2a4SVikram Hegde found_part:
8567c478bd9Sstevel@tonic-gate /* get confirmation for -m */
857af28f636SEnrico Perla - Sun Microsystems if (write_mbr && !force_mbr) {
8587c478bd9Sstevel@tonic-gate (void) fprintf(stdout, MBOOT_PROMPT);
85921ba817cSToomas Soome if (!yes()) {
860af28f636SEnrico Perla - Sun Microsystems write_mbr = 0;
8617c478bd9Sstevel@tonic-gate (void) fprintf(stdout, MBOOT_NOT_UPDATED);
862af28f636SEnrico Perla - Sun Microsystems return (BC_ERROR);
8637c478bd9Sstevel@tonic-gate }
8647c478bd9Sstevel@tonic-gate }
8657c478bd9Sstevel@tonic-gate
8667fc5d2a4SVikram Hegde /*
8677fc5d2a4SVikram Hegde * Currently if Solaris is in an extended partition we need to
8687fc5d2a4SVikram Hegde * write GRUB to the MBR. Check for this.
8697fc5d2a4SVikram Hegde */
870af28f636SEnrico Perla - Sun Microsystems if (log_part && !write_mbr) {
871af28f636SEnrico Perla - Sun Microsystems (void) fprintf(stdout, gettext("Installing Solaris on an "
872af28f636SEnrico Perla - Sun Microsystems "extended partition... forcing MBR update\n"));
873af28f636SEnrico Perla - Sun Microsystems write_mbr = 1;
874aa1b14e7SSheshadri Vasudevan }
875aa1b14e7SSheshadri Vasudevan
8767fc5d2a4SVikram Hegde /*
8777fc5d2a4SVikram Hegde * warn, if Solaris in primary partition and GRUB not in MBR and
8787fc5d2a4SVikram Hegde * partition is not active
8797fc5d2a4SVikram Hegde */
880af28f636SEnrico Perla - Sun Microsystems if (!log_part && part->bootid != 128 && !write_mbr) {
881af28f636SEnrico Perla - Sun Microsystems (void) fprintf(stdout, SOLPAR_INACTIVE, device->partition + 1);
8827c478bd9Sstevel@tonic-gate }
8837c478bd9Sstevel@tonic-gate
884af28f636SEnrico Perla - Sun Microsystems return (BC_SUCCESS);
8857c478bd9Sstevel@tonic-gate }
8867c478bd9Sstevel@tonic-gate
887af28f636SEnrico Perla - Sun Microsystems static int
get_disk_fd(ig_device_t * device)888af28f636SEnrico Perla - Sun Microsystems get_disk_fd(ig_device_t *device)
889af28f636SEnrico Perla - Sun Microsystems {
890af28f636SEnrico Perla - Sun Microsystems int i;
891af28f636SEnrico Perla - Sun Microsystems char save[2];
892af28f636SEnrico Perla - Sun Microsystems char *end = NULL;
893af28f636SEnrico Perla - Sun Microsystems
894af28f636SEnrico Perla - Sun Microsystems assert(device != NULL);
895af28f636SEnrico Perla - Sun Microsystems assert(device->path != NULL);
896af28f636SEnrico Perla - Sun Microsystems
897af28f636SEnrico Perla - Sun Microsystems if (is_bootpar(device->type)) {
898af28f636SEnrico Perla - Sun Microsystems end = strstr(device->path, "p0:boot");
899af28f636SEnrico Perla - Sun Microsystems /* tested at the start of init_device() */
900af28f636SEnrico Perla - Sun Microsystems assert(end != NULL);
901af28f636SEnrico Perla - Sun Microsystems /* chop off :boot */
902af28f636SEnrico Perla - Sun Microsystems save[0] = end[2];
903af28f636SEnrico Perla - Sun Microsystems end[2] = '\0';
904af28f636SEnrico Perla - Sun Microsystems } else {
905af28f636SEnrico Perla - Sun Microsystems i = strlen(device->path);
906af28f636SEnrico Perla - Sun Microsystems save[0] = device->path[i - 2];
907af28f636SEnrico Perla - Sun Microsystems save[1] = device->path[i - 1];
908af28f636SEnrico Perla - Sun Microsystems device->path[i - 2] = 'p';
909af28f636SEnrico Perla - Sun Microsystems device->path[i - 1] = '0';
910af28f636SEnrico Perla - Sun Microsystems }
911af28f636SEnrico Perla - Sun Microsystems
912af28f636SEnrico Perla - Sun Microsystems if (nowrite)
913af28f636SEnrico Perla - Sun Microsystems device->disk_fd = open(device->path, O_RDONLY);
914af28f636SEnrico Perla - Sun Microsystems else
915af28f636SEnrico Perla - Sun Microsystems device->disk_fd = open(device->path, O_RDWR);
916af28f636SEnrico Perla - Sun Microsystems
917af28f636SEnrico Perla - Sun Microsystems device->path_p0 = strdup(device->path);
918af28f636SEnrico Perla - Sun Microsystems if (device->path_p0 == NULL) {
919af28f636SEnrico Perla - Sun Microsystems perror("strdup");
920af28f636SEnrico Perla - Sun Microsystems return (BC_ERROR);
921af28f636SEnrico Perla - Sun Microsystems }
922af28f636SEnrico Perla - Sun Microsystems
923af28f636SEnrico Perla - Sun Microsystems if (is_bootpar(device->type)) {
924af28f636SEnrico Perla - Sun Microsystems end[2] = save[0];
925af28f636SEnrico Perla - Sun Microsystems } else {
926af28f636SEnrico Perla - Sun Microsystems device->path[i - 2] = save[0];
927af28f636SEnrico Perla - Sun Microsystems device->path[i - 1] = save[1];
928af28f636SEnrico Perla - Sun Microsystems }
929af28f636SEnrico Perla - Sun Microsystems
930af28f636SEnrico Perla - Sun Microsystems if (device->disk_fd == -1) {
931af28f636SEnrico Perla - Sun Microsystems perror("open");
932af28f636SEnrico Perla - Sun Microsystems return (BC_ERROR);
933af28f636SEnrico Perla - Sun Microsystems }
934af28f636SEnrico Perla - Sun Microsystems
935af28f636SEnrico Perla - Sun Microsystems return (BC_SUCCESS);
936af28f636SEnrico Perla - Sun Microsystems }
937af28f636SEnrico Perla - Sun Microsystems
938af28f636SEnrico Perla - Sun Microsystems static void
prepare_fake_multiboot(ig_stage2_t * stage2)939af28f636SEnrico Perla - Sun Microsystems prepare_fake_multiboot(ig_stage2_t *stage2)
940af28f636SEnrico Perla - Sun Microsystems {
941af28f636SEnrico Perla - Sun Microsystems multiboot_header_t *mboot;
942af28f636SEnrico Perla - Sun Microsystems
943af28f636SEnrico Perla - Sun Microsystems assert(stage2 != NULL);
944af28f636SEnrico Perla - Sun Microsystems assert(stage2->mboot != NULL);
945af28f636SEnrico Perla - Sun Microsystems assert(stage2->buf != NULL);
946af28f636SEnrico Perla - Sun Microsystems
947af28f636SEnrico Perla - Sun Microsystems mboot = stage2->mboot;
948af28f636SEnrico Perla - Sun Microsystems
949af28f636SEnrico Perla - Sun Microsystems /*
950af28f636SEnrico Perla - Sun Microsystems * Currently we expect find_multiboot() to have located a multiboot
951af28f636SEnrico Perla - Sun Microsystems * header with the AOUT kludge flag set.
952af28f636SEnrico Perla - Sun Microsystems */
953af28f636SEnrico Perla - Sun Microsystems assert(mboot->flags & BB_MBOOT_AOUT_FLAG);
954af28f636SEnrico Perla - Sun Microsystems
955af28f636SEnrico Perla - Sun Microsystems /* Insert the information necessary to locate stage2. */
956af28f636SEnrico Perla - Sun Microsystems mboot->header_addr = stage2->mboot_off;
957af28f636SEnrico Perla - Sun Microsystems mboot->load_addr = 0;
958af28f636SEnrico Perla - Sun Microsystems mboot->load_end_addr = stage2->file_size;
959af28f636SEnrico Perla - Sun Microsystems }
960af28f636SEnrico Perla - Sun Microsystems
961af28f636SEnrico Perla - Sun Microsystems static void
add_stage2_einfo(ig_stage2_t * stage2,char * updt_str)962af28f636SEnrico Perla - Sun Microsystems add_stage2_einfo(ig_stage2_t *stage2, char *updt_str)
963af28f636SEnrico Perla - Sun Microsystems {
964af28f636SEnrico Perla - Sun Microsystems bblk_hs_t hs;
965af28f636SEnrico Perla - Sun Microsystems uint32_t avail_space;
966af28f636SEnrico Perla - Sun Microsystems
967af28f636SEnrico Perla - Sun Microsystems assert(stage2 != NULL);
968af28f636SEnrico Perla - Sun Microsystems
969af28f636SEnrico Perla - Sun Microsystems /* Fill bootblock hashing source information. */
970af28f636SEnrico Perla - Sun Microsystems hs.src_buf = (unsigned char *)stage2->file;
971af28f636SEnrico Perla - Sun Microsystems hs.src_size = stage2->file_size;
972af28f636SEnrico Perla - Sun Microsystems /* How much space for the extended information structure? */
973af28f636SEnrico Perla - Sun Microsystems avail_space = stage2->buf_size - P2ROUNDUP(stage2->file_size, 8);
974af28f636SEnrico Perla - Sun Microsystems add_einfo(stage2->extra, updt_str, &hs, avail_space);
975af28f636SEnrico Perla - Sun Microsystems }
976af28f636SEnrico Perla - Sun Microsystems
977af28f636SEnrico Perla - Sun Microsystems
978af28f636SEnrico Perla - Sun Microsystems static int
write_stage2(ig_data_t * install)979af28f636SEnrico Perla - Sun Microsystems write_stage2(ig_data_t *install)
980af28f636SEnrico Perla - Sun Microsystems {
981af28f636SEnrico Perla - Sun Microsystems ig_device_t *device = &install->device;
982af28f636SEnrico Perla - Sun Microsystems ig_stage2_t *stage2 = &install->stage2;
983af28f636SEnrico Perla - Sun Microsystems off_t offset;
984af28f636SEnrico Perla - Sun Microsystems
985af28f636SEnrico Perla - Sun Microsystems assert(install != NULL);
986af28f636SEnrico Perla - Sun Microsystems
987af28f636SEnrico Perla - Sun Microsystems if (is_bootpar(device->type)) {
988af28f636SEnrico Perla - Sun Microsystems /*
989af28f636SEnrico Perla - Sun Microsystems * stage2 is already on the filesystem, we only need to update
990af28f636SEnrico Perla - Sun Microsystems * the first two blocks (that we have modified during
991af28f636SEnrico Perla - Sun Microsystems * prepare_stage2())
992af28f636SEnrico Perla - Sun Microsystems */
993af28f636SEnrico Perla - Sun Microsystems if (write_out(device->part_fd, stage2->file, SECTOR_SIZE,
994af28f636SEnrico Perla - Sun Microsystems stage2->pcfs_first_sectors[0] * SECTOR_SIZE)
995af28f636SEnrico Perla - Sun Microsystems != BC_SUCCESS ||
996af28f636SEnrico Perla - Sun Microsystems write_out(device->part_fd, stage2->file + SECTOR_SIZE,
997af28f636SEnrico Perla - Sun Microsystems SECTOR_SIZE, stage2->pcfs_first_sectors[1] * SECTOR_SIZE)
998af28f636SEnrico Perla - Sun Microsystems != BC_SUCCESS) {
999af28f636SEnrico Perla - Sun Microsystems (void) fprintf(stderr, WRITE_FAIL_STAGE2);
1000af28f636SEnrico Perla - Sun Microsystems return (BC_ERROR);
1001af28f636SEnrico Perla - Sun Microsystems }
1002af28f636SEnrico Perla - Sun Microsystems (void) fprintf(stdout, WRITE_STAGE2_PCFS);
1003af28f636SEnrico Perla - Sun Microsystems return (BC_SUCCESS);
1004af28f636SEnrico Perla - Sun Microsystems }
1005af28f636SEnrico Perla - Sun Microsystems
1006af28f636SEnrico Perla - Sun Microsystems /*
1007af28f636SEnrico Perla - Sun Microsystems * For disk, write stage2 starting at STAGE2_BLKOFF sector.
1008af28f636SEnrico Perla - Sun Microsystems * Note that we use stage2->buf rather than stage2->file, because we
1009af28f636SEnrico Perla - Sun Microsystems * may have extended information after the latter.
10109348d232SHans Rosenfeld *
10119348d232SHans Rosenfeld * If we're writing to an EFI-labeled disk where stage2 lives in the
10129348d232SHans Rosenfeld * 3.5MB boot loader gap following the ZFS vdev labels, make sure the
10139348d232SHans Rosenfeld * size of the buffer doesn't exceed the size of the gap.
1014af28f636SEnrico Perla - Sun Microsystems */
10159348d232SHans Rosenfeld if (is_efi(device->type) && stage2->buf_size > STAGE2_MAXSIZE) {
10169348d232SHans Rosenfeld (void) fprintf(stderr, WRITE_FAIL_STAGE2);
10179348d232SHans Rosenfeld return (BC_ERROR);
10189348d232SHans Rosenfeld }
10199348d232SHans Rosenfeld
10201a902ef8SHans Rosenfeld offset = STAGE2_BLKOFF(device->type) * SECTOR_SIZE;
10211a902ef8SHans Rosenfeld
1022af28f636SEnrico Perla - Sun Microsystems if (write_out(device->part_fd, stage2->buf, stage2->buf_size,
1023af28f636SEnrico Perla - Sun Microsystems offset) != BC_SUCCESS) {
1024af28f636SEnrico Perla - Sun Microsystems perror("write");
1025af28f636SEnrico Perla - Sun Microsystems return (BC_ERROR);
1026af28f636SEnrico Perla - Sun Microsystems }
1027af28f636SEnrico Perla - Sun Microsystems
1028af28f636SEnrico Perla - Sun Microsystems /* Simulate the "old" installgrub output. */
1029af28f636SEnrico Perla - Sun Microsystems (void) fprintf(stdout, WRITE_STAGE2_DISK, device->partition,
10301a902ef8SHans Rosenfeld (stage2->buf_size / SECTOR_SIZE) + 1, STAGE2_BLKOFF(device->type),
1031af28f636SEnrico Perla - Sun Microsystems stage2->first_sector);
1032af28f636SEnrico Perla - Sun Microsystems
1033af28f636SEnrico Perla - Sun Microsystems return (BC_SUCCESS);
1034af28f636SEnrico Perla - Sun Microsystems }
1035af28f636SEnrico Perla - Sun Microsystems
1036af28f636SEnrico Perla - Sun Microsystems static int
write_stage1(ig_data_t * install)1037af28f636SEnrico Perla - Sun Microsystems write_stage1(ig_data_t *install)
1038af28f636SEnrico Perla - Sun Microsystems {
1039af28f636SEnrico Perla - Sun Microsystems ig_device_t *device = &install->device;
1040af28f636SEnrico Perla - Sun Microsystems
1041af28f636SEnrico Perla - Sun Microsystems assert(install != NULL);
1042af28f636SEnrico Perla - Sun Microsystems
1043af28f636SEnrico Perla - Sun Microsystems if (write_out(device->part_fd, install->stage1_buf,
1044af28f636SEnrico Perla - Sun Microsystems sizeof (install->stage1_buf), 0) != BC_SUCCESS) {
1045af28f636SEnrico Perla - Sun Microsystems (void) fprintf(stdout, WRITE_FAIL_PBOOT);
1046af28f636SEnrico Perla - Sun Microsystems perror("write");
1047af28f636SEnrico Perla - Sun Microsystems return (BC_ERROR);
1048af28f636SEnrico Perla - Sun Microsystems }
1049af28f636SEnrico Perla - Sun Microsystems
1050af28f636SEnrico Perla - Sun Microsystems /* Simulate "old" installgrub output. */
1051af28f636SEnrico Perla - Sun Microsystems (void) fprintf(stdout, WRITE_PBOOT, device->partition,
1052af28f636SEnrico Perla - Sun Microsystems device->start_sector);
1053af28f636SEnrico Perla - Sun Microsystems
1054af28f636SEnrico Perla - Sun Microsystems if (write_mbr) {
1055af28f636SEnrico Perla - Sun Microsystems if (write_out(device->disk_fd, install->stage1_buf,
1056af28f636SEnrico Perla - Sun Microsystems sizeof (install->stage1_buf), 0) != BC_SUCCESS) {
1057af28f636SEnrico Perla - Sun Microsystems (void) fprintf(stdout, WRITE_FAIL_BOOTSEC);
1058af28f636SEnrico Perla - Sun Microsystems perror("write");
1059af28f636SEnrico Perla - Sun Microsystems return (BC_ERROR);
1060af28f636SEnrico Perla - Sun Microsystems }
1061af28f636SEnrico Perla - Sun Microsystems /* Simulate "old" installgrub output. */
1062af28f636SEnrico Perla - Sun Microsystems (void) fprintf(stdout, WRITE_MBOOT);
1063af28f636SEnrico Perla - Sun Microsystems }
1064af28f636SEnrico Perla - Sun Microsystems
1065af28f636SEnrico Perla - Sun Microsystems return (BC_SUCCESS);
1066af28f636SEnrico Perla - Sun Microsystems }
1067af28f636SEnrico Perla - Sun Microsystems
1068af28f636SEnrico Perla - Sun Microsystems #define USAGE_STRING "%s [-m|-f|-n|-F|-u verstr] stage1 stage2 device\n" \
1069af28f636SEnrico Perla - Sun Microsystems "%s -M [-n] device1 device2\n" \
1070af28f636SEnrico Perla - Sun Microsystems "%s [-V|-e] -i device\n" \
1071af28f636SEnrico Perla - Sun Microsystems
1072af28f636SEnrico Perla - Sun Microsystems #define CANON_USAGE_STR gettext(USAGE_STRING)
1073af28f636SEnrico Perla - Sun Microsystems
10747c478bd9Sstevel@tonic-gate static void
usage(char * progname)10757c478bd9Sstevel@tonic-gate usage(char *progname)
10767c478bd9Sstevel@tonic-gate {
1077af28f636SEnrico Perla - Sun Microsystems (void) fprintf(stdout, CANON_USAGE_STR, progname, progname, progname);
10787c478bd9Sstevel@tonic-gate }
10797c478bd9Sstevel@tonic-gate
1080af28f636SEnrico Perla - Sun Microsystems
10817c478bd9Sstevel@tonic-gate static int
read_stage1_from_file(char * path,ig_data_t * dest)1082af28f636SEnrico Perla - Sun Microsystems read_stage1_from_file(char *path, ig_data_t *dest)
10837c478bd9Sstevel@tonic-gate {
10847c478bd9Sstevel@tonic-gate int fd;
10857c478bd9Sstevel@tonic-gate
1086af28f636SEnrico Perla - Sun Microsystems assert(dest);
1087af28f636SEnrico Perla - Sun Microsystems
10887c478bd9Sstevel@tonic-gate /* read the stage1 file from filesystem */
1089af28f636SEnrico Perla - Sun Microsystems fd = open(path, O_RDONLY);
1090af28f636SEnrico Perla - Sun Microsystems if (fd == -1 ||
1091af28f636SEnrico Perla - Sun Microsystems read(fd, dest->stage1_buf, SECTOR_SIZE) != SECTOR_SIZE) {
1092af28f636SEnrico Perla - Sun Microsystems (void) fprintf(stderr, READ_FAIL_STAGE1, path);
1093af28f636SEnrico Perla - Sun Microsystems return (BC_ERROR);
10947c478bd9Sstevel@tonic-gate }
10957c478bd9Sstevel@tonic-gate (void) close(fd);
1096af28f636SEnrico Perla - Sun Microsystems return (BC_SUCCESS);
10977c478bd9Sstevel@tonic-gate }
10987c478bd9Sstevel@tonic-gate
1099af28f636SEnrico Perla - Sun Microsystems static int
read_stage2_from_file(char * path,ig_data_t * dest)1100af28f636SEnrico Perla - Sun Microsystems read_stage2_from_file(char *path, ig_data_t *dest)
11017c478bd9Sstevel@tonic-gate {
1102af28f636SEnrico Perla - Sun Microsystems int fd;
1103af28f636SEnrico Perla - Sun Microsystems struct stat sb;
1104af28f636SEnrico Perla - Sun Microsystems ig_stage2_t *stage2 = &dest->stage2;
1105af28f636SEnrico Perla - Sun Microsystems ig_device_t *device = &dest->device;
1106af28f636SEnrico Perla - Sun Microsystems uint32_t buf_size;
1107af28f636SEnrico Perla - Sun Microsystems
1108af28f636SEnrico Perla - Sun Microsystems assert(dest);
1109af28f636SEnrico Perla - Sun Microsystems assert(stage2->buf == NULL);
1110af28f636SEnrico Perla - Sun Microsystems
1111af28f636SEnrico Perla - Sun Microsystems fd = open(path, O_RDONLY);
1112af28f636SEnrico Perla - Sun Microsystems if (fstat(fd, &sb) == -1) {
1113af28f636SEnrico Perla - Sun Microsystems perror("fstat");
1114af28f636SEnrico Perla - Sun Microsystems goto out;
11157c478bd9Sstevel@tonic-gate }
11167c478bd9Sstevel@tonic-gate
1117af28f636SEnrico Perla - Sun Microsystems stage2->file_size = sb.st_size;
11187c478bd9Sstevel@tonic-gate
1119af28f636SEnrico Perla - Sun Microsystems if (!is_bootpar(device->type)) {
1120af28f636SEnrico Perla - Sun Microsystems /*
1121af28f636SEnrico Perla - Sun Microsystems * buffer size needs to account for stage2 plus the extra
1122af28f636SEnrico Perla - Sun Microsystems * versioning information at the end of it. We reserve one
1123af28f636SEnrico Perla - Sun Microsystems * extra sector (plus we round up to the next sector boundary).
1124af28f636SEnrico Perla - Sun Microsystems */
1125af28f636SEnrico Perla - Sun Microsystems buf_size = stage2->file_size + SECTOR_SIZE;
11267c478bd9Sstevel@tonic-gate } else {
1127af28f636SEnrico Perla - Sun Microsystems /* In the PCFS case we only need to read in stage2. */
1128af28f636SEnrico Perla - Sun Microsystems buf_size = stage2->file_size;
11297c478bd9Sstevel@tonic-gate }
11307c478bd9Sstevel@tonic-gate
1131af28f636SEnrico Perla - Sun Microsystems stage2->buf_size = P2ROUNDUP(buf_size, SECTOR_SIZE);
1132af28f636SEnrico Perla - Sun Microsystems
1133af28f636SEnrico Perla - Sun Microsystems BOOT_DEBUG("stage2 buffer size = %d (%d sectors)\n", stage2->buf_size,
1134af28f636SEnrico Perla - Sun Microsystems stage2->buf_size / SECTOR_SIZE);
1135af28f636SEnrico Perla - Sun Microsystems
1136af28f636SEnrico Perla - Sun Microsystems stage2->buf = malloc(stage2->buf_size);
1137af28f636SEnrico Perla - Sun Microsystems if (stage2->buf == NULL) {
1138af28f636SEnrico Perla - Sun Microsystems perror(gettext("Memory allocation failed"));
1139af28f636SEnrico Perla - Sun Microsystems goto out_fd;
1140af28f636SEnrico Perla - Sun Microsystems }
1141af28f636SEnrico Perla - Sun Microsystems
1142af28f636SEnrico Perla - Sun Microsystems stage2->file = stage2->buf;
11437c478bd9Sstevel@tonic-gate
11447c478bd9Sstevel@tonic-gate /*
1145af28f636SEnrico Perla - Sun Microsystems * Extra information (e.g. the versioning structure) is placed at the
1146af28f636SEnrico Perla - Sun Microsystems * end of stage2, aligned on a 8-byte boundary.
11477c478bd9Sstevel@tonic-gate */
1148af28f636SEnrico Perla - Sun Microsystems if (!(is_bootpar(device->type)))
1149af28f636SEnrico Perla - Sun Microsystems stage2->extra = stage2->file + P2ROUNDUP(stage2->file_size, 8);
11507c478bd9Sstevel@tonic-gate
1151af28f636SEnrico Perla - Sun Microsystems if (lseek(fd, 0, SEEK_SET) == -1) {
1152af28f636SEnrico Perla - Sun Microsystems perror("lseek");
1153af28f636SEnrico Perla - Sun Microsystems goto out_alloc;
11547c478bd9Sstevel@tonic-gate }
11557c478bd9Sstevel@tonic-gate
1156af28f636SEnrico Perla - Sun Microsystems if (read(fd, stage2->file, stage2->file_size) < 0) {
1157af28f636SEnrico Perla - Sun Microsystems perror(gettext("unable to read stage2"));
1158af28f636SEnrico Perla - Sun Microsystems goto out_alloc;
11597c478bd9Sstevel@tonic-gate }
11607c478bd9Sstevel@tonic-gate
1161af28f636SEnrico Perla - Sun Microsystems (void) close(fd);
1162af28f636SEnrico Perla - Sun Microsystems return (BC_SUCCESS);
11637ce76caaSEnrico Perla - Sun Microsystems
1164af28f636SEnrico Perla - Sun Microsystems out_alloc:
1165af28f636SEnrico Perla - Sun Microsystems free(stage2->buf);
1166af28f636SEnrico Perla - Sun Microsystems stage2->buf = NULL;
1167af28f636SEnrico Perla - Sun Microsystems out_fd:
1168af28f636SEnrico Perla - Sun Microsystems (void) close(fd);
1169af28f636SEnrico Perla - Sun Microsystems out:
1170af28f636SEnrico Perla - Sun Microsystems return (BC_ERROR);
11717ce76caaSEnrico Perla - Sun Microsystems }
11727ce76caaSEnrico Perla - Sun Microsystems
11737ce76caaSEnrico Perla - Sun Microsystems static int
prepare_stage1(ig_data_t * install)1174af28f636SEnrico Perla - Sun Microsystems prepare_stage1(ig_data_t *install)
11757ce76caaSEnrico Perla - Sun Microsystems {
1176af28f636SEnrico Perla - Sun Microsystems ig_device_t *device = &install->device;
11777ce76caaSEnrico Perla - Sun Microsystems
1178af28f636SEnrico Perla - Sun Microsystems assert(install != NULL);
11797ce76caaSEnrico Perla - Sun Microsystems
1180af28f636SEnrico Perla - Sun Microsystems /* If PCFS add the BIOS Parameter Block. */
1181af28f636SEnrico Perla - Sun Microsystems if (is_bootpar(device->type)) {
1182af28f636SEnrico Perla - Sun Microsystems char bpb_sect[SECTOR_SIZE];
1183af28f636SEnrico Perla - Sun Microsystems
1184af28f636SEnrico Perla - Sun Microsystems if (pread(device->part_fd, bpb_sect, SECTOR_SIZE, 0)
1185af28f636SEnrico Perla - Sun Microsystems != SECTOR_SIZE) {
1186af28f636SEnrico Perla - Sun Microsystems (void) fprintf(stderr, READ_FAIL_BPB);
1187af28f636SEnrico Perla - Sun Microsystems return (BC_ERROR);
1188af28f636SEnrico Perla - Sun Microsystems }
1189af28f636SEnrico Perla - Sun Microsystems bcopy(bpb_sect + STAGE1_BPB_OFFSET,
1190af28f636SEnrico Perla - Sun Microsystems install->stage1_buf + STAGE1_BPB_OFFSET, STAGE1_BPB_SIZE);
11917ce76caaSEnrico Perla - Sun Microsystems }
11927ce76caaSEnrico Perla - Sun Microsystems
1193af28f636SEnrico Perla - Sun Microsystems /* copy MBR to stage1 in case of overwriting MBR sector. */
1194af28f636SEnrico Perla - Sun Microsystems bcopy(device->boot_sector + BOOTSZ, install->stage1_buf + BOOTSZ,
1195af28f636SEnrico Perla - Sun Microsystems SECTOR_SIZE - BOOTSZ);
1196af28f636SEnrico Perla - Sun Microsystems /* modify default stage1 file generated by GRUB. */
1197af28f636SEnrico Perla - Sun Microsystems *((unsigned char *)(install->stage1_buf + STAGE1_FORCE_LBA)) = 1;
1198af28f636SEnrico Perla - Sun Microsystems *((ulong_t *)(install->stage1_buf + STAGE1_STAGE2_SECTOR))
1199af28f636SEnrico Perla - Sun Microsystems = install->stage2.first_sector;
1200af28f636SEnrico Perla - Sun Microsystems *((ushort_t *)(install->stage1_buf + STAGE1_STAGE2_ADDRESS))
1201af28f636SEnrico Perla - Sun Microsystems = STAGE2_MEMADDR;
1202af28f636SEnrico Perla - Sun Microsystems *((ushort_t *)(install->stage1_buf + STAGE1_STAGE2_SEGMENT))
1203af28f636SEnrico Perla - Sun Microsystems = STAGE2_MEMADDR >> 4;
12047ce76caaSEnrico Perla - Sun Microsystems
1205af28f636SEnrico Perla - Sun Microsystems return (BC_SUCCESS);
12067ce76caaSEnrico Perla - Sun Microsystems }
12077ce76caaSEnrico Perla - Sun Microsystems
1208af28f636SEnrico Perla - Sun Microsystems /*
1209af28f636SEnrico Perla - Sun Microsystems * Grab stage1 from the specified device file descriptor.
1210af28f636SEnrico Perla - Sun Microsystems */
1211af28f636SEnrico Perla - Sun Microsystems static int
read_stage1_from_disk(int dev_fd,char * stage1_buf)1212af28f636SEnrico Perla - Sun Microsystems read_stage1_from_disk(int dev_fd, char *stage1_buf)
1213af28f636SEnrico Perla - Sun Microsystems {
1214af28f636SEnrico Perla - Sun Microsystems assert(stage1_buf != NULL);
12157ce76caaSEnrico Perla - Sun Microsystems
1216af28f636SEnrico Perla - Sun Microsystems if (read_in(dev_fd, stage1_buf, SECTOR_SIZE, 0) != BC_SUCCESS) {
1217af28f636SEnrico Perla - Sun Microsystems perror(gettext("Unable to read stage1 from disk"));
1218af28f636SEnrico Perla - Sun Microsystems return (BC_ERROR);
12197ce76caaSEnrico Perla - Sun Microsystems }
1220af28f636SEnrico Perla - Sun Microsystems return (BC_SUCCESS);
12217ce76caaSEnrico Perla - Sun Microsystems }
12227ce76caaSEnrico Perla - Sun Microsystems
12237ce76caaSEnrico Perla - Sun Microsystems static int
read_stage2_from_disk(int dev_fd,ig_stage2_t * stage2,int type)12241a902ef8SHans Rosenfeld read_stage2_from_disk(int dev_fd, ig_stage2_t *stage2, int type)
12257ce76caaSEnrico Perla - Sun Microsystems {
1226af28f636SEnrico Perla - Sun Microsystems uint32_t size;
1227af28f636SEnrico Perla - Sun Microsystems uint32_t buf_size;
1228af28f636SEnrico Perla - Sun Microsystems uint32_t mboot_off;
1229af28f636SEnrico Perla - Sun Microsystems multiboot_header_t *mboot;
12307ce76caaSEnrico Perla - Sun Microsystems
1231af28f636SEnrico Perla - Sun Microsystems assert(stage2 != NULL);
1232af28f636SEnrico Perla - Sun Microsystems assert(dev_fd != -1);
12337ce76caaSEnrico Perla - Sun Microsystems
1234af28f636SEnrico Perla - Sun Microsystems if (read_in(dev_fd, mboot_scan, sizeof (mboot_scan),
12351a902ef8SHans Rosenfeld STAGE2_BLKOFF(type) * SECTOR_SIZE) != BC_SUCCESS) {
1236af28f636SEnrico Perla - Sun Microsystems perror(gettext("Error reading stage2 sectors"));
1237af28f636SEnrico Perla - Sun Microsystems return (BC_ERROR);
1238af28f636SEnrico Perla - Sun Microsystems }
12397ce76caaSEnrico Perla - Sun Microsystems
1240af28f636SEnrico Perla - Sun Microsystems /* No multiboot means no chance of knowing stage2 size */
1241af28f636SEnrico Perla - Sun Microsystems if (find_multiboot(mboot_scan, sizeof (mboot_scan), &mboot_off)
1242af28f636SEnrico Perla - Sun Microsystems != BC_SUCCESS) {
1243af28f636SEnrico Perla - Sun Microsystems BOOT_DEBUG("Unable to find multiboot header\n");
1244af28f636SEnrico Perla - Sun Microsystems return (BC_NOEXTRA);
1245af28f636SEnrico Perla - Sun Microsystems }
1246af28f636SEnrico Perla - Sun Microsystems mboot = (multiboot_header_t *)(mboot_scan + mboot_off);
12477ce76caaSEnrico Perla - Sun Microsystems
1248af28f636SEnrico Perla - Sun Microsystems /*
1249af28f636SEnrico Perla - Sun Microsystems * Unfilled mboot values mean an older version of installgrub installed
1250af28f636SEnrico Perla - Sun Microsystems * the stage2. Again we have no chance of knowing stage2 size.
1251af28f636SEnrico Perla - Sun Microsystems */
1252af28f636SEnrico Perla - Sun Microsystems if (mboot->load_end_addr == 0 ||
1253af28f636SEnrico Perla - Sun Microsystems mboot->load_end_addr < mboot->load_addr)
1254af28f636SEnrico Perla - Sun Microsystems return (BC_NOEXTRA);
1255af28f636SEnrico Perla - Sun Microsystems
1256af28f636SEnrico Perla - Sun Microsystems /*
1257af28f636SEnrico Perla - Sun Microsystems * Currently, the amount of space reserved for extra information
1258af28f636SEnrico Perla - Sun Microsystems * is "fixed". We may have to scan for the terminating extra payload
1259af28f636SEnrico Perla - Sun Microsystems * in the future.
1260af28f636SEnrico Perla - Sun Microsystems */
1261af28f636SEnrico Perla - Sun Microsystems size = mboot->load_end_addr - mboot->load_addr;
1262af28f636SEnrico Perla - Sun Microsystems buf_size = P2ROUNDUP(size + SECTOR_SIZE, SECTOR_SIZE);
1263af28f636SEnrico Perla - Sun Microsystems
1264af28f636SEnrico Perla - Sun Microsystems stage2->buf = malloc(buf_size);
1265af28f636SEnrico Perla - Sun Microsystems if (stage2->buf == NULL) {
1266af28f636SEnrico Perla - Sun Microsystems perror(gettext("Memory allocation failed"));
1267af28f636SEnrico Perla - Sun Microsystems return (BC_ERROR);
1268af28f636SEnrico Perla - Sun Microsystems }
1269af28f636SEnrico Perla - Sun Microsystems stage2->buf_size = buf_size;
1270af28f636SEnrico Perla - Sun Microsystems
12711a902ef8SHans Rosenfeld if (read_in(dev_fd, stage2->buf, buf_size, STAGE2_BLKOFF(type) *
1272af28f636SEnrico Perla - Sun Microsystems SECTOR_SIZE) != BC_SUCCESS) {
1273af28f636SEnrico Perla - Sun Microsystems perror("read");
1274af28f636SEnrico Perla - Sun Microsystems free(stage2->buf);
1275af28f636SEnrico Perla - Sun Microsystems return (BC_ERROR);
1276af28f636SEnrico Perla - Sun Microsystems }
1277af28f636SEnrico Perla - Sun Microsystems
1278af28f636SEnrico Perla - Sun Microsystems /* Update pointers. */
1279af28f636SEnrico Perla - Sun Microsystems stage2->file = stage2->buf;
1280af28f636SEnrico Perla - Sun Microsystems stage2->file_size = size;
1281af28f636SEnrico Perla - Sun Microsystems stage2->mboot_off = mboot_off;
1282af28f636SEnrico Perla - Sun Microsystems stage2->mboot = (multiboot_header_t *)(stage2->buf + stage2->mboot_off);
1283af28f636SEnrico Perla - Sun Microsystems stage2->extra = stage2->buf + P2ROUNDUP(stage2->file_size, 8);
128414d44f22SHans Rosenfeld stage2->extra_size = stage2->buf_size - P2ROUNDUP(stage2->file_size, 8);
1285af28f636SEnrico Perla - Sun Microsystems
1286af28f636SEnrico Perla - Sun Microsystems return (BC_SUCCESS);
1287af28f636SEnrico Perla - Sun Microsystems }
1288af28f636SEnrico Perla - Sun Microsystems
1289af28f636SEnrico Perla - Sun Microsystems static boolean_t
is_update_necessary(ig_data_t * data,char * updt_str)1290af28f636SEnrico Perla - Sun Microsystems is_update_necessary(ig_data_t *data, char *updt_str)
1291af28f636SEnrico Perla - Sun Microsystems {
1292af28f636SEnrico Perla - Sun Microsystems bblk_einfo_t *einfo;
1293af28f636SEnrico Perla - Sun Microsystems bblk_hs_t stage2_hs;
1294af28f636SEnrico Perla - Sun Microsystems ig_stage2_t stage2_disk;
1295af28f636SEnrico Perla - Sun Microsystems ig_stage2_t *stage2_file = &data->stage2;
1296af28f636SEnrico Perla - Sun Microsystems ig_device_t *device = &data->device;
1297af28f636SEnrico Perla - Sun Microsystems int dev_fd = device->part_fd;
1298af28f636SEnrico Perla - Sun Microsystems
1299af28f636SEnrico Perla - Sun Microsystems assert(data != NULL);
1300af28f636SEnrico Perla - Sun Microsystems assert(device->part_fd != -1);
1301af28f636SEnrico Perla - Sun Microsystems
1302af28f636SEnrico Perla - Sun Microsystems bzero(&stage2_disk, sizeof (ig_stage2_t));
1303af28f636SEnrico Perla - Sun Microsystems
1304af28f636SEnrico Perla - Sun Microsystems /* Gather stage2 (if present) from the target device. */
13051a902ef8SHans Rosenfeld if (read_stage2_from_disk(dev_fd, &stage2_disk, device->type)
13061a902ef8SHans Rosenfeld != BC_SUCCESS) {
1307af28f636SEnrico Perla - Sun Microsystems BOOT_DEBUG("Unable to read stage2 from %s\n", device->path);
1308af28f636SEnrico Perla - Sun Microsystems BOOT_DEBUG("No multiboot wrapped stage2 on %s\n", device->path);
1309af28f636SEnrico Perla - Sun Microsystems return (B_TRUE);
1310af28f636SEnrico Perla - Sun Microsystems }
1311af28f636SEnrico Perla - Sun Microsystems
1312af28f636SEnrico Perla - Sun Microsystems /*
1313af28f636SEnrico Perla - Sun Microsystems * Look for the extended information structure in the extra payload
1314af28f636SEnrico Perla - Sun Microsystems * area.
1315af28f636SEnrico Perla - Sun Microsystems */
131614d44f22SHans Rosenfeld einfo = find_einfo(stage2_disk.extra, stage2_disk.extra_size);
1317af28f636SEnrico Perla - Sun Microsystems if (einfo == NULL) {
1318af28f636SEnrico Perla - Sun Microsystems BOOT_DEBUG("No extended information available\n");
1319af28f636SEnrico Perla - Sun Microsystems return (B_TRUE);
1320af28f636SEnrico Perla - Sun Microsystems }
1321af28f636SEnrico Perla - Sun Microsystems
1322af28f636SEnrico Perla - Sun Microsystems if (!do_version || updt_str == NULL) {
1323af28f636SEnrico Perla - Sun Microsystems (void) fprintf(stdout, "WARNING: target device %s has a "
1324af28f636SEnrico Perla - Sun Microsystems "versioned stage2 that is going to be overwritten by a non "
1325af28f636SEnrico Perla - Sun Microsystems "versioned one\n", device->path);
1326af28f636SEnrico Perla - Sun Microsystems return (B_TRUE);
1327af28f636SEnrico Perla - Sun Microsystems }
1328af28f636SEnrico Perla - Sun Microsystems
1329af28f636SEnrico Perla - Sun Microsystems if (force_update) {
1330af28f636SEnrico Perla - Sun Microsystems BOOT_DEBUG("Forcing update of %s bootblock\n", device->path);
1331af28f636SEnrico Perla - Sun Microsystems return (B_TRUE);
1332af28f636SEnrico Perla - Sun Microsystems }
1333af28f636SEnrico Perla - Sun Microsystems
1334af28f636SEnrico Perla - Sun Microsystems /* Compare the two extended information structures. */
1335af28f636SEnrico Perla - Sun Microsystems stage2_hs.src_buf = (unsigned char *)stage2_file->file;
1336af28f636SEnrico Perla - Sun Microsystems stage2_hs.src_size = stage2_file->file_size;
1337af28f636SEnrico Perla - Sun Microsystems
1338af28f636SEnrico Perla - Sun Microsystems return (einfo_should_update(einfo, &stage2_hs, updt_str));
13397ce76caaSEnrico Perla - Sun Microsystems }
13407ce76caaSEnrico Perla - Sun Microsystems
13417ce76caaSEnrico Perla - Sun Microsystems
13427c478bd9Sstevel@tonic-gate #define START_BLOCK(pos) (*(ulong_t *)(pos))
13437c478bd9Sstevel@tonic-gate #define NUM_BLOCK(pos) (*(ushort_t *)((pos) + 4))
13447c478bd9Sstevel@tonic-gate #define START_SEG(pos) (*(ushort_t *)((pos) + 6))
13457c478bd9Sstevel@tonic-gate
1346af28f636SEnrico Perla - Sun Microsystems static int
prepare_stage2(ig_data_t * install,char * updt_str)1347af28f636SEnrico Perla - Sun Microsystems prepare_stage2(ig_data_t *install, char *updt_str)
13487c478bd9Sstevel@tonic-gate {
1349af28f636SEnrico Perla - Sun Microsystems ig_device_t *device = &install->device;
1350af28f636SEnrico Perla - Sun Microsystems ig_stage2_t *stage2 = &install->stage2;
1351af28f636SEnrico Perla - Sun Microsystems uint32_t mboot_off = 0;
13527ce76caaSEnrico Perla - Sun Microsystems
1353af28f636SEnrico Perla - Sun Microsystems assert(install != NULL);
1354af28f636SEnrico Perla - Sun Microsystems assert(stage2->file != NULL);
1355af28f636SEnrico Perla - Sun Microsystems
1356af28f636SEnrico Perla - Sun Microsystems /* New stage2 files come with an embedded stage2. */
1357af28f636SEnrico Perla - Sun Microsystems if (find_multiboot(stage2->file, stage2->file_size, &mboot_off)
1358af28f636SEnrico Perla - Sun Microsystems != BC_SUCCESS) {
1359af28f636SEnrico Perla - Sun Microsystems BOOT_DEBUG("WARNING: no multiboot structure found in stage2, "
1360af28f636SEnrico Perla - Sun Microsystems "are you using an old GRUB stage2?\n");
1361af28f636SEnrico Perla - Sun Microsystems if (do_version == B_TRUE) {
1362af28f636SEnrico Perla - Sun Microsystems (void) fprintf(stderr, gettext("Versioning requested "
1363af28f636SEnrico Perla - Sun Microsystems "but stage2 does not support it.. skipping.\n"));
1364af28f636SEnrico Perla - Sun Microsystems do_version = B_FALSE;
1365af28f636SEnrico Perla - Sun Microsystems }
1366af28f636SEnrico Perla - Sun Microsystems } else {
1367af28f636SEnrico Perla - Sun Microsystems /* Keep track of where the multiboot header is. */
1368af28f636SEnrico Perla - Sun Microsystems stage2->mboot_off = mboot_off;
1369af28f636SEnrico Perla - Sun Microsystems stage2->mboot = (multiboot_header_t *)(stage2->file +
1370af28f636SEnrico Perla - Sun Microsystems mboot_off);
13717ce76caaSEnrico Perla - Sun Microsystems if (do_version) {
1372af28f636SEnrico Perla - Sun Microsystems /*
1373af28f636SEnrico Perla - Sun Microsystems * Adding stage2 information needs to happen before
1374af28f636SEnrico Perla - Sun Microsystems * we modify the copy of stage2 we have in memory, so
1375af28f636SEnrico Perla - Sun Microsystems * that the hashing reflects the one of the file.
1376af28f636SEnrico Perla - Sun Microsystems * An error here is not fatal.
1377af28f636SEnrico Perla - Sun Microsystems */
1378af28f636SEnrico Perla - Sun Microsystems add_stage2_einfo(stage2, updt_str);
1379af28f636SEnrico Perla - Sun Microsystems }
1380af28f636SEnrico Perla - Sun Microsystems /*
1381af28f636SEnrico Perla - Sun Microsystems * Fill multiboot information. We add them even without
1382af28f636SEnrico Perla - Sun Microsystems * versioning to support as much as possible mirroring.
1383af28f636SEnrico Perla - Sun Microsystems */
1384af28f636SEnrico Perla - Sun Microsystems prepare_fake_multiboot(stage2);
13857ce76caaSEnrico Perla - Sun Microsystems }
13867c478bd9Sstevel@tonic-gate
1387af28f636SEnrico Perla - Sun Microsystems if (is_bootpar(device->type)) {
1388af28f636SEnrico Perla - Sun Microsystems uint32_t blocklist[SECTOR_SIZE / sizeof (uint32_t)];
1389af28f636SEnrico Perla - Sun Microsystems uint32_t install_addr = STAGE2_MEMADDR + SECTOR_SIZE;
13907c478bd9Sstevel@tonic-gate int i = 0;
1391af28f636SEnrico Perla - Sun Microsystems uchar_t *pos;
13927c478bd9Sstevel@tonic-gate
1393af28f636SEnrico Perla - Sun Microsystems bzero(blocklist, sizeof (blocklist));
1394af28f636SEnrico Perla - Sun Microsystems if (read_stage2_blocklist(device->part_fd, blocklist) != 0) {
1395af28f636SEnrico Perla - Sun Microsystems (void) fprintf(stderr, gettext("Error reading pcfs "
1396af28f636SEnrico Perla - Sun Microsystems "stage2 blocklist\n"));
1397af28f636SEnrico Perla - Sun Microsystems return (BC_ERROR);
1398af28f636SEnrico Perla - Sun Microsystems }
13997c478bd9Sstevel@tonic-gate
1400af28f636SEnrico Perla - Sun Microsystems pos = (uchar_t *)stage2->file + STAGE2_BLOCKLIST;
1401af28f636SEnrico Perla - Sun Microsystems stage2->first_sector = device->start_sector + blocklist[0];
1402af28f636SEnrico Perla - Sun Microsystems stage2->pcfs_first_sectors[0] = blocklist[0];
1403af28f636SEnrico Perla - Sun Microsystems BOOT_DEBUG("stage2 first sector: %d\n", stage2->first_sector);
1404af28f636SEnrico Perla - Sun Microsystems
1405af28f636SEnrico Perla - Sun Microsystems
14067c478bd9Sstevel@tonic-gate if (blocklist[1] > 1) {
14077c478bd9Sstevel@tonic-gate blocklist[0]++;
14087c478bd9Sstevel@tonic-gate blocklist[1]--;
14097c478bd9Sstevel@tonic-gate } else {
14107c478bd9Sstevel@tonic-gate i += 2;
14117c478bd9Sstevel@tonic-gate }
14127c478bd9Sstevel@tonic-gate
1413af28f636SEnrico Perla - Sun Microsystems stage2->pcfs_first_sectors[1] = blocklist[i];
14147c478bd9Sstevel@tonic-gate
14157c478bd9Sstevel@tonic-gate while (blocklist[i]) {
14167c478bd9Sstevel@tonic-gate if (START_BLOCK(pos - 8) != 0 &&
14177c478bd9Sstevel@tonic-gate START_BLOCK(pos - 8) != blocklist[i + 2]) {
14187c478bd9Sstevel@tonic-gate (void) fprintf(stderr, PCFS_FRAGMENTED);
1419af28f636SEnrico Perla - Sun Microsystems return (BC_ERROR);
14207c478bd9Sstevel@tonic-gate }
1421af28f636SEnrico Perla - Sun Microsystems START_BLOCK(pos) = blocklist[i] + device->start_sector;
14227c478bd9Sstevel@tonic-gate START_SEG(pos) = (ushort_t)(install_addr >> 4);
14237c478bd9Sstevel@tonic-gate NUM_BLOCK(pos) = blocklist[i + 1];
14247c478bd9Sstevel@tonic-gate install_addr += blocklist[i + 1] * SECTOR_SIZE;
14257c478bd9Sstevel@tonic-gate pos -= 8;
14267c478bd9Sstevel@tonic-gate i += 2;
14277c478bd9Sstevel@tonic-gate }
14287c478bd9Sstevel@tonic-gate } else {
1429af28f636SEnrico Perla - Sun Microsystems /* Solaris VTOC */
14301a902ef8SHans Rosenfeld stage2->first_sector = device->start_sector +
14311a902ef8SHans Rosenfeld STAGE2_BLKOFF(device->type);
1432af28f636SEnrico Perla - Sun Microsystems BOOT_DEBUG("stage2 first sector: %d\n", stage2->first_sector);
14337c478bd9Sstevel@tonic-gate /*
14347c478bd9Sstevel@tonic-gate * In a solaris partition, stage2 is written to contiguous
14357c478bd9Sstevel@tonic-gate * blocks. So we update the starting block only.
14367c478bd9Sstevel@tonic-gate */
1437af28f636SEnrico Perla - Sun Microsystems *((ulong_t *)(stage2->file + STAGE2_BLOCKLIST)) =
1438af28f636SEnrico Perla - Sun Microsystems stage2->first_sector + 1;
14397c478bd9Sstevel@tonic-gate }
14407c478bd9Sstevel@tonic-gate
14417c478bd9Sstevel@tonic-gate /* force lba and set disk partition */
1442af28f636SEnrico Perla - Sun Microsystems *((unsigned char *) (stage2->file + STAGE2_FORCE_LBA)) = 1;
1443af28f636SEnrico Perla - Sun Microsystems *((long *)(stage2->file + STAGE2_INSTALLPART))
1444af28f636SEnrico Perla - Sun Microsystems = (device->partition << 16) | (device->slice << 8) | 0xff;
1445af28f636SEnrico Perla - Sun Microsystems
1446af28f636SEnrico Perla - Sun Microsystems return (BC_SUCCESS);
14477c478bd9Sstevel@tonic-gate }
14487c478bd9Sstevel@tonic-gate
1449af28f636SEnrico Perla - Sun Microsystems static int
find_x86_bootpar(struct mboot * mboot,int * part_num,uint32_t * start_sect)1450af28f636SEnrico Perla - Sun Microsystems find_x86_bootpar(struct mboot *mboot, int *part_num, uint32_t *start_sect)
1451af28f636SEnrico Perla - Sun Microsystems {
1452af28f636SEnrico Perla - Sun Microsystems int i;
14537c478bd9Sstevel@tonic-gate
1454af28f636SEnrico Perla - Sun Microsystems for (i = 0; i < FD_NUMPART; i++) {
1455af28f636SEnrico Perla - Sun Microsystems struct ipart *part;
14567c478bd9Sstevel@tonic-gate
1457af28f636SEnrico Perla - Sun Microsystems part = (struct ipart *)mboot->parts + i;
1458af28f636SEnrico Perla - Sun Microsystems if (part->systid == 0xbe) {
1459af28f636SEnrico Perla - Sun Microsystems if (start_sect)
1460af28f636SEnrico Perla - Sun Microsystems *start_sect = part->relsect;
1461af28f636SEnrico Perla - Sun Microsystems if (part_num)
1462af28f636SEnrico Perla - Sun Microsystems *part_num = i;
1463af28f636SEnrico Perla - Sun Microsystems /* solaris boot part */
1464af28f636SEnrico Perla - Sun Microsystems return (BC_SUCCESS);
14657c478bd9Sstevel@tonic-gate }
14667c478bd9Sstevel@tonic-gate }
1467af28f636SEnrico Perla - Sun Microsystems return (BC_ERROR);
14687c478bd9Sstevel@tonic-gate }
14697c478bd9Sstevel@tonic-gate
14707c478bd9Sstevel@tonic-gate static char *
get_raw_partition_path(ig_device_t * device)1471af28f636SEnrico Perla - Sun Microsystems get_raw_partition_path(ig_device_t *device)
14727c478bd9Sstevel@tonic-gate {
1473af28f636SEnrico Perla - Sun Microsystems char *raw;
14747c478bd9Sstevel@tonic-gate int len;
1475af28f636SEnrico Perla - Sun Microsystems
1476af28f636SEnrico Perla - Sun Microsystems if (is_bootpar(device->type)) {
1477af28f636SEnrico Perla - Sun Microsystems int part;
14787c478bd9Sstevel@tonic-gate struct mboot *mboot;
14797c478bd9Sstevel@tonic-gate
1480af28f636SEnrico Perla - Sun Microsystems mboot = (struct mboot *)device->boot_sector;
1481af28f636SEnrico Perla - Sun Microsystems if (find_x86_bootpar(mboot, &part, NULL) != BC_SUCCESS) {
1482af28f636SEnrico Perla - Sun Microsystems (void) fprintf(stderr, BOOTPAR_NOTFOUND,
1483af28f636SEnrico Perla - Sun Microsystems device->path_p0);
1484af28f636SEnrico Perla - Sun Microsystems return (NULL);
14857c478bd9Sstevel@tonic-gate }
14867c478bd9Sstevel@tonic-gate
1487af28f636SEnrico Perla - Sun Microsystems raw = strdup(device->path_p0);
1488af28f636SEnrico Perla - Sun Microsystems if (raw == NULL) {
1489af28f636SEnrico Perla - Sun Microsystems perror(gettext("Memory allocation failed"));
1490af28f636SEnrico Perla - Sun Microsystems return (NULL);
14917c478bd9Sstevel@tonic-gate }
1492af28f636SEnrico Perla - Sun Microsystems
1493af28f636SEnrico Perla - Sun Microsystems raw[strlen(raw) - 2] = '1' + part;
14947c478bd9Sstevel@tonic-gate return (raw);
14957c478bd9Sstevel@tonic-gate }
14967c478bd9Sstevel@tonic-gate
14977c478bd9Sstevel@tonic-gate /* For disk, remember slice and return whole fdisk partition */
1498af28f636SEnrico Perla - Sun Microsystems raw = strdup(device->path);
1499af28f636SEnrico Perla - Sun Microsystems if (raw == NULL) {
1500af28f636SEnrico Perla - Sun Microsystems perror(gettext("Memory allocation failed"));
1501af28f636SEnrico Perla - Sun Microsystems return (NULL);
1502af28f636SEnrico Perla - Sun Microsystems }
1503af28f636SEnrico Perla - Sun Microsystems
15047c478bd9Sstevel@tonic-gate len = strlen(raw);
15051a902ef8SHans Rosenfeld if (!is_efi(device->type) &&
15061a902ef8SHans Rosenfeld (raw[len - 2] != 's' || raw[len - 1] == '2')) {
15077c478bd9Sstevel@tonic-gate (void) fprintf(stderr, NOT_ROOT_SLICE);
1508af28f636SEnrico Perla - Sun Microsystems free(raw);
1509af28f636SEnrico Perla - Sun Microsystems return (NULL);
15107c478bd9Sstevel@tonic-gate }
1511af28f636SEnrico Perla - Sun Microsystems device->slice = atoi(&raw[len - 1]);
15127c478bd9Sstevel@tonic-gate
15131a902ef8SHans Rosenfeld if (!is_efi(device->type)) {
15147c478bd9Sstevel@tonic-gate raw[len - 2] = 's';
15157c478bd9Sstevel@tonic-gate raw[len - 1] = '2';
15161a902ef8SHans Rosenfeld }
1517af28f636SEnrico Perla - Sun Microsystems
15187c478bd9Sstevel@tonic-gate return (raw);
15197c478bd9Sstevel@tonic-gate }
15207c478bd9Sstevel@tonic-gate
1521af28f636SEnrico Perla - Sun Microsystems static int
get_raw_partition_fd(ig_device_t * device)1522af28f636SEnrico Perla - Sun Microsystems get_raw_partition_fd(ig_device_t *device)
1523af28f636SEnrico Perla - Sun Microsystems {
1524af28f636SEnrico Perla - Sun Microsystems struct stat stat = {0};
1525af28f636SEnrico Perla - Sun Microsystems char *raw;
1526af28f636SEnrico Perla - Sun Microsystems
1527af28f636SEnrico Perla - Sun Microsystems raw = get_raw_partition_path(device);
1528af28f636SEnrico Perla - Sun Microsystems if (raw == NULL)
1529af28f636SEnrico Perla - Sun Microsystems return (BC_ERROR);
1530af28f636SEnrico Perla - Sun Microsystems
1531af28f636SEnrico Perla - Sun Microsystems if (nowrite)
1532af28f636SEnrico Perla - Sun Microsystems device->part_fd = open(raw, O_RDONLY);
1533af28f636SEnrico Perla - Sun Microsystems else
1534af28f636SEnrico Perla - Sun Microsystems device->part_fd = open(raw, O_RDWR);
1535af28f636SEnrico Perla - Sun Microsystems
1536af28f636SEnrico Perla - Sun Microsystems if (device->part_fd < 0 || fstat(device->part_fd, &stat) != 0) {
1537af28f636SEnrico Perla - Sun Microsystems (void) fprintf(stderr, OPEN_FAIL, raw);
1538af28f636SEnrico Perla - Sun Microsystems free(raw);
1539af28f636SEnrico Perla - Sun Microsystems return (BC_ERROR);
1540af28f636SEnrico Perla - Sun Microsystems }
1541af28f636SEnrico Perla - Sun Microsystems
1542af28f636SEnrico Perla - Sun Microsystems if (S_ISCHR(stat.st_mode) == 0) {
1543af28f636SEnrico Perla - Sun Microsystems (void) fprintf(stderr, NOT_RAW_DEVICE, raw);
1544af28f636SEnrico Perla - Sun Microsystems (void) close(device->part_fd);
1545af28f636SEnrico Perla - Sun Microsystems device->part_fd = -1;
1546af28f636SEnrico Perla - Sun Microsystems free(raw);
1547af28f636SEnrico Perla - Sun Microsystems return (BC_ERROR);
1548af28f636SEnrico Perla - Sun Microsystems }
1549af28f636SEnrico Perla - Sun Microsystems
1550af28f636SEnrico Perla - Sun Microsystems free(raw);
1551af28f636SEnrico Perla - Sun Microsystems return (BC_SUCCESS);
1552af28f636SEnrico Perla - Sun Microsystems }
1553af28f636SEnrico Perla - Sun Microsystems
15547c478bd9Sstevel@tonic-gate #define TMP_MNTPT "/tmp/installgrub_pcfs"
1555af28f636SEnrico Perla - Sun Microsystems static int
copy_stage2_to_pcfs(ig_data_t * install)1556af28f636SEnrico Perla - Sun Microsystems copy_stage2_to_pcfs(ig_data_t *install)
15577c478bd9Sstevel@tonic-gate {
15587c478bd9Sstevel@tonic-gate FILE *mntfp;
1559af28f636SEnrico Perla - Sun Microsystems int pcfs_fp;
1560af28f636SEnrico Perla - Sun Microsystems int status = BC_ERROR;
15617c478bd9Sstevel@tonic-gate char buf[SECTOR_SIZE];
15627c478bd9Sstevel@tonic-gate char *cp;
15637c478bd9Sstevel@tonic-gate struct mnttab mp = {0}, mpref = {0};
1564af28f636SEnrico Perla - Sun Microsystems ig_device_t *device = &install->device;
1565af28f636SEnrico Perla - Sun Microsystems ig_stage2_t *stage2 = &install->stage2;
15667c478bd9Sstevel@tonic-gate
15677c478bd9Sstevel@tonic-gate /* convert raw to block device name by removing the first 'r' */
1568af28f636SEnrico Perla - Sun Microsystems (void) strncpy(buf, device->path, sizeof (buf));
15697c478bd9Sstevel@tonic-gate buf[sizeof (buf) - 1] = 0;
15707c478bd9Sstevel@tonic-gate cp = strchr(buf, 'r');
15717c478bd9Sstevel@tonic-gate if (cp == NULL) {
1572af28f636SEnrico Perla - Sun Microsystems (void) fprintf(stderr, CONVERT_FAIL, device->path);
1573af28f636SEnrico Perla - Sun Microsystems return (BC_ERROR);
15747c478bd9Sstevel@tonic-gate }
15757c478bd9Sstevel@tonic-gate do {
15767c478bd9Sstevel@tonic-gate *cp = *(cp + 1);
15777c478bd9Sstevel@tonic-gate } while (*(++cp));
15787c478bd9Sstevel@tonic-gate
15797c478bd9Sstevel@tonic-gate /* get the mount point, if any */
15807c478bd9Sstevel@tonic-gate mntfp = fopen("/etc/mnttab", "r");
15817c478bd9Sstevel@tonic-gate if (mntfp == NULL) {
15827c478bd9Sstevel@tonic-gate (void) fprintf(stderr, OPEN_FAIL_FILE, "/etc/mnttab");
1583af28f636SEnrico Perla - Sun Microsystems return (BC_ERROR);
15847c478bd9Sstevel@tonic-gate }
15857c478bd9Sstevel@tonic-gate
15867c478bd9Sstevel@tonic-gate mpref.mnt_special = buf;
15877c478bd9Sstevel@tonic-gate if (getmntany(mntfp, &mp, &mpref) != 0) {
15887c478bd9Sstevel@tonic-gate char cmd[128];
15897c478bd9Sstevel@tonic-gate
15907c478bd9Sstevel@tonic-gate /* not mounted, try remount */
15917c478bd9Sstevel@tonic-gate (void) mkdir(TMP_MNTPT, S_IRWXU);
15927c478bd9Sstevel@tonic-gate (void) snprintf(cmd, sizeof (cmd), "mount -F pcfs %s %s",
15937c478bd9Sstevel@tonic-gate buf, TMP_MNTPT);
15947c478bd9Sstevel@tonic-gate (void) system(cmd);
15957c478bd9Sstevel@tonic-gate rewind(mntfp);
15967c478bd9Sstevel@tonic-gate bzero(&mp, sizeof (mp));
15977c478bd9Sstevel@tonic-gate if (getmntany(mntfp, &mp, &mpref) != 0) {
15987c478bd9Sstevel@tonic-gate (void) fprintf(stderr, MOUNT_FAIL, buf);
1599af28f636SEnrico Perla - Sun Microsystems return (BC_ERROR);
16007c478bd9Sstevel@tonic-gate }
16017c478bd9Sstevel@tonic-gate }
16027c478bd9Sstevel@tonic-gate
16037c478bd9Sstevel@tonic-gate (void) snprintf(buf, sizeof (buf),
16047c478bd9Sstevel@tonic-gate "%s/boot", mp.mnt_mountp);
16057c478bd9Sstevel@tonic-gate (void) mkdir(buf, S_IRWXU);
16067c478bd9Sstevel@tonic-gate (void) strcat(buf, "/grub");
16077c478bd9Sstevel@tonic-gate (void) mkdir(buf, S_IRWXU);
16087c478bd9Sstevel@tonic-gate
16097c478bd9Sstevel@tonic-gate (void) strcat(buf, "/stage2");
16107c478bd9Sstevel@tonic-gate pcfs_fp = open(buf, O_WRONLY | O_CREAT, S_IRWXU);
16117c478bd9Sstevel@tonic-gate if (pcfs_fp == -1) {
16127c478bd9Sstevel@tonic-gate (void) fprintf(stderr, OPEN_FAIL_FILE, buf);
16137c478bd9Sstevel@tonic-gate perror("open:");
1614af28f636SEnrico Perla - Sun Microsystems goto out;
16157c478bd9Sstevel@tonic-gate }
16167c478bd9Sstevel@tonic-gate
1617af28f636SEnrico Perla - Sun Microsystems /* write stage2 to the pcfs mounted filesystem. */
1618af28f636SEnrico Perla - Sun Microsystems if (write(pcfs_fp, stage2->file, stage2->file_size)
1619af28f636SEnrico Perla - Sun Microsystems != stage2->file_size) {
1620af28f636SEnrico Perla - Sun Microsystems perror(gettext("Error writing stage2"));
1621af28f636SEnrico Perla - Sun Microsystems goto out;
16227c478bd9Sstevel@tonic-gate }
1623af28f636SEnrico Perla - Sun Microsystems
1624af28f636SEnrico Perla - Sun Microsystems status = BC_SUCCESS;
1625af28f636SEnrico Perla - Sun Microsystems out_fd:
16267c478bd9Sstevel@tonic-gate (void) close(pcfs_fp);
1627af28f636SEnrico Perla - Sun Microsystems out:
16287c478bd9Sstevel@tonic-gate (void) umount(TMP_MNTPT);
1629af28f636SEnrico Perla - Sun Microsystems (void) rmdir(TMP_MNTPT);
1630af28f636SEnrico Perla - Sun Microsystems return (status);
16317c478bd9Sstevel@tonic-gate }
1632