1# SPDX-License-Identifier: GPL-2.0+
2# Copyright 2023 Linaro Limited
3#
4"""Bintool implementation for mkeficapsule tool
5
6mkeficapsule is a tool used for generating EFI capsules.
7
8The following are the commandline options to be provided
9to the tool
10Usage: mkeficapsule [options] <image blob> <output file>
11Options:
12	-g, --guid <guid string>    guid for image blob type
13	-i, --index <index>         update image index
14	-I, --instance <instance>   update hardware instance
15	-v, --fw-version <version>  firmware version
16	-p, --private-key <privkey file>  private key file
17	-c, --certificate <cert file>     signer's certificate file
18	-m, --monotonic-count <count>     monotonic count
19	-d, --dump_sig              dump signature (*.p7)
20	-A, --fw-accept  firmware accept capsule, requires GUID, no image blob
21	-R, --fw-revert  firmware revert capsule, takes no GUID, no image blob
22	-o, --capoemflag Capsule OEM Flag, an integer between 0x0000 and 0xffff
23	-h, --help                  print a help message
24"""
25
26from binman import bintool
27
28class Bintoolmkeficapsule(bintool.Bintool):
29    """Handles the 'mkeficapsule' tool
30
31    This bintool is used for generating the EFI capsules. The
32    capsule generation parameters can either be specified through
33    commandline, or through a config file.
34    """
35    def __init__(self, name):
36        super().__init__(name, 'mkeficapsule tool for generating capsules',
37                         r'mkeficapsule version (.*)')
38
39    def generate_capsule(self, image_index, image_guid, hardware_instance,
40                         payload, output_fname, priv_key, pub_key,
41                         monotonic_count=0, version=0, oemflags=0):
42        """Generate a capsule through commandline-provided parameters
43
44        Args:
45            image_index (int): Unique number for identifying payload image
46            image_guid (str): GUID used for identifying the image
47            hardware_instance (int): Optional unique hardware instance of
48            a device in the system. 0 if not being used
49            payload (str): Path to the input payload image
50            output_fname (str): Path to the output capsule file
51            priv_key (str): Path to the private key
52            pub_key(str): Path to the public key
53            monotonic_count (int): Count used when signing an image
54            version (int): Image version (Optional)
55            oemflags (int): Optional 16 bit OEM flags
56
57        Returns:
58            str: Tool output
59        """
60        args = [
61            f'--index={image_index}',
62            f'--guid={image_guid}',
63            f'--instance={hardware_instance}'
64        ]
65
66        if version:
67            args += [f'--fw-version={version}']
68        if oemflags:
69            args += [f'--capoemflag={oemflags}']
70        if priv_key and pub_key:
71            args += [
72                f'--monotonic-count={monotonic_count}',
73                f'--private-key={priv_key}',
74                f'--certificate={pub_key}'
75            ]
76
77        args += [
78            payload,
79            output_fname
80        ]
81
82        return self.run_cmd(*args)
83
84    def generate_empty_capsule(self, image_guid, output_fname,
85                               accept=True):
86        """Generate empty capsules for FWU A/B updates
87
88        Args:
89            image_guid (str): GUID used for identifying the image
90                in case of an accept capsule
91            output_fname (str): Path to the output capsule file
92            accept (bool): Generate an accept capsule,
93                else a revert capsule
94
95        Returns:
96            str: Tool output
97        """
98        if accept:
99            args = [
100                f'--guid={image_guid}',
101                '--fw-accept'
102            ]
103        else:
104            args = [ '--fw-revert' ]
105
106        args += [ output_fname ]
107
108        return self.run_cmd(*args)
109
110    def fetch(self, method):
111        """Fetch handler for mkeficapsule
112
113        This builds the tool from source
114
115        Returns:
116            tuple:
117                str: Filename of fetched file to copy to a suitable directory
118                str: Name of temp directory to remove, or None
119        """
120        if method != bintool.FETCH_BUILD:
121            return None
122
123        cmd = ['tools-only_defconfig', 'tools']
124        result = self.build_from_git(
125            'https://source.denx.de/u-boot/u-boot.git',
126            cmd,
127            'tools/mkeficapsule')
128        return result
129