# 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 <