# Super Grub Disk - supergrub-mkcommon # Copyright (C) 2009,2010,2011,2012,2013,2014,2015 Adrian Gibanel Lopez. # # Super Grub Disk is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # Super Grub Disk is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Super Grub Disk. If not, see . function init_overlay_dir () { mkdir -p "$overlay/boot/grub/" cp -r menus/* "$overlay/boot/grub/" } function copy_boot_isos_directory () { if [ -d ${BOOT_ISOS_DIRECTORY} ] ; then cp -r ${BOOT_ISOS_DIRECTORY} "$overlay/boot/" fi } function copy_copyright () { cp AUTHORS COPYING "$overlay/boot/grub/sgd/" } function generate_and_copy_mo_files () { # Generate mo files and add them to overlay for pofile in po/*.po; do basename=${pofile##*/} lang_code="${basename%.po}" info_cfg="menus/sgd/sgd_locale/${lang_code}_info.cfg" msgfmt "$pofile" --output-file="$overlay/boot/grub/sgd/sgd_locale/${lang_code}.mo" if ! [[ -f "$info_cfg" ]]; then echo "Thank you for providing a new translation for Super GRUB2 Disk!" echo "Before this translation can be used in Super GRUB2 Disk we need to know what" echo "to call it in our language selection menu." echo "We need to know the name of the language you've translated, in that language." echo "For example, for Spanish you would enter \"EspaƱol\" (without the quotes)." echo -n "Please enter the name of the language for $pofile: " read language_name cp info_cfg_header.cfg "$info_cfg" echo "lang_code='${lang_code}'" >> "$info_cfg" # This will fail if $language_name contains a single quote character. # TODO: Fix aforementioned problem by escaping quotes in $language_name. echo "language_name='${language_name}'" >> "$info_cfg" echo "A file, ${info_cfg}, was created with this information." echo "Thanks again for contributing a new translation!" echo; echo fi done } function check_unifont () { # Find unifont font file to create grub font. This is needed for gfxterm in grub, which # in turn is needed for displaying non-ASCII characters for non-English translations. # This unifont finding code was copied from grub's configure.ac. for ext in pcf pcf.gz bdf bdf.gz ttf ttf.gz; do for dir in . /usr/src /usr/share/fonts/X11/misc /usr/share/fonts/unifont; do if test -f "$dir/unifont.$ext"; then font_source="$dir/unifont.$ext" break 2 fi done done if [[ -n "$font_source" ]]; then "$GRUB_MKFONT_BINARY" "$font_source" --output="$overlay/boot/grub/unifont.pf2" else echo "Error: Unifont not found. Unifont is needed for Super GRUB2 Disk" >&2 echo "to properly display non-ASCII characters. Aborting without creating an iso." >&2 exit 1 fi } function generate_filename_hashes () { local ISO_FILENAME="$1" local TMP_PRE_CHECKSUMS_DIR="$(pwd)" local SHORT_ISO_FILENAME="$(basename ${ISO_FILENAME})" local ISO_FILENAME_DIR="$(dirname ${ISO_FILENAME})" cd "${ISO_FILENAME_DIR}" md5sum ${SHORT_ISO_FILENAME} > ${SHORT_ISO_FILENAME}.md5 sha1sum ${SHORT_ISO_FILENAME} > ${SHORT_ISO_FILENAME}.sha1 sha256sum ${SHORT_ISO_FILENAME} > ${SHORT_ISO_FILENAME}.sha256 cd "${TMP_PRE_CHECKSUMS_DIR}" } function generate_SG2D_UUID_FILE () { LIVEID_DIR_PREFIX="LIVEID" SG2D_UUID_SEED="\ ${ISO_FILENAME}\ -\ ${GRUB_MKRESCUE_BINARY}\ -\ ${GRUB_MKFONT_BINARY}\ -\ ${EFI_PLATFORMS}\ " SG2D_UUID=$(echo -n "${SG2D_UUID_SEED}" | md5sum | tr 'a-z' 'A-Z') SG2D_UUID_DIR1="$(echo ${SG2D_UUID} | cut -c1-8)" SG2D_UUID_DIR2="$(echo ${SG2D_UUID} | cut -c9-16)" SG2D_UUID_DIR3="$(echo ${SG2D_UUID} | cut -c17-24)" SG2D_UUID_FILE4="$(echo ${SG2D_UUID} | cut -c25-32)" SG2D_UUID_DIR="${LIVEID_DIR_PREFIX}/${SG2D_UUID_DIR1}"'/'"${SG2D_UUID_DIR2}"'/'"${SG2D_UUID_DIR3}" SGD2_UUID_FILE="${SG2D_UUID_DIR}"'/'"${SG2D_UUID_FILE4}" mkdir -p "$overlay/${SG2D_UUID_DIR}/" touch "$overlay/${SGD2_UUID_FILE}" } function get_vendor_grub_cfg_content () { nvendor=$1 cat < "${overlay}/EFI/${nvendor}/grub.cfg" fi done done cd "${PRE_LOOP_DIR}" } Lodetach () { DEVICE="${1}" ATTEMPT="${2:-1}" if [ "${ATTEMPT}" -gt 3 ] then echo "Failed to detach loop device (${DEVICE})." exit 1 fi # Changes to block devices result in uevents which trigger rules which in # turn access the loop device (ex. udisks-part-id, blkid) which can cause # a race condition. We call 'udevadm settle' to help avoid this. if [ -x "$(which udevadm 2>/dev/null)" ] then udevadm settle fi # Loop back devices aren't the most reliable when it comes to writes. # We sleep and sync for good measure - better than build failure. sync sleep 1 /sbin/losetup -d "${DEVICE}" || Lodetach "${DEVICE}" "$(expr ${ATTEMPT} + 1)" } function generate_usb_image_mbr () { generate_usb_image mbr } function generate_usb_image_gpt () { generate_usb_image gpt } function generate_usb_image () { MODE="$1" # Many code was adapted from binary_hdd and losetup.sh from live-build package if [ "${MODE}" == "gpt" ] ; then PART0_NUMBER=1 PART1_NUMBER=2 PART2_NUMBER=3 else # mbr PART0_NUMBER=0 # Not actually used PART1_NUMBER=1 PART2_NUMBER=2 fi # Step 1: Prepare the disk DU_DIM="$(du -ms ${overlay} | cut -f1)" PART0_START=1 PART0_END=2 PART1_REAL_DIM="$(expr ${DU_DIM} + ${DU_DIM} \* 3 / 100 + 1)" PART1_MINIMAL_DIM="33" # Minimal FAT32 size is about 32 megabytes # We want two of thems for iso partition # Make sure the minimal size is 256 megabytes # else gparted cannot resize such small partitions # We finally used 265 megabytes PART2_MINIMAL_DIM="265" PART2_REAL_DIM=${PART2_MINIMAL_DIM} # No need currently for specific space if [ ${PART1_MINIMAL_DIM} -gt ${PART1_REAL_DIM} ] ; then PART1_REAL_DIM=${PART1_MINIMAL_DIM} fi PART1_START=3 # We start at 2 megabyte PART1_END=$((${PART1_START} + ${PART1_REAL_DIM})) REAL_DIM=$((${PART1_REAL_DIM} + ${PART2_REAL_DIM})) # Add both partitions REAL_DIM=$((${REAL_DIM} + 5)) # Add 5 extra megabytes just in case PART2_START=$((${PART1_END} + 1)) # One megabyte after first partition ending PART2_END=$((${PART2_START} + ${PART2_REAL_DIM})) # Fill requested space dd if=/dev/zero of=${ISO_FILENAME} bs=1024k count=0 seek=${REAL_DIM} echo "!!! The following error/warning messages can be ignored !!!" if [ "${MODE}" == "gpt" ] ; then /sbin/parted --script -- ${ISO_FILENAME} \ mklabel gpt \ mkpart primary ${PART0_START}mib ${PART0_END}mib \ set ${PART0_NUMBER} bios_grub on \ mkpart primary fat32 ${PART1_START}mib ${PART1_END}mib \ set ${PART1_NUMBER} boot on \ mkpart primary fat32 ${PART2_START}mib ${PART2_END}mib else /sbin/parted --script -- ${ISO_FILENAME} \ mklabel msdos \ mkpart primary fat32 ${PART1_START}mib ${PART1_END}mib \ set ${PART1_NUMBER} boot on \ set ${PART1_NUMBER} lba off \ mkpart primary fat32 ${PART2_START}mib ${PART2_END}mib fi # Step 2: Prepare the isos filesystem FREELO="$(losetup --show -f -P ${ISO_FILENAME})" mkfs.vfat -F 32 -n "SG2DISOS" ${FREELO}p${PART2_NUMBER} SG2D_USB_TMP_MOUNT=$(mktemp -d) mount ${FREELO}p${PART2_NUMBER} ${SG2D_USB_TMP_MOUNT} mkdir -p ${SG2D_USB_TMP_MOUNT}/BOOTISOS cat << EOF > ${SG2D_USB_TMP_MOUNT}/BOOTISOS/README.TXT 1) Put here your GNU/Linux distribution isos based on: loopback.cfg and Super Grub2 Disk will find them and offer you to boot them. More information at: https://www.supergrubdisk.org/wiki/Loopback.cfg 2) You can use gparted or another tool to extend this second partition to fill your usb device. You will have to unmount or extract in a saffer manner the device before running gparted (or similar tool). EOF umount ${SG2D_USB_TMP_MOUNT} rmdir ${SG2D_USB_TMP_MOUNT} Lodetach ${FREELO} # Step 3: Prepare the filesystem FREELO="$(losetup --show -f -P ${ISO_FILENAME})" mkfs.vfat -F 32 -n "SG2DBOOT" ${FREELO}p${PART1_NUMBER} # Step 4: Mount boot partition SG2D_USB_TMP_MOUNT=$(mktemp -d) mount ${FREELO}p${PART1_NUMBER} ${SG2D_USB_TMP_MOUNT} # Step 5: Install hybrid Grub mkdir -p ${overlay}/EFI mkdir -p ${overlay}/boot/grub cat > ${overlay}/boot/grub/device.map <