main
  1#!/usr/bin/env bash
  2# check-firmware-usage.sh
  3# Analyzes which firmware is actually loaded/needed on your system
  4
  5set -euo pipefail
  6
  7# Colors
  8BOLD='\033[1m'
  9GREEN='\033[0;32m'
 10YELLOW='\033[1;33m'
 11CYAN='\033[0;36m'
 12NC='\033[0m'
 13
 14echo -e "${BOLD}=== Firmware Usage Analysis ===${NC}"
 15echo ""
 16
 17# 1. Check what firmware files are actually loaded
 18echo -e "${BOLD}${CYAN}1. Firmware Files Currently Loaded${NC}"
 19echo "---"
 20echo "Checking dmesg for firmware loading..."
 21echo ""
 22
 23LOADED_FW=$(dmesg | grep -i "firmware" | grep -i "load" | grep -v "failed" | sort -u || echo "")
 24if [ -n "$LOADED_FW" ]; then
 25    echo "$LOADED_FW" | while read -r line; do
 26        # Extract firmware filename
 27        fw=$(echo "$line" | grep -oP '(?<=firmware: ).*?(?=\s|$)' || echo "$line")
 28        echo -e "  ${GREEN}${NC} $fw"
 29    done
 30else
 31    echo "  No firmware load messages found in dmesg"
 32fi
 33echo ""
 34
 35# 2. Check for firmware loading failures
 36echo -e "${BOLD}${CYAN}2. Firmware Loading Failures (if any)${NC}"
 37echo "---"
 38FAILED_FW=$(dmesg | grep -i "firmware" | grep -iE "fail|error|not found" | sort -u || echo "")
 39if [ -n "$FAILED_FW" ]; then
 40    echo "$FAILED_FW" | while read -r line; do
 41        fw=$(echo "$line" | grep -oP '(?<=firmware: ).*?(?=\s|$)' || echo "$line")
 42        echo -e "  ${YELLOW}${NC} $fw"
 43    done
 44else
 45    echo -e "  ${GREEN}✓ No firmware failures detected${NC}"
 46fi
 47echo ""
 48
 49# 3. Identify hardware that typically needs firmware
 50echo -e "${BOLD}${CYAN}3. Hardware Components${NC}"
 51echo "---"
 52
 53echo -e "${YELLOW}WiFi/Wireless:${NC}"
 54lspci | grep -iE "network|wireless|wifi|802.11" || echo "  None found via lspci"
 55lsusb | grep -iE "network|wireless|wifi|802.11" || echo "  None found via lsusb"
 56echo ""
 57
 58echo -e "${YELLOW}Graphics:${NC}"
 59lspci | grep -iE "vga|3d|display|graphics" || echo "  None found"
 60echo ""
 61
 62echo -e "${YELLOW}Bluetooth:${NC}"
 63lsusb | grep -i bluetooth || lspci | grep -i bluetooth || echo "  None found"
 64echo ""
 65
 66echo -e "${YELLOW}Sound/Audio:${NC}"
 67lspci | grep -i audio || echo "  None found"
 68echo ""
 69
 70# 4. Check loaded kernel modules
 71echo -e "${BOLD}${CYAN}4. Loaded Kernel Modules (firmware-heavy drivers)${NC}"
 72echo "---"
 73
 74MODULES=$(lsmod | tail -n +2 | awk '{print $1}' | sort)
 75
 76# Common modules that need firmware
 77FW_MODULES=(
 78    "iwlwifi"      # Intel WiFi
 79    "ath10k"       # Atheros WiFi
 80    "ath9k"        # Atheros WiFi
 81    "rtw88"        # Realtek WiFi
 82    "mt76"         # MediaTek WiFi
 83    "brcmfmac"     # Broadcom WiFi
 84    "btusb"        # Bluetooth
 85    "i915"         # Intel graphics
 86    "amdgpu"       # AMD graphics
 87    "nouveau"      # Nvidia (open)
 88    "nvidia"       # Nvidia (proprietary)
 89    "snd_hda"      # HD Audio
 90)
 91
 92echo "Firmware-dependent modules currently loaded:"
 93for mod in "${FW_MODULES[@]}"; do
 94    if echo "$MODULES" | grep -q "^${mod}"; then
 95        echo -e "  ${GREEN}${NC} $mod"
 96    fi
 97done
 98echo ""
 99
100# 5. List firmware files in /lib/firmware
101echo -e "${BOLD}${CYAN}5. Firmware Files Present in /lib/firmware${NC}"
102echo "---"
103if [ -d /lib/firmware ]; then
104    FW_COUNT=$(find /lib/firmware -type f 2>/dev/null | wc -l)
105    FW_SIZE=$(du -sh /lib/firmware 2>/dev/null | cut -f1)
106    echo "Total firmware files: $FW_COUNT"
107    echo "Total size: $FW_SIZE"
108    echo ""
109
110    echo "Largest firmware directories:"
111    du -sh /lib/firmware/* 2>/dev/null | sort -rh | head -10
112else
113    echo "  /lib/firmware not found"
114fi
115echo ""
116
117# 6. Check what's actually being used from linux-firmware
118echo -e "${BOLD}${CYAN}6. Specific Firmware Recommendations${NC}"
119echo "---"
120
121RECOMMENDATIONS=""
122
123# Check for Intel WiFi
124if echo "$MODULES" | grep -q "^iwlwifi"; then
125    RECOMMENDATIONS="${RECOMMENDATIONS}hardware.firmware = [ pkgs.linux-firmware ];  # Intel WiFi (iwlwifi)\n"
126fi
127
128# Check for AMD GPU
129if lspci | grep -q "AMD.*Radeon\|AMD.*Graphics" || echo "$MODULES" | grep -q "^amdgpu"; then
130    RECOMMENDATIONS="${RECOMMENDATIONS}hardware.firmware = [ pkgs.linux-firmware ];  # AMD GPU needs firmware\n"
131fi
132
133# Check for Atheros WiFi
134if echo "$MODULES" | grep -qE "^ath10k|^ath9k"; then
135    RECOMMENDATIONS="${RECOMMENDATIONS}hardware.firmware = [ pkgs.linux-firmware ];  # Atheros WiFi\n"
136fi
137
138# Check for Realtek
139if lspci | grep -qi "realtek" || echo "$MODULES" | grep -q "^rtw"; then
140    RECOMMENDATIONS="${RECOMMENDATIONS}hardware.firmware = [ pkgs.linux-firmware ];  # Realtek devices\n"
141fi
142
143# Check for Broadcom
144if lspci | grep -qi "broadcom" || echo "$MODULES" | grep -q "^brcm"; then
145    RECOMMENDATIONS="${RECOMMENDATIONS}hardware.firmware = [ pkgs.linux-firmware ];  # Broadcom WiFi\n"
146fi
147
148# Check for Intel graphics
149if lspci | grep -q "Intel.*Graphics\|Intel.*VGA" || echo "$MODULES" | grep -q "^i915"; then
150    echo -e "${GREEN}${NC} Intel graphics detected - usually works without firmware"
151fi
152
153if [ -n "$RECOMMENDATIONS" ]; then
154    echo ""
155    echo -e "${YELLOW}Based on your hardware, you likely need:${NC}"
156    echo ""
157    echo -e "$RECOMMENDATIONS"
158else
159    echo ""
160    echo -e "${GREEN}${NC} No obvious firmware dependencies detected"
161    echo "  Your hardware might work fine without linux-firmware package"
162fi
163
164echo ""
165echo -e "${BOLD}${CYAN}7. NixOS Configuration Recommendations${NC}"
166echo "---"
167
168cat << 'EOF'
169For a laptop, you have several options:
170
171Option 1: Keep redistributable firmware (safest for laptops)
172  hardware.enableRedistributableFirmware = true;
173  # Includes: WiFi, Bluetooth, GPU firmware (~730MB)
174
175Option 2: Minimal firmware (if WiFi/GPU work without it)
176  hardware.enableRedistributableFirmware = false;
177  hardware.firmware = with pkgs; [
178    # Only include what you actually need, e.g.:
179    # wireless-regdb  # Regulatory database for WiFi
180  ];
181
182Option 3: Disable entirely (test carefully!)
183  hardware.enableRedistributableFirmware = false;
184  # Only works if all hardware functions without firmware
185
186To test Option 2 or 3:
1871. Boot with current config
1882. Test all hardware (WiFi, Bluetooth, suspend/resume, graphics)
1893. Check 'dmesg | grep -i firmware' for failures
1904. If anything breaks, revert to Option 1
191EOF
192
193echo ""
194echo -e "${BOLD}Next Steps:${NC}"
195echo "1. Review the loaded firmware and hardware above"
196echo "2. Choose a configuration option"
197echo "3. Test thoroughly before committing to production"
198echo ""