summaryrefslogtreecommitdiff
path: root/usr/src
diff options
context:
space:
mode:
authorToomas Soome <tsoome@me.com>2017-02-12 22:54:26 +0200
committerRobert Mustacchi <rm@joyent.com>2017-02-23 00:20:27 +0000
commitec2c76eb1d5ecd7a4fccccefc1bc4aa7c1531606 (patch)
tree5676052bd06db9f9a8c0e0f5f6357f31723a0874 /usr/src
parent48bbca816818409505a6e214d0911fda44e622e3 (diff)
downloadillumos-joyent-ec2c76eb1d5ecd7a4fccccefc1bc4aa7c1531606.tar.gz
7854 installboot should set MBR to load partition boot block if it was installed
Reviewed by: Jason King <jason.brian.king@gmail.com> Reviewed by: Dan McDonald <danmcd@omniti.com> Approved by: Robert Mustacchi <rm@joyent.com>
Diffstat (limited to 'usr/src')
-rw-r--r--usr/src/cmd/boot/installboot/i386/installboot.c52
1 files changed, 42 insertions, 10 deletions
diff --git a/usr/src/cmd/boot/installboot/i386/installboot.c b/usr/src/cmd/boot/installboot/i386/installboot.c
index a822b46b71..9cc5e0582b 100644
--- a/usr/src/cmd/boot/installboot/i386/installboot.c
+++ b/usr/src/cmd/boot/installboot/i386/installboot.c
@@ -533,21 +533,42 @@ write_bootblock(ib_data_t *data)
return (BC_SUCCESS);
}
+/*
+ * Partition boot block or volume boot record (VBR). The VBR is
+ * stored on partition relative sector 0 and allows chainloading
+ * to read boot program from partition.
+ *
+ * As the VBR will use the first sector of the partition,
+ * this means, we need to be sure the space is not used.
+ * We do support three partitioning chemes:
+ * 1. GPT: zfs and ufs have reserved space for first 8KB, but
+ * only zfs does have space for boot2. The pcfs has support
+ * for VBR, but no space for boot2. So with GPT, to support
+ * ufs or pcfs boot, we must have separate dedicated boot
+ * partition and we will store VBR on it.
+ * 2. MBR: we have almost the same situation as with GPT, except that
+ * if the partitions start from cylinder 1, we will have space
+ * between MBR and cylinder 0. If so, we do not require separate
+ * boot partition.
+ * 3. MBR+VTOC: with this combination we store VBR in sector 0 of the
+ * solaris2 MBR partition. The slice 0 will start from cylinder 1,
+ * and we do have space for boot2, so we do not require separate
+ * boot partition.
+ */
static int
write_stage1(ib_data_t *data)
{
ib_device_t *device = &data->device;
+ uint64_t start = 0;
assert(data != NULL);
/*
- * Partition boot block or volume boot record.
- * This is essentially copy of MBR (1 sector) and we store it
- * to support multi boot setups.
- *
- * Not all combinations are supported; as pcfs does not leave
- * space, we will not write to pcfs target.
- * In addition, in VTOC setup, we will only write VBR to slice 2.
+ * We have separate partition for boot programs and the stage1
+ * location is not absolute sector 0.
+ * We will write VBR and trigger MBR to read 1 sector from VBR.
+ * This case does also cover MBR+VTOC case, as the solaris 2 partition
+ * name and the root file system slice names are different.
*/
if (device->stage.start != 0 &&
strcmp(device->target.path, device->stage.path)) {
@@ -564,12 +585,13 @@ write_stage1(ib_data_t *data)
"%s %d sector 0 (abs %d)\n"),
device->devtype == IG_DEV_MBR? "partition":"slice",
device->stage.id, device->stage.start);
+ start = device->stage.start;
}
/*
- * both ufs and zfs have initial 8k reserved for VTOC/boot
- * so its safe to use this area. however, only
- * write to target if we have MBR/GPT.
+ * We have either GPT or MBR (without VTOC) and if the root
+ * file system is not pcfs, we can store VBR. Also trigger
+ * MBR to read 1 sector from VBR.
*/
if (device->devtype != IG_DEV_VTOC &&
device->target.fstype != IG_FS_PCFS) {
@@ -585,9 +607,19 @@ write_stage1(ib_data_t *data)
"%s %d sector 0 (abs %d)\n"),
device->devtype == IG_DEV_MBR? "partition":"slice",
device->target.id, device->target.start);
+ start = device->target.start;
}
if (write_mbr) {
+ /*
+ * If we did write partition boot block, update MBR to
+ * read partition boot block, not boot2.
+ */
+ if (start != 0) {
+ *((uint16_t *)(data->stage1 + STAGE1_STAGE2_SIZE)) = 1;
+ *((uint64_t *)(data->stage1 + STAGE1_STAGE2_LBA)) =
+ start;
+ }
if (write_out(device->fd, data->stage1,
sizeof (data->stage1), 0) != BC_SUCCESS) {
(void) fprintf(stdout,