penguin/monok8s

k8s image for Mono Gateway Dev Kit

commit ec8ceb169059252ffc4782fe547630dc697a146ab49935fc492da4ca0c8627d2

author斟酌 鵬兄 <tgckpg@gmail.com>
date2026-03-24T15:58:33Z
subjectinitramfs to also use merge-rootfs
commit ec8ceb169059252ffc4782fe547630dc697a146ab49935fc492da4ca0c8627d2
Author: 斟酌 鵬兄 <tgckpg@gmail.com>
Date:   2026-03-24T15:58:33Z

    initramfs to also use merge-rootfs
---
 alpine/install-packages.sh                    |  3 --
 alpine/merge-rootfs.sh                        | 73 ++++++++++++++++++++++-----
 alpine/rootfs-extra/etc/init.d/crio           |  2 +-
 build.env                                     |  3 ++
 docker/initramfs.Dockerfile                   | 17 +++----
 initramfs/build-rootfs.sh                     |  9 ++++
 initramfs/rootfs-extra/bin/flash-emmc.sh.tmpl | 67 ++++++++++++++++++++++++
 initramfs/{ => rootfs-extra}/init             |  2 +
 makefile                                      | 17 +++++++
 9 files changed, 167 insertions(+), 26 deletions(-)

diff --git a/alpine/install-packages.sh b/alpine/install-packages.sh
index d87444e..9038ab3 100755
--- a/alpine/install-packages.sh
+++ b/alpine/install-packages.sh
@@ -28,9 +28,6 @@ mv /etc/cni/net.d/10-crio-bridge.conflist.disabled \
 sed -i "s/default_runtime = \"crun\"/\0\ncgroup_manager = \"cgroupfs\"/g" /etc/crio/crio.conf.d/10-crio.conf
 grep cgroup_manager /etc/crio/crio.conf.d/10-crio.conf || exit 1
 
-chmod +x /opt/scripts/*
-chmod +x /etc/init.d/*
-
 mkdir -p /var/run/crio
 mkdir -p /var/lib/containers/storage
 mkdir -p /var/lib/cni
diff --git a/alpine/merge-rootfs.sh b/alpine/merge-rootfs.sh
index 4dd0aae..3f992f1 100755
--- a/alpine/merge-rootfs.sh
+++ b/alpine/merge-rootfs.sh
@@ -75,21 +75,60 @@ check_template_vars() {
     [[ "$missing" -eq 0 ]]
 }
 
+preserve_exec_bit() {
+    local old="$1"
+    local new="$2"
+
+    if [[ -e "$old" && -x "$old" ]]; then
+        chmod +x "$new"
+    fi
+}
+
+get_envsubst_vars() {
+    local rel="$1"
+
+    case "$rel" in
+        bin/flash-emmc.sh.tmpl)
+            echo '${BUILD_TAG}'
+            ;;
+        *)
+            echo ''
+            ;;
+    esac
+}
+
 render_template() {
     local src="$1"
     local out="$2"
+    local allowed="${3:-}"
 
     mkdir -p "$(dirname "$out")"
-    check_template_vars "$src"
-    envsubst < "$src" > "$out"
+
+    if [[ -n "$allowed" ]]; then
+        envsubst "$allowed" < "$src" > "$out"
+    else
+		check_template_vars "$src"
+        envsubst < "$src" > "$out"
+    fi
+    if [[ -x "$src" ]]; then
+        chmod +x "$out"
+    fi
 }
 
 replace_file() {
     local src="$1"
     local dst="$2"
 
+    local had_exec=0
+    [[ -e "$dst" && -x "$dst" ]] && had_exec=1
+
     mkdir -p "$(dirname "$dst")"
     cp -a "$src" "$dst"
+
+    if [[ "$had_exec" -eq 1 ]]; then
+        chmod +x "$dst"
+    fi
+
     echo "Replaced file: $dst"
 }
 
@@ -101,11 +140,19 @@ merge_or_copy_file() {
     mkdir -p "$(dirname "$dst")"
 
     # scripts: replace
-    if [[ "$rel" == opt/scripts/* ]]; then
-        cp -a "$src" "$dst"
-        echo "Replaced script: $dst"
-        return
-    fi
+	if [[ "$rel" == opt/scripts/* ]]; then
+		local had_exec=0
+		[[ -e "$dst" && -x "$dst" ]] && had_exec=1
+
+		cp -a "$src" "$dst"
+
+		if [[ "$had_exec" -eq 1 ]]; then
+			chmod +x "$dst"
+		fi
+
+		echo "Replaced script: $dst"
+		return
+	fi
 
     # /etc: merge missing lines
     if [[ "$rel" == etc/* ]]; then
@@ -177,12 +224,12 @@ find "$SRC_ROOT" -mindepth 1 | while IFS= read -r src_path; do
         mode="override"
         rel_for_target="${rel_for_target%.override}"
 
-    elif [[ "$rel_for_target" == *.tmpl ]]; then
-        rel_for_target="${rel_for_target%.tmpl}"
-        rendered="$TMP_DIR/$rel_for_target"
-        render_template "$src_path" "$rendered"
-        src_for_merge="$rendered"
-    fi
+	elif [[ "$rel_for_target" == *.tmpl ]]; then
+		rel_for_target="${rel_for_target%.tmpl}"
+		rendered="$TMP_DIR/$rel_for_target"
+		render_template "$src_path" "$rendered" "$(get_envsubst_vars "$rel_path")"
+		src_for_merge="$rendered"
+	fi
 
     dst_path="$DST_ROOT/$rel_for_target"
 
diff --git a/alpine/rootfs-extra/etc/init.d/crio b/alpine/rootfs-extra/etc/init.d/crio
index c0c49d3..901a50d 100755
--- a/alpine/rootfs-extra/etc/init.d/crio
+++ b/alpine/rootfs-extra/etc/init.d/crio
@@ -15,7 +15,7 @@ start_stop_daemon_args=" \
 	--stderr /var/log/${RC_SVCNAME}/${RC_SVCNAME}.log"
 
 depend() {
-	need net
+	need loopback localmount
 }
 
 checkconfig() {
diff --git a/build.env b/build.env
index ead4d6d..9f5bbb5 100644
--- a/build.env
+++ b/build.env
@@ -27,3 +27,6 @@ ALPINE_ARCH=aarch64
 
 # Only applies to new installations
 ALPINE_HOSTNAME=monok8s-hostname
+
+# Upper case [A-Z]_ only, used for naming env vars
+BUILD_TAG=MONOK8S
diff --git a/docker/initramfs.Dockerfile b/docker/initramfs.Dockerfile
index ff73516..db0cdc3 100644
--- a/docker/initramfs.Dockerfile
+++ b/docker/initramfs.Dockerfile
@@ -25,19 +25,18 @@ RUN make ARCH=${ARCH} CROSS_COMPILE=${CROSS_COMPILE} defconfig \
 RUN make CROSS_COMPILE=${CROSS_COMPILE} -j"$(nproc)"
 RUN make CROSS_COMPILE=${CROSS_COMPILE} CONFIG_PREFIX=/out/initramfs install
 
-WORKDIR /out/initramfs
+WORKDIR /build
 
-COPY initramfs/init init
-RUN chmod +x init
-RUN mkdir -p bin sbin etc proc sys dev lib mnt usr/bin usr/sbin
+ARG BUILD_TAG
 
-# Selective mods
-RUN mkdir -p /out/selected-mods /out/kernel
-COPY initramfs/selective-mods.sh /
+COPY alpine/*.sh ./
+COPY initramfs/*.sh ./
 COPY out/rootfs /out/rootfs
-RUN /selective-mods.sh /out/rootfs/lib/modules/$(ls /out/rootfs/lib/modules/) ./lib/
+COPY initramfs/rootfs-extra ./rootfs-extra
+COPY out/build-info ./rootfs-extra/etc/build-info
 
-RUN find . -print0 | cpio --null -ov --format=newc | gzip -9 > ../initramfs.cpio.gz
+WORKDIR /out/initramfs
+RUN /build/build-rootfs.sh
 
 FROM scratch
 COPY --from=build /out/initramfs.cpio.gz /initramfs.cpio.gz
diff --git a/initramfs/build-rootfs.sh b/initramfs/build-rootfs.sh
new file mode 100755
index 0000000..f044640
--- /dev/null
+++ b/initramfs/build-rootfs.sh
@@ -0,0 +1,9 @@
+#!/bin/bash
+set -euo pipefail
+
+mkdir -p bin sbin etc proc sys dev lib mnt usr/bin usr/sbin
+
+/build/selective-mods.sh /out/rootfs/lib/modules/$(ls /out/rootfs/lib/modules/) ./
+/build/merge-rootfs.sh "/build/rootfs-extra" "./"
+
+find . -print0 | cpio --null -ov --format=newc | gzip -9 > ../initramfs.cpio.gz
diff --git a/initramfs/rootfs-extra/bin/flash-emmc.sh.tmpl b/initramfs/rootfs-extra/bin/flash-emmc.sh.tmpl
new file mode 100755
index 0000000..af75fcf
--- /dev/null
+++ b/initramfs/rootfs-extra/bin/flash-emmc.sh.tmpl
@@ -0,0 +1,67 @@
+#!/bin/sh
+set -eu
+
+MNT=/mnt
+USB_DEV=/dev/sda
+EMMC_DEV=/dev/mmcblk0
+DEFAULT_GLOB="${MNT}/$${BUILD_TAG}_RELEASE_IMAGE"
+
+mkdir -p "$MNT"
+
+echo "[*] Mounting USB..."
+mount "$USB_DEV" "$MNT"
+
+# Find a default image (first match)
+DEFAULT_IMG="$(ls $DEFAULT_GLOB 2>/dev/null | head -n1 || true)"
+
+echo
+if [ -n "$DEFAULT_IMG" ]; then
+    echo "Default image found:"
+    echo "  $DEFAULT_IMG"
+else
+    echo "No default image found under $DEFAULT_GLOB"
+fi
+echo
+
+# Prompt user
+printf "Image Location (%s): " "${DEFAULT_IMG:-/mnt/...}"
+read -r IMG
+
+# Use default if empty
+if [ -z "$IMG" ]; then
+    IMG="$DEFAULT_IMG"
+fi
+
+# Validate
+if [ -z "$IMG" ] || [ ! -f "$IMG" ]; then
+    echo "Invalid image: $IMG"
+    umount "$MNT" || true
+    exit 1
+fi
+
+echo
+echo "About to write:"
+echo "  Image: $IMG"
+echo "  Target: $EMMC_DEV"
+echo
+
+printf "Type 'YES' to continue: "
+read -r CONFIRM
+
+if [ "$CONFIRM" != "YES" ]; then
+    echo "Aborted."
+    umount "$MNT" || true
+    exit 1
+fi
+
+echo "[*] Flashing..."
+gunzip -c "$IMG" > "$EMMC_DEV"
+
+echo "[*] Syncing..."
+sync
+
+echo "[*] Done."
+umount "$MNT" || true
+
+echo "[*] Rebooting..."
+reboot -f
diff --git a/initramfs/init b/initramfs/rootfs-extra/init
similarity index 95%
rename from initramfs/init
rename to initramfs/rootfs-extra/init
index 1b674e3..cc1495e 100755
--- a/initramfs/init
+++ b/initramfs/rootfs-extra/init
@@ -14,6 +14,8 @@ mount -t devpts devpts /dev/pts
 echo "Booting kernel took $(cut -d' ' -f1 /proc/uptime) seconds."
 echo "Dropping to shell on ttyS0..."
 
+. /etc/build-info
+
 while true; do
     setsid cttyhack /bin/sh
     echo "Shell exited. Starting another one..."
diff --git a/makefile b/makefile
index 4c40939..7fed2b7 100644
--- a/makefile
+++ b/makefile
@@ -26,6 +26,11 @@ BUILD_BASE_STAMP := $(OUT_DIR)/.build-base-$(TAG).stamp
 
 ALPINE_SERIES := $(word 1,$(subst ., ,$(ALPINE_VER))).$(word 2,$(subst ., ,$(ALPINE_VER)))
 
+BUILD_VERSION   ?= $(KUBE_VERSION)
+BUILD_DATE      := $(shell date -u +%Y-%m-%dT%H:%M:%SZ)
+BUILD_GIT       := $(shell git rev-parse --short HEAD 2>/dev/null || echo unknown)
+BUILD_INFO_FILE := $(OUT_DIR)/build-info
+
 # ---- File groups -------------------------------------------------------------
 
 # Use find so adding new files under these dirs is automatically picked up.
@@ -52,6 +57,7 @@ INITRAMFS_DEPS := \
 	$(BUSYBOX_TAR) \
 	docker/initramfs.Dockerfile \
 	$(INITRAMFS_SRCS) \
+	$(BUILD_INFO_FILE) \
 	build.env \
 	makefile
 
@@ -64,6 +70,7 @@ ITB_DEPS := \
 
 RELEASE_DEPS := \
 	$(BUILD_BASE_STAMP) \
+	$(BUILD_INFO_FILE) \
 	$(BOARD_ITB) \
 	$(ALPINE_TAR) \
 	$(CRIO_TAR) \
@@ -111,6 +118,15 @@ $(CRIO_TAR): | $(PACKAGES_DIR)
 
 # ---- Build stages ------------------------------------------------------------
 
+$(BUILD_INFO_FILE):
+	@mkdir -p $(dir $@)
+	@printf '%s\n' \
+		'export $(BUILD_TAG)_VERSION="$(BUILD_VERSION)"' \
+		'export $(BUILD_TAG)_BUILD_DATE="$(BUILD_DATE)"' \
+		'export $(BUILD_TAG)_GIT="$(BUILD_GIT)"' \
+		'export $(BUILD_TAG)_RELEASE_IMAGE="$(notdir $(RELEASE_IMAGE))"' \
+		> $@
+
 $(BUILD_BASE_STAMP): $(BUILD_BASE_DEPS) | $(OUT_DIR)
 	docker build \
 		-f docker/build-base.Dockerfile \
@@ -138,6 +154,7 @@ $(INITRAMFS): $(INITRAMFS_DEPS) | $(OUT_DIR)
 		--build-arg ARCH=$(ARCH) \
 		--build-arg CROSS_COMPILE=$(CROSS_COMPILE) \
 		--build-arg BUSYBOX_VERSION=$(BUSYBOX_VERSION) \
+		--build-arg BUILD_TAG=$(BUILD_TAG) \
 		--output type=local,dest=./$(OUT_DIR) .
 	test -f $@