binman: Add support for a collection of entries
[platform/kernel/u-boot.git] / tools / binman / etype / vblock.py
1 # SPDX-License-Identifier: GPL-2.0+
2 # Copyright (c) 2018 Google, Inc
3 # Written by Simon Glass <sjg@chromium.org>
4 #
5
6 # Support for a Chromium OS verified boot block, used to sign a read-write
7 # section of the image.
8
9 from collections import OrderedDict
10 import os
11
12 from binman.entry import EntryArg
13 from binman.etype.collection import Entry_collection
14
15 from dtoc import fdt_util
16 from patman import tools
17
18 class Entry_vblock(Entry_collection):
19     """An entry which contains a Chromium OS verified boot block
20
21     Properties / Entry arguments:
22         - content: List of phandles to entries to sign
23         - keydir: Directory containing the public keys to use
24         - keyblock: Name of the key file to use (inside keydir)
25         - signprivate: Name of provide key file to use (inside keydir)
26         - version: Version number of the vblock (typically 1)
27         - kernelkey: Name of the kernel key to use (inside keydir)
28         - preamble-flags: Value of the vboot preamble flags (typically 0)
29
30     Output files:
31         - input.<unique_name> - input file passed to futility
32         - vblock.<unique_name> - output file generated by futility (which is
33             used as the entry contents)
34
35     Chromium OS signs the read-write firmware and kernel, writing the signature
36     in this block. This allows U-Boot to verify that the next firmware stage
37     and kernel are genuine.
38     """
39     def __init__(self, section, etype, node):
40         super().__init__(section, etype, node)
41         (self.keydir, self.keyblock, self.signprivate, self.version,
42          self.kernelkey, self.preamble_flags) = self.GetEntryArgsOrProps([
43             EntryArg('keydir', str),
44             EntryArg('keyblock', str),
45             EntryArg('signprivate', str),
46             EntryArg('version', int),
47             EntryArg('kernelkey', str),
48             EntryArg('preamble-flags', int)])
49
50     def GetVblock(self):
51         """Get the contents of this entry
52
53         Returns:
54             bytes content of the entry, which is the signed vblock for the
55                 provided data
56         """
57         # Join up the data files to be signed
58         input_data = self.GetContents()
59         if input_data is None:
60             return None
61
62         uniq = self.GetUniqueName()
63         output_fname = tools.GetOutputFilename('vblock.%s' % uniq)
64         input_fname = tools.GetOutputFilename('input.%s' % uniq)
65         tools.WriteFile(input_fname, input_data)
66         prefix = self.keydir + '/'
67         args = [
68             'vbutil_firmware',
69             '--vblock', output_fname,
70             '--keyblock', prefix + self.keyblock,
71             '--signprivate', prefix + self.signprivate,
72             '--version', '%d' % self.version,
73             '--fv', input_fname,
74             '--kernelkey', prefix + self.kernelkey,
75             '--flags', '%d' % self.preamble_flags,
76         ]
77         #out.Notice("Sign '%s' into %s" % (', '.join(self.value), self.label))
78         stdout = tools.Run('futility', *args)
79         return tools.ReadFile(output_fname)
80
81     def ObtainContents(self):
82         data = self.GetVblock()
83         if data is None:
84             return False
85         self.SetContents(data)
86         return True
87
88     def ProcessContents(self):
89         # The blob may have changed due to WriteSymbols()
90         data = self.GetVblock()
91         return self.ProcessContentsUpdate(data)