| # Copyright 2018 Google LLC |
| # |
| # 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 = "vm" |
| image_name = target_name |
| } |
| } |
| |
| # 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 = "${root_out_dir}/initrd/${target_name}" |
| initrd_file = "${initrd_base}.img" |
| initrd_staging = "${initrd_base}" |
| vm_dir = rebase_path("${root_out_dir}/vm/") |
| |
| deps = [ |
| invoker.primary_vm, |
| ] |
| |
| args = [ |
| "--primary_vm", |
| vm_dir + get_label_info(invoker.primary_vm, "name") + ".bin", |
| "--staging", |
| rebase_path(initrd_staging), |
| "--output", |
| rebase_path(initrd_file), |
| ] |
| |
| # 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. |
| # |
| # TODO: is there a less hacky way to do this? |
| if (defined(invoker.secondary_vms)) { |
| foreach(vm, invoker.secondary_vms) { |
| args += [ "--secondary_vm" ] |
| |
| # This is a hack to find the field which names the build target for the |
| # VM so it can be added to the dependencies and the image path be |
| # passed to the script. The target will be a path or have a semicolon |
| # so getting the label name will yield a diferent value. The other |
| # fields are simple text so won't change. |
| foreach(field, vm) { |
| if (get_label_info(field, "name") != field) { |
| deps += [ field ] |
| args += [ vm_dir + get_label_info(field, "name") + ".bin" ] |
| } else { |
| args += [ field ] |
| } |
| } |
| } |
| } |
| |
| outputs = [ |
| initrd_file, |
| "${initrd_staging}/vms.txt", |
| ] |
| } |
| } |