mirror of
https://gitlab.archlinux.org/tpowa/archboot.git
synced 2024-09-20 03:50:37 +02:00
move function patch to archboot install file
This commit is contained in:
parent
c75c57f091
commit
63c89eeb6a
15 changed files with 267 additions and 1211 deletions
|
@ -9,7 +9,7 @@ FILES=()
|
|||
# SETUP
|
||||
#
|
||||
# Please change the hooks only if you know what you are doing.
|
||||
HOOKS=(kms udev keyboard archboot_base_common archboot_base_latest archboot_installer_common \
|
||||
HOOKS=(archboot kms udev keyboard archboot_base_common archboot_base_latest archboot_installer_common \
|
||||
archboot_net_common archboot_remote archboot_kexec archboot_licenses)
|
||||
|
||||
# COMPRESSION
|
||||
|
|
|
@ -10,7 +10,7 @@ FILES=()
|
|||
# SETUP
|
||||
#
|
||||
# Please change the hooks only if you know what you are doing.
|
||||
HOOKS=(archboot_cache archboot_cache_cleanup archboot_firmware archboot_firmware_cleanup \
|
||||
HOOKS=(archboot archboot_cache archboot_cache_cleanup archboot_firmware archboot_firmware_cleanup \
|
||||
archboot_base_common archboot_base_common_cleanup archboot_base archboot_base_cleanup \
|
||||
archboot_filesystems archboot_filesystems_cleanup archboot_net archboot_net_cleanup \
|
||||
block lvm2 encrypt btrfs keyboard archboot_acpi kms udev archboot_cpufreq \
|
||||
|
|
|
@ -9,7 +9,7 @@ FILES=()
|
|||
# SETUP
|
||||
#
|
||||
# Please change the hooks only if you know what you are doing.
|
||||
HOOKS=(kms udev archboot_base_common archboot_base archboot_installer_common \
|
||||
HOOKS=(archboot kms udev archboot_base_common archboot_base archboot_installer_common \
|
||||
archboot_installer archboot_tz archboot_keymap archboot_acpi archboot_motd archboot_hwdetect \
|
||||
block archboot_net_common archboot_net keyboard archboot_devicemapper archboot_mdadm \
|
||||
mdadm_udev lvm2 archboot_lvm2 encrypt btrfs archboot_filesystems archboot_remote archboot_cpufreq \
|
||||
|
|
|
@ -1,40 +0,0 @@
|
|||
# Created by Tobias Powalowski <tpowa@archlinux.org>
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
# For more information on how using mkinitcpio please refer to the main config file
|
||||
# or check the wiki.
|
||||
MODULES=()
|
||||
BINARIES=()
|
||||
FILES=()
|
||||
|
||||
# SETUP
|
||||
#
|
||||
# Please change the hooks only if you know what you are doing.
|
||||
HOOKS=(archboot_cache archboot_cache_cleanup archboot_firmware archboot_firmware_cleanup \
|
||||
archboot_base_common archboot_base_common_cleanup archboot_base archboot_base_cleanup \
|
||||
archboot_filesystems archboot_filesystems_cleanup archboot_net archboot_net_cleanup \
|
||||
block lvm2 encrypt btrfs keyboard archboot_acpi kms udev archboot_devicemapper \
|
||||
archboot_hypervisor archboot_net_common archboot_platform archboot_wireless \
|
||||
archboot_wireless_staging archboot_installer_common archboot_installer archboot_installer_cleanup \
|
||||
archboot_tz archboot_keymap archboot_motd archboot_hwdetect archboot_mdadm mdadm_udev \
|
||||
archboot_lvm2 archboot_remote archboot_kexec archboot_efibootmgr archboot_pciutils \
|
||||
archboot_usbutils archboot_smartmontools archboot_licenses \
|
||||
archboot_neovim \
|
||||
archboot_secure_boot archboot_efivar archboot_lshw)
|
||||
|
||||
# COMPRESSION
|
||||
# Use this to compress the initramfs image. By default, gzip compression
|
||||
# is used. Use 'cat' to create an uncompressed image.
|
||||
COMPRESSION="zstd"
|
||||
#COMPRESSION="gzip"
|
||||
#COMPRESSION="bzip2"
|
||||
#COMPRESSION="lzma"
|
||||
#COMPRESSION="xz"
|
||||
#COMPRESSION="lzop"
|
||||
#COMPRESSION="lz4"
|
||||
|
||||
# COMPRESSION_OPTIONS
|
||||
# Additional options for the compressor
|
||||
#COMPRESSION_OPTIONS=()
|
||||
MODULES_DECOMPRESS="no"
|
||||
|
||||
# vim: set ft=sh ts=4 sw=4 et:
|
|
@ -9,7 +9,7 @@ FILES=()
|
|||
# SETUP
|
||||
#
|
||||
# Please change the hooks only if you know what you are doing.
|
||||
HOOKS=(kms udev archboot_base_common archboot_base archboot_installer_common \
|
||||
HOOKS=(archboot kms udev archboot_base_common archboot_base archboot_installer_common \
|
||||
archboot_installer archboot_tz archboot_keymap archboot_acpi archboot_motd archboot_hwdetect \
|
||||
block archboot_net_common archboot_net keyboard archboot_devicemapper archboot_mdadm \
|
||||
mdadm_udev lvm2 archboot_lvm2 encrypt btrfs archboot_filesystems archboot_remote \
|
||||
|
|
|
@ -9,7 +9,7 @@ FILES=()
|
|||
# SETUP
|
||||
#
|
||||
# Please change the hooks only if you know what you are doing.
|
||||
HOOKS=(kms udev keyboard archboot_base_common archboot_base_latest \
|
||||
HOOKS=(archboot kms udev keyboard archboot_base_common archboot_base_latest \
|
||||
archboot_installer_common archboot_net_common archboot_remote archboot_kexec archboot_licenses)
|
||||
|
||||
# COMPRESSION
|
||||
|
|
|
@ -9,7 +9,7 @@ FILES=()
|
|||
# SETUP
|
||||
#
|
||||
# Please change the hooks only if you know what you are doing.
|
||||
HOOKS=(kms udev keyboard archboot_base_common archboot_base_latest \
|
||||
HOOKS=(archboot kms udev keyboard archboot_base_common archboot_base_latest \
|
||||
archboot_installer_common archboot_kexec archboot_licenses archboot_cache)
|
||||
|
||||
# COMPRESSION
|
||||
|
|
|
@ -9,7 +9,7 @@ FILES=()
|
|||
# SETUP
|
||||
#
|
||||
# Please change the hooks only if you know what you are doing.
|
||||
HOOKS=(archboot_cache archboot_cache_cleanup archboot_firmware archboot_firmware_cleanup \
|
||||
HOOKS=(archboot archboot_cache archboot_cache_cleanup archboot_firmware archboot_firmware_cleanup \
|
||||
archboot_base_common archboot_base_common_cleanup archboot_base archboot_base_cleanup \
|
||||
archboot_filesystems archboot_filesystems_cleanup archboot_net archboot_net_cleanup block \
|
||||
lvm2 encrypt btrfs keyboard archboot_acpi kms udev archboot_cpufreq \
|
||||
|
|
|
@ -9,7 +9,7 @@ FILES=()
|
|||
# SETUP
|
||||
#
|
||||
# Please change the hooks only if you know what you are doing.
|
||||
HOOKS=(kms udev archboot_base_common archboot_base archboot_installer_common \
|
||||
HOOKS=(archboot kms udev archboot_base_common archboot_base archboot_installer_common \
|
||||
archboot_installer archboot_tz archboot_keymap archboot_acpi archboot_motd \
|
||||
archboot_hwdetect block archboot_pcspkr archboot_net_common archboot_net keyboard \
|
||||
archboot_devicemapper archboot_mdadm mdadm_udev lvm2 archboot_lvm2 encrypt \
|
||||
|
|
|
@ -191,7 +191,4 @@ _set_hostname() {
|
|||
echo 'archboot' > "${1}/etc/hostname"
|
||||
}
|
||||
|
||||
_speed_patch() {
|
||||
cp /usr/share/archboot/patches/functions "${1}"/usr/lib/initcpio/
|
||||
}
|
||||
# vim: set ft=sh ts=4 sw=4 et:
|
||||
|
|
|
@ -56,6 +56,5 @@ fi
|
|||
_change_pacman_conf "${1}" || exit 1
|
||||
_reproducibility "${1}"
|
||||
_set_hostname "${1}" || exit 1
|
||||
_speed_patch "${1}" || exit 1
|
||||
echo "Finished container setup in ${1}."
|
||||
# vim: set ft=sh ts=4 sw=4 et:
|
||||
|
|
259
usr/lib/initcpio/install/archboot
Normal file
259
usr/lib/initcpio/install/archboot
Normal file
|
@ -0,0 +1,259 @@
|
|||
#!/usr/bin/env bash
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
# Created by Tobias Powalowski <tpowa@archlinux.org>
|
||||
|
||||
build ()
|
||||
{
|
||||
add_firmware() {
|
||||
# add a firmware file to the image.
|
||||
# $1: firmware path fragment
|
||||
|
||||
local fw fwpath
|
||||
fwpath=/lib/firmware
|
||||
|
||||
for fw; do
|
||||
# _d_firmware is assigned in mkinitcpio
|
||||
# shellcheck disable=SC2154
|
||||
if [[ -f $fwpath/$fw.xz ]]; then
|
||||
add_file "$fwpath/$fw.xz" "$fwpath/$fw.xz"
|
||||
elif [[ -f $fwpath/$fw ]]; then
|
||||
add_file "$fwpath/$fw" "$fwpath/$fw"
|
||||
fi
|
||||
done
|
||||
return 0
|
||||
}
|
||||
|
||||
add_module() {
|
||||
# Add a kernel module to the initcpio image. Dependencies will be
|
||||
# discovered and added.
|
||||
# $1: module name
|
||||
|
||||
local target='' module='' softdeps=() deps=() field='' value='' firmware=()
|
||||
local ign_errors=0 found=0
|
||||
|
||||
[[ "$KERNELVERSION" == 'none' ]] && return 0
|
||||
|
||||
if [[ "$1" == *\? ]]; then
|
||||
ign_errors=1
|
||||
set -- "${1%?}"
|
||||
fi
|
||||
|
||||
target="${1%.ko*}" target="${target//-/_}"
|
||||
|
||||
# skip expensive stuff if this module has already been added
|
||||
(( _addedmodules["$target"] == 1 )) && return
|
||||
|
||||
while IFS=':= ' read -r -d '' field value; do
|
||||
case "$field" in
|
||||
filename)
|
||||
# Only add modules with filenames that look like paths (e.g.
|
||||
# it might be reported as "(builtin)"). We'll defer actually
|
||||
# checking whether or not the file exists -- any errors can be
|
||||
# handled during module install time.
|
||||
if [[ "$value" == /* ]]; then
|
||||
found=1
|
||||
module="${value##*/}" module="${module%.ko*}"
|
||||
quiet "adding module: %s (%s)" "$module" "$value"
|
||||
_modpaths["$value"]=1
|
||||
_addedmodules["${module//-/_}"]=1
|
||||
fi
|
||||
;;
|
||||
depends)
|
||||
IFS=',' read -r -a deps <<< "$value"
|
||||
map add_module "${deps[@]}"
|
||||
;;
|
||||
firmware)
|
||||
firmware+=("$value")
|
||||
;;
|
||||
softdep)
|
||||
read -ra softdeps <<<"$value"
|
||||
for module in "${softdeps[@]}"; do
|
||||
[[ $module == *: ]] && continue
|
||||
add_module "$module?"
|
||||
done
|
||||
;;
|
||||
esac
|
||||
done < <(modinfo -b "$_optmoduleroot" -k "$KERNELVERSION" -0 "$target" 2>/dev/null)
|
||||
|
||||
if (( !found )); then
|
||||
(( ign_errors || _addedmodules["$target"] )) && return 0
|
||||
error "module not found: '%s'" "$target"
|
||||
return 1
|
||||
fi
|
||||
|
||||
if (( ${#firmware[*]} )); then
|
||||
add_firmware "${firmware[@]}"
|
||||
fi
|
||||
}
|
||||
|
||||
add_full_dir() {
|
||||
# Add a directory and all its contents, recursively, to the initcpio image.
|
||||
# No parsing is performed and the contents of the directory is added as is.
|
||||
# $1: path to directory
|
||||
if [[ -n $1 && -d $1 ]]; then
|
||||
command tar -C / -cpf - ."$1" | tar -C "${BUILDROOT}" -xspf -
|
||||
fi
|
||||
}
|
||||
|
||||
add_dir() {
|
||||
# add a directory (with parents) to $BUILDROOT
|
||||
# $1: pathname on initcpio
|
||||
# $2: mode (optional)
|
||||
|
||||
if [[ -z "$1" || "$1" != /?* ]]; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
local path="$1" mode="${2:-755}"
|
||||
|
||||
# shellcheck disable=SC2153
|
||||
if [[ -d "${BUILDROOT}${1}" ]]; then
|
||||
# ignore dir already exists
|
||||
return 0
|
||||
fi
|
||||
|
||||
command install -dm"${mode}" "${BUILDROOT}${path}"
|
||||
}
|
||||
|
||||
add_symlink() {
|
||||
# Add a symlink to the initcpio image. There is no checking done
|
||||
# to ensure that the target of the symlink exists.
|
||||
# $1: pathname of symlink on image
|
||||
# $2: absolute path to target of symlink (optional, can be read from $1)
|
||||
|
||||
local name="$1" target="${2:-$1}" linkobject
|
||||
|
||||
(( $# == 1 || $# == 2 )) || return 1
|
||||
|
||||
# find out the link target
|
||||
if [[ "$name" == "$target" ]]; then
|
||||
linkobject="$(find "$target" -prune -printf '%l')"
|
||||
# use relative path if the target is a file in the same directory as the link
|
||||
# anything more would lead to the insanity of parsing each element in its path
|
||||
if [[ "$linkobject" != *'/'* && ! -L "${name%/*}/${linkobject}" ]]; then
|
||||
target="$linkobject"
|
||||
else
|
||||
target="$(realpath -eq -- "$target")"
|
||||
fi
|
||||
elif [[ -L "$target" ]]; then
|
||||
target="$(realpath -eq -- "$target")"
|
||||
fi
|
||||
if [[ -z "$target" ]]; then
|
||||
error "invalid symlink: '%s'" "$name"
|
||||
return 1
|
||||
fi
|
||||
|
||||
add_dir "${name%/*}"
|
||||
ln -sfn "$target" "${BUILDROOT}${name}"
|
||||
}
|
||||
|
||||
add_file() {
|
||||
# Add a plain file to the initcpio image. No parsing is performed and only
|
||||
# the singular file is added.
|
||||
# $1: path to file
|
||||
# $2: destination on initcpio (optional, defaults to same as source)
|
||||
# $3: mode
|
||||
|
||||
(( $# )) || return 1
|
||||
|
||||
# determine source and destination
|
||||
local src="$1" dest="${2:-$1}" mode="$3" srcrealpath
|
||||
|
||||
if [[ ! -f "$src" ]]; then
|
||||
error "file not found: '%s'" "$src"
|
||||
return 1
|
||||
fi
|
||||
if [[ ! -e "${BUILDROOT}${dest}" ]]; then
|
||||
if [[ "$src" != "$dest" ]]; then
|
||||
command tar --transform="s|"$src"|"$dest"|" -C / -cpf - ."$src" | tar -C "${BUILDROOT}" -xpf -
|
||||
else
|
||||
command tar -C / -cpf - ."$src" | tar -C "${BUILDROOT}" -xpf -
|
||||
fi
|
||||
if [[ -L "$src" ]]; then
|
||||
srcrealpath="$(realpath -- "$src")"
|
||||
add_file "$srcrealpath" "$srcrealpath" "$mode"
|
||||
else
|
||||
if [[ -n $mode ]]; then
|
||||
command chmod "$mode" ${BUILDROOT}${dest}
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
add_binary() {
|
||||
# Add a binary file to the initcpio image. library dependencies will
|
||||
# be discovered and added.
|
||||
# $1: path to binary
|
||||
# $2: destination on initcpio (optional, defaults to same as source)
|
||||
|
||||
local line='' regex='' binary='' dest='' mode='' sodep='' resolved='' shebang='' interpreter=''
|
||||
|
||||
if [[ "${1:0:1}" != '/' ]]; then
|
||||
binary="$(type -P "$1")"
|
||||
else
|
||||
binary="$1"
|
||||
fi
|
||||
|
||||
if [[ ! -f "$binary" ]]; then
|
||||
error "file not found: '%s'" "$1"
|
||||
return 1
|
||||
fi
|
||||
|
||||
dest="${2:-$binary}"
|
||||
|
||||
add_file "$binary" "$dest"
|
||||
|
||||
# non-binaries
|
||||
if ! lddout="$(ldd "$binary" 2>/dev/null)"; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
# resolve sodeps
|
||||
regex='^(|.+ )(/.+) \(0x[a-fA-F0-9]+\)'
|
||||
while read -r line; do
|
||||
if [[ "$line" =~ $regex ]]; then
|
||||
sodep="${BASH_REMATCH[2]}"
|
||||
elif [[ "$line" = *'not found' ]]; then
|
||||
error "binary dependency '%s' not found for '%s'" "${line%% *}" "$1"
|
||||
(( ++_builderrors ))
|
||||
continue
|
||||
fi
|
||||
|
||||
if [[ -f "$sodep" && ! -e "${BUILDROOT}${sodep}" ]]; then
|
||||
add_file "$sodep" "$sodep"
|
||||
fi
|
||||
done <<< "$lddout"
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
install_modules() {
|
||||
local m
|
||||
local -a xz_comp gz_comp zst_comp
|
||||
|
||||
[[ "$KERNELVERSION" == 'none' ]] && return 0
|
||||
|
||||
if (( $# == 0 )); then
|
||||
warning "No modules were added to the image. This is probably not what you want."
|
||||
return 0
|
||||
fi
|
||||
|
||||
for m in "$@"; do
|
||||
add_file "$m" "$m"
|
||||
done
|
||||
|
||||
msg "Generating module dependencies"
|
||||
map add_file "$_d_kmoduledir"/modules.{builtin,builtin.modinfo,order}
|
||||
depmod -b "$BUILDROOT" "$KERNELVERSION"
|
||||
|
||||
# remove all non-binary module.* files (except devname for on-demand module loading)
|
||||
rm "${BUILDROOT}${_d_kmoduledir}"/modules.!(*.bin|devname|softdep)
|
||||
}
|
||||
|
||||
help ()
|
||||
{
|
||||
cat <<HELPEOF
|
||||
This hook adds speed functions for an archboot image creation.
|
||||
HELPEOF
|
||||
}
|
||||
# vim: set ft=sh ts=4 sw=4 et:
|
|
@ -10,7 +10,6 @@ build ()
|
|||
add_full_dir "/usr/lib/archboot/update-installer"
|
||||
add_file "/usr/bin/archboot-update-installer.sh" "/usr/bin/update-installer"
|
||||
add_file "/usr/share/archboot/gpg/tpowa.gpg"
|
||||
add_file "/usr/share/archboot/patches/functions"
|
||||
# use /etc/profile to launch login.sh
|
||||
echo ". /usr/lib/archboot/login.sh" >> $BUILDROOT/root/.bashrc
|
||||
}
|
||||
|
|
|
@ -1,225 +0,0 @@
|
|||
--- functions 2023-02-17 10:48:03.804097093 +0100
|
||||
+++ functions 2023-02-17 21:32:45.737767266 +0100
|
||||
@@ -447,26 +447,19 @@
|
||||
# add a firmware file to the image.
|
||||
# $1: firmware path fragment
|
||||
|
||||
- local fw fwpath r=1
|
||||
+ local fw fwpath
|
||||
+ fwpath=/lib/firmware
|
||||
|
||||
for fw; do
|
||||
# _d_firmware is assigned in mkinitcpio
|
||||
# shellcheck disable=SC2154
|
||||
- for fwpath in "${_d_firmware[@]}"; do
|
||||
- if [[ -f $fwpath/$fw.xz ]]; then
|
||||
- add_file "$fwpath/$fw.xz" "$fwpath/$fw.xz" 644 && r=0
|
||||
- break
|
||||
- elif [[ -f "$fwpath/$fw.zst" ]]; then
|
||||
- add_file "$fwpath/$fw.zst" "$fwpath/$fw.zst" 644 && r=0
|
||||
- break
|
||||
- elif [[ -f $fwpath/$fw ]]; then
|
||||
- add_file "$fwpath/$fw" "$fwpath/$fw" 644 && r=0
|
||||
- break
|
||||
- fi
|
||||
- done
|
||||
+ if [[ -f $fwpath/$fw.xz ]]; then
|
||||
+ add_file "$fwpath/$fw.xz" "$fwpath/$fw.xz"
|
||||
+ elif [[ -f $fwpath/$fw ]]; then
|
||||
+ add_file "$fwpath/$fw" "$fwpath/$fw"
|
||||
+ fi
|
||||
done
|
||||
-
|
||||
- return "$r"
|
||||
+ return 0
|
||||
}
|
||||
|
||||
add_module() {
|
||||
@@ -528,60 +521,16 @@
|
||||
fi
|
||||
|
||||
if (( ${#firmware[*]} )); then
|
||||
- add_firmware "${firmware[@]}" ||
|
||||
- warning "Possibly missing firmware for module: '%s'" "$target"
|
||||
+ add_firmware "${firmware[@]}"
|
||||
fi
|
||||
-
|
||||
- # handle module quirks
|
||||
- case "$target" in
|
||||
- fat)
|
||||
- add_module "nls_ascii?" # from CONFIG_FAT_DEFAULT_IOCHARSET
|
||||
- add_module "nls_cp437?" # from CONFIG_FAT_DEFAULT_CODEPAGE
|
||||
- ;;
|
||||
- ocfs2)
|
||||
- add_module "configfs?"
|
||||
- ;;
|
||||
- btrfs)
|
||||
- add_module "libcrc32c?"
|
||||
- ;;
|
||||
- f2fs)
|
||||
- add_module "crypto-crc32?"
|
||||
- ;;
|
||||
- ext4)
|
||||
- add_module "crypto-crc32c?"
|
||||
- ;;
|
||||
- esac
|
||||
}
|
||||
|
||||
add_full_dir() {
|
||||
# Add a directory and all its contents, recursively, to the initcpio image.
|
||||
# No parsing is performed and the contents of the directory is added as is.
|
||||
# $1: path to directory
|
||||
- # $2: glob pattern to filter file additions (optional)
|
||||
- # $3: path prefix that will be stripped off from the image path (optional)
|
||||
-
|
||||
- local f='' filter="${2:-*}" strip_prefix="$3"
|
||||
-
|
||||
- if [[ -n "$1" && -d "$1" ]]; then
|
||||
- add_dir "$1"
|
||||
-
|
||||
- for f in "$1"/*; do
|
||||
- if [[ -L "$f" ]]; then
|
||||
- # Explicit glob matching
|
||||
- # shellcheck disable=SC2053
|
||||
- if [[ "$f" == $filter ]]; then
|
||||
- add_symlink "${f#"${strip_prefix}"}" "$(readlink "$f")"
|
||||
- fi
|
||||
- elif [[ -d "$f" ]]; then
|
||||
- add_full_dir "$f" "$filter" "$strip_prefix"
|
||||
- elif [[ -f "$f" ]]; then
|
||||
- # Explicit glob matching
|
||||
- # shellcheck disable=SC2053
|
||||
- if [[ "$f" == $filter ]]; then
|
||||
- add_file "$f" "${f#"${strip_prefix}"}"
|
||||
- fi
|
||||
- fi
|
||||
- done
|
||||
+ if [[ -n $1 && -d $1 ]]; then
|
||||
+ command tar -C / -cpf - ."$1" | tar -C "${BUILDROOT}" -xspf -
|
||||
fi
|
||||
}
|
||||
|
||||
@@ -602,7 +551,6 @@
|
||||
return 0
|
||||
fi
|
||||
|
||||
- quiet "adding dir: %s" "$path"
|
||||
command install -dm"${mode}" "${BUILDROOT}${path}"
|
||||
}
|
||||
|
||||
@@ -635,12 +583,6 @@
|
||||
fi
|
||||
|
||||
add_dir "${name%/*}"
|
||||
-
|
||||
- if [[ -L "${BUILDROOT}${1}" ]]; then
|
||||
- quiet "overwriting symlink %s -> %s" "$name" "$target"
|
||||
- else
|
||||
- quiet "adding symlink: %s -> %s" "$name" "$target"
|
||||
- fi
|
||||
ln -sfn "$target" "${BUILDROOT}${name}"
|
||||
}
|
||||
|
||||
@@ -660,32 +602,21 @@
|
||||
error "file not found: '%s'" "$src"
|
||||
return 1
|
||||
fi
|
||||
-
|
||||
- # check if $src is a symlink
|
||||
- if [[ -L "$src" ]]; then
|
||||
- srcrealpath="$(realpath -- "$src")"
|
||||
- if [[ "$srcrealpath" != "$dest" ]]; then
|
||||
- # add the target file
|
||||
- add_file "$srcrealpath" "$srcrealpath" "$mode"
|
||||
- # create the symlink
|
||||
- add_symlink "$dest" "$src"
|
||||
- return
|
||||
+ if [[ ! -e "${BUILDROOT}${dest}" ]]; then
|
||||
+ if [[ "$src" != "$dest" ]]; then
|
||||
+ command tar --transform="s|"$src"|"$dest"|" -C / -cpf - ."$src" | tar -C "${BUILDROOT}" -xpf -
|
||||
+ else
|
||||
+ command tar -C / -cpf - ."$src" | tar -C "${BUILDROOT}" -xpf -
|
||||
fi
|
||||
- fi
|
||||
-
|
||||
- # unlike install, cp does not create directories leading to the destination
|
||||
- [[ -z "$mode" ]] && add_dir "${dest%/*}"
|
||||
-
|
||||
- if [[ -e "${BUILDROOT}${dest}" ]]; then
|
||||
- quiet 'overwriting file: %s' "$dest"
|
||||
- else
|
||||
- quiet 'adding file: %s' "$dest"
|
||||
- fi
|
||||
- if [[ -z "$mode" ]]; then
|
||||
- command cp --remove-destination --preserve=mode,ownership "$src" "${BUILDROOT}${dest}"
|
||||
- else
|
||||
- command install -Dm"$mode" "$src" "${BUILDROOT}${dest}"
|
||||
- fi
|
||||
+ if [[ -L "$src" ]]; then
|
||||
+ srcrealpath="$(realpath -- "$src")"
|
||||
+ add_file "$srcrealpath" "$srcrealpath" "$mode"
|
||||
+ else
|
||||
+ if [[ -n $mode ]]; then
|
||||
+ command chmod "$mode" ${BUILDROOT}${dest}
|
||||
+ fi
|
||||
+ fi
|
||||
+ fi
|
||||
}
|
||||
|
||||
add_runscript() {
|
||||
@@ -750,26 +681,6 @@
|
||||
|
||||
# non-binaries
|
||||
if ! lddout="$(ldd "$binary" 2>/dev/null)"; then
|
||||
- # detect if the file has a shebang
|
||||
- if IFS='' LC_ALL=C read -rn2 -d '' shebang < "$binary" && [[ "$shebang" == '#!' ]]; then
|
||||
- read -r shebang < "$binary"
|
||||
- interpreter="${shebang##\#\!*([[:space:]])}"
|
||||
- # strip /usr/bin/env and warn if it is missing
|
||||
- if [[ "$interpreter" == '/usr/bin/env'* ]]; then
|
||||
- [[ -e "${BUILDROOT}/usr/bin/env" ]] || warning "Possibly missing '/usr/bin/env' for script: %s" "$binary"
|
||||
- interpreter="${interpreter##'/usr/bin/env'+([[:space:]])}"
|
||||
- fi
|
||||
- # strip parameters
|
||||
- interpreter="${interpreter%%[[:space:]]*}"
|
||||
- # check if the interpreter exists in BUILDROOT
|
||||
- if [[ "$interpreter" != '/'* ]] && PATH="${BUILDROOT}/usr/local/sbin:${BUILDROOT}/usr/local/bin:${BUILDROOT}/usr/bin" type -P "$interpreter" &>/dev/null; then
|
||||
- :
|
||||
- elif [[ -e "${BUILDROOT}/${interpreter}" ]]; then
|
||||
- :
|
||||
- else
|
||||
- warning "Possibly missing '%s' for script: %s" "$interpreter" "$binary"
|
||||
- fi
|
||||
- fi
|
||||
return 0
|
||||
fi
|
||||
|
||||
@@ -1008,27 +919,9 @@
|
||||
fi
|
||||
|
||||
for m in "$@"; do
|
||||
- add_file "$m" "$m" 644
|
||||
- # unzip modules prior to recompression
|
||||
- if [[ "$MODULES_DECOMPRESS" == 'yes' ]]; then
|
||||
- case "$m" in
|
||||
- *.xz)
|
||||
- xz_comp+=("$BUILDROOT/$m")
|
||||
- ;;
|
||||
- *.gz)
|
||||
- gz_comp+=("$BUILDROOT/$m")
|
||||
- ;;
|
||||
- *.zst)
|
||||
- zst_comp+=("$BUILDROOT/$m")
|
||||
- ;;
|
||||
- esac
|
||||
- fi
|
||||
+ add_file "$m" "$m"
|
||||
done
|
||||
|
||||
- (( ${#xz_comp[*]} )) && xz -d "${xz_comp[@]}"
|
||||
- (( ${#gz_comp[*]} )) && gzip -d "${gz_comp[@]}"
|
||||
- (( ${#zst_comp[*]} )) && zstd -d --rm -q "${zst_comp[@]}"
|
||||
-
|
||||
msg "Generating module dependencies"
|
||||
map add_file "$_d_kmoduledir"/modules.{builtin,builtin.modinfo,order}
|
||||
depmod -b "$BUILDROOT" "$KERNELVERSION"
|
|
@ -1,933 +0,0 @@
|
|||
#!/usr/bin/env bash
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
|
||||
parseopts() {
|
||||
local opt='' optarg='' i='' shortopts="$1"
|
||||
local -a longopts=() unused_argv=()
|
||||
|
||||
shift
|
||||
while [[ -n "$1" && "$1" != '--' ]]; do
|
||||
longopts+=("$1")
|
||||
shift
|
||||
done
|
||||
shift
|
||||
|
||||
longoptmatch() {
|
||||
local o longmatch=()
|
||||
for o in "${longopts[@]}"; do
|
||||
if [[ "${o%:}" == "$1" ]]; then
|
||||
longmatch=("$o")
|
||||
break
|
||||
fi
|
||||
[[ "${o%:}" == "$1"* ]] && longmatch+=("$o")
|
||||
done
|
||||
|
||||
case "${#longmatch[*]}" in
|
||||
1)
|
||||
# success, override with opt and return arg req (0 == none, 1 == required)
|
||||
opt="${longmatch%:}"
|
||||
if [[ "${longmatch[*]}" == *: ]]; then
|
||||
return 1
|
||||
else
|
||||
return 0
|
||||
fi ;;
|
||||
0)
|
||||
# fail, no match found
|
||||
return 255 ;;
|
||||
*)
|
||||
# fail, ambiguous match
|
||||
printf "%s: option '%s' is ambiguous; possibilities:%s\n" "${0##*/}" \
|
||||
"--$1" "$(printf " '%s'" "${longmatch[@]%:}")"
|
||||
return 254 ;;
|
||||
esac
|
||||
}
|
||||
|
||||
while (( $# )); do
|
||||
case "$1" in
|
||||
--) # explicit end of options
|
||||
shift
|
||||
break
|
||||
;;
|
||||
-[!-]*) # short option
|
||||
for (( i = 1; i < ${#1}; i++ )); do
|
||||
opt=${1:i:1}
|
||||
|
||||
# option doesn't exist
|
||||
if [[ $shortopts != *$opt* ]]; then
|
||||
printf "%s: invalid option -- '%s'\n" "${0##*/}" "$opt"
|
||||
OPTRET=(--)
|
||||
return 1
|
||||
fi
|
||||
|
||||
OPTRET+=("-$opt")
|
||||
# option requires optarg
|
||||
if [[ "$shortopts" == *"${opt}:"* ]]; then
|
||||
# if we're not at the end of the option chunk, the rest is the optarg
|
||||
if (( i < ${#1} - 1 )); then
|
||||
OPTRET+=("${1:i+1}")
|
||||
break
|
||||
# if we're at the end, grab the the next positional, if it exists
|
||||
elif (( i == ${#1} - 1 )) && [[ -n "$2" ]]; then
|
||||
OPTRET+=("$2")
|
||||
shift
|
||||
break
|
||||
# parse failure
|
||||
else
|
||||
printf "%s: option '%s' requires an argument\n" "${0##*/}" "-$opt"
|
||||
OPTRET=(--)
|
||||
return 1
|
||||
fi
|
||||
fi
|
||||
done
|
||||
;;
|
||||
--?*=*|--?*) # long option
|
||||
IFS='=' read -r opt optarg <<< "${1#--}"
|
||||
longoptmatch "$opt"
|
||||
case $? in
|
||||
0)
|
||||
if [[ -n "$optarg" ]]; then
|
||||
printf "%s: option '--%s' doesn't allow an argument\n" "${0##*/}" "$opt"
|
||||
OPTRET=(--)
|
||||
return 1
|
||||
else
|
||||
OPTRET+=("--$opt")
|
||||
fi
|
||||
;;
|
||||
1)
|
||||
# --longopt=optarg
|
||||
if [[ -n "$optarg" ]]; then
|
||||
OPTRET+=("--$opt" "$optarg")
|
||||
# --longopt optarg
|
||||
elif [[ -n "$2" ]]; then
|
||||
OPTRET+=("--$opt" "$2" )
|
||||
shift
|
||||
else
|
||||
printf "%s: option '--%s' requires an argument\n" "${0##*/}" "$opt"
|
||||
OPTRET=(--)
|
||||
return 1
|
||||
fi
|
||||
;;
|
||||
254)
|
||||
# ambiguous option -- error was reported for us by longoptmatch()
|
||||
OPTRET=(--)
|
||||
return 1
|
||||
;;
|
||||
255)
|
||||
# parse failure
|
||||
printf "%s: unrecognized option '%s'\n" "${0##*/}" "--$opt"
|
||||
OPTRET=(--)
|
||||
return 1
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
*) # non-option arg encountered, add it as a parameter
|
||||
unused_argv+=("$1")
|
||||
;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
|
||||
# add end-of-opt terminator and any leftover positional parameters
|
||||
OPTRET+=('--' "${unused_argv[@]}" "$@")
|
||||
unset longoptmatch
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
kver_x86() {
|
||||
local kver
|
||||
local -i offset
|
||||
# scrape the version out of the kernel image. locate the offset
|
||||
# to the version string by reading 2 bytes out of image at at
|
||||
# address 0x20E. this leads us to a string of, at most, 128 bytes.
|
||||
# read the first word from this string as the kernel version.
|
||||
offset="$(od -An -j0x20E -dN2 "$1")" || return
|
||||
|
||||
read -r kver _ < \
|
||||
<(dd if="$1" bs=1 count=127 skip=$((offset + 0x200)) 2>/dev/null)
|
||||
|
||||
printf '%s' "$kver"
|
||||
}
|
||||
|
||||
detect_compression() {
|
||||
local bytes
|
||||
|
||||
bytes="$(od -An -t x1 -N6 "$1" | tr -dc '[:alnum:]')"
|
||||
case "$bytes" in
|
||||
'fd377a585a00')
|
||||
echo 'xz'
|
||||
return
|
||||
;;
|
||||
esac
|
||||
|
||||
bytes="$(od -An -t x1 -N4 "$1" | tr -dc '[:alnum:]')"
|
||||
if [[ "$bytes" == '894c5a4f' ]]; then
|
||||
echo 'lzop'
|
||||
return
|
||||
fi
|
||||
|
||||
bytes="$(od -An -t x2 -N2 "$1" | tr -dc '[:alnum:]')"
|
||||
if [[ "$bytes" == '8b1f' ]]; then
|
||||
echo 'gzip'
|
||||
return
|
||||
fi
|
||||
|
||||
bytes="$(od -An -t x4 -N4 "$1" | tr -dc '[:alnum:]')"
|
||||
case "$bytes" in
|
||||
'184d2204')
|
||||
error 'Newer lz4 stream format detected! This may not boot!'
|
||||
echo 'lz4'
|
||||
return
|
||||
;;
|
||||
'184c2102')
|
||||
echo 'lz4 -l'
|
||||
return
|
||||
;;
|
||||
'fd2fb528')
|
||||
echo 'zstd'
|
||||
return
|
||||
;;
|
||||
esac
|
||||
|
||||
bytes="$(od -An -c -N3 "$1" | tr -dc '[:alnum:]')"
|
||||
if [[ "$bytes" == 'BZh' ]]; then
|
||||
echo 'bzip2'
|
||||
return
|
||||
fi
|
||||
|
||||
# lzma detection sucks and there's really no good way to
|
||||
# do it without reading large portions of the stream. this
|
||||
# check is good enough for GNU tar, apparently, so it's good
|
||||
# enough for me.
|
||||
bytes="$(od -An -t x1 -N3 "$1" | tr -dc '[:alnum:]')"
|
||||
if [[ "$bytes" == '5d0000' ]]; then
|
||||
echo 'lzma'
|
||||
return
|
||||
fi
|
||||
|
||||
# out of ideas, assuming uncompressed
|
||||
}
|
||||
|
||||
kver_generic() {
|
||||
# For unknown architectures, we can try to grep the uncompressed or gzipped
|
||||
# image for the boot banner.
|
||||
# This should work at least for ARM when run on /boot/Image, or RISC-V on
|
||||
# gzipped /boot/vmlinuz-linuz. On other architectures it may be worth trying
|
||||
# rather than bailing, and inform the user if none was found.
|
||||
|
||||
# Loosely grep for `linux_banner`:
|
||||
# https://elixir.bootlin.com/linux/v5.7.2/source/init/version.c#L46
|
||||
local kver='' reader='cat'
|
||||
|
||||
[[ "$(detect_compression "$1")" == 'gzip' ]] && reader='zcat'
|
||||
|
||||
read -r _ _ kver _ < <($reader "$1" | grep -m1 -aoE 'Linux version .(\.[-[:alnum:]+]+)+')
|
||||
|
||||
printf '%s' "$kver"
|
||||
}
|
||||
|
||||
kver() {
|
||||
# this is intentionally very loose. only ensure that we're
|
||||
# dealing with some sort of string that starts with something
|
||||
# resembling dotted decimal notation. remember that there's no
|
||||
# requirement for CONFIG_LOCALVERSION to be set.
|
||||
local kver re='^[[:digit:]]+(\.[[:digit:]]+)+'
|
||||
|
||||
local arch
|
||||
arch="$(uname -m)"
|
||||
if [[ $arch == @(i?86|x86_64) ]]; then
|
||||
kver="$(kver_x86 "$1")"
|
||||
else
|
||||
kver="$(kver_generic "$1")"
|
||||
fi
|
||||
|
||||
[[ "$kver" =~ $re ]] || return 1
|
||||
|
||||
printf '%s' "$kver"
|
||||
}
|
||||
|
||||
plain() {
|
||||
local mesg="$1"; shift
|
||||
# shellcheck disable=SC2059
|
||||
printf " $_color_bold$mesg$_color_none\n" "$@" >&1
|
||||
}
|
||||
|
||||
quiet() {
|
||||
# _optquiet is assigned in mkinitcpio
|
||||
# shellcheck disable=SC2154
|
||||
(( _optquiet )) || plain "$@"
|
||||
}
|
||||
|
||||
msg() {
|
||||
local mesg="$1"; shift
|
||||
# shellcheck disable=SC2059
|
||||
printf "$_color_green==>$_color_none $_color_bold$mesg$_color_none\n" "$@" >&1
|
||||
}
|
||||
|
||||
msg2() {
|
||||
local mesg="$1"; shift
|
||||
# shellcheck disable=SC2059
|
||||
printf " $_color_blue->$_color_none $_color_bold$mesg$_color_none\n" "$@" >&1
|
||||
}
|
||||
|
||||
warning() {
|
||||
local mesg="$1"; shift
|
||||
# shellcheck disable=SC2059
|
||||
printf "$_color_yellow==> WARNING:$_color_none $_color_bold$mesg$_color_none\n" "$@" >&2
|
||||
}
|
||||
|
||||
error() {
|
||||
local mesg="$1"; shift
|
||||
# shellcheck disable=SC2059
|
||||
printf "$_color_red==> ERROR:$_color_none $_color_bold$mesg$_color_none\n" "$@" >&2
|
||||
return 1
|
||||
}
|
||||
|
||||
die() {
|
||||
error "$@"
|
||||
cleanup 1
|
||||
}
|
||||
|
||||
map() {
|
||||
local r=0
|
||||
for _ in "${@:2}"; do
|
||||
"$1" "$_" || (( $# > 255 ? r=1 : ++r ))
|
||||
done
|
||||
return "$r"
|
||||
}
|
||||
|
||||
arrayize_config() {
|
||||
set -f
|
||||
[[ ${MODULES@a} != *a* ]] && IFS=' ' read -r -a MODULES <<< "$MODULES"
|
||||
[[ ${BINARIES@a} != *a* ]] && IFS=' ' read -r -a BINARIES <<< "$BINARIES"
|
||||
[[ ${FILES@a} != *a* ]] && IFS=' ' read -r -a FILES <<< "$FILES"
|
||||
[[ ${HOOKS@a} != *a* ]] && IFS=' ' read -r -a HOOKS <<< "$HOOKS"
|
||||
[[ ${COMPRESSION_OPTIONS@a} != *a* ]] && IFS=' ' read -r -a COMPRESSION_OPTIONS <<< "$COMPRESSION_OPTIONS"
|
||||
set +f
|
||||
}
|
||||
|
||||
in_array() {
|
||||
# Search for an element in an array.
|
||||
# $1: needle
|
||||
# ${@:2}: haystack
|
||||
|
||||
local item='' needle="$1"; shift
|
||||
|
||||
for item in "$@"; do
|
||||
[[ "$item" == "$needle" ]] && return 0 # Found
|
||||
done
|
||||
return 1 # Not Found
|
||||
}
|
||||
|
||||
index_of() {
|
||||
# get the array index of an item. sets the global var _idx with
|
||||
# index and returns 0 if found, otherwise returns 1.
|
||||
local item="$1"; shift
|
||||
|
||||
for (( _idx=1; _idx <= $#; _idx++ )); do
|
||||
if [[ "$item" == "${!_idx}" ]]; then
|
||||
(( --_idx ))
|
||||
return 0
|
||||
fi
|
||||
done
|
||||
|
||||
# not found
|
||||
unset _idx
|
||||
return 1
|
||||
}
|
||||
|
||||
funcgrep() {
|
||||
awk -v funcmatch="$1" '
|
||||
/^[[:space:]]*[[:alnum:]_]+[[:space:]]*\([[:space:]]*\)/ {
|
||||
match($1, funcmatch)
|
||||
print substr($1, RSTART, RLENGTH)
|
||||
}' "$2"
|
||||
}
|
||||
|
||||
list_hookpoints() {
|
||||
local funcs script
|
||||
|
||||
# _d_hooks is assigned in mkinitcpio
|
||||
# shellcheck disable=SC2154
|
||||
script="$(PATH="$_d_hooks" type -P "$1")" || return 0
|
||||
|
||||
mapfile -t funcs < <(funcgrep '^run_[[:alnum:]_]+' "$script")
|
||||
|
||||
echo
|
||||
msg "This hook has runtime scripts:"
|
||||
in_array run_earlyhook "${funcs[@]}" && msg2 "early hook"
|
||||
in_array run_hook "${funcs[@]}" && msg2 "pre-mount hook"
|
||||
in_array run_latehook "${funcs[@]}" && msg2 "post-mount hook"
|
||||
in_array run_cleanuphook "${funcs[@]}" && msg2 "cleanup hook"
|
||||
}
|
||||
|
||||
modprobe() {
|
||||
# _optmoduleroot is assigned in mkinitcpio
|
||||
# shellcheck disable=SC2154
|
||||
command modprobe -d "$_optmoduleroot" -S "$KERNELVERSION" "$@"
|
||||
}
|
||||
|
||||
auto_modules() {
|
||||
# Perform auto detection of modules via sysfs.
|
||||
|
||||
local mods=()
|
||||
|
||||
mapfile -t mods < <(find /sys/devices -name uevent \
|
||||
-exec sort -u {} + | awk -F= '$1 == "MODALIAS" && !_[$0]++')
|
||||
mapfile -t mods < <(modprobe -S "$1" -qaR "${mods[@]#MODALIAS=}")
|
||||
|
||||
(( ${#mods[*]} )) && printf "%s\n" "${mods[@]//-/_}"
|
||||
}
|
||||
|
||||
all_modules() {
|
||||
# Add modules to the initcpio, filtered by grep.
|
||||
# $@: filter arguments to grep
|
||||
# -f FILTER: ERE to filter found modules
|
||||
|
||||
local -i count=0
|
||||
local mod='' OPTIND='' OPTARG='' modfilter=()
|
||||
|
||||
while getopts ':f:' flag; do
|
||||
[[ "$flag" = "f" ]] && modfilter+=("$OPTARG")
|
||||
done
|
||||
shift $(( OPTIND - 1 ))
|
||||
|
||||
# _d_kmoduledir is assigned in mkinitcpio
|
||||
# shellcheck disable=SC2154
|
||||
while read -r -d '' mod; do
|
||||
(( ++count ))
|
||||
|
||||
for f in "${modfilter[@]}"; do
|
||||
[[ "$mod" =~ $f ]] && continue 2
|
||||
done
|
||||
|
||||
mod="${mod##*/}"
|
||||
mod="${mod%.ko*}"
|
||||
printf '%s\n' "${mod//-/_}"
|
||||
done < <(find "$_d_kmoduledir" -name '*.ko*' -print0 2>/dev/null | grep -EZz "$@")
|
||||
|
||||
(( count ))
|
||||
}
|
||||
|
||||
add_all_modules() {
|
||||
# Add modules to the initcpio.
|
||||
# $@: arguments to all_modules
|
||||
|
||||
local mod
|
||||
local -a mods
|
||||
|
||||
mapfile -t mods < <(all_modules "$@")
|
||||
map add_module "${mods[@]}"
|
||||
|
||||
return $(( !${#mods[*]} ))
|
||||
}
|
||||
|
||||
add_checked_modules() {
|
||||
# Add modules to the initcpio, filtered by the list of autodetected
|
||||
# modules.
|
||||
# $@: arguments to all_modules
|
||||
|
||||
local mod
|
||||
local -a mods
|
||||
|
||||
# _autodetect_cache is declared in mkinitcpio and assigned in install/autodetect
|
||||
# shellcheck disable=SC2154
|
||||
if (( ${#_autodetect_cache[*]} )); then
|
||||
mapfile -t mods < <(all_modules "$@" | grep -xFf <(printf '%s\n' "${!_autodetect_cache[@]}"))
|
||||
else
|
||||
mapfile -t mods < <(all_modules "$@")
|
||||
fi
|
||||
|
||||
map add_module "${mods[@]}"
|
||||
|
||||
return $(( !${#mods[*]} ))
|
||||
}
|
||||
|
||||
add_firmware() {
|
||||
# add a firmware file to the image.
|
||||
# $1: firmware path fragment
|
||||
|
||||
local fw fwpath
|
||||
fwpath=/lib/firmware
|
||||
|
||||
for fw; do
|
||||
# _d_firmware is assigned in mkinitcpio
|
||||
# shellcheck disable=SC2154
|
||||
if [[ -f $fwpath/$fw.xz ]]; then
|
||||
add_file "$fwpath/$fw.xz" "$fwpath/$fw.xz"
|
||||
elif [[ -f $fwpath/$fw ]]; then
|
||||
add_file "$fwpath/$fw" "$fwpath/$fw"
|
||||
fi
|
||||
done
|
||||
return 0
|
||||
}
|
||||
|
||||
add_module() {
|
||||
# Add a kernel module to the initcpio image. Dependencies will be
|
||||
# discovered and added.
|
||||
# $1: module name
|
||||
|
||||
local target='' module='' softdeps=() deps=() field='' value='' firmware=()
|
||||
local ign_errors=0 found=0
|
||||
|
||||
[[ "$KERNELVERSION" == 'none' ]] && return 0
|
||||
|
||||
if [[ "$1" == *\? ]]; then
|
||||
ign_errors=1
|
||||
set -- "${1%?}"
|
||||
fi
|
||||
|
||||
target="${1%.ko*}" target="${target//-/_}"
|
||||
|
||||
# skip expensive stuff if this module has already been added
|
||||
(( _addedmodules["$target"] == 1 )) && return
|
||||
|
||||
while IFS=':= ' read -r -d '' field value; do
|
||||
case "$field" in
|
||||
filename)
|
||||
# Only add modules with filenames that look like paths (e.g.
|
||||
# it might be reported as "(builtin)"). We'll defer actually
|
||||
# checking whether or not the file exists -- any errors can be
|
||||
# handled during module install time.
|
||||
if [[ "$value" == /* ]]; then
|
||||
found=1
|
||||
module="${value##*/}" module="${module%.ko*}"
|
||||
quiet "adding module: %s (%s)" "$module" "$value"
|
||||
_modpaths["$value"]=1
|
||||
_addedmodules["${module//-/_}"]=1
|
||||
fi
|
||||
;;
|
||||
depends)
|
||||
IFS=',' read -r -a deps <<< "$value"
|
||||
map add_module "${deps[@]}"
|
||||
;;
|
||||
firmware)
|
||||
firmware+=("$value")
|
||||
;;
|
||||
softdep)
|
||||
read -ra softdeps <<<"$value"
|
||||
for module in "${softdeps[@]}"; do
|
||||
[[ $module == *: ]] && continue
|
||||
add_module "$module?"
|
||||
done
|
||||
;;
|
||||
esac
|
||||
done < <(modinfo -b "$_optmoduleroot" -k "$KERNELVERSION" -0 "$target" 2>/dev/null)
|
||||
|
||||
if (( !found )); then
|
||||
(( ign_errors || _addedmodules["$target"] )) && return 0
|
||||
error "module not found: '%s'" "$target"
|
||||
return 1
|
||||
fi
|
||||
|
||||
if (( ${#firmware[*]} )); then
|
||||
add_firmware "${firmware[@]}"
|
||||
fi
|
||||
}
|
||||
|
||||
add_full_dir() {
|
||||
# Add a directory and all its contents, recursively, to the initcpio image.
|
||||
# No parsing is performed and the contents of the directory is added as is.
|
||||
# $1: path to directory
|
||||
if [[ -n $1 && -d $1 ]]; then
|
||||
command tar -C / -cpf - ."$1" | tar -C "${BUILDROOT}" -xspf -
|
||||
fi
|
||||
}
|
||||
|
||||
add_dir() {
|
||||
# add a directory (with parents) to $BUILDROOT
|
||||
# $1: pathname on initcpio
|
||||
# $2: mode (optional)
|
||||
|
||||
if [[ -z "$1" || "$1" != /?* ]]; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
local path="$1" mode="${2:-755}"
|
||||
|
||||
# shellcheck disable=SC2153
|
||||
if [[ -d "${BUILDROOT}${1}" ]]; then
|
||||
# ignore dir already exists
|
||||
return 0
|
||||
fi
|
||||
|
||||
command install -dm"${mode}" "${BUILDROOT}${path}"
|
||||
}
|
||||
|
||||
add_symlink() {
|
||||
# Add a symlink to the initcpio image. There is no checking done
|
||||
# to ensure that the target of the symlink exists.
|
||||
# $1: pathname of symlink on image
|
||||
# $2: absolute path to target of symlink (optional, can be read from $1)
|
||||
|
||||
local name="$1" target="${2:-$1}" linkobject
|
||||
|
||||
(( $# == 1 || $# == 2 )) || return 1
|
||||
|
||||
# find out the link target
|
||||
if [[ "$name" == "$target" ]]; then
|
||||
linkobject="$(find "$target" -prune -printf '%l')"
|
||||
# use relative path if the target is a file in the same directory as the link
|
||||
# anything more would lead to the insanity of parsing each element in its path
|
||||
if [[ "$linkobject" != *'/'* && ! -L "${name%/*}/${linkobject}" ]]; then
|
||||
target="$linkobject"
|
||||
else
|
||||
target="$(realpath -eq -- "$target")"
|
||||
fi
|
||||
elif [[ -L "$target" ]]; then
|
||||
target="$(realpath -eq -- "$target")"
|
||||
fi
|
||||
if [[ -z "$target" ]]; then
|
||||
error "invalid symlink: '%s'" "$name"
|
||||
return 1
|
||||
fi
|
||||
|
||||
add_dir "${name%/*}"
|
||||
ln -sfn "$target" "${BUILDROOT}${name}"
|
||||
}
|
||||
|
||||
add_file() {
|
||||
# Add a plain file to the initcpio image. No parsing is performed and only
|
||||
# the singular file is added.
|
||||
# $1: path to file
|
||||
# $2: destination on initcpio (optional, defaults to same as source)
|
||||
# $3: mode
|
||||
|
||||
(( $# )) || return 1
|
||||
|
||||
# determine source and destination
|
||||
local src="$1" dest="${2:-$1}" mode="$3" srcrealpath
|
||||
|
||||
if [[ ! -f "$src" ]]; then
|
||||
error "file not found: '%s'" "$src"
|
||||
return 1
|
||||
fi
|
||||
if [[ ! -e "${BUILDROOT}${dest}" ]]; then
|
||||
if [[ "$src" != "$dest" ]]; then
|
||||
command tar --transform="s|"$src"|"$dest"|" -C / -cpf - ."$src" | tar -C "${BUILDROOT}" -xpf -
|
||||
else
|
||||
command tar -C / -cpf - ."$src" | tar -C "${BUILDROOT}" -xpf -
|
||||
fi
|
||||
if [[ -L "$src" ]]; then
|
||||
srcrealpath="$(realpath -- "$src")"
|
||||
add_file "$srcrealpath" "$srcrealpath" "$mode"
|
||||
else
|
||||
if [[ -n $mode ]]; then
|
||||
command chmod "$mode" ${BUILDROOT}${dest}
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
add_runscript() {
|
||||
# Adds a runtime script to the initcpio image. The name is derived from the
|
||||
# script which calls it as the basename of the caller.
|
||||
|
||||
local fn script hookname="${BASH_SOURCE[1]##*/}"
|
||||
local -a funcs
|
||||
|
||||
if ! script="$(PATH="$_d_hooks" type -P "$hookname")"; then
|
||||
error "runtime script for '%s' not found" "$hookname"
|
||||
return
|
||||
fi
|
||||
|
||||
if [[ -L "$script" ]]; then
|
||||
script="$(realpath -- "$script")"
|
||||
fi
|
||||
add_file "$script" "/hooks/$hookname" 755
|
||||
|
||||
mapfile -t funcs < <(funcgrep '^run_[[:alnum:]_]+' "$script")
|
||||
|
||||
for fn in "${funcs[@]}"; do
|
||||
case $fn in
|
||||
run_earlyhook)
|
||||
_runhooks['early']+=" $hookname"
|
||||
;;
|
||||
run_hook)
|
||||
_runhooks['hooks']+=" $hookname"
|
||||
;;
|
||||
run_latehook)
|
||||
_runhooks['late']+=" $hookname"
|
||||
;;
|
||||
run_cleanuphook)
|
||||
_runhooks['cleanup']="$hookname ${_runhooks['cleanup']}"
|
||||
;;
|
||||
esac
|
||||
done
|
||||
}
|
||||
|
||||
add_binary() {
|
||||
# Add a binary file to the initcpio image. library dependencies will
|
||||
# be discovered and added.
|
||||
# $1: path to binary
|
||||
# $2: destination on initcpio (optional, defaults to same as source)
|
||||
|
||||
local line='' regex='' binary='' dest='' mode='' sodep='' resolved='' shebang='' interpreter=''
|
||||
|
||||
if [[ "${1:0:1}" != '/' ]]; then
|
||||
binary="$(type -P "$1")"
|
||||
else
|
||||
binary="$1"
|
||||
fi
|
||||
|
||||
if [[ ! -f "$binary" ]]; then
|
||||
error "file not found: '%s'" "$1"
|
||||
return 1
|
||||
fi
|
||||
|
||||
dest="${2:-$binary}"
|
||||
|
||||
add_file "$binary" "$dest"
|
||||
|
||||
# non-binaries
|
||||
if ! lddout="$(ldd "$binary" 2>/dev/null)"; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
# resolve sodeps
|
||||
regex='^(|.+ )(/.+) \(0x[a-fA-F0-9]+\)'
|
||||
while read -r line; do
|
||||
if [[ "$line" =~ $regex ]]; then
|
||||
sodep="${BASH_REMATCH[2]}"
|
||||
elif [[ "$line" = *'not found' ]]; then
|
||||
error "binary dependency '%s' not found for '%s'" "${line%% *}" "$1"
|
||||
(( ++_builderrors ))
|
||||
continue
|
||||
fi
|
||||
|
||||
if [[ -f "$sodep" && ! -e "${BUILDROOT}${sodep}" ]]; then
|
||||
add_file "$sodep" "$sodep"
|
||||
fi
|
||||
done <<< "$lddout"
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
add_udev_rule() {
|
||||
# Add an udev rules file to the initcpio image. Dependencies on binaries
|
||||
# will be discovered and added.
|
||||
# $1: path to rules file (or name of rules file)
|
||||
|
||||
local rules="$1" rule=() key='' value='' binary=''
|
||||
|
||||
if [[ "${rules:0:1}" != '/' ]]; then
|
||||
rules="$(PATH='/usr/lib/udev/rules.d:/lib/udev/rules.d' type -P "$rules")"
|
||||
fi
|
||||
if [[ -z "$rules" ]]; then
|
||||
# complain about not found rules
|
||||
return 1
|
||||
fi
|
||||
|
||||
add_file "$rules" /usr/lib/udev/rules.d/"${rules##*/}"
|
||||
|
||||
while IFS=, read -ra rule; do
|
||||
# skip empty lines, comments
|
||||
[[ -z "$rule" || "$rule" == @(+([[:space:]])|#*) ]] && continue
|
||||
|
||||
for pair in "${rule[@]}"; do
|
||||
IFS=' =' read -r key value <<< "$pair"
|
||||
case "$key" in
|
||||
'RUN{program}'|'RUN+'|'IMPORT{program}'|'ENV{REMOVE_CMD}')
|
||||
# strip quotes
|
||||
binary="${value//[\"\']/}"
|
||||
# just take the first word as the binary name
|
||||
binary="${binary%% *}"
|
||||
[[ "${binary:0:1}" == '$' ]] && continue
|
||||
if [[ "${binary:0:1}" != '/' ]]; then
|
||||
binary="$(PATH='/usr/lib/udev:/lib/udev' type -P "$binary")"
|
||||
fi
|
||||
add_binary "$binary"
|
||||
;;
|
||||
esac
|
||||
done
|
||||
done <"$rules"
|
||||
}
|
||||
|
||||
parse_config() {
|
||||
# parse key global variables set by the config file.
|
||||
|
||||
map add_module "${MODULES[@]}"
|
||||
map add_binary "${BINARIES[@]}"
|
||||
map add_file "${FILES[@]}"
|
||||
|
||||
tee "$BUILDROOT/buildconfig" < "$1" | {
|
||||
# When MODULES is not an array (but instead implicitly converted at
|
||||
# startup), sourcing the config causes the string value of MODULES
|
||||
# to be assigned as MODULES[0]. Avoid this by explicitly unsetting
|
||||
# MODULES before re-sourcing the config.
|
||||
unset MODULES
|
||||
|
||||
# shellcheck disable=SC1091
|
||||
. /dev/stdin
|
||||
|
||||
# arrayize MODULES if necessary.
|
||||
[[ ${MODULES@a} != *a* ]] && read -ra MODULES <<<"${MODULES//-/_}"
|
||||
|
||||
for mod in "${MODULES[@]%\?}"; do
|
||||
mod="${mod//-/_}"
|
||||
# only add real modules (2 == builtin)
|
||||
(( _addedmodules["$mod"] == 1 )) && add+=("$mod")
|
||||
done
|
||||
(( ${#add[*]} )) && printf 'MODULES="%s"\n' "${add[*]}"
|
||||
|
||||
printf '%s="%s"\n' \
|
||||
'EARLYHOOKS' "${_runhooks['early']# }" \
|
||||
'HOOKS' "${_runhooks['hooks']# }" \
|
||||
'LATEHOOKS' "${_runhooks['late']# }" \
|
||||
'CLEANUPHOOKS' "${_runhooks['cleanup']% }"
|
||||
} >"$BUILDROOT/config"
|
||||
}
|
||||
|
||||
initialize_buildroot() {
|
||||
# creates a temporary directory for the buildroot and initialize it with a
|
||||
# basic set of necessary directories and symlinks
|
||||
|
||||
local workdir='' kernver="$1" arch buildroot osreleasefile
|
||||
arch="$(uname -m)"
|
||||
|
||||
if ! workdir="$(mktemp -d --tmpdir mkinitcpio.XXXXXX)"; then
|
||||
error 'Failed to create temporary working directory in %s' "${TMPDIR:-/tmp}"
|
||||
return 1
|
||||
fi
|
||||
buildroot="${2:-$workdir/root}"
|
||||
|
||||
if [[ ! -w "${2:-$workdir}" ]]; then
|
||||
error 'Unable to write to build root: %s' "$buildroot"
|
||||
return 1
|
||||
fi
|
||||
|
||||
# base directory structure
|
||||
install -dm755 "$buildroot"/{new_root,proc,sys,dev,run,tmp,var,etc,usr/{local{,/bin,/sbin,/lib},lib,bin}}
|
||||
ln -s "usr/lib" "$buildroot/lib"
|
||||
ln -s "bin" "$buildroot/usr/sbin"
|
||||
ln -s "usr/bin" "$buildroot/bin"
|
||||
ln -s "usr/bin" "$buildroot/sbin"
|
||||
ln -s "/run" "$buildroot/var/run"
|
||||
|
||||
case "$arch" in
|
||||
x86_64)
|
||||
ln -s "lib" "$buildroot/usr/lib64"
|
||||
ln -s "usr/lib" "$buildroot/lib64"
|
||||
;;
|
||||
esac
|
||||
|
||||
# mkinitcpio version stamp
|
||||
# shellcheck disable=SC2154
|
||||
printf '%s' "$version" >"$buildroot/VERSION"
|
||||
|
||||
# kernel module dir
|
||||
[[ "$kernver" != 'none' ]] && install -dm755 "$buildroot/usr/lib/modules/$kernver/kernel"
|
||||
|
||||
# mount tables
|
||||
ln -s ../proc/self/mounts "$buildroot/etc/mtab"
|
||||
: >"$buildroot/etc/fstab"
|
||||
|
||||
# add os-release and initrd-release for systemd
|
||||
if [[ -e /etc/os-release ]]; then
|
||||
if [[ -L /etc/os-release ]]; then
|
||||
osreleasefile="$(realpath -- /etc/os-release)"
|
||||
install -Dm0644 "$osreleasefile" "${buildroot}${osreleasefile}"
|
||||
cp -adT /etc/os-release "${buildroot}/etc/os-release"
|
||||
cp -adT /etc/os-release "${buildroot}/etc/initrd-release"
|
||||
else
|
||||
install -Dm0644 /etc/os-release "${buildroot}/etc/os-release"
|
||||
ln -sT os-release "${buildroot}/etc/initrd-release"
|
||||
fi
|
||||
else
|
||||
: >"$buildroot/etc/initrd-release"
|
||||
fi
|
||||
|
||||
# add a blank ld.so.conf to keep ldconfig happy
|
||||
: >"$buildroot/etc/ld.so.conf"
|
||||
|
||||
printf '%s' "$workdir"
|
||||
}
|
||||
|
||||
run_build_hook() {
|
||||
local hook="$1" script='' resolved=''
|
||||
local MODULES=() BINARIES=() FILES=() SCRIPT=''
|
||||
|
||||
# find script in install dirs
|
||||
# _d_install is assigned in mkinitcpio
|
||||
# shellcheck disable=SC2154
|
||||
if ! script="$(PATH="$_d_install" type -P "$hook")"; then
|
||||
error "Hook '$hook' cannot be found"
|
||||
return 1
|
||||
fi
|
||||
|
||||
# check for deprecation
|
||||
if resolved="$(readlink -e "$script")" && [[ "${script##*/}" != "${resolved##*/}" ]]; then
|
||||
warning "Hook '%s' is deprecated. Replace it with '%s' in your config" \
|
||||
"${script##*/}" "${resolved##*/}"
|
||||
script="$resolved"
|
||||
fi
|
||||
|
||||
# source
|
||||
unset -f build
|
||||
# shellcheck disable=SC1090
|
||||
if ! . "$script"; then
|
||||
error 'Failed to read %s' "$script"
|
||||
return 1
|
||||
fi
|
||||
|
||||
if ! declare -f build >/dev/null; then
|
||||
error "Hook '%s' has no build function" "${script}"
|
||||
return 1
|
||||
fi
|
||||
|
||||
# run
|
||||
if (( _optquiet )); then
|
||||
msg2 "Running build hook: [%s]" "${script##*/}"
|
||||
else
|
||||
msg2 "Running build hook: [%s]" "$script"
|
||||
fi
|
||||
build
|
||||
|
||||
# if we made it this far, return successfully. Hooks can
|
||||
# do their own error catching if it's severe enough, and
|
||||
# we already capture errors from the add_* functions.
|
||||
return 0
|
||||
}
|
||||
|
||||
try_enable_color() {
|
||||
local colors
|
||||
|
||||
if ! colors="$(tput colors 2>/dev/null)"; then
|
||||
warning "Failed to enable color. Check your TERM environment variable"
|
||||
return
|
||||
fi
|
||||
|
||||
if (( colors > 0 )) && tput setaf 0 &>/dev/null; then
|
||||
_color_none="$(tput sgr0)"
|
||||
_color_bold="$(tput bold)"
|
||||
_color_blue="$_color_bold$(tput setaf 4)"
|
||||
_color_green="$_color_bold$(tput setaf 2)"
|
||||
_color_red="$_color_bold$(tput setaf 1)"
|
||||
_color_yellow="$_color_bold$(tput setaf 3)"
|
||||
fi
|
||||
}
|
||||
|
||||
install_modules() {
|
||||
local m
|
||||
local -a xz_comp gz_comp zst_comp
|
||||
|
||||
[[ "$KERNELVERSION" == 'none' ]] && return 0
|
||||
|
||||
if (( $# == 0 )); then
|
||||
warning "No modules were added to the image. This is probably not what you want."
|
||||
return 0
|
||||
fi
|
||||
|
||||
for m in "$@"; do
|
||||
add_file "$m" "$m"
|
||||
done
|
||||
|
||||
msg "Generating module dependencies"
|
||||
map add_file "$_d_kmoduledir"/modules.{builtin,builtin.modinfo,order}
|
||||
depmod -b "$BUILDROOT" "$KERNELVERSION"
|
||||
|
||||
# remove all non-binary module.* files (except devname for on-demand module loading)
|
||||
rm "${BUILDROOT}${_d_kmoduledir}"/modules.!(*.bin|devname|softdep)
|
||||
}
|
||||
|
||||
# vim: set ft=sh ts=4 sw=4 et:
|
Loading…
Reference in a new issue