Skip to content

Instantly share code, notes, and snippets.

@diederikdehaas
Created July 19, 2014 17:22
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save diederikdehaas/3b6d6a3d6bed3d4df763 to your computer and use it in GitHub Desktop.
Save diederikdehaas/3b6d6a3d6bed3d4df763 to your computer and use it in GitHub Desktop.
scripts/etc/init.d/rcS
#!/bin/busybox sh
LOGFILE=/tmp/raspbian-ua-netinst.log
# default options, can be overriden in installer-config.txt
preset=server
packages=
mirror=http://mirrordirector.raspbian.org/raspbian/
release=wheezy
hostname=pi
domainname=
rootpw=raspbian
cdebootstrap_cmdline=
bootsize=+50M
rootsize=
timeserver=time.nist.gov
ip_addr=dhcp
ip_netmask=0.0.0.0
ip_broadcast=0.0.0.0
ip_gateway=0.0.0.0
ip_nameservers=
online_config=
usbroot=
cmdline="dwc_otg.lpm_enable=0 console=ttyAMA0,115200 kgdboc=ttyAMA0,115200 console=tty1 elevator=deadline"
rootfstype=ext4
# these shouldn't really be changed unless auto-detection fails
bootdev=/dev/mmcblk0
bootpartition=/dev/mmcblk0p1
rootdev=/dev/mmcblk0
rootpartition=
fail()
{
echo
echo "Oh noes, something went wrong!"
echo "You have 10 seconds to hit ENTER to get a shell..."
# copy logfile to /boot/ partition to preserve it.
cp $LOGFILE /bootfs/raspbian-ua-netinst-`date +%Y%m%dT%H%M%S`.log
read -t 10 || reboot && exit
sh
}
sanitize_inputfile()
{
if [ -z "$1" ]
then
echo "No input file specified!"
else
inputfile=$1
# convert line endings to unix
dos2unix $inputfile
fi
}
mkdir -p /proc
mkdir -p /sys
mkdir -p /boot
mkdir -p /usr/bin
mkdir -p /usr/sbin
mkdir -p /var/run
mkdir -p /rootfs/boot
mkdir -p /bootfs
mkdir -p /tmp/
/bin/busybox --install
export PATH=/bin:/sbin:/usr/bin
mount -t proc none /proc
mount -t sysfs none /sys
echo /sbin/mdev > /proc/sys/kernel/hotplug
mdev -s
klogd -c 1
# redirect stdout and stderr also to logfile
# http://stackoverflow.com/questions/3173131/redirect-copy-of-stdout-to-log-file-from-within-bash-script-itself/6635197#6635197
mkfifo ${LOGFILE}.pipe
tee < ${LOGFILE}.pipe $LOGFILE &
exec &> ${LOGFILE}.pipe
rm ${LOGFILE}.pipe
echo ""
echo "================================================="
echo "raspbian-ua-netinst"
echo "================================================="
echo "Revision __VERSION__"
echo "Built on __DATE__"
echo "================================================="
echo "https://github.com/debian-pi/raspbian-ua-netinst/"
echo "================================================="
echo -n "Copying boot files... "
# copy boot data to safety
mount $bootpartition /boot || fail
cp /boot/bootcode.bin \
/boot/fixup_cd.dat \
/boot/fixup.dat \
/boot/fixup_x.dat \
/boot/installer.cpio \
/boot/kernel_install.img \
/boot/start_cd.elf \
/boot/start.elf \
/boot/start_x.elf /bootfs/ || fail
if [ -f /boot/installer-config.txt ]; then
cp /boot/installer-config.txt /bootfs/installer-config.txt || fail
fi
if [ -f /boot/post-install.txt ]; then
cp /boot/post-install.txt /bootfs/post-install.txt || fail
fi
# if installation aborts it will restart
cp /boot/config.txt /bootfs/config.txt || fail
umount /boot || fail
echo "OK"
if [ -e /bootfs/installer-config.txt ]; then
echo "================================================="
echo "=== Start executing installer-config.txt. ==="
sanitize_inputfile /bootfs/installer-config.txt
source /bootfs/installer-config.txt
echo "=== Finished executing installer-config.txt. ==="
echo "================================================="
fi
case "$rootfstype" in
"btrfs")
kernel_module=true
rootfs_mkfs_options=${rootfs_mkfs_options:-'-f'}
rootfs_install_mount_options=${rootfs_install_mount_options:-'noatime'}
rootfs_mount_options=${rootfs_mount_options:-'noatime'}
;;
"ext4")
kernel_module=true
rootfs_mkfs_options=${rootfs_mkfs_options:-''}
rootfs_install_mount_options=${rootfs_install_mount_options:-'noatime,data=writeback,nobarrier,noinit_itable'}
rootfs_mount_options=${rootfs_mount_options:-'errors=remount-ro,noatime'}
;;
"f2fs")
kernel_module=true
rootfs_mkfs_options=${rootfs_mkfs_options:-''}
rootfs_install_mount_options=${rootfs_install_mount_options:-'noatime'}
rootfs_mount_options=${rootfs_mount_options:-'noatime'}
;;
esac
echo
echo "Network configuration:"
echo " ip_addr = $ip_addr"
if [ "$ip_addr" != "dhcp" ]; then
echo " ip_netmask = $ip_netmask"
echo " ip_broadcast = $ip_broadcast"
echo " ip_gateway = $ip_gateway"
echo " ip_nameservers = $ip_nameservers"
fi
echo " online_config = $online_config"
echo
echo -n "Waiting for eth0... "
for i in `seq 1 10`; do
ifconfig eth0 &>/dev/null
if [ $? -eq 0 ]; then
break
fi
if [ $i -eq 10 ]; then
echo "FAILED"
fail
fi
sleep 1
echo -n "$i.. "
done
if [ "$ip_addr" = "dhcp" ]; then
echo -n "Configuring eth0 with DHCP... "
udhcpc -i eth0 &>/dev/null
if [ $? -eq 0 ]; then
ifconfig eth0 | fgrep addr: | awk '{print $2}' | cut -d: -f2
else
echo "FAILED"
fail
fi
else
echo -n "Configuring eth0 with static ip $ip_addr... "
ifconfig eth0 up inet $ip_addr netmask $ip_netmask broadcast $ip_broadcast || fail
route add default gw $ip_gateway || fail
echo -n > /etc/resolv.conf
for i in $ip_nameservers; do
echo "nameserver $i" >> /etc/resolv.conf
done
echo "OK"
fi
if [ "$online_config" != "" ]; then
echo -n "Downloading online config from $online_config... "
wget -q -O /online-config.txt $online_config &>/dev/null || fail
echo "OK"
echo "================================================="
echo "=== Start executing online-config.txt. ==="
sanitize_inputfile /online-config.txt
source /online-config.txt
echo "=== Finished executing online-config.txt. ==="
echo "================================================="
fi
# configure different kinds of presets
if [ "$cdebootstrap_cmdline" = "" ]; then
# minimal
cdebootstrap_cmdline="--flavour=minimal --include=kmod,fake-hwclock,ifupdown,net-tools,ntp,openssh-server$dhcp_packages"
# add dhcp client if using dhcp
if [ "$ip_addr" = "dhcp" ]; then
cdebootstrap_cmdline="$cdebootstrap_cmdline,isc-dhcp-client"
fi
# add latest kernel if rootfstype requires a module.
# Changed it so it is always installed.
# Firmware can't be installed just yet, we'll do so at the end
if [ "$kernel_module" = true ] ; then
cdebootstrap_cmdline="$cdebootstrap_cmdline,linux-image-rpi-rpfv"
fi
case $preset in
minimal)
;;
base)
cdebootstrap_cmdline="--flavour=minimal"
;;
*)
cdebootstrap_cmdline="$cdebootstrap_cmdline,vim-tiny,iputils-ping,wget,ca-certificates,rsyslog,cron,dialog,locales,less,man-db"
preset=server
;;
esac
# add extra packages
if [ "$packages" != "" ]; then
if [ "$preset" = "base" ]; then
cdebootstrap_cmdline="$cdebootstrap_cmdline --include=$packages"
else
cdebootstrap_cmdline="$cdebootstrap_cmdline,$packages"
fi
fi
else
preset=none
fi
if [ "$usbroot" != "" ]; then
rootdev=/dev/sda
echo -n "Loading USB modules... "
modprobe sd_mod &> /dev/null || fail
modprobe usb-storage &> /dev/null || fail
echo "OK"
fi
if [ "$rootpartition" = "" ]; then
if [ "$rootdev" = "/dev/sda" ]; then
rootpartition=/dev/sda1
else
rootpartition=/dev/mmcblk0p2
fi
fi
echo
echo "Installer configuration:"
echo " preset = $preset"
echo " packages = $packages"
echo " mirror = $mirror"
echo " release = $release"
echo " hostname = $hostname"
echo " domainname = $domainname"
echo " rootpw = $rootpw"
echo " cdebootstrap_cmdline = $cdebootstrap_cmdline"
echo " bootsize = $bootsize"
echo " rootsize = $rootsize"
echo " timeserver = $timeserver"
echo " cmdline = $cmdline"
echo " usbroot = $usbroot"
echo " rootdev = $rootdev"
echo " rootpartition = $rootpartition"
echo " rootfstype = $rootfstype"
echo " rootfs_mkfs_options = $rootfs_mkfs_options"
echo " rootfs_install_mount_options = $rootfs_install_mount_options"
echo " rootfs_mount_options = $rootfs_mount_options"
echo
date_set=false
#if [ "$timeserver" != "" ]; then
# echo -n "Configuring the clock using rdate... "
# rdate $timeserver &>/dev/null
# if [ $? -eq 0 ]; then
# date
# date_set=true
# else
# echo "failed (not fatal)"
# fi
#fi
if [ "$date_set" = "false" ] ; then
# time server addresses taken from http://tf.nist.gov/tf-cgi/servers.cgi
timeservers=$timeserver
timeservers="$timeservers time.nist.gov nist1.symmetricom.com"
timeservers="$timeservers nist-time-server.eoni.com utcnist.colorado.edu"
timeservers="$timeservers nist1-pa.ustiming.org nist.expertsmi.com"
timeservers="$timeservers nist1-macon.macon.ga.us wolfnisttime.com"
timeservers="$timeservers nist.time.nosc.us nist.netservicesgroup.com"
timeservers="$timeservers nisttime.carsoncity.k12.mi.us nist1-lnk.binary.net"
timeservers="$timeservers ntp-nist.ldsbc.edu utcnist2.colorado.edu"
timeservers="$timeservers nist1-ny2.ustiming.org wwv.nist.gov"
for ts in $timeservers
do
rdate $ts &>/dev/null
if [ $? -eq 0 ]; then
echo -n "Time set using timeserver '$ts' to... "
date
date_set=true
break
else
echo "Failed to set time using timeserver '$ts'."
fi
done
fi
if [ "$date_set" = "false" ] ; then
echo "FAILED to set the date, so things are likely to fail now ..."
fi
echo -n "Waiting for $rootdev... "
for i in `seq 1 10`; do
if [ "`fdisk -l $rootdev 2>&1 | fgrep Disk`" != "" ]; then
echo "OK"
break
fi
if [ $i -eq 10 ]; then
echo "FAILED"
fail
fi
sleep 1
echo -n "$i.. "
done
if [ "$rootdev" = "$bootdev" ]; then
echo -n "Applying new partition table... "
dd if=/dev/zero of=$bootdev bs=512 count=1 &>/dev/null
fdisk $bootdev &>/dev/null <<EOF
n
p
1
$bootsize
t
b
n
p
2
$rootsize
w
EOF
echo "OK"
else
echo -n "Applying new partition table for $bootdev... "
dd if=/dev/zero of=$bootdev bs=512 count=1 &>/dev/null
fdisk $bootdev &>/dev/null <<EOF
n
p
1
$bootsize
t
b
w
EOF
echo "OK"
echo -n "Applying new partition table for $rootdev... "
dd if=/dev/zero of=$rootdev bs=512 count=1 &>/dev/null
fdisk $rootdev &>/dev/null <<EOF
n
p
1
$rootsize
w
EOF
echo "OK"
fi
echo -n "Initializing /boot as vfat... "
mkfs.vfat $bootpartition &>/dev/null || fail
echo "OK"
if [ "$kernel_module" = true ] ; then
if [ "$rootfstype" != "ext4" ] ; then
echo -n "Loading $rootfstype module... "
modprobe $rootfstype &> /dev/null || fail
echo "OK"
fi
fi
echo -n "Initializing / as $rootfstype... "
mkfs.$rootfstype $rootfs_mkfs_options $rootpartition &>/dev/null || fail
echo "OK"
echo -n "Mounting new filesystems... "
mount $rootpartition /rootfs -o $rootfs_install_mount_options || fail
mkdir /rootfs/boot || fail
mount $bootpartition /rootfs/boot || fail
echo "OK"
echo -n "Copying /boot files in... "
cp /bootfs/* /rootfs/boot || fail
sync
echo "OK"
if [ "$kernel_module" = true ] ; then
if [ "$rootfstype" != "ext4" ] ; then
mkdir -p /rootfs/etc/initramfs-tools
echo $rootfstype >> /rootfs/etc/initramfs-tools/modules
fi
fi
echo "Starting install process..."
cdebootstrap-static --arch=armhf $cdebootstrap_cmdline $release /rootfs $mirror --keyring=/usr/share/keyrings/raspbian-archive-keyring.gpg || fail
# allow root login
echo "Configuring installed system:"
echo -n " Setting root password... "
echo -n root:$rootpw | chroot /rootfs /usr/sbin/chpasswd || fail
echo "OK"
# default mounts
echo -n " Configuring /etc/fstab... "
echo "$bootpartition /boot vfat defaults 0 2" > /rootfs/etc/fstab || fail
if [ "$rootfstype" = "f2fs" ]; then
echo "$rootpartition / $rootfstype $rootfs_mount_options 0 0" >> /rootfs/etc/fstab || fail
elif [ "$rootfstype" = "btrfs" ]; then
echo "$rootpartition / $rootfstype $rootfs_mount_options 0 0" >> /rootfs/etc/fstab || fail
else
echo "$rootpartition / $rootfstype $rootfs_mount_options 0 1" >> /rootfs/etc/fstab || fail
fi
echo "OK"
# use ram tmpfs by default
echo -n " Configuring tmpfs to use RAM... "
echo "RAMTMP=yes" >> /rootfs/etc/default/tmpfs
echo "OK"
# default hostname
echo -n " Configuring hostname... "
echo -n $hostname > /rootfs/etc/hostname || fail
echo "127.0.0.1 localhost" > /rootfs/etc/hosts || fail
if [ "$domainname" = "" ]; then
echo "127.0.1.1 $hostname" >> /rootfs/etc/hosts || fail
else
echo "127.0.1.1 $hostname.$domainname $hostname" >> /rootfs/etc/hosts || fail
fi
echo "OK"
# networking
echo -n " Configuring network settings... "
echo "auto lo" > /rootfs/etc/network/interfaces || fail
echo "iface lo inet loopback" >> /rootfs/etc/network/interfaces || fail
echo "" >> /rootfs/etc/network/interfaces || fail
# eth0 config
echo "auto eth0" >> /rootfs/etc/network/interfaces || fail
if [ "$ip_addr" = "dhcp" ]; then
echo "iface eth0 inet dhcp" >> /rootfs/etc/network/interfaces || fail
else
echo "iface eth0 inet static" >> /rootfs/etc/network/interfaces || fail
echo " address $ip_addr" >> /rootfs/etc/network/interfaces || fail
echo " netmask $ip_netmask" >> /rootfs/etc/network/interfaces || fail
echo " broadcast $ip_broadcast" >> /rootfs/etc/network/interfaces || fail
echo " gateway $ip_gateway" >> /rootfs/etc/network/interfaces || fail
cp /etc/resolv.conf /rootfs/etc/ || fail
fi
echo "OK"
# openssh-server in jessie doesn't allow root to login using password anymore
# this hack does allow it (until a proper solution is implemented)
if [ "$release" = "jessie" ] ; then
echo -n " Allowing root to login with password... "
sed -i 's/PermitRootLogin without-password/PermitRootLogin yes/' /rootfs/etc/ssh/sshd_config || fail
echo "OK"
fi
echo ""
# there is no hw clock on rpi
echo "HWCLOCKACCESS=no" >> /rootfs/etc/default/hwclock || fail
# remove cdebootstrap-helper-rc.d which prevents rc.d scripts from running
echo -n "Removing cdebootstrap-helper-rc.d... "
chroot /rootfs /usr/bin/dpkg -r cdebootstrap-helper-rc.d &>/dev/null || fail
echo "OK"
# add firmware to default apt sources
echo -n "Configuring apt... "
echo "deb http://mirrordirector.raspbian.org/raspbian $release main firmware" > /rootfs/etc/apt/sources.list
echo "deb http://archive.raspberrypi.org/debian wheezy main" >> /rootfs/etc/apt/sources.list
cat /usr/share/keyrings/raspberrypi.gpg.key | chroot /rootfs /usr/bin/apt-key add - &>/dev/null
echo "OK"
echo -n "Updating package lists... "
chroot /rootfs /usr/bin/apt-get update &>/dev/null
echo "OK"
# firmware package can't be installed during cdebootstrap fase, so do so now
if [ "$kernel_module" = true ] ; then
echo -n "Installing bootloader package (=firmware)... "
chroot /rootfs /usr/bin/apt-get -y install raspberrypi-bootloader-nokernel &>/dev/null
if [ $? -eq 0 ]; then
echo "OK"
else
echo "FAILED !"
fi
fi
# add reasonable default modules, works only after kernel is properly installed
echo "snd-bcm2835" >> /rootfs/etc/modules
echo "Configuring bootloader to start the installed system..."
mv /rootfs/boot/config.txt /rootfs/boot/config-reinstall.txt
# find kernel/initramfs version
KERNEL_VERSION=$(sed -n -e '/^Package: linux-image-rpi-rpfv$/,/Package: /{s/^Depends: .*linux-image-\(.*-rpi\).*$/\1/p}' /rootfs/var/lib/dpkg/status)
echo "Kernel version: '${KERNEL_VERSION}'"
if [ -f /rootfs/vmlinuz ] ; then
# use latest kernel with initramfs in first boot
echo -n "Copying new kernel to installed system... "
cp /rootfs/vmlinuz /rootfs/boot/kernel.img
echo "OK"
echo -n "Specify new initramfs in config.txt... "
echo "initramfs initrd.img-${KERNEL_VERSION}" > /rootfs/boot/config.txt
echo "OK"
else
echo -n "Copying installer kernel to installed system... "
# use install kernel in first boot
cp /rootfs/boot/kernel_install.img /rootfs/boot/kernel.img || fail
echo "OK"
fi
# default cmdline.txt
echo -n "Creating default cmdline.txt... "
echo "$cmdline root=$rootpartition rootfstype=$rootfstype rootwait" > /rootfs/boot/cmdline.txt
echo "OK"
# run post install script if exists
if [ -e /bootfs/post-install.txt ]; then
echo "================================================="
echo "=== Start executing post-install.txt. ==="
sanitize_inputfile /bootfs/post-install.txt
source /bootfs/post-install.txt
echo "=== Finished executing post-install.txt. ==="
echo "================================================="
fi
# save current time if fake-hwclock
echo "Saving current time for fake-hwclock..."
sync # synchronize before saving time to make it "more accurate"
date +"%Y-%m-%d %H:%M:%S" > /rootfs/etc/fake-hwclock.data
echo -n "Unmounting filesystems... "
# copy logfile to standard log directory
cp $LOGFILE /rootfs/var/log/raspbian-ua-netinst.log
umount /rootfs/boot
umount /rootfs
echo "OK"
echo -n "Finished! Rebooting to installed system in 5 seconds..."
for i in `seq 5 -1 1`; do
sleep 1
echo -n "$i.. "
done
echo " rebooting now"
reboot
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment