0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome/*
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome * CDDL HEADER START
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome *
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome * The contents of this file are subject to the terms of the
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome * Common Development and Distribution License (the "License").
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome * You may not use this file except in compliance with the License.
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome *
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome * or http://www.opensolaris.org/os/licensing.
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome * See the License for the specific language governing permissions
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome * and limitations under the License.
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome *
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome * When distributing Covered Code, include this CDDL HEADER in each
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome * If applicable, add the following below this CDDL HEADER, with the
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome * fields enclosed by brackets "[]" replaced with your own identifying
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome * information: Portions Copyright [yyyy] [name of copyright owner]
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome *
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome * CDDL HEADER END
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome */
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome/*
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome * Copyright 2012 Nexenta Systems, Inc. All rights reserved.
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome * Copyright 2016 Toomas Soome <tsoome@me.com>
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome */
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome#include <stdio.h>
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome#include <errno.h>
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome#include <unistd.h>
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome#include <fcntl.h>
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome#include <assert.h>
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome#include <locale.h>
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome#include <strings.h>
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome#include <libfdisk.h>
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome#include <sys/dktp/fdisk.h>
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome#include <sys/dkio.h>
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome#include <sys/vtoc.h>
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome#include <sys/multiboot.h>
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome#include <sys/types.h>
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome#include <sys/stat.h>
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome#include <sys/sysmacros.h>
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome#include <sys/efi_partition.h>
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome#include <libfstyp.h>
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome#include <uuid/uuid.h>
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome#include "installboot.h"
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome#include "../../common/bblk_einfo.h"
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome#include "../../common/boot_utils.h"
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome#include "../../common/mboot_extra.h"
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome#include "getresponse.h"
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome#ifndef TEXT_DOMAIN
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome#define TEXT_DOMAIN "SUNW_OST_OSCMD"
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome#endif
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome/*
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome * BIOS bootblock installation:
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome *
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome * 1. MBR is first sector of the disk. If the file system on target is
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome * ufs or zfs, the same MBR code is installed on first sector of the
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome * partition as well; this will allow to have real MBR sector to be
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome * replaced by some other boot loader and have illumos chainloaded.
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome *
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome * installboot will record the start LBA and size of stage2 code in MBR code.
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome * On boot, the MBR code will read the stage2 code and executes it.
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome *
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome * 2. Stage2 location depends on file system type;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome * In case of zfs, installboot will store stage2 to zfs bootblk area,
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome * which is 512k bytes from partition start and size is 3.5MB.
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome *
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome * In case of ufs, the stage2 location is 50 512B sectors from
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome * Solaris2 MBR partition start, within boot slice, boot slice size is
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome * one cylinder.
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome *
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome * In case of pcfs, the stage2 location is 50 512B sectors from beginning
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome * of the disk, filling the space between MBR and first partition.
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome * This location assumes no other bootloader and the space is one cylinder,
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome * as first partition is starting from cylinder 1.
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome *
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome * In case of GPT partitioning and if file system is not zfs, the boot
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome * support is only possible with dedicated boot partition. For GPT,
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome * the current implementation is using BOOT partition, which must exist.
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome * BOOT partition does only contain raw boot blocks, without any file system.
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome *
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome * Loader stage2 is created with embedded version, by using fake multiboot (MB)
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome * header within first 32k and EINFO block is at the end of the actual
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome * boot block. MB header load_addr is set to 0 and load_end_addr is set to
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome * actual block end, so the EINFO size is (file size - load_end_addr).
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome * installboot does also store the illumos boot partition LBA to MB space,
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome * starting from bss_end_addr structure member location; stage2 will
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome * detect the partition and file system based on this value.
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome *
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome * Stored location values in MBR/stage2 also mean the bootblocks must be
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome * reinstalled in case the partition content is relocated.
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome */
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soomestatic boolean_t write_mbr = B_FALSE;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soomestatic boolean_t force_mbr = B_FALSE;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soomestatic boolean_t force_update = B_FALSE;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soomestatic boolean_t do_getinfo = B_FALSE;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soomestatic boolean_t do_version = B_FALSE;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soomestatic boolean_t do_mirror_bblk = B_FALSE;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soomestatic boolean_t strip = B_FALSE;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soomestatic boolean_t verbose_dump = B_FALSE;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome/* Versioning string, if present. */
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soomestatic char *update_str;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome/*
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome * Temporary buffer to store the first 32K of data looking for a multiboot
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome * signature.
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome */
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soomechar mboot_scan[MBOOT_SCAN_SIZE];
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome/* Function prototypes. */
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soomestatic void check_options(char *);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soomestatic int get_start_sector(ib_device_t *);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soomestatic int read_stage1_from_file(char *, ib_data_t *data);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soomestatic int read_bootblock_from_file(char *, ib_data_t *data);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soomestatic int read_bootblock_from_disk(ib_device_t *device, ib_bootblock_t *,
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome char **);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soomestatic void add_bootblock_einfo(ib_bootblock_t *, char *);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soomestatic int prepare_stage1(ib_data_t *);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soomestatic int prepare_bootblock(ib_data_t *, char *);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soomestatic int write_stage1(ib_data_t *);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soomestatic int write_bootblock(ib_data_t *);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soomestatic int init_device(ib_device_t *, char *);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soomestatic void cleanup_device(ib_device_t *);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soomestatic int commit_to_disk(ib_data_t *, char *);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soomestatic int handle_install(char *, char **);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soomestatic int handle_getinfo(char *, char **);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soomestatic int handle_mirror(char *, char **);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soomestatic boolean_t is_update_necessary(ib_data_t *, char *);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soomestatic int propagate_bootblock(ib_data_t *, ib_data_t *, char *);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soomestatic void usage(char *);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soomestatic int
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soomeread_stage1_from_file(char *path, ib_data_t *dest)
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome{
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome int fd;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome assert(dest != NULL);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome /* read the stage1 file from filesystem */
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome fd = open(path, O_RDONLY);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome if (fd == -1 ||
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome read(fd, dest->stage1, SECTOR_SIZE) != SECTOR_SIZE) {
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome (void) fprintf(stderr, gettext("cannot read stage1 file %s\n"),
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome path);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome return (BC_ERROR);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome }
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome (void) close(fd);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome return (BC_SUCCESS);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome}
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soomestatic int
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soomeread_bootblock_from_file(char *file, ib_data_t *data)
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome{
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome ib_bootblock_t *bblock = &data->bootblock;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome struct stat sb;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome uint32_t buf_size;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome uint32_t mboot_off;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome int fd = -1;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome int retval = BC_ERROR;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome assert(data != NULL);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome assert(file != NULL);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome fd = open(file, O_RDONLY);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome if (fd == -1) {
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome BOOT_DEBUG("Error opening %s\n", file);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome perror("open");
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome goto out;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome }
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome if (fstat(fd, &sb) == -1) {
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome BOOT_DEBUG("Error getting information (stat) about %s", file);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome perror("stat");
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome goto outfd;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome }
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome /* loader bootblock has version built in */
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome buf_size = sb.st_size;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome bblock->buf_size = buf_size;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome BOOT_DEBUG("bootblock in-memory buffer size is %d\n",
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome bblock->buf_size);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome bblock->buf = malloc(buf_size);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome if (bblock->buf == NULL) {
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome perror(gettext("Memory allocation failure"));
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome goto outbuf;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome }
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome bblock->file = bblock->buf;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome if (read(fd, bblock->file, bblock->buf_size) != bblock->buf_size) {
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome BOOT_DEBUG("Read from %s failed\n", file);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome perror("read");
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome goto outfd;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome }
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome if (find_multiboot(bblock->file, MBOOT_SCAN_SIZE, &mboot_off)
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome != BC_SUCCESS) {
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome (void) fprintf(stderr,
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome gettext("Unable to find multiboot header\n"));
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome goto outfd;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome }
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome bblock->mboot = (multiboot_header_t *)(bblock->file + mboot_off);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome bblock->mboot_off = mboot_off;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome bblock->file_size =
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome bblock->mboot->load_end_addr - bblock->mboot->load_addr;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome BOOT_DEBUG("bootblock file size is %d\n", bblock->file_size);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome bblock->extra = bblock->buf + P2ROUNDUP(bblock->file_size, 8);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome bblock->extra_size = bblock->buf_size - P2ROUNDUP(bblock->file_size, 8);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome BOOT_DEBUG("mboot at %p offset %d, extra at %p size %d, buf=%p "
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome "(size=%d)\n", bblock->mboot, bblock->mboot_off, bblock->extra,
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome bblock->extra_size, bblock->buf, bblock->buf_size);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome (void) close(fd);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome return (BC_SUCCESS);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soomeoutbuf:
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome (void) free(bblock->buf);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome bblock->buf = NULL;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soomeoutfd:
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome (void) close(fd);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soomeout:
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome return (retval);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome}
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soomestatic int
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soomeread_bootblock_from_disk(ib_device_t *device, ib_bootblock_t *bblock,
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome char **path)
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome{
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome int dev_fd;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome uint32_t size, offset;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome uint32_t buf_size;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome uint32_t mboot_off;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome multiboot_header_t *mboot;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome assert(device != NULL);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome assert(bblock != NULL);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome if (device->target.fstype == IG_FS_ZFS) {
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome dev_fd = device->target.fd;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome offset = BBLK_ZFS_BLK_OFF * SECTOR_SIZE;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome *path = device->target.path;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome } else {
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome dev_fd = device->stage.fd;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome offset = device->stage.offset * SECTOR_SIZE;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome *path = device->stage.path;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome }
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome if (read_in(dev_fd, mboot_scan, sizeof (mboot_scan), offset)
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome != BC_SUCCESS) {
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome BOOT_DEBUG("Error reading bootblock area\n");
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome perror("read");
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome return (BC_ERROR);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome }
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome /* No multiboot means no chance of knowing bootblock size */
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome if (find_multiboot(mboot_scan, sizeof (mboot_scan), &mboot_off)
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome != BC_SUCCESS) {
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome BOOT_DEBUG("Unable to find multiboot header\n");
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome return (BC_NOEXTRA);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome }
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome mboot = (multiboot_header_t *)(mboot_scan + mboot_off);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome /*
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome * make sure mboot has sane values
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome */
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome if (mboot->load_end_addr == 0 ||
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome mboot->load_end_addr < mboot->load_addr)
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome return (BC_NOEXTRA);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome /*
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome * Currently, the amount of space reserved for extra information
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome * is "fixed". We may have to scan for the terminating extra payload
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome * in the future.
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome */
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome size = mboot->load_end_addr - mboot->load_addr;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome buf_size = P2ROUNDUP(size + SECTOR_SIZE, SECTOR_SIZE);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome bblock->file_size = size;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome bblock->buf = malloc(buf_size);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome if (bblock->buf == NULL) {
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome BOOT_DEBUG("Unable to allocate enough memory to read"
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome " the extra bootblock from the disk\n");
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome perror(gettext("Memory allocation failure"));
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome return (BC_ERROR);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome }
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome bblock->buf_size = buf_size;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome if (read_in(dev_fd, bblock->buf, buf_size, offset) != BC_SUCCESS) {
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome BOOT_DEBUG("Error reading the bootblock\n");
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome (void) free(bblock->buf);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome bblock->buf = NULL;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome return (BC_ERROR);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome }
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome /* Update pointers. */
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome bblock->file = bblock->buf;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome bblock->mboot_off = mboot_off;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome bblock->mboot = (multiboot_header_t *)(bblock->buf + bblock->mboot_off);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome bblock->extra = bblock->buf + P2ROUNDUP(bblock->file_size, 8);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome bblock->extra_size = bblock->buf_size - P2ROUNDUP(bblock->file_size, 8);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome BOOT_DEBUG("mboot at %p offset %d, extra at %p size %d, buf=%p "
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome "(size=%d)\n", bblock->mboot, bblock->mboot_off, bblock->extra,
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome bblock->extra_size, bblock->buf, bblock->buf_size);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome return (BC_SUCCESS);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome}
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soomestatic boolean_t
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soomeis_update_necessary(ib_data_t *data, char *updt_str)
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome{
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome bblk_einfo_t *einfo;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome bblk_einfo_t *einfo_file;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome bblk_hs_t bblock_hs;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome ib_bootblock_t bblock_disk;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome ib_bootblock_t *bblock_file = &data->bootblock;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome ib_device_t *device = &data->device;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome int ret;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome char *path;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome assert(data != NULL);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome bzero(&bblock_disk, sizeof (ib_bootblock_t));
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome ret = read_bootblock_from_disk(device, &bblock_disk, &path);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome if (ret != BC_SUCCESS) {
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome BOOT_DEBUG("Unable to read bootblock from %s\n", path);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome return (B_TRUE);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome }
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome einfo = find_einfo(bblock_disk.extra, bblock_disk.extra_size);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome if (einfo == NULL) {
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome BOOT_DEBUG("No extended information available on disk\n");
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome return (B_TRUE);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome }
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome einfo_file = find_einfo(bblock_file->extra, bblock_file->extra_size);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome if (einfo_file == NULL) {
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome /*
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome * loader bootblock is versioned. missing version means
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome * probably incompatible block. installboot can not install
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome * grub, for example.
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome */
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome (void) fprintf(stderr,
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome gettext("ERROR: non versioned bootblock in file\n"));
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome return (B_FALSE);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome } else {
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome if (updt_str == NULL) {
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome updt_str = einfo_get_string(einfo_file);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome do_version = B_TRUE;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome }
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome }
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome if (!do_version || updt_str == NULL) {
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome (void) fprintf(stderr,
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome gettext("WARNING: target device %s has a "
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome "versioned bootblock that is going to be overwritten by a "
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome "non versioned one\n"), device->path);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome return (B_TRUE);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome }
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome if (force_update) {
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome BOOT_DEBUG("Forcing update of %s bootblock\n", device->path);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome return (B_TRUE);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome }
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome BOOT_DEBUG("Ready to check installed version vs %s\n", updt_str);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome bblock_hs.src_buf = (unsigned char *)bblock_file->file;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome bblock_hs.src_size = bblock_file->file_size;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome return (einfo_should_update(einfo, &bblock_hs, updt_str));
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome}
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soomestatic void
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soomeadd_bootblock_einfo(ib_bootblock_t *bblock, char *updt_str)
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome{
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome bblk_hs_t hs;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome uint32_t avail_space;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome assert(bblock != NULL);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome if (updt_str == NULL) {
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome BOOT_DEBUG("WARNING: no update string passed to "
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome "add_bootblock_einfo()\n");
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome return;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome }
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome /* Fill bootblock hashing source information. */
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome hs.src_buf = (unsigned char *)bblock->file;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome hs.src_size = bblock->file_size;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome /* How much space for the extended information structure? */
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome avail_space = bblock->buf_size - P2ROUNDUP(bblock->file_size, 8);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome /* Place the extended information structure. */
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome add_einfo(bblock->extra, updt_str, &hs, avail_space);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome}
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome/*
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome * set up data for case stage1 is installed as MBR
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome * set up location and size of bootblock
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome * set disk guid to provide unique information for biosdev command
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome */
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soomestatic int
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soomeprepare_stage1(ib_data_t *data)
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome{
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome ib_device_t *device;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome assert(data != NULL);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome device = &data->device;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome /* copy BPB */
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome bcopy(device->mbr + STAGE1_BPB_OFFSET,
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome data->stage1 + STAGE1_BPB_OFFSET, STAGE1_BPB_SIZE);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome /* copy MBR, note STAGE1_SIG == BOOTSZ */
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome bcopy(device->mbr + STAGE1_SIG, data->stage1 + STAGE1_SIG,
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome SECTOR_SIZE - STAGE1_SIG);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome /* set stage2 size */
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome *((uint16_t *)(data->stage1 + STAGE1_STAGE2_SIZE)) =
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome (uint16_t)(data->bootblock.buf_size / SECTOR_SIZE);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome /*
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome * set stage2 location.
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome * for zfs always use zfs embedding, for ufs/pcfs use partition_start
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome * as base for stage2 location, for ufs/pcfs in MBR partition, use
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome * free space after MBR record.
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome */
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome if (device->target.fstype == IG_FS_ZFS)
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome *((uint64_t *)(data->stage1 + STAGE1_STAGE2_LBA)) =
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome device->target.start + device->target.offset;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome else {
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome *((uint64_t *)(data->stage1 + STAGE1_STAGE2_LBA)) =
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome device->stage.start + device->stage.offset;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome }
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome /*
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome * set disk uuid. we only need reasonable amount of uniqueness
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome * to allow biosdev to identify disk based on mbr differences.
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome */
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome uuid_generate(data->stage1 + STAGE1_STAGE2_UUID);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome return (BC_SUCCESS);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome}
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soomestatic int
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soomeprepare_bootblock(ib_data_t *data, char *updt_str)
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome{
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome ib_bootblock_t *bblock;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome ib_device_t *device;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome uint64_t *ptr;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome assert(data != NULL);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome bblock = &data->bootblock;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome device = &data->device;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome ptr = (uint64_t *)(&bblock->mboot->bss_end_addr);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome *ptr = device->target.start;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome /*
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome * the loader bootblock has built in version, if custom
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome * version was provided, update it.
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome */
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome if (do_version)
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome add_bootblock_einfo(bblock, updt_str);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome return (BC_SUCCESS);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome}
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soomestatic int
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soomewrite_bootblock(ib_data_t *data)
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome{
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome ib_device_t *device = &data->device;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome ib_bootblock_t *bblock = &data->bootblock;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome uint64_t abs;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome int dev_fd, ret;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome off_t offset;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome char *path;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome assert(data != NULL);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome /*
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome * ZFS bootblock area is 3.5MB, make sure we can fit.
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome * buf_size is size of bootblk+EINFO.
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome */
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome if (bblock->buf_size > BBLK_ZFS_BLK_SIZE) {
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome (void) fprintf(stderr, gettext("bootblock is too large\n"));
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome return (BC_ERROR);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome }
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome if (device->target.fstype == IG_FS_ZFS) {
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome dev_fd = device->target.fd;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome abs = device->target.start + device->target.offset;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome offset = BBLK_ZFS_BLK_OFF * SECTOR_SIZE;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome path = device->target.path;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome } else {
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome dev_fd = device->stage.fd;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome abs = device->stage.start + device->stage.offset;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome offset = device->stage.offset * SECTOR_SIZE;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome path = device->stage.path;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome if (bblock->buf_size >
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome (device->stage.size - device->stage.offset) * SECTOR_SIZE) {
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome (void) fprintf(stderr, gettext("Device %s is "
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome "too small to fit the stage2\n"), path);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome return (BC_ERROR);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome }
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome }
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome ret = write_out(dev_fd, bblock->buf, bblock->buf_size, offset);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome if (ret != BC_SUCCESS) {
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome BOOT_DEBUG("Error writing the ZFS bootblock "
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome "to %s at offset %d\n", path, offset);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome return (BC_ERROR);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome }
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome (void) fprintf(stdout, gettext("bootblock written for %s,"
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome " %d sectors starting at %d (abs %lld)\n"), path,
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome (bblock->buf_size / SECTOR_SIZE) + 1, offset / SECTOR_SIZE, abs);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome return (BC_SUCCESS);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome}
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soomestatic int
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soomewrite_stage1(ib_data_t *data)
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome{
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome ib_device_t *device = &data->device;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome assert(data != NULL);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome /*
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome * Partition boot block or volume boot record.
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome * This is essentially copy of MBR (1 sector) and we store it
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome * to support multi boot setups.
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome *
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome * Not all combinations are supported; as pcfs does not leave
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome * space, we will not write to pcfs target.
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome * In addition, in VTOC setup, we will only write VBR to slice 2.
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome */
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome if (device->stage.start != 0 &&
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome strcmp(device->target.path, device->stage.path)) {
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome /* we got separate stage area, use it */
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome if (write_out(device->stage.fd, data->stage1,
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome sizeof (data->stage1), 0) != BC_SUCCESS) {
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome (void) fprintf(stdout, gettext("cannot write "
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome "partition boot sector\n"));
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome perror("write");
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome return (BC_ERROR);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome }
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome (void) fprintf(stdout, gettext("stage1 written to "
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome "%s %d sector 0 (abs %d)\n"),
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome device->devtype == IG_DEV_MBR? "partition":"slice",
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome device->stage.id, device->stage.start);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome }
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome /*
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome * both ufs and zfs have initial 8k reserved for VTOC/boot
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome * so its safe to use this area. however, only
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome * write to target if we have MBR/GPT.
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome */
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome if (device->devtype != IG_DEV_VTOC &&
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome device->target.fstype != IG_FS_PCFS) {
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome if (write_out(device->target.fd, data->stage1,
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome sizeof (data->stage1), 0) != BC_SUCCESS) {
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome (void) fprintf(stdout, gettext("cannot write "
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome "partition boot sector\n"));
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome perror("write");
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome return (BC_ERROR);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome }
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome (void) fprintf(stdout, gettext("stage1 written to "
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome "%s %d sector 0 (abs %d)\n"),
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome device->devtype == IG_DEV_MBR? "partition":"slice",
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome device->target.id, device->target.start);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome }
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome if (write_mbr) {
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome if (write_out(device->fd, data->stage1,
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome sizeof (data->stage1), 0) != BC_SUCCESS) {
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome (void) fprintf(stdout,
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome gettext("cannot write master boot sector\n"));
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome perror("write");
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome return (BC_ERROR);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome }
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome (void) fprintf(stdout,
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome gettext("stage1 written to master boot sector\n"));
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome }
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome return (BC_SUCCESS);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome}
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome/*
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome * find partition/slice start sector. will be recorded in stage2 and used
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome * by stage2 to identify partition with boot file system.
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome */
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soomestatic int
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soomeget_start_sector(ib_device_t *device)
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome{
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome uint32_t secnum = 0, numsec = 0;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome int i, pno, rval, log_part = 0;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome struct mboot *mboot;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome struct ipart *part = NULL;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome ext_part_t *epp;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome struct part_info dkpi;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome struct extpart_info edkpi;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome if (device->devtype == IG_DEV_EFI) {
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome struct dk_gpt *vtoc;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome if (efi_alloc_and_read(device->fd, &vtoc) < 0)
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome return (BC_ERROR);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome if (device->stage.start == 0) {
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome /* zero size means the fstype must be zfs */
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome assert(device->target.fstype == IG_FS_ZFS);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome device->stage.start =
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome vtoc->efi_parts[device->stage.id].p_start;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome device->stage.size =
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome vtoc->efi_parts[device->stage.id].p_size;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome device->stage.offset = BBLK_ZFS_BLK_OFF;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome device->target.offset = BBLK_ZFS_BLK_OFF;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome }
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome device->target.start =
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome vtoc->efi_parts[device->target.id].p_start;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome device->target.size =
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome vtoc->efi_parts[device->target.id].p_size;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome /* with pcfs we always write MBR */
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome if (device->target.fstype == IG_FS_PCFS) {
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome force_mbr = 1;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome write_mbr = 1;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome }
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome efi_free(vtoc);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome goto found_part;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome }
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome mboot = (struct mboot *)device->mbr;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome /* For MBR we have device->stage filled already. */
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome if (device->devtype == IG_DEV_MBR) {
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome /* MBR partition starts from 0 */
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome pno = device->target.id - 1;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome part = (struct ipart *)mboot->parts + pno;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome if (part->relsect == 0) {
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome (void) fprintf(stderr, gettext("Partition %d of the "
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome "disk has an incorrect offset\n"),
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome device->target.id);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome return (BC_ERROR);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome }
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome device->target.start = part->relsect;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome device->target.size = part->numsect;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome /* with pcfs we always write MBR */
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome if (device->target.fstype == IG_FS_PCFS) {
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome force_mbr = 1;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome write_mbr = 1;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome }
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome if (device->target.fstype == IG_FS_ZFS)
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome device->target.offset = BBLK_ZFS_BLK_OFF;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome goto found_part;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome }
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome /*
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome * Search for Solaris fdisk partition
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome * Get the solaris partition information from the device
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome * and compare the offset of S2 with offset of solaris partition
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome * from fdisk partition table.
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome */
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome if (ioctl(device->target.fd, DKIOCEXTPARTINFO, &edkpi) < 0) {
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome if (ioctl(device->target.fd, DKIOCPARTINFO, &dkpi) < 0) {
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome (void) fprintf(stderr, gettext("cannot get the "
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome "slice information of the disk\n"));
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome return (BC_ERROR);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome } else {
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome edkpi.p_start = dkpi.p_start;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome edkpi.p_length = dkpi.p_length;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome }
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome }
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome device->target.start = edkpi.p_start;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome device->target.size = edkpi.p_length;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome if (device->target.fstype == IG_FS_ZFS)
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome device->target.offset = BBLK_ZFS_BLK_OFF;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome for (i = 0; i < FD_NUMPART; i++) {
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome part = (struct ipart *)mboot->parts + i;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome if (part->relsect == 0) {
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome (void) fprintf(stderr, gettext("Partition %d of the "
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome "disk has an incorrect offset\n"), i+1);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome return (BC_ERROR);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome }
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome if (edkpi.p_start >= part->relsect &&
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome edkpi.p_start < (part->relsect + part->numsect)) {
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome /* Found the partition */
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome break;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome }
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome }
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome if (i == FD_NUMPART) {
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome /* No solaris fdisk partitions (primary or logical) */
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome (void) fprintf(stderr, gettext("Solaris partition not found. "
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome "Aborting operation.\n"));
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome return (BC_ERROR);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome }
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome /*
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome * We have found a Solaris fdisk partition (primary or extended)
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome * Handle the simple case first: Solaris in a primary partition
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome */
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome if (!fdisk_is_dos_extended(part->systid)) {
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome device->stage.start = part->relsect;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome device->stage.size = part->numsect;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome if (device->target.fstype == IG_FS_ZFS)
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome device->stage.offset = BBLK_ZFS_BLK_OFF;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome else
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome device->stage.offset = BBLK_BLKLIST_OFF;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome device->stage.id = i + 1;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome goto found_part;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome }
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome /*
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome * Solaris in a logical partition. Find that partition in the
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome * extended part.
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome */
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome if ((rval = libfdisk_init(&epp, device->path, NULL, FDISK_READ_DISK))
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome != FDISK_SUCCESS) {
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome switch (rval) {
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome /*
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome * The first 3 cases are not an error per-se, just that
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome * there is no Solaris logical partition
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome */
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome case FDISK_EBADLOGDRIVE:
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome case FDISK_ENOLOGDRIVE:
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome case FDISK_EBADMAGIC:
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome (void) fprintf(stderr, gettext("Solaris "
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome "partition not found. "
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome "Aborting operation.\n"));
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome return (BC_ERROR);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome case FDISK_ENOVGEOM:
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome (void) fprintf(stderr, gettext("Could not get "
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome "virtual geometry\n"));
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome return (BC_ERROR);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome case FDISK_ENOPGEOM:
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome (void) fprintf(stderr, gettext("Could not get "
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome "physical geometry\n"));
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome return (BC_ERROR);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome case FDISK_ENOLGEOM:
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome (void) fprintf(stderr, gettext("Could not get "
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome "label geometry\n"));
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome return (BC_ERROR);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome default:
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome (void) fprintf(stderr, gettext("Failed to "
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome "initialize libfdisk.\n"));
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome return (BC_ERROR);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome }
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome }
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome rval = fdisk_get_solaris_part(epp, &pno, &secnum, &numsec);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome libfdisk_fini(&epp);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome if (rval != FDISK_SUCCESS) {
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome /* No solaris logical partition */
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome (void) fprintf(stderr, gettext("Solaris partition not found. "
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome "Aborting operation.\n"));
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome return (BC_ERROR);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome }
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome device->stage.start = secnum;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome device->stage.size = numsec;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome device->stage.id = pno;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome log_part = 1;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soomefound_part:
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome /* get confirmation for -m */
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome if (write_mbr && !force_mbr) {
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome (void) fprintf(stdout, gettext("Updating master boot sector "
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome "destroys existing boot managers (if any).\n"
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome "continue (y/n)? "));
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome if (!yes()) {
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome write_mbr = 0;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome (void) fprintf(stdout, gettext("master boot sector "
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome "not updated\n"));
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome return (BC_ERROR);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome }
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome }
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome /*
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome * warn, if illumos in primary partition and loader not in MBR and
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome * partition is not active
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome */
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome if (device->devtype != IG_DEV_EFI) {
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome if (!log_part && part->bootid != 128 && !write_mbr) {
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome (void) fprintf(stdout, gettext("Solaris fdisk "
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome "partition is inactive.\n"), device->stage.id);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome }
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome }
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome return (BC_SUCCESS);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome}
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soomestatic int
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soomeopen_device(char *path)
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome{
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome struct stat statbuf = {0};
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome int fd = -1;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome if (nowrite)
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome fd = open(path, O_RDONLY);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome else
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome fd = open(path, O_RDWR);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome if (fd == -1) {
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome BOOT_DEBUG("Unable to open %s\n", path);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome perror("open");
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome return (-1);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome }
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome if (fstat(fd, &statbuf) != 0) {
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome BOOT_DEBUG("Unable to stat %s\n", path);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome perror("stat");
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome (void) close(fd);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome return (-1);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome }
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome if (S_ISCHR(statbuf.st_mode) == 0) {
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome (void) fprintf(stderr, gettext("%s: Not a character device\n"),
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome path);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome (void) close(fd);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome return (-1);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome }
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome return (fd);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome}
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soomestatic int
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soomeget_boot_partition(ib_device_t *device, struct mboot *mbr)
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome{
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome struct ipart *part;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome char *path, *ptr;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome int i;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome part = (struct ipart *)mbr->parts;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome for (i = 0; i < FD_NUMPART; i++) {
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome if (part[i].systid == X86BOOT)
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome break;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome }
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome /* no X86BOOT, try to use space between MBR and first partition */
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome if (i == FD_NUMPART) {
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome device->stage.path = strdup(device->path);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome if (device->stage.path == NULL) {
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome perror(gettext("Memory allocation failure"));
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome return (BC_ERROR);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome }
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome device->stage.fd = dup(device->fd);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome device->stage.id = 0;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome device->stage.devtype = IG_DEV_MBR;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome device->stage.fstype = IG_FS_NONE;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome device->stage.start = 0;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome device->stage.size = part[0].relsect;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome device->stage.offset = BBLK_BLKLIST_OFF;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome return (BC_SUCCESS);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome }
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome if ((path = strdup(device->path)) == NULL) {
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome perror(gettext("Memory allocation failure"));
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome return (BC_ERROR);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome }
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome ptr = strrchr(path, 'p');
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome ptr++;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome *ptr = '\0';
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome (void) asprintf(&ptr, "%s%d", path, i+1); /* partitions are p1..p4 */
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome free(path);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome if (ptr == NULL) {
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome perror(gettext("Memory allocation failure"));
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome return (BC_ERROR);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome }
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome device->stage.path = ptr;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome device->stage.fd = open_device(ptr);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome device->stage.id = i + 1;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome device->stage.devtype = IG_DEV_MBR;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome device->stage.fstype = IG_FS_NONE;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome device->stage.start = part[i].relsect;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome device->stage.size = part[i].numsect;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome device->stage.offset = 1; /* leave sector 0 for VBR */
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome return (BC_SUCCESS);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome}
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soomestatic int
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soomeget_boot_slice(ib_device_t *device, struct dk_gpt *vtoc)
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome{
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome uint_t i;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome char *path, *ptr;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome for (i = 0; i < vtoc->efi_nparts; i++) {
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome if (vtoc->efi_parts[i].p_tag == V_BOOT) {
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome if ((path = strdup(device->target.path)) == NULL) {
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome perror(gettext("Memory allocation failure"));
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome return (BC_ERROR);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome }
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome ptr = strrchr(path, 's');
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome ptr++;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome *ptr = '\0';
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome (void) asprintf(&ptr, "%s%d", path, i);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome free(path);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome if (ptr == NULL) {
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome perror(gettext("Memory allocation failure"));
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome return (BC_ERROR);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome }
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome device->stage.path = ptr;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome device->stage.fd = open_device(ptr);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome device->stage.id = i;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome device->stage.devtype = IG_DEV_EFI;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome device->stage.fstype = IG_FS_NONE;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome device->stage.start = vtoc->efi_parts[i].p_start;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome device->stage.size = vtoc->efi_parts[i].p_size;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome device->stage.offset = 1; /* leave sector 0 for VBR */
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome return (BC_SUCCESS);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome }
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome }
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome return (BC_SUCCESS);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome}
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soomestatic int
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soomeinit_device(ib_device_t *device, char *path)
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome{
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome struct dk_gpt *vtoc;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome fstyp_handle_t fhdl;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome const char *fident;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome char *p;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome int pathlen = strlen(path);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome int ret;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome bzero(device, sizeof (*device));
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome device->fd = -1; /* whole disk fd */
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome device->stage.fd = -1; /* bootblock partition fd */
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome device->target.fd = -1; /* target fs partition fd */
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome /* basic check, whole disk is not allowed */
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome if ((p = strrchr(path, '/')) == NULL)
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome p = path;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome if ((strrchr(p, 'p') == NULL && strrchr(p, 's') == NULL) ||
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome (path[pathlen-2] == 'p' && path[pathlen-1] == '0')) {
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome (void) fprintf(stderr, gettext("installing loader to "
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome "whole disk device is not supported\n"));
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome }
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome device->target.path = strdup(path);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome if (device->target.path == NULL) {
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome perror(gettext("Memory allocation failure"));
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome return (BC_ERROR);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome }
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome device->path = strdup(path);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome if (device->path == NULL) {
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome perror(gettext("Memory allocation failure"));
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome return (BC_ERROR);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome }
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome /* change device name to p0 */
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome device->path[pathlen - 2] = 'p';
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome device->path[pathlen - 1] = '0';
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome if (strstr(device->target.path, "diskette")) {
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome (void) fprintf(stderr, gettext("installing loader to a floppy "
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome "disk is not supported\n"));
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome return (BC_ERROR);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome }
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome /* Detect if the target device is a pcfs partition. */
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome if (strstr(device->target.path, "p0:boot")) {
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome (void) fprintf(stderr, gettext("installing loader to x86 boot "
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome "partition is not supported\n"));
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome return (BC_ERROR);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome }
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome if ((device->fd = open_device(device->path)) == -1)
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome return (BC_ERROR);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome /* read in the device boot sector. */
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome if (read(device->fd, device->mbr, SECTOR_SIZE) != SECTOR_SIZE) {
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome (void) fprintf(stderr, gettext("Error reading boot sector\n"));
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome perror("read");
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome return (BC_ERROR);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome }
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome device->devtype = IG_DEV_VTOC;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome if (efi_alloc_and_read(device->fd, &vtoc) >= 0) {
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome ret = get_boot_slice(device, vtoc);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome device->devtype = IG_DEV_EFI;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome efi_free(vtoc);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome if (ret == BC_ERROR)
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome return (BC_ERROR);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome } else if (device->target.path[pathlen - 2] == 'p') {
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome device->devtype = IG_DEV_MBR;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome ret = get_boot_partition(device, (struct mboot *)device->mbr);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome if (ret == BC_ERROR)
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome return (BC_ERROR);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome } else if (device->target.path[pathlen - 1] == '2') {
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome /*
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome * NOTE: we could relax there and allow zfs boot on
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome * slice 2 for instance, but lets keep traditional limits.
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome */
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome (void) fprintf(stderr,
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome gettext("raw device must be a root slice (not s2)\n"));
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome return (BC_ERROR);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome }
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome /* fill stage partition for case there is no boot partition */
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome if (device->stage.path == NULL) {
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome if ((device->stage.path = strdup(path)) == NULL) {
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome perror(gettext("Memory allocation failure"));
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome return (BC_ERROR);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome }
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome if (device->devtype == IG_DEV_VTOC) {
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome /* use slice 2 */
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome device->stage.path[pathlen - 2] = 's';
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome device->stage.path[pathlen - 1] = '2';
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome device->stage.id = 2;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome } else {
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome p = strrchr(device->stage.path, 'p');
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome if (p == NULL)
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome p = strrchr(device->stage.path, 's');
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome device->stage.id = atoi(++p);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome }
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome device->stage.devtype = device->devtype;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome device->stage.fd = open_device(device->stage.path);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome }
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome p = strrchr(device->target.path, 'p');
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome if (p == NULL)
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome p = strrchr(device->target.path, 's');
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome device->target.id = atoi(++p);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome if (strcmp(device->stage.path, device->target.path) == 0)
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome device->target.fd = dup(device->stage.fd);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome else
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome device->target.fd = open_device(device->target.path);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome if (fstyp_init(device->target.fd, 0, NULL, &fhdl) != 0)
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome return (BC_ERROR);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome if (fstyp_ident(fhdl, NULL, &fident) != 0) {
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome fstyp_fini(fhdl);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome (void) fprintf(stderr, gettext("Failed to detect file "
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome "system type\n"));
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome return (BC_ERROR);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome }
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome /* at this moment non-boot partition has no size set, use this fact */
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome if (device->devtype == IG_DEV_EFI && strcmp(fident, "zfs") &&
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome device->stage.size == 0) {
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome fstyp_fini(fhdl);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome (void) fprintf(stderr, gettext("Booting %s of EFI labeled "
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome "disks requires the boot partition.\n"), fident);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome return (BC_ERROR);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome }
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome if (strcmp(fident, "zfs") == 0)
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome device->target.fstype = IG_FS_ZFS;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome else if (strcmp(fident, "ufs") == 0) {
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome device->target.fstype = IG_FS_UFS;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome } else if (strcmp(fident, "pcfs") == 0) {
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome device->target.fstype = IG_FS_PCFS;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome } else {
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome (void) fprintf(stderr, gettext("File system %s is not "
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome "supported by loader\n"), fident);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome fstyp_fini(fhdl);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome return (BC_ERROR);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome }
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome fstyp_fini(fhdl);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome /* check for boot partition content */
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome if (device->stage.size) {
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome if (fstyp_init(device->stage.fd, 0, NULL, &fhdl) != 0)
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome return (BC_ERROR);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome if (fstyp_ident(fhdl, NULL, &fident) == 0) {
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome (void) fprintf(stderr, gettext("Unexpected %s file "
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome "system on boot partition\n"), fident);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome fstyp_fini(fhdl);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome return (BC_ERROR);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome }
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome fstyp_fini(fhdl);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome }
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome return (get_start_sector(device));
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome}
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soomestatic void
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soomecleanup_device(ib_device_t *device)
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome{
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome if (device->path)
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome free(device->path);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome if (device->stage.path)
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome free(device->stage.path);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome if (device->target.path)
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome free(device->target.path);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome if (device->fd != -1)
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome (void) close(device->fd);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome if (device->stage.fd != -1)
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome (void) close(device->stage.fd);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome if (device->target.fd != -1)
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome (void) close(device->target.fd);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome bzero(device, sizeof (*device));
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome}
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soomestatic void
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soomecleanup_bootblock(ib_bootblock_t *bblock)
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome{
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome free(bblock->buf);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome bzero(bblock, sizeof (ib_bootblock_t));
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome}
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome/*
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome * Propagate the bootblock on the source disk to the destination disk and
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome * version it with 'updt_str' in the process. Since we cannot trust any data
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome * on the attaching disk, we do not perform any specific check on a potential
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome * target extended information structure and we just blindly update.
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome */
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soomestatic int
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soomepropagate_bootblock(ib_data_t *src, ib_data_t *dest, char *updt_str)
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome{
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome ib_bootblock_t *src_bblock = &src->bootblock;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome ib_bootblock_t *dest_bblock = &dest->bootblock;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome assert(src != NULL);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome assert(dest != NULL);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome /* read the stage1 file from source disk */
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome if (read(src->device.fd, dest->stage1, SECTOR_SIZE) != SECTOR_SIZE) {
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome (void) fprintf(stderr, gettext("cannot read stage1 from %s\n"),
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome src->device.path);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome return (BC_ERROR);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome }
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome cleanup_bootblock(dest_bblock);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome dest_bblock->buf_size = src_bblock->buf_size;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome dest_bblock->buf = malloc(dest_bblock->buf_size);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome if (dest_bblock->buf == NULL) {
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome perror(gettext("Memory Allocation Failure"));
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome return (BC_ERROR);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome }
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome dest_bblock->file = dest_bblock->buf;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome dest_bblock->file_size = src_bblock->file_size;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome (void) memcpy(dest_bblock->buf, src_bblock->buf,
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome dest_bblock->buf_size);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome dest_bblock->mboot = (multiboot_header_t *)(dest_bblock->file +
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome src_bblock->mboot_off);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome dest_bblock->mboot_off = src_bblock->mboot_off;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome dest_bblock->extra = (char *)dest_bblock->file +
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome P2ROUNDUP(dest_bblock->file_size, 8);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome dest_bblock->extra_size = src_bblock->extra_size;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome (void) fprintf(stdout, gettext("Propagating %s bootblock to %s\n"),
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome src->device.path, dest->device.path);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome return (commit_to_disk(dest, updt_str));
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome}
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soomestatic int
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soomecommit_to_disk(ib_data_t *data, char *update_str)
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome{
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome assert(data != NULL);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome if (prepare_bootblock(data, update_str) != BC_SUCCESS) {
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome (void) fprintf(stderr, gettext("Error updating the bootblock "
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome "image\n"));
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome return (BC_ERROR);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome }
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome if (prepare_stage1(data) != BC_SUCCESS) {
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome (void) fprintf(stderr, gettext("Error updating the stage1 "
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome "image\n"));
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome return (BC_ERROR);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome }
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome if (write_bootblock(data) != BC_SUCCESS) {
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome (void) fprintf(stderr, gettext("Error writing bootblock to "
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome "disk\n"));
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome return (BC_ERROR);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome }
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome return (write_stage1(data));
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome}
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome/*
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome * Install a new bootblock on the given device. handle_install() expects argv
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome * to contain 3 parameters (the target device path and the path to the
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome * bootblock.
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome *
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome * Returns: BC_SUCCESS - if the installation is successful
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome * BC_ERROR - if the installation failed
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome * BC_NOUPDT - if no installation was performed because the
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome * version currently installed is more recent than the
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome * supplied one.
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome *
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome */
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soomestatic int
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soomehandle_install(char *progname, char **argv)
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome{
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome ib_data_t install_data;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome char *stage1 = NULL;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome char *bootblock = NULL;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome char *device_path = NULL;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome int ret = BC_ERROR;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome stage1 = strdup(argv[0]);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome bootblock = strdup(argv[1]);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome device_path = strdup(argv[2]);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome if (!device_path || !bootblock || !stage1) {
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome (void) fprintf(stderr, gettext("Missing parameter"));
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome usage(progname);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome goto out;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome }
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome BOOT_DEBUG("device path: %s, stage1 path: %s bootblock path: %s\n",
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome device_path, stage1, bootblock);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome bzero(&install_data, sizeof (ib_data_t));
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome if (init_device(&install_data.device, device_path) != BC_SUCCESS) {
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome (void) fprintf(stderr, gettext("Unable to open device %s\n"),
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome device_path);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome goto out;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome }
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome if (read_stage1_from_file(stage1, &install_data) != BC_SUCCESS) {
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome (void) fprintf(stderr, gettext("Error opening %s\n"), stage1);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome goto out_dev;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome }
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome if (read_bootblock_from_file(bootblock, &install_data) != BC_SUCCESS) {
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome (void) fprintf(stderr, gettext("Error reading %s\n"),
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome bootblock);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome goto out_dev;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome }
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome /*
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome * is_update_necessary() will take care of checking if versioning and/or
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome * forcing the update have been specified. It will also emit a warning
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome * if a non-versioned update is attempted over a versioned bootblock.
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome */
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome if (!is_update_necessary(&install_data, update_str)) {
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome (void) fprintf(stderr, gettext("bootblock version installed "
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome "on %s is more recent or identical\n"
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome "Use -F to override or install without the -u option\n"),
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome device_path);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome ret = BC_NOUPDT;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome goto out_dev;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome }
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome BOOT_DEBUG("Ready to commit to disk\n");
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome ret = commit_to_disk(&install_data, update_str);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soomeout_dev:
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome cleanup_device(&install_data.device);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soomeout:
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome free(stage1);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome free(bootblock);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome free(device_path);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome return (ret);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome}
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome/*
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome * Retrieves from a device the extended information (einfo) associated to the
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome * installed stage2.
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome * Expects one parameter, the device path, in the form: /dev/rdsk/c?[t?]d?s0.
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome * Returns:
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome * - BC_SUCCESS (and prints out einfo contents depending on 'flags')
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome * - BC_ERROR (on error)
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome * - BC_NOEINFO (no extended information available)
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome */
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soomestatic int
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soomehandle_getinfo(char *progname, char **argv)
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome{
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome ib_data_t data;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome ib_bootblock_t *bblock = &data.bootblock;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome ib_device_t *device = &data.device;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome bblk_einfo_t *einfo;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome uint8_t flags = 0;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome char *device_path, *path;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome int retval = BC_ERROR;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome int ret;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome device_path = strdup(argv[0]);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome if (!device_path) {
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome (void) fprintf(stderr, gettext("Missing parameter"));
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome usage(progname);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome goto out;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome }
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome bzero(&data, sizeof (ib_data_t));
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome BOOT_DEBUG("device path: %s\n", device_path);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome if (init_device(device, device_path) != BC_SUCCESS) {
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome (void) fprintf(stderr, gettext("Unable to gather device "
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome "information from %s\n"), device_path);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome goto out_dev;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome }
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome ret = read_bootblock_from_disk(device, bblock, &path);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome if (ret == BC_ERROR) {
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome (void) fprintf(stderr, gettext("Error reading bootblock from "
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome "%s\n"), path);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome goto out_dev;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome }
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome if (ret == BC_NOEXTRA) {
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome BOOT_DEBUG("No multiboot header found on %s, unable "
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome "to locate extra information area (old/non versioned "
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome "bootblock?) \n", device_path);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome (void) fprintf(stderr, gettext("No extended information "
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome "found\n"));
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome retval = BC_NOEINFO;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome goto out_dev;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome }
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome einfo = find_einfo(bblock->extra, bblock->extra_size);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome if (einfo == NULL) {
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome retval = BC_NOEINFO;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome (void) fprintf(stderr, gettext("No extended information "
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome "found\n"));
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome goto out_dev;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome }
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome /* Print the extended information. */
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome if (strip)
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome flags |= EINFO_EASY_PARSE;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome if (verbose_dump)
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome flags |= EINFO_PRINT_HEADER;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome print_einfo(flags, einfo, bblock->extra_size);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome retval = BC_SUCCESS;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soomeout_dev:
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome cleanup_device(&data.device);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soomeout:
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome free(device_path);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome return (retval);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome}
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome/*
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome * Attempt to mirror (propagate) the current bootblock over the attaching disk.
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome *
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome * Returns:
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome * - BC_SUCCESS (a successful propagation happened)
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome * - BC_ERROR (an error occurred)
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome * - BC_NOEXTRA (it is not possible to dump the current bootblock since
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome * there is no multiboot information)
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome */
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soomestatic int
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soomehandle_mirror(char *progname, char **argv)
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome{
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome ib_data_t curr_data;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome ib_data_t attach_data;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome ib_device_t *curr_device = &curr_data.device;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome ib_device_t *attach_device = &attach_data.device;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome ib_bootblock_t *bblock_curr = &curr_data.bootblock;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome ib_bootblock_t *bblock_attach = &attach_data.bootblock;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome bblk_einfo_t *einfo_curr = NULL;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome char *curr_device_path;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome char *attach_device_path;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome char *updt_str = NULL;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome char *path;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome int retval = BC_ERROR;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome int ret;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome curr_device_path = strdup(argv[0]);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome attach_device_path = strdup(argv[1]);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome if (!curr_device_path || !attach_device_path) {
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome (void) fprintf(stderr, gettext("Missing parameter"));
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome usage(progname);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome goto out;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome }
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome BOOT_DEBUG("Current device path is: %s, attaching device path is: "
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome " %s\n", curr_device_path, attach_device_path);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome bzero(&curr_data, sizeof (ib_data_t));
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome bzero(&attach_data, sizeof (ib_data_t));
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome if (init_device(curr_device, curr_device_path) != BC_SUCCESS) {
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome (void) fprintf(stderr, gettext("Unable to gather device "
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome "information from %s (current device)\n"),
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome curr_device_path);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome goto out_currdev;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome }
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome if (init_device(attach_device, attach_device_path) != BC_SUCCESS) {
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome (void) fprintf(stderr, gettext("Unable to gather device "
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome "information from %s (attaching device)\n"),
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome attach_device_path);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome goto out_devs;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome }
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome ret = read_bootblock_from_disk(curr_device, bblock_curr, &path);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome if (ret == BC_ERROR) {
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome BOOT_DEBUG("Error reading bootblock from %s\n", path);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome retval = BC_ERROR;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome goto out_devs;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome }
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome if (ret == BC_NOEXTRA) {
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome BOOT_DEBUG("No multiboot header found on %s, unable to retrieve"
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome " the bootblock\n", path);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome retval = BC_NOEXTRA;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome goto out_devs;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome }
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome write_mbr = B_TRUE;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome force_mbr = B_TRUE;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome einfo_curr = find_einfo(bblock_curr->extra, bblock_curr->extra_size);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome if (einfo_curr != NULL)
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome updt_str = einfo_get_string(einfo_curr);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome retval = propagate_bootblock(&curr_data, &attach_data, updt_str);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome cleanup_bootblock(bblock_curr);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome cleanup_bootblock(bblock_attach);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soomeout_devs:
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome cleanup_device(attach_device);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soomeout_currdev:
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome cleanup_device(curr_device);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soomeout:
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome free(curr_device_path);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome free(attach_device_path);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome return (retval);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome}
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome#define USAGE_STRING "Usage:\t%s [-h|-m|-f|-n|-F|-u verstr] stage1 stage2 " \
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome "raw-device\n" \
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome "\t%s -M [-n] raw-device attach-raw-device\n" \
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome "\t%s [-e|-V] -i raw-device\n"
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome#define CANON_USAGE_STR gettext(USAGE_STRING)
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soomestatic void
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soomeusage(char *progname)
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome{
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome (void) fprintf(stdout, CANON_USAGE_STR, progname, progname, progname);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome}
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soomeint
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soomemain(int argc, char **argv)
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome{
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome int opt;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome int params = 3;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome int ret;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome char *progname;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome char **handle_args;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome (void) setlocale(LC_ALL, "");
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome (void) textdomain(TEXT_DOMAIN);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome if (init_yes() < 0) {
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome (void) fprintf(stderr, gettext(ERR_MSG_INIT_YES),
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome strerror(errno));
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome exit(BC_ERROR);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome }
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome while ((opt = getopt(argc, argv, "deFfhiMmnu:V")) != EOF) {
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome switch (opt) {
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome case 'd':
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome boot_debug = B_TRUE;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome break;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome case 'e':
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome strip = B_TRUE;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome break;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome case 'F':
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome force_update = B_TRUE;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome break;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome case 'f':
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome force_mbr = B_TRUE;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome break;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome case 'h':
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome usage(argv[0]);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome exit(BC_SUCCESS);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome break;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome case 'i':
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome do_getinfo = B_TRUE;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome params = 1;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome break;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome case 'M':
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome do_mirror_bblk = B_TRUE;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome params = 2;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome break;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome case 'm':
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome write_mbr = B_TRUE;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome break;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome case 'n':
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome nowrite = B_TRUE;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome break;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome case 'u':
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome do_version = B_TRUE;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome update_str = malloc(strlen(optarg) + 1);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome if (update_str == NULL) {
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome perror(gettext("Memory allocation failure"));
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome exit(BC_ERROR);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome }
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome (void) strlcpy(update_str, optarg, strlen(optarg) + 1);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome break;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome case 'V':
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome verbose_dump = B_TRUE;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome break;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome default:
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome /* fall through to process non-optional args */
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome break;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome }
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome }
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome /* check arguments */
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome if (argc != optind + params) {
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome usage(argv[0]);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome exit(BC_ERROR);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome }
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome progname = argv[0];
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome check_options(progname);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome handle_args = argv + optind;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome if (nowrite)
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome (void) fprintf(stdout, gettext("Dry run requested. Nothing will"
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome " be written to disk.\n"));
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome if (do_getinfo) {
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome ret = handle_getinfo(progname, handle_args);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome } else if (do_mirror_bblk) {
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome ret = handle_mirror(progname, handle_args);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome } else {
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome ret = handle_install(progname, handle_args);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome }
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome return (ret);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome}
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome#define MEANINGLESS_OPT gettext("%s specified but meaningless, ignoring\n")
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soomestatic void
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soomecheck_options(char *progname)
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome{
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome if (do_getinfo && do_mirror_bblk) {
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome (void) fprintf(stderr, gettext("Only one of -M and -i can be "
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome "specified at the same time\n"));
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome usage(progname);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome exit(BC_ERROR);
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome }
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome if (do_mirror_bblk) {
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome /*
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome * -u and -F may actually reflect a user intent that is not
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome * correct with this command (mirror can be interpreted
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome * "similar" to install. Emit a message and continue.
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome * -e and -V have no meaning, be quiet here and only report the
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome * incongruence if a debug output is requested.
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome */
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome if (do_version) {
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome (void) fprintf(stderr, MEANINGLESS_OPT, "-u");
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome do_version = B_FALSE;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome }
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome if (force_update) {
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome (void) fprintf(stderr, MEANINGLESS_OPT, "-F");
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome force_update = B_FALSE;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome }
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome if (strip || verbose_dump) {
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome BOOT_DEBUG(MEANINGLESS_OPT, "-e|-V");
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome strip = B_FALSE;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome verbose_dump = B_FALSE;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome }
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome }
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome if (do_getinfo) {
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome if (write_mbr || force_mbr || do_version || force_update) {
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome BOOT_DEBUG(MEANINGLESS_OPT, "-m|-f|-u|-F");
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome write_mbr = force_mbr = do_version = B_FALSE;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome force_update = B_FALSE;
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome }
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome }
0c946d80993858b7b1314e0b31773e48500e03fbToomas Soome}