#!/bin/bash # # Script de creation d'un media bootable Debian # Pour l'ACAQB # # Dépend : syslinux,wget # OPTIND=1 # Default Variables debian_arch="amd64" debian_version=$(wget -q --output-document - https://cdimage.debian.org/debian-cd/ | \ grep -o '[0-9]\{1,2\}\.[0-9]\{1,2\}\.[0.9]\{1,2\}' | head -1) archive=0 boot_type="efi64" repo_dir="repo" tmp_dir="tmp" current_dir=`pwd` # In Archlinux, this is default files for syslinux... conf_file="conf/archlinux.conf" key_mountpoint="/mnt/usbstick" device="" # constant APP_NAME="Debian USB Creator" VERSION="1.99.0" SYSLINUX_EXE=$(command -v syslinux) PARTED_EXE=$(command -v parted) MCOPY=$(command -v mtoos) SYSLINUX_FILES="menu.c32 vesamenu.c32 libutil.c32 libcom32.c32" SYSLINUX_BIOS_FILES="" SYSLINUX_EFI_FILES="ldlinux.e64" process_args() { # While getops doesn't handle long parameters # I need an personnal function # Inspired by http://mywiki.wooledge.org/BashFAQ/035 while :; do case $1 in -h|-\?|--help) usage exit 0 ;; -a|--arch) if [[ $2 == "amd64" || $2 == "i386" ]] then debian_arch=$2 shift else printf "Error : CPU architecture must be amd64 or i386" exit 1 fi ;; -b|--bios) boot_type="bios" ;; -c|--conf) if [ -f $2 ] then conf_file=$2 else printf "%s file not found" $2 exit 1 fi shift ;; -d|--device) if [ -b $2 ] then device=$2 shift else printf "%s doesn't a block device, exiting" "$2" exit 1 fi ;; --debian-version) if [[ $debian_version != $2 ]] then archive=1 debian_version=$2 fi shift ;; --repo) repo_dir=$2 shift ;; --tmp) tmp_dir=$2 shift ;; -v|--version) show_version exit 0 ;; *) break esac shift done } usage() { cat << EOF USAGE: ${0} [-a architecture] [-b] -a | --arch Select CPU Architecture amd64 | i386 CPU -b | --bios Create a bios bott compatible key -d | --device Device_block USB key to write --debian-version Choose Debian Version to download --repo Repo directory (defaukt is ./repo) --temp Temp directory (default is ./tmp) -v | --version Show version ${0} initialize an usb key for Debian automatic install with preseed and a partman recipe. EOF } show_version () { printf "%s %s 2016-2017 ephase@xieme-art.org\n" "$APP_NAME" "$VERSION" } download (){ #Download function # $1 : filename # $2 : url # $3 : 1 if abort download if file exist printf "Downloading %s : " "$1" local url local http_response url="$2/$1" http_response=$(wget --spider --server-response "$url" 2>&1 | grep HTTP/ | tail -1 | awk ' { printf $2 }') if [ "$http_response" -eq 200 ] then wget -c --progress=dot "$url" 2>&1 | grep --line-buffered "[0-9]\{1,3\}%" -o | awk '{printf ("\b\b\b\b%4s", $1)}' if [ $? -eq 0 ] then printf " \b\b\b\b\b done\n " else printf " error, exiting.\n" exit 1 fi else printf "Error 404 : file not found, exiting\n" exit 1 fi } process_conf_file (){ while read -r p do var=$(echo "$p" | awk -F"=" '{print $1}') param=$(echo "$p" | awk -F"=" '{print $2}') eval "$var"="$param" done < <( cat "$1" | grep '^[^#].*') } create_dir(){ # $1 directory to create if [ ! -d "$1" ] then mkdir -p "$1" else if [ -n "$2" ] && [ "$2" -eq 1 ] then rm -rf "$1" create_dir "$1" fi fi } # unmount if device is mounted umount_device (){ local mounted_part="" mounted_part=$(mount | grep "${1}[0-9]" | awk '{print $3}') if [ ! "$mounted_part" == "" ] then for part in $mounted_part do if [ -d "$part" ] then printf "Unmount %s\n " "$part" umount "$part" --recursive fi done fi } efi_create_key_structure () { parted -s "$1" mklabel gpt mkpart EFS fat32 1MiB 128MiB set 1 boot on mkpart debian fat32 128MiB 100% sleep 2 mkfs.vfat "${1}1" -n efi &> /dev/null mkfs.vfat "${1}2" -n debian &> /dev/null sync mount "${1}2" "$2" create_dir "$2/efi" mount "${1}1" "$2/efi" } bios_create_key_structure() { parted -s "$1" mklabel msdos mkpart primary fat32 1MiB 100% set 1 boot on sleep 2 mkfs.vfat "${1}1" -n debian &> /dev/null mount "${1}1" "$2" } #Stop script if syslinux is not installed if [ -z "$SYSLINUX_EXE" ] then printf "Syslinux not found, script can't continue.\n" exit 1 fi if [ -z "$PARTED_EXE" ] then printf "Parted not found, script can't continue.\n" exit 1 fi process_args "$@" process_conf_file "$conf_file" if [[ ! -d "$syslinux_mbr_bl_folder" || ! -d "$syslinux_efi_bl_folder" || ! -d "$syslinux_modules_folder" ]] then printf "Bad folder configuration in %s\n" "$conf_file" exit 1 fi if [ "$boot_type" == "bios" ] && [ -z "$MCOPY" ] then printf "Bios key creation need mcopy from mtools packages\n" exit 1 fi bootfiles_Debian="http://ftp.debian.org/debian/dists/stable/main/installer-${debian_arch}/current/images/hd-media" if [ $archive -eq 1 ] then iso_url="http://cdimage.debian.org/cdimage/archive/${debian_version}/${debian_arch}/iso-cd" else iso_url="http://cdimage.debian.org/debian-cd/${debian_version}/${debian_arch}/iso-cd" fi iso_file="debian-${debian_version}-${debian_arch}-netinst.iso" repo_path="$repo_dir/$debian_arch/$debian_version" # Download Debian files (kernel, initrd and iso) printf "Downloading Debian files\n---\n" # Création du répertoire temporaire create_dir "$repo_path" cd "$repo_path" download "$iso_file" "$iso_url" 1 for file in "vmlinuz" "initrd.gz" do download "$file" "$bootfiles_Debian" 1 done cd "$current_dir" if [ -z "$device" ] then printf "No destination device specified, USB key will not be created.\n" fi create_dir "$tmp_dir" 1 cp "$repo_path/$iso_file" "$tmp_dir" # Copy wanted syslinux file from archive case $boot_type in efi64) syslinux_folder=${tmp_dir}/efi/EFI/boot create_dir "$syslinux_folder" cp -T "$syslinux_efi_bl_folder/$boot_type/syslinux.efi" "$syslinux_folder/bootx64.efi" &> /dev/null for file in $SYSLINUX_EFI_FILES do printf "copying %s \n" "$file" cp "$syslinux_modules_folder/$boot_type/$file" "$syslinux_folder" done cp "$repo_path"/{vmlinuz,initrd.gz} "$tmp_dir/efi" cp -R syslinux/syslinux.cfg "$syslinux_folder" &> /dev/null ;; bios) syslinux_folder=${tmp_dir}/syslinux create_dir "$syslinux_folder" for file in $SYSLINUX_BIOS_FILES do printf "copying %s\n" "$file" cp "$syslinux_modules_folder/$boot_type/$file" "$syslinux_folder" done cp "$repo_path"/{vmlinuz,initrd.gz} "$tmp_dir" cp -R syslinux "$tmp_dir" &> /dev/null ;; esac for file in $SYSLINUX_FILES do printf "copying %s\n" "$file" cp "$syslinux_modules_folder/$boot_type/$file" "$syslinux_folder" done echo Copying configurations files create_dir "$tmp_dir/partman_recipes" cp -R partman_recipes "$tmp_dir" &> /dev/null create_dir "$tmp_dir/preseeds" cp -R preseeds "$tmp_dir" &> /dev/null if [ -n "$device" ] then printf "Partitionning and formating %s\n" "$device" read -p "[WARNING] Disk $device will be erased continue [Y/N]? " -n 1 -r if [[ ! $REPLY =~ ^[Yy]$ ]] then exit 1 fi printf "\n\n" umount_device "$device" create_dir "$key_mountpoint" #dd if=/dev/zero of=${dest} bs=512 count=1 conv=notrunc &> /dev/null case "$boot_type" in "efi64") efi_create_key_structure "$device" "$key_mountpoint" ;; "bios") bios_create_key_structure "$device" "$key_mountpoint" ;; esac printf "copying all file to USB drive\n" cp -R "$tmp_dir"/* "$key_mountpoint" umount_device "$device" sleep 5 # Make key bootable if bios. if [ "$boot_type" = "bios" ] then # In this mode, we need to write syslinux MBR. printf "Writing syslinux mbr.ini to %s\n" "$device" dd bs=440 count=1 conv=notrunc if="$syslinux_mbr_bl_folder"/mbr.bin of="$device" sleep 2 "$SYSLINUX_EXE" --directory /syslinux --install "${device}1" fi rm -rf "$tmp_dir" printf "\nBootable USB key created\n" exit 0 fi