pilc-bootstrap.sh 34 KB

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