#!/system/bin/sh # Driver Manager v2 - Driver Registry # Discovers, catalogs, and manages system drivers MODDIR=${MODDIR:-/data/adb/modules/driver-manager} . "$MODDIR/scripts/core.sh" log_init "$LOGDIR/registry.log" REGISTRY="$CONFIGDIR/drivers.json" # --- Driver discovery paths by category --- scan_drivers() { log "Starting driver scan" local tmp="$CONFIGDIR/.drivers_tmp.json" cat > "$tmp" << 'HEADER' {"drivers":[ HEADER local first=true # GPU drivers for path in /vendor/lib64/egl /vendor/lib/egl /system/lib64/egl; do [ -d "$path" ] || continue for f in "$path"/lib*.so; do [ -f "$f" ] || continue local name=$(basename "$f" .so) local hash=$(sha256 "$f") local ctx=$(get_selinux_context "$f") local sz=$(file_size "$f") [ "$first" = true ] && first=false || echo "," >> "$tmp" cat >> "$tmp" << ENTRY { "id": "gpu-$name", "name": "$name", "category": "gpu", "path": "$f", "hash": "$hash", "selinux": "$ctx", "size": $sz, "protected": true, "variants": [{"name": "stock", "path": "$f", "hash": "$hash", "active": true}] } ENTRY done done # Vulkan ICD for path in /vendor/lib64/hw /vendor/lib/hw; do [ -d "$path" ] || continue for f in "$path"/vulkan.*.so; do [ -f "$f" ] || continue local name=$(basename "$f" .so) local hash=$(sha256 "$f") local ctx=$(get_selinux_context "$f") local sz=$(file_size "$f") [ "$first" = true ] && first=false || echo "," >> "$tmp" cat >> "$tmp" << ENTRY { "id": "vulkan-$name", "name": "$name", "category": "gpu", "path": "$f", "hash": "$hash", "selinux": "$ctx", "size": $sz, "protected": true, "variants": [{"name": "stock", "path": "$f", "hash": "$hash", "active": true}] } ENTRY done done # WiFi firmware for path in /vendor/firmware /vendor/etc/wifi /lib/firmware; do [ -d "$path" ] || continue for f in "$path"/fw_bcm*.bin "$path"/fw_wcn*.bin "$path"/wlan_*.bin; do [ -f "$f" ] || continue local name=$(basename "$f") local hash=$(sha256 "$f") local ctx=$(get_selinux_context "$f") local sz=$(file_size "$f") [ "$first" = true ] && first=false || echo "," >> "$tmp" cat >> "$tmp" << ENTRY { "id": "wifi-$name", "name": "$name", "category": "wifi", "path": "$f", "hash": "$hash", "selinux": "$ctx", "size": $sz, "protected": true, "variants": [{"name": "stock", "path": "$f", "hash": "$hash", "active": true}] } ENTRY done done # Bluetooth firmware for path in /vendor/firmware /vendor/etc/bluetooth /lib/firmware; do [ -d "$path" ] || continue for f in "$path"/*.hcd "$path"/bt_fw*.bin "$path"/BCM*.hcd; do [ -f "$f" ] || continue local name=$(basename "$f") local hash=$(sha256 "$f") local ctx=$(get_selinux_context "$f") local sz=$(file_size "$f") [ "$first" = true ] && first=false || echo "," >> "$tmp" cat >> "$tmp" << ENTRY { "id": "bt-$name", "name": "$name", "category": "bluetooth", "path": "$f", "hash": "$hash", "selinux": "$ctx", "size": $sz, "protected": true, "variants": [{"name": "stock", "path": "$f", "hash": "$hash", "active": true}] } ENTRY done done # Audio HAL for path in /vendor/lib64/hw /vendor/lib/hw; do [ -d "$path" ] || continue for f in "$path"/audio*.so; do [ -f "$f" ] || continue local name=$(basename "$f" .so) local hash=$(sha256 "$f") local ctx=$(get_selinux_context "$f") local sz=$(file_size "$f") [ "$first" = true ] && first=false || echo "," >> "$tmp" cat >> "$tmp" << ENTRY { "id": "audio-$name", "name": "$name", "category": "audio", "path": "$f", "hash": "$hash", "selinux": "$ctx", "size": $sz, "protected": true, "variants": [{"name": "stock", "path": "$f", "hash": "$hash", "active": true}] } ENTRY done done # Camera HAL for path in /vendor/lib64/hw /vendor/lib/hw; do [ -d "$path" ] || continue for f in "$path"/camera*.so; do [ -f "$f" ] || continue local name=$(basename "$f" .so) local hash=$(sha256 "$f") local ctx=$(get_selinux_context "$f") local sz=$(file_size "$f") [ "$first" = true ] && first=false || echo "," >> "$tmp" cat >> "$tmp" << ENTRY { "id": "camera-$name", "name": "$name", "category": "camera", "path": "$f", "hash": "$hash", "selinux": "$ctx", "size": $sz, "protected": false, "variants": [{"name": "stock", "path": "$f", "hash": "$hash", "active": true}] } ENTRY done done # Sensor HAL for path in /vendor/lib64/hw /vendor/lib/hw; do [ -d "$path" ] || continue for f in "$path"/sensors*.so; do [ -f "$f" ] || continue local name=$(basename "$f" .so) local hash=$(sha256 "$f") local ctx=$(get_selinux_context "$f") local sz=$(file_size "$f") [ "$first" = true ] && first=false || echo "," >> "$tmp" cat >> "$tmp" << ENTRY { "id": "sensor-$name", "name": "$name", "category": "sensor", "path": "$f", "hash": "$hash", "selinux": "$ctx", "size": $sz, "protected": false, "variants": [{"name": "stock", "path": "$f", "hash": "$hash", "active": true}] } ENTRY done done # Kernel modules currently loaded if [ -f /proc/modules ]; then while read -r name rest; do [ "$first" = true ] && first=false || echo "," >> "$tmp" cat >> "$tmp" << ENTRY { "id": "kmod-$name", "name": "$name", "category": "kernel", "path": "/proc/modules", "hash": "", "selinux": "", "size": 0, "protected": false, "variants": [{"name": "loaded", "path": "", "hash": "", "active": true}] } ENTRY done < /proc/modules fi echo "" >> "$tmp" echo "]}" >> "$tmp" mv "$tmp" "$REGISTRY" log "Driver scan complete" } # --- Count drivers --- count_drivers() { if [ -f "$REGISTRY" ]; then grep -c '"id"' "$REGISTRY" 2>/dev/null || echo "0" else echo "0" fi } # --- List drivers as JSON --- list_drivers() { [ -f "$REGISTRY" ] && cat "$REGISTRY" || echo '{"drivers":[]}' } # --- Get single driver info --- get_driver() { local id="$1" if [ -f "$REGISTRY" ]; then # Extract the driver block matching the id awk -v id="$id" ' /"id".*:.*"/ { found = ($0 ~ "\"" id "\"") } found && /\{/ { depth++ } found && depth > 0 { print } found && /\}/ { depth--; if (depth == 0) { found=0 } } ' "$REGISTRY" fi } # --- Add a custom variant to a driver --- add_variant() { local driver_id="$1" local variant_name="$2" local variant_path="$3" if [ ! -f "$variant_path" ]; then echo '{"error": "Variant file not found"}' return 1 fi local hash=$(sha256 "$variant_path") log "Adding variant '$variant_name' to driver '$driver_id': $variant_path (hash: $hash)" # Copy variant to drivers directory local dest="$MODDIR/drivers/${driver_id}_${variant_name}_$(basename "$variant_path")" cp "$variant_path" "$dest" chmod 644 "$dest" echo "{\"status\": \"ok\", \"driver\": \"$driver_id\", \"variant\": \"$variant_name\", \"path\": \"$dest\", \"hash\": \"$hash\"}" } # --- Verify a driver's current hash matches registry --- verify_driver() { local id="$1" local reg_path=$(grep -A5 "\"$id\"" "$REGISTRY" 2>/dev/null | grep '"path"' | head -1 | sed 's/.*: *"\([^"]*\)".*/\1/') local reg_hash=$(grep -A5 "\"$id\"" "$REGISTRY" 2>/dev/null | grep '"hash"' | head -1 | sed 's/.*: *"\([^"]*\)".*/\1/') if [ -z "$reg_path" ] || [ -z "$reg_hash" ]; then echo '{"status": "unknown", "reason": "driver not in registry"}' return 1 fi local cur_hash=$(sha256 "$reg_path") if [ "$cur_hash" = "$reg_hash" ]; then echo "{\"status\": \"ok\", \"driver\": \"$id\", \"hash\": \"$cur_hash\"}" else echo "{\"status\": \"changed\", \"driver\": \"$id\", \"expected\": \"$reg_hash\", \"actual\": \"$cur_hash\"}" fi } # --- Main --- case "$1" in scan) scan_drivers ;; count) count_drivers ;; list) list_drivers ;; get) get_driver "$2" ;; add_variant) add_variant "$2" "$3" "$4" ;; verify) verify_driver "$2" ;; *) echo "Usage: driver_registry.sh {scan|count|list|get|add_variant|verify} [args]" ;; esac