pilc-bootstrap.sh 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212
  1. #!/bin/sh
  2. #
  3. # PiLC bootstrap
  4. #
  5. # Copyright 2016-2021 Michael Buesch <m@bues.ch>
  6. #
  7. # This program is free software; you can redistribute it and/or modify
  8. # it under the terms of the GNU General Public License as published by
  9. # the Free Software Foundation; either version 2 of the License, or
  10. # (at your option) any later version.
  11. #
  12. # This program is distributed in the hope that it will be useful,
  13. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. # GNU General Public License for more details.
  16. #
  17. # You should have received a copy of the GNU General Public License along
  18. # with this program; if not, write to the Free Software Foundation, Inc.,
  19. # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  20. #
  21. basedir="$(dirname "$0")"
  22. [ "$(echo "$basedir" | cut -c1)" = '/' ] || basedir="$PWD/$basedir"
  23. basedir="$(readlink -e "$basedir")"
  24. [ -n "$basedir" ] || { echo "Failed to canonicalize base directory." >&2; exit 1; }
  25. AWLSIM_MIRROR="https://git.bues.ch/git/awlsim.git"
  26. DEFAULT_SUITE=bullseye
  27. MAIN_MIRROR_32="http://mirrordirector.raspbian.org/raspbian/"
  28. MAIN_MIRROR_ARCHIVE="http://archive.raspberrypi.org/debian/"
  29. MAIN_MIRROR_64="http://deb.debian.org/debian/"
  30. MAIN_MIRROR_64_SECURITY="http://deb.debian.org/debian-security/"
  31. KEYRING_VERSION="20120528.2"
  32. KEYRING_BASEURL="$MAIN_MIRROR_32/pool/main/r/raspbian-archive-keyring"
  33. KEYRING_TGZ_FILE="raspbian-archive-keyring_${KEYRING_VERSION}.tar.gz"
  34. KEYRING_TGZ_SHA256="fdf50f775b60901a2783f21a6362e2bf5ee6203983e884940b163faa1293c002"
  35. PPL_VERSION="0.1.1"
  36. PPL_FILE="ppl_v$PPL_VERSION.zip"
  37. PPL_PATH="libs/pixtend/v1/ppl/$PPL_FILE"
  38. PPL_SHA256="103edcdbc377f8b478fcbc89117cbad143500c611cb714568f55513cece220d4"
  39. PPL2_VERSION="0.1.4"
  40. PPL2_FILE="pplv2_v$PPL2_VERSION.zip"
  41. PPL2_PATH="libs/pixtend/v2/pplv2/$PPL2_FILE"
  42. PPL2_SHA256="4c379e15c6536b67b3eb36b79946a52e57aa79681265e6d46104e07987147bf1"
  43. info()
  44. {
  45. echo "--- $*"
  46. }
  47. error()
  48. {
  49. echo "=== ERROR: $*" >&2
  50. }
  51. warning()
  52. {
  53. echo "=== WARNING: $*" >&2
  54. }
  55. die()
  56. {
  57. error "$*"
  58. exit 1
  59. }
  60. # print the first of its arguments.
  61. first()
  62. {
  63. echo "$1"
  64. }
  65. # print the last of its arguments.
  66. last()
  67. {
  68. while [ $# -gt 1 ]; do shift; done
  69. echo "$1"
  70. }
  71. # $1=program_name
  72. have_program()
  73. {
  74. which "$1" >/dev/null 2>&1
  75. }
  76. # $1=program_name, ($2=description)
  77. assert_program()
  78. {
  79. local bin="$1"
  80. local desc="$2"
  81. [ -n "$desc" ] || desc="$bin"
  82. have_program "$bin" || die "$bin not found. Please install $desc."
  83. }
  84. term_signal()
  85. {
  86. die "Terminating signal received"
  87. }
  88. cleanup()
  89. {
  90. info "Cleaning up..."
  91. for mp in "$mp_shm" "$mp_proc_binfmt_misc" "$mp_proc" "$mp_sys" "$mp_bootimgfile" "$mp_rootimgfile"; do
  92. [ -n "$mp" -a -d "$mp" ] &&\
  93. umount -l "$mp" >/dev/null 2>&1
  94. done
  95. for mp in "$mp_bootimgfile" "$mp_rootimgfile"; do
  96. [ -n "$mp" -a -d "$mp" ] &&\
  97. rmdir "$mp" >/dev/null 2>&1
  98. done
  99. }
  100. do_install()
  101. {
  102. install "$@" || die "Failed install $*"
  103. }
  104. do_systemctl()
  105. {
  106. info "systemctl $*"
  107. systemctl "$@" || die "Failed to systemctl $*"
  108. }
  109. write_image()
  110. {
  111. local image="$1"
  112. local dev="$2"
  113. [ -b "$dev" ] || die "$dev is not a block device"
  114. mount | grep -q "$dev" && die "$dev is mounted. Refusing to write to it!"
  115. if have_program blkdiscard; then
  116. info "Discarding $dev ..."
  117. blkdiscard -f "$dev" ||\
  118. error "blkdiscard failed."
  119. else
  120. warning "Skipping discard. blkdiscard not installed."
  121. fi
  122. info "Writing $image to $dev ..."
  123. dd if="$image" of="$dev" bs=32M status=progress ||\
  124. die "Failed to write image."
  125. }
  126. download()
  127. {
  128. local target="$1"
  129. local mirror="$2"
  130. local sha256="$3"
  131. info "Downloading $mirror..."
  132. rm -f "$target"
  133. if printf '%s' "$mirror" | grep -qEe '^\./|^\../|^/'; then
  134. # "mirror" starts with ./ ../ or /
  135. # This is a local file.
  136. cp "$mirror" "$target" || die "Failed to fetch $mirror"
  137. else
  138. # Download the file
  139. wget -O "$target" "$mirror" || die "Failed to fetch $mirror"
  140. fi
  141. [ "$(sha256sum -b "$target" | cut -f1 -d' ')" = "$sha256" ] ||\
  142. die "SHA256 verification of $target failed"
  143. }
  144. extract_archive()
  145. {
  146. local archive="$1"
  147. local extract_dir="$2"
  148. local make_extract_dir="$3"
  149. if [ $make_extract_dir -ne 0 ]; then
  150. mkdir "$extract_dir" ||\
  151. die "Failed to create directory $extract_dir"
  152. fi
  153. if printf '%s' "$archive" | grep -qEe '\.zip$'; then
  154. if [ $make_extract_dir -ne 0 ]; then
  155. unzip -d "$extract_dir" "$archive" ||\
  156. die "Failed to unpack $archive"
  157. else
  158. unzip "$archive" ||\
  159. die "Failed to unpack $archive"
  160. fi
  161. else
  162. if [ $make_extract_dir -ne 0 ]; then
  163. tar --one-top-level="$extract_dir" -xf "$archive" ||\
  164. die "Failed to unpack $archive"
  165. else
  166. tar -xf "$archive" ||\
  167. die "Failed to unpack $archive"
  168. fi
  169. fi
  170. }
  171. build_pythonpack()
  172. {
  173. local python="$1"
  174. local name="$2"
  175. local archive="$3"
  176. local extract_dir="$4"
  177. local make_extract_dir="$5"
  178. info "Building $name for $python..."
  179. rm -rf "/tmp/$extract_dir"
  180. (
  181. cd /tmp || die "Failed to cd /tmp"
  182. extract_archive "$archive" "$extract_dir" "$make_extract_dir"
  183. cd "$extract_dir" ||\
  184. die "Failed to cd $extract_dir"
  185. "$python" ./setup.py install ||\
  186. die "Failed to install $name"
  187. ) || die
  188. rm -r "/tmp/$extract_dir" ||\
  189. die "Failed to remove $name build files."
  190. }
  191. build_ppl()
  192. {
  193. local archive="$PPL_FILE"
  194. for python in python3; do
  195. build_pythonpack "$python" "ppl-$PPL_VERSION" \
  196. "$archive" "ppl-$PPL_VERSION" 1
  197. done
  198. rm "/tmp/$archive" ||\
  199. die "Failed to remove /tmp/$archive."
  200. }
  201. build_ppl2()
  202. {
  203. local archive="$PPL2_FILE"
  204. for python in python3; do
  205. build_pythonpack "$python" "ppl2-$PPL2_VERSION" \
  206. "$archive" "ppl2-$PPL2_VERSION" 1
  207. done
  208. rm "/tmp/$archive" ||\
  209. die "Failed to remove /tmp/$archive."
  210. }
  211. pilc_bootstrap_first_stage()
  212. {
  213. echo "Running first stage..."
  214. [ "$(id -u)" = "0" ] || die "Permission denied. Must be root."
  215. # Check host tools (first/third stage).
  216. assert_program 7z
  217. assert_program chroot
  218. assert_program dd
  219. assert_program debootstrap
  220. assert_program git
  221. assert_program gpg
  222. assert_program install
  223. assert_program mkfs.ext4
  224. assert_program mkfs.vfat
  225. assert_program parted
  226. assert_program rsync
  227. assert_program setarch
  228. assert_program tar
  229. assert_program unzip
  230. assert_program wget
  231. [ -x "$opt_qemu" ] ||\
  232. die "The qemu binary '$opt_qemu' is not executable."
  233. info "Cleaning tmp..."
  234. rm -rf "$opt_target_dir"/tmp/*
  235. do_install -d -o root -g root -m 1777 "$opt_target_dir/tmp"
  236. info "Downloading and extracting keys..."
  237. do_install -o root -g root -m 644 \
  238. "$basedir/keys/CF8A1AF502A2AA2D763BAE7E82B129927FA3303E.gpg" \
  239. "$opt_target_dir/tmp/"
  240. if [ $opt_bit -eq 32 ]; then
  241. download "$opt_target_dir/tmp/$KEYRING_TGZ_FILE" \
  242. "$KEYRING_BASEURL/$KEYRING_TGZ_FILE" \
  243. "$KEYRING_TGZ_SHA256"
  244. tar -C "$opt_target_dir/tmp" -x -f "$opt_target_dir/tmp/$KEYRING_TGZ_FILE" ||\
  245. die "Failed to extract keys."
  246. local raspbian_asc="$opt_target_dir/tmp/raspbian-archive-keyring-$KEYRING_VERSION/raspbian.public.key"
  247. local raspbian_gpg="$raspbian_asc.gpg"
  248. gpg --dearmor < "$raspbian_asc" > "$raspbian_gpg" ||\
  249. die "Failed to convert key."
  250. fi
  251. # debootstrap first stage.
  252. if [ $opt_skip_debootstrap1 -eq 0 ]; then
  253. info "Running debootstrap first stage..."
  254. if [ $opt_bit -eq 32 ]; then
  255. local arch="armhf"
  256. local keyopt="--keyring=$raspbian_gpg"
  257. local mirror="$MAIN_MIRROR_32"
  258. else
  259. local arch="arm64"
  260. local keyopt=
  261. local mirror="$MAIN_MIRROR_64"
  262. fi
  263. setarch "linux$opt_bit" \
  264. debootstrap --arch="$arch" --foreign \
  265. --components="main,contrib,non-free" \
  266. $keyopt \
  267. "$opt_suite" "$opt_target_dir" "$mirror" \
  268. || die "debootstrap failed"
  269. fi
  270. [ -d "$opt_target_dir" ] ||\
  271. die "Target directory '$opt_target_dir' does not exist."
  272. # Avoid the start of daemons during second stage.
  273. do_install -o root -g root -m 755 \
  274. "$basedir/templates/policy-rc.d" \
  275. "$opt_target_dir/usr/sbin/"
  276. # Copy qemu.
  277. local qemu_bin="$opt_target_dir/$opt_qemu"
  278. if ! [ -x "$qemu_bin" ]; then
  279. info "Copying qemu binary from '$opt_qemu' to '$qemu_bin'..."
  280. do_install -d -o root -g root -m 755 \
  281. "$(dirname "$qemu_bin")"
  282. do_install -T -o root -g root -m 755 \
  283. "$opt_qemu" "$qemu_bin"
  284. fi
  285. info "Copying PiLC bootstrap script and templates..."
  286. do_install -o root -g root -m 755 \
  287. "$basedir/pilc-bootstrap.sh" \
  288. "$opt_target_dir/"
  289. cp -r "$basedir/templates" "$opt_target_dir/tmp/" ||\
  290. die "Failed to copy PiLC templates"
  291. cp -r "$basedir/deb" "$opt_target_dir/tmp/" ||\
  292. die "Failed to copy PiLC deb packages"
  293. info "Checking out awlsim..."
  294. local awlsim_dir="$opt_target_dir/tmp/awlsim"
  295. local awlsim_checkout_dir="$awlsim_dir/src"
  296. rm -rf "$awlsim_dir"
  297. do_install -d -o root -g root -m 755 "$awlsim_dir"
  298. git clone --no-checkout "$AWLSIM_MIRROR" "$awlsim_checkout_dir" ||\
  299. die "Failed to clone"
  300. (
  301. cd "$awlsim_checkout_dir" ||\
  302. die "Failed to cd"
  303. git checkout "$opt_branch" ||\
  304. die "Failed to check out branch."
  305. git submodule update --init submodules/pyprofibus ||\
  306. die "Failed to pull pyprofibus submodule"
  307. rm -r .git submodules/pyprofibus/.git ||\
  308. die "Failed to remove .git directory."
  309. mv submodules/pyprofibus .. ||\
  310. die "Failed to move pyprofibus submodule."
  311. ) || die
  312. # Fetch packages
  313. download "$opt_target_dir/tmp/$PPL_FILE" \
  314. "$awlsim_checkout_dir/$PPL_PATH" \
  315. "$PPL_SHA256"
  316. download "$opt_target_dir/tmp/$PPL2_FILE" \
  317. "$awlsim_checkout_dir/$PPL2_PATH" \
  318. "$PPL2_SHA256"
  319. # Second stage will mount a few filesystems.
  320. # Keep track to umount them in cleanup.
  321. mp_proc="$opt_target_dir/proc"
  322. mp_proc_binfmt_misc="$opt_target_dir/proc/sys/fs/binfmt_misc"
  323. mp_sys="$opt_target_dir/sys"
  324. mp_shm="$opt_target_dir/dev/shm"
  325. }
  326. pilc_bootstrap_second_stage()
  327. {
  328. info "Running second stage..."
  329. [ -x /pilc-bootstrap.sh ] ||\
  330. die "Second stage does not contain the bootstrap script."
  331. # Set up environment.
  332. export LC_ALL=C
  333. export LANGUAGE=C
  334. export LANG=C
  335. if [ "$opt_rpiver" = "1" -o "$opt_rpiver" = "0" ]; then
  336. info "Optimizing for RPi 1, zero(w)"
  337. local march="-march=armv6kz"
  338. local mtune="-mtune=arm1176jzf-s"
  339. elif [ "$opt_rpiver" = "2" ]; then
  340. info "Optimizing for RPi 2"
  341. local march="-march=armv7-a"
  342. local mtune="-mtune=cortex-a7"
  343. elif [ "$opt_rpiver" = "3" ]; then
  344. info "Optimizing for RPi 3"
  345. local march="-march=armv8-a"
  346. local mtune="-mtune=cortex-a53"
  347. elif [ "$opt_rpiver" = "4" ]; then
  348. info "Optimizing for RPi 4"
  349. local march="-march=armv8-a"
  350. local mtune="-mtune=cortex-a72"
  351. else
  352. info "Optimizing for generic RPi"
  353. if [ $opt_bit -eq 32 ]; then
  354. local march="-march=armv6kz"
  355. local mtune=
  356. else
  357. local march="-march=armv8-a"
  358. local mtune=
  359. fi
  360. fi
  361. export CFLAGS="-O3 $march $mtune -pipe"
  362. [ $opt_bit -eq 32 ] && export CFLAGS="$CFLAGS -mfpu=vfp -mfloat-abi=hard"
  363. export CXXFLAGS="$CFLAGS"
  364. # debootstrap second stage.
  365. if [ $opt_skip_debootstrap2 -eq 0 ]; then
  366. info "Running debootstrap second stage..."
  367. /debootstrap/debootstrap --verbose --second-stage ||\
  368. die "Debootstrap second stage failed."
  369. fi
  370. if [ $opt_bit -eq 32 ]; then
  371. info "Disabling raspi-copies-and-fills..."
  372. rm -f /etc/ld.so.preload || die "Failed to disable raspi-copies-and-fills"
  373. fi
  374. info "Mounting /proc..."
  375. do_install -d -o root -g root -m 755 /proc
  376. mount -t proc proc /proc || die "Mounting /proc failed."
  377. info "Mounting /sys..."
  378. do_install -d -o root -g root -m 755 /sys
  379. mount -t sysfs sysfs /sys || die "Mounting /sys failed."
  380. info "Mounting /dev/shm..."
  381. do_install -d -o root -g root -m 755 /dev/shm
  382. mount -t tmpfs tmpfs /dev/shm || die "Mounting /dev/shm failed."
  383. info "Creating /etc/fstab"
  384. do_install -d -o root -g root -m 755 /config
  385. do_install -T -o root -g root -m 644 \
  386. /tmp/templates/fstab \
  387. /etc/fstab
  388. info "Writing misc /etc stuff..."
  389. echo "pilc" > /etc/hostname || die "Failed to set hostname"
  390. printf 'PiLC GNU/Linux (based on Raspberry Pi OS) \\n \\l\n\n' > /etc/issue ||\
  391. die "Failed to create /etc/issue"
  392. printf 'PiLC GNU/Linux (based on Raspberry Pi OS)\n' > /etc/issue.net ||\
  393. die "Failed to create /etc/issue.net"
  394. sed -i -e 's|PRETTY_NAME=.*|PRETTY_NAME="PiLC"|' \
  395. /etc/os-release ||\
  396. die "Failed to set os-release PRETTY_NAME."
  397. sed -i -e 's|NAME=.*|NAME="PiLC"|' \
  398. /etc/os-release ||\
  399. die "Failed to set os-release NAME."
  400. sed -i -e 's|ID=.*|ID=pilc|' \
  401. /etc/os-release ||\
  402. die "Failed to set os-release ID."
  403. sed -i -e 's|ID_LIKE=.*|ID_LIKE=debian|' \
  404. /etc/os-release ||\
  405. die "Failed to set os-release ID_LIKE."
  406. sed -i -e 's|HOME_URL=.*|HOME_URL="https://bues.ch/a/pilc"|' \
  407. /etc/os-release ||\
  408. die "Failed to set os-release HOME_URL."
  409. sed -i -e 's|SUPPORT_URL=.*|SUPPORT_URL="https://bues.ch/a/pilc"|' \
  410. /etc/os-release ||\
  411. die "Failed to set os-release SUPPORT_URL."
  412. sed -i -e 's|BUG_REPORT_URL=.*|BUG_REPORT_URL="https://bues.ch/a/pilc"|' \
  413. /etc/os-release ||\
  414. die "Failed to set os-release BUG_REPORT_URL."
  415. info "Writing apt configuration..."
  416. local apt_opts="-y -o Acquire::Retries=3"
  417. if [ $opt_bit -eq 32 ]; then
  418. cat > /etc/apt/sources.list <<EOF
  419. deb $MAIN_MIRROR_32 $opt_suite main contrib non-free rpi firmware
  420. #deb-src $MAIN_MIRROR_32 $opt_suite main contrib non-free rpi firmware
  421. EOF
  422. [ $? -eq 0 ] || die "Failed to set sources.list"
  423. else
  424. cat > /etc/apt/sources.list <<EOF
  425. deb $MAIN_MIRROR_64 $opt_suite main contrib non-free
  426. #deb-src $MAIN_MIRROR_64 $opt_suite main contrib non-free
  427. deb $MAIN_MIRROR_64_SECURITY $opt_suite-security main contrib non-free
  428. #deb-src $MAIN_MIRROR_64_SECURITY $opt_suite-security main contrib non-free
  429. deb $MAIN_MIRROR_64 $opt_suite-updates main contrib non-free
  430. #deb-src $MAIN_MIRROR_64 $opt_suite-updates main contrib non-free
  431. EOF
  432. [ $? -eq 0 ] || die "Failed to set sources.list"
  433. dpkg --add-architecture armhf ||\
  434. die "dpkg --add-architecture failed"
  435. fi
  436. echo 'Acquire { Languages "none"; };' > /etc/apt/apt.conf.d/99no-translations ||\
  437. die "Failed to set apt.conf.d"
  438. cat /tmp/templates/debconf-set-selections-preinstall.conf | debconf-set-selections ||\
  439. die "Failed to configure debconf settings"
  440. apt-get $apt_opts update ||\
  441. die "apt-get update failed"
  442. apt-get $apt_opts install apt-transport-https ||\
  443. die "apt-get install apt-transport-https failed"
  444. apt-get $apt_opts install \
  445. gnupg2 \
  446. debian-keyring \
  447. || die "apt-get install keyrings failed"
  448. cat >> /etc/apt/sources.list <<EOF
  449. deb $MAIN_MIRROR_ARCHIVE $opt_suite main
  450. #deb-src $MAIN_MIRROR_ARCHIVE $opt_suite main
  451. EOF
  452. [ $? -eq 0 ] || die "Failed to update sources.list"
  453. do_install -o root -g root -m 644 \
  454. /tmp/CF8A1AF502A2AA2D763BAE7E82B129927FA3303E.gpg \
  455. /etc/apt/trusted.gpg.d/
  456. apt-get $apt_opts update ||\
  457. die "apt-get update failed"
  458. if [ $opt_bit -eq 32 ]; then
  459. apt-get $apt_opts install \
  460. raspbian-archive-keyring \
  461. || die "apt-get install archive-keyrings failed"
  462. fi
  463. info "Upgrading system..."
  464. apt-get $apt_opts dist-upgrade ||\
  465. die "apt-get dist-upgrade failed"
  466. info "Installing packages..."
  467. apt-get $apt_opts install \
  468. aptitude \
  469. bash \
  470. build-essential \
  471. console-setup \
  472. cython3 \
  473. dbus \
  474. debconf-utils \
  475. debsums \
  476. devscripts \
  477. dh-python \
  478. ethtool \
  479. fdisk \
  480. firmware-atheros \
  481. firmware-brcm80211 \
  482. firmware-libertas \
  483. firmware-linux \
  484. firmware-linux-free \
  485. firmware-linux-nonfree \
  486. firmware-misc-nonfree \
  487. firmware-realtek \
  488. git \
  489. htop \
  490. i2c-tools \
  491. irqbalance \
  492. iw \
  493. locales \
  494. nano \
  495. ntp \
  496. openssh-server \
  497. parted \
  498. python3 \
  499. python3-cffi \
  500. python3-dev \
  501. python3-serial \
  502. python3-setuptools \
  503. python3-spidev \
  504. rng-tools \
  505. schedtool \
  506. sudo \
  507. systemd \
  508. tmux \
  509. vim \
  510. wireless-tools \
  511. wpasupplicant \
  512. || die "apt-get install failed"
  513. info "Configuring locales..."
  514. dpkg-reconfigure -u locales ||\
  515. die "Failed to reconfigure locales"
  516. info "Configuring console..."
  517. sed -i -e 's|CHARMAP=.*|CHARMAP="UTF-8"|' \
  518. -e 's|FONTFACE=.*|FONTFACE=""|' \
  519. -e 's|FONTSIZE=.*|FONTSIZE=""|' \
  520. /etc/default/console-setup ||\
  521. die "Failed to edit /etc/default/console-setup"
  522. info "Creating /etc/rc.local..."
  523. do_install -o root -g root -m 755 \
  524. /tmp/templates/rc.local \
  525. /etc/
  526. info "Creating users/groups..."
  527. userdel -f pi
  528. groupdel pi
  529. rm -rf /home/pi
  530. groupadd -g 1000 pi ||\
  531. die "Failed to create group pi."
  532. useradd -u 1000 -d /home/pi -m -g pi\
  533. -G pi,lp,dialout,cdrom,floppy,audio,dip,src,video,plugdev,netdev,i2c\
  534. -s /bin/bash\
  535. pi ||\
  536. die "Failed to create user pi."
  537. printf 'raspberry\nraspberry\n' | passwd pi ||\
  538. die "Failed to set 'pi' password."
  539. info "Initializing home directory..."
  540. do_install -d -o pi -g pi -m 755 /home/pi/.vim
  541. do_install -o pi -g pi -m 644 \
  542. /tmp/templates/vimrc \
  543. /home/pi/.vim/
  544. do_install -T -o pi -g pi -m 644 \
  545. /tmp/templates/tmux.conf \
  546. /home/pi/.tmux.conf
  547. info "Installing Raspberry Pi OS packages..."
  548. apt-get $apt_opts install \
  549. libraspberrypi-bin \
  550. libraspberrypi-dev \
  551. libraspberrypi-doc \
  552. python3-rpi.gpio \
  553. raspberrypi-bootloader \
  554. raspberrypi-kernel \
  555. raspberrypi-net-mods \
  556. raspberrypi-sys-mods \
  557. raspi-config \
  558. raspi-gpio \
  559. raspinfo \
  560. rpi-eeprom \
  561. rpi-eeprom-images \
  562. || die "apt-get install failed"
  563. info "Removing unnecessary keys and repos..."
  564. for file in /etc/apt/trusted.gpg.d/microsoft.gpg \
  565. /etc/apt/sources.list.d/vscode.list; do
  566. info "Replacing $file with dummy..."
  567. if [ -e "$file" ]; then
  568. rm "$file" || die "Failed to rm $file"
  569. fi
  570. touch "$file" || die "Failed to touch $file"
  571. chmod 444 "$file" || die "Failed to chmod 444 $file"
  572. done
  573. for file in /etc/apt/*.gpg~; do
  574. if [ -e "$file" ]; then
  575. info "Removing $file..."
  576. rm "$file" || die "Failed to rm $file"
  577. fi
  578. done
  579. apt-get $apt_opts update ||\
  580. die "apt-get update failed"
  581. info "Running debconf-set-selections..."
  582. cat /tmp/templates/debconf-set-selections-postinstall.conf | debconf-set-selections ||\
  583. die "Failed to configure debconf settings"
  584. info "Cleaning apt..."
  585. apt-get $apt_opts autoremove --purge ||\
  586. die "apt-get autoremove failed"
  587. apt-get $apt_opts clean ||\
  588. die "apt-get clean failed"
  589. info "Disabling some services..."
  590. do_systemctl mask apt-daily.service
  591. do_systemctl mask apt-daily.timer
  592. do_systemctl mask apt-daily-upgrade.timer
  593. do_systemctl mask rsync.service
  594. do_systemctl mask exim4.service
  595. do_systemctl mask triggerhappy.service
  596. do_systemctl mask triggerhappy.socket
  597. do_systemctl mask alsa-state.service
  598. do_systemctl mask alsa-restore.service
  599. do_systemctl mask alsa-utils.service
  600. info "Building and installing PiLC system package..."
  601. (
  602. cd /tmp/deb/pilc-system || die "Failed to cd to pilc-system"
  603. debuild -uc -us -b -d || die "debuild failed"
  604. dpkg -i ../pilc-system_*.deb || die "Failed to install pilc-system"
  605. # Copy debs
  606. rm -rf /home/pi/deb/pilc-system
  607. do_install -d -o pi -g pi -m 755 /home/pi/deb/pilc-system
  608. do_install -o pi -g pi -m 644 \
  609. ../*pilc-system*.deb \
  610. /home/pi/deb/pilc-system/
  611. ) || die
  612. info "Updating /etc/hosts..."
  613. if ! grep -qe pilc /etc/hosts; then
  614. printf '\n127.0.0.1\tpilc\n' >> /etc/hosts ||\
  615. die "Failed to update /etc/hosts"
  616. fi
  617. info "Building Python modules..."
  618. build_ppl
  619. build_ppl2
  620. info "Building awlsim..."
  621. (
  622. cd /tmp/awlsim/src || die "Failed to cd"
  623. if [ $opt_cython -eq 0 ]; then
  624. # Disable cython
  625. sed -i -e '/Package: cython/,/^$/ d' \
  626. debian/control ||\
  627. die "Failed to patch control file (cython)"
  628. sed -i -e 's/export AWLSIM_CYTHON_BUILD=1/export AWLSIM_CYTHON_BUILD=0/' \
  629. debian/rules ||\
  630. die "Failed to patch rules file (cython)"
  631. fi
  632. # Update the systemd service file.
  633. sed -i -e 's|AWLSIM_SCHED=|AWLSIM_SCHED=realtime-if-multicore|g' \
  634. -e 's|AWLSIM_PRIO=|AWLSIM_PRIO=50|g' \
  635. -e 's|AWLSIM_AFFINITY=|AWLSIM_AFFINITY=-1,-2,-3|g' \
  636. -e 's|AWLSIM_MLOCK=|AWLSIM_MLOCK=1|g' \
  637. -e 's|Nice=.*$|Nice=-5|g' \
  638. awlsim-server.service ||\
  639. die "Failed to patch awlsim-server.service"
  640. # Build the packages.
  641. debuild -uc -us -b -d || die "debuild failed"
  642. info "Installing awlsim..."
  643. # Core
  644. dpkg -i ../python3-awlsim_*.deb ||\
  645. die "Failed to install python3-awlsim"
  646. if [ $opt_cython -ne 0 ]; then
  647. dpkg -i ../cython3-awlsim_*.deb ||\
  648. die "Failed to install cython3-awlsim"
  649. fi
  650. # hardware: dummy
  651. dpkg -i ../python3-awlsimhw-dummy_*.deb ||\
  652. die "Failed to install python3-awlsimhw-dummy"
  653. if [ $opt_cython -ne 0 ]; then
  654. dpkg -i ../cython3-awlsimhw-dummy_*.deb ||\
  655. die "Failed to install cython3-awlsimhw-dummy"
  656. fi
  657. # hardware: linuxcnc
  658. dpkg -i ../python3-awlsimhw-linuxcnc_*.deb ||\
  659. die "Failed to install python3-awlsimhw-linuxcnc"
  660. if [ $opt_cython -ne 0 ]; then
  661. dpkg -i ../cython3-awlsimhw-linuxcnc_*.deb ||\
  662. die "Failed to install cython3-awlsimhw-linuxcnc"
  663. fi
  664. # hardware: profibus
  665. dpkg -i ../python3-awlsimhw-profibus_*.deb ||\
  666. die "Failed to install python3-awlsimhw-profibus"
  667. if [ $opt_cython -ne 0 ]; then
  668. dpkg -i ../cython3-awlsimhw-profibus_*.deb ||\
  669. die "Failed to install cython3-awlsimhw-profibus"
  670. fi
  671. # hardware: RPi GPIO
  672. dpkg -i ../python3-awlsimhw-rpigpio_*.deb ||\
  673. die "Failed to install python3-awlsimhw-rpigpio"
  674. if [ $opt_cython -ne 0 ]; then
  675. dpkg -i ../cython3-awlsimhw-rpigpio_*.deb ||\
  676. die "Failed to install cython3-awlsimhw-rpigpio"
  677. fi
  678. # hardware: PiXtend
  679. dpkg -i ../python3-awlsimhw-pixtend_*.deb ||\
  680. die "Failed to install python3-awlsimhw-pixtend"
  681. if [ $opt_cython -ne 0 ]; then
  682. dpkg -i ../cython3-awlsimhw-pixtend_*.deb ||\
  683. die "Failed to install cython3-awlsimhw-pixtend"
  684. fi
  685. # Executables
  686. dpkg -i ../awlsim-server_*.deb ||\
  687. die "Failed to install awlsim-server"
  688. dpkg -i ../awlsim-client_*.deb ||\
  689. die "Failed to install awlsim-client"
  690. dpkg -i ../awlsim-symtab_*.deb ||\
  691. die "Failed to install awlsim-symtab"
  692. dpkg -i ../awlsim-test_*.deb ||\
  693. die "Failed to install awlsim-test"
  694. dpkg -i ../awlsim-proupgrade_*.deb ||\
  695. die "Failed to install awlsim-proupgrade"
  696. # Copy debs
  697. rm -rf /home/pi/deb/awlsim
  698. do_install -d -o pi -g pi -m 755 /home/pi/deb/awlsim
  699. do_install -o pi -g pi -m 644 \
  700. ../*awlsim*.deb \
  701. /home/pi/deb/awlsim/
  702. # Copy examples
  703. do_install -T -o pi -g pi -m 644 \
  704. examples/EXAMPLE.awlpro \
  705. /home/pi/generic-example.awlpro
  706. do_install -T -o pi -g pi -m 644 \
  707. examples/raspberrypi-gpio.awlpro \
  708. /home/pi/raspberrypi-gpio-example.awlpro
  709. do_install -T -o pi -g pi -m 644 \
  710. examples/raspberrypi-profibus.awlpro \
  711. /home/pi/raspberrypi-profibus-example.awlpro
  712. do_install -T -o pi -g pi -m 644 \
  713. examples/raspberrypi-pixtend.awlpro \
  714. /home/pi/raspberrypi-pixtend-example.awlpro
  715. ) || die
  716. info "Building pyprofibus..."
  717. (
  718. cd /tmp/awlsim/pyprofibus ||\
  719. die "Failed to cd"
  720. if [ $opt_cython -eq 0 ]; then
  721. # Disable cython
  722. sed -i -e '/Package: cython/,/^$/ d' \
  723. debian/control ||\
  724. die "Failed to patch control file (cython)"
  725. sed -i -e 's/export PYPROFIBUS_CYTHON_BUILD=1/export PYPROFIBUS_CYTHON_BUILD=0/' \
  726. debian/rules ||\
  727. die "Failed to patch rules file (cython)"
  728. fi
  729. # Build the packages.
  730. debuild -uc -us -b -d || die "debuild failed"
  731. info "Installing pyprofibus..."
  732. dpkg -i ../python3-pyprofibus_*.deb ||\
  733. die "Failed to install python3-pyprofibus"
  734. dpkg -i ../profisniff_*.deb ||\
  735. die "Failed to install profisniff"
  736. dpkg -i ../gsdparser_*.deb ||\
  737. die "Failed to install gsdparser"
  738. # Copy debs
  739. rm -rf /home/pi/deb/pyprofibus
  740. do_install -d -o pi -g pi -m 755 /home/pi/deb/pyprofibus
  741. do_install -o pi -g pi -m 644 \
  742. ../*pyprofibus*.deb \
  743. ../profisniff_*.deb \
  744. ../gsdparser_*.deb \
  745. /home/pi/deb/pyprofibus/
  746. ) || die
  747. rm -r /tmp/awlsim ||\
  748. die "Failed to remove awlsim checkout."
  749. info "Updating home directory permissions..."
  750. chown -R pi:pi /home/pi || die "Failed to change /home/pi permissions."
  751. # Remove rc.d policy file
  752. if [ -e /usr/sbin/policy-rc.d ]; then
  753. rm /usr/sbin/policy-rc.d ||\
  754. die "Failed to remove policy-rc.d"
  755. fi
  756. if [ $opt_bit -eq 32 ]; then
  757. # Install this last. It won't work correctly in the qemu environment.
  758. info "Installing raspi-copies-and-fills..."
  759. apt-get $apt_opts install --reinstall raspi-copies-and-fills ||\
  760. die "apt-get install failed"
  761. fi
  762. info "Stopping processes..."
  763. for i in dbus ssh irqbalance; do
  764. /etc/init.d/$i stop
  765. done
  766. }
  767. pilc_bootstrap_third_stage()
  768. {
  769. info "Running third stage..."
  770. info "Umounting /dev/shm..."
  771. umount -l "$mp_shm" || die "Failed to umount /dev/shm"
  772. info "Umounting /sys..."
  773. umount -l "$mp_sys" || die "Failed to umount /sys"
  774. info "Umounting /proc/sys/fs/binfmt_misc..."
  775. umount -l "$mp_proc_binfmt_misc"
  776. info "Umounting /proc..."
  777. umount -l "$mp_proc" || die "Failed to umount /proc"
  778. info "Removing PiLC bootstrap script..."
  779. rm "$opt_target_dir/pilc-bootstrap.sh" ||\
  780. die "Failed to remove bootstrap script."
  781. info "Cleaning tmp..."
  782. rm -rf "$opt_target_dir"/tmp/*
  783. info "Configuring boot..."
  784. do_install -T -o root -g root -m 644 \
  785. "$basedir/templates/boot_cmdline.txt" \
  786. "$opt_target_dir/boot/cmdline.txt"
  787. do_install -T -o root -g root -m 644 \
  788. "$basedir/templates/boot_config.txt" \
  789. "$opt_target_dir/boot/config.txt"
  790. if [ $opt_bit -eq 64 ]; then
  791. sed -i -e 's/arm_64bit=0/arm_64bit=1/g' \
  792. "$opt_target_dir/boot/config.txt" ||\
  793. die "Failed to set arm_64bit=1"
  794. fi
  795. # Prepare image paths.
  796. local imgfile="${opt_target_dir}${opt_imgsuffix}.img"
  797. local imgfile_zip="${imgfile}.7z"
  798. local bootimgfile="${imgfile}.boot"
  799. mp_bootimgfile="${bootimgfile}.mp"
  800. local rootimgfile="${imgfile}.root"
  801. mp_rootimgfile="${rootimgfile}.mp"
  802. rm -f "$imgfile" "$imgfile_zip" "$rootimgfile" "$bootimgfile"
  803. rmdir "$mp_bootimgfile" "$mp_rootimgfile" 2>/dev/null
  804. # Create images.
  805. if [ "$opt_img" -ne 0 ]; then
  806. # Calculate image size.
  807. local imgsize_b="$(expr "$opt_imgsize" \* 1000 \* 1000 \* 1000)"
  808. local imgsize_mib="$(expr "$imgsize_b" \/ 1024 \/ 1024)"
  809. # Reduce the size to make sure it fits every SD card.
  810. local imgsize_mib_red="$(expr \( "$imgsize_mib" \* 98 \) \/ 100)"
  811. [ -n "$imgsize_mib_red" ] || die "Failed to calculate image size"
  812. info "SD image size = $imgsize_mib_red MiB"
  813. info "Creating boot image..."
  814. mkfs.vfat -F 32 -i 7771B0BB -n boot -C "$bootimgfile" \
  815. $(expr \( 256 \* 1024 \) ) ||\
  816. die "Failed to create boot partition file system."
  817. mkdir "$mp_bootimgfile" ||\
  818. die "Failed to make boot partition mount point."
  819. mount -o loop "$bootimgfile" "$mp_bootimgfile" ||\
  820. die "Failed to mount boot partition."
  821. rsync -aHAX --inplace \
  822. "$opt_target_dir/boot/" "$mp_bootimgfile/" ||\
  823. die "Failed to copy boot files."
  824. umount "$mp_bootimgfile" ||\
  825. die "Failed to umount boot partition."
  826. rmdir "$mp_bootimgfile" ||\
  827. die "Failed to remove boot partition mount point."
  828. info "Creating root image..."
  829. mkfs.ext4 "$rootimgfile" $(expr \( "$imgsize_mib_red" - \( 256 + 4 + 4 \) \) \* 1024 ) ||\
  830. die "Failed to create root filesystem."
  831. mkdir "$mp_rootimgfile" ||\
  832. die "Failed to make root partition mount point."
  833. mount -o loop "$rootimgfile" "$mp_rootimgfile" ||\
  834. die "Failed to mount root partition."
  835. rsync -aHAX --inplace \
  836. --exclude='boot/*' \
  837. --exclude='dev/shm/*' \
  838. --exclude='proc/*' \
  839. --exclude='run/*' \
  840. --exclude='sys/*' \
  841. --exclude='tmp/*' \
  842. --exclude="$(basename "$opt_qemu")" \
  843. "$opt_target_dir/" "$mp_rootimgfile/" ||\
  844. die "Failed to copy root files."
  845. umount "$mp_rootimgfile" ||\
  846. die "Failed to umount root partition."
  847. rmdir "$mp_rootimgfile" ||\
  848. die "Failed to remove root partition mount point."
  849. info "Creating image '$imgfile'..."
  850. dd if=/dev/zero of="$imgfile" bs=1M count="$imgsize_mib_red" conv=sparse ||\
  851. die "Failed to create image file."
  852. parted "$imgfile" <<EOF
  853. unit b
  854. mklabel msdos
  855. mkpart primary fat32 $(expr 4 \* 1024 \* 1024) $(expr \( 256 + 4 \) \* 1024 \* 1024)
  856. mkpart primary ext4 $(expr \( 256 + 4 + 4 \) \* 1024 \* 1024) 100%
  857. EOF
  858. [ $? -eq 0 ] || die "Failed to create partitions."
  859. info "Integrating boot image..."
  860. dd if="$bootimgfile" of="$imgfile"\
  861. seek=4 bs=1M conv=notrunc,sparse ||\
  862. die "Failed to integrate boot partition."
  863. rm "$bootimgfile" ||\
  864. die "Failed to delete boot partition image."
  865. info "Integrating root image..."
  866. dd if="$rootimgfile" of="$imgfile"\
  867. seek="$(expr 256 + 4 + 4)" bs=1M conv=notrunc,sparse ||\
  868. die "Failed to integrate root partition."
  869. rm "$rootimgfile" ||\
  870. die "Failed to delete root partition image."
  871. # Create zipped image.
  872. if [ "$opt_zimg" -ne 0 ]; then
  873. info "Compressing image..."
  874. 7z -mx=9 a "$imgfile_zip" "$imgfile" ||\
  875. die "Failed to compress partition image."
  876. fi
  877. # Write the image to the SD card.
  878. if [ -n "$opt_writedev" ]; then
  879. write_image "$imgfile" "$opt_writedev"
  880. fi
  881. fi
  882. }
  883. usage()
  884. {
  885. echo "pilc-bootstrap.sh [OPTIONS] TARGET_DIR"
  886. echo
  887. echo "Options:"
  888. echo
  889. echo " --branch|-b BRANCH Select the awlsim branch or tag."
  890. echo " Default: $default_branch"
  891. echo
  892. echo " --no-cython|-C Do not build Cython modules."
  893. echo " Default: Build cython modules"
  894. echo
  895. echo " --suite|-s SUITE Select the suite."
  896. echo " Default: $default_suite"
  897. echo
  898. echo " --bit|-B BIT Build 32 bit or 64 bit image."
  899. echo " Default: $default_bit"
  900. echo
  901. echo " --qemu-bin|-Q PATH Select qemu-user-static binary."
  902. echo " Default: $default_qemu"
  903. echo
  904. echo " --img-suffix|-X SUFFIX Image file suffix."
  905. echo " Default: $default_imgsuffix"
  906. echo
  907. echo " --img-size|-S SIZEGB Image file size, in Gigabytes (base 1000)."
  908. echo " Default: $default_imgsize"
  909. echo
  910. echo " --no-img|-I Do not create an image."
  911. echo " Default: Create image."
  912. echo
  913. echo " --no-zimg|-Z Do not create a 7zipped image."
  914. echo " Default: Create 7zipped image."
  915. echo
  916. echo " --write|-w DEV Write image to an SD card after bootstrap."
  917. echo " DEV must be the /dev/mmcblkX path to the card."
  918. echo
  919. echo " --write-only|-W DEV Write an existing image to an SD card"
  920. echo " without bootstrap and image generation."
  921. echo
  922. echo " --skip-debootstrap1|-1 Skip debootstrap first stage."
  923. echo " --skip-debootstrap2|-2 Skip debootstrap second stage."
  924. echo
  925. echo " --quick|-q Quick build. This is a shortcut for:"
  926. echo " --no-cython --no-zimg"
  927. echo
  928. echo " --rpiver|-R VERSION Raspberry Pi version to build for."
  929. echo " Can be either 0, 1, 2, 3, 4 or generic"
  930. echo " 0 and 1 are equivalent."
  931. echo " generic runs on any Raspberry Pi 0-4."
  932. echo " Default: generic"
  933. }
  934. # Mountpoints. Will be umounted on cleanup.
  935. mp_shm=
  936. mp_proc=
  937. mp_proc_binfmt_misc=
  938. mp_sys=
  939. mp_bootimgfile=
  940. mp_rootimgfile=
  941. trap term_signal TERM INT
  942. if [ -z "$__PILC_BOOTSTRAP_SECOND_STAGE__" ]; then
  943. # First stage
  944. export _NPROCESSORS_ONLN="$(getconf _NPROCESSORS_ONLN)"
  945. [ -n "$_NPROCESSORS_ONLN" ] || die "Failed to get # of online CPUs"
  946. default_branch="master"
  947. default_suite="$DEFAULT_SUITE"
  948. default_bit=32
  949. default_qemu="/usr/bin/qemu-arm-static"
  950. default_imgsuffix="-$(date '+%Y%m%d')"
  951. default_imgsize=4
  952. default_img=1
  953. default_zimg=1
  954. default_writedev=
  955. default_writeonly=0
  956. default_rpiver="generic"
  957. opt_target_dir=
  958. opt_branch="$default_branch"
  959. opt_cython=1
  960. opt_suite="$default_suite"
  961. opt_bit="$default_bit"
  962. opt_qemu="$default_qemu"
  963. opt_skip_debootstrap1=0
  964. opt_skip_debootstrap2=0
  965. opt_imgsuffix="$default_imgsuffix"
  966. opt_imgsize="$default_imgsize"
  967. opt_img="$default_img"
  968. opt_zimg="$default_zimg"
  969. opt_writedev="$default_writedev"
  970. opt_writeonly="$default_writeonly"
  971. opt_rpiver="$default_rpiver"
  972. while [ $# -ge 1 ]; do
  973. case "$1" in
  974. --help|-h)
  975. usage
  976. exit 0
  977. ;;
  978. --branch|-b)
  979. shift
  980. opt_branch="$1"
  981. [ -n "$opt_branch" ] || die "No branch given"
  982. ;;
  983. --no-cython|-C)
  984. opt_cython=0
  985. ;;
  986. --suite|-s)
  987. shift
  988. opt_suite="$1"
  989. [ -n "$opt_suite" ] || die "No suite given"
  990. ;;
  991. --bit|-B)
  992. shift
  993. opt_bit="$1"
  994. [ "$opt_bit" = "32" -o "$opt_bit" = "64" ] || die "Invalid --bit. Must be 32 or 64."
  995. ;;
  996. --qemu-bin|-Q)
  997. shift
  998. opt_qemu="$1"
  999. [ -x "$opt_qemu" ] || die "No valid qemu binary given"
  1000. ;;
  1001. --skip-debootstrap1|-1)
  1002. opt_skip_debootstrap1=1
  1003. ;;
  1004. --skip-debootstrap2|-2)
  1005. opt_skip_debootstrap2=1
  1006. ;;
  1007. --img-suffix|-X)
  1008. shift
  1009. opt_imgsuffix="$1"
  1010. ;;
  1011. --img-size|-S)
  1012. shift
  1013. opt_imgsize="$(expr "$1" \* 1)"
  1014. [ -n "$opt_imgsize" ] || die "--img-size|-S is invalid"
  1015. ;;
  1016. --no-zimg|-Z)
  1017. opt_zimg=0
  1018. ;;
  1019. --no-img|-I)
  1020. opt_img=0
  1021. ;;
  1022. --quick|-q)
  1023. opt_cython=0
  1024. opt_zimg=0
  1025. ;;
  1026. --write|-w|--write-only|-W)
  1027. if [ "$1" = "--write" -o "$1" = "-w" ]; then
  1028. opt_writeonly=0
  1029. else
  1030. opt_writeonly=1
  1031. fi
  1032. shift
  1033. opt_writedev="$1"
  1034. [ -b "$opt_writedev" ] || die "Invalid SD card block device"
  1035. ;;
  1036. --rpiver|-R)
  1037. shift
  1038. opt_rpiver="$1"
  1039. [ "$opt_rpiver" = "generic" -o\
  1040. "$opt_rpiver" = "0" -o\
  1041. "$opt_rpiver" = "1" -o\
  1042. "$opt_rpiver" = "2" -o\
  1043. "$opt_rpiver" = "3" -o\
  1044. "$opt_rpiver" = "4" ] || die "Invalid --rpiver|-R"
  1045. ;;
  1046. *)
  1047. opt_target_dir="$*"
  1048. break
  1049. ;;
  1050. esac
  1051. shift
  1052. done
  1053. [ -n "$opt_target_dir" ] ||\
  1054. die "No TARGET_DIR"
  1055. opt_target_dir="$(readlink -m "${opt_target_dir}")"
  1056. [ -n "$opt_target_dir" ] || die "Failed to resolve target dir."
  1057. [ -d "$opt_target_dir" -o ! -e "$opt_target_dir" ] ||\
  1058. die "$opt_target_dir is not a directory"
  1059. if [ "$opt_rpiver" = "2" -o "$opt_rpiver" = "1" -o "$opt_rpiver" = "0" ]; then
  1060. [ $opt_bit -eq 32 ] || die "Option --bit must be 32 for RPi zero, 1 or 2."
  1061. fi
  1062. trap cleanup EXIT
  1063. if [ -n "$opt_writedev" -a $opt_writeonly -ne 0 ]; then
  1064. # Just write the image to the SD card, then exit.
  1065. write_image "${opt_target_dir}${opt_imgsuffix}.img" "$opt_writedev"
  1066. exit 0
  1067. fi
  1068. # Run first stage.
  1069. pilc_bootstrap_first_stage
  1070. info "Starting second stage."
  1071. # Export options for use by second stage.
  1072. export opt_target_dir
  1073. export opt_branch
  1074. export opt_cython
  1075. export opt_suite
  1076. export opt_bit
  1077. export opt_qemu
  1078. export opt_skip_debootstrap1
  1079. export opt_skip_debootstrap2
  1080. export opt_imgsuffix
  1081. export opt_zimg
  1082. export opt_img
  1083. export opt_writedev
  1084. export opt_writeonly
  1085. export opt_rpiver
  1086. export __PILC_BOOTSTRAP_SECOND_STAGE__=1
  1087. setarch "linux$opt_bit" \
  1088. chroot "$opt_target_dir" "/pilc-bootstrap.sh" ||\
  1089. die "Chroot failed."
  1090. # Run third stage.
  1091. pilc_bootstrap_third_stage
  1092. info ""
  1093. info "Successfully bootstrapped PiLC."
  1094. exit 0
  1095. else
  1096. # Run second stage
  1097. pilc_bootstrap_second_stage
  1098. exit 0
  1099. fi