Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1b61e038 authored by David Zeuthen's avatar David Zeuthen Committed by android-build-merger
Browse files

Merge "Add support for Brillo Verified Boot."

am: 003bec43

* commit '003bec43':
  Add support for Brillo Verified Boot.
parents 9d005005 003bec43
Loading
Loading
Loading
Loading
+53 −0
Original line number Diff line number Diff line
@@ -507,8 +507,28 @@ INTERNAL_BOOTIMAGE_ARGS := \
	$(addprefix --second ,$(INSTALLED_2NDBOOTLOADER_TARGET)) \
	--kernel $(INSTALLED_KERNEL_TARGET)

INTERNAL_BVBTOOL_MAKE_BOOT_IMAGE_ARGS := \
	--kernel $(INSTALLED_KERNEL_TARGET) \
	--rootfs_with_hashes $(PRODUCT_OUT)/system.img

ifdef BOARD_BVB_ROLLBACK_INDEX
INTERNAL_BVBTOOL_MAKE_BOOT_IMAGE_ARGS += \
	--rollback_index $(BOARD_BVB_ROLLBACK_INDEX)
endif

ifndef BOARD_BVB_KEY_PATH
# If key path isn't specified, use the 4096-bit test key.
INTERNAL_BVBTOOL_SIGN_BOOT_IMAGE_ARGS := --algorithm SHA256_RSA4096 \
	--key system/bvb/test/testkey_rsa4096.pem
else
INTERNAL_BVBTOOL_SIGN_BOOT_IMAGE_ARGS := \
	--algorithm $(BOARD_BVB_ALGORITHM) --key $(BOARD_BVB_KEY_PATH)
endif


ifneq ($(BOARD_BUILD_SYSTEM_ROOT_IMAGE),true)
INTERNAL_BOOTIMAGE_ARGS += --ramdisk $(INSTALLED_RAMDISK_TARGET)
INTERNAL_BVBTOOL_MAKE_BOOT_IMAGE_ARGS += --initrd $(INSTALLED_RAMDISK_TARGET)
endif

INTERNAL_BOOTIMAGE_FILES := $(filter-out --%,$(INTERNAL_BOOTIMAGE_ARGS))
@@ -516,6 +536,7 @@ INTERNAL_BOOTIMAGE_FILES := $(filter-out --%,$(INTERNAL_BOOTIMAGE_ARGS))
BOARD_KERNEL_CMDLINE := $(strip $(BOARD_KERNEL_CMDLINE))
ifdef BOARD_KERNEL_CMDLINE
  INTERNAL_BOOTIMAGE_ARGS += --cmdline "$(BOARD_KERNEL_CMDLINE)"
  INTERNAL_BVBTOOL_MAKE_BOOT_IMAGE_ARGS += --kernel_cmdline "$(BOARD_KERNEL_CMDLINE)"
endif

BOARD_KERNEL_BASE := $(strip $(BOARD_KERNEL_BASE))
@@ -541,6 +562,23 @@ ifneq ($(BOARD_BUILD_SYSTEM_ROOT_IMAGE),true)
endif
endif

ifeq ($(BOARD_BVB_ENABLE),true)

$(INSTALLED_BOOTIMAGE_TARGET): $(BVBTOOL) $(INTERNAL_BOOTIMAGE_FILES) $(PRODUCT_OUT)/system.img
	$(call pretty,"Target boot image: $@")
	$(hide) $(BVBTOOL) make_boot_image $(INTERNAL_BVBTOOL_MAKE_BOOT_IMAGE_ARGS) $(BOARD_BVB_MAKE_BOOT_IMAGE_ARGS) --output $@
	$(hide) $(BVBTOOL) sign_boot_image $(INTERNAL_BVBTOOL_SIGN_BOOT_IMAGE_ARGS) $(BOARD_BVB_SIGN_BOOT_IMAGE_ARGS) --image $@
	$(hide) $(call assert-max-image-size,$@,$(BOARD_BOOTIMAGE_PARTITION_SIZE))

.PHONY: bootimage-nodeps
bootimage-nodeps: $(BVBTOOL)
	@echo "make $@: ignoring dependencies"
	$(hide) $(BVBTOOL) make_boot_image $(INTERNAL_BVBTOOL_MAKE_BOOT_IMAGE_ARGS) $(BOARD_BVB_MAKE_BOOT_IMAGE_ARGS) --output $(INSTALLED_BOOTIMAGE_TARGET)
	$(hide) $(BVBTOOL) sign_boot_image $(INTERNAL_BVBTOOL_SIGN_BOOT_IMAGE_ARGS) $(BOARD_BVB_SIGN_BOOT_IMAGE_ARGS) --image $(INSTALLED_BOOTIMAGE_TARGET)
	$(hide) $(call assert-max-image-size,$(INSTALLED_BOOTIMAGE_TARGET),$(BOARD_BOOTIMAGE_PARTITION_SIZE))

else # BOARD_BVB_ENABLE

# We build recovery as boot image if BOARD_USES_RECOVERY_AS_BOOT is true.
ifneq ($(BOARD_USES_RECOVERY_AS_BOOT),true)
ifeq ($(TARGET_BOOTIMAGE_USE_EXT2),true)
@@ -590,6 +628,7 @@ bootimage-nodeps: $(MKBOOTIMG)

endif # TARGET_BOOTIMAGE_USE_EXT2
endif # BOARD_USES_RECOVERY_AS_BOOT
endif # BOARD_BVB_ENABLE

else	# TARGET_NO_KERNEL
# HACK: The top-level targets depend on the bootimage.  Not all targets
@@ -1128,8 +1167,13 @@ define build-systemimage-target
           fi; \
           mkdir -p $(DIST_DIR); cp $(INSTALLED_FILES_FILE) $(DIST_DIR)/installed-files-rescued.txt; \
           exit 1 )
  $(if $(BOARD_BVB_ENABLE), $(hide) $(BVBTOOL) add_image_hashes $(BOARD_BVB_ADD_IMAGE_HASHES_ARGS) --image $(1))
endef

ifeq ($(BOARD_BVB_ENABLE),true)
FULL_SYSTEMIMAGE_DEPS += $(BVBTOOL)
endif

$(BUILT_SYSTEMIMAGE): $(FULL_SYSTEMIMAGE_DEPS) $(INSTALLED_FILES_FILE)
	$(call build-systemimage-target,$@)

@@ -1772,6 +1816,15 @@ ifneq ($(strip $(SANITIZE_TARGET)),)
endif
ifeq ($(BOARD_USES_FULL_RECOVERY_IMAGE),true)
	$(hide) echo "full_recovery_image=true" >> $(zip_root)/META/misc_info.txt
endif
ifeq ($(BOARD_BVB_ENABLE),true)
	$(hide) echo "board_bvb_enable=true" >> $(zip_root)/META/misc_info.txt
	$(hide) echo "board_bvb_make_boot_image_args=$(BOARD_BVB_MAKE_BOOT_IMAGE_ARGS)" >> $(zip_root)/META/misc_info.txt
	$(hide) echo "board_bvb_sign_boot_image_args=$(BOARD_BVB_SIGN_BOOT_IMAGE_ARGS)" >> $(zip_root)/META/misc_info.txt
	$(hide) echo "board_bvb_algorithm=$(BOARD_BVB_ALGORITHM)" >> $(zip_root)/META/misc_info.txt
	$(hide) echo "board_bvb_key_path=$(BOARD_BVB_KEY_PATH)" >> $(zip_root)/META/misc_info.txt
	$(hide) echo "board_bvb_rollback_index=$(BOARD_BVB_ROLLBACK_INDEX)" >> $(zip_root)/META/misc_info.txt
	$(hide) echo "board_bvb_add_image_hashes_args=$(BOARD_BVB_ADD_IMAGE_HASHES_ARGS)" >> $(zip_root)/META/misc_info.txt
endif
	$(call generate-userimage-prop-dictionary, $(zip_root)/META/misc_info.txt)
ifneq ($(INSTALLED_RECOVERYIMAGE_TARGET),)
+5 −0
Original line number Diff line number Diff line
@@ -528,6 +528,11 @@ MKBOOTIMG := $(HOST_OUT_EXECUTABLES)/mkbootimg$(HOST_EXECUTABLE_SUFFIX)
else
MKBOOTIMG := $(BOARD_CUSTOM_MKBOOTIMG)
endif
ifeq (,$(strip $(BOARD_CUSTOM_BVBTOOL)))
BVBTOOL := $(HOST_OUT_EXECUTABLES)/bvbtool$(HOST_EXECUTABLE_SUFFIX)
else
BVBTOOL := $(BOARD_CUSTOM_BVBTOOL)
endif
APICHECK := $(HOST_OUT_EXECUTABLES)/apicheck$(HOST_EXECUTABLE_SUFFIX)
FS_GET_STATS := $(HOST_OUT_EXECUTABLES)/fs_get_stats$(HOST_EXECUTABLE_SUFFIX)
MAKE_EXT4FS := $(HOST_OUT_EXECUTABLES)/make_ext4fs$(HOST_EXECUTABLE_SUFFIX)
+51 −7
Original line number Diff line number Diff line
@@ -31,7 +31,9 @@ if sys.hexversion < 0x02070000:
import datetime
import errno
import os
import shlex
import shutil
import subprocess
import tempfile
import zipfile

@@ -48,12 +50,12 @@ OPTIONS.verity_signer_path = None

def AddSystem(output_zip, prefix="IMAGES/", recovery_img=None, boot_img=None):
  """Turn the contents of SYSTEM into a system image and store it in
  output_zip."""
  output_zip. Returns the name of the system image file."""

  prebuilt_path = os.path.join(OPTIONS.input_tmp, prefix, "system.img")
  if os.path.exists(prebuilt_path):
    print "system.img already exists in %s, no need to rebuild..." % (prefix,)
    return
    return prebuilt_path

  def output_sink(fn, data):
    ofile = open(os.path.join(OPTIONS.input_tmp, "SYSTEM", fn), "w")
@@ -68,8 +70,23 @@ def AddSystem(output_zip, prefix="IMAGES/", recovery_img=None, boot_img=None):
  block_list = common.MakeTempFile(prefix="system-blocklist-", suffix=".map")
  imgname = BuildSystem(OPTIONS.input_tmp, OPTIONS.info_dict,
                        block_list=block_list)

  # If requested, calculate and add dm-verity integrity hashes and
  # metadata to system.img.
  if OPTIONS.info_dict.get("board_bvb_enable", None) == "true":
    bvbtool = os.getenv('BVBTOOL') or "bvbtool"
    cmd = [bvbtool, "add_image_hashes", "--image", imgname]
    args = OPTIONS.info_dict.get("board_bvb_add_image_hashes_args", None)
    if args and args.strip():
      cmd.extend(shlex.split(args))
    p = common.Run(cmd, stdout=subprocess.PIPE)
    p.communicate()
    assert p.returncode == 0, "bvbtool add_image_hashes of %s image failed" % (
      os.path.basename(OPTIONS.input_tmp),)

  common.ZipWrite(output_zip, imgname, prefix + "system.img")
  common.ZipWrite(output_zip, block_list, prefix + "system.map")
  return imgname


def BuildSystem(input_dir, info_dict, block_list=None):
@@ -275,19 +292,36 @@ def AddImagesToTargetFiles(filename):
                               compression=zipfile.ZIP_DEFLATED)

  has_recovery = (OPTIONS.info_dict.get("no_recovery") != "true")
  system_root_image = (OPTIONS.info_dict.get("system_root_image", None) == "true")
  board_bvb_enable = (OPTIONS.info_dict.get("board_bvb_enable", None) == "true")

  # Brillo Verified Boot is incompatible with certain
  # configurations. Explicitly check for these.
  if board_bvb_enable:
    assert not has_recovery, "has_recovery incompatible with bvb"
    assert not system_root_image, "system_root_image incompatible with bvb"
    assert not OPTIONS.rebuild_recovery, "rebuild_recovery incompatible with bvb"
    assert not has_vendor, "VENDOR images currently incompatible with bvb"

  def banner(s):
    print "\n\n++++ " + s + " ++++\n\n"

  banner("boot")
  prebuilt_path = os.path.join(OPTIONS.input_tmp, "IMAGES", "boot.img")
  boot_image = None
  if os.path.exists(prebuilt_path):
    banner("boot")
    print "boot.img already exists in IMAGES/, no need to rebuild..."
    if OPTIONS.rebuild_recovery:
      boot_image = common.GetBootableImage(
          "IMAGES/boot.img", "boot.img", OPTIONS.input_tmp, "BOOT")
  else:
    if board_bvb_enable:
      # With Brillo Verified Boot, we need to build system.img before
      # boot.img since the latter includes the dm-verity root hash and
      # salt for the former.
      pass
    else:
      banner("boot")
      boot_image = common.GetBootableImage(
        "IMAGES/boot.img", "boot.img", OPTIONS.input_tmp, "BOOT")
      if boot_image:
@@ -310,7 +344,17 @@ def AddImagesToTargetFiles(filename):
        recovery_image.AddToZip(output_zip)

  banner("system")
  AddSystem(output_zip, recovery_img=recovery_image, boot_img=boot_image)
  system_img_path = AddSystem(
    output_zip, recovery_img=recovery_image, boot_img=boot_image)
  if OPTIONS.info_dict.get("board_bvb_enable", None) == "true":
    # If we're using Brillo Verified Boot, we can now build boot.img
    # given that we have system.img.
    banner("boot")
    boot_image = common.GetBootableImage(
      "IMAGES/boot.img", "boot.img", OPTIONS.input_tmp, "BOOT",
      system_img_path=system_img_path)
    if boot_image:
      boot_image.AddToZip(output_zip)
  if has_vendor:
    banner("vendor")
    AddVendor(output_zip)
+115 −4
Original line number Diff line number Diff line
@@ -473,8 +473,114 @@ def _BuildBootableImage(sourcedir, fs_config_file, info_dict=None,
  return data


def _BuildBvbBootableImage(sourcedir, fs_config_file, system_img_path,
                           info_dict=None, has_ramdisk=False):
  """Build a bootable image compatible with Brillo Verified Boot from the
  specified sourcedir.

  Take a kernel, cmdline, system image path, and optionally a ramdisk
  directory from the input (in 'sourcedir'), and turn them into a boot
  image.  Return the image data, or None if sourcedir does not appear
  to contains files for building the requested image.
  """

  def make_ramdisk():
    ramdisk_img = tempfile.NamedTemporaryFile()

    if os.access(fs_config_file, os.F_OK):
      cmd = ["mkbootfs", "-f", fs_config_file,
             os.path.join(sourcedir, "RAMDISK")]
    else:
      cmd = ["mkbootfs", os.path.join(sourcedir, "RAMDISK")]
    p1 = Run(cmd, stdout=subprocess.PIPE)
    p2 = Run(["minigzip"], stdin=p1.stdout, stdout=ramdisk_img.file.fileno())

    p2.wait()
    p1.wait()
    assert p1.returncode == 0, "mkbootfs of %s ramdisk failed" % (sourcedir,)
    assert p2.returncode == 0, "minigzip of %s ramdisk failed" % (sourcedir,)

    return ramdisk_img

  if not os.access(os.path.join(sourcedir, "kernel"), os.F_OK):
    return None

  if has_ramdisk and not os.access(os.path.join(sourcedir, "RAMDISK"), os.F_OK):
    return None

  if info_dict is None:
    info_dict = OPTIONS.info_dict

  img = tempfile.NamedTemporaryFile()

  if has_ramdisk:
    ramdisk_img = make_ramdisk()

  # use BVBTOOL from environ, or "bvbtool" if empty or not set
  bvbtool = os.getenv('BVBTOOL') or "bvbtool"

  # First, create boot.img.
  cmd = [bvbtool, "make_boot_image"]

  fn = os.path.join(sourcedir, "cmdline")
  if os.access(fn, os.F_OK):
    cmd.append("--kernel_cmdline")
    cmd.append(open(fn).read().rstrip("\n"))

  cmd.extend(["--kernel", os.path.join(sourcedir, "kernel")])

  if has_ramdisk:
    cmd.extend(["--initrd", ramdisk_img.name])

  cmd.extend(["--rootfs_with_hashes", system_img_path])

  args = info_dict.get("board_bvb_make_boot_image_args", None)
  if args and args.strip():
    cmd.extend(shlex.split(args))

  rollback_index = info_dict.get("board_bvb_rollback_index", None)
  if rollback_index and rollback_index.strip():
    cmd.extend(["--rollback_index", rollback_index.strip()])

  cmd.extend(["--output", img.name])

  p = Run(cmd, stdout=subprocess.PIPE)
  p.communicate()
  assert p.returncode == 0, "bvbtool make_boot_image of %s image failed" % (
      os.path.basename(sourcedir),)

  # Then, sign boot.img.
  cmd = [bvbtool, "sign_boot_image", "--image", img.name]

  algorithm = info_dict.get("board_bvb_algorithm", None)
  key_path = info_dict.get("board_bvb_key_path", None)
  if algorithm and algorithm.strip() and key_path and key_path.strip():
    cmd.extend(["--algorithm", algorithm, "--key", key_path])
  else:
    cmd.extend(["--algorithm", "SHA256_RSA4096"])
    cmd.extend(["--key", "system/bvb/test/testkey_rsa4096.pem"])

  args = info_dict.get("board_bvb_sign_boot_image_args", None)
  if args and args.strip():
    cmd.extend(shlex.split(args))

  p = Run(cmd, stdout=subprocess.PIPE)
  p.communicate()
  assert p.returncode == 0, "bvbtool sign_boot_image of %s image failed" % (
      os.path.basename(sourcedir),)

  img.seek(os.SEEK_SET, 0)
  data = img.read()

  if has_ramdisk:
    ramdisk_img.close()
  img.close()

  return data


def GetBootableImage(name, prebuilt_name, unpack_dir, tree_subdir,
                     info_dict=None):
                     info_dict=None, system_img_path=None):
  """Return a File object with the desired bootable image.

  Look for it in 'unpack_dir'/BOOTABLE_IMAGES under the name 'prebuilt_name',
@@ -504,6 +610,11 @@ def GetBootableImage(name, prebuilt_name, unpack_dir, tree_subdir,
                 info_dict.get("recovery_as_boot") == "true")

  fs_config = "META/" + tree_subdir.lower() + "_filesystem_config.txt"
  if info_dict.get("board_bvb_enable", None) == "true":
    data = _BuildBvbBootableImage(os.path.join(unpack_dir, tree_subdir),
                                  os.path.join(unpack_dir, fs_config),
                                  system_img_path, info_dict, has_ramdisk)
  else:
    data = _BuildBootableImage(os.path.join(unpack_dir, tree_subdir),
                               os.path.join(unpack_dir, fs_config),
                               info_dict, has_ramdisk)