3 # Purpose: create a multiboot grml ISO using grml2usb
4 # Authors: Michael Prokop <mika@grml.org>,
5 # Thorsten Glaser <tg@mirbsd.org>
6 # Bug-Reports: see http://grml.org/bugs/
7 # License: This file is licensed under the GPL v2 or any later version.
8 ################################################################################
10 # make sure we have the sbin directories in our PATH to find grml2usb ootb
11 PATH="${PATH}:/sbin:/usr/local/sbin:/usr/sbin"
13 # define function getfilesize before "set -e" {{{
14 if stat --help >/dev/null 2>&1; then
15 getfilesize='stat -c %s' # GNU stat
17 getfilesize='stat -f %z' # BSD stat
21 # adjust variables if necessary through environment {{{
22 # path to the grml2usb script you'd like to use
23 [ -n "$GRML2USB" ] || GRML2USB='grml2usb'
24 # work directory for creating the filesystem
25 [ -n "$TMPDIR" ] && WRKDIR="${TMPDIR}/grml2iso.tmp"
26 [ -n "$WRKDIR" ] || WRKDIR='/tmp/grml2iso.tmp'
27 # support mkisofs as well as genisoimage
28 if which xorriso >/dev/null 2>&1 ; then
29 MKISOFS='xorriso -as mkisofs'
30 elif which mkisofs >/dev/null 2>&1; then
32 elif which genisoimage >/dev/null 2>&1; then
35 echo "Error: neither xorriso nor mkisofs nor genisoimage available - can not create ISO." >&2
39 if ! which isohybrid >/dev/null 2>&1 ; then
40 echo "Error: isohybrid executable not found (install syslinux/isolinux/syslinux-utils?)." >&2
49 echo >&2 "Usage: $0 [OPTIONS] -o target.iso source1.iso [source2.iso ...]"
52 -b Boot Params Additional boot parameters passed to grml2usb
53 -c Directory Copy files from directory to generated ISO
54 -f Force overwrite of existing target.iso
55 -r BootParam Remove specified boot params.
56 Can be specified multiple times.
57 -p <grml2usb param> Add the specified parameter to the grml2usb
58 commandline. For a list of valid parameters have
59 a look at the grml2usb manpage.
60 Can be specified multiple times.
61 -s URI Generate a small ISO file which downloads the squashfs
62 file from the specified URI. Please note that due to
63 restrictions in the bootprocess only IPs are allowed.
64 Supported protocols are: http and ftp
65 -t Directory Directory that should be used for temporary files
66 during build. Defaults to /tmp/grml2iso.tmp if unset.
69 $0 -s http://192.168.23.42:8000/grml/ -o small.iso grml64-small_2018.12.iso
71 Will generate a file small.iso which tries to download the squashfs file from
72 http://192.168.23.42:8000/grml/ - the squashfs file is placed in the same
73 output directory as the ISO file.
75 [ -n "$1" ] && exit $1 || exit 1
79 # command line handling {{{
80 [[ $# -gt 2 ]] || usage 1
87 typeset -a GRML2USB_OPTS
88 while getopts fb:c:o:r:p:s:t: name; do
90 o) ISOFILE="$OPTARG";;
91 b) GRML2USB_OPTS+=(--bootoptions="$OPTARG");;
92 c) DIR="$(readlink -f "$OPTARG")"; [ -n "$DIR" ] || { echo "Could not read $OPTARG - exiting" >&2 ; exit 1 ; } ;;
94 r) GRML2USB_OPTS+=(--remove-bootoption="$OPTARG");;
95 p) GRML2USB_OPTS+=("$OPTARG");;
97 t) WRKDIR="$(readlink -f "$OPTARG")";;
102 # test for specified URI
103 if [ -n "$URI" ] ; then
104 GRML2USB_OPTS+=(--bootoptions="fetch=$URI")
107 if [ -n "$WRKDIR" ] ; then
108 GRML2USB_OPTS+=(--tmpdir="$WRKDIR")
111 # make sure -o is specified
112 [ -n "$ISOFILE" ] || usage 1
114 # we don't to override any files by accident
115 if [ -e "$ISOFILE" -a ! -n "$FORCE" ]; then
116 echo "Error: target file $ISOFILE exists already." >&2
120 if [ ! -z "$DIR" -a ! -d "$DIR" ] ; then
121 echo "Error: specified parameter for -c is not a directory" >&2
126 # we need root permissions for executing grml2usb {{{
127 if [[ $(id -u) != 0 ]]; then
128 echo >&2 "Error: please run $0 as root."
133 # check for grml2usb {{{
134 if [ ! -x "$(which $GRML2USB)" ] && [ ! -x "$GRML2USB" ] ; then
135 echo "Error: Could not find grml2usb executable. Is /usr/sbin missing in PATH?" >&2
136 echo "Tip: run GRML2USB=/usr/sbin/grml2usb grml2iso ... as workaround" >&2
137 if [ -x "./$GRML2USB" ] ; then
138 echo >&2 "If you executed grml2iso from the grml2usb repository use"
139 echo >&2 "GRML2USB=./grml2usb $0 $*"
151 *) ISOFILE=$ORIG_DIR/$ISOFILE ;;
155 # create necessary stuff under WRKDIR {{{
156 [ -d "$WRKDIR" ] && WRKDIR_EXISTED='true' || WRKDIR_EXISTED='false'
157 rm -rf "$WRKDIR/cddir" "$WRKDIR/grub_tmp"
158 mkdir -p "$WRKDIR/cddir"
161 # execute grml2usb with all ISOs you'd like to install {{{
162 # remove all parameters
163 shift $(($OPTIND - 1))
165 $GRML2USB "${GRML2USB_OPTS[@]}" "$@" "$WRKDIR/cddir"
168 # move syslinux to isolinux {{{
169 mv "$WRKDIR"/cddir/boot/syslinux "$WRKDIR"/cddir/boot/isolinux
170 echo "menu label ^Isolinux prompt" > "$WRKDIR"/cddir/boot/isolinux/promptname.cfg
171 echo "include hd.cfg" >> "$WRKDIR"/cddir/boot/isolinux/grmlmain.cfg
174 # change to $WRKDIR {{{
175 # make sure $WRKDIR is an absolute path, otherwise accessing files
176 # in it will fail later in the code path if user provided a
178 WRKDIR=$(realpath $WRKDIR)
183 # default, independent of UEFI support
184 BOOT_ARGS="-no-emul-boot -boot-load-size 4 -boot-info-table -b boot/isolinux/isolinux.bin -c boot/isolinux/boot.cat"
189 echo "Using xorriso for ISO generation."
190 if ! dpkg --compare-versions $(dpkg-query -W -f='${Version}\n' xorriso 2>/dev/null) gt-nl 1.1.6-1 ; then
191 echo "Disabling (U)EFI boot support since xorriso version is not recent enough."
193 echo "xorriso with -eltorito-alt-boot support present"
196 if ! [ -r "${WRKDIR}/cddir/boot/efi.img" ] ; then
197 echo "Warning: File /boot/efi.img not found, not extending boot arguments for (U)EFI boot."
200 echo "/boot/efi.img found, extending boot arguments for (U)EFI boot."
201 BOOT_ARGS="$BOOT_ARGS -boot-info-table -eltorito-alt-boot -e boot/efi.img -no-emul-boot"
206 echo "Using $MKISOFS for ISO generation (lacking UEFI option), disabling (U)EFI boot support."
211 # adjust ISO for small output if necessary {{{
212 if [ -n "$URI" ] ; then
213 bootloader_files=$(find . -name "*.cfg" -type f)
214 bootloader_files+=" "
215 bootloader_files+=$(find . -name "*.lst" -type f)
216 output_dir=$(dirname "$ISOFILE")
217 for squashfs in $(find . -name *.squashfs) ; do
218 media_path="$(dirname "$squashfs")"
219 filename="$(basename "$squashfs")"
220 target="$output_dir/$filename"
221 if [ -f "$target" ] && [ ! -n "$FORCE" ] ; then
222 echo >&2 "Warning: $target already exists, and -force not specified, not overwriting"
225 OUTPUT_FILES+=("$target")
227 sed -i -e "s#^\(^.*$media_path.*\)\($URI\)\(.*$\)#\1$URI/$filename\3#g" $bootloader_files
233 # copy specified directory to cd {{{
234 if [ -n "$DIR" ] ; then
235 echo >&2 "Copying ${DIR} to generated ISO"
236 for param in GRML_NAME VERSION RELEASENAME DATE SHORT_NAME \
237 VERSION BOOTID RELEASE_INFO ; do
238 EXCLUDE_PARAM="$EXCLUDE_PARAM --exclude **%${param}%**"
240 rsync -a ${DIR}/ $EXCLUDE_PARAM .
243 # adjust files from overlay directory
244 for GRML_VERSION_FILE in $(find . -name grml-version) ; do
245 GRML_NAME=$(awk '{print $1}' "$GRML_VERSION_FILE")
246 VERSION=$(awk '{print $2}' "$GRML_VERSION_FILE")
247 RELEASENAME=$(sed 's/.*- \(.*\).*\[.*/\1/' "$GRML_VERSION_FILE")
248 DATE=$(sed 's/.*\[\(.*\)].*/\1/' "$GRML_VERSION_FILE")
249 SHORT_NAME="$(echo $GRML_NAME | tr -d ',./;\- ')"
250 RELEASE_INFO="$GRML_NAME $VERSION - $RELEASENAME"
251 BOOTID=$(cat conf/bootid.txt)
253 for param in GRML_NAME VERSION RELEASENAME DATE SHORT_NAME \
254 RELEASE_INFO BOOTID ; do
255 value="$(eval echo '$'"$param")"
257 # copy parameterized files from the overlay directory
258 for file in $(find ${DIR} -name "*%$param%*") ; do
260 target_dir="$(dirname ${file})"
261 mkdir -p "$target_dir" || true
262 cp -r ${DIR}/${file} ./${target_dir}/"$(basename ${file/\%${param}\%/$value})"
265 # adjust config files
266 for file in ./boot/isolinux/*.cfg ./boot/isolinux/*.msg \
267 ./boot/grub/*.cfg ; do
268 sed -i "s/%$param%/$value/g" ${file} 2>/dev/null || true
274 # generate the CD/DVD ISO {{{
275 $MKISOFS -V 'grml-multiboot' -l -r -J -no-pad $BOOT_ARGS \
279 # pad the output ISO to multiples of 256 KiB for partition table support {{{
280 siz=$($getfilesize "$ISOFILE")
281 cyls=$(($siz / 512 / 32 / 16 + 1)) # C=$cyls H=16 S=32
282 ofs=$(($cyls * 16 * 32 * 512 - 1)) # padding offset (size - 1)
283 dd if=/dev/zero bs=1 count=1 seek=$ofs of="$ISOFILE" 2>/dev/null
286 # make ISO dd-able {{{
287 if ! $UEFI_ENABLE ; then
288 echo "Skipping check for --uefi option in isohybrid since prerequisites are not fulfilled."
290 if ! isohybrid --help | grep -q -- --uefi ; then
291 echo "isohybrid version does NOT support --uefi option, disabling"
293 echo "isohybrid version supports --uefi option"
294 ISOHYBRID_OPTIONS=--uefi
298 echo "Creating dd-able ISO using isohybrid"
299 isohybrid $ISOHYBRID_OPTIONS "$ISOFILE"
305 rm -rf "$WRKDIR/cddir" "$WRKDIR/grub_tmp"
306 [[ $WRKDIR_EXISTED = 'false' ]] && rmdir "$WRKDIR"
307 echo "Generated $ISOFILE"
308 if [ -n "$URI" ] ; then
312 You requested to generate a small ISO image. Your generated
313 ISO image $ISOFILE does _not_ contain the squashfs files from
314 the source ISO images.
316 You have to provide the extracted squashfs files under $URI.
319 Squashfs files: ${OUTPUT_FILES[@]}
325 ## EOF #########################################################################
326 # vim:foldmethod=marker ts=2 ft=sh ai expandtab tw=80 sw=2