pilc-bootstrap.sh 34 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211
  1. #!/bin/sh
  2. #
  3. # PiLC bootstrap
  4. #
  5. # Copyright 2016-2024 Michael Büsch <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. SUITE=bookworm
  27. MAIN_MIRROR_32="http://raspbian.raspberrypi.com/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. if have_program 7zz; then
  217. SEVENZIP=7zz
  218. elif have_program 7z; then
  219. SEVENZIP=7z
  220. else
  221. die "7z not found. Please install 7z."
  222. fi
  223. assert_program chroot
  224. assert_program dd
  225. assert_program debootstrap
  226. assert_program git
  227. assert_program gpg
  228. assert_program install
  229. assert_program mkfs.ext4
  230. assert_program mkfs.vfat
  231. assert_program parted
  232. assert_program rsync
  233. assert_program setarch
  234. assert_program tar
  235. assert_program unzip
  236. assert_program wget
  237. [ -x "$opt_qemu" ] ||\
  238. die "The qemu binary '$opt_qemu' is not executable."
  239. info "Cleaning tmp..."
  240. rm -rf "$opt_target_dir"/tmp/*
  241. do_install -d -o root -g root -m 1777 "$opt_target_dir/tmp"
  242. info "Downloading and extracting keys..."
  243. do_install -o root -g root -m 644 \
  244. "$basedir/keys/CF8A1AF502A2AA2D763BAE7E82B129927FA3303E.gpg" \
  245. "$opt_target_dir/tmp/"
  246. if [ $opt_bit -eq 32 ]; then
  247. download "$opt_target_dir/tmp/$KEYRING_TGZ_FILE" \
  248. "$KEYRING_BASEURL/$KEYRING_TGZ_FILE" \
  249. "$KEYRING_TGZ_SHA256"
  250. tar -C "$opt_target_dir/tmp" -x -f "$opt_target_dir/tmp/$KEYRING_TGZ_FILE" ||\
  251. die "Failed to extract keys."
  252. local raspbian_asc="$opt_target_dir/tmp/raspbian-archive-keyring-$KEYRING_VERSION/raspbian.public.key"
  253. local raspbian_gpg="$raspbian_asc.gpg"
  254. gpg --dearmor < "$raspbian_asc" > "$raspbian_gpg" ||\
  255. die "Failed to convert key."
  256. fi
  257. # debootstrap first stage.
  258. if [ $opt_skip_debootstrap1 -eq 0 ]; then
  259. info "Running debootstrap first stage..."
  260. if [ $opt_bit -eq 32 ]; then
  261. local arch="armhf"
  262. local keyopt="--keyring=$raspbian_gpg"
  263. local mirror="$MAIN_MIRROR_32"
  264. else
  265. local arch="arm64"
  266. local keyopt=
  267. local mirror="$MAIN_MIRROR_64"
  268. fi
  269. setarch "linux$opt_bit" \
  270. debootstrap --arch="$arch" --foreign \
  271. --components="main,contrib,non-free" \
  272. $keyopt \
  273. "$SUITE" "$opt_target_dir" "$mirror" \
  274. || die "debootstrap failed"
  275. fi
  276. [ -d "$opt_target_dir" ] ||\
  277. die "Target directory '$opt_target_dir' does not exist."
  278. # Avoid the start of daemons during second stage.
  279. do_install -o root -g root -m 755 \
  280. "$basedir/templates/policy-rc.d" \
  281. "$opt_target_dir/usr/sbin/"
  282. # Copy qemu.
  283. info "Copying qemu binary from '$opt_qemu' into '$opt_target_dir/usr/bin/'..."
  284. do_install -o root -g root -m 755 "$opt_qemu" "$opt_target_dir/usr/bin"
  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 --recursive submodules/pyprofibus ||\
  306. die "Failed to pull pyprofibus submodule"
  307. rm -r \
  308. .git \
  309. submodules/pyprofibus/.git \
  310. submodules/pyprofibus/phy_fpga/crcgen/.git ||\
  311. die "Failed to remove .git directory."
  312. mv submodules/pyprofibus .. ||\
  313. die "Failed to move pyprofibus submodule."
  314. ) || die
  315. # Fetch packages
  316. download "$opt_target_dir/tmp/$PPL_FILE" \
  317. "$awlsim_checkout_dir/$PPL_PATH" \
  318. "$PPL_SHA256"
  319. download "$opt_target_dir/tmp/$PPL2_FILE" \
  320. "$awlsim_checkout_dir/$PPL2_PATH" \
  321. "$PPL2_SHA256"
  322. # Second stage will mount a few filesystems.
  323. # Keep track to umount them in cleanup.
  324. mp_proc="$opt_target_dir/proc"
  325. mp_proc_binfmt_misc="$opt_target_dir/proc/sys/fs/binfmt_misc"
  326. mp_sys="$opt_target_dir/sys"
  327. mp_shm="$opt_target_dir/dev/shm"
  328. }
  329. pilc_bootstrap_second_stage()
  330. {
  331. info "Running second stage..."
  332. [ -x /pilc-bootstrap.sh ] ||\
  333. die "Second stage does not contain the bootstrap script."
  334. # Set up environment.
  335. export LC_ALL=C
  336. export LANGUAGE=C
  337. export LANG=C
  338. if [ "$opt_rpiver" = "1" -o "$opt_rpiver" = "0" ]; then
  339. info "Optimizing for RPi 1, zero(w)"
  340. local march="-march=armv6kz"
  341. local mtune="-mtune=arm1176jzf-s"
  342. elif [ "$opt_rpiver" = "2" ]; then
  343. info "Optimizing for RPi 2"
  344. local march="-march=armv7-a"
  345. local mtune="-mtune=cortex-a7"
  346. elif [ "$opt_rpiver" = "3" ]; then
  347. info "Optimizing for RPi 3"
  348. local march="-march=armv8-a"
  349. local mtune="-mtune=cortex-a53"
  350. elif [ "$opt_rpiver" = "4" ]; then
  351. info "Optimizing for RPi 4"
  352. local march="-march=armv8-a"
  353. local mtune="-mtune=cortex-a72"
  354. else
  355. info "Optimizing for generic RPi"
  356. if [ $opt_bit -eq 32 ]; then
  357. local march="-march=armv6kz"
  358. local mtune=
  359. else
  360. local march="-march=armv8-a"
  361. local mtune=
  362. fi
  363. fi
  364. export CFLAGS="-O3 $march $mtune -pipe"
  365. [ $opt_bit -eq 32 ] && export CFLAGS="$CFLAGS -mfpu=vfp -mfloat-abi=hard"
  366. export CXXFLAGS="$CFLAGS"
  367. # debootstrap second stage.
  368. if [ $opt_skip_debootstrap2 -eq 0 ]; then
  369. info "Running debootstrap second stage..."
  370. /debootstrap/debootstrap --verbose --second-stage ||\
  371. die "Debootstrap second stage failed."
  372. fi
  373. if [ $opt_bit -eq 32 ]; then
  374. info "Disabling raspi-copies-and-fills..."
  375. rm -f /etc/ld.so.preload || die "Failed to disable raspi-copies-and-fills"
  376. fi
  377. info "Mounting /proc..."
  378. do_install -d -o root -g root -m 755 /proc
  379. mount -t proc proc /proc || die "Mounting /proc failed."
  380. info "Mounting /sys..."
  381. do_install -d -o root -g root -m 755 /sys
  382. mount -t sysfs sysfs /sys || die "Mounting /sys failed."
  383. info "Mounting /dev/shm..."
  384. do_install -d -o root -g root -m 755 /dev/shm
  385. mount -t tmpfs tmpfs /dev/shm || die "Mounting /dev/shm failed."
  386. info "Creating /etc/fstab"
  387. do_install -d -o root -g root -m 755 /config
  388. do_install -T -o root -g root -m 644 \
  389. /tmp/templates/fstab \
  390. /etc/fstab
  391. info "Writing misc /etc stuff..."
  392. echo "pilc" > /etc/hostname || die "Failed to set hostname"
  393. printf 'PiLC GNU/Linux (based on Raspberry Pi OS) \\n \\l\n\n' > /etc/issue ||\
  394. die "Failed to create /etc/issue"
  395. printf 'PiLC GNU/Linux (based on Raspberry Pi OS)\n' > /etc/issue.net ||\
  396. die "Failed to create /etc/issue.net"
  397. sed -i -e 's|PRETTY_NAME=.*|PRETTY_NAME="PiLC"|' \
  398. /etc/os-release ||\
  399. die "Failed to set os-release PRETTY_NAME."
  400. sed -i -e 's|NAME=.*|NAME="PiLC"|' \
  401. /etc/os-release ||\
  402. die "Failed to set os-release NAME."
  403. sed -i -e 's|ID=.*|ID=pilc|' \
  404. /etc/os-release ||\
  405. die "Failed to set os-release ID."
  406. sed -i -e 's|ID_LIKE=.*|ID_LIKE=debian|' \
  407. /etc/os-release ||\
  408. die "Failed to set os-release ID_LIKE."
  409. sed -i -e 's|HOME_URL=.*|HOME_URL="https://bues.ch/a/pilc"|' \
  410. /etc/os-release ||\
  411. die "Failed to set os-release HOME_URL."
  412. sed -i -e 's|SUPPORT_URL=.*|SUPPORT_URL="https://bues.ch/a/pilc"|' \
  413. /etc/os-release ||\
  414. die "Failed to set os-release SUPPORT_URL."
  415. sed -i -e 's|BUG_REPORT_URL=.*|BUG_REPORT_URL="https://bues.ch/a/pilc"|' \
  416. /etc/os-release ||\
  417. die "Failed to set os-release BUG_REPORT_URL."
  418. info "Writing apt configuration..."
  419. local apt_opts="-y -o Acquire::Retries=3"
  420. if [ $opt_bit -eq 32 ]; then
  421. cat > /etc/apt/sources.list <<EOF
  422. deb [ arch=armhf ] $MAIN_MIRROR_32 $SUITE main contrib non-free rpi
  423. EOF
  424. [ $? -eq 0 ] || die "Failed to set sources.list"
  425. dpkg --add-architecture arm64 ||\
  426. die "dpkg --add-architecture failed"
  427. else
  428. cat > /etc/apt/sources.list <<EOF
  429. deb $MAIN_MIRROR_64 $SUITE main contrib non-free
  430. deb $MAIN_MIRROR_64_SECURITY $SUITE-security main contrib non-free
  431. deb $MAIN_MIRROR_64 $SUITE-updates main contrib non-free
  432. EOF
  433. [ $? -eq 0 ] || die "Failed to set sources.list"
  434. dpkg --add-architecture armhf ||\
  435. die "dpkg --add-architecture failed"
  436. fi
  437. echo 'Acquire { Languages "none"; };' > /etc/apt/apt.conf.d/99no-translations ||\
  438. die "Failed to set apt.conf.d"
  439. cat /tmp/templates/debconf-set-selections-preinstall.conf | debconf-set-selections ||\
  440. die "Failed to configure debconf settings"
  441. apt-get $apt_opts update ||\
  442. die "apt-get update failed"
  443. apt-get $apt_opts install apt-transport-https ||\
  444. die "apt-get install apt-transport-https failed"
  445. apt-get $apt_opts install \
  446. gnupg2 \
  447. debian-keyring \
  448. || die "apt-get install keyrings failed"
  449. cat > /etc/apt/sources.list.d/raspi.list <<EOF
  450. deb $MAIN_MIRROR_ARCHIVE $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. if [ $opt_bit -eq 32 ]; then
  549. local kernel_pkgs="linux-image-rpi-v6 linux-image-rpi-v7 linux-image-rpi-v7l linux-image-rpi-v8:arm64"
  550. else
  551. local kernel_pkgs="linux-image-rpi-v8"
  552. fi
  553. apt-get $apt_opts install \
  554. $kernel_pkgs \
  555. libraspberrypi-dev \
  556. libraspberrypi-doc \
  557. python3-rpi.gpio \
  558. raspberrypi-net-mods \
  559. raspberrypi-sys-mods \
  560. raspi-config \
  561. raspi-firmware \
  562. raspi-gpio \
  563. raspi-utils \
  564. rpi-eeprom \
  565. rpi-update \
  566. || die "apt-get install failed"
  567. info "Removing unnecessary keys and repos..."
  568. for file in /etc/apt/trusted.gpg.d/microsoft.gpg \
  569. /etc/apt/sources.list.d/vscode.list; do
  570. info "Replacing $file with dummy..."
  571. if [ -e "$file" ]; then
  572. rm "$file" || die "Failed to rm $file"
  573. fi
  574. touch "$file" || die "Failed to touch $file"
  575. chmod 444 "$file" || die "Failed to chmod 444 $file"
  576. done
  577. for file in /etc/apt/*.gpg~; do
  578. if [ -e "$file" ]; then
  579. info "Removing $file..."
  580. rm "$file" || die "Failed to rm $file"
  581. fi
  582. done
  583. apt-get $apt_opts update ||\
  584. die "apt-get update failed"
  585. info "Running debconf-set-selections..."
  586. cat /tmp/templates/debconf-set-selections-postinstall.conf | debconf-set-selections ||\
  587. die "Failed to configure debconf settings"
  588. info "Cleaning apt..."
  589. apt-get $apt_opts autoremove --purge ||\
  590. die "apt-get autoremove failed"
  591. apt-get $apt_opts clean ||\
  592. die "apt-get clean failed"
  593. info "Disabling some services..."
  594. do_systemctl mask apt-daily.service
  595. do_systemctl mask apt-daily.timer
  596. do_systemctl mask apt-daily-upgrade.timer
  597. do_systemctl mask rsync.service
  598. do_systemctl mask exim4.service
  599. do_systemctl mask triggerhappy.service
  600. do_systemctl mask triggerhappy.socket
  601. do_systemctl mask alsa-state.service
  602. do_systemctl mask alsa-restore.service
  603. do_systemctl mask alsa-utils.service
  604. info "Building and installing PiLC system package..."
  605. (
  606. cd /tmp/deb/pilc-system || die "Failed to cd to pilc-system"
  607. debuild -uc -us -b -d || die "debuild failed"
  608. dpkg -i ../pilc-system_*.deb || die "Failed to install pilc-system"
  609. # Copy debs
  610. rm -rf /home/pi/deb/pilc-system
  611. do_install -d -o pi -g pi -m 755 /home/pi/deb/pilc-system
  612. do_install -o pi -g pi -m 644 \
  613. ../*pilc-system*.deb \
  614. /home/pi/deb/pilc-system/
  615. ) || die
  616. info "Updating /etc/hosts..."
  617. if ! grep -qe pilc /etc/hosts; then
  618. printf '\n127.0.0.1\tpilc\n' >> /etc/hosts ||\
  619. die "Failed to update /etc/hosts"
  620. fi
  621. info "Building Python modules..."
  622. build_ppl
  623. build_ppl2
  624. info "Building awlsim..."
  625. (
  626. cd /tmp/awlsim/src || die "Failed to cd"
  627. if [ $opt_cython -eq 0 ]; then
  628. # Disable cython
  629. sed -i -e '/Package: cython/,/^$/ d' \
  630. debian/control ||\
  631. die "Failed to patch control file (cython)"
  632. sed -i -e 's/export AWLSIM_CYTHON_BUILD=1/export AWLSIM_CYTHON_BUILD=0/' \
  633. debian/rules ||\
  634. die "Failed to patch rules file (cython)"
  635. fi
  636. # Update the systemd service file.
  637. sed -i -e 's|AWLSIM_SCHED=|AWLSIM_SCHED=realtime-if-multicore|g' \
  638. -e 's|AWLSIM_PRIO=|AWLSIM_PRIO=50|g' \
  639. -e 's|AWLSIM_AFFINITY=|AWLSIM_AFFINITY=-1,-2,-3|g' \
  640. -e 's|AWLSIM_MLOCK=|AWLSIM_MLOCK=1|g' \
  641. -e 's|Nice=.*$|Nice=-5|g' \
  642. awlsim-server.service ||\
  643. die "Failed to patch awlsim-server.service"
  644. # Build the packages.
  645. debuild -uc -us -b -d || die "debuild failed"
  646. info "Installing awlsim..."
  647. # Core
  648. dpkg -i ../python3-awlsim_*.deb ||\
  649. die "Failed to install python3-awlsim"
  650. if [ $opt_cython -ne 0 ]; then
  651. dpkg -i ../cython3-awlsim_*.deb ||\
  652. die "Failed to install cython3-awlsim"
  653. fi
  654. # hardware: dummy
  655. dpkg -i ../python3-awlsimhw-dummy_*.deb ||\
  656. die "Failed to install python3-awlsimhw-dummy"
  657. if [ $opt_cython -ne 0 ]; then
  658. dpkg -i ../cython3-awlsimhw-dummy_*.deb ||\
  659. die "Failed to install cython3-awlsimhw-dummy"
  660. fi
  661. # hardware: linuxcnc
  662. dpkg -i ../python3-awlsimhw-linuxcnc_*.deb ||\
  663. die "Failed to install python3-awlsimhw-linuxcnc"
  664. if [ $opt_cython -ne 0 ]; then
  665. dpkg -i ../cython3-awlsimhw-linuxcnc_*.deb ||\
  666. die "Failed to install cython3-awlsimhw-linuxcnc"
  667. fi
  668. # hardware: profibus
  669. dpkg -i ../python3-awlsimhw-profibus_*.deb ||\
  670. die "Failed to install python3-awlsimhw-profibus"
  671. if [ $opt_cython -ne 0 ]; then
  672. dpkg -i ../cython3-awlsimhw-profibus_*.deb ||\
  673. die "Failed to install cython3-awlsimhw-profibus"
  674. fi
  675. # hardware: RPi GPIO
  676. dpkg -i ../python3-awlsimhw-rpigpio_*.deb ||\
  677. die "Failed to install python3-awlsimhw-rpigpio"
  678. if [ $opt_cython -ne 0 ]; then
  679. dpkg -i ../cython3-awlsimhw-rpigpio_*.deb ||\
  680. die "Failed to install cython3-awlsimhw-rpigpio"
  681. fi
  682. # hardware: PiXtend
  683. dpkg -i ../python3-awlsimhw-pixtend_*.deb ||\
  684. die "Failed to install python3-awlsimhw-pixtend"
  685. if [ $opt_cython -ne 0 ]; then
  686. dpkg -i ../cython3-awlsimhw-pixtend_*.deb ||\
  687. die "Failed to install cython3-awlsimhw-pixtend"
  688. fi
  689. # Executables
  690. dpkg -i ../awlsim-server_*.deb ||\
  691. die "Failed to install awlsim-server"
  692. dpkg -i ../awlsim-client_*.deb ||\
  693. die "Failed to install awlsim-client"
  694. dpkg -i ../awlsim-symtab_*.deb ||\
  695. die "Failed to install awlsim-symtab"
  696. dpkg -i ../awlsim-test_*.deb ||\
  697. die "Failed to install awlsim-test"
  698. dpkg -i ../awlsim-proupgrade_*.deb ||\
  699. die "Failed to install awlsim-proupgrade"
  700. # Copy debs
  701. rm -rf /home/pi/deb/awlsim
  702. do_install -d -o pi -g pi -m 755 /home/pi/deb/awlsim
  703. do_install -o pi -g pi -m 644 \
  704. ../*awlsim*.deb \
  705. /home/pi/deb/awlsim/
  706. # Copy examples
  707. do_install -T -o pi -g pi -m 644 \
  708. examples/EXAMPLE.awlpro \
  709. /home/pi/generic-example.awlpro
  710. do_install -T -o pi -g pi -m 644 \
  711. examples/raspberrypi-gpio.awlpro \
  712. /home/pi/raspberrypi-gpio-example.awlpro
  713. do_install -T -o pi -g pi -m 644 \
  714. examples/raspberrypi-profibus.awlpro \
  715. /home/pi/raspberrypi-profibus-example.awlpro
  716. do_install -T -o pi -g pi -m 644 \
  717. examples/raspberrypi-pixtend.awlpro \
  718. /home/pi/raspberrypi-pixtend-example.awlpro
  719. ) || die
  720. info "Building pyprofibus..."
  721. (
  722. cd /tmp/awlsim/pyprofibus ||\
  723. die "Failed to cd"
  724. if [ $opt_cython -eq 0 ]; then
  725. # Disable cython
  726. sed -i -e '/Package: cython/,/^$/ d' \
  727. debian/control ||\
  728. die "Failed to patch control file (cython)"
  729. sed -i -e 's/export PYPROFIBUS_CYTHON_BUILD=1/export PYPROFIBUS_CYTHON_BUILD=0/' \
  730. debian/rules ||\
  731. die "Failed to patch rules file (cython)"
  732. fi
  733. # Build the packages.
  734. debuild -uc -us -b -d || die "debuild failed"
  735. info "Installing pyprofibus..."
  736. dpkg -i ../python3-pyprofibus_*.deb ||\
  737. die "Failed to install python3-pyprofibus"
  738. dpkg -i ../profisniff_*.deb ||\
  739. die "Failed to install profisniff"
  740. dpkg -i ../gsdparser_*.deb ||\
  741. die "Failed to install gsdparser"
  742. # Copy debs
  743. rm -rf /home/pi/deb/pyprofibus
  744. do_install -d -o pi -g pi -m 755 /home/pi/deb/pyprofibus
  745. do_install -o pi -g pi -m 644 \
  746. ../*pyprofibus*.deb \
  747. ../profisniff_*.deb \
  748. ../gsdparser_*.deb \
  749. /home/pi/deb/pyprofibus/
  750. ) || die
  751. rm -r /tmp/awlsim ||\
  752. die "Failed to remove awlsim checkout."
  753. info "Updating home directory permissions..."
  754. chown -R pi:pi /home/pi || die "Failed to change /home/pi permissions."
  755. # Remove rc.d policy file
  756. if [ -e /usr/sbin/policy-rc.d ]; then
  757. rm /usr/sbin/policy-rc.d ||\
  758. die "Failed to remove policy-rc.d"
  759. fi
  760. if [ $opt_bit -eq 32 ]; then
  761. # Install this last. It won't work correctly in the qemu environment.
  762. info "Installing raspi-copies-and-fills..."
  763. apt-get $apt_opts install --reinstall raspi-copies-and-fills ||\
  764. die "apt-get install failed"
  765. fi
  766. info "Stopping processes..."
  767. for i in dbus ssh irqbalance; do
  768. /etc/init.d/$i stop
  769. done
  770. }
  771. pilc_bootstrap_third_stage()
  772. {
  773. info "Running third stage..."
  774. info "Umounting /dev/shm..."
  775. umount -l "$mp_shm" || die "Failed to umount /dev/shm"
  776. info "Umounting /sys..."
  777. umount -l "$mp_sys" || die "Failed to umount /sys"
  778. info "Umounting /proc/sys/fs/binfmt_misc..."
  779. umount -l "$mp_proc_binfmt_misc"
  780. info "Umounting /proc..."
  781. umount -l "$mp_proc" || die "Failed to umount /proc"
  782. info "Removing PiLC bootstrap script..."
  783. rm "$opt_target_dir/pilc-bootstrap.sh" ||\
  784. die "Failed to remove bootstrap script."
  785. info "Cleaning tmp..."
  786. rm -rf "$opt_target_dir"/tmp/*
  787. info "Configuring /boot/firmware..."
  788. do_install -T -o root -g root -m 644 \
  789. "$basedir/templates/boot_cmdline.txt" \
  790. "$opt_target_dir/boot/firmware/cmdline.txt"
  791. do_install -T -o root -g root -m 644 \
  792. "$basedir/templates/boot_config.txt" \
  793. "$opt_target_dir/boot/firmware/config.txt"
  794. ln -sf firmware/cmdline.txt "$opt_target_dir/boot/cmdline.txt" ||\
  795. die "Failed to create cmdline.txt link."
  796. ln -sf firmware/config.txt "$opt_target_dir/boot/config.txt" ||\
  797. die "Failed to create config.txt link."
  798. if [ $opt_bit -eq 64 ]; then
  799. sed -i -e 's/arm_64bit=0/arm_64bit=1/g' \
  800. "$opt_target_dir/boot/firmware/config.txt" ||\
  801. die "Failed to set arm_64bit=1"
  802. fi
  803. # Prepare image paths.
  804. local imgfile="${opt_target_dir}${opt_imgsuffix}.img"
  805. local imgfile_zip="${imgfile}.7z"
  806. local firmwareimgfile="${imgfile}.firmware"
  807. mp_firmwareimgfile="${firmwareimgfile}.mp"
  808. local rootimgfile="${imgfile}.root"
  809. mp_rootimgfile="${rootimgfile}.mp"
  810. rm -f "$imgfile" "$imgfile_zip" "$rootimgfile" "$firmwareimgfile"
  811. rmdir "$mp_firmwareimgfile" "$mp_rootimgfile" 2>/dev/null
  812. # Create images.
  813. if [ "$opt_img" -ne 0 ]; then
  814. # Calculate image size.
  815. local imgsize_b="$(expr "$opt_imgsize" \* 1000 \* 1000 \* 1000)"
  816. local imgsize_mib="$(expr "$imgsize_b" \/ 1024 \/ 1024)"
  817. # Reduce the size to make sure it fits every SD card.
  818. local imgsize_mib_red="$(expr \( "$imgsize_mib" \* 98 \) \/ 100)"
  819. [ -n "$imgsize_mib_red" ] || die "Failed to calculate image size"
  820. info "SD image size = $imgsize_mib_red MiB"
  821. info "Creating /boot/firmware image..."
  822. mkfs.vfat -F 32 -i 7771B0BB -n boot -C "$firmwareimgfile" \
  823. $(expr \( 256 \* 1024 \) ) ||\
  824. die "Failed to create /boot/firmware partition file system."
  825. mkdir "$mp_firmwareimgfile" ||\
  826. die "Failed to make /boot/firmware partition mount point."
  827. mount -o loop "$firmwareimgfile" "$mp_firmwareimgfile" ||\
  828. die "Failed to mount /boot/firmware partition."
  829. rsync -rt --inplace \
  830. "$opt_target_dir/boot/firmware/" "$mp_firmwareimgfile/" ||\
  831. die "Failed to copy /boot/firmware files."
  832. umount "$mp_firmwareimgfile" ||\
  833. die "Failed to umount /boot/firmware partition."
  834. rmdir "$mp_firmwareimgfile" ||\
  835. die "Failed to remove /boot/firmware partition mount point."
  836. info "Creating root image..."
  837. mkfs.ext4 -O ^metadata_csum_seed \
  838. "$rootimgfile" \
  839. $(expr \( "$imgsize_mib_red" - \( 256 + 4 + 4 \) \) \* 1024 ) ||\
  840. die "Failed to create root filesystem."
  841. mkdir "$mp_rootimgfile" ||\
  842. die "Failed to make root partition mount point."
  843. mount -o loop "$rootimgfile" "$mp_rootimgfile" ||\
  844. die "Failed to mount root partition."
  845. rsync -aHAX --inplace \
  846. --exclude='boot/firmware/*' \
  847. --exclude='dev/shm/*' \
  848. --exclude='proc/*' \
  849. --exclude='run/*' \
  850. --exclude='sys/*' \
  851. --exclude='tmp/*' \
  852. --exclude="$(basename "$opt_qemu")" \
  853. "$opt_target_dir/" "$mp_rootimgfile/" ||\
  854. die "Failed to copy root files."
  855. umount "$mp_rootimgfile" ||\
  856. die "Failed to umount root partition."
  857. rmdir "$mp_rootimgfile" ||\
  858. die "Failed to remove root partition mount point."
  859. info "Creating image '$imgfile'..."
  860. dd if=/dev/zero of="$imgfile" bs=1M count="$imgsize_mib_red" conv=sparse ||\
  861. die "Failed to create image file."
  862. parted "$imgfile" <<EOF
  863. unit b
  864. mklabel msdos
  865. mkpart primary fat32 $(expr 4 \* 1024 \* 1024) $(expr \( 256 + 4 \) \* 1024 \* 1024)
  866. mkpart primary ext4 $(expr \( 256 + 4 + 4 \) \* 1024 \* 1024) 100%
  867. EOF
  868. [ $? -eq 0 ] || die "Failed to create partitions."
  869. info "Integrating /boot/firmware image..."
  870. dd if="$firmwareimgfile" of="$imgfile"\
  871. seek=4 bs=1M conv=notrunc,sparse ||\
  872. die "Failed to integrate /boot/firmware partition."
  873. rm "$firmwareimgfile" ||\
  874. die "Failed to delete /boot/firmware partition image."
  875. info "Integrating root image..."
  876. dd if="$rootimgfile" of="$imgfile"\
  877. seek="$(expr 256 + 4 + 4)" bs=1M conv=notrunc,sparse ||\
  878. die "Failed to integrate root partition."
  879. rm "$rootimgfile" ||\
  880. die "Failed to delete root partition image."
  881. # Create zipped image.
  882. if [ "$opt_zimg" -ne 0 ]; then
  883. info "Compressing image..."
  884. "$SEVENZIP" -mx=9 a "$imgfile_zip" "$imgfile" ||\
  885. die "Failed to compress partition image."
  886. fi
  887. # Write the image to the SD card.
  888. if [ -n "$opt_writedev" ]; then
  889. write_image "$imgfile" "$opt_writedev"
  890. fi
  891. fi
  892. }
  893. usage()
  894. {
  895. echo "pilc-bootstrap.sh [OPTIONS] TARGET_DIR"
  896. echo
  897. echo "Options:"
  898. echo
  899. echo " --branch|-b BRANCH Select the awlsim branch or tag."
  900. echo " Default: $default_branch"
  901. echo
  902. echo " --no-cython|-C Do not build Cython modules."
  903. echo " Default: Build cython modules"
  904. echo
  905. echo " --bit|-B BIT Build 32 bit or 64 bit image."
  906. echo " Default: $default_bit"
  907. echo
  908. echo " --qemu-bin|-Q PATH Select qemu-user-static binary."
  909. echo " Default: $default_qemu"
  910. echo
  911. echo " --img-suffix|-X SUFFIX Image file suffix."
  912. echo " Default: $default_imgsuffix"
  913. echo
  914. echo " --img-size|-S SIZEGB Image file size, in Gigabytes (base 1000)."
  915. echo " Default: $default_imgsize"
  916. echo
  917. echo " --no-img|-I Do not create an image."
  918. echo " Default: Create image."
  919. echo
  920. echo " --no-zimg|-Z Do not create a 7zipped image."
  921. echo " Default: Create 7zipped image."
  922. echo
  923. echo " --write|-w DEV Write image to an SD card after bootstrap."
  924. echo " DEV must be the /dev/mmcblkX path to the card."
  925. echo
  926. echo " --write-only|-W DEV Write an existing image to an SD card"
  927. echo " without bootstrap and image generation."
  928. echo
  929. echo " --skip-debootstrap1|-1 Skip debootstrap first stage."
  930. echo " --skip-debootstrap2|-2 Skip debootstrap second stage."
  931. echo
  932. echo " --quick|-q Quick build. This is a shortcut for:"
  933. echo " --no-cython --no-zimg"
  934. echo
  935. echo " --rpiver|-R VERSION Raspberry Pi version to build for."
  936. echo " Can be either 0, 1, 2, 3, 4 or generic"
  937. echo " 0 and 1 are equivalent."
  938. echo " generic runs on any Raspberry Pi 0-4."
  939. echo " Default: generic"
  940. }
  941. # Mountpoints. Will be umounted on cleanup.
  942. mp_shm=
  943. mp_proc=
  944. mp_proc_binfmt_misc=
  945. mp_sys=
  946. mp_bootimgfile=
  947. mp_rootimgfile=
  948. trap term_signal TERM INT
  949. if [ -z "$__PILC_BOOTSTRAP_SECOND_STAGE__" ]; then
  950. # First stage
  951. export _NPROCESSORS_ONLN="$(getconf _NPROCESSORS_ONLN)"
  952. [ -n "$_NPROCESSORS_ONLN" ] || die "Failed to get # of online CPUs"
  953. default_branch="master"
  954. default_bit=32
  955. default_qemu="/usr/bin/qemu-arm-static"
  956. default_imgsuffix="-$(date '+%Y%m%d')"
  957. default_imgsize=4
  958. default_img=1
  959. default_zimg=1
  960. default_writedev=
  961. default_writeonly=0
  962. default_rpiver="generic"
  963. opt_target_dir=
  964. opt_branch="$default_branch"
  965. opt_cython=1
  966. opt_bit="$default_bit"
  967. opt_qemu="$default_qemu"
  968. opt_skip_debootstrap1=0
  969. opt_skip_debootstrap2=0
  970. opt_imgsuffix="$default_imgsuffix"
  971. opt_imgsize="$default_imgsize"
  972. opt_img="$default_img"
  973. opt_zimg="$default_zimg"
  974. opt_writedev="$default_writedev"
  975. opt_writeonly="$default_writeonly"
  976. opt_rpiver="$default_rpiver"
  977. while [ $# -ge 1 ]; do
  978. case "$1" in
  979. --help|-h)
  980. usage
  981. exit 0
  982. ;;
  983. --branch|-b)
  984. shift
  985. opt_branch="$1"
  986. [ -n "$opt_branch" ] || die "No branch given"
  987. ;;
  988. --no-cython|-C)
  989. opt_cython=0
  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_bit
  1076. export opt_qemu
  1077. export opt_skip_debootstrap1
  1078. export opt_skip_debootstrap2
  1079. export opt_imgsuffix
  1080. export opt_zimg
  1081. export opt_img
  1082. export opt_writedev
  1083. export opt_writeonly
  1084. export opt_rpiver
  1085. export __PILC_BOOTSTRAP_SECOND_STAGE__=1
  1086. setarch "linux$opt_bit" \
  1087. chroot "$opt_target_dir" "/pilc-bootstrap.sh" ||\
  1088. die "Chroot failed."
  1089. # Run third stage.
  1090. pilc_bootstrap_third_stage
  1091. info ""
  1092. info "Successfully bootstrapped PiLC."
  1093. exit 0
  1094. else
  1095. # Run second stage
  1096. pilc_bootstrap_second_stage
  1097. exit 0
  1098. fi