pilc-bootstrap.sh 30 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046
  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. # GPU memory
  110. gpu_mem=16
  111. #uncomment to overclock the arm. 700 MHz is the default.
  112. #arm_freq=800
  113. # Uncomment some or all of these to enable the optional hardware interfaces
  114. dtparam=i2c_arm=on
  115. dtparam=i2c_vc=on
  116. #dtparam=i2s=on
  117. #dtparam=spi=on
  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. assert_program install
  139. [ -x "$opt_qemu" ] ||\
  140. die "The qemu binary '$opt_qemu' is not executable."
  141. # debootstrap first stage.
  142. if [ $opt_skip_debootstrap1 -eq 0 ]; then
  143. info "Running debootstrap first stage..."
  144. debootstrap --arch="$opt_arch" --foreign --verbose \
  145. --keyring="$basedir/pilc/raspbian.public.key.gpg" \
  146. "$opt_suite" "$opt_target_dir" "$MAIN_MIRROR" \
  147. || die "debootstrap failed"
  148. mkdir -p "$opt_target_dir/usr/share/keyrings" ||\
  149. die "Failed to create keyrings dir."
  150. cp "$basedir/pilc/raspbian.archive.public.key.gpg" \
  151. "$opt_target_dir/usr/share/keyrings/" ||\
  152. die "Failed to copy raspbian.archive.public.key.gpg."
  153. cp /usr/share/keyrings/debian-archive-keyring.gpg \
  154. "$opt_target_dir/usr/share/keyrings/debian-archive-keyring.gpg" ||\
  155. die "Failed to copy debian-archive-keyring.gpg."
  156. fi
  157. [ -d "$opt_target_dir" ] ||\
  158. die "Target directory '$opt_target_dir' does not exist."
  159. # Copy qemu.
  160. local qemu_bin="$opt_target_dir/$opt_qemu"
  161. if ! [ -x "$qemu_bin" ]; then
  162. info "Copying qemu binary from '$opt_qemu' to '$qemu_bin'..."
  163. mkdir -p "$(dirname "$qemu_bin")" ||\
  164. die "Failed to make qemu base directory."
  165. cp "$opt_qemu" "$qemu_bin" ||\
  166. die "Failed to copy qemu binary."
  167. fi
  168. info "Copying PiLC bootstrap script..."
  169. cp "$basedir/pilc/pilc-bootstrap.sh" "$opt_target_dir/" ||\
  170. die "Failed to copy bootstrap script."
  171. info "Checking out awlsim..."
  172. local awlsim_dir="$opt_target_dir/tmp/awlsim"
  173. local checkout_dir="$awlsim_dir/src"
  174. rm -rf "$awlsim_dir"
  175. mkdir -p "$awlsim_dir" || die "mkdir failed"
  176. git clone --no-checkout "$basedir/.git" "$checkout_dir" ||\
  177. die "Failed to clone"
  178. (
  179. cd "$checkout_dir" ||\
  180. die "Failed to cd"
  181. git checkout -b __build origin/"$opt_branch" ||\
  182. die "Failed to check out branch."
  183. git submodule update --init submodules/pyprofibus ||\
  184. die "Failed to pull pyprofibus submodule"
  185. rm -r .git submodules/pyprofibus/.git ||\
  186. die "Failed to remove .git directory."
  187. mv submodules/pyprofibus .. ||\
  188. die "Failed to move pyprofibus submodule."
  189. ) || die
  190. # Copy kernel tree
  191. if [ "$opt_kernel" = "pilc" ]; then
  192. info "Copying PiLC kernel tree..."
  193. rsync -rlt --inplace --exclude='.git*' \
  194. "$basedir/pilc/kernel/" "$opt_target_dir/tmp/kernel/" ||\
  195. die "Failed to copy PiLC kernel."
  196. cp "$basedir/pilc/kernel.config" "$opt_target_dir/tmp/kernel/.config" ||\
  197. die "Failed to copy PiLC kernel config."
  198. fi
  199. # Second stage will mount a few filesystems.
  200. # Keep track to umount them in cleanup.
  201. mp_proc="$opt_target_dir/proc"
  202. mp_sys="$opt_target_dir/sys"
  203. mp_shm="$opt_target_dir/dev/shm"
  204. }
  205. pilc_bootstrap_second_stage()
  206. {
  207. info "Running second stage ($opt_arch)..."
  208. [ -x /pilc-bootstrap.sh ] ||\
  209. die "Second stage does not contain the bootstrap script."
  210. # Set up environment.
  211. export LC_ALL=C
  212. export LANGUAGE=C
  213. export LANG=C
  214. # debootstrap second stage.
  215. if [ $opt_skip_debootstrap2 -eq 0 ]; then
  216. info "Running debootstrap second stage..."
  217. /debootstrap/debootstrap --verbose --second-stage ||\
  218. die "Debootstrap second stage failed."
  219. fi
  220. info "Mounting /proc..."
  221. mkdir -p /proc ||\
  222. die "Failed to create /proc mountpoint."
  223. mount -t proc proc /proc ||\
  224. die "Mounting /proc failed."
  225. info "Mounting /sys..."
  226. mkdir -p /sys ||\
  227. die "Failed to create /sys mountpoint."
  228. mount -t sysfs sysfs /sys ||\
  229. die "Mounting /sys failed."
  230. info "Mounting /dev/shm..."
  231. mkdir -p /dev/shm ||\
  232. die "Failed to create /dev/shm mountpoint."
  233. mount -t tmpfs tmpfs /dev/shm ||\
  234. die "Mounting /dev/shm failed."
  235. info "Writing apt configuration..."
  236. cat > /etc/apt/sources.list <<EOF
  237. deb $MAIN_MIRROR $opt_suite main firmware rpi
  238. deb http://archive.raspberrypi.org/debian/ $opt_suite main ui
  239. EOF
  240. [ $? -eq 0 ] || die "Failed to set sources.list"
  241. echo 'Acquire { Languages "none"; };' > /etc/apt/apt.conf.d/99no-translations ||\
  242. die "Failed to set apt.conf.d"
  243. info "Creating /etc/fstab"
  244. mkdir -p /config ||\
  245. die "Failed to create /config"
  246. cat > /etc/fstab <<EOF
  247. proc /proc proc auto,defaults 0 0
  248. debugfs /sys/kernel/debug debugfs auto,defaults 0 0
  249. configfs /config configfs auto,defaults 0 0
  250. tmpfs /tmp tmpfs auto,mode=1777 0 0
  251. /dev/mmcblk0p2 / ext4 auto,noatime,errors=remount-ro 0 1
  252. /dev/mmcblk0p1 /boot vfat auto,noatime 0 0
  253. EOF
  254. info "Writing misc /etc stuff..."
  255. echo "PiLC" > /etc/hostname ||\
  256. die "Failed to set hostname"
  257. printf 'PiLC GNU/Linux (based on Raspbian) \\n \\l\n\n' > /etc/issue ||\
  258. die "Failed to create /etc/issue"
  259. printf 'PiLC GNU/Linux (based on Raspbian)\n' > /etc/issue.net ||\
  260. die "Failed to create /etc/issue.net"
  261. sed -i -e 's|PRETTY_NAME=.*|PRETTY_NAME="PiLC"|' \
  262. /etc/os-release ||\
  263. die "Failed to set os-release PRETTY_NAME."
  264. sed -i -e 's|NAME=.*|NAME="PiLC"|' \
  265. /etc/os-release ||\
  266. die "Failed to set os-release NAME."
  267. sed -i -e 's|ID=.*|ID=pilc|' \
  268. /etc/os-release ||\
  269. die "Failed to set os-release ID."
  270. sed -i -e 's|ID_LIKE=.*|ID_LIKE=raspbian|' \
  271. /etc/os-release ||\
  272. die "Failed to set os-release ID_LIKE."
  273. sed -i -e 's|HOME_URL=.*|HOME_URL="https://bues.ch/a/pilc"|' \
  274. /etc/os-release ||\
  275. die "Failed to set os-release HOME_URL."
  276. sed -i -e 's|SUPPORT_URL=.*|SUPPORT_URL="https://bues.ch/a/pilc"|' \
  277. /etc/os-release ||\
  278. die "Failed to set os-release SUPPORT_URL."
  279. sed -i -e 's|BUG_REPORT_URL=.*|BUG_REPORT_URL="https://bues.ch/a/pilc"|' \
  280. /etc/os-release ||\
  281. die "Failed to set os-release BUG_REPORT_URL."
  282. sed -i -e 's|#FSCKFIX=no|FSCKFIX=yes|' \
  283. /etc/default/rcS ||\
  284. die "Failed to set FSCKFIX=yes"
  285. info "Updating packages..."
  286. cat <<EOF | debconf-set-selections
  287. debconf debconf/priority select high
  288. debconf debconf/frontend select Noninteractive
  289. locales locales/locales_to_be_generated multiselect en_US.UTF-8 UTF-8
  290. locales locales/default_environment_locale select None
  291. EOF
  292. [ $? -eq 0 ] || die "Failed to configure debconf settings"
  293. apt-key add /usr/share/keyrings/raspbian.archive.public.key.gpg ||\
  294. die "apt-key add failed"
  295. apt-get -y update ||\
  296. die "apt-get update failed"
  297. apt-get -y dist-upgrade ||\
  298. die "apt-get dist-upgrade failed"
  299. info "Installing packages..."
  300. if [ "$opt_kernel" = "raspi" ]; then
  301. local bootloader=raspberrypi-bootloader
  302. apt-get -y purge raspberrypi-bootloader-nokernel ||\
  303. die "Failed to remove bootloader"
  304. elif [ "$opt_kernel" = "pilc" ]; then
  305. local bootloader=raspberrypi-bootloader-nokernel
  306. apt-get -y purge raspberrypi-bootloader ||\
  307. die "Failed to remove bootloader"
  308. else
  309. die "Invalid opt_kernel"
  310. fi
  311. apt-get -y install \
  312. "$bootloader" \
  313. aptitude \
  314. autoconf \
  315. automake \
  316. bc \
  317. build-essential \
  318. bwidget \
  319. console-setup \
  320. cython \
  321. cython3 \
  322. dbus \
  323. debconf-utils \
  324. devscripts \
  325. git \
  326. gnu-fdisk \
  327. htop \
  328. i2c-tools \
  329. irqbalance \
  330. libboost-python-dev \
  331. libgl1-mesa-dev \
  332. libglu1-mesa-dev \
  333. libglib2.0-dev \
  334. libgtk2.0-dev \
  335. libncurses5-dev \
  336. libmodbus-dev \
  337. libreadline-gplv2-dev \
  338. libtk-img \
  339. libudev-dev \
  340. libusb-1.0-0-dev \
  341. libxmu-dev \
  342. locales \
  343. nano \
  344. openssh-server \
  345. openssh-blacklist \
  346. openssh-blacklist-extra \
  347. parted \
  348. pkg-config \
  349. pypy \
  350. python \
  351. python-all-dev \
  352. python-cairo \
  353. python-gtk2 \
  354. python-rpi.gpio \
  355. python-serial \
  356. python-setuptools \
  357. python-smbus \
  358. python-tk \
  359. python3 \
  360. python3-all-dev \
  361. python3-cairo \
  362. python3-rpi.gpio \
  363. python3-serial \
  364. python3-setuptools \
  365. python3-smbus \
  366. python3-tk \
  367. schedtool \
  368. screen \
  369. sudo \
  370. systemd \
  371. tcl-dev \
  372. tclx \
  373. tk-dev \
  374. tmux \
  375. vim ||\
  376. die "apt-get install failed"
  377. apt-get install --reinstall libc6-dev ||\
  378. die "Failed to reinstall"
  379. cat <<EOF | debconf-set-selections
  380. debconf debconf/frontend select Dialog
  381. locales locales/default_environment_locale select en_US.UTF-8
  382. EOF
  383. [ $? -eq 0 ] || die "Failed to configure debconf settings"
  384. dpkg-reconfigure -u locales ||\
  385. die "Failed to reconfigure locales"
  386. apt-get -y clean ||\
  387. die "apt-get clean failed"
  388. # Build and install kernel
  389. if [ "$opt_kernel" = "pilc" ]; then
  390. info "Building PiLC kernel..."
  391. (
  392. cd "/tmp/kernel" ||\
  393. die "Failed to cd to /tmp/kernel"
  394. make oldconfig ||\
  395. die "Kernel oldconfig failed"
  396. make -j "$_NPROCESSORS_ONLN" ||\
  397. die "Kernel build failed"
  398. #TODO
  399. ) || die
  400. die "TODO: PiLC kernel"
  401. fi
  402. info "Removing ssh keys..."
  403. if [ -e "$(first /etc/ssh/ssh_host_*_key*)" ]; then
  404. rm /etc/ssh/ssh_host_*_key* ||\
  405. die "Failed to remove ssh keys."
  406. fi
  407. echo 1 > /etc/ssh/sshd_not_to_be_run ||\
  408. die "Failed to create /etc/ssh/sshd_not_to_be_run"
  409. echo 1 > /etc/ssh/ssh_create_keys ||\
  410. die "Failed to create /etc/ssh/ssh_create_keys"
  411. info "Creating /etc/rc.local..."
  412. cat > /etc/rc.local <<EOF
  413. #!/bin/sh -e
  414. #
  415. # rc.local
  416. #
  417. # This script is executed at the end of each multiuser runlevel.
  418. # Make sure that the script will "exit 0" on success or any other
  419. # value on error.
  420. #
  421. # In order to enable or disable this script just change the execution
  422. # bits.
  423. #
  424. # Re-generate ssh keys, if requested.
  425. if [ -e /etc/ssh/ssh_create_keys ]; then
  426. /bin/rm -f /etc/ssh/ssh_host_*_key*
  427. LC_ALL=C LANGUAGE=C LANG=C /usr/sbin/dpkg-reconfigure openssh-server
  428. /bin/rm /etc/ssh/sshd_not_to_be_run
  429. /bin/rm /etc/ssh/ssh_create_keys
  430. /etc/init.d/ssh start
  431. fi
  432. # Workaround firmware issue leaving i2c0 in an non-ALT0 state.
  433. for i in 28 29; do
  434. /bin/echo \$i > /sys/class/gpio/export
  435. /bin/echo in > /sys/class/gpio/gpio\${i}/direction
  436. done
  437. # Add HAT eeprom device.
  438. if ! [ -d "/sys/class/i2c-adapter/i2c-0/0-0050" ]; then
  439. /bin/echo "24c32 0x50" > /sys/class/i2c-adapter/i2c-0/new_device
  440. fi
  441. # Add /dev/ttyS0 link for convenience.
  442. if ! [ -e /dev/ttyS0 ]; then
  443. /bin/ln -s /dev/ttyAMA0 /dev/ttyS0
  444. fi
  445. exit 0
  446. EOF
  447. [ $? -eq 0 ] || die "Failed to create /etc/rc.local"
  448. info "Creating /etc/modules-load.d/i2c.conf..."
  449. cat > /etc/modules-load.d/i2c.conf <<EOF
  450. i2c-dev
  451. i2c-bcm2708
  452. at24
  453. rtc-rv3029c2
  454. EOF
  455. [ $? -eq 0 ] || die "Failed to create /etc/modules-load.d/i2c.conf"
  456. info "Creating users/groups..."
  457. userdel -f pi
  458. groupdel pi
  459. rm -rf /home/pi
  460. groupadd -g 1000 pi ||\
  461. die "Failed to create group pi."
  462. useradd -u 1000 -d /home/pi -m -g pi\
  463. -G pi,lp,dialout,cdrom,floppy,audio,dip,src,video,plugdev,netdev,i2c\
  464. -s /bin/bash\
  465. pi ||\
  466. die "Failed to create user pi."
  467. printf 'raspberry\nraspberry\n' | passwd pi ||\
  468. die "Failed to set 'pi' password."
  469. echo 'pi ALL=(ALL:ALL) ALL' > "/etc/sudoers.d/00-pi" ||\
  470. die "Failed to create /etc/sudoers.d/00-pi"
  471. info "Initializing home directory..."
  472. mkdir -p /home/pi/.vim || die "Failed to mkdir /home/pi/.vim"
  473. cat > /home/pi/.vim/vimrc <<EOF
  474. set nocompatible
  475. set autoindent
  476. syntax enable
  477. set backspace=indent,start
  478. set number
  479. EOF
  480. [ $? -eq 0 ] || die "Failed to create /home/pi/.vim/vimrc"
  481. cat > /home/pi/.tmux.conf <<EOF
  482. # Default new panes and windows to be opened in the current panes path
  483. bind-key c new-window -c "#{pane_current_path}"
  484. bind-key % split-window -h -c "#{pane_current_path}"
  485. bind-key "\"" split-window -c "#{pane_current_path}"
  486. EOF
  487. [ $? -eq 0 ] || die "Failed to create /home/pi/.tmux.conf"
  488. info "Building awlsim..."
  489. (
  490. cd /tmp/awlsim/src ||\
  491. die "Failed to cd"
  492. if [ $opt_cython -eq 0 ]; then
  493. # Disable cython
  494. sed -i -e '/Package: cython/,/^$/ d' \
  495. debian/control ||\
  496. die "Failed to patch control file"
  497. sed -i -e 's/export AWLSIM_CYTHON=1/export AWLSIM_CYTHON=0/' \
  498. debian/rules ||\
  499. die "Failed to patch rules file"
  500. fi
  501. debuild -uc -us -b -d || die "debuild failed"
  502. info "Built awlsim files:"
  503. ls .. || die "Failed to list results"
  504. info "Installing awlsim..."
  505. # Core
  506. dpkg -i ../python-awlsim_*.deb ||\
  507. die "Failed to install python-awlsim"
  508. dpkg -i ../python3-awlsim_*.deb ||\
  509. die "Failed to install python3-awlsim"
  510. dpkg -i ../pypy-awlsim_*.deb ||\
  511. die "Failed to install pypy-awlsim"
  512. if [ $opt_cython -ne 0 ]; then
  513. dpkg -i ../cython-awlsim_*.deb ||\
  514. die "Failed to install cython-awlsim"
  515. dpkg -i ../cython3-awlsim_*.deb ||\
  516. die "Failed to install cython3-awlsim"
  517. fi
  518. # hardware: dummy
  519. dpkg -i ../python-awlsimhw-dummy_*.deb ||\
  520. die "Failed to install python-awlsimhw-dummy"
  521. dpkg -i ../python3-awlsimhw-dummy_*.deb ||\
  522. die "Failed to install python3-awlsimhw-dummy"
  523. dpkg -i ../pypy-awlsimhw-dummy_*.deb ||\
  524. die "Failed to install pypy-awlsimhw-dummy"
  525. if [ $opt_cython -ne 0 ]; then
  526. dpkg -i ../cython-awlsimhw-dummy_*.deb ||\
  527. die "Failed to install cython-awlsimhw-dummy"
  528. dpkg -i ../cython3-awlsimhw-dummy_*.deb ||\
  529. die "Failed to install cython3-awlsimhw-dummy"
  530. fi
  531. # hardware: linuxcnc
  532. dpkg -i ../python-awlsimhw-linuxcnc_*.deb ||\
  533. die "Failed to install python-awlsimhw-linuxcnc"
  534. dpkg -i ../python3-awlsimhw-linuxcnc_*.deb ||\
  535. die "Failed to install python3-awlsimhw-linuxcnc"
  536. if [ $opt_cython -ne 0 ]; then
  537. dpkg -i ../cython-awlsimhw-linuxcnc_*.deb ||\
  538. die "Failed to install cython-awlsimhw-linuxcnc"
  539. dpkg -i ../cython3-awlsimhw-linuxcnc_*.deb ||\
  540. die "Failed to install cython3-awlsimhw-linuxcnc"
  541. fi
  542. # hardware: profibus
  543. dpkg -i ../python-awlsimhw-profibus_*.deb ||\
  544. die "Failed to install python-awlsimhw-profibus"
  545. dpkg -i ../python3-awlsimhw-profibus_*.deb ||\
  546. die "Failed to install python3-awlsimhw-profibus"
  547. dpkg -i ../pypy-awlsimhw-profibus_*.deb ||\
  548. die "Failed to install pypy-awlsimhw-profibus"
  549. if [ $opt_cython -ne 0 ]; then
  550. dpkg -i ../cython-awlsimhw-profibus_*.deb ||\
  551. die "Failed to install cython-awlsimhw-profibus"
  552. dpkg -i ../cython3-awlsimhw-profibus_*.deb ||\
  553. die "Failed to install cython3-awlsimhw-profibus"
  554. fi
  555. # hardware: RPi GPIO
  556. dpkg -i ../python-awlsimhw-rpigpio_*.deb ||\
  557. die "Failed to install python-awlsimhw-rpigpio"
  558. dpkg -i ../python3-awlsimhw-rpigpio_*.deb ||\
  559. die "Failed to install python3-awlsimhw-rpigpio"
  560. dpkg -i ../pypy-awlsimhw-rpigpio_*.deb ||\
  561. die "Failed to install pypy-awlsimhw-rpigpio"
  562. if [ $opt_cython -ne 0 ]; then
  563. dpkg -i ../cython-awlsimhw-rpigpio_*.deb ||\
  564. die "Failed to install cython-awlsimhw-rpigpio"
  565. dpkg -i ../cython3-awlsimhw-rpigpio_*.deb ||\
  566. die "Failed to install cython3-awlsimhw-rpigpio"
  567. fi
  568. # PiLC libraries
  569. dpkg -i ../python-libpilc_*.deb ||\
  570. die "Failed to install python-libpilc"
  571. dpkg -i ../python3-libpilc_*.deb ||\
  572. die "Failed to install python3-libpilc"
  573. # Executables
  574. dpkg -i ../awlsim-server_*.deb ||\
  575. die "Failed to install awlsim-server"
  576. dpkg -i ../awlsim-client_*.deb ||\
  577. die "Failed to install awlsim-client"
  578. dpkg -i ../awlsim-symtab_*.deb ||\
  579. die "Failed to install awlsim-symtab"
  580. dpkg -i ../awlsim-test_*.deb ||\
  581. die "Failed to install awlsim-test"
  582. dpkg -i ../awlsim-linuxcnc-hal_*.deb ||\
  583. die "Failed to install awlsim-linuxcnc-hal"
  584. dpkg -i ../pilc-hat-conf_*.deb ||\
  585. die "Failed to install pilc-hat-conf"
  586. # GUI and misc
  587. mkdir -p /home/pi/awlsim-gui ||\
  588. die "mkdir /home/pi/awlsim-gui failed"
  589. cp ../python*-awlsim-gui_*.deb ../awlsim-gui_*.deb \
  590. /home/pi/awlsim-gui/ ||\
  591. die "Failed to copy awlsim-gui"
  592. cp examples/EXAMPLE.awlpro /home/pi/generic-example.awlpro ||\
  593. die "Failed to copy EXAMPLE.awlpro."
  594. cp examples/raspberrypi-gpio.awlpro /home/pi/raspberrypi-gpio-example.awlpro ||\
  595. die "Failed to copy raspberrypi-gpio.awlpro."
  596. cp examples/raspberrypi-profibus.awlpro /home/pi/raspberrypi-profibus-example.awlpro ||\
  597. die "Failed to copy raspberrypi-profibus.awlpro."
  598. #TODO run the testsuite
  599. #TODO install unit via package
  600. info "Installing awlsim service unit..."
  601. local awlsim_prefix=/usr
  602. local site="$awlsim_prefix/lib/python3/dist-packages"
  603. cat awlsim-server.service.in |\
  604. sed -e 's|@USER@|root|g' \
  605. -e 's|@GROUP@|root|g' \
  606. -e "s|@PREFIX@|$awlsim_prefix|g" \
  607. -e 's|@PROJECT@|/etc/awlsim-server.awlpro|g' \
  608. -e "s|@PYTHON_SITE@|$site|g" >\
  609. /etc/systemd/system/awlsim-server.service ||\
  610. die "Failed to create awlsim-server.service"
  611. systemctl enable awlsim-server.service ||\
  612. die "Failed to enable awlsim-server-service"
  613. ) || die
  614. info "Building pyprofibus..."
  615. (
  616. cd /tmp/awlsim/pyprofibus ||\
  617. die "Failed to cd"
  618. debuild -uc -us -b -d || die "debuild failed"
  619. info "Built pyprofibus files:"
  620. ls .. || die "Failed to list results"
  621. info "Installing pyprofibus..."
  622. dpkg -i ../python-pyprofibus_*.deb ||\
  623. die "Failed to install python-pyprofibus"
  624. dpkg -i ../python3-pyprofibus_*.deb ||\
  625. die "Failed to install python3-pyprofibus"
  626. dpkg -i ../pypy-pyprofibus_*.deb ||\
  627. die "Failed to install pypy-pyprofibus"
  628. dpkg -i ../profisniff_*.deb ||\
  629. die "Failed to install profisniff"
  630. dpkg -i ../gsdparser_*.deb ||\
  631. die "Failed to install gsdparser"
  632. dpkg -i ../pyprofibus-linuxcnc-hal_*.deb ||\
  633. die "Failed to install pyprofibus-linuxcnc-hal"
  634. ) || die
  635. rm -r /tmp/awlsim ||\
  636. die "Failed to remove awlsim checkout."
  637. info "Extending pi user environment..."
  638. cat >> /home/pi/.bashrc <<EOF
  639. # PiLC
  640. for __i in /opt/awlsim/lib/python*/site-packages/; do
  641. export PYTHONPATH="\$PYTHONPATH:\$__i"
  642. done
  643. export PATH="\$PATH:/opt/awlsim/bin"
  644. EOF
  645. [ $? -eq 0 ] || die "Failed to extend /home/pi/.bashrc"
  646. info "Configuring network..."
  647. cat > /etc/network/interfaces.d/lo <<EOF
  648. auto lo
  649. iface lo inet loopback
  650. EOF
  651. [ $? -eq 0 ] || die "Failed to create /etc/network/interfaces.d/lo"
  652. for i in $(seq 0 9); do
  653. cat > /etc/network/interfaces.d/eth$i <<EOF
  654. allow-hotplug eth$i
  655. iface eth$i inet dhcp
  656. iface eth$i inet6 auto
  657. EOF
  658. [ $? -eq 0 ] || die "Failed to create /etc/network/interfaces.d/eth$i"
  659. done
  660. info "Updating home directory permissions..."
  661. chown -R pi:pi /home/pi || die "Failed to change /home/pi permissions."
  662. info "Stopping processes..."
  663. for i in dbus ssh atd; do
  664. /etc/init.d/$i stop
  665. done
  666. info "Umounting /dev/shm..."
  667. umount /dev/shm || die "Failed to umount /dev/shm"
  668. info "Umounting /sys..."
  669. umount /sys || die "Failed to umount /sys"
  670. info "Umounting /proc..."
  671. umount /proc || die "Failed to umount /proc"
  672. }
  673. pilc_bootstrap_third_stage()
  674. {
  675. info "Running third stage..."
  676. info "Removing PiLC bootstrap script..."
  677. rm "$opt_target_dir/pilc-bootstrap.sh" ||\
  678. die "Failed to remove bootstrap script."
  679. info "Configuring boot..."
  680. cat > "$opt_target_dir/boot/cmdline.txt" <<EOF
  681. dwc_otg.lpm_enable=0 console=tty1 root=/dev/mmcblk0p2 rootfstype=ext4 elevator=deadline fsck.repair=yes rootwait quiet
  682. EOF
  683. [ $? -eq 0 ] || die "Failed to create /boot/cmdline.txt"
  684. boot_config_file > "$opt_target_dir/boot/config.txt" ||\
  685. die "Failed to create /boot/config.txt"
  686. local img="$(first "$opt_target_dir/boot/"vmlinuz-*-rpi)"
  687. if [ -e "$img" ]; then
  688. mv "$img" "$opt_target_dir/boot/kernel.img" ||\
  689. die "Failed to create kernel.img"
  690. fi
  691. local img="$(first "$opt_target_dir/boot/"initrd.img-*-rpi)"
  692. if [ -e "$img" ]; then
  693. mv "$img" "$opt_target_dir/boot/initrd.img" ||\
  694. die "Failed to create initrd.img"
  695. fi
  696. local img="$(first "$opt_target_dir/boot/"vmlinuz-*-rpi2)"
  697. if [ -e "$img" ]; then
  698. mv "$img" "$opt_target_dir/boot/kernel7.img" ||\
  699. die "Failed to create kernel7.img"
  700. fi
  701. local img="$(first "$opt_target_dir/boot/"initrd.img-*-rpi2)"
  702. if [ -e "$img" ]; then
  703. mv "$img" "$opt_target_dir/boot/initrd7.img" ||\
  704. die "Failed to create initrd7.img"
  705. fi
  706. # Prepare image paths.
  707. local target_dir="$(readlink -m "${opt_target_dir}")"
  708. [ -n "$target_dir" ] || die "Failed to resolve target dir."
  709. local imgfile="${target_dir}${opt_imgsuffix}.img"
  710. local imgfile_zip="${imgfile}.7z"
  711. local bootimgfile="${imgfile}.boot"
  712. mp_bootimgfile="${bootimgfile}.mp"
  713. local rootimgfile="${imgfile}.root"
  714. mp_rootimgfile="${rootimgfile}.mp"
  715. rm -f "$imgfile" "$imgfile_zip" "$rootimgfile" "$bootimgfile"
  716. rmdir "$mp_bootimgfile" "$mp_rootimgfile" 2>/dev/null
  717. # Create images.
  718. if [ "$opt_img" -ne 0 ]; then
  719. info "Creating boot image..."
  720. mkfs.vfat -F 32 -i 7771B0BB -n boot -C "$bootimgfile" \
  721. $(expr \( 64 \* 1024 \) - \( 4 \* 1024 \) ) ||\
  722. die "Failed to create boot partition file system."
  723. mkdir "$mp_bootimgfile" ||\
  724. die "Failed to make boot partition mount point."
  725. mount -o loop "$bootimgfile" "$mp_bootimgfile" ||\
  726. die "Failed to mount boot partition."
  727. rsync -aHAX --inplace \
  728. "$target_dir/boot/" "$mp_bootimgfile/" ||\
  729. die "Failed to copy boot files."
  730. umount "$mp_bootimgfile" ||\
  731. die "Failed to umount boot partition."
  732. rmdir "$mp_bootimgfile" ||\
  733. die "Failed to remove boot partition mount point."
  734. info "Creating root image..."
  735. mkfs.ext4 "$rootimgfile" $(expr \( 4000 - 64 \) \* 1024 ) ||\
  736. die "Failed to create root filesystem."
  737. mkdir "$mp_rootimgfile" ||\
  738. die "Failed to make root partition mount point."
  739. mount -o loop "$rootimgfile" "$mp_rootimgfile" ||\
  740. die "Failed to mount root partition."
  741. rsync -aHAX --inplace \
  742. --exclude='boot/*' \
  743. --exclude='proc/*' \
  744. --exclude='sys/*' \
  745. --exclude='dev/shm/*' \
  746. --exclude='tmp/*' \
  747. --exclude="$(basename "$opt_qemu")" \
  748. "$target_dir/" "$mp_rootimgfile/" ||\
  749. die "Failed to copy root files."
  750. umount "$mp_rootimgfile" ||\
  751. die "Failed to umount root partition."
  752. rmdir "$mp_rootimgfile" ||\
  753. die "Failed to remove root partition mount point."
  754. info "Creating image '$imgfile'..."
  755. dd if=/dev/zero of="$imgfile" bs=1M count=4000 conv=sparse ||\
  756. die "Failed to create image file."
  757. parted "$imgfile" <<EOF
  758. unit b
  759. mklabel msdos
  760. mkpart primary fat32 $(expr 4 \* 1024 \* 1024) $(expr 64 \* 1024 \* 1024 - 1)
  761. mkpart primary ext4 $(expr 64 \* 1024 \* 1024) 100%
  762. EOF
  763. [ $? -eq 0 ] || die "Failed to create partitions."
  764. info "Integrating boot image..."
  765. dd if="$bootimgfile" of="$imgfile"\
  766. seek=4 bs=1M conv=notrunc,sparse ||\
  767. die "Failed to integrate boot partition."
  768. rm "$bootimgfile" ||\
  769. die "Failed to delete boot partition image."
  770. info "Integrating root image..."
  771. dd if="$rootimgfile" of="$imgfile"\
  772. seek=64 bs=1M conv=notrunc,sparse ||\
  773. die "Failed to integrate root partition."
  774. rm "$rootimgfile" ||\
  775. die "Failed to delete root partition image."
  776. # Create zipped image.
  777. if [ "$opt_zimg" -ne 0 ]; then
  778. info "Compressing image..."
  779. 7z -mx=9 a "$imgfile_zip" "$imgfile" ||\
  780. die "Failed to compress partition image."
  781. fi
  782. fi
  783. }
  784. usage()
  785. {
  786. echo "pilc-bootstrap.sh [OPTIONS] TARGET_DIR"
  787. echo
  788. echo "Options:"
  789. echo
  790. echo " --branch|-b BRANCH Select the awlsim branch."
  791. echo " Default: $default_branch"
  792. echo
  793. echo " --no-cython|-C Do not build Cython modules."
  794. echo " Default: Build cython modules"
  795. echo
  796. echo " --suite|-s SUITE Select the suite."
  797. echo " Default: $default_suite"
  798. echo
  799. echo " --arch|-a ARCH Select the default arch."
  800. echo " Default: $default_arch"
  801. echo
  802. echo " --kernel|-k KERNEL Kernel selection. Any of:"
  803. echo " raspi -> raspberrypi-bootloader package (default)"
  804. echo " pilc -> PiLC kernel"
  805. echo
  806. echo " --qemu-bin|-q PATH Select qemu-user-static binary."
  807. echo " Default: $default_qemu"
  808. echo
  809. echo " --img-suffix|-s SUFFIX Image file suffix."
  810. echo " Default: $default_imgsuffix"
  811. echo
  812. echo " --no-img|-I Do not create an image."
  813. echo " Default: Create image."
  814. echo
  815. echo " --no-zimg|-Z Do not create a 7zipped image."
  816. echo " Default: Create 7zipped image."
  817. echo
  818. echo " --skip-debootstrap1|-1 Skip debootstrap first stage."
  819. echo " --skip-debootstrap2|-2 Skip debootstrap second stage."
  820. }
  821. # canonicalize basedir
  822. basedir="$(readlink -e "$basedir")"
  823. [ -n "$basedir" ] || die "Failed to canonicalize base directory."
  824. # Mountpoints. Will be umounted on cleanup.
  825. mp_shm=
  826. mp_proc=
  827. mp_sys=
  828. mp_bootimgfile=
  829. mp_rootimgfile=
  830. trap term_signal TERM INT
  831. if [ -z "$__PILC_BOOTSTRAP_SECOND_STAGE__" ]; then
  832. # First stage
  833. trap cleanup EXIT
  834. export _NPROCESSORS_ONLN="$(getconf _NPROCESSORS_ONLN)"
  835. [ -n "$_NPROCESSORS_ONLN" ] || die "Failed to get # of online CPUs"
  836. default_branch="master"
  837. default_suite="jessie"
  838. default_arch="armhf"
  839. default_kernel="raspi"
  840. default_qemu="/usr/bin/qemu-arm-static"
  841. default_imgsuffix="-$(date '+%Y%m%d')"
  842. default_img=1
  843. default_zimg=1
  844. opt_target_dir=
  845. opt_branch="$default_branch"
  846. opt_cython=1
  847. opt_suite="$default_suite"
  848. opt_arch="$default_arch"
  849. opt_kernel="$default_kernel"
  850. opt_qemu="$default_qemu"
  851. opt_skip_debootstrap1=0
  852. opt_skip_debootstrap2=0
  853. opt_imgsuffix="$default_imgsuffix"
  854. opt_img="$default_img"
  855. opt_zimg="$default_zimg"
  856. while [ $# -ge 1 ]; do
  857. case "$1" in
  858. --help|-h)
  859. usage
  860. exit 0
  861. ;;
  862. --branch|-b)
  863. shift
  864. opt_branch="$1"
  865. [ -n "$opt_branch" ] || die "No branch given"
  866. ;;
  867. --no-cython|-C)
  868. opt_cython=0
  869. ;;
  870. --suite|-s)
  871. shift
  872. opt_suite="$1"
  873. [ -n "$opt_suite" ] || die "No suite given"
  874. ;;
  875. --arch|-a)
  876. shift
  877. opt_arch="$1"
  878. [ -n "$opt_arch" ] || die "No arch given"
  879. ;;
  880. --kernel|-k)
  881. shift
  882. opt_kernel="$1"
  883. [ "$opt_kernel" = "raspi" -o \
  884. "$opt_kernel" = "pilc" ] || die "Invalid kernel"
  885. ;;
  886. --qemu-bin|-q)
  887. shift
  888. opt_qemu="$1"
  889. [ -x "$opt_qemu" ] || die "No valid qemu binary given"
  890. ;;
  891. --skip-debootstrap1|-1)
  892. opt_skip_debootstrap1=1
  893. ;;
  894. --skip-debootstrap2|-2)
  895. opt_skip_debootstrap2=1
  896. ;;
  897. --img-suffix|-s)
  898. shift
  899. opt_imgsuffix="$1"
  900. ;;
  901. --no-zimg|-Z)
  902. opt_zimg=0
  903. ;;
  904. --no-img|-I)
  905. opt_img=0
  906. ;;
  907. *)
  908. opt_target_dir="$*"
  909. break
  910. ;;
  911. esac
  912. shift
  913. done
  914. [ -n "$opt_target_dir" ] ||\
  915. die "No TARGET_DIR"
  916. [ -d "$opt_target_dir" -o ! -e "$opt_target_dir" ] ||\
  917. die "$opt_target_dir is not a directory"
  918. # Run first stage.
  919. pilc_bootstrap_first_stage
  920. info "Starting second stage."
  921. # Export options for use by second stage.
  922. export opt_target_dir
  923. export opt_branch
  924. export opt_cython
  925. export opt_suite
  926. export opt_arch
  927. export opt_kernel
  928. export opt_qemu
  929. export opt_skip_debootstrap1
  930. export opt_skip_debootstrap2
  931. export opt_imgsuffix
  932. export opt_zimg
  933. export opt_img
  934. export __PILC_BOOTSTRAP_SECOND_STAGE__=1
  935. chroot "$opt_target_dir" "/pilc-bootstrap.sh" ||\
  936. die "Chroot failed."
  937. # Run third stage.
  938. pilc_bootstrap_third_stage
  939. info ""
  940. info "Successfully bootstrapped PiLC."
  941. exit 0
  942. else
  943. # Run second stage
  944. pilc_bootstrap_second_stage
  945. exit 0
  946. fi