Skip to content

Instantly share code, notes, and snippets.

@mikemackintosh
Created November 6, 2015 23:13
Show Gist options
  • Save mikemackintosh/f745c7dd850737167c02 to your computer and use it in GitHub Desktop.
Save mikemackintosh/f745c7dd850737167c02 to your computer and use it in GitHub Desktop.
pibuilder.sh
#!/bin/bash
set -e
IMAGESIZE="990" # in Megabytes
USERNAME="bill"
PASSWORD="b0ard"
PACKAGES="wireless-tools xinit consolekit net-tools fonts-freefont-ttf ifplugd ifupdown hostname fontconfig-config fontconfig iputils-ping wpasupplicant curl binutils locales sudo openssh-server ntp usbmount patch less rsync sudo raspi-config matchbox chromium x11-xserver-utils xwit sqlite3 libnss3 vim"
PI_HOSTNAME=${PI_HOSTNAME-"dashboard${RANDOM:0:3}"}
# Print some configurations
echo "Final Image Size: ${IMAGESIZE}"
echo "Device Username: ${USERNAME}"
echo "Device Password: ${PASSWORD}"
echo "Device Hostname: ${PI_HOSTNAME}"
echo "Setting Access Point to: ${WIFI_AP}"
echo "Setting Access Point Password to: ${WIFI_PASSWORD}"
echo "Installing packages: ${PACKAGES}"
echo -e "\n\n\n"
# System defaults
MIRROR="http://mirror.umd.edu/raspbian/raspbian"
#MIRROR="http://archive.raspbian.org/raspbian"
CODENAME="wheezy"
BOOTSIZE="64M"
# Set environment
relative_path=`dirname $0`
# locate path of this script
absolute_path=`cd ${relative_path}; pwd`
# Set todays date
today=`date +%Y%m%d`
# Set variables to help
ROOTFS=$absolute_path/rootfs-${today}
BOOTFS=$absolute_path/bootfs-${today}
OUTIMAGE=$absolute_path/dashboard.img
# Build out dirs
mkdir -p $ROOTFS $BOOTFS
# Check for permissions
if [ ${EUID} -ne 0 ]; then
echo "this tool must be run as root"
exit 1
fi
# Catch errors and handle cleaning up the mess
trap cleanup 0 1 2 3 9 15
exec 2> ./errors.log
# Log helper
log() {
echo "$@"
}
# Log errors with this
error() {
echo "[!!] $@"
}
# Run commands wihtin the CHROOT
chroot_cmd() {
PATH=/usr/bin:/usr/sbin:/usr/local/bin:/sbin:$PATH LC_ALL=C LANGUAGE=C LANG=C chroot $ROOTFS "$@"
}
# Handle cleanup
cleanup(){
log "== Cleanup =="
cleanup_bootstrap
cat ./errors.log
error $@
rm -rf $BOOTFS $ROOTFS $OUTIMAGE
}
# Bootstrap the OS
bootstrap() {
# Get the raspbian base
log " - Installing base OS "
if [ -z $MIRROR ]; then
curl -sI http://mirror.umd.edu/raspbian/raspbian/|grep 200
if [ $? -eq 0 ]; then
MIRROR="http://archive.raspbian.org/raspbian"
else
MIRROR="http://mirror.umd.edu/raspbian/raspbian"
fi
fi
# Download and extract the base os
qemu-debootstrap --variant=minbase --include wget,curl,binutils --arch armhf wheezy $ROOTFS $MIRROR > /dev/null &
while kill -0 ${!} 2>/dev/null; do
echo -n "."
sleep 1
done
echo " Done!"
log " - Mounting chroot"
#mount binfmt_misc -t binfmt_misc /proc/sys/fs/binfmt_misc
mount -t proc proc $ROOTFS/proc
mount -t sysfs sysfs $ROOTFS/sys
mount -o bind /dev $ROOTFS/dev
cp /usr/bin/qemu-arm-static $ROOTFS/usr/bin/
#chroot_cmd /debootstrap/debootstrap --second-stage
manage_firmware
}
manage_firmware() {
# Get pi firmware
log " - Downloading Firmware "
wget https://github.com/raspberrypi/firmware/archive/master.zip --append-output ./errors.log &
while kill -0 ${!} 2>/dev/null; do
echo -n "."
sleep 1
done
echo " Done!"
sleep 2
log " - Extracting Firmware "
unzip -o master.zip > /dev/null&
while kill -0 ${!} 2>/dev/null; do
echo -n "."
sleep 1
done
echo " Done!"
log " - Copying Firmware "
# Copy over the firmware
cp -R firmware-master/boot/* $BOOTFS/
cp -R firmware-master/hardfp/opt/* $ROOTFS/opt/
cp -R firmware-master/modules $ROOTFS/lib/modules
}
# Unmount and get read to image
cleanup_bootstrap(){
rm $ROOTFS/usr/bin/qemu-*
umount --force $ROOTFS/proc
umount --force $ROOTFS/sys
umount --force $ROOTFS/dev
}
# Create the boot partition
create_boot(){
#[[ -d rootfs/ ]] && cp -rv rootfs/* $ROOTFS
log " - Copying Local Firmware"
cp -rv firmware/* $ROOTFS/boot/
cp -rv firmware/* $BOOTFS
# sh -c 'cat >/mnt/bootfs/config.txt<<EOF
#dtparam=i2c_arm=on
#dtparam=i2c_vc=on
#dtparam=act_led_trigger=heartbeat
#dtparam=pwr_led_trigger=mmc0
#arm_freq=800
#core_freq=250
#sdram_freq=400
#over_voltage=0
#gpu_mem=16
#disable_overscan=1
#framebuffer_width=1900
#framebuffer_height=1200
#framebuffer_depth=32
#framebuffer_ignore_alpha=1
#hdmi_pixel_encoding=1
#hdmi_group=2
#
#EOF
#'
#dwc_otg.lpm_enable=0 root=/dev/mmcblk0p2 rootfstype=ext4 rootwait
#sudo sh -c 'cat >/mnt/bootfs/cmdline.txt<<EOF
#dwc_otg.lpm_enable=0 console=ttyAMA0,115200 console=tty1 root=/dev/mmcblk0p2 rootfstype=ext4 elevator=deadline rootwait
#EOF
# '
}
# Create the user
create_user() {
log " - Creating User: ${USERNAME}"
log " - Creating PASSWORD: ${PASSWORD}"
chroot_cmd useradd $USERNAME -m -p `mkpasswd $PASSWORD` -s /bin/bash
chroot_cmd usermod -a -G adm,sudo,staff,kmem,plugdev $USERNAME
}
# Create the image
create_img() {
log " - Creating Blank Image: ${OUTIMAGE}"
dd if=/dev/zero of=$OUTIMAGE bs=1MB count=$IMAGESIZE
sudo losetup -f $OUTIMAGE
# Partition the device
log " - Partitioning"
sudo fdisk /dev/loop0 << EOF
n
p
1
+64M
t
c
n
p
2
w
EOF
# Remove the loopback device
sudo losetup -d /dev/loop0
kpartx -va $OUTIMAGE | sed -E 's/.*(loop[0-9])p.*/1/g' | head -1
# Format the devices
log " - Formatting"
mkfs.vfat /dev/mapper/loop0p1
mkfs.ext4 /dev/mapper/loop0p2
if [ $? -ne 0 ]; then
mkfs.ext4 /dev/mapper/loop0p2
fi
log " - Installing RootFS"
sudo mkdir -p /mnt/rootfs
sudo mount /dev/mapper/loop0p2 /mnt/rootfs
sudo rsync -a $ROOTFS/ /mnt/rootfs
sudo cp -a firmware-master/hardfp/opt/vc /mnt/rootfs/opt/
sudo umount /mnt/rootfs
log " - Installing BootFS"
sudo mkdir -p /mnt/bootfs
sudo mount /dev/mapper/loop0p1 /mnt/bootfs
sudo cp -R $BOOTFS/* /mnt/bootfs
sudo umount /mnt/bootfs
sudo kpartx -d $OUTIMAGE
log " - Copy complete image"
cp *.img /build/pkgs/
}
configure(){
log " - Update Root .bashrc LANG"
echo 'LC_ALL=C
LANGUAGE=C
LANG=C
' > $ROOTFS/root/.bashrc
# Set apt sources.list
log " - Configuring Kernel Conf"
echo "# Kernel image management overrides
# See kernel-img.conf(5) for details
do_symlinks = yes
do_bootloader = no
do_initrd = yes
link_in_boot = yes
" > $ROOTFS/etc/kernel-img.conf
# Set apt sources.list
log " - Configuring apt packages"
# Install wget if it's not installed
chroot_cmd apt-get update
#echo "deb http://archive.raspbian.org/raspbian wheezy main" >> $ROOTFS/etc/apt/sources.list
echo "deb http://www.mirrorservice.org/sites/archive.raspbian.org/raspbian wheezy main" >> $ROOTFS/etc/apt/sources.list
echo "deb http://archive.raspberrypi.org/debian/ wheezy main" >> $ROOTFS/etc/apt/sources.list
#chroot_cmd wget http://archive.raspbian.org/raspbian.public.key -O - | apt-key add -
chroot_cmd wget http://www.mirrorservice.org/sites/archive.raspbian.org/raspbian.public.key -O - | apt-key add -
chroot_cmd wget http://archive.raspberrypi.org/debian/raspberrypi.gpg.key -O - | apt-key add -
#chroot_cmd add-apt-repository -y universe
chroot_cmd apt-get update
chroot_cmd apt-get dist-upgrade --force-yes -y
chroot_cmd apt-get install -y --force-yes $PACKAGES
# Update raspberry pi
log " - Configuring raspberry-pi update"
chroot_cmd wget http://goo.gl/1BOfJ -O /usr/bin/rpi-update
chroot_cmd chmod +x /usr/bin/rpi-update
chroot_cmd ldconfig
chroot_cmd /usr/bin/rpi-update
# Configure cmdline.txt
#log " - Configuring cmdline.txt"
#echo "dwc_otg.lpm_enable=0 console=ttyAMA0,115200 kgdboc=ttyAMA0,115200 console=tty1 root=/dev/mmcblk0p2 rootfstype=ext4 rootwait" > $ROOTFS/boot/cmdline.txt
# Set fstab
log " - Configuring fstab "
echo "proc /proc proc defaults 0 0
/dev/mmcblk0p1 /boot vfat defaults 0 0
" > $ROOTFS/etc/fstab
# Set hostname
log " - Configuring Hostname"
echo $PI_HOSTNAME > $ROOTFS/etc/hostname
log " - Configuring Hostname DNS"
echo "127.0.0.1 ${PI_HOSTNAME}" >> $ROOTFS/etc/hosts
if [ -z $HOSTOVERIDE ]; then
log " - Configuring Hostname Override"
echo $HOSTOVERIDE >> $ROOTFS/etc/hosts
fi
# Set interfaces
log " - Configuring Interfaces"
echo "auto lo
iface lo inet loopback
auto eth0
allow-hotplug eth0
iface eth0 inet dhcp
auto wlan0
allow-hotplug wlan0
iface wlan0 inet dhcp
wpa-conf /etc/wpa_supplicant/wpa_supplicant.conf
iface default inet dhcp
# Include files from /etc/network/interfaces.d:
source-directory /etc/network/interfaces.d
" > $ROOTFS/etc/network/interfaces
# Set interfaces
log " - Configuring WPA Supplicant"
echo "
ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev
update_config=1
network={
ssid=\"${WIFI_AP}\"
psk=\"${WIFI_PASSWORD}\"
proto=RSN
key_mgmt=WPA-PSK
pairwise=CCMP
auth_alg=OPEN
}" > $ROOTFS/etc/wpa_supplicant/wpa_supplicant.conf
# Set interfaces
log " - Configuring rc.local"
cp skel/rc.local $ROOTFS/etc/rc.local
sed -i -e "s/USERNAME/$USERNAME/g" $ROOTFS/etc/rc.local
log " - Configuring X11"
sed -i -e "s/allowed_users=console/allowed_users=anybody/g" $ROOTFS/etc/X11/Xwrapper.config
# Set Serial
log " - Configuring Serial"
echo '# ttyAMA0 - getty
#
# This service maintains a getty on ttyAMA0 from the point the system is
# started until it is shut down again.
start on stopped rc RUNLEVEL=[2345] and (
not-container or
container CONTAINER=lxc or
container CONTAINER=lxc-libvirt)
stop on runlevel [!2345]
respawn
exec /sbin/getty -8 115200 ttyAMA0
' > $ROOTFS/etc/init/ttyAMA0.conf
# Set Modules
log " - Configuring Modules"
echo "vchiq
snd_bcm2835
" >> $ROOTFS/etc/modules
# Set usbmount
log " - Configuring usbmount"
sed -i -e 's/""/"-fstype=vfat,flush,gid=plugdev,dmask=0007,fmask=0117"/g' $ROOTFS/etc/usbmount/usbmount.conf
# Set cleanup
log " - Cleaning Up"
echo '#!/bin/bash
apt-get clean
rm -f /cleanup
' > $ROOTFS/cleanup
chmod +x $ROOTFS/cleanup
chroot_cmd /cleanup
}
log "## Starting Script ##"
log "== Beginning Bootstrap =="
bootstrap
log "== Creating Boot Image =="
create_boot
log "== Creating User =="
create_user
log "== Configuring OS =="
configure
log "== Preparing Image =="
cleanup_bootstrap
log "== Create the image =="
create_img
trap - EXIT
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment