#!/bin/bash set -e -u # editions declare -ar VALID_INITS=('openrc' 'systemd') declare -ar VALID_GUIS=('cli' 'lxde' 'mate') # edition-specific strings iso_title="Parabola GNU/Linux-libre Live" # $iso_edition and $iso_version appended # CLI option defaults iso_edition="SystemD/CLI" archs='i686 x86_64' iso_arch='dual' iso_version=$(date +%Y.%m.%d) iso_label="PARA_$(date +%Y%m)" iso_dirname='parabola' enable_offline_install='false' offline_switch='' work_dir=./work out_dir=./out target='' verbose='' efi_img_kbytes=40000 pacman_conf=${work_dir}/pacman.conf # environment data_dir=/usr/share/parabolaiso/data releng_dir=$(readlink -f ${0%/*}) initcpio_dir=${releng_dir}/../../parabolaiso/initcpio packages_dir=${releng_dir}/packages [ "`which mkparabolaiso 2> /dev/null`" ] || export PATH=$PATH:"${releng_dir}/../../parabolaiso" _usage () { echo "usage ${0} [options]" echo echo " General options:" echo " -E Release edition (init/WM pair e.g. 'SystemD/CLI')" echo " Default: ${iso_edition}" echo " -T Target architecture (one of 'i686', 'x86_64', or 'dual')" echo " Default: ${iso_arch}" echo " -V Set the iso version in the filename" echo " Default: ${iso_version}" echo " -L Set the iso volume label" echo " Default: ${iso_label}" echo " -D Set the name of the directory inside the ISO" echo " Default: ${iso_dirname}" echo " -O Enable offline install." echo " Default: '${enable_offline_install}'" echo " -C Specify the pacman.conf file used for chroot install." echo " Default: '${pacman_conf}'" echo " -w Set the working directory" echo " Default: ${work_dir}" echo " -o Set the output directory" echo " Default: ${out_dir}" echo " -v Enable verbose output" echo " -h This help message" exit ${1} } LOG_STEP() { printf "\033[01;34m%s\033[00m\n" "$(echo -e $*)" ; } LOG_ERROR() { printf "\033[00;31m%s\033[00m\n" "$(echo -e $*)" ; } # Helper function to run make_*() only one time per architecture. run_once() { local buid_stamp="build.${1}_${arch}" if [[ ! -e ${work_dir}/${buid_stamp} ]]; then LOG_STEP "runnning build step: '${buid_stamp}'" $1 touch ${work_dir}/${buid_stamp} fi } # Setup custom pacman.conf to cache packages on the target filesystem. make_pacman_conf() { sed -r "s|^#?\\s*CacheDir.+|CacheDir = ${work_dir}/${arch}/root-image/isorepo/|g" ${releng_dir}/pacman.conf > ${pacman_conf} } # Base installation, plus needed packages (root-image) make_basefs() { setarch ${arch} mkparabolaiso ${verbose} -w ${work_dir}/${arch} -C ${pacman_conf} -D ${iso_dirname} -B ${base_group} init setarch ${arch} mkparabolaiso ${verbose} -w ${work_dir}/${arch} -C ${pacman_conf} -D ${iso_dirname} -p "memtest86+ mkinitcpio-nfs-utils nbd" install } # Additional packages (root-image) make_packages() { local _packages_msg="standard packages as declared in the following files:" local _gui_packages_msg="non-graphical packages as declared in the following files:" # standard package lists local _install_base_lists=$( ls ${packages_dir}/packages-{all,${iso_init}}.{all,${arch}} 2> /dev/null || true) local _cache_base_lists=$( ls ${packages_dir}/cache-{all,${iso_init}}.{all,${arch}} 2> /dev/null || true) # gui-specific package lists local _install_gui_lists=$( ls ${packages_dir}/packages-{gui,${iso_gui}}.{all,${arch}} 2> /dev/null || true) local _cache_gui_lists=$( ls ${packages_dir}/cache-{gui,${iso_gui}}.{all,${arch}} 2> /dev/null || true) # init-specific gui package lists local _install_initgui_lists=$(ls ${packages_dir}/packages-${iso_init}-gui.{all,${arch}} 2> /dev/null || true) local _cache_initgui_lists=$( ls ${packages_dir}/cache-${iso_init}-gui.{all,${arch}} 2> /dev/null || true) _install_base_lists=${_install_base_lists// /} _cache_base_lists=${_cache_base_lists// /} _install_gui_lists=${_install_gui_lists// /} _cache_gui_lists=${_cache_gui_lists// /} _install_initgui_lists=${_install_initgui_lists// /} _cache_initgui_lists=${_cache_initgui_lists// /} # collect standard packages local _install_base_packages=$( [ "${_install_base_lists}" ] && grep -hv ^# ${_install_base_lists}) local _cache_base_packages=$( [ "${_cache_base_lists}" ] && grep -hv ^# ${_cache_base_lists}) # collect gui-specific packages local _install_gui_packages=$( [ "${_install_gui_lists}" ] && grep -hv ^# ${_install_gui_lists}) local _cache_gui_packages=$( [ "${_cache_gui_lists}" ] && grep -hv ^# ${_cache_gui_lists}) # collect init-specific gui packages local _install_initgui_packages=$([ "${_install_initgui_lists}" ] && grep -hv ^# ${_install_initgui_lists}) local _cache_initgui_packages=$( [ "${_cache_initgui_lists}" ] && grep -hv ^# ${_cache_initgui_lists}) if [[ "${iso_gui}" != 'cli' ]]; then _gui_packages_msg="${_gui_packages_msg/non-graphical/graphical}" _install_gui_lists="${_install_gui_lists} ${_install_initgui_lists}" _cache_gui_lists="${_cache_gui_lists} ${_cache_initgui_lists}" _install_gui_packages="${_install_gui_packages} ${_install_initgui_packages}" _cache_gui_packages="${_cache_gui_packages} ${_cache_initgui_packages}" fi # display results _install_gui_lists=${_install_gui_lists// /} _cache_gui_lists=${_cache_gui_lists// /} _cache_base_packages=${_cache_base_packages// /} _install_gui_packages=${_install_gui_packages// /} _cache_gui_packages=${_cache_gui_packages// /} local _install_packages="${_install_base_packages} ${_install_gui_packages}" local _cache_packages="${_cache_base_packages} ${_cache_gui_packages}" _install_packages=${_install_packages// /} _cache_packages=${_cache_packages// /} [ "${_install_base_packages}" ] && echo "Installing ${_packages_msg}" && echo "${_install_base_lists}" | sed "s/.*\//\t/" [ "${_cache_base_packages}" ] && echo "Caching ${_packages_msg}" && echo "${_cache_base_lists}" | sed "s/.*\//\t/" [ "${_install_gui_packages}" ] && echo "Installing ${_gui_packages_msg}" && echo "${_install_gui_lists}" | sed "s/.*\//\t/" [ "${_cache_gui_packages}" ] && echo "Caching ${_gui_packages_msg}" && echo "${_cache_gui_lists}" | sed "s/.*\//\t/" # install packages setarch ${arch} mkparabolaiso ${verbose} -w ${work_dir}/${arch} -C ${pacman_conf} -D ${iso_dirname} -p "${_install_packages}" install # create live environment local repo or stash package cache if [[ "$enable_offline_install" == 'true' ]]; then if [[ -n ${_cache_packages} ]]; then # download any cache packages and prune obsolete packages setarch ${arch} mkparabolaiso ${verbose} -w ${work_dir}/${arch} -C ${pacman_conf} -D ${iso_dirname} -p "${_cache_packages}" ${offline_switch} cache fi # create 'isorepo' for offline install pushd ${work_dir}/${arch}/root-image/isorepo > /dev/null setarch ${arch} repo-add --new isorepo.db.tar.gz ./* popd > /dev/null else # stash package cache for next build mv ${work_dir}/${arch}/root-image/isorepo ${work_dir}/../isorepo-${arch} || true fi # refresh pacman keyring in chroot # cp -r /etc/pacman.d/gnupg/ ./hostgnupg/ # cp -r ${work_dir}/${arch}/root-image/etc/pacman.d/gnupg/ ./chrootgnupg/ # arch-chroot ${work_dir}/${arch}/root-image rm -rf /etc/pacman.d/gnupg/ && \ # pacman-key --init && \ # pacman -S --noconfirm archlinux-keyring \ # archlinux32-keyring \ # archlinuxarm-keyring \ # parabola-keyring && \ # pacman-key --populate archlinux archlinux32 \ # archlinuxarm parabola && \ # pacman-key --refresh && \ # pacman -S --noconfirm archlinux-keyring \ # archlinux32-keyring \ # archlinuxarm-keyring \ # parabola-keyring ; # echo "ls ./hostgnupg/" ; ls -al /etc/pacman.d/gnupg/ ./hostgnupg/ # echo "ls ./chrootgnupg/" ; ls -al ${work_dir}/${arch}/root-image/etc/pacman.d/gnupg/ ./chrootgnupg/ } # Copy mkinitcpio parabolaiso hooks and build initramfs (root-image) make_setup_mkinitcpio() { local _hook for _hook in parabolaiso parabolaiso_shutdown parabolaiso_pxe_common parabolaiso_pxe_nbd parabolaiso_pxe_http parabolaiso_pxe_nfs parabolaiso_loop_mnt; do cp ${initcpio_dir}/hooks/${_hook} ${work_dir}/${arch}/root-image/usr/lib/initcpio/hooks cp ${initcpio_dir}/install/${_hook} ${work_dir}/${arch}/root-image/usr/lib/initcpio/install done cp ${initcpio_dir}/install/parabolaiso_kms ${work_dir}/${arch}/root-image/usr/lib/initcpio/install cp ${initcpio_dir}/hooks/parabolaiso_shutdown ${work_dir}/${arch}/root-image/usr/lib/initcpio cp ${releng_dir}/mkinitcpio.conf ${work_dir}/${arch}/root-image/etc/mkinitcpio-parabolaiso.conf setarch ${arch} mkparabolaiso ${verbose} -w ${work_dir}/${arch} -C ${pacman_conf} -D ${iso_dirname} -r 'mkinitcpio -c /etc/mkinitcpio-parabolaiso.conf -k /boot/vmlinuz-linux-libre -g /boot/parabolaiso.img' run } # Customize installation (root-image) make_customize_root_image() { cp -af ${releng_dir}/root-image ${work_dir}/${arch} echo "Customizing root image" arch="${arch}" \ iso_title="${iso_title}" \ iso_init="${iso_init}" \ iso_gui="${iso_gui}" \ enable_offline_install="${enable_offline_install}" \ setarch ${arch} mkparabolaiso ${verbose} -w ${work_dir}/${arch} \ -C ${pacman_conf} \ -D ${iso_dirname} \ ${offline_switch} \ -r /root/customize_root_image.sh \ run rm ${work_dir}/${arch}/root-image/root/customize_root_image* } # Prepare kernel/initramfs ${iso_dirname}/boot/ make_boot() { mkdir -p ${work_dir}/iso/${iso_dirname}/boot/${arch} cp ${work_dir}/${arch}/root-image/boot/parabolaiso.img ${work_dir}/iso/${iso_dirname}/boot/${arch}/parabolaiso.img cp ${work_dir}/${arch}/root-image/boot/vmlinuz-linux-libre ${work_dir}/iso/${iso_dirname}/boot/${arch}/vmlinuz } # Add other aditional/extra files to ${iso_dirname}/boot/ make_boot_extra() { cp ${work_dir}/${arch}/root-image/boot/memtest86+/memtest.bin ${work_dir}/iso/${iso_dirname}/boot/memtest cp ${work_dir}/${arch}/root-image/usr/share/licenses/common/GPL2/license.txt ${work_dir}/iso/${iso_dirname}/boot/memtest.COPYING } # Prepare /${iso_dirname}/boot/syslinux make_syslinux() { mkdir -p ${work_dir}/iso/${iso_dirname}/boot/syslinux for _cfg in ${releng_dir}/syslinux/*.cfg; do sed "s|%PARABOLAISO_LABEL%|${iso_label}|g; s|%INSTALL_DIR%|${iso_dirname}|g" ${_cfg} > ${work_dir}/iso/${iso_dirname}/boot/syslinux/${_cfg##*/} done cp ${releng_dir}/syslinux/syslinux-splash-${iso_init}.png ${work_dir}/iso/${iso_dirname}/boot/syslinux/splash.png cp ${work_dir}/${arch}/root-image/usr/lib/syslinux/bios/*.c32 ${work_dir}/iso/${iso_dirname}/boot/syslinux cp ${work_dir}/${arch}/root-image/usr/lib/syslinux/bios/lpxelinux.0 ${work_dir}/iso/${iso_dirname}/boot/syslinux cp ${work_dir}/${arch}/root-image/usr/lib/syslinux/bios/memdisk ${work_dir}/iso/${iso_dirname}/boot/syslinux mkdir -p ${work_dir}/iso/${iso_dirname}/boot/syslinux/hdt gzip -c -9 ${work_dir}/${arch}/root-image/usr/share/hwdata/pci.ids > ${work_dir}/iso/${iso_dirname}/boot/syslinux/hdt/pciids.gz gzip -c -9 ${work_dir}/${arch}/root-image/usr/lib/modules/*-gnu-*/modules.alias > ${work_dir}/iso/${iso_dirname}/boot/syslinux/hdt/modalias.gz # inject edition title into boot menu sed -i "s|_EDITION_TITLE_|${iso_title}|" ${work_dir}/iso/${iso_dirname}/boot/syslinux/parabolaiso_head.cfg # prune orphan boot entries for single-architecture ISO if [[ "${archs}" == 'i686' ]]; then rm ${work_dir}/iso/${iso_dirname}/boot/syslinux/parabolaiso_*64*.cfg elif [[ "${archs}" == 'x86_64' ]]; then rm ${work_dir}/iso/${iso_dirname}/boot/syslinux/parabolaiso_*32*.cfg fi } # Prepare /isolinux make_isolinux() { mkdir -p ${work_dir}/iso/isolinux sed "s|%INSTALL_DIR%|${iso_dirname}|g" ${releng_dir}/isolinux/isolinux.cfg > ${work_dir}/iso/isolinux/isolinux.cfg cp ${work_dir}/${arch}/root-image/usr/lib/syslinux/bios/isolinux.bin ${work_dir}/iso/isolinux/ cp ${work_dir}/${arch}/root-image/usr/lib/syslinux/bios/isohdpfx.bin ${work_dir}/iso/isolinux/ cp ${work_dir}/${arch}/root-image/usr/lib/syslinux/bios/ldlinux.c32 ${work_dir}/iso/isolinux/ } # Prepare /EFI make_efi() { mkdir -p ${work_dir}/iso/EFI/boot if [[ "${iso_init}" == 'systemd' ]]; then cp ${work_dir}/x86_64/root-image/usr/lib/systemd/boot/efi/systemd-bootx64.efi ${work_dir}/iso/EFI/boot/bootx64.efi fi mkdir -p ${work_dir}/iso/loader/entries cp ${releng_dir}/efiboot/loader/loader.conf ${work_dir}/iso/loader/ cp ${releng_dir}/efiboot/loader/entries/uefi-shell-v2-x86_64.conf ${work_dir}/iso/loader/entries/ cp ${releng_dir}/efiboot/loader/entries/uefi-shell-v1-x86_64.conf ${work_dir}/iso/loader/entries/ sed "s|%PARABOLAISO_LABEL%|${iso_label}|g; s|%INSTALL_DIR%|${iso_dirname}|g" \ ${releng_dir}/efiboot/loader/entries/parabolaiso-x86_64-usb.conf > ${work_dir}/iso/loader/entries/parabolaiso-x86_64.conf # EFI Shell 2.0 for UEFI 2.3+ ( http://sourceforge.net/apps/mediawiki/tianocore/index.php?title=UEFI_Shell ) cp ${data_dir}/Shell.efi ${work_dir}/iso/EFI/shellx64_v2.efi # EFI Shell 1.0 for non UEFI 2.3+ ( http://sourceforge.net/apps/mediawiki/tianocore/index.php?title=Efi-shell ) cp ${data_dir}/Shell_Full.efi ${work_dir}/iso/EFI/shellx64_v1.efi } # Prepare efiboot.img::/EFI for "El Torito" EFI boot mode make_efiboot() { # Cleanup in case of previous aborted run while mount | grep ${work_dir}/efiboot > /dev/null; do umount ${work_dir}/efiboot; sleep 1; done; rm ${work_dir}/iso/EFI/parabolaiso/efiboot.img 2> /dev/null || true # create EFI image mkdir -p ${work_dir}/iso/EFI/parabolaiso truncate -s ${efi_img_kbytes}K ${work_dir}/iso/EFI/parabolaiso/efiboot.img mkfs.vfat -n PARABOLAISO_EFI ${work_dir}/iso/EFI/parabolaiso/efiboot.img mkdir -p ${work_dir}/efiboot mkdir -p ${work_dir}/efiboot-staging mount ${work_dir}/iso/EFI/parabolaiso/efiboot.img ${work_dir}/efiboot mkdir -p ${work_dir}/efiboot-staging/EFI/parabolaiso cp ${work_dir}/iso/${iso_dirname}/boot/x86_64/vmlinuz ${work_dir}/efiboot-staging/EFI/parabolaiso/vmlinuz.efi cp ${work_dir}/iso/${iso_dirname}/boot/x86_64/parabolaiso.img ${work_dir}/efiboot-staging/EFI/parabolaiso/parabolaiso.img mkdir -p ${work_dir}/efiboot-staging/EFI/boot if [[ "${iso_init}" == 'systemd' ]]; then cp ${work_dir}/x86_64/root-image/usr/lib/systemd/boot/efi/systemd-bootx64.efi ${work_dir}/efiboot-staging/EFI/boot/bootx64.efi fi mkdir -p ${work_dir}/efiboot-staging/loader/entries cp ${releng_dir}/efiboot/loader/loader.conf ${work_dir}/efiboot-staging/loader/ cp ${releng_dir}/efiboot/loader/entries/uefi-shell-v2-x86_64.conf ${work_dir}/efiboot-staging/loader/entries/ cp ${releng_dir}/efiboot/loader/entries/uefi-shell-v1-x86_64.conf ${work_dir}/efiboot-staging/loader/entries/ sed "s|%PARABOLAISO_LABEL%|${iso_label}|g; s|%INSTALL_DIR%|${iso_dirname}|g" \ ${releng_dir}/efiboot/loader/entries/parabolaiso-x86_64-cd.conf > ${work_dir}/efiboot-staging/loader/entries/parabolaiso-x86_64.conf cp ${work_dir}/iso/EFI/shellx64_v2.efi ${work_dir}/efiboot-staging/EFI/ cp ${work_dir}/iso/EFI/shellx64_v1.efi ${work_dir}/efiboot-staging/EFI/ efi_kbytes=$(($(du -ks ${work_dir}/efiboot-staging | cut -f 1) + 32)) if [[ ${efi_kbytes} -lt $((${efi_img_kbytes})) ]]; then echo "Populating EFI image (${efi_kbytes}KB)" cp -rT ${work_dir}/efiboot-staging ${work_dir}/efiboot rm -rf ${work_dir}/efiboot-staging umount ${work_dir}/efiboot else echo "Error: Not enough space on EFI image (${efi_img_kbytes}KB - need ${efi_kbytes}KB)" umount ${work_dir}/efiboot exit 1 fi } # Copy aitab make_aitab() { mkdir -p ${work_dir}/iso/${iso_dirname} cp ${releng_dir}/aitab ${work_dir}/iso/${iso_dirname}/aitab } # Build all filesystem images specified in aitab (.fs.sfs .sfs) make_prepare() { cp -a -l -f ${work_dir}/${arch}/root-image ${work_dir} setarch ${arch} mkparabolaiso ${verbose} -w ${work_dir} -D ${iso_dirname} pkglist setarch ${arch} mkparabolaiso ${verbose} -w ${work_dir} -D ${iso_dirname} -C ${pacman_conf} ${offline_switch} prepare rm -rf ${work_dir}/root-image # rm -rf ${work_dir}/${arch}/root-image (if low space, this helps) } # Build ISO make_iso() { mkparabolaiso ${verbose} -w ${work_dir} -D ${iso_dirname} checksum mkparabolaiso ${verbose} -w ${work_dir} -D ${iso_dirname} -L ${iso_label} -o ${out_dir} iso ${iso_filename} } ## prepare state ## # set CLI options while getopts 'E:T:V:L:D:OC:w:o:vh' arg; do case "${arg}" in E) iso_edition="${OPTARG}" ;; T) target="${OPTARG}" ;; V) iso_version="${OPTARG}" ;; L) iso_label="${OPTARG}" ;; D) iso_dirname="${OPTARG}" ;; O) enable_offline_install='true' offline_switch='-O' ;; C) pacman_conf="${OPTARG}" ;; w) work_dir="${OPTARG}" ;; o) out_dir="${OPTARG}" ;; v) verbose="-v" ;; h) _usage 0 ;; *) echo "Invalid argument '${arg}'" _usage 1 ;; esac done # set target arch, GRUB title, and ISO filename case "${target}" in 'i686'|'x86_64') archs=${target} iso_arch=${target} launch_msg="Building single-architecture ${iso_edition} ISO for ${archs}" ;; *) launch_msg="Building multi-architecture ${iso_edition} ISO for ${archs}" ;; esac if [[ "$enable_offline_install" == 'true' ]]; then iso_type='complete' launch_msg="${launch_msg} (offline install enabled)" else iso_type='netinstall' launch_msg="${launch_msg} (net install only)" fi iso_title="${iso_title} - ${iso_edition} Edition ${iso_version}" iso_filename="parabola-${iso_edition}-${iso_arch}-${iso_type}-${iso_version}.iso" iso_filename=$(echo ${iso_filename} | tr '[:upper:]/' '[:lower:]-') iso_init=$(echo ${iso_edition} | cut -d '/' -f 1 | tr '[:upper:]' '[:lower:]') iso_gui=$( echo ${iso_edition} | cut -d '/' -f 2 | tr '[:upper:]' '[:lower:]') [[ "${iso_init}" == 'openrc' ]] && base_group='base-openrc' || base_group='base' [[ "${archs}" == 'i686' ]] && arch='i686' || arch='x86_64' ## sanity checks ## # sanitize paths iso_label=${iso_label// /} iso_dirname=${iso_dirname// /} iso_filename=${iso_filename// /} iso_init=${iso_init// /} iso_gui=${iso_gui// /} work_dir=${work_dir// /} out_dir=${out_dir// /} pacman_conf=${pacman_conf// /} # validate build environment if [[ "$(uname -m)" != 'x86_64' ]] || ! grep 'ID_LIKE=.*archlinux' /usr/lib/os-release > /dev/null; then echo "This script needs to be run on an x86_64 ArchLinux derrivative." exit 1 elif [[ ${EUID} -ne 0 ]]; then echo "This script needs to be run with root privileges." exit 1 elif ! pacman --version | grep libalpm > /dev/null; then echo "This script needs the 'pacman' package manager to be installed." exit 1 elif ! pacman -Qi parabolaiso-data > /dev/null; then echo "This script needs the 'parabolaiso-data' package to be installed." exit 1 elif ! echo "${VALID_INITS[@]}" | tr " " "\n" | grep -E "^${iso_init}$" > /dev/null || \ ! echo "${VALID_GUIS[@]}" | tr " " "\n" | grep -E "^${iso_gui}$" > /dev/null; then echo "Invalid init/wm combination: '${iso_edition}'." exit 1 fi # detect previously completed build prefix=${work_dir}/build.make_ is_done=1 [ ! -f ${prefix}pacman_conf_${arch} -o ! -f ${prefix}boot_extra_${arch} -o \ ! -f ${prefix}syslinux_${arch} -o ! -f ${prefix}isolinux_${arch} -o \ ! -f ${prefix}aitab_${arch} -o ! -f ${prefix}iso_${arch} ] && \ is_done=0 for arch in ${archs}; do [ ! -f ${prefix}basefs_${arch} -o ! -f ${prefix}packages_${arch} -o \ ! -f ${prefix}setup_mkinitcpio_${arch} -o ! -f ${prefix}customize_root_image_${arch} -o \ ! -f ${prefix}boot_${arch} -o ! -f ${prefix}prepare_${arch} ] && \ is_done=0 done if ! (($is_done)); then echo ${launch_msg}; else echo "Nothing to do"; exit; fi; ## build ISO ## # prepare environment chown -R 0:0 "${releng_dir}/root-image/" mkdir -p ${work_dir} # prepare target filesystems for arch in ${archs}; do run_once make_pacman_conf run_once make_basefs run_once make_packages run_once make_setup_mkinitcpio run_once make_customize_root_image done # prepare kernels and initrds for arch in ${archs}; do run_once make_boot done # prepare ISO run_once make_boot_extra run_once make_syslinux run_once make_isolinux # prepare EFI if [[ "`echo ${archs} | grep x86_64`" ]]; then run_once make_efi run_once make_efiboot fi # prepare SFSs run_once make_aitab for arch in ${archs}; do run_once make_prepare done # build ISO run_once make_iso