#!/usr/bin/python3
#
# SPDX-License-Identifier: GPL-2.0-only
# (c) 2026 Gerd Hoffmann
#
# pylint: disable=too-many-arguments
# pylint: disable=too-many-positional-arguments
# pylint: disable=too-many-branches
""" misc helper functions for automagic configuration """
import os
import glob

from virt.qemutest.firmware import QemuFirmware

QEMU_BINARY = os.environ.get("QEMU_BINARY")

def find_qemu_binary(guestarch = None):
    hostarch = os.uname().machine
    if guestarch is None:
        guestarch = hostarch
    path = os.environ.get('PATH').split(':')
    name = f'qemu-system-{guestarch}'
    bins = []
    for directory in path:
        bins.append(f'{directory}/{name}')
    if guestarch == hostarch:
        bins.append("/usr/bin/qemu-kvm")
        bins.append("/usr/libexec/qemu-kvm")
    if QEMU_BINARY is not None:
        bins.insert(0, QEMU_BINARY)
    for qemu in bins:
        if os.path.exists(qemu):
            return qemu
    return None

def qemu_default_tcg_cpu(arch):
    if arch in ('riscv64', 'loongarch64'):
        return 'max'
    if arch == 'aarch64':
        return 'cortex-a76'
    if arch == 'arm':
        return 'cortex-a15'
    if arch == 'i386':
        return 'coreduo'
    if arch == 'x86_64':
        return 'Haswell'
    raise RuntimeError(f'unknown arch: {arch}')

def qemu_default_machine(arch = None):
    if arch is None:
        arch = os.uname().machine
    if arch in ('arm', 'aarch64', 'riscv64', 'loongarch64'):
        return 'virt'
    if arch == 'i386':
        return 'pc'
    if arch == 'x86_64':
        return 'q35'
    raise RuntimeError(f'unknown arch: {arch}')

def find_firmware(arch = None, machine = None,
                  smm = False, qemuvars = False, sb = False,
                  sev = False, snp = False):
    if arch is None:
        arch = os.uname().machine
    if machine is None:
        machine = qemu_default_machine(arch)
    mbase = machine.split(',')[0]

    for filename in sorted(glob.glob('/usr/share/qemu/firmware/*.json')):
        fw = QemuFirmware(filename = filename)
        if not 'uefi' in fw.data.get('interface-types'):
            continue

        # check sb features
        if fw.requires_smm() and not smm:
            continue
        if qemuvars and not fw.requires_qemu_vars():
            continue
        if sb and not fw.has_sb_enabled():
            continue

        # check cc features
        if sev and not fw.has_cc_sev():
            continue
        if snp and not fw.has_cc_snp():
            continue

        # check arch + machine type
        for target in fw.data.get('targets'):
            if target.get('architecture') != arch:
                continue
            for item in target.get('machines'):
                if mbase == item:
                    return fw
                if mbase == 'virt' and item == 'virt-*':
                    return fw
                if mbase == 'q35' and item == 'pc-q35-*':
                    return fw
                if mbase == 'pc' and item == 'pc-i440fx-*':
                    return fw

    return None
