blob: d4b13475cd67e19faa8811851262d864fdc0e5c9 [file] [log] [blame]
# Copyright 2018 The Fuchsia Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
import("//build/compiled_action.gni")
import("//build/config.gni")
import("//build/config/clang/clang.gni")
import("//build/config/fuchsia/zbi.gni")
import("//build/config/fuchsia/zircon.gni")
import("//build/images/boot.gni")
import("//build/images/collect_blob_manifest.gni")
import("//build/images/custom_signing.gni")
import("//build/images/fvm.gni")
import("//build/images/json.gni")
import("//build/images/manifest.gni")
import("//build/images/max_fvm_size.gni")
import("//build/images/shell_commands.gni")
import("//build/images/zxcrypt.gni")
import("//build/package.gni")
import("//build/sdk/sdk_atom.gni")
import("//build/sdk/sdk_molecule.gni")
import("//garnet/build/pkgfs.gni")
import("//garnet/go/src/pm/pm.gni")
declare_args() {
# Path to manifest file containing data to place into the initial /data
# partition.
data_partition_manifest = ""
# Whether to build the netboot zbi by default.
#
# You can still build //build/images:netboot explicitly even if enable_netboot is false.
enable_netboot = false
# A list of labels for meta packages to be included in the monolith.
meta_package_labels = []
# arguments to fx flash script
zircon_a_partition = ""
zircon_b_partition = ""
zircon_r_partition = ""
vbmeta_a_partition = ""
vbmeta_b_partition = ""
vbmeta_r_partition = ""
active_partition = ""
signed_image = false
fastboot_product = ""
# Whether to include images necessary to run Fuchsia in QEMU in build
# archives.
add_qemu_to_build_archives = false
}
assert(
meta_package_labels != [],
"Missing meta_package_labels. Are you using a supported product configuration? " + "Check your args.gn file for an import of a product configuration, and consider " + "using one of the products in the `//products` or `//vendor/*/products` directories.")
assert(custom_signing_script == "" || !use_vboot,
"custom_signing_script and use_vboot cannot be used together!")
board_name_file = "$root_build_dir/board_name"
write_file(board_name_file, "${board_name}")
# This will collect a list of scopes describing each image exported.
# See json.gni.
images = [
{
sources = [
"$root_build_dir/args.gn",
]
json = {
name = "buildargs"
type = "gn"
archive = true
}
deps = []
},
{
sources = [
"//.jiri_root/update_history/latest",
]
json = {
name = "jiri_snapshot"
type = "xml"
archive = true
}
deps = []
},
{
json = {
name = "bootserver"
type = "exe.$host_platform"
archive = true
}
sources = [
"$zircon_tools_dir/bootserver",
]
deps = []
},
]
group("meta_packages") {
testonly = true
visibility = [ ":*" ]
public_deps = meta_package_labels
}
group("monolith_packages") {
testonly = true
visibility = [ ":*" ]
public_deps = [
"//:additional_base_packages",
]
}
group("preinstall_packages") {
testonly = true
visibility = [ ":*" ]
public_deps = [
"//:additional_cache_packages",
]
}
group("available_packages") {
testonly = true
visibility = [ ":*" ]
public_deps = [
":monolith_packages",
":preinstall_packages",
"//:additional_universe_packages",
]
}
group("packages") {
testonly = true
public_deps = [
":available_packages",
":meta_packages",
]
if (enable_netboot) {
data_deps = [
":netboot",
":netboot-script",
]
}
}
template("package_list") {
generated_file(target_name) {
testonly = true
forward_variables_from(invoker,
[
"deps",
"public_deps",
"visibility",
])
data_keys = [ "package_names" ]
walk_keys = [ "package_barrier" ]
outputs = [
"$root_out_dir/$target_name",
]
}
}
package_list("monolith_packages.list") {
visibility = [ ":*" ]
deps = [
":meta_packages",
":monolith_packages",
]
}
package_list("preinstall_packages.list") {
visibility = [ ":*" ]
deps = [
":preinstall_packages",
]
}
package_list("available_packages.list") {
visibility = [ ":*" ]
deps = [
":available_packages",
]
}
group("package_lists") {
testonly = true
visibility = [ ":*" ]
deps = [
":available_packages.list",
":monolith_packages.list",
":preinstall_packages.list",
":all_package_manifests.list",
]
}
config_package("config-data") {
testonly = true
visibility = [ ":*" ]
deps = [
":available_packages",
]
}
shell_commands("shell-commands") {
testonly = true
visibility = [ ":*" ]
deps = [
":available_packages",
]
}
###
### Fuchsia system image. This aggregates contributions from all the
### package() targets enabled in the build.
###
pm_binary_label = "//garnet/go/src/pm:pm_bin($host_toolchain)"
pm_out_dir = get_label_info(pm_binary_label, "root_out_dir")
pm_binary = "$pm_out_dir/pm"
# This just runs `pm -k $system_package_key genkey` if the file doesn't exist.
# Every package() target depends on this.
action("system_package_key_check") {
visibility = [ "*" ]
deps = [
pm_binary_label,
]
outputs = [
"$target_out_dir/system_package_key_check_ok.stamp",
]
script = "//build/gn_run_binary.sh"
inputs = [
"system_package_key_check.py",
pm_binary,
]
args =
[ clang_prefix ] + rebase_path(inputs + outputs + [ system_package_key ])
}
monolith_meta_far_merkle_index =
"$target_out_dir/monolith_meta_far_merkle_index"
package_metadata_list("monolith_meta_far_merkle_index") {
testonly = true
outputs = [
monolith_meta_far_merkle_index,
]
data_keys = [ "meta_far_merkle_index_entries" ]
deps = [
":meta_packages",
":monolith_packages",
]
}
# The pkgsvr index is a manifest mapping `package_name/package_version` to
# the merkleroot of the package's meta.far file.
pkgsvr_index = "$target_out_dir/pkgsvr_index"
action("pkgsvr_index") {
visibility = [
":system_image.manifest",
":update_packages.manifest",
]
testonly = true
outputs = [
"$target_out_dir/$target_name",
]
deps = [
":monolith_meta_far_merkle_index",
]
inputs = [
monolith_meta_far_merkle_index,
]
script = "//build/images/manifest_content_expand.sh"
args = [
rebase_path(monolith_meta_far_merkle_index, root_build_dir),
rebase_path(outputs[0], root_build_dir),
]
}
preinstall_meta_far_merkle_index =
"$target_out_dir/preinstall_meta_far_merkle_index"
package_metadata_list("preinstall_meta_far_merkle_index") {
testonly = true
outputs = [
preinstall_meta_far_merkle_index,
]
data_keys = [ "meta_far_merkle_index_entries" ]
deps = [
":preinstall_packages",
":update.meta",
]
}
# preinstall.manifest is a manifest of files that are a pkgfs "dynamic index"
# populated inside /pkgfs/packages that are {name}/{version} containing the
# merkleroot of the meta.far of that package.
action("preinstall.manifest") {
visibility = [ ":data.blk" ]
testonly = true
deps = [
":preinstall_meta_far_merkle_index",
]
inputs = [
preinstall_meta_far_merkle_index,
]
script = "manifest_add_dest_prefix.sh"
args = [ "pkgfs_index/packages/" ]
outputs = [
# The output is in the root build dir in order to avoid a complex rewrite
# of the source path. The minfs tool this is passed to interprets source
# locations relative to the manifest.
"$root_build_dir/$target_name",
]
args += [
rebase_path(preinstall_meta_far_merkle_index, root_build_dir),
rebase_path(outputs[0], root_build_dir),
]
}
# The /boot and /system manifests have to be generated in concert. Things
# like drivers going into /system can affect what needs to go into /boot.
boot_manifest = "$target_out_dir/boot.manifest"
system_image_manifest_args = "system_image.manifest_args"
system_image_manifest_args_path = target_gen_dir + "/system_image.manifest_args"
generated_file(system_image_manifest_args) {
testonly = true
outputs = [
system_image_manifest_args_path,
]
data_keys = [ "system_image_rsps" ]
walk_keys = [ "package_barrier" ]
deps = [
":meta_packages",
":monolith_packages",
]
}
# The system_image "package" manifest is everything that appears in /system.
generate_manifest("system_image.manifest") {
visibility = [ ":*" ]
testonly = true
# Create the /boot manifest that gets packed into BOOTFS in the ZBI.
# /system manifest files can assume that the /boot files are visible at
# runtime, so dependencies already in /boot won't be copied into /system.
bootfs_manifest = boot_manifest
bootfs_zircon_groups = "all"
# Collect whatever we want from Zircon that didn't go into /boot.
zircon_groups = ""
# Now each package() target in the build contributes manifest entries.
# For system_image packages, these contain binaries that need their
# references resolved from the auxiliary manifests or /boot (above).
deps = [
":" + system_image_manifest_args,
]
sources = [
system_image_manifest_args_path,
]
args = [ "@" + rebase_path(system_image_manifest_args_path, root_build_dir) ]
args += [ "--entry-manifest=" +
get_label_info(":$target_name", "label_no_toolchain") ]
# Add the meta/package JSON file that makes this the "system_image" package.
json = "system_meta_package.json"
sources += [ json ]
args += [ "--entry=meta/package=" + rebase_path(json, root_build_dir) ]
# Add the static packages (pkgsvr) index.
deps += [ ":pkgsvr_index" ]
sources += [ pkgsvr_index ]
args += [ "--entry=data/static_packages=" +
rebase_path(pkgsvr_index, root_build_dir) ]
}
system_manifest_outputs = get_target_outputs(":system_image.manifest")
assert(boot_manifest == system_manifest_outputs[2])
system_build_id_map = system_manifest_outputs[1]
# Generate, sign, and seal the system_image package file.
pm_build_package("system_image.meta") {
package_name = "system_image"
visibility = [ ":*" ]
testonly = true
manifest = ":system_image.manifest"
}
# Now generate the blob manifest. This lists all the source files
# that need to go into the blobfs image. That is everything from the
# system_image manifest, everything from each package manifest, and
# all the synthesized meta.far files.
blob_manifest = "$root_build_dir/blob.manifest"
collect_blob_manifest("blob.manifest") {
testonly = true
visibility = [ ":*" ]
outputs = [
blob_manifest,
]
deps = [
":meta_packages",
":monolith_packages",
":preinstall_packages",
":system_image.meta",
":update.meta",
pkgfs_package_label,
]
}
# Pack up all the blobs!
zircon_tool_action("blob.blk") {
visibility = [ ":*" ]
testonly = true
deps = [
":blob.manifest",
]
blob_image_path = "$target_out_dir/$target_name"
blob_size_list = "$root_build_dir/blob.sizes"
outputs = [
blob_image_path,
# This should be an output too, but the generate_fvm template assumes that all
# outputs of these actions are inputs to the fvm tool.
# blob_size_list
]
depfile = blob_image_path + ".d"
inputs = [
blob_manifest,
]
tool = "blobfs"
args = [
"--depfile",
"--sizes",
rebase_path(blob_size_list, root_build_dir),
"--compress",
rebase_path(blob_image_path, root_build_dir),
"create",
"--manifest",
rebase_path(blob_manifest, root_build_dir),
]
}
images += [
{
deps = [
":blob.blk",
]
public = [
"IMAGE_BLOB_RAW",
]
json = {
name = "blob"
type = "blk"
}
},
]
###
### Zircon Boot Images
###
declare_args() {
# List of arguments to add to /boot/config/devmgr.
# These come after synthesized arguments to configure blobfs and pkgfs.
devmgr_config = []
# List of kernel command line arguments to bake into the boot image.
# See also //zircon/docs/kernel_cmdline.md and
# [`devmgr_config`](#devmgr_config).
kernel_cmdline_args = []
# Files containing additional kernel command line arguments to bake into
# the boot image. The contents of these files (in order) come after any
# arguments directly in [`kernel_cmdline_args`](#kernel_cmdline_args).
# These can be GN `//` source pathnames or absolute system pathnames.
kernel_cmdline_files = []
# List of extra manifest entries for files to add to the BOOTFS.
# Each entry can be a "TARGET=SOURCE" string, or it can be a scope
# with `sources` and `outputs` in the style of a copy() target:
# `outputs[0]` is used as `TARGET` (see `gn help source_expansion`).
bootfs_extra = []
# (deprecated) List of kernel images to include in the update (OTA) package.
# If no list is provided, all built kernels are included. The names in the
# list are strings that must match the filename to be included in the update
# package.
update_kernels = []
}
images += [
{
# This is the file to give QEMU's `-kernel` switch with a complete
# ZBI (some `IMAGE_*_ZBI` file) for its `-initrd` switch.
public = [
"IMAGE_QEMU_KERNEL_RAW",
]
json = {
name = "qemu-kernel"
type = "kernel"
archive = add_qemu_to_build_archives
}
sdk = "qemu-kernel.bin"
deps = []
foreach(image, zircon_images) {
if (image.name == "qemu-kernel" && image.cpu == target_cpu) {
sources = [
"$zircon_root_build_dir/${image.path}",
]
}
}
},
]
# Generate the /boot/config/devmgr file. This looks like a kernel command
# line file, but is read by devmgr (in addition to kernel command line
# arguments), not by the kernel or boot loader.
action("devmgr_config.txt") {
visibility = [ ":fuchsia" ]
testonly = true
script = "manifest.py"
outputs = [
"$target_out_dir/$target_name",
]
pkgfs = "bin/" + pkgfs_binary_name
pkgfs_label = pkgfs_package_label
pkgfs_pkg_out_dir = get_label_info(pkgfs_label, "target_out_dir") + "/" +
get_label_info(pkgfs_label, "name")
pkgfs_blob_manifest = "$pkgfs_pkg_out_dir/meta/contents"
system_image_merkleroot = "$target_out_dir/system_image.meta/meta.far.merkle"
deps = [
":system_image.meta",
pkgfs_label,
]
sources = [
pkgfs_blob_manifest,
system_image_merkleroot,
]
args = [
"--output=" + rebase_path(outputs[0], root_build_dir),
# Start with the fixed options.
"--entry=devmgr.require-system=true",
]
# Add the pkgfs command line, embedding the merkleroot of the system image.
args += [
"--contents",
"--rewrite=*=zircon.system.pkgfs.cmd={target}+{source}",
"--entry=${pkgfs}=" + rebase_path(system_image_merkleroot, root_build_dir),
"--no-contents",
"--reset-rewrite",
]
# Embed the pkgfs blob manifest with the "zircon.system.pkgfs.file."
# prefix on target file names.
args += [
"--rewrite=*=zircon.system.pkgfs.file.{target}={source}",
"--manifest=" + rebase_path(pkgfs_blob_manifest, root_build_dir),
"--reset-rewrite",
]
foreach(entry, devmgr_config) {
args += [ "--entry=$entry" ]
}
# If there were any ASan drivers in the build, bin/devhost.asan
# should have been brought into the boot manifest. devmgr needs to
# be told to use it in case there are ASan drivers in /system but
# none in /boot. If there were any non-ASan drivers in the build,
# bin/devhost.asan will load them and needs to know to moderate the
# checking for interacting with uninstrumented code.
deps += [ ":system_image.manifest" ]
sources += [ boot_manifest ]
args += [
"--include=bin/devhost.asan",
"--include=bin/devhost",
"--rewrite=bin/devhost.asan=devmgr.devhost.asan=true",
"--rewrite=bin/devhost=devhost.asan.strict=false",
"--manifest=" + rebase_path(boot_manifest, root_build_dir),
]
}
generated_file("zxcrypt_config.txt") {
outputs = [
"$target_out_dir/$target_name",
]
contents = zxcrypt_key_source
}
component_manager_label = "//src/sys/component_manager:component_manager.bootfs"
component_manager_target_dir =
get_label_info(component_manager_label, "target_out_dir")
component_manager_target_name = get_label_info(component_manager_label, "name")
component_manager_manifest =
component_manager_target_dir + "/" + component_manager_target_name
# The main bootable image, which requires `blob.blk` to appear on some
# attached storage device at runtime.
zbi("fuchsia") {
testonly = true
deps = [
":devmgr_config.txt",
":system_image.manifest",
":zxcrypt_config.txt",
component_manager_label,
]
inputs = [
component_manager_manifest,
boot_manifest,
zircon_kernel_zbi,
]
manifest = [
{
outputs = [
"config/devmgr",
]
sources = get_target_outputs(":devmgr_config.txt")
},
"config/zxcrypt=" +
rebase_path("$target_out_dir/zxcrypt_config.txt", root_build_dir),
]
cmdline = kernel_cmdline_args
cmdline_inputs = kernel_cmdline_files
manifest += bootfs_extra
}
images += [
{
deps = [
":fuchsia",
]
sdk = "fuchsia.zbi"
if (!use_vboot && custom_signing_script == "") {
updater = "zbi"
}
if (!use_vboot) {
installer = "fuchsia.zbi"
}
json = {
name = "zircon-a"
type = "zbi"
# TODO(IN-892): Although we wish to minimize the usage of mexec (ZX-2069),
# the infrastructure currently requires it for vim2 lifecycle management.
# (`fastboot continue` does not continue back to fuchsia after paving and
# rebooting in the case we do not mexec a kernel.)
bootserver_pave = [ "--boot" ]
if (custom_signing_script == "" && !use_vboot) {
bootserver_pave += [
"--zircona",
# TODO(ZX-2625): `dm reboot-recovery` boots from zircon-b instead of
# zircon-r, so for now zedboot is being paved to this slot.
# "--zirconb",
]
}
}
public = [
"IMAGE_ZIRCONA_ZBI",
# TODO(mcgrathr): The complete ZBI can be used with a separate
# kernel too, the kernel image in it will just be ignored. So
# just use the primary ZBI for this until all uses are
# converted to using the ZBI alone. Then remove this as
# IMAGE_BOOT_RAM variable should no longer be in use.
"IMAGE_BOOT_RAM",
]
},
]
if (custom_signing_script != "") {
custom_signed_zbi("signed") {
output_name = "fuchsia.zbi"
testonly = true
deps = [
":fuchsia",
]
zbi = get_target_outputs(":fuchsia")
}
images += [
{
deps = [
":signed",
]
sdk = "fuchsia.zbi.signed"
updater = "zbi.signed"
json = {
name = "zircon-a.signed"
type = "zbi.signed"
bootserver_pave = [ "--zircona" ]
}
public = [
"IMAGE_ZIRCONA_SIGNEDZBI",
]
},
]
if (use_vbmeta) {
images += [
{
deps = [
":signed",
]
sources = [
"$root_out_dir/fuchsia.zbi.vbmeta",
]
json = {
name = "zircon-a.vbmeta"
type = "vbmeta"
bootserver_pave = [ "--vbmetaa" ]
}
public = [
"IMAGE_VBMETAA_RAW",
]
},
]
}
} else if (use_vboot) {
# ChromeOS vboot images.
vboot("signed") {
testonly = true
output_name = "fuchsia.zbi"
deps = [
":fuchsia",
]
}
images += [
{
deps = [
":signed",
]
sdk = "zircon-a.signed"
updater = "zbi.signed"
installer = "fuchsia.zbi"
json = {
name = "zircon-a.signed"
type = "zbi.signed"
bootserver_pave = [ "--zircona" ]
}
public = [
"IMAGE_ZIRCONA_SIGNEDZBI",
]
},
]
}
# The updater also wants the zedboot zbi as recovery.
if (custom_signing_script != "") {
images += [
{
deps = [
"zedboot:signed",
]
sources = [
"$root_out_dir/zedboot.zbi.signed",
]
updater = "zedboot.signed"
},
]
} else if (use_vboot) {
images += [
{
deps = [
"zedboot:signed",
]
sources = [
"$root_out_dir/zedboot.vboot",
]
# TODO(ZX-2689): Re-enable after system_updater is fixed.
# updater = "zedboot.signed"
installer = "zedboot.zbi"
},
]
} else {
images += [
{
deps = [
"zedboot:zbi",
]
sources = [
"$root_out_dir/zedboot.zbi",
]
updater = "zedboot"
installer = "zedboot.zbi"
},
]
}
###
### Complete images for booting and installing the whole system.
###
declare_args() {
# Build boot images that prefer Zedboot over local boot (only for EFI).
always_zedboot = false
}
# data.blk creates minfs data partition containing the preinstall package
# index. The partition is included in fvm.blk and fvm.sparse.blk.
# To increase the size of the data partition, increase the total size of the
# fvm images using |fvm_image_size|.
zircon_tool_action("data.blk") {
testonly = true
tool = "minfs"
data_image_path = "$target_out_dir/$target_name"
outputs = [
data_image_path,
]
depfile = data_image_path + ".d"
deps = [
":preinstall.manifest",
]
preinstall_manifest = get_target_outputs(deps[0])
args = [
"--depfile",
rebase_path(data_image_path, root_build_dir),
"create",
"--manifest",
rebase_path(preinstall_manifest[0], root_build_dir),
]
if (data_partition_manifest != "") {
args += [
"--manifest",
rebase_path(data_partition_manifest),
]
}
}
images += [
{
public = [
"IMAGE_DATA_RAW",
]
json = {
name = "data"
type = "blk"
}
deps = [
":data.blk",
]
},
]
# Record the maximum allowable FVM size in the build directory for later steps
# to check against.
max_fvm_size_file = "$root_build_dir/max_fvm_size.txt"
write_file(max_fvm_size_file, max_fvm_size)
# fvm.blk creates an FVM partition image containing the blob partition produced
# by blob.blk and the data partition produced by data.blk. fvm.blk is primarily
# invoked and used by the qemu run, via `fx run`.
generate_fvm("fvm.blk") {
testonly = true
output_name = "$target_out_dir/fvm.blk"
args = fvm_create_args
if (fvm_image_size != "") {
args += [
"--length",
fvm_image_size,
]
}
partitions = [
{
type = "blob"
dep = ":blob.blk"
minimum_inodes = blobfs_minimum_inodes
minimum_data_bytes = blobfs_minimum_data_bytes
maximum_bytes = blobfs_maximum_bytes
},
{
type = "data"
dep = ":data.blk"
minimum_inodes = minfs_minimum_inodes
minimum_data_bytes = minfs_minimum_data_bytes
maximum_bytes = minfs_maximum_bytes
},
]
}
images += [
{
deps = [
":fvm.blk",
]
json = {
name = "storage-full"
type = "blk"
archive = add_qemu_to_build_archives
}
sdk = "fvm.blk"
public = [
"IMAGE_FVM_RAW",
]
},
]
# fvm.sparse.blk creates a sparse FVM partition image containing the blob
# partition produced by blob.blk and the data partition produced by data.blk.
# fvm.sparse.blk is primarily invoked and used by the paver boot, via `fx
# pave`.
generate_fvm("fvm.sparse.blk") {
testonly = true
output_name = "$target_out_dir/fvm.sparse.blk"
deps = [
":blob.blk",
":data.blk",
]
args = fvm_sparse_args
partitions = [
{
type = "blob"
dep = ":blob.blk"
minimum_inodes = blobfs_minimum_inodes
minimum_data_bytes = blobfs_minimum_data_bytes
maximum_bytes = blobfs_maximum_bytes
},
{
type = "data"
dep = ":data.blk"
minimum_inodes = minfs_minimum_inodes
minimum_data_bytes = minfs_minimum_data_bytes
maximum_bytes = minfs_maximum_bytes
},
]
}
images += [
{
deps = [
":fvm.sparse.blk",
]
json = {
name = "storage-sparse"
type = "blk"
bootserver_pave = [ "--fvm" ]
}
installer = "fvm.sparse.blk"
sdk = "fvm.sparse.blk"
public = [
"IMAGE_FVM_SPARSE",
]
},
]
# fvm.blob.sparse.blk creates a sprase FVM partition image containing the blob
# partition produced by blob.blk.
generate_fvm("fvm.blob.sparse.blk") {
testonly = true
output_name = "$target_out_dir/$target_name"
deps = [
":blob.blk",
]
args = fvm_sparse_args
partitions = [
{
type = "blob"
dep = ":blob.blk"
minimum_inodes = blobfs_minimum_inodes
minimum_data_bytes = blobfs_minimum_data_bytes
maximum_bytes = blobfs_maximum_bytes
},
]
}
images += [
{
deps = [
":fvm.blob.sparse.blk",
]
public = [
"IMAGE_FVM_BLOB_SPARSE",
]
},
]
# This rolls the primary ZBI together with a compressed RAMDISK image of
# fvm.blk into a fat ZBI that boots the full system without using any real
# storage. The system decompresses the fvm.blk image into memory and then
# sees that RAM disk just as if it were a real disk on the device.
zbi("netboot") {
testonly = true
deps = [
":fuchsia",
":fvm.blk",
]
inputs = get_target_outputs(":fuchsia")
ramdisk_inputs = get_target_outputs(":fvm.blk")
}
images += [
{
default = false
json = {
bootserver_netboot = [ "--boot" ]
name = "netboot"
type = "zbi"
}
public = [
"IMAGE_NETBOOT_ZBI",
# TODO(mcgrathr): The complete ZBI can be used with a separate kernel
# too, the kernel image in it will just be ignored. So just use the
# primary ZBI for this until all uses are converted to using the ZBI
# alone. Then remove this as IMAGE_BOOT_RAM variable should no
# longer be in use.
"IMAGE_NETBOOT_RAM",
]
deps = [
":netboot",
]
},
]
if (target_cpu != "arm64" && !use_vboot) {
# TODO(surajmalhotra): Remove this target once SDK no longer depends on it.
vboot("vboot") {
testonly = true
output_name = "fuchsia"
deps = [
":fuchsia",
]
}
images += [
{
json = {
name = "zircon-vboot"
type = "vboot"
}
deps = [
":vboot",
]
sdk = "zircon.vboot"
},
]
# EFI ESP images.
esp("esp") {
output_name = "fuchsia"
testonly = true
if (always_zedboot) {
cmdline = "zedboot/efi_cmdline.txt"
} else {
cmdline = "efi_local_cmdline.txt"
}
}
images += [
{
deps = [
":esp",
]
json = {
name = "efi"
type = "blk"
bootserver_pave = [ "--bootloader" ]
}
installer = "fuchsia.esp.blk"
sdk = "local.esp.blk"
if (!use_vboot && custom_signing_script == "") {
updater = "bootloader"
}
public = [
"IMAGE_ESP_RAW",
]
},
{
deps = [
"zedboot:esp",
]
sources = [
"$root_out_dir/zedboot.esp.blk",
]
},
]
}
installer_label = "//garnet/bin/installer:install-fuchsia"
installer_out_dir = get_label_info(installer_label, "root_out_dir")
installer_path = "$installer_out_dir/install-fuchsia"
action("installer.manifest") {
script = "manifest.py"
outputs = [
"$target_out_dir/installer.manifest",
]
args = [
"--output=" + rebase_path(outputs[0], root_build_dir),
"--output-cwd=" + rebase_path(target_out_dir, root_build_dir),
"--entry=install-fuchsia=" + rebase_path(installer_path, root_build_dir),
]
foreach(image, images) {
if (defined(image.installer)) {
image_sources = []
if (defined(image.sources)) {
image_sources += image.sources
} else {
foreach(label, image.deps) {
image_sources += get_target_outputs(label)
}
}
assert(image_sources == [ image_sources[0] ])
args += [ "--entry=${image.installer}=" +
rebase_path(image_sources[0], root_build_dir) ]
}
}
}
# installer.blk is a minfs partition image that includes all of the
# images required to install a Fuchsia build.
zircon_tool_action("installer") {
testonly = true
tool = "minfs"
deps = [
":installer.manifest",
installer_label,
]
outputs = [
"$target_out_dir/installer.blk",
]
sources = []
foreach(image, images) {
if (defined(image.installer)) {
deps += image.deps
if (defined(image.sources)) {
sources += image.sources
} else {
foreach(label, image.deps) {
sources += get_target_outputs(label)
}
}
}
}
depfile = "$target_out_dir/installer.blk.d"
args = [
"--depfile",
rebase_path(outputs[0], root_build_dir),
"create",
"--manifest",
]
args += rebase_path(get_target_outputs(deps[0]), root_build_dir)
}
images += [
{
default = false
public = [
"IMAGE_INSTALLER_RAW",
]
deps = [
":installer",
]
},
]
group("images") {
testonly = true
deps = [
":ids.txt",
":package_lists",
":paver-script",
"zedboot",
]
}
group("default-images") {
testonly = true
deps = []
foreach(image, images) {
if (!defined(image.default) || image.default) {
deps += image.deps
}
}
}
###
### Paver and flash scripts, and archives using those images and zedboot's images.
###
action("flash_script") {
script = "//build/images/generate_flash_script.sh"
outputs = [
"$root_out_dir/flash.sh",
]
image = "$root_out_dir/zedboot.zbi"
args = [
"--image=" + rebase_path(image, root_build_dir),
"--output=" + rebase_path(outputs[0], root_build_dir),
"--zircon-a=${zircon_a_partition}",
"--zircon-b=${zircon_b_partition}",
"--zircon-r=${zircon_r_partition}",
"--vbmeta-a=${vbmeta_a_partition}",
"--vbmeta-b=${vbmeta_b_partition}",
"--vbmeta-r=${vbmeta_r_partition}",
"--active=${active_partition}",
"--signed=${signed_image}",
"--product=${fastboot_product}",
]
}
paver_targets = [
{
name = "paver-script"
outputs = [
"$root_build_dir/pave.sh",
]
switch = "--pave="
json = {
name = "pave"
type = "sh"
}
},
{
name = "netboot-script"
outputs = [
"$root_build_dir/netboot.sh",
]
switch = "--netboot="
json = {
name = "netboot"
type = "sh"
}
},
]
foreach(format,
[
"tgz",
"zip",
]) {
paver_targets += [
{
name = "archive-$format"
outputs = [
"$root_build_dir/build-archive.$format",
]
switch = "--archive="
json = {
name = "archive"
type = "$format"
}
},
{
name = "symbol-archive-$format"
outputs = [
"$root_build_dir/symbol-archive.$format",
]
switch = "--symbol-archive="
json = {
name = "symbol-archive"
type = "$format"
}
},
]
}
foreach(target, paver_targets) {
images += [
{
path = rebase_path(target.outputs, root_build_dir)
path = path[0]
json = target.json
deps = [
":${target.name}",
]
},
]
action(target.name) {
deps = [
":default-images",
":flash_script",
":ids.txt",
":netboot",
"zedboot",
]
testonly = true
sources = [
"$root_build_dir/images.json",
"$root_build_dir/zedboot_images.json",
]
outputs = target.outputs
depfile = "${outputs[0]}.d"
script = "pack-images.py"
args = [
"--depfile=" + rebase_path(depfile, root_build_dir),
target.switch + rebase_path(outputs[0], root_build_dir),
"--board_name=${board_name}",
]
args += rebase_path(sources, root_build_dir)
}
}
###
### Amber updates.
###
# update_packages.manifest contains the same entries as the pkgsvr_index but
# additionally includes the system_image package.
update_meta_far_merkle_index = "$target_out_dir/update_meta_far_merkle_index"
package_metadata_list("update_meta_far_merkle_index") {
testonly = true
outputs = [
update_meta_far_merkle_index,
]
data_keys = [ "meta_far_merkle_index_entries" ]
deps = [
":meta_packages",
":monolith_packages",
":system_image.meta",
]
}
action("update_packages.manifest") {
visibility = [ ":update.manifest" ]
testonly = true
outputs = [
"$target_out_dir/$target_name",
]
deps = [
":update_meta_far_merkle_index",
]
inputs = [
update_meta_far_merkle_index,
]
script = "manifest_content_expand.sh"
args = [
rebase_path(update_meta_far_merkle_index, root_build_dir),
rebase_path(outputs[0], root_build_dir),
]
}
# The update package manifest contains the pkgsvr_index and the target
# system kernel images.
action("update.manifest") {
visibility = [ ":*" ]
testonly = true
update_manifest = [
{
target = "packages"
deps = [
":update_packages.manifest",
]
},
# Add the meta/package JSON file that makes this the "update" package.
{
target = "meta/package"
sources = [
"update_package.json",
]
},
]
foreach(image, images) {
if (defined(image.updater)) {
update_manifest += [
{
target = image.updater
forward_variables_from(image,
[
"deps",
"sources",
])
},
]
}
}
update_manifest += [
{
target = "board"
sources = [
board_name_file,
]
},
]
script = "manifest.py"
outputs = [
"$target_out_dir/$target_name",
]
args = [ "--output=" + rebase_path(outputs[0], root_build_dir) ]
sources = []
deps = []
foreach(entry, update_manifest) {
entry_source = ""
if (defined(entry.deps)) {
deps += entry.deps
}
if (defined(entry.sources)) {
# TODO(BLD-354): We should only have single source
sources = []
sources += entry.sources
entry_source = sources[0]
} else if (defined(entry.deps)) {
foreach(label, entry.deps) {
# TODO(BLD-354): We should only have single output
dep_outputs = []
dep_outputs += get_target_outputs(label)
entry_source = dep_outputs[0]
}
}
entry_source = rebase_path(entry_source, root_build_dir)
args += [ "--entry=${entry.target}=${entry_source}" ]
}
}
pm_build_package("update.meta") {
visibility = [ ":*" ]
testonly = true
manifest = ":update.manifest"
package_name = "update"
}
# XXX(raggi): The following manifests retain the "meta/" files, resulting in
# them being added as blobs, which they should not be. A likely better solution
# here is to teach pm_build_package to produce either a blob manifest or a
# manifest.py --contents compatible response file that excludes these files.
action("update.sources.manifest") {
visibility = [ ":*" ]
testonly = true
script = "manifest.py"
deps = [
":update.manifest",
]
outputs = [
"$target_out_dir/update.sources.manifest",
]
update_manifests = get_target_outputs(deps[0])
args = [
"--sources",
"--output=" + rebase_path(outputs[0], root_build_dir),
"--manifest=" + rebase_path(update_manifests[0]),
]
}
# This output is a manifest of manifests that is usable as an input to `pm
# publish -lp`, a tool for publishing a set of packages from a build produced
# list of package manifests.
all_package_manifests_list = root_build_dir + "/all_package_manifests.list"
package_metadata_list("all_package_manifests.list") {
testonly = true
outputs = [
all_package_manifests_list,
]
data_keys = [ "package_output_manifests" ]
rebase = root_build_dir
deps = [
":packages",
":system_image.meta",
":update.meta",
]
}
# The component index is the index of components in all available packages.
component_index_metadata = "$target_out_dir/component_index_metadata"
component_index_metadata_list("component_index_metadata") {
visibility = [ "//src/sys/component_index:*" ]
testonly = true
outputs = [
component_index_metadata,
]
deps = [
":available_packages",
]
}
# The system index is the index of all available packages, naming each blobs.json
# file instead of its merkleroot, and including a tag of the package set the
# package is a part of (monolith/preinstall/available). Additionally the
# system_index has the system package itself, and the system update package.
system_index = "$target_out_dir/system_index"
tagged_snapshot_manifests = [
{
tag = "monolith"
deps = [
":meta_packages",
":monolith_packages",
":system_image.meta",
":update.meta",
]
},
{
tag = "preinstall"
deps = [
":preinstall_packages",
]
},
{
tag = "available"
deps = [
":available_packages",
]
},
]
all_snapshot_entries = []
foreach(manifest, tagged_snapshot_manifests) {
untagged_entries = "${manifest.tag}.snapshot_entries.untagged"
package_metadata_list(untagged_entries) {
testonly = true
outputs = [
target_gen_dir + "/" + target_name,
]
deps = manifest.deps
data_keys = [ "snapshot_entries" ]
}
tagged_entries = "${manifest.tag}.snapshot_entries"
action(tagged_entries) {
testonly = true
deps = [
":" + untagged_entries,
]
script = "add_tag_to_manifest.sh"
inputs = [
target_gen_dir + "/" + untagged_entries,
]
outputs = [
root_build_dir + "/" + target_name,
]
args = [
manifest.tag,
rebase_path(inputs[0], root_build_dir),
rebase_path(outputs[0], root_build_dir),
]
}
all_snapshot_entries += [ tagged_entries ]
}
action("system_index") {
visibility = [ ":system_snapshot" ]
testonly = true
script = "//build/cat.sh"
outputs = [
"$target_out_dir/$target_name",
]
args = [ rebase_path(outputs[0], root_build_dir) ]
deps = []
foreach(entry, all_snapshot_entries) {
args += [ entry ]
deps += [ ":" + entry ]
}
}
compiled_action("system_snapshot") {
tool = "//garnet/go/src/pm:pm_bin"
tool_output_name = "pm"
visibility = [ ":updates" ]
testonly = true
deps = [
":system_index",
]
inputs = [
system_index,
]
outputs = [
"$target_out_dir/system.snapshot",
]
args = [
"snapshot",
"--manifest",
rebase_path(inputs[0], root_build_dir),
"--output",
rebase_path(outputs[0], root_build_dir),
]
}
# publish all packages to the package repository.
pm_publish("publish") {
testonly = true
deps = [
":all_package_manifests.list",
]
inputs = [
all_package_manifests_list,
]
}
group("updates") {
testonly = true
deps = [
":publish",
":ids.txt",
":package_lists",
":system_snapshot",
]
}
###
### Build ID maps.
###
### TODO(TC-303): ids.txt is deprecated and will be removed.
### The toolchain rules already populate $root_build_dir/.build-id/.
###
generated_file("package-build-id-files.list") {
testonly = true
visibility = [ ":package-ids.txt" ]
data_keys = [ "build_ids" ]
walk_keys = [ "build_ids_barrier" ]
outputs = [
"$target_gen_dir/package-build-id-files.list",
]
deps = [
":available_packages",
]
}
compiled_action("package-ids.txt") {
testonly = true
visibility = [ ":ids.txt" ]
deps = [
":package-build-id-files.list",
]
inputs = [
"$target_gen_dir/package-build-id-files.list",
]
outputs = [
"$target_gen_dir/package-ids.txt",
]
depfile = "$target_gen_dir/package-ids.txt.d"
tool = "//build/tools/merge_and_sort"
args = rebase_path(inputs + outputs + [ depfile ], root_build_dir)
}
# Combine the /boot, /system, and package build ID maps into one.
# Nothing in the build uses this, but top-level targets always update
# it so that debugging tools can rely on it.
action("ids.txt") {
testonly = true
deps = [
":kernel-ids.txt",
":package-ids.txt",
":system_image.manifest",
]
sources = [
"$target_gen_dir/package-ids.txt",
"$target_out_dir/kernel-ids.txt",
system_build_id_map,
]
script = "/usr/bin/sort"
outputs = [
"$root_out_dir/ids.txt",
]
args = [
"-u",
"-o",
] + rebase_path(outputs + sources, root_build_dir)
}
# The vDSO doesn't appear in any package and so doesn't get into any
# ids.txt file produced by generate_manifest(). But it appears in memory
# at runtime and in backtraces, so it should be in the aggregated ids.txt
# for symbolization. The vDSO doesn't appear in zircon_boot_manifests, so
# fetching it out of Zircon's own ids.txt by name is the only thing to do.
# Likewise for the kernel itself, whose build ID is useful to have in the map.
action("kernel-ids.txt") {
script = "manifest.py"
sources = [
"$zircon_root_build_dir/ids-$current_cpu.txt",
]
outputs = [
"$target_out_dir/kernel-ids.txt",
]
args = [
"--separator= ",
"--absolute",
"--output=" + rebase_path(outputs[0], root_build_dir),
"--include-source=*/libzircon.so.debug",
"--include-source=*/zircon.elf",
"--cwd=" + rebase_path(zircon_root_build_dir, root_build_dir),
"--manifest=" + rebase_path(sources[0], root_build_dir),
]
}
images += [
{
deps = [
":ids.txt",
]
json = {
name = "build-id"
type = "txt"
}
},
]
write_images_manifest("images-manifest") {
public = [
"FUCHSIA_BOARD_NAME=${board_name}",
]
outputs = [
"$root_build_dir/images.json",
"$root_build_dir/image_paths.sh",
]
}
###
### SDK
###
sdk_images = []
foreach(image, images) {
if (defined(image.sdk)) {
image_target_name = "${image.sdk}_sdk"
sdk_images += [ ":$image_target_name" ]
sdk_atom(image_target_name) {
id = "sdk://images/${image.sdk}"
category = "partner"
testonly = true
file_content = "target/$target_cpu/${image.sdk}"
meta = {
dest = "images/${image.sdk}-meta.json"
schema = "image"
value = {
type = "image"
name = "${image.sdk}"
file = {
if (target_cpu == "x64") {
x64 = file_content
} else if (target_cpu == "arm64") {
arm64 = file_content
} else {
assert(false, "Unsupported target architecture: $target_cpu")
}
}
}
}
image_sources = []
if (defined(image.sources)) {
image_sources += image.sources
} else {
foreach(label, image.deps) {
image_sources += get_target_outputs(label)
}
}
files = [
{
source = image_sources[0]
dest = "target/$target_cpu/${image.sdk}"
},
]
non_sdk_deps = image.deps
}
}
}
sdk_molecule("images_sdk") {
testonly = true
deps = sdk_images
}