installgrub.c (14d44f22) installgrub.c (1a902ef8)
1/*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE

--- 7 unchanged lines hidden (view full) ---

16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21/*
22 * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
23 * Copyright 2012 Milan Jurik. All rights reserved.
1/*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE

--- 7 unchanged lines hidden (view full) ---

16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21/*
22 * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
23 * Copyright 2012 Milan Jurik. All rights reserved.
24 * Copyright 2012 Nexenta Systems, Inc. All rights reserved.
24 * Copyright 2015 Nexenta Systems, Inc. All rights reserved.
25 */
26
27#include <stdio.h>
28#include <stdlib.h>
29#include <libgen.h>
30#include <malloc.h>
31#include <string.h>
32#include <fcntl.h>

--- 10 unchanged lines hidden (view full) ---

43#include <sys/mnttab.h>
44#include <sys/dktp/fdisk.h>
45#include <sys/dkio.h>
46#include <sys/vtoc.h>
47#include <sys/types.h>
48#include <sys/stat.h>
49#include <sys/multiboot.h>
50#include <sys/sysmacros.h>
25 */
26
27#include <stdio.h>
28#include <stdlib.h>
29#include <libgen.h>
30#include <malloc.h>
31#include <string.h>
32#include <fcntl.h>

--- 10 unchanged lines hidden (view full) ---

43#include <sys/mnttab.h>
44#include <sys/dktp/fdisk.h>
45#include <sys/dkio.h>
46#include <sys/vtoc.h>
47#include <sys/types.h>
48#include <sys/stat.h>
49#include <sys/multiboot.h>
50#include <sys/sysmacros.h>
51#include <sys/efi_partition.h>
51
52
53#include <libnvpair.h>
54#include <libfstyp.h>
55
52#include "message.h"
53#include "installgrub.h"
54#include "./../common/bblk_einfo.h"
55#include "./../common/boot_utils.h"
56#include "./../common/mboot_extra.h"
57
58#ifndef TEXT_DOMAIN
59#define TEXT_DOMAIN "SUNW_OST_OSCMD"

--- 42 unchanged lines hidden (view full) ---

102static int find_x86_bootpar(struct mboot *, int *, uint32_t *);
103static int copy_stage2_to_pcfs(ig_data_t *);
104static int write_stage2(ig_data_t *);
105static int write_stage1(ig_data_t *);
106static void usage(char *);
107static int read_stage1_from_file(char *, ig_data_t *);
108static int read_stage2_from_file(char *, ig_data_t *);
109static int read_stage1_from_disk(int, char *);
56#include "message.h"
57#include "installgrub.h"
58#include "./../common/bblk_einfo.h"
59#include "./../common/boot_utils.h"
60#include "./../common/mboot_extra.h"
61
62#ifndef TEXT_DOMAIN
63#define TEXT_DOMAIN "SUNW_OST_OSCMD"

--- 42 unchanged lines hidden (view full) ---

106static int find_x86_bootpar(struct mboot *, int *, uint32_t *);
107static int copy_stage2_to_pcfs(ig_data_t *);
108static int write_stage2(ig_data_t *);
109static int write_stage1(ig_data_t *);
110static void usage(char *);
111static int read_stage1_from_file(char *, ig_data_t *);
112static int read_stage2_from_file(char *, ig_data_t *);
113static int read_stage1_from_disk(int, char *);
110static int read_stage2_from_disk(int, ig_stage2_t *);
114static int read_stage2_from_disk(int, ig_stage2_t *, int);
111static int prepare_stage1(ig_data_t *);
112static int prepare_stage2(ig_data_t *, char *);
113static void prepare_fake_multiboot(ig_stage2_t *);
114static void add_stage2_einfo(ig_stage2_t *, char *updt_str);
115static boolean_t is_update_necessary(ig_data_t *, char *);
116
117extern int read_stage2_blocklist(int, unsigned int *);
118

--- 265 unchanged lines hidden (view full) ---

384 }
385
386 if (is_bootpar(device->type)) {
387 (void) fprintf(stderr, gettext("Versioning not supported on "
388 "PCFS\n"));
389 goto out_dev;
390 }
391
115static int prepare_stage1(ig_data_t *);
116static int prepare_stage2(ig_data_t *, char *);
117static void prepare_fake_multiboot(ig_stage2_t *);
118static void add_stage2_einfo(ig_stage2_t *, char *updt_str);
119static boolean_t is_update_necessary(ig_data_t *, char *);
120
121extern int read_stage2_blocklist(int, unsigned int *);
122

--- 265 unchanged lines hidden (view full) ---

388 }
389
390 if (is_bootpar(device->type)) {
391 (void) fprintf(stderr, gettext("Versioning not supported on "
392 "PCFS\n"));
393 goto out_dev;
394 }
395
392 ret = read_stage2_from_disk(device->part_fd, stage2);
396 ret = read_stage2_from_disk(device->part_fd, stage2, device->type);
393 if (ret == BC_ERROR) {
394 (void) fprintf(stderr, gettext("Error reading stage2 from "
395 "%s\n"), device_path);
396 goto out_dev;
397 }
398
399 if (ret == BC_NOEXTRA) {
400 (void) fprintf(stdout, gettext("No multiboot header found on "

--- 81 unchanged lines hidden (view full) ---

482 }
483
484 if (is_bootpar(curr_device->type) || is_bootpar(attach_device->type)) {
485 (void) fprintf(stderr, gettext("boot block mirroring is not "
486 "supported on PCFS\n"));
487 goto out_devs;
488 }
489
397 if (ret == BC_ERROR) {
398 (void) fprintf(stderr, gettext("Error reading stage2 from "
399 "%s\n"), device_path);
400 goto out_dev;
401 }
402
403 if (ret == BC_NOEXTRA) {
404 (void) fprintf(stdout, gettext("No multiboot header found on "

--- 81 unchanged lines hidden (view full) ---

486 }
487
488 if (is_bootpar(curr_device->type) || is_bootpar(attach_device->type)) {
489 (void) fprintf(stderr, gettext("boot block mirroring is not "
490 "supported on PCFS\n"));
491 goto out_devs;
492 }
493
490 ret = read_stage2_from_disk(curr_device->part_fd, stage2_curr);
494 ret = read_stage2_from_disk(curr_device->part_fd, stage2_curr,
495 curr_device->type);
491 if (ret == BC_ERROR) {
492 BOOT_DEBUG("Error reading first stage2 blocks from %s\n",
493 curr_device->path);
494 retval = BC_ERROR;
495 goto out_devs;
496 }
497
498 if (ret == BC_NOEXTRA) {

--- 119 unchanged lines hidden (view full) ---

618}
619
620/*
621 * open the device and fill the various members of ig_device_t.
622 */
623static int
624init_device(ig_device_t *device, char *path)
625{
496 if (ret == BC_ERROR) {
497 BOOT_DEBUG("Error reading first stage2 blocks from %s\n",
498 curr_device->path);
499 retval = BC_ERROR;
500 goto out_devs;
501 }
502
503 if (ret == BC_NOEXTRA) {

--- 119 unchanged lines hidden (view full) ---

623}
624
625/*
626 * open the device and fill the various members of ig_device_t.
627 */
628static int
629init_device(ig_device_t *device, char *path)
630{
631 struct dk_gpt *vtoc;
632 fstyp_handle_t fhdl;
633 const char *fident;
634
626 bzero(device, sizeof (*device));
627 device->part_fd = -1;
628 device->disk_fd = -1;
629 device->path_p0 = NULL;
630
631 device->path = strdup(path);
632 if (device->path == NULL) {
633 perror(gettext("Memory allocation failed"));

--- 16 unchanged lines hidden (view full) ---

650 /* read in the device boot sector. */
651 if (read(device->disk_fd, device->boot_sector, SECTOR_SIZE)
652 != SECTOR_SIZE) {
653 (void) fprintf(stderr, gettext("Error reading boot sector\n"));
654 perror("read");
655 return (BC_ERROR);
656 }
657
635 bzero(device, sizeof (*device));
636 device->part_fd = -1;
637 device->disk_fd = -1;
638 device->path_p0 = NULL;
639
640 device->path = strdup(path);
641 if (device->path == NULL) {
642 perror(gettext("Memory allocation failed"));

--- 16 unchanged lines hidden (view full) ---

659 /* read in the device boot sector. */
660 if (read(device->disk_fd, device->boot_sector, SECTOR_SIZE)
661 != SECTOR_SIZE) {
662 (void) fprintf(stderr, gettext("Error reading boot sector\n"));
663 perror("read");
664 return (BC_ERROR);
665 }
666
667 if (efi_alloc_and_read(device->disk_fd, &vtoc) > 0) {
668 device->type = IG_DEV_EFI;
669 efi_free(vtoc);
670 }
671
658 if (get_raw_partition_fd(device) != BC_SUCCESS)
659 return (BC_ERROR);
660
672 if (get_raw_partition_fd(device) != BC_SUCCESS)
673 return (BC_ERROR);
674
675 if (fstyp_init(device->part_fd, 0, NULL, &fhdl) != 0)
676 return (BC_ERROR);
677
678 if (fstyp_ident(fhdl, "zfs", &fident) != 0) {
679 fstyp_fini(fhdl);
680 (void) fprintf(stderr, gettext("Booting of EFI labeled disks "
681 "is only supported with ZFS\n"));
682 return (BC_ERROR);
683 }
684 fstyp_fini(fhdl);
685
661 if (get_start_sector(device) != BC_SUCCESS)
662 return (BC_ERROR);
663
664 return (BC_SUCCESS);
665}
666
667static void
668cleanup_device(ig_device_t *device)

--- 27 unchanged lines hidden (view full) ---

696 uint32_t secnum = 0, numsec = 0;
697 int i, pno, rval, log_part = 0;
698 struct mboot *mboot;
699 struct ipart *part;
700 ext_part_t *epp;
701 struct part_info dkpi;
702 struct extpart_info edkpi;
703
686 if (get_start_sector(device) != BC_SUCCESS)
687 return (BC_ERROR);
688
689 return (BC_SUCCESS);
690}
691
692static void
693cleanup_device(ig_device_t *device)

--- 27 unchanged lines hidden (view full) ---

721 uint32_t secnum = 0, numsec = 0;
722 int i, pno, rval, log_part = 0;
723 struct mboot *mboot;
724 struct ipart *part;
725 ext_part_t *epp;
726 struct part_info dkpi;
727 struct extpart_info edkpi;
728
729 if (is_efi(device->type)) {
730 struct dk_gpt *vtoc;
731
732 if (efi_alloc_and_read(device->disk_fd, &vtoc) <= 0)
733 return (BC_ERROR);
734
735 device->start_sector = vtoc->efi_parts[device->slice].p_start;
736 /* GPT doesn't use traditional slice letters */
737 device->slice = 0xff;
738 device->partition = 0;
739
740 efi_free(vtoc);
741 goto found_part;
742 }
743
704 mboot = (struct mboot *)device->boot_sector;
705
706 if (is_bootpar(device->type)) {
707 if (find_x86_bootpar(mboot, &pno, &secnum) != BC_SUCCESS) {
708 (void) fprintf(stderr, NOBOOTPAR);
709 return (BC_ERROR);
710 } else {
711 device->start_sector = secnum;

--- 242 unchanged lines hidden (view full) ---

954 return (BC_SUCCESS);
955 }
956
957 /*
958 * For disk, write stage2 starting at STAGE2_BLKOFF sector.
959 * Note that we use stage2->buf rather than stage2->file, because we
960 * may have extended information after the latter.
961 */
744 mboot = (struct mboot *)device->boot_sector;
745
746 if (is_bootpar(device->type)) {
747 if (find_x86_bootpar(mboot, &pno, &secnum) != BC_SUCCESS) {
748 (void) fprintf(stderr, NOBOOTPAR);
749 return (BC_ERROR);
750 } else {
751 device->start_sector = secnum;

--- 242 unchanged lines hidden (view full) ---

994 return (BC_SUCCESS);
995 }
996
997 /*
998 * For disk, write stage2 starting at STAGE2_BLKOFF sector.
999 * Note that we use stage2->buf rather than stage2->file, because we
1000 * may have extended information after the latter.
1001 */
962 offset = STAGE2_BLKOFF * SECTOR_SIZE;
1002 offset = STAGE2_BLKOFF(device->type) * SECTOR_SIZE;
1003
963 if (write_out(device->part_fd, stage2->buf, stage2->buf_size,
964 offset) != BC_SUCCESS) {
965 perror("write");
966 return (BC_ERROR);
967 }
968
969 /* Simulate the "old" installgrub output. */
970 (void) fprintf(stdout, WRITE_STAGE2_DISK, device->partition,
1004 if (write_out(device->part_fd, stage2->buf, stage2->buf_size,
1005 offset) != BC_SUCCESS) {
1006 perror("write");
1007 return (BC_ERROR);
1008 }
1009
1010 /* Simulate the "old" installgrub output. */
1011 (void) fprintf(stdout, WRITE_STAGE2_DISK, device->partition,
971 (stage2->buf_size / SECTOR_SIZE) + 1, STAGE2_BLKOFF,
1012 (stage2->buf_size / SECTOR_SIZE) + 1, STAGE2_BLKOFF(device->type),
972 stage2->first_sector);
973
974 return (BC_SUCCESS);
975}
976
977static int
978write_stage1(ig_data_t *install)
979{

--- 177 unchanged lines hidden (view full) ---

1157 if (read_in(dev_fd, stage1_buf, SECTOR_SIZE, 0) != BC_SUCCESS) {
1158 perror(gettext("Unable to read stage1 from disk"));
1159 return (BC_ERROR);
1160 }
1161 return (BC_SUCCESS);
1162}
1163
1164static int
1013 stage2->first_sector);
1014
1015 return (BC_SUCCESS);
1016}
1017
1018static int
1019write_stage1(ig_data_t *install)
1020{

--- 177 unchanged lines hidden (view full) ---

1198 if (read_in(dev_fd, stage1_buf, SECTOR_SIZE, 0) != BC_SUCCESS) {
1199 perror(gettext("Unable to read stage1 from disk"));
1200 return (BC_ERROR);
1201 }
1202 return (BC_SUCCESS);
1203}
1204
1205static int
1165read_stage2_from_disk(int dev_fd, ig_stage2_t *stage2)
1206read_stage2_from_disk(int dev_fd, ig_stage2_t *stage2, int type)
1166{
1167 uint32_t size;
1168 uint32_t buf_size;
1169 uint32_t mboot_off;
1170 multiboot_header_t *mboot;
1171
1172 assert(stage2 != NULL);
1173 assert(dev_fd != -1);
1174
1175 if (read_in(dev_fd, mboot_scan, sizeof (mboot_scan),
1207{
1208 uint32_t size;
1209 uint32_t buf_size;
1210 uint32_t mboot_off;
1211 multiboot_header_t *mboot;
1212
1213 assert(stage2 != NULL);
1214 assert(dev_fd != -1);
1215
1216 if (read_in(dev_fd, mboot_scan, sizeof (mboot_scan),
1176 STAGE2_BLKOFF * SECTOR_SIZE) != BC_SUCCESS) {
1217 STAGE2_BLKOFF(type) * SECTOR_SIZE) != BC_SUCCESS) {
1177 perror(gettext("Error reading stage2 sectors"));
1178 return (BC_ERROR);
1179 }
1180
1181 /* No multiboot means no chance of knowing stage2 size */
1182 if (find_multiboot(mboot_scan, sizeof (mboot_scan), &mboot_off)
1183 != BC_SUCCESS) {
1184 BOOT_DEBUG("Unable to find multiboot header\n");

--- 19 unchanged lines hidden (view full) ---

1204
1205 stage2->buf = malloc(buf_size);
1206 if (stage2->buf == NULL) {
1207 perror(gettext("Memory allocation failed"));
1208 return (BC_ERROR);
1209 }
1210 stage2->buf_size = buf_size;
1211
1218 perror(gettext("Error reading stage2 sectors"));
1219 return (BC_ERROR);
1220 }
1221
1222 /* No multiboot means no chance of knowing stage2 size */
1223 if (find_multiboot(mboot_scan, sizeof (mboot_scan), &mboot_off)
1224 != BC_SUCCESS) {
1225 BOOT_DEBUG("Unable to find multiboot header\n");

--- 19 unchanged lines hidden (view full) ---

1245
1246 stage2->buf = malloc(buf_size);
1247 if (stage2->buf == NULL) {
1248 perror(gettext("Memory allocation failed"));
1249 return (BC_ERROR);
1250 }
1251 stage2->buf_size = buf_size;
1252
1212 if (read_in(dev_fd, stage2->buf, buf_size, STAGE2_BLKOFF *
1253 if (read_in(dev_fd, stage2->buf, buf_size, STAGE2_BLKOFF(type) *
1213 SECTOR_SIZE) != BC_SUCCESS) {
1214 perror("read");
1215 free(stage2->buf);
1216 return (BC_ERROR);
1217 }
1218
1219 /* Update pointers. */
1220 stage2->file = stage2->buf;

--- 17 unchanged lines hidden (view full) ---

1238 int dev_fd = device->part_fd;
1239
1240 assert(data != NULL);
1241 assert(device->part_fd != -1);
1242
1243 bzero(&stage2_disk, sizeof (ig_stage2_t));
1244
1245 /* Gather stage2 (if present) from the target device. */
1254 SECTOR_SIZE) != BC_SUCCESS) {
1255 perror("read");
1256 free(stage2->buf);
1257 return (BC_ERROR);
1258 }
1259
1260 /* Update pointers. */
1261 stage2->file = stage2->buf;

--- 17 unchanged lines hidden (view full) ---

1279 int dev_fd = device->part_fd;
1280
1281 assert(data != NULL);
1282 assert(device->part_fd != -1);
1283
1284 bzero(&stage2_disk, sizeof (ig_stage2_t));
1285
1286 /* Gather stage2 (if present) from the target device. */
1246 if (read_stage2_from_disk(dev_fd, &stage2_disk) != BC_SUCCESS) {
1287 if (read_stage2_from_disk(dev_fd, &stage2_disk, device->type)
1288 != BC_SUCCESS) {
1247 BOOT_DEBUG("Unable to read stage2 from %s\n", device->path);
1248 BOOT_DEBUG("No multiboot wrapped stage2 on %s\n", device->path);
1249 return (B_TRUE);
1250 }
1251
1252 /*
1253 * Look for the extended information structure in the extra payload
1254 * area.

--- 107 unchanged lines hidden (view full) ---

1362 START_SEG(pos) = (ushort_t)(install_addr >> 4);
1363 NUM_BLOCK(pos) = blocklist[i + 1];
1364 install_addr += blocklist[i + 1] * SECTOR_SIZE;
1365 pos -= 8;
1366 i += 2;
1367 }
1368 } else {
1369 /* Solaris VTOC */
1289 BOOT_DEBUG("Unable to read stage2 from %s\n", device->path);
1290 BOOT_DEBUG("No multiboot wrapped stage2 on %s\n", device->path);
1291 return (B_TRUE);
1292 }
1293
1294 /*
1295 * Look for the extended information structure in the extra payload
1296 * area.

--- 107 unchanged lines hidden (view full) ---

1404 START_SEG(pos) = (ushort_t)(install_addr >> 4);
1405 NUM_BLOCK(pos) = blocklist[i + 1];
1406 install_addr += blocklist[i + 1] * SECTOR_SIZE;
1407 pos -= 8;
1408 i += 2;
1409 }
1410 } else {
1411 /* Solaris VTOC */
1370 stage2->first_sector = device->start_sector + STAGE2_BLKOFF;
1412 stage2->first_sector = device->start_sector +
1413 STAGE2_BLKOFF(device->type);
1371 BOOT_DEBUG("stage2 first sector: %d\n", stage2->first_sector);
1372 /*
1373 * In a solaris partition, stage2 is written to contiguous
1374 * blocks. So we update the starting block only.
1375 */
1376 *((ulong_t *)(stage2->file + STAGE2_BLOCKLIST)) =
1377 stage2->first_sector + 1;
1378 }

--- 57 unchanged lines hidden (view full) ---

1436 /* For disk, remember slice and return whole fdisk partition */
1437 raw = strdup(device->path);
1438 if (raw == NULL) {
1439 perror(gettext("Memory allocation failed"));
1440 return (NULL);
1441 }
1442
1443 len = strlen(raw);
1414 BOOT_DEBUG("stage2 first sector: %d\n", stage2->first_sector);
1415 /*
1416 * In a solaris partition, stage2 is written to contiguous
1417 * blocks. So we update the starting block only.
1418 */
1419 *((ulong_t *)(stage2->file + STAGE2_BLOCKLIST)) =
1420 stage2->first_sector + 1;
1421 }

--- 57 unchanged lines hidden (view full) ---

1479 /* For disk, remember slice and return whole fdisk partition */
1480 raw = strdup(device->path);
1481 if (raw == NULL) {
1482 perror(gettext("Memory allocation failed"));
1483 return (NULL);
1484 }
1485
1486 len = strlen(raw);
1444 if (raw[len - 2] != 's' || raw[len - 1] == '2') {
1487 if (!is_efi(device->type) &&
1488 (raw[len - 2] != 's' || raw[len - 1] == '2')) {
1445 (void) fprintf(stderr, NOT_ROOT_SLICE);
1446 free(raw);
1447 return (NULL);
1448 }
1449 device->slice = atoi(&raw[len - 1]);
1450
1489 (void) fprintf(stderr, NOT_ROOT_SLICE);
1490 free(raw);
1491 return (NULL);
1492 }
1493 device->slice = atoi(&raw[len - 1]);
1494
1451 raw[len - 2] = 's';
1452 raw[len - 1] = '2';
1495 if (!is_efi(device->type)) {
1496 raw[len - 2] = 's';
1497 raw[len - 1] = '2';
1498 }
1453
1454 return (raw);
1455}
1456
1457static int
1458get_raw_partition_fd(ig_device_t *device)
1459{
1460 struct stat stat = {0};

--- 107 unchanged lines hidden ---
1499
1500 return (raw);
1501}
1502
1503static int
1504get_raw_partition_fd(ig_device_t *device)
1505{
1506 struct stat stat = {0};

--- 107 unchanged lines hidden ---