2021-08-04 11:05:49 +00:00
|
|
|
#!/bin/sh
|
|
|
|
# SPDX-License-Identifier: MIT
|
|
|
|
|
|
|
|
#
|
|
|
|
# This script is responsible for loading firmware blobs from firmware
|
|
|
|
# partitions on qcom devices. It will make a dir in tmp, mount all of the
|
|
|
|
# interesting partitions there and then symlink blobs to a single dir that can
|
|
|
|
# be then provided to the kernel. (At this time only single additional
|
|
|
|
# directory can be provided)
|
|
|
|
#
|
|
|
|
# This script attempts to load everything at runtime and be as generic
|
|
|
|
# as possible between the target devices: It should allow a single rootfs
|
|
|
|
# to be used on multiple different devices as long as all the blobs
|
|
|
|
# are present on dedicated partitions.
|
|
|
|
# (Usually the case, Samsung devices ship all blobs, other devices may miss
|
|
|
|
# venus but that still allows for WiFi and modem to work)
|
|
|
|
#
|
|
|
|
|
|
|
|
# Configurations:
|
|
|
|
|
|
|
|
# List of partitions to be mounted and inspected for blobs.
|
|
|
|
FW_PARTITIONS="
|
|
|
|
apnhlos
|
|
|
|
modem
|
|
|
|
"
|
|
|
|
|
|
|
|
# Base dirrectory to be used to unfold the partitions into.
|
|
|
|
BASEDIR="/lib/firmware/msm-firmware-loader"
|
|
|
|
|
|
|
|
# Preparations:
|
|
|
|
|
|
|
|
# This script is intended to run before udev. This means that writeable fs
|
|
|
|
# May not be available yet. Since this script only creates symlinks, it
|
|
|
|
# uses tmpfs to work around the early-run limitations as well as to reduce
|
|
|
|
# disk wear slightly.
|
|
|
|
mount -o mode=755,nodev,noexec,nosuid -t tmpfs none "$BASEDIR"
|
|
|
|
|
|
|
|
mkdir "$BASEDIR/mnt"
|
|
|
|
mkdir "$BASEDIR/target"
|
|
|
|
|
|
|
|
# Scanning and mounting partitions we're interested in:
|
|
|
|
|
|
|
|
# /dev/disk/by-partlabel symlinks don't exist yet, scan sysfs for names instead
|
|
|
|
for part in /sys/block/mmcblk*/mmcblk*p*
|
|
|
|
do
|
|
|
|
DEVNAME="$(grep DEVNAME "$part"/uevent | sed 's/DEVNAME=//g')"
|
|
|
|
PARTNAME="$(grep PARTNAME "$part"/uevent | sed 's/PARTNAME=//g')"
|
|
|
|
|
2021-12-15 22:59:55 +00:00
|
|
|
if [ -z "${FW_PARTITIONS##*"$PARTNAME"*}" ] && [ -n "$PARTNAME" ]
|
2021-08-04 11:05:49 +00:00
|
|
|
then
|
|
|
|
mkdir "$BASEDIR/mnt/$PARTNAME"
|
|
|
|
mount -o ro,nodev,noexec,nosuid \
|
|
|
|
"/dev/$DEVNAME" "$BASEDIR/mnt/$PARTNAME"
|
|
|
|
fi
|
|
|
|
done
|
|
|
|
|
|
|
|
# Linking blobs from all partitions:
|
|
|
|
|
|
|
|
# Backup the preselected path, link all of the installed blobs.
|
|
|
|
# This is needed for devices that require blobs either not present
|
|
|
|
# on the partitions (e.g. venus on many msm8916 devices) or if
|
|
|
|
# the device has secure-boot disabled and can run newer blobs.
|
|
|
|
EXTRA_PATH="$(cat /sys/module/firmware_class/parameters/path)"
|
|
|
|
|
|
|
|
if [ -d "$EXTRA_PATH" ]
|
|
|
|
then
|
|
|
|
for blob in "$EXTRA_PATH"/*
|
|
|
|
do
|
|
|
|
if ! [ -e "$blob" ]; then break; fi
|
|
|
|
ln -s "$blob" "$BASEDIR/target/$(basename "$blob")"
|
|
|
|
done
|
|
|
|
fi
|
|
|
|
|
|
|
|
# Scan through mounted partitions and symlink all of the blobs.
|
|
|
|
# This loop ignores blobs with names already present in the
|
|
|
|
# target to allow preinstalled blobs to override ones in the partitions.
|
|
|
|
for blob in "$BASEDIR"/mnt/*/image/*
|
|
|
|
do
|
|
|
|
BLOBBASE="${blob##*/}"
|
|
|
|
BLOBBASE="${BLOBBASE%.*}"
|
|
|
|
|
|
|
|
# Skip blob prefix if it's already present.
|
|
|
|
for prefix in "$BASEDIR/target/$BLOBBASE."*
|
|
|
|
do
|
|
|
|
if [ -e "$prefix" ]; then continue 2; fi
|
|
|
|
done
|
|
|
|
|
|
|
|
for part in "$BASEDIR"/mnt/*/image/"$BLOBBASE"*
|
|
|
|
do
|
|
|
|
ln -s "$part" "$BASEDIR/target/$(basename "$part")"
|
|
|
|
done
|
|
|
|
done
|
|
|
|
|
|
|
|
# Fixup the directory structure:
|
|
|
|
|
|
|
|
# venus (video encoder/decoder) blobs are expected to be in a subdir.
|
|
|
|
# Re-link the blobs if the venus firmware wasn't already preinstalled.
|
|
|
|
# Different platforms expect firmware in different subdirs
|
|
|
|
# (as in linux-firmware-qcom) so the venus dir is duplicated multiple times
|
|
|
|
# under possible names for the scritpt to be generic without complex detection.
|
|
|
|
|
|
|
|
if [ -f "$BASEDIR/target/venus.mdt" ] && ! [ -d "$BASEDIR/target/qcom" ]
|
|
|
|
then
|
|
|
|
mkdir -p "$BASEDIR/target/qcom/venus-x"
|
|
|
|
for part in "$BASEDIR"/target/venus.*
|
|
|
|
do
|
|
|
|
ln -s "$part" "$BASEDIR/target/qcom/venus-x/$(basename "$part")"
|
|
|
|
done
|
|
|
|
fi
|
|
|
|
|
|
|
|
VENUS_DIRS="
|
|
|
|
venus-1.8
|
|
|
|
venus-4.2
|
|
|
|
venus-5.2
|
|
|
|
venus-5.4
|
|
|
|
vpu-1.0
|
|
|
|
vpu-2.0
|
|
|
|
"
|
|
|
|
|
|
|
|
for vdir in $VENUS_DIRS
|
|
|
|
do
|
|
|
|
if ! [ -d "$BASEDIR/target/qcom/$vdir" ] && [ -f "$BASEDIR/target/venus.mdt" ]
|
|
|
|
then
|
|
|
|
ln -s "$BASEDIR/target/qcom/venus-x" \
|
|
|
|
"$BASEDIR/target/qcom/$vdir"
|
|
|
|
fi
|
|
|
|
done
|
|
|
|
|
|
|
|
# Set the new custom firmware path:
|
|
|
|
printf "%s" "$BASEDIR/target" > /sys/module/firmware_class/parameters/path
|
|
|
|
|