@@ -716,6 +716,25 @@ run_with_timeout() {
716716 return $status
717717}
718718
719+ # Only apply a timeout if TIMEOUT is set; prefer `timeout`; avoid functestlib here
720+ runWithTimeoutIfSet () {
721+ # Normalize TIMEOUT: treat empty or non-numeric as 0
722+ t=" ${TIMEOUT:- } "
723+ case " $t " in
724+ ' ' |* [!0-9]* )
725+ t=0
726+ ;;
727+ esac
728+
729+ if [ " $t " -gt 0 ] && command -v run_with_timeout > /dev/null 2>&1 ; then
730+ # Correct signature: run_with_timeout <seconds> <cmd> [args...]
731+ run_with_timeout " $t " " $@ "
732+ else
733+ # No timeout -> run command directly
734+ " $@ "
735+ fi
736+ }
737+
719738# DHCP client logic (dhclient and udhcpc with timeouts)
720739run_dhcp_client () {
721740 iface=" $1 "
@@ -2309,4 +2328,287 @@ EOF
23092328 log_warn " resize2fs not available; skipping resize."
23102329 fi
23112330 return 0
2312- }
2331+ }
2332+
2333+ log_soc_info () {
2334+ m=" " ; s=" " ; pv=" "
2335+ [ -r /sys/devices/soc0/machine ] && m=" $( cat /sys/devices/soc0/machine 2> /dev/null) "
2336+ [ -r /sys/devices/soc0/soc_id ] && s=" $( cat /sys/devices/soc0/soc_id 2> /dev/null) "
2337+ [ -r /sys/devices/soc0/platform_version ] && pv=" $( cat /sys/devices/soc0/platform_version 2> /dev/null) "
2338+ [ -n " $m " ] && log_info " SoC.machine: $m "
2339+ [ -n " $s " ] && log_info " SoC.soc_id: $s "
2340+ [ -n " $pv " ] && log_info " SoC.platform_version: $pv "
2341+ }
2342+
2343+ # ##############################################################################
2344+ # Platform detection (SoC / Target / Machine / OS) — POSIX, no sourcing files
2345+ # Sets & exports:
2346+ # PLATFORM_KERNEL, PLATFORM_ARCH, PLATFORM_UNAME_S, PLATFORM_HOSTNAME
2347+ # PLATFORM_SOC_MACHINE, PLATFORM_SOC_ID, PLATFORM_SOC_FAMILY
2348+ # PLATFORM_DT_MODEL, PLATFORM_DT_COMPAT
2349+ # PLATFORM_OS_LIKE, PLATFORM_OS_NAME
2350+ # PLATFORM_TARGET, PLATFORM_MACHINE
2351+ # ##############################################################################
2352+ detect_platform () {
2353+ # --- Basic uname/host ---
2354+ PLATFORM_KERNEL=" $( uname -r 2> /dev/null) "
2355+ PLATFORM_ARCH=" $( uname -m 2> /dev/null) "
2356+ PLATFORM_UNAME_S=" $( uname -s 2> /dev/null) "
2357+ PLATFORM_HOSTNAME=" $( hostname 2> /dev/null) "
2358+
2359+ # --- soc0 details ---
2360+ if [ -r /sys/devices/soc0/machine ]; then
2361+ PLATFORM_SOC_MACHINE=" $( cat /sys/devices/soc0/machine 2> /dev/null) "
2362+ else
2363+ PLATFORM_SOC_MACHINE=" "
2364+ fi
2365+
2366+ if [ -r /sys/devices/soc0/soc_id ]; then
2367+ PLATFORM_SOC_ID=" $( cat /sys/devices/soc0/soc_id 2> /dev/null) "
2368+ else
2369+ PLATFORM_SOC_ID=" "
2370+ fi
2371+
2372+ if [ -r /sys/devices/soc0/family ]; then
2373+ PLATFORM_SOC_FAMILY=" $( cat /sys/devices/soc0/family 2> /dev/null) "
2374+ else
2375+ PLATFORM_SOC_FAMILY=" "
2376+ fi
2377+
2378+ # --- Device Tree model / compatible (strip NULs) ---
2379+ if [ -r /proc/device-tree/model ]; then
2380+ PLATFORM_DT_MODEL=" $( tr -d ' \000' < /proc/device-tree/model 2> /dev/null | head -n 1) "
2381+ else
2382+ PLATFORM_DT_MODEL=" "
2383+ fi
2384+
2385+ PLATFORM_DT_COMPAT=" "
2386+ if [ -d /proc/device-tree ]; then
2387+ for f in /proc/device-tree/compatible /proc/device-tree/* /compatible; do
2388+ if [ -f " $f " ]; then
2389+ PLATFORM_DT_COMPAT=" $( tr -d ' \000' < " $f " 2> /dev/null | tr ' \n' ' ' ) "
2390+ break
2391+ fi
2392+ done
2393+ fi
2394+
2395+ # --- OS (parse, do not source /etc/os-release) ---
2396+ PLATFORM_OS_LIKE=" "
2397+ PLATFORM_OS_NAME=" "
2398+ if [ -r /etc/os-release ]; then
2399+ PLATFORM_OS_LIKE=" $(
2400+ awk -F= ' $1=="ID_LIKE"{gsub(/"/,"",$2); print $2}' /etc/os-release 2> /dev/null
2401+ ) "
2402+ if [ -z " $PLATFORM_OS_LIKE " ]; then
2403+ PLATFORM_OS_LIKE=" $(
2404+ awk -F= ' $1=="ID"{gsub(/"/,"",$2); print $2}' /etc/os-release 2> /dev/null
2405+ ) "
2406+ fi
2407+ PLATFORM_OS_NAME=" $(
2408+ awk -F= ' $1=="PRETTY_NAME"{gsub(/"/,"",$2); print $2}' /etc/os-release 2> /dev/null
2409+ ) "
2410+ fi
2411+
2412+ # --- Target guess (mutually-exclusive; generic names only) ---
2413+ lc_compat=" $( printf ' %s %s' " $PLATFORM_DT_MODEL " " $PLATFORM_DT_COMPAT " \
2414+ | tr ' [:upper:]' ' [:lower:]' ) "
2415+
2416+ case " $lc_compat " in
2417+ # Kodiak: qcs6490 / RB3 Gen2
2418+ * qcs6490* |* kodiak* |* rb3gen2* |* rb3-gen2* |* rb3* gen2* )
2419+ PLATFORM_TARGET=" Kodiak"
2420+ ;;
2421+ # LeMans family: qcs9100, qcs9075, SA8775P, IQ-9075-EVK (accept 'lemand' too)
2422+ * qcs9100* |* qcs9075* |* lemans* |* lemand* |* sa8775p* |* iq-9075-evk* )
2423+ PLATFORM_TARGET=" LeMans"
2424+ ;;
2425+ # Monaco: qcs8300
2426+ * qcs8300* |* monaco* )
2427+ PLATFORM_TARGET=" Monaco"
2428+ ;;
2429+ # Agatti: QRB2210 RB1 Core Kit
2430+ * qrb2210* |* agatti* |* rb1-core-kit* )
2431+ PLATFORM_TARGET=" Agatti"
2432+ ;;
2433+ # Talos: QCS615 ADP Air
2434+ * qcs615* |* talos* |* adp-air* )
2435+ PLATFORM_TARGET=" Talos"
2436+ ;;
2437+ * )
2438+ PLATFORM_TARGET=" unknown"
2439+ ;;
2440+ esac
2441+
2442+ # --- Human-friendly machine name ---
2443+ if [ -n " $PLATFORM_DT_MODEL " ]; then
2444+ PLATFORM_MACHINE=" $PLATFORM_DT_MODEL "
2445+ else
2446+ if [ -n " $PLATFORM_SOC_MACHINE " ]; then
2447+ PLATFORM_MACHINE=" $PLATFORM_SOC_MACHINE "
2448+ else
2449+ PLATFORM_MACHINE=" $PLATFORM_HOSTNAME "
2450+ fi
2451+ fi
2452+
2453+ # Export for callers (and to silence SC2034 in this file)
2454+ export \
2455+ PLATFORM_KERNEL PLATFORM_ARCH PLATFORM_UNAME_S PLATFORM_HOSTNAME \
2456+ PLATFORM_SOC_MACHINE PLATFORM_SOC_ID PLATFORM_SOC_FAMILY \
2457+ PLATFORM_DT_MODEL PLATFORM_DT_COMPAT PLATFORM_OS_LIKE PLATFORM_OS_NAME \
2458+ PLATFORM_TARGET PLATFORM_MACHINE
2459+
2460+ return 0
2461+ }
2462+
2463+ # ---------- minimal root / FS helpers (Yocto-safe, no underscores) ----------
2464+ isroot () { uid=" $( id -u 2> /dev/null || echo 1) " ; [ " $uid " -eq 0 ]; }
2465+
2466+ iswritabledir () { d=" $1 " ; [ -d " $d " ] && [ -w " $d " ]; }
2467+
2468+ mountpointfor () {
2469+ p=" $1 "
2470+ awk -v p=" $p " '
2471+ BEGIN{best="/"; bestlen=1}
2472+ {
2473+ mp=$2
2474+ if (index(p, mp)==1 && length(mp)>bestlen) { best=mp; bestlen=length(mp) }
2475+ }
2476+ END{print best}
2477+ ' /proc/mounts 2> /dev/null
2478+ }
2479+
2480+ tryremountrw () {
2481+ path=" $1 "
2482+ mp=" $( mountpointfor " $path " ) "
2483+ [ -n " $mp " ] || mp=" /"
2484+ if mount -o remount,rw " $mp " 2> /dev/null; then
2485+ printf ' %s\n' " $mp "
2486+ return 0
2487+ fi
2488+ return 1
2489+ }
2490+
2491+ # ---------------- DSP autolink (generic, sudo-free, no underscores) ----------------
2492+ # Env:
2493+ # FASTRPC_DSP_AUTOLINK=yes|no (default: yes)
2494+ # FASTRPC_DSP_SRC=/path/to/dsp (force a source dir)
2495+ # FASTRPC_AUTOREMOUNT=yes|no (default: no) allow remount rw if needed
2496+ # FASTRPC_AUTOREMOUNT_RO=yes|no (default: yes) remount ro after linking
2497+ ensure_usr_lib_dsp_symlinks () {
2498+ [ " ${FASTRPC_DSP_AUTOLINK:- yes} " = " yes" ] || { log_info " DSP autolink disabled" return 0; }
2499+
2500+ dsptgt=" /usr/lib/dsp"
2501+
2502+ # If already populated, skip
2503+ if [ -d " $dsptgt " ]; then
2504+ if find " $dsptgt " -mindepth 1 -maxdepth 1 -print -quit 2> /dev/null | grep -q . ; then
2505+ log_info " $dsptgt already populated, skipping DSP autolink"
2506+ return 0
2507+ fi
2508+ fi
2509+
2510+ # Choose source: explicit env wins, else discover
2511+ if [ -n " ${FASTRPC_DSP_SRC:- } " ] && [ -d " $FASTRPC_DSP_SRC " ]; then
2512+ dspsrc=" $FASTRPC_DSP_SRC "
2513+ else
2514+ # Best-effort platform hints (detect_platform may exist in functestlib)
2515+ if command -v detect_platform > /dev/null 2>&1 ; then detect_platform > /dev/null 2>&1 || true ; fi
2516+ hintstr=" $( printf ' %s %s %s %s' \
2517+ " ${PLATFORM_SOC_ID:- } " " ${PLATFORM_DT_MODEL:- } " " ${PLATFORM_DT_COMPAT:- } " " ${PLATFORM_TARGET:- } " \
2518+ | tr ' [:upper:]' ' [:lower:]' ) "
2519+
2520+ candidateslist=" $( find /usr/share/qcom -maxdepth 6 -type d -name dsp 2> /dev/null | sort) "
2521+ best=" " ; bestscore=-1; bestcount=-1
2522+ IFS='
2523+ '
2524+ for d in $candidateslist ; do
2525+ [ -d " $d " ] || continue
2526+ if ! find " $d " -mindepth 1 -maxdepth 1 -print -quit 2> /dev/null | grep -q . ; then
2527+ continue
2528+ fi
2529+ score=0
2530+ pathlc=" $( printf ' %s' " $d " | tr ' [:upper:]' ' [:lower:]' ) "
2531+ for tok in $hintstr ; do
2532+ [ -n " $tok " ] || continue
2533+ case " $pathlc " in * " $tok " * ) score=$(( score+ 1 )) ;; esac
2534+ done
2535+ cnt=" $( find " $d " -mindepth 1 -maxdepth 1 -printf ' .' 2> /dev/null | wc -c | tr -d ' ' ) "
2536+ if [ " $score " -gt " $bestscore " ] || { [ " $score " -eq " $bestscore " ] && [ " $cnt " -gt " $bestcount " ]; }; then
2537+ best=" $d " ; bestscore=" $score " ; bestcount=" $cnt "
2538+ fi
2539+ done
2540+ unset IFS
2541+ dspsrc=" $best "
2542+ fi
2543+
2544+ if [ -z " $dspsrc " ]; then
2545+ log_warn " No DSP skeleton source found under /usr/share/qcom, skipping autolink."
2546+ return 0
2547+ fi
2548+
2549+ # Must be root on Yocto (no sudo). If not root, skip safely.
2550+ if ! isroot; then
2551+ log_warn " Not root; cannot write to $dsptgt on Yocto (no sudo). Skipping DSP autolink."
2552+ return 0
2553+ fi
2554+
2555+ # Ensure target dir exists; handle read-only rootfs if requested
2556+ remounted=" "
2557+ mountpt=" "
2558+ if ! mkdir -p " $dsptgt " 2> /dev/null; then
2559+ if [ " ${FASTRPC_AUTOREMOUNT:- no} " = " yes" ]; then
2560+ mountpt=" $( tryremountrw " $dsptgt " ) " || {
2561+ log_warn " Rootfs read-only and remount failed, skipping DSP autolink."
2562+ return 0
2563+ }
2564+ remounted=" yes"
2565+ if ! mkdir -p " $dsptgt " 2> /dev/null; then
2566+ log_warn " mkdir -p $dsptgt still failed after remount, skipping."
2567+ if [ -n " $mountpt " ] && [ " ${FASTRPC_AUTOREMOUNT_RO:- yes} " = " yes" ]; then
2568+ mount -o remount,ro " $mountpt " 2> /dev/null || true
2569+ fi
2570+ return 0
2571+ fi
2572+ else
2573+ log_warn " Rootfs likely read-only. Set FASTRPC_AUTOREMOUNT=yes to remount rw automatically."
2574+ return 0
2575+ fi
2576+ fi
2577+
2578+ # If something appeared meanwhile, stop (idempotent)
2579+ if find " $dsptgt " -mindepth 1 -maxdepth 1 -print -quit 2> /dev/null | grep -q . ; then
2580+ log_info " $dsptgt now contains entries, not linking from $dspsrc "
2581+ if [ -n " $remounted " ] && [ -n " $mountpt " ] && [ " ${FASTRPC_AUTOREMOUNT_RO:- yes} " = " yes" ]; then
2582+ mount -o remount,ro " $mountpt " 2> /dev/null || true
2583+ fi
2584+ return 0
2585+ fi
2586+
2587+ # Link both files and directories; don't clobber existing names
2588+ log_info " Linking DSP artifacts from: $dspsrc → $dsptgt "
2589+ linked=0
2590+ for f in " $dspsrc " /* ; do
2591+ [ -e " $f " ] || continue
2592+ base=" $( basename " $f " ) "
2593+ if [ ! -e " $dsptgt /$base " ]; then
2594+ if ln -s " $f " " $dsptgt /$base " 2> /dev/null; then
2595+ linked=$(( linked+ 1 ))
2596+ else
2597+ log_warn " ln -s failed: $f "
2598+ fi
2599+ fi
2600+ done
2601+
2602+ # Final visibility + sanity
2603+ if find " $dsptgt " -mindepth 1 -maxdepth 1 -print -quit 2> /dev/null | grep -q . ; then
2604+ log_info " DSP autolink complete ($linked link(s))"
2605+ ls -l " $dsptgt " 2> /dev/null | sed ' s/^/[INFO] /' || true
2606+ else
2607+ log_warn " DSP autolink finished but $dsptgt is still empty, source may contain only nested content or FS is RO."
2608+ fi
2609+
2610+ # Optionally restore read-only
2611+ if [ -n " $remounted " ] && [ -n " $mountpt " ] && [ " ${FASTRPC_AUTOREMOUNT_RO:- yes} " = " yes" ]; then
2612+ mount -o remount,ro " $mountpt " 2> /dev/null || true
2613+ fi
2614+ }
0 commit comments