Exemple #1
0
    def create_image(
        self,
        location: Location,
        system_context: SystemContext,
        export_volume: str,
        *,
        efi_partition: str,
        root_partition: str,
        verity_partition: str,
        root_hash: str,
    ):
        image_name = system_context.substitution_expanded(
            "CLRM_IMAGE_FILENAME", "")
        assert image_name

        image_filename = os.path.join(
            export_volume,
            image_name,
        )

        assert efi_partition
        assert root_partition
        assert verity_partition

        total_size = ((2 * 1024 * 1024) + file_size(None, efi_partition) +
                      file_size(None, root_partition) +
                      file_size(None, verity_partition))

        root_uuid = _uuid_ify(root_hash[:32]) if root_hash else ""
        verity_uuid = _uuid_ify(root_hash[32:]) if root_hash else ""

        with open(image_filename, "wb") as fd:
            fd.seek(total_size - 1)
            fd.write(b"\b")

        self._execute(
            location,
            system_context,
            "_create_export_image",
            image_filename,
            efi_fsimage=efi_partition,
            efi_label="ESP",
            root_fsimage=root_partition,
            root_label=system_context.substitution_expanded(
                "ROOTFS_PARTLABEL", ""),
            root_uuid=root_uuid,
            verity_fsimage=verity_partition,
            verity_label=system_context.substitution_expanded(
                "VRTYFS_PARTLABEL", ""),
            verity_uuid=verity_uuid,
        )
Exemple #2
0
    def __call__(
        self,
        location: Location,
        system_context: SystemContext,
        *args: typing.Any,
        **kwargs: typing.Any,
    ) -> None:
        """Execute command."""
        image_filename = args[0]

        efi_partition = kwargs.get("efi_fsimage", "")
        efi_label = kwargs.get("efi_label", "")
        efi_uuid = kwargs.get("efi_uuid", "")
        assert efi_partition

        root_partition = kwargs.get("root_fsimage", "")
        root_label = kwargs.get("root_label", "")
        root_uuid = kwargs.get("root_uuid", "")
        assert root_partition

        verity_partition = kwargs.get("verity_fsimage", "")
        verity_label = kwargs.get("verity_label", "")
        verity_uuid = kwargs.get("verity_uuid", "")
        assert verity_partition

        efi_size = file_size(None, efi_partition)
        root_size = file_size(None, root_partition)
        verity_size = file_size(None, verity_partition)
        total_size = (2 * 1024 * 1024) + efi_size + root_size + verity_size

        debug(
            f"Creating export image with {total_size} bytes (EFI: {efi_size}, root: {root_size}, verity: {verity_size})"
        )

        with open(image_filename, "wb") as fd:
            fd.seek(total_size - 1)
            fd.write(b"\0")

        repart_d_directory = os.path.join(system_context.cache_directory,
                                          "repart.d")
        os.makedirs(repart_d_directory)

        _write_repart_config(
            repart_d_directory,
            "10_efi.conf",
            type="esp",
            image=efi_partition,
            label=efi_label,
            uuid=efi_uuid,
        )
        _write_repart_config(
            repart_d_directory,
            "20_rootfs.conf",
            type="root-x86-64",
            image=root_partition,
            label=root_label,
            uuid=root_uuid,
        )
        _write_repart_config(
            repart_d_directory,
            "30_verity.conf",
            type="root-x86-64-verity",
            image=verity_partition,
            label=verity_label,
            uuid=verity_uuid,
        )

        run(
            self._binary(Binaries.SYSTEMD_REPART),
            "--dry-run=no",
            "--empty=require",
            f"--root={system_context.fs_directory}",
            f"--definitions={repart_d_directory}",
            image_filename,
        )
    def __call__(
        self,
        location: Location,
        system_context: SystemContext,
        *args: typing.Any,
        **kwargs: typing.Any,
    ) -> None:
        """Execute command."""
        efi_file = args[0]

        kernel_file = kwargs.get("kernel_file", "")
        boot_loader_file = kwargs.get("systemd_boot_loader", "")
        requested_size = int(kwargs.get("requested_size", "0"))
        extra_files = kwargs.get("extra_files", "")
        efi_emulator = kwargs.get("efi_emulator", "")
        partition_label = kwargs.get("partition_label", "")
        root_hash = kwargs.get("root_hash", "")

        if kernel_file:
            if not os.path.isfile(boot_loader_file):
                raise GenerateError(
                    "You must provide a boot loader file and that must be a file when passing a kernel file."
                )

        if extra_files:
            extra_files = os.path.join(
                system_context.systems_definition_directory, extra_files)
            if not os.path.isdir(extra_files):
                raise GenerateError(
                    f"extra_files {extra_files} is not a directory.")

        kernel_size = file_size(None,
                                kernel_file) if kernel_file else 256 * 1024
        boot_loader_size = file_size(None, boot_loader_file)

        min_efi_size = kernel_size
        if kernel_file:
            if efi_emulator:
                min_efi_size += 10 * mib
            if extra_files:
                min_efi_size += _get_tree_size(extra_files)
            min_efi_size += 2 * boot_loader_size

        efi_size = _calculate_efi_size(min_efi_size, requested_size)

        # create file:
        with open(efi_file, "wb") as fd:
            fd.seek(efi_size - 1)
            fd.write(b"\0")

        # format file:
        self._format_efi_partition(efi_file, partition_label=partition_label)

        with TemporaryDirectory() as staging_area:
            if kernel_file:
                if efi_emulator:
                    _populate_with_efi_emulator(staging_area, efi_emulator)
                    trace("... Clover binaries have been installed.")

                if extra_files:
                    shutil.copytree(extra_files,
                                    staging_area,
                                    dirs_exist_ok=True)
                    trace("... Extra EFI files installed.")

                # install systemd as default boot loader:
                default_boot_path = os.path.join(staging_area, "EFI/Boot")
                os.makedirs(default_boot_path)
                trace('... "EFI/boot" directory created.')
                _copy_efi_file(boot_loader_file,
                               os.path.join(default_boot_path, "BOOTX64.EFI"))
                trace("... default boot loader installed")

                os.makedirs(os.path.join(staging_area, "EFI/systemd"))
                trace('... "EFI/systemd" directory created.')
                _copy_efi_file(
                    boot_loader_file,
                    os.path.join(staging_area, "EFI/systemd/"
                                 "systemd-bootx64.efi"),
                )
                trace("... systemd boot loader installed.")

                linux_dir = os.path.join(staging_area, "EFI/Linux")
                os.makedirs(linux_dir)
                trace('... "EFI/Linux" created.')
                _copy_efi_file(kernel_file, linux_dir)
                trace("... kernel installed")
            else:
                with open(os.path.join(staging_area, "no_boot.txt"), "w") as f:
                    f.write("No EFI boot support installed\n")

            if root_hash:
                with open(os.path.join(staging_area, "root_hash"), "w") as f:
                    f.write(f"{root_hash}")

            _copy_staging_area_into_efi_partition_file(
                staging_area,
                efi_file,
                mmd=self._binary(Binaries.MTOOLS_MMD),
                mcopy=self._binary(Binaries.MTOOLS_MCOPY),
            )