Add firmware packaging and validation scripts

Red Bear OS Team
This commit is contained in:
2026-04-16 12:45:24 +01:00
parent 54e63420ec
commit 7b98843b97
1012 changed files with 121829 additions and 0 deletions
@@ -0,0 +1,40 @@
#!/usr/bin/env bash
# Build redbear-wifictl for the Redox target using the repo-provided cross toolchain.
set -euo pipefail
usage() {
cat <<'EOF'
Usage: build-redbear-wifictl-redox.sh [cargo build args...]
This helper ensures the repository's Redox cross-linker directory is on PATH before invoking
`cargo build --target x86_64-unknown-redox` for `redbear-wifictl`.
Examples:
./local/scripts/build-redbear-wifictl-redox.sh
./local/scripts/build-redbear-wifictl-redox.sh --release
EOF
}
if [[ "${1:-}" == "--help" || "${1:-}" == "-h" ]]; then
usage
exit 0
fi
repo_root="$(cd "$(dirname "$0")/../.." && pwd)"
toolchain_bin="$repo_root/prefix/x86_64-unknown-redox/sysroot/bin"
crate_dir="$repo_root/local/recipes/system/redbear-wifictl/source"
if [[ ! -d "$toolchain_bin" ]]; then
echo "ERROR: missing Redox toolchain bin dir: $toolchain_bin" >&2
echo "Build the prefix/sysroot first before using this helper." >&2
exit 1
fi
if [[ ! -x "$toolchain_bin/x86_64-unknown-redox-gcc" ]]; then
echo "ERROR: missing executable linker: $toolchain_bin/x86_64-unknown-redox-gcc" >&2
exit 1
fi
echo "Using Redox toolchain from: $toolchain_bin"
PATH="$toolchain_bin:$PATH" cargo build --target x86_64-unknown-redox "$@"
+170
View File
@@ -0,0 +1,170 @@
#!/usr/bin/env bash
set -euo pipefail
script_dir="$(CDPATH= cd -- "$(dirname -- "$0")" && pwd)"
root_dir="$(CDPATH= cd -- "${script_dir}/../.." && pwd)"
target="${TARGET:-x86_64-unknown-redox}"
source_sysroot="${SOURCE_SYSROOT:-${root_dir}/prefix/${target}/sysroot}"
dest_root="${1:-${root_dir}/build/toolchain-export/${target}}"
dest_sysroot="${dest_root}/sysroot"
dest_bin="${dest_root}/bin"
partial_root="${dest_root}.partial"
partial_sysroot="${partial_root}/sysroot"
partial_bin="${partial_root}/bin"
if [ ! -d "${source_sysroot}" ]; then
echo "error: missing source sysroot: ${source_sysroot}" >&2
echo "hint: build the prefix first with 'make prefix TARGET=${target}' or 'make prefix'" >&2
exit 1
fi
rm -rf "${partial_root}"
mkdir -p "${partial_root}"
cp -a "${source_sysroot}" "${partial_sysroot}"
mkdir -p "${partial_bin}"
for tool in gcc c++ ar ranlib ld strip objcopy objdump; do
tool_name="${target}-${tool}"
if [ -x "${partial_sysroot}/bin/${tool_name}" ]; then
ln -s "../sysroot/bin/${tool_name}" "${partial_bin}/${tool_name}"
fi
done
cat > "${partial_bin}/${target}-pkg-config" <<EOF
#!/usr/bin/env bash
set -euo pipefail
script_dir="\$(CDPATH= cd -- "\$(dirname -- "\$0")" && pwd)"
toolchain_root="\$(CDPATH= cd -- "\${script_dir}/.." && pwd)"
sysroot="\${REDBEAR_REDOX_SYSROOT:-\${toolchain_root}/sysroot}"
export PKG_CONFIG_SYSROOT_DIR="\${PKG_CONFIG_SYSROOT_DIR:-\${sysroot}}"
export PKG_CONFIG_LIBDIR="\${PKG_CONFIG_LIBDIR:-\${sysroot}/lib/pkgconfig}"
export PKG_CONFIG_PATH="\${PKG_CONFIG_PATH:-\${sysroot}/share/pkgconfig}"
if [ -n "\${COOKBOOK_DYNAMIC:-}" ]; then
exec pkg-config "\$@"
else
exec pkg-config --static "\$@"
fi
EOF
cat > "${partial_bin}/${target}-llvm-config" <<EOF
#!/usr/bin/env python3
import os
import subprocess
import sys
LLVM_CONFIG = "/bin/llvm-config"
TARGET = "${target}"
ARCH_MAP = {
"x86_64": ("X86", "x86", "X86"),
"i586": ("X86", "x86", "X86"),
"aarch64": ("AArch64", "aarch64", "AArch64"),
"riscv64gc": ("RISCV", "riscv", "RISCV"),
}
ALL_ARCH_COMPS = ["x86", "aarch64", "riscv"]
ALL_ARCH_LIBS = ["X86", "AArch64", "RISCV"]
def is_unwanted_arch(item, allowed_prefix, all_prefixes, is_lib=False):
matched_arch = None
for arch in all_prefixes:
if is_lib and f"LLVM{arch}" in item:
matched_arch = arch
break
if not is_lib and item.startswith(arch):
matched_arch = arch
break
return matched_arch is not None and matched_arch != allowed_prefix
def main():
script_dir = os.path.dirname(os.path.realpath(__file__))
toolchain_root = os.path.dirname(script_dir)
toolchain_path = os.environ.get("COOKBOOK_HOST_SYSROOT", os.path.join(toolchain_root, "sysroot"))
sysroot_path = os.environ.get("COOKBOOK_SYSROOT", toolchain_path)
target_triple = os.environ.get("TARGET", TARGET)
target_arch = target_triple.split("-")[0]
mapped_archs = ARCH_MAP.get(target_arch)
if mapped_archs is None:
print(f"Error: unsupported target architecture in {target_triple}", file=sys.stderr)
sys.exit(1)
target_built_name, comp_prefix, lib_prefix = mapped_archs
cmd = [toolchain_path + LLVM_CONFIG] + sys.argv[1:]
try:
result = subprocess.run(
cmd,
stdout=subprocess.PIPE,
stderr=sys.stderr,
check=False,
text=True,
)
except FileNotFoundError:
print(f"Error: Could not find executable '{LLVM_CONFIG}' under {toolchain_path}", file=sys.stderr)
sys.exit(1)
if result.returncode != 0:
sys.exit(result.returncode)
output = result.stdout.strip()
args_set = set(sys.argv[1:])
if "--bindir" in args_set:
output = toolchain_path + "/usr/bin"
elif "--targets-built" in args_set:
output = target_built_name
elif "--components" in args_set:
components = output.split()
output = " ".join(
c for c in components if not is_unwanted_arch(c, comp_prefix, ALL_ARCH_COMPS, is_lib=False)
)
elif "--libs" in args_set:
libs = output.split()
output = " ".join(
l for l in libs if not is_unwanted_arch(l, lib_prefix, ALL_ARCH_LIBS, is_lib=True)
)
output = output.replace(toolchain_path.rstrip(os.sep), sysroot_path.rstrip(os.sep))
else:
output = output.replace(toolchain_path.rstrip(os.sep), sysroot_path.rstrip(os.sep))
print(output, end="\n")
if __name__ == "__main__":
main()
EOF
cat > "${partial_root}/activate.sh" <<EOF
#!/usr/bin/env bash
set -euo pipefail
toolchain_root="\$(CDPATH= cd -- "\$(dirname -- "\${BASH_SOURCE[0]}")" && pwd)"
export TARGET="${target}"
export REDBEAR_REDOX_SYSROOT="\${REDBEAR_REDOX_SYSROOT:-\${toolchain_root}/sysroot}"
export COOKBOOK_HOST_SYSROOT="\${COOKBOOK_HOST_SYSROOT:-\${REDBEAR_REDOX_SYSROOT}}"
export COOKBOOK_SYSROOT="\${COOKBOOK_SYSROOT:-\${REDBEAR_REDOX_SYSROOT}}"
export PATH="\${toolchain_root}/bin:\${REDBEAR_REDOX_SYSROOT}/bin:\${PATH}"
echo "Activated ${target} toolchain from \${toolchain_root}"
EOF
chmod 0755 \
"${partial_root}/activate.sh" \
"${partial_bin}/${target}-pkg-config" \
"${partial_bin}/${target}-llvm-config"
rm -rf "${dest_root}"
mv "${partial_root}" "${dest_root}"
echo "exported ${target} toolchain to ${dest_root}"
echo "source ${dest_root}/activate.sh"
@@ -0,0 +1,50 @@
#!/usr/bin/env bash
# Summarize and package Wi-Fi validation artifacts after a real run.
set -euo pipefail
usage() {
cat <<'EOF'
Usage: finalize-wifi-validation-run.sh <capture.json> [artifact.tar.gz] [additional files...]
Runs the packaged Wi-Fi analyzer on the supplied capture JSON and then packages the provided
artifacts into a tarball.
Defaults:
artifact tarball: ./wifi-validation-artifacts.tar.gz
EOF
}
if [[ $# -lt 1 || "${1:-}" == "--help" || "${1:-}" == "-h" ]]; then
usage
[[ $# -ge 1 ]] && exit 0 || exit 1
fi
capture="$1"
shift
archive="${1:-wifi-validation-artifacts.tar.gz}"
if [[ $# -gt 0 ]]; then
shift
fi
if [[ ! -f "$capture" ]]; then
echo "ERROR: missing capture file $capture" >&2
exit 1
fi
echo "=== Wi-Fi Validation Analysis ==="
if command -v redbear-phase5-wifi-analyze >/dev/null 2>&1; then
redbear-phase5-wifi-analyze "$capture"
else
echo "WARN: redbear-phase5-wifi-analyze not installed; skipping analyzer"
fi
echo "=== Packaging Artifacts ==="
files=("$capture")
if [[ $# -gt 0 ]]; then
for path in "$@"; do
files+=("$path")
done
fi
./local/scripts/package-wifi-validation-artifacts.sh "$archive" "${files[@]}"
echo "finalized_archive=$archive"
@@ -0,0 +1,76 @@
#!/usr/bin/env bash
# Package Wi-Fi validation artifacts into a single tarball.
set -euo pipefail
usage() {
cat <<'EOF'
Usage: package-wifi-validation-artifacts.sh [OUTPUT_TARBALL] [FILES...]
Default output tarball:
./wifi-validation-artifacts.tar.gz
If no FILES are provided, this script packages the common host-side artifact names referenced by the
Wi-Fi validation runbook when they exist in the current directory.
If a provided FILE argument is a directory, it is included recursively.
EOF
}
if [[ "${1:-}" == "--help" || "${1:-}" == "-h" ]]; then
usage
exit 0
fi
output="${1:-wifi-validation-artifacts.tar.gz}"
shift || true
inputs=()
if [[ $# -gt 0 ]]; then
for path in "$@"; do
if [[ -e "$path" ]]; then
inputs+=("$path")
else
echo "WARN: skipping missing artifact $path" >&2
fi
done
else
defaults=(
"wifi-passthrough-capture.json"
"wifi-passthrough-capture.json.meta.json"
"wifi-baremetal-capture.json"
"wifi-baremetal-serial.log"
"wifi-baremetal-console.log"
)
for path in "${defaults[@]}"; do
if [[ -e "$path" ]]; then
inputs+=("$path")
fi
done
fi
if [[ ${#inputs[@]} -eq 0 ]]; then
echo "ERROR: no Wi-Fi validation artifacts found to package" >&2
exit 1
fi
manifest_dir=$(mktemp -d)
manifest_path="$manifest_dir/wifi-validation-artifacts.manifest.txt"
{
echo "output=$output"
for path in "${inputs[@]}"; do
if command -v sha256sum >/dev/null 2>&1 && [[ -f "$path" ]]; then
checksum=$(sha256sum "$path" | awk '{print $1}')
printf 'file=%s sha256=%s\n' "$path" "$checksum"
else
printf 'path=%s\n' "$path"
fi
done
} > "$manifest_path"
tar -czf "$output" "${inputs[@]}" -C "$manifest_dir" "$(basename "$manifest_path")"
rm -rf "$manifest_dir"
echo "packaged_artifacts=$output"
printf 'included=%s\n' "${inputs[*]}"
echo "manifest=wifi-validation-artifacts.manifest.txt"
+136
View File
@@ -0,0 +1,136 @@
#!/usr/bin/env bash
# Bind or unbind an Intel Wi-Fi PCI function to vfio-pci for Red Bear validation.
set -euo pipefail
usage() {
cat <<'EOF'
Usage:
prepare-wifi-vfio.sh bind <PCI_BDF>
prepare-wifi-vfio.sh unbind <PCI_BDF> <HOST_DRIVER>
Examples:
sudo ./local/scripts/prepare-wifi-vfio.sh bind 0000:00:14.3
sudo ./local/scripts/prepare-wifi-vfio.sh unbind 0000:00:14.3 iwlwifi
Notes:
- This helper only prepares host PCI binding for VFIO-backed validation.
- It does NOT itself prove Wi-Fi works inside Red Bear OS.
- Use with care on a machine where the selected device is safe to detach.
EOF
}
require_root() {
if [[ ${EUID:-$(id -u)} -ne 0 ]]; then
echo "ERROR: this script must run as root" >&2
exit 1
fi
}
require_sysfs_path() {
local path="$1"
if [[ ! -e "$path" ]]; then
echo "ERROR: missing sysfs path $path" >&2
exit 1
fi
}
read_pci_id() {
local bdf="$1"
local vendor device
vendor=$(<"/sys/bus/pci/devices/$bdf/vendor")
device=$(<"/sys/bus/pci/devices/$bdf/device")
printf '%s %s\n' "$vendor" "$device"
}
current_driver() {
local bdf="$1"
local link="/sys/bus/pci/devices/$bdf/driver"
if [[ -L "$link" ]]; then
basename "$(readlink -f "$link")"
else
printf 'none\n'
fi
}
bind_vfio() {
local bdf="$1"
require_sysfs_path "/sys/bus/pci/devices/$bdf"
local driver vendor device
driver=$(current_driver "$bdf")
read -r vendor device < <(read_pci_id "$bdf")
echo "Preparing $bdf for vfio-pci"
echo "vendor=$vendor device=$device current_driver=$driver"
modprobe vfio-pci
if [[ "$driver" != "none" && "$driver" != "vfio-pci" ]]; then
echo "$bdf" > "/sys/bus/pci/devices/$bdf/driver/unbind"
fi
printf '%s %s\n' "$vendor" "$device" > /sys/bus/pci/drivers/vfio-pci/new_id || true
echo "$bdf" > /sys/bus/pci/drivers/vfio-pci/bind
echo "vfio_driver=$(current_driver "$bdf")"
}
unbind_vfio() {
local bdf="$1"
local host_driver="$2"
require_sysfs_path "/sys/bus/pci/devices/$bdf"
require_sysfs_path "/sys/bus/pci/drivers/$host_driver"
local driver
driver=$(current_driver "$bdf")
echo "Restoring $bdf from $driver to $host_driver"
if [[ "$driver" == "vfio-pci" ]]; then
echo "$bdf" > /sys/bus/pci/drivers/vfio-pci/unbind
elif [[ "$driver" != "none" && "$driver" != "$host_driver" ]]; then
echo "$bdf" > "/sys/bus/pci/devices/$bdf/driver/unbind"
fi
echo "$bdf" > "/sys/bus/pci/drivers/$host_driver/bind"
echo "restored_driver=$(current_driver "$bdf")"
}
main() {
if [[ $# -lt 1 ]]; then
usage
exit 1
fi
case "$1" in
--help|-h|help)
usage
exit 0
;;
esac
require_root
case "$1" in
bind)
if [[ $# -ne 2 ]]; then
usage
exit 1
fi
bind_vfio "$2"
;;
unbind)
if [[ $# -ne 3 ]]; then
usage
exit 1
fi
unbind_vfio "$2" "$3"
;;
*)
usage
exit 1
;;
esac
}
main "$@"
@@ -0,0 +1,140 @@
#!/usr/bin/env bash
# Prepare a host Intel Wi-Fi PCI function for VFIO, run the Red Bear Wi-Fi passthrough
# validation harness, and restore the host driver afterwards.
set -euo pipefail
usage() {
cat <<'EOF'
Usage: run-wifi-passthrough-validation.sh --host-pci 0000:xx:yy.z --host-driver DRIVER [--artifact-dir DIR] [--capture-output PATH] [--metadata-output PATH] [-- extra qemu args...]
Examples:
sudo ./local/scripts/run-wifi-passthrough-validation.sh \
--host-pci 0000:00:14.3 \
--host-driver iwlwifi \
--capture-output ./wifi-passthrough-capture.json
This wrapper:
1. binds the selected PCI function to vfio-pci,
2. launches test-wifi-passthrough-qemu.sh --check,
3. restores the selected host driver on exit.
It does NOT itself prove end-to-end Wi-Fi connectivity; it automates the strongest in-repo
passthrough validation path.
EOF
}
host_pci=""
host_driver=""
capture_output=""
artifact_dir=""
extra_args=()
run_started="$(date -u +%Y-%m-%dT%H:%M:%SZ)"
metadata_output=""
while [[ $# -gt 0 ]]; do
case "$1" in
--host-pci)
host_pci="$2"
shift 2
;;
--host-driver)
host_driver="$2"
shift 2
;;
--capture-output)
capture_output="$2"
shift 2
;;
--artifact-dir)
artifact_dir="$2"
shift 2
;;
--metadata-output)
metadata_output="$2"
shift 2
;;
--help|-h)
usage
exit 0
;;
--)
shift
extra_args+=("$@")
break
;;
*)
extra_args+=("$1")
shift
;;
esac
done
if [[ -z "$host_pci" || -z "$host_driver" ]]; then
echo "ERROR: --host-pci and --host-driver are required" >&2
usage
exit 1
fi
script_root="$(dirname "$0")"
prepare_script="$script_root/prepare-wifi-vfio.sh"
passthrough_script="$script_root/test-wifi-passthrough-qemu.sh"
cleanup() {
if [[ -n "$host_pci" && -n "$host_driver" ]]; then
echo "=== Restoring host driver ==="
"$prepare_script" unbind "$host_pci" "$host_driver" || true
fi
}
trap cleanup EXIT
echo "=== Binding Intel Wi-Fi function to vfio-pci ==="
"$prepare_script" bind "$host_pci"
echo "=== Running Wi-Fi passthrough validation ==="
if [[ -n "$artifact_dir" ]]; then
mkdir -p "$artifact_dir"
if [[ -z "$capture_output" ]]; then
capture_output="$artifact_dir/wifi-passthrough-capture.json"
fi
if [[ -z "$metadata_output" ]]; then
metadata_output="$artifact_dir/wifi-passthrough-capture.meta.json"
fi
fi
if [[ -z "$capture_output" ]]; then
capture_output="$(pwd)/wifi-passthrough-capture.json"
fi
cmd=("$passthrough_script" --host-pci "$host_pci" --check)
cmd+=(--capture-output "$capture_output")
cmd+=("${extra_args[@]}")
"${cmd[@]}"
run_finished="$(date -u +%Y-%m-%dT%H:%M:%SZ)"
if [[ -z "$metadata_output" ]]; then
metadata_output="${capture_output}.meta.json"
fi
if [[ -n "$metadata_output" ]]; then
python - <<'PY' "$metadata_output" "$host_pci" "$host_driver" "$capture_output" "$run_started" "$run_finished"
import json, sys
path, host_pci, host_driver, capture_output, run_started, run_finished = sys.argv[1:7]
payload = {
"host_pci": host_pci,
"host_driver": host_driver,
"capture_output": capture_output or None,
"run_started": run_started,
"run_finished": run_finished,
}
with open(path, "w", encoding="utf-8") as f:
json.dump(payload, f, indent=2, sort_keys=True)
f.write("\n")
PY
fi
echo "=== Validation complete ==="
if [[ -n "$capture_output" ]]; then
echo "capture_output=$capture_output"
fi
if [[ -n "$metadata_output" ]]; then
echo "metadata_output=$metadata_output"
fi
@@ -0,0 +1,96 @@
#!/usr/bin/env bash
# Summarize packaged Wi-Fi validation artifacts for quick review.
set -euo pipefail
usage() {
cat <<'EOF'
Usage: summarize-wifi-validation-artifacts.sh <capture.json|artifact.tar.gz>
Print a compact summary of the packaged Wi-Fi validation evidence so the next debugging loop can
see the most important runtime signals quickly.
EOF
}
if [[ $# -ne 1 || "$1" == "--help" || "$1" == "-h" ]]; then
usage
[[ $# -eq 1 ]] && exit 0 || exit 1
fi
input="$1"
tmpdir=""
cleanup() {
if [[ -n "$tmpdir" && -d "$tmpdir" ]]; then
rm -rf "$tmpdir"
fi
}
trap cleanup EXIT
json_path=""
if [[ "$input" == *.tar.gz ]]; then
tmpdir=$(mktemp -d)
tar -xzf "$input" -C "$tmpdir"
json_path=$(find "$tmpdir" -maxdepth 2 -type f \( -name '*wifi*capture*.json' -o -name 'redbear-phase5-wifi-capture.json' \) | head -n 1 || true)
if [[ -z "$json_path" ]]; then
echo "ERROR: no Wi-Fi capture JSON found inside $input" >&2
exit 1
fi
else
json_path="$input"
fi
python - <<'PY' "$json_path"
import json, sys
path = sys.argv[1]
with open(path, 'r', encoding='utf-8') as f:
data = json.load(f)
def cmd_stdout(name):
return str(data.get('commands', {}).get(name, {}).get('stdout', '')).strip()
def scheme_value(name):
value = data.get('scheme', {}).get(name, {})
if isinstance(value, dict):
return value.get('value', '').strip()
return ''
print("=== Red Bear Wi-Fi Validation Summary ===")
print(f"capture={path}")
print(f"captured_at_unix={data.get('captured_at_unix', 'unknown')}")
print(f"profile={data.get('profile', 'unknown')}")
print(f"interface={data.get('interface', 'unknown')}")
installed = data.get('installed', {})
print(f"driver_installed={installed.get('driver')}")
print(f"wifictl_installed={installed.get('wifictl')}")
print(f"netctl_installed={installed.get('netctl')}")
for key in [
'driver_probe',
'driver_status',
'wifictl_probe',
'wifictl_status',
'netctl_status',
'phase5_network_check',
'phase5_wifi_check',
]:
out = cmd_stdout(key)
first = out.splitlines()[0] if out else ''
print(f"{key}_first_line={first}")
for key in [
'status',
'link_state',
'firmware_status',
'transport_status',
'transport_init_status',
'activation_status',
'connect_result',
'disconnect_result',
'last_error',
]:
print(f"scheme_{key}={scheme_value(key)}")
scan = scheme_value('scan_results')
print(f"scheme_scan_results={scan}")
PY
+146
View File
@@ -0,0 +1,146 @@
#!/usr/bin/env bash
# Launch or validate the bounded Bluetooth Battery Level slice in QEMU.
set -euo pipefail
find_uefi_firmware() {
local candidates=(
"/usr/share/ovmf/x64/OVMF.4m.fd"
"/usr/share/OVMF/x64/OVMF.4m.fd"
"/usr/share/ovmf/x64/OVMF_CODE.4m.fd"
"/usr/share/OVMF/x64/OVMF_CODE.4m.fd"
"/usr/share/ovmf/OVMF.fd"
"/usr/share/OVMF/OVMF_CODE.fd"
"/usr/share/qemu/edk2-x86_64-code.fd"
)
local path
for path in "${candidates[@]}"; do
if [[ -f "$path" ]]; then
printf '%s\n' "$path"
return 0
fi
done
return 1
}
usage() {
cat <<'USAGE'
Usage: test-bluetooth-qemu.sh [--check] [extra qemu args...]
Boot or validate the Red Bear OS bounded Bluetooth Battery Level slice on
redbear-bluetooth-experimental.
USAGE
}
check_mode=0
filtered_args=()
for arg in "$@"; do
case "$arg" in
--help|-h|help)
usage
exit 0
;;
--check)
check_mode=1
;;
*)
filtered_args+=("$arg")
;;
esac
done
firmware="$(find_uefi_firmware)" || {
echo "ERROR: no usable x86_64 UEFI firmware found" >&2
exit 1
}
arch="${ARCH:-$(uname -m)}"
image="build/$arch/redbear-bluetooth-experimental/harddrive.img"
extra="build/$arch/redbear-bluetooth-experimental/extra.img"
extra_qemu_args="${filtered_args[*]:-}"
if [[ -n "${QEMUFLAGS:-}" ]]; then
combined_qemu_args="${QEMUFLAGS} ${extra_qemu_args}"
else
combined_qemu_args="${extra_qemu_args}"
fi
if [[ ! -f "$image" ]]; then
echo "ERROR: missing image $image" >&2
echo "Build it first with: ./local/scripts/build-redbear.sh redbear-bluetooth-experimental" >&2
exit 1
fi
if [[ ! -f "$extra" ]]; then
truncate -s 1g "$extra"
fi
pcap="build/$arch/redbear-bluetooth-experimental/network.pcap"
echo "=== Red Bear OS Bluetooth QEMU Launch ==="
echo "Config: redbear-bluetooth-experimental"
echo "Image: $image"
echo "UEFI: $firmware"
echo
echo "Suggested in-guest checks:"
echo " redbear-btusb --status"
echo " redbear-btctl --status"
echo " redbear-bluetooth-battery-check"
echo " test-bluetooth-runtime.sh"
echo
if [[ "$check_mode" -eq 1 ]]; then
expect <<EOF
log_user 1
set timeout 300
spawn qemu-system-x86_64 -name {Red Bear OS x86_64} -device qemu-xhci -smp 4 -m 2048 -bios $firmware -chardev stdio,id=debug,signal=off,mux=on -serial chardev:debug -mon chardev=debug -machine q35 -device ich9-intel-hda -device hda-output -device virtio-net,netdev=net0 -netdev user,id=net0 -object filter-dump,id=f1,netdev=net0,file=$pcap -nographic -vga none -drive file=$image,format=raw,if=none,id=drv0 -device nvme,drive=drv0,serial=NVME_SERIAL -drive file=$extra,format=raw,if=none,id=drv1 -device nvme,drive=drv1,serial=NVME_EXTRA -enable-kvm -cpu host $combined_qemu_args
expect "login:"
send "root\r"
expect "assword:"
send "password\r"
expect "Type 'help' for available commands."
send "redbear-bluetooth-battery-check\r"
expect "Red Bear OS Bluetooth Battery Check"
expect "BLUETOOTH_BATTERY_CHECK=pass"
send "redbear-bluetooth-battery-check\r"
expect "Red Bear OS Bluetooth Battery Check"
expect "BLUETOOTH_BATTERY_CHECK=pass"
send "shutdown\r"
expect eof
spawn qemu-system-x86_64 -name {Red Bear OS x86_64} -device qemu-xhci -smp 4 -m 2048 -bios $firmware -chardev stdio,id=debug,signal=off,mux=on -serial chardev:debug -mon chardev=debug -machine q35 -device ich9-intel-hda -device hda-output -device virtio-net,netdev=net0 -netdev user,id=net0 -object filter-dump,id=f1,netdev=net0,file=$pcap -nographic -vga none -drive file=$image,format=raw,if=none,id=drv0 -device nvme,drive=drv0,serial=NVME_SERIAL -drive file=$extra,format=raw,if=none,id=drv1 -device nvme,drive=drv1,serial=NVME_EXTRA -enable-kvm -cpu host $combined_qemu_args
expect "login:"
send "root\r"
expect "assword:"
send "password\r"
expect "Type 'help' for available commands."
send "redbear-bluetooth-battery-check\r"
expect "Red Bear OS Bluetooth Battery Check"
expect "BLUETOOTH_BATTERY_CHECK=pass"
send "shutdown\r"
expect eof
EOF
exit 0
fi
exec qemu-system-x86_64 \
-name "Red Bear OS x86_64" \
-device qemu-xhci \
-smp 4 \
-m 2048 \
-bios "$firmware" \
-chardev stdio,id=debug,signal=off,mux=on \
-serial chardev:debug \
-mon chardev=debug \
-machine q35 \
-device ich9-intel-hda -device hda-output \
-device virtio-net,netdev=net0 \
-netdev user,id=net0 \
-object filter-dump,id=f1,netdev=net0,file="$pcap" \
-nographic -vga none \
-drive file="$image",format=raw,if=none,id=drv0 \
-device nvme,drive=drv0,serial=NVME_SERIAL \
-drive file="$extra",format=raw,if=none,id=drv1 \
-device nvme,drive=drv1,serial=NVME_EXTRA \
-enable-kvm -cpu host \
$combined_qemu_args
+10
View File
@@ -0,0 +1,10 @@
#!/usr/bin/env bash
set -euo pipefail
if [ "$(uname -s)" != "Redox" ]; then
echo "SKIP: Bluetooth runtime helper is guest-only and requires a Redox runtime"
echo "Use the host checks for build/test verification, and run this script inside a Redox guest."
exit 0
fi
exec redbear-bluetooth-battery-check
+71
View File
@@ -0,0 +1,71 @@
#!/usr/bin/env bash
set -euo pipefail
echo "[iwlwifi-runtime] checking driver binary"
if [ ! -x /usr/lib/drivers/redbear-iwlwifi ]; then
echo "[iwlwifi-runtime] FAIL: /usr/lib/drivers/redbear-iwlwifi is missing"
exit 1
fi
echo "[iwlwifi-runtime] checking PCI surface"
if [ ! -d /scheme/pci ]; then
echo "[iwlwifi-runtime] FAIL: /scheme/pci is missing"
exit 1
fi
echo "[iwlwifi-runtime] running bounded probe"
/usr/lib/drivers/redbear-iwlwifi --probe || {
echo "[iwlwifi-runtime] FAIL: driver probe failed"
exit 1
}
echo "[iwlwifi-runtime] running bounded status"
/usr/lib/drivers/redbear-iwlwifi --status || {
echo "[iwlwifi-runtime] FAIL: driver status failed"
exit 1
}
echo "[iwlwifi-runtime] running bounded prepare"
/usr/lib/drivers/redbear-iwlwifi --prepare || {
echo "[iwlwifi-runtime] FAIL: driver prepare failed"
exit 1
}
echo "[iwlwifi-runtime] running bounded transport init"
/usr/lib/drivers/redbear-iwlwifi --init-transport || {
echo "[iwlwifi-runtime] FAIL: driver init-transport failed"
exit 1
}
echo "[iwlwifi-runtime] running bounded activate-nic"
/usr/lib/drivers/redbear-iwlwifi --activate-nic || {
echo "[iwlwifi-runtime] FAIL: driver activate-nic failed"
exit 1
}
echo "[iwlwifi-runtime] running bounded scan"
/usr/lib/drivers/redbear-iwlwifi --scan || {
echo "[iwlwifi-runtime] FAIL: driver scan failed"
exit 1
}
echo "[iwlwifi-runtime] running bounded connect"
/usr/lib/drivers/redbear-iwlwifi --connect demo wpa2-psk secret || {
echo "[iwlwifi-runtime] FAIL: driver connect failed"
exit 1
}
echo "[iwlwifi-runtime] running bounded disconnect"
/usr/lib/drivers/redbear-iwlwifi --disconnect || {
echo "[iwlwifi-runtime] FAIL: driver disconnect failed"
exit 1
}
echo "[iwlwifi-runtime] running bounded retry"
/usr/lib/drivers/redbear-iwlwifi --retry || {
echo "[iwlwifi-runtime] FAIL: driver retry failed"
exit 1
}
echo "[iwlwifi-runtime] PASS: bounded Intel Wi-Fi driver-side action set executed"
echo "[iwlwifi-runtime] NOTE: this still does not prove real scan, real association, or network connectivity"
@@ -0,0 +1,147 @@
#!/usr/bin/env bash
# Validate the bounded Intel Wi-Fi runtime path on a real Red Bear OS target.
set -euo pipefail
PROFILE="${1:-wifi-open-bounded}"
IFACE="${2:-wlan0}"
usage() {
cat <<'EOF'
Usage: test-wifi-baremetal-runtime.sh [PROFILE] [INTERFACE]
Run the strongest in-OS validation currently available for the bounded Intel Wi-Fi path.
Defaults:
PROFILE wifi-open-bounded
INTERFACE wlan0
This script validates runtime surfaces and bounded lifecycle behavior on a real Red Bear OS target.
It does NOT prove real AP association, packet flow, or end-to-end Wi-Fi connectivity by itself.
EOF
}
if [[ "${1:-}" == "--help" || "${1:-}" == "-h" ]]; then
usage
exit 0
fi
echo "=== Red Bear OS Wi-Fi Bare-Metal Runtime Check ==="
echo "profile=$PROFILE"
echo "interface=$IFACE"
need_cmd() {
if ! command -v "$1" >/dev/null 2>&1; then
echo "FAIL: missing command $1"
exit 1
fi
}
need_cmd redbear-iwlwifi
need_cmd redbear-wifictl
need_cmd redbear-netctl
need_cmd redbear-info
need_cmd redbear-phase5-wifi-capture
need_cmd redbear-phase5-wifi-check
need_cmd redbear-phase5-wifi-run
echo "--- packaged wifi check ---"
redbear-phase5-wifi-run "$PROFILE" "$IFACE" "/tmp/redbear-phase5-wifi-capture.json"
echo "--- driver probe ---"
driver_probe=$(redbear-iwlwifi --probe)
printf '%s\n' "$driver_probe"
case "$driver_probe" in
*"candidates="*) ;;
*)
echo "FAIL: redbear-iwlwifi --probe did not report candidates"
exit 1
;;
esac
echo "--- control probe ---"
wifictl_probe=$(redbear-wifictl --probe)
printf '%s\n' "$wifictl_probe"
case "$wifictl_probe" in
*"interfaces="*"$IFACE"*) ;;
*)
echo "FAIL: redbear-wifictl --probe did not report interface $IFACE"
exit 1
;;
esac
echo "--- bounded connect ---"
connect_output=$(redbear-wifictl --connect "$IFACE" demo open)
printf '%s\n' "$connect_output"
case "$connect_output" in
*"status=connected"*|*"status=associated"*|*"status=associating"*) ;;
*)
echo "FAIL: bounded connect did not report bounded connect state"
exit 1
;;
esac
case "$connect_output" in
*"connect_result="*) ;;
*)
echo "FAIL: bounded connect did not report connect_result"
exit 1
;;
esac
echo "--- bounded disconnect ---"
disconnect_output=$(redbear-wifictl --disconnect "$IFACE")
printf '%s\n' "$disconnect_output"
case "$disconnect_output" in
*"status=device-detected"*|*"status=firmware-ready"*) ;;
*)
echo "FAIL: bounded disconnect did not return interface to post-disconnect state"
exit 1
;;
esac
case "$disconnect_output" in
*"disconnect_result="*) ;;
*)
echo "FAIL: bounded disconnect did not report disconnect_result"
exit 1
;;
esac
echo "--- profile manager start/stop ---"
start_output=$(redbear-netctl start "$PROFILE")
printf '%s\n' "$start_output"
status_output=$(redbear-netctl status "$PROFILE")
printf '%s\n' "$status_output"
case "$status_output" in
*"interface=$IFACE"*) ;;
*)
echo "FAIL: netctl status did not report interface $IFACE"
exit 1
;;
esac
case "$status_output" in
*"connect_result="*) ;;
*)
echo "FAIL: netctl status did not report connect_result"
exit 1
;;
esac
stop_output=$(redbear-netctl stop "$PROFILE")
printf '%s\n' "$stop_output"
echo "--- runtime report ---"
info_output=$(redbear-info --json)
printf '%s\n' "$info_output"
case "$info_output" in
*"wifi_control_state"*"wifi_connect_result"*"wifi_disconnect_result"*) ;;
*)
echo "FAIL: redbear-info --json did not include Wi-Fi lifecycle reporting fields"
exit 1
;;
esac
capture_path="/tmp/redbear-phase5-wifi-capture.json"
echo "PASS: bounded Intel Wi-Fi runtime path exercised on target"
echo "CAPTURE: $capture_path"
echo "NOTE: this still does not prove real AP scan/auth/association, packet flow, DHCP success over Wi-Fi, or validated end-to-end connectivity"
+252
View File
@@ -0,0 +1,252 @@
#!/usr/bin/env bash
set -euo pipefail
echo "[wifi-runtime] checking wifictl scheme"
if [ ! -d /scheme/wifictl ]; then
echo "[wifi-runtime] FAIL: /scheme/wifictl is missing"
exit 1
fi
echo "[wifi-runtime] checking bounded Intel driver package"
if [ ! -x /usr/lib/drivers/redbear-iwlwifi ]; then
echo "[wifi-runtime] FAIL: /usr/lib/drivers/redbear-iwlwifi is missing"
exit 1
fi
echo "[wifi-runtime] probing Intel Wi-Fi candidates"
driver_probe=$(/usr/lib/drivers/redbear-iwlwifi --probe 2>/dev/null)
printf '%s\n' "$driver_probe"
case "$driver_probe" in
*"candidates="*)
;;
*)
echo "[wifi-runtime] FAIL: redbear-iwlwifi --probe did not report candidates=..."
exit 1
;;
esac
echo "[wifi-runtime] checking backend selection behavior"
probe_output=$(redbear-wifictl --probe 2>/dev/null || true)
printf '%s\n' "$probe_output"
case "$driver_probe" in
*"candidates=0"*)
case "$probe_output" in
*"backend=no-device"*)
echo "[wifi-runtime] NOTE: no Intel Wi-Fi candidates detected; no-device backend fallback is expected"
;;
*)
echo "[wifi-runtime] FAIL: expected no-device fallback when no Intel Wi-Fi candidates are detected"
exit 1
;;
esac
;;
*)
case "$probe_output" in
*"backend=intel"*)
;;
*)
echo "[wifi-runtime] FAIL: redbear-wifictl --probe did not report backend=intel when Intel Wi-Fi candidates are present"
exit 1
;;
esac
;;
esac
echo "[wifi-runtime] checking wifictl interface surface"
if [ ! -d /scheme/wifictl/ifaces ]; then
echo "[wifi-runtime] FAIL: /scheme/wifictl/ifaces is missing"
exit 1
fi
echo "[wifi-runtime] checking firmware base path"
if [ ! -d /lib/firmware ]; then
echo "[wifi-runtime] FAIL: /lib/firmware is missing"
exit 1
fi
echo "[wifi-runtime] listing interfaces"
ls /scheme/wifictl/ifaces || true
first_iface=$(ls /scheme/wifictl/ifaces 2>/dev/null | head -n 1 || true)
if [ -n "$first_iface" ]; then
echo "[wifi-runtime] checking firmware-status for $first_iface"
if [ ! -f "/scheme/wifictl/ifaces/$first_iface/firmware-status" ]; then
echo "[wifi-runtime] FAIL: missing /scheme/wifictl/ifaces/$first_iface/firmware-status"
exit 1
fi
cat "/scheme/wifictl/ifaces/$first_iface/firmware-status" || true
echo "[wifi-runtime] checking transport-status for $first_iface"
if [ ! -f "/scheme/wifictl/ifaces/$first_iface/transport-status" ]; then
echo "[wifi-runtime] FAIL: missing /scheme/wifictl/ifaces/$first_iface/transport-status"
exit 1
fi
cat "/scheme/wifictl/ifaces/$first_iface/transport-status" || true
echo "[wifi-runtime] checking prepare control node for $first_iface"
if [ ! -f "/scheme/wifictl/ifaces/$first_iface/prepare" ]; then
echo "[wifi-runtime] FAIL: missing /scheme/wifictl/ifaces/$first_iface/prepare"
exit 1
fi
echo "[wifi-runtime] checking scan control and scan-results for $first_iface"
if [ ! -f "/scheme/wifictl/ifaces/$first_iface/scan" ]; then
echo "[wifi-runtime] FAIL: missing /scheme/wifictl/ifaces/$first_iface/scan"
exit 1
fi
if [ ! -f "/scheme/wifictl/ifaces/$first_iface/scan-results" ]; then
echo "[wifi-runtime] FAIL: missing /scheme/wifictl/ifaces/$first_iface/scan-results"
exit 1
fi
echo "[wifi-runtime] checking transport-probe control node for $first_iface"
if [ ! -f "/scheme/wifictl/ifaces/$first_iface/transport-probe" ]; then
echo "[wifi-runtime] FAIL: missing /scheme/wifictl/ifaces/$first_iface/transport-probe"
exit 1
fi
echo "[wifi-runtime] checking transport-init nodes for $first_iface"
if [ ! -f "/scheme/wifictl/ifaces/$first_iface/init-transport" ]; then
echo "[wifi-runtime] FAIL: missing /scheme/wifictl/ifaces/$first_iface/init-transport"
exit 1
fi
if [ ! -f "/scheme/wifictl/ifaces/$first_iface/transport-init-status" ]; then
echo "[wifi-runtime] FAIL: missing /scheme/wifictl/ifaces/$first_iface/transport-init-status"
exit 1
fi
cat "/scheme/wifictl/ifaces/$first_iface/transport-init-status" || true
echo "[wifi-runtime] checking activate-nic and activation-status for $first_iface"
if [ ! -f "/scheme/wifictl/ifaces/$first_iface/activate-nic" ]; then
echo "[wifi-runtime] FAIL: missing /scheme/wifictl/ifaces/$first_iface/activate-nic"
exit 1
fi
if [ ! -f "/scheme/wifictl/ifaces/$first_iface/activation-status" ]; then
echo "[wifi-runtime] FAIL: missing /scheme/wifictl/ifaces/$first_iface/activation-status"
exit 1
fi
cat "/scheme/wifictl/ifaces/$first_iface/activation-status" || true
echo "[wifi-runtime] checking connect control and profile fields for $first_iface"
if [ ! -f "/scheme/wifictl/ifaces/$first_iface/connect" ]; then
echo "[wifi-runtime] FAIL: missing /scheme/wifictl/ifaces/$first_iface/connect"
exit 1
fi
if [ ! -f "/scheme/wifictl/ifaces/$first_iface/ssid" ]; then
echo "[wifi-runtime] FAIL: missing /scheme/wifictl/ifaces/$first_iface/ssid"
exit 1
fi
if [ ! -f "/scheme/wifictl/ifaces/$first_iface/security" ]; then
echo "[wifi-runtime] FAIL: missing /scheme/wifictl/ifaces/$first_iface/security"
exit 1
fi
if [ ! -f "/scheme/wifictl/ifaces/$first_iface/key" ]; then
echo "[wifi-runtime] FAIL: missing /scheme/wifictl/ifaces/$first_iface/key"
exit 1
fi
if [ ! -f "/scheme/wifictl/ifaces/$first_iface/connect-result" ]; then
echo "[wifi-runtime] FAIL: missing /scheme/wifictl/ifaces/$first_iface/connect-result"
exit 1
fi
if [ ! -f "/scheme/wifictl/ifaces/$first_iface/disconnect-result" ]; then
echo "[wifi-runtime] FAIL: missing /scheme/wifictl/ifaces/$first_iface/disconnect-result"
exit 1
fi
echo "[wifi-runtime] exercising bounded connect for $first_iface"
printf 'demo-open\n' > "/scheme/wifictl/ifaces/$first_iface/ssid"
printf 'open\n' > "/scheme/wifictl/ifaces/$first_iface/security"
printf '\n' > "/scheme/wifictl/ifaces/$first_iface/key"
printf '1\n' > "/scheme/wifictl/ifaces/$first_iface/connect"
connect_status=$(cat "/scheme/wifictl/ifaces/$first_iface/status" 2>/dev/null || true)
connect_result=$(cat "/scheme/wifictl/ifaces/$first_iface/connect-result" 2>/dev/null || true)
printf '%s\n' "$connect_status"
printf '%s\n' "$connect_result"
case "$connect_status" in
*"connected"*|*"associated"*)
;;
*)
echo "[wifi-runtime] FAIL: bounded connect did not update status to a connected/associated state"
exit 1
;;
esac
case "$connect_result" in
*"connect_result="*)
;;
*)
echo "[wifi-runtime] FAIL: bounded connect did not produce connect-result output"
exit 1
;;
esac
echo "[wifi-runtime] exercising bounded disconnect for $first_iface"
if [ ! -f "/scheme/wifictl/ifaces/$first_iface/disconnect" ]; then
echo "[wifi-runtime] FAIL: missing /scheme/wifictl/ifaces/$first_iface/disconnect"
exit 1
fi
printf '1\n' > "/scheme/wifictl/ifaces/$first_iface/disconnect"
disconnect_status=$(cat "/scheme/wifictl/ifaces/$first_iface/status" 2>/dev/null || true)
disconnect_result=$(cat "/scheme/wifictl/ifaces/$first_iface/disconnect-result" 2>/dev/null || true)
printf '%s\n' "$disconnect_status"
printf '%s\n' "$disconnect_result"
case "$disconnect_status" in
*"device-detected"*|*"firmware-ready"*)
;;
*)
echo "[wifi-runtime] FAIL: bounded disconnect did not return the interface to a post-disconnect state"
exit 1
;;
esac
case "$disconnect_result" in
*"disconnect"*)
;;
*)
echo "[wifi-runtime] FAIL: bounded disconnect did not produce disconnect result output"
exit 1
;;
esac
else
case "$driver_probe" in
*"candidates=0"*)
echo "[wifi-runtime] NOTE: no wifictl interfaces are expected when no Intel Wi-Fi candidates are present"
;;
*)
echo "[wifi-runtime] FAIL: Intel Wi-Fi candidates were detected but /scheme/wifictl/ifaces is empty"
exit 1
;;
esac
fi
echo "[wifi-runtime] checking netctl Wi-Fi examples"
if [ ! -f /etc/netctl/examples/wifi-dhcp ]; then
echo "[wifi-runtime] FAIL: missing /etc/netctl/examples/wifi-dhcp"
exit 1
fi
if [ ! -f /etc/netctl/examples/wifi-open-bounded ]; then
echo "[wifi-runtime] FAIL: missing /etc/netctl/examples/wifi-open-bounded"
exit 1
fi
echo "[wifi-runtime] exercising netctl profile stop for wifi-open-bounded"
redbear-netctl stop wifi-open-bounded >/tmp/redbear-netctl-stop.out 2>/tmp/redbear-netctl-stop.err || {
cat /tmp/redbear-netctl-stop.err || true
echo "[wifi-runtime] FAIL: redbear-netctl stop wifi-open-bounded failed"
exit 1
}
cat /tmp/redbear-netctl-stop.out || true
echo "[wifi-runtime] checking netcfg interface tree"
if [ ! -d /scheme/netcfg/ifaces ]; then
echo "[wifi-runtime] FAIL: /scheme/netcfg/ifaces is missing"
exit 1
fi
echo "[wifi-runtime] netcfg interfaces:"
cat /scheme/netcfg/ifaces || true
echo "[wifi-runtime] PASS: bounded Wi-Fi control-plane surfaces are present"
echo "[wifi-runtime] PASS: experimental runtime selects the Intel backend only when Intel Wi-Fi candidates are actually present"
echo "[wifi-runtime] NOTE: this does not prove real radio association or working Wi-Fi connectivity"
+170
View File
@@ -0,0 +1,170 @@
#!/usr/bin/env bash
# Launch Red Bear OS with an Intel Wi-Fi PCI device passed through for runtime validation.
set -euo pipefail
find_uefi_firmware() {
local candidates=(
"/usr/share/ovmf/x64/OVMF.4m.fd"
"/usr/share/OVMF/x64/OVMF.4m.fd"
"/usr/share/ovmf/x64/OVMF_CODE.4m.fd"
"/usr/share/OVMF/x64/OVMF_CODE.4m.fd"
"/usr/share/ovmf/OVMF.fd"
"/usr/share/OVMF/OVMF_CODE.fd"
"/usr/share/qemu/edk2-x86_64-code.fd"
)
local path
for path in "${candidates[@]}"; do
if [[ -f "$path" ]]; then
printf '%s\n' "$path"
return 0
fi
done
return 1
}
capture_output=""
usage() {
cat <<'EOF'
Usage: test-wifi-passthrough-qemu.sh --host-pci 0000:xx:yy.z [--check] [--capture-output PATH] [extra qemu args...]
Boot Red Bear OS with an Intel Wi-Fi PCI function passed through via VFIO and optionally run the
bounded in-guest Wi-Fi runtime check.
Options:
--host-pci BDF Host PCI address of the Intel Wi-Fi device to pass through (required)
--check Auto-login and run redbear-phase5-network-check plus the bounded Wi-Fi runtime check
--capture-output PATH Save the in-guest Wi-Fi capture bundle to a host-side file during --check
-h, --help Show this help text
Notes:
- The host device must already be detached from the host driver and bound to vfio-pci.
- This script only provides the launch/check harness. Real success still depends on Red Bear OS
runtime behavior on the passed-through hardware.
EOF
}
host_pci=""
check_mode=0
filtered_args=()
while [[ $# -gt 0 ]]; do
case "$1" in
--host-pci)
if [[ $# -lt 2 ]]; then
echo "ERROR: --host-pci requires a PCI BDF" >&2
exit 1
fi
host_pci="$2"
shift 2
;;
--check)
check_mode=1
shift
;;
--capture-output)
if [[ $# -lt 2 ]]; then
echo "ERROR: --capture-output requires a path" >&2
exit 1
fi
capture_output="$2"
shift 2
;;
--help|-h)
usage
exit 0
;;
*)
filtered_args+=("$1")
shift
;;
esac
done
if [[ -z "$host_pci" ]]; then
echo "ERROR: --host-pci is required" >&2
usage
exit 1
fi
firmware="$(find_uefi_firmware)" || {
echo "ERROR: no usable x86_64 UEFI firmware found" >&2
exit 1
}
arch="${ARCH:-$(uname -m)}"
image="build/$arch/redbear-full/harddrive.img"
extra="build/$arch/redbear-full/extra.img"
if [[ ! -f "$image" ]]; then
echo "ERROR: missing image $image" >&2
echo "Build it first with: ./local/scripts/build-redbear.sh redbear-full" >&2
exit 1
fi
if [[ ! -f "$extra" ]]; then
truncate -s 1g "$extra"
fi
vfio_arg="vfio-pci,host=${host_pci}"
if [[ "$check_mode" -eq 1 ]]; then
capture_output="${capture_output:-$(pwd)/wifi-passthrough-capture.json}"
expect <<EOF
log_user 1
set timeout 420
spawn qemu-system-x86_64 -name {Red Bear OS Wi-Fi Passthrough} -device qemu-xhci -smp 4 -m 4096 -bios $firmware -chardev stdio,id=debug,signal=off,mux=on -serial chardev:debug -mon chardev=debug -machine q35 -device ich9-intel-hda -device hda-output -device vfio-pci,host=$host_pci -vga std -drive file=$image,format=raw,if=none,id=drv0 -device nvme,drive=drv0,serial=NVME_SERIAL -drive file=$extra,format=raw,if=none,id=drv1 -device nvme,drive=drv1,serial=NVME_EXTRA -enable-kvm -cpu host ${filtered_args[*]}
expect "login:"
send "root\r"
expect "assword:"
send "password\r"
expect "Type 'help' for available commands."
send "redbear-phase5-network-check\r"
expect "Red Bear OS Phase 5 Networking Check"
send "redbear-phase5-wifi-run wifi-open-bounded wlan0 /tmp/redbear-phase5-wifi-capture.json\r"
expect "Red Bear OS Phase 5 Wi-Fi Check"
expect "PASS: bounded Intel Wi-Fi runtime path exercised on target"
expect "capture_output=/tmp/redbear-phase5-wifi-capture.json"
expect "root@"
send "wc -c /tmp/redbear-phase5-wifi-capture.json\r"
expect "/tmp/redbear-phase5-wifi-capture.json"
send "printf 'CAPTURE-BEGIN\\n'; cat /tmp/redbear-phase5-wifi-capture.json; printf '\\nCAPTURE-END\\n'\r"
expect "CAPTURE-BEGIN"
expect {
-re {(\{.*\})\r?\nCAPTURE-END} {
set capture $expect_out(1,string)
set fh [open "$capture_output" "w"]
puts $fh $capture
close $fh
}
timeout {
send_user "ERROR: timed out while capturing Wi-Fi bundle\n"
exit 1
}
}
send "shutdown\r"
expect eof
EOF
echo "capture_output=$capture_output"
exit 0
fi
exec qemu-system-x86_64 \
-name "Red Bear OS Wi-Fi Passthrough" \
-device qemu-xhci \
-smp 4 \
-m 4096 \
-bios "$firmware" \
-chardev stdio,id=debug,signal=off,mux=on \
-serial chardev:debug \
-mon chardev=debug \
-machine q35 \
-device ich9-intel-hda -device hda-output \
-device "$vfio_arg" \
-vga std \
-drive file="$image",format=raw,if=none,id=drv0 \
-device nvme,drive=drv0,serial=NVME_SERIAL \
-drive file="$extra",format=raw,if=none,id=drv1 \
-device nvme,drive=drv1,serial=NVME_EXTRA \
-enable-kvm -cpu host \
"${filtered_args[@]}"
+175
View File
@@ -0,0 +1,175 @@
#!/usr/bin/env bash
# Validate host prerequisites for Intel Wi-Fi VFIO passthrough testing.
set -euo pipefail
usage() {
cat <<'EOF'
Usage: validate-wifi-vfio-host.sh --host-pci 0000:xx:yy.z [--expect-driver DRIVER]
Check whether the current host appears ready to run the Red Bear Intel Wi-Fi VFIO passthrough
validation path.
Options:
--host-pci BDF Host PCI address of the Intel Wi-Fi device to validate (required)
--expect-driver NAME Host driver expected before VFIO rebind (optional)
-h, --help Show this help text
This command does not modify the host. It only reports readiness signals and common blockers.
EOF
}
host_pci=""
expect_driver=""
while [[ $# -gt 0 ]]; do
case "$1" in
--host-pci)
host_pci="$2"
shift 2
;;
--expect-driver)
expect_driver="$2"
shift 2
;;
--help|-h)
usage
exit 0
;;
*)
echo "ERROR: unknown argument $1" >&2
usage
exit 1
;;
esac
done
if [[ -z "$host_pci" ]]; then
echo "ERROR: --host-pci is required" >&2
usage
exit 1
fi
script_root="$(dirname "$0")"
repo_root="$(cd "$script_root/../.." && pwd)"
arch="${ARCH:-$(uname -m)}"
image="$repo_root/build/$arch/redbear-full/harddrive.img"
find_uefi_firmware() {
local candidates=(
"/usr/share/ovmf/x64/OVMF.4m.fd"
"/usr/share/OVMF/x64/OVMF.4m.fd"
"/usr/share/ovmf/x64/OVMF_CODE.4m.fd"
"/usr/share/OVMF/x64/OVMF_CODE.4m.fd"
"/usr/share/ovmf/OVMF.fd"
"/usr/share/OVMF/OVMF_CODE.fd"
"/usr/share/qemu/edk2-x86_64-code.fd"
)
local path
for path in "${candidates[@]}"; do
if [[ -f "$path" ]]; then
printf '%s\n' "$path"
return 0
fi
done
return 1
}
current_driver() {
local bdf="$1"
local link="/sys/bus/pci/devices/$bdf/driver"
if [[ -L "$link" ]]; then
basename "$(readlink -f "$link")"
else
printf 'none\n'
fi
}
read_pci_id() {
local bdf="$1"
local vendor device
vendor=$(<"/sys/bus/pci/devices/$bdf/vendor")
device=$(<"/sys/bus/pci/devices/$bdf/device")
printf '%s %s\n' "$vendor" "$device"
}
status=0
echo "=== Red Bear Wi-Fi VFIO Host Validation ==="
echo "host_pci=$host_pci"
if [[ ! -e "/sys/bus/pci/devices/$host_pci" ]]; then
echo "FAIL: PCI device $host_pci not found in sysfs"
exit 1
fi
read -r vendor device < <(read_pci_id "$host_pci")
driver=$(current_driver "$host_pci")
echo "vendor=$vendor"
echo "device=$device"
echo "current_driver=$driver"
if [[ -n "$expect_driver" && "$driver" != "$expect_driver" && "$driver" != "vfio-pci" ]]; then
echo "WARN: expected host driver $expect_driver but found $driver"
status=1
fi
if ! find_uefi_firmware >/dev/null; then
echo "FAIL: no supported x86_64 UEFI firmware found for QEMU"
status=1
else
echo "uefi_firmware=present"
fi
if [[ ! -f "$image" ]]; then
echo "FAIL: missing image $image"
status=1
else
echo "redbear_image=present"
fi
if ! command -v qemu-system-x86_64 >/dev/null 2>&1; then
echo "FAIL: missing qemu-system-x86_64"
status=1
else
echo "qemu=present"
fi
if ! command -v expect >/dev/null 2>&1; then
echo "FAIL: missing expect"
status=1
else
echo "expect=present"
fi
if ! lsmod | grep -q '^vfio_pci'; then
echo "WARN: vfio_pci module is not currently loaded"
status=1
else
echo "vfio_pci=loaded"
fi
if [[ -d /sys/kernel/iommu_groups && -n "$(find /sys/kernel/iommu_groups -mindepth 1 -maxdepth 1 -type d 2>/dev/null)" ]]; then
echo "iommu_groups=present"
else
echo "WARN: IOMMU groups not visible under /sys/kernel/iommu_groups"
status=1
fi
if command -v lspci >/dev/null 2>&1; then
echo "lspci_summary=$(lspci -nn -s "$host_pci" 2>/dev/null || true)"
fi
if [[ "$driver" == "vfio-pci" ]]; then
echo "vfio_binding=already-bound"
else
echo "vfio_binding=not-bound"
fi
if [[ "$status" -eq 0 ]]; then
echo "PASS: host appears ready for Wi-Fi VFIO validation"
else
echo "FAIL: host validation found one or more blockers/warnings"
fi
exit "$status"