systemd: prepare the /etc overlay prior to launching systemd

systemd performs a bunch of critical tasks prior to loading any unit
files from disk, or running generators. Examples of this include the
/etc/machine-id setup (which we worked around by a bind mount some time
ago), or reading )and setting) the hostname configuration.

Rather than playing the whack-a-mole game over and over again by adding
just enough scripts to re-kick a given daemon/subsystem once a
particular /etc file becomes available, this change moves /etc setup
(which includes the overlay and the /cfg filesystem as well) into an
"initramfs" (without actually using a separate initramfs, of course).

Thanks to Mantas Mikulėnas (grawity on IRC) for suggesting this.

Change-Id: I9ec4d7f1243929ea498142d435ae6689c53b6097
diff --git a/board/czechlight/clearfog/boot.scr.txt b/board/czechlight/clearfog/boot.scr.txt
index 5a12f39..bf45913 100644
--- a/board/czechlight/clearfog/boot.scr.txt
+++ b/board/czechlight/clearfog/boot.scr.txt
@@ -7,8 +7,7 @@
 i2c mw 0x60 0x0a 0x80
 i2c mw 0x60 0x0b 0x80
 i2c mw 0x60 0x0c 0x80
-setenv bootargs root=/dev/mmcblk0p${rauc_part} rauc.slot=${rauc_slot} czechlight=${czechlight} systemd.machine_id=${machineid} panic=10 oops=panic
-setenv bootargs ${bootargs} spidev.bufsiz=65535
+setenv bootargs root=/dev/mmcblk0p${rauc_part} init=/sbin/init-czechlight.sh rauc.slot=${rauc_slot} czechlight=${czechlight} systemd.machine_id=${machineid} panic=10 oops=panic spidev.bufsiz=65535
 if test -n ${czechlight} && load mmc 0:${rauc_part} ${fdt_addr_r} /boot/${czechlight}-clearfog.dtb; then
   echo "DTS: ${czechlight}-clearfog"
 else
diff --git a/package/czechlight-cfg-fs/cfg-restore-etc.service b/package/czechlight-cfg-fs/cfg-restore-etc.service
deleted file mode 100644
index d735d99..0000000
--- a/package/czechlight-cfg-fs/cfg-restore-etc.service
+++ /dev/null
@@ -1,12 +0,0 @@
-[Unit]
-Description=Restore /etc from the Persistent config
-DefaultDependencies=no
-Conflicts=umount.target
-Before=local-fs.target umount.target
-After=cfg.mount etc-overlay.service
-Requires=cfg.mount etc-overlay.service
-ConditionDirectoryNotEmpty=/cfg/etc
-
-[Service]
-Type=oneshot
-ExecStart=/bin/sh -c 'cp -a /cfg/etc/* /etc/'
diff --git a/package/czechlight-cfg-fs/czechlight-cfg-fs.mk b/package/czechlight-cfg-fs/czechlight-cfg-fs.mk
index a94e2e0..98ca80c 100644
--- a/package/czechlight-cfg-fs/czechlight-cfg-fs.mk
+++ b/package/czechlight-cfg-fs/czechlight-cfg-fs.mk
@@ -13,23 +13,10 @@
 endif
 
 define CZECHLIGHT_CFG_FS_INSTALL_TARGET_CMDS
-	$(INSTALL) -D -m 0644 \
-		$(BR2_EXTERNAL_CZECHLIGHT_PATH)/package/czechlight-cfg-fs/etc-fstab \
-		$(TARGET_DIR)/etc/fstab
-	mkdir -p $(TARGET_DIR)/cfg
-	mkdir -p $(TARGET_DIR)/usr/lib/systemd/system/local-fs.target.wants/
-	$(INSTALL) -D -m 0644 \
-		$(BR2_EXTERNAL_CZECHLIGHT_PATH)/package/czechlight-cfg-fs/etc-overlay.service \
-		$(TARGET_DIR)/usr/lib/systemd/system/etc-overlay.service
-	ln -sf ../etc-overlay.service $(TARGET_DIR)/usr/lib/systemd/system/local-fs.target.wants/
-	mkdir -p $(TARGET_DIR)/usr/lib/systemd/system-generators/
 	$(INSTALL) -D -m 0755 \
-		$(BR2_EXTERNAL_CZECHLIGHT_PATH)/package/czechlight-cfg-fs/czechlight-cfg-mount-generator \
-		$(TARGET_DIR)/usr/lib/systemd/system-generators/
-	$(INSTALL) -D -m 0644 \
-		$(BR2_EXTERNAL_CZECHLIGHT_PATH)/package/czechlight-cfg-fs/cfg-restore-etc.service \
-		$(TARGET_DIR)/usr/lib/systemd/system/cfg-restore-etc.service
-	ln -sf ../cfg-restore-etc.service $(TARGET_DIR)/usr/lib/systemd/system/local-fs.target.wants/
+		$(BR2_EXTERNAL_CZECHLIGHT_PATH)/package/czechlight-cfg-fs/init-czechlight.sh \
+		$(TARGET_DIR)/sbin/init-czechlight.sh
+	mkdir -p $(TARGET_DIR)/cfg
 	$(ifeq ($(CZECHLIGHT_CFG_FS_PERSIST_SYSREPO),y))
 		mkdir -p $(TARGET_DIR)/usr/lib/systemd/system/multi-user.target.wants/
 		$(INSTALL) -D -m 0644 \
diff --git a/package/czechlight-cfg-fs/czechlight-cfg-mount-generator b/package/czechlight-cfg-fs/czechlight-cfg-mount-generator
deleted file mode 100755
index 3197722..0000000
--- a/package/czechlight-cfg-fs/czechlight-cfg-mount-generator
+++ /dev/null
@@ -1,47 +0,0 @@
-#!/bin/sh
-
-set -e
-
-if grep -q rauc.slot=A /proc/cmdline; then
-  RAUC_SLOT_NO=0
-  RAUC_SLOT_NAME=A
-elif grep -q rauc.slot=B /proc/cmdline; then
-  RAUC_SLOT_NO=1
-  RAUC_SLOT_NAME=B
-else
-  echo "Cannot determine active RAUC rootfs slot"
-  exit 1
-fi
-
-# sed magic:
-# 1) use `sed -n` so that we only print what's explicitly printed
-# 2) anchor the search between the "[slot.cfg.$RAUC_SLOT_NO]" and any other section
-# 3) look for a line beginning with "device="
-# 4) take stuff which is behind the "="
-# 5) print it
-DEVICE=$(sed -n "/\[slot\.cfg\.${RAUC_SLOT_NO}\]/,/\[.*\]/{/^device=/s/\(.*\)=\(.*\)/\\2/p}" /etc/rauc/system.conf)
-
-if [ x$DEVICE -eq x ]; then
-  echo "Cannot determine device for /cfg from RAUC"
-  exit 1
-fi
-
-if [ ! -b $DEVICE ]; then
-  echo "Device ${DEVICE} is not a block device"
-  exit 1
-fi
-
-cat > $1/cfg.mount <<EOF
-[Unit]
-Description=Persistent config (slot ${RAUC_SLOT_NAME})
-DefaultDependencies=no
-Conflicts=umount.target
-Before=local-fs.target umount.target
-After=swap.target
-
-[Mount]
-What=${DEVICE}
-Where=/cfg
-Type=auto
-Options=relatime,nosuid,nodev
-EOF
diff --git a/package/czechlight-cfg-fs/etc-fstab b/package/czechlight-cfg-fs/etc-fstab
deleted file mode 100644
index 7517ca9..0000000
--- a/package/czechlight-cfg-fs/etc-fstab
+++ /dev/null
@@ -1,3 +0,0 @@
-/dev/root / auto ro,errors=panic 0 1
-tmpfs /var tmpfs mode=1777 0 0
-tmpfs /.ov tmpfs mode=0700 0 0
diff --git a/package/czechlight-cfg-fs/etc-overlay.service b/package/czechlight-cfg-fs/etc-overlay.service
deleted file mode 100644
index 3af78fa..0000000
--- a/package/czechlight-cfg-fs/etc-overlay.service
+++ /dev/null
@@ -1,18 +0,0 @@
-[Unit]
-Description=Overlay filesystem over /etc
-DefaultDependencies=no
-Conflicts=umount.target
-Before=local-fs.target umount.target systemd-networkd.service
-After=swap.target \x2eov.mount
-
-[Service]
-Type=oneshot
-ExecStart=/bin/mkdir /.ov/etc-u
-ExecStart=/bin/mkdir /.ov/etc-w
-# Moving /etc/machine-id. Cannot --move, we have to --bind.
-ExecStart=/bin/touch /.ov/etc-machine-id
-ExecStart=/bin/mount --bind /etc/machine-id /.ov/etc-machine-id
-ExecStart=/bin/umount /etc/machine-id
-ExecStart=/bin/mount overlay -t overlay /etc -olowerdir=/etc,upperdir=/.ov/etc-u,workdir=/.ov/etc-w
-ExecStart=/bin/mount --bind /.ov/etc-machine-id /etc/machine-id
-ExecStart=/bin/umount /.ov/etc-machine-id
diff --git a/package/czechlight-cfg-fs/init-czechlight.sh b/package/czechlight-cfg-fs/init-czechlight.sh
new file mode 100644
index 0000000..a550906
--- /dev/null
+++ b/package/czechlight-cfg-fs/init-czechlight.sh
@@ -0,0 +1,49 @@
+#!/bin/sh
+
+echo "Preparing /etc overlay"
+/bin/mount -t tmpfs tmpfs /.ov -o mode=0700
+/bin/mkdir /.ov/etc-u
+/bin/mkdir /.ov/etc-w
+/bin/mount overlay -t overlay /etc -olowerdir=/etc,upperdir=/.ov/etc-u,workdir=/.ov/etc-w
+
+/bin/mount -t proc proc /proc -o rw,nosuid,nodev,noexec,relatime
+if grep -q rauc.slot=A /proc/cmdline; then
+  RAUC_SLOT_NO=0
+  RAUC_SLOT_NAME=A
+elif grep -q rauc.slot=B /proc/cmdline; then
+  RAUC_SLOT_NO=1
+  RAUC_SLOT_NAME=B
+else
+  echo "Cannot determine active RAUC rootfs slot"
+  #exit 1
+fi
+/bin/umount /proc
+echo "RAUC: active slot ${RAUC_SLOT_NAME}"
+
+# sed magic:
+# 1) use `sed -n` so that we only print what's explicitly printed
+# 2) anchor the search between the "[slot.cfg.$RAUC_SLOT_NO]" and any other section
+# 3) look for a line beginning with "device="
+# 4) take stuff which is behind the "="
+# 5) print it
+DEVICE=$(sed -n "/\[slot\.cfg\.${RAUC_SLOT_NO}\]/,/\[.*\]/{/^device=/s/\(.*\)=\(.*\)/\\2/p}" /etc/rauc/system.conf)
+
+if [ x$DEVICE = x ]; then
+  echo "Cannot determine device for /cfg from RAUC"
+  #exit 1
+fi
+
+if [ ! -b $DEVICE ]; then
+  echo "Device ${DEVICE} is not a block device"
+  #exit 1
+fi
+
+echo "Mounting /cfg"
+/bin/mount ${DEVICE} /cfg -t auto -o relatime,nosuid,nodev
+
+if [ -d /cfg/etc ]; then
+  echo "Restoring /etc from /cfg"
+  /bin/cp -a /cfg/etc/* /etc/
+fi
+
+exec /sbin/init