diff --git a/build_rpi_sdcard.sh b/build_rpi_sdcard.sh new file mode 100644 index 0000000..a8a90bb --- /dev/null +++ b/build_rpi_sdcard.sh @@ -0,0 +1,195 @@ +#!/bin/bash + +# build your own Raspberry Pi SD card +# +# by Klaus M Pfeiffer, http://blog.kmp.or.at/ , 2012-06-24 + +# 2012-06-24 +# just checking for how partitions are called on the system (thanks to Ricky Birtles and Luke Wilkinson) +# using http.debian.net as debian mirror, see http://rgeissert.blogspot.co.at/2012/06/introducing-httpdebiannet-debians.html +# tested successfully in debian squeeze and wheezy VirtualBox +# added hint for lvm2 +# added debconf-set-selections for kezboard +# corrected bug in writing to etc/modules +# 2012-06-16 +# improoved handling of local debian mirror +# added hint for dosfstools (thanks to Mike) +# added vchiq & snd_bcm2835 to /etc/modules (thanks to Tony Jones) +# take the value fdisk suggests for the boot partition to start (thanks to Mike) +# 2012-06-02 +# improoved to directly generate an image file with the help of kpartx +# added deb_local_mirror for generating images with correct sources.list +# 2012-05-27 +# workaround for https://github.com/Hexxeh/rpi-update/issues/4 just touching /boot/start.elf before running rpi-update +# 2012-05-20 +# back to wheezy, http://bugs.debian.org/672851 solved, http://packages.qa.debian.org/i/ifupdown/news/20120519T163909Z.html +# 2012-05-19 +# stage3: remove eth* from /lib/udev/rules.d/75-persistent-net-generator.rules +# initial + +# you need at least +# apt-get install binfmt-support qemu qemu-user-static debootstrap kpartx lvm2 dosfstools + +deb_mirror="http://http.debian.net/debian" +#deb_local_mirror="http://debian.kmp.or.at:3142/debian" + +bootsize="64M" +deb_release="wheezy" + +device=$1 +buildenv="/root/rpi" +rootfs="${buildenv}/rootfs" +bootfs="${rootfs}/boot" + +mydate=`date +%Y%m%d` + +if [ "$deb_local_mirror" == "" ]; then + deb_local_mirror=$deb_mirror +fi + +image="" + + +if [ $EUID -ne 0 ]; then + echo "this tool must be run as root" + exit 1 +fi + +if ! [ -b $device ]; then + echo "$device is not a block device" + exit 1 +fi + +if [ "$device" == "" ]; then + echo "no block device given, just creating an image" + mkdir -p $buildenv + image="${buildenv}/rpi_basic_${deb_release}_${mydate}.img" + dd if=/dev/zero of=$image bs=1MB count=1000 + device=`losetup -f --show $image` + echo "image $image created and mounted as $device" +else + dd if=/dev/zero of=$device bs=512 count=1 +fi + +fdisk $device << EOF +n +p +1 + ++$bootsize +t +c +n +p +2 + + +w +EOF + + +if [ "$image" != "" ]; then + losetup -d $device + device=`kpartx -va $image | sed -E 's/.*(loop[0-9])p.*/\1/g' | head -1` + device="/dev/mapper/${device}" + bootp=${device}p1 + rootp=${device}p2 +else + if ! [ -b ${device}1 ]; then + bootp=${device}p1 + rootp=${device}p2 + if ! [ -b ${bootp} ]; then + echo "uh, oh, something went wrong, can't find bootpartition neither as ${device}1 nor as ${device}p1, exiting." + exit 1 + fi + else + bootp=${device}1 + rootp=${device}2 + fi +fi + +mkfs.vfat $bootp +mkfs.ext4 $rootp + +mkdir -p $rootfs + +mount $rootp $rootfs + +cd $rootfs + +debootstrap --foreign --arch armel $deb_release $rootfs $deb_local_mirror +cp /usr/bin/qemu-arm-static usr/bin/ +LANG=C chroot $rootfs /debootstrap/debootstrap --second-stage + +mount $bootp $bootfs + +echo "deb $deb_local_mirror $deb_release main contrib non-free +" > etc/apt/sources.list + +echo "dwc_otg.lpm_enable=0 console=ttyAMA0,115200 kgdboc=ttyAMA0,115200 console=tty1 root=/dev/mmcblk0p2 rootfstype=ext4 rootwait" > boot/cmdline.txt + +echo "proc /proc proc defaults 0 0 +/dev/mmcblk0p1 /boot vfat defaults 0 0 +" > etc/fstab + +echo "raspberrypi" > etc/hostname + +echo "auto lo +iface lo inet loopback + +auto eth0 +iface eth0 inet dhcp +" > etc/network/interfaces + +echo "vchiq +snd_bcm2835 +" >> etc/modules + +echo "console-common console-data/keymap/policy select Select keymap from full list +console-common console-data/keymap/full select de-latin1-nodeadkeys +" > debconf.set + +echo "#!/bin/bash +debconf-set-selections /debconf.set +rm -f /debconf.set +apt-get update +apt-get -y install git-core binutils ca-certificates +wget http://goo.gl/1BOfJ -O /usr/bin/rpi-update +chmod +x /usr/bin/rpi-update +mkdir -p /lib/modules/3.1.9+ +touch /boot/start.elf +rpi-update +apt-get -y install locales console-common ntp openssh-server less vim +echo \"root:raspberry\" | chpasswd +sed -i -e 's/KERNEL\!=\"eth\*|/KERNEL\!=\"/' /lib/udev/rules.d/75-persistent-net-generator.rules +rm -f /etc/udev/rules.d/70-persistent-net.rules +rm -f third-stage +" > third-stage +chmod +x third-stage +LANG=C chroot $rootfs /third-stage + +echo "deb $deb_mirror $deb_release main contrib non-free +" > etc/apt/sources.list + +echo "#!/bin/bash +aptitude update +aptitude clean +apt-get clean +rm -f cleanup +" > cleanup +chmod +x cleanup +LANG=C chroot $rootfs /cleanup + +cd + +umount $bootp +umount $rootp + +if [ "$image" != "" ]; then + kpartx -d $image + echo "created image $image" +fi + + +echo "done." + diff --git a/overlayRoot.sh b/overlayRoot.sh new file mode 100644 index 0000000..555fd10 --- /dev/null +++ b/overlayRoot.sh @@ -0,0 +1,119 @@ +#!/bin/sh +# Read-only Root-FS for Raspian using overlayfs +# Version 1.0 +# +# Created 2017 by Pascal Suter @ DALCO AG, Switzerland to work on Raspian as custom init script +# (raspbian does not use an initramfs on boot) +# +# 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 3 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, see +# . +# +# +# Tested with Raspbian mini, 2017-01-11 +# +# This script will mount the root filesystem read-only and overlay it with a temporary tempfs +# which is read-write mounted. This is done using the overlayFS which is part of the linux kernel +# since version 3.18. +# when this script is in use, all changes made to anywhere in the root filesystem mount will be lost +# upon reboot of the system. The SD card will only be accessed as read-only drive, which significantly +# helps to prolong its life and prevent filesystem coruption in environments where the system is usually +# not shut down properly +# +# Install: +# copy this script to /sbin/overlayRoot.sh and add "init=/sbin/overlayRoot.sh" to the cmdline.txt +# file in the raspbian image's boot partition. +# I strongly recommend to disable swapping before using this. it will work with swap but that just does +# not make sens as the swap file will be stored in the tempfs which again resides in the ram. +# run these commands on the booted raspberry pi BEFORE you set the init=/sbin/overlayRoot.sh boot option: +# sudo dphys-swapfile swapoff +# sudo dphys-swapfile uninstall +# sudo update-rc.d dphys-swapfile remove +# +# To install software, run upgrades and do other changes to the raspberry setup, simply remove the init= +# entry from the cmdline.txt file and reboot, make the changes, add the init= entry and reboot once more. + +fail(){ + echo -e "$1" + /bin/bash +} + +# load module +modprobe overlay +if [ $? -ne 0 ]; then + fail "ERROR: missing overlay kernel module" +fi +# mount /proc +mount -t proc proc /proc +if [ $? -ne 0 ]; then + fail "ERROR: could not mount proc" +fi +# create a writable fs to then create our mountpoints +mount -t tmpfs inittemp /mnt +if [ $? -ne 0 ]; then + fail "ERROR: could not create a temporary filesystem to mount the base filesystems for overlayfs" +fi +mkdir /mnt/lower +mkdir /mnt/rw +mount -t tmpfs root-rw /mnt/rw +if [ $? -ne 0 ]; then + fail "ERROR: could not create tempfs for upper filesystem" +fi +mkdir /mnt/rw/upper +mkdir /mnt/rw/work +mkdir /mnt/newroot +# mount root filesystem readonly +rootDev=/dev/mmcblk0p2 +rootPARTUUID=`awk '$2 == "/" {print $1}' /etc/fstab` +rootMountOpt=`awk '$2 == "/" {print $4}' /etc/fstab` +rootFsType=`awk '$2 == "/" {print $3}' /etc/fstab` +mount -t ${rootFsType} -o ${rootMountOpt},ro ${rootDev} /mnt/lower +if [ $? -ne 0 ]; then + fail "ERROR: could not ro-mount original root partition" +fi +mount -t overlay -o lowerdir=/mnt/lower,upperdir=/mnt/rw/upper,workdir=/mnt/rw/work overlayfs-root /mnt/newroot +if [ $? -ne 0 ]; then + fail "ERROR: could not mount overlayFS" +fi +# create mountpoints inside the new root filesystem-overlay +mkdir /mnt/newroot/ro +mkdir /mnt/newroot/rw +# remove root mount from fstab (this is already a non-permanent modification) +grep -v "$rootPARTUUID" /mnt/lower/etc/fstab > /mnt/newroot/etc/fstab +echo "#the original root mount has been removed by overlayRoot.sh" >> /mnt/newroot/etc/fstab +echo "#this is only a temporary modification, the original fstab" >> /mnt/newroot/etc/fstab +echo "#stored on the disk can be found in /ro/etc/fstab" >> /mnt/newroot/etc/fstab +# change to the new overlay root +cd /mnt/newroot +pivot_root . mnt +exec chroot . sh -c "$(cat <