pilc-bootstrap.sh 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891
  1. #!/bin/sh
  2. #
  3. # PiLC bootstrap
  4. #
  5. # Copyright 2016 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. die()
  27. {
  28. echo "=== $*" >&2
  29. exit 1
  30. }
  31. info()
  32. {
  33. echo "--- $*"
  34. }
  35. # print the first of its arguments.
  36. first()
  37. {
  38. echo "$1"
  39. }
  40. # print the last of its arguments.
  41. last()
  42. {
  43. while [ $# -gt 1 ]; do shift; done
  44. echo "$1"
  45. }
  46. # $1=program_name
  47. have_program()
  48. {
  49. which "$1" >/dev/null 2>&1
  50. }
  51. # $1=program_name, ($2=description)
  52. assert_program()
  53. {
  54. local bin="$1"
  55. local desc="$2"
  56. [ -n "$desc" ] || desc="$bin"
  57. have_program "$bin" || die "$bin not found. Please install $desc."
  58. }
  59. term_signal()
  60. {
  61. die "Terminating signal received"
  62. }
  63. cleanup()
  64. {
  65. info "Cleaning up..."
  66. for mp in "$mp_shm" "$mp_proc" "$mp_sys" "$mp_bootimgfile" "$mp_rootimgfile"; do
  67. [ -n "$mp" -a -d "$mp" ] &&\
  68. umount "$mp" >/dev/null 2>&1
  69. done
  70. for mp in "$mp_bootimgfile" "$mp_rootimgfile"; do
  71. [ -n "$mp" -a -d "$mp" ] &&\
  72. rmdir "$mp" >/dev/null 2>&1
  73. done
  74. }
  75. boot_config_file()
  76. {
  77. cat <<EOF
  78. # For more options and information see
  79. # http://www.raspberrypi.org/documentation/configuration/config-txt.md
  80. # Some settings may impact device functionality. See link above for details
  81. # uncomment if you get no picture on HDMI for a default "safe" mode
  82. #hdmi_safe=1
  83. # uncomment this if your display has a black border of unused pixels visible
  84. # and your display can output without overscan
  85. #disable_overscan=1
  86. # uncomment the following to adjust overscan. Use positive numbers if console
  87. # goes off screen, and negative if there is too much border
  88. #overscan_left=16
  89. #overscan_right=16
  90. #overscan_top=16
  91. #overscan_bottom=16
  92. # uncomment to force a console size. By default it will be display's size minus
  93. # overscan.
  94. #framebuffer_width=1280
  95. #framebuffer_height=720
  96. # uncomment if hdmi display is not detected and composite is being output
  97. #hdmi_force_hotplug=1
  98. # uncomment to force a specific HDMI mode (this will force VGA)
  99. #hdmi_group=1
  100. #hdmi_mode=1
  101. # uncomment to force a HDMI mode rather than DVI. This can make audio work in
  102. # DMT (computer monitor) modes
  103. #hdmi_drive=2
  104. # uncomment to increase signal to HDMI, if you have interference, blanking, or
  105. # no display
  106. #config_hdmi_boost=4
  107. # uncomment for composite PAL
  108. #sdtv_mode=2
  109. #uncomment to overclock the arm. 700 MHz is the default.
  110. #arm_freq=800
  111. # Uncomment some or all of these to enable the optional hardware interfaces
  112. dtparam=i2c_arm=on
  113. dtparam=i2c_vc=on
  114. #dtparam=i2s=on
  115. #dtparam=spi=on
  116. # RV3029 RTC
  117. dtoverlay=rv3029-rtc
  118. # Uncomment this to enable the lirc-rpi module
  119. #dtoverlay=lirc-rpi
  120. # Additional overlays and parameters are documented /boot/overlays/README
  121. # Enable audio (loads snd_bcm2835)
  122. dtparam=audio=on
  123. EOF
  124. }
  125. pilc_bootstrap_first_stage()
  126. {
  127. echo "Running first stage..."
  128. [ "$(id -u)" = "0" ] || die "Permission denied. Must be root."
  129. # Check host tools (first/third stage).
  130. assert_program debootstrap
  131. assert_program git
  132. assert_program chroot
  133. assert_program rsync
  134. assert_program parted
  135. assert_program mkfs.vfat
  136. assert_program mkfs.ext4
  137. assert_program 7z
  138. [ -x "$opt_qemu" ] ||\
  139. die "The qemu binary '$opt_qemu' is not executable."
  140. # debootstrap first stage.
  141. if [ $opt_skip_debootstrap1 -eq 0 ]; then
  142. info "Running debootstrap first stage..."
  143. debootstrap --arch="$opt_arch" --foreign --verbose \
  144. --keyring="$basedir/pilc/raspbian.public.key.gpg" \
  145. "$opt_suite" "$opt_target_dir" "$MAIN_MIRROR" \
  146. || die "debootstrap failed"
  147. mkdir -p "$opt_target_dir/usr/share/keyrings" ||\
  148. die "Failed to create keyrings dir."
  149. cp "$basedir/pilc/raspbian.archive.public.key.gpg" \
  150. "$opt_target_dir/usr/share/keyrings/" ||\
  151. die "Failed to copy raspbian.archive.public.key.gpg."
  152. cp /usr/share/keyrings/debian-archive-keyring.gpg \
  153. "$opt_target_dir/usr/share/keyrings/debian-archive-keyring.gpg" ||\
  154. die "Failed to copy debian-archive-keyring.gpg."
  155. fi
  156. [ -d "$opt_target_dir" ] ||\
  157. die "Target directory '$opt_target_dir' does not exist."
  158. # Copy qemu.
  159. local qemu_bin="$opt_target_dir/$opt_qemu"
  160. if ! [ -x "$qemu_bin" ]; then
  161. info "Copying qemu binary from '$opt_qemu' to '$qemu_bin'..."
  162. mkdir -p "$(dirname "$qemu_bin")" ||\
  163. die "Failed to make qemu base directory."
  164. cp "$opt_qemu" "$qemu_bin" ||\
  165. die "Failed to copy qemu binary."
  166. fi
  167. info "Copying rv3029 kernel module..."
  168. local rv3029_dir="$opt_target_dir/tmp/rv3029"
  169. mkdir -p "$rv3029_dir" ||\
  170. die "Failed to make rv3029 directory."
  171. cp "$basedir/pilc/kernel/rtc-rv3029c2.c" "$rv3029_dir/" ||\
  172. die "Failed to copy rv3029 source code."
  173. cp "$basedir/pilc/kernel/Makefile.kbuild" "$rv3029_dir/Makefile" ||\
  174. die "Failed to copy rv3029 Makefile."
  175. info "Copying PiLC bootstrap script..."
  176. cp "$basedir/pilc/pilc-bootstrap.sh" "$opt_target_dir/" ||\
  177. die "Failed to copy bootstrap script."
  178. info "Checking out awlsim..."
  179. local awlsim_dir="$opt_target_dir/tmp/awlsim"
  180. local checkout_dir="$awlsim_dir/src"
  181. rm -rf "$awlsim_dir"
  182. mkdir -p "$awlsim_dir" || die "mkdir failed"
  183. git clone --no-checkout "$basedir/.git" "$checkout_dir" ||\
  184. die "Failed to clone"
  185. (
  186. cd "$checkout_dir" ||\
  187. die "Failed to cd"
  188. git checkout -b __build "$opt_branch" ||\
  189. die "Failed to check out branch."
  190. rm -r ".git" ||\
  191. die "Failed to remove .git directory."
  192. ) || die
  193. # Second stage will mount a few filesystems.
  194. # Keep track to umount them in cleanup.
  195. mp_proc="$opt_target_dir/proc"
  196. mp_sys="$opt_target_dir/sys"
  197. mp_shm="$opt_target_dir/dev/shm"
  198. }
  199. pilc_bootstrap_second_stage()
  200. {
  201. info "Running second stage ($opt_arch)..."
  202. [ -x /pilc-bootstrap.sh ] ||\
  203. die "Second stage does not contain the bootstrap script."
  204. # Set up environment.
  205. export LC_ALL=C
  206. export LANGUAGE=C
  207. export LANG=C
  208. # debootstrap second stage.
  209. if [ $opt_skip_debootstrap2 -eq 0 ]; then
  210. info "Running debootstrap second stage..."
  211. /debootstrap/debootstrap --verbose --second-stage ||\
  212. die "Debootstrap second stage failed."
  213. fi
  214. info "Mounting /proc..."
  215. mkdir -p /proc ||\
  216. die "Failed to create /proc mountpoint."
  217. mount -t proc proc /proc ||\
  218. die "Mounting /proc failed."
  219. info "Mounting /sys..."
  220. mkdir -p /sys ||\
  221. die "Failed to create /sys mountpoint."
  222. mount -t sysfs sysfs /sys ||\
  223. die "Mounting /sys failed."
  224. info "Mounting /dev/shm..."
  225. mkdir -p /dev/shm ||\
  226. die "Failed to create /dev/shm mountpoint."
  227. mount -t tmpfs tmpfs /dev/shm ||\
  228. die "Mounting /dev/shm failed."
  229. info "Writing apt configuration..."
  230. cat > /etc/apt/sources.list <<EOF
  231. deb $MAIN_MIRROR $opt_suite main firmware rpi
  232. deb http://archive.raspberrypi.org/debian/ $opt_suite main ui
  233. EOF
  234. [ $? -eq 0 ] || die "Failed to set sources.list"
  235. echo 'Acquire { Languages "none"; };' > /etc/apt/apt.conf.d/99no-translations ||\
  236. die "Failed to set apt.conf.d"
  237. info "Creating /etc/fstab"
  238. mkdir -p /config ||\
  239. die "Failed to create /config"
  240. cat > /etc/fstab <<EOF
  241. proc /proc proc auto,defaults 0 0
  242. debugfs /sys/kernel/debug debugfs auto,defaults 0 0
  243. configfs /config configfs auto,defaults 0 0
  244. tmpfs /tmp tmpfs auto,mode=1777 0 0
  245. /dev/mmcblk0p2 / ext4 auto,noatime,errors=remount-ro 0 1
  246. /dev/mmcblk0p1 /boot vfat auto,noatime 0 0
  247. EOF
  248. info "Writing misc /etc stuff..."
  249. echo "PiLC" > /etc/hostname ||\
  250. die "Failed to set hostname"
  251. printf 'PiLC GNU/Linux (based on Raspbian) \\n \\l\n\n' > /etc/issue ||\
  252. die "Failed to create /etc/issue"
  253. printf 'PiLC GNU/Linux (based on Raspbian)\n' > /etc/issue.net ||\
  254. die "Failed to create /etc/issue.net"
  255. sed -i -e 's|PRETTY_NAME=.*|PRETTY_NAME="PiLC"|' \
  256. /etc/os-release ||\
  257. die "Failed to set os-release PRETTY_NAME."
  258. sed -i -e 's|NAME=.*|NAME="PiLC"|' \
  259. /etc/os-release ||\
  260. die "Failed to set os-release NAME."
  261. sed -i -e 's|ID=.*|ID=pilc|' \
  262. /etc/os-release ||\
  263. die "Failed to set os-release ID."
  264. sed -i -e 's|ID_LIKE=.*|ID_LIKE=raspbian|' \
  265. /etc/os-release ||\
  266. die "Failed to set os-release ID_LIKE."
  267. sed -i -e 's|HOME_URL=.*|HOME_URL="https://bues.ch/h/pilc"|' \
  268. /etc/os-release ||\
  269. die "Failed to set os-release HOME_URL."
  270. sed -i -e 's|SUPPORT_URL=.*|SUPPORT_URL="https://bues.ch/h/pilc"|' \
  271. /etc/os-release ||\
  272. die "Failed to set os-release SUPPORT_URL."
  273. sed -i -e 's|BUG_REPORT_URL=.*|BUG_REPORT_URL="https://bues.ch/h/pilc"|' \
  274. /etc/os-release ||\
  275. die "Failed to set os-release BUG_REPORT_URL."
  276. sed -i -e 's|#FSCKFIX=no|FSCKFIX=yes|' \
  277. /etc/default/rcS ||\
  278. die "Failed to set FSCKFIX=yes"
  279. info "Updating packages..."
  280. cat <<EOF | debconf-set-selections
  281. debconf debconf/priority select high
  282. debconf debconf/frontend select Noninteractive
  283. locales locales/locales_to_be_generated multiselect en_US.UTF-8 UTF-8
  284. locales locales/default_environment_locale select None
  285. EOF
  286. [ $? -eq 0 ] || die "Failed to configure debconf settings"
  287. apt-key add /usr/share/keyrings/raspbian.archive.public.key.gpg ||\
  288. die "apt-key add failed"
  289. apt-get -y update ||\
  290. die "apt-get update failed"
  291. apt-get -y dist-upgrade ||\
  292. die "apt-get dist-upgrade failed"
  293. info "Installing packages..."
  294. apt-get -y install \
  295. aptitude \
  296. build-essential \
  297. console-setup \
  298. cython \
  299. cython3 \
  300. dbus \
  301. debconf-utils \
  302. devscripts \
  303. git \
  304. htop \
  305. i2c-tools \
  306. linux-headers-rpi-rpfv \
  307. linux-image-rpi-rpfv \
  308. linux-headers-rpi2-rpfv \
  309. linux-image-rpi2-rpfv \
  310. locales \
  311. nano \
  312. openssh-server \
  313. openssh-blacklist \
  314. openssh-blacklist-extra \
  315. pypy \
  316. python \
  317. python-all-dev \
  318. python-rpi.gpio \
  319. python-setuptools \
  320. python3 \
  321. python3-all-dev \
  322. python3-rpi.gpio \
  323. python3-setuptools \
  324. raspberrypi-bootloader-nokernel \
  325. screen \
  326. sudo \
  327. systemd \
  328. tmux \
  329. vim ||\
  330. die "apt-get install failed"
  331. apt-get install --reinstall libc6-dev ||\
  332. die "Failed to reinstall"
  333. cat <<EOF | debconf-set-selections
  334. debconf debconf/frontend select Dialog
  335. locales locales/default_environment_locale select en_US.UTF-8
  336. EOF
  337. [ $? -eq 0 ] || die "Failed to configure debconf settings"
  338. dpkg-reconfigure -u locales ||\
  339. die "Failed to reconfigure locales"
  340. apt-get -y clean ||\
  341. die "apt-get clean failed"
  342. info "Removing ssh keys..."
  343. if [ -e "$(first /etc/ssh/ssh_host_*_key*)" ]; then
  344. rm /etc/ssh/ssh_host_*_key* ||\
  345. die "Failed to remove ssh keys."
  346. fi
  347. echo 1 > /etc/ssh/sshd_not_to_be_run ||\
  348. die "Failed to create /etc/ssh/sshd_not_to_be_run"
  349. echo 1 > /etc/ssh/ssh_create_keys ||\
  350. die "Failed to create /etc/ssh/ssh_create_keys"
  351. info "Creating /etc/rc.local..."
  352. cat > /etc/rc.local <<EOF
  353. #!/bin/sh -e
  354. #
  355. # rc.local
  356. #
  357. # This script is executed at the end of each multiuser runlevel.
  358. # Make sure that the script will "exit 0" on success or any other
  359. # value on error.
  360. #
  361. # In order to enable or disable this script just change the execution
  362. # bits.
  363. #
  364. set -e
  365. # Re-generate ssh keys, if requested.
  366. if [ -e /etc/ssh/ssh_create_keys ]; then
  367. /bin/rm -f /etc/ssh/ssh_host_*_key*
  368. LC_ALL=C LANGUAGE=C LANG=C /usr/sbin/dpkg-reconfigure openssh-server
  369. /bin/rm /etc/ssh/sshd_not_to_be_run
  370. /bin/rm /etc/ssh/ssh_create_keys
  371. /etc/init.d/ssh start
  372. fi
  373. # Workaround firmware issue leaving i2c0 in an non-ALT0 state.
  374. for i in 28 29; do
  375. /bin/echo $i > /sys/class/gpio/export
  376. /bin/echo in > /sys/class/gpio/gpio${i}/direction
  377. done
  378. exit 0
  379. EOF
  380. [ $? -eq 0 ] || die "Failed to create /etc/rc.local"
  381. info "Creating /etc/modules-load.d/i2c.conf..."
  382. cat > /etc/modules-load.d/i2c.conf <<EOF
  383. i2c-dev
  384. i2c-bcm2708
  385. at24
  386. rtc-rv3029c2
  387. EOF
  388. [ $? -eq 0 ] || die "Failed to create /etc/modules-load.d/i2c.conf"
  389. info "Creating users/groups..."
  390. userdel -f pi
  391. groupdel pi
  392. rm -rf /home/pi
  393. groupadd -g 1000 pi ||\
  394. die "Failed to create group pi."
  395. useradd -u 1000 -d /home/pi -m -g pi\
  396. -G pi,lp,dialout,cdrom,floppy,audio,dip,src,video,plugdev,netdev\
  397. -s /bin/bash\
  398. pi ||\
  399. die "Failed to create user pi."
  400. printf 'raspberry\nraspberry\n' | passwd pi ||\
  401. die "Failed to set 'pi' password."
  402. echo 'pi ALL=(ALL:ALL) ALL' > "/etc/sudoers.d/00-pi" ||\
  403. die "Failed to create /etc/sudoers.d/00-pi"
  404. info "Building updated rv3029 kernel module..."
  405. (
  406. cd /tmp/rv3029 ||\
  407. die "Failed to cd to rv3029 build dir"
  408. for moddir in /lib/modules/*; do
  409. [ -d "$moddir" ] || die "Invalid moddir '$moddir'"
  410. make KBUILD_DIR="$moddir/build" MODNAME=rtc-rv3029c2 \
  411. CFLAGS=-DCONFIG_RTC_DRV_RV3029_HWMON \
  412. clean ||\
  413. die "rv3029: Failed to clean"
  414. make KBUILD_DIR="$moddir/build" MODNAME=rtc-rv3029c2 \
  415. CFLAGS=-DCONFIG_RTC_DRV_RV3029_HWMON ||\
  416. die "rv3029: Failed to build"
  417. cp rtc-rv3029c2.ko "$moddir/kernel/drivers/rtc/" ||\
  418. die "rv3029: Failed to install kernel module"
  419. depmod "$(basename "$moddir")" ||\
  420. die "Failed to run depmod"
  421. done
  422. ) || die
  423. rm -r /tmp/rv3029 ||\
  424. die "Failed to remove rv3029 build dir."
  425. info "Building awlsim..."
  426. (
  427. cd /tmp/awlsim/src ||\
  428. die "Failed to cd"
  429. if [ $opt_cython -eq 0 ]; then
  430. # Disable cython
  431. sed -i -e '/Package: cython/,/^$/ d' \
  432. debian/control ||\
  433. die "Failed to patch control file"
  434. sed -i -e 's/export NOCYTHON=0/export NOCYTHON=1/' \
  435. debian/rules ||\
  436. die "Failed to patch rules file"
  437. fi
  438. debuild -uc -us -b -d || die "debuild failed"
  439. info "Built awlsim files:"
  440. ls .. || die "Failed to list results"
  441. info "Installing awlsim..."
  442. # Core
  443. dpkg -i ../python-awlsim_*.deb ||\
  444. die "Failed to install python-awlsim"
  445. dpkg -i ../python3-awlsim_*.deb ||\
  446. die "Failed to install python3-awlsim"
  447. dpkg -i ../pypy-awlsim_*.deb ||\
  448. die "Failed to install pypy-awlsim"
  449. if [ $opt_cython -ne 0 ]; then
  450. dpkg -i ../cython-awlsim_*.deb ||\
  451. die "Failed to install cython-awlsim"
  452. dpkg -i ../cython3-awlsim_*.deb ||\
  453. die "Failed to install cython3-awlsim"
  454. fi
  455. # hardware: dummy
  456. dpkg -i ../python-awlsimhw-dummy_*.deb ||\
  457. die "Failed to install python-awlsimhw-dummy"
  458. dpkg -i ../python3-awlsimhw-dummy_*.deb ||\
  459. die "Failed to install python3-awlsimhw-dummy"
  460. dpkg -i ../pypy-awlsimhw-dummy_*.deb ||\
  461. die "Failed to install pypy-awlsimhw-dummy"
  462. if [ $opt_cython -ne 0 ]; then
  463. dpkg -i ../cython-awlsimhw-dummy_*.deb ||\
  464. die "Failed to install cython-awlsimhw-dummy"
  465. dpkg -i ../cython3-awlsimhw-dummy_*.deb ||\
  466. die "Failed to install cython3-awlsimhw-dummy"
  467. fi
  468. # hardware: linuxcnc
  469. dpkg -i ../python-awlsimhw-linuxcnc_*.deb ||\
  470. die "Failed to install python-awlsimhw-linuxcnc"
  471. dpkg -i ../python3-awlsimhw-linuxcnc_*.deb ||\
  472. die "Failed to install python3-awlsimhw-linuxcnc"
  473. if [ $opt_cython -ne 0 ]; then
  474. dpkg -i ../cython-awlsimhw-linuxcnc_*.deb ||\
  475. die "Failed to install cython-awlsimhw-linuxcnc"
  476. dpkg -i ../cython3-awlsimhw-linuxcnc_*.deb ||\
  477. die "Failed to install cython3-awlsimhw-linuxcnc"
  478. fi
  479. # hardware: profibus
  480. dpkg -i ../python-awlsimhw-profibus_*.deb ||\
  481. die "Failed to install python-awlsimhw-profibus"
  482. dpkg -i ../python3-awlsimhw-profibus_*.deb ||\
  483. die "Failed to install python3-awlsimhw-profibus"
  484. dpkg -i ../pypy-awlsimhw-profibus_*.deb ||\
  485. die "Failed to install pypy-awlsimhw-profibus"
  486. if [ $opt_cython -ne 0 ]; then
  487. dpkg -i ../cython-awlsimhw-profibus_*.deb ||\
  488. die "Failed to install cython-awlsimhw-profibus"
  489. dpkg -i ../cython3-awlsimhw-profibus_*.deb ||\
  490. die "Failed to install cython3-awlsimhw-profibus"
  491. fi
  492. # hardware: RPi GPIO
  493. dpkg -i ../python-awlsimhw-rpigpio_*.deb ||\
  494. die "Failed to install python-awlsimhw-rpigpio"
  495. dpkg -i ../python3-awlsimhw-rpigpio_*.deb ||\
  496. die "Failed to install python3-awlsimhw-rpigpio"
  497. dpkg -i ../pypy-awlsimhw-rpigpio_*.deb ||\
  498. die "Failed to install pypy-awlsimhw-rpigpio"
  499. if [ $opt_cython -ne 0 ]; then
  500. dpkg -i ../cython-awlsimhw-rpigpio_*.deb ||\
  501. die "Failed to install cython-awlsimhw-rpigpio"
  502. dpkg -i ../cython3-awlsimhw-rpigpio_*.deb ||\
  503. die "Failed to install cython3-awlsimhw-rpigpio"
  504. fi
  505. # Executables
  506. dpkg -i ../awlsim-server_*.deb ||\
  507. die "Failed to install awlsim-server"
  508. dpkg -i ../awlsim-client_*.deb ||\
  509. die "Failed to install awlsim-client"
  510. dpkg -i ../awlsim-symtab_*.deb ||\
  511. die "Failed to install awlsim-symtab"
  512. dpkg -i ../awlsim-test_*.deb ||\
  513. die "Failed to install awlsim-test"
  514. dpkg -i ../awlsim-linuxcnc-hal_*.deb ||\
  515. die "Failed to install awlsim-linuxcnc-hal"
  516. # GUI
  517. mkdir -p /home/pi/awlsim-gui ||\
  518. die "mkdir /home/pi/awlsim-gui failed"
  519. cp ../python*-awlsim-gui_*.deb ../awlsim-gui_*.deb \
  520. /home/pi/awlsim-gui/ ||\
  521. die "Failed to copy awlsim-gui"
  522. cp examples/EXAMPLE.awlpro /home/pi/generic-example.awlpro ||\
  523. die "Failed to copy EXAMPLE.awlpro."
  524. cp examples/raspberrypi.awlpro /home/pi/raspberrypi-example.awlpro ||\
  525. die "Failed to copy raspberrypi.awlpro."
  526. #TODO run the testsuite
  527. #TODO install unit via package
  528. info "Installing awlsim service unit..."
  529. local awlsim_prefix=/usr
  530. local site="$awlsim_prefix/lib/python3/dist-packages"
  531. cat awlsim-server.service.in |\
  532. sed -e 's|@USER@|pi|g' \
  533. -e 's|@GROUP@|pi|g' \
  534. -e "s|@PREFIX@|$awlsim_prefix|g" \
  535. -e "s|@PYTHON_SITE@|$site|g" >\
  536. /etc/systemd/system/awlsim-server.service ||\
  537. die "Failed to create awlsim-server.service"
  538. systemctl enable awlsim-server.service ||\
  539. die "Failed to enable awlsim-server-service"
  540. ) || die
  541. rm -r /tmp/awlsim ||\
  542. die "Failed to remove awlsim checkout."
  543. info "Extending pi user environment..."
  544. cat >> /home/pi/.bashrc <<EOF
  545. # PiLC
  546. for __i in /opt/awlsim/lib/python*/site-packages/; do
  547. export PYTHONPATH="\$PYTHONPATH:\$__i"
  548. done
  549. export PATH="\$PATH:/opt/awlsim/bin"
  550. EOF
  551. [ $? -eq 0 ] || die "Failed to extend /home/pi/.bashrc"
  552. info "Configuring network..."
  553. cat > /etc/network/interfaces.d/lo <<EOF
  554. auto lo
  555. iface lo inet loopback
  556. EOF
  557. [ $? -eq 0 ] || die "Failed to create /etc/network/interfaces.d/lo"
  558. cat > /etc/network/interfaces.d/eth0 <<EOF
  559. allow-hotplug eth0
  560. iface eth0 inet dhcp
  561. iface eth0 inet6 auto
  562. EOF
  563. [ $? -eq 0 ] || die "Failed to create /etc/network/interfaces.d/eth0"
  564. info "Stopping processes..."
  565. for i in dbus ssh atd; do
  566. /etc/init.d/$i stop
  567. done
  568. info "Umounting /dev/shm..."
  569. umount /dev/shm || die "Failed to umount /dev/shm"
  570. info "Umounting /sys..."
  571. umount /sys || die "Failed to umount /sys"
  572. info "Umounting /proc..."
  573. umount /proc || die "Failed to umount /proc"
  574. }
  575. pilc_bootstrap_third_stage()
  576. {
  577. info "Running third stage..."
  578. info "Removing PiLC bootstrap script..."
  579. rm "$opt_target_dir/pilc-bootstrap.sh" ||\
  580. die "Failed to remove bootstrap script."
  581. info "Configuring boot..."
  582. cat > "$opt_target_dir/boot/cmdline.txt" <<EOF
  583. dwc_otg.lpm_enable=0 console=tty1 root=/dev/mmcblk0p2 rootfstype=ext4 elevator=deadline fsck.repair=yes rootwait quiet
  584. EOF
  585. [ $? -eq 0 ] || die "Failed to create /boot/cmdline.txt"
  586. boot_config_file > "$opt_target_dir/boot/config.txt" ||\
  587. die "Failed to create /boot/config.txt"
  588. cp "$basedir/pilc/kernel/rv3029.dtb" \
  589. "$opt_target_dir/boot/overlays/rv3029-rtc-overlay.dtb" ||\
  590. die "Failed to copy rv3029 dt overlay"
  591. local img="$(first "$opt_target_dir/boot/"vmlinuz-*-rpi)"
  592. if [ -e "$img" ]; then
  593. mv "$img" "$opt_target_dir/boot/kernel.img" ||\
  594. die "Failed to create kernel.img"
  595. fi
  596. local img="$(first "$opt_target_dir/boot/"initrd.img-*-rpi)"
  597. if [ -e "$img" ]; then
  598. mv "$img" "$opt_target_dir/boot/initrd.img" ||\
  599. die "Failed to create initrd.img"
  600. fi
  601. local img="$(first "$opt_target_dir/boot/"vmlinuz-*-rpi2)"
  602. if [ -e "$img" ]; then
  603. mv "$img" "$opt_target_dir/boot/kernel7.img" ||\
  604. die "Failed to create kernel7.img"
  605. fi
  606. local img="$(first "$opt_target_dir/boot/"initrd.img-*-rpi2)"
  607. if [ -e "$img" ]; then
  608. mv "$img" "$opt_target_dir/boot/initrd7.img" ||\
  609. die "Failed to create initrd7.img"
  610. fi
  611. # Prepare image paths.
  612. local target_dir="$(readlink -m "${opt_target_dir}")"
  613. [ -n "$target_dir" ] || die "Failed to resolve target dir."
  614. local imgfile="${target_dir}.img"
  615. local bootimgfile="${imgfile}.boot"
  616. mp_bootimgfile="${bootimgfile}.mp"
  617. local rootimgfile="${imgfile}.root"
  618. mp_rootimgfile="${rootimgfile}.mp"
  619. rm -f "$rootimgfile" "$bootimgfile"
  620. rmdir "$mp_bootimgfile" "$mp_rootimgfile" 2>/dev/null
  621. info "Creating boot image..."
  622. mkfs.vfat -F 32 -i 7771B0BB -n boot -C "$bootimgfile" \
  623. $(expr \( 64 \* 1024 \) - \( 4 \* 1024 \) ) ||\
  624. die "Failed to create boot partition file system."
  625. mkdir "$mp_bootimgfile" ||\
  626. die "Failed to make boot partition mount point."
  627. mount -o loop "$bootimgfile" "$mp_bootimgfile" ||\
  628. die "Failed to mount boot partition."
  629. rsync -aHAX --inplace \
  630. "$target_dir/boot/" "$mp_bootimgfile/" ||\
  631. die "Failed to copy boot files."
  632. umount "$mp_bootimgfile" ||\
  633. die "Failed to umount boot partition."
  634. rmdir "$mp_bootimgfile" ||\
  635. die "Failed to remove boot partition mount point."
  636. info "Creating root image..."
  637. mkfs.ext4 "$rootimgfile" $(expr \( 1391 - 64 \) \* 1024 ) ||\
  638. die "Failed to create root filesystem."
  639. mkdir "$mp_rootimgfile" ||\
  640. die "Failed to make root partition mount point."
  641. mount -o loop "$rootimgfile" "$mp_rootimgfile" ||\
  642. die "Failed to mount root partition."
  643. rsync -aHAX --inplace \
  644. --exclude='boot/*' \
  645. --exclude='proc/*' \
  646. --exclude='sys/*' \
  647. --exclude='dev/shm/*' \
  648. --exclude="$(basename "$opt_qemu")" \
  649. "$target_dir/" "$mp_rootimgfile/" ||\
  650. die "Failed to copy root files."
  651. umount "$mp_rootimgfile" ||\
  652. die "Failed to umount root partition."
  653. rmdir "$mp_rootimgfile" ||\
  654. die "Failed to remove root partition mount point."
  655. info "Creating image '$imgfile'..."
  656. dd if=/dev/zero of="$imgfile" bs=1M count=1391 conv=sparse ||\
  657. die "Failed to create image file."
  658. parted "$imgfile" <<EOF
  659. unit b
  660. mklabel msdos
  661. mkpart primary fat32 $(expr 4 \* 1024 \* 1024) $(expr 64 \* 1024 \* 1024 - 1)
  662. mkpart primary ext4 $(expr 64 \* 1024 \* 1024) 100%
  663. EOF
  664. [ $? -eq 0 ] || die "Failed to create partitions."
  665. info "Integrating boot image..."
  666. dd if="$bootimgfile" of="$imgfile"\
  667. seek=4 bs=1M conv=notrunc,sparse ||\
  668. die "Failed to integrate boot partition."
  669. rm "$bootimgfile" ||\
  670. die "Failed to delete boot partition image."
  671. info "Integrating root image..."
  672. dd if="$rootimgfile" of="$imgfile"\
  673. seek=64 bs=1M conv=notrunc,sparse ||\
  674. die "Failed to integrate root partition."
  675. rm "$rootimgfile" ||\
  676. die "Failed to delete root partition image."
  677. info "Compressing image..."
  678. local imgfile_zip="${imgfile}.7z"
  679. rm -f "$imgfile_zip"
  680. 7z -mx=9 a "$imgfile_zip" "$imgfile" ||\
  681. die "Failed to compress partition image."
  682. }
  683. usage()
  684. {
  685. echo "pilc-bootstrap.sh [OPTIONS] TARGET_DIR"
  686. echo
  687. echo "Options:"
  688. echo " --branch|-b BRANCH Select the awlsim branch."
  689. echo " Default: $default_branch"
  690. echo " --no-cython|-C Do not build Cython modules."
  691. echo " Default: Build cython modules"
  692. echo " --suite|-s SUITE Select the suite."
  693. echo " Default: $default_suite"
  694. echo " --arch|-a ARCH Select the default arch."
  695. echo " Default: $default_arch"
  696. echo " --qemu-bin|-q PATH Select qemu-user-static binary."
  697. echo " Default: $default_qemu"
  698. echo
  699. echo " --skip-debootstrap1|-1 Skip debootstrap first stage."
  700. echo " --skip-debootstrap2|-2 Skip debootstrap second stage."
  701. }
  702. # canonicalize basedir
  703. basedir="$(readlink -e "$basedir")"
  704. [ -n "$basedir" ] || die "Failed to canonicalize base directory."
  705. # Mountpoints. Will be umounted on cleanup.
  706. mp_shm=
  707. mp_proc=
  708. mp_sys=
  709. mp_bootimgfile=
  710. mp_rootimgfile=
  711. trap term_signal TERM INT
  712. if [ -z "$__PILC_BOOTSTRAP_SECOND_STAGE__" ]; then
  713. # First stage
  714. trap cleanup EXIT
  715. default_branch="master"
  716. default_suite="jessie"
  717. default_arch="armhf"
  718. default_qemu="/usr/bin/qemu-arm-static"
  719. opt_target_dir=
  720. opt_branch="$default_branch"
  721. opt_cython=1
  722. opt_suite="$default_suite"
  723. opt_arch="$default_arch"
  724. opt_qemu="$default_qemu"
  725. opt_skip_debootstrap1=0
  726. opt_skip_debootstrap2=0
  727. while [ $# -ge 1 ]; do
  728. case "$1" in
  729. --help|-h)
  730. usage
  731. exit 0
  732. ;;
  733. --branch|-b)
  734. shift
  735. opt_branch="$1"
  736. [ -n "$opt_branch" ] || die "No branch given"
  737. ;;
  738. --no-cython|-C)
  739. opt_cython=0
  740. ;;
  741. --suite|-s)
  742. shift
  743. opt_suite="$1"
  744. [ -n "$opt_suite" ] || die "No suite given"
  745. ;;
  746. --arch|-a)
  747. shift
  748. opt_arch="$1"
  749. [ -n "$opt_arch" ] || die "No arch given"
  750. ;;
  751. --qemu-bin|-q)
  752. shift
  753. opt_qemu="$1"
  754. [ -x "$opt_qemu" ] || die "No valid qemu binary given"
  755. ;;
  756. --skip-debootstrap1|-1)
  757. opt_skip_debootstrap1=1
  758. ;;
  759. --skip-debootstrap2|-2)
  760. opt_skip_debootstrap2=1
  761. ;;
  762. *)
  763. opt_target_dir="$*"
  764. break
  765. ;;
  766. esac
  767. shift
  768. done
  769. [ -n "$opt_target_dir" ] ||\
  770. die "No TARGET_DIR"
  771. [ -d "$opt_target_dir" -o ! -e "$opt_target_dir" ] ||\
  772. die "$opt_target_dir is not a directory"
  773. # Run first stage.
  774. pilc_bootstrap_first_stage
  775. info "Starting second stage."
  776. # Export options for use by second stage.
  777. export opt_target_dir
  778. export opt_branch
  779. export opt_cython
  780. export opt_suite
  781. export opt_arch
  782. export opt_qemu
  783. export opt_skip_debootstrap1
  784. export opt_skip_debootstrap2
  785. export __PILC_BOOTSTRAP_SECOND_STAGE__=1
  786. chroot "$opt_target_dir" "/pilc-bootstrap.sh" ||\
  787. die "Chroot failed."
  788. # Run third stage.
  789. pilc_bootstrap_third_stage
  790. info ""
  791. info "Successfully bootstrapped PiLC."
  792. exit 0
  793. else
  794. # Run second stage
  795. pilc_bootstrap_second_stage
  796. exit 0
  797. fi