# Copyright (c) 2021 The Regents of the University of California
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met: redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer;
# redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution;
# neither the name of the copyright holders nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

from abc import abstractmethod

from ...resources.resource import AbstractResource

from typing import List, Optional
import os

import m5

class KernelDiskWorkload:
    """
    The purpose of this abstract class is to enable a full-system boot
    consisting of of a kernel which will then load a disk image.

    For this to function correctly, the KernelDiskWorkload class should be
    added as a superclass to a board and the abstract methods implemented.
    E.g.:

    ```
    class X86Board(AbstractBoard, KernelDiskWorkload):
        ...
        @overrides(KernelDiskWorkload)
        def get_default_kernel_args(self) -> List[str]:
            return [
                "earlyprintk=ttyS0",
                "console=ttyS0",
                "lpj=7999923",
                "root={root_value}",
            ]
        ...
    ```

    Notes
    -----

    * This assumes only one disk is set.
    * This assumes the Linux kernel is used.
    """

    @abstractmethod
    def get_default_kernel_args(self) -> List[str]:
        """
        Returns a default list of arguments for the workload kernel. We assume
        the following strings may be used as placeholders, to be replaced when
        `set_kernel_disk_workload` is executed:

        * `{root_value}` : set to `get_default_kernel_root_val()`.

        :returns: A default list of arguments for the workload kernel.
        """
        raise NotImplementedError

    @abstractmethod
    def get_disk_device(self) -> str:
        """
        Get the disk device, e.g., "/dev/sda", where the disk image is placed.

        :returns: The disk device.
        """
        raise NotImplementedError

    @abstractmethod
    def _add_disk_to_board(self, disk_image: AbstractResource) -> None:
        """
        Sets the configuration needed to add the disk image to the board.

        **Note:** This will be executed at the end of the
        `set_kernel_disk_workload` function.

        :param disk_image: The disk image to add to the system.
        """
        raise NotImplementedError

    def get_disk_root_partition(
        cls, disk_image: AbstractResource
    ) -> Optional[str]:
        """
        Obtains the root partition of a disk image by inspecting the resource's
        metadata.

        :returns: The disk image's root partition.
        """
        try:
            return disk_image.get_metadata()["additional_metadata"][
                "root_partition"
            ]
        except KeyError:
            return None

    def get_default_kernel_root_val(self, disk_image: AbstractResource) -> str:
        """
        Get the default kernel root value to be passed to the kernel. This is
        determined by the value implemented in the `get_disk_device()`
        function, and the disk image partition, obtained from
        `get_disk_root_partition()`


        :param disk_image: The disk image to be added to the system.
        :returns: The default value for the 'root' argument to be passed to the
        kernel.
        """
        return self.get_disk_device() + (
            self.get_disk_root_partition(disk_image) or ""
        )

    def set_kernel_disk_workload(
        self,
        kernel: AbstractResource,
        disk_image: AbstractResource,
        readfile: Optional[str] = None,
        readfile_contents: Optional[str] = None,
        kernel_args: Optional[List[str]] = None,
        exit_on_work_items: bool = True,
    ) -> None:
        """
        This function allows the setting of a full-system run with a Kernel
        and a disk image.

        :param kernel: The kernel to boot.
        :param disk_image: The disk image to mount.
        :param readfile: An optional parameter stating the file to be read by
        by `m5 readfile`.
        :param readfile_contents: An optional parameter stating the contents of
        the readfile file. If set with `readfile`, the contents of `readfile`
        will be overwritten with `readfile_contents`, otherwise a new file will
        be created with the value of `readfile_contents`.
        :param kernel_args: An optional parameter for setting arguments to be
        passed to the kernel. By default set to `get_default_kernel_args()`.
        :param exit_on_work_items: Whether the simulation should exit on work
        items. True by default.
        """

        # Set the kernel to use.
        self.workload.object_file = kernel.get_local_path()

        # Set the arguments to be passed to the kernel.
        self.workload.command_line = (
            " ".join(kernel_args or self.get_default_kernel_args())
        ).format(
            root_value=self.get_default_kernel_root_val(disk_image=disk_image)
        )

        # Set the readfile.
        if readfile:
            self.readfile = readfile
        elif readfile_contents:
            self.readfile = os.path.join(m5.options.outdir, "readfile")

        # Add the contents to the readfile, if specified.
        if readfile_contents:
            file = open(self.readfile, "w+")
            file.write(readfile_contents)
            file.close()

        self._add_disk_to_board(disk_image=disk_image)

        # Set whether to exit on work items.
        self.exit_on_work_items = exit_on_work_items