summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSam Thursfield <sam.thursfield@codethink.co.uk>2017-11-08 17:52:41 +0000
committerSam Thursfield <sam.thursfield@codethink.co.uk>2017-12-06 13:32:34 +0000
commit58d9422afe0191276109e2ecaeaec721d8816a88 (patch)
tree22e806333095785d66510f0928f1b7b0578542ad
parente230e8172a80cfde96f780af5f6be901b55bfbd0 (diff)
downloaddefinitions-58d9422afe0191276109e2ecaeaec721d8816a88.tar.gz
Add support for building an initramfs
The scripts are taken from https://gitlab.com/BuildStream/buildstream-tests (branch build-gnome). Those in turn were taken from http://git.baserock.org/baserock/baserock/initramfs-scripts.git We manually set the executable permissions in the init scripts using chmod, because https://gitlab.com/BuildStream/buildstream/issues/84
-rw-r--r--elements/initramfs/initramfs-gz.bst26
-rw-r--r--elements/initramfs/initramfs-scripts.bst6
-rw-r--r--elements/initramfs/initramfs.bst12
-rw-r--r--files/initramfs-scripts/init132
-rw-r--r--files/initramfs-scripts/shutdown67
5 files changed, 243 insertions, 0 deletions
diff --git a/elements/initramfs/initramfs-gz.bst b/elements/initramfs/initramfs-gz.bst
new file mode 100644
index 00000000..383e9603
--- /dev/null
+++ b/elements/initramfs/initramfs-gz.bst
@@ -0,0 +1,26 @@
+kind: script
+description: The compressed initramfs
+
+depends:
+- filename: initramfs/initramfs.bst
+ type: build
+- filename: gnu-toolchain.bst
+ type: build
+
+variables:
+ cwd: "%{build-root}"
+
+config:
+ layout:
+ - element: gnu-toolchain.bst
+ destination: /
+ - element: initramfs/initramfs.bst
+ destination: "%{build-root}"
+
+ commands:
+ - mkdir -p %{install-root}/boot
+ # We need to ensure exec permissions here.
+ # See: https://gitlab.com/BuildStream/buildstream/issues/84
+ - chmod +x ./sbin/init ./sbin/shutdown
+ - (find . -print0 | cpio -0 -H newc -o) |
+ gzip -c > %{install-root}/boot/initramfs.gz
diff --git a/elements/initramfs/initramfs-scripts.bst b/elements/initramfs/initramfs-scripts.bst
new file mode 100644
index 00000000..536a3302
--- /dev/null
+++ b/elements/initramfs/initramfs-scripts.bst
@@ -0,0 +1,6 @@
+kind: import
+
+sources:
+- kind: local
+ path: files/initramfs-scripts
+ directory: /sbin
diff --git a/elements/initramfs/initramfs.bst b/elements/initramfs/initramfs.bst
new file mode 100644
index 00000000..15ef4c0d
--- /dev/null
+++ b/elements/initramfs/initramfs.bst
@@ -0,0 +1,12 @@
+kind: compose
+description: Initramfs composition
+
+depends:
+- filename: gnu-toolchain.bst
+ type: build
+- filename: initramfs/initramfs-scripts.bst
+ type: build
+
+config:
+ include:
+ - runtime
diff --git a/files/initramfs-scripts/init b/files/initramfs-scripts/init
new file mode 100644
index 00000000..d1d1042b
--- /dev/null
+++ b/files/initramfs-scripts/init
@@ -0,0 +1,132 @@
+#!/bin/sh
+trap 'exec /bin/sh' INT EXIT
+
+# We need proc for reading the kernel command line
+mount -n -t proc none /proc
+
+set -- $(cat /proc/cmdline)
+
+# We don't want to leave mount points around
+umount /proc
+
+rootwait=true # defaults to off in the kernel, I think it's more useful on
+for arg; do
+ case "$arg" in
+ root=LABEL=*)
+ if [ x"$root_type" != x ]; then
+ echo "Warning, multiple root= specified, using latest."
+ fi
+ root_type=label
+ root="${arg#root=LABEL=}"
+ ;;
+ root=UUID=*)
+ if [ x"$root_type" != x ]; then
+ echo "Warning, multiple root= specified, using latest."
+ fi
+ root_type=uuid
+ root="${arg#root=UUID=}"
+ ;;
+ root=*)
+ if [ x"$root_type" != x ]; then
+ echo "Warning, multiple root= specified, using latest."
+ fi
+ root_type=disk
+ root="${arg#root=}"
+ ;;
+ rootflags=*)
+ if [ x"$rootflags" != x ]; then
+ echo "Warning, multiple rootflags= specified, using latest."
+ fi
+ rootflags=",${arg#rootflags=}"
+ ;;
+ rootfstype=*)
+ if [ x"$rootfstype" != x ]; then
+ echo "Warning, multiple rootfstype= specified, using latest."
+ fi
+ rootfstype="${arg#rootfstype=}"
+ ;;
+ rootdelay=*)
+ if [ x"$rootdelay" != x ]; then
+ echo "Warning, multiple rootdelay= specified, using latest."
+ fi
+ rootdelay="${arg#rootdelay=}"
+ ;;
+ rootwait)
+ rootwait=true
+ ;;
+ norootwait)
+ rootwait=false
+ ;;
+ ro)
+ ro=ro
+ ;;
+ rw)
+ ro=rw
+ ;;
+ init=*)
+ init="${arg#init=}"
+ ;;
+ esac
+done
+
+
+if [ x"$rootdelay" != x ]; then
+ sleep "$rootdelay"
+fi
+
+if [ x"$rootfstype" = x ]; then
+ # Warn that busybox may not be able to auto-detect rootfs type
+ cat <<\EOF
+Warning, rootfs type not specified, auto-detection of type is slow and
+may fail. Please add rootfstype=$type to kernel command line.
+EOF
+fi
+
+mount -n -t devtmpfs devtmpfs /dev
+
+while true; do
+ case "$root_type" in
+ disk)
+ if mount -n -t "${rootfstype}" -o "${ro-rw}""$rootflags" "$root" /mnt; then
+ break
+ else
+ echo disk $root not found
+ blkid
+ fi
+ ;;
+ label)
+ disk="$(findfs LABEL="$root")"
+ if [ x"$disk" = x ]; then
+ echo disk with label $root not found
+ blkid
+ else
+ mount -n -t "${rootfstype}" -o "${ro-rw}""$rootflags" "$disk" /mnt && break
+ fi
+ ;;
+ uuid)
+ disk="$(findfs UUID="$root")"
+ if [ x"$disk" = x ]; then
+ echo disk with UUID $root not found
+ blkid
+ else
+ mount -n -t "${rootfstype}" -o "${ro-rw}""$rootflags" "$disk" /mnt && break
+ fi
+ ;;
+ '')
+ echo "Error, no root specified"
+ exit 1
+ ;;
+ esac
+ if "$rootwait"; then
+ echo Trying again in 0.5 seconds
+ sleep 0.5
+ fi
+done
+umount -n /dev
+
+# We dont create any static device nodes while building,
+# device nodes will be created by systemd but before that
+# we at least need the console
+mknod -m 0600 /mnt/dev/console c 5 1
+
+exec switch_root -c /dev/console /mnt "${init-/sbin/init}"
diff --git a/files/initramfs-scripts/shutdown b/files/initramfs-scripts/shutdown
new file mode 100644
index 00000000..0065bcc8
--- /dev/null
+++ b/files/initramfs-scripts/shutdown
@@ -0,0 +1,67 @@
+#!/bin/sh
+
+fail(){
+ echo "$@" >&2
+ # The behaviour on failure of systemd when shutting down without a
+ # shutdownramfs is to freeze if it fails, but the behaviour of an initramfs
+ # on failure is to drop you into a recovery shell. The latter seems more
+ # useful.
+ exec /bin/sh
+}
+
+startswith(){
+ # Filter out lines that don't start with $1
+ # grep ^EXPR is usually sufficient, but would require escaping of EXPR.
+ # Instead this compares the line to the line with its prefix stripped,
+ # so if the line is different, then it started with that prefix.
+ # It's ugly, but is less logic than escaping the regular expression and
+ # using grep, more reliable than not making any effort to escape, and
+ # less surprising than requiring the parameter to be pre-escaped.
+ while read -r line; do
+ if [ "${line#"$1"}" != "$line" ]; then
+ printf '%s\n' "$line"
+ fi
+ done
+}
+
+recursive_umount(){
+ # Recursively unmount every mountpoint under $1.
+ # This works by filtering to select mountpoints from mountinfo that start
+ # with the absolute path of the directory given.
+ # It unmounts in reverse-order, so that it may unmount dependent mounts
+ # first, and it has to handle the paths having octal escape sequences.
+ set -- "$(readlink -f "$1")"
+ cut -d' ' -f5 /proc/self/mountinfo | startswith "$1" \
+ | sort -r | while read -r mp; do
+ umount "$(echo -e "$mp")"
+ done
+}
+
+# Give the rootfs another chance to write its state to disk.
+sync
+
+# Kill any http://www.freedesktop.org/wiki/Software/systemd/RootStorageDaemons/
+# as we don't have any facility to cleanly shut them down in this initramfs.
+killall5
+
+# Recursively unmount the old root, so they have a chance of performing
+# unmount-time cleanup.
+recursive_umount /oldroot
+
+case "$1" in
+reboot|poweroff|halt)
+ if ! "$1" -f; then
+ fail "$1 command failed"
+ fi
+ ;;
+kexec)
+ # probably don't have this, but we'll try anyway
+ if ! kexec -e; then
+ fail "$1 command failed"
+ fi
+ ;;
+*)
+ fail "Unrecognized shutdown verb $1"
+ ;;
+esac
+