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.
 
 

346 lines
9.1 KiB

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