stratux/image/spindle/common

447 wiersze
12 KiB
Bash
Executable File

#!/bin/sh
# Part of spindle http://asbradbury.org/projects/spindle
#
# See LICENSE file for copyright and license details
set -e
. ./config
run_qemu() {
rm fifo.out fifo.in || true
mkfifo fifo.out fifo.in
qemu-system-arm -M versatilepb -cpu arm1136-r2 -m 256 -display none -no-reboot \
-kernel zImage -hda qemu_rootfs.sqf -drive file=$1,index=1,media=disk,cache=unsafe \
-drive file=wheezy_apt_cache.$IMGFORMAT,index=2,media=disk,cache=unsafe \
-append "root=/dev/sda rw init=/sbin/init.sh panic=1 PATH=/bin:/sbin console=ttyAMA0 HOST=armv6l"\
-net nic,model=rtl8139 -net user -redir tcp:22000::22 -daemonize -serial pipe:fifo \
-pidfile qemu.pid
sleep 10
}
ssh_in_to_qemu() {
ssh -i qemu_arm_key -p 22000 -lroot localhost "$@"
}
scp_in_to_qemu() {
scp -i qemu_arm_key -P 22000 "$1" root@localhost:"$2"
}
scp_r_from_qemu() {
scp -r -i qemu_arm_key -P 22000 root@localhost:"$1" "$2"
}
onvm_chroot() {
ssh_in_to_qemu chroot /mnt "$@"
}
shutdown_qemu() {
ssh_in_to_qemu "sync && umount -a" || true
echo "exit" > fifo.in
sleep 5
if [ -e qemu.pid ]; then
QEMU_PID=$(cat qemu.pid)
while [ -n "$QEMU_PID" ]; do
set +e
kill -0 $QEMU_PID 2>/dev/null
if [ $? -eq 0 ]; then
printf "Qemu pid %s not finished yet. Waiting\n" "$QEMU_PID"
sleep 1
else
QEMU_PID=""
fi
set -e
done
fi
rm fifo.in
rm fifo.out
# sleep 15
}
attach_image_to_nbd() {
# use -v as we seem to have problems otherwise...
sudo qemu-nbd --nocache -v -c $2 $1 &
sleep 5
}
detach_image_from_nbd() {
sudo qemu-nbd -d $1
}
inspect_image() {
cd work
qemu-img create -f $IMGFORMAT -b ../$1 temp.$IMGFORMAT
# Sigh http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=390433
trap '[ -p fifo.in ] && shutdown_qemu' EXIT
trap '[ -p fifo.in ] && shutdown_qemu; trap - INT; kill -INT $$' INT
run_qemu temp.$IMGFORMAT
ssh_in_to_qemu # -t chroot /mnt bash -l
shutdown_qemu
cd $OLDPWD
}
branch_image() {
qemu-img create -f $IMGFORMAT -b $1 $2
}
write_image() {
attach_image_to_nbd $1 /dev/nbd0 &&
sudo dd if=/dev/nbd0 of=$2 bs=4M &&
detach_image_from_nbd /dev/nbd0
}
convert_image() {
qemu-img convert -f $IMGFORMAT -O raw $1 $2
}
export_image_for_release() {
cd work
qemu-img create -f $IMGFORMAT -b ../$1 temp.$IMGFORMAT
run_qemu temp.$IMGFORMAT
# Change mirror in sources.list to our preferred one. This will go horribly
# wrong if there is more than one entry in sources.list
onvm_chroot sh -l -ex <<\EOF
if grep armhf /etc/rpi-issue; then
sed -i /etc/apt/sources.list -e "s|^deb [^ ]*|deb http://mirrordirector.raspbian.org/raspbian/|"
else
sed -i /etc/apt/sources.list -e "s|^deb [^ ]*|deb http://http.debian.net/debian|"
fi
cp /usr/share/doc/raspi-config/sample_profile_d.sh /etc/profile.d/raspi-config.sh
apt-get update
# Default to a known-good nameserver
printf "nameserver 8.8.8.8\n" > /etc/resolv.conf
/etc/init.d/fake-hwclock stop # save current time
#rm /usr/bin/raspi-config
#cd /usr/bin
#wget https://raw.github.com/asb/raspi-config/master/raspi-config
#chmod +x raspi-config
cat <<EOF1 > /etc/apt/sources.list.d/raspi.list
deb http://archive.raspberrypi.org/debian/ wheezy main
# Uncomment line below then 'apt-get update' to enable 'apt-get source'
#deb-src http://archive.raspberrypi.org/debian/ wheezy main
EOF1
apt-get update
EOF
shutdown_qemu
attach_image_to_nbd temp.$IMGFORMAT /dev/nbd0
sudo zerofree -v /dev/nbd0p2
mkdir -p rootfs boot
sudo mount $BOOT_DEV boot
sudo mount $ROOT_DEV rootfs
sudo cp rootfs/etc/rpi-issue boot/issue.txt
sudo wget http://asbradbury.org/tmp/raspi/oracle_license.txt -O boot/LICENSE.oracle
[ -n "$RASPBIAN" ] && sudo mv rootfs/etc/ld.so.preload.disable rootfs/etc/ld.so.preload
if [ -n "$NOOBS" ]; then
mkdir -p ../noobs
sudo tar -C boot -cJf ../noobs/boot.tar.xz --preserve .
sudo tar -C rootfs -cJf ../noobs/root.tar.xz --preserve .
cat <<\EOF > ../noobs/partition_setup.sh
#!/bin/sh
set -ex
if [ -z "$part1" ] || [ -z "$part2" ]; then
printf "Error: missing environment variable part1 or part2\n" 1>&2
exit 1
fi
mkdir -p /tmp/1 /tmp/2
mount "$part1" /tmp/1
mount "$part2" /tmp/2
sed /tmp/1/cmdline.txt -i -e "s|root=/dev/[^ ]*|root=${part2}|"
sed /tmp/2/etc/fstab -i -e "s|^.* / |${part2} / |"
sed /tmp/2/etc/fstab -i -e "s|^.* /boot |${part1} /boot |"
umount /tmp/1
umount /tmp/2
EOF
cat <<\EOF > ../noobs/partitions.json
{
"partitions": [
{
"label": "boot",
"filesystem_type": "FAT",
"partition_size_nominal": 60,
"want_maximised": false,
"uncompressed_tarball_size": 19
},
{
"label": "root",
"filesystem_type": "ext4",
"partition_size_nominal": 2500,
"want_maximised": true,
"mkfs_options": "-O ^huge_file",
"uncompressed_tarball_size": 2280
}
]
}
EOF
cat <<\EOF > ../noobs/flavours.json
{
"flavours": [
{
"name": "Raspbian - Boot to Scratch",
"description": "A version of Raspbian that boots straight into Scratch"
},
{
"name": "Raspbian",
"description": "A Debian wheezy port, optimised for the Raspberry Pi"
}
]
}
EOF
cat <<\EOF > ../noobs/os.json
{
"name": "Raspbian",
"version": "wheezy",
"release_date": "2015-02-16",
"kernel": "3.18",
"description": "A community-created port of Debian wheezy, optimised for the Raspberry Pi"
}
EOF
cat <<\EOF > ../noobs/release_notes.txt
2015-02-16:
* Newer firmware with various fixes
* New Sonic Pi release
* Pi2 compatible RPi.GPIO
* Updated Wolfram Mathematica
2015-01-31:
* Support for Pi2
* Newer firmware
* New Sonic Pi release
* Updated Scratch
* New Wolfram Mathematica release
* Updated Epiphany
2014-12-24:
* Fix regression with omission of python-pygame
2014-12-22:
* New firmware with variosu fixes and improvements
* New UI configuration for lxde
* Various package updates
* python3-pygame preinstalled
* 'nuscratch', scratch running on the Cog StackVM
* Misc other changes
2014-09-09:
* New firmware with various fixes and improvements
* Minecraft Pi pre-installed
* Sonic Pi upgraded to 2.0
* Include Epiphany browser work from Collabora
* Switch to Java 8 from Java 7
* Updated Mathematica
* Misc minor configuration changes
2014-06-20:
* New firmware with various fixes, and kernel bugfix
2014-06-02:
* Many, many firmware updates with major USB improvements
* pyserial installed by default
* picamera installed by default
2014-01-07:
* Firmware updated
* Some space saved on the root filesystem
2013-12-20:
* Firmware updated, includes V4L2 fixes
* Update omxplayer
2013-12-18:
* Firmware updated and now using kernel 3.10. Many, many improvements
* fbturbo XOrg driver is now included and enabled by default. Thanks to
ssvb https://github.com/ssvb/xf86-video-fbturbo
* Update Scratch image with further bug fixes
* Include Wolfram Mathematica
* Update to PyPy 2.2
* Update omxplayer
* Include v4l-utils for use with experimental V4L2 Raspberry Pi camera driver
* Update squeak-vm to fix issues with loading JPEGs
2013-09-25:
* Update Scratch image for further performance improvements
* Include Oracle JDK
* At least a 4GiB SD card is now required (see above)
* Include PyPy 2.1
* Include base piface packages
* Update raspi-config to include bugfix for inheriting language settings
from NOOBS
2013-09-10:
* Updated to current top of tree firmware
* Update squeak-vm, including fastblit optimised for the Raspbery Pi
* Include Sonic Pi and a fixed jackd2 package
* Support boot to Scratch
* Inherit keyboard and language settings from NOOBS
EOF
wget http://asbradbury.org/tmp/raspi/marketing.tar -O ../noobs/marketing.tar
fi
sleep 10
sudo umount $BOOT_DEV
sudo umount $ROOT_DEV
detach_image_from_nbd /dev/nbd0
convert_image temp.$IMGFORMAT ../$2
}
disable_starting_services() {
ssh_in_to_qemu chroot /mnt sh -ex - <<EOF
export PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
printf '#!/bin/sh\nexit 101\n' > /usr/sbin/policy-rc.d
chmod 755 /usr/sbin/policy-rc.d
EOF
}
allow_starting_services() {
ssh_in_to_qemu chroot /mnt sh -ex - <<EOF
rm /usr/sbin/policy-rc.d
EOF
}
save_space_using_hardlink() {
onvm_chroot sh -l -e - <<\EOF
hardlink -t /usr/share/doc
EOF
}
mount_apt_cache() {
ssh_in_to_qemu sh -e - <<EOF
mount -o noatime /dev/sdc /mnt/var/cache/apt
EOF
}
download_if_necessary() {
[ -f $(basename "$1") ] || wget "$1"
}
get_git_hash() {
git log --pretty=format:'%h' -n 1
}
update_issue() {
GIT_HASH=$(get_git_hash) &&
CUR_DATE=$(date "+%Y-%m-%d")
onvm_chroot sh -l -e <<EOF
printf "Raspberry Pi reference $CUR_DATE ($TGT_ARCH)\nGenerated using spindle, http://asbradbury.org/projects/spindle/, $GIT_HASH, $CURIMG\n" > /etc/rpi-issue
EOF
}
# Create a list of all installed packages, all manually installed packages and
# the debconf selections
fingerprint_debian() {
FNGPRNT_DIR="$CURIMG.fingerprint" &&
onvm_chroot sh -l -e <<EOF &&
mkdir -p "/tmp/$FNGPRNT_DIR"
cd "/tmp/$FNGPRNT_DIR"
dpkg --get-selections > dpkg_selections
dpkg -l > dpkg_l
apt-mark showauto > apt-mark_showauto
debconf-get-selections > debconf_selections
EOF
scp_r_from_qemu "/mnt/tmp/$FNGPRNT_DIR" . &&
cd "$FNGPRNT_DIR" &&
grep "[[:space:]]install$" dpkg_selections | cut -f1 | sort apt-mark_showauto - | uniq -u > manually_installed_packages &&
cd "$OLDPWD"
}
finish_image() {
chmod -w $CURIMG &&
mkdir -p ../$OUTDIR &&
mv -f $CURIMG ../$OUTDIR &&
if [ -d "$CURIMG.fingerprint" ]; then
rm -rf "../$OUTDIR/$CURIMG.fingerprint" &&
mv "$CURIMG.fingerprint" ../$OUTDIR
fi &&
FINISHED_SUCCESSFULLY=1 &&
printf "Completed script successfully\n"
}
# Usage: ask_yn default prompt [printf_args...]
# Read a Yes / No user response. If $ASK_YN_USE_DEFAULT is set, assume the
# default. Return of 0 indicates a yes, and non-zero is no.
ask_yn() {
OPT="y/n"
case "$1" in
y*|Y*) OPT="Y/n"; RET=0;;
n*|N*) OPT="y/N"; RET=1;;
*) die "Programmer error: invalid argument to ask_yn"
esac
shift
if [ "$ASK_YN_USE_DEFAULT" ]; then
return $RET
else
PROMPT=$1
shift
printf "$PROMPT [$OPT]: " "$@" && read YN
case "$YN" in
y*|Y*) return 0;;
n*|N*) return 1;;
"") return $RET
esac
fi
}
# Usage: read_val var default prompt [printf_args...]
read_val() {
RV_VAR=$1
RV_DEFAULT=$2
RV_PROMPT=$3
shift 3
printf "$RV_PROMPT [$RV_DEFAULT]: " "$@" && read RV_VAL
[ -z "$RV_VAL" ] && RV_VAL=$RV_DEFAULT
eval "$RV_VAR=\$RV_VAL"
}
die() {
FMTSTR=$1
shift
printf "Died: $FMTSTR\n" "$@" >&2
exit 1
}
# do a task
# Inspects $DOTASK_MODE to see if the user:
# e*: wants to have the command echoed
# q*: wants to be questioned as to whether to run, skip or quit.
# If the task fails it asks the user whether to quit (default: y), or if
# $DOTASK_QUIT_ON_FAILURE is set then quit without asking the user.
dotask() {
case "$DOTASK_MODE" in
e*) printf "Run: '%s'\n" "$*"; false;;
q*) printf "Run: '%s' [Y/n/q] ? " "$*" && read SHOULD_RUN;
case "$SHOULD_RUN" in
n*|N*|s*|S*) printf "Skip '%s'\n" "$*";;
q*|Q*) die "Exit at user request";;
*) false;;
esac;;
*) false;;
esac || "$@" || { RC=$?
[ -z "$DOTASK_QUIT_ON_FAILURE" ] && printf "'%s' failed (returned $RC) - Quit? [Y/n] : " "$*" && read YN
case "$YN" in n*|N*) true ;; *) die "Failed while performing task: %s" "$*";; esac;
}
}
FINISHED_SUCCESSFULLY=0
CLEANED_UP=0
WAS_TRAPPED=0
# Sigh http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=390433
trap 'WAS_TRAPPED=1; universal_cleanup' EXIT
trap 'WAS_TRAPPED=1; universal_cleanup; trap - INT; kill -INT $$' INT
universal_cleanup() {
set +e
if [ $CLEANED_UP -ne 1 ]; then
printf "Initiating cleanup\n"
trap - INT
trap - EXIT
[ -p fifo.in ] && shutdown_qemu
[ -b "$BOOT_DEV" ] && sudo umount $BOOT_DEV
[ -b "$ROOT_DEV" ] && sudo umount $ROOT_DEV
[ -b "$NBD_DEV" ] && sudo umount $NBD_DEV
[ -b "$NBD_DEV" ] && detach_image_from_nbd $NBD_DEV
fi
if [ $WAS_TRAPPED -eq 1 ] && [ $FINISHED_SUCCESSFULLY -eq 0 ]; then
printf "Did not complete script successfully\n"
fi
set -e
}