summaryrefslogtreecommitdiffstats
path: root/update-initramfs
diff options
context:
space:
mode:
Diffstat (limited to '')
-rwxr-xr-xupdate-initramfs398
-rw-r--r--update-initramfs.895
-rw-r--r--update-initramfs.conf.535
3 files changed, 528 insertions, 0 deletions
diff --git a/update-initramfs b/update-initramfs
new file mode 100755
index 0000000..4bb8d8a
--- /dev/null
+++ b/update-initramfs
@@ -0,0 +1,398 @@
+#!/bin/sh
+
+BOOTDIR=/boot
+CONF=/etc/initramfs-tools/update-initramfs.conf
+mode=""
+version=""
+update_initramfs=yes
+backup_initramfs=no
+
+set -e
+
+[ -r ${CONF} ] && . ${CONF}
+
+if [ -n "$DPKG_MAINTSCRIPT_PACKAGE" ] && [ $# = 1 ] && [ "$1" = -u ]; then
+ if dpkg-trigger --no-await update-initramfs; then
+ echo "update-initramfs: deferring update (trigger activated)"
+ exit 0
+ fi
+fi
+
+usage()
+{
+ cat << EOF
+
+Usage: update-initramfs {-c|-d|-u} [-k version] [-v] [-b directory]
+
+Options:
+ -k version Specify kernel version or 'all'
+ -c Create a new initramfs
+ -u Update an existing initramfs
+ -d Remove an existing initramfs
+ -b directory Set alternate boot directory
+ -v Be verbose
+
+See update-initramfs(8) for further details.
+
+EOF
+}
+
+usage_error()
+{
+ if [ -n "${1:-}" ]; then
+ printf "%s\\n\\n" "${*}" >&2
+ fi
+ usage >&2
+ exit 2
+}
+
+mild_panic()
+{
+ if [ -n "${1:-}" ]; then
+ printf "%s\\n" "${*}" >&2
+ fi
+ exit 0
+}
+
+panic()
+{
+ if [ -n "${1:-}" ]; then
+ printf "%s\\n" "${*}" >&2
+ fi
+ exit 1
+}
+
+verbose()
+{
+ if [ "${verbose}" = 1 ]; then
+ printf "%s\\n" "${*}"
+ fi
+}
+
+set_initramfs()
+{
+ initramfs="${BOOTDIR}/initrd.img-${version}"
+}
+
+
+# backup initramfs while running
+backup_initramfs()
+{
+ [ ! -r "${initramfs}" ] && return 0
+ initramfs_bak="${initramfs}.dpkg-bak"
+ [ -r "${initramfs_bak}" ] && rm -f "${initramfs_bak}"
+ ln -f "${initramfs}" "${initramfs_bak}" 2>/dev/null \
+ || cp -a "${initramfs}" "${initramfs_bak}"
+ verbose "Keeping ${initramfs_bak}"
+}
+
+# keep booted initramfs
+backup_booted_initramfs()
+{
+ initramfs_bak="${initramfs}.dpkg-bak"
+
+ # first time run thus no backup
+ [ ! -r "${initramfs_bak}" ] && return 0
+
+ # chroot with no /proc
+ [ ! -r /proc/uptime ] && rm -f "${initramfs_bak}" && return 0
+
+ # no kept backup wanted
+ [ "${backup_initramfs}" = "no" ] && rm -f "${initramfs_bak}" && return 0
+
+ # no backup yet
+ if [ ! -r "${initramfs}.bak" ]; then
+ mv -f "${initramfs_bak}" "${initramfs}.bak"
+ verbose "Backup ${initramfs}.bak"
+ return 0
+ fi
+
+ # keep booted initramfs
+ boot_initramfs=
+ uptime_days=$(awk '{printf "%d", $1 / 3600 / 24}' /proc/uptime)
+ if [ -n "$uptime_days" ]; then
+ boot_initramfs=$(find "${initramfs}.bak" -mtime "+${uptime_days}")
+ fi
+ if [ -n "${boot_initramfs}" ]; then
+ mv -f "${initramfs_bak}" "${initramfs}.bak"
+ verbose "Backup ${initramfs}.bak"
+ return 0
+ fi
+ verbose "Removing current backup ${initramfs_bak}"
+ rm -f "${initramfs_bak}"
+}
+
+# nuke generated copy
+remove_initramfs_bak()
+{
+ [ -z "${initramfs_bak:-}" ] && return 0
+ rm -f "${initramfs_bak}"
+ verbose "Removing ${initramfs_bak}"
+}
+
+
+generate_initramfs()
+{
+ echo "update-initramfs: Generating ${initramfs}"
+ OPTS="-o"
+ if [ "${verbose}" = 1 ]; then
+ OPTS="-v ${OPTS}"
+ fi
+ # shellcheck disable=SC2086
+ if mkinitramfs ${OPTS} "${initramfs}.new" "${version}"; then
+ mv -f "${initramfs}.new" "${initramfs}"
+ # Guard against an unclean shutdown
+ sync -f "${initramfs}"
+ else
+ mkinitramfs_return="$?"
+ remove_initramfs_bak
+ rm -f "${initramfs}.new"
+ echo "update-initramfs: failed for ${initramfs} with $mkinitramfs_return." >&2
+ exit $mkinitramfs_return
+ fi
+}
+
+# Invoke bootloader
+run_bootloader()
+{
+ # invoke policy conformant bootloader hooks
+ if [ -d /etc/initramfs/post-update.d/ ]; then
+ run-parts --arg="${version}" --arg="${initramfs}" \
+ /etc/initramfs/post-update.d/
+ return 0
+ fi
+}
+
+# ro /boot is not modified
+ro_boot_check()
+{
+ # check irrelevant inside of a chroot
+ if [ ! -r /proc/mounts ] || ischroot; then
+ return 0
+ fi
+
+ # shellcheck disable=SC1004
+ boot_opts=$(awk '/boot/{if ((match($4, /^ro/) || match($4, /,ro/)) \
+ && $2 == "/boot") print "ro"}' /proc/mounts)
+ if [ -n "${boot_opts}" ]; then
+ echo "W: /boot is ro mounted." >&2
+ echo "W: update-initramfs: Not updating ${initramfs}" >&2
+ exit 0
+ fi
+}
+
+get_sorted_versions()
+{
+ version_list="$(
+ linux-version list |
+ while read -r version; do
+ test -e "${BOOTDIR}/initrd.img-$version" && echo "$version"
+ done |
+ linux-version sort --reverse
+ )"
+ verbose "Available versions: ${version_list}"
+}
+
+set_current_version()
+{
+ if [ -f "/boot/initrd.img-$(uname -r)" ]; then
+ version=$(uname -r)
+ fi
+}
+
+set_linked_version()
+{
+ linktarget=
+ if [ -e /initrd.img ] && [ -L /initrd.img ]; then
+ linktarget="$(basename "$(readlink /initrd.img)")"
+ fi
+
+ if [ -e /boot/initrd.img ] && [ -L /boot/initrd.img ]; then
+ linktarget="$(basename "$(readlink /boot/initrd.img)")"
+ fi
+
+ if [ -z "${linktarget}" ]; then
+ return
+ fi
+
+ version="${linktarget##initrd.img-}"
+}
+
+set_highest_version()
+{
+ get_sorted_versions
+ if [ -z "${version_list}" ]; then
+ version=
+ return
+ fi
+ # shellcheck disable=SC2086
+ set -- ${version_list}
+ version=${1}
+}
+
+create()
+{
+ if [ -z "${version}" ]; then
+ usage_error "Create mode requires a version argument"
+ fi
+
+ set_initramfs
+
+ generate_initramfs
+
+ run_bootloader
+}
+
+update()
+{
+ if [ "${update_initramfs}" = "no" ]; then
+ echo "update-initramfs: Not updating initramfs."
+ exit 0
+ fi
+
+ if [ -z "${version}" ]; then
+ set_highest_version
+ fi
+
+ if [ -z "${version}" ]; then
+ set_linked_version
+ fi
+
+ if [ -z "${version}" ]; then
+ set_current_version
+ fi
+
+ if [ -z "${version}" ]; then
+ verbose "Nothing to do, exiting."
+ exit 0
+ fi
+
+ set_initramfs
+
+ ro_boot_check
+
+ backup_initramfs
+
+ generate_initramfs
+
+ run_bootloader
+
+ backup_booted_initramfs
+}
+
+delete()
+{
+ if [ -z "${version}" ]; then
+ usage_error "Delete mode requires a version argument"
+ fi
+
+ set_initramfs
+
+ echo "update-initramfs: Deleting ${initramfs}"
+
+ rm -f "${initramfs}" "${initramfs}.bak"
+}
+
+# Defaults
+verbose=0
+
+##
+
+OPTIONS=$(getopt -o "k:cudvtb:h?" --long help -n "$0" -- "$@") || usage_error
+
+eval set -- "$OPTIONS"
+
+while true; do
+ case "$1" in
+ -k)
+ version="$2"
+ shift 2
+ ;;
+ -c)
+ mode="c"
+ shift
+ ;;
+ -d)
+ mode="d"
+ shift
+ ;;
+ -u)
+ mode="u"
+ shift
+ ;;
+ -v)
+ verbose="1"
+ shift
+ ;;
+ -t)
+ # accepted for compatibility, but ignored
+ shift
+ ;;
+ -b)
+ BOOTDIR="$2"
+ if [ ! -d "${BOOTDIR}" ]; then
+ echo "E: ${BOOTDIR} is not a directory." >&2
+ exit 1
+ fi
+ shift 2
+ ;;
+ -h|-\?|--help)
+ usage
+ exit 0
+ ;;
+ --)
+ shift
+ break
+ ;;
+ esac
+done
+
+if [ $# -ne 0 ]; then
+ printf "Extra argument '%s'\\n\\n" "$1" >&2
+ usage_error
+fi
+
+# Validate arguments
+if [ -z "${mode}" ]; then
+ usage_error "You must specify at least one of -c, -u, or -d."
+fi
+
+if [ "${version}" = "all" ] \
+ || { [ "${update_initramfs}" = "all" ] && [ -z "${version}" ]; }; then
+ case "${mode}" in
+ c)
+ version_list="$(linux-version list)"
+ ;;
+ d | u)
+ get_sorted_versions
+ ;;
+ esac
+ if [ -z "${version_list}" ]; then
+ verbose "Nothing to do, exiting."
+ exit 0
+ fi
+
+ OPTS="-b ${BOOTDIR}"
+ if [ "${verbose}" = "1" ]; then
+ OPTS="${OPTS} -v"
+ fi
+ for u_version in ${version_list}; do
+ verbose "Execute: ${0} -${mode} -k \"${u_version}\" ${OPTS}"
+ # shellcheck disable=SC2086
+ "${0}" -${mode} -k "${u_version}" ${OPTS}
+ done
+ exit 0
+fi
+
+
+case "${mode}" in
+ c)
+ create
+ ;;
+ d)
+ delete
+ ;;
+ u)
+ update
+ ;;
+esac
diff --git a/update-initramfs.8 b/update-initramfs.8
new file mode 100644
index 0000000..b36fc57
--- /dev/null
+++ b/update-initramfs.8
@@ -0,0 +1,95 @@
+.TH UPDATE-INITRAMFS 8 "2014/10/16" "initramfs\-tools" "System Administration"
+
+.SH NAME
+update\-initramfs \- generate an initramfs image
+
+.SH SYNOPSIS
+.B update\-initramfs
+.RB { \-c | \-d | \-u }
+.RB [ \-k
+.IR version ]
+.RB [ \-v ]
+.RB [ \-b
+.IR directory ]
+.br
+.BR update\-initramfs " " \-h
+.SH DESCRIPTION
+The
+.B update\-initramfs
+script manages your initramfs images on your local box.
+It keeps track of the existing initramfs archives in /boot.
+There are three modes of operation create, update or delete.
+You must at least specify one of those modes.
+
+The initramfs is a gzipped cpio archive.
+At boot time, the kernel unpacks that archive into RAM disk, mounts and
+uses it as initial root file system. All finding of the root device
+happens in this early userspace.
+
+.SH OPTIONS
+.TP
+\fB\-k \fI version
+Set the specific kernel version for whom the initramfs will be generated.
+For example the output of uname \-r for your currently running kernel.
+This argument is optional for update. The default is the latest kernel version.
+
+The use of "all" for the
+.I version
+string specifies that
+.B update\-initramfs
+should operate on all installed kernel versions (with \fB\-c\fR), or
+on all installed kernel versions that already have an initramfs
+(with \fB\-d\fR or \fB\-u\fR).
+
+.TP
+\fB\-c
+This mode creates a new initramfs.
+
+.TP
+\fB\-u
+This mode updates an existing initramfs.
+
+.TP
+\fB\-d
+This mode deletes an existing initramfs.
+
+.TP
+\fB\-v
+This option increases the amount of information you are given during
+the chosen action.
+
+.TP
+\fB\-b \fI directory
+Set an different bootdir for the image creation.
+
+.TP
+\fB\-h\fR, \fB--help\fR
+Print a short help page describing the available options in
+.B update\-initramfs.
+
+.SH EXAMPLES
+
+Update the initramfs of the newest kernel:
+
+.PP
+.B update\-initramfs -u
+
+
+Create the initramfs for a specific kernel:
+
+.PP
+.B update\-initramfs -c -k 2.6.18-1-686
+
+.SH FILES
+/etc/initramfs-tools/update-initramfs.conf
+
+.SH AUTHOR
+The initramfs-tools are written by Maximilian Attems <maks@debian.org>,
+Jeff Bailey <jbailey@raspberryginger.com> and numerous others.
+
+.SH SEE ALSO
+.BR
+.IR initramfs.conf (5),
+.IR initramfs-tools (7),
+.IR mkinitramfs (8),
+.IR lsinitramfs (8).
diff --git a/update-initramfs.conf.5 b/update-initramfs.conf.5
new file mode 100644
index 0000000..cd1f4ea
--- /dev/null
+++ b/update-initramfs.conf.5
@@ -0,0 +1,35 @@
+.TH UPDATE-INITRAMFS.CONF 5 "2010/04/05" "initramfs\-tools" "File Formats Manual"
+
+.SH NAME
+update-initramfs.conf \- configuration file for update-initramfs
+
+.SH DESCRIPTION
+The configuration file allows one to disable the update action from
+.B update-initramfs.
+
+.SH GENERAL VARIABLES
+.TP
+\fB update_initramfs
+Default is \fIyes\fP for running the latest initramfs-tools hooks in the
+newest Linux image.
+Setting it to \fIall\fP updates any known initramfs.
+It is possible to set it to \fIno\fP for remote servers or boxes where
+conservative manners needs to be applied. This disables
+the \fBupdate_initramfs \-u\fP call.
+.TP
+\fB backup_initramfs
+If set \fBupdate_initramfs\fP keeps an .bak file of the previous initramfs. If unset the backup initramfs will not be kept.
+
+.SH FILES
+.TP
+.I /etc/initramfs-tools/update-initramfs.conf
+
+.SH AUTHOR
+The initramfs-tools are written by Maximilian Attems <maks@debian.org>,
+Jeff Bailey <jbailey@raspberryginger.com> and numerous others.
+.SH SEE ALSO
+.BR
+.IR initramfs.conf (5),
+.IR initramfs-tools (7),
+.IR mkinitramfs (8),
+.IR update-initramfs (8).