pilc-bootstrap.sh 35 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286
  1. #!/bin/sh
  2. #
  3. # PiLC bootstrap
  4. #
  5. # Copyright 2016-2018 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. # The repository root is basedir.
  24. basedir="$basedir/.."
  25. MAIN_MIRROR="http://mirrordirector.raspbian.org/raspbian/"
  26. DEFAULT_SUITE=stretch
  27. RPIGPIO_VERSION="0.6.3"
  28. RPIGPIO_FILE="RPi.GPIO-$RPIGPIO_VERSION.tar.gz"
  29. RPIGPIO_MIRROR="https://netcologne.dl.sourceforge.net/project/raspberry-gpio-python/$RPIGPIO_FILE"
  30. RPIGPIO_SHA256="9366ff36104a39368759929e71f0d8ad6a88553497b3064cbc40f4248806cc19"
  31. SPIDEV_VERSION="3.2"
  32. SPIDEV_FILE="spidev-$SPIDEV_VERSION.tar.gz"
  33. SPIDEV_MIRROR="https://pypi.python.org/packages/36/83/73748b6e1819b57d8e1df8090200195cdae33aaa22a49a91ded16785eedd/$SPIDEV_FILE"
  34. SPIDEV_SHA256="09d2b5122f0dd79910713a11f9a0020f71537224bf829916def4fffc0ea59456"
  35. PPL_VERSION="0.1.1"
  36. PPL_FILE="ppl_v$PPL_VERSION.zip"
  37. PPL_MIRROR="./libs/pixtend/v1/ppl/$PPL_FILE"
  38. PPL_SHA256="103edcdbc377f8b478fcbc89117cbad143500c611cb714568f55513cece220d4"
  39. PPL2_VERSION="0.1.1-awlsim1"
  40. PPL2_FILE="pplv2_v$PPL2_VERSION.zip"
  41. PPL2_MIRROR="./libs/pixtend/v2/pplv2/$PPL2_FILE"
  42. PPL2_SHA256="ba5259e612beccb55f664bfa22d27390ec766ce655b193c27695fe8a2ceca606"
  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. write_image()
  101. {
  102. local image="$1"
  103. local dev="$2"
  104. if have_program blkdiscard; then
  105. info "Discarding $dev ..."
  106. blkdiscard "$dev" ||\
  107. error "blkdiscard failed."
  108. else
  109. warning "Skipping discard. blkdiscard not installed."
  110. fi
  111. info "Writing $image to $dev ..."
  112. [ -b "$dev" ] || die "$dev is not a block device"
  113. mount | grep -q "$dev" && die "$dev is mounted. Refusing to write to it!"
  114. dd if="$image" of="$dev" bs=32M status=progress ||\
  115. die "Failed to write image."
  116. }
  117. boot_config_file()
  118. {
  119. cat <<EOF
  120. # For more options and information see
  121. # http://www.raspberrypi.org/documentation/configuration/config-txt.md
  122. # Some settings may impact device functionality. See link above for details
  123. # uncomment if you get no picture on HDMI for a default "safe" mode
  124. #hdmi_safe=1
  125. # uncomment this if your display has a black border of unused pixels visible
  126. # and your display can output without overscan
  127. #disable_overscan=1
  128. # uncomment the following to adjust overscan. Use positive numbers if console
  129. # goes off screen, and negative if there is too much border
  130. #overscan_left=16
  131. #overscan_right=16
  132. #overscan_top=16
  133. #overscan_bottom=16
  134. # uncomment to force a console size. By default it will be display's size minus
  135. # overscan.
  136. #framebuffer_width=1280
  137. #framebuffer_height=720
  138. # uncomment if hdmi display is not detected and composite is being output
  139. #hdmi_force_hotplug=1
  140. # uncomment to force a specific HDMI mode (this will force VGA)
  141. #hdmi_group=1
  142. #hdmi_mode=1
  143. # uncomment to force a HDMI mode rather than DVI. This can make audio work in
  144. # DMT (computer monitor) modes
  145. #hdmi_drive=2
  146. # uncomment to increase signal to HDMI, if you have interference, blanking, or
  147. # no display
  148. #config_hdmi_boost=4
  149. # uncomment for composite PAL
  150. #sdtv_mode=2
  151. # GPU memory
  152. gpu_mem=16
  153. #uncomment to overclock the arm. 700 MHz is the default.
  154. #arm_freq=800
  155. # Uncomment some or all of these to enable the optional hardware interfaces
  156. dtparam=i2c_arm=on
  157. dtparam=i2c_vc=on
  158. #dtparam=i2s=on
  159. dtparam=spi=on
  160. # I2C-1 baud rate 100 kHz
  161. dtparam=i2c1_baudrate=100000
  162. # Enable DS1307 real time clock
  163. dtoverlay=i2c-rtc,ds1307
  164. # Uncomment this to enable the lirc-rpi module
  165. #dtoverlay=lirc-rpi
  166. # Additional overlays and parameters are documented /boot/overlays/README
  167. # Enable audio (loads snd_bcm2835)
  168. dtparam=audio=on
  169. EOF
  170. }
  171. policy_rcd_file()
  172. {
  173. cat <<EOF
  174. #!/bin/sh
  175. exit 101
  176. EOF
  177. }
  178. download()
  179. {
  180. local target="$1"
  181. local mirror="$2"
  182. local sha256="$3"
  183. info "Downloading $mirror..."
  184. rm -f "$target"
  185. if printf '%s' "$mirror" | grep -qe '^\./'; then
  186. # "mirror" starts with ./
  187. # This is a local file in the repository.
  188. cp "$basedir/$mirror" "$target" || die "Failed to fetch $mirror"
  189. else
  190. # Download the file
  191. wget -O "$target" "$mirror" || die "Failed to fetch $mirror"
  192. fi
  193. [ "$(sha256sum -b "$target" | cut -f1 -d' ')" = "$sha256" ] ||\
  194. die "SHA256 verification of $target failed"
  195. }
  196. extract_archive()
  197. {
  198. local archive="$1"
  199. local extract_dir="$2"
  200. local make_extract_dir="$3"
  201. if [ $make_extract_dir -ne 0 ]; then
  202. mkdir "$extract_dir" ||\
  203. die "Failed to create directory $extract_dir"
  204. fi
  205. if printf '%s' "$archive" | grep -qEe '\.zip$'; then
  206. if [ $make_extract_dir -ne 0 ]; then
  207. unzip -d "$extract_dir" "$archive" ||\
  208. die "Failed to unpack $archive"
  209. else
  210. unzip "$archive" ||\
  211. die "Failed to unpack $archive"
  212. fi
  213. else
  214. if [ $make_extract_dir -ne 0 ]; then
  215. tar --one-top-level="$extract_dir" -xf "$archive" ||\
  216. die "Failed to unpack $archive"
  217. else
  218. tar -xf "$archive" ||\
  219. die "Failed to unpack $archive"
  220. fi
  221. fi
  222. }
  223. build_pythonpack()
  224. {
  225. local python="$1"
  226. local name="$2"
  227. local archive="$3"
  228. local extract_dir="$4"
  229. local make_extract_dir="$5"
  230. info "Building $name for $python..."
  231. rm -rf "/tmp/$extract_dir"
  232. (
  233. cd /tmp || die "Failed to cd /tmp"
  234. extract_archive "$archive" "$extract_dir" "$make_extract_dir"
  235. cd "$extract_dir" ||\
  236. die "Failed to cd $extract_dir"
  237. "$python" ./setup.py install ||\
  238. die "Failed to install $name"
  239. ) || die
  240. rm -r "/tmp/$extract_dir" ||\
  241. die "Failed to remove $name build files."
  242. }
  243. build_rpigpio()
  244. {
  245. local archive="$RPIGPIO_FILE"
  246. for python in pypy; do
  247. build_pythonpack "$python" "RPi.GPIO-$RPIGPIO_VERSION" \
  248. "$archive" "RPi.GPIO-$RPIGPIO_VERSION" 0
  249. done
  250. rm "/tmp/$archive" ||\
  251. die "Failed to remove /tmp/$archive."
  252. }
  253. build_spidev()
  254. {
  255. local archive="$SPIDEV_FILE"
  256. for python in pypy; do
  257. build_pythonpack "$python" "spidev-$SPIDEV_VERSION" \
  258. "$archive" "spidev-$SPIDEV_VERSION" 0
  259. done
  260. rm "/tmp/$archive" ||\
  261. die "Failed to remove /tmp/$archive."
  262. }
  263. build_ppl()
  264. {
  265. local archive="$PPL_FILE"
  266. for python in python python3 pypy; do
  267. build_pythonpack "$python" "ppl-$PPL_VERSION" \
  268. "$archive" "ppl-$PPL_VERSION" 1
  269. done
  270. rm "/tmp/$archive" ||\
  271. die "Failed to remove /tmp/$archive."
  272. }
  273. build_ppl2()
  274. {
  275. local archive="$PPL2_FILE"
  276. for python in python python3 pypy; do
  277. build_pythonpack "$python" "ppl2-$PPL2_VERSION" \
  278. "$archive" "ppl2-$PPL2_VERSION" 1
  279. done
  280. rm "/tmp/$archive" ||\
  281. die "Failed to remove /tmp/$archive."
  282. }
  283. pilc_bootstrap_first_stage()
  284. {
  285. echo "Running first stage..."
  286. [ "$(id -u)" = "0" ] || die "Permission denied. Must be root."
  287. # Check host tools (first/third stage).
  288. assert_program debootstrap
  289. assert_program git
  290. assert_program chroot
  291. assert_program rsync
  292. assert_program parted
  293. assert_program mkfs.vfat
  294. assert_program mkfs.ext4
  295. assert_program 7z
  296. assert_program tar
  297. assert_program unzip
  298. assert_program install
  299. [ -x "$opt_qemu" ] ||\
  300. die "The qemu binary '$opt_qemu' is not executable."
  301. # debootstrap first stage.
  302. if [ $opt_skip_debootstrap1 -eq 0 ]; then
  303. info "Running debootstrap first stage..."
  304. debootstrap --arch="$opt_arch" --foreign --verbose \
  305. --keyring="$basedir/pilc/raspbian.public.key.gpg" \
  306. "$opt_suite" "$opt_target_dir" "$MAIN_MIRROR" \
  307. || die "debootstrap failed"
  308. mkdir -p "$opt_target_dir/usr/share/keyrings" ||\
  309. die "Failed to create keyrings dir."
  310. cp "$basedir/pilc/raspbian.archive.public.key.gpg" \
  311. "$opt_target_dir/usr/share/keyrings/" ||\
  312. die "Failed to copy raspbian.archive.public.key.gpg."
  313. cp /usr/share/keyrings/debian-archive-keyring.gpg \
  314. "$opt_target_dir/usr/share/keyrings/debian-archive-keyring.gpg" ||\
  315. die "Failed to copy debian-archive-keyring.gpg."
  316. fi
  317. [ -d "$opt_target_dir" ] ||\
  318. die "Target directory '$opt_target_dir' does not exist."
  319. # Avoid the start of daemons during second stage.
  320. policy_rcd_file > "$opt_target_dir/usr/sbin/policy-rc.d" ||\
  321. die "Failed to create policy-rc.d"
  322. chmod 755 "$opt_target_dir/usr/sbin/policy-rc.d" ||\
  323. die "Failed to chmod policy-rc.d"
  324. info "Cleaning tmp..."
  325. rm -rf "$opt_target_dir"/tmp/*
  326. # Copy qemu.
  327. local qemu_bin="$opt_target_dir/$opt_qemu"
  328. if ! [ -x "$qemu_bin" ]; then
  329. info "Copying qemu binary from '$opt_qemu' to '$qemu_bin'..."
  330. mkdir -p "$(dirname "$qemu_bin")" ||\
  331. die "Failed to make qemu base directory."
  332. cp "$opt_qemu" "$qemu_bin" ||\
  333. die "Failed to copy qemu binary."
  334. fi
  335. info "Copying PiLC bootstrap script..."
  336. cp "$basedir/pilc/pilc-bootstrap.sh" "$opt_target_dir/" ||\
  337. die "Failed to copy bootstrap script."
  338. info "Checking out awlsim..."
  339. local awlsim_dir="$opt_target_dir/tmp/awlsim"
  340. local checkout_dir="$awlsim_dir/src"
  341. rm -rf "$awlsim_dir"
  342. mkdir -p "$awlsim_dir" || die "mkdir failed"
  343. git clone --no-checkout "$basedir/.git" "$checkout_dir" ||\
  344. die "Failed to clone"
  345. (
  346. cd "$checkout_dir" ||\
  347. die "Failed to cd"
  348. git checkout "$opt_branch" ||\
  349. die "Failed to check out branch."
  350. git submodule update --init submodules/pyprofibus ||\
  351. die "Failed to pull pyprofibus submodule"
  352. rm -r .git submodules/pyprofibus/.git ||\
  353. die "Failed to remove .git directory."
  354. mv submodules/pyprofibus .. ||\
  355. die "Failed to move pyprofibus submodule."
  356. ) || die
  357. # Fetch packages
  358. download "$opt_target_dir/tmp/$RPIGPIO_FILE" "$RPIGPIO_MIRROR" "$RPIGPIO_SHA256"
  359. download "$opt_target_dir/tmp/$SPIDEV_FILE" "$SPIDEV_MIRROR" "$SPIDEV_SHA256"
  360. download "$opt_target_dir/tmp/$PPL_FILE" "$PPL_MIRROR" "$PPL_SHA256"
  361. download "$opt_target_dir/tmp/$PPL2_FILE" "$PPL2_MIRROR" "$PPL2_SHA256"
  362. # Second stage will mount a few filesystems.
  363. # Keep track to umount them in cleanup.
  364. mp_proc="$opt_target_dir/proc"
  365. mp_proc_binfmt_misc="$opt_target_dir/proc/sys/fs/binfmt_misc"
  366. mp_sys="$opt_target_dir/sys"
  367. mp_shm="$opt_target_dir/dev/shm"
  368. }
  369. pilc_bootstrap_second_stage()
  370. {
  371. info "Running second stage ($opt_arch)..."
  372. [ -x /pilc-bootstrap.sh ] ||\
  373. die "Second stage does not contain the bootstrap script."
  374. # Set up environment.
  375. export LC_ALL=C
  376. export LANGUAGE=C
  377. export LANG=C
  378. if [ "$opt_rpiver" = "1" -o "$opt_rpiver" = "0" ]; then
  379. info "Optimizing for RPi 1.x, zero(w) or later"
  380. local march="armv6kz"
  381. elif [ "$opt_rpiver" = "2" ]; then
  382. info "Optimizing for RPi 2.x or later"
  383. local march="armv7-a"
  384. else
  385. info "Optimizing for RPi 3.x or later"
  386. local march="armv8-a"
  387. fi
  388. export CFLAGS="-O3 -march=$march -mfpu=vfp -mfloat-abi=hard -pipe"
  389. export CXXFLAGS="$CFLAGS"
  390. # export CC=clang LINKCC=clang LDSHARED="clang -shared" CXX=clang++
  391. # debootstrap second stage.
  392. if [ $opt_skip_debootstrap2 -eq 0 ]; then
  393. info "Running debootstrap second stage..."
  394. /debootstrap/debootstrap --verbose --second-stage ||\
  395. die "Debootstrap second stage failed."
  396. fi
  397. info "Mounting /proc..."
  398. mkdir -p /proc ||\
  399. die "Failed to create /proc mountpoint."
  400. mount -t proc proc /proc ||\
  401. die "Mounting /proc failed."
  402. info "Mounting /sys..."
  403. mkdir -p /sys ||\
  404. die "Failed to create /sys mountpoint."
  405. mount -t sysfs sysfs /sys ||\
  406. die "Mounting /sys failed."
  407. info "Mounting /dev/shm..."
  408. mkdir -p /dev/shm ||\
  409. die "Failed to create /dev/shm mountpoint."
  410. mount -t tmpfs tmpfs /dev/shm ||\
  411. die "Mounting /dev/shm failed."
  412. info "Writing apt configuration..."
  413. cat > /etc/apt/sources.list <<EOF
  414. deb $MAIN_MIRROR $opt_suite main firmware rpi
  415. deb http://archive.raspberrypi.org/debian/ $opt_suite main ui
  416. EOF
  417. [ $? -eq 0 ] || die "Failed to set sources.list"
  418. echo 'Acquire { Languages "none"; };' > /etc/apt/apt.conf.d/99no-translations ||\
  419. die "Failed to set apt.conf.d"
  420. info "Creating /etc/fstab"
  421. mkdir -p /config ||\
  422. die "Failed to create /config"
  423. cat > /etc/fstab <<EOF
  424. proc /proc proc auto,defaults 0 0
  425. debugfs /sys/kernel/debug debugfs auto,defaults 0 0
  426. configfs /config configfs auto,defaults 0 0
  427. tmpfs /tmp tmpfs auto,mode=1777 0 0
  428. /dev/mmcblk0p2 / ext4 auto,noatime,errors=remount-ro 0 1
  429. /dev/mmcblk0p1 /boot vfat auto,noatime 0 0
  430. EOF
  431. info "Writing misc /etc stuff..."
  432. echo "PiLC" > /etc/hostname ||\
  433. die "Failed to set hostname"
  434. printf 'PiLC GNU/Linux (based on Raspbian) \\n \\l\n\n' > /etc/issue ||\
  435. die "Failed to create /etc/issue"
  436. printf 'PiLC GNU/Linux (based on Raspbian)\n' > /etc/issue.net ||\
  437. die "Failed to create /etc/issue.net"
  438. sed -i -e 's|PRETTY_NAME=.*|PRETTY_NAME="PiLC"|' \
  439. /etc/os-release ||\
  440. die "Failed to set os-release PRETTY_NAME."
  441. sed -i -e 's|NAME=.*|NAME="PiLC"|' \
  442. /etc/os-release ||\
  443. die "Failed to set os-release NAME."
  444. sed -i -e 's|ID=.*|ID=pilc|' \
  445. /etc/os-release ||\
  446. die "Failed to set os-release ID."
  447. sed -i -e 's|ID_LIKE=.*|ID_LIKE=raspbian|' \
  448. /etc/os-release ||\
  449. die "Failed to set os-release ID_LIKE."
  450. sed -i -e 's|HOME_URL=.*|HOME_URL="https://bues.ch/a/pilc"|' \
  451. /etc/os-release ||\
  452. die "Failed to set os-release HOME_URL."
  453. sed -i -e 's|SUPPORT_URL=.*|SUPPORT_URL="https://bues.ch/a/pilc"|' \
  454. /etc/os-release ||\
  455. die "Failed to set os-release SUPPORT_URL."
  456. sed -i -e 's|BUG_REPORT_URL=.*|BUG_REPORT_URL="https://bues.ch/a/pilc"|' \
  457. /etc/os-release ||\
  458. die "Failed to set os-release BUG_REPORT_URL."
  459. info "Updating packages..."
  460. cat <<EOF | debconf-set-selections
  461. debconf debconf/priority select high
  462. debconf debconf/frontend select Noninteractive
  463. locales locales/locales_to_be_generated multiselect en_US.UTF-8 UTF-8
  464. locales locales/default_environment_locale select None
  465. EOF
  466. [ $? -eq 0 ] || die "Failed to configure debconf settings"
  467. apt-key add /usr/share/keyrings/raspbian.archive.public.key.gpg ||\
  468. die "apt-key add failed"
  469. apt-get -y update ||\
  470. die "apt-get update failed"
  471. apt-get -y dist-upgrade ||\
  472. die "apt-get dist-upgrade failed"
  473. info "Installing packages..."
  474. apt-get -y install \
  475. aptitude \
  476. autoconf \
  477. automake \
  478. bc \
  479. build-essential \
  480. bwidget \
  481. clang \
  482. console-setup \
  483. cython \
  484. cython3 \
  485. dbus \
  486. debconf-utils \
  487. devscripts \
  488. firmware-brcm80211 \
  489. git \
  490. gnu-fdisk \
  491. htop \
  492. i2c-tools \
  493. irqbalance \
  494. iw \
  495. libboost-python-dev \
  496. libgl1-mesa-dev \
  497. libglu1-mesa-dev \
  498. libglib2.0-dev \
  499. libgtk2.0-dev \
  500. libncurses5-dev \
  501. libmodbus-dev \
  502. libreadline-gplv2-dev \
  503. libtk-img \
  504. libudev-dev \
  505. libusb-1.0-0-dev \
  506. libxmu-dev \
  507. locales \
  508. nano \
  509. ntp \
  510. openssh-server \
  511. openssh-blacklist \
  512. openssh-blacklist-extra \
  513. parted \
  514. pkg-config \
  515. pypy \
  516. pypy-dev \
  517. pypy-setuptools \
  518. python \
  519. python-all-dev \
  520. python-cairo \
  521. python-dev \
  522. python-gtk2 \
  523. python-rpi.gpio \
  524. python-serial \
  525. python-setuptools \
  526. python-smbus \
  527. python-spidev \
  528. python-tk \
  529. python3 \
  530. python3-all-dev \
  531. python3-cairo \
  532. python3-dev \
  533. python3-rpi.gpio \
  534. python3-serial \
  535. python3-setuptools \
  536. python3-smbus \
  537. python3-spidev \
  538. python3-tk \
  539. raspberrypi-bootloader \
  540. raspi-config \
  541. schedtool \
  542. screen \
  543. sudo \
  544. systemd \
  545. tcl-dev \
  546. tclx \
  547. tk-dev \
  548. tmux \
  549. vim \
  550. wireless-tools \
  551. wpasupplicant ||\
  552. die "apt-get install failed"
  553. cat <<EOF | debconf-set-selections
  554. debconf debconf/frontend select Dialog
  555. locales locales/default_environment_locale select en_US.UTF-8
  556. EOF
  557. [ $? -eq 0 ] || die "Failed to configure debconf settings"
  558. dpkg-reconfigure -u locales ||\
  559. die "Failed to reconfigure locales"
  560. apt-get -y clean ||\
  561. die "apt-get clean failed"
  562. # Build python modules
  563. build_rpigpio
  564. build_spidev
  565. build_ppl
  566. build_ppl2
  567. info "Removing ssh keys..."
  568. if [ -e "$(first /etc/ssh/ssh_host_*_key*)" ]; then
  569. rm /etc/ssh/ssh_host_*_key* ||\
  570. die "Failed to remove ssh keys."
  571. fi
  572. echo 1 > /etc/ssh/sshd_not_to_be_run ||\
  573. die "Failed to create /etc/ssh/sshd_not_to_be_run"
  574. echo 1 > /etc/ssh/ssh_create_keys ||\
  575. die "Failed to create /etc/ssh/ssh_create_keys"
  576. info "Creating /etc/rc.local..."
  577. cat > /etc/rc.local <<EOF
  578. #!/bin/sh -e
  579. #
  580. # rc.local
  581. #
  582. # This script is executed at the end of each multiuser runlevel.
  583. # Make sure that the script will "exit 0" on success or any other
  584. # value on error.
  585. #
  586. # In order to enable or disable this script just change the execution
  587. # bits.
  588. #
  589. # Re-generate ssh keys, if requested.
  590. if [ -e /etc/ssh/ssh_create_keys ]; then
  591. /bin/rm -f /etc/ssh/ssh_host_*_key*
  592. LC_ALL=C LANGUAGE=C LANG=C /usr/sbin/dpkg-reconfigure openssh-server
  593. /bin/rm /etc/ssh/sshd_not_to_be_run
  594. /bin/rm /etc/ssh/ssh_create_keys
  595. /etc/init.d/ssh start
  596. fi
  597. # Workaround firmware issue leaving i2c0 in an non-ALT0 state.
  598. for i in 28 29; do
  599. /bin/echo \$i > /sys/class/gpio/export
  600. /bin/echo in > /sys/class/gpio/gpio\${i}/direction
  601. done
  602. # Add /dev/ttyS0 link for convenience.
  603. if ! [ -e /dev/ttyS0 ]; then
  604. /bin/ln -s /dev/ttyAMA0 /dev/ttyS0
  605. fi
  606. exit 0
  607. EOF
  608. [ $? -eq 0 ] || die "Failed to create /etc/rc.local"
  609. chmod 755 /etc/rc.local || die "Failed to chmod /etc/rc.local"
  610. info "Creating /etc/modules-load.d/i2c.conf..."
  611. cat > /etc/modules-load.d/i2c.conf <<EOF
  612. i2c_dev
  613. EOF
  614. [ $? -eq 0 ] || die "Failed to create /etc/modules-load.d/i2c.conf"
  615. info "Creating users/groups..."
  616. userdel -f pi
  617. groupdel pi
  618. rm -rf /home/pi
  619. groupadd -g 1000 pi ||\
  620. die "Failed to create group pi."
  621. useradd -u 1000 -d /home/pi -m -g pi\
  622. -G pi,lp,dialout,cdrom,floppy,audio,dip,src,video,plugdev,netdev,i2c\
  623. -s /bin/bash\
  624. pi ||\
  625. die "Failed to create user pi."
  626. printf 'raspberry\nraspberry\n' | passwd pi ||\
  627. die "Failed to set 'pi' password."
  628. echo 'pi ALL=(ALL:ALL) ALL' > "/etc/sudoers.d/00-pi" ||\
  629. die "Failed to create /etc/sudoers.d/00-pi"
  630. info "Initializing home directory..."
  631. mkdir -p /home/pi/.vim || die "Failed to mkdir /home/pi/.vim"
  632. cat > /home/pi/.vim/vimrc <<EOF
  633. set nocompatible
  634. set autoindent
  635. syntax enable
  636. set backspace=indent,start
  637. set number
  638. EOF
  639. [ $? -eq 0 ] || die "Failed to create /home/pi/.vim/vimrc"
  640. cat > /home/pi/.tmux.conf <<EOF
  641. # Default new panes and windows to be opened in the current panes path
  642. bind-key c new-window -c "#{pane_current_path}"
  643. bind-key % split-window -h -c "#{pane_current_path}"
  644. bind-key "\"" split-window -c "#{pane_current_path}"
  645. EOF
  646. [ $? -eq 0 ] || die "Failed to create /home/pi/.tmux.conf"
  647. info "Building awlsim..."
  648. (
  649. cd /tmp/awlsim/src ||\
  650. die "Failed to cd"
  651. if [ $opt_cython -eq 0 ]; then
  652. # Disable cython
  653. sed -i -e '/Package: cython/,/^$/ d' \
  654. debian/control ||\
  655. die "Failed to patch control file"
  656. sed -i -e 's/export AWLSIM_CYTHON_BUILD=1/export AWLSIM_CYTHON_BUILD=0/' \
  657. debian/rules ||\
  658. die "Failed to patch rules file"
  659. fi
  660. debuild -uc -us -b -d || die "debuild failed"
  661. info "Built awlsim files:"
  662. ls .. || die "Failed to list results"
  663. info "Installing awlsim..."
  664. # Core
  665. dpkg -i ../python3-awlsim_*.deb ||\
  666. die "Failed to install python3-awlsim"
  667. dpkg -i ../pypy-awlsim_*.deb ||\
  668. die "Failed to install pypy-awlsim"
  669. if [ $opt_cython -ne 0 ]; then
  670. dpkg -i ../cython3-awlsim_*.deb ||\
  671. die "Failed to install cython3-awlsim"
  672. fi
  673. # hardware: dummy
  674. dpkg -i ../python3-awlsimhw-dummy_*.deb ||\
  675. die "Failed to install python3-awlsimhw-dummy"
  676. dpkg -i ../pypy-awlsimhw-dummy_*.deb ||\
  677. die "Failed to install pypy-awlsimhw-dummy"
  678. if [ $opt_cython -ne 0 ]; then
  679. dpkg -i ../cython3-awlsimhw-dummy_*.deb ||\
  680. die "Failed to install cython3-awlsimhw-dummy"
  681. fi
  682. # hardware: linuxcnc
  683. dpkg -i ../python3-awlsimhw-linuxcnc_*.deb ||\
  684. die "Failed to install python3-awlsimhw-linuxcnc"
  685. if [ $opt_cython -ne 0 ]; then
  686. dpkg -i ../cython3-awlsimhw-linuxcnc_*.deb ||\
  687. die "Failed to install cython3-awlsimhw-linuxcnc"
  688. fi
  689. # hardware: profibus
  690. dpkg -i ../python3-awlsimhw-profibus_*.deb ||\
  691. die "Failed to install python3-awlsimhw-profibus"
  692. dpkg -i ../pypy-awlsimhw-profibus_*.deb ||\
  693. die "Failed to install pypy-awlsimhw-profibus"
  694. if [ $opt_cython -ne 0 ]; then
  695. dpkg -i ../cython3-awlsimhw-profibus_*.deb ||\
  696. die "Failed to install cython3-awlsimhw-profibus"
  697. fi
  698. # hardware: RPi GPIO
  699. dpkg -i ../python3-awlsimhw-rpigpio_*.deb ||\
  700. die "Failed to install python3-awlsimhw-rpigpio"
  701. dpkg -i ../pypy-awlsimhw-rpigpio_*.deb ||\
  702. die "Failed to install pypy-awlsimhw-rpigpio"
  703. if [ $opt_cython -ne 0 ]; then
  704. dpkg -i ../cython3-awlsimhw-rpigpio_*.deb ||\
  705. die "Failed to install cython3-awlsimhw-rpigpio"
  706. fi
  707. # hardware: PiXtend
  708. dpkg -i ../python3-awlsimhw-pixtend_*.deb ||\
  709. die "Failed to install python3-awlsimhw-pixtend"
  710. dpkg -i ../pypy-awlsimhw-pixtend_*.deb ||\
  711. die "Failed to install pypy-awlsimhw-pixtend"
  712. if [ $opt_cython -ne 0 ]; then
  713. dpkg -i ../cython3-awlsimhw-pixtend_*.deb ||\
  714. die "Failed to install cython3-awlsimhw-pixtend"
  715. fi
  716. # Executables
  717. dpkg -i ../awlsim-server_*.deb ||\
  718. die "Failed to install awlsim-server"
  719. dpkg -i ../awlsim-client_*.deb ||\
  720. die "Failed to install awlsim-client"
  721. dpkg -i ../awlsim-symtab_*.deb ||\
  722. die "Failed to install awlsim-symtab"
  723. dpkg -i ../awlsim-test_*.deb ||\
  724. die "Failed to install awlsim-test"
  725. dpkg -i ../awlsim-proupgrade_*.deb ||\
  726. die "Failed to install awlsim-proupgrade"
  727. # Copy debs
  728. rm -rf /home/pi/deb/awlsim
  729. mkdir -p /home/pi/deb/awlsim ||\
  730. die "mkdir /home/pi/deb/awlsim failed"
  731. cp ../*awlsim*.deb ../*awlsim*.buildinfo ../*awlsim*.changes \
  732. /home/pi/deb/awlsim/ ||\
  733. die "Failed to copy awlsim debs"
  734. # Copy examples
  735. cp examples/EXAMPLE.awlpro /home/pi/generic-example.awlpro ||\
  736. die "Failed to copy EXAMPLE.awlpro."
  737. cp examples/raspberrypi-gpio.awlpro /home/pi/raspberrypi-gpio-example.awlpro ||\
  738. die "Failed to copy raspberrypi-gpio.awlpro."
  739. cp examples/raspberrypi-profibus.awlpro /home/pi/raspberrypi-profibus-example.awlpro ||\
  740. die "Failed to copy raspberrypi-profibus.awlpro."
  741. cp examples/raspberrypi-pixtend.awlpro /home/pi/raspberrypi-pixtend-example.awlpro ||\
  742. die "Failed to copy raspberrypi-pixtend.awlpro."
  743. #TODO run the testsuite
  744. #TODO install unit via package
  745. info "Installing awlsim service unit..."
  746. local awlsim_prefix=/usr
  747. local pyver=3
  748. local site="$awlsim_prefix/lib/python$pyver/dist-packages"
  749. cat awlsim-server.service.in |\
  750. sed -e 's|@USER@|root|g' \
  751. -e 's|@GROUP@|root|g' \
  752. -e "s|@PREFIX@|$awlsim_prefix|g" \
  753. -e 's|@PROJECT@|/etc/awlsim-server.awlpro|g' \
  754. -e "s|@PYTHON@|/usr/bin/python$pyver|g" \
  755. -e "s|@PYTHON_SITE@|$site|g" >\
  756. /etc/systemd/system/awlsim-server.service ||\
  757. die "Failed to create awlsim-server.service"
  758. systemctl enable awlsim-server.service ||\
  759. die "Failed to enable awlsim-server-service"
  760. ) || die
  761. info "Building pyprofibus..."
  762. (
  763. cd /tmp/awlsim/pyprofibus ||\
  764. die "Failed to cd"
  765. debuild -uc -us -b -d || die "debuild failed"
  766. info "Built pyprofibus files:"
  767. ls .. || die "Failed to list results"
  768. info "Installing pyprofibus..."
  769. dpkg -i ../python3-pyprofibus_*.deb ||\
  770. die "Failed to install python3-pyprofibus"
  771. dpkg -i ../pypy-pyprofibus_*.deb ||\
  772. die "Failed to install pypy-pyprofibus"
  773. dpkg -i ../profisniff_*.deb ||\
  774. die "Failed to install profisniff"
  775. dpkg -i ../gsdparser_*.deb ||\
  776. die "Failed to install gsdparser"
  777. # Copy debs
  778. rm -rf /home/pi/deb/pyprofibus
  779. mkdir -p /home/pi/deb/pyprofibus ||\
  780. die "mkdir /home/pi/deb/pyprofibus failed"
  781. cp ../*pyprofibus*.deb ../*pyprofibus*.buildinfo ../*pyprofibus*.changes \
  782. ../profisniff_*.deb ../gsdparser_*.deb \
  783. /home/pi/deb/pyprofibus/ ||\
  784. die "Failed to copy pyprofibus debs"
  785. ) || die
  786. rm -r /tmp/awlsim ||\
  787. die "Failed to remove awlsim checkout."
  788. info "Configuring network..."
  789. cat > /etc/network/interfaces.d/lo <<EOF
  790. auto lo
  791. iface lo inet loopback
  792. EOF
  793. [ $? -eq 0 ] || die "Failed to create /etc/network/interfaces.d/lo"
  794. cat > /etc/network/interfaces.d/enx <<EOF
  795. allow-hotplug /enx*=enx
  796. iface enx inet dhcp
  797. iface enx inet6 auto
  798. EOF
  799. [ $? -eq 0 ] || die "Failed to create /etc/network/interfaces.d/enx"
  800. cat > /etc/network/interfaces.d/eth <<EOF
  801. allow-hotplug /eth*=eth
  802. iface eth inet dhcp
  803. iface eth inet6 auto
  804. EOF
  805. [ $? -eq 0 ] || die "Failed to create /etc/network/interfaces.d/eth"
  806. for i in $(seq 0 9); do
  807. cat > /etc/network/interfaces.d/eth$i <<EOF
  808. allow-hotplug eth$i
  809. iface eth$i inet dhcp
  810. iface eth$i inet6 auto
  811. EOF
  812. [ $? -eq 0 ] || die "Failed to create /etc/network/interfaces.d/eth$i"
  813. done
  814. cat > /etc/network/interfaces.d/wlan0 <<EOF
  815. #allow-hotplug wlan0
  816. #iface wlan0 inet dhcp
  817. # wpa-ssid 'enter your SSID here'
  818. # wpa-psk 'enter your pre-shared-key (PSK) here'
  819. #iface wlan0 inet6 auto
  820. EOF
  821. [ $? -eq 0 ] || die "Failed to create /etc/network/interfaces.d/wlan0"
  822. info "Updating home directory permissions..."
  823. chown -R pi:pi /home/pi || die "Failed to change /home/pi permissions."
  824. # Remove rc.d policy file
  825. if [ -e /usr/sbin/policy-rc.d ]; then
  826. rm /usr/sbin/policy-rc.d ||\
  827. die "Failed to remove policy-rc.d"
  828. fi
  829. info "Stopping processes..."
  830. for i in dbus ssh atd irqbalance; do
  831. /etc/init.d/$i stop
  832. done
  833. }
  834. pilc_bootstrap_third_stage()
  835. {
  836. info "Running third stage..."
  837. info "Umounting /dev/shm..."
  838. umount -l "$mp_shm" || die "Failed to umount /dev/shm"
  839. info "Umounting /sys..."
  840. umount -l "$mp_sys" || die "Failed to umount /sys"
  841. info "Umounting /proc/sys/fs/binfmt_misc..."
  842. umount -l "$mp_proc_binfmt_misc"
  843. info "Umounting /proc..."
  844. umount -l "$mp_proc" || die "Failed to umount /proc"
  845. info "Removing PiLC bootstrap script..."
  846. rm "$opt_target_dir/pilc-bootstrap.sh" ||\
  847. die "Failed to remove bootstrap script."
  848. info "Cleaning tmp..."
  849. rm -rf "$opt_target_dir"/tmp/*
  850. info "Configuring boot..."
  851. cat > "$opt_target_dir/boot/cmdline.txt" <<EOF
  852. dwc_otg.lpm_enable=0 console=tty1 root=/dev/mmcblk0p2 rootfstype=ext4 elevator=deadline isolcpus=2,3 rcu_nocbs=2,3 nohz_full=2,3 fsck.repair=yes net.ifnames=0 rootwait quiet
  853. EOF
  854. [ $? -eq 0 ] || die "Failed to create /boot/cmdline.txt"
  855. boot_config_file > "$opt_target_dir/boot/config.txt" ||\
  856. die "Failed to create /boot/config.txt"
  857. local img="$(first "$opt_target_dir/boot/"vmlinuz-*-rpi)"
  858. if [ -e "$img" ]; then
  859. mv "$img" "$opt_target_dir/boot/kernel.img" ||\
  860. die "Failed to create kernel.img"
  861. fi
  862. local img="$(first "$opt_target_dir/boot/"initrd.img-*-rpi)"
  863. if [ -e "$img" ]; then
  864. mv "$img" "$opt_target_dir/boot/initrd.img" ||\
  865. die "Failed to create initrd.img"
  866. fi
  867. local img="$(first "$opt_target_dir/boot/"vmlinuz-*-rpi2)"
  868. if [ -e "$img" ]; then
  869. mv "$img" "$opt_target_dir/boot/kernel7.img" ||\
  870. die "Failed to create kernel7.img"
  871. fi
  872. local img="$(first "$opt_target_dir/boot/"initrd.img-*-rpi2)"
  873. if [ -e "$img" ]; then
  874. mv "$img" "$opt_target_dir/boot/initrd7.img" ||\
  875. die "Failed to create initrd7.img"
  876. fi
  877. # Prepare image paths.
  878. local imgfile="${opt_target_dir}${opt_imgsuffix}.img"
  879. local imgfile_zip="${imgfile}.7z"
  880. local bootimgfile="${imgfile}.boot"
  881. mp_bootimgfile="${bootimgfile}.mp"
  882. local rootimgfile="${imgfile}.root"
  883. mp_rootimgfile="${rootimgfile}.mp"
  884. rm -f "$imgfile" "$imgfile_zip" "$rootimgfile" "$bootimgfile"
  885. rmdir "$mp_bootimgfile" "$mp_rootimgfile" 2>/dev/null
  886. # Create images.
  887. if [ "$opt_img" -ne 0 ]; then
  888. info "Creating boot image..."
  889. mkfs.vfat -F 32 -i 7771B0BB -n boot -C "$bootimgfile" \
  890. $(expr \( 64 \* 1024 \) - \( 4 \* 1024 \) ) ||\
  891. die "Failed to create boot partition file system."
  892. mkdir "$mp_bootimgfile" ||\
  893. die "Failed to make boot partition mount point."
  894. mount -o loop "$bootimgfile" "$mp_bootimgfile" ||\
  895. die "Failed to mount boot partition."
  896. rsync -aHAX --inplace \
  897. "$opt_target_dir/boot/" "$mp_bootimgfile/" ||\
  898. die "Failed to copy boot files."
  899. umount "$mp_bootimgfile" ||\
  900. die "Failed to umount boot partition."
  901. rmdir "$mp_bootimgfile" ||\
  902. die "Failed to remove boot partition mount point."
  903. info "Creating root image..."
  904. mkfs.ext4 "$rootimgfile" $(expr \( 4000 - 64 \) \* 1024 ) ||\
  905. die "Failed to create root filesystem."
  906. mkdir "$mp_rootimgfile" ||\
  907. die "Failed to make root partition mount point."
  908. mount -o loop "$rootimgfile" "$mp_rootimgfile" ||\
  909. die "Failed to mount root partition."
  910. rsync -aHAX --inplace \
  911. --exclude='boot/*' \
  912. --exclude='proc/*' \
  913. --exclude='sys/*' \
  914. --exclude='dev/shm/*' \
  915. --exclude='tmp/*' \
  916. --exclude="$(basename "$opt_qemu")" \
  917. "$opt_target_dir/" "$mp_rootimgfile/" ||\
  918. die "Failed to copy root files."
  919. umount "$mp_rootimgfile" ||\
  920. die "Failed to umount root partition."
  921. rmdir "$mp_rootimgfile" ||\
  922. die "Failed to remove root partition mount point."
  923. info "Creating image '$imgfile'..."
  924. dd if=/dev/zero of="$imgfile" bs=1M count=4000 conv=sparse ||\
  925. die "Failed to create image file."
  926. parted "$imgfile" <<EOF
  927. unit b
  928. mklabel msdos
  929. mkpart primary fat32 $(expr 4 \* 1024 \* 1024) $(expr 64 \* 1024 \* 1024 - 1)
  930. mkpart primary ext4 $(expr 64 \* 1024 \* 1024) 100%
  931. EOF
  932. [ $? -eq 0 ] || die "Failed to create partitions."
  933. info "Integrating boot image..."
  934. dd if="$bootimgfile" of="$imgfile"\
  935. seek=4 bs=1M conv=notrunc,sparse ||\
  936. die "Failed to integrate boot partition."
  937. rm "$bootimgfile" ||\
  938. die "Failed to delete boot partition image."
  939. info "Integrating root image..."
  940. dd if="$rootimgfile" of="$imgfile"\
  941. seek=64 bs=1M conv=notrunc,sparse ||\
  942. die "Failed to integrate root partition."
  943. rm "$rootimgfile" ||\
  944. die "Failed to delete root partition image."
  945. # Create zipped image.
  946. if [ "$opt_zimg" -ne 0 ]; then
  947. info "Compressing image..."
  948. 7z -mx=9 a "$imgfile_zip" "$imgfile" ||\
  949. die "Failed to compress partition image."
  950. fi
  951. # Write the image to the SD card.
  952. if [ -n "$opt_writedev" ]; then
  953. write_image "$imgfile" "$opt_writedev"
  954. fi
  955. fi
  956. }
  957. usage()
  958. {
  959. echo "pilc-bootstrap.sh [OPTIONS] TARGET_DIR"
  960. echo
  961. echo "Options:"
  962. echo
  963. echo " --branch|-b BRANCH Select the awlsim branch or tag."
  964. echo " Default: $default_branch"
  965. echo
  966. echo " --no-cython|-C Do not build Cython modules."
  967. echo " Default: Build cython modules"
  968. echo
  969. echo " --suite|-s SUITE Select the suite."
  970. echo " Default: $default_suite"
  971. echo
  972. echo " --arch|-a ARCH Select the default arch."
  973. echo " Default: $default_arch"
  974. echo
  975. echo " --qemu-bin|-Q PATH Select qemu-user-static binary."
  976. echo " Default: $default_qemu"
  977. echo
  978. echo " --img-suffix|-s SUFFIX Image file suffix."
  979. echo " Default: $default_imgsuffix"
  980. echo
  981. echo " --no-img|-I Do not create an image."
  982. echo " Default: Create image."
  983. echo
  984. echo " --no-zimg|-Z Do not create a 7zipped image."
  985. echo " Default: Create 7zipped image."
  986. echo
  987. echo " --write|-w DEV Write image to an SD card after bootstrap."
  988. echo " DEV must be the /dev/mmcblkX path to the card."
  989. echo
  990. echo " --write-only|-W DEV Write an existing image to an SD card"
  991. echo " without bootstrap and image generation."
  992. echo
  993. echo " --skip-debootstrap1|-1 Skip debootstrap first stage."
  994. echo " --skip-debootstrap2|-2 Skip debootstrap second stage."
  995. echo
  996. echo " --quick|-q Quick build. This is a shortcut for:"
  997. echo " --no-cython --no-zimg"
  998. echo
  999. echo " --rpiver|-R VERSION Minimum Raspberry Pi version to build for."
  1000. echo " Can be either 0, 1, 2 or 3."
  1001. echo " 0 and 1 are equivalent."
  1002. echo " Default: 1"
  1003. }
  1004. # canonicalize basedir
  1005. basedir="$(readlink -e "$basedir")"
  1006. [ -n "$basedir" ] || die "Failed to canonicalize base directory."
  1007. # Mountpoints. Will be umounted on cleanup.
  1008. mp_shm=
  1009. mp_proc=
  1010. mp_proc_binfmt_misc=
  1011. mp_sys=
  1012. mp_bootimgfile=
  1013. mp_rootimgfile=
  1014. trap term_signal TERM INT
  1015. if [ -z "$__PILC_BOOTSTRAP_SECOND_STAGE__" ]; then
  1016. # First stage
  1017. export _NPROCESSORS_ONLN="$(getconf _NPROCESSORS_ONLN)"
  1018. [ -n "$_NPROCESSORS_ONLN" ] || die "Failed to get # of online CPUs"
  1019. default_branch="master"
  1020. default_suite="$DEFAULT_SUITE"
  1021. default_arch="armhf"
  1022. default_qemu="/usr/bin/qemu-arm-static"
  1023. default_imgsuffix="-$(date '+%Y%m%d')"
  1024. default_img=1
  1025. default_zimg=1
  1026. default_writedev=
  1027. default_writeonly=0
  1028. default_rpiver=1
  1029. opt_target_dir=
  1030. opt_branch="$default_branch"
  1031. opt_cython=1
  1032. opt_suite="$default_suite"
  1033. opt_arch="$default_arch"
  1034. opt_qemu="$default_qemu"
  1035. opt_skip_debootstrap1=0
  1036. opt_skip_debootstrap2=0
  1037. opt_imgsuffix="$default_imgsuffix"
  1038. opt_img="$default_img"
  1039. opt_zimg="$default_zimg"
  1040. opt_writedev="$default_writedev"
  1041. opt_writeonly="$default_writeonly"
  1042. opt_rpiver="$default_rpiver"
  1043. while [ $# -ge 1 ]; do
  1044. case "$1" in
  1045. --help|-h)
  1046. usage
  1047. exit 0
  1048. ;;
  1049. --branch|-b)
  1050. shift
  1051. opt_branch="$1"
  1052. [ -n "$opt_branch" ] || die "No branch given"
  1053. ;;
  1054. --no-cython|-C)
  1055. opt_cython=0
  1056. ;;
  1057. --suite|-s)
  1058. shift
  1059. opt_suite="$1"
  1060. [ -n "$opt_suite" ] || die "No suite given"
  1061. ;;
  1062. --arch|-a)
  1063. shift
  1064. opt_arch="$1"
  1065. [ -n "$opt_arch" ] || die "No arch given"
  1066. ;;
  1067. --qemu-bin|-Q)
  1068. shift
  1069. opt_qemu="$1"
  1070. [ -x "$opt_qemu" ] || die "No valid qemu binary given"
  1071. ;;
  1072. --skip-debootstrap1|-1)
  1073. opt_skip_debootstrap1=1
  1074. ;;
  1075. --skip-debootstrap2|-2)
  1076. opt_skip_debootstrap2=1
  1077. ;;
  1078. --img-suffix|-s)
  1079. shift
  1080. opt_imgsuffix="$1"
  1081. ;;
  1082. --no-zimg|-Z)
  1083. opt_zimg=0
  1084. ;;
  1085. --no-img|-I)
  1086. opt_img=0
  1087. ;;
  1088. --quick|-q)
  1089. opt_cython=0
  1090. opt_zimg=0
  1091. ;;
  1092. --write|-w|--write-only|-W)
  1093. if [ "$1" = "--write" -o "$1" = "-w" ]; then
  1094. opt_writeonly=0
  1095. else
  1096. opt_writeonly=1
  1097. fi
  1098. shift
  1099. opt_writedev="$1"
  1100. [ -b "$opt_writedev" ] || die "Invalid SD card block device"
  1101. ;;
  1102. --rpiver|-R)
  1103. shift
  1104. opt_rpiver="$1"
  1105. [ "$opt_rpiver" = "0" -o\
  1106. "$opt_rpiver" = "1" -o\
  1107. "$opt_rpiver" = "2" -o\
  1108. "$opt_rpiver" = "3" ] || die "Invalid --rpiver|-R"
  1109. ;;
  1110. *)
  1111. opt_target_dir="$*"
  1112. break
  1113. ;;
  1114. esac
  1115. shift
  1116. done
  1117. [ -n "$opt_target_dir" ] ||\
  1118. die "No TARGET_DIR"
  1119. opt_target_dir="$(readlink -m "${opt_target_dir}")"
  1120. [ -n "$opt_target_dir" ] || die "Failed to resolve target dir."
  1121. [ -d "$opt_target_dir" -o ! -e "$opt_target_dir" ] ||\
  1122. die "$opt_target_dir is not a directory"
  1123. trap cleanup EXIT
  1124. if [ -n "$opt_writedev" -a $opt_writeonly -ne 0 ]; then
  1125. # Just write the image to the SD card, then exit.
  1126. write_image "${opt_target_dir}${opt_imgsuffix}.img" "$opt_writedev"
  1127. exit 0
  1128. fi
  1129. # Run first stage.
  1130. pilc_bootstrap_first_stage
  1131. info "Starting second stage."
  1132. # Export options for use by second stage.
  1133. export opt_target_dir
  1134. export opt_branch
  1135. export opt_cython
  1136. export opt_suite
  1137. export opt_arch
  1138. export opt_qemu
  1139. export opt_skip_debootstrap1
  1140. export opt_skip_debootstrap2
  1141. export opt_imgsuffix
  1142. export opt_zimg
  1143. export opt_img
  1144. export opt_writedev
  1145. export opt_writeonly
  1146. export opt_rpiver
  1147. export __PILC_BOOTSTRAP_SECOND_STAGE__=1
  1148. chroot "$opt_target_dir" "/pilc-bootstrap.sh" ||\
  1149. die "Chroot failed."
  1150. # Run third stage.
  1151. pilc_bootstrap_third_stage
  1152. info ""
  1153. info "Successfully bootstrapped PiLC."
  1154. exit 0
  1155. else
  1156. # Run second stage
  1157. pilc_bootstrap_second_stage
  1158. exit 0
  1159. fi