Import Upstream version 0.136

This commit is contained in:
openKylinBot 2022-05-14 00:19:54 +08:00
commit 4073b78a30
62 changed files with 7445 additions and 0 deletions

8
.dir-locals.el Normal file
View File

@ -0,0 +1,8 @@
;;; Directory Local Variables
;;; For more information see (info "(emacs) Directory Variables")
((sh-mode
(sh-basic-offset . 8)
(sh-indentation . 8)
(sh-indent-for-case-label . 0)
(sh-indent-for-case-alt . +)))

0
.mine Normal file
View File

View File

@ -0,0 +1,23 @@
# update-initramfs(8) completion
_update_initramfs()
{
local cur prev valid_options
_get_comp_words_by_ref cur prev
# The only option that takes an argument is -k
if [[ "$prev" == '-k' ]]; then
# Complete with kernel versions
_kernel_versions
COMPREPLY=( $( compgen -W '${COMPREPLY[@]} all' -- "$cur" ) )
return;
fi
# Complete with available options (obtained from -h)
valid_options=$( update-initramfs -h 2>&1 | \
sed -e '/^ -/!d;s/^ \(-\w\+\).*/\1/' )
COMPREPLY=( $( compgen -W "$valid_options" -- $cur ) )
}
complete -F _update_initramfs update-initramfs

81
conf/initramfs.conf Normal file
View File

@ -0,0 +1,81 @@
#
# initramfs.conf
# Configuration file for mkinitramfs(8). See initramfs.conf(5).
#
# Note that configuration options from this file can be overridden
# by config files in the /etc/initramfs-tools/conf.d directory.
#
# MODULES: [ most | netboot | dep | list ]
#
# most - Add most filesystem and all harddrive drivers.
#
# dep - Try and guess which modules to load.
#
# netboot - Add the base modules, network modules, but skip block devices.
#
# list - Only include modules from the 'additional modules' list
#
MODULES=most
#
# BUSYBOX: [ y | n | auto ]
#
# Use busybox shell and utilities. If set to n, klibc utilities will be used.
# If set to auto (or unset), busybox will be used if installed and klibc will
# be used otherwise.
#
BUSYBOX=auto
#
# COMPCACHE_SIZE: [ "x K" | "x M" | "x G" | "x %" ]
#
# Amount of RAM to use for RAM-based compressed swap space.
#
# An empty value - compcache isn't used, or added to the initramfs at all.
# An integer and K (e.g. 65536 K) - use a number of kilobytes.
# An integer and M (e.g. 256 M) - use a number of megabytes.
# An integer and G (e.g. 1 G) - use a number of gigabytes.
# An integer and % (e.g. 50 %) - use a percentage of the amount of RAM.
#
# You can optionally install the compcache package to configure this setting
# via debconf and have userspace scripts to load and unload compcache.
#
COMPCACHE_SIZE=""
#
# COMPRESS: [ gzip | bzip2 | lz4 | lzma | lzop | xz ]
#
COMPRESS=lz4
#
# NFS Section of the config.
#
#
# DEVICE: ...
#
# Specify a specific network interface, like eth0
# Overridden by optional ip= or BOOTIF= bootarg
#
DEVICE=
#
# NFSROOT: [ auto | HOST:MOUNT ]
#
NFSROOT=auto
#
# RUNSIZE: ...
#
# The size of the /run tmpfs mount point, like 256M or 10%
# Overridden by optional initramfs.runsize= bootarg
#
RUNSIZE=10%

14
conf/modules Normal file
View File

@ -0,0 +1,14 @@
### This file is the template for /etc/initramfs-tools/modules.
### It is not a configuration file itself.
###
# List of modules that you want to include in your initramfs.
# They will be loaded at boot time in the order below.
#
# Syntax: module_name [args ...]
#
# You must run update-initramfs(8) to effect this change.
#
# Examples:
#
# raid1
# sd_mod

View File

@ -0,0 +1,20 @@
#
# Configuration file for update-initramfs(8)
#
#
# update_initramfs [ yes | all | no ]
#
# Default is yes
# If set to all update-initramfs will update all initramfs
# If set to no disables any update to initramfs beside kernel upgrade
update_initramfs=yes
#
# backup_initramfs [ yes | no ]
#
# Default is no
# If set to no leaves no .bak backup files.
backup_initramfs=no

68
docs/example_hook Normal file
View File

@ -0,0 +1,68 @@
#!/bin/sh
#
#
# This is an example hook script. It will be run by 'mkinitramfs'
# when it creates the image. It's job is to decide which files to
# install, then install them into the staging area, where the
# initramfs is being created. This happens when a new 'linux-image'
# package is installed, or when the administrator runs 'mkinitramfs'
# by hand to update an initramfs image.
#
# CONFDIR -- usually /etc/initramfs-tools, can be set on mkinitramfs
# command line.
#
# DESTDIR -- The staging directory where we are building the image.
#
# see initramfs-tools(7)
#
# List the soft prerequisites here. This is a space separated list of
# names, of scripts that are in the same directory as this one, that
# must be run before this one can be.
#
PREREQ=""
prereqs()
{
echo "$PREREQ"
}
case $1 in
# get pre-requisites
prereqs)
prereqs
exit 0
;;
esac
# You can do anything you need to from here on.
#
# Source the optional 'hook-functions' scriptlet, if you need the
# functions defined within it. Read it to see what is available to
# you. It contains functions for copying dynamically linked program
# binaries, and kernel modules into the DESTDIR.
#
. /usr/share/initramfs-tools/hook-functions
# If this hook script is a conffile (and thus stored in
# /etc/mkinitramfs/hooks), it must take care to do the right thing
# when the package containing it is removed but not purged. There of
# course may be other reasons to have custom logic deciding what to
# install. The version variable may be useful for this.
#
if command -v myprog >/dev/null 2>&1; then
copy_exec /usr/bin/myprog usr/bin
fi
# To accompany this, there should usually be a script for inside the
# initramfs named something like:
#
# "/etc/mkinitramfs/local-premount/myprog"
#
# ... and it should do what is necessary to have 'myprog' get run
# inside the early runtime environment.
exit 0

48
docs/example_script Normal file
View File

@ -0,0 +1,48 @@
#!/bin/sh
#
# This script is run inside of the initramfs environment during the
# system boot process. It is installed there by 'update-initramfs'.
# The # package that owns it may opt to install it in an appropriate
# location under "/usr/share/initramfs-tools/scripts/".
#
# see initramfs-tools(7) for more details.
#
# List the soft prerequisites here. This is a space separated list of
# names, of scripts that are in the same directory as this one, that
# must be run before this one can be.
#
PREREQ=""
prereqs()
{
echo "$PREREQ"
}
case $1 in
# get pre-requisites
prereqs)
prereqs
exit 0
;;
mountfail) # Called if the script has previously registered a mountroot
# failure.
# Check status, and display any relevant information about the
# failure if there is a problem, then exit with a status of 1.
;;
esac
# Do the work here.
# If this script is to be placed in either init-premount, or local-top,
# register a mountroot failure hook, so that further information can be given
# to the user, in the event that the root device cannot be found.
. /scripts/functions
add_mountroot_fail_hook
echo "Got here!"
exit 0

116
docs/framebuffer Normal file
View File

@ -0,0 +1,116 @@
#!/bin/sh
PREREQ=""
prereqs()
{
echo "$PREREQ"
}
case $1 in
# get pre-requisites
prereqs)
prereqs
exit 0
;;
esac
# The options part of the kernel "video=" argument (i.e. everyting
# after "video=<fbdriver>:") has very inconsistent rules.
#
# Generally the following applies:
# 1) options are comma-separated
# 2) options can be in either of these three forms:
# <arg>=<value>, <arg>:<value>, <boolean-arg>.
# 3) the "mode" or "mode_option" option (name depends on the framebuffer driver)
# has the form <xres>x<yres>[M][R][-<bpp>][@<refresh>][i][m]
# and may or may not start with "mode=" or "mode_option="
# -> please adjust as necessary in the parse_video_opts() function
#
# When the options are used with modules, they need to be space-separated
# and the following conversions are needed:
# <arg>:<value> -> <arg>=<value>
# <boolean-arg> -> <boolean-arg>=1
# <modevalue> -> mode=<modevalue> or mode_option=<modevalue>
parse_video_opts()
{
local OPTS="$1"
local IFS=","
# Must be a line like video=<fbdriver>:<opt1>,[opt2]...
if [ "${OPTS}" = "${OPTS%%:*}" ]; then
return
fi
OPTS="${OPTS#*:}"
for opt in ${OPTS}; do
# Already in the "<arg>=<value>" form
if [ "${opt}" != "${opt#*=}" ]; then
printf "%s" "$opt "
# In the "<arg>:<value>" form
elif [ "${opt}" != "${opt#*:}" ]; then
printf "%s" "${opt%:*}=${opt#*:} "
# Presumably a modevalue without the "mode=" prefix
elif [ "${opt}" != "${opt#[0-9]*x[0-9]}" ]; then
# Adjust: mode= option?
printf "%s" "mode=$opt "
# ... or mode_option= option?
# printf "%s" "mode_option=$opt "
# Presumably a boolean
else
printf "%s" "${opt}=1 "
fi
done
}
FB=""
OPTS=""
# shellcheck disable=SC2013
for x in $(cat /proc/cmdline); do
case ${x} in
vga=*)
FB="vesafb";
OPTS="";
;;
video=*)
FB=${x#*=}
FB="${FB%%:*}"
OPTS="$(parse_video_opts "${x}")"
esac
done
# Module-specific workarounds
case ${FB} in
matroxfb)
# Map command line name to module name
FB=matroxfb_base
;;
intelfb|i810fb|i915)
# Needs AGP driver loaded
modprobe intel-agp
;;
uvesafb)
# v86d requires /dev/zero and dev/mem, but udev haven't been started yet
[ -e /dev/zero ] || mknod -m 0666 /dev/zero c 1 5
[ -e /dev/mem ] || mknod -m 0640 /dev/mem c 1 1
;;
*)
;;
esac
if [ -n "${FB}" ]; then
unset MODPROBE_OPTIONS
modprobe -q fbcon
# shellcheck disable=SC2086
modprobe -q ${FB} ${OPTS}
fi
if [ -e /proc/fb ]; then
# shellcheck disable=SC2034
while read -r fbno desc; do
if [ $((fbno < 32)) ]; then
mknod -m 0640 "/dev/fb${fbno}" c 29 "${fbno}"
fi
done < /proc/fb
else
mknod -m 0640 /dev/fb0 c 29 0
fi

234
docs/maintainer-notes.md Normal file
View File

@ -0,0 +1,234 @@
***
# Maintainer documentation for initramfs-tools
***
## Table of Contents
* [1. Definitions](#definitions)
* [2. Preparations](#preparations)
* [3. Workflow for daily work](#workflow)
* [3.1 Implement new features](#newfeature)
* [3.2 Merge branches](#merge)
* [3.3 Test specific branch](#test)
* [3.4 Build snapshot version](#snapshot)
* [4. Contribute](#contribute)
* [5. Release new version](#release)
* [6. Resources](#resources)
* [7. Credits](#credits)
* [8. License](#license)
***
**NOTE:** The most recent version of this document is available at
docs/maintainer-notes.md in the [the git repository](#checkout)
or online at [salsa.debian.org](https://salsa.debian.org/kernel-team/initramfs-tools/blob/master/docs/maintainer-notes.md).
***
## <a name="definitions">1. Definitions</a>
<table>
<tr><td><code><b>$mailaddress:</b></code></td><td>mailaddress of the user</td></tr>
<tr><td><code><b>$username:</b></code></td><td>name of the Salsa account</td></tr>
<tr><td><code><b>$version:</b></code></td><td>version string</td></tr>
<tr><td><code><b>$yourname:</b></code></td><td>your fullname</td></tr>
</table>
***
## <a name="preparations">2. Preparations</a>
1. Install required software:
# apt-get install git git-buildpackage dpkg-dev
1. Set environment variables (e.g. through your ~/.bashrc or ~/.zshrc) for devscripts (gbp dch):
export DEBEMAIL=$mailaddress
export DEBFULLNAME=$yourname
1. Set user name and email address for git (drop the --global option to use configuration per-repo basis):
% git config --global user.name "$yourname"
% git config --global user.email "$mailaddress"
1. <a name="checkout">Checkout repository (anonymous):</a>
% git clone https://salsa.debian.org/kernel-team/initramfs-tools.git
% cd initramfs-tools
1. Checkout repository (with developer access):
% git clone ssh://git@salsa.debian.org/kernel-team/initramfs-tools.git
% cd initramfs-tools
***
## <a name="workflow">3. Workflow for daily work</a>
### <a name="newfeature">3.1 Implement new features</a>
1. Checkout new branch and switch to it:
% git checkout -b $username/short-descr-of-new-feature
1. Hack and commit work:
% $EDITOR $somefile
% git add $somefile
% git commit -s
**NOTE:** Use 'Closes: #BUGID' for closing a bugreport and 'Thanks: Fullname
&lt;mailaddress&gt;' for giving credits in your commit message. gbp dch will use
this information for generating the changelog using the --meta option later
on.
1. Finally push your branch to Salsa:
% git push origin $username/short-descr-of-new-feature
### <a name="merge">3.2 Merge branches</a>
1. Switch to the branch you want to merge:
% git checkout $username/new-feature
1. Rebase to master:
% git rebase master
1. Switch to master branch and merge:
% git checkout master
% git merge $username/new-feature
1. Push:
% git push
1. After branch is merged delete branch on server and locally:
% git push origin :$username/short-descr-of-new-feature
% git branch -d $username/short-descr-of-new-feature
1. If a branch is removed from the server it will stay locally. You can get of
any stale remote branches locally by executing:
% git remote prune origin
### <a name="test">3.3 Test specific branch</a>
1. Checkout a specific branch iff branch is not already present locally:
% git checkout -b somename/short-descr-of-new-feature origin/somename/short-descr-of-new-feature
1. Checkout a specific branch iff branch is already present locally:
% git checkout -b somename/short-descr-of-new-feature
1. Adjust debian/changelog accordingly:
% gbp dch --debian-branch="$(git branch | awk -F\*\ '/^* / { print $2}' )" \
--since="v$(dpkg-parsechangelog | awk '/^Version:/ {print $2}')" -S --id-length=7 --meta --multimaint-merge
1. Build package:
% gbp buildpackage --git-ignore-new --git-debian-branch="$(git branch | awk -F\*\ '/^* / { print $2}' )" --post-clean
***
### <a name="snapshot">3.4 Build snapshot version</a>
1. Adjust debian/changelog accordingly:
% gbp dch --debian-branch="$(git branch | awk -F\*\ '/^* / { print $2}' )" \
--since="v$(dpkg-parsechangelog | awk '/^Version:/ {print $2}')" -S --id-length=7 --meta --multimaint-merge
1. Build package:
% gbp buildpackage --git-debian-branch="$(git branch | awk -F\*\ '/^* / { print $2}' )" --post-clean [-us -uc]
***
## <a name="contribute">4. Contribute</a>
1. Create patch:
% git format-patch -s -p origin/master
1. Send patch file(s) to maintainers via mail (requires Debian package git-email):
% git send-email --to=initramfs-tools@packages.debian.org $PATCHFILE[S]
1. The development mailinglists are [debian-kernel@lists.debian.org](mailto:debian-kernel@lists.debian.org)
and [initramfs@vger.kernel.org](mailto:initramfs@vger.kernel.org).
Discussion of features, bugs and patches are more than welcome on one
of these lists.
***
## <a name="release">5. Release new version</a>
1. Creating changelog:
% gbp dch --debian-branch master --release --since HASH
or more dynamically:
% gbp dch --meta --release --since v$(dpkg-parsechangelog | awk '/^Version:/ {print $2}') --debian-branch="$(git branch | awk -F\*\ '/^* / { print $2}' )" --id-length=7 --meta --multimaint-merge
**NOTE:** we do not use history based sorting for the changelog entries but
sort them by author.
1. Releasing:
% git commit -a -s -m "Releasing version $version."
1. Tagging:
% git tag -s v"$version" -m "release $version"
1. Pushing:
% git push
% git push --tags
1. Build in chroot and upload to ftp-master.
1. Send mail announcing the new initramfs-tools version with subject
"initramfs-tools $VERSION release" to initramfs@vger.kernel.org,
debian-kernel@lists.debian.org + kernel-team@lists.ubuntu.com - including a
shortlog (generated through "git shortlog $TAG..").
***
## <a name="resources">6. Resources</a>
* [initramfs-tools git web interface](https://salsa.debian.org/kernel-team/initramfs-tools)
* [initramfs @ debian-wiki](https://wiki.debian.org/initramfs)
* [bugreports](https://bugs.debian.org/cgi-bin/pkgreport.cgi?src=initramfs-tools;dist=unstable)
* [initramfs-tools @ tracker](https://tracker.debian.org/pkg/initramfs-tools)
* [popcon graph](https://qa.debian.org/popcon.php?package=initramfs-tools)
* [bugreports @ ubuntu](https://bugs.launchpad.net/ubuntu/+source/initramfs-tools)
* [qa page @ ubuntu](http://status.qa.ubuntu.com/qapkgstatus/initramfs-tools)
***
## <a name="credits">7. Credits</a>
* Thanks to Daniel Baumann for his "[Debian Packaging with Git](http://documentation.debian-projects.org/other/debian-packaging-git/)" which inspired this document.
***
## <a name="license">8. License</a>
* This document is licensed under GPL v2 or any later version.
***
*-- Michael Prokop &lt;[mika@debian.org](mailto:mika@debian.org)&gt;,
Ben Hutchings &lt;[ben@decadent.org.uk](mailto:ben@decadent.org.uk)&gt;*
***

929
hook-functions Normal file
View File

@ -0,0 +1,929 @@
# -*- shell-script -*-
catenate_cpiogz() {
# Sanity check
if [ ! -e "${1}" ]; then
echo "W: catenate_cpiogz: arg1='${1}' does not exist." >&2
return
fi
cat "${1}" >>"${__TMPCPIOGZ}"
}
prepend_earlyinitramfs() {
# Sanity check
if [ ! -e "${1}" ]; then
echo "W: prepend_earlyinitramfs: arg1='${1}' does not exist." >&2
return
fi
cat "${1}" >>"${__TMPEARLYCPIO}"
}
# force_load module [args...]
force_load()
{
manual_add_modules "$1"
echo "${@}" >>"${DESTDIR}/conf/modules"
}
# Takes a file containing a list of modules to be added as an
# argument, figures out dependancies, and adds them.
#
# Input file syntax:
#
# # comment
# modprobe_module_name [args ...]
# [...]
#
add_modules_from_file()
{
# Sanity check
if [ ! -e "${1}" ]; then
echo "W: add_modules_from_file: arg1='${1}' does not exist." >&2
return
fi
grep '^[^#]' "${1}" | while read -r module args; do
[ -n "$module" ] || continue
force_load "${module}" "${args}"
done
}
# Is this module available?
have_module()
{
modprobe --set-version="${version?}" --ignore-install \
--show-depends "${1}" >/dev/null 2>&1
}
# Add dependent modules + eventual firmware
manual_add_modules()
{
local prefix kmod options firmware
if [ $# -eq 0 ]; then
return
fi
# modprobe --ignore-install inhibits processing of 'install'
# configuration lines, so that instead we will see 'insmod
# module.ko' as we want. However it also means that 'softdep'
# configuration lines and embedded softdep information is not
# processed. So we run twice, with and without this option.
# shellcheck disable=SC2034
{ modprobe --all --set-version="${version?}" --ignore-install --quiet --show-depends "$@";
modprobe --all --set-version="${version}" --quiet --show-depends "$@"; } |
while read -r prefix kmod options ; do
if [ "${prefix}" != "insmod" ]; then
continue
fi
copy_file module "${kmod}" || continue
# Add required firmware
for firmware in $(modinfo -k "${version}" -F firmware "${kmod}"); do
if [ -e "${DESTDIR}/lib/firmware/${firmware}" ] \
|| [ -e "${DESTDIR}/lib/firmware/${version}/${firmware}" ]; then
continue
fi
# Only print warning for missing fw of loaded module
# or forced loaded module
if [ ! -e "/lib/firmware/${firmware}" ] \
&& [ ! -e "/lib/firmware/${version}/${firmware}" ] ; then
# Only warn about missing firmware if
# /proc/modules exists
if [ ! -e /proc/modules ] ; then
continue
fi
kmod_modname="${kmod##*/}"
kmod_modname="${kmod_modname%%.*}"
if grep -q "^$kmod_modname\\>" /proc/modules "${CONFDIR}/modules"; then
echo "W: Possible missing firmware /lib/firmware/${firmware} for module ${kmod_modname}" >&2
fi
continue
fi
if [ -e "/lib/firmware/${version}/${firmware}" ]; then
copy_file firmware \
"/lib/firmware/${version}/${firmware}"
else
copy_file firmware "/lib/firmware/${firmware}"
fi
done
done
}
# $1 = file type (for logging)
# $2 = file to copy to initramfs
# $3 (optional) Name for the file on the initramfs
# Location of the image dir is assumed to be $DESTDIR
# If the target exists, we leave it and return 1.
# On any other error, we return >1.
copy_file() {
local type src target link_target
type="${1}"
src="${2}"
target="${3:-$2}"
[ -f "${src}" ] || return 2
if [ -d "${DESTDIR}/${target}" ]; then
target="${target}/${src##*/}"
fi
# Canonicalise usr-merged target directories
case "${target}" in
/bin/* | /lib* | /sbin/*) target="/usr${target}" ;;
esac
# check if already copied
[ -e "${DESTDIR}/${target}" ] && return 1
mkdir -p "${DESTDIR}/${target%/*}"
if [ -h "${src}" ]; then
# We don't need to replicate a chain of links completely;
# just link directly to the ultimate target
link_target="$(readlink -f "${src}")" || return $(($? + 1))
# Update source for the copy
src="${link_target}"
# Canonicalise usr-merged target directories
case "${link_target}" in
/bin/* | /lib* | /sbin/*) link_target="/usr${link_target}" ;;
esac
if [ "${link_target}" != "${target}" ]; then
[ "${verbose?}" = "y" ] && echo "Adding ${type}-link ${src}"
# Create a relative link so it always points
# to the right place
ln -rs "${DESTDIR}/${link_target}" "${DESTDIR}/${target}"
fi
# Copy the link target if it doesn't already exist
target="${link_target}"
[ -e "${DESTDIR}/${target}" ] && return 0
mkdir -p "${DESTDIR}/${target%/*}"
fi
[ "${verbose}" = "y" ] && echo "Adding ${type} ${src}"
cp -pP "${src}" "${DESTDIR}/${target}" || return $(($? + 1))
}
# $1 = executable to copy to initramfs, with library dependencies
# $2 (optional) Name for the file on the initramfs
# Location of the image dir is assumed to be $DESTDIR
# We never overwrite the target if it exists.
copy_exec() {
local src target x nonoptlib ret
src="${1}"
target="${2:-$1}"
copy_file binary "${src}" "${target}" || return $(($? - 1))
# Copy the dependant libraries
for x in $(env --unset=LD_PRELOAD ldd "${src}" 2>/dev/null | sed -e '
/\//!d;
/linux-gate/d;
/=>/ {s/.*=>[[:blank:]]*\([^[:blank:]]*\).*/\1/};
s/[[:blank:]]*\([^[:blank:]]*\) (.*)/\1/' 2>/dev/null); do
# Try to use non-optimised libraries where possible.
# We assume that all HWCAP libraries will be in tls,
# sse2, vfp or neon.
nonoptlib=$(echo "${x}" | sed -e 's#/lib/\([^/]*/\)\?\(tls\|i686\|sse2\|neon\|vfp\).*/\(lib.*\)#/lib/\1\3#')
nonoptlib=$(echo "${nonoptlib}" | sed -e 's#-linux-gnu/\(tls\|i686\|sse2\|neon\|vfp\).*/\(lib.*\)#-linux-gnu/\2#')
if [ -e "${nonoptlib}" ]; then
x="${nonoptlib}"
fi
# Handle common dlopen() dependency (Debian bug #950254)
case "${x}" in
*/libpthread.so.*)
copy_exec "/lib/libgcc_s.so.1" || copy_exec "${x%/*}/libgcc_s.so.1" || return
;;
esac
copy_file library "${x}" || {
ret=$?
[ ${ret} = 1 ] || return $((ret - 1))
}
done
}
# Copy entire subtrees to the initramfs
copy_modules_dir()
{
local kmod first exclude
local modules=
local dir="$1"
shift
if ! [ -d "${MODULESDIR}/${dir}" ]; then
return;
fi
if [ "${verbose}" = "y" ]; then
echo "Copying module directory ${dir}"
if [ $# -ge 1 ]; then
echo "(excluding $*)"
fi
fi
# Build up an expression for find
first=true
for exclude in "$@"; do
# Change .ko suffix in exclusion to .ko*
if [ "${exclude%.ko}" != "${exclude}" ]; then
exclude="${exclude}*"
fi
$first && set --
set -- "$@" -name "${exclude}" -prune -o
first=false
done
# shellcheck disable=SC2044
for kmod in $(find "${MODULESDIR}/${dir}" "$@" -name '*.ko*' -printf '%f\n'); do
modules="$modules ${kmod%%.*}"
done
# shellcheck disable=SC2086
manual_add_modules $modules
}
# walk /sys for relevant modules
sys_walk_mod_add()
{
local driver_path module device_path modalias
device_path="$1"
while [ "${device_path}" != "/sys" ]; do
# device modalias
if [ -e "${device_path}/modalias" ]; then
modalias=$(cat "${device_path}/modalias")
if [ -n "${modalias}" ]; then
manual_add_modules "${modalias}"
fi
fi
# current driver module
driver_path="$(readlink -f "${device_path}/driver/module")"
if [ -e "$driver_path" ]; then
module="$(basename "$(readlink -f "$driver_path")")"
if [ -n "${module}" ]; then
manual_add_modules "${module}"
fi
fi
device_path="$(dirname "${device_path}")"
done
}
nvme_dev_sys_walk_mod_add()
{
local dev_sys_path component nvme_sys_path
dev_sys_path="$(readlink -f "$1")"
if ! echo "$dev_sys_path" | grep -q "nvme-subsys"; then
return
fi
for component in "$dev_sys_path"/nvme* ; do
if [ -L "$component" ] ; then
nvme_sys_path=$(readlink -f "$component")
sys_walk_mod_add "$nvme_sys_path"
fi
done
}
block_dev_sys_walk_mod_add()
{
local dev_sys_path disk_sys_path component
# Resolve symlink so sys_walk_mod_add can walk up the hierarchy
dev_sys_path="$(readlink -f "$1")"
# Find whole disk from partition
if grep -q "^DEVTYPE=partition$" "$dev_sys_path/uevent"; then
disk_sys_path="$dev_sys_path/.."
else
disk_sys_path="$dev_sys_path"
fi
# Iterate over component of a layered device
find "$disk_sys_path/slaves" -mindepth 1 -maxdepth 1 | while read -r component; do
block_dev_sys_walk_mod_add "$component"
done
nvme_dev_sys_walk_mod_add "$disk_sys_path/device"
sys_walk_mod_add "${dev_sys_path}"
}
block_dev_mod_add()
{
local dev_node dev_num dev_sys_path
dev_node="$1"
# Look up device number and convert to decimal as it appears in sysfs
dev_num="$(stat -L -c %t:%T "$dev_node")"
dev_num="$((0x${dev_num%:*})):$((0x${dev_num#*:}))"
# Look up device in sysfs
dev_sys_path="/sys/dev/block/$dev_num"
if [ ! -d "$dev_sys_path" ]; then
echo "mkinitramfs: for device ${dev_node} missing ${dev_sys_path}" >&2
echo "mkinitramfs: workaround is MODULES=most" >&2
echo "mkinitramfs: Error please report the bug" >&2
exit 1
fi
block_dev_sys_walk_mod_add "$dev_sys_path"
}
# Copy all loaded or built-in modules matching the given pattern.
# Pattern mustn't include directory or '.ko' suffix but should use
# '[-_]' to allow for differences in naming between /sys/module and
# modules.builtin.
add_loaded_modules()
{
local pattern="$1"
local module builtin
builtin="/lib/modules/$(uname -r)/modules.builtin"
for module in /sys/module/$pattern; do
if [ -d "$module" ]; then
manual_add_modules "$(basename "$module")"
fi
done
if [ -f "$builtin" ]; then
while read -r module; do
case "$module" in
*/$pattern.ko)
manual_add_modules "$(basename "$module" .ko)"
;;
esac
done < "$builtin"
fi
}
# find and only copy modules relevant to a mountpoint
dep_add_modules_mount()
{
local dir dev_node FSTYPE
dir="$1"
# require mounted sysfs
if [ ! -d /sys/devices/ ]; then
echo "mkinitramfs: MODULES dep requires mounted sysfs on /sys" >&2
exit 1
fi
# find out block device + fstype
# shellcheck disable=SC2034
eval "$(while read -r dev mp fs opts rest ; do \
[ "$mp" = "$dir" ] && [ "$fs" != "rootfs" ] \
&& printf "dev_node=%s\\nFSTYPE=%s" "$dev" "$fs"\
&& break; done < /proc/mounts)"
# Only the root mountpoint has to exist; do nothing if any other
# directory is not a mountpoint.
if [ "$dir" != / ] && [ -z "$dev_node" ]; then
return
fi
# handle ubifs and return since ubifs is mounted on char devices
# but most of the commands below only work with block devices.
if [ "${FSTYPE}" = "ubifs" ]; then
manual_add_modules "${FSTYPE}"
return
fi
if [ "${FSTYPE}" = "zfs" ]; then
manual_add_modules "${FSTYPE}"
# ZFS uses the name of a filesystem instead of a device. Find
# the devices that make up the pool containing the specified
# filesystem, and add the appropriate driver for each device.
local poolname="${dev_node%%/*}"
# shellcheck disable=SC2034
zpool list -vPL "$poolname" | while read -r dev ignored; do
# Ignore non-leaf vdevs by skipping anything that doesn't
# look like an absolute path
echo "$dev" | grep -q '^/' && block_dev_mod_add "$dev"
done
return
fi
if [ "$dir" = / ] && [ "${dev_node}" = "/dev/root" ] ; then
if [ -b "${dev_node}" ]; then
# Match it to the canonical device name by UUID
dev_node="/dev/disk/by-uuid/"$(blkid -o value -s UUID "${dev_node}") 2>/dev/null
else
# Does not exist in our namespace, so look at the
# kernel command line
dev_node=
# shellcheck disable=SC2013
for arg in $(cat /proc/cmdline); do
case "$arg" in
root=*)
dev_node="${arg#root=}"
if [ "${dev_node#/dev/}" = "$dev_node" ]; then
dev_node="/dev/$dev_node"
fi
;;
--)
break
;;
*)
;;
esac
done
fi
fi
# recheck device
if [ -z "$dev_node" ] || ! dev_node="$(readlink -f "${dev_node}")" \
|| ! [ -b "$dev_node" ]; then
echo "mkinitramfs: failed to determine device for $dir" >&2
echo "mkinitramfs: workaround is MODULES=most, check:" >&2
echo "grep -r MODULES ${CONFDIR}" >&2
echo "" >&2
echo "Error please report bug on initramfs-tools" >&2
echo "Include the output of 'mount' and 'cat /proc/mounts'" >&2
exit 1
fi
# do not trust mount, check superblock
FSTYPE=$(blkid -o value -s TYPE "${dev_node}")
if [ -z "${FSTYPE}" ]; then
echo "mkinitramfs: unknown fstype on device ${dev_node}" >&2
echo "mkinitramfs: workaround is MODULES=most" >&2
echo "Error please report bug on initramfs-tools" >&2
exit 1
fi
# Add filesystem
manual_add_modules "${FSTYPE}"
block_dev_mod_add "$dev_node"
}
dep_add_modules()
{
local device dev_node
local modules=
dep_add_modules_mount /
dep_add_modules_mount /usr
if [ -n "${RESUME}" ]; then
dev_node="$(resolve_device "${RESUME}")"
if [ -n "${dev_node}" ]; then
block_dev_mod_add "${dev_node}"
fi
fi
# sys walk some important device classes
for class in backlight extcon gpio phy pwm regulator rtc; do
for device in "/sys/class/$class"/*; do
device="$(readlink -f "$device")" \
&& sys_walk_mod_add "$device"
done
done
# clk, USB-PHY and pinctrl devices are outside the device model (!) so
# match loaded modules by name
add_loaded_modules 'clk[-_]*'
add_loaded_modules 'phy[-_]*'
add_loaded_modules 'pinctrl[-_]*'
# Sys walk keyboards. We identify keyboards as input devices
# that can generate at least key events 1-31; udev has the
# same heuristic. Note that the format of the bitmap
# properties depends on the word size of the process reading
# the uevent file!
for device in /sys/class/input/input*; do
if grep -qs "^KEY=.*fffffff[ef]$" "${device}/uevent"; then
sys_walk_mod_add "$(readlink -f "$device")"
fi
done
# Sys walk graphics for machines that don't have a generic framebuffer
# device and wouldn't have a working video console otherwise.
walk_graphics=yes
for device in /sys/bus/platform/drivers/efi-framebuffer/* \
/sys/bus/platform/drivers/platform-framebuffer/* \
/sys/bus/platform/drivers/simple-framebuffer/* \
/sys/bus/platform/drivers/vesa-framebuffer/*; do
if [ -d "$device" ]; then
walk_graphics=no
break
fi
done
if [ "$walk_graphics" = "yes" ]; then
for device in /sys/class/graphics/*; do
device="$(readlink -f "$device")" \
&& sys_walk_mod_add "$device"
done
fi
# catch old-style IDE
if [ -e /sys/bus/ide/devices/ ]; then
modules="$modules ide-gd_mod ide-cd"
fi
if [ -e /sys/bus/scsi/devices/ ]; then
modules="$modules sd_mod"
fi
if [ -e /sys/bus/mmc/devices/ ]; then
modules="$modules mmc_block"
fi
if [ -e /sys/bus/virtio ] ; then
modules="$modules virtio_pci virtio_mmio"
fi
if [ -e /sys/bus/i2o/devices/ ]; then
force_load i2o_block
force_load i2o_config
fi
if [ -e /sys/bus/ps3_system_bus/ ]; then
modules="$modules ps3disk ps3rom ps3-gelic ps3_sys_manager"
fi
if [ -e /sys/bus/vio/ ]; then
modules="$modules sunvnet sunvdc"
fi
if [ -e /sys/devices/platform/edp-panel ]; then
sys_walk_mod_add /sys/devices/platform/edp-panel
fi
# shellcheck disable=SC2086
manual_add_modules $modules
}
# The modules "most" classes added per default to the initramfs
auto_add_modules()
{
local arg
local modules=
if [ "$#" -eq 0 ] ; then
set -- base net ide scsi block ata i2o dasd ieee1394 firewire mmc usb_storage fb virtual nx
fi
for arg in "$@" ; do
case "$arg" in
base)
modules="$modules btrfs ext2 ext3 ext4 f2fs"
modules="$modules isofs jfs reiserfs squashfs udf xfs"
modules="$modules nfs nfsv2 nfsv3 nfsv4"
modules="$modules af_packet atkbd i8042 psmouse"
modules="$modules virtio_pci virtio_mmio"
# nls not automatically pulled in as ubuntu has built-in vfat
modules="$modules vfat nls_cp437 nls_iso8859-1"
# Include most USB host and dual-role drivers
copy_modules_dir kernel/drivers/usb/host \
hwa-hc.ko sl811_cs.ko sl811-hcd.ko \
u132-hcd.ko whci-hcd.ko
copy_modules_dir kernel/drivers/usb/c67x00
copy_modules_dir kernel/drivers/usb/chipidea
copy_modules_dir kernel/drivers/usb/dwc2
copy_modules_dir kernel/drivers/usb/dwc3
copy_modules_dir kernel/drivers/usb/isp1760
copy_modules_dir kernel/drivers/usb/musb
copy_modules_dir kernel/drivers/usb/renesas_usbhs
# and any extcon drivers for USB
modules="$modules extcon-usb-gpio extcon-usbc-cros-ec"
# Add the axp20x_usb_power power supply driver,
# required to initialize the USB host controllers
# on a number of armhf systems
modules="$modules axp20x_usb_power"
# Include all keyboard drivers and all HID drivers
# unless we're sure they don't support keyboards.
# hid-*ff covers various game controllers with
# force feedback.
copy_modules_dir kernel/drivers/input/keyboard
copy_modules_dir kernel/drivers/hid \
'hid-*ff.ko' hid-a4tech.ko hid-cypress.ko \
hid-dr.ko hid-elecom.ko hid-gyration.ko \
hid-icade.ko hid-kensington.ko hid-kye.ko \
hid-lcpower.ko hid-magicmouse.ko \
hid-multitouch.ko hid-ntrig.ko \
hid-petalynx.ko hid-picolcd.ko hid-pl.ko \
hid-ps3remote.ko hid-quanta.ko \
'hid-roccat-ko*.ko' hid-roccat-pyra.ko \
hid-saitek.ko hid-sensor-hub.ko hid-sony.ko \
hid-speedlink.ko hid-tivo.ko hid-twinhan.ko \
hid-uclogic.ko hid-wacom.ko hid-waltop.ko \
hid-wiimote.ko hid-zydacron.ko
# needed to access keyboard on some ChromeOS devices
modules="$modules cros_ec_spi"
# Any of these might be needed by other drivers
copy_modules_dir kernel/drivers/bus
copy_modules_dir kernel/drivers/clk
copy_modules_dir kernel/drivers/gpio
copy_modules_dir kernel/drivers/i2c/busses
copy_modules_dir kernel/drivers/i2c/muxes
copy_modules_dir kernel/drivers/mfd
copy_modules_dir kernel/drivers/phy
copy_modules_dir kernel/drivers/pinctrl
copy_modules_dir kernel/drivers/regulator
copy_modules_dir kernel/drivers/spi
copy_modules_dir kernel/drivers/usb/phy
# Needed for periodic fsck
copy_modules_dir kernel/drivers/rtc
;;
net)
copy_modules_dir kernel/drivers/net \
appletalk arcnet bonding can dummy.ko \
hamradio hippi ifb.ko irda macvlan.ko \
macvtap.ko pcmcia sb1000.ko team tokenring \
tun.ko usb veth.ko wan wimax wireless \
xen-netback.ko
modules="$modules 8021q"
;;
ide)
copy_modules_dir kernel/drivers/ide
;;
mmc)
copy_modules_dir kernel/drivers/mmc
;;
scsi)
copy_modules_dir kernel/drivers/scsi
modules="$modules mptfc mptsas mptscsih mptspi zfcp"
;;
ata)
copy_modules_dir kernel/drivers/ata
;;
block)
copy_modules_dir kernel/drivers/block
copy_modules_dir kernel/drivers/nvme
modules="$modules vmd"
;;
ubi)
modules="$modules deflate zlib lzo ubi ubifs"
;;
ieee1394)
modules="$modules ohci1394 sbp2"
;;
firewire)
modules="$modules firewire-ohci firewire-sbp2"
;;
i2o)
modules="$modules i2o_block"
;;
dasd)
modules="$modules dasd_diag_mod dasd_eckd_mod dasd_fba_mod"
;;
usb_storage)
copy_modules_dir kernel/drivers/usb/storage
;;
fb)
# For machines that don't have a generic framebuffer device.
modules="$modules rockchipdrm pwm-cros-ec pwm_bl panel-simple"
;;
virtual)
# Hyper-V
modules="$modules hv_vmbus hv_utils hv_netvsc hv_mouse hv_storvsc hyperv-keyboard"
;;
nx)
# PowerPC NX Crypto Coprocessor
modules="$modules nx-compress nx-compress-crypto nx-compress-platform"
modules="$modules nx-compress-pseries nx-compress-powernv 842-decompress"
;;
esac
done
# shellcheck disable=SC2086
manual_add_modules $modules
}
# 'depmod' only looks at symbol dependencies and the 'softdep' module
# information field; there is no way for modules to declare weaker
# dependencies (modules that *might* be needed at run-time) through
# module information, Until this is fixed, we need to handle those
# hidden dependencies.
hidden_dep_add_modules()
{
# shellcheck disable=SC2046
manual_add_modules $(
{
cat "${DESTDIR}/lib/modules/${version}/modules.builtin"
find "${DESTDIR}/lib/modules/${version}/kernel" -name '*.ko*'
} |
while read -r module; do
module="${module##*/}"
module="${module%%.*}"
case "$module" in
libcrc32c)
echo crc32c
;;
ubifs)
echo deflate zlib lzo
;;
btrfs)
echo crc32c
;;
f2fs)
echo crc32
;;
mlx4_core)
echo mlx4_ib
;;
mlx5_core)
echo mlx5_ib
;;
i8042)
echo psmouse
;;
nvme)
echo vmd
;;
spi-rockchip)
echo pl330
;;
dw_mmc-rockchip)
echo rockchip-io-domain
;;
esac
done
)
}
# Find the source for a script file. This is needed to work around
# temporary directories mounted with the noexec option. The source
# will be on / or /usr which must be executable.
get_source()
{
if [ -z "$scriptdir" ]; then
echo "${initdir}/$1"
elif [ -f "${CONFDIR}${scriptdir}/$1" ]; then
echo "${CONFDIR}${scriptdir}/$1"
else
echo "/usr/share/initramfs-tools${scriptdir}/$1"
fi
}
set_initlist()
{
unset initlist
for si_x in "${initdir}"/*; do
# skip empty dirs without warning
[ "${si_x}" = "${initdir}/*" ] && return
# only allow variable name chars
case ${si_x#${initdir}/} in
*[![:alnum:]\._-]*)
[ "${verbose}" = "y" ] \
&& echo "$si_x ignored: not alphanumeric or '_' file" >&2
continue
;;
esac
# skip directories
if [ -d "${si_x}" ]; then
[ "${verbose}" = "y" ] \
&& echo "$si_x ignored: a directory" >&2
continue
fi
si_x="$(get_source "${si_x#${initdir}/}")"
# skip non executable scripts
if [ ! -x "${si_x}" ]; then
[ "${verbose}" = "y" ] \
&& echo "$si_x ignored: not executable" >&2
continue
fi
# skip bad syntax
if ! sh -n "${si_x}" ; then
[ "${verbose}" = "y" ] \
&& echo "$si_x ignored: bad syntax" >&2
continue
fi
initlist="${initlist:-} ${si_x##*/}"
done
}
get_prereq_pairs()
{
set_initlist
for gp_x in ${initlist:-}; do
echo "${gp_x} ${gp_x}"
gp_src="$(get_source "$gp_x")"
prereqs=$("${gp_src}" prereqs)
for prereq in ${prereqs}; do
echo "${prereq} ${gp_x}"
done
done
}
# cache boot scripts order
cache_run_scripts()
{
DESTDIR=${1}
scriptdir=${2}
initdir=${DESTDIR}${scriptdir}
[ ! -d "${initdir}" ] && return
true > "${initdir}/ORDER"
runlist=$(get_prereq_pairs | tsort)
for crs_x in ${runlist}; do
[ -f "${initdir}/${crs_x}" ] || continue
echo "${scriptdir}/${crs_x} \"\$@\"" >> "${initdir}/ORDER"
echo "[ -e /conf/param.conf ] && . /conf/param.conf" >> "${initdir}/ORDER"
done
}
call_scripts()
{
set -e
for cs_x in ${runlist}; do
[ -f "${initdir}/${cs_x}" ] || continue
if [ x"$call_scripts_optional" = "xy" ]; then
option=$(sed '/^OPTION=/!d;$d;s/^OPTION=//;s/[[:space:]]*$//' "${initdir}/${cs_x}")
# shellcheck disable=SC1083,2086
[ -z "${option}" ] || eval test -n \"\${$option}\" -a \"\${$option}\" != \"n\" || continue
fi
# mkinitramfs verbose output
if [ "${verbose}" = "y" ]; then
echo "Calling hook ${cs_x}"
fi
"${initdir}/${cs_x}" && ec=$? || ec=$?
# allow hooks to abort build:
if [ "$ec" -ne 0 ]; then
echo "E: ${initdir}/${cs_x} failed with return $ec." >&2
# only errexit on mkinitramfs
[ -n "${version}" ] && exit $ec
fi
# allow boot scripts to modify exported boot parameters
if [ -e /conf/param.conf ]; then
. /conf/param.conf
fi
done
set +e
}
run_scripts()
{
scriptdir=${2:-}
initdir=${1}
[ ! -d "${initdir}" ] && return
runlist=$(get_prereq_pairs | tsort)
call_scripts "$scriptdir"
}
run_scripts_optional()
{
call_scripts_optional=y
run_scripts "$@"
}
add_dns() {
local destdir="$1" nsswitch="" lib="" libdir="" f="" d=""
# find the multiarch lib dir (for example /lib/x86_64-linux-gnu)
# by finding a directory with libc.so.6.
for d in /lib/* /lib; do
for f in "$d"/libc.so.?; do [ -f "$f" ] && break; done
[ -f "$f" ] && libdir="$d" && break
done
if [ -z "$libdir" ]; then
echo "WARNING: no libdir found for adding dns." 1>&2
return
fi
nsswitch="$destdir/etc/nsswitch.conf"
if ! grep -qs "^hosts:" "$nsswitch"; then
echo "hosts: files dns" >> "$nsswitch"
fi
local found=""
for lib in libnss_files libnss_dns libresolv; do
found=""
for f in "$libdir/$lib.so".?; do
[ -e "$f" ] || continue
[ "$verbose" = "y" ] && echo "dns: $lib: $f"
copy_file library "$f"
found="$f"
done
[ -n "$found" ] || echo "WARNING: no $libdir/$lib.? file" 1>&2
done
return 0
}

156
hooks/compcache Executable file
View File

@ -0,0 +1,156 @@
#!/bin/sh
set -e
if [ "$1" = prereqs ]; then
exit 0
fi
. /usr/share/initramfs-tools/hook-functions
number=
suffix=
# shellcheck disable=SC2046
eval $(printf "%s" "$COMPCACHE_SIZE" | \
sed -nre 's/^ *([1-9][0-9]*) *([%KMGT]) *$/number="\1"; suffix="\2";/p')
if [ -z "$number" ] || [ -z "$suffix" ]; then
exit 0
fi
if have_module zram; then
name=zram
manual_add_modules zram
elif have_module ramzswap; then
name=ramzswap
manual_add_modules ramzswap
elif have_module compcache; then
name=compcache
manual_add_modules compcache
else
exit 0
fi
copy_exec /sbin/swapon
copy_exec /sbin/mkswap
copy_exec /usr/lib/initramfs-tools/bin/rzscontrol /sbin
mem_total="\$(sed -nre 's/^MemTotal:\\s*([0-9]+) kB\$/\\1/p' /proc/meminfo)"
case "$suffix" in
%) kbytes="\$(($mem_total * $number / 100))" ;;
K) kbytes=$((number)) ;;
M) kbytes=$((number * 1024)) ;;
G) kbytes=$((number * 1024 * 1024)) ;;
T) kbytes=$((number * 1024 * 1024 * 1024)) ;;
esac
cat >"$DESTDIR"/sbin/compcache-enable <<'EOF'
#!/bin/sh
if [ "$#" != 3 ]; then
echo "Usage: $0 <type> <size> <device>" 1>&2
exit 1
fi
type="$1"
size="$2"
device="$3"
number=
suffix=
eval $(printf "%s" "$size" | \
sed -nre 's/^ *([1-9][0-9]*) *([%KMGT]) *$/number="\1"; suffix="\2";/p')
mem_total="$(sed -nre 's/^MemTotal:\s*([0-9]+) kB$/\1/p' /proc/meminfo)"
case "$suffix" in
%) kbytes="$(($mem_total * $number / 100))" ;;
K) kbytes=$(($number)) ;;
M) kbytes=$(($number * 1024)) ;;
G) kbytes=$(($number * 1024 * 1024)) ;;
T) kbytes=$(($number * 1024 * 1024 * 1024)) ;;
esac
bytes="$(($kbytes * 1024))"
if [ "$type" = zram ]; then
echo "$bytes" >/sys/block/$device/disksize && \
/sbin/mkswap "/dev/$device" >/dev/null
elif [ "$type" = ramzswap ]; then
/sbin/rzscontrol "/dev/$device" --disksize_kb="$kbytes" --init
fi
/sbin/swapon -p 100 "/dev/$device" 2>/dev/null
exit 0
EOF
chmod 0755 "$DESTDIR"/sbin/compcache-enable
mkdir -p "$DESTDIR"/etc/udev/rules.d
if [ "$name" = zram ]; then
cat >"$DESTDIR"/etc/udev/rules.d/80-compcache.rules <<EOF
KERNEL=="zram0", ACTION=="add", \\
RUN+="/sbin/compcache-enable zram $COMPCACHE_SIZE zram0"
EOF
elif [ "$name" = ramzswap ]; then
cat >"$DESTDIR"/etc/udev/rules.d/80-compcache.rules <<EOF
KERNEL=="ramzswap0", ACTION=="add", \\
RUN+="/sbin/compcache-enable ramzswap $COMPCACHE_SIZE ramzswap0"
EOF
else
cat >"$DESTDIR"/etc/udev/rules.d/80-compcache.rules <<EOF
KERNEL=="ramzswap0", ACTION=="add", \\
RUN+="/sbin/compcache-enable compcache $COMPCACHE_SIZE ramzswap0"
EOF
fi
cat >"$DESTDIR"/scripts/init-top/compcache <<EOF
#!/bin/sh
PREREQ=""
prereqs()
{
echo "\$PREREQ"
}
case \$1 in
prereqs)
prereqs
exit 0
;;
esac
# find total amount of available ram
TOTAL_RAM=\$( grep MemTotal /proc/meminfo |tr -d ': [A-Z][a-z]')
# Do not use compcache on the liveCD if we have more than 512M
if [ "\${BOOT}" = "casper" ]; then
if [ "\${TOTAL_RAM}" -gt 524288 ]; then
exit 0
fi
fi
for x in \$(cat /proc/cmdline); do
case \${x} in
nocompcache)
exit 0
;;
esac
done
EOF
if [ "$name" = zram ]; then
cat >>"$DESTDIR"/scripts/init-top/compcache <<EOF
modprobe -q --ignore-install zram
EOF
elif [ "$name" = ramzswap ]; then
cat >>"$DESTDIR"/scripts/init-top/compcache <<EOF
modprobe -q --ignore-install ramzswap
EOF
else
cat >>"$DESTDIR"/scripts/init-top/compcache <<EOF
modprobe -q --ignore-install compcache compcache_size_kbytes="$kbytes"
EOF
fi
chmod 0755 "$DESTDIR"/scripts/init-top/compcache
# vim:set et sw=2 sts=2:

24
hooks/fixrtc Executable file
View File

@ -0,0 +1,24 @@
#!/bin/sh -e
# initramfs hook for fixing broken rtc clock
# without battery
PREREQ="udev"
# Output pre-requisites
prereqs()
{
echo "$PREREQ"
}
case "$1" in
prereqs)
prereqs
exit 0
;;
esac
. /usr/share/initramfs-tools/hook-functions
# We use the full dumpe2fs because we basically get it for "free"
# if we're already on extN due to e2fsck pulling in all the libs:
copy_exec /sbin/dumpe2fs /sbin

43
hooks/framebuffer Executable file
View File

@ -0,0 +1,43 @@
#!/bin/sh
# shellcheck disable=SC2034
OPTION=FRAMEBUFFER
PREREQ=""
prereqs()
{
echo "$PREREQ"
}
case $1 in
# get pre-requisites
prereqs)
prereqs
exit 0
;;
esac
. /usr/share/initramfs-tools/hook-functions
copy_modules_dir kernel/drivers/char/agp
copy_modules_dir kernel/drivers/gpu
copy_modules_dir kernel/ubuntu/i915
manual_add_modules fbcon
manual_add_modules vesafb
manual_add_modules vga16fb
manual_add_modules vboxvideo
for x in "${MODULESDIR}"/initrd/*; do
x=${x##*/}
x=${x%.*}
case ${x} in
'*')
break
;;
*fb)
;;
esac
manual_add_modules "${x}"
done

98
hooks/fsck Executable file
View File

@ -0,0 +1,98 @@
#!/bin/sh
PREREQ=""
prereqs()
{
echo "$PREREQ"
}
# Find a specific fstab entry
# $1=mountpoint
# $2=fstype (optional)
_read_fstab_entry () {
# Not found by default.
echo "MNT_FSNAME="
echo "MNT_DIR="
echo "MNT_TYPE="
for file in /etc/fstab /etc/fstab.d/*.fstab; do
if [ -f "$file" ]; then
# shellcheck disable=SC2034
while read -r MNT_FSNAME MNT_DIR MNT_TYPE MNT_OPTS MNT_FREQ MNT_PASS MNT_JUNK; do
case "$MNT_FSNAME" in
""|\#*)
continue;
;;
esac
if [ "$MNT_DIR" = "$1" ]; then
if [ -n "$2" ]; then
[ "$MNT_TYPE" = "$2" ] || continue;
fi
echo "MNT_FSNAME=$MNT_FSNAME"
echo "MNT_DIR=$MNT_DIR"
echo "MNT_TYPE=$MNT_TYPE"
echo "MNT_PASS=$MNT_PASS"
break 2
fi
MNT_DIR=""
done < "$file"
fi
done
}
# Find a specific fstab entry and print its type (if found, and pass != 0)
# $1=mountpoint
get_fsck_type_fstab () {
eval "$(_read_fstab_entry "$1")"
# Not found by default.
if [ "$1" = "$MNT_DIR" ] && [ "$MNT_PASS" != 0 ]; then
# Ignore filesystem type for /, as it is not available and
# therefore never used at boot time
if [ "${MNT_DIR}" = "/" ] || [ "${MNT_TYPE}" = "auto" ]; then
MNT_FSNAME="$(resolve_device "${MNT_FSNAME}")"
if ! get_fstype "${MNT_FSNAME}"; then
echo "W: Couldn't identify type of $2 file system for fsck hook" >&2
fi
else
echo "${MNT_TYPE}"
fi
fi
}
get_fsck_types() {
get_fsck_type_fstab / root
get_fsck_type_fstab /usr /usr
}
case $1 in
prereqs)
prereqs
exit 0
;;
esac
if [ ! -x /sbin/fsck ]; then
exit 0
fi
. /usr/share/initramfs-tools/scripts/functions
. /usr/share/initramfs-tools/hook-functions
fsck_types="$(get_fsck_types | sort | uniq)"
if [ -z "$fsck_types" ]; then
exit 0
fi
copy_exec /sbin/fsck
copy_exec /sbin/logsave
for type in $fsck_types; do
if prog="$(command -v "fsck.${type}")"; then
copy_exec "$prog"
else
echo "W: /sbin/fsck.${type} doesn't exist, can't install to initramfs" >&2
fi
done

112
hooks/resume Executable file
View File

@ -0,0 +1,112 @@
#!/bin/sh
PREREQ=""
prereqs()
{
echo "$PREREQ"
}
case $1 in
# get pre-requisites
prereqs)
prereqs
exit 0
;;
esac
. /usr/share/initramfs-tools/scripts/functions
# First check if a location is set and is a valid swap partition.
# If so, the config file will be copied in and there is nothing to do.
if [ -n "$RESUME" ] && [ "$RESUME" != auto ]; then
if [ "$RESUME" = none ]; then
exit 0
fi
if resume_dev_node="$(resolve_device "$RESUME")" && \
blkid -p -n swap "$resume_dev_node" >/dev/null 2>&1; then
exit 0
fi
echo >&2 "W: initramfs-tools configuration sets RESUME=$RESUME"
echo >&2 "W: but no matching swap device is available."
fi
# If we were not explicitly requested to select a device, or the -v
# option is used, report that we are doing so
report_auto()
{
test "${verbose?}" != y && test "$RESUME" = auto || echo "I: $*"
}
# Report in excruciating detail if the -v option is used
report_verbose()
{
test "${verbose?}" != y || echo "I: $*"
}
report_verbose "Configuration sets RESUME=$RESUME"
# Try to autodetect the RESUME partition, using biggest swap device that
# is not ephemeral. We need to be able to read the listed swap partitions.
resume_auto=
if ! ischroot && [ -r /proc/swaps ]; then
# shellcheck disable=SC2013
for resume_auto in $(grep ^/dev/ /proc/swaps | sort -rnk3 | cut -d " " -f 1); do
report_verbose "Checking swap device $resume_auto"
ephemeral=false
dm_name="$(dmsetup info -c --noheadings -o name "$resume_auto" 2>/dev/null)"
# dm-crypt is ephemeral if the key file is /dev/urandom
if [ -n "$dm_name" ] && [ -e /etc/crypttab ]; then
report_verbose "$resume_auto has device-mapper name $dm_name; checking crypttab"
# shellcheck disable=SC2034
while read -r cryptdev srcdev keyfile junk; do
report_verbose "Found cryptdev=$cryptdev keyfile=$keyfile"
if [ "$cryptdev" = "$dm_name" ] && [ "$keyfile" = /dev/urandom ]; then
report_verbose "Rejecting $resume_auto since it has no permanent key"
ephemeral=true
fi
done < /etc/crypttab
fi
# zram is ephemeral
case "$resume_auto" in
/dev/zram*)
report_verbose "Rejecting $resume_auto since it is zram"
ephemeral=true
;;
esac
$ephemeral || break
done
if $ephemeral; then
resume_auto=
fi
if [ -n "$resume_auto" ]; then
if [ -n "$dm_name" ]; then
resume_auto_canon="/dev/mapper/$dm_name"
elif UUID=$(blkid -s UUID -o value "$resume_auto"); then
resume_auto_canon="UUID=$UUID"
else
resume_auto_canon=
fi
report_auto "The initramfs will attempt to resume from $resume_auto"
if [ -n "$resume_auto_canon" ]; then
report_auto "($resume_auto_canon)"
resume_auto="$resume_auto_canon"
fi
report_auto "Set the RESUME variable to override this."
fi
fi
# Write selected resume device to intramfs conf.d
if [ "$RESUME" = auto ] || [ -n "$resume_auto" ]; then
# If we were explicitly requested to select a device, and we failed,
# report that
if [ -z "$resume_auto" ]; then
echo >&2 "W: initramfs-tools failed to select a resume device"
fi
echo "RESUME=${resume_auto}" > "${DESTDIR}/conf/conf.d/zz-resume-auto"
fi

71
hooks/thermal Executable file
View File

@ -0,0 +1,71 @@
#!/bin/sh
PREREQ=""
prereqs()
{
echo "$PREREQ"
}
case $1 in
# get pre-requisites
prereqs)
prereqs
exit 0
;;
esac
# Hooks for loading thermal bits into the initramfs
. /usr/share/initramfs-tools/hook-functions
case "$DPKG_ARCH" in
# copy the right modules
powerpc|ppc64)
# Only G5 Mac machines need to load
# windfarm_core or one of the windfarm_pm* modules.
[ -r /proc/cpuinfo ] || exit 0
MODEL="$(grep model /proc/cpuinfo)"
MODEL="${MODEL##*: }"
case "$MODEL" in
RackMac3,1)
force_load windfarm_rm31
;;
PowerMac7,2|PowerMac7,3)
force_load windfarm_pm72
;;
PowerMac8,1|PowerMac8,2)
force_load windfarm_pm81
;;
PowerMac9,1)
force_load windfarm_pm91
;;
PowerMac11,2)
force_load windfarm_pm112
;;
PowerMac12,1)
force_load windfarm_pm121
;;
*)
# No other machine needs windfarm_* modules on initrd.
exit 0
;;
esac
manual_add_modules windfarm_core
manual_add_modules windfarm_cpufreq_clamp
manual_add_modules windfarm_lm75_sensor
manual_add_modules windfarm_max6690_sensor
manual_add_modules windfarm_pid
manual_add_modules windfarm_smu_controls
manual_add_modules windfarm_smu_sat
manual_add_modules windfarm_smu_sensors
;;
i386|amd64|ia64)
manual_add_modules fan
manual_add_modules thermal
;;
esac

375
init Executable file
View File

@ -0,0 +1,375 @@
#!/bin/sh
# Default PATH differs between shells, and is not automatically exported
# by klibc dash. Make it consistent.
# Furthermore, this PATH ends up being used by the init, set it to the
# Standard PATH, without /snap/bin as documented in
# https://wiki.ubuntu.com/PATH
# This also matches /etc/environment, but without games path
export PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
[ -d /dev ] || mkdir -m 0755 /dev
[ -d /root ] || mkdir -m 0700 /root
[ -d /sys ] || mkdir /sys
[ -d /proc ] || mkdir /proc
[ -d /tmp ] || mkdir /tmp
mkdir -p /var/lock
mount -t sysfs -o nodev,noexec,nosuid sysfs /sys
mount -t proc -o nodev,noexec,nosuid proc /proc
# shellcheck disable=SC2013
for x in $(cat /proc/cmdline); do
case $x in
initramfs.clear)
clear
;;
quiet)
quiet=y
;;
esac
done
if [ "$quiet" != "y" ]; then
quiet=n
echo "Loading, please wait..."
fi
export quiet
# Note that this only becomes /dev on the real filesystem if udev's scripts
# are used; which they will be, but it's worth pointing out
test -x /usr/sbin/v86d && dev_exec="exec" || dev_exec="noexec"
mount -t devtmpfs -o $dev_exec,nosuid,mode=0755 udev /dev
mkdir /dev/pts
mount -t devpts -o noexec,nosuid,gid=5,mode=0620 devpts /dev/pts || true
# Export the dpkg architecture
export DPKG_ARCH=
. /conf/arch.conf
# Set modprobe env
export MODPROBE_OPTIONS="-qb"
# Export relevant variables
export ROOT=
export ROOTDELAY=
export ROOTFLAGS=
export ROOTFSTYPE=
export IP=
export IP6=
export VLAN=
export DEVICE=
export BOOT=
export BOOTIF=
export UBIMTD=
export NETWORK_SKIP_ENSLAVED=
export break=
export init=/sbin/init
export readonly=y
export rootmnt=/root
export debug=
export panic=
export blacklist=
export resume=
export resume_offset=
export noresume=
export drop_caps=
export fastboot=n
export forcefsck=n
export fsckfix=
# mdadm needs hostname to be set. This has to be done before the udev rules are called!
if [ -f "/etc/hostname" ]; then
/bin/hostname -F /etc/hostname >/dev/null 2>&1
fi
# Bring in the main config
. /conf/initramfs.conf
for conf in conf/conf.d/*; do
[ -f "${conf}" ] && . "${conf}"
done
. /scripts/functions
# Parse command line options
# shellcheck disable=SC2013
for x in $(cat /proc/cmdline); do
case $x in
init=*)
init=${x#init=}
;;
root=*)
ROOT=${x#root=}
if [ -z "${BOOT}" ] && [ "$ROOT" = "/dev/nfs" ]; then
BOOT=nfs
fi
;;
rootflags=*)
ROOTFLAGS="-o ${x#rootflags=}"
;;
rootfstype=*)
ROOTFSTYPE="${x#rootfstype=}"
;;
rootdelay=*)
ROOTDELAY="${x#rootdelay=}"
case ${ROOTDELAY} in
*[![:digit:].]*)
ROOTDELAY=
;;
esac
;;
roottimeout=*)
ROOTDELAY="${x#roottimeout=}"
case ${ROOTDELAY} in
*[![:digit:].]*)
ROOTDELAY=
;;
esac
;;
loop=*)
# shellcheck disable=SC2034
LOOP="${x#loop=}"
;;
loopflags=*)
# shellcheck disable=SC2034
LOOPFLAGS="-o ${x#loopflags=}"
;;
loopfstype=*)
# shellcheck disable=SC2034
LOOPFSTYPE="${x#loopfstype=}"
;;
nfsroot=*)
# shellcheck disable=SC2034
NFSROOT="${x#nfsroot=}"
;;
initramfs.runsize=*)
RUNSIZE="${x#initramfs.runsize=}"
;;
ip=*)
IP="${x#ip=}"
;;
ip6=*)
IP6="${x#ip6=}"
;;
vlan=*)
VLAN="${x#vlan=}"
;;
boot=*)
BOOT=${x#boot=}
;;
ubi.mtd=*)
UBIMTD=${x#ubi.mtd=}
;;
resume=*)
RESUME="${x#resume=}"
case $RESUME in
UUID=*)
RESUME="/dev/disk/by-uuid/${RESUME#UUID=}"
esac
;;
resume_offset=*)
resume_offset="${x#resume_offset=}"
;;
noresume)
noresume=y
;;
drop_capabilities=*)
drop_caps="-d ${x#drop_capabilities=}"
;;
panic=*)
panic="${x#panic=}"
case ${panic} in
-1) ;;
*[![:digit:].]*)
panic=
;;
esac
;;
ro)
readonly=y
;;
rw)
readonly=n
;;
debug)
debug=y
quiet=n
if [ -n "${netconsole}" ]; then
log_output=/dev/kmsg
else
log_output=/run/initramfs/initramfs.debug
fi
set -x
;;
debug=*)
debug=y
quiet=n
set -x
;;
break=*)
break=${x#break=}
;;
break)
break=premount
;;
blacklist=*)
blacklist=${x#blacklist=}
;;
netconsole=*)
netconsole=${x#netconsole=}
[ "x$debug" = "xy" ] && log_output=/dev/kmsg
;;
BOOTIF=*)
BOOTIF=${x#BOOTIF=}
;;
hwaddr=*)
BOOTIF=${x#hwaddr=}
;;
fastboot|fsck.mode=skip)
fastboot=y
;;
forcefsck|fsck.mode=force)
forcefsck=y
;;
fsckfix|fsck.repair=yes)
fsckfix=y
;;
fsck.repair=no)
fsckfix=n
;;
esac
done
# Default to BOOT=local if no boot script defined.
if [ -z "${BOOT}" ]; then
BOOT=local
fi
if [ -n "${noresume}" ] || [ "$RESUME" = none ]; then
noresume=y
else
resume=${RESUME:-}
fi
mount -t tmpfs -o "nodev,noexec,nosuid,size=${RUNSIZE:-10%},mode=0755" tmpfs /run
mkdir -m 0700 /run/initramfs
if [ -n "$log_output" ]; then
exec >$log_output 2>&1
unset log_output
fi
maybe_break top
# export BOOT variable value for compcache,
# so we know if we run from casper
export BOOT
# Don't do log messages here to avoid confusing graphical boots
run_scripts /scripts/init-top
maybe_break modules
[ "$quiet" != "y" ] && log_begin_msg "Loading essential drivers"
[ -n "${netconsole}" ] && modprobe netconsole netconsole="${netconsole}"
load_modules
[ "$quiet" != "y" ] && log_end_msg
maybe_break premount
[ "$quiet" != "y" ] && log_begin_msg "Running /scripts/init-premount"
run_scripts /scripts/init-premount
[ "$quiet" != "y" ] && log_end_msg
maybe_break mount
log_begin_msg "Mounting root file system"
# Always load local and nfs (since these might be needed for /etc or
# /usr, irrespective of the boot script used to mount the rootfs).
. /scripts/local
. /scripts/nfs
. /scripts/${BOOT}
parse_numeric "${ROOT}"
maybe_break mountroot
mount_top
mount_premount
mountroot
log_end_msg
if read_fstab_entry /usr; then
log_begin_msg "Mounting /usr file system"
mountfs /usr
log_end_msg
fi
# Mount cleanup
mount_bottom
nfs_bottom
local_bottom
maybe_break bottom
[ "$quiet" != "y" ] && log_begin_msg "Running /scripts/init-bottom"
# We expect udev's init-bottom script to move /dev to ${rootmnt}/dev
run_scripts /scripts/init-bottom
[ "$quiet" != "y" ] && log_end_msg
# Move /run to the root
mount -n -o move /run ${rootmnt}/run
validate_init() {
run-init -n "${rootmnt}" "${1}"
}
# Check init is really there
if ! validate_init "$init"; then
echo "Target filesystem doesn't have requested ${init}."
init=
for inittest in /sbin/init /etc/init /bin/init /bin/sh; do
if validate_init "${inittest}"; then
init="$inittest"
break
fi
done
fi
# No init on rootmount
if ! validate_init "${init}" ; then
panic "No init found. Try passing init= bootarg."
fi
maybe_break init
# don't leak too much of env - some init(8) don't clear it
# (keep init, rootmnt, drop_caps)
unset debug
unset MODPROBE_OPTIONS
unset DPKG_ARCH
unset ROOTFLAGS
unset ROOTFSTYPE
unset ROOTDELAY
unset ROOT
unset IP
unset IP6
unset VLAN
unset BOOT
unset BOOTIF
unset DEVICE
unset UBIMTD
unset blacklist
unset break
unset noresume
unset panic
unset quiet
unset readonly
unset resume
unset resume_offset
unset noresume
unset fastboot
unset forcefsck
unset fsckfix
# Move virtual filesystems over to the real filesystem
mount -n -o move /sys ${rootmnt}/sys
mount -n -o move /proc ${rootmnt}/proc
# Chain to real filesystem
# shellcheck disable=SC2086,SC2094
exec run-init ${drop_caps} "${rootmnt}" "${init}" "$@" <"${rootmnt}/dev/console" >"${rootmnt}/dev/console" 2>&1
echo "Something went badly wrong in the initramfs."
panic "Please file a bug on initramfs-tools."

708
initramfs-tools.7 Normal file
View File

@ -0,0 +1,708 @@
.TH INITRAMFS-TOOLS 7 "2018/07/18" "initramfs\-tools" "Linux Programmer's Manual"
.SH NAME
initramfs-tools \- an introduction to writing scripts for mkinitramfs
.SH DESCRIPTION
initramfs-tools has one main script and two different sets of subscripts which
will be used during different phases of execution. Each of these will be
discussed separately below with the help of an imaginary tool which performs a
frobnication of a lvm partition prior to mounting the root partition.
.SH Kernel Command Line
The root filesystem used by the kernel is specified by the boot loader as
always. The traditional \fBroot=/dev/sda1\fR style device specification is
allowed. If a label is used, as in \fBroot=LABEL=rootPart\fR the initrd will
search all available devices for a filesystem with the appropriate label, and
mount that device as the root filesystem. \fBroot=UUID=uuidnumber\fR will
mount the partition with that UUID as the root filesystem.
.SS Standard
.TP
\fB\fI init= "<path to real init>"
the binary to hand over execution to on the root fs after the initramfs scripts are done.
.TP
\fB\fI initramfs.clear
clear screen at the beginning
.TP
\fB\fI initramfs.runsize
The size of the \fI/run\fP tmpfs mount point in bytes (suffixes are supported)
or as percentage of your physical RAM. This parameter is used as the value of
the size mount option to tmpfs. See
\fBhttps://www.kernel.org/doc/Documentation/filesystems/tmpfs.txt\fR for
details. The default is 10%.
.TP
\fB\fI root= "<path to blockdevice>"
the device node to mount as the root file system.
The recommended usage is to specify the UUID as followed "root=UUID=xxx".
.TP
\fB\fI rootfstype
set the root file system type.
.TP
\fB\fI roottimeout
set timeout in seconds. Determines how long mountroot waits for root to appear.
The default is 30 seconds.
.TP
\fB\fI rootdelay
alias for roottimeout.
.TP
\fB\fI rootflags
set the file system mount option string.
.TP
\fB\fI loop= "<path to image>"
path within the original root file system to loop-mount and use as the real
root file system.
.TP
\fB\fI loopfstype
set the loop file system type, if applicable.
.TP
\fB\fI loopflags
set the loop file system mount option string, if applicable.
.TP
\fB\fI nfsroot
can be either "auto" to try to get the relevant information from DHCP or a
string of the form NFSSERVER:NFSPATH or NFSSERVER:NFSPATH:NFSOPTS.
Use root=/dev/nfs for NFS to kick to in. NFSOPTS can be looked up in
\fInfs(5)\fP.
.TP
\fB\fI ip
tells how to configure the ip address. Allows one to specify an different
NFS server than the DHCP server. See Documentation/filesystems/nfsroot.txt
in any recent Linux source for details. Optional parameter for NFS root.
.TP
\fB\fI vlan
tells to create a VLAN tagged device. Allows one to configure one or
multiple VLAN tagged devices using the "vlan=$name.$id:$parent"
syntax. E.g. "vlan=eth0.1:eth0" Optional parameter for NFS root.
.TP
\fB\fI BOOTIF
is a mac address in pxelinux format with leading "01-" and "-" as separations.
pxelinux passes mac address of network card used to PXE boot on with this
bootarg.
.TP
\fB\fI boot
either local or NFS (affects which initramfs scripts are run, see the "Subdirectories" section under boot scripts).
.TP
\fB\fI resume
The resume hook tries to autodetect the resume partition and uses the first
swap partition as valid guess. It is possible to set the RESUME variable in
/etc/initramfs-tools/conf.d/resume.
The boot variable noresume overrides it.
.TP
\fB\fI resume_offset
Specify the offset from the partition given by "resume=" at which the swap
header of the swap file is located.
.TP
\fB\fI quiet
reduces the amount of text output to the console during boot.
.TP
\fB\fI ro
mounts the rootfs read-only.
.TP
\fB\fI rw
mounts the rootfs read-write.
.TP
\fB\fI blacklist
disables load of specific modules.
Use blacklist=module1,module2,module3 bootparameter.
.SS Debug
.TP
\fB\fI panic
sets an timeout on panic.
panic=<sec> is a documented security feature: it disables the debug shell.
.TP
\fB\fI debug
generates lots of output. It writes a log to /run/initramfs/initramfs.debug.
Instead when invoked with an arbitrary argument output is written to console.
Use for example "debug=vc".
.TP
\fB\fI break
spawns a shell in the initramfs image at the chosen phase
(top, modules, premount, mount, mountroot, bottom, init)
before actually executing the corresponding scripts
(see the "Boot scripts" section) or action. Multiple
phases may be specified, delimited by commas.
The default, if no phase is specified, is "premount".
Beware that if both "panic" and "break" are present,
initramfs will not spawn any shells but reboot instead.
.TP
\fB\fI netconsole
loads netconsole linux modules with the chosen args.
.TP
\fB\fI all_generic_ide
loads generic IDE/ATA chipset support on boot.
.SH SCRIPTS
Valid boot and hook scripts names consist solely of alphabetics, numerics,
dashes and underscores. Other scripts are discarded.
.SS Configuration hook scripts
These are used to override the user configuration where necessary, for
example to force use of busybox instead of klibc utilities.
.SS Hook scripts
These are used when an initramfs image is created and not included in the
image itself. They can however cause files to be included in the image.
Hook scripts are executed under errexit. Thus a hook script can abort the
mkinitramfs build on possible errors (exitcode != 0).
.SS Boot scripts
These are included in the initramfs image and normally executed during
kernel boot in the early user-space before the root partition has been
mounted.
.SH CONFIGURATION HOOK SCRIPTS
Configuration hook scripts can be found in
/usr/share/initramfs-tools/conf-hooks.d. They are sourced by
mkinitramfs after the configuration files in /etc and before running
any hook scripts. They can override any of the variables documented
in \fIinitramfs.conf\fR(5), but this should be done only if absolutely
necessary. For example, if a package's boot script requires commands
not provided by klibc-utils, it should also install a configuration
hook that sets \fBBUSYBOX=y\fR.
.SH HOOK SCRIPTS
Hooks can be found in two places: /usr/share/initramfs-tools/hooks and
/etc/initramfs-tools/hooks. They are executed during generation of the
initramfs-image and are responsible for including all the necessary components
in the image itself. No guarantees are made as to the order in which the
different scripts are executed unless the prereqs are setup in the script.
Please notice that PREREQ is only honored inside a single directory. So first
the scripts in /usr/share/initramfs-tools are ordered according to their PREREQ
values and executed. Then all scripts in /etc/initramfs-tools are ordered
according to \fBtheir\fR PREREQ values and executed. This mean that currently
there is no possibility to have a local script (/etc/initramfs-tools) get
executed before one from the package (/usr/share/initramfs-tools).
If a hook script requires configuration beyond the exported variables
listed below, it should read a private configuration file that is
separate from the /etc/initramfs-tools directory. It \fImust not\fR
read initramfs-tools configuration files directly.
.SS Header
In order to support prereqs, each script should begin with the following lines:
.RS
.nf
#!/bin/sh
PREREQ=""
prereqs()
{
echo "$PREREQ"
}
case $1 in
prereqs)
prereqs
exit 0
;;
esac
\fR. /usr/share/initramfs-tools/hook-functions
# Begin real processing below this line
.fi
.RE
For example, if you are writing a new hook script which relies on lvm, the line
starting with PREREQ should be changed to PREREQ="lvm" which will ensure that
the lvm hook script is run before your custom script.
.SS Help functions
/usr/share/initramfs-tools/hook-functions contains a number of functions which
deal with some common tasks in a hook script:
.TP
\fB\fI
manual_add_modules
adds a module (and any modules which it depends on) to the initramfs image.
.RS
.PP
.B Example:
manual_add_modules isofs
.RE
.TP
\fB\fI
add_modules_from_file
reads a file containing a list of modules (one per line) to be added to the
initramfs image. The file can contain comments (lines starting with #) and
arguments to the modules by writing the arguments on the same line as the name
of the module.
.RS
.PP
.B Example:
add_modules_from_file /tmp/modlist
.RE
.TP
\fB\fI
force_load
adds a module (and its dependencies) to the initramfs image and also
unconditionally loads the module during boot. Also supports passing arguments
to the module by listing them after the module name.
.RS
.PP
.B Example:
force_load cdrom debug=1
.RE
.TP
\fB\fI
copy_modules_dir
copies an entire module directory from /lib/modules/KERNELVERSION/ into the
initramfs image.
.RS
.PP
.B Example:
copy_modules_dir kernel/drivers/ata
.RE
.SS Including binaries
If you need to copy binaries to the initramfs module, a command like this
should be used:
.PP
.RS
copy_exec /sbin/mdadm /sbin
.RE
mkinitramfs will automatically detect which libraries the executable depends on
and copy them to the initramfs. This means that most executables, unless
compiled with klibc, will automatically include glibc in the image which will
increase its size by several hundred kilobytes.
.SS Including a system firmware preimage (early initramfs)
If you need to prepend data to the initramfs image, you need to prepare it
in a file, and call the \fB\fIprepend_earlyinitramfs\fR function. The file
can be disposed of as soon as the function returns.
.B Example:
.nf
TEMP_FILE=$(mktemp ...)
...
prepend_earlyinitramfs ${TEMP_FILE}
rm -f ${TEMP_FILE}
.RE
.SS Exported variables
mkinitramfs sets several variables for the hook scripts environment.
.TP
\fB\fI MODULESDIR
corresponds to the linux modules dir.
.TP
\fB\fI version
is the $(uname \-r) linux version against mkinitramfs is run.
.TP
\fB\fI CONFDIR
is the path of the used initramfs-tools configurations.
.TP
\fB\fI DESTDIR
is the root path of the newly build initramfs.
.TP
\fB\fI DPKG_ARCH
allows arch specific hook additions.
.TP
\fB\fI verbose
corresponds to the verbosity of the update-initramfs run.
.TP
\fB\fI BUSYBOX, MODULES
are as described in \fIinitramfs.conf\fR(5).
.TP
\fB\fI BUSYBOXDIR
is the directory where busybox utilities should be installed from, or
empty if busybox is not being used.
.SH BOOT SCRIPTS
Similarly to hook scripts, boot scripts can be found in two places
/usr/share/initramfs-tools/scripts/ and /etc/initramfs-tools/scripts/. There
are a number of subdirectories to these two directories which control the boot
stage at which the scripts are executed.
.SS Header
Like for hook scripts, there are no guarantees as to the order in which the
different scripts in one subdirectory (see "Subdirectories" below) are
executed. In order to define a certain order, a similar header as for hook
scripts should be used:
.RS
.nf
#!/bin/sh
PREREQ=""
prereqs()
{
echo "$PREREQ"
}
case $1 in
prereqs)
prereqs
exit 0
;;
esac
.fi
.RE
Where PREREQ is modified to list other scripts in the same subdirectory if necessary.
.SS Help functions
A number of functions (mostly dealing with output) are provided to boot scripts in
.I /scripts/functions
:
.TP
\fB\fI
log_success_msg
Logs a success message
.RS
.PP
.B Example:
log_success_msg "Frobnication successful"
.RE
.TP
\fB\fI
log_failure_msg
Logs a failure message
.RS
.PP
.B Example:
log_failure_msg "Frobnication component froobz missing"
.RE
.TP
\fB\fI
log_warning_msg
Logs a warning message
.RS
.PP
.B Example:
log_warning_msg "Only partial frobnication possible"
.RE
.TP
\fB\fI
log_begin_msg
Logs a message that some processing step has begun
.TP
\fB\fI
log_end_msg
Logs a message that some processing step is finished
.RS
.PP
.B Example:
.PP
.RS
.nf
log_begin_msg "Frobnication begun"
# Do something
log_end_msg
.fi
.RE
.RE
.TP
\fB\fI
panic
Logs an error message and executes a shell in the initramfs image to allow the
user to investigate the situation.
.RS
.PP
.B Example:
panic "Frobnication failed"
.fi
.RE
.RE
.TP
\fB\fI
add_mountroot_fail_hook
Registers the script as able to provide possible further information, in the
event that the root device cannot be found. See the example script in the
initramfs-tools examples directory for more information.
.RS
.PP
.B Example:
add_mountroot_fail_hook
.RE
.SS Subdirectories
Both /usr/share/initramfs-tools/scripts and /etc/initramfs-tools/scripts
contains the following subdirectories.
.TP
\fB\fI
init-top
the scripts in this directory are the first scripts to be executed after sysfs
and procfs have been mounted.
It also runs the udev hook for populating the /dev tree (udev will keep
running until init-bottom).
.TP
\fB\fI
init-premount
happens after modules specified by hooks and /etc/initramfs-tools/modules
have been loaded.
.TP
\fB\fI
local-top OR nfs-top
After these scripts have been executed, the root device node is expected to be
present (local) or the network interface is expected to be usable (NFS).
.TP
\fB\fI
local-block
These scripts are called with the name of a local block device. After
these scripts have been executed, that device node should be present.
If the local-top or local-block scripts fail to create the wanted
device node, the local-block scripts will be called periodically to
try again.
.TP
\fB\fI
local-premount OR nfs-premount
are run after the sanity of the root device has been verified (local) or the
network interface has been brought up (NFS), but before the actual root fs has
been mounted.
.TP
\fB\fI
local-bottom OR nfs-bottom
are run after the rootfs has been mounted (local) or the NFS root share has
been mounted.
.TP
\fB\fI
init-bottom
are the last scripts to be executed before procfs and sysfs are moved to the
real rootfs and execution is turned over to the init binary which should now be
found in the mounted rootfs. udev is stopped.
.SS Boot parameters
.TP
\fB\fI
/conf/param.conf
allows boot scripts to change exported variables that are listed on top of init. Write the new values to it. It will be sourced after an boot script run if it exists.
.SH EXAMPLES
.SS Hook script
An example hook script would look something like this (and would usually be
placed in /etc/initramfs-tools/hooks/frobnicate):
.RS
.nf
#!/bin/sh
# Example frobnication hook script
PREREQ="lvm"
prereqs()
{
echo "$PREREQ"
}
case $1 in
prereqs)
prereqs
exit 0
;;
esac
\fR. /usr/share/initramfs-tools/hook-functions
# Begin real processing below this line
if [ ! \-x "/sbin/frobnicate" ]; then
exit 0
fi
force_load frobnicator interval=10
copy_exec /sbin/frobnicate /sbin
exit 0
.fi
.RE
.SS Boot script
An example boot script would look something like this (and would usually be placed in /etc/initramfs-tools/scripts/local-top/frobnicate):
.RS
.nf
#!/bin/sh
# Example frobnication boot script
PREREQ="lvm"
prereqs()
{
echo "$PREREQ"
}
case $1 in
prereqs)
prereqs
exit 0
;;
esac
\fR. /scripts/functions
# Begin real processing below this line
if [ ! \-x "/sbin/frobnicate" ]; then
panic "Frobnication executable not found"
fi
if [ ! \-e "/dev/mapper/frobb" ]; then
panic "Frobnication device not found"
fi
log_begin_msg "Starting frobnication"
/sbin/frobnicate "/dev/mapper/frobb" || panic "Frobnication failed"
log_end_msg
exit 0
.fi
.RE
.SS Exported variables
init sets several variables for the boot scripts environment.
.TP
\fB\fI ROOT
corresponds to the root boot option.
Advanced boot scripts like cryptsetup or live-initramfs need to play tricks.
Otherwise keep it alone.
.TP
\fB\fI ROOTDELAY, ROOTFLAGS, ROOTFSTYPE, IP
corresponds to the rootdelay, rootflags, rootfstype or ip boot option.
Use of ROOTDELAY is deprecated; you should implement a \fIlocal-block\fR
boot script rather than delaying or polling.
.TP
\fB\fI DPKG_ARCH
allows arch specific boot actions.
.TP
\fB\fI blacklist, panic, quiet, resume, noresume, resume_offset
set according relevant boot option.
.TP
\fB\fI break
Useful for manual intervention during setup and coding an boot script.
.TP
\fB\fI REASON
Argument passed to the \fIpanic\fP helper function. Use to find out why
you landed in the initramfs shell.
.TP
\fB\fI init
passes the path to init(8) usually /sbin/init.
.TP
\fB\fI readonly
is the default for mounting the root corresponds to the ro bootarg.
Overridden by rw bootarg.
.TP
\fB\fI rootmnt
is the path where root gets mounted usually /root.
.TP
\fB\fI debug
indicates that a debug log is captured for further investigation.
.SH UPDATING THE INITRAMFS FROM ANOTHER PACKAGE
Package maintainer scripts should not run \fBupdate-initramfs\fR
directly. A package that installs hooks for initramfs-tools should
include a triggers file containing:
.RS
.nf
activate\-noawait update\-initramfs
.fi
.RE
Kernel packages must call the kernel hooks as documented in the
Debian Kernel Handbook.
A package that requires an initramfs to function, but is not a kernel
package, should include a triggers file containing:
.RS
.nf
activate\-await update\-initramfs
.fi
.RE
.SH KERNEL HOOKS
initramfs-tools includes hook scripts that are called by kernel
packages on installation and removal, so that an initramfs is
automatically created, updated or deleted as necessary. The hook
scripts do nothing if the environment variable \fBINITRD\fR is
set to \fBNo\fR. This will be the case for kernel packages
built with \fBmake deb-pkg\fR and with \fBCONFIG_BLK_DEV_INITRD\fR
not set in the kernel config, or built with \fBmake-kpkg\fR and not
using the \fB--initrd\fR option.
.SH DEBUG
It is easy to check the generated initramfs for its content. One may need
to double-check if it contains the relevant binaries, libs or modules:
.RS
.nf
lsinitramfs /boot/initrd.img\-3.16\-3\-amd64
.fi
.RE
.SH FILES
.TP
.I /run/initramfs/fsck.log
Log of fsck commands run within the initramfs, with their output.
.TP
.I /run/initramfs/fsck-root
Exists only if fsck ran successfully for the root filesystem.
.TP
.I /run/initramfs/fsck-usr
Exists only if fsck ran successfully for the \fI/usr\fR filesystem.
.SH AUTHOR
The initramfs-tools are written by Maximilian Attems <maks@debian.org>,
Jeff Bailey <jbailey@raspberryginger.com> and numerous others.
.PP
This manual was written by David H\[:a]rdeman <david@hardeman.nu>,
updated by Maximilian Attems <maks@debian.org>.
.SH SEE ALSO
.BR
.IR initramfs.conf (5),
.IR mkinitramfs (8),
.IR update-initramfs (8),
.IR lsinitramfs (8).

141
initramfs.conf.5 Normal file
View File

@ -0,0 +1,141 @@
.TH INITRAMFS.CONF 5 "2018/07/18" "initramfs\-tools" "File Formats Manual"
.SH NAME
initramfs.conf \- configuration file for mkinitramfs
.SH DESCRIPTION
The behaviour of
.B mkinitramfs
can be modified by its configuration file.
Each line in the file can be a configuration variable, a blank line,
or a comment. The value of an variable is assigned by an statement
of the form: \fIname\fP=[\fIvalue\fP]
Configuration options can be broken out into configuration snippets and
placed in individual files in the /etc/initramfs-tools/conf.d directory. Files
in this directory are always read \fBafter\fP the main configuration file,
so you can override the settings in the main config file without editing it
directly.
.SH GENERAL VARIABLES
.TP
\fB MODULES
Specifies the modules for the initramfs image.
Modules listed in \fI/etc/initramfs-tools/modules\fP and
\fI/usr/share/initramfs-tools/modules.d/*\fP are always included in the
initramfs, and are loaded early in the boot process.
\fIlist\fP doesn't load any additional modules at boot time, other than those
listed in the above files.
\fImost\fP adds most file system, all ata, sata, scsi and usb drivers.
\fIdep\fP tries to guess which modules are necessary for the running box and
only adds those modules.
\fInetboot\fP adds the base and network modules, but skips block devices.
The default setting is \fImost\fP.
.TP
\fB BUSYBOX
Include busybox utilities for the boot scripts.
If set to 'n'
.B mkinitramfs
will build an initramfs without busybox.
Beware that many boot scripts need busybox utilities.
.TP
\fB COMPCACHE_SIZE
Amount of RAM to use for RAM-based compressed swap space.
The default is not to use compcache.
An empty value \- compcache isn't used, or added to the initramfs at all.
An integer and K (e.g. \fI65536 K\fP) \- use a number of kilobytes.
An integer and M (e.g. \fI256 M\fP) \- use a number of megabytes.
An integer and G (e.g. \fI1 G\fP) \- use a number of gigabytes.
An integer and % (e.g. \fI50 %\fP) \- use a percentage of the amount of RAM.
You can optionally install the \fIcompcache\fP package to configure this
setting via debconf and have userspace scripts to load and unload compcache.
.TP
\fB COMPRESS
Specifies the compression method used for the initramfs image.
.B mkinitramfs
will default to gzip if the kernel lacks support (CONFIG_RD) or the
corresponding userspace utility is not present.
.TP
\fB UMASK
Set the umask value of the generated initramfs file.
Useful to not disclose eventual keys.
.TP
\fB BOOT
Allows one to use an nfs drive as the root of the drive.
The default is to boot from \fIlocal\fP media (hard drive, USB stick).
Set to \fInfs\fP for an NFS root share.
.TP
\fB RUNSIZE
The size of the \fI/run\fP tmpfs mount point in bytes (suffixes are supported)
or as percentage of your physical RAM. This parameter is used as the value of
the size mount option to tmpfs. See
\fBhttps://www.kernel.org/doc/Documentation/filesystems/tmpfs.txt\fR for
details. Can be overridden by an optional \fBinitramfs.runsize=\fR bootarg.
The default is 10%.
.SH VARIABLES FOR LOCAL BOOT
.TP
\fB RESUME
Specifies the device used for suspend-to-disk (hibernation), which the
initramfs code should attempt to resume from. If this is not defined
or is set to \fIauto\fP,
.B mkinitramfs
will automatically select the largest available swap partition.
Set it to \fInone\fP to disable resume from disk.
.SH VARIABLES FOR NFS BOOT
.TP
\fB DEVICE
Specifies the default network interface to use, like eth0. The \fIip\fP or
\fIBOOTIF\fP bootargs may override this.
.TP
\fB VLAN
Specifies the VLAN tag id to setup, e.g. VLAN=eth0.1:eth0. The \fIvlan\fP
bootarg may override this.
.TP
\fB ROOT
Allows optional root bootarg hardcoding, when no root bootarg can be passed.
A root bootarg overrides that special setting.
.TP
\fB NFSROOT
Defaults to \fIauto\fP in order to pick up value from DHCP server.
Otherwise you need to specify \fIHOST:MOUNT\fP.
.SH FILES
.TP
.I /etc/initramfs-tools/initramfs.conf
.SH AUTHOR
The initramfs-tools are written by Maximilian Attems <maks@debian.org>,
Jeff Bailey <jbailey@raspberryginger.com> and numerous others.
Loosely based on mkinitrd.conf by Herbert Xu.
.SH SEE ALSO
.BR
.IR initramfs-tools (7),
.IR mkinitramfs (8),
.IR update-initramfs (8).

View File

@ -0,0 +1,36 @@
#!/bin/sh -e
version="$1"
bootopt=""
command -v update-initramfs >/dev/null 2>&1 || exit 0
# passing the kernel version is required
if [ -z "${version}" ]; then
echo >&2 "W: initramfs-tools: ${DPKG_MAINTSCRIPT_PACKAGE:-kernel package} did not pass a version number"
exit 2
fi
# exit if kernel does not need an initramfs
if [ "$INITRD" = 'No' ]; then
exit 0
fi
# absolute file name of kernel image may be passed as a second argument;
# create the initrd in the same directory
if [ -n "$2" ]; then
bootdir=$(dirname "$2")
bootopt="-b ${bootdir}"
fi
# avoid running multiple times
if [ -n "$DEB_MAINT_PARAMS" ]; then
eval set -- "$DEB_MAINT_PARAMS"
if [ -z "$1" ] || [ "$1" != "configure" ]; then
exit 0
fi
fi
# we're good - create initramfs. update runs do_bootloader
# shellcheck disable=SC2086
INITRAMFS_TOOLS_KERNEL_HOOK=1 update-initramfs -c -k "${version}" ${bootopt} >&2

36
kernel/postrm.d/initramfs-tools Executable file
View File

@ -0,0 +1,36 @@
#!/bin/sh -e
version="$1"
bootopt=""
[ -x /usr/sbin/update-initramfs ] || exit 0
# passing the kernel version is required
if [ -z "${version}" ]; then
echo >&2 "W: initramfs-tools: ${DPKG_MAINTSCRIPT_PACKAGE:-kernel package} did not pass a version number"
exit 0
fi
# exit if custom kernel does not need an initramfs
if [ "$INITRD" = 'No' ]; then
exit 0
fi
# absolute file name of kernel image may be passed as a second argument;
# create the initrd in the same directory
if [ -n "$2" ]; then
bootdir=$(dirname "$2")
bootopt="-b ${bootdir}"
fi
# avoid running multiple times
if [ -n "$DEB_MAINT_PARAMS" ]; then
eval set -- "$DEB_MAINT_PARAMS"
if [ -z "$1" ] || [ "$1" != "remove" ]; then
exit 0
fi
fi
# delete initramfs
# shellcheck disable=SC2086
INITRAMFS_TOOLS_KERNEL_HOOK=1 update-initramfs -d -k "${version}" ${bootopt} >&2

57
lsinitramfs Executable file
View File

@ -0,0 +1,57 @@
#!/bin/sh
set -eu
usage()
{
cat << EOF
Usage: lsinitramfs [-l] initramfs-file...
Options:
-l Display long and more verbose listing of initramfs content
See lsinitramfs(8) for further details.
EOF
}
usage_error()
{
usage >&2
exit 2
}
umi_opts="--list"
OPTIONS=$(getopt -o hl --long help,long -n "$0" -- "$@") || usage_error
eval set -- "$OPTIONS"
while true; do
case "$1" in
-h|--help)
usage
exit 0
;;
-l|--long)
umi_opts="${umi_opts:+${umi_opts} --verbose}"
shift
;;
--)
shift
break
;;
*)
echo "Internal error!" >&2
exit 1
esac
done
if [ "$#" -eq 0 ] ; then
usage_error
fi
for initramfs in "$@" ; do
unmkinitramfs $umi_opts -- "$initramfs"
done

56
lsinitramfs.8 Normal file
View File

@ -0,0 +1,56 @@
.TH LSINITRAMFS 8 "2015/12/09" "initramfs\-tools" "System Administration"
.SH NAME
lsinitramfs \- list content of an initramfs image
.SH SYNOPSIS
.B lsinitramfs
.RB [ -l ]
.IR initramfs-file ...
.br
.BR lsinitramfs " " -h
.SH DESCRIPTION
The
.B lsinitramfs
command lists the content of given initramfs images. It allows one to quickly check
the content of one (or multiple) specified initramfs files.
.SH OPTIONS
.TP
.B -h
Display usage information and exit.
.TP
.B -l
Display long and more verbose listing of initramfs content.
.SH USAGE EXAMPLES
List initramfs content of current running kernel:
.PP
.B lsinitramfs /boot/initrd.img-$(uname -r)
List content of two initramfs files in verbose mode:
.PP
.B lsinitramfs -l /boot/vmlinuz-2.6.31-grml64 /boot/vmlinuz-2.6.33-grml64
.SH BUGS
.BR lsinitramfs
cannot deal with multiple-segmented initramfs images, except where an
early (uncompressed) initramfs with system firmware is prepended to
the regular compressed initramfs.
.SH AUTHOR
The initramfs-tools are written by Maximilian Attems <maks@debian.org>
and numerous others.
.SH SEE ALSO
.BR
.IR initramfs-tools (7),
.IR mkinitramfs (8),
.IR unmkinitramfs (8),
.IR update-initramfs (8).

476
mkinitramfs Normal file
View File

@ -0,0 +1,476 @@
#!/bin/sh
umask 0022
export PATH='/usr/bin:/sbin:/bin'
# Defaults
keep="n"
CONFDIR="/etc/initramfs-tools"
verbose="n"
# Will be updated by busybox's conf hook, if present
BUSYBOXDIR=
export BUSYBOXDIR
usage()
{
cat << EOF
Usage: mkinitramfs [option]... -o outfile [version]
Options:
-c compress Override COMPRESS setting in initramfs.conf.
-d confdir Specify an alternative configuration directory.
-k Keep temporary directory used to make the image.
-o outfile Write to outfile.
-r root Override ROOT setting in initramfs.conf.
See mkinitramfs(8) for further details.
EOF
}
usage_error()
{
usage >&2
exit 2
}
OPTIONS=$(getopt -o c:d:hko:r:v --long help -n "$0" -- "$@") || usage_error
eval set -- "$OPTIONS"
while true; do
case "$1" in
-c)
compress="$2"
shift 2
;;
-d)
CONFDIR="$2"
shift 2
if [ ! -d "${CONFDIR}" ]; then
echo "${0}: ${CONFDIR}: Not a directory" >&2
exit 1
fi
;;
-h|--help)
usage
exit 0
;;
-o)
outfile="$2"
shift 2
;;
-k)
keep="y"
shift
;;
-r)
ROOT="$2"
shift 2
;;
-v)
verbose="y"
shift
;;
--)
shift
break
;;
*)
echo "Internal error!" >&2
exit 1
;;
esac
done
# For dependency ordered mkinitramfs hook scripts.
. /usr/share/initramfs-tools/scripts/functions
. /usr/share/initramfs-tools/hook-functions
# Auto-export any variables set in the conf snippets such that
# initramfs hooks can configure each other
# i.e. initramfs-tools-ubuntu-core affecting
# intel-microcode/amd-microcode hook defaults
set -a
. "${CONFDIR}/initramfs.conf"
EXTRA_CONF=''
maybe_add_conf() {
if [ -e "$1" ] && \
basename "$1" \
| grep '^[[:alnum:]][[:alnum:]\._-]*$' \
| grep -qv '\.dpkg-.*$'; then
if [ -d "$1" ]; then
echo "W: $1 is a directory instead of file" >&2
else
EXTRA_CONF="${EXTRA_CONF} $1"
. "$1"
fi
fi
}
for i in /usr/share/initramfs-tools/conf.d/*; do
# Configuration files in /etc mask those in /usr/share
if ! [ -e "${CONFDIR}"/conf.d/"$(basename "${i}")" ]; then
maybe_add_conf "${i}"
fi
done
for i in "${CONFDIR}"/conf.d/*; do
maybe_add_conf "${i}"
done
# source package confs
for i in /usr/share/initramfs-tools/conf-hooks.d/*; do
if [ -d "${i}" ]; then
echo "W: ${i} is a directory instead of file." >&2
elif [ -e "${i}" ]; then
. "${i}"
fi
done
# Finish loading conf snippets
set +a
# Check busybox dependency
if [ "${BUSYBOX}" = "y" ] && [ -z "${BUSYBOXDIR}" ]; then
echo >&2 "E: @BUSYBOX_PACKAGES@, version @BUSYBOX_MIN_VERSION@ or later, is required but not installed"
exit 1
fi
if [ -n "${UMASK:-}" ]; then
umask "${UMASK}"
fi
if [ -z "${outfile}" ]; then
usage_error
fi
touch "$outfile"
outfile="$(readlink -f "$outfile")"
# And by "version" we really mean path to kernel modules
# This is braindead, and exists to preserve the interface with mkinitrd
if [ ${#} -ne 1 ]; then
version="$(uname -r)"
else
version="${1}"
fi
case "${version}" in
/lib/modules/*/[!/]*)
;;
/lib/modules/[!/]*)
version="${version#/lib/modules/}"
version="${version%%/*}"
;;
esac
case "${version}" in
*/*)
echo "$PROG: ${version} is not a valid kernel version" >&2
exit 2
;;
esac
if [ -z "${compress:-}" ]; then
compress=${COMPRESS?}
fi
unset COMPRESS
if ! command -v "${compress}" >/dev/null 2>&1; then
compress=gzip
[ "${verbose}" = y ] && \
echo "No ${compress} in ${PATH}, using gzip"
fi
case "${compress}" in
gzip) # If we're doing a reproducible build, use gzip -n
if [ -n "${SOURCE_DATE_EPOCH}" ]; then
compress="gzip -n"
# Otherwise, substitute pigz if it's available
elif command -v pigz >/dev/null; then
compress=pigz
fi
;;
lz4) compress="lz4 -9 -l" ;;
xz) compress="xz --check=crc32"
# If we're not doing a reproducible build, enable multithreading
test -z "${SOURCE_DATE_EPOCH}" && compress="$compress --threads=0"
;;
bzip2|lzma|lzop)
# no parameters needed
;;
*) echo "W: Unknown compression command ${compress}" >&2 ;;
esac
if [ -d "${outfile}" ]; then
echo "${outfile} is a directory" >&2
exit 1
fi
MODULESDIR="/lib/modules/${version}"
if [ ! -e "${MODULESDIR}" ]; then
echo "W: missing ${MODULESDIR}" >&2
echo "W: Ensure all necessary drivers are built into the linux image!" >&2
fi
if [ ! -e "${MODULESDIR}/modules.dep" ]; then
depmod "${version}"
fi
# Prepare to clean up temporary files on exit
DESTDIR=
__TMPCPIOGZ=
__TMPEARLYCPIO=
clean_on_exit() {
if [ "${keep}" = "y" ]; then
echo "Working files in ${DESTDIR:-<not yet created>}, early initramfs in ${__TMPEARLYCPIO:-<not yet created>} and overlay in ${__TMPCPIOGZ:-<not yet created>}"
else
for path in "${DESTDIR}" "${__TMPCPIOGZ}" "${__TMPEARLYCPIO}"; do
test -z "${path}" || rm -rf "${path}"
done
fi
}
trap clean_on_exit EXIT
trap "exit 1" INT TERM # makes the EXIT trap effective even when killed
# Create temporary directory and files for initramfs contents
[ -n "${TMPDIR}" ] && [ ! -w "${TMPDIR}" ] && unset TMPDIR
DESTDIR="$(mktemp -d "${TMPDIR:-/var/tmp}/mkinitramfs_XXXXXX")" || exit 1
chmod 755 "${DESTDIR}"
__TMPCPIOGZ="$(mktemp "${TMPDIR:-/var/tmp}/mkinitramfs-OL_XXXXXX")" || exit 1
__TMPEARLYCPIO="$(mktemp "${TMPDIR:-/var/tmp}/mkinitramfs-FW_XXXXXX")" || exit 1
DPKG_ARCH=$(dpkg --print-architecture)
# Export environment for hook scripts.
#
export MODULESDIR
export version
export CONFDIR
export DESTDIR
export DPKG_ARCH
export verbose
export MODULES
export BUSYBOX
export COMPCACHE_SIZE
export RESUME
# Private, used by 'catenate_cpiogz'.
export __TMPCPIOGZ
# Private, used by 'prepend_earlyinitramfs'.
export __TMPEARLYCPIO
# Create usr-merged filesystem layout, to avoid duplicates if the host
# filesystem is usr-merged.
for d in /bin /lib* /sbin; do
mkdir -p "${DESTDIR}/usr${d}"
ln -s "usr${d}" "${DESTDIR}${d}"
done
for d in conf/conf.d etc run scripts ${MODULESDIR}; do
mkdir -p "${DESTDIR}/${d}"
done
# Copy in modules.builtin and modules.order (not generated by depmod)
# and modules.builtin.bin (generated by depmod, but too late to avoid
# error messages as in #948257)
for x in modules.builtin modules.builtin.bin modules.order; do
if [ -f "${MODULESDIR}/${x}" ]; then
cp -p "${MODULESDIR}/${x}" "${DESTDIR}${MODULESDIR}/${x}"
fi
done
# MODULES=list case. Always honour.
for x in "${CONFDIR}/modules" /usr/share/initramfs-tools/modules.d/*; do
if [ -f "${x}" ]; then
add_modules_from_file "${x}"
fi
done
# MODULES=most is default
case "${MODULES}" in
dep)
dep_add_modules
;;
most)
auto_add_modules
;;
netboot)
auto_add_modules base
auto_add_modules net
;;
list)
# nothing to add
;;
*)
echo "W: mkinitramfs: unsupported MODULES setting: ${MODULES}." >&2
echo "W: mkinitramfs: Falling back to MODULES=most." >&2
auto_add_modules
;;
esac
# Resolve hidden dependencies
hidden_dep_add_modules
# First file executed by linux
cp -p /usr/share/initramfs-tools/init "${DESTDIR}/init"
# add existant boot scripts
for b in $(cd /usr/share/initramfs-tools/scripts/ && find . \
-regextype posix-extended -regex '.*/[[:alnum:]\._-]+$' -type f); do
option=$(sed '/^OPTION=/!d;$d;s/^OPTION=//;s/[[:space:]]*$//' "/usr/share/initramfs-tools/scripts/${b}")
# shellcheck disable=SC1083,SC2086
[ -z "$option" ] || eval test -n \"\${$option}\" -a \"\${$option}\" != \"n\" || continue
[ -d "${DESTDIR}/scripts/$(dirname "${b}")" ] \
|| mkdir -p "${DESTDIR}/scripts/$(dirname "${b}")"
cp -p "/usr/share/initramfs-tools/scripts/${b}" \
"${DESTDIR}/scripts/$(dirname "${b}")/"
done
# Prune dot-files/directories and limit depth to exclude VCS files
for b in $(cd "${CONFDIR}/scripts" && find . -maxdepth 2 -name '.?*' -prune -o \
-regextype posix-extended -regex '.*/[[:alnum:]\._-]+$' -type f -print); do
option=$(sed '/^OPTION=/!d;$d;s/^OPTION=//;s/[[:space:]]*$//' "${CONFDIR}/scripts/${b}")
# shellcheck disable=SC1083,SC2086
[ -z "$option" ] || eval test -n \"\${$option}\" -a \"\${$option}\" != \"n\" || continue
[ -d "${DESTDIR}/scripts/$(dirname "${b}")" ] \
|| mkdir -p "${DESTDIR}/scripts/$(dirname "${b}")"
cp -p "${CONFDIR}/scripts/${b}" "${DESTDIR}/scripts/$(dirname "${b}")/"
done
echo "DPKG_ARCH=${DPKG_ARCH}" > "${DESTDIR}/conf/arch.conf"
cp -p "${CONFDIR}/initramfs.conf" "${DESTDIR}/conf"
for i in ${EXTRA_CONF}; do
copy_file config "${i}" /conf/conf.d
done
# ROOT hardcoding
if [ -n "${ROOT:-}" ]; then
echo "ROOT=${ROOT}" > "${DESTDIR}/conf/conf.d/root"
fi
if ! command -v ldd >/dev/null 2>&1 ; then
echo "E: no ldd around - install libc-bin" >&2
exit 1
fi
# fstab and mtab
touch "${DESTDIR}/etc/fstab"
ln -s /proc/mounts "${DESTDIR}/etc/mtab"
# install wait-for-root binary.
copy_exec /usr/lib/initramfs-tools/bin/wait-for-root /sbin
# module-init-tools
copy_exec /sbin/modprobe /sbin
copy_exec /sbin/rmmod /sbin
mkdir -p "${DESTDIR}/etc/modprobe.d" "${DESTDIR}/lib/modprobe.d"
for file in /etc/modprobe.d/*.conf /lib/modprobe.d/*.conf ; do
if test -e "$file" || test -L "$file" ; then
copy_file config "$file"
fi
done
run_scripts_optional /usr/share/initramfs-tools/hooks
run_scripts_optional "${CONFDIR}"/hooks
# cache boot run order
for b in $(cd "${DESTDIR}/scripts" && find . -mindepth 1 -type d); do
cache_run_scripts "${DESTDIR}" "/scripts/${b#./}"
done
# generate module deps
depmod -a -b "${DESTDIR}" "${version}"
rm -f "${DESTDIR}/lib/modules/${version}"/modules.*map
# make sure that library search path is up to date
cp -pPr /etc/ld.so.conf* "$DESTDIR"/etc/
if ! ldconfig -r "$DESTDIR" ; then
[ "$(id -u)" != "0" ] \
&& echo "ldconfig might need uid=0 (root) for chroot()" >&2
fi
# The auxiliary cache is not reproducible and is always invalid at boot
# (see #845034)
if [ -d "${DESTDIR}"/var/cache/ldconfig ]; then
rm -f "${DESTDIR}"/var/cache/ldconfig/aux-cache
rmdir --ignore-fail-on-non-empty "${DESTDIR}"/var/cache/ldconfig
fi
# Apply DSDT to initramfs
if [ -e "${CONFDIR}/DSDT.aml" ]; then
copy_file DSDT "${CONFDIR}/DSDT.aml"
fi
case "${MODULES}" in
netboot|most) add_dns "${DESTDIR}/";;
esac
# Remove any looping or broken symbolic links, since they break cpio.
[ "${verbose}" = y ] && xargs_verbose="-t"
(cd "${DESTDIR}" && find . -type l -printf '%p %Y\n' | sed -n 's/ [LN]$//p' \
| xargs ${xargs_verbose:-} -rL1 rm -f)
[ "${verbose}" = y ] && echo "Building cpio ${outfile} initramfs"
if [ -s "${__TMPEARLYCPIO}" ]; then
cat "${__TMPEARLYCPIO}" >"${outfile}" || exit 1
else
# truncate
true > "${outfile}"
fi
(
# preserve permissions if root builds the image, see #633582
[ "$(id -ru)" != 0 ] && cpio_owner_root="-R 0:0"
# if SOURCE_DATE_EPOCH is set, try and create a reproducible image
if [ -n "${SOURCE_DATE_EPOCH}" ]; then
# ensure that no timestamps are newer than $SOURCE_DATE_EPOCH
find "${DESTDIR}" -newermt "@${SOURCE_DATE_EPOCH}" -print0 | \
xargs -0r touch --no-dereference --date="@${SOURCE_DATE_EPOCH}"
# --reproducible requires cpio >= 2.12
cpio_reproducible="--reproducible"
fi
# work around lack of "set -o pipefail" for the following pipe:
# cd "${DESTDIR}" && find . | LC_ALL=C sort | cpio --quiet $cpio_owner_root $cpio_reproducible -o -H newc | gzip >>"${outfile}" || exit 1
ec1=1
ec2=1
ec3=1
exec 3>&1
eval "$(
# http://cfaj.freeshell.org/shell/cus-faq-2.html
exec 4>&1 >&3 3>&-
cd "${DESTDIR}"
{
find . 4>&-; echo "ec1=$?;" >&4
} | {
LC_ALL=C sort
} | {
# shellcheck disable=SC2086
cpio --quiet $cpio_owner_root $cpio_reproducible -o -H newc 4>&-; echo "ec2=$?;" >&4
} | ${compress} >>"${outfile}"
echo "ec3=$?;" >&4
)"
if [ "$ec1" -ne 0 ]; then
echo "E: mkinitramfs failure find $ec1 cpio $ec2 $compress $ec3" >&2
exit "$ec1"
fi
if [ "$ec2" -ne 0 ]; then
echo "E: mkinitramfs failure cpio $ec2 $compress $ec3" >&2
exit "$ec2"
fi
if [ "$ec3" -ne 0 ]; then
echo "E: mkinitramfs failure $compress $ec3" >&2
exit "$ec3"
fi
) || exit 1
if [ -s "${__TMPCPIOGZ}" ]; then
cat "${__TMPCPIOGZ}" >>"${outfile}" || exit 1
fi
exit 0

146
mkinitramfs.8 Normal file
View File

@ -0,0 +1,146 @@
.TH MKINITRAMFS 8 "2018/07/18" "initramfs\-tools" "System Administration"
.SH NAME
mkinitramfs \- low-level tool for generating an initramfs image
.SH SYNOPSIS
.B mkinitramfs
.RI [ option ]...
.B \-o
.IR outfile
.RI [ version ]
.br
.BR mkinitramfs " " -h
.SH DESCRIPTION
The
.B mkinitramfs
script generates an initramfs image.
The initramfs is a compressed cpio archive. The archive can be used on a
different box of the same arch with the corresponding Linux kernel.
.B mkinitramfs
is meant for advanced usage. On your local box
.B update-initramfs
calls
.B mkinitramfs
with the relevant parameters.
.B update-initramfs
keeps sha1sum of generated initramfs. It takes care to generate backups
and eventually runs the bootloader.
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\-c \fI compress
Override the
.B COMPRESS
setting in
.IR initramfs.conf .
.TP
\fB\-d \fI confdir
Set an alternate configuration directory.
.TP
\fB\-k
Keep the temporary directory used to make the image.
.TP
\fB\-o \fI outfile
Write the image to
.IR outfile .
.TP
\fB\-r \fI root
Override the
.B ROOT
setting in
.IR initramfs.conf .
.TP
\fB\-v
Set the verbose mode output.
.TP
\fIversion
Set the kernel version of the initramfs image
(defaults to the running kernel).
.TP
\fB\-h\fR, \fB\-\-help\fR
Display usage information and exit.
.SH ENVIRONMENT
.B mkinitramfs
honours the
.B TMPDIR
environment variable. If set, it uses subdirectories in the given
directory to create its temporary working directories. Else it uses
.I /var/tmp
as default value for that purpose. The given directory should be on a
filesystem which allows the execution of files stored there, i.e.
should not be mounted with the
.B noexec
mount option.
If
.B SOURCE_DATE_EPOCH
is set,
.B mkinitramfs
attempts to generate a reproducible initramfs image.
.SH FILES
.TP
.I /etc/initramfs-tools/initramfs.conf
The default configuration file for the script. See
.BR initramfs.conf (5)
for a description of the available configuration parameter.
.TP
.I /etc/initramfs-tools/modules
Specified modules will be put in the generated image and loaded when the system boots. The format - one per line - is identical to that of
.I /etc/modules,
which is described in
.BR modules (5).
.TP
.I /etc/initramfs-tools/conf.d
The conf.d directory allows one to hardcode bootargs at initramfs build time
via config snippets. This allows one to set ROOT or RESUME.
This is especially useful for bootloaders, which do not pass an root bootarg.
.TP
.I /etc/initramfs-tools/DSDT.aml
If this file exists, it will be appended to the initramfs in a way that causes
it to be loaded by ACPI.
.SH EXAMPLES
Create an initramfs for current running kernel:
.PP
.B mkinitramfs -o ~/tmp/initramfs-$(uname -r)
Create an initramfs for specific kernel and keep builddirs:
.PP
.B mkinitramfs -k -o ~/tmp/initramfs-2.6.21-686 2.6.21-686
Debug initramfs creation (check out written logfile)
.PP
.B sh -x mkinitramfs -o ~/tmp/initramfs-$(uname -r) 2> ~/tmp/log
.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 update-initramfs (8),
.IR lsinitramfs (8),
.IR unmkinitramfs (8).

910
scripts/functions Normal file
View File

@ -0,0 +1,910 @@
# -*- shell-script -*-
_log_msg()
{
if [ "${quiet?}" = "y" ]; then return; fi
# shellcheck disable=SC2059
printf "$@"
}
log_success_msg()
{
_log_msg "Success: %s\\n" "$*"
}
log_failure_msg()
{
_log_msg "Failure: %s\\n" "$*"
}
log_warning_msg()
{
_log_msg "Warning: %s\\n" "$*"
}
log_begin_msg()
{
_log_msg "Begin: %s ... " "$*"
}
log_end_msg()
{
_log_msg "done.\\n"
}
# Add failure hook
add_mountroot_fail_hook()
{
mkdir -p /tmp/mountroot-fail-hooks.d
ln -s "$0" /tmp/mountroot-fail-hooks.d/"$0"
}
# Run failure hooks.
# When a failure hook exits "1", it has not done anything to correct the
# system. Exiting "0" means that something has been attempted to resolve
# the lack of a root filesystem.
# Hooks are run in lexigraphical order, and are responsible for removing
# themselves if they should not re-run in a later cycle. When one exits
# "0", the stack is stopped, so the caller can return to the main rootfs
# wait loop.
try_failure_hooks()
{
local hook
chvt 1
if [ -x /bin/plymouth ] && plymouth --ping; then
/bin/plymouth hide-splash > /dev/null 2>&1
fi
for hook in /tmp/mountroot-fail-hooks.d/*; do
if [ -x "${hook}" ] && "${hook}" mountfail; then
return 0
fi
done
return 1
}
panic()
{
local console rest IFS
if command -v chvt >/dev/null 2>&1; then
chvt 1
fi
echo "$@"
# Disallow console access
if [ -n "${panic?}" ]; then
echo "Rebooting automatically due to panic= boot argument"
[ "$panic" = "-1" ] || sleep "${panic}"
reboot -f
exit # in case reboot fails, force kernel panic
fi
run_scripts /scripts/panic
# Try to use setsid, which will enable job control in the shell
# and paging in more
if command -v setsid >/dev/null 2>&1; then
unset IFS
read -r console rest </proc/consoles
if [ "${console}" = "tty0" ]; then
# Need to choose a specific VT
console="tty1"
fi
# We don't have 'setsid -c' so we need to setsid, open
# the tty, and finally exec an interactive shell
REASON="$*" PS1='(initramfs) ' setsid sh -c "exec sh -i <>/dev/${console} 1>&0 2>&1"
else
REASON="$*" PS1='(initramfs) ' sh -i </dev/console >/dev/console 2>&1
fi
}
maybe_break()
{
case ",${break?}," in
*,$1,*)
if [ "$1" = "top" ]; then
# udev is not yet running, so load keyboard drivers
if [ "${quiet}" = "y" ]; then
opts="-q"
else
opts="-v"
fi
modprobe ${opts} -a i8042 atkbd ehci-pci ehci-orion \
ehci-hcd ohci-hcd ohci-pci uhci-hcd usbhid xhci \
xhci-pci xhci-hcd
sleep 2
for modalias in /sys/bus/hid/devices/*/modalias; do
if [ -f "${modalias}" ]; then
modprobe ${opts} -b "$(cat "${modalias}")"
fi
done
fi
panic "Spawning shell within the initramfs"
;;
esac
}
# For boot time only; this is overridden at build time in hook-functions
run_scripts()
{
initdir=${1}
[ ! -d "${initdir}" ] && return
shift
. "${initdir}/ORDER"
}
# Load custom modules first
load_modules()
{
if [ -e /conf/modules ]; then
while read -r m; do
# Skip empty lines
if [ -z "$m" ]; then
continue
fi
# Skip comments - d?ash removes whitespace prefix
com=$(printf "%.1s" "${m}")
if [ "$com" = "#" ]; then
continue
fi
# shellcheck disable=SC2086
modprobe $m
done < /conf/modules
fi
}
# lilo compatibility
parse_numeric() {
case $1 in
*:*)
# Does it match /[0-9]*:[0-9]*/?
minor=${1#*:}
major=${1%:*}
case $major$minor in
*[!0-9]*)
# No.
return
;;
esac
;;
"" | *[!A-Fa-f0-9]*)
# "", "/*", etc.
return
;;
*)
# [A-Fa-f0-9]*
value=$(( 0x${1} ))
minor=$(( (value & 0xff) | (value >> 12) & 0xfff00 ))
major=$(( (value >> 8) & 0xfff ))
;;
esac
# shellcheck disable=SC2034
ROOT="/dev/block/${major}:${minor}"
}
# Parameter: device node to check
# Echos fstype to stdout
# Return value: indicates if an fs could be recognized
get_fstype ()
{
local FS FSTYPE
FS="${1}"
FSTYPE=$(blkid -o value -s TYPE "${FS}") || return
echo "${FSTYPE}"
return 0
}
_handle_device_vs_ip()
{
# If the ip= parameter is present and is a colon-separated list,
# then:
# - If it specifies a device, use that in preference to any
# device name we already have
# - Otherwise, substitute in any device name we already have
local IFS=:
set -f
# shellcheck disable=SC2086
set -- ${IP}
set +f
if [ -n "$6" ]; then
DEVICE="$6"
elif [ $# -ge 2 ] && [ -n "${DEVICE}" ]; then
IP="$1:$2:$3:$4:$5:${DEVICE}"
shift 6 || shift $#
IP="${IP}:$*"
fi
}
run_dhclient() {
local timeout conffile pidfile pid
timeout=$1
shift
conffile="/etc/dhcp/dhclient.conf.$timeout"
pidfile="/tmp/dhclient.pid.$timeout"
cp /etc/dhcp/dhclient.conf "$conffile"
echo "timeout $timeout;" >> "$conffile"
rm -f "$pidfile"
dhclient -v -1 -cf "$conffile" -pf "$pidfile" "$@"
# We do not want the dhclient persisting past the initramfs so
# just kill it here (the pid file will only be written if
# dhclient daemonized, i.e. found an address).
[ -f "$pidfile" ] && read -r pid < "$pidfile" && [ -n "$pid" ] && kill "$pid"
}
all_non_enslaved_devices()
{
for device in /sys/class/net/* ; do
if [ ! -e "$device/flags" ]; then
continue
fi
loop=$(($(cat "$device/flags") & 0x8 && 1 || 0))
bc=$(($(cat "$device/flags") & 0x2 && 1 || 0))
ptp=$(($(cat "$device/flags") & 0x10 && 1 || 0))
# Skip any device that is a loopback
if [ $loop = 1 ]; then
continue
fi
# Skip any device that isn't a broadcast
# or point-to-point.
if [ $bc = 0 ] && [ $ptp = 0 ]; then
continue
fi
# Skip any enslaved device (has "master" link
# attribute on it)
device=$(basename "$device")
ip -o link show "$device" | grep -q -w master && continue
DEVICE="$DEVICE $device"
done
echo "$DEVICE"
}
configure_networking()
{
if [ -n "${BOOTIF}" ]; then
# pxelinux sets BOOTIF to a value based on the mac address of the
# network card used to PXE boot, so use this value for DEVICE rather
# than a hard-coded device name from initramfs.conf. this facilitates
# network booting when machines may have multiple network cards.
# pxelinux sets BOOTIF to 01-$mac_address
# strip off the leading "01-", which isn't part of the mac
# address
temp_mac=${BOOTIF#*-}
# convert to typical mac address format by replacing "-" with ":"
bootif_mac=""
IFS='-'
for x in $temp_mac ; do
if [ -z "$bootif_mac" ]; then
bootif_mac="$x"
else
bootif_mac="$bootif_mac:$x"
fi
done
unset IFS
# look for devices with matching mac address, and set DEVICE to
# appropriate value if match is found.
for device in /sys/class/net/* ; do
if [ -f "$device/address" ]; then
current_mac=$(cat "$device/address")
if [ "$bootif_mac" = "$current_mac" ]; then
DEVICE=${device##*/}
DEVICE6=${device##*/}
break
fi
fi
done
fi
_handle_device_vs_ip
for v in $VLAN; do
VLAN_LINK="$VLAN_LINK ${v##*:}"
done
# activate non-autoconfigured s390x devices
for dev in $DEVICE $DEVICE6 $IP6 $VLAN_LINK; do
case ${dev} in
enc*)
zdev=${dev#enc}
chzdev -e "$zdev" || true
;;
esac
done
for v in $VLAN; do
vlink=${v##*:}
vname=${v%:*}
vid=${vname#*.}
ip link set up dev "$vlink"
ip link add name "$vname" link "$vlink" type vlan id "$vid"
done
wait_for_udev 10
# support ip options see linux sources
# Documentation/filesystems/nfs/nfsroot.txt
# Documentation/frv/booting.txt
for ROUNDTTT in 2 3 4 6 9 16 25 36 64 100; do
# The NIC is to be configured if this file does not exist.
# Ip-Config tries to create this file and when it succeds
# creating the file, ipconfig is not run again.
for x in /run/net-"${DEVICE}".conf /run/net-*.conf ; do
if [ -e "$x" ]; then
IP=done
break
fi
done
for x in /run/net6-"${DEVICE}".conf /run/net6-*.conf ; do
if [ -e "$x" ]; then
IP6=done
break
fi
done
# if we've reached a point where both IP and IP6 are "done",
# then we're finished with network configuration.
if [ "$IP" = done ] && [ "$IP6" = done ]; then
break
fi
case ${IP} in
none|done|off)
# Do nothing
IP=done
;;
""|on|any|dhcp|bootp|both)
if [ "${NETWORK_SKIP_ENSLAVED:-0}" = 0 ] || [ -n "${DEVICE}" ]; then
run_dhclient $ROUNDTTT -4 ${DEVICE:+"${DEVICE}"}
else
# shellcheck disable=SC2046
run_dhclient $ROUNDTTT -4 $(all_non_enslaved_devices)
fi
;;
*)
ipconfig -t ${ROUNDTTT} -d "$IP"
;;
esac
case ${IP6} in
""|none|done|off)
# Do nothing
IP6=done
;;
*)
# check the content of IP6 and if it is not on/dhcp/any use it as
# a device name. Otherwise all devices will be tried (unless
# BOOTIF was set, see above).
case "${IP6}" in
on|dhcp|any)
;;
*)
DEVICE6="$IP6" ;;
esac
if [ "${NETWORK_SKIP_ENSLAVED:-0}" = 0 ] || [ -n "${DEVICE6}" ]; then
run_dhclient $ROUNDTTT -6 ${DEVICE6:+"${DEVICE6}"}
else
# shellcheck disable=SC2046
run_dhclient $ROUNDTTT -6 $(all_non_enslaved_devices)
fi
;;
esac
done
# source ipconfig output for either $DEVICE or the first one.
# If the user is booting with only IPv6, then DEVICE may be set,
# but no IPv4 conf files exist.
for conf in /run/"net-$DEVICE.conf" /run/net-*.conf; do
if [ -e "$conf" ]; then
# source specific bootdevice
. "$conf"
break
fi
done
netinfo_to_resolv_conf /etc/resolv.conf \
/run/"net-${DEVICE}.conf" /run/net-*.conf /run/net6-*.conf
netinfo_to_netplan /run/netplan \
/run/"net-${DEVICE}.conf" /run/net-*.conf /run/net6-*.conf
}
netinfo_to_resolv_conf() {
# netinfo_to_resolv_conf(output, files)
# write resolv_conf from /run/net-<device> style files.
if [ "${_in_subshell:-0}" = "0" ]; then
# subshell to avoid modification of variables by '.'
# shellcheck disable=SC2030
( _in_subshell=1; netinfo_to_resolv_conf "$@" )
return
fi
local output="$1" search="" ns="" f="" n=""
shift
for f in "$@"; do
[ -f "$f" ] || continue
unset IPV4DNS0 IPV4DNS1 IPV6DNS0 IPV6DNS1
unset DOMAINSEARCH IPV6DOMAINSEARCH
. "$f" || { echo "WARN: failed '. \"$f\"'" 1>&2; return 1; }
for n in "${IPV4DNS0}" "${IPV4DNS1}" \
"${IPV6DNS0}" "${IPV6DNS1}"; do
[ -n "$n" ] && [ "$n" != 0.0.0.0 ] || continue
# skip if 'n' already in list.
case " ${ns} " in
*\ $n\ *) continue;;
esac
ns="${ns} ${n}"
done
for n in "${DOMAINSEARCH}" "${IPV6DOMAINSEARCH}"; do
[ -n "$n" ] || continue
# skip if already in search.
case " ${search}" in
*\ $n\ *) continue;;
esac
search="$search $n"
done
search=${search# }
ns=${ns# }
done
local rconf="" CR="
"
for n in ${ns}; do
rconf="${rconf}nameserver $n${CR}"
done
if [ -n "${search}" ]; then
rconf="${rconf}search ${search}${CR}"
fi
if [ -z "$rconf" ]; then
echo "no search or nameservers found in $*" 1>&2
fi
if [ "$rconf" = "-" ]; then
echo -n "$rconf"
else
echo -n "$rconf" > "$output"
fi
}
mask2cidr() {
# https://forum.openwrt.org/viewtopic.php?pid=220781#p220781
# Assumes there's no "255." after a non-255 byte in the mask
local x=${1##*255.}
set -- 0^^^128^192^224^240^248^252^254^ $(( (${#1} - ${#x})*2 )) "${x%%.*}"
x=${1%%$3*}
echo $(( $2 + (${#x}/4) ))
}
_declare_sh_append_var() {
# append_var(name, skip, strings)
# write a declaration of name that will append to any existing
local name="$1" skip="$2" add="" n=""
shift 2
for n in "$@"; do
[ -n "$n" ] && [ "$n" != "$skip" ] || continue
add="$add $n"
done
add=${add# }
[ -n "$add" ] || return 0
echo "$name=\"\${${name}:+\${${name}} }${add}\""
}
_declare_ip_info() {
# declare_ip_info(version, proto, address, netmask, gateway)
local version="$1" proto="$2" address="$3" netmask="$4" gateway="$5"
local netprefix=""
case $proto in
dhcp|dhcp4|dhcp6)
echo "dhcp${version}=true"
;;
none)
if [ -n "$address" ]; then
netprefix=$netmask
if [ "$version" = "4" ]; then
netprefix=$(mask2cidr "$netmask")
fi
_declare_sh_append_var addresses "" "$address/$netprefix"
fi
if [ -n "$gateway" ]; then
echo "gateway${version}=$gateway"
fi
;;
esac
}
_render_netplan() {
# write a netplan stanza for the given device.
local name="$1" mac="$2" dhcp4="$3" dhcp6="$4" addrs="$5" \
gateway4="$6" gateway6="$7" ns_addrs="$8" ns_search="$9" \
vlink="${10}" vname="${11}" vid="${12}"
local n found=""
if [ -n "$vlink" ]; then
name=$vlink
fi
echo "network:"
echo " version: 2"
echo " renderer: networkd"
echo " ethernets:"
echo " $name:"
if [ -n "$mac" ] && grep -q net.ifnames=0 /proc/cmdline 2>/dev/null; then
echo " match:"
echo " macaddress: \"$mac\""
echo " set-name: $name"
elif [ -n "$vname" ]; then
echo " {}"
fi
if [ -n "$vname" ]; then
echo " vlans:"
echo " $vname:"
echo " id: $vid"
echo " link: $name"
fi
if [ -n "$dhcp4" ]; then
echo " dhcp4: $dhcp4"
echo " dhcp-identifier: mac"
fi
[ -n "$dhcp6" ] && echo " dhcp6: $dhcp6" || true
[ -n "$dhcp4$dhcp6" ] && echo " critical: true" || true
if [ -n "$addrs" ]; then
echo " addresses:"
found=","
for n in $addrs; do
# remove dups
[ "${found#*,$n,}" = "${found}" ] || continue
found="${found}$n,"
echo " - \"$n\""
done
fi
[ -n "$gateway4" ] && echo " gateway4: \"$gateway4\"" || true
[ -n "$gateway6" ] && echo " gateway6: \"$gateway6\"" || true
if [ -n "$ns_addrs" ]; then
local alist="[" slist=""
for n in $ns_addrs; do
# do not put in duplicates
[ "${alist#*\"$n\"}" = "$alist" ] || continue
alist="${alist}\"$n\", ";
done
alist="${alist%, }]"
if [ -n "$ns_search" ]; then
slist="["
for n in ${ns_search}; do
# do not put in duplicates
[ "${slist#*\"$n\"}" = "$slist" ] || continue
slist="${slist}\"$n\", ";
done
slist="${slist%, }]"
fi
echo " nameservers:"
echo " addresses: $alist"
[ -n "$slist" ] && echo " search: $slist" || true
fi
}
netinfo_to_netplan() {
# read /run/net-* files write netplan config.
# shellcheck disable=SC2031
if [ "${_in_subshell:-0}" = "0" ]; then
# subshell to avoid modification of variables by '.'
( _in_subshell=1; netinfo_to_netplan "$@" )
return
fi
local out_d="$1" tmpd
if command -v mktemp >/dev/null 2>&1; then
tmpd=$(mktemp -d "${TMPDIR:-/tmp}/${0##*/}.XXXXXX")
else
tmpd="${TMPDIR:-/tmp}/${0##*/}.niinfo.$$"
mkdir -p "$tmpd" || return
fi
local devices="" mac=""
# we go through all the files presented and create per-device files in
# a tmpdir that are shell sourceable and closer to the netplan that
# we want to render. Then render those to netplan stanzas.
for f in "$@"; do
[ -f "$f" ] || continue
unset DEVICE DEVICE6 PROTO IPV6PROTO
unset IPV6ADDR IPV6NETMASK IPV6GATEWAY
unset IPV4ADDR IPV4NETMASK IPV4GATEWAY
. "$f" || { echo "WARN: failed '. \"$f\"'" 1>&2; return 1; }
local name=""
name=${DEVICE:-${DEVICE6}}
[ -n "$name" ] || {
echo "WARN: $f did not define DEVICE or DEVICE6" 1>&2;
return 1;
}
case " ${devices} " in
*\ ${name}\ *) :;;
*) devices="${devices} ${name}"
esac
if [ ! -e "$tmpd/$name" ] \
&& [ -r "/sys/class/net/$name/address" ]
then
read -r mac < /sys/class/net/"$name"/address &&
echo "macaddress=$mac" > "$tmpd/$name"
fi
{
for v in $VLAN; do
vlink=${v##*:}
vname=${v%:*}
vid=${vname#*.}
if [ "$name" = "$vname" ]; then
echo "vlink=$vlink"
echo "vname=$vname"
echo "vid=$vid"
break
fi
done
if [ -n "$DEVICE" ]; then
# shellcheck disable=SC2153
_declare_ip_info 4 "$PROTO" "$IPV4ADDR" "$IPV4NETMASK" "$IPV4GATEWAY"
elif [ -n "$DEVICE6" ]; then
_declare_ip_info 6 "$IPV6PROTO" "$IPV6ADDR" "$IPV6NETMASK" \
"$IPV6GATEWAY"
fi
_declare_sh_append_var ns_addresses "0.0.0.0" \
"${IPV4DNS0}" "${IPV4DNS1}" "${IPV6DNS0}" "${IPV6DNS1}"
_declare_sh_append_var ns_search "" "$DOMAINSEARCH" "$IPV6DOMAINSEARCH"
} >> "$tmpd/$name"
done
[ -d "$out_d" ] || mkdir -p "$out_d" ||
{ echo "WARN: failed mkdir $out_d"; return 1; }
for name in $devices; do
local macaddress="" dhcp4="" dhcp6="" addresses=""
local gateway4="" gateway6="" ns_addresses="" ns_search=""
local vlink="" vname="" vid=""
. "$tmpd/$name"
_render_netplan "$name" "$macaddress" "$dhcp4" "$dhcp6" "$addresses" \
"$gateway4" "$gateway6" "$ns_addresses" "$ns_search" \
"$vlink" "$vname" "$vid" \
> "${out_d}/$name.yaml"
done
rm -Rf "$tmpd"
}
# Wait for queued kernel/udev events
wait_for_udev()
{
command -v udevadm >/dev/null 2>&1 || return 0
udevadm settle ${1:+--timeout=$1}
}
# Find a specific fstab entry
# $1=mountpoint
# $2=fstype (optional)
# returns 0 on success, 1 on failure (not found or no fstab)
read_fstab_entry() {
# Not found by default.
found=1
for file in ${rootmnt?}/etc/fstab; do
if [ -f "$file" ]; then
# shellcheck disable=SC2034
while read -r MNT_FSNAME MNT_DIR MNT_TYPE MNT_OPTS MNT_FREQ MNT_PASS MNT_JUNK; do
case "$MNT_FSNAME" in
""|\#*)
continue;
;;
esac
if [ "$MNT_DIR" = "$1" ]; then
if [ -n "$2" ]; then
[ "$MNT_TYPE" = "$2" ] || continue;
fi
found=0
break 2
fi
done < "$file"
fi
done
return $found
}
# Resolve device node from a name. This expands any LABEL or UUID.
# $1=name
# Resolved name is echoed.
resolve_device() {
DEV="$1"
local orig="$DEV"
case "$DEV" in
LABEL=* | UUID=* | PARTLABEL=* | PARTUUID=*)
if ! DEV="$(blkid -l -t "$DEV" -o device)"; then
DEV="$orig"
# Support uppercase and lowercase UUIDs -- see RFC#4122:
# "Each field is treated as an integer and has its value printed as
# a zero-filled hexadecimal digit string with the most significant
# digit first. The hexadecimal values "a" through "f" are output as
# lower case characters and are case insensitive on input."
#
# Note: that blkid which we will use to map these assums the input is lower
# case.
# Only apply this behaviour to UUIDs.
case "$DEV" in
UUID=* | PARTUUID=*) ;;
*) return 1 ;;
esac
# Pull DEV apart and map it.
local type value fmt
type=$(echo "${DEV}" | cut -f 1 -d =)
value=$(echo "${DEV}" | cut -f 2 -d = | tr 'A-F' 'a-f')
# ... in RFC#4122 format;
# look for five hexadecimal fragments separated by minus signs.
fmt=$( echo "$value" | sed -e 's/[0-9a-fA-F]*//g' )
if [ "$fmt" != '----' ]; then
return 1
fi
DEV="${type}=${value}"
# Retry with the lower cased UUID.
DEV="$(blkid -l -t "$DEV" -o device)" || return 1
fi
;;
esac
[ -e "$DEV" ] && echo "$DEV"
}
# Check a file system.
# $1=device
# $2=mountpoint (for diagnostics only)
# $3=type (may be "auto")
_checkfs_once()
{
DEV="$1"
NAME="$2"
TYPE="$3"
if [ "$NAME" = "/" ] ; then
NAME="root"
fi
FSCK_LOGFILE=/run/initramfs/fsck.log
FSCK_STAMPFILE=/run/initramfs/fsck-${NAME#/}
if [ "${TYPE}" = "auto" ]; then
TYPE="$(get_fstype "${DEV}")"
fi
FSCKCODE=0
if [ -z "${TYPE}" ]; then
log_warning_msg "Type of $NAME file system is unknown, so skipping check."
return
fi
if ! command -v fsck >/dev/null 2>&1; then
log_warning_msg "fsck not present, so skipping $NAME file system"
return
fi
if [ "${fastboot?}" = "y" ] ; then
log_warning_msg "Fast boot enabled, so skipping $NAME file system check."
return
fi
if [ "${forcefsck?}" = "y" ]
then
force="-f"
else
force=""
fi
if [ "${fsckfix?}" = "y" ]
then
fix="-y"
elif [ "${fsckfix?}" = "n" ]
then
fix="-n"
else
fix="-a"
fi
spinner=""
if [ -z "${debug?}" ]; then
spinner="-C"
fi
if [ "${quiet}" = n ]
then
log_begin_msg "Will now check $NAME file system"
logsave -a -s $FSCK_LOGFILE fsck $spinner $force $fix -V -t "$TYPE" "$DEV"
FSCKCODE=$?
log_end_msg
else
log_begin_msg "Checking $NAME file system"
logsave -a -s $FSCK_LOGFILE fsck $spinner $force $fix -T -t "$TYPE" "$DEV"
FSCKCODE=$?
log_end_msg
fi
# NOTE: "failure" is defined as exiting with a return code of
# 4, possibly or-ed with other flags. A return code of 1
# indicates that file system errors were corrected but that
# the boot may proceed.
#
if [ "$FSCKCODE" -eq 32 ]
then
log_warning_msg "File system check was interrupted by user"
elif [ $((FSCKCODE & 4)) -eq 4 ]
then
log_failure_msg "File system check of the $NAME filesystem failed"
return 1
elif [ "$FSCKCODE" -gt 1 ]
then
log_warning_msg "File system check failed but did not detect errors"
sleep 5
else
true > $FSCK_STAMPFILE
fi
return 0
}
checkfs()
{
while ! _checkfs_once "$@"; do
panic "The $2 filesystem on $1 requires a manual fsck"
done
}
# Mount a file system. We parse the information from the fstab. This
# should be overridden by any boot script which can mount arbitrary
# filesystems such as /usr. This default implementation delegates to
# local or nfs based upon the filesystem type.
# $1=mountpoint mount location
mountfs()
{
type=local
read_fstab_entry "$1"
if [ "${MNT_TYPE}" = "nfs" ] || [ "${MNT_TYPE}" = "nfs4" ]; then
type=nfs
fi
${type}_mount_fs "$1"
}
# Mount the root file system. It should be overridden by all
# boot scripts.
mountroot()
{
:
}
# Run /scripts/${boot}-top. This should be overridden by all boot
# scripts.
mount_top()
{
:
}
# Run /scripts/${boot}-premount. This should be overridden by all boot
# scripts.
mount_premount()
{
:
}
# Run /scripts/${boot}-bottom. This should be overridden by all boot
# scripts.
mount_bottom()
{
:
}

View File

@ -0,0 +1,28 @@
#!/bin/sh
PREREQ=""
prereqs()
{
echo "$PREREQ"
}
case $1 in
# get pre-requisites
prereqs)
prereqs
exit 0
;;
esac
# shellcheck disable=SC2013
for x in $(cat /proc/cmdline); do
case ${x} in
all_generic_ide)
modprobe ata_generic all_generic_ide=1
;;
all_generic_ide=*)
if [ -n "${x#all_generic_ide=}" ]; then
modprobe ata_generic all_generic_ide=1
fi
;;
esac
done

35
scripts/init-top/blacklist Executable file
View File

@ -0,0 +1,35 @@
#!/bin/sh
PREREQ=""
prereqs()
{
echo "$PREREQ"
}
case $1 in
# get pre-requisites
prereqs)
prereqs
exit 0
;;
esac
# blacklist vga16fb when vga= or video= given
# shellcheck disable=SC2013
for x in $(cat /proc/cmdline); do
case ${x} in
vga=*|video=*)
echo "blacklist vga16fb" >> /etc/modprobe.d/initramfs.conf
;;
esac
done
# sanity check
[ -z "${blacklist?}" ] && exit 0
# write blacklist to modprobe.d
IFS=','
for b in ${blacklist}; do
echo "blacklist $b" >> /etc/modprobe.d/initramfs.conf
done

129
scripts/init-top/framebuffer Executable file
View File

@ -0,0 +1,129 @@
#!/bin/sh
# shellcheck disable=SC2034
OPTION=FRAMEBUFFER
PREREQ="udev"
prereqs()
{
echo "$PREREQ"
}
case $1 in
# get pre-requisites
prereqs)
prereqs
exit 0
;;
esac
# The options part of the kernel "video=" argument (i.e. everyting
# after "video=<fbdriver>:") has very inconsistent rules.
#
# Generally the following applies:
# 1) options are comma-separated
# 2) options can be in either of these three forms:
# <arg>=<value>, <arg>:<value>, <boolean-arg>.
# 3) the "mode" option has the form <xres>x<yres>[M][R][-<bpp>][@<refresh>][i][m]
# and may or may not start with "mode="
#
# When the options are used with modules, they need to be space-separated
# and the following conversions are needed:
# <arg>:<value> -> <arg>=<value>
# <boolean-arg> -> <boolean-arg>=1
# <modevalue> -> mode=<modevalue>
parse_video_opts()
{
local OPTS="$1"
local IFS=","
# Must be a line like video=<fbdriver>:<opt1>,[opt2]...
if [ "${OPTS}" = "${OPTS%%:*}" ]; then
return
fi
OPTS="${OPTS#*:}"
for opt in ${OPTS}; do
# Already in the "<arg>=<value>" form
if [ "${opt}" != "${opt#*=}" ]; then
echo -n "$opt "
# In the "<arg>:<value>" form
elif [ "${opt}" != "${opt#*:}" ]; then
echo -n "${opt%:*}=${opt#*:} "
# Presumably a modevalue without the "mode=" prefix
elif [ "${opt}" != "${opt#[0-9]*x[0-9]}" ]; then
echo -n "mode=$opt "
# Presumably a boolean
else
echo -n "${opt}=1 "
fi
done
}
FB=""
OPTS=""
# shellcheck disable=SC2013
for x in $(cat /proc/cmdline); do
case ${x} in
vga=*)
FB="vesafb";
OPTS="";
;;
video=*)
FB=${x#*=}
FB="${FB%%:*}"
OPTS="$(parse_video_opts "${x}")"
esac
done
# Map command line name to module name
case ${FB} in
matroxfb)
FB=matroxfb_base
;;
esac
if [ -n "${FB}" ]; then
# Some framebuffer devices need character devices :-/
udevadm settle
# shellcheck disable=SC2086
MODPROBE_OPTIONS=-q modprobe ${FB} ${OPTS}
# Wait for the framebuffer devices to be ready
udevadm settle
else
# If we have no graphics devices yet, wait for udev to settle
[ -d /sys/class/graphics/fbcon ] && \
[ -d /sys/class/graphics/fb0 ] && \
[ -d /sys/class/drm/card0 ] || udevadm settle
# If we still have no graphics device, fall back to vesafb like
# we do in the post-initramfs case in
# /etc/init/udev-fallback-graphics.conf.
# There is a higher risk of racing the regular video driver init
# than there is in the post-initramfs case, because this is earlier
# in boot and the kernel has had less time to finish probing the
# video drivers; and if we probe vesafb when we aren't meant to it
# will cause problems later. So just to be sure, add a sleep(1)
# which seems to be enough time to let the drm interface get loaded.
[ -d /sys/class/graphics/fbcon ] && \
[ -d /sys/class/graphics/fb0 ] && \
[ -d /sys/class/drm/card0 ] || sleep 1
if ! [ -d /sys/class/graphics/fbcon ] \
|| ! [ -d /sys/class/graphics/fb0 ] \
|| ! [ -d /sys/class/drm/card0 ]
then
modprobe -q vesafb 2>/dev/null
udevadm settle
fi
fi
# Force fb mode via /sys interface
# shellcheck disable=SC2013
for x in $(cat /proc/cmdline); do
case ${x} in
fbmode=*)
MODE=${x#*=}
echo "$MODE" > /sys/class/graphics/fb0/mode
;;
esac
done

303
scripts/local Normal file
View File

@ -0,0 +1,303 @@
# Local filesystem mounting -*- shell-script -*-
local_top()
{
if [ "${local_top_used}" != "yes" ]; then
[ "${quiet?}" != "y" ] && log_begin_msg "Running /scripts/local-top"
run_scripts /scripts/local-top
[ "$quiet" != "y" ] && log_end_msg
fi
local_top_used=yes
# Start time for measuring elapsed time in local_device_setup
if [ -z "${local_top_time}" ]; then
local_top_time="$(cat /proc/uptime)"
local_top_time="${local_top_time%%[. ]*}"
local_top_time=$((local_top_time + 1)) # round up
export local_top_time
fi
}
local_block()
{
[ "${quiet?}" != "y" ] && log_begin_msg "Running /scripts/local-block"
run_scripts /scripts/local-block "$@"
[ "$quiet" != "y" ] && log_end_msg
}
local_premount()
{
if [ "${local_premount_used}" != "yes" ]; then
[ "${quiet?}" != "y" ] && log_begin_msg "Running /scripts/local-premount"
run_scripts /scripts/local-premount
[ "$quiet" != "y" ] && log_end_msg
fi
local_premount_used=yes
}
local_bottom()
{
if [ "${local_premount_used}" = "yes" ] || [ "${local_top_used}" = "yes" ]; then
[ "${quiet?}" != "y" ] && log_begin_msg "Running /scripts/local-bottom"
run_scripts /scripts/local-bottom
[ "$quiet" != "y" ] && log_end_msg
fi
local_premount_used=no
local_top_used=no
unset local_top_time
}
# $1=device ID to mount
# $2=optionname (for root and etc)
# $3=panic if device is missing (true or false, default: true)
# Sets $DEV to the resolved device node
local_device_setup()
{
local dev_id="$1"
local name="$2"
local may_panic="${3:-true}"
local real_dev
local time_elapsed
local count
# If wait-for-root understands this prefix, then use it to wait for
# the device rather than settling the whole of udev.
# Timeout is max(30, rootdelay) seconds (approximately)
local slumber=30
case $DPKG_ARCH in
powerpc|ppc64|ppc64el)
slumber=180
;;
*)
slumber=30
;;
esac
if [ "${ROOTDELAY:-0}" -gt $slumber ]; then
slumber=$ROOTDELAY
fi
case "$dev_id" in
UUID=*|LABEL=*|PARTUUID=*|/dev/*)
FSTYPE=$( wait-for-root "$dev_id" "$slumber" )
;;
*)
wait_for_udev 10
;;
esac
# Load ubi with the correct MTD partition and return since fstype
# doesn't work with a char device like ubi.
if [ -n "$UBIMTD" ]; then
modprobe ubi "mtd=$UBIMTD"
DEV="${dev_id}"
return
fi
# Don't wait for a device that doesn't have a corresponding
# device in /dev and isn't resolvable by blkid (e.g. mtd0)
if [ "${dev_id#/dev}" = "${dev_id}" ] &&
[ "${dev_id#*=}" = "${dev_id}" ]; then
DEV="${dev_id}"
return
fi
# If the root device hasn't shown up yet, give it a little while
# to allow for asynchronous device discovery (e.g. USB). We
# also need to keep invoking the local-block scripts in case
# there are devices stacked on top of those.
#
# in Ubuntu, we should never actually enter this loop as wait-for-root
# above should have waited until the device appeared.
if ! real_dev=$(resolve_device "${dev_id}") ||
! get_fstype "${real_dev}" >/dev/null; then
log_begin_msg "Waiting for ${name}"
while true; do
sleep 1
time_elapsed="$(cat /proc/uptime)"
time_elapsed="${time_elapsed%%[. ]*}"
time_elapsed=$((time_elapsed - local_top_time))
local_block "${dev_id}"
# If mdadm's local-block script counts the
# number of times it is run, make sure to
# run it the expected number of times.
while true; do
if [ -f /run/count.mdadm.initrd ]; then
count="$(cat /run/count.mdadm.initrd)"
elif [ -n "${count}" ]; then
# mdadm script deleted it; put it back
count=$((count + 1))
echo "${count}" >/run/count.mdadm.initrd
else
break
fi
if [ ${count} -ge ${time_elapsed} ]; then
break;
fi
/scripts/local-block/mdadm "${dev_id}"
done
if real_dev=$(resolve_device "${dev_id}") &&
get_fstype "${real_dev}" >/dev/null; then
wait_for_udev 10
log_end_msg 0
break
fi
if [ ${time_elapsed} -ge "${slumber}" ]; then
log_end_msg 1 || true
break
fi
done
fi
# We've given up, but we'll let the user fix matters if they can
while ! real_dev=$(resolve_device "${dev_id}") ||
! get_fstype "${real_dev}" >/dev/null; do
if ! $may_panic; then
echo "Gave up waiting for ${name}"
return 1
fi
echo "Gave up waiting for ${name} device. Common problems:"
echo " - Boot args (cat /proc/cmdline)"
echo " - Check rootdelay= (did the system wait long enough?)"
if [ "${name}" = root ]; then
echo " - Check root= (did the system wait for the right device?)"
fi
echo " - Missing modules (cat /proc/modules; ls /dev)"
panic "ALERT! ${dev_id} does not exist. Dropping to a shell!"
done
DEV="${real_dev}"
}
local_mount_root()
{
local_top
if [ -z "${ROOT}" ]; then
panic "No root device specified. Boot arguments must include a root= parameter."
fi
local_device_setup "${ROOT}" "root file system"
ROOT="${DEV}"
# Get the root filesystem type if not set
if [ -z "${ROOTFSTYPE}" ] || [ "${ROOTFSTYPE}" = auto ]; then
FSTYPE=$(get_fstype "${ROOT}")
else
FSTYPE=${ROOTFSTYPE}
fi
local_premount
if [ "${readonly?}" = "y" ] && \
[ -z "$LOOP" ]; then
roflag=-r
else
roflag=-w
fi
checkfs "${ROOT}" root "${FSTYPE}"
# Mount root
# shellcheck disable=SC2086
mount ${roflag} ${FSTYPE:+-t "${FSTYPE}"} ${ROOTFLAGS} "${ROOT}" "${rootmnt?}"
mountroot_status="$?"
if [ "$LOOP" ]; then
if [ "$mountroot_status" != 0 ]; then
if [ "${FSTYPE}" = ntfs ] || [ "${FSTYPE}" = vfat ]
then
panic "
Could not mount the partition ${ROOT}.
This could also happen if the file system is not clean because of an operating
system crash, an interrupted boot process, an improper shutdown, or unplugging
of a removable device without first unmounting or ejecting it. To fix this,
simply reboot into Windows, let it fully start, log in, run 'chkdsk /r', then
gracefully shut down and reboot back into Windows. After this you should be
able to reboot again and resume the installation.
(filesystem = ${FSTYPE}, error code = $mountroot_status)
"
fi
fi
mkdir -p /host
mount -o move "$rootmnt" /host
while [ ! -e "/host/${LOOP#/}" ]; do
panic "ALERT! /host/${LOOP#/} does not exist. Dropping to a shell!"
done
# Get the loop filesystem type if not set
FSTYPE="$LOOPFSTYPE"
if [ -z "$FSTYPE" ] || [ "$FSTYPE" = "unknown" ]; then
FSTYPE=$(/sbin/blkid -s TYPE -o value "/host/${LOOP#/}")
[ -z "$FSTYPE" ] && FSTYPE="unknown"
fi
if [ "$readonly" = y ]; then
roflag=-r
else
roflag=-w
fi
# FIXME This has no error checking
modprobe loop
# FIXME This has no error checking
# shellcheck disable=SC2086
mount ${roflag} -o loop -t ${FSTYPE} ${LOOPFLAGS} "/host/${LOOP#/}" "${rootmnt?}"
if [ -d "$rootmnt/host" ]; then
mount -o move /host "$rootmnt/host"
fi
fi
}
local_mount_fs()
{
read_fstab_entry "$1"
local_device_setup "$MNT_FSNAME" "$1 file system"
MNT_FSNAME="${DEV}"
local_premount
if [ "${readonly}" = "y" ]; then
roflag=-r
else
roflag=-w
fi
if [ "$MNT_PASS" != 0 ]; then
checkfs "$MNT_FSNAME" "$MNT_DIR" "${MNT_TYPE}"
fi
# Mount filesystem
if ! mount ${roflag} -t "${MNT_TYPE}" -o "${MNT_OPTS}" "$MNT_FSNAME" "${rootmnt}${MNT_DIR}"; then
panic "Failed to mount ${MNT_FSNAME} as $MNT_DIR file system."
fi
}
mountroot()
{
local_mount_root
}
mount_top()
{
# Note, also called directly in case it's overridden.
local_top
}
mount_premount()
{
# Note, also called directly in case it's overridden.
local_premount
}
mount_bottom()
{
# Note, also called directly in case it's overridden.
local_bottom
}

133
scripts/local-premount/fixrtc Executable file
View File

@ -0,0 +1,133 @@
#!/bin/sh -e
# initramfs local-premount script for fixrtc
PREREQ=""
# Output pre-requisites
prereqs()
{
echo "$PREREQ"
}
case "$1" in
prereqs)
prereqs
exit 0
;;
esac
# use the fixrtc cmdline option in your bootloader to
# automatically set the hardware clock to the date of
# the last mount of your root filesystem to avoid fsck
# to get confused by the superblock being in the future
BROKEN_CLOCK=""
ROOTDEV=""
# System partition is currently used by ubuntu touch only
SYSTEMPART=""
# shellcheck disable=SC2013
for x in $(cat /proc/cmdline); do
case ${x} in
root=*)
value=${x#*=}
# Find the device node path depending on the form of root= :
case ${value} in
UUID=*)
ROOTDEV=/dev/disk/by-uuid/${value#UUID=}
;;
LABEL=*)
ROOTDEV=/dev/disk/by-label/${value#LABEL=}
;;
*)
ROOTDEV=${value}
;;
esac
;;
systempart=*)
value=${x#*=}
# Find the device node path depending on the form of root= :
case ${value} in
UUID=*)
SYSTEMPART=/dev/disk/by-uuid/${value#UUID=}
;;
LABEL=*)
SYSTEMPART=/dev/disk/by-label/${value#LABEL=}
;;
*)
SYSTEMPART=${value}
;;
esac
# if systempart= is defined we do not want root=/dev/ram
# been taken into account
[ "$ROOTDEV" = "/dev/ram" ] && ROOTDEV=""
;;
fixrtc)
BROKEN_CLOCK=1
;;
esac
done
# Touch devices might not have a valid 'root', so use system part if available
if [ -z "$ROOTDEV" ] && [ -n "$SYSTEMPART" ]; then
ROOTDEV=$SYSTEMPART
fi
if [ -n "$BROKEN_CLOCK" ] && [ -n "$ROOTDEV" ]; then
# need udev settle for /dev/disk/by-* symlinks to be added
udevadm settle
wait-for-root "$ROOTDEV" "${ROOTDELAY:-180}"
ROOTDISK=$(readlink -f "$ROOTDEV")
MOUNTDATESTR=$(dumpe2fs -h "$ROOTDISK" 2>/dev/null|grep "Last mount time")
# Trim whitespace for busybox
MOUNTDATE="${MOUNTDATESTR#*:}"
CREATEDATESTR=$(dumpe2fs -h "$ROOTDISK" 2>/dev/null|grep "Filesystem created") || true
# Trim whitespace for busybox
CREATEDATE="${CREATEDATESTR#*:}"
# Hide stderr to avoid ugly message:
# can't open '/dev/misc/rtc': No such file or directory
# on pi2 (and possible more PIs) where there is no /dev/rtc of
# any kind. We still need to keep this call because we use
# fixrtc on all armhf images.
hwclock -s 2>/dev/null || true
# make sure we're also compatible with busybox, if available
DATE="/bin/date -D%c"
date -D%c 2>/dev/null || DATE=/bin/date
if [ "$MOUNTDATE" = "n/a" ]; then
# some versions of mkfs set n/a now, date is not happy with this so
# let us use some half way sane epoch instead
MOUNTDATE="Fri Jan 1 00:00:00 1999"
fi
TIMESTR=$MOUNTDATE
TIME=$(${DATE} --utc --date "${TIMESTR}" +%s)
CURTIME=$(${DATE} --utc +%s)
# in case the created time is newer than last mount, use that instead
if [ -n "$CREATEDATE" ]; then
CREATETIME=$(${DATE} --utc --date "${CREATEDATE}" +%s)
if [ "$CREATETIME" -gt "$TIME" ]; then
TIMESTR=$CREATEDATE
TIME=$CREATETIME
fi
fi
if [ "$TIME" -gt "$CURTIME" ]; then
${DATE} --set="${TIMESTR} 1 minute" >/dev/null 2>&1
fi
fi
# This script is best-effort. If we couldn't fudge the clock as desired,
# just try to carry on boot anyway:
# It will probably fail, but we won't have made the situation any worse.
exit 0

76
scripts/local-premount/resume Executable file
View File

@ -0,0 +1,76 @@
#!/bin/sh
PREREQ=""
prereqs()
{
echo "$PREREQ"
}
case $1 in
# get pre-requisites
prereqs)
prereqs
exit 0
;;
esac
if [ -z "${resume?}" ] || [ ! -e /sys/power/resume ]; then
exit 0
fi
. /scripts/functions
. /scripts/local
PAGE_SIZE=4096
if [ -x /bin/getconf ]; then
PAGE_SIZE=$(getconf PAGESIZE)
fi
export PAGE_SIZE
if ! local_device_setup "${resume}" "suspend/resume device" false; then
exit 0
fi
DEV=$(readlink "$resume")
DEV=/sys/class/block/${DEV##*/}/dev
if [ -r "$DEV" ]; then
read -r MAJMIN < "$DEV"
fi
if [ -z "$MAJMIN" ]; then
exit 1
fi
if [ "${resume_offset?}" -ge 0 ] 2>/dev/null; then
offset_option=$((${resume_offset?} * PAGE_SIZE))
SWAPTYPE=$(blkid -p -O ${offset_option} "${resume}" -s TYPE -o value)
MAJMIN="${MAJMIN}:${resume_offset?}"
else
SWAPTYPE=$(blkid -p -o value -s TYPE "$resume")
fi
use_plymouth=false
if command -v plymouth >/dev/null && plymouth --ping; then
use_plymouth=true
fi
case "${SWAPTYPE}" in
swsuspend|s1suspend|s2suspend|ulsuspend|tuxonice)
if "$use_plymouth"; then
plymouth message --text="Resuming from $resume"
# The above command does not wait for a framebuffer update to
# complete, so the kernel can freeze the framebuffer before
# the message is even visible. Wait just a moment to make
# that less likely.
sleep 0.1
fi
echo "${MAJMIN}" > /sys/power/resume
;;
esac
if "$use_plymouth"; then
# plymouth hide-message does not work yet
plymouth display-message --text=""
fi

166
scripts/nfs Normal file
View File

@ -0,0 +1,166 @@
# NFS filesystem mounting -*- shell-script -*-
# FIXME This needs error checking
nfs_top()
{
if [ "${nfs_top_used}" != "yes" ]; then
[ "${quiet?}" != "y" ] && log_begin_msg "Running /scripts/nfs-top"
run_scripts /scripts/nfs-top
[ "$quiet" != "y" ] && log_end_msg
fi
nfs_top_used=yes
}
nfs_premount()
{
if [ "${nfs_premount_used}" != "yes" ]; then
[ "${quiet?}" != "y" ] && log_begin_msg "Running /scripts/nfs-premount"
run_scripts /scripts/nfs-premount
[ "$quiet" != "y" ] && log_end_msg
fi
nfs_premount_used=yes
}
nfs_bottom()
{
if [ "${nfs_premount_used}" = "yes" ] || [ "${nfs_top_used}" = "yes" ]; then
[ "${quiet?}" != "y" ] && log_begin_msg "Running /scripts/nfs-bottom"
run_scripts /scripts/nfs-bottom
[ "$quiet" != "y" ] && log_end_msg
fi
nfs_premount_used=no
nfs_top_used=no
}
# parse nfs bootargs and mount nfs
nfs_mount_root_impl()
{
configure_networking
# get nfs root from dhcp
if [ "x${NFSROOT}" = "xauto" ]; then
# check if server ip is part of dhcp root-path
if [ "${ROOTPATH#*:}" = "${ROOTPATH}" ]; then
NFSROOT=${ROOTSERVER}:${ROOTPATH}
else
NFSROOT=${ROOTPATH}
fi
# nfsroot=[<server-ip>:]<root-dir>[,<nfs-options>]
elif [ -n "${NFSROOT}" ]; then
# nfs options are an optional arg
if [ "${NFSROOT#*,}" != "${NFSROOT}" ]; then
NFSOPTS="-o ${NFSROOT#*,}"
fi
NFSROOT=${NFSROOT%%,*}
if [ "${NFSROOT#*:}" = "$NFSROOT" ]; then
NFSROOT=${ROOTSERVER}:${NFSROOT}
fi
fi
if [ -z "${NFSOPTS}" ]; then
NFSOPTS="-o retrans=10"
fi
nfs_premount
if [ "${readonly?}" = y ]; then
roflag="-o ro"
else
roflag="-o rw"
fi
# shellcheck disable=SC2086
nfsmount -o nolock ${roflag} ${NFSOPTS} "${NFSROOT}" "${rootmnt?}"
}
# NFS root mounting
nfs_mount_root()
{
nfs_top
# For DHCP
modprobe af_packet
wait_for_udev 10
# Default delay is around 180s
delay=${ROOTDELAY:-180}
# loop until nfsmount succeeds
nfs_mount_root_impl
ret=$?
nfs_retry_count=0
while [ ${nfs_retry_count} -lt "${delay}" ] \
&& [ $ret -ne 0 ] ; do
[ "$quiet" != "y" ] && log_begin_msg "Retrying nfs mount"
sleep 1
nfs_mount_root_impl
ret=$?
nfs_retry_count=$(( nfs_retry_count + 1 ))
[ "$quiet" != "y" ] && log_end_msg
done
}
nfs_mount_fs_impl()
{
configure_networking
if [ -z "${NFSOPTS}" ]; then
NFSOPTS="-o retrans=10"
fi
nfs_premount
if [ "${readonly}" = y ]; then
roflag="-o ro"
else
roflag="-o rw"
fi
read_fstab_entry "$1"
# shellcheck disable=SC2086
nfsmount ${roflag} ${NFSOPTS} -o "${MNT_OPTS}" "$MNT_FSNAME" "${rootmnt}${MNT_DIR}"
}
nfs_mount_fs()
{
nfs_top
# For DHCP
modprobe af_packet
wait_for_udev 10
# Default delay is around 180s
delay=${ROOTDELAY:-180}
# Don't loop here; we can't sanely check if it worked like for
# the rootfs or /etc.
nfs_mount_fs_impl "$1"
}
mountroot()
{
nfs_mount_root
}
mount_top()
{
# Note, also called directly in case it's overridden.
nfs_top
}
mount_premount()
{
# Note, also called directly in case it's overridden.
nfs_premount
}
mount_bottom()
{
# Note, also called directly in case it's overridden.
nfs_bottom
}

21
src/Makefile Normal file
View File

@ -0,0 +1,21 @@
PKG_CONFIG = pkg-config
UDEV_CFLAGS = $(shell $(PKG_CONFIG) --cflags libudev)
UDEV_LIBS = $(shell $(PKG_CONFIG) --libs libudev)
CC = gcc
CFLAGS = -g -Wall -O2 $(UDEV_CFLAGS)
LDFLAGS =
.PHONY: all
all: wait-for-root rzscontrol
wait-for-root: wait-for-root.o
$(CC) $(LDFLAGS) -o $@ $< $(UDEV_LIBS)
rzscontrol: rzscontrol.o
$(CC) $(LDFLAGS) -o $@ $<
.PHONY: clean
clean:
rm -f wait-for-root.o wait-for-root rzscontrol.o rzscontrol core *~

42
src/ramzswap_ioctl.h Normal file
View File

@ -0,0 +1,42 @@
/*
* Compressed RAM based swap device
*
* Copyright (C) 2008, 2009, 2010 Nitin Gupta
*
* This code is released using a dual license strategy: BSD/GPL
* You can choose the licence that better fits your requirements.
*
* Released under the terms of 3-clause BSD License
* Released under the terms of GNU General Public License Version 2.0
*
* Project home: http://compcache.googlecode.com
*/
#ifndef _RAMZSWAP_IOCTL_H_
#define _RAMZSWAP_IOCTL_H_
struct ramzswap_ioctl_stats {
u64 disksize; /* user specified or equal to backing swap
* size (if present) */
u64 num_reads; /* failed + successful */
u64 num_writes; /* --do-- */
u64 failed_reads; /* should NEVER! happen */
u64 failed_writes; /* can happen when memory is too low */
u64 invalid_io; /* non-swap I/O requests */
u64 notify_free; /* no. of swap slot free notifications */
u32 pages_zero; /* no. of zero filled pages */
u32 good_compress_pct; /* no. of pages with compression ratio<=50% */
u32 pages_expand_pct; /* no. of incompressible pages */
u32 pages_stored;
u32 pages_used;
u64 orig_data_size;
u64 compr_data_size;
u64 mem_used_total;
} __attribute__ ((packed, aligned(4)));
#define RZSIO_SET_DISKSIZE_KB _IOW('z', 0, size_t)
#define RZSIO_GET_STATS _IOR('z', 1, struct ramzswap_ioctl_stats)
#define RZSIO_INIT _IO('z', 2)
#define RZSIO_RESET _IO('z', 3)
#endif

250
src/rzscontrol.c Normal file
View File

@ -0,0 +1,250 @@
/*
* rzscontrol - Control ramzswap devices
*
* Copyright (C) 2008, 2009 Nitin Gupta
*
* This code is released using a dual license strategy: BSD/GPL
* You can choose the licence that better fits your requirements.
*
* Released under the terms of 3-clause BSD License
* Released under the terms of GNU General Public License Version 2.0
*
* Project home: http://compcache.googlecode.com
*/
#define _GNU_SOURCE
#include <errno.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <getopt.h>
#include <string.h>
#include <stdlib.h>
#include <inttypes.h>
#include <stdint.h>
typedef uint8_t u8;
typedef uint16_t u16;
typedef uint32_t u32;
typedef uint64_t u64;
#include "ramzswap_ioctl.h"
/* Flag set by '--verbose' */
static int verbose_flag;
/* /dev/ramzswapX */
#define MAX_DEVICE_NAME_LEN 32
/*
* 10 decimal digits can represent 2^32.
* All input sizes are in KB, so 10 digits are sufficient.
*/
#define MAX_SIZE_LEN 10
#define VERBOSE(args...) do { \
if (verbose_flag) \
printf(args); \
} while (0)
struct rzs_args {
u64 disksize_kb;
int init;
int reset;
int stats;
};
void usage(void)
{
printf("Usage: rzscontrol {<ramzswap device>} [<options>]\n"
"Example: rzscontrol /dev/ramzswap0 --init\n"
"See rzscontrol manpage for details.\n");
}
void show_stats(struct ramzswap_ioctl_stats *s)
{
#define K(x) ((x) >> 10)
/* Basic stats */
printf(
"DiskSize: %8" PRIu64 " kB\n",
K(s->disksize)
);
/* Extended stats */
printf(
"NumReads: %8" PRIu64 "\n"
"NumWrites: %8" PRIu64 "\n"
"FailedReads: %8" PRIu64 "\n"
"FailedWrites: %8" PRIu64 "\n"
"InvalidIO: %8" PRIu64 "\n"
"NotifyFree: %8" PRIu64 "\n"
"ZeroPages: %8u\n"
"GoodCompress: %8u %%\n"
"NoCompress: %8u %%\n"
"PagesStored: %8u\n"
"PagesUsed: %8u\n"
"OrigDataSize: %8" PRIu64 " kB\n"
"ComprDataSize: %8" PRIu64 " kB\n"
"MemUsedTotal: %8" PRIu64 " kB\n",
s->num_reads,
s->num_writes,
s->failed_reads,
s->failed_writes,
s->invalid_io,
s->notify_free,
s->pages_zero,
s->good_compress_pct,
s->pages_expand_pct,
s->pages_stored,
s->pages_used,
K(s->orig_data_size),
K(s->compr_data_size),
K(s->mem_used_total)
);
}
int do_ioctl(int fd, int argc, struct rzs_args *args)
{
int ret = 0;
/* Print an error message if ioctl fails */
#define ON_ERR(str) do { \
int err; \
if (ret == -1) { \
err = errno; \
printf("%s: %s\n", str, strerror(err)); \
goto out; \
} \
} while (0)
while (argc--) {
if (args->disksize_kb) {
VERBOSE("disksize_kb: %" PRIu64 "\n", args->disksize_kb);
ret = ioctl(fd, RZSIO_SET_DISKSIZE_KB, &args->disksize_kb);
args->disksize_kb = 0;
ON_ERR("disksize_kb");
}
if (args->init) {
ret = ioctl(fd, RZSIO_INIT);
args->init = 0;
ON_ERR("init");
}
if (args->reset) {
ret = ioctl(fd, RZSIO_RESET);
args->reset = 0;
ON_ERR("reset");
}
if (args->stats) {
struct ramzswap_ioctl_stats s;
memset(&s, 0, sizeof(s));
ret = ioctl(fd, RZSIO_GET_STATS, &s);
args->stats = 0;
ON_ERR("stats");
show_stats(&s);
}
} /* while (argc--) */
out:
return ret;
}
int main(int argc, char *argv[])
{
int fd, ret, opt, idx;
struct rzs_args args;
char dev_name[MAX_DEVICE_NAME_LEN];
if (argc < 3) {
usage();
exit(0);
}
memset(&args, 0, sizeof(args));
strncpy(dev_name, argv[1], MAX_DEVICE_NAME_LEN - 1);
dev_name[MAX_DEVICE_NAME_LEN - 1] = '\0';
fd = open(dev_name, O_NONBLOCK);
if (fd == -1) {
ret = errno;
printf("Failed to open %s: %s\n", dev_name, strerror(ret));
return ret;
}
VERBOSE("device: %s\n", dev_name);
ret = 0;
while (1) {
char *endptr = NULL;
static struct option long_options[] = {
{ "disksize_kb", required_argument, 0, 'd' },
{ "init", no_argument, 0, 'i' },
{ "reset", no_argument, 0, 'r' },
{ "stats", no_argument, 0, 's' },
{ "verbose", no_argument, NULL, 'v' },
{ "help", no_argument, NULL, 'h' },
{ NULL, no_argument, NULL, 0 }
};
opt = getopt_long(argc, argv, "m:d:b:irsvh", long_options, &idx);
if (opt == -1)
break;
switch (opt) {
case 'd':
if (strnlen(optarg, MAX_SIZE_LEN + 1) > MAX_SIZE_LEN) {
printf("disksize_kb: %s\n", strerror(EOVERFLOW));
ret = -EOVERFLOW;
goto out;
}
args.disksize_kb = strtoul(optarg, &endptr, 10);
break;
case 's':
args.stats = 1;
break;
case 'i':
args.init = 1;
break;
case 'r':
args.reset = 1;
break;
case 'v':
verbose_flag = 1;
break;
case 'h':
usage();
break;
case '?':
usage();
ret = -EINVAL;
goto out;
default:
/* We never reach here */
break;
}
}
ret = do_ioctl(fd, argc - 2, &args);
out:
close(fd);
return ret;
}

171
src/wait-for-root.c Normal file
View File

@ -0,0 +1,171 @@
#include <libudev.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <time.h>
#include <stdio.h>
#include <limits.h>
#include <signal.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
static int matching_device (struct udev_device *device, const char *path);
static void alarm_handler (int signum);
int
main (int argc,
char *argv[])
{
const char * devpath;
char path[PATH_MAX];
int timeout;
struct udev * udev;
struct udev_monitor *udev_monitor;
struct stat devstat;
struct udev_device * udev_device;
const char * type;
int flags;
if (argc != 3) {
fprintf (stderr, "Usage: %s DEVICE TIMEOUT\n", argv[0]);
exit (2);
}
devpath = argv[1];
if (! strncmp (devpath, "UUID=", 5)) {
strcpy (path, "/dev/disk/by-uuid/");
strcat (path, devpath + 5);
} else if (! strncmp (devpath, "LABEL=", 6)) {
strcpy (path, "/dev/disk/by-label/");
strcat (path, devpath + 6);
} else if (! strncmp (devpath, "PARTUUID=", 9)) {
strcpy (path, "/dev/disk/by-partuuid/");
strcat (path, devpath + 9);
} else {
strcpy (path, devpath);
}
timeout = atoi (argv[2]);
signal (SIGALRM, alarm_handler);
alarm (timeout);
/* Connect to the udev monitor first; if we stat() first, the
* event might happen between the stat() and the time we actually
* get hooked up.
*/
udev = udev_new ();
udev_monitor = udev_monitor_new_from_netlink (udev, "udev");
udev_monitor_filter_add_match_subsystem_devtype (udev_monitor, "block", NULL);
udev_monitor_enable_receiving (udev_monitor);
udev_monitor_set_receive_buffer_size(udev_monitor, 128*1024*1024);
/* Check to see whether the device exists already on the filesystem.
* If this is true, we don't need to wait for it can obtain the
* filesystem type by looking up the udevdb record by major/minor.
*/
if (stat (path, &devstat) == 0 && S_ISBLK (devstat.st_mode))
{
udev_device = udev_device_new_from_devnum (udev, 'b', devstat.st_rdev);
if (udev_device) {
type = udev_device_get_property_value (udev_device, "ID_FS_TYPE");
if (type) {
printf ("%s\n", type);
udev_device_unref (udev_device);
goto exit;
}
udev_device_unref (udev_device);
}
}
/* udev monitor socket is nonblocking by default, but we want to wait
* for events */
flags = fcntl (udev_monitor_get_fd (udev_monitor), F_GETFL, 0);
flags &= ~O_NONBLOCK;
fcntl (udev_monitor_get_fd (udev_monitor), F_SETFL, flags);
/* When the device doesn't exist yet, or is still being processed
* by udev, use the monitor socket to wait it to be done.
*/
while (1) {
/* even though we use a blocking socket this might still fail
* due to ENOBUFS or similar. */
while ((udev_device = udev_monitor_receive_device (udev_monitor)) == NULL)
sleep (1);
if (matching_device (udev_device, devpath)) {
type = udev_device_get_property_value (udev_device, "ID_FS_TYPE");
if (type) {
printf ("%s\n", type);
udev_device_unref (udev_device);
goto exit;
}
}
udev_device_unref (udev_device);
}
exit:
udev_monitor_unref (udev_monitor);
udev_unref (udev);
exit (0);
}
static int
matching_device (struct udev_device *device,
const char * path)
{
const char * devnode;
struct udev_list_entry *devlinks_entry;
/* Match by name */
devnode = udev_device_get_devnode (device);
if (devnode && (! strcmp (path, devnode)))
return 1;
/* Match by UUID */
if (! strncmp (path, "UUID=", 5)) {
const char *uuid;
uuid = udev_device_get_property_value (device, "ID_FS_UUID");
if (uuid && (! strcmp (path + 5, uuid)))
return 1;
}
/* Match by LABEL */
if (! strncmp (path, "LABEL=", 6)) {
const char *label;
label = udev_device_get_property_value (device, "ID_FS_LABEL");
if (label && (! strcmp (path + 6, label)))
return 1;
}
/* Match by symlink */
for (devlinks_entry = udev_device_get_devlinks_list_entry (device);
devlinks_entry != NULL;
devlinks_entry = udev_list_entry_get_next (devlinks_entry))
if (! strcmp (path, udev_list_entry_get_name (devlinks_entry)))
return 1;
return 0;
}
static void
alarm_handler (int signum)
{
exit (1);
}

30
tests/run-tests Executable file
View File

@ -0,0 +1,30 @@
#!/bin/sh
# Simply call all files named 'test_*' in the same directory as this file.
# Record their exit code as pass or fail. exit 1 if any failed.
my_dir=$(dirname "$0")
npass=0
nfail=0
for test_file in "${my_dir}/test_"*; do
[ -f "$test_file" -a -x "$test_file" ] || continue
echo "executing $test_file" 1>&2
"$test_file"
ret=$?
if [ $ret -eq 0 ]; then
npass=$(($npass+1))
else
nfail=$(($nfail+1))
fails="${fails:+${fails} }${test_file}"
fi
done
if [ $nfail -ne 0 ]; then
echo "Passed $npass tests. Failed $nfail tests: ${fails}." 1>&2
exit 1
elif [ $npass -eq 0 ]; then
echo "No tests executed?" 1>&2
else
echo "Passed $npass tests. Failed 0 tests." 1>&2
fi
exit 0

View File

@ -0,0 +1,2 @@
nameserver 192.168.122.1
search foo.com

View File

@ -0,0 +1,17 @@
DEVICE='example1'
PROTO='dhcp'
IPV4ADDR='192.168.122.89'
IPV4BROADCAST='192.168.122.255'
IPV4NETMASK='255.255.255.0'
IPV4GATEWAY='192.168.122.1'
IPV4DNS0='192.168.122.1'
IPV4DNS1='0.0.0.0'
HOSTNAME='foohost'
DNSDOMAIN=''
NISDOMAIN=''
ROOTSERVER='192.168.122.1'
ROOTPATH=''
filename=''
UPTIME='21'
DHCPLEASETIME='3600'
DOMAINSEARCH='foo.com'

View File

@ -0,0 +1,11 @@
network:
version: 2
renderer: networkd
ethernets:
example1:
dhcp4: true
dhcp-identifier: mac
critical: true
nameservers:
addresses: ["192.168.122.1"]
search: ["foo.com"]

View File

@ -0,0 +1,3 @@
nameserver 192.168.122.1
nameserver 2001:67c:1562:8010::2:1
search foo.com example.com ubuntu.com

View File

@ -0,0 +1,17 @@
DEVICE='example1'
PROTO='dhcp'
IPV4ADDR='192.168.122.89'
IPV4BROADCAST='192.168.122.255'
IPV4NETMASK='255.255.255.0'
IPV4GATEWAY='192.168.122.1'
IPV4DNS0='192.168.122.1'
IPV4DNS1='0.0.0.0'
HOSTNAME='foohost'
DNSDOMAIN=''
NISDOMAIN=''
ROOTSERVER='192.168.122.1'
ROOTPATH=''
filename=''
UPTIME='21'
DHCPLEASETIME='3600'
DOMAINSEARCH='foo.com'

View File

@ -0,0 +1,10 @@
DEVICE6=example1
HOSTNAME=
DNSDOMAIN=
IPV6PROTO=dhcp6
IPV6ADDR=2001:67c:1562:8010:0:1::
IPV6NETMASK=64
IPV6DNS0=2001:67c:1562:8010::2:1
IPV6DOMAINSEARCH="example.com ubuntu.com"
HOSTNAME=
DNSDOMAIN=

View File

@ -0,0 +1,12 @@
network:
version: 2
renderer: networkd
ethernets:
example1:
dhcp4: true
dhcp-identifier: mac
dhcp6: true
critical: true
nameservers:
addresses: ["192.168.122.1", "2001:67c:1562:8010::2:1"]
search: ["foo.com", "example.com", "ubuntu.com"]

View File

@ -0,0 +1,12 @@
DEVICE='example1'
PROTO='none'
IPV4ADDR='10.0.0.2'
IPV4BROADCAST='10.0.0.255'
IPV4NETMASK='255.255.255.0'
IPV4GATEWAY='10.0.0.1'
IPV4DNS0='0.0.0.0'
IPV4DNS1='0.0.0.0'
HOSTNAME='foohost'
UPTIME='21'
DHCPLEASETIME=''
DOMAINSEARCH=''

View File

@ -0,0 +1,8 @@
network:
version: 2
renderer: networkd
ethernets:
example1:
addresses:
- "10.0.0.2/24"
gateway4: "10.0.0.1"

View File

@ -0,0 +1,2 @@
nameserver 2001:67c:1562:8010::2:1
search example.com ubuntu.com

View File

@ -0,0 +1,10 @@
DEVICE6=example1
HOSTNAME=
DNSDOMAIN=
IPV6PROTO=dhcp6
IPV6ADDR=2001:67c:1562:8010:0:1::
IPV6NETMASK=64
IPV6DNS0=2001:67c:1562:8010::2:1
IPV6DOMAINSEARCH="example.com ubuntu.com"
HOSTNAME=
DNSDOMAIN=

View File

@ -0,0 +1,10 @@
network:
version: 2
renderer: networkd
ethernets:
example1:
dhcp6: true
critical: true
nameservers:
addresses: ["2001:67c:1562:8010::2:1"]
search: ["example.com", "ubuntu.com"]

View File

@ -0,0 +1,3 @@
nameserver 192.168.122.1
nameserver 2001:67c:1562:8010::2:1
search foo.com example.com ubuntu.com

View File

@ -0,0 +1,22 @@
# VLAN actually comes from vlan= kernel cmdline...
# ... but this file is sourced, so pretend it was
# parsed out kernel cmdline
VLAN=example1.1:example1
# end of hack
DEVICE='example1.1'
PROTO='dhcp'
IPV4ADDR='192.168.122.89'
IPV4BROADCAST='192.168.122.255'
IPV4NETMASK='255.255.255.0'
IPV4GATEWAY='192.168.122.1'
IPV4DNS0='192.168.122.1'
IPV4DNS1='0.0.0.0'
HOSTNAME='foohost'
DNSDOMAIN=''
NISDOMAIN=''
ROOTSERVER='192.168.122.1'
ROOTPATH=''
filename=''
UPTIME='21'
DHCPLEASETIME='3600'
DOMAINSEARCH='foo.com'

View File

@ -0,0 +1,15 @@
# VLAN actually comes from vlan= kernel cmdline...
# ... but this file is sourced, so pretend it was
# parsed out kernel cmdline
VLAN=example1.1:example1
# end of hack
DEVICE6=example1.1
HOSTNAME=
DNSDOMAIN=
IPV6PROTO=dhcp6
IPV6ADDR=2001:67c:1562:8010:0:1::
IPV6NETMASK=64
IPV6DNS0=2001:67c:1562:8010::2:1
IPV6DOMAINSEARCH="example.com ubuntu.com"
HOSTNAME=
DNSDOMAIN=

View File

@ -0,0 +1,17 @@
network:
version: 2
renderer: networkd
ethernets:
example1:
{}
vlans:
example1.1:
id: 1
link: example1
dhcp4: true
dhcp-identifier: mac
dhcp6: true
critical: true
nameservers:
addresses: ["192.168.122.1", "2001:67c:1562:8010::2:1"]
search: ["foo.com", "example.com", "ubuntu.com"]

119
tests/test_netinfo.sh Executable file
View File

@ -0,0 +1,119 @@
#!/bin/sh
data_dir="${0%.sh}.d"
my_dir=$(dirname "$0")
SCRIPTS_D=$(cd "$my_dir/../scripts" && pwd)
RET_SKIP=99
RET_FAIL=2
RET_PASS=0
PASSES=0
FAILS=0
SKIPS=0
logfail() { echo "FAIL:" "$@" 1>&2; return $RET_FAIL; }
logpass() { echo "PASS:" "$@" 1>&2; return $RET_PASS; }
pass_on_nodiff() {
# log_on_diff(tname, expected, found)
local tname="$1" expected="$2" found="$3" out="" opts="-u"
[ -d "$expected" ] && opts="-Naur"
out=$(diff $opts "$expected" "$found")
r=$?
if [ $r -eq 0 ]; then
logpass "$tname"
else
logfail "$tname: expected output differed"
echo "$out" 1>&2
return $RET_FAIL
fi
}
_run_in_functions() {
local name="$1" r=""
shift
sh -ec '. "$1"; shift; "$@";' \
"test-$name" "$SCRIPTS_D/functions" "$@" || {
r=$?
logfail "$name execution returned $r. ($*)"
return $r
}
}
run_resolvconf() {
local bname="$1" testdir="$2" results_d="$3"
local tname="$bname-netinfo-to-resolv.conf"
shift 3
local expected="$testdir/expected-resolv.conf"
local found="$results_d/resolv.conf"
[ -f "$expected" ] || return $RET_SKIP
_run_in_functions "$tname" netinfo_to_resolv_conf "$found" "$@" || return
pass_on_nodiff "$tname" "$expected" "$found"
}
run_netinfo_to_netplan() {
local bname="$1" testdir="$2" results_d="$3"
local tname="$bname-netinfo-to-netplan"
shift 3
local found_d="$results_d/netplan"
local expected_d="$testdir/netplan"
[ -d "$expected_d" ] || return $RET_SKIP
_run_in_functions "$tname" netinfo_to_netplan "$found_d" "$@" || return
pass_on_nodiff "$tname" "$expected_d" "$found_d"
}
run_netplan_generate() {
local bname="$1" testdir="$2" results_d="$3"
local tname="$bname-netplan-generate"
shift 3
local expected_d="$testdir/netplan"
[ -d "$expected_d" ] || return $RET_SKIP
type netplan >/dev/null 2>/dev/null || return $RET_SKIP
mkdir -p $results_d/lib/
cp -r $expected_d $results_d/lib
netplan generate --root-dir $results_d
r=$?
if [ $r -eq 0 ]; then
logpass "$tname"
else
logfail "$tname: netplan generate failed"
return $RET_FAIL
fi
}
record() {
local ret="$1"
case "$ret" in
0) PASSES=$(($PASSES+1));;
$RET_SKIP) SKIPS=$(($SKIPS+1));;
*) FAILS=$(($FAILS+1));;
esac
}
for testdir in "${data_dir}"/*; do
[ -d "$testdir" ] || continue
dname="${testdir##*/}"
results_d=$(mktemp -d "${TMPDIR:-/tmp}/${0##*/}.XXXX")
confs=$(
for f in "${testdir}"/net-*.conf "${testdir}/net6-"*.conf; do
[ -f "$f" ] && echo "$f"
done
)
run_resolvconf "$dname" "$testdir" "$results_d" $confs
record $?
run_netinfo_to_netplan "$dname" "$testdir" "$results_d" $confs
record $?
run_netplan_generate "$dname" "$testdir" "$results_d" $confs
record $?
rm -Rf "${results_d}"
done
echo "INFO: ran $(($PASSES+$FAILS)) tests: $PASSES pass. $FAILS fail."
[ $FAILS -eq 0 ]
exit

172
unmkinitramfs Normal file
View File

@ -0,0 +1,172 @@
#!/bin/sh
set -eu
usage()
{
cat << EOF
Usage: unmkinitramfs [-v] initramfs-file directory
Options:
-v Display verbose messages about extraction
See unmkinitramfs(8) for further details.
EOF
}
usage_error()
{
usage >&2
exit 2
}
# Extract a compressed cpio archive
xcpio()
{
archive="$1"
dir="$2"
shift 2
if gzip -t "$archive" >/dev/null 2>&1 ; then
gzip -c -d "$archive"
elif xzcat -t "$archive" >/dev/null 2>&1 ; then
xzcat "$archive"
elif lz4cat -t < "$archive" >/dev/null 2>&1 ; then
lz4cat "$archive"
elif bzip2 -t "$archive" >/dev/null 2>&1 ; then
bzip2 -c -d "$archive"
elif lzop -t "$archive" >/dev/null 2>&1 ; then
lzop -c -d "$archive"
# Ignoring other data, which may be garbage at the end of the file
fi | (
if [ -n "$dir" ]; then
mkdir -p -- "$dir"
cd -- "$dir"
fi
cpio "$@"
)
}
# Read bytes out of a file, checking that they are valid hex digits
readhex()
{
dd < "$1" bs=1 skip="$2" count="$3" 2> /dev/null | \
LANG=C grep -E "^[0-9A-Fa-f]{$3}\$"
}
# Check for a zero byte in a file
checkzero()
{
dd < "$1" bs=1 skip="$2" count=1 2> /dev/null | \
LANG=C grep -q -z '^$'
}
# Split an initramfs into archives and call xcpio on each
splitinitramfs()
{
initramfs="$1"
dir="$2"
shift 2
count=0
start=0
while true; do
# There may be prepended uncompressed archives. cpio
# won't tell us the true size of these so we have to
# parse the headers and padding ourselves. This is
# very roughly based on linux/lib/earlycpio.c
end=$start
while true; do
if checkzero "$initramfs" $end; then
# This is the EOF marker. There might
# be more zero padding before the next
# archive, so read through all of it.
end=$((end + 4))
while checkzero "$initramfs" $end; do
end=$((end + 4))
done
break
fi
magic="$(readhex "$initramfs" $end 6)" || break
test "$magic" = 070701 || test "$magic" = 070702 || break
namesize=0x$(readhex "$initramfs" $((end + 94)) 8)
filesize=0x$(readhex "$initramfs" $((end + 54)) 8)
end=$(((end + 110)))
end=$(((end + namesize + 3) & ~3))
end=$(((end + filesize + 3) & ~3))
done
if [ $end -eq $start ]; then
break
fi
# Extract to early, early2, ... subdirectories
count=$((count + 1))
if [ $count -eq 1 ]; then
subdir=early
else
subdir=early$count
fi
dd < "$initramfs" skip=$start count=$((end - start)) iflag=skip_bytes 2> /dev/null |
(
if [ -n "$dir" ]; then
mkdir -p -- "$dir/$subdir"
cd -- "$dir/$subdir"
fi
cpio -i "$@"
)
start=$end
done
if [ $end -gt 0 ]; then
# Extract to main subdirectory
subarchive=$(mktemp "${TMPDIR:-/var/tmp}/unmkinitramfs_XXXXXX")
trap 'rm -f "$subarchive"' EXIT
dd < "$initramfs" skip=$end iflag=skip_bytes 2> /dev/null \
> "$subarchive"
xcpio "$subarchive" "${dir:+$dir/main}" -i "$@"
else
# Don't use subdirectories (for backward compatibility)
xcpio "$initramfs" "$dir" -i "$@"
fi
}
OPTIONS=$(getopt -o hv --long help,list,verbose -n "$0" -- "$@") || usage_error
cpio_opts="--preserve-modification-time --no-absolute-filenames --quiet"
expected_args=2
eval set -- "$OPTIONS"
while true; do
case "$1" in
-h|--help)
usage
exit 0
;;
--list)
# For lsinitramfs
cpio_opts="${cpio_opts:+${cpio_opts} --list}"
expected_args=1
shift
;;
-v|--verbose)
cpio_opts="${cpio_opts:+${cpio_opts} --verbose}"
shift
;;
--)
shift
break
;;
*)
echo "Internal error!" >&2
exit 1
esac
done
if [ $# -ne $expected_args ]; then
usage_error
fi
# shellcheck disable=SC2086
splitinitramfs "$1" "${2:-}" $cpio_opts

56
unmkinitramfs.8 Normal file
View File

@ -0,0 +1,56 @@
.TH UNMKINITRAMFS 8 "2016/12/15" "initramfs\-tools" "System Administration"
.SH NAME
unmkinitramfs \- extract content from an initramfs image
.SH SYNOPSIS
.B unmkinitramfs
.RB [ -v ]
.IR initramfs-file " " directory
.br
.BR unmkinitramfs " " -h
.SH DESCRIPTION
The
.B unmkinitramfs
command extracts the content of a given initramfs image using
.BR cpio .
If the image contains multiple segments, each are passed to
.B cpio
in order.
.SH OPTIONS
.TP
.B -h
Display usage information and exit.
.TP
.B -v
Display verbose messages about extraction.
.SH USAGE EXAMPLES
Extract initramfs content of current running kernel:
.PP
.B unmkinitramfs /boot/initrd.img-$(uname -r) initramfs/
.SH BUGS
.BR unmkinitramfs
cannot deal with multiple-segmented initramfs images, except where an
early (uncompressed) initramfs with system firmware is prepended to
the regular compressed initramfs.
.SH AUTHOR
The initramfs-tools are written by Maximilian Attems <maks@debian.org>
and numerous others.
.SH SEE ALSO
.BR
.IR initramfs-tools (7),
.IR lsinitramfs (8),
.IR mkinitramfs (8),
.IR update-initramfs (8).

427
update-initramfs Normal file
View File

@ -0,0 +1,427 @@
#!/bin/sh
STATEDIR=/var/lib/initramfs-tools
BOOTDIR=/boot
CONF=/etc/initramfs-tools/update-initramfs.conf
mode=""
version=""
update_initramfs=yes
backup_initramfs=no
set -e
[ -r ${CONF} ] && . ${CONF}
case "$DPKG_MAINTSCRIPT_PACKAGE" in
linux-image-*)
if [ -z "$INITRAMFS_TOOLS_KERNEL_HOOK" ]; then
# kernel maintainer script called us directly; ignore
# it and let the hook script handle it instead
echo "update-initramfs: deferring update (hook will be called later)"
exit 0
fi
;;
?*)
if [ $# = 1 ] \
&& [ x"$1" = x-u ]
then
if dpkg-trigger --no-await update-initramfs; then
echo "update-initramfs: deferring update (trigger activated)"
exit 0
fi
fi
;;
esac
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}" \
|| 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}"
set_sha1
# 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
}
# Note that this must overwrite so that updates work.
set_sha1()
{
sha1sum "${initramfs}" > "${STATEDIR}/${version}"
}
delete_sha1()
{
rm -f "${STATEDIR}/${version}"
}
# 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}"
delete_sha1
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

95
update-initramfs.8 Normal file
View File

@ -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).

35
update-initramfs.conf.5 Normal file
View File

@ -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).