From patchwork Tue Jul 17 19:25:44 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Glass X-Patchwork-Id: 945305 X-Patchwork-Delegate: sjg@chromium.org Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=lists.denx.de (client-ip=81.169.180.215; helo=lists.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=chromium.org Received: from lists.denx.de (dione.denx.de [81.169.180.215]) by ozlabs.org (Postfix) with ESMTP id 41VW7Q1ZXQz9s3R for ; Wed, 18 Jul 2018 05:49:06 +1000 (AEST) Received: by lists.denx.de (Postfix, from userid 105) id DE779C21C3F; Tue, 17 Jul 2018 19:39:36 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on lists.denx.de X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=unavailable autolearn_force=no version=3.4.0 Received: from lists.denx.de (localhost [IPv6:::1]) by lists.denx.de (Postfix) with ESMTP id 46C9AC21F7D; Tue, 17 Jul 2018 19:26:53 +0000 (UTC) Received: by lists.denx.de (Postfix, from userid 105) id BDFEEC21C27; Tue, 17 Jul 2018 19:26:44 +0000 (UTC) Received: from mail-io0-f201.google.com (mail-io0-f201.google.com [209.85.223.201]) by lists.denx.de (Postfix) with ESMTPS id 86C78C21F03 for ; Tue, 17 Jul 2018 19:26:39 +0000 (UTC) Received: by mail-io0-f201.google.com with SMTP id z9-v6so1619222iom.14 for ; Tue, 17 Jul 2018 12:26:39 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:date:in-reply-to:message-id :references:subject:from:to:cc; bh=erXKO5KYwPQS21KzyoA6V8l6bFD2Lnv4V5eXT/UPCak=; b=LsPXBX+G1ngGQ+XKcvjG4SYAL4r2VNcSRCX2EqpnJBNu3Ls9SUxIXAgsbyMlZyv0kF uQ77G3dJD+3/bX3Zo3zTAjyFgqIaxWIQ/fWikg0z5RNVjzYHs81wHZ6bH7UAwMFzq4e0 j94LppicmWuimFMn7jhESKLzfzd0COJf+JzYQ2xc8mdEB+bt1CKtttMXYzH9daKWyxHN wXj1wkstnQrjh2why6e5soHRo79mWIvUYD5KYuT5nQY6DNvLk0n43vI8xWHbC4DlOpEX g6p7vOwi9O9EE75v1YpGWlrTROO+glzx0mNNOxlbB4a+9AadbxdX0uzLQs8AKxgvCYJY Ui7g== X-Gm-Message-State: AOUpUlEHPeQE/Vs7oqxkRvAgNxJA4tk8b2I8hJm8xCgEzCnP7FZLUHv1 8+9vgXEjxTz281C5SkPN1SGmHII= X-Google-Smtp-Source: AA+uWPxyewlIyEbpfA2aCQRpOSBXWAtIs27HU+TtWiY+sKku7hS/ZGXGJyJkK/REr1QFUM/9sJz9P54= MIME-Version: 1.0 X-Received: by 2002:a6b:ab81:: with SMTP id u123-v6mr1220206ioe.102.1531855598588; Tue, 17 Jul 2018 12:26:38 -0700 (PDT) Date: Tue, 17 Jul 2018 13:25:44 -0600 In-Reply-To: <20180717192552.198496-1-sjg@chromium.org> Message-Id: <20180717192552.198496-22-sjg@chromium.org> References: <20180717192552.198496-1-sjg@chromium.org> X-Mailer: git-send-email 2.18.0.203.gfac676dfb9-goog From: Simon Glass To: U-Boot Mailing List Cc: Tom Rini Subject: [U-Boot] [PATCH 21/29] binman: Add support for Chromium GBB X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.18 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" This entry contains a Google Binary Block, used to store keys and bitmaps in a Chromium image. Signed-off-by: Simon Glass --- tools/binman/README.entries | 19 +++++ tools/binman/etype/gbb.py | 96 ++++++++++++++++++++++++++ tools/binman/ftest.py | 56 +++++++++++++++ tools/binman/test/71_gbb.dts | 31 +++++++++ tools/binman/test/72_gbb_too_small.dts | 10 +++ tools/binman/test/73_gbb_no_size.dts | 9 +++ 6 files changed, 221 insertions(+) create mode 100644 tools/binman/etype/gbb.py create mode 100644 tools/binman/test/71_gbb.dts create mode 100644 tools/binman/test/72_gbb_too_small.dts create mode 100644 tools/binman/test/73_gbb_no_size.dts diff --git a/tools/binman/README.entries b/tools/binman/README.entries index 6f09626b24..41b70192c0 100644 --- a/tools/binman/README.entries +++ b/tools/binman/README.entries @@ -91,6 +91,25 @@ FMAP does not support this. +Entry: gbb: An entry which contains a Chromium OS Google Binary Block +--------------------------------------------------------------------- + +Properties / Entry arguments: + - hardware-id: Hardware ID to use for this build (a string) + - keydir: Directory containing the public keys to use + - bmpblk: Filename containing images used by recovery + +Chromium OS uses a GBB to store various pieces of information, in particular +the root and recovery keys that are used to verify the boot process. Some +more details are here: + + https://www.chromium.org/chromium-os/firmware-porting-guide/2-concepts + +but note that the page dates from 2013 so is quite out of date. See +README.chromium for how to obtain the required keys and tools. + + + Entry: intel-cmc: Entry containing an Intel Chipset Micro Code (CMC) file ------------------------------------------------------------------------- diff --git a/tools/binman/etype/gbb.py b/tools/binman/etype/gbb.py new file mode 100644 index 0000000000..8fe10f4713 --- /dev/null +++ b/tools/binman/etype/gbb.py @@ -0,0 +1,96 @@ +# SPDX-License-Identifier: GPL-2.0+ +# Copyright (c) 2018 Google, Inc +# Written by Simon Glass +# + +# Support for a Chromium OS Google Binary Block, used to record read-only +# information mostly used by firmware. + +from collections import OrderedDict + +import command +from entry import Entry, EntryArg + +import fdt_util +import tools + +# Build GBB flags. +# (src/platform/vboot_reference/firmware/include/gbb_header.h) +gbb_flag_properties = { + 'dev-screen-short-delay': 0x1, + 'load-option-roms': 0x2, + 'enable-alternate-os': 0x4, + 'force-dev-switch-on': 0x8, + 'force-dev-boot-usb': 0x10, + 'disable-fw-rollback-check': 0x20, + 'enter-triggers-tonorm': 0x40, + 'force-dev-boot-legacy': 0x80, + 'faft-key-override': 0x100, + 'disable-ec-software-sync': 0x200, + 'default-dev-boot-legacy': 0x400, + 'disable-pd-software-sync': 0x800, + 'disable-lid-shutdown': 0x1000, + 'force-dev-boot-fastboot-full-cap': 0x2000, + 'enable-serial': 0x4000, + 'disable-dwmp': 0x8000, +} + + +class Entry_gbb(Entry): + """An entry which contains a Chromium OS Google Binary Block + + Properties / Entry arguments: + - hardware-id: Hardware ID to use for this build (a string) + - keydir: Directory containing the public keys to use + - bmpblk: Filename containing images used by recovery + + Chromium OS uses a GBB to store various pieces of information, in particular + the root and recovery keys that are used to verify the boot process. Some + more details are here: + + https://www.chromium.org/chromium-os/firmware-porting-guide/2-concepts + + but note that the page dates from 2013 so is quite out of date. See + README.chromium for how to obtain the required keys and tools. + """ + def __init__(self, section, etype, node): + Entry.__init__(self, section, etype, node) + self.hardware_id, self.keydir, self.bmpblk = self.GetEntryArgsOrProps( + [EntryArg('hardware-id', str), + EntryArg('keydir', str), + EntryArg('bmpblk', str)]) + + # Read in the GBB flags from the config + self.gbb_flags = 0 + flags_node = node.FindNode('flags') + if flags_node: + for flag, value in gbb_flag_properties.iteritems(): + if fdt_util.GetBool(flags_node, flag): + self.gbb_flags |= value + + def ObtainContents(self): + gbb = 'gbb.bin' + fname = tools.GetOutputFilename(gbb) + if not self.size: + self.Raise('GBB must have a fixed size') + gbb_size = self.size + bmpfv_size = gbb_size - 0x2180 + if bmpfv_size < 0: + self.Raise('GBB is too small (minimum 0x2180 bytes)') + sizes = [0x100, 0x1000, bmpfv_size, 0x1000] + sizes = ['%#x' % size for size in sizes] + keydir = tools.GetInputFilename(self.keydir) + gbb_set_command = [ + 'gbb_utility', '-s', + '--hwid=%s' % self.hardware_id, + '--rootkey=%s/root_key.vbpubk' % keydir, + '--recoverykey=%s/recovery_key.vbpubk' % keydir, + '--flags=%d' % self.gbb_flags, + '--bmpfv=%s' % tools.GetInputFilename(self.bmpblk), + fname] + + tools.Run('futility', 'gbb_utility', '-c', ','.join(sizes), fname) + tools.Run('futility', *gbb_set_command) + + self.SetContents(tools.ReadFile(fname)) + return True diff --git a/tools/binman/ftest.py b/tools/binman/ftest.py index 4e467145d7..f15b215c60 100644 --- a/tools/binman/ftest.py +++ b/tools/binman/ftest.py @@ -47,6 +47,8 @@ TEXT_DATA = 'text' TEXT_DATA2 = 'text2' TEXT_DATA3 = 'text3' CROS_EC_RW_DATA = 'ecrw' +GBB_DATA = 'gbbd' +BMPBLK_DATA = 'bmp' class TestFunctional(unittest.TestCase): @@ -95,6 +97,8 @@ class TestFunctional(unittest.TestCase): TestFunctional._MakeInputFile('vbt.bin', VBT_DATA) TestFunctional._MakeInputFile('mrc.bin', MRC_DATA) TestFunctional._MakeInputFile('ecrw.bin', CROS_EC_RW_DATA) + TestFunctional._MakeInputDir('devkeys') + TestFunctional._MakeInputFile('bmpblk.bin', BMPBLK_DATA) self._output_setup = False # ELF file with a '_dt_ucode_base_size' symbol @@ -287,6 +291,21 @@ class TestFunctional(unittest.TestCase): fd.write(contents) return pathname + @classmethod + def _MakeInputDir(self, dirname): + """Create a new test input directory, creating directories as needed + + Args: + dirname: Directory name to create + + Returns: + Full pathname of directory created + """ + pathname = os.path.join(self._indir, dirname) + if not os.path.exists(pathname): + os.makedirs(pathname) + return pathname + @classmethod def TestFile(self, fname): return os.path.join(self._binman_dir, 'test', fname) @@ -1248,6 +1267,43 @@ class TestFunctional(unittest.TestCase): self.assertIn("'fill' entry must have a size property", str(e.exception)) + def _HandleGbbCommand(self, pipe_list): + """Fake calls to the futility utility""" + if pipe_list[0][0] == 'futility': + fname = pipe_list[0][-1] + # Append our GBB data to the file, which will happen every time the + # futility command is called. + with open(fname, 'a') as fd: + fd.write(GBB_DATA) + return command.CommandResult() + + def testGbb(self): + """Test for the Chromium OS Google Binary Block""" + command.test_result = self._HandleGbbCommand + entry_args = { + 'keydir': 'devkeys', + 'bmpblk': 'bmpblk.bin', + } + data, _, _, _ = self._DoReadFileDtb('71_gbb.dts', entry_args=entry_args) + + # Since futility + expected = GBB_DATA + GBB_DATA + 8 * chr(0) + (0x2180 - 16) * chr(0) + self.assertEqual(expected, data) + + def testGbbTooSmall(self): + """Test for the Chromium OS Google Binary Block being large enough""" + with self.assertRaises(ValueError) as e: + self._DoReadFileDtb('72_gbb_too_small.dts') + self.assertIn("Node '/binman/gbb': GBB is too small", + str(e.exception)) + + def testGbbNoSize(self): + """Test for the Chromium OS Google Binary Block having a size""" + with self.assertRaises(ValueError) as e: + self._DoReadFileDtb('73_gbb_no_size.dts') + self.assertIn("Node '/binman/gbb': GBB must have a fixed size", + str(e.exception)) + if __name__ == "__main__": unittest.main() diff --git a/tools/binman/test/71_gbb.dts b/tools/binman/test/71_gbb.dts new file mode 100644 index 0000000000..551756372a --- /dev/null +++ b/tools/binman/test/71_gbb.dts @@ -0,0 +1,31 @@ +// SPDX-License-Identifier: GPL-2.0+ +/dts-v1/; + +/ { + #address-cells = <1>; + #size-cells = <1>; + + binman { + gbb { + size = <0x2180>; + flags { + dev-screen-short-delay; + load-option-roms; + enable-alternate-os; + force-dev-switch-on; + force-dev-boot-usb; + disable-fw-rollback-check; + enter-triggers-tonorm; + force-dev-boot-legacy; + faft-key-override; + disable-ec-software-sync; + default-dev-boot-legacy; + disable-pd-software-sync; + disable-lid-shutdown; + force-dev-boot-fastboot-full-cap; + enable-serial; + disable-dwmp; + }; + }; + }; +}; diff --git a/tools/binman/test/72_gbb_too_small.dts b/tools/binman/test/72_gbb_too_small.dts new file mode 100644 index 0000000000..c088f36a1d --- /dev/null +++ b/tools/binman/test/72_gbb_too_small.dts @@ -0,0 +1,10 @@ +// SPDX-License-Identifier: GPL-2.0+ +/dts-v1/; + +/ { + binman { + gbb { + size = <0x200>; + }; + }; +}; diff --git a/tools/binman/test/73_gbb_no_size.dts b/tools/binman/test/73_gbb_no_size.dts new file mode 100644 index 0000000000..83be403785 --- /dev/null +++ b/tools/binman/test/73_gbb_no_size.dts @@ -0,0 +1,9 @@ +// SPDX-License-Identifier: GPL-2.0+ +/dts-v1/; + +/ { + binman { + gbb { + }; + }; +};