A tool to create Debian automatic installer USB key with preseed, partman recipe, syslinux and parted.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

337 lines
8.9KB

  1. #!/bin/bash
  2. #
  3. # Script de creation d'un media bootable Debian
  4. # Pour l'ACAQB
  5. #
  6. # Dépend : syslinux,wget
  7. #
  8. OPTIND=1
  9. # Default Variables
  10. debian_arch="amd64"
  11. debian_version=$(wget -q --output-document - https://cdimage.debian.org/debian-cd/ | \
  12. grep -o '[0-9]\{1,2\}\.[0-9]\{1,2\}\.[0.9]\{1,2\}' | head -1)
  13. archive=0
  14. boot_type="efi64"
  15. repo_dir="repo"
  16. tmp_dir="tmp"
  17. current_dir=`pwd`
  18. # In Archlinux, this is default files for syslinux...
  19. conf_file="conf/archlinux.conf"
  20. key_mountpoint="/mnt/usbstick"
  21. device=""
  22. # constant
  23. APP_NAME="Debian USB Creator"
  24. VERSION="1.99.0"
  25. SYSLINUX_EXE=$(which syslinux)
  26. PARTED_EXE=$(which parted)
  27. SYSLINUX_FILES="menu.c32 vesamenu.c32 libutil.c32 libcom32.c32"
  28. SYSLINUX_BIOS_FILES=""
  29. SYSLINUX_EFI_FILES="ldlinux.e64"
  30. process_args() {
  31. # While getops doesn't handle long parameters
  32. # I need an personnal function
  33. # Inspired by http://mywiki.wooledge.org/BashFAQ/035
  34. while :; do
  35. case $1 in
  36. -h|-\?|--help)
  37. usage
  38. exit 0
  39. ;;
  40. -a|--arch)
  41. if [[ $2 == "amd64" || $2 == "i386" ]]
  42. then
  43. debian_arch=$2
  44. shift
  45. else
  46. printf "Error : CPU architecture must be amd64 or i386"
  47. exit 1
  48. fi
  49. ;;
  50. -b|--bios)
  51. boot_type="bios"
  52. ;;
  53. -c|--conf)
  54. if [ -f $2 ]
  55. then
  56. conf_file=$2
  57. else
  58. printf "%s file not found" $2
  59. exit 1
  60. fi
  61. shift
  62. ;;
  63. -d|--device)
  64. if [ -b $2 ]
  65. then
  66. device=$2
  67. shift
  68. else
  69. printf "%s doesn't a block device, exiting" "$2"
  70. exit 1
  71. fi
  72. ;;
  73. --debian-version)
  74. if [[ $debian_version != $2 ]]
  75. then
  76. archive=1
  77. debian_version=$2
  78. fi
  79. shift
  80. ;;
  81. --repo)
  82. repo_dir=$2
  83. shift
  84. ;;
  85. --tmp)
  86. tmp_dir=$2
  87. shift
  88. ;;
  89. -v|--version)
  90. show_version
  91. exit 0
  92. ;;
  93. *)
  94. break
  95. esac
  96. shift
  97. done
  98. }
  99. usage() {
  100. cat << EOF
  101. USAGE: ${0} [-a architecture] [-b]
  102. -a | --arch Select CPU Architecture amd64 | i386 CPU
  103. -b | --bios Create a bios bott compatible key
  104. -d | --device Device_block USB key to write
  105. --debian-version Choose Debian Version to download
  106. --repo Repo directory (defaukt is ./repo)
  107. --temp Temp directory (default is ./tmp)
  108. -v | --version Show version
  109. ${0} initialize an usb key for Debian automatic install with preseed and a partman recipe.
  110. EOF
  111. }
  112. show_version () {
  113. printf "%s %s 2016-2017 ephase@xieme-art.org\n" "$APP_NAME" "$VERSION"
  114. }
  115. download (){
  116. #Download function
  117. # $1 : filename
  118. # $2 : url
  119. # $3 : 1 if abort download if file exist
  120. printf "Downloading %s : " "$1"
  121. local url
  122. local http_response
  123. url="$2/$1"
  124. http_response=$(wget --spider --server-response "$url" 2>&1 | grep HTTP/ | tail -1 | awk ' { printf $2 }')
  125. if [ "$http_response" -eq 200 ]
  126. then
  127. wget -c --progress=dot "$url" 2>&1 | grep --line-buffered "[0-9]\{1,3\}%" -o | awk '{printf ("\b\b\b\b%4s", $1)}'
  128. if [ $? -eq 0 ]
  129. then
  130. printf " \b\b\b\b\b done\n "
  131. else
  132. printf " error, exiting.\n"
  133. exit 1
  134. fi
  135. else
  136. printf "Error 404 : file not found, exiting\n"
  137. exit 1
  138. fi
  139. }
  140. process_conf_file (){
  141. while read -r p
  142. do
  143. var=$(echo "$p" | awk -F"=" '{print $1}')
  144. param=$(echo "$p" | awk -F"=" '{print $2}')
  145. eval "$var"="$param"
  146. done < <( cat "$1" | grep '^[^#].*')
  147. }
  148. create_dir(){
  149. # $1 directory to create
  150. if [ ! -d "$1" ]
  151. then
  152. mkdir -p "$1"
  153. else
  154. if [ -n "$2" ] && [ "$2" -eq 1 ]
  155. then
  156. rm -rf "$1"
  157. create_dir "$1"
  158. fi
  159. fi
  160. }
  161. # unmount if device is mounted
  162. umount_device (){
  163. local mounted_part=""
  164. mounted_part=$(mount | grep "${1}[0-9]" | awk '{print $3}')
  165. if [ ! "$mounted_part" == "" ]
  166. then
  167. for part in $mounted_part
  168. do
  169. if [ -d "$part" ]
  170. then
  171. printf "Unmount %s\n " "$part"
  172. umount "$part" --recursive
  173. fi
  174. done
  175. fi
  176. }
  177. efi_create_key_structure () {
  178. parted -s "$1" mklabel gpt mkpart EFS fat32 1MiB 128MiB set 1 boot on mkpart debian fat32 128MiB 100%
  179. sleep 2
  180. mkfs.vfat "${1}1" -n efi &> /dev/null
  181. mkfs.vfat "${1}2" -n debian &> /dev/null
  182. sync
  183. mount "${1}2" "$2"
  184. create_dir "$2/efi"
  185. mount "${1}1" "$2/efi"
  186. }
  187. bios_create_key_structure() {
  188. parted -s "$1" mklabel msdos mkpart primary fat32 1MiB 100% set 1 boot on
  189. sleep 2
  190. mkfs.vfat "${1}1" -n debian &> /dev/null
  191. mount "${1}1" "$2"
  192. }
  193. #Stop script if syslinux is not installed
  194. if [ -z "$SYSLINUX_EXE" ]
  195. then
  196. printf "Syslinux not found, script can't continue.\n"
  197. exit 1
  198. fi
  199. if [ -z "$PARTED_EXE" ]
  200. then
  201. printf "Parted not found, script can't continue.\n"
  202. exit 1
  203. fi
  204. process_args "$@"
  205. process_conf_file "$conf_file"
  206. if [[ ! -d "$syslinux_mbr_bl_folder" || ! -d "$syslinux_efi_bl_folder" || ! -d "$syslinux_modules_folder" ]]
  207. then
  208. printf "Bad folder configuration in %s\n" "$conf_file"
  209. exit 1
  210. fi
  211. bootfiles_Debian="http://ftp.debian.org/debian/dists/stable/main/installer-${debian_arch}/current/images/hd-media"
  212. if [ $archive -eq 1 ]
  213. then
  214. iso_url="http://cdimage.debian.org/cdimage/archive/${debian_version}/${debian_arch}/iso-cd"
  215. else
  216. iso_url="http://cdimage.debian.org/debian-cd/${debian_version}/${debian_arch}/iso-cd"
  217. fi
  218. iso_file="debian-${debian_version}-${debian_arch}-netinst.iso"
  219. repo_path="$repo_dir/$debian_arch/$debian_version"
  220. # Download Debian files (kernel, initrd and iso)
  221. printf "Downloading Debian files\n---\n"
  222. # Création du répertoire temporaire
  223. create_dir "$repo_path"
  224. cd "$repo_path"
  225. download "$iso_file" "$iso_url" 1
  226. for file in "vmlinuz" "initrd.gz"
  227. do
  228. download "$file" "$bootfiles_Debian" 1
  229. done
  230. cd "$current_dir"
  231. if [ -z "$device" ]
  232. then
  233. printf "No destination device specified, USB key will not be created.\n"
  234. fi
  235. create_dir "$tmp_dir" 1
  236. cp "$repo_path/$iso_file" "$tmp_dir"
  237. # Copy wanted syslinux file from archive
  238. case $boot_type in
  239. efi64)
  240. syslinux_folder=${tmp_dir}/efi/EFI/boot
  241. create_dir "$syslinux_folder"
  242. cp -T "$syslinux_efi_bl_folder/$boot_type/syslinux.efi" "$syslinux_folder/bootx64.efi" &> /dev/null
  243. for file in $SYSLINUX_EFI_FILES
  244. do
  245. printf "copying %s \n" "$file"
  246. cp "$syslinux_modules_folder/$boot_type/$file" "$syslinux_folder"
  247. done
  248. cp "$repo_path"/{vmlinuz,initrd.gz} "$tmp_dir/efi"
  249. cp -R syslinux/syslinux.cfg "$syslinux_folder" &> /dev/null
  250. ;;
  251. bios)
  252. syslinux_folder=${tmp_dir}/syslinux
  253. create_dir "$syslinux_folder"
  254. for file in $SYSLINUX_BIOS_FILES
  255. do
  256. printf "copying %s\n" "$file"
  257. cp "$syslinux_modules_folder/$boot_type/$file" "$syslinux_folder"
  258. done
  259. cp "$repo_path"/{vmlinuz,initrd.gz} "$tmp_dir"
  260. cp -R syslinux "$tmp_dir" &> /dev/null
  261. ;;
  262. esac
  263. for file in $SYSLINUX_FILES
  264. do
  265. printf "copying %s\n" "$file"
  266. cp "$syslinux_modules_folder/$boot_type/$file" "$syslinux_folder"
  267. done
  268. echo Copying configurations files
  269. create_dir "$tmp_dir/partman_recipes"
  270. cp -R partman_recipes "$tmp_dir" &> /dev/null
  271. create_dir "$tmp_dir/preseeds"
  272. cp -R preseeds "$tmp_dir" &> /dev/null
  273. if [ -n "$device" ]
  274. then
  275. printf "Partitionning and formating %s\n" "$device"
  276. read -p "[WARNING] Disk $device will be erased continue [Y/N]? " -n 1 -r
  277. if [[ ! $REPLY =~ ^[Yy]$ ]]
  278. then
  279. exit 1
  280. fi
  281. printf "\n\n"
  282. umount_device "$device"
  283. create_dir "$key_mountpoint"
  284. #dd if=/dev/zero of=${dest} bs=512 count=1 conv=notrunc &> /dev/null
  285. case "$boot_type" in
  286. "efi64")
  287. efi_create_key_structure "$device" "$key_mountpoint"
  288. ;;
  289. "bios")
  290. bios_create_key_structure "$device" "$key_mountpoint"
  291. ;;
  292. esac
  293. printf "copying all file to USB drive\n"
  294. cp -R "$tmp_dir"/* "$key_mountpoint"
  295. umount_device "$device"
  296. sleep 5
  297. # Make key bootable if bios.
  298. if [ "$boot_type" = "bios" ]
  299. then
  300. # In this mode, we need to write syslinux MBR.
  301. printf "Writing syslinux mbr.ini to %s\n" "$device"
  302. dd bs=440 count=1 conv=notrunc if="$syslinux_mbr_bl_folder"/mbr.bin of="$device"
  303. sleep 2
  304. "$SYSLINUX_EXE" --directory /syslinux --install "${device}1"
  305. fi
  306. rm -rf "$tmp_dir"
  307. printf "\nBootable USB key created\n"
  308. exit 0
  309. fi