#!/bin/sh # # PiLC bootstrap # # Copyright 2016 Michael Buesch # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License along # with this program; if not, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. # basedir="$(dirname "$0")" [ "$(echo "$basedir" | cut -c1)" = '/' ] || basedir="$PWD/$basedir" # The repository root is basedir. basedir="$basedir/.." MAIN_MIRROR="http://mirrordirector.raspbian.org/raspbian/" die() { echo "=== $*" >&2 exit 1 } info() { echo "--- $*" } # print the first of its arguments. first() { echo "$1" } # print the last of its arguments. last() { while [ $# -gt 1 ]; do shift; done echo "$1" } # $1=program_name have_program() { which "$1" >/dev/null 2>&1 } # $1=program_name, ($2=description) assert_program() { local bin="$1" local desc="$2" [ -n "$desc" ] || desc="$bin" have_program "$bin" || die "$bin not found. Please install $desc." } term_signal() { die "Terminating signal received" } cleanup() { info "Cleaning up..." for mp in "$mp_shm" "$mp_proc" "$mp_sys" "$mp_bootimgfile" "$mp_rootimgfile"; do [ -n "$mp" -a -d "$mp" ] &&\ umount "$mp" >/dev/null 2>&1 done for mp in "$mp_bootimgfile" "$mp_rootimgfile"; do [ -n "$mp" -a -d "$mp" ] &&\ rmdir "$mp" >/dev/null 2>&1 done } boot_config_file() { cat < /etc/apt/sources.list < /etc/apt/apt.conf.d/99no-translations ||\ die "Failed to set apt.conf.d" info "Creating /etc/fstab" mkdir -p /config ||\ die "Failed to create /config" cat > /etc/fstab < /etc/hostname ||\ die "Failed to set hostname" printf 'PiLC GNU/Linux (based on Raspbian) \\n \\l\n\n' > /etc/issue ||\ die "Failed to create /etc/issue" printf 'PiLC GNU/Linux (based on Raspbian)\n' > /etc/issue.net ||\ die "Failed to create /etc/issue.net" sed -i -e 's|PRETTY_NAME=.*|PRETTY_NAME="PiLC"|' \ /etc/os-release ||\ die "Failed to set os-release PRETTY_NAME." sed -i -e 's|NAME=.*|NAME="PiLC"|' \ /etc/os-release ||\ die "Failed to set os-release NAME." sed -i -e 's|ID=.*|ID=pilc|' \ /etc/os-release ||\ die "Failed to set os-release ID." sed -i -e 's|ID_LIKE=.*|ID_LIKE=raspbian|' \ /etc/os-release ||\ die "Failed to set os-release ID_LIKE." sed -i -e 's|HOME_URL=.*|HOME_URL="https://bues.ch/h/pilc"|' \ /etc/os-release ||\ die "Failed to set os-release HOME_URL." sed -i -e 's|SUPPORT_URL=.*|SUPPORT_URL="https://bues.ch/h/pilc"|' \ /etc/os-release ||\ die "Failed to set os-release SUPPORT_URL." sed -i -e 's|BUG_REPORT_URL=.*|BUG_REPORT_URL="https://bues.ch/h/pilc"|' \ /etc/os-release ||\ die "Failed to set os-release BUG_REPORT_URL." sed -i -e 's|#FSCKFIX=no|FSCKFIX=yes|' \ /etc/default/rcS ||\ die "Failed to set FSCKFIX=yes" info "Updating packages..." cat < /etc/ssh/sshd_not_to_be_run ||\ die "Failed to create /etc/ssh/sshd_not_to_be_run" echo 1 > /etc/ssh/ssh_create_keys ||\ die "Failed to create /etc/ssh/ssh_create_keys" info "Creating /etc/rc.local..." cat > /etc/rc.local < /etc/modules-load.d/i2c.conf < "/etc/sudoers.d/00-pi" ||\ die "Failed to create /etc/sudoers.d/00-pi" info "Building updated rv3029 kernel module..." ( cd /tmp/rv3029 ||\ die "Failed to cd to rv3029 build dir" for moddir in /lib/modules/*; do [ -d "$moddir" ] || die "Invalid moddir '$moddir'" make KBUILD_DIR="$moddir/build" MODNAME=rtc-rv3029c2 \ CFLAGS=-DCONFIG_RTC_DRV_RV3029_HWMON \ clean ||\ die "rv3029: Failed to clean" make KBUILD_DIR="$moddir/build" MODNAME=rtc-rv3029c2 \ CFLAGS=-DCONFIG_RTC_DRV_RV3029_HWMON ||\ die "rv3029: Failed to build" cp rtc-rv3029c2.ko "$moddir/kernel/drivers/rtc/" ||\ die "rv3029: Failed to install kernel module" depmod "$(basename "$moddir")" ||\ die "Failed to run depmod" done ) || die rm -r /tmp/rv3029 ||\ die "Failed to remove rv3029 build dir." info "Building awlsim..." ( cd /tmp/awlsim/src ||\ die "Failed to cd" if [ $opt_cython -eq 0 ]; then # Disable cython sed -i -e '/Package: cython/,/^$/ d' \ debian/control ||\ die "Failed to patch control file" sed -i -e 's/export NOCYTHON=0/export NOCYTHON=1/' \ debian/rules ||\ die "Failed to patch rules file" fi debuild -uc -us -b -d || die "debuild failed" info "Built awlsim files:" ls .. || die "Failed to list results" info "Installing awlsim..." # Core dpkg -i ../python-awlsim_*.deb ||\ die "Failed to install python-awlsim" dpkg -i ../python3-awlsim_*.deb ||\ die "Failed to install python3-awlsim" dpkg -i ../pypy-awlsim_*.deb ||\ die "Failed to install pypy-awlsim" if [ $opt_cython -ne 0 ]; then dpkg -i ../cython-awlsim_*.deb ||\ die "Failed to install cython-awlsim" dpkg -i ../cython3-awlsim_*.deb ||\ die "Failed to install cython3-awlsim" fi # hardware: dummy dpkg -i ../python-awlsimhw-dummy_*.deb ||\ die "Failed to install python-awlsimhw-dummy" dpkg -i ../python3-awlsimhw-dummy_*.deb ||\ die "Failed to install python3-awlsimhw-dummy" dpkg -i ../pypy-awlsimhw-dummy_*.deb ||\ die "Failed to install pypy-awlsimhw-dummy" if [ $opt_cython -ne 0 ]; then dpkg -i ../cython-awlsimhw-dummy_*.deb ||\ die "Failed to install cython-awlsimhw-dummy" dpkg -i ../cython3-awlsimhw-dummy_*.deb ||\ die "Failed to install cython3-awlsimhw-dummy" fi # hardware: linuxcnc dpkg -i ../python-awlsimhw-linuxcnc_*.deb ||\ die "Failed to install python-awlsimhw-linuxcnc" dpkg -i ../python3-awlsimhw-linuxcnc_*.deb ||\ die "Failed to install python3-awlsimhw-linuxcnc" if [ $opt_cython -ne 0 ]; then dpkg -i ../cython-awlsimhw-linuxcnc_*.deb ||\ die "Failed to install cython-awlsimhw-linuxcnc" dpkg -i ../cython3-awlsimhw-linuxcnc_*.deb ||\ die "Failed to install cython3-awlsimhw-linuxcnc" fi # hardware: profibus dpkg -i ../python-awlsimhw-profibus_*.deb ||\ die "Failed to install python-awlsimhw-profibus" dpkg -i ../python3-awlsimhw-profibus_*.deb ||\ die "Failed to install python3-awlsimhw-profibus" dpkg -i ../pypy-awlsimhw-profibus_*.deb ||\ die "Failed to install pypy-awlsimhw-profibus" if [ $opt_cython -ne 0 ]; then dpkg -i ../cython-awlsimhw-profibus_*.deb ||\ die "Failed to install cython-awlsimhw-profibus" dpkg -i ../cython3-awlsimhw-profibus_*.deb ||\ die "Failed to install cython3-awlsimhw-profibus" fi # hardware: RPi GPIO dpkg -i ../python-awlsimhw-rpigpio_*.deb ||\ die "Failed to install python-awlsimhw-rpigpio" dpkg -i ../python3-awlsimhw-rpigpio_*.deb ||\ die "Failed to install python3-awlsimhw-rpigpio" dpkg -i ../pypy-awlsimhw-rpigpio_*.deb ||\ die "Failed to install pypy-awlsimhw-rpigpio" if [ $opt_cython -ne 0 ]; then dpkg -i ../cython-awlsimhw-rpigpio_*.deb ||\ die "Failed to install cython-awlsimhw-rpigpio" dpkg -i ../cython3-awlsimhw-rpigpio_*.deb ||\ die "Failed to install cython3-awlsimhw-rpigpio" fi # Executables dpkg -i ../awlsim-server_*.deb ||\ die "Failed to install awlsim-server" dpkg -i ../awlsim-client_*.deb ||\ die "Failed to install awlsim-client" dpkg -i ../awlsim-symtab_*.deb ||\ die "Failed to install awlsim-symtab" dpkg -i ../awlsim-test_*.deb ||\ die "Failed to install awlsim-test" dpkg -i ../awlsim-linuxcnc-hal_*.deb ||\ die "Failed to install awlsim-linuxcnc-hal" # GUI mkdir -p /home/pi/awlsim-gui ||\ die "mkdir /home/pi/awlsim-gui failed" cp ../python*-awlsim-gui_*.deb ../awlsim-gui_*.deb \ /home/pi/awlsim-gui/ ||\ die "Failed to copy awlsim-gui" cp examples/EXAMPLE.awlpro /home/pi/generic-example.awlpro ||\ die "Failed to copy EXAMPLE.awlpro." cp examples/raspberrypi.awlpro /home/pi/raspberrypi-example.awlpro ||\ die "Failed to copy raspberrypi.awlpro." #TODO run the testsuite #TODO install unit via package info "Installing awlsim service unit..." local awlsim_prefix=/usr local site="$awlsim_prefix/lib/python3/dist-packages" cat awlsim-server.service.in |\ sed -e 's|@USER@|pi|g' \ -e 's|@GROUP@|pi|g' \ -e "s|@PREFIX@|$awlsim_prefix|g" \ -e "s|@PYTHON_SITE@|$site|g" >\ /etc/systemd/system/awlsim-server.service ||\ die "Failed to create awlsim-server.service" systemctl enable awlsim-server.service ||\ die "Failed to enable awlsim-server-service" ) || die rm -r /tmp/awlsim ||\ die "Failed to remove awlsim checkout." info "Extending pi user environment..." cat >> /home/pi/.bashrc < /etc/network/interfaces.d/lo < /etc/network/interfaces.d/eth0 < "$opt_target_dir/boot/cmdline.txt" < "$opt_target_dir/boot/config.txt" ||\ die "Failed to create /boot/config.txt" cp "$basedir/pilc/kernel/rv3029.dtb" \ "$opt_target_dir/boot/overlays/rv3029-rtc-overlay.dtb" ||\ die "Failed to copy rv3029 dt overlay" local img="$(first "$opt_target_dir/boot/"vmlinuz-*-rpi)" if [ -e "$img" ]; then mv "$img" "$opt_target_dir/boot/kernel.img" ||\ die "Failed to create kernel.img" fi local img="$(first "$opt_target_dir/boot/"initrd.img-*-rpi)" if [ -e "$img" ]; then mv "$img" "$opt_target_dir/boot/initrd.img" ||\ die "Failed to create initrd.img" fi local img="$(first "$opt_target_dir/boot/"vmlinuz-*-rpi2)" if [ -e "$img" ]; then mv "$img" "$opt_target_dir/boot/kernel7.img" ||\ die "Failed to create kernel7.img" fi local img="$(first "$opt_target_dir/boot/"initrd.img-*-rpi2)" if [ -e "$img" ]; then mv "$img" "$opt_target_dir/boot/initrd7.img" ||\ die "Failed to create initrd7.img" fi # Prepare image paths. local target_dir="$(readlink -m "${opt_target_dir}")" [ -n "$target_dir" ] || die "Failed to resolve target dir." local imgfile="${target_dir}.img" local bootimgfile="${imgfile}.boot" mp_bootimgfile="${bootimgfile}.mp" local rootimgfile="${imgfile}.root" mp_rootimgfile="${rootimgfile}.mp" rm -f "$rootimgfile" "$bootimgfile" rmdir "$mp_bootimgfile" "$mp_rootimgfile" 2>/dev/null info "Creating boot image..." mkfs.vfat -F 32 -i 7771B0BB -n boot -C "$bootimgfile" \ $(expr \( 64 \* 1024 \) - \( 4 \* 1024 \) ) ||\ die "Failed to create boot partition file system." mkdir "$mp_bootimgfile" ||\ die "Failed to make boot partition mount point." mount -o loop "$bootimgfile" "$mp_bootimgfile" ||\ die "Failed to mount boot partition." rsync -aHAX --inplace \ "$target_dir/boot/" "$mp_bootimgfile/" ||\ die "Failed to copy boot files." umount "$mp_bootimgfile" ||\ die "Failed to umount boot partition." rmdir "$mp_bootimgfile" ||\ die "Failed to remove boot partition mount point." info "Creating root image..." mkfs.ext4 "$rootimgfile" $(expr \( 1391 - 64 \) \* 1024 ) ||\ die "Failed to create root filesystem." mkdir "$mp_rootimgfile" ||\ die "Failed to make root partition mount point." mount -o loop "$rootimgfile" "$mp_rootimgfile" ||\ die "Failed to mount root partition." rsync -aHAX --inplace \ --exclude='boot/*' \ --exclude='proc/*' \ --exclude='sys/*' \ --exclude='dev/shm/*' \ --exclude="$(basename "$opt_qemu")" \ "$target_dir/" "$mp_rootimgfile/" ||\ die "Failed to copy root files." umount "$mp_rootimgfile" ||\ die "Failed to umount root partition." rmdir "$mp_rootimgfile" ||\ die "Failed to remove root partition mount point." info "Creating image '$imgfile'..." dd if=/dev/zero of="$imgfile" bs=1M count=1391 conv=sparse ||\ die "Failed to create image file." parted "$imgfile" <