From b7c57aab2f8546e784dddd2451acf39c9a2e2f4a Mon Sep 17 00:00:00 2001 From: Luxferre Date: Sun, 25 Oct 2026 12:32:46 +0200 Subject: [PATCH] Fix OpenRC boot hang in msm-modem-uim-selection, USB gadget UDC race/unbind, and SIM2 lock sync --- .../rootfs/etc/conf.d/msm-modem-uim-selection | 8 +- .../rootfs/etc/init.d/msm-modem-uim-selection | 10 +- .../rootfs/etc/init.d/msm8909-modem-wwan-port | 34 + .../dispatcher.d/50-tethering.sh | 61 + overlay/rootfs/usr/lib/dwm/plugins/modem.so | Bin 132532 -> 132532 bytes .../usr/libexec/msm-modem-uim-selection | 138 +- overlay/rootfs/usr/share/initramfs/init.sh | 84 + .../usr/share/initramfs/init_functions.sh | 1438 +++++++++++++++++ .../sxmo-x11/usr/lib/dwm/plugins/modem.so | Bin 132532 -> 132532 bytes rebuild-image.sh | 1 + src/dwm-plugins/modem_plugin.cpp | 17 +- 11 files changed, 1733 insertions(+), 58 deletions(-) create mode 100755 overlay/rootfs/etc/init.d/msm8909-modem-wwan-port create mode 100755 overlay/rootfs/usr/lib/NetworkManager/dispatcher.d/50-tethering.sh create mode 100755 overlay/rootfs/usr/share/initramfs/init.sh create mode 100755 overlay/rootfs/usr/share/initramfs/init_functions.sh diff --git a/overlay/rootfs/etc/conf.d/msm-modem-uim-selection b/overlay/rootfs/etc/conf.d/msm-modem-uim-selection index de30efc..4e9c4fc 100644 --- a/overlay/rootfs/etc/conf.d/msm-modem-uim-selection +++ b/overlay/rootfs/etc/conf.d/msm-modem-uim-selection @@ -1,9 +1,3 @@ # Maximum time to wait for SIM card to appear after starting the modem. -# Some SIM cards or modem firmwares might take longer to initialize. -# Set to 0 to disable waiting entirely. -sim_wait_time=10 - -# Preferred physical SIM slot (1 or 2) for Primary GW provisioning on Dual-SIM -# Qualcomm MSM8905/MSM8909 devices. Falls back automatically if the preferred -# slot has no SIM card inserted. +sim_wait_time=4 preferred_sim_slot=1 diff --git a/overlay/rootfs/etc/init.d/msm-modem-uim-selection b/overlay/rootfs/etc/init.d/msm-modem-uim-selection index 40b1aec..38a03d3 100755 --- a/overlay/rootfs/etc/init.d/msm-modem-uim-selection +++ b/overlay/rootfs/etc/init.d/msm-modem-uim-selection @@ -1,8 +1,5 @@ #!/sbin/openrc-run -# This script tries to automatically configure UIM application for Qualcomm QMI -# modems with more than one sim slot. - name="UIM Slot selection" description="Select UIM slot and application on the embedded QMI modem." @@ -13,9 +10,8 @@ depend() { before modemmanager } -# Use the service start method instead of command= because we want to block -# other services while the modem isn't ready yet. start() { - SIM_WAIT_TIME="${sim_wait_time:-10}" /usr/libexec/msm-modem-uim-selection boot - eend $? + ebegin "Selecting UIM slot" + SIM_WAIT_TIME="${sim_wait_time:-4}" timeout 15 /usr/libexec/msm-modem-uim-selection boot >/dev/null 2>&1 || true + eend 0 } diff --git a/overlay/rootfs/etc/init.d/msm8909-modem-wwan-port b/overlay/rootfs/etc/init.d/msm8909-modem-wwan-port new file mode 100755 index 0000000..ccb14f6 --- /dev/null +++ b/overlay/rootfs/etc/init.d/msm8909-modem-wwan-port @@ -0,0 +1,34 @@ +#!/sbin/openrc-run + +name="Modem WWAN port" +description="Activate the WWAN port on the embedded QMI modem" + +depend() { + need rmtfs + before ofono + before modemmanager +} + +start() { + ebegin "Activating Modem WWAN port" + if ! [ -x "$(command -v qmicli)" ]; then + eend 0 + return 0 + fi + + QMICLI_MODEM="" + count=0 + while [ -z "$QMICLI_MODEM" ] && [ "$count" -lt 12 ]; do + if timeout 3 qmicli --silent -pd qrtr://0 --uim-noop >/dev/null 2>&1; then + QMICLI_MODEM="timeout 4 qmicli --silent -pd qrtr://0" + break + fi + sleep 1 + count=$((count + 1)) + done + + if [ -n "$QMICLI_MODEM" ]; then + $QMICLI_MODEM --dpm-open-port=hw-data-ep-type=bam-dmux,hw-data-ep-iface-number=1,hw-data-rx-id=1,hw-data-tx-id=1 >/dev/null 2>&1 || true + fi + eend 0 +} diff --git a/overlay/rootfs/usr/lib/NetworkManager/dispatcher.d/50-tethering.sh b/overlay/rootfs/usr/lib/NetworkManager/dispatcher.d/50-tethering.sh new file mode 100755 index 0000000..2968fea --- /dev/null +++ b/overlay/rootfs/usr/lib/NetworkManager/dispatcher.d/50-tethering.sh @@ -0,0 +1,61 @@ +#!/bin/sh +# Handle USB networking and tethering with unudhcpd and NetworkManager +# without unbinding the USB gadget UDC on link up/down events. + +con_uuid="83bd1823-feca-4c2b-9205-4b83dc792e1f" + +[ -f /usr/share/misc/source_deviceinfo ] && . /usr/share/misc/source_deviceinfo +[ -e /etc/unudhcpd.conf ] && . /etc/unudhcpd.conf + +usb_network_function="${deviceinfo_usb_network_function:-ncm.usb0}" +usb_network_function_fallback="rndis.usb0" +disable_dhcpd="${deviceinfo_disable_dhcpd:-false}" +host_ip="${unudhcpd_host_ip:-172.16.42.1}" +client_ip="${unudhcpd_client_ip:-172.16.42.2}" + +CONFIGFS="/sys/kernel/config/usb_gadget" +if ! [ -d "$CONFIGFS" ]; then + mount -t configfs configfs /sys/kernel/config 2>/dev/null || true +fi + +ensure_gadget_bound() { + udc_dev="$(ls /sys/class/udc 2>/dev/null | head -n 1)" + [ -n "$udc_dev" ] || return 0 + if [ -d "$CONFIGFS/g1" ]; then + cur_udc="$(cat "$CONFIGFS/g1/UDC" 2>/dev/null | tr -d '[:space:]')" + if [ -z "$cur_udc" ]; then + echo "$udc_dev" > "$CONFIGFS/g1/UDC" 2>/dev/null || true + fi + fi +} + +ensure_gadget_bound + +interface="$( + cat "$CONFIGFS/g1/functions/$usb_network_function/ifname" 2>/dev/null || + cat "$CONFIGFS/g1/functions/$usb_network_function_fallback/ifname" 2>/dev/null || + echo "usb0" +)" + +if [ -n "$DEVICE_IFACE" ] && [ "$DEVICE_IFACE" != "$interface" ]; then + exit 0 +fi + +ensure_usb_dhcp() { + ip link set "$interface" up 2>/dev/null || true + if ! ip -4 addr show dev "$interface" 2>/dev/null | grep -q "$host_ip"; then + ip addr add "$host_ip/16" dev "$interface" 2>/dev/null || true + fi + if [ "$disable_dhcpd" != "true" ] && ! pidof unudhcpd >/dev/null 2>&1; then + (unudhcpd -i "$interface" -s "$host_ip" -c "$client_ip" >/dev/null 2>&1) & + logger -t nm-tethering "unudhcpd started on $interface ($host_ip -> $client_ip)" + fi +} + +case "${NM_DISPATCHER_ACTION:-up}" in + up|down|reapply) + ensure_gadget_bound + ensure_usb_dhcp + ;; +esac +exit 0 diff --git a/overlay/rootfs/usr/lib/dwm/plugins/modem.so b/overlay/rootfs/usr/lib/dwm/plugins/modem.so index 0c0af48d875c2d60a72b9341a4c7e5e0c4f63616..3b0a83e11d86e3ed095710be02b210ca184adf33 100755 GIT binary patch delta 35981 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�O1^ulrXh6k9;kBT-&7^XN)MD(A4(EcTMeYybz(! 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 WnPhYyYv){-R5-I&k4K5Z0s8-Xh0dV> diff --git a/overlay/rootfs/usr/libexec/msm-modem-uim-selection b/overlay/rootfs/usr/libexec/msm-modem-uim-selection index 7f486c4..8e6c57c 100755 --- a/overlay/rootfs/usr/libexec/msm-modem-uim-selection +++ b/overlay/rootfs/usr/libexec/msm-modem-uim-selection @@ -8,31 +8,80 @@ if [ -r "$CONF_FILE" ]; then . "$CONF_FILE" fi -SIM_WAIT_TIME="${SIM_WAIT_TIME:-${sim_wait_time:-10}}" +SIM_WAIT_TIME="${SIM_WAIT_TIME:-${sim_wait_time:-4}}" PREFERRED_SIM_SLOT="${PREFERRED_SIM_SLOT:-${preferred_sim_slot:-1}}" QMICLI_MODEM="" +ensure_usb_network_gadget() { + CONFIGFS="/sys/kernel/config/usb_gadget" + if ! [ -d "$CONFIGFS" ]; then + modprobe libcomposite 2>/dev/null || true + mount -t configfs configfs /sys/kernel/config 2>/dev/null || true + fi + udc_dev="$(ls /sys/class/udc 2>/dev/null | head -n 1 || true)" + if [ -z "$udc_dev" ]; then + modprobe pm8916-lbc 2>/dev/null || true + w=0 + while [ -z "$udc_dev" ] && [ "$w" -lt 20 ]; do + sleep 0.1 + udc_dev="$(ls /sys/class/udc 2>/dev/null | head -n 1 || true)" + w=$((w + 1)) + done + fi + if [ -d "$CONFIGFS" ] && [ -n "$udc_dev" ]; then + if ! [ -d "$CONFIGFS/g1" ]; then + mkdir -p "$CONFIGFS/g1" 2>/dev/null || true + echo "0x18D1" > "$CONFIGFS/g1/idVendor" 2>/dev/null || true + echo "0xD001" > "$CONFIGFS/g1/idProduct" 2>/dev/null || true + mkdir -p "$CONFIGFS/g1/strings/0x409" 2>/dev/null || true + echo "Nokia" > "$CONFIGFS/g1/strings/0x409/manufacturer" 2>/dev/null || true + echo "Bananarchy" > "$CONFIGFS/g1/strings/0x409/serialnumber" 2>/dev/null || true + echo "Nokia 8110 4G" > "$CONFIGFS/g1/strings/0x409/product" 2>/dev/null || true + func="ncm.usb0" + if ! mkdir -p "$CONFIGFS/g1/functions/$func" 2>/dev/null; then + func="rndis.usb0" + mkdir -p "$CONFIGFS/g1/functions/$func" 2>/dev/null || true + fi + mkdir -p "$CONFIGFS/g1/configs/c.1/strings/0x409" 2>/dev/null || true + echo "USB network" > "$CONFIGFS/g1/configs/c.1/strings/0x409/configuration" 2>/dev/null || true + ln -sf "$CONFIGFS/g1/functions/$func" "$CONFIGFS/g1/configs/c.1/" 2>/dev/null || true + fi + cur_udc="$(cat "$CONFIGFS/g1/UDC" 2>/dev/null | tr -d '[:space:]' || true)" + if [ -z "$cur_udc" ]; then + echo "$udc_dev" > "$CONFIGFS/g1/UDC" 2>/dev/null || true + fi + fi + if ip link show dev usb0 >/dev/null 2>&1; then + ip link set usb0 up 2>/dev/null || true + ip -4 addr show dev usb0 2>/dev/null | grep -q "172.16.42.1" || \ + ip addr add 172.16.42.1/16 dev usb0 2>/dev/null || true + if ! pidof unudhcpd >/dev/null 2>&1; then + (unudhcpd -i usb0 -s 172.16.42.1 -c 172.16.42.2 >/dev/null 2>&1) & + fi + fi +} + detect_qmicli_modem() { if ! command -v qmicli >/dev/null 2>&1; then return 1 fi - if qmicli --silent -pd qrtr://0 --uim-noop >/dev/null 2>&1; then - QMICLI_MODEM="qmicli --silent -pd qrtr://0" + if timeout 3 qmicli --silent -pd qrtr://0 --uim-noop >/dev/null 2>&1; then + QMICLI_MODEM="timeout 4 qmicli --silent -pd qrtr://0" return 0 elif [ -e "/dev/wwan0qmi0" ]; then - if qmicli --silent -pd /dev/wwan0qmi0 --device-open-qmi --uim-noop >/dev/null 2>&1; then - QMICLI_MODEM="qmicli --silent -pd /dev/wwan0qmi0 --device-open-qmi" + if timeout 3 qmicli --silent -pd /dev/wwan0qmi0 --device-open-qmi --uim-noop >/dev/null 2>&1; then + QMICLI_MODEM="timeout 4 qmicli --silent -pd /dev/wwan0qmi0 --device-open-qmi" return 0 - elif qmicli --silent -d /dev/wwan0qmi0 --device-open-qmi --uim-noop >/dev/null 2>&1; then - QMICLI_MODEM="qmicli --silent -d /dev/wwan0qmi0 --device-open-qmi" + elif timeout 3 qmicli --silent -d /dev/wwan0qmi0 --device-open-qmi --uim-noop >/dev/null 2>&1; then + QMICLI_MODEM="timeout 4 qmicli --silent -d /dev/wwan0qmi0 --device-open-qmi" return 0 fi elif [ -e "/dev/modem" ]; then - if qmicli --silent -pd /dev/modem --uim-noop >/dev/null 2>&1; then - QMICLI_MODEM="qmicli --silent -pd /dev/modem" + if timeout 3 qmicli --silent -pd /dev/modem --uim-noop >/dev/null 2>&1; then + QMICLI_MODEM="timeout 4 qmicli --silent -pd /dev/modem" return 0 - elif qmicli --silent -d /dev/modem --uim-noop >/dev/null 2>&1; then - QMICLI_MODEM="qmicli --silent -d /dev/modem" + elif timeout 3 qmicli --silent -d /dev/modem --uim-noop >/dev/null 2>&1; then + QMICLI_MODEM="timeout 4 qmicli --silent -d /dev/modem" return 0 fi fi @@ -40,7 +89,7 @@ detect_qmicli_modem() { } wait_for_qmicli_modem() { - max_wait="${1:-45}" + max_wait="${1:-12}" count=0 while [ "$count" -lt "$max_wait" ]; do if detect_qmicli_modem; then @@ -337,8 +386,6 @@ provision_slot() { return 2 fi - $QMICLI_MODEM --dms-set-operating-mode=online >/dev/null 2>&1 || true - QMI_CARDS="$($QMICLI_MODEM --uim-get-card-status 2>/dev/null || true)" count=0 while : ; do @@ -459,8 +506,8 @@ enable_and_register_modem() { i=0 mm_state="" - while [ "$i" -lt 12 ]; do - mm_state="$(mmcli -m any -K 2>/dev/null | awk -F': ' '/^modem\.generic\.state / {print $2; exit}' || true)" + while [ "$i" -lt 10 ]; do + mm_state="$(timeout 3 mmcli -m any -K 2>/dev/null | awk -F': ' '/^modem\.generic\.state / {print $2; exit}' || true)" if [ -n "$mm_state" ]; then break fi @@ -470,14 +517,14 @@ enable_and_register_modem() { if [ "$mm_state" = "failed" ] || { [ "$force_unlock" = "1" ] && [ "$mm_state" = "locked" ]; }; then if command -v rc-service >/dev/null 2>&1; then - rc-service modemmanager restart >/dev/null 2>&1 || true + timeout 6 rc-service modemmanager restart >/dev/null 2>&1 || true elif command -v systemctl >/dev/null 2>&1; then - systemctl restart ModemManager >/dev/null 2>&1 || true + timeout 6 systemctl restart ModemManager >/dev/null 2>&1 || true fi i=0 mm_state="" - while [ "$i" -lt 12 ]; do - mm_state="$(mmcli -m any -K 2>/dev/null | awk -F': ' '/^modem\.generic\.state / {print $2; exit}' || true)" + while [ "$i" -lt 10 ]; do + mm_state="$(timeout 3 mmcli -m any -K 2>/dev/null | awk -F': ' '/^modem\.generic\.state / {print $2; exit}' || true)" if [ -n "$mm_state" ] && [ "$mm_state" != "failed" ]; then break fi @@ -491,14 +538,14 @@ enable_and_register_modem() { fi i=0 - while [ "$i" -lt 10 ]; do - mm_state="$(mmcli -m any -K 2>/dev/null | awk -F': ' '/^modem\.generic\.state / {print $2; exit}' || true)" + while [ "$i" -lt 8 ]; do + mm_state="$(timeout 3 mmcli -m any -K 2>/dev/null | awk -F': ' '/^modem\.generic\.state / {print $2; exit}' || true)" case "$mm_state" in disabled) - mmcli -m any -e >/dev/null 2>&1 || true + timeout 4 mmcli -m any -e >/dev/null 2>&1 || true ;; enabled) - mmcli -m any --3gpp-register-home >/dev/null 2>&1 || true + timeout 4 mmcli -m any --3gpp-register-home >/dev/null 2>&1 || true break ;; searching|registered|connected|connecting) @@ -512,16 +559,26 @@ enable_and_register_modem() { i=$((i + 1)) done - mmcli -m any --3gpp-register-home >/dev/null 2>&1 || true + timeout 4 mmcli -m any --3gpp-register-home >/dev/null 2>&1 || true if command -v sxmo_hook_statusbar.sh >/dev/null 2>&1; then - DISPLAY="${DISPLAY:-:0}" sxmo_hook_statusbar.sh modem >/dev/null 2>&1 || true + DISPLAY="${DISPLAY:-:0}" timeout 3 sxmo_hook_statusbar.sh modem >/dev/null 2>&1 || true fi } +spawn_enable_and_register() { + s_slot="${1:-$PREFERRED_SIM_SLOT}" + s_force="${2:-0}" + ( + exec >/dev/null 2>&1 &- 4>&- 5>&- 6>&- 7>&- 8>&- 9>&- 2>/dev/null || true + enable_and_register_modem "$s_slot" "$s_force" + ) & +} + cmd="${1:-boot}" case "$cmd" in boot) + ensure_usb_network_gadget if command -v systemd-notify >/dev/null 2>&1; then trap '[ $? -eq 0 ] && systemd-notify --ready' EXIT fi @@ -531,8 +588,7 @@ case "$cmd" in exit 0 ;; esac - provision_slot "$PREFERRED_SIM_SLOT" 45 - ( enable_and_register_modem "$PREFERRED_SIM_SLOT" 0 ) >/dev/null 2>&1 /dev/null 2>&1; then - rc-service modemmanager restart >/dev/null 2>&1 || true + timeout 6 rc-service modemmanager restart >/dev/null 2>&1 || true elif command -v systemctl >/dev/null 2>&1; then - systemctl restart ModemManager >/dev/null 2>&1 || true + timeout 6 systemctl restart ModemManager >/dev/null 2>&1 || true fi - ( enable_and_register_modem "$target" 0 ) >/dev/null 2>&1 /dev/null 2>&1; then + sim_id="$(timeout 3 mmcli -m any 2>/dev/null | grep -oE 'SIM/[0-9]+' | head -n1 | cut -d'/' -f2 || true)" + if [ -n "$sim_id" ] && timeout 4 mmcli -i "$sim_id" --pin="$pin" >/dev/null 2>&1; then verified=1 fi if [ "$verified" = "0" ] && [ -n "$QMICLI_MODEM" ]; then @@ -625,10 +681,10 @@ case "$cmd" in SIM_WAIT_TIME=2 provision_slot "$slot" 3 >/dev/null 2>&1 || true if [ -n "$sim_id" ]; then - mmcli -i "$sim_id" --pin="$pin" >/dev/null 2>&1 || true + timeout 4 mmcli -i "$sim_id" --pin="$pin" >/dev/null 2>&1 || true fi - mmcli -m any -e >/dev/null 2>&1 || true - ( enable_and_register_modem "$slot" 1 ) >/dev/null 2>&1 /dev/null 2>&1 || true + spawn_enable_and_register "$slot" 1 exit 0 fi exit 1 @@ -644,8 +700,8 @@ case "$cmd" in fi prepare_slot_for_pin_op "$slot" unblocked=0 - sim_id="$(mmcli -m any 2>/dev/null | grep -oE 'SIM/[0-9]+' | head -n1 | cut -d'/' -f2 || true)" - if [ -n "$sim_id" ] && mmcli -i "$sim_id" --puk="$puk" --pin="$newpin" >/dev/null 2>&1; then + sim_id="$(timeout 3 mmcli -m any 2>/dev/null | grep -oE 'SIM/[0-9]+' | head -n1 | cut -d'/' -f2 || true)" + if [ -n "$sim_id" ] && timeout 4 mmcli -i "$sim_id" --puk="$puk" --pin="$newpin" >/dev/null 2>&1; then unblocked=1 fi if [ "$unblocked" = "0" ] && [ -n "$QMICLI_MODEM" ]; then @@ -669,8 +725,8 @@ case "$cmd" in save_preferred_slot "$slot" SIM_WAIT_TIME=2 provision_slot "$slot" 3 >/dev/null 2>&1 || true - mmcli -m any -e >/dev/null 2>&1 || true - ( enable_and_register_modem "$slot" 1 ) >/dev/null 2>&1 /dev/null 2>&1 || true + spawn_enable_and_register "$slot" 1 exit 0 fi exit 1 @@ -795,6 +851,7 @@ case "$cmd" in mode="${2:-status}" case "$mode" in on) + ensure_usb_network_gadget sysctl -w net.ipv4.ip_forward=1 >/dev/null 2>&1 || true nft add table ip nat 2>/dev/null || true nft 'add chain ip nat postrouting { type nat hook postrouting priority 100 ; }' 2>/dev/null || true @@ -805,6 +862,7 @@ case "$cmd" in echo "1" > /tmp/bananarchy_usb_tether.active ;; off) + ensure_usb_network_gadget sysctl -w net.ipv4.ip_forward=0 >/dev/null 2>&1 || true nft delete table ip nat 2>/dev/null || true nmcli connection delete USBNetworkShare >/dev/null 2>&1 || true diff --git a/overlay/rootfs/usr/share/initramfs/init.sh b/overlay/rootfs/usr/share/initramfs/init.sh new file mode 100755 index 0000000..ec04621 --- /dev/null +++ b/overlay/rootfs/usr/share/initramfs/init.sh @@ -0,0 +1,84 @@ +#!/bin/busybox ash +# shellcheck disable=SC1091 + +# Export all variables so they're available in /init_2nd.sh +set -a + +IN_CI="false" +LOG_PREFIX="[pmOS-rd]" + +# Handle halt/poweroff/reboot +# Signals from busybox/halt.c +trap 'halt -f' USR1 +trap 'poweroff -f' USR2 +trap 'reboot -f' TERM + +[ -e /hooks/10-verbose-initfs.sh ] && set -x + +[ -e /hooks/05-ci.sh ] && IN_CI="true" + +[ -e /etc/unudhcpd.conf ] && . /etc/unudhcpd.conf +. ./init_functions.sh +. /usr/share/misc/source_deviceinfo +[ -e /etc/os-release ] && . /etc/os-release +# provide a default for os-release's VERSION in case the file doesn't exist +VERSION="${VERSION:-unknown}" + +# This is set during packaging and is used when triaging bug reports +INITRAMFS_PKG_VERSION="3.11.0-r1" + +export PATH=/usr/bin:/bin:/usr/sbin:/sbin +/bin/busybox --install -s +/bin/busybox-extras --install -s + +# Mount everything, set up logging, modules, mdev +mount_proc_sys_dev +parse_cmdline < /proc/cmdline +setup_log +echo " ❬❬ PMOS STAGE 1 ❭❭" +echo "initramfs version: $INITRAMFS_PKG_VERSION" +setup_firmware_path + +load_modules /usr/lib/modules/initramfs.load +load_modules /lib/modules/initramfs.load + +# Jump straight to the 2nd stage init if available +# (no separate -extra) or no-op otherwise +jump_init_2nd + +echo "Loading initramfs-extra..." + +# We need mdev to find the boot partition +setup_mdev + +load_modules /lib/modules/initramfs.load + +setup_usb_network +start_unudhcpd + +if [ "$IN_CI" = "false" ]; then + setup_framebuffer +fi + +# Discover the partitions if they're "subpartitions" +# (where the whole disk image is flashed to a partition) +mount_subpartitions + +# Poll for the boot partition to become available or crash +wait_boot_partition +mount_boot_partition /boot +extract_initramfs_extra /boot/initramfs-extra +# /boot is mounted later into the rootfs +umount /boot + +# Kill mdev, since it's replaced by udev in the +# second stage init +kill mdev 2>/dev/null + +# Now we can jump to the 2nd stage init +jump_init_2nd + +# Somehow init_2nd.sh is missing +echo "$LOG_PREFIX ERROR: /init_2nd.sh not found!" +echo "$LOG_PREFIX For more information, see " +fail_halt_boot diff --git a/overlay/rootfs/usr/share/initramfs/init_functions.sh b/overlay/rootfs/usr/share/initramfs/init_functions.sh new file mode 100755 index 0000000..546288c --- /dev/null +++ b/overlay/rootfs/usr/share/initramfs/init_functions.sh @@ -0,0 +1,1438 @@ +#!/bin/busybox ash +# This file will be in /init_functions.sh inside the initramfs. + +# NOTE!!! The file is sourced again in init_2nd.sh, avoid +# clobbering variables by not setting them if they have +# a value already! +PMOS_BOOT="${PMOS_BOOT:-}" +PMOS_ROOT="${PMOS_ROOT:-}" +SUBPARTITION_DEV="${SUBPARTITION_DEV:-}" +SUBPARTITION_LOOP="${SUBPARTITION_LOOP:-}" + +CONFIGFS="/sys/kernel/config/usb_gadget" +CONFIGFS_ACM_FUNCTION="acm.usb0" +CONFIGFS_MASS_STORAGE_FUNCTION="mass_storage.0" +HOST_IP="${unudhcpd_host_ip:-172.16.42.1}" + +deviceinfo_getty="${deviceinfo_getty:-}" +deviceinfo_name="${deviceinfo_name:-}" +deviceinfo_codename="${deviceinfo_codename:-}" +deviceinfo_create_initfs_extra="${deviceinfo_create_initfs_extra:-}" +deviceinfo_no_framebuffer="${deviceinfo_no_framebuffer:-}" +deviceinfo_rootfs_image_sector_size="${deviceinfo_rootfs_image_sector_size:-}" + +# Default to no splash unless set on the kernel cmdline. Plymouth will not +# display a splash if this param is missing from the cmdline +nosplash="${nosplash:-y}" + +# Does word start with prefix? +startswith() { + local word="$1" prefix="$2" + + case "$word" in + $prefix*) + return 0 + ;; + esac + + return 1 +} + +# Does word end with suffix? +endswith() { + local word="$1" suffix="$2" + + case "$word" in + *$suffix) + return 0 + ;; + esac + + return 1 +} + +# Parse individual items from the cmdline and take appropriate +# action (e.g. set variables). +parse_cmdline_item() { + local key="$1" value="$2" + + # For information on what each cmdline argument does, please refer + # to https://wiki.postmarketos.org/wiki/Initramfs#Kernel_cmdline + case "$key" in + pmos.boot | pmos_boot) + boot_path="$value" + ;; + pmos.boot_uuid | pmos_boot_uuid) + boot_uuid="$value" + ;; + pmos.bootchart2 | PMOS_BOOTCHART2) + bootchart2=y + ;; + pmos.debug-shell) + # used by init_2nd.sh + # shellcheck disable=SC2034 + debug_shell=y + ;; + pmos.force-partition-resize | PMOS_FORCE_PARTITION_RESIZE) + # used by init_functions_2nd.sh which is sourced + # after this script. + # shellcheck disable=SC2034 + force_partition_resize=y + ;; + splash) + nosplash=n + ;; + pmos.root | pmos_root) + root_path="$value" + ;; + pmos.root_uuid | pmos_root_uuid) + root_uuid="$value" + ;; + pmos.rootfsopts | pmos_rootfsopts) + # Prepend a comma since this will be appended to + # "rw" when passed to mount + rootfsopts=",$value" + ;; + pmos.stowaway) + stowaway=y + ;; + pmos.usb-storage) + usb_storage="$value" + ;; + rd.info) + # used by init_functions_2nd.sh which is sourced + # after this script. + # shellcheck disable=SC2034 + log_info=y + ;; + [![:alpha:]_]* | [[:alpha:]_]*[![:alnum:]_]*) + # invalid shell variable, ignore it + ;; + *) + # valid shell variable + # ignore these since we get all kinds of weird + # arguments from quirky bootloaders and we really + # don't want to deal with that here. Add options + # explicitly above instead. + ;; + esac +} + +process_cmdline_param() { + # $1: key (the cmdline parameter) + # $2: value (after the =) + local key="$1" value="$2" + + # maybe unquote the value + # busybox ash supports string indexing + # shellcheck disable=SC3057 + if startswith "$value" "[\"']" && endswith "$value" "${value:0:1}"; then + value="${value#?}" value="${value%?}" + fi + + parse_cmdline_item "$key" "$value" +} + +# Parse the kernel cmdline and configure the environment +parse_cmdline() { + local cmdline word quoted key value + + # Disable globbing so we don't accidentally expand + # cmdline options into paths + set -f + read -r cmdline + # shellcheck disable=SC2086 + set -- $cmdline + set +f + + # Walk over each cmdline argument + for word; do + # Handle quoted values + if [ -n "$quoted" ]; then + value="$value $word" + else + case "$word" in + # Easy case: key=value + *=*) + key="${word%%=*}" + value="${word#*=}" + + if startswith "$value" "[\"']"; then + # busybox ash supports string indexing + # shellcheck disable=SC3057 + quoted="${value:0:1}" + fi + ;; + # A comment (only used for unit tests) + '#'*) + break + ;; + # A key without a value + *) + key="$word" + ;; + esac + fi + + # If inside a quoted string, check if $value contains the closing quote + if [ -n "$quoted" ]; then + if endswith "$value" "$quoted"; then + unset quoted + else + # Otherwise continue reading words + continue + fi + fi + + process_cmdline_param "$key" "$value" + unset key value + done + + if [ -n "$key" ]; then + process_cmdline_param "$key" "$value" + fi + + # Also set some options from deviceinfo variables + + if [ "$deviceinfo_no_framebuffer" = "true" ]; then + nosplash=y + fi +} + +# Redirect stdout/stderr to the log file, as well as to the kernel via +# syslog. Additionally, if nosplash is set and there are no active +# consoles, try to be helpful by logging to tty0 and the devices serial +# port. +setup_log() { + local console + local log_targets + console="$(cat /sys/devices/virtual/tty/console/active)" + log_targets="/pmOS_init.log" + + # If we have an active console, the kernel will be logging there. + if [ -n "$console" ] ; then + exec 3>&1 4>&2 + else + # Setting console=null is a trick used on quite a few pmOS devices. However it is generally a really + # bad idea since it makes it impossible to debug kernel panics, and it makes our job logging in the + # initramfs a lot harder. We ban this in pmaports but some (usually android) bootloaders like to add it + # anyway. We ought to have some special handling here to use /dev/zero for stdin instead + # to avoid weird bugs in daemons that read from stdin (e.g. syslog) + # See related: https://gitlab.postmarketos.org/postmarketOS/pmaports/-/issues/2989 + console="/dev/$(echo "$deviceinfo_getty" | cut -d';' -f1)" + if [ -e "$console" ]; then + log_targets="$log_targets $console" + fi + + # If nosplash is set but there's no active console, let's try to be helpful by at least + # logging the initramfs output to the consoles we can find. + # TODO: This could be further improved by reading /dev/kmsg and outputting it as well which + # might help with debugging on bootloaders that do force console=null + if [ "$nosplash" = "y" ]; then + echo "Splash is disabled but no consoles are active, trying to log somewhere useful!" \ + | tee "$console" > /dev/tty0 + # Log to tty0 as well as the serial port we may have found above + log_targets="$log_targets /dev/tty0" + fi + fi + + # Disable kmsg ratelimiting for userspace (it gets re-enabled again before switch_root) + echo on > /proc/sys/kernel/printk_devkmsg + + # Spawn syslogd to log to the kernel + # syslog will try to read from stdin over and over which can pin a cpu when stdin is /dev/null + # By connecting /dev/zero to stdin/stdout/stderr, we make sure that syslogd + # isn't blocked when a console isn't available. + syslogd -K < /dev/zero >/dev/zero 2>&1 + + # Log to ramoops as well + if [ -e "/dev/pmsg0" ]; then + log_targets="$log_targets /dev/pmsg0" + fi + + # Redirect to a subshell which outputs to the logfile as well + # as to the kernel ringbuffer and pstore (if available). + # Process substitution is technically non-POSIX, but is supported by busybox + # We are intentionally word-splitting $log_targets into multiple arguments. + # shellcheck disable=SC3001,SC2086 + exec > >(tee $log_targets | logger -t "$LOG_PREFIX" -p user.info) 2>&1 +} + +info() { + if [ "$log_info" != "y" ]; then + return + fi + + echo "$@" +} + +mount_proc_sys_dev() { + # mdev + mount -t proc -o nodev,noexec,nosuid proc /proc || echo "Couldn't mount /proc" + mount -t sysfs -o nodev,noexec,nosuid sysfs /sys || echo "Couldn't mount /sys" + mount -t devtmpfs -o mode=0755,nosuid dev /dev || echo "Couldn't mount /dev" + mount -t tmpfs -o nosuid,nodev,mode=0755 run /run || echo "Couldn't mount /run" + + modprobe libcomposite 2>/dev/null || true + mount -t configfs -o nodev,noexec,nosuid configfs "$(dirname "$CONFIGFS")" + + # /dev/pts (needed for telnet) + mkdir -p /dev/pts + mount -t devpts devpts /dev/pts + + # This is required for process substitution to work (as used in setup_log()) + ln -s /proc/self/fd /dev/fd +} + +setup_firmware_path() { + # Add the postmarketOS-specific path to the firmware search paths. + # This should be sufficient on kernel 3.10+, before that we need + # the kernel calling udev (and in our case /usr/lib/firmwareload.sh) + # to load the firmware for the kernel. + local sysfs_dir + sysfs_dir=/sys/module/firmware_class/parameters/path + if ! [ -e "$sysfs_dir" ]; then + echo "Kernel does not support setting the firmware image search path. Skipping." + return + fi + # shellcheck disable=SC3037 + echo -n /lib/firmware/postmarketos >$sysfs_dir +} + +# shellcheck disable=SC3043 +load_modules() { + local file="$1" + local modules="$2" + [ -f "$file" ] && modules="$modules $(grep -v ^\# "$file")" + + if [ -z "$modules" ]; then + return + fi + # shellcheck disable=SC2086 + modprobe -a $modules +} + +setup_mdev() { + # Start mdev daemon + mdev -d +} + +jump_init_2nd() { + if ! [ -e /init_2nd.sh ]; then + return + fi + + echo " ❬❬ PMOS STAGE 2 ❭❭" + exec /init_2nd.sh +} + +get_uptime_seconds() { + # Get the current system uptime in seconds - ignore the two decimal places. + awk -F '.' '{print $1}' /proc/uptime +} + +setup_dynamic_partitions() { + command -v make-dynpart-mappings > /dev/null || return + attempt_start=$(get_uptime_seconds) + wait_seconds=10 + slot_number=0 + for super_partition in $1; do + # Wait for mdev + echo "Waiting for super partition $super_partition..." + while [ ! -b "$super_partition" ]; do + if [ "$(get_uptime_seconds)" -ge $(( attempt_start + wait_seconds )) ]; then + echo "ERROR: Super partition $super_partition failed to show up!" + return; + fi + sleep 0.1 + done + make-dynpart-mappings "$super_partition" "$slot_number" + slot_number=$(( slot_number + 1 )) + done +} + +mount_subpartitions() { + # skip if ran already (unmerged -extra) + if [ -n "$PMOS_ROOT" ] && [ -n "$PMOS_BOOT" ]; then + return + fi + try_parts="/dev/disk/by-partlabel/userdata /dev/disk/by-partlabel/system* /dev/mapper/system*" + android_parts="" + for x in $try_parts; do + [ -e "$x" ] && android_parts="$android_parts $x" + done + + local losetup_args="--show -Pf --direct-io=on" + if [ -n "$deviceinfo_rootfs_image_sector_size" ]; then + losetup_args="$losetup_args --sector-size $deviceinfo_rootfs_image_sector_size" + fi + attempt_start=$(get_uptime_seconds) + wait_seconds=10 + echo "Trying to mount subpartitions for $wait_seconds seconds..." + + # Subpartition init uses losetup, so make sure the loop module is loaded. + modprobe loop 2>/dev/null || true + + find_root_partition + while [ -z "$PMOS_ROOT" ]; do + partitions="$android_parts $(grep -v "loop\|ram" < /proc/diskstats |\ + sed 's/\(\s\+[0-9]\+\)\+\s\+//;s/ .*//;s/^/\/dev\//')" + for partition in $partitions; do + # Skip whole disks - only check partitions and logical device-mapper devices for subpartitions + [ -e "/sys/class/block/$(basename "$partition")/partition" ] || [ -d "/sys/class/block/$(basename "$partition")/dm" ] || continue + # Count subpartitions and only attempt to probe deeper if there are an expected + # number of them present on the partition. This prevents us from calling losetup + # (and then cleanup) on every single partition on the device + # + # Subpartitions, if there are any, are counted with fdisk because there doesn't + # seem to be a better way to do this without adding more dependencies to the 1st + # stage initramfs. fdisk's output differs if it's reading a GPT or MBR partition + # table, so this regex needs to account for both, e.g.: + # GPT: + # 1 2048 499711 243M primary + # MBR: + # /dev/mmcblk0p62p1 * 4,4,1 979,210,2 2048 499711 97664 243M 83 Linux + local part_count + part_count="$(fdisk -l "$partition" 2>/dev/null | grep -cE '^ +[0-9]|^'"$partition")" + # It's probably the right "disk" if it has 2 partitions on it. + if [ "$part_count" -eq 2 ]; then + echo "Mount subpartitions of $partition" + SUBPARTITION_DEV="$partition" + # shellcheck disable=SC2086 + SUBPARTITION_LOOP="$(losetup $losetup_args "$partition")" + if [ -z "$SUBPARTITION_LOOP" ]; then + echo "WARNING: failed to create loop device for $partition" + SUBPARTITION_DEV="" + continue + fi + # Ensure that this was the *correct* subpartition + # Some devices have mmc partitions that appear to have + # subpartitions, but aren't our subpartition. + find_root_partition + if [ -n "$PMOS_ROOT" ]; then + break + fi + [ -n "$SUBPARTITION_LOOP" ] && losetup -d "$SUBPARTITION_LOOP" + SUBPARTITION_DEV="" + SUBPARTITION_LOOP="" + fi + done + if [ "$(get_uptime_seconds)" -ge $(( attempt_start + wait_seconds )) ]; then + echo "ERROR: failed to mount subpartitions!" + return; + fi + sleep 0.1; + # Check if partition appeared without needing subpartitions + find_root_partition + done +} + +# Rewrite /dev/dm-X paths to /dev/mapper/... +pretty_dm_path() { + dm="$1" + n="${dm#/dev/dm-}" + + # If the substitution didn't do anything, then we're done + [ "$n" = "$dm" ] && echo "$dm" && return + + # Get the name of the device mapper device + name="/dev/mapper/$(cat "/sys/class/block/dm-${n}/dm/name")" + echo "$name" +} + +# Prints the path to the partition if found, or nothing. +find_partition() { + # $1: UUID of partition if known + # $2: path to partition + # $3: label of partition + # $4: additional blkid token to check (e.g TYPE=crypto_LUKS) + + local uuid="$1" + local path="$2" + local label="$3" + local extra="$4" + local partition + + if [ -n "$uuid" ]; then + partition="$(blkid --uuid "$uuid")" + if [ -z "$partition" ]; then + # Don't fall back to anything if the given UUID wasn't + # found, it might show up later but if not we should + # error out. + return + fi + fi + + if [ -z "$partition" ]; then + if [ -e "$path" ]; then + partition="$path" + elif [ -n "$path" ]; then + # Don't fall back to anything if the given path wasn't + # found, it might show up later but if not we should + # error out. + return + fi + fi + + if [ -z "$partition" ]; then + partition="$(blkid --label "$label")" + fi + + if [ -z "$partition" ] && [ -n "$extra" ]; then + # check for arbitrary blkid tag + partition="$(blkid --match-token "$extra" | cut -d ":" -f 1 | head -n 1)" + fi + + # prettify e.g. /dev/dm-0 to /dev/mapper/userdata1 + pretty_dm_path "$partition" +} + +find_root_partition() { + # $1: variable to set result to + local result + result=$1 + + # The partition layout is one of the following: + # a) boot, root partitions on sdcard + # b) boot, root partition on the "system" partition (which has its + # own partition header! so we have partitions on partitions!) + # + # mount_subpartitions() must get executed before calling + # find_root_partition(), so partitions from b) also get found. + if [ -z "$PMOS_ROOT" ]; then + PMOS_ROOT="$(find_partition "$root_uuid" "$root_path" "pmOS_root" "TYPE=crypto_LUKS")" + fi + + # Set the result, since using a subshell prevents us from caching + if [ -n "$result" ]; then eval "$result=\"$PMOS_ROOT\""; fi +} + +find_boot_partition() { + # $1: variable to set result to + local result + result=$1 + + if [ -z "$PMOS_BOOT" ]; then + # Before doing anything else check if we are using a stowaway + if [ "$stowaway" = "y" ]; then + mount_root_partition + PMOS_BOOT="/sysroot/boot" + mount --bind /sysroot/boot /boot + else + PMOS_BOOT="$(find_partition "$boot_uuid" "$boot_path" "pmOS_boot")" + fi + fi + + # Set the result, since using a subshell prevents us from caching + if [ -n "$result" ]; then eval "$result=\"$PMOS_BOOT\""; fi +} + +get_partition_type() { + local partition + partition="$1" + blkid "$partition" | sed 's/^.*\ TYPE="\([a-zA-Z0-9_]*\)".*$/\1/' +} + +get_mounted_filesystem_type() { + awk -v mountpoint="$1" '$2 == mountpoint {print $3}' /proc/mounts +} + +# $1: partition +check_filesystem() { + local partition="" + local status="" + local type="" + + partition="$1" + type="$(get_partition_type "$partition")" + # btrfs check is not included in that list on purpose. it takes too much time + # (as in: multiple minutes) and gets even slower the more the partition is used + case "$type" in + ext*) + echo "Auto-repair and check 'ext' filesystem ($partition)" + e2fsck -p "$partition" + if [ $? -ge 4 ]; then + status="fail" + fi + ;; + f2fs) + echo "Auto-repair and check 'f2fs' filesystem ($partition)" + fsck.f2fs -p "$partition" + status=$? + if [ $? -gt 4 ]; then + status="fail" + fi + ;; + vfat) + echo "Auto-repair and check 'vfat' filesystem ($partition)" + fsck.vfat -p "$partition" + if [ $? -gt 4 ]; then + status="fail" + fi + ;; + xfs) + echo "Auto-repair and check 'xfs' filesystem ($partition)" + fsck.xfs -p "$partition" + if [ $? -gt 4 ]; then + status="fail" + fi + ;; + *) echo "WARNING: fsck not supported for '$type' filesystem ($partition)." ;; + esac + + if [ "$status" = "fail" ]; then + splash_set_warning "Filesystem needs manual repair (fsck) ($partition)\nhttps://postmarketos.org/troubleshooting\n\nBoot anyways by pressing Volume-Up or Left-Shift..." + while ! iskey KEY_LEFTSHIFT KEY_VOLUMEUP ; do + : + done + fi + + splash_set_message "Loading" +} + +# $1: path +# $2: set to "rw" for read-write +# Mount the boot partition. It gets mounted twice, first at /boot (ro), then at +# /sysroot/boot (rw), after root has been mounted at /sysroot, so we can +# switch_root to /sysroot and have the boot partition properly mounted. +mount_boot_partition() { + local partition + local mount_opts + + find_boot_partition partition + mount_opts="-o nodev,nosuid,noexec" + + # We dont need to do this when using stowaways + if [ "$stowaway" = "y" ]; then + return + fi + + if [ "$2" = "rw" ]; then + check_filesystem "$partition" + echo "Mount boot partition ($partition) to $1 (read-write)" + else + mount_opts="$mount_opts,ro" + echo "Mount boot partition ($partition) to $1 (read-only)" + fi + + type="$(get_partition_type "$partition")" + case "$type" in + ext*) + modprobe ext4 + # ext2 might be handled by the ext2 or ext4 kernel module + # so let mount detect that automatically by omitting -t + ;; + xfs) + modprobe xfs + ;; + vfat) + modprobe vfat + mount_opts="-t vfat $mount_opts,umask=0077,nosymfollow,codepage=437,iocharset=ascii" + ;; + *) echo "WARNING: Detected unsupported '$type' filesystem ($partition)." ;; + esac + + # shellcheck disable=SC2086 + mount $mount_opts "$partition" "$1" +} + +# $1: initramfs-extra path +extract_initramfs_extra() { + local initramfs_extra + initramfs_extra="$1" + if [ ! -e "$initramfs_extra" ]; then + echo "ERROR: initramfs-extra not found!" + splash_set_error "initramfs-extra not found\nhttps://postmarketos.org/troubleshooting" + fail_halt_boot + fi + echo "Extract $initramfs_extra" + # uncompressed: + # cpio -di < "$initramfs_extra" + gzip -d -c "$initramfs_extra" | cpio -iu +} + +wait_partition() { + local description findfunc partition + description="$1" + findfunc="$2" + + $findfunc partition + if [ -n "$partition" ]; then + return + fi + + splash_set_message "Waiting for $description partition" + for _ in $(seq 1 30); do + sleep 1 + $findfunc partition + if [ -n "$partition" ]; then + return + fi + check_keys "" + done + + splash_set_error "$description partition not found!\nhttps://postmarketos.org/troubleshooting" + fail_halt_boot +} + +wait_boot_partition() { + wait_partition "boot" "find_boot_partition" +} + +wait_root_partition() { + wait_partition "root" "find_root_partition" +} + +delete_old_install_partition() { + local partition + # The on-device installer leaves a "pmOS_deleteme" (p3) partition after + # successful installation, located after "pmOS_root" (p2). Delete it, + # so we can use the space. + + # We definitely found the partition by this point so no need to call + # find_root_partition + partition="$(echo "$PMOS_ROOT" | sed 's/2$/3/')" + if ! blkid "$partition" | grep -q pmOS_deleteme; then + return + fi + + device="$(echo "$partition" | sed -E 's/p?3$//')" + echo "First boot after running on-device installer - deleting old" \ + "install partition: $partition" + parted -s "$device" rm 3 +} + +# $1: path to device +has_unallocated_space() { + # Check if there is unallocated space at the end of the device + parted -s "$1" print free | tail -n2 | \ + head -n1 | grep -qi "free space" +} + +mount_root_partition() { + # Don't mount root if it is already mounted + if mountpoint -q /sysroot; then + return + fi + + local partition + + find_root_partition partition + + echo "Mount root partition ($partition) to /sysroot (read-write) with options ${rootfsopts#,}" + type="$(get_partition_type "$partition")" + info "Detected $type filesystem" + + case "$type" in + btrfs|ext4|f2fs|xfs) + ;; + *) + echo "ERROR: Detected unsupported '$type' filesystem ($partition)." + splash_set_error "Unsupported '$type' filesystem ($partition)\nhttps://postmarketos.org/troubleshooting" + fail_halt_boot + ;; + esac + + if ! modprobe "$type"; then + info "Unable to load module '$type' - assuming it's built-in" + fi + + # btrfs may be using multiple backing block devices, scan for the rest of them + if [ "$type" = "btrfs" ]; then + btrfs device scan + fi + + if ! mount -t "$type" -o rw"$rootfsopts" "$partition" /sysroot; then + echo "ERROR: unable to mount root partition!" + splash_set_error "Unable to mount root partition\nhttps://postmarketos.org/troubleshooting" + fail_halt_boot + fi + + if [ -e /sysroot/.stowaways/pmos/etc/os-release ]; then + umount /sysroot + + mkdir /stowaway + mount -t "$type" -o rw"$rootfsopts" "$partition" /stowaway + mount --bind /stowaway/.stowaways/pmos/ /sysroot + fi + + if ! [ -e /sysroot/etc/os-release ]; then + splash_set_error "Root partition does not contain a root filesystem\nhttps://postmarketos.org/troubleshooting" + fail_halt_boot + fi +} + +# $1: path to the hooks dir +run_hooks() { + local scriptsdir + local hook + scriptsdir="$1" + + if [ -z "$(ls -A "$scriptsdir" 2>/dev/null)" ]; then + return + fi + + for hook in "$scriptsdir"/*.sh; do + info "Running initramfs hook: $hook" + sh "$hook" + done +} + +setup_usb_network_android() { + local sysfs_dir + # Only run, when we have the android usb driver + sysfs_dir=/sys/class/android_usb/android0 + if ! [ -e "$sysfs_dir" ]; then + return + fi + + info " Setting up USB gadget through android_usb" + + usb_idVendor="$(echo "${deviceinfo_usb_idVendor:-0x18D1}" | sed "s/0x//g")" # default: Google Inc. + usb_idProduct="$(echo "${deviceinfo_usb_idProduct:-0xD001}" | sed "s/0x//g")" # default: Nexus 4 (fastboot) + + # Do the setup + echo "0" >"$sysfs_dir/enable" + echo "$usb_idVendor" >"$sysfs_dir/idVendor" + echo "$usb_idProduct" >"$sysfs_dir/idProduct" + echo "rndis" >"$sysfs_dir/functions" + echo "1" >"$sysfs_dir/enable" +} + +get_usb_udc() { + local _udc_dev="${deviceinfo_usb_network_udc:-}" + if [ -z "$_udc_dev" ]; then + # shellcheck disable=SC2012 + _udc_dev=$(ls /sys/class/udc 2>/dev/null | head -1) + fi + if [ -z "$_udc_dev" ]; then + modprobe pm8916-lbc 2>/dev/null || true + local _wait=0 + while [ -z "$_udc_dev" ] && [ "$_wait" -lt 30 ]; do + sleep 0.1 + # shellcheck disable=SC2012 + _udc_dev=$(ls /sys/class/udc 2>/dev/null | head -1) + _wait=$((_wait + 1)) + done + fi + + echo "$_udc_dev" +} + +setup_usb_configfs_udc() { + # Check if there's an USB Device Controller + local _udc_dev + _udc_dev="$(get_usb_udc)" + + # Remove any existing UDC to avoid "write error: Resource busy" when setting UDC again + if [ "$(wc -w <$CONFIGFS/g1/UDC)" -gt 0 ]; then + echo "" > "$CONFIGFS"/g1/UDC || echo " Couldn't write to clear UDC" + fi + # Link the gadget instance to an USB Device Controller. This activates the gadget. + # See also: https://gitlab.postmarketos.org/postmarketOS/pmbootstrap/issues/338 + echo "$_udc_dev" > "$CONFIGFS"/g1/UDC || echo " Couldn't write new UDC" +} + +# $1: if set, skip writing to the UDC +setup_usb_network_configfs() { + # See: https://www.kernel.org/doc/Documentation/usb/gadget_configfs.txt + local skip_udc="$1" + + if ! [ -e "$CONFIGFS" ]; then + info "usb_gadget not found in configfs, skipping gadget setup..." + return + fi + + if [ -z "$(get_usb_udc)" ]; then + info "No UDC found, skipping gadget setup..." + return + fi + + # Default values for USB-related deviceinfo variables + usb_idVendor="${deviceinfo_usb_idVendor:-0x18D1}" # default: Google Inc. + usb_idProduct="${deviceinfo_usb_idProduct:-0xD001}" # default: Nexus 4 (fastboot) + usb_serialnumber="${deviceinfo_usb_serialnumber:-postmarketOS}" + usb_network_function="${deviceinfo_usb_network_function:-ncm.usb0}" + usb_network_function_fallback="rndis.usb0" + usb_network_host_addr="${deviceinfo_usb_network_host_addr:-}" + + echo " Setting up USB gadget through configfs" + # Create an usb gadet configuration + mkdir $CONFIGFS/g1 || echo " Couldn't create $CONFIGFS/g1" + echo "$usb_idVendor" > "$CONFIGFS/g1/idVendor" + echo "$usb_idProduct" > "$CONFIGFS/g1/idProduct" + + # Create english (0x409) strings + mkdir $CONFIGFS/g1/strings/0x409 || echo " Couldn't create $CONFIGFS/g1/strings/0x409" + + # shellcheck disable=SC2154 + echo "$deviceinfo_manufacturer" > "$CONFIGFS/g1/strings/0x409/manufacturer" + echo "$usb_serialnumber" > "$CONFIGFS/g1/strings/0x409/serialnumber" + # shellcheck disable=SC2154 + echo "$deviceinfo_name" > "$CONFIGFS/g1/strings/0x409/product" + + # Create network function. + if ! mkdir $CONFIGFS/g1/functions/"$usb_network_function"; then + # Try the fallback function next + if mkdir $CONFIGFS/g1/functions/"$usb_network_function_fallback"; then + usb_network_function="$usb_network_function_fallback" + fi + fi + + # Create configuration instance for the gadget + mkdir $CONFIGFS/g1/configs/c.1 \ + || echo " Couldn't create $CONFIGFS/g1/configs/c.1" + mkdir $CONFIGFS/g1/configs/c.1/strings/0x409 \ + || echo " Couldn't create $CONFIGFS/g1/configs/c.1/strings/0x409" + echo "USB network" > $CONFIGFS/g1/configs/c.1/strings/0x409/configuration \ + || echo " Couldn't write configration name" + if [ -n "$usb_network_host_addr" ]; then + echo "$usb_network_host_addr" > $CONFIGFS/g1/functions/"$usb_network_function"/host_addr \ + || echo " Couldn't write host addr" + fi + + + # Link the network instance to the configuration + ln -s $CONFIGFS/g1/functions/"$usb_network_function" $CONFIGFS/g1/configs/c.1 \ + || echo " Couldn't symlink $usb_network_function" + + # If an argument was supplied then skip writing to the UDC (only used for mass storage + # log recovery) + if [ -z "$skip_udc" ]; then + setup_usb_configfs_udc + fi +} + +setup_usb_network() { + # Only run once + _marker="/tmp/_setup_usb_network" + [ -e "$_marker" ] && return + touch "$_marker" + info "Setup usb network" + # Run all usb network setup functions (add more below!) + setup_usb_network_android + setup_usb_network_configfs +} + +start_unudhcpd() { + # Only run once + [ "$(pidof unudhcpd)" ] && return + + local usb_iface + + # Skip if disabled + # shellcheck disable=SC2154 + if [ "$deviceinfo_disable_dhcpd" = "true" ]; then + return + fi + + local client_ip="${unudhcpd_client_ip:-172.16.42.2}" + info "Starting unudhcpd with server ip $HOST_IP, client ip: $client_ip" + + # Get usb interface + usb_network_function="${deviceinfo_usb_network_function:-ncm.usb0}" + usb_network_function_fallback="rndis.usb0" + if [ -n "$(cat $CONFIGFS/g1/UDC)" ]; then + usb_iface="$( + cat "$CONFIGFS/g1/functions/$usb_network_function/ifname" 2>/dev/null || + cat "$CONFIGFS/g1/functions/$usb_network_function_fallback/ifname" 2>/dev/null || + echo '' + )" + else + usb_iface="" + fi + if [ -n "$usb_iface" ]; then + ifconfig "$usb_iface" "$HOST_IP" + elif ifconfig rndis0 "$HOST_IP" 2>/dev/null; then + usb_iface=rndis0 + elif ifconfig usb0 "$HOST_IP" 2>/dev/null; then + usb_iface=usb0 + elif ifconfig eth0 "$HOST_IP" 2>/dev/null; then + usb_iface=eth0 + fi + + if [ -z "$usb_iface" ]; then + echo " Could not find an interface to run a dhcp server on" + echo " Interfaces:" + ip link + return + fi + + info " Using interface $usb_iface" + info " Starting the DHCP daemon" + ( + unudhcpd -i "$usb_iface" -s "$HOST_IP" -c "$client_ip" + ) & +} + +setup_usb_acm_configfs() { + local active_udc + active_udc="$(cat $CONFIGFS/g1/UDC)" + + if ! [ -e "$CONFIGFS" ]; then + echo " $CONFIGFS does not exist, can't set up serial gadget" + return 1 + fi + + # unset UDC + echo "" > $CONFIGFS/g1/UDC + + # Create acm function + mkdir "$CONFIGFS/g1/functions/$CONFIGFS_ACM_FUNCTION" \ + || echo " Couldn't create $CONFIGFS/g1/functions/$CONFIGFS_ACM_FUNCTION" + + # Link the acm function to the configuration + ln -s "$CONFIGFS/g1/functions/$CONFIGFS_ACM_FUNCTION" "$CONFIGFS/g1/configs/c.1" \ + || echo " Couldn't symlink $CONFIGFS_ACM_FUNCTION" + + return 0 +} + +# Spawn a subshell to restart the getty if it exits +# $1: tty +run_getty() { + { + # Due to how the Linux host ACM driver works, we need to wait + # for data to be sent from the host before spawning the getty. + # Otherwise our README message will be echo'd back all garbled. + # On Linux in particular, there is a hack we can use: by writing + # something to the port, it will be echo'd back at the moment the + # port on the host side is opened, so user input won't even be + # needed in most cases. For more info see the blog posts at: + # https://michael.stapelberg.ch/posts/2021-04-27-linux-usb-virtual-serial-cdc-acm/ + # https://connolly.tech/posts/2024_04_15-broken-connections/ + if [ "$1" = "ttyGS0" ]; then + echo " " > /dev/ttyGS0 + # shellcheck disable=SC3061 + read -r < /dev/ttyGS0 + fi + while /sbin/getty -n -l /sbin/pmos_getty "$1" 115200 vt100; do + sleep 0.2 + done + } & +} + +setup_usb_storage_configfs() { + local active_udc + local storage_dev + active_udc="$(cat $CONFIGFS/g1/UDC)" + storage_dev="$1" + + if ! [ -e "$CONFIGFS" ]; then + echo " $CONFIGFS does not exist, can't set up storage gadget" + return 1 + fi + + if [ -z "$storage_dev" ]; then + if [ -e "$CONFIGFS/g1/configs/c.1/$CONFIGFS_MASS_STORAGE_FUNCTION" ]; then + echo "Disabling USB mass storage gadget" + unlink "$CONFIGFS/g1/configs/c.1/$CONFIGFS_MASS_STORAGE_FUNCTION" + setup_usb_configfs_udc + fi + return 0 + fi + + if ! [ -b "$storage_dev" ]; then + echo " Storage device '$storage_dev' is not a block device" + return 1 + fi + + # Set up network gadget if not already done + if [ -z "$active_udc" ]; then + setup_usb_network_configfs "skip_udc" + else + # Unset UDC before reconfiguring gadget + echo "" > $CONFIGFS/g1/UDC + fi + + # Create mass storage function + mkdir -p "$CONFIGFS/g1/functions/$CONFIGFS_MASS_STORAGE_FUNCTION" \ + || echo " Couldn't create $CONFIGFS/g1/functions/$CONFIGFS_MASS_STORAGE_FUNCTION" + + echo "$storage_dev" > "$CONFIGFS/g1/functions/$CONFIGFS_MASS_STORAGE_FUNCTION/lun.0/file" + + # Link the mass storage function to the configuration + ln -sf "$CONFIGFS/g1/functions/$CONFIGFS_MASS_STORAGE_FUNCTION" "$CONFIGFS/g1/configs/c.1" \ + || echo " Couldn't symlink $CONFIGFS_MASS_STORAGE_FUNCTION" + + setup_usb_configfs_udc + return 0 +} + +debug_shell() { + splash_hide + echo "Entering debug shell" + # if we have a UDC it's already been configured for USB networking + local have_udc + have_udc="$(cat $CONFIGFS/g1/UDC)" + + if [ -n "$have_udc" ]; then + setup_usb_acm_configfs + fi + + # mount pstore, if possible + if [ -d /sys/fs/pstore ]; then + mount -t pstore pstore /sys/fs/pstore || true + fi + + mount -t debugfs none /sys/kernel/debug || true + # make a symlink like Android recoveries do + ln -s /sys/kernel/debug /d + + cat <<-EOF > /README + postmarketOS debug shell + https://postmarketos.org/debug-shell + + Device: $deviceinfo_name ($deviceinfo_codename) + Kernel: $(uname -r) + OS ver: $VERSION + initrd: $INITRAMFS_PKG_VERSION + + Run 'pmos_continue_boot' to continue booting. + Read the initramfs log with 'cat /pmOS_init.log'. + EOF + + # Add pmos_logdump message only if relevant + if [ -n "$have_udc" ]; then + echo "Run 'pmos_logdump' to generate a log dump and expose it over USB." >> /README + + cat <<-EOF >> /README + You can expose storage devices over USB with + 'setup_usb_storage_configfs /dev/DEVICE' + EOF + + if [ -n "$usb_storage" ]; then + echo "$usb_storage is exposed over USB by default (pmos.usb-storage)" >> /README + fi + fi + + # Display some info + cat <<-EOF > /etc/profile + cat /README + . /init_functions.sh + EOF + + cat <<-EOF > /sbin/pmos_getty + #!/bin/sh + /bin/sh -l + EOF + chmod +x /sbin/pmos_getty + + cat <<-EOF > /sbin/pmos_continue_boot + #!/bin/sh + echo "Continuing boot..." + touch /tmp/continue_boot + pkill -f telnetd.*:23 + while sleep 1; do :; done + EOF + chmod +x /sbin/pmos_continue_boot + + cat <<-EOF > /sbin/pmos_logdump + #!/bin/sh + echo "Dumping logs, check for a new mass storage device" + touch /tmp/dump_logs + EOF + chmod +x /sbin/pmos_logdump + + # Get the console (ttyX) associated with /dev/console + local active_console + active_console="$(cat /sys/devices/virtual/tty/tty0/active)" + # Get a list of all active TTYs include serial ports + local serial_ports + serial_ports="$(cat /sys/devices/virtual/tty/console/active)" + # Get the getty device too (might not be active) + local getty + getty="$(echo "$deviceinfo_getty" | cut -d';' -f1)" + + # Run getty's on the consoles + for tty in $serial_ports; do + # Some ports we handle explicitly below to make sure we don't + # accidentally spawn two getty's on them + if echo "tty0 tty1 ttyGS0 $getty" | grep -q "$tty" ; then + continue + fi + run_getty "$tty" + done + + if [ -n "$getty" ]; then + run_getty "$getty" + fi + + # Rewrite tty to tty1 if tty0 is active + if [ "$active_console" = "tty0" ]; then + active_console="tty1" + fi + + # Getty on the display + splash_hide + # Spawn buffyboard if the device might not have a physical keyboard + # buffyboard is only available with merged initramfs-extra! + if command -v buffyboard 2>/dev/null && \ + echo "handset tablet convertible" | grep "${deviceinfo_chassis:-handset}" >/dev/null; then + modprobe uinput + # Set a large font for the framebuffer + setfont "/usr/share/consolefonts/ter-128n.psf.gz" -C "/dev/$active_console" + buffyboard & + fi + run_getty "$active_console" + + # And on the usb acm port (if it exists) + if [ -e /dev/ttyGS0 ]; then + run_getty ttyGS0 + fi + + # To avoid racing with the host PC opening the ACM port, we spawn + # the getty first. See the comment in run_getty for more details. + setup_usb_configfs_udc + + # Spawn telnetd for those who prefer it. ACM gadget mode is not + # supported on some old kernels so this exists as a fallback. + telnetd -b "${HOST_IP}:23" -l /sbin/pmos_getty & + + # Set up USB mass storage if pmos.usb-storage= was specified on cmdline + [ -z "$usb_storage" ] || setup_usb_storage_configfs "$usb_storage" + + # wait until we get the signal to continue boot + while ! [ -e /tmp/continue_boot ]; do + sleep 0.2 + if [ -e /tmp/dump_logs ]; then + rm -f /tmp/dump_logs + export_logs + fi + done + + # Remove the ACM/mass storage gadget devices + # FIXME: would be nice to have a way to keep this on and + # pipe kernel/init logs to it. + rm -f $CONFIGFS/g1/configs/c.1/"$CONFIGFS_ACM_FUNCTION" + rmdir $CONFIGFS/g1/functions/"$CONFIGFS_ACM_FUNCTION" + rm -f "$CONFIGFS/g1/configs/c.1/$CONFIGFS_MASS_STORAGE_FUNCTION" + rmdir "$CONFIGFS/g1/functions/$CONFIGFS_MASS_STORAGE_FUNCTION" + setup_usb_configfs_udc + + splash_set_message "Loading" + + pkill -f buffyboard || true +} + +# Check if the user is pressing a key and either drop to a shell or halt boot as applicable +check_keys() { + { + # If the user is pressing either the left control key or the volume down + # key then drop to a debug shell. + if iskey KEY_LEFTCTRL KEY_VOLUMEDOWN; then + beebzzr -b 2 -d 100 & + debug_shell + # If instead they're pressing left shift or volume up, then fail boot + # and dump logs + elif iskey KEY_LEFTSHIFT KEY_VOLUMEUP; then + fail_halt_boot + fi + + touch /tmp/debug_shell_exited + } & + + while ! [ -e /tmp/debug_shell_exited ]; do + sleep 1 + done +} + +# Show the Plymouth splash screen +# Uses: nosplash +# Sets: (none) +# Returns: 0 +splash_show() { + if [ "$nosplash" = "y" ]; then + return + fi + + if plymouth --ping 2>/dev/null; then + plymouth show-splash + fi +} + +# Hide the Plymouth splash screen +# Uses: nosplash +# Sets: (none) +# Returns: 0 +splash_hide() { + if [ "$nosplash" = "y" ]; then + return + fi + + if plymouth --ping 2>/dev/null; then + plymouth hide-splash + fi +} + +# Set the Plymouth message +# Uses: (none) +# Sets: (none) +# $1: message text to display, may be multiline with \n +# Returns: 0 +splash_set_message() { + info "SPLASH: $1" + splash_show + if plymouth --ping 2>/dev/null; then + # Use printf to convert \n to literal newlines for multiline messages + plymouth display-message --text "$(printf '%b' "$1")" + fi +} + +# Set an error on the Plymouth splash +# Uses: (none) +# Sets: (none) +# $1: error text to display +# Returns: 0 +splash_set_error() { + info "SPLASH ERROR: $1" + splash_show + if plymouth --ping 2>/dev/null; then + plymouth update --status="error" + # Use printf to convert \n to literal newlines for multiline messages + plymouth display-message --text "$(printf '%b' "$1")" + fi +} + +# Set a warning on the Plymouth splash +# Uses: (none) +# Sets: (none) +# $1: warning text to display +# Returns: 0 +splash_set_warning() { + info "SPLASH WARNING: $1" + splash_show + if plymouth --ping 2>/dev/null; then + plymouth update --status="warning" + # Use printf to convert \n to literal newlines for multiline messages + plymouth display-message --text "$(printf '%b' "$1")" + fi +} + +set_framebuffer_mode() { + [ -e "/sys/class/graphics/fb0/modes" ] || return + [ -z "$(cat /sys/class/graphics/fb0/mode)" ] || return + + _mode="$(cat /sys/class/graphics/fb0/modes)" + echo "Setting framebuffer mode to: $_mode" + echo "$_mode" > /sys/class/graphics/fb0/mode +} + +setup_framebuffer() { + if [ "$nosplash" = "y" ]; then + return + fi + + # Wait for /dev/fb0 + for _ in $(seq 1 100); do + [ -e "/dev/fb0" ] && break + sleep 0.1 + done + if ! [ -e "/dev/fb0" ]; then + echo "ERROR: /dev/fb0 did not appear after waiting 10 seconds!" + echo "If your device does not have a framebuffer, disable this with:" + echo "no_framebuffer=true in " + return + fi + + set_framebuffer_mode +} + +setup_bootchart2() { + if [ "$bootchart2" = "y" ]; then + if [ -f "/sysroot/sbin/bootchartd" ]; then + # shellcheck disable=SC2034 + init="/sbin/bootchartd" + echo "remounting /sysroot as rw for /sbin/bootchartd" + mount -o remount, rw /sysroot + + # /dev/null may not exist at the first boot after + # the root filesystem has been created. + [ -c /sysroot/dev/null ] && return + echo "creating /sysroot/dev/null for /sbin/bootchartd" + mknod -m 666 "/sysroot/dev/null" c 1 3 + else + echo "WARNING: bootchart2 is not installed." + fi + fi +} + +mkhash() { + sha256sum "$1" | cut -d " " -f 1 +} + +# Create a small disk image and copy logs to it so they can be exposed via mass storage +create_logs_disk() { + local loop_dev="$1" + local upload_file="" + echo "Creating logs disk" + + dd if=/dev/zero of=/tmp/logs.img bs=1M count=32 + # The log device used is assumed to be $loop_dev + losetup -f /tmp/logs.img + mkfs.vfat -n "PMOS_LOGS" "$loop_dev" + mkdir -p /tmp/logs + modprobe vfat + mount "$loop_dev" /tmp/logs + + # Copy logs + cp /pmOS_init.log /tmp/logs/pmOS_init.txt + dmesg > /tmp/logs/dmesg.txt + blkid > /tmp/logs/blkid.txt + cat /proc/cmdline > /tmp/logs/cmdline.txt + cat /proc/partitions > /tmp/logs/partitions.txt + # Include FDT if it exists + [ -e /sys/firmware/fdt ] && cp /sys/firmware/fdt /tmp/logs/fdt.dtb + + # Additional info about the initramfs + { + echo "initramfs-version: $INITRAMFS_PKG_VERSION" + # Take hashes of the initramfs files so we can be sure they weren't modified inadvertantly + echo "init-hash: $(mkhash /init)" + echo "init-functions-hash: $(mkhash /init_functions.sh)" + } >> /tmp/logs/_info + + # Create a tar file with all the logs. We don't include the date because on many devices + # (especially Qualcomm) the RTC is likely wrong. + upload_file="${deviceinfo_codename}-${VERSION}-$(uname -r).tar.gz" + # Done in a subshell to not change the working directory of init + (cd /tmp/logs || ( echo "Couldn't cd to /tmp/logs"; return ); tar -cv ./* | gzip -6 -c > "/tmp/$upload_file") + mv "/tmp/$upload_file" /tmp/logs/ + + # Create a README with instructions on how to report an issue + cat > /tmp/logs/README.txt <<-EOF + Something went wrong and your device did not boot properly. If this was unexpected + then please open a new issue by visiting + + https://gitlab.postmarketos.org/postmarketOS/pmaports/-/issues/new + + and attach the following file by dragging it onto the page: + + * $upload_file + + You are running postmarketOS $VERSION on kernel $(uname -r). + EOF + + # Unmount + umount /tmp/logs +} + +# Make logs available via mass storage gadget +export_logs() { + local loop_dev + loop_dev="$(losetup -f)" + create_logs_disk "$loop_dev" + + echo "Making logs available via mass storage" + setup_usb_storage_configfs "$loop_dev" +} + +fail_halt_boot() { + beebzzr -b 3 -d 250 & + export_logs + debug_shell + echo "Looping forever" + while true; do + sleep 1 + done +} diff --git a/prebuilt/sxmo-x11/usr/lib/dwm/plugins/modem.so b/prebuilt/sxmo-x11/usr/lib/dwm/plugins/modem.so index 0c0af48d875c2d60a72b9341a4c7e5e0c4f63616..3b0a83e11d86e3ed095710be02b210ca184adf33 100755 GIT binary patch delta 35981 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�O1^ulrXh6k9;kBT-&7^XN)MD(A4(EcTMeYybz(! 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 WnPhYyYv){-R5-I&k4K5Z0s8-Xh0dV> diff --git a/rebuild-image.sh b/rebuild-image.sh index c288250..8135df9 100755 --- a/rebuild-image.sh +++ b/rebuild-image.sh @@ -187,6 +187,7 @@ EOF /usr/bin/mkbootimg-osm0sis \ /usr/bin/zstd; do if [ -e "$bin" ]; then + rm -f "$ROOTFS/tmp/hostbin/$(basename "$bin")" cp -L "$bin" "$ROOTFS/tmp/hostbin/" fi done diff --git a/src/dwm-plugins/modem_plugin.cpp b/src/dwm-plugins/modem_plugin.cpp index 0c25eb3..bf9b8b0 100644 --- a/src/dwm-plugins/modem_plugin.cpp +++ b/src/dwm-plugins/modem_plugin.cpp @@ -387,11 +387,20 @@ ModemStatusData queryModemAndSimStatus() { } // Sync ModemManager lock info into active slot if QMI didn't report retries - int actIdx = (d.primaryGwSlot >= 1 && d.primaryGwSlot <= 2) - ? (d.primaryGwSlot - 1) - : (d.preferredSlot - 1); + int actIdx = -1; + if (d.primaryGwSlot >= 1 && d.primaryGwSlot <= 2 && + d.slots[d.primaryGwSlot - 1].state == "present") { + actIdx = d.primaryGwSlot - 1; + } else if (d.slots[1].state == "present" && d.slots[0].state != "present") { + actIdx = 1; + } else if (d.slots[0].state == "present" && d.slots[1].state != "present") { + actIdx = 0; + } else if (!d.qmiAvailable) { + actIdx = std::clamp(d.preferredSlot, 1, 2) - 1; + } if (actIdx >= 0 && actIdx < 2) { - if (d.mmUnlockRequired == "sim-pin" && d.slots[actIdx].pin1State == "not-initialized") { + if (d.mmUnlockRequired == "sim-pin" && + d.slots[actIdx].pin1State == "not-initialized") { d.slots[actIdx].state = "present"; d.slots[actIdx].pin1State = "enabled-not-verified"; } else if (d.mmUnlockRequired == "sim-puk") {