mirror of
https://github.com/Fishwaldo/u-boot.git
synced 2025-06-24 23:53:04 +00:00
binman: Add support for Chromium GBB
This entry contains a Google Binary Block, used to store keys and bitmaps in a Chromium image. Signed-off-by: Simon Glass <sjg@chromium.org>
This commit is contained in:
parent
aeffc5e956
commit
0ef87aa332
6 changed files with 221 additions and 0 deletions
|
@ -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
|
Entry: intel-cmc: Entry containing an Intel Chipset Micro Code (CMC) file
|
||||||
-------------------------------------------------------------------------
|
-------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
96
tools/binman/etype/gbb.py
Normal file
96
tools/binman/etype/gbb.py
Normal file
|
@ -0,0 +1,96 @@
|
||||||
|
# SPDX-License-Identifier: GPL-2.0+
|
||||||
|
# Copyright (c) 2018 Google, Inc
|
||||||
|
# Written by Simon Glass <sjg@chromium.org>
|
||||||
|
#
|
||||||
|
|
||||||
|
# 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
|
|
@ -47,6 +47,8 @@ TEXT_DATA = 'text'
|
||||||
TEXT_DATA2 = 'text2'
|
TEXT_DATA2 = 'text2'
|
||||||
TEXT_DATA3 = 'text3'
|
TEXT_DATA3 = 'text3'
|
||||||
CROS_EC_RW_DATA = 'ecrw'
|
CROS_EC_RW_DATA = 'ecrw'
|
||||||
|
GBB_DATA = 'gbbd'
|
||||||
|
BMPBLK_DATA = 'bmp'
|
||||||
|
|
||||||
|
|
||||||
class TestFunctional(unittest.TestCase):
|
class TestFunctional(unittest.TestCase):
|
||||||
|
@ -95,6 +97,8 @@ class TestFunctional(unittest.TestCase):
|
||||||
TestFunctional._MakeInputFile('vbt.bin', VBT_DATA)
|
TestFunctional._MakeInputFile('vbt.bin', VBT_DATA)
|
||||||
TestFunctional._MakeInputFile('mrc.bin', MRC_DATA)
|
TestFunctional._MakeInputFile('mrc.bin', MRC_DATA)
|
||||||
TestFunctional._MakeInputFile('ecrw.bin', CROS_EC_RW_DATA)
|
TestFunctional._MakeInputFile('ecrw.bin', CROS_EC_RW_DATA)
|
||||||
|
TestFunctional._MakeInputDir('devkeys')
|
||||||
|
TestFunctional._MakeInputFile('bmpblk.bin', BMPBLK_DATA)
|
||||||
self._output_setup = False
|
self._output_setup = False
|
||||||
|
|
||||||
# ELF file with a '_dt_ucode_base_size' symbol
|
# ELF file with a '_dt_ucode_base_size' symbol
|
||||||
|
@ -287,6 +291,21 @@ class TestFunctional(unittest.TestCase):
|
||||||
fd.write(contents)
|
fd.write(contents)
|
||||||
return pathname
|
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
|
@classmethod
|
||||||
def TestFile(self, fname):
|
def TestFile(self, fname):
|
||||||
return os.path.join(self._binman_dir, 'test', 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",
|
self.assertIn("'fill' entry must have a size property",
|
||||||
str(e.exception))
|
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__":
|
if __name__ == "__main__":
|
||||||
unittest.main()
|
unittest.main()
|
||||||
|
|
31
tools/binman/test/71_gbb.dts
Normal file
31
tools/binman/test/71_gbb.dts
Normal file
|
@ -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;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
10
tools/binman/test/72_gbb_too_small.dts
Normal file
10
tools/binman/test/72_gbb_too_small.dts
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
// SPDX-License-Identifier: GPL-2.0+
|
||||||
|
/dts-v1/;
|
||||||
|
|
||||||
|
/ {
|
||||||
|
binman {
|
||||||
|
gbb {
|
||||||
|
size = <0x200>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
9
tools/binman/test/73_gbb_no_size.dts
Normal file
9
tools/binman/test/73_gbb_no_size.dts
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
// SPDX-License-Identifier: GPL-2.0+
|
||||||
|
/dts-v1/;
|
||||||
|
|
||||||
|
/ {
|
||||||
|
binman {
|
||||||
|
gbb {
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
Loading…
Add table
Add a link
Reference in a new issue