0fac39abe1
cpio expects a newline-separated list of files from stdin by default, and you can change that to a NULL-terminated list of files by using the '-0' switch. Previously we were passing a NULL-terminated list ('-print0') and using cpio with the default setting. For some reason busybox cpio works with that but GNU cpio doesn't like that and generates an initramfs without any files (as it only gets "a single file"). With this change the initramfs generation works fine with both busybox cpio and gnu cpio. Fixes #815
470 lines
12 KiB
Bash
470 lines
12 KiB
Bash
#!/bin/sh
|
|
|
|
# Declare used deviceinfo variables to pass shellcheck (order alphabetically)
|
|
deviceinfo_append_dtb=""
|
|
deviceinfo_arch=""
|
|
deviceinfo_bootimg_append_seandroidenforce=""
|
|
deviceinfo_bootimg_blobpack=""
|
|
deviceinfo_bootimg_dtb_second=""
|
|
deviceinfo_bootimg_mtk_mkimage=""
|
|
deviceinfo_bootimg_qcdt=""
|
|
deviceinfo_dtb=""
|
|
deviceinfo_flash_offset_base=""
|
|
deviceinfo_flash_offset_kernel=""
|
|
deviceinfo_flash_offset_ramdisk=""
|
|
deviceinfo_flash_offset_second=""
|
|
deviceinfo_flash_offset_tags=""
|
|
deviceinfo_flash_pagesize=""
|
|
deviceinfo_generate_bootimg=""
|
|
deviceinfo_generate_legacy_uboot_initfs=""
|
|
deviceinfo_initfs_compression=""
|
|
deviceinfo_kernel_cmdline=""
|
|
deviceinfo_legacy_uboot_load_address=""
|
|
deviceinfo_modules_initfs=""
|
|
|
|
# Overwritten by mkinitfs.sh
|
|
tmpdir=""
|
|
|
|
source_deviceinfo()
|
|
{
|
|
if [ ! -e "/etc/deviceinfo" ]; then
|
|
echo "NOTE: deviceinfo (from device package) not installed yet," \
|
|
"not building the initramfs now (it should get built later" \
|
|
"automatically.)"
|
|
exit 0
|
|
fi
|
|
# shellcheck disable=SC1091
|
|
. /etc/deviceinfo
|
|
}
|
|
|
|
parse_commandline()
|
|
{
|
|
if [ "$1" != "-o" ]; then
|
|
echo "postmarketos-mkinitfs"
|
|
echo "usage: $(basename "$0") -o OUTFILE KERNELVERSION"
|
|
exit 1
|
|
fi
|
|
|
|
outfile=$2
|
|
outfile_extra=$2-extra
|
|
kernel=$3
|
|
}
|
|
|
|
# Verify that each file required by the installed hooks exists and exit with an
|
|
# error if they don't.
|
|
check_hook_files()
|
|
{
|
|
for file in "/etc/postmarketos-mkinitfs/files"/*.files; do
|
|
[ -f "$file" ] || continue
|
|
while IFS= read -r line; do
|
|
if ! [ -f "$line" ]; then
|
|
echo "ERROR: File ${line} specified in ${file} does not exist!"
|
|
exit 1
|
|
fi
|
|
done < "$file"
|
|
done
|
|
}
|
|
|
|
create_folders()
|
|
{
|
|
for dir in /bin /sbin /usr/bin /usr/sbin /proc /sys /dev /tmp /lib \
|
|
/boot /sysroot /etc; do
|
|
mkdir -p "$tmpdir$dir"
|
|
done
|
|
}
|
|
|
|
get_modules_by_globs()
|
|
{
|
|
globs="
|
|
# base.modules
|
|
kernel/drivers/block/loop.ko
|
|
kernel/fs/overlayfs
|
|
|
|
# cryptsetup.modules
|
|
kernel/crypto/*
|
|
kernel/arch/*/crypto/*
|
|
kernel/drivers/md/dm-crypt.ko
|
|
|
|
# required for modprobe
|
|
modules.*
|
|
"
|
|
|
|
for glob in $globs; do
|
|
for file in /lib/modules/$kernel/$glob; do
|
|
if [ -d "$file" ]; then
|
|
find "$file" -type f
|
|
elif [ -e "$file" ]; then
|
|
echo "$file"
|
|
fi
|
|
done
|
|
done
|
|
}
|
|
|
|
# Read a modules-load.d style file into a single line. The file is expected to
|
|
# have empty lines, lines starting with "#" that are comments or one word in
|
|
# the line. The resulting parsed line is printed to stdout.
|
|
# $1: file to parse
|
|
parse_file_as_line()
|
|
{
|
|
_first="true"
|
|
while IFS= read -r line; do
|
|
case "$line" in
|
|
""|"#"*)
|
|
# Comment or empty line, ignore
|
|
;;
|
|
*)
|
|
if [ "$_first" = "true" ]; then
|
|
_first="false"
|
|
else
|
|
printf " "
|
|
fi
|
|
printf "%s" "$line"
|
|
;;
|
|
esac
|
|
done < "$1"
|
|
}
|
|
|
|
# Parse modules by name from deviceinfo and from these files:
|
|
# /etc/postmarketos-mkinitfs/modules/*.modules. The postmarketos-mkinitfs
|
|
# package installs a 00-default.modules there.
|
|
# Resolved kernel module paths get printed to stdout, informative logging to
|
|
# stderr.
|
|
# NOTE: This does not work with busybox' modprobe. That's why
|
|
# postmarketos-mkinitfs depends on kmod.
|
|
get_modules_by_name()
|
|
{
|
|
{
|
|
echo "Scanning kernel module dependencies..."
|
|
echo "NOTE: ** modprobe warnings below can be ignored ** if your device does not run the"
|
|
echo "mainline kernel yet (most devices!) or if the related kernel options are enabled"
|
|
echo "with 'y' instead of 'm' (module)."
|
|
} >&2
|
|
|
|
MODULES="$deviceinfo_modules_initfs"
|
|
echo " - deviceinfo: $deviceinfo_modules_initfs" >&2
|
|
|
|
for file in "/etc/postmarketos-mkinitfs/modules/"*.modules; do
|
|
[ -f "$file" ] || continue
|
|
_modules_file="$(parse_file_as_line "$file")"
|
|
echo " - $(basename "$file"): $_modules_file" >&2
|
|
MODULES="$MODULES $_modules_file"
|
|
done
|
|
|
|
# shellcheck disable=SC2086
|
|
modprobe \
|
|
-a \
|
|
--dry-run \
|
|
--show-depends \
|
|
--set-version="$kernel" \
|
|
$MODULES \
|
|
| sort -u \
|
|
| cut -d ' ' -f 2
|
|
}
|
|
|
|
get_modules()
|
|
{
|
|
get_modules_by_globs
|
|
get_modules_by_name
|
|
}
|
|
|
|
# Get the paths to all binaries and their dependencies
|
|
get_binaries()
|
|
{
|
|
BINARIES="
|
|
/bin/busybox
|
|
/bin/busybox-extras
|
|
/usr/sbin/telnetd
|
|
/sbin/kpartx
|
|
"
|
|
|
|
for file in "/etc/postmarketos-mkinitfs/files"/*.files; do
|
|
[ -f "$file" ] || continue
|
|
while IFS= read -r line; do
|
|
BINARIES="${BINARIES} ${line}"
|
|
done < "$file"
|
|
done
|
|
# shellcheck disable=SC2086
|
|
sudo -u nobody lddtree -l $BINARIES | sort -u
|
|
}
|
|
|
|
# Collect non-binary files for osk-sdl and its dependencies
|
|
# This gets called as $(get_osk_config), so the exit code can be checked/handled.
|
|
get_osk_config()
|
|
{
|
|
fontpath=$(awk '/^keyboard-font/{print $3}' /etc/osk.conf)
|
|
if [ ! -f "$fontpath" ]; then
|
|
echo "ERROR: failed to parse 'keyboard-font' from osk-sdl config!"
|
|
exit 1
|
|
fi
|
|
ret="
|
|
/etc/osk.conf
|
|
/etc/ts.conf
|
|
/etc/pointercal
|
|
/etc/fb.modes
|
|
/etc/directfbrc
|
|
$fontpath
|
|
"
|
|
echo "${ret}"
|
|
}
|
|
|
|
get_binaries_extra()
|
|
{
|
|
BINARIES_EXTRA="
|
|
$(find /usr/lib/directfb-* -name '*.so')
|
|
/lib/libz.so.1
|
|
/sbin/cryptsetup
|
|
/sbin/dmsetup
|
|
/sbin/e2fsck
|
|
/usr/bin/charging-sdl
|
|
/usr/bin/osk-sdl
|
|
/usr/lib/libGL.so.1
|
|
/usr/lib/libts*
|
|
/usr/lib/ts/*
|
|
/usr/sbin/parted
|
|
/usr/sbin/resize2fs
|
|
/usr/sbin/thd
|
|
"
|
|
|
|
tmp1=$(mktemp /tmp/mkinitfs.XXXXXX)
|
|
get_binaries > "$tmp1"
|
|
tmp2=$(mktemp /tmp/mkinitfs.XXXXXX)
|
|
|
|
# shellcheck disable=SC2086
|
|
sudo -u nobody lddtree -l $BINARIES_EXTRA | sort -u > "$tmp2"
|
|
ret=$(comm -13 "$tmp1" "$tmp2")
|
|
rm "$tmp1" "$tmp2"
|
|
echo "${ret}"
|
|
}
|
|
|
|
# Copy files to the destination specified
|
|
# $1: files
|
|
# $2: destination
|
|
copy_files()
|
|
{
|
|
for file in $1; do
|
|
[ -e "$file" ] || continue
|
|
cp -a --parents "$file" "$2"
|
|
done
|
|
}
|
|
|
|
create_device_nodes()
|
|
{
|
|
mknod -m 666 "$tmpdir/dev/null" c 1 3
|
|
mknod -m 644 "$tmpdir/dev/random" c 1 8
|
|
mknod -m 644 "$tmpdir/dev/urandom" c 1 9
|
|
}
|
|
|
|
replace_init_variables()
|
|
{
|
|
sed -i "s:@INITRAMFS_EXTRA@:${outfile_extra}:g" "$tmpdir/init"
|
|
}
|
|
|
|
# Create a cpio image of the specified folder
|
|
# $1: folder
|
|
# $2: outfile
|
|
create_cpio_image()
|
|
{
|
|
if ! cd "$1"; then
|
|
echo "ERROR: failed to cd to '$1'"
|
|
exit 1
|
|
fi
|
|
[ -z "$deviceinfo_initfs_compression" ] && deviceinfo_initfs_compression='gzip -1'
|
|
find . -print0 \
|
|
| cpio --quiet -o -0 -H newc \
|
|
| $deviceinfo_initfs_compression > "$2"
|
|
}
|
|
|
|
# Required command check with useful error message
|
|
# $1: command (e.g. "mkimage")
|
|
# $2: package (e.g. "uboot-tools")
|
|
# $3: related deviceinfo variable (e.g. "generate_bootimg")
|
|
require_package()
|
|
{
|
|
[ "$(command -v "$1")" = "" ] || return
|
|
echo "ERROR: 'deviceinfo_$3' is set, but the package '$2' was not"
|
|
echo "installed! Please add '$2' to the depends= line of your device's"
|
|
echo "APKBUILD. See also: <https://postmarketos.org/deviceinfo>"
|
|
exit 1
|
|
}
|
|
|
|
# Legacy u-boot images
|
|
create_uboot_files()
|
|
{
|
|
arch="arm"
|
|
if [ "${deviceinfo_arch}" = "aarch64" ]; then
|
|
arch="arm64"
|
|
fi
|
|
|
|
[ "${deviceinfo_generate_legacy_uboot_initfs}" = "true" ] || return
|
|
require_package "mkimage" "uboot-tools" "generate_legacy_uboot_initfs"
|
|
|
|
echo "==> initramfs: creating uInitrd"
|
|
# shellcheck disable=SC2039
|
|
mkimage -A $arch -T ramdisk -C none -n uInitrd -d "$outfile" \
|
|
"${outfile/initramfs-/uInitrd-}" || exit 1
|
|
|
|
echo "==> kernel: creating uImage"
|
|
# shellcheck disable=SC2039
|
|
kernelfile="${outfile/initramfs-/vmlinuz-}"
|
|
if [ "${deviceinfo_append_dtb}" = "true" ]; then
|
|
kernelfile="${kernelfile}-dtb"
|
|
fi
|
|
|
|
if [ -z "$deviceinfo_legacy_uboot_load_address" ]; then
|
|
deviceinfo_legacy_uboot_load_address="80008000"
|
|
fi
|
|
|
|
# shellcheck disable=SC2039
|
|
mkimage -A $arch -O linux -T kernel -C none -a "$deviceinfo_legacy_uboot_load_address" \
|
|
-e "$deviceinfo_legacy_uboot_load_address" \
|
|
-n postmarketos -d "$kernelfile" "${outfile/initramfs-/uImage-}" || exit 1
|
|
}
|
|
|
|
# Android devices
|
|
create_bootimg()
|
|
{
|
|
[ "${deviceinfo_generate_bootimg}" = "true" ] || return
|
|
require_package "mkbootimg-osm0sis" "mkbootimg" "generate_bootimg"
|
|
|
|
echo "==> initramfs: creating boot.img"
|
|
_base="${deviceinfo_flash_offset_base}"
|
|
[ -z "$_base" ] && _base="0x10000000"
|
|
|
|
# shellcheck disable=SC2039
|
|
kernelfile="${outfile/initramfs-/vmlinuz-}"
|
|
if [ "${deviceinfo_append_dtb}" = "true" ]; then
|
|
kernelfile="${kernelfile}-dtb"
|
|
fi
|
|
|
|
if [ "${deviceinfo_bootimg_mtk_mkimage}" = "true" ]; then
|
|
kernelfile="${kernelfile}-mtk"
|
|
fi
|
|
|
|
_second=""
|
|
if [ "${deviceinfo_bootimg_dtb_second}" = "true" ]; then
|
|
if [ -z "${deviceinfo_dtb}" ]; then
|
|
echo "ERROR: deviceinfo_bootimg_dtb_second is set, but"
|
|
echo "'deviceinfo_dtb' is missing. Set 'deviceinfo_dtb'"
|
|
echo "to the device tree blob for your device."
|
|
echo "See also: <https://postmarketos.org/deviceinfo>"
|
|
exit 1
|
|
fi
|
|
dtb="/usr/share/dtb/${deviceinfo_dtb}.dtb"
|
|
_second="--second $dtb"
|
|
if ! [ -e "$dtb" ]; then
|
|
echo "ERROR: File not found: $dtb. Please set 'deviceinfo_dtb'"
|
|
echo "to the relative path to the device tree blob for your"
|
|
echo "device (without .dtb)."
|
|
echo "See also: <https://postmarketos.org/deviceinfo>"
|
|
exit 1
|
|
fi
|
|
fi
|
|
_dt=""
|
|
if [ "${deviceinfo_bootimg_qcdt}" = "true" ]; then
|
|
_dt="--dt /boot/dt.img"
|
|
if ! [ -e "/boot/dt.img" ]; then
|
|
echo "ERROR: File not found: /boot/dt.img, but"
|
|
echo "'deviceinfo_bootimg_qcdt' is set. Please verify that your"
|
|
echo "device is a QCDT device by analyzing the boot.img file"
|
|
echo "(e.g. 'pmbootstrap bootimg_analyze path/to/twrp.img')"
|
|
echo "and based on that, set the deviceinfo variable to false or"
|
|
echo "adjust your linux APKBUILD to properly generate the dt.img"
|
|
echo "file. See also: <https://postmarketos.org/deviceinfo>"
|
|
exit 1
|
|
fi
|
|
fi
|
|
# shellcheck disable=SC2039 disable=SC2086
|
|
mkbootimg-osm0sis \
|
|
--kernel "${kernelfile}" \
|
|
--ramdisk "$outfile" \
|
|
--base "${_base}" \
|
|
--second_offset "${deviceinfo_flash_offset_second}" \
|
|
--cmdline "${deviceinfo_kernel_cmdline}" \
|
|
--kernel_offset "${deviceinfo_flash_offset_kernel}" \
|
|
--ramdisk_offset "${deviceinfo_flash_offset_ramdisk}" \
|
|
--tags_offset "${deviceinfo_flash_offset_tags}" \
|
|
--pagesize "${deviceinfo_flash_pagesize}" \
|
|
${_second} \
|
|
${_dt} \
|
|
-o "${outfile/initramfs-/boot.img-}" || exit 1
|
|
if [ "${deviceinfo_bootimg_blobpack}" = "true" ]; then
|
|
echo "==> initramfs: creating blob"
|
|
# shellcheck disable=SC2039
|
|
blobpack "${outfile/initramfs-/blob-}" LNX \
|
|
"${outfile/initramfs-/boot.img-}" || exit 1
|
|
fi
|
|
if [ "${deviceinfo_bootimg_append_seandroidenforce}" = "true" ]; then
|
|
echo "==> initramfs: appending 'SEANDROIDENFORCE' to boot.img"
|
|
# shellcheck disable=SC2039 disable=SC2039
|
|
echo -n "SEANDROIDENFORCE" >> "${outfile/initramfs-/boot.img-}"
|
|
fi
|
|
}
|
|
|
|
# Append the correct device tree to the linux image file or copy the dtb to the boot partition
|
|
append_or_copy_dtb()
|
|
{
|
|
[ -n "${deviceinfo_dtb}" ] || return
|
|
echo "==> kernel: device-tree blob operations"
|
|
dtb=""
|
|
for filename in $deviceinfo_dtb; do
|
|
if ! [ -e "/usr/share/dtb/$filename.dtb" ]; then
|
|
echo "ERROR: File not found: /usr/share/dtb/$filename.dtb"
|
|
exit 1
|
|
fi
|
|
dtb="$dtb /usr/share/dtb/$filename.dtb"
|
|
done
|
|
# shellcheck disable=SC2039
|
|
kernel="${outfile/initramfs-/vmlinuz-}"
|
|
if [ "${deviceinfo_append_dtb}" = "true" ]; then
|
|
echo "==> kernel: appending device-tree ${deviceinfo_dtb}"
|
|
# shellcheck disable=SC2086
|
|
cat "$kernel" $dtb > "${kernel}-dtb"
|
|
else
|
|
echo "==> kernel: copying dtb ${deviceinfo_dtb} to boot partition"
|
|
# shellcheck disable=SC2086
|
|
cp $dtb "$(dirname "${outfile}")"
|
|
fi
|
|
}
|
|
|
|
# Add Mediatek header to kernel & initramfs
|
|
add_mtk_header()
|
|
{
|
|
[ "${deviceinfo_bootimg_mtk_mkimage}" = "true" ] || return
|
|
require_package "mtk-mkimage" "mtk-mkimage" "bootimg_mtk_mkimage"
|
|
|
|
echo "==> initramfs: adding Mediatek header"
|
|
mv "$outfile" "$outfile-orig"
|
|
mtk-mkimage ROOTFS "$outfile-orig" "$outfile"
|
|
rm "$outfile-orig"
|
|
|
|
echo "==> kernel: adding Mediatek header"
|
|
# shellcheck disable=SC2039
|
|
kernel="${outfile/initramfs-/vmlinuz-}"
|
|
rm -f "${kernel}-mtk"
|
|
mtk-mkimage KERNEL "$kernel" "${kernel}-mtk"
|
|
}
|
|
|
|
# Create the initramfs-extra archive
|
|
# $1: outfile
|
|
generate_initramfs_extra()
|
|
{
|
|
echo "==> initramfs: creating $1"
|
|
|
|
osk_conf="$(get_osk_config)"
|
|
if [ $? -eq 1 ]; then
|
|
echo "ERROR: Font specified in /etc/osk.conf does not exist!"
|
|
exit 1
|
|
fi
|
|
|
|
# Set up initramfs-extra in temp folder
|
|
tmpdir_extra=$(mktemp -d /tmp/mkinitfs.XXXXXX)
|
|
mkdir -p "$tmpdir_extra"
|
|
copy_files "$(get_binaries_extra)" "$tmpdir_extra"
|
|
copy_files "$osk_conf" "$tmpdir_extra"
|
|
create_cpio_image "$tmpdir_extra" "$1.new"
|
|
rm -rf "$tmpdir_extra"
|
|
|
|
# Replace old initramfs-extra *after* we are done to make sure
|
|
# it does not become corrupted if something goes wrong.
|
|
mv "$1.new" "$1"
|
|
}
|