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 Google Binary Block, used to record read-only
7# information mostly used by firmware.
8
9from collections import OrderedDict
10
11from u_boot_pylib import command
12from binman.entry import Entry, EntryArg
13
14from dtoc import fdt_util
15from u_boot_pylib import tools
16
17# Build GBB flags.
18# (src/platform/vboot_reference/firmware/include/gbb_header.h)
19gbb_flag_properties = {
20  'dev-screen-short-delay': 0x1,
21  'load-option-roms': 0x2,
22  'enable-alternate-os': 0x4,
23  'force-dev-switch-on': 0x8,
24  'force-dev-boot-usb': 0x10,
25  'disable-fw-rollback-check': 0x20,
26  'enter-triggers-tonorm': 0x40,
27  'force-dev-boot-legacy': 0x80,
28  'faft-key-override': 0x100,
29  'disable-ec-software-sync': 0x200,
30  'default-dev-boot-legacy': 0x400,
31  'disable-pd-software-sync': 0x800,
32  'disable-lid-shutdown': 0x1000,
33  'force-dev-boot-fastboot-full-cap': 0x2000,
34  'enable-serial': 0x4000,
35  'disable-dwmp': 0x8000,
36}
37
38
39class Entry_gbb(Entry):
40    """An entry which contains a Chromium OS Google Binary Block
41
42    Properties / Entry arguments:
43        - hardware-id: Hardware ID to use for this build (a string)
44        - keydir: Directory containing the public keys to use
45        - bmpblk: Filename containing images used by recovery
46
47    Chromium OS uses a GBB to store various pieces of information, in particular
48    the root and recovery keys that are used to verify the boot process. Some
49    more details are here:
50
51        https://www.chromium.org/chromium-os/firmware-porting-guide/2-concepts
52
53    but note that the page dates from 2013 so is quite out of date. See
54    README.chromium for how to obtain the required keys and tools.
55    """
56    def __init__(self, section, etype, node):
57        super().__init__(section, etype, node)
58        self.hardware_id, self.keydir, self.bmpblk = self.GetEntryArgsOrProps(
59            [EntryArg('hardware-id', str),
60             EntryArg('keydir', str),
61             EntryArg('bmpblk', str)])
62
63        # Read in the GBB flags from the config
64        self.gbb_flags = 0
65        flags_node = node.FindNode('flags')
66        if flags_node:
67            for flag, value in gbb_flag_properties.items():
68                if fdt_util.GetBool(flags_node, flag):
69                    self.gbb_flags |= value
70
71    def ObtainContents(self):
72        gbb = 'gbb.bin'
73        fname = tools.get_output_filename(gbb)
74        if not self.size:
75            self.Raise('GBB must have a fixed size')
76        gbb_size = self.size
77        bmpfv_size = gbb_size - 0x2180
78        if bmpfv_size < 0:
79            self.Raise('GBB is too small (minimum 0x2180 bytes)')
80        keydir = tools.get_input_filename(self.keydir)
81
82        stdout = self.futility.gbb_create(
83            fname, [0x100, 0x1000, bmpfv_size, 0x1000])
84        if stdout is not None:
85            stdout = self.futility.gbb_set(
86                fname,
87                hwid=self.hardware_id,
88                rootkey='%s/root_key.vbpubk' % keydir,
89                recoverykey='%s/recovery_key.vbpubk' % keydir,
90                flags=self.gbb_flags,
91                bmpfv=tools.get_input_filename(self.bmpblk))
92
93        if stdout is not None:
94            self.SetContents(tools.read_file(fname))
95        else:
96            # Bintool is missing; just use the required amount of zero data
97            self.record_missing_bintool(self.futility)
98            self.SetContents(tools.get_bytes(0, gbb_size))
99
100        return True
101
102    def AddBintools(self, btools):
103        super().AddBintools(btools)
104        self.futility = self.AddBintool(btools, 'futility')
105