Overview
Overview
What is a Donor Dump?
A donor dump is a comprehensive snapshot of a physical PCI device’s configuration and capabilities. The PCILeech Firmware Generator uses this information to create firmware that accurately emulates the donor device’s behavior.
Key Information Captured:
Component | Description | Purpose |
---|---|---|
Device Identity | Vendor/Device IDs, Subsystem IDs, Revision | Device identification and driver matching |
Configuration Space | Full 4KB extended PCI configuration | Complete device state and capabilities |
Power Management | MPC/MPR values, power states | Power efficiency and compatibility |
Capabilities | AER, MSI/MSI-X, vendor-specific | Advanced PCI features |
Memory Layout | BAR sizes, Device Serial Number (DSN) | Memory mapping and addressing |
Class Information | 24-bit class code | Device type classification |
When to Use Manual Process
- Debugging: When automated tools fail or produce unexpected results
- Custom Workflows: Integration with existing automation or CI/CD pipelines
- Research: Understanding the donor extraction process in detail
- Troubleshooting: Isolating issues in the firmware generation pipeline
Prerequisites
System Requirements
Requirement | Linux |
---|---|
OS Version | Any modern distribution |
Privileges | Root access (sudo ) |
Shell | Bash/Zsh |
Build Tools | GCC, Make, Kernel Headers |
Quick Prerequisite Check
Linux:
# Check if all prerequisites are available
echo "Checking prerequisites..."
command -v gcc >/dev/null 2>&1 && echo "✓ GCC available" || echo "✗ GCC missing"
command -v make >/dev/null 2>&1 && echo "✓ Make available" || echo "✗ Make missing"
[ -d "/lib/modules/$(uname -r)/build" ] && echo "✓ Kernel headers available" || echo "✗ Kernel headers missing"
[ "$EUID" -eq 0 ] && echo "✓ Running as root" || echo "✗ Need root privileges"
Installing Prerequisites
Debian/Ubuntu
sudo apt-get update && sudo apt-get install -y \
linux-headers-$(uname -r) \
build-essential \
dkms
Fedora/CentOS/RHEL
sudo dnf install -y \
kernel-devel-$(uname -r) \
gcc \
make \
dkms
Arch Linux/Manjaro
sudo pacman -S --needed \
linux-headers \
base-devel \
dkms
openSUSE
sudo zypper install -y \
kernel-devel-$(uname -r) \
gcc \
make \
dkms
Linux Manual Process
Step 1: Device Discovery and Validation
Find Your Donor Device
# List all PCI devices with detailed information
lspci -vv
# Filter by device type (example: network controllers)
lspci -vv | grep -A 20 "Ethernet controller"
# Get specific device information
lspci -s 03:00.0 -vv
Validate Device Accessibility
# Check if device is bound to a driver
lspci -k -s 03:00.0
# Verify device is not in use by critical services
systemctl status NetworkManager # For network devices
systemctl status display-manager # For graphics devices
Extract BDF Information
# Get BDF with domain information
DEVICE_BDF=$(lspci | grep "Ethernet controller" | head -1 | cut -d' ' -f1)
FULL_BDF="0000:${DEVICE_BDF}"
echo "Using device: ${FULL_BDF}"
Step 2: Build Environment Setup
Navigate to Build Directory
# Ensure we're in the correct directory
cd "$(dirname "$0")/../PCILeechFWGenerator/src/donor_dump" || {
echo "Error: Cannot find donor_dump directory"
exit 1
}
# Verify required files exist
[ -f "Makefile" ] || { echo "Error: Makefile not found"; exit 1; }
[ -f "donor_dump.c" ] || { echo "Error: Source file not found"; exit 1; }
Clean Build Environment
# Clean any previous builds
make clean
# Verify kernel build environment
make -n 2>&1 | grep -q "No rule to make target" && {
echo "Error: Kernel build environment not properly configured"
exit 1
}
Build with Error Handling
# Build the kernel module with verbose output
if ! make V=1; then
echo "Build failed. Common issues:"
echo "1. Kernel headers mismatch: $(uname -r) vs $(ls /lib/modules/)"
echo "2. Missing dependencies: gcc, make, kernel-devel"
echo "3. Insufficient permissions"
exit 1
fi
# Verify build artifacts
[ -f "donor_dump.ko" ] || { echo "Error: Module not built"; exit 1; }
echo "✓ Module built successfully: $(ls -lh donor_dump.ko)"
Step 3: Module Loading and Device Binding
Pre-load Validation
# Check if module is already loaded
if lsmod | grep -q donor_dump; then
echo "Warning: donor_dump module already loaded"
sudo rmmod donor_dump || {
echo "Error: Cannot unload existing module"
exit 1
}
fi
# Verify device exists and is accessible
if ! lspci -s "${DEVICE_BDF}" >/dev/null 2>&1; then
echo "Error: Device ${FULL_BDF} not found"
exit 1
fi
Load Module with Comprehensive Error Handling
# Load module with device binding
if ! sudo insmod donor_dump.ko bdf="${FULL_BDF}"; then
echo "Module load failed. Checking kernel logs..."
dmesg | tail -20 | grep donor_dump
exit 1
fi
# Verify module loaded successfully
if ! lsmod | grep -q donor_dump; then
echo "Error: Module not loaded despite successful insmod"
exit 1
fi
echo "✓ Module loaded successfully for device ${FULL_BDF}"
Verify Proc Interface
# Check if proc file is created and accessible
if [ ! -r "/proc/donor_dump" ]; then
echo "Error: /proc/donor_dump not accessible"
echo "Module may have loaded but device binding failed"
sudo rmmod donor_dump
exit 1
fi
echo "✓ Proc interface available"
Step 4: Data Extraction and Validation
Extract Raw Data
# Read donor information with error checking
if ! DONOR_DATA=$(cat /proc/donor_dump 2>/dev/null); then
echo "Error: Cannot read donor information"
sudo rmmod donor_dump
exit 1
fi
# Validate data completeness
if [ -z "$DONOR_DATA" ]; then
echo "Error: No donor data extracted"
sudo rmmod donor_dump
exit 1
fi
echo "✓ Donor data extracted ($(echo "$DONOR_DATA" | wc -l) lines)"
Save Raw Data with Metadata
# Create output directory with timestamp
OUTPUT_DIR="donor_dumps/$(date +%Y%m%d_%H%M%S)_${DEVICE_BDF//:/_}"
mkdir -p "$OUTPUT_DIR"
# Save raw data with metadata
{
echo "# Donor dump generated on $(date)"
echo "# Device: ${FULL_BDF}"
echo "# Kernel: $(uname -r)"
echo "# System: $(uname -a)"
echo ""
echo "$DONOR_DATA"
} > "${OUTPUT_DIR}/donor_info.txt"
echo "✓ Raw data saved to ${OUTPUT_DIR}/donor_info.txt"
Convert to JSON with Validation
# Enhanced JSON conversion with validation
convert_to_json() {
local input_file="$1"
local output_file="$2"
# Create JSON with proper escaping and validation
{
echo "{"
echo " \"metadata\": {"
echo " \"generated_at\": \"$(date -Iseconds)\","
echo " \"device_bdf\": \"${FULL_BDF}\","
echo " \"kernel_version\": \"$(uname -r)\","
echo " \"generator_version\": \"manual-v1.0\""
echo " },"
echo " \"device_info\": {"
# Process each line, handling special characters
grep -v '^#' "$input_file" | while IFS=':' read -r key value; do
if [ -n "$key" ] && [ -n "$value" ]; then
# Escape special characters in JSON
key=$(echo "$key" | sed 's/"/\\"/g' | xargs)
value=$(echo "$value" | sed 's/"/\\"/g' | xargs)
echo " \"$key\": \"$value\","
fi
done | sed '$ s/,$//' # Remove trailing comma
echo " }"
echo "}"
} > "$output_file"
# Validate JSON syntax
if command -v python3 >/dev/null 2>&1; then
if ! python3 -m json.tool "$output_file" >/dev/null 2>&1; then
echo "Warning: Generated JSON may be invalid"
return 1
fi
fi
return 0
}
# Convert to JSON
JSON_FILE="${OUTPUT_DIR}/donor_info.json"
if convert_to_json "${OUTPUT_DIR}/donor_info.txt" "$JSON_FILE"; then
echo "✓ JSON file created: $JSON_FILE"
else
echo "⚠ JSON conversion completed with warnings"
fi
Step 5: Cleanup and Verification
Safe Module Unloading
# Unload module with verification
cleanup_module() {
if lsmod | grep -q donor_dump; then
if sudo rmmod donor_dump; then
echo "✓ Module unloaded successfully"
else
echo "Warning: Module unload failed"
echo "Check: lsmod | grep donor_dump"
echo "Force remove: sudo rmmod -f donor_dump"
fi
fi
}
# Set trap for cleanup on script exit
trap cleanup_module EXIT
Verify Output Quality
# Comprehensive output validation
validate_donor_dump() {
local json_file="$1"
echo "Validating donor dump quality..."
# Check required fields
local required_fields=("vendor_id" "device_id" "class_code")
for field in "${required_fields[@]}"; do
if ! grep -q "\"$field\"" "$json_file"; then
echo "Warning: Missing required field: $field"
fi
done
# Check file size (should be reasonable)
local file_size=$(stat -f%z "$json_file" 2>/dev/null || stat -c%s "$json_file" 2>/dev/null)
if [ "$file_size" -lt 100 ]; then
echo "Warning: Donor dump seems too small ($file_size bytes)"
elif [ "$file_size" -gt 10000 ]; then
echo "Warning: Donor dump seems unusually large ($file_size bytes)"
else
echo "✓ Donor dump size looks reasonable ($file_size bytes)"
fi
}
validate_donor_dump "$JSON_FILE"
Validation and Testing
Donor Dump Quality Validation
Comprehensive Validation Script
#!/bin/bash
# validate_donor_dump.sh - Comprehensive donor dump validation
validate_donor_dump() {
local json_file="$1"
local errors=0
local warnings=0
echo "=== Donor Dump Validation Report ==="
echo "File: $json_file"
echo "Generated: $(date)"
echo ""
# Check file existence and readability
if [ ! -f "$json_file" ]; then
echo "❌ ERROR: File does not exist"
return 1
fi
if [ ! -r "$json_file" ]; then
echo "❌ ERROR: File is not readable"
return 1
fi
# Validate JSON syntax
if command -v jq >/dev/null 2>&1; then
if ! jq empty "$json_file" 2>/dev/null; then
echo "❌ ERROR: Invalid JSON syntax"
((errors++))
else
echo "✓ JSON syntax valid"
fi
else
echo "⚠ WARNING: jq not available, skipping JSON validation"
((warnings++))
fi
# Check required fields
local required_fields=(
".device_info.vendor_id"
".device_info.device_id"
".metadata.device_bdf"
)
for field in "${required_fields[@]}"; do
if command -v jq >/dev/null 2>&1; then
if [ "$(jq -r "$field // empty" "$json_file")" = "" ]; then
echo "❌ ERROR: Missing required field: $field"
((errors++))
else
echo "✓ Required field present: $field"
fi
fi
done
# Validate field formats
if command -v jq >/dev/null 2>&1; then
# Check vendor_id format (4 hex digits)
vendor_id=$(jq -r '.device_info.vendor_id // empty' "$json_file")
if [[ ! "$vendor_id" =~ ^[0-9A-Fa-f]{4}$ ]]; then
echo "❌ ERROR: Invalid vendor_id format: $vendor_id"
((errors++))
fi
# Check device_id format (4 hex digits)
device_id=$(jq -r '.device_info.device_id // empty' "$json_file")
if [[ ! "$device_id" =~ ^[0-9A-Fa-f]{4}$ ]]; then
echo "❌ ERROR: Invalid device_id format: $device_id"
((errors++))
fi
# Check BDF format
bdf=$(jq -r '.metadata.device_bdf // empty' "$json_file")
if [[ ! "$bdf" =~ ^[0-9A-Fa-f]{4}:[0-9A-Fa-f]{2}:[0-9A-Fa-f]{2}\.[0-9A-Fa-f]$ ]]; then
echo "⚠ WARNING: Unusual BDF format: $bdf"
((warnings++))
fi
fi
# File size checks
local file_size=$(stat -f%z "$json_file" 2>/dev/null || stat -c%s "$json_file" 2>/dev/null)
if [ "$file_size" -lt 200 ]; then
echo "⚠ WARNING: File seems small ($file_size bytes) - may be incomplete"
((warnings++))
elif [ "$file_size" -gt 50000 ]; then
echo "⚠ WARNING: File seems large ($file_size bytes) - may contain unexpected data"
((warnings++))
fi
echo ""
echo "=== Validation Summary ==="
echo "Errors: $errors"
echo "Warnings: $warnings"
if [ "$errors" -eq 0 ]; then
echo "✅ Validation PASSED"
return 0
else
echo "❌ Validation FAILED"
return 1
fi
}
# Usage: validate_donor_dump "path/to/donor_info.json"
Integration Testing
Test with PCILeech Generator
#!/bin/bash
# test_donor_integration.sh - Test donor dump with PCILeech
test_donor_integration() {
local donor_file="$1"
local test_board="${2:-pcileech_35t325_x1}"
local test_bdf="${3:-0000:03:00.0}"
echo "Testing donor dump integration..."
# Validate donor file first
if ! validate_donor_dump "$donor_file"; then
echo "❌ Donor dump validation failed"
return 1
fi
# Test dry-run with PCILeech generator
if command -v pcileech-generate >/dev/null 2>&1; then
echo "Testing with PCILeech generator (dry-run)..."
if pcileech-generate \
--bdf "$test_bdf" \
--board "$test_board" \
--donor-info-file "$donor_file" \
--dry-run; then
echo "✅ Integration test PASSED"
return 0
else
echo "❌ Integration test FAILED"
return 1
fi
else
echo "⚠ PCILeech generator not available, skipping integration test"
return 0
fi
}
Troubleshooting
Common Issues and Solutions
Linux-Specific Issues
1. Kernel Headers Mismatch
# Problem: Headers don't match running kernel
# Solution: Install correct headers or use DKMS
# Check current kernel vs available headers
echo "Running kernel: $(uname -r)"
echo "Available headers:"
ls /lib/modules/*/build 2>/dev/null || echo "No headers found"
# Fix with DKMS (recommended)
sudo apt-get install dkms
sudo dkms add ./donor_dump
sudo dkms build donor_dump/1.0
sudo dkms install donor_dump/1.0
2. Module Loading Failures
# Comprehensive module debugging
debug_module_load() {
local module_path="$1"
local bdf="$2"
echo "Debugging module load for $module_path with BDF $bdf"
# Check module dependencies
echo "Module info:"
modinfo "$module_path"
# Check for conflicting modules
echo "Checking for conflicts:"
lsmod | grep -E "(pci|donor)"
# Attempt load with verbose logging
echo "Loading with verbose logging:"
sudo insmod "$module_path" bdf="$bdf" debug=1
# Check kernel logs
echo "Recent kernel messages:"
dmesg | tail -20
}
3. Device Access Issues
# Check device binding and driver conflicts
check_device_binding() {
local bdf="$1"
echo "Device binding status for $bdf:"
# Check current driver
if [ -d "/sys/bus/pci/devices/$bdf" ]; then
echo "Device exists in sysfs"
if [ -L "/sys/bus/pci/devices/$bdf/driver" ]; then
current_driver=$(readlink "/sys/bus/pci/devices/$bdf/driver" | xargs basename)
echo "Current driver: $current_driver"
# Suggest unbinding if necessary
echo "To unbind: echo '$bdf' | sudo tee /sys/bus/pci/devices/$bdf/driver/unbind"
else
echo "No driver bound"
fi
else
echo "❌ Device not found in sysfs"
fi
}
Performance Optimization
Batch Processing Multiple Devices
#!/bin/bash
# batch_donor_dump.sh - Process multiple devices efficiently
batch_donor_dump() {
local device_list="$1" # File with one BDF per line
local output_dir="$2"
mkdir -p "$output_dir"
# Build module once
echo "Building donor_dump module..."
if ! make -C src/donor_dump; then
echo "❌ Module build failed"
return 1
fi
# Process each device
while IFS= read -r bdf; do
[ -z "$bdf" ] && continue
[[ "$bdf" =~ ^#.*$ ]] && continue # Skip comments
echo "Processing device: $bdf"
# Create device-specific output directory
device_dir="$output_dir/${bdf//:/_}"
mkdir -p "$device_dir"
# Load module for this device
if sudo insmod src/donor_dump/donor_dump.ko bdf="$bdf"; then
# Extract data
cat /proc/donor_dump > "$device_dir/donor_info.txt"
# Convert to JSON
convert_to_json "$device_dir/donor_info.txt" "$device_dir/donor_info.json"
# Unload module
sudo rmmod donor_dump
echo "✓ Completed: $bdf"
else
echo "❌ Failed: $bdf"
fi
# Brief pause to avoid overwhelming the system
sleep 1
done < "$device_list"
}
Advanced Usage
Custom Data Extraction
Extended Information Gathering
# Enhanced donor dump with additional system context
create_extended_donor_dump() {
local bdf="$1"
local output_file="$2"
# Standard donor dump
cat /proc/donor_dump > "${output_file}.raw"
# Add system context
{
echo "=== EXTENDED DONOR DUMP ==="
echo "Generated: $(date -Iseconds)"
echo "System: $(uname -a)"
echo "BDF: $bdf"
echo ""
echo "=== DEVICE INFORMATION ==="
lspci -vvv -s "${bdf#0000:}"
echo ""
echo "=== SYSTEM PCI TREE ==="
lspci -tv
echo ""
echo "=== IOMMU GROUPS ==="
find /sys/kernel/iommu_groups/ -name "*" -type l | \
xargs -I {} sh -c 'echo "Group $(basename $(dirname {})): $(basename $(readlink {}))"' | \
grep "$bdf" || echo "No IOMMU group found"
echo ""
echo "=== DONOR DUMP DATA ==="
cat "${output_file}.raw"
} > "$output_file"
}
Automation Integration
CI/CD Pipeline Integration
# .github/workflows/donor-dump-validation.yml
name: Donor Dump Validation
on:
push:
paths:
- 'donor_dumps/**'
- 'src/donor_dump/**'
jobs:
validate:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Install dependencies
run: |
sudo apt-get update
sudo apt-get install -y jq
- name: Validate donor dumps
run: |
for dump in donor_dumps/*.json; do
echo "Validating $dump"
./scripts/validate_donor_dump.sh "$dump"
done
Security Considerations
Safe Module Handling
# Secure module loading with verification
secure_module_load() {
local module_path="$1
Automation Integration
CI/CD Pipeline Integration
# .github/workflows/donor-dump-validation.yml
name: Donor Dump Validation
on:
push:
paths:
- 'donor_dumps/**'
- 'src/donor_dump/**'
jobs:
validate:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Install dependencies
run: |
sudo apt-get update
sudo apt-get install -y jq
- name: Validate donor dumps
run: |
for dump in donor_dumps/*.json; do
echo "Validating $dump"
./scripts/validate_donor_dump.sh "$dump"
done
Security Considerations
Safe Module Handling
# Secure module loading with verification
secure_module_load() {
local module_path="$1"
local bdf="$2"
# Verify module signature (if available)
if command -v modinfo >/dev/null 2>&1; then
modinfo "$module_path" | grep -q "signature" && echo "✓ Module is signed"
fi
# Check module for suspicious content
if command -v strings >/dev/null 2>&1; then
if strings "$module_path" | grep -qE "(rm -rf|format|delete)"; then
echo "⚠ WARNING: Module contains potentially dangerous strings"
read -p "Continue anyway? (y/N): " -n 1 -r
echo
[[ ! $REPLY =~ ^[Yy]$ ]] && return 1
fi
fi
# Load with restricted permissions
sudo insmod "$module_path" bdf="$bdf"
}
Privilege Management
# Check and minimize required privileges
check_privileges() {
if [ "$EUID" -ne 0 ]; then
echo "This script requires root privileges for:"
echo "- Loading kernel modules"
echo "- Accessing PCI configuration space"
echo "- Reading /proc interfaces"
echo ""
echo "Run with: sudo $0"
exit 1
fi
# Drop privileges where possible
if command -v sudo >/dev/null 2>&1; then
ORIGINAL_USER="${SUDO_USER:-$USER}"
echo "Running as root, will drop privileges where possible"
fi
}
Best Practices Summary
Development Workflow
- Always validate prerequisites before starting
- Use version control for donor dump files
- Document device-specific quirks in metadata
- Test with multiple board types when possible
- Maintain backup copies of working donor dumps
Production Deployment
- Automate validation in CI/CD pipelines
- Use secure module signing in production
- Monitor for kernel compatibility issues
- Implement rollback procedures for failed dumps
- Log all operations for audit trails
Performance Optimization
- Batch process multiple devices when possible
- Cache build artifacts to avoid rebuilds
- Use parallel processing for validation
- Minimize module load/unload cycles
- Implement smart retry logic for transient failures
Conclusion
This enhanced manual donor dump generation guide provides:
- Comprehensive error handling for robust operation
- Cross-platform support for Linux and Windows
- Validation and testing frameworks for quality assurance
- Performance optimizations for batch processing
- Security considerations for safe operation
- Integration examples for automation workflows
The manual process gives you complete control over donor dump generation, making it ideal for:
- Debugging automated tool failures
- Research and development of new features
- Custom integration with existing workflows
- Educational purposes to understand the process
For most users, the automated pcileech.py
command or TUI interface remains the recommended approach, but this manual process provides a powerful alternative when needed.
Quick Reference
Essential Commands
Linux:
# Quick donor dump
cd PCILeechFWGenerator/src/donor_dump
make && sudo insmod donor_dump.ko bdf=0000:03:00.0
cat /proc/donor_dump > donor_info.txt
sudo rmmod donor_dump
File Locations
- Linux module source:
src/donor_dump/
- Validation tools:
scripts/validate_donor_dump.sh
- Output directory:
donor_dumps/YYYYMMDD_HHMMSS_BDF/
Support Resources
- Main documentation: Home
- TUI guide: TUI README
- Development guide: Development
- Firmware uniqueness: Firmware Uniqueness