main/msm-firmware-loader: add a package to load firmware on msm devices (MR 2431)
Many devices need proprietary firmware blobs. So far those blobs were packaged and installed from the repository but this approach has many drawbacks: - The rootfs can only be used on a single device model. - If a model has multiple variants that have diferent secire-boot key, each must have it's own firmware blobs. This makes maintaining packaged firmware very hard and outweights the benefits of having a repeatable installation in most cases. Instead we can load blobs dynamically from preexisting firmware partitions that usually have same structure and contain the blobs we are interested in. The proposed scripts place symlinks to the blobs in a special dir that then given to the kernel. Blobs from firmware/postmarketos (or another dir that was set as extra path prior the script execution) will take priority which allows to override some blobs (e.g. for deviecs with no secure-boot)
This commit is contained in:
parent
f58e9d912e
commit
bc50dd0279
7 changed files with 241 additions and 0 deletions
|
@ -25,6 +25,8 @@ sh_files="
|
|||
./main/swclock-offset/swclock-offset-shutdown.sh
|
||||
./main/ttyescape/*.sh
|
||||
./main/ttyescape/*.post-install
|
||||
./main/msm-firmware-loader/*.sh
|
||||
./main/msm-firmware-loader/*.post-install
|
||||
|
||||
$(find . -path './main/postmarketos-ui-*/*.sh')
|
||||
$(find . -path './main/postmarketos-ui-*/*.pre-install')
|
||||
|
|
40
main/msm-firmware-loader/APKBUILD
Normal file
40
main/msm-firmware-loader/APKBUILD
Normal file
|
@ -0,0 +1,40 @@
|
|||
pkgname=msm-firmware-loader
|
||||
pkgver=1
|
||||
pkgrel=0
|
||||
pkgdesc="Set of init services to automatically load firmware from device partitions"
|
||||
url="https://postmarketos.org/"
|
||||
arch="armhf armv7 aarch64"
|
||||
license="MIT"
|
||||
install="$pkgname.post-install"
|
||||
source="
|
||||
msm-firmware-loader.sh
|
||||
msm-firmware-loader.initd
|
||||
msm-firmware-loader-unpack.sh
|
||||
msm-firmware-loader-unpack.initd
|
||||
"
|
||||
options="!check"
|
||||
|
||||
package() {
|
||||
mkdir -p "$pkgdir"
|
||||
|
||||
install -Dm755 "$srcdir/msm-firmware-loader.initd" \
|
||||
"$pkgdir/etc/init.d/msm-firmware-loader"
|
||||
install -Dm755 "$srcdir/msm-firmware-loader-unpack.initd" \
|
||||
"$pkgdir/etc/init.d/msm-firmware-loader-unpack"
|
||||
|
||||
# Create mountpoint for the scripts
|
||||
mkdir -p "$pkgdir/lib/firmware/msm-firmware-loader"
|
||||
|
||||
install -Dm755 "$srcdir/msm-firmware-loader.sh" \
|
||||
"$pkgdir/usr/sbin/msm-firmware-loader.sh"
|
||||
install -Dm755 "$srcdir/msm-firmware-loader-unpack.sh" \
|
||||
"$pkgdir/usr/sbin/msm-firmware-loader-unpack.sh"
|
||||
}
|
||||
|
||||
|
||||
sha512sums="
|
||||
ce6d8a072673bcdf6a3b24455d690291c87046802a460742271c2465db3326a09792b7c0c3e07d3e741b75cc34a5e416a64899153a0b920149e70718d0188761 msm-firmware-loader.sh
|
||||
d9ad3b21564de9a4970a8923b8598fb46a54543ac9f1494676a6833800bc68c64f230737b308fec54aae09c2cf635794e8f1abc46253b0386260b4580587483d msm-firmware-loader.initd
|
||||
93063f24b64206f4e6115ca0276d47bb65e1c510fc56fe1a939030d09d3b63cf07f001fb789309bb317f787cbe687906258bb5eb961a9ea90568f672378e86ea msm-firmware-loader-unpack.sh
|
||||
616a28c3a65a45bb65f798989d93daacdeea08a90a9a8538b5bac2d73b2c8b135554ecaf49b4084829f88af760a144802adcd89b50f46bc267d6b04c9c733ff8 msm-firmware-loader-unpack.initd
|
||||
"
|
16
main/msm-firmware-loader/msm-firmware-loader-unpack.initd
Normal file
16
main/msm-firmware-loader/msm-firmware-loader-unpack.initd
Normal file
|
@ -0,0 +1,16 @@
|
|||
#!/sbin/openrc-run
|
||||
|
||||
name="Firmware Unpacker"
|
||||
description="Unpack dynamically loaded firmware"
|
||||
|
||||
depend() {
|
||||
before rmtfs
|
||||
}
|
||||
|
||||
start() {
|
||||
ebegin "Starting msm-firmware-loader (Unpacking the firmware)"
|
||||
# This script must be executed before rmtfs, block other services until it's done.
|
||||
/usr/sbin/msm-firmware-loader-unpack.sh
|
||||
eend $?
|
||||
}
|
||||
|
31
main/msm-firmware-loader/msm-firmware-loader-unpack.sh
Normal file
31
main/msm-firmware-loader/msm-firmware-loader-unpack.sh
Normal file
|
@ -0,0 +1,31 @@
|
|||
#!/bin/sh
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
#
|
||||
# Some devices have their modem firmware packaged as .gz blobs.
|
||||
# Those needs to be unpacked as Kernel can't handle .gz packed
|
||||
# firmware at this time.
|
||||
#
|
||||
|
||||
BASEDIR="/lib/firmware/msm-firmware-loader/target"
|
||||
|
||||
for blob in "$BASEDIR"/*.gz
|
||||
do
|
||||
if ! [ -e "$blob" ]
|
||||
then
|
||||
exit
|
||||
else
|
||||
break
|
||||
fi
|
||||
done
|
||||
|
||||
UNPACKDIR="$(mktemp -td "unpacked_fw.XXXXXX")"
|
||||
|
||||
for blob in "$BASEDIR"/*.gz
|
||||
do
|
||||
blob_name="$(basename "${blob%.gz}")"
|
||||
gzip -d < "$blob" > "$UNPACKDIR/$blob_name"
|
||||
rm "$blob"
|
||||
ln -s "$UNPACKDIR/$blob_name" "$BASEDIR/$blob_name"
|
||||
done
|
||||
|
16
main/msm-firmware-loader/msm-firmware-loader.initd
Normal file
16
main/msm-firmware-loader/msm-firmware-loader.initd
Normal file
|
@ -0,0 +1,16 @@
|
|||
#!/sbin/openrc-run
|
||||
|
||||
name="MSM Firmware Loader"
|
||||
description="Load firmware that is located on dedicated partitions of qcom devices"
|
||||
|
||||
depend() {
|
||||
need sysfs devfs
|
||||
before udev
|
||||
}
|
||||
|
||||
start() {
|
||||
ebegin "Starting msm-firmware-loader"
|
||||
# This script must be executed before udev, block other services until it's done.
|
||||
/usr/sbin/msm-firmware-loader.sh
|
||||
eend $?
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
#!/bin/sh
|
||||
# We need to start before udev in sysinit runlevel
|
||||
rc-update add msm-firmware-loader sysinit
|
||||
# We also sometimes need to unpack modem blobs before rmtfs
|
||||
rc-update add msm-firmware-loader-unpack boot
|
131
main/msm-firmware-loader/msm-firmware-loader.sh
Normal file
131
main/msm-firmware-loader/msm-firmware-loader.sh
Normal file
|
@ -0,0 +1,131 @@
|
|||
#!/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')"
|
||||
|
||||
if [ -z "${FW_PARTITIONS##*$PARTNAME*}" ] && [ -n "$PARTNAME" ]
|
||||
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
|
||||
|
Loading…
Reference in a new issue