# Copyright 2018 The Hafnium Authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

import("//build/toolchain/embedded.gni")

# Build image, link to an ELF file then convert to plain binary.
template("image_binary") {
  assert(defined(invoker.image_name),
         "image_binary() must specify an \"image_name\" value")

  output_root = ""
  if (defined(invoker.output_path)) {
    output_root += "${invoker.output_path}/"
  }
  output_root += invoker.image_name

  # Link objects together
  executable("${target_name}__elf") {
    forward_variables_from(invoker,
                           [
                             "cflags",
                             "cflags_c",
                             "defines",
                             "deps",
                             "include_dirs",
                             "public_configs",
                             "public_deps",
                             "sources",
                             "testonly",
                           ])
    output_name = "${output_root}.elf"
    inputs = [
      rebase_path("//build/image/image.ld"),
    ]
    ldflags = [
      "-T",
      rebase_path("//build/image/image.ld"),
    ]
    visibility = [ ":${invoker.target_name}" ]
  }

  action(target_name) {
    forward_variables_from(invoker, [ "testonly" ])

    file_root = "${root_out_dir}/${output_root}"
    elf_file = "${file_root}.elf"
    bin_file = "${file_root}.bin"

    script = "//build/image/convert_to_binary.py"
    deps = [
      ":${target_name}__elf",
    ]
    args = [
      "--tool_prefix",
      tool_prefix,
      "--input",
      rebase_path(elf_file),
      "--output",
      rebase_path(bin_file),
    ]
    outputs = [
      bin_file,
    ]
  }
}

# Helper to build a hypervisor image
template("hypervisor") {
  image_binary(target_name) {
    forward_variables_from(invoker,
                           [
                             "cflags",
                             "cflags_c",
                             "defines",
                             "deps",
                             "public_deps",
                             "sources",
                             "testonly",
                           ])
    image_name = target_name
  }
}

# Helper to build a virtual machine kernel
template("vm_kernel") {
  image_binary(target_name) {
    forward_variables_from(invoker,
                           [
                             "cflags",
                             "cflags_c",
                             "defines",
                             "deps",
                             "include_dirs",
                             "public_configs",
                             "public_deps",
                             "sources",
                             "testonly",
                           ])
    output_path = rebase_path(".", root_out_dir, target_out_dir)
    image_name = target_name
  }
}

# Build the initial RAM disk for the Linux VM.
template("linux_initrd") {
  initrd_base = "${target_out_dir}/${target_name}/initrd"
  initrd_file = "${initrd_base}.img"
  initrd_staging = "${initrd_base}"

  copy("${target_name}__staging") {
    forward_variables_from(invoker,
                           [
                             "testonly",
                             "sources",
                             "deps",
                           ])
    outputs = [
      "${initrd_staging}/{{source_file_part}}",
    ]
  }

  action(target_name) {
    forward_variables_from(invoker, [ "testonly" ])
    script = "//build/image/generate_linux_initrd.py"
    args = [
      "--staging",
      rebase_path(initrd_staging),
      "--output",
      rebase_path(initrd_file),
    ]
    deps = [
      ":${target_name}__staging",
    ]
    outputs = [
      initrd_file,
    ]
  }
}

# Build the initial RAM disk for the hypervisor.
template("initrd") {
  assert(defined(invoker.primary_vm),
         "initrd() must specify a \"primary_vm\" value")

  action(target_name) {
    forward_variables_from(invoker, [ "testonly" ])
    script = "//build/image/generate_initrd.py"

    initrd_base = "${target_out_dir}/${target_name}/initrd"
    initrd_file = "${initrd_base}.img"
    initrd_staging = "${initrd_base}"

    # Cannot get target outputs here as they are defined in a different file.
    primary_vm_image = get_label_info(invoker.primary_vm, "target_out_dir") +
                       "/" + get_label_info(invoker.primary_vm, "name") + ".bin"

    deps = [
      invoker.primary_vm,
    ]
    args = [
      "--primary_vm",
      rebase_path(primary_vm_image),
      "--staging",
      rebase_path(initrd_staging),
      "--output",
      rebase_path(initrd_file),
    ]

    if (defined(invoker.primary_initrd)) {
      deps += [ invoker.primary_initrd ]
      primary_initrd_outputs = get_target_outputs(invoker.primary_initrd)
      args += [
        "--primary_vm_initrd",
        rebase_path(primary_initrd_outputs[0]),
      ]
    }

    # Add the info about the secondary VMs. The information about the VMs is
    # encoded in lists with the following elements:
    #
    #    1. Memory in bytes.
    #    2. Number of cores.
    #    3. File name for the VM image.
    #    4. Build target for the VM.
    if (defined(invoker.secondary_vms)) {
      foreach(vm, invoker.secondary_vms) {
        deps += [ vm[3] ]
        args += [
          "--secondary_vm",
          vm[0],
          vm[1],
          vm[2],
          rebase_path(get_label_info(vm[3], "target_out_dir") + "/" +
                      get_label_info(vm[3], "name") + ".bin"),
        ]
      }
    }

    outputs = [
      initrd_file,
      "${initrd_staging}/vms.txt",
    ]
  }
}
