Skip to content

Instantly share code, notes, and snippets.

@dash17291
Created May 18, 2013 09:14
Show Gist options
  • Save dash17291/5603816 to your computer and use it in GitHub Desktop.
Save dash17291/5603816 to your computer and use it in GitHub Desktop.
#!/bin/sh
# Copyright (C) 2012 Michael Gorven <http://michael.gorven.za.net/>
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
set -ev
NAME="${1?Please specify output image name.}"
IMAGE_SIZE=1000
BOOT_SIZE=64
ALIGN_SECTORS=8192
ALIGN_FSBLOCKS="$(($ALIGN_SECTORS*512/4096))"
MIRROR="http://mirrordirector.raspbian.org/raspbian"
BASE_PACKAGES="openssh-server sudo ntp fake-hwclock raspi-copies-and-fills raspi-config"
XBMC_PACKAGES="nfs-client xbmc udisks avahi-daemon"
XBMC_USER="xbmc"
XBMC_HOSTNAME="xbmc"
export LANG=en_US.UTF-8
export LC_ALL=en_US.UTF-8
check_host() {
if [ $(id -u) != 0 ]; then
echo "This script must be run as root."
exit 2
fi
for BINARY in wget gpg qemu-debootstrap rsync kpartx sfdisk mkfs.ext4 mkfs.vfat tune2fs tar sha256sum; do
if ! which $BINARY > /dev/null; then
echo "Unable to find $BINARY binary, please install it"
exit 1
fi
done
}
bootstrap() {
if [ ! "$BUILDROOT" ]; then
echo "BUILDROOT is empty, aborting."
exit 1
fi
KEYRING="${TMPDIR:-/tmp}/raspbian.gpg"
if [ ! -s "$KEYRING" ]; then
wget -O- http://archive.raspbian.org/raspbian.public.key | gpg --no-default-keyring --keyring "$KEYRING" --import
fi
qemu-debootstrap --arch=armhf --keyring="$KEYRING" wheezy "$BUILDROOT" "$MIRROR"
}
configure_base() {
if [ ! "$BUILDROOT" ]; then
echo "BUILDROOT is empty, aborting."
exit 1
fi
cat > "$BUILDROOT/usr/sbin/policy-rc.d" <<-EOF
#!/bin/sh
exit 101
EOF
chmod +x "$BUILDROOT/usr/sbin/policy-rc.d"
cat > "$BUILDROOT/etc/apt/sources.list" <<-EOF
deb $MIRROR wheezy main contrib non-free rpi
EOF
cat > "$BUILDROOT/etc/apt/sources.list.d/mene.list" <<-EOF
deb http://archive.mene.za.net/raspbian wheezy contrib
EOF
cat > "$BUILDROOT/etc/apt/sources.list.d/raspi.list" <<-EOF
deb http://archive.raspberrypi.org/debian/ wheezy main
EOF
if [ "$http_proxy" ]; then
cat > "$BUILDROOT/etc/apt/apt.conf.d/30proxy" <<-EOF
Acquire::http::proxy "$http_proxy";
EOF
fi
wget -O- http://archive.raspberrypi.org/debian/raspberrypi.gpg.key | chroot "$BUILDROOT" apt-key add -
wget -O- http://archive.mene.za.net/key.asc | chroot "$BUILDROOT" apt-key add -
export DEBIAN_FRONTEND=noninteractive
chroot "$BUILDROOT" apt-get --yes dist-upgrade
chroot "$BUILDROOT" apt-get --yes update
chroot "$BUILDROOT" apt-get --yes install raspberrypi-bootloader libraspberrypi-bin $BASE_PACKAGES
cat > "$BUILDROOT/boot/config.txt" <<-EOF
disable_overscan=1
EOF
cat > "$BUILDROOT/boot/cmdline.txt" <<-EOF
dwc_otg.lpm_enable=0 dwc_otg.fiq_fix_enable=1 console=ttyAMA0,115200 kgdboc=ttyAMA0,115200 console=tty1 root=/dev/mmcblk0p2 rootfstype=ext4 elevator=noop rootwait
EOF
chroot "$BUILDROOT" adduser --disabled-password --gecos 'Raspberry Pi User,,,,' pi
echo 'pi:raspberry' | chroot "$BUILDROOT" chpasswd
chroot "$BUILDROOT" adduser pi sudo
cat >> "$BUILDROOT/etc/network/interfaces" <<-EOF
auto eth0
iface eth0 inet dhcp
EOF
echo "$XBMC_HOSTNAME" > "$BUILDROOT/etc/hostname"
cat >> "$BUILDROOT/etc/hosts" <<-EOF
127.0.0.2 $XBMC_HOSTNAME
EOF
cat > "$BUILDROOT/etc/fstab" <<-EOF
LABEL=boot /boot vfat defaults 0 2
LABEL=root / ext4 errors=remount-ro,noatime,nodiratime 0 1
EOF
cat >> "$BUILDROOT/etc/modules" <<-EOF
vchiq
snd_bcm2835
EOF
cat > "$BUILDROOT/etc/sysctl.d/raspi.conf" <<-EOF
vm.min_free_kbytes = 8192
EOF
cat > "$BUILDROOT/etc/init.d/regenerate_ssh_host_keys" <<-"EOF"
#!/bin/sh
### BEGIN INIT INFO
# Provides: regenerate_ssh_host_keys
# Required-Start:
# Required-Stop:
# Default-Start: 2
# Default-Stop:
# Short-Description: Regenerate ssh host keys
# Description:
### END INIT INFO
. /lib/lsb/init-functions
set -e
case "$1" in
start)
log_daemon_msg "Regenerating ssh host keys (in background)"
nohup sh -c "yes | ssh-keygen -q -N '' -t dsa -f /etc/ssh/ssh_host_dsa_key && \
yes | ssh-keygen -q -N '' -t rsa -f /etc/ssh/ssh_host_rsa_key && \
yes | ssh-keygen -q -N '' -t ecdsa -f /etc/ssh/ssh_host_ecdsa_key && \
update-rc.d ssh enable && sync && \
rm /etc/init.d/regenerate_ssh_host_keys && \
update-rc.d regenerate_ssh_host_keys remove && \
printf '\nfinished\n' && invoke-rc.d ssh start" > /var/log/regen_ssh_keys.log 2>&1 &
log_end_msg $?
;;
*)
echo "Usage: $0 start" >&2
exit 3
;;
esac
EOF
chmod +x "$BUILDROOT/etc/init.d/regenerate_ssh_host_keys"
chroot "$BUILDROOT" update-rc.d ssh disable
chroot "$BUILDROOT" update-rc.d regenerate_ssh_host_keys defaults
}
configure_xbmc() {
cp "$BUILDROOT/boot/arm128_start.elf" "$BUILDROOT/boot/start.elf"
chroot "$BUILDROOT" apt-get --yes install $XBMC_PACKAGES
chroot "$BUILDROOT" addgroup --system input
chroot "$BUILDROOT" adduser --disabled-login --shell /bin/false --gecos 'XBMC Media Centre,,,' "$XBMC_USER"
chroot "$BUILDROOT" adduser "$XBMC_USER" video
chroot "$BUILDROOT" adduser "$XBMC_USER" audio
chroot "$BUILDROOT" adduser "$XBMC_USER" plugdev
chroot "$BUILDROOT" adduser "$XBMC_USER" input
cat > "$BUILDROOT/etc/default/xbmc" <<-EOF
ENABLED=1
USER="$XBMC_USER"
NICE=-5
EOF
cat > "$BUILDROOT/etc/udev/rules.d/99-input.rules" <<-EOF
SUBSYSTEM=="input", GROUP="input", MODE="0660"
EOF
cat > "$BUILDROOT/var/lib/polkit-1/localauthority/50-local.d/50-xbmc.pkla" <<-EOF
[Actions for $XBMC_USER user]
Identity=unix-user:$XBMC_USER
Action=Action=org.freedesktop.upower.*;org.freedesktop.consolekit.system.*;org.freedesktop.udisks.*
ResultActive=yes
ResultAny=yes
ResultInactive=no
EOF
chown -R 1001:1001 "$BUILDROOT/home/$XBMC_USER"
}
cleanup() {
chroot "$BUILDROOT" apt-get --yes clean
find "$BUILDROOT/var/lib/apt/lists/" -type f -delete
rm -f "$BUILDROOT/etc/apt/apt.conf.d/30proxy" "$BUILDROOT/usr/sbin/policy-rc.d"
}
mkimage() {
IMAGE="$NAME.img"
TAR="$NAME.tar.xz"
dd if=/dev/zero of="$IMAGE" bs=1MB count=0 seek="$IMAGE_SIZE"
BOOT_SECTORS="$(($BOOT_SIZE*2048/$ALIGN_SECTORS*$ALIGN_SECTORS))"
cat | sfdisk --quiet --unit S --force "$IMAGE" <<-EOF
$ALIGN_SECTORS,$(($BOOT_SECTORS)),c,*
$(($ALIGN_SECTORS+$BOOT_SECTORS)),,L
EOF
LOOP="$(basename $(losetup -f))"
kpartx -a "$IMAGE"
BOOT="/dev/mapper/${LOOP}p1"
ROOT="/dev/mapper/${LOOP}p2"
mkfs.vfat -F 32 -n boot "$BOOT"
mkfs.ext4 -b 4096 -E stride=$ALIGN_FSBLOCKS,stripe-width=$ALIGN_FSBLOCKS -m 1 -L root "$ROOT"
tune2fs -i 0 -c 0 "$ROOT"
MNT="$(mktemp -d --tmpdir raspbian.XXXXXX)"
mount "$ROOT" "$MNT"
mkdir "$MNT/boot"
mount "$BOOT" "$MNT/boot"
rsync --archive --devices --specials --hard-links --acls --xattrs --sparse --verbose "$BUILDROOT" "$MNT"
umount "$MNT/boot"
umount "$MNT"
kpartx -d "$IMAGE"
tar -cSJvf "$TAR" "$IMAGE"
sha256sum "$TAR" > "$TAR.sha256"
}
BUILDROOT="$(mktemp -d $PWD/raspbian.XXXXXX)/root/"
check_host
bootstrap
configure_base
configure_xbmc
cleanup
mkimage
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment