kopia lustrzana https://github.com/cyoung/stratux
447 wiersze
12 KiB
Bash
Executable File
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 -nographic -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
|
|
}
|