2019-11-12 21:00:04 +01:00
#!/bin/sh
2019-11-02 14:41:03 +01:00
set -e
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# User config
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
: ${ ALPINE_BRANCH : = "3.10" }
: ${ ALPINE_MIRROR : = "http://dl-cdn.alpinelinux.org/alpine" }
2019-11-03 21:18:53 +01:00
: ${ DEFAULT_TIMEZONE : = "Etc/UTC" }
: ${ DEFAULT_HOSTNAME : = "alpine" }
2019-11-04 20:23:45 +01:00
: ${ DEFAULT_ROOT_PASSWORD : = "alpine" }
2019-11-03 21:18:53 +01:00
: ${ SIZE_BOOT : = "100M" }
2019-11-08 22:33:12 +01:00
: ${ SIZE_ROOT_FS : = "200M" }
: ${ SIZE_ROOT_PART : = "500M" }
2019-11-03 21:18:53 +01:00
: ${ SIZE_DATA : = "20M" }
2019-11-13 20:23:22 +01:00
: ${ IMG_NAME : = "sdcard" }
2019-11-02 14:41:03 +01:00
2019-11-17 10:58:55 +01:00
: ${ OUTPUT_PATH : = "/output" }
: ${ INPUT_PATH : = "/input" }
: ${ CUSTOM_IMAGE_SCRIPT : = "image.sh" }
2019-11-02 14:41:03 +01:00
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# static config
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
RES_PATH = /resources/
2019-11-08 22:33:12 +01:00
BASE_PACKAGES = "alpine-base tzdata parted ifupdown e2fsprogs-extra util-linux coreutils linux-rpi linux-rpi2"
2019-11-02 14:41:03 +01:00
WORK_PATH = "/work"
ROOTFS_PATH = " ${ WORK_PATH } /root_fs "
BOOTFS_PATH = " ${ WORK_PATH } /boot_fs "
DATAFS_PATH = " ${ WORK_PATH } /data_fs "
IMAGE_PATH = " ${ WORK_PATH } /img "
# ensure work directory is clean
rm -rf ${ WORK_PATH } /*
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# functions
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
chroot_exec( ) {
chroot " ${ ROOTFS_PATH } " " $@ " 1>& 2
}
make_image( ) {
[ -d /tmp/genimage ] && rm -rf /tmp/genimage
genimage --rootpath $1 \
--tmppath /tmp/genimage \
--inputpath ${ IMAGE_PATH } \
--outputpath ${ IMAGE_PATH } \
--config $2
}
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# create root FS
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
echo ">> Prepare root FS"
# update local repositories to destination ones to ensure the right packages where installed
cat >/etc/apk/repositories <<EOF
${ ALPINE_MIRROR } /v${ ALPINE_BRANCH } /main
${ ALPINE_MIRROR } /v${ ALPINE_BRANCH } /community
EOF
# copy apk keys to new root (required for initial apk add run)
mkdir -p ${ ROOTFS_PATH } /etc/apk/keys/
cp /usr/share/apk/keys/*.rsa.pub ${ ROOTFS_PATH } /etc/apk/keys/
# copy repositories to new root
cp /etc/apk/repositories ${ ROOTFS_PATH } /etc/apk/repositories
# initial package installation
apk --root ${ ROOTFS_PATH } --update-cache --initdb --arch armhf add $BASE_PACKAGES
# add google DNS to enable network access inside chroot
echo "nameserver 8.8.8.8" > ${ ROOTFS_PATH } /etc/resolv.conf
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
echo ">> Configure root FS"
# Set time zone
2019-11-03 21:18:53 +01:00
ln -fs /data/etc/timezone ${ ROOTFS_PATH } /etc/timezone
ln -fs /data/etc/localtime ${ ROOTFS_PATH } /etc/localtime
2019-11-02 14:41:03 +01:00
# Set host name
chroot_exec rc-update add hostname default
2019-11-03 21:18:53 +01:00
ln -fs /data/etc/hostname ${ ROOTFS_PATH } /etc/hostname
2019-11-02 14:41:03 +01:00
# enable local startup files (stored in /etc/local.d/)
chroot_exec rc-update add local default
cat >${ ROOTFS_PATH } /etc/conf.d/local <<EOF
rc_verbose = yes
EOF
# prepare network
chroot_exec rc-update add networking default
2019-11-29 19:53:17 +01:00
ln -fs /data/etc/network/interfaces ${ ROOTFS_PATH } /etc/network/interfaces
2019-11-02 14:41:03 +01:00
2019-11-03 19:17:48 +01:00
# run local before network -> local brings up the interface
2019-11-02 14:41:03 +01:00
sed -i '/^\tneed/ s/$/ local/' ${ ROOTFS_PATH } /etc/init.d/networking
# bring up eth0 on startup
cat >${ ROOTFS_PATH } /etc/local.d/11-up_eth0.start <<EOF
#!/bin/sh
ifconfig eth0 up
EOF
chmod +x ${ ROOTFS_PATH } /etc/local.d/11-up_eth0.start
# add script to resize data partition
cp ${ RES_PATH } /resizedata.sh ${ ROOTFS_PATH } /etc/local.d/90-resizedata.start
chmod +x ${ ROOTFS_PATH } /etc/local.d/90-resizedata.start
# mount data and boot partition (root is already mounted)
cat >${ ROOTFS_PATH } /etc/fstab <<EOF
2019-11-03 20:35:33 +01:00
none / ext4 defaults,ro 0 0
2019-11-02 23:51:56 +01:00
/dev/mmcblk0p1 /uboot vfat defaults,ro 0 2
/dev/mmcblk0p4 /data ext4 defaults 0 1
proc /proc proc defaults 0 0
sysfs /sys sysfs defaults 0 0
devpts /dev/pts devpts gid = 4,mode= 620 0 0
tmpfs /dev/shm tmpfs defaults 0 0
tmpfs /tmp tmpfs defaults 0 0
tmpfs /run tmpfs defaults 0 0
2019-11-03 19:17:48 +01:00
tmpfs /var/lock tmpfs defaults 0 0
2019-11-02 14:41:03 +01:00
EOF
2019-11-03 19:17:48 +01:00
# prepare mount points
mkdir -p ${ ROOTFS_PATH } /uboot
mkdir -p ${ ROOTFS_PATH } /data
mkdir -p ${ ROOTFS_PATH } /proc
mkdir -p ${ ROOTFS_PATH } /sys
mkdir -p ${ ROOTFS_PATH } /tmp
mkdir -p ${ ROOTFS_PATH } /run
mkdir -p ${ ROOTFS_PATH } /dev/pts
mkdir -p ${ ROOTFS_PATH } /dev/shm
mkdir -p ${ ROOTFS_PATH } /var/lock
2019-11-03 16:04:17 +01:00
2019-11-03 20:35:33 +01:00
# time
2019-11-08 22:33:12 +01:00
chroot_exec rc-update add ntpd default
2019-11-03 20:35:33 +01:00
2019-11-03 16:04:17 +01:00
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
2019-11-08 22:33:12 +01:00
# uboot tools
cp /uboot_tool ${ ROOTFS_PATH } /sbin/uboot_tool
2019-11-03 16:04:17 +01:00
# TODO REMOVE THIS
# mark system as booted (should be moved to application)
cat >${ ROOTFS_PATH } /etc/local.d/99-uboot.start <<EOF
#!/bin/sh
mount -o remount,rw /uboot
2019-11-08 22:33:12 +01:00
/sbin/uboot_tool reset_counter
2019-11-03 16:04:17 +01:00
sync
mount -o remount,ro /uboot
EOF
chmod +x ${ ROOTFS_PATH } /etc/local.d/99-uboot.start
# copy helper scripts
cp ${ RES_PATH } /scripts/* ${ ROOTFS_PATH } /sbin/
# TODO configurable
# dropbear
2019-11-02 14:41:03 +01:00
chroot_exec apk add dropbear
chroot_exec rc-update add dropbear
2019-11-03 20:35:33 +01:00
ln -s /data/etc/dropbear/ ${ ROOTFS_PATH } /etc/dropbear
2019-11-03 16:04:17 +01:00
mv ${ ROOTFS_PATH } /etc/conf.d/dropbear ${ ROOTFS_PATH } /etc/conf.d/dropbear_org
2019-11-03 20:35:33 +01:00
ln -s /data/etc/dropbear/dropbear.conf ${ ROOTFS_PATH } /etc/conf.d/dropbear
2019-11-02 14:41:03 +01:00
2019-11-03 19:17:48 +01:00
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
echo ">> Move persistent data to /data"
# prepare /data
cat >${ ROOTFS_PATH } /etc/local.d/20-data_prepare.start <<EOF
#!/bin/sh
2019-11-03 20:35:33 +01:00
mkdir -p /data/etc/
touch /data/etc/resolv.conf
2019-11-03 19:17:48 +01:00
2019-11-03 21:18:53 +01:00
# Set time zone
if [ ! -f /data/etc/timezone ] ; then
echo " ${ DEFAULT_TIMEZONE } " > /data/etc/timezone
ln -fs /usr/share/zoneinfo/${ DEFAULT_TIMEZONE } /data/etc/localtime
fi
2019-11-03 19:17:48 +01:00
2019-11-03 21:18:53 +01:00
# set host name
if [ ! -f /data/etc/hostname ] ; then
echo " ${ DEFAULT_HOSTNAME } " > /data/etc/hostname
fi
2019-11-04 20:23:45 +01:00
# root password
root_pw = \$ ( mkpasswd -m sha-512 -s " ${ DEFAULT_ROOT_PASSWORD } " )
echo "root:\${root_pw}:0:0:::::" > /data/etc/shadow
# interface
2019-11-29 19:53:17 +01:00
if [ ! -f /data/etc/network/interfaces ] ; then
cat > /data/etc/network/interfaces <<EOF2
2019-11-03 21:18:53 +01:00
auto lo
iface lo inet loopback
auto eth0
iface eth0 inet dhcp
EOF2
fi
# dropbear
2019-11-03 20:35:33 +01:00
mkdir -p /data/etc/dropbear/
if [ ! -f /data/etc/dropbear/dropbear.conf ] ; then
cp /etc/conf.d/dropbear_org /data/etc/dropbear/dropbear.conf
2019-11-03 19:17:48 +01:00
fi
2019-11-03 21:18:53 +01:00
mkdir -p /data/root/
2019-11-03 19:17:48 +01:00
EOF
chmod +x ${ ROOTFS_PATH } /etc/local.d/20-data_prepare.start
# link root dir
rmdir ${ ROOTFS_PATH } /root
ln -s /data/root ${ ROOTFS_PATH } /root
# resolv.conf & udhcpc
mkdir -p ${ ROOTFS_PATH } /etc/udhcpc
cat >${ ROOTFS_PATH } /etc/udhcpc/udhcpc.conf <<EOF
2019-11-03 20:35:33 +01:00
RESOLV_CONF = /data/etc/resolv.conf
2019-11-03 19:17:48 +01:00
EOF
2019-11-03 21:18:53 +01:00
ln -fs /data/etc/resolv.conf ${ ROOTFS_PATH } /etc/resolv.conf
2019-11-03 19:17:48 +01:00
2019-11-04 20:23:45 +01:00
# root password
ln -fs /data/etc/shadow ${ ROOTFS_PATH } /etc/shadow
2019-11-02 14:41:03 +01:00
2019-11-02 23:51:56 +01:00
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
echo ">> Prepare kernel for uboot"
# build uImage
2019-11-08 22:33:12 +01:00
mkimage -A arm -O linux -T kernel -C none -a 0x00008000 -e 0x00008000 -n "Linux kernel" -d ${ ROOTFS_PATH } /boot/vmlinuz-rpi ${ ROOTFS_PATH } /boot/uImage
mkimage -A arm -O linux -T kernel -C none -a 0x00008000 -e 0x00008000 -n "Linux kernel" -d ${ ROOTFS_PATH } /boot/vmlinuz-rpi2 ${ ROOTFS_PATH } /boot/uImage2
2019-11-02 23:51:56 +01:00
2019-11-02 14:41:03 +01:00
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# create boot FS
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
echo ">> Configure boot FS"
# download base firmware
mkdir -p ${ BOOTFS_PATH }
wget -P ${ BOOTFS_PATH } https://github.com/raspberrypi/firmware/raw/master/boot/bootcode.bin
wget -P ${ BOOTFS_PATH } https://github.com/raspberrypi/firmware/raw/master/boot/fixup.dat
wget -P ${ BOOTFS_PATH } https://github.com/raspberrypi/firmware/raw/master/boot/fixup_cd.dat
2019-11-02 23:51:56 +01:00
wget -P ${ BOOTFS_PATH } https://github.com/raspberrypi/firmware/raw/master/boot/fixup_db.dat
2019-11-02 14:41:03 +01:00
wget -P ${ BOOTFS_PATH } https://github.com/raspberrypi/firmware/raw/master/boot/fixup_x.dat
2019-11-02 23:51:56 +01:00
wget -P ${ BOOTFS_PATH } https://github.com/raspberrypi/firmware/raw/master/boot/fixup4.dat
wget -P ${ BOOTFS_PATH } https://github.com/raspberrypi/firmware/raw/master/boot/fixup4cd.dat
wget -P ${ BOOTFS_PATH } https://github.com/raspberrypi/firmware/raw/master/boot/fixup4db.dat
wget -P ${ BOOTFS_PATH } https://github.com/raspberrypi/firmware/raw/master/boot/fixup4x.dat
2019-11-02 14:41:03 +01:00
wget -P ${ BOOTFS_PATH } https://github.com/raspberrypi/firmware/raw/master/boot/start.elf
wget -P ${ BOOTFS_PATH } https://github.com/raspberrypi/firmware/raw/master/boot/start_cd.elf
2019-11-02 23:51:56 +01:00
wget -P ${ BOOTFS_PATH } https://github.com/raspberrypi/firmware/raw/master/boot/start_db.elf
2019-11-02 14:41:03 +01:00
wget -P ${ BOOTFS_PATH } https://github.com/raspberrypi/firmware/raw/master/boot/start_x.elf
2019-11-02 23:51:56 +01:00
wget -P ${ BOOTFS_PATH } https://github.com/raspberrypi/firmware/raw/master/boot/start4.elf
wget -P ${ BOOTFS_PATH } https://github.com/raspberrypi/firmware/raw/master/boot/start4cd.elf
wget -P ${ BOOTFS_PATH } https://github.com/raspberrypi/firmware/raw/master/boot/start4db.elf
wget -P ${ BOOTFS_PATH } https://github.com/raspberrypi/firmware/raw/master/boot/start4x.elf
2019-11-02 14:41:03 +01:00
2019-11-02 23:51:56 +01:00
# copy linux kernel and overlays to boot
2019-11-02 14:41:03 +01:00
cp ${ ROOTFS_PATH } /usr/lib/linux-*-rpi2/*.dtb ${ BOOTFS_PATH } /
cp -r ${ ROOTFS_PATH } /usr/lib/linux-*-rpi2/overlays ${ BOOTFS_PATH } /
2019-11-02 23:51:56 +01:00
# copy u-boot
cp /uboot/* ${ BOOTFS_PATH } /
# generate boot script
mkimage -A arm -T script -C none -n "Boot script" -d ${ RES_PATH } /boot.cmd ${ BOOTFS_PATH } /boot.scr
2019-11-02 14:41:03 +01:00
# write boot config
cat >${ BOOTFS_PATH } /config.txt <<EOF
disable_splash = 1
boot_delay = 0
gpu_mem = 256
gpu_mem_256 = 64
hdmi_drive = 1
hdmi_group = 2
hdmi_mode = 1
hdmi_mode = 87
hdmi_cvt 800 480 60 6 0 0 0
2019-11-02 23:51:56 +01:00
kernel = u-boot_rpi1.bin
[ pi0w]
kernel = u-boot_rpi0_w.bin
2019-11-02 14:41:03 +01:00
[ pi2]
2019-11-02 23:51:56 +01:00
kernel = u-boot_rpi2.bin
2019-11-02 14:41:03 +01:00
[ pi3]
2019-11-02 23:51:56 +01:00
kernel = u-boot_rpi3.bin
[ pi4]
kernel = u-boot_rpi4.bin
2019-11-02 14:41:03 +01:00
[ all]
2019-11-02 23:51:56 +01:00
enable_uart = 1
2019-11-02 14:41:03 +01:00
EOF
cat >${ BOOTFS_PATH } /cmdline.txt <<EOF
2019-11-03 19:17:48 +01:00
console = serial0,115200 console = tty1 root = /dev/mmcblk0p2 rootfstype = ext4 fsck.repair= yes ro rootwait quiet
2019-11-02 14:41:03 +01:00
EOF
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# create data FS
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
echo ">> Configure data FS"
mkdir -p ${ DATAFS_PATH }
2019-11-12 21:00:04 +01:00
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# Custom modification
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
2019-11-17 10:58:55 +01:00
if [ -f ${ INPUT_PATH } /${ CUSTOM_IMAGE_SCRIPT } ] ; then
. ${ INPUT_PATH } /${ CUSTOM_IMAGE_SCRIPT }
2019-11-12 21:00:04 +01:00
fi
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# Cleanup
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
rm -rf ${ ROOTFS_PATH } /var/cache/apk/*
rm -rf ${ ROOTFS_PATH } /boot/initramfs*
rm -rf ${ ROOTFS_PATH } /boot/System*
rm -rf ${ ROOTFS_PATH } /boot/config*
2019-11-02 14:41:03 +01:00
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# create image
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
echo ">> Create SD card image"
# boot partition
cat >${ WORK_PATH } /genimage_boot.cfg <<EOF
image boot.vfat {
vfat {
2019-11-02 23:51:56 +01:00
label = "boot"
2019-11-02 14:41:03 +01:00
}
2019-11-03 21:18:53 +01:00
size = ${ SIZE_BOOT }
2019-11-02 14:41:03 +01:00
}
EOF
make_image ${ BOOTFS_PATH } ${ WORK_PATH } /genimage_boot.cfg
# root partition
cat >${ WORK_PATH } /genimage_root.cfg <<EOF
image rootfs.ext4 {
ext4 {
2019-11-02 23:51:56 +01:00
label = "rootfs"
2019-11-02 14:41:03 +01:00
}
2019-11-03 21:18:53 +01:00
size = ${ SIZE_ROOT_FS }
2019-11-02 14:41:03 +01:00
}
EOF
make_image ${ ROOTFS_PATH } ${ WORK_PATH } /genimage_root.cfg
# data partition
cat >${ WORK_PATH } /genimage_data.cfg <<EOF
image datafs.ext4 {
ext4 {
2019-11-02 23:51:56 +01:00
label = "data"
2019-11-02 14:41:03 +01:00
}
2019-11-03 21:18:53 +01:00
size = ${ SIZE_DATA }
2019-11-02 14:41:03 +01:00
}
EOF
make_image ${ DATAFS_PATH } ${ WORK_PATH } /genimage_data.cfg
# sd card image
cat >${ WORK_PATH } /genimage_sdcard.cfg <<EOF
image sdcard.img {
hdimage {
}
partition boot {
partition-type = 0xC
bootable = "true"
image = "boot.vfat"
}
2019-11-02 23:51:56 +01:00
partition rootfs_a {
partition-type = 0x83
image = "rootfs.ext4"
2019-11-03 21:18:53 +01:00
size = ${ SIZE_ROOT_PART }
2019-11-02 23:51:56 +01:00
}
partition rootfs_b {
2019-11-02 14:41:03 +01:00
partition-type = 0x83
image = "rootfs.ext4"
2019-11-03 21:18:53 +01:00
size = ${ SIZE_ROOT_PART }
2019-11-02 14:41:03 +01:00
}
partition datafs {
partition-type = 0x83
image = "datafs.ext4"
}
}
EOF
make_image ${ IMAGE_PATH } ${ WORK_PATH } /genimage_sdcard.cfg
2019-11-03 16:04:17 +01:00
echo ">> Compress images"
2019-11-02 14:41:03 +01:00
# copy final image
2019-11-03 16:04:17 +01:00
gzip -c ${ IMAGE_PATH } /sdcard.img > ${ OUTPUT_PATH } /${ IMG_NAME } .img.gz
gzip -c ${ IMAGE_PATH } /rootfs.ext4 > ${ OUTPUT_PATH } /${ IMG_NAME } _update.img.gz
# create checksums
cd ${ OUTPUT_PATH } /
sha256sum ${ IMG_NAME } .img.gz > ${ IMG_NAME } .img.gz.sha256
sha256sum ${ IMG_NAME } _update.img.gz > ${ IMG_NAME } _update.img.gz.sha256