# -*- mode: python -*-
# qemu_helpers: Helpers to find QEMU and handle its quirks
# Copyright © 2014 Andy Lutomirski
# Licensed under the GPLv2, which is available in the virtme distribution
# as a file called LICENSE with SHA-256 hash:
# 8177f97513213526df2cf6184d8ff986c675afb514d4e68a404010521b880643

import os

class Arch(object):
    def __init__(self, name):
        self.virtmename = name
        self.qemuname = name
        self.linuxname = name
        self.gccname = name

    defconfig_target = 'defconfig'

    @staticmethod
    def serial_dev_name(index):
        return 'ttyS%d' % index

    @staticmethod
    def qemuargs(is_native):
        return []

    @staticmethod
    def virtio_dev_type(virtiotype):
        # Return a full name for a virtio device.  It would be
        # nice if QEMU abstracted this away, but it doesn't.
        return 'virtio-%s-pci' % virtiotype

    @staticmethod
    def earlyconsole_args():
        return []

    @staticmethod
    def serial_console_args():
        return []

    @staticmethod
    def qemu_nodisplay_args():
        return ['-vga', 'none', '-display', 'none']

    @staticmethod
    def config_base():
        return []

    def kimg_path(self):
        return 'arch/%s/boot/bzImage' % self.linuxname

    @staticmethod
    def dtb_path():
        return None

class Arch_unknown(Arch):
    @staticmethod
    def qemuargs(is_native):
        return Arch.qemuargs(is_native)

class Arch_x86(Arch):
    def __init__(self, name):
        Arch.__init__(self, name)

        self.linuxname = 'x86'
        self.defconfig_target = '%s_defconfig' % name

    @staticmethod
    def qemuargs(is_native):
        ret = Arch.qemuargs(is_native)

        # Add a watchdog.  This is useful for testing.
        ret.extend(['-watchdog', 'i6300esb'])

        if is_native and os.access('/dev/kvm', os.R_OK):
            # If we're likely to use KVM, request a full-featured CPU.
            # (NB: if KVM fails, this will cause problems.  We should probe.)
            ret.extend(['-cpu', 'host'])  # We can't migrate regardless.

        return ret

    @staticmethod
    def earlyconsole_args():
        return ['earlyprintk=serial,ttyS0,115200']

    @staticmethod
    def serial_console_args():
        return ['console=ttyS0']

    @staticmethod
    def config_base():
        return ['CONFIG_SERIO=y',
                'CONFIG_PCI=y',
                'CONFIG_INPUT=y',
                'CONFIG_INPUT_KEYBOARD=y',
                'CONFIG_KEYBOARD_ATKBD=y',
                'CONFIG_SERIAL_8250=y',
                'CONFIG_SERIAL_8250_CONSOLE=y',
                'CONFIG_X86_VERBOSE_BOOTUP=y',
                'CONFIG_VGA_CONSOLE=y',
                'CONFIG_FB=y',
                'CONFIG_FB_VESA=y',
                'CONFIG_FRAMEBUFFER_CONSOLE=y',
                'CONFIG_RTC_CLASS=y',
                'CONFIG_RTC_HCTOSYS=y',
                'CONFIG_RTC_DRV_CMOS=y',
                'CONFIG_HYPERVISOR_GUEST=y',
                'CONFIG_PARAVIRT=y',
                'CONFIG_KVM_GUEST=y',

                # Depending on the host kernel, virtme can nest!
                'CONFIG_KVM=y',
                'CONFIG_KVM_INTEL=y',
                'CONFIG_KVM_AMD=y',
            ]

class Arch_arm(Arch):
    def __init__(self):
        Arch.__init__(self, 'arm')

        self.defconfig_target = 'vexpress_defconfig'

    @staticmethod
    def qemuargs(is_native):
        ret = Arch.qemuargs(is_native)

        # Emulate a vexpress-a15.
        ret.extend(['-M', 'vexpress-a15'])

        # TODO: consider adding a PCI bus (and figuring out how)

        # TODO: This won't boot unless -dtb is set, but we need to figure
        # out how to find the dtb file.

        return ret

    @staticmethod
    def virtio_dev_type(virtiotype):
        return 'virtio-%s-device' % virtiotype

    @staticmethod
    def earlyconsole_args():
        return ['earlyprintk=serial,ttyAMA0,115200']

    @staticmethod
    def serial_console_args():
        return ['console=ttyAMA0']

    def kimg_path(self):
        return 'arch/arm/boot/zImage'

    def dtb_path(self):
        return 'arch/arm/boot/dts/vexpress-v2p-ca15-tc1.dtb'

class Arch_aarch64(Arch):
    def __init__(self):
        Arch.__init__(self, 'aarch64')

        self.qemuname = 'aarch64'
        self.linuxname = 'arm64'
        self.gccname = 'aarch64'

    @staticmethod
    def qemuargs(is_native):
        ret = Arch.qemuargs(is_native)

        # Emulate a fully virtual system.
        ret.extend(['-M', 'virt'])

        # Despite being called qemu-system-aarch64, QEMU defaults to
        # emulating a 32-bit CPU.  Override it.
        ret.extend(['-cpu', 'cortex-a57'])

        return ret

    @staticmethod
    def virtio_dev_type(virtiotype):
        return 'virtio-%s-device' % virtiotype

    @staticmethod
    def earlyconsole_args():
        return ['earlyprintk=serial,ttyAMA0,115200']

    @staticmethod
    def serial_console_args():
        return ['console=ttyAMA0']

    def kimg_path(self):
        return 'arch/arm64/boot/Image'

class Arch_ppc64(Arch):
    def __init__(self):
        Arch.__init__(self, 'ppc64')

        self.defconfig_target = 'ppc64_defconfig'
        self.qemuname = 'ppc64'
        self.linuxname = 'powerpc'
        self.gccname = 'ppc64'

    def qemuargs(self, is_native):
        ret = Arch.qemuargs(is_native)

        ret.extend(['-M', 'pseries'])

        return ret

    def kimg_path(self):
        # Apparently SLOF (QEMU's bundled firmware?) can't boot a zImage.
        return 'vmlinux'

class Arch_riscv64(Arch):
    def __init__(self):
        Arch.__init__(self, 'riscv64')

        self.defconfig_target = 'defconfig'
        self.qemuname = 'riscv64'
        self.linuxname = 'riscv'
        self.gccname = 'riscv64'

    def qemuargs(self, is_native):
        ret = Arch.qemuargs(is_native)

        ret.extend(['-machine', 'virt'])
        ret.extend(['-bios', 'default'])

        return ret

    @staticmethod
    def serial_console_args():
        return ['console=ttyS0']

    def kimg_path(self):
        return 'arch/riscv/boot/Image'

class Arch_sparc64(Arch):
    def __init__(self):
        Arch.__init__(self, 'sparc64')

        self.defconfig_target = 'sparc64_defconfig'
        self.qemuname = 'sparc64'
        self.linuxname = 'sparc'
        self.gccname = 'sparc64'

    def qemuargs(self, is_native):
        ret = Arch.qemuargs(is_native)

        return ret

    def kimg_path(self):
        return 'arch/sparc/boot/image'

    def qemu_nodisplay_args(self):
        # qemu-system-sparc fails to boot if -display none is set.
        return ['-nographic', '-vga', 'none']

class Arch_s390x(Arch):
    def __init__(self):
        Arch.__init__(self, 's390x')

        self.qemuname = 's390x'
        self.linuxname = 's390'
        self.gccname = 's390x'

    @staticmethod
    def virtio_dev_type(virtiotype):
        return 'virtio-%s-ccw' % virtiotype

    def qemuargs(self, is_native):
        ret = Arch.qemuargs(is_native)

        # Ask for the latest version of s390-ccw
        ret.extend(['-M', 's390-ccw-virtio'])

        # To be able to configure a console, we need to get rid of the
        # default console
        ret.extend(['-nodefaults'])

        ret.extend(['-device', 'sclpconsole,chardev=console'])

        return ret

    @staticmethod
    def config_base():
        return ['CONFIG_MARCH_Z900=y']

ARCHES = {arch.virtmename: arch for arch in [
    Arch_x86('x86_64'),
    Arch_x86('i386'),
    Arch_arm(),
    Arch_aarch64(),
    Arch_ppc64(),
    Arch_riscv64(),
    Arch_sparc64(),
    Arch_s390x(),
]}

def get(arch):
    if arch in ARCHES:
        return ARCHES[arch]
    else:
        return Arch_unknown(arch)
