Skip to content

Instantly share code, notes, and snippets.

@g3rhard
Last active March 2, 2026 11:00
Show Gist options
  • Select an option

  • Save g3rhard/73b3476736217d0d6a53e8c8b5800d6e to your computer and use it in GitHub Desktop.

Select an option

Save g3rhard/73b3476736217d0d6a53e8c8b5800d6e to your computer and use it in GitHub Desktop.
#!/bin/sh
# =============================================================================
# e1000e Data Collector - MINIMAL BusyBox Version (Enhanced v2)
# Purpose: Collect data in initramfs environment with minimal dependencies
# =============================================================================
#
# DEPENDENCIES (ALL standard BusyBox applets):
# sh, cat, echo, test, mkdir, cp, ls, readlink, cut, tr, basename
# find, sort, grep, head, tail, date, sync, dd, od
#
# OPTIONAL (if available in your BusyBox build):
# md5sum, ip, dmesg, mount, umount
#
# OPTIONAL EXTERNAL TOOLS (greatly enhance diagnostics):
# ethtool - NIC configuration and register dumps
#
# ENHANCED DATA COLLECTED (v2):
# - PCI config space dump
# - PCIe link status (speed/width)
# - MSI/MSI-X state
# - ACPI/power management
# - Full ethtool diagnostics (pause, coalesce, rings, EEE, register dump)
# - TX/RX queue information
# - IRQ affinity
# - debugfs data (if accessible)
# - Boot timing extraction
#
# TO INCLUDE IN INITRAMFS:
# 1. Copy this script to /etc/initramfs-tools/scripts/init-premount/
# or /usr/lib/dracut/modules.d/99e1000e-debug/
# 2. Rebuild initramfs: update-initramfs -u -k $(uname -r)
#
# =============================================================================
# Output directory - change to your mounted USB/boot partition
OUT="${1:-/tmp/e1000e-busybox-$(cat /proc/uptime | cut -d. -f1)}"
# PCI device for e1000e NIC
PCIDEV="0000:00:1f.6"
# Create output directory
mkdir -p "$OUT"
echo "=== E1000E BusyBox Data Collector ===" > "$OUT/00_header.txt"
echo "Timestamp: $(date 2>/dev/null || echo 'unknown')" >> "$OUT/00_header.txt"
echo "Uptime: $(cat /proc/uptime)" >> "$OUT/00_header.txt"
# -----------------------------------------------------------------------------
# 1. Boot Identity
# -----------------------------------------------------------------------------
echo "Collecting boot identity..."
uname -a > "$OUT/uname_a.txt" 2>&1
cat /proc/cmdline > "$OUT/proc_cmdline.txt" 2>&1
cat /proc/version > "$OUT/proc_version.txt" 2>&1
# UEFI detection
if [ -d /sys/firmware/efi ]; then
echo "UEFI" > "$OUT/firmware_mode.txt"
else
echo "BIOS" > "$OUT/firmware_mode.txt"
fi
# PID 1 (init system)
cat /proc/1/comm > "$OUT/pid1_comm.txt" 2>&1
tr '\0' ' ' < /proc/1/cmdline > "$OUT/pid1_cmdline.txt" 2>/dev/null
# Secure boot indicators
grep -oE '(module\.sig_enforce|secureboot|efi=)[^ ]*' /proc/cmdline > "$OUT/secureboot_cmdline.txt" 2>/dev/null || echo "none" > "$OUT/secureboot_cmdline.txt"
cat /proc/sys/kernel/module_sig_enforce > "$OUT/module_sig_enforce.txt" 2>/dev/null || echo "unavailable" > "$OUT/module_sig_enforce.txt"
# -----------------------------------------------------------------------------
# 2. Modules
# -----------------------------------------------------------------------------
echo "Collecting modules info..."
cat /proc/modules > "$OUT/proc_modules.txt" 2>&1
ls -1 /sys/module > "$OUT/sys_module_list.txt" 2>&1
# e1000e parameters
if [ -d /sys/module/e1000e/parameters ]; then
echo "loaded" > "$OUT/e1000e_loaded.txt"
for p in /sys/module/e1000e/parameters/*; do
[ -r "$p" ] && echo "$(basename "$p")=$(cat "$p" 2>/dev/null)" >> "$OUT/e1000e_params.txt"
done
# === NEW: Full e1000e module sysfs tree ===
ls -laR /sys/module/e1000e/ > "$OUT/e1000e_sysfs_full.txt" 2>&1
# === NEW: Driver info from sysfs ===
for attr in /sys/module/e1000e/*; do
[ -f "$attr" ] && [ -r "$attr" ] && echo "$(basename "$attr")=$(cat "$attr" 2>/dev/null)" >> "$OUT/e1000e_module_attrs.txt"
done
else
echo "not_loaded" > "$OUT/e1000e_loaded.txt"
fi
# Modprobe config (if accessible)
if [ -d /etc/modprobe.d ]; then
cat /etc/modprobe.d/*.conf > "$OUT/modprobe_d.txt" 2>/dev/null || echo "empty" > "$OUT/modprobe_d.txt"
fi
# -----------------------------------------------------------------------------
# 3. PCI Device State
# -----------------------------------------------------------------------------
echo "Collecting PCI device state..."
PCISYS="/sys/bus/pci/devices/$PCIDEV"
if [ -d "$PCISYS" ]; then
echo "present" > "$OUT/pci_device_status.txt"
# Basic attributes
for attr in vendor device subsystem_vendor subsystem_device class irq enable; do
[ -r "$PCISYS/$attr" ] && echo "$attr=$(cat "$PCISYS/$attr" 2>/dev/null)" >> "$OUT/pci_attrs.txt"
done
# Driver binding
readlink "$PCISYS/driver" > "$OUT/pci_driver_link.txt" 2>&1 || echo "none" > "$OUT/pci_driver_link.txt"
# Power state
if [ -d "$PCISYS/power" ]; then
for attr in control runtime_status runtime_suspended_time; do
[ -r "$PCISYS/power/$attr" ] && echo "$attr=$(cat "$PCISYS/power/$attr" 2>/dev/null)" >> "$OUT/pci_power.txt"
done
fi
# Resources
cat "$PCISYS/resource" > "$OUT/pci_resource.txt" 2>/dev/null
# === NEW: PCI config space (first 256 bytes as hex) ===
if [ -r "$PCISYS/config" ]; then
od -A x -t x1 -N 256 "$PCISYS/config" > "$OUT/pci_config_space.txt" 2>&1
fi
# === NEW: MSI/MSI-X capability ===
[ -d "$PCISYS/msi_irqs" ] && ls "$PCISYS/msi_irqs" > "$OUT/pci_msi_irqs.txt" 2>&1
[ -r "$PCISYS/msi_bus" ] && cat "$PCISYS/msi_bus" > "$OUT/pci_msi_bus.txt" 2>&1
# === NEW: PCIe link status ===
for attr in current_link_speed current_link_width max_link_speed max_link_width; do
[ -r "$PCISYS/$attr" ] && echo "$attr=$(cat "$PCISYS/$attr" 2>/dev/null)" >> "$OUT/pci_link_status.txt"
done
# === NEW: D3cold and ASPM status ===
[ -r "$PCISYS/d3cold_allowed" ] && echo "d3cold_allowed=$(cat "$PCISYS/d3cold_allowed")" >> "$OUT/pci_power_extended.txt"
[ -r "$PCISYS/link/l1_aspm" ] && echo "l1_aspm=$(cat "$PCISYS/link/l1_aspm" 2>/dev/null)" >> "$OUT/pci_power_extended.txt"
# === NEW: All sysfs attributes for this device ===
ls -la "$PCISYS/" > "$OUT/pci_sysfs_listing.txt" 2>&1
else
echo "not_found" > "$OUT/pci_device_status.txt"
fi
# List all PCI devices
ls /sys/bus/pci/devices/ > "$OUT/all_pci_devices.txt" 2>&1
# -----------------------------------------------------------------------------
# 3b. ACPI & Power Management (NEW SECTION)
# -----------------------------------------------------------------------------
echo "Collecting ACPI/power management info..."
# ACPI tables list
ls /sys/firmware/acpi/tables/ > "$OUT/acpi_tables.txt" 2>/dev/null || echo "no acpi tables" > "$OUT/acpi_tables.txt"
# ACPI power state
cat /sys/power/state > "$OUT/power_state.txt" 2>/dev/null || echo "unavailable" > "$OUT/power_state.txt"
cat /sys/power/mem_sleep > "$OUT/power_mem_sleep.txt" 2>/dev/null || true
# PCI device power management for all devices
for dev in /sys/bus/pci/devices/*/power/runtime_status; do
[ -r "$dev" ] && echo "$(dirname "$dev" | xargs basename): $(cat "$dev")" >> "$OUT/all_pci_power.txt"
done 2>/dev/null
# Check for ASPM state
if [ -r /sys/module/pcie_aspm/parameters/policy ]; then
cat /sys/module/pcie_aspm/parameters/policy > "$OUT/pcie_aspm_policy.txt" 2>&1
fi
# Intel ME status if available
[ -d /sys/bus/mei/devices ] && ls -la /sys/bus/mei/devices/ > "$OUT/mei_devices.txt" 2>&1
# -----------------------------------------------------------------------------
# 4. Interrupts
# -----------------------------------------------------------------------------
echo "Collecting interrupt info..."
cat /proc/interrupts > "$OUT/proc_interrupts.txt" 2>&1
grep -E "(e1000|eth|enp|eno)" /proc/interrupts > "$OUT/nic_interrupts.txt" 2>/dev/null || echo "none" > "$OUT/nic_interrupts.txt"
# -----------------------------------------------------------------------------
# 5. Network State
# -----------------------------------------------------------------------------
echo "Collecting network state..."
# sysfs network interfaces
ls -la /sys/class/net/ > "$OUT/net_interfaces.txt" 2>&1
# Find our interface
IFACE=""
for i in eth0 enp0s31f6 eno1 eno2; do
if [ -d "/sys/class/net/$i" ]; then
IFACE="$i"
break
fi
done
echo "$IFACE" > "$OUT/detected_iface.txt"
# Interface sysfs data
if [ -n "$IFACE" ] && [ -d "/sys/class/net/$IFACE" ]; then
NETSYS="/sys/class/net/$IFACE"
for attr in operstate carrier speed duplex mtu address; do
[ -r "$NETSYS/$attr" ] && echo "$attr=$(cat "$NETSYS/$attr" 2>/dev/null)" >> "$OUT/iface_attrs.txt"
done
readlink "$NETSYS/device" >> "$OUT/iface_pci_link.txt" 2>/dev/null
# === NEW: TX/RX queue information ===
if [ -d "$NETSYS/queues" ]; then
ls -la "$NETSYS/queues/" > "$OUT/iface_queues_list.txt" 2>&1
for q in $NETSYS/queues/tx-*; do
[ -d "$q" ] && {
QN=$(basename "$q")
for attr in tx_timeout byte_queue_limits/limit byte_queue_limits/limit_max; do
[ -r "$q/$attr" ] && echo "$QN/$attr=$(cat "$q/$attr" 2>/dev/null)" >> "$OUT/iface_tx_queues.txt"
done
}
done
for q in $NETSYS/queues/rx-*; do
[ -d "$q" ] && {
QN=$(basename "$q")
for attr in rps_cpus rps_flow_cnt; do
[ -r "$q/$attr" ] && echo "$QN/$attr=$(cat "$q/$attr" 2>/dev/null)" >> "$OUT/iface_rx_queues.txt"
done
}
done
fi
# === NEW: Interface statistics from sysfs ===
if [ -d "$NETSYS/statistics" ]; then
for stat in $NETSYS/statistics/*; do
[ -r "$stat" ] && echo "$(basename "$stat")=$(cat "$stat" 2>/dev/null)" >> "$OUT/iface_sysfs_stats.txt"
done
fi
# === NEW: Interface flags ===
[ -r "$NETSYS/flags" ] && echo "flags=$(cat "$NETSYS/flags")" >> "$OUT/iface_flags.txt"
[ -r "$NETSYS/tx_queue_len" ] && echo "tx_queue_len=$(cat "$NETSYS/tx_queue_len")" >> "$OUT/iface_flags.txt"
fi
# ip command if available
if command -v ip >/dev/null 2>&1; then
ip link show > "$OUT/ip_link.txt" 2>&1
ip addr show > "$OUT/ip_addr.txt" 2>&1
fi
# /proc/net/dev
cat /proc/net/dev > "$OUT/proc_net_dev.txt" 2>&1
# ethtool if available (comprehensive collection)
if command -v ethtool >/dev/null 2>&1 && [ -n "$IFACE" ]; then
ethtool "$IFACE" > "$OUT/ethtool.txt" 2>&1 || true
ethtool -i "$IFACE" > "$OUT/ethtool_i.txt" 2>&1 || true
ethtool -S "$IFACE" > "$OUT/ethtool_S.txt" 2>&1 || true
# Additional ethtool diagnostics
ethtool -a "$IFACE" > "$OUT/ethtool_pause.txt" 2>&1 || true # Pause/flow control
ethtool -c "$IFACE" > "$OUT/ethtool_coalesce.txt" 2>&1 || true # Interrupt coalescing
ethtool -g "$IFACE" > "$OUT/ethtool_ring.txt" 2>&1 || true # Ring buffer sizes
ethtool -k "$IFACE" > "$OUT/ethtool_offload.txt" 2>&1 || true # Offload features
ethtool -d "$IFACE" > "$OUT/ethtool_dump.txt" 2>&1 || true # Register dump (PHY!)
ethtool --show-eee "$IFACE" > "$OUT/ethtool_eee.txt" 2>&1 || true # Energy Efficient Ethernet
ethtool -m "$IFACE" > "$OUT/ethtool_module.txt" 2>&1 || true # Module/SFP info
ethtool -e "$IFACE" > "$OUT/ethtool_eeprom.txt" 2>&1 || true # EEPROM dump
ethtool --show-priv-flags "$IFACE" > "$OUT/ethtool_privflags.txt" 2>&1 || true
fi
# -----------------------------------------------------------------------------
# 6. Kernel Messages
# -----------------------------------------------------------------------------
echo "Collecting kernel messages..."
if command -v dmesg >/dev/null 2>&1; then
dmesg > "$OUT/dmesg_full.txt" 2>&1
dmesg | grep -iE "(e1000|intel.*eth)" > "$OUT/dmesg_e1000e.txt" 2>/dev/null || true
dmesg | grep -iE "(error|fail|timeout|reset|watchdog)" > "$OUT/dmesg_errors.txt" 2>/dev/null || true
dmesg | tail -n 200 > "$OUT/dmesg_tail.txt" 2>&1
# === NEW: More specific dmesg filters ===
dmesg | grep -iE "(pci|pcie|aspm|d3cold|d3hot)" > "$OUT/dmesg_pci.txt" 2>/dev/null || true
dmesg | grep -iE "(acpi|power|pm|sleep|wake)" > "$OUT/dmesg_power.txt" 2>/dev/null || true
dmesg | grep -iE "(dma|iommu|iova|swiotlb)" > "$OUT/dmesg_dma.txt" 2>/dev/null || true
dmesg | grep -iE "(irq|interrupt|msi)" > "$OUT/dmesg_irq.txt" 2>/dev/null || true
dmesg | grep -iE "(firmware|microcode|mei)" > "$OUT/dmesg_firmware.txt" 2>/dev/null || true
# === NEW: Boot timing extraction ===
dmesg | grep -E "^\[[ ]*[0-9]+\.[0-9]+\]" | head -50 > "$OUT/dmesg_boot_timing.txt" 2>&1
else
echo "dmesg not available" > "$OUT/dmesg_full.txt"
fi
# === NEW: Kernel ring buffer size ===
[ -r /proc/sys/kernel/printk ] && cat /proc/sys/kernel/printk > "$OUT/kernel_printk.txt"
# -----------------------------------------------------------------------------
# 6b. Debug Filesystem (NEW SECTION)
# -----------------------------------------------------------------------------
echo "Checking debugfs..."
if [ -d /sys/kernel/debug ]; then
ls /sys/kernel/debug/ > "$OUT/debugfs_root.txt" 2>&1 || echo "no access" > "$OUT/debugfs_root.txt"
# e1000e debug info if available
if [ -d /sys/kernel/debug/e1000e ]; then
ls -la /sys/kernel/debug/e1000e/ > "$OUT/debugfs_e1000e.txt" 2>&1
for f in /sys/kernel/debug/e1000e/$PCIDEV/*; do
[ -r "$f" ] && {
echo "=== $(basename "$f") ===" >> "$OUT/debugfs_e1000e_data.txt"
cat "$f" >> "$OUT/debugfs_e1000e_data.txt" 2>&1
}
done
fi
# PCIe debug info
[ -d /sys/kernel/debug/pcie_aspm ] && cat /sys/kernel/debug/pcie_aspm/* > "$OUT/debugfs_aspm.txt" 2>/dev/null
# DMA debug
[ -r /sys/kernel/debug/dma-api/stats ] && cat /sys/kernel/debug/dma-api/stats > "$OUT/debugfs_dma_stats.txt" 2>&1
fi
# -----------------------------------------------------------------------------
# 7. Processes, Mounts & System State
# -----------------------------------------------------------------------------
echo "Collecting process/mount/system info..."
cat /proc/mounts > "$OUT/proc_mounts.txt" 2>&1
cat /proc/meminfo > "$OUT/meminfo.txt" 2>&1
if command -v ps >/dev/null 2>&1; then
ps > "$OUT/ps.txt" 2>&1
fi
# === NEW: CPU info (may affect interrupt handling) ===
cat /proc/cpuinfo > "$OUT/cpuinfo.txt" 2>&1 || true
grep -E "^(processor|model name|cpu MHz|flags)" /proc/cpuinfo > "$OUT/cpuinfo_summary.txt" 2>/dev/null
# === NEW: IRQ affinity for NIC ===
if [ -n "$IFACE" ]; then
for irqdir in /proc/irq/*; do
if grep -q "$IFACE\|e1000" "$irqdir/smp_affinity_list" 2>/dev/null; then
IRQNUM=$(basename "$irqdir")
echo "IRQ $IRQNUM:" >> "$OUT/nic_irq_affinity.txt"
cat "$irqdir/smp_affinity" >> "$OUT/nic_irq_affinity.txt" 2>&1
cat "$irqdir/smp_affinity_list" >> "$OUT/nic_irq_affinity.txt" 2>&1
fi
done 2>/dev/null
fi
# === NEW: Kernel timers/delays ===
[ -r /proc/timer_list ] && head -100 /proc/timer_list > "$OUT/timer_list.txt" 2>&1
# === NEW: Softirq statistics ===
cat /proc/softirqs > "$OUT/softirqs.txt" 2>&1 || true
# === NEW: System uptime at collection moment ===
echo "Collection uptime: $(cat /proc/uptime)" > "$OUT/collection_timing.txt"
echo "System clock: $(date 2>/dev/null || echo 'unavailable')" >> "$OUT/collection_timing.txt"
# -----------------------------------------------------------------------------
# 8. Initramfs contents (if we can see /boot)
# -----------------------------------------------------------------------------
echo "Checking initramfs..."
ls -la /boot/init* /boot/vmlinuz* > "$OUT/boot_files.txt" 2>/dev/null || echo "no /boot access" > "$OUT/boot_files.txt"
# Detect initramfs compression via magic bytes
INITRD=""
KVER=$(uname -r)
for f in "/boot/initrd.img-$KVER" "/boot/initramfs-$KVER.img"; do
[ -r "$f" ] && INITRD="$f" && break
done
if [ -n "$INITRD" ]; then
echo "Found: $INITRD" > "$OUT/initrd_found.txt"
# Magic byte detection
MAGIC=$(dd if="$INITRD" bs=1 count=4 2>/dev/null | od -An -tx1 | tr -d ' ')
case "$MAGIC" in
1f8b*) echo "gzip" ;;
fd37*) echo "xz" ;;
28b5*) echo "zstd" ;;
0422*) echo "lz4" ;;
3037*) echo "cpio" ;;
*) echo "unknown:$MAGIC" ;;
esac > "$OUT/initrd_compression.txt"
# Hash if possible
if command -v md5sum >/dev/null 2>&1; then
md5sum "$INITRD" > "$OUT/initrd_md5.txt" 2>&1
fi
else
echo "no initrd found" > "$OUT/initrd_found.txt"
fi
# -----------------------------------------------------------------------------
# 9. Create file list manifest
# -----------------------------------------------------------------------------
echo "Creating manifest..."
ls -la "$OUT"/ > "$OUT/00_manifest.txt" 2>&1
# Checksums
if command -v md5sum >/dev/null 2>&1; then
(cd "$OUT" && md5sum * 2>/dev/null) > "$OUT/00_checksums.txt"
fi
# -----------------------------------------------------------------------------
# 10. Post-hang Repeated Collection (NEW SECTION)
# -----------------------------------------------------------------------------
# If the hang is happening, this captures state AFTER the hang started
echo "Capturing post-hang state..."
# Wait a brief moment then re-capture critical info
sleep 2 2>/dev/null || true
if command -v ethtool >/dev/null 2>&1 && [ -n "$IFACE" ]; then
ethtool -S "$IFACE" > "$OUT/ethtool_S_post.txt" 2>&1 || true
fi
cat /proc/interrupts > "$OUT/proc_interrupts_post.txt" 2>&1
dmesg | tail -100 > "$OUT/dmesg_tail_post.txt" 2>&1 || true
# === NEW: Capture multiple PHY/MAC status samples over time ===
echo "Sampling dmesg for Hardware Unit Hang patterns..."
dmesg | grep -A15 "Detected Hardware Unit Hang" | head -50 > "$OUT/hang_details.txt" 2>/dev/null || true
# -----------------------------------------------------------------------------
# 11. Diagnostic Commands Hints
# -----------------------------------------------------------------------------
cat > "$OUT/DIAGNOSTIC_HINTS.txt" << 'HINTS_EOF'
=== Manual Diagnostic Commands to Try ===
1. PHY Reset (try before hang occurs):
ethtool -s enp0s31f6 autoneg off speed 100 duplex full
sleep 2
ethtool -s enp0s31f6 autoneg on
2. Disable Flow Control:
ethtool -A enp0s31f6 rx off tx off autoneg off
3. Force PCI device reset:
echo 1 > /sys/bus/pci/devices/0000:00:1f.6/reset
4. Check if PHY registers are readable:
ethtool -d enp0s31f6
5. Try different autoneg settings:
ethtool -s enp0s31f6 autoneg on advertise 0x020
6. Try disabling EEE (Energy Efficient Ethernet):
ethtool --set-eee enp0s31f6 eee off
7. If lspci available, check device status:
lspci -vvv -s 00:1f.6
8. Reload module with debug:
rmmod e1000e
modprobe e1000e debug=16
HINTS_EOF
# -----------------------------------------------------------------------------
# Done
# -----------------------------------------------------------------------------
echo ""
echo "=== Collection Complete (Enhanced v2) ==="
echo "Output: $OUT"
echo "Files collected: $(ls -1 "$OUT" | wc -l)"
echo ""
echo "To copy to USB:"
echo " mount /dev/sda1 /mnt"
echo " cp -a $OUT /mnt/"
echo " sync && umount /mnt"
echo ""
echo "See $OUT/DIAGNOSTIC_HINTS.txt for manual commands to try"
echo ""
#!/bin/sh
# =============================================================================
# e1000e Data Collector Script
# Purpose: Collect comprehensive system/driver data for comparison between
# BusyBox/initramfs and full system environments
# =============================================================================
# =============================================================================
# DEPENDENCIES / TOOLS REQUIRED
# =============================================================================
#
# MINIMAL (Required for BusyBox/initramfs - include these in initramfs):
# - sh (BusyBox sh or dash)
# - cat, echo, test, mkdir, cp, ls, readlink
# - dd (for magic byte detection)
# - od (for hex output)
# - cut, tr, basename, dirname
# - find (BusyBox find)
# - sort (BusyBox sort)
# - grep (BusyBox grep)
# - head, tail
# - date (for timestamp)
# - sync
# - mount, umount (if saving to external media)
#
# OPTIONAL (Enhanced data collection - nice to have):
# - md5sum or sha256sum (checksums)
# - ip (iproute2 - network state)
# - ethtool (NIC diagnostics)
# - dmesg (kernel ring buffer)
# - lspci (PCI device info)
# - modinfo (module information)
# - lsmod (formatted module list)
# - zcat/xzcat/zstdcat (config.gz extraction)
# - file (magic detection)
# - cpio (initramfs extraction)
#
# FULL SYSTEM ONLY:
# - journalctl (systemd logs)
# - lsinitramfs / unmkinitramfs (initramfs inspection)
# - update-initramfs / dracut / mkinitcpio (rebuild)
#
# =============================================================================
set -e
# =============================================================================
# CONFIGURATION
# =============================================================================
# Target PCI device (e1000e NIC)
PCI_DEVICE="0000:00:1f.6"
# Network interface name (adjust if different)
NET_IFACE="${NET_IFACE:-eth0}"
# Output directory (override with environment variable or first argument)
OUT_DIR="${1:-${OUT_DIR:-/tmp/e1000e-manifest-$(date +%Y%m%d-%H%M%S)}}"
# =============================================================================
# HELPER FUNCTIONS
# =============================================================================
log() {
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $*"
}
log_section() {
echo ""
echo "=============================================="
echo " $*"
echo "=============================================="
}
# Check if command exists
cmd_exists() {
command -v "$1" >/dev/null 2>&1
}
# Safe cat with error handling
safe_cat() {
cat "$1" 2>/dev/null || echo "[ERROR: Cannot read $1]"
}
# Safe read of sysfs/procfs value
sysfs_read() {
local path="$1"
local name="$2"
if [ -e "$path" ]; then
echo "${name}=$(cat "$path" 2>/dev/null || echo '[unreadable]')"
else
echo "${name}=[not present]"
fi
}
# Detect environment type
detect_environment() {
local pid1_comm=""
if [ -r /proc/1/comm ]; then
pid1_comm=$(cat /proc/1/comm 2>/dev/null)
fi
case "$pid1_comm" in
systemd)
echo "systemd"
;;
init)
# Could be sysvinit or busybox init
if [ -x /bin/busybox ] || grep -q "BusyBox" /proc/1/cmdline 2>/dev/null; then
echo "busybox"
else
echo "sysvinit"
fi
;;
sh|ash|bash|dash)
echo "initramfs-shell"
;;
*)
if [ -x /bin/busybox ]; then
echo "busybox"
elif [ -d /run/systemd/system ]; then
echo "systemd"
else
echo "unknown"
fi
;;
esac
}
# =============================================================================
# DATA COLLECTION FUNCTIONS
# =============================================================================
collect_boot_identity() {
log_section "Boot Identity"
local section_dir="$OUT_DIR/01_boot_identity"
mkdir -p "$section_dir"
# Kernel version
log "Collecting kernel version..."
uname -a > "$section_dir/uname_a.txt" 2>&1
uname -r > "$section_dir/uname_r.txt" 2>&1
# Kernel command line (authoritative boot args)
log "Collecting kernel command line..."
safe_cat /proc/cmdline > "$section_dir/proc_cmdline.txt"
# UEFI vs BIOS detection
log "Detecting firmware mode..."
if [ -d /sys/firmware/efi ]; then
echo "UEFI" > "$section_dir/firmware_mode.txt"
ls -la /sys/firmware/efi/ > "$section_dir/efi_vars_ls.txt" 2>&1 || true
else
echo "BIOS/Legacy" > "$section_dir/firmware_mode.txt"
fi
# PID 1 info (what's running the system)
log "Collecting PID 1 info..."
safe_cat /proc/1/comm > "$section_dir/pid1_comm.txt"
tr '\0' ' ' < /proc/1/cmdline > "$section_dir/pid1_cmdline.txt" 2>/dev/null || echo "[unreadable]" > "$section_dir/pid1_cmdline.txt"
# Environment detection
detect_environment > "$section_dir/environment_type.txt"
# Secure Boot / Module signature enforcement
log "Checking secure boot / module signing..."
{
echo "=== Kernel cmdline secure boot indicators ==="
grep -oE '(module\.sig_enforce=[^ ]*|efi=[^ ]*|secureboot[^ ]*)' /proc/cmdline 2>/dev/null || echo "[none found]"
echo ""
echo "=== Module signature enforce sysctl ==="
sysfs_read /proc/sys/kernel/module_sig_enforce "module_sig_enforce"
echo ""
echo "=== Secure boot EFI variable ==="
if [ -r /sys/firmware/efi/efivars/SecureBoot-* ]; then
echo "SecureBoot EFI var present"
ls -la /sys/firmware/efi/efivars/SecureBoot-* 2>/dev/null || true
else
echo "SecureBoot EFI var not found"
fi
} > "$section_dir/secure_boot_info.txt" 2>&1
}
collect_kernel_config() {
log_section "Kernel Configuration"
local section_dir="$OUT_DIR/02_kernel_config"
mkdir -p "$section_dir"
log "Collecting kernel config..."
# Try /proc/config.gz first (if CONFIG_IKCONFIG_PROC=y)
if [ -r /proc/config.gz ]; then
log " Found /proc/config.gz"
if cmd_exists zcat; then
zcat /proc/config.gz > "$section_dir/kernel_config.txt" 2>&1
elif cmd_exists gunzip; then
gunzip -c /proc/config.gz > "$section_dir/kernel_config.txt" 2>&1
else
cp /proc/config.gz "$section_dir/config.gz"
echo "[config.gz copied, no zcat available to extract]" > "$section_dir/kernel_config.txt"
fi
# Try /boot/config-<version>
elif [ -r "/boot/config-$(uname -r)" ]; then
log " Found /boot/config-$(uname -r)"
cp "/boot/config-$(uname -r)" "$section_dir/kernel_config.txt"
else
echo "[Kernel config not available]" > "$section_dir/kernel_config.txt"
fi
# Extract e1000e-specific config if available
if [ -s "$section_dir/kernel_config.txt" ] && [ "$(head -c 1 "$section_dir/kernel_config.txt")" != "[" ]; then
log " Extracting e1000e config options..."
grep -E '^CONFIG_(E1000|E1000E|INTEL)' "$section_dir/kernel_config.txt" > "$section_dir/e1000e_config.txt" 2>/dev/null || echo "[no e1000e config found]" > "$section_dir/e1000e_config.txt"
# Module vs built-in determination
grep -E '^CONFIG_E1000E=' "$section_dir/kernel_config.txt" > "$section_dir/e1000e_builtin_or_module.txt" 2>/dev/null || echo "[CONFIG_E1000E not found]" > "$section_dir/e1000e_builtin_or_module.txt"
fi
}
collect_modules_info() {
log_section "Modules Information"
local section_dir="$OUT_DIR/03_modules"
mkdir -p "$section_dir"
# Loaded modules
log "Collecting loaded modules..."
safe_cat /proc/modules > "$section_dir/proc_modules.txt"
if cmd_exists lsmod; then
lsmod > "$section_dir/lsmod.txt" 2>&1
fi
# All modules in /sys/module
log "Listing /sys/module entries..."
ls -1 /sys/module > "$section_dir/sys_module_list.txt" 2>&1
# e1000e specific module info
log "Collecting e1000e module parameters..."
if [ -d /sys/module/e1000e ]; then
echo "e1000e module is loaded" > "$section_dir/e1000e_status.txt"
# Parameters
if [ -d /sys/module/e1000e/parameters ]; then
mkdir -p "$section_dir/e1000e_parameters"
for param in /sys/module/e1000e/parameters/*; do
if [ -r "$param" ]; then
pname=$(basename "$param")
echo "${pname}=$(cat "$param" 2>/dev/null)" >> "$section_dir/e1000e_params.txt"
cat "$param" > "$section_dir/e1000e_parameters/${pname}" 2>/dev/null
fi
done
else
echo "[no parameters directory]" > "$section_dir/e1000e_params.txt"
fi
# Module refcount and holders
sysfs_read /sys/module/e1000e/refcnt "refcnt" >> "$section_dir/e1000e_status.txt"
if [ -d /sys/module/e1000e/holders ]; then
echo "holders: $(ls /sys/module/e1000e/holders 2>/dev/null | tr '\n' ' ')" >> "$section_dir/e1000e_status.txt"
fi
else
echo "e1000e module is NOT loaded (may be built-in or not present)" > "$section_dir/e1000e_status.txt"
echo "[module not loaded]" > "$section_dir/e1000e_params.txt"
fi
# modinfo if available
if cmd_exists modinfo; then
log "Collecting modinfo for e1000e..."
modinfo e1000e > "$section_dir/modinfo_e1000e.txt" 2>&1 || echo "[modinfo failed]" > "$section_dir/modinfo_e1000e.txt"
fi
# modprobe configuration
log "Collecting modprobe configuration..."
{
echo "=== /etc/modprobe.d/ ==="
if [ -d /etc/modprobe.d ]; then
ls -la /etc/modprobe.d/ 2>/dev/null
echo ""
for f in /etc/modprobe.d/*.conf; do
if [ -r "$f" ]; then
echo "--- $f ---"
cat "$f"
echo ""
fi
done
else
echo "[directory not present]"
fi
echo ""
echo "=== /lib/modprobe.d/ ==="
if [ -d /lib/modprobe.d ]; then
ls -la /lib/modprobe.d/ 2>/dev/null
for f in /lib/modprobe.d/*.conf; do
if [ -r "$f" ]; then
echo "--- $f ---"
cat "$f"
echo ""
fi
done
else
echo "[directory not present]"
fi
echo ""
echo "=== /usr/lib/modprobe.d/ ==="
if [ -d /usr/lib/modprobe.d ]; then
ls -la /usr/lib/modprobe.d/ 2>/dev/null
else
echo "[directory not present]"
fi
} > "$section_dir/modprobe_config.txt" 2>&1
# e1000e specific modprobe options
log "Extracting e1000e modprobe options..."
grep -r -h "e1000e" /etc/modprobe.d/ /lib/modprobe.d/ /usr/lib/modprobe.d/ 2>/dev/null | grep -v "^#" > "$section_dir/e1000e_modprobe_opts.txt" || echo "[no e1000e options found]" > "$section_dir/e1000e_modprobe_opts.txt"
}
collect_pci_info() {
log_section "PCI Device Information"
local section_dir="$OUT_DIR/04_pci"
mkdir -p "$section_dir"
local pci_path="/sys/bus/pci/devices/${PCI_DEVICE}"
log "Collecting PCI device info for ${PCI_DEVICE}..."
if [ -d "$pci_path" ]; then
echo "PCI device ${PCI_DEVICE} exists" > "$section_dir/device_status.txt"
# Basic device info
{
sysfs_read "$pci_path/vendor" "vendor"
sysfs_read "$pci_path/device" "device"
sysfs_read "$pci_path/subsystem_vendor" "subsystem_vendor"
sysfs_read "$pci_path/subsystem_device" "subsystem_device"
sysfs_read "$pci_path/class" "class"
sysfs_read "$pci_path/revision" "revision"
sysfs_read "$pci_path/irq" "irq"
sysfs_read "$pci_path/numa_node" "numa_node"
sysfs_read "$pci_path/enable" "enable"
sysfs_read "$pci_path/broken_parity_status" "broken_parity_status"
sysfs_read "$pci_path/msi_bus" "msi_bus"
sysfs_read "$pci_path/d3cold_allowed" "d3cold_allowed"
} > "$section_dir/pci_device_attrs.txt"
# Driver binding
log " Checking driver binding..."
if [ -L "$pci_path/driver" ]; then
readlink "$pci_path/driver" > "$section_dir/driver_link.txt" 2>&1
basename "$(readlink "$pci_path/driver")" > "$section_dir/bound_driver.txt" 2>&1
else
echo "[no driver bound]" > "$section_dir/driver_link.txt"
echo "[no driver bound]" > "$section_dir/bound_driver.txt"
fi
# Power management
log " Collecting power management state..."
if [ -d "$pci_path/power" ]; then
{
echo "=== Power directory listing ==="
ls -la "$pci_path/power/"
echo ""
echo "=== Power attributes ==="
for attr in control runtime_status runtime_suspended_time runtime_active_time autosuspend_delay_ms; do
sysfs_read "$pci_path/power/$attr" "$attr"
done
} > "$section_dir/power_state.txt" 2>&1
else
echo "[power directory not present]" > "$section_dir/power_state.txt"
fi
# Resource info
log " Collecting resource info..."
safe_cat "$pci_path/resource" > "$section_dir/resource.txt"
# MSI/MSI-X info
if [ -d "$pci_path/msi_irqs" ]; then
ls -la "$pci_path/msi_irqs/" > "$section_dir/msi_irqs.txt" 2>&1
else
echo "[no msi_irqs directory]" > "$section_dir/msi_irqs.txt"
fi
# Full sysfs dump of the device
ls -la "$pci_path/" > "$section_dir/sysfs_ls.txt" 2>&1
else
echo "PCI device ${PCI_DEVICE} NOT FOUND" > "$section_dir/device_status.txt"
log " WARNING: PCI device ${PCI_DEVICE} not found!"
fi
# lspci if available
if cmd_exists lspci; then
log "Collecting lspci output..."
lspci -v > "$section_dir/lspci_v.txt" 2>&1
lspci -vvv -s "$PCI_DEVICE" > "$section_dir/lspci_vvv_device.txt" 2>&1 || true
lspci -nn > "$section_dir/lspci_nn.txt" 2>&1
fi
# All network-class PCI devices
log "Listing all PCI devices..."
ls -la /sys/bus/pci/devices/ > "$section_dir/all_pci_devices.txt" 2>&1
}
collect_interrupt_info() {
log_section "Interrupt Information"
local section_dir="$OUT_DIR/05_interrupts"
mkdir -p "$section_dir"
log "Collecting interrupt info..."
safe_cat /proc/interrupts > "$section_dir/proc_interrupts.txt"
# Filter for e1000e/eth related interrupts
grep -E "(e1000e|eth|enp|eno)" /proc/interrupts > "$section_dir/nic_interrupts.txt" 2>/dev/null || echo "[no NIC interrupts found]" > "$section_dir/nic_interrupts.txt"
# IRQ info
if [ -d /proc/irq ]; then
ls -la /proc/irq/ > "$section_dir/proc_irq_ls.txt" 2>&1
fi
# Softirqs
safe_cat /proc/softirqs > "$section_dir/proc_softirqs.txt"
}
collect_network_info() {
log_section "Network Information"
local section_dir="$OUT_DIR/06_network"
mkdir -p "$section_dir"
# Detect actual interface name
log "Detecting network interfaces..."
ls -la /sys/class/net/ > "$section_dir/net_interfaces_sysfs.txt" 2>&1
# Try to find e1000e interface
local actual_iface="$NET_IFACE"
if [ -d "/sys/class/net/${NET_IFACE}/device" ]; then
actual_iface="$NET_IFACE"
else
# Try common names
for iface in eth0 enp0s31f6 eno1 eno2 enp0s25; do
if [ -d "/sys/class/net/${iface}/device" ]; then
# Check if it's our PCI device
if [ "$(readlink /sys/class/net/${iface}/device 2>/dev/null | grep -o '[0-9a-f:.]*$')" = "$PCI_DEVICE" ]; then
actual_iface="$iface"
break
fi
fi
done
fi
echo "$actual_iface" > "$section_dir/detected_interface.txt"
log " Using interface: $actual_iface"
# ip commands if available
if cmd_exists ip; then
log "Collecting ip command output..."
ip link show > "$section_dir/ip_link.txt" 2>&1
ip addr show > "$section_dir/ip_addr.txt" 2>&1
ip -s link show > "$section_dir/ip_s_link.txt" 2>&1
ip route show > "$section_dir/ip_route.txt" 2>&1
ip -d link show "$actual_iface" > "$section_dir/ip_d_link_iface.txt" 2>&1 || true
fi
# Interface sysfs info
local net_sysfs="/sys/class/net/${actual_iface}"
if [ -d "$net_sysfs" ]; then
log "Collecting interface sysfs info..."
{
sysfs_read "$net_sysfs/operstate" "operstate"
sysfs_read "$net_sysfs/carrier" "carrier"
sysfs_read "$net_sysfs/speed" "speed"
sysfs_read "$net_sysfs/duplex" "duplex"
sysfs_read "$net_sysfs/mtu" "mtu"
sysfs_read "$net_sysfs/flags" "flags"
sysfs_read "$net_sysfs/tx_queue_len" "tx_queue_len"
sysfs_read "$net_sysfs/addr_len" "addr_len"
sysfs_read "$net_sysfs/address" "address"
sysfs_read "$net_sysfs/broadcast" "broadcast"
} > "$section_dir/interface_sysfs.txt"
# Device link
readlink "$net_sysfs/device" > "$section_dir/interface_pci_device.txt" 2>&1 || echo "[no device link]" > "$section_dir/interface_pci_device.txt"
# Statistics
if [ -d "$net_sysfs/statistics" ]; then
for stat in "$net_sysfs/statistics"/*; do
if [ -r "$stat" ]; then
echo "$(basename "$stat")=$(cat "$stat")"
fi
done > "$section_dir/interface_statistics.txt" 2>&1
fi
else
echo "[interface $actual_iface not found in sysfs]" > "$section_dir/interface_sysfs.txt"
fi
# ethtool if available
if cmd_exists ethtool; then
log "Collecting ethtool output..."
ethtool "$actual_iface" > "$section_dir/ethtool.txt" 2>&1 || true
ethtool -i "$actual_iface" > "$section_dir/ethtool_i.txt" 2>&1 || true
ethtool -k "$actual_iface" > "$section_dir/ethtool_k.txt" 2>&1 || true
ethtool -S "$actual_iface" > "$section_dir/ethtool_S.txt" 2>&1 || true
ethtool -c "$actual_iface" > "$section_dir/ethtool_c.txt" 2>&1 || true
ethtool -g "$actual_iface" > "$section_dir/ethtool_g.txt" 2>&1 || true
ethtool -a "$actual_iface" > "$section_dir/ethtool_a.txt" 2>&1 || true
ethtool -T "$actual_iface" > "$section_dir/ethtool_T.txt" 2>&1 || true
ethtool --show-eee "$actual_iface" > "$section_dir/ethtool_eee.txt" 2>&1 || true
ethtool -d "$actual_iface" > "$section_dir/ethtool_d.txt" 2>&1 || true
ethtool -e "$actual_iface" > "$section_dir/ethtool_e.txt" 2>&1 || true
fi
# /proc/net info
log "Collecting /proc/net info..."
safe_cat /proc/net/dev > "$section_dir/proc_net_dev.txt"
safe_cat /proc/net/dev_mcast > "$section_dir/proc_net_dev_mcast.txt"
}
collect_dmesg() {
log_section "Kernel Messages (dmesg)"
local section_dir="$OUT_DIR/07_dmesg"
mkdir -p "$section_dir"
if cmd_exists dmesg; then
log "Collecting dmesg..."
dmesg > "$section_dir/dmesg_full.txt" 2>&1
# Timestamps if available
dmesg -T > "$section_dir/dmesg_T.txt" 2>&1 || true
# Filter for relevant messages
log "Extracting e1000e-related messages..."
grep -iE "(e1000e|e1000|intel.*ethernet)" "$section_dir/dmesg_full.txt" > "$section_dir/dmesg_e1000e.txt" 2>/dev/null || echo "[no e1000e messages]" > "$section_dir/dmesg_e1000e.txt"
log "Extracting network-related messages..."
grep -iE "(eth|enp|eno|link|carrier|NIC|network)" "$section_dir/dmesg_full.txt" > "$section_dir/dmesg_network.txt" 2>/dev/null || true
log "Extracting PCI-related messages..."
grep -iE "(pci|00:1f)" "$section_dir/dmesg_full.txt" > "$section_dir/dmesg_pci.txt" 2>/dev/null || true
log "Extracting error/warning messages..."
grep -iE "(error|fail|warn|timeout|reset|hang|watchdog)" "$section_dir/dmesg_full.txt" > "$section_dir/dmesg_errors.txt" 2>/dev/null || true
# Last 500 lines
tail -n 500 "$section_dir/dmesg_full.txt" > "$section_dir/dmesg_tail500.txt"
else
# Fallback: try /dev/kmsg if readable
if [ -r /dev/kmsg ]; then
log "dmesg not available, trying /dev/kmsg..."
timeout 1 cat /dev/kmsg > "$section_dir/kmsg.txt" 2>&1 || true
else
echo "[dmesg not available]" > "$section_dir/dmesg_full.txt"
fi
fi
# Kernel log levels
safe_cat /proc/sys/kernel/printk > "$section_dir/printk_levels.txt"
}
collect_journalctl() {
log_section "Systemd Journal (if available)"
local section_dir="$OUT_DIR/08_journal"
mkdir -p "$section_dir"
if cmd_exists journalctl; then
log "Collecting journalctl output..."
journalctl -b --no-pager > "$section_dir/journalctl_b.txt" 2>&1 || true
journalctl -b -k --no-pager > "$section_dir/journalctl_b_k.txt" 2>&1 || true
journalctl -b -p err --no-pager > "$section_dir/journalctl_b_err.txt" 2>&1 || true
# e1000e specific
journalctl -b --no-pager | grep -iE "e1000e" > "$section_dir/journalctl_e1000e.txt" 2>/dev/null || true
else
echo "[journalctl not available - likely BusyBox/initramfs environment]" > "$section_dir/journalctl_status.txt"
fi
}
collect_initramfs_info() {
log_section "Initramfs Information"
local section_dir="$OUT_DIR/09_initramfs"
mkdir -p "$section_dir"
# Identify which initramfs framework
log "Detecting initramfs framework..."
{
echo "=== Framework Detection ==="
if [ -d /usr/share/initramfs-tools ]; then
echo "initramfs-tools detected"
echo " /usr/share/initramfs-tools exists"
fi
if [ -d /usr/lib/dracut ]; then
echo "dracut detected"
echo " /usr/lib/dracut exists"
fi
if [ -f /etc/mkinitcpio.conf ]; then
echo "mkinitcpio detected"
echo " /etc/mkinitcpio.conf exists"
fi
} > "$section_dir/framework_detection.txt"
# List initramfs files
log "Listing initramfs images..."
{
echo "=== /boot contents ==="
ls -la /boot/initrd* /boot/initramfs* 2>/dev/null || echo "[no initrd/initramfs found in /boot]"
echo ""
echo "=== Current kernel initramfs ==="
local kver=$(uname -r)
for f in "/boot/initrd.img-${kver}" "/boot/initramfs-${kver}.img" "/boot/initrd-${kver}" "/boot/initramfs-linux.img"; do
if [ -e "$f" ]; then
echo "Found: $f"
ls -la "$f"
fi
done
} > "$section_dir/initramfs_files.txt" 2>&1
# Hash initramfs if found
log "Computing initramfs checksums..."
local kver=$(uname -r)
local initrd=""
for f in "/boot/initrd.img-${kver}" "/boot/initramfs-${kver}.img" "/boot/initrd-${kver}"; do
if [ -e "$f" ]; then
initrd="$f"
break
fi
done
if [ -n "$initrd" ] && [ -e "$initrd" ]; then
if cmd_exists sha256sum; then
sha256sum "$initrd" > "$section_dir/initramfs_sha256.txt" 2>&1
elif cmd_exists md5sum; then
md5sum "$initrd" > "$section_dir/initramfs_md5.txt" 2>&1
fi
# Detect compression type
log "Detecting initramfs compression..."
if cmd_exists file; then
file "$initrd" > "$section_dir/initramfs_type.txt" 2>&1
else
# Manual magic detection
local magic=$(dd if="$initrd" bs=1 count=6 2>/dev/null | od -An -tx1 | tr -d ' \n')
case "$magic" in
1f8b*) echo "gzip compressed" ;;
fd377a585a00*) echo "xz compressed" ;;
28b52ffd*) echo "zstd compressed" ;;
04224d18*) echo "lz4 compressed" ;;
303730*) echo "cpio archive (uncompressed or multi-segment)" ;;
*) echo "unknown (magic: $magic)" ;;
esac > "$section_dir/initramfs_type.txt"
fi
else
echo "[no initramfs found for kernel $kver]" > "$section_dir/initramfs_type.txt"
fi
# lsinitramfs if available
if cmd_exists lsinitramfs && [ -n "$initrd" ] && [ -e "$initrd" ]; then
log "Listing initramfs contents..."
lsinitramfs "$initrd" > "$section_dir/lsinitramfs_full.txt" 2>&1 || true
# Filter for interesting items
grep -E "(e1000|modprobe|modules)" "$section_dir/lsinitramfs_full.txt" > "$section_dir/lsinitramfs_modules.txt" 2>/dev/null || true
grep -E "\.conf$" "$section_dir/lsinitramfs_full.txt" > "$section_dir/lsinitramfs_configs.txt" 2>/dev/null || true
fi
# initramfs-tools config
if [ -d /etc/initramfs-tools ]; then
log "Collecting initramfs-tools config..."
mkdir -p "$section_dir/initramfs-tools"
cp /etc/initramfs-tools/initramfs.conf "$section_dir/initramfs-tools/" 2>/dev/null || true
cp /etc/initramfs-tools/modules "$section_dir/initramfs-tools/" 2>/dev/null || true
ls -la /etc/initramfs-tools/ > "$section_dir/initramfs-tools/ls.txt" 2>&1
fi
# dracut config
if [ -d /etc/dracut.conf.d ] || [ -f /etc/dracut.conf ]; then
log "Collecting dracut config..."
mkdir -p "$section_dir/dracut"
cp /etc/dracut.conf "$section_dir/dracut/" 2>/dev/null || true
if [ -d /etc/dracut.conf.d ]; then
cp -r /etc/dracut.conf.d "$section_dir/dracut/" 2>/dev/null || true
fi
fi
}
collect_process_info() {
log_section "Process Information"
local section_dir="$OUT_DIR/10_processes"
mkdir -p "$section_dir"
log "Collecting process list..."
if cmd_exists ps; then
ps aux > "$section_dir/ps_aux.txt" 2>&1 || ps > "$section_dir/ps.txt" 2>&1 || true
fi
# Mount points
log "Collecting mount points..."
cat /proc/mounts > "$section_dir/proc_mounts.txt" 2>&1
if cmd_exists mount; then
mount > "$section_dir/mount.txt" 2>&1
fi
# Memory info
safe_cat /proc/meminfo > "$section_dir/meminfo.txt"
# CPU info
safe_cat /proc/cpuinfo > "$section_dir/cpuinfo.txt"
}
collect_system_info() {
log_section "Additional System Information"
local section_dir="$OUT_DIR/11_system"
mkdir -p "$section_dir"
# DMI/SMBIOS info
log "Collecting DMI info..."
if [ -d /sys/class/dmi/id ]; then
{
for f in /sys/class/dmi/id/*; do
if [ -r "$f" ] && [ ! -d "$f" ]; then
echo "$(basename "$f")=$(cat "$f" 2>/dev/null || echo '[unreadable]')"
fi
done
} > "$section_dir/dmi_info.txt" 2>&1
fi
# Boot time
safe_cat /proc/uptime > "$section_dir/uptime.txt"
# ACPI info (power management related)
if [ -d /sys/firmware/acpi ]; then
ls -la /sys/firmware/acpi/ > "$section_dir/acpi_ls.txt" 2>&1
fi
# /proc/version
safe_cat /proc/version > "$section_dir/proc_version.txt"
# Available kernel modules in /lib/modules
local kver=$(uname -r)
if [ -d "/lib/modules/${kver}" ]; then
log "Listing available kernel modules..."
find "/lib/modules/${kver}" -name "*.ko*" 2>/dev/null | head -n 1000 > "$section_dir/available_modules.txt"
# Check for e1000e specifically
find "/lib/modules/${kver}" -name "e1000e*" > "$section_dir/e1000e_module_path.txt" 2>/dev/null || echo "[not found]" > "$section_dir/e1000e_module_path.txt"
fi
}
generate_manifest() {
log_section "Generating Manifest"
local manifest="$OUT_DIR/MANIFEST.txt"
{
echo "========================================"
echo " E1000E Data Collection Manifest"
echo "========================================"
echo ""
echo "Collection timestamp: $(date '+%Y-%m-%d %H:%M:%S %Z')"
echo "Kernel version: $(uname -r)"
echo "Environment type: $(detect_environment)"
echo "PCI device: ${PCI_DEVICE}"
echo "Network interface: ${NET_IFACE}"
echo "Output directory: ${OUT_DIR}"
echo ""
echo "========================================"
echo " Available Tools at Collection Time"
echo "========================================"
for cmd in sh cat ls find grep sort dmesg ip ethtool lspci lsmod modinfo journalctl lsinitramfs file sha256sum md5sum zcat; do
if cmd_exists "$cmd"; then
echo " [X] $cmd"
else
echo " [ ] $cmd"
fi
done
echo ""
echo "========================================"
echo " Collected Files"
echo "========================================"
find "$OUT_DIR" -type f | sort | while read -r f; do
echo " $f"
done
} > "$manifest"
# Create checksums for all collected files
log "Creating checksums..."
if cmd_exists sha256sum; then
find "$OUT_DIR" -type f ! -name "CHECKSUMS.txt" -exec sha256sum {} \; > "$OUT_DIR/CHECKSUMS.txt" 2>/dev/null || true
elif cmd_exists md5sum; then
find "$OUT_DIR" -type f ! -name "CHECKSUMS.txt" -exec md5sum {} \; > "$OUT_DIR/CHECKSUMS.txt" 2>/dev/null || true
fi
}
# =============================================================================
# MAIN EXECUTION
# =============================================================================
main() {
echo "========================================"
echo " E1000E Data Collector"
echo " Output: ${OUT_DIR}"
echo "========================================"
echo ""
mkdir -p "$OUT_DIR"
# Detect and log environment
ENV_TYPE=$(detect_environment)
log "Detected environment: $ENV_TYPE"
echo "$ENV_TYPE" > "$OUT_DIR/environment_type.txt"
# Run all collection functions
collect_boot_identity
collect_kernel_config
collect_modules_info
collect_pci_info
collect_interrupt_info
collect_network_info
collect_dmesg
collect_journalctl
collect_initramfs_info
collect_process_info
collect_system_info
generate_manifest
log_section "Collection Complete"
echo ""
echo "Data collected to: $OUT_DIR"
echo ""
echo "To save to external media (USB/boot partition):"
echo " mount /dev/sdX1 /mnt"
echo " cp -a $OUT_DIR /mnt/"
echo " sync && umount /mnt"
echo ""
echo "For comparison, run this script on both:"
echo " 1. BusyBox/initramfs environment (boot with break=premount)"
echo " 2. Fully booted system"
echo ""
echo "Then diff the results:"
echo " diff -r /path/to/busybox-manifest /path/to/system-manifest"
echo ""
}
# Run main
main "$@"
#!/bin/sh
# net_collect.sh - collect NIC and driver diagnostics in busybox/initramfs
OUT="${1:-/tmp/netdiag-$(date +%Y%m%d-%H%M%S).log}"
echo "==== NET DIAGNOSTIC DUMP $(date) ====" > "$OUT"
echo >> "$OUT"
echo "== uname -a ==" >> "$OUT"
uname -a >> "$OUT" 2>&1
echo >> "$OUT"
echo "== /proc/cmdline ==" >> "$OUT"
cat /proc/cmdline >> "$OUT" 2>&1
echo >> "$OUT"
echo "== Loaded modules ==" >> "$OUT"
# busybox lsmod is fine
lsmod >> "$OUT" 2>&1
echo >> "$OUT"
echo "== PCI info for Intel NICs (if any) ==" >> "$OUT"
if [ -d /sys/bus/pci/devices ]; then
for p in /sys/bus/pci/devices/*; do
[ -e "$p/vendor" ] || continue
vend=$(cat "$p/vendor" 2>/dev/null)
dev=$(cat "$p/device" 2>/dev/null)
# 0x8086 is Intel
if [ "$vend" = "0x8086" ]; then
echo "--- $p ---" >> "$OUT"
echo "vendor=$vend device=$dev" >> "$OUT"
[ -e "$p/class" ] && echo "class=$(cat "$p/class")" >> "$OUT"
[ -e "$p/subsystem_vendor" ] && echo "subsystem_vendor=$(cat "$p/subsystem_vendor")" >> "$OUT"
[ -e "$p/subsystem_device" ] && echo "subsystem_device=$(cat "$p/subsystem_device")" >> "$OUT"
fi
done
fi
echo >> "$OUT"
echo "== Network interfaces ==" >> "$OUT"
for n in /sys/class/net/*; do
IF=$(basename "$n")
echo "--- $IF ---" >> "$OUT"
if [ -e "$n/device/driver" ]; then
drv=$(readlink -f "$n/device/driver" 2>/dev/null | sed 's#.*/##')
echo "driver=$drv" >> "$OUT"
else
echo "driver=(none)" >> "$OUT"
fi
echo "ip link show $IF:" >> "$OUT"
ip link show "$IF" >> "$OUT" 2>&1
echo "ethtool $IF:" >> "$OUT"
ethtool "$IF" >> "$OUT" 2>&1
echo "ethtool -k $IF:" >> "$OUT"
ethtool -k "$IF" >> "$OUT" 2>&1
echo "ethtool -g $IF:" >> "$OUT"
ethtool -g "$IF" >> "$OUT" 2>&1
echo "ethtool -S $IF:" >> "$OUT"
ethtool -S "$IF" >> "$OUT" 2>&1
done
echo >> "$OUT"
echo "== e1000e module parameters (if present) ==" >> "$OUT"
if [ -d /sys/module/e1000e ]; then
for p in /sys/module/e1000e/parameters/*; do
name=$(basename "$p")
val=$(cat "$p" 2>/dev/null)
echo "$name=$val" >> "$OUT"
done
else
echo "e1000e module not loaded" >> "$OUT"
fi
echo >> "$OUT"
echo "== dmesg (last 200 lines) ==" >> "$OUT"
dmesg | tail -n 200 >> "$OUT" 2>&1
echo >> "$OUT"
echo "==== END ====" >> "$OUT"
echo "Written diagnostics to: $OUT"
#!/bin/sh
# net_fuzz_e1000e.sh - brute-test e1000e + ethtool combinations in busybox
LOG="${1:-/tmp/e1000e-fuzz-$(date +%Y%m%d-%H%M%S).log}"
SLEEP_SEC="${SLEEP_SEC:-8}" # time to wait after bringing link up
MAX_ITERS="${MAX_ITERS:-999999}" # safety cap if you tweak loops
echo "==== e1000e fuzz run $(date) ====" > "$LOG"
echo "LOG=$LOG" >> "$LOG"
echo >> "$LOG"
# Find all interfaces driven by e1000e
find_e1000e_ifs() {
for n in /sys/class/net/*; do
IF=$(basename "$n")
drv=$(readlink -f "$n"/device/driver 2>/dev/null | sed 's#.*/##')
[ "$drv" = "e1000e" ] && echo "$IF"
done
}
IFS_LIST=$(find_e1000e_ifs)
if [ -z "$IFS_LIST" ]; then
echo "No interfaces with driver e1000e found" | tee -a "$LOG"
exit 1
fi
echo "Interfaces on e1000e: $IFS_LIST" | tee -a "$LOG"
echo >> "$LOG"
# Helper: reload e1000e with options
reload_e1000e() {
INTMODE="$1"
ITR="$2"
echo "Reloading e1000e IntMode=$INTMODE ITR=$ITR" >> "$LOG"
# remove if loaded
if lsmod | grep -q '^e1000e'; then
rmmod e1000e 2>>"$LOG"
sleep 1
fi
# now load with given options
modprobe e1000e IntMode="$INTMODE" InterruptThrottleRate="$ITR" 2>>"$LOG"
RET=$?
if [ $RET -ne 0 ]; then
echo "modprobe failed: IntMode=$INTMODE ITR=$ITR ret=$RET" >> "$LOG"
return 1
fi
return 0
}
# Helper: configure one interface with ethtool + speed mode
config_if() {
IF="$1"
OFFLOAD_MODE="$2" # on/off
SPEED_MODE="$3" # auto/100
echo "Configuring $IF offload=$OFFLOAD_MODE speed=$SPEED_MODE" >> "$LOG"
# reset link down
ip link set "$IF" down 2>>"$LOG"
# speed
case "$SPEED_MODE" in
auto)
ethtool -s "$IF" autoneg on 2>>"$LOG"
;;
100)
# you might need matching config on switch side
ethtool -s "$IF" speed 100 duplex full autoneg off 2>>"$LOG"
;;
esac
# offloads
if [ "$OFFLOAD_MODE" = "off" ]; then
ethtool -K "$IF" tso off gso off gro off lro off rx off tx off 2>>"$LOG"
ethtool --set-eee "$IF" eee off 2>>"$LOG"
else
# try to restore defaults best-effort
ethtool -K "$IF" tso on gso on gro on rx on tx on 2>>"$LOG"
ethtool --set-eee "$IF" eee on 2>>"$LOG"
fi
# bring up
ip link set "$IF" up 2>>"$LOG"
}
# Helper: capture dmesg delta
snapshot_dmesg() {
dmesg > "$1"
}
dmesg_has_error() {
# grep for patterns that indicate trouble
dmesg_diff="$1"
grep -E "e1000e.*Hardware Unit Hang|NETDEV WATCHDOG|TX Unit Hang|Detected Hardware Unit Hang" "$dmesg_diff" >/dev/null 2>&1
}
# main test loop
ITER=0
for INTMODE in 0 1 2; do
for ITR in 0 3000 1; do
# reload driver for this pair
reload_e1000e "$INTMODE" "$ITR" || continue
# after reloading, recompute interface list (names may change in theory)
IFS_LIST=$(find_e1000e_ifs)
for OFFLOAD_MODE in off on; do
for SPEED_MODE in auto 100; do
ITER=$((ITER+1))
[ $ITER -gt $MAX_ITERS ] && echo "Reached MAX_ITERS=$MAX_ITERS, stopping" >> "$LOG" && exit 0
echo "---- TEST #$ITER ----" >> "$LOG"
echo "IntMode=$INTMODE ITR=$ITR offload=$OFFLOAD_MODE speed=$SPEED_MODE" >> "$LOG"
# snapshot dmesg before
BEFORE="/tmp/dmesg_before_$$"
AFTER="/tmp/dmesg_after_$$"
DIFF="/tmp/dmesg_diff_$$"
snapshot_dmesg "$BEFORE"
# apply config to each e1000e interface
for IF in $IFS_LIST; do
echo "Testing interface $IF" >> "$LOG"
config_if "$IF" "$OFFLOAD_MODE" "$SPEED_MODE"
# Optional: you can add a simple ping here if you know a target
# ping -c 2 -w 3 <gateway_or_host> >/dev/null 2>&1
done
# wait for potential hang/watchdog
sleep "$SLEEP_SEC"
snapshot_dmesg "$AFTER"
# busybox 'diff' might not exist; use a crude way:
# cut new messages from AFTER that are not in BEFORE by tailing
# simplest: just 'tail' and search for patterns
tail -n 100 "$AFTER" > "$DIFF"
if dmesg_has_error "$DIFF"; then
echo "RESULT: PROBLEM DETECTED" >> "$LOG"
echo "Relevant dmesg lines:" >> "$LOG"
grep -E "e1000e.*Hardware Unit Hang|NETDEV WATCHDOG|TX Unit Hang|Detected Hardware Unit Hang" "$DIFF" >> "$LOG"
else
echo "RESULT: OK (no hang/watchdog in last $SLEEP_SEC s)" >> "$LOG"
fi
echo >> "$LOG"
rm -f "$BEFORE" "$AFTER" "$DIFF"
done
done
done
done
echo "==== DONE $(date) ====" >> "$LOG"
echo "Fuzz log written to: $LOG"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment