diff --git a/Makefile b/Makefile index 15ff791..b55efca 100644 --- a/Makefile +++ b/Makefile @@ -36,7 +36,7 @@ INSTALLS=anon.dtrace.conf anon.system build_image.sh build_zfs_send.sh \ data/known_extras data/mdb data/platform disk_help.sh install_help.sh \ install_image.sh src/takeover-console.c Makefile net_help.sh README.md \ build_iso.sh digest find-and-install.sh kayak-menu.sh config-menu.sh \ - usbgen.sh ipcalc dialog src/passutil.c \ + build_usb.sh ipcalc dialog src/passutil.c \ loader.conf.local rpool-install.sh \ sample/000000000000.sample sample/menu.lst.000000000000 @@ -171,7 +171,8 @@ install-iso: bins kbd.list install-tftp install-web BUILDSEND_MP=$(BUILDSEND_MP) VERSION=$(VERSION) ./build_iso.sh install-usb: install-iso - ./usbgen.sh $(BUILDSEND_MP)/$(VERSION).iso $(BUILDSEND_MP)/$(VERSION).usb-dd /tmp + ./build_usb.sh $(BUILDSEND_MP)/$(VERSION).iso \ + $(BUILDSEND_MP)/$(VERSION).usb-dd clean: rm -f takeover-console passutil mount_media ipcalc dialog zpool_patch \ diff --git a/build_usb.sh b/build_usb.sh new file mode 100755 index 0000000..f50389b --- /dev/null +++ b/build_usb.sh @@ -0,0 +1,210 @@ +#!/usr/bin/ksh + +# {{{ CDDL HEADER +# +# This file and its contents are supplied under the terms of the +# Common Development and Distribution License ("CDDL"), version 1.0. +# You may only use this file in accordance with the terms of version +# 1.0 of the CDDL. +# +# A full copy of the text of the CDDL should have accompanied this +# source. A copy of the CDDL is also available via the Internet at +# http://www.illumos.org/license/CDDL. +# }}} + +# Copyright 2018 OmniOS Community Edition (OmniOSce) Association. + +export LC_ALL=C + +if [ `id -u` != "0" ]; then + echo "You must be root to run this script." + exit 1 +fi + +ISO_FILE=${1:?iso} +USB_FILE=${2:?usb} + +[ ! -f "$ISO_FILE" ] && echo "Cannot find $ISO_FILE" && exit 1 + +# Uncomment the following line to build a UEFI image. +# We aren't building UEFI yet. +#UEFI_SIZE=34M + +# Allow temporary directory override +: ${TMPDIR:=/tmp} + +UEFI_ROOT=$TMPDIR/uefi_root.$$ +USB_ROOT=$TMPDIR/usb_root.$$ +ISO_ROOT=$TMPDIR/iso_root.$$ + +stage() +{ + echo "***" + echo "*** $*" + echo "***" +} + +set -o errexit + +###################################################################### +# Find UEFI boot file + +if [ -n "$UEFI_SIZE" ]; then + if [ -n "$PREBUILT_ILLUMOS" -a \ + -f $PREBUILT_ILLUMOS/proto/root_i386-nd/boot/boot1.efi ]; then + echo "Using boot1.efi from proto" + EFI_LOADER=$PREBUILT_ILLUMOS/proto/root_i386-nd/boot/boot1.efi + elif [ -f /boot/boot1.efi ]; then + echo "Using boot1.efi from running system" + EFI_LOADER=/boot/boot1.efi + else + echo "Cannot find boot1.efi" + exit 1 + fi +fi + +###################################################################### +# Compute the size for the new USB image. +# +# Use the ISO file size + 20% to account for smaller block size on UFS +# and the log. Round to nearest KiB plus 512. + +ISO_SIZE=`stat -c %s $ISO_FILE` +(( USB_SIZE = int((ISO_SIZE * 1.2) / 1024.) * 1024 + 512 )) + +# In MBR mode: +# plus 4MB for MBR+SMI label +# In UEFI mode: +# plus 4MB for label +# plus 34MB for system partition +# plus 1MB for boot partition + +if [ -n "$UEFI_SIZE" ]; then + ((USB_SIZE += 41943040)) +else + ((USB_SIZE += 4194304)) +fi + +echo "USB Size = $USB_SIZE (ISO_SIZE = $ISO_SIZE)" + +###################################################################### +# Create the new empty USB image and partition it +# + +stage "Creating USB image file" + +mkfile -n $USB_SIZE $USB_FILE +LOFI_USB=`lofiadm -la $USB_FILE` +RLOFI_USB=${LOFI_USB/dsk/rdsk} +# LOFI_USB fill be of the form /dev/dsk/c1t1d0p0 + +if [ -n "$UEFI_SIZE" ]; then + # Let zpool do the partitioning work for us + zpool create -B -o bootsize=$UEFI_SIZE usbtmp-$$ ${LOFI_USB/p0/} + zpool destroy usbtmp-$$ + + # At this point, the disk has three EFI partitions: + # V_SYSTEM ESP @ $UEFI_SIZE + # V_USR For ZFS data + # V_RESERVED Reserved + + # 1 MiB assuming 512-byte sectors + boot_size=2048 + + # Shrink slice 1 to $boot_size sectors and change the partition type + # to 1 (V_BOOT). + new_boot=`prtvtoc -h $RLOFI_USB | nawk -v size=$boot_size ' + $1 == 1 { printf("1:1:00:%d:%d\n", $4, size) } + '` + + # Allocate the remaining free space to slice 2 and set the + # partition type to 2 (V_ROOT) + new_root=`prtvtoc -h $RLOFI_USB | nawk -v size=$boot_size ' + $1 == 1 { printf("2:2:00:%d:%d\n", $4 + size, $5 - size) } + '` + + fmthard -d $new_boot $RLOFI_USB + fmthard -d $new_root $RLOFI_USB + + stage "Building UEFI bootblock" + + yes | mkfs -F pcfs -o b=System ${RLOFI_USB/p0/s0} + mkdir $UEFI_ROOT + mount -F pcfs ${LOFI_USB/p0/s0} $UEFI_ROOT + mkdir -p $UEFI_ROOT/efi/boot + cp $EFI_LOADER $UEFI_ROOT/efi/boot/bootx64.efi + umount $UEFI_ROOT + rmdir $UEFI_ROOT + + ufs=2 +else + # Create Solaris2 partition filling the entire disk + fdisk -B $RLOFI_USB + fdisk -W - $RLOFI_USB | tail -5 | head -2 + echo + + # Create slice 0 covering all of the non-reserved space + OIFS="$IFS"; IFS=" =" + set -- `prtvtoc -f $RLOFI_USB` + IFS="$OIFS" + # FREE_START=2048 FREE_SIZE=196608 FREE_COUNT=1 FREE_PART=... + start=$2; size=$4 + fmthard -d 0:2:01:$start:$size $RLOFI_USB + + ufs=0 +fi + +prtvtoc -s $RLOFI_USB + +###################################################################### +# Format and mount the UFS area + +stage "Formatting UFS slice $ufs" + +UFS_SLICE=${RLOFI_USB/p0/s$ufs} +yes | newfs $UFS_SLICE +mkdir $USB_ROOT +mount -o nologging ${UFS_SLICE/rdsk/dsk} $USB_ROOT + +###################################################################### +# Mount the source ISO, copy files to USB, unmount again + +stage "Mounting source ISO" +LOFI_ISO=`lofiadm -a $ISO_FILE` +mkdir $ISO_ROOT +mount -F hsfs -o ro $LOFI_ISO $ISO_ROOT + +stage "Copying ISO contents to USB image..." +( cd $ISO_ROOT; find . -print | cpio -pmudV $USB_ROOT ) + +stage "Unmounting source ISO" +umount $ISO_ROOT +rmdir $ISO_ROOT +lofiadm -d $LOFI_ISO + +# Create hidden file to stop OSX indexing this image (for example when +# installing via dd) +touch $USB_ROOT/.metadata_never_index + +df -h $USB_ROOT + +###################################################################### +# Install bootblocks +# + +stage "Installing boot blocks" +installboot -mf $USB_ROOT/boot/pmbr $USB_ROOT/boot/gptzfsboot $UFS_SLICE + +###################################################################### +# Unmount and clean up + +stage "Cleaning up" + +umount $USB_ROOT +rmdir $USB_ROOT +lofiadm -d $LOFI_USB + +chmod 444 $USB_FILE + +exit 0 + diff --git a/usbgen.sh b/usbgen.sh deleted file mode 100755 index cb548b0..0000000 --- a/usbgen.sh +++ /dev/null @@ -1,413 +0,0 @@ -#!/usr/bin/ksh93 - -# -# CDDL HEADER START -# -# The contents of this file are subject to the terms of the -# Common Development and Distribution License (the "License"). -# You may not use this file except in compliance with the License. -# -# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE -# or http://www.opensolaris.org/os/licensing. -# See the License for the specific language governing permissions -# and limitations under the License. -# -# When distributing Covered Code, include this CDDL HEADER in each -# file and include the License file at usr/src/OPENSOLARIS.LICENSE. -# If applicable, add the following below this CDDL HEADER, with the -# fields enclosed by brackets "[]" replaced with your own identifying -# information: Portions Copyright [yyyy] [name of copyright owner] -# -# CDDL HEADER END -# - -# -# Copyright 2008 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# - -# -# Generate USB image from iso -# Originally from slim_install, modified by Toomas Soome. -# - -# Solaris needs /usr/xpg4/bin/ because the tools in /usr/bin are not -# POSIX-conformant -export PATH=/usr/xpg4/bin:/bin:/usr/bin:/usr/sbin - -# Make sure all math stuff runs in the "C" locale to avoid problems -# with alternative # radix point representations (e.g. ',' instead of -# '.' in de_DE.*-locales). This needs to be set _before_ any -# floating-point constants are defined in this script). -if [[ "${LC_ALL}" != "" ]] ; then - export \ - LC_MONETARY="${LC_ALL}" \ - LC_MESSAGES="${LC_ALL}" \ - LC_COLLATE="${LC_ALL}" \ - LC_CTYPE="${LC_ALL}" - unset LC_ALL -fi -export LC_NUMERIC=C - -####################################################################### -# usage -# Print the usage message. -# Input: none -# Returns: none -# -####################################################################### -function usage -{ - print -u2 "\nUsage: " - print -u2 "${progname} iso_file usb_image tmpdir" - print -u2 "iso_file : The path to an existing iso file." - print -u2 "usb_image : The path to usb image to be created." - print -u2 "tmpdir : Temporary directy used during usb image " \ - "creation.\n" - - print -u2 "If tmpdir does not exist it will be created. If " \ - "it or subdirectories under tmpdir can not be created " \ - " an error is generated and this script exits." - -} - -####################################################################### -# get_filesize -# Get filesize for the file argv[2] and return it to the -# variable defined by argv[1]. -# Input: -# $1 - variable to return filesize in -# $2 - file to query -# -# Returns: -# $1 - variable to return filesize in -# -# -1 if file does not exist -# -# A non-zero exit code only for internal errors and success -# in all other cases -# -####################################################################### -function get_filesize -{ - set -o errexit - nameref filesize_ret="$1" # return filesize into this varable - typeset filename="$2" # file to query - integer filesize=-1 # temporary integer for "read" below - typeset dummy # dummy string - - if [[ -f "${filename}" ]] ; then - ls -lb "${filename}" | \ - grep "${filename}" | \ - read dummy dummy dummy dummy filesize dummy - fi - - (( filesize_ret=filesize )) - return 0 -} - -# -# -####################################################################### -# cleanup -# This function attempst to clean up any resources this script -# could generate. Depending on where in the script this function -# is involked some resouces may not be there to cleanup, but -# that will not adversely effect anything. -# -# This function is not defined using the function keyword -# to avoid an exit loop. -# -# Input: none -# Returns: none -# -####################################################################### -cleanup () -{ - - { - trap "" ERR INT - set +o errexit - - # unmounting, and uninstalling the lofi'ed devices and - # cleanup temporary files. - IFS='' - - typeset mount_output="$(mount)" - - [[ "${mount_output}" == ~(E).*"${usb_path}".* ]] && \ - umount "${usb_path}" - - [[ "${mount_output}" == ~(E).*"${iso_path}".* ]] && \ - umount "${iso_path}" - - lofiadm "${usb_file}" && \ - lofiadm -d "${usb_file}" - - lofiadm "${iso_file}" && \ - lofiadm -d "${iso_file}" - - if [[ -d "${iso_path}" ]] ; then - rm -rf "${iso_path}" - fi - - if [[ -d "${usb_path}" ]] ; then - rm -rf "${usb_path}" - fi - - # - # If the tmpdir did not exist this script could - # have created it, so remove it here. - # - if ! ${tmpdir_existed} ; then - rm -rf "${tmpdir}" - fi - } > /dev/null 2>&1 - -} - -####################################################################### -# error_handler -# The error_handler for this script. Will cleanup the usb image -# that could have been partially created. Then invoke cleanup -# to clean up any temporary resouces. -# -# This function is not defined using the function keyword -# to avoid an exit loop. -# -# Input: none -# Returns: none -# -####################################################################### -error_handler () -{ - trap "" ERR INT - set +o errexit - - print -u2 "\nError:\n" - print -u2 -r -- "${progname}: $*" - cleanup - - # - # If an error was encountered while attempting to create - # the new usb image file don't leave a possibley partially - # constructed one around. - # - if [[ -f "${usb_file}" ]] ; then - rm -rf "${usb_file}" > /dev/null 2>&1 - fi - - exit 1 -} - -# main -####################################################################### -# main -# -# Input: -# iso_file : The path to an existing iso file. -# usb_image : The path to usb image to be created. -# tmpdir : Temporary directroy used during usb image creation. -# -# If tmpdir does not exist it will be created. If it can not be -# created an error is generated and this script exits. -# -# This script must be run as root" -# -# Logic Flow: -# Set up error handling. -# Confirm input arguments. -# Create temporary directories. -# Mount up the existing ISO image file. -# Compute the size for the new USB image. -# Create and mount an empty new USB image. -# Copy the contents of the ISO file to the new USB image. -# Remove GRUB entries from the USB image which apply only to ISO. -# Set the file protections for the new USB image. -# -# Returns: -# 1 on failure -# 0 on success -# -####################################################################### -builtin chmod -builtin cp -builtin mkdir -builtin mv -builtin rm - -typeset -r progname="$0" -typeset -r iso_file="$1" -typeset -r tmpdir="$3" -typeset tmpdir_existed=true -typeset -r iso_path="${tmpdir}/iso" - -typeset -r usb_file="$2" -typeset -r usb_path="${tmpdir}/usb" -float usb_size # need floating-point for the calculations below - -typeset isodev -typeset devs -typeset rdevs -typeset s0devs -typeset rs0devs -typeset rs2devs - -# -# Confirm input arguments. -# -if [[ $(id) != ~(E).*uid=0\(root\).* ]]; then - print -u2 "Error:\nYou must run this script as root" - usage - exit 1 -fi - -if (( $# != 3 )) ; then - print -u2 "Error:\nImproper arguments" - usage - exit 1 -fi - -# -# Set up error handling. -# Use set -o errexit to trap errors. However, where possible, -# explicitly check command return status for errors. -# -trap "error_handler Error or interrupt encountered. Exiting" ERR INT -set -o errexit - -# -# Create temporary directories. -# -[[ ! -d $tmpdir ]] && tmpdir_existed=false -mkdir -p "${iso_path}" -if [[ ! -d "${iso_path}" ]] ; then - error_handler "Unable to create or access tmpdir ${iso_path}" -fi - -mkdir -p "${usb_path}" -if [[ ! -d "${usb_path}" ]] ; then - error_handler "Unable to create or access tmpdir ${usb_path}" -fi - -# -# Mount up the existing ISO image file. -# -isodev="$(lofiadm -a "${iso_file}")" || \ - error_handler "Failed to lofiadm ${iso_file}" - -mount -F hsfs "${isodev}" "${iso_path}" || \ - error_handler "Failed to mount ${isodev} on ${iso_path}" - - -# -# Compute the size for the new USB image. -# Use ISO file size + 20% to account for smaller block size on UFS -# and the log. Round to nearest kbyte plus 512 -# plus 4MB for MBR+SMI label -# -get_filesize "usb_size" "${iso_file}" -if (( usb_size == -1 )) ; then - error_handler "Failed to get size of file ${iso_file}" -fi -(( usb_size=((int( (usb_size * 1.2) / 1024.) * 1024.) + 512) + 4194304 )) - -# -# Create and mount an empty new USB image. -# -mkfile -n ${usb_size} "${usb_file}" || \ - error_handler "Failed to create file ${usb_file}" - -devs="$(lofiadm -la "${usb_file}")" || \ - error_handler "Failed to lofiadm file ${usb_file}" - -# -# Set rdevs by replacing dsk with rdsk in devs -# -rdevs="${devs/dsk/rdsk}" -# for mount -s0devs="${devs/p0/s0}" -# for newfs and installboot -rs0devs="${rdevs/p0/s0}" -# for prtvtoc | fmthard -rs2devs="${rdevs/p0/s2}" - -# -# create Solaris2 partition -# -fdisk -B "${rdevs}" -prtvtoc "${rs2devs}" | nawk ' -/^[^\*]/ { r = $1; for(n = 1; n <= NF; n++) vtoc[r,n] = $n } -END { -vtoc[0,1] = 0; -vtoc[0,2] = 2; -vtoc[0,3] = 00; -vtoc[0,4] = vtoc[8,6] + 1; -vtoc[0,5] = vtoc[2,6] - vtoc[8,6]; -vtoc[0,6] = vtoc[2,6]; -printf("\t%d\t%d\t%02d\t%d\t%d\t%d\n", - vtoc[0,1], vtoc[0,2], vtoc[0,3], vtoc[0,4], vtoc[0,5], vtoc[0,6]); -printf("\t%d\t%d\t%02d\t%d\t%d\t%d\n", - vtoc[2,1], vtoc[2,2], vtoc[2,3], vtoc[2,4], vtoc[2,5], vtoc[2,6]); -printf("\t%d\t%d\t%02d\t%d\t%d\t%d\n", - vtoc[8,1], vtoc[8,2], vtoc[8,3], vtoc[8,4], vtoc[8,5], vtoc[8,6]); -}' | fmthard -s- "${rs2devs}" - -# newfs doesn't ask questions if stdin isn't a tty. -newfs "${rs0devs}" ${usb_path}/boot/grub/menu2.lst -if [[ $? == 0 ]] ; then - mv ${usb_path}/boot/grub/menu2.lst ${usb_path}/boot/grub/menu.lst -else - print -u2 "Warning: Could not remove \"Hard Disk\" entry from boot menu" -fi - -# -# Set the file protections for the new USB image. -# -chmod 444 "${usb_file}" - -# -# unmounting, and uninstalling the lofi'ed devices -# -cleanup - -printf "=== %s completed at %s\n\n" "$0" "$(date)" - -exit 0 -