From 11e36ccea174043229319263f9d0b5b7f7cca654 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Tue, 17 Jul 2018 13:25:38 -0600 Subject: [PATCH] binman: Add support for flashrom FMAP Add an entry which can hold an FMAP region as used by flashrom, an open-source flashing tool used on Linux x86 machines. This provides a simplified non-hierarchical view of the entries in the image and has a signature at the start to allow flashrom to find it in the image. Signed-off-by: Simon Glass --- tools/binman/README.entries | 20 +++++++ tools/binman/entry.py | 9 +++ tools/binman/etype/fmap.py | 61 +++++++++++++++++++ tools/binman/etype/section.py | 7 ++- tools/binman/fmap_util.py | 109 ++++++++++++++++++++++++++++++++++ tools/binman/ftest.py | 32 ++++++++++ tools/binman/test/67_fmap.dts | 29 +++++++++ 7 files changed, 265 insertions(+), 2 deletions(-) create mode 100644 tools/binman/etype/fmap.py create mode 100644 tools/binman/fmap_util.py create mode 100644 tools/binman/test/67_fmap.dts diff --git a/tools/binman/README.entries b/tools/binman/README.entries index 60cb2488c0..0b3be69f5e 100644 --- a/tools/binman/README.entries +++ b/tools/binman/README.entries @@ -26,6 +26,26 @@ example the 'u_boot' entry which provides the filename 'u-boot.bin'. +Entry: fmap: An entry which contains an Fmap section +---------------------------------------------------- + +Properties / Entry arguments: + None + +FMAP is a simple format used by flashrom, an open-source utility for +reading and writing the SPI flash, typically on x86 CPUs. The format +provides flashrom with a list of areas, so it knows what it in the flash. +It can then read or write just a single area, instead of the whole flash. + +The format is defined by the flashrom project, in the file lib/fmap.h - +see www.flashrom.org/Flashrom for more information. + +When used, this entry will be populated with an FMAP which reflects the +entries in the current image. Note that any hierarchy is squashed, since +FMAP does not support this. + + + Entry: intel-cmc: Entry containing an Intel Chipset Micro Code (CMC) file ------------------------------------------------------------------------- diff --git a/tools/binman/entry.py b/tools/binman/entry.py index dc09b81677..8b910feff6 100644 --- a/tools/binman/entry.py +++ b/tools/binman/entry.py @@ -361,6 +361,15 @@ class Entry(object): """ self.WriteMapLine(fd, indent, self.name, self.offset, self.size) + def GetEntries(self): + """Return a list of entries contained by this entry + + Returns: + List of entries, or None if none. A normal entry has no entries + within it so will return None + """ + return None + def GetArg(self, name, datatype=str): """Get the value of an entry argument or device-tree-node property diff --git a/tools/binman/etype/fmap.py b/tools/binman/etype/fmap.py new file mode 100644 index 0000000000..f1dd81ec49 --- /dev/null +++ b/tools/binman/etype/fmap.py @@ -0,0 +1,61 @@ +# SPDX-License-Identifier: GPL-2.0+ +# Copyright (c) 2018 Google, Inc +# Written by Simon Glass +# +# Entry-type module for a Flash map, as used by the flashrom SPI flash tool +# + +from entry import Entry +import fmap_util + + +class Entry_fmap(Entry): + """An entry which contains an Fmap section + + Properties / Entry arguments: + None + + FMAP is a simple format used by flashrom, an open-source utility for + reading and writing the SPI flash, typically on x86 CPUs. The format + provides flashrom with a list of areas, so it knows what it in the flash. + It can then read or write just a single area, instead of the whole flash. + + The format is defined by the flashrom project, in the file lib/fmap.h - + see www.flashrom.org/Flashrom for more information. + + When used, this entry will be populated with an FMAP which reflects the + entries in the current image. Note that any hierarchy is squashed, since + FMAP does not support this. + """ + def __init__(self, section, etype, node): + Entry.__init__(self, section, etype, node) + + def _GetFmap(self): + """Build an FMAP from the entries in the current image + + Returns: + FMAP binary data + """ + def _AddEntries(areas, entry): + entries = entry.GetEntries() + if entries: + for subentry in entries.values(): + _AddEntries(areas, subentry) + else: + areas.append(fmap_util.FmapArea(entry.image_pos or 0, + entry.size or 0, entry.name, 0)) + + entries = self.section.GetEntries() + areas = [] + for entry in entries.values(): + _AddEntries(areas, entry) + return fmap_util.EncodeFmap(self.section.GetSize() or 0, self.name, + areas) + + def ObtainContents(self): + """Obtain a placeholder for the fmap contents""" + self.SetContents(self._GetFmap()) + return True + + def ProcessContents(self): + self.SetContents(self._GetFmap()) diff --git a/tools/binman/etype/section.py b/tools/binman/etype/section.py index 2e68f276f0..f5b2ed67cf 100644 --- a/tools/binman/etype/section.py +++ b/tools/binman/etype/section.py @@ -30,8 +30,8 @@ class Entry_section(Entry): hierarchical images to be created. See 'Sections and hierarchical images' in the binman README for more information. """ - def __init__(self, image, etype, node): - Entry.__init__(self, image, etype, node) + def __init__(self, section, etype, node): + Entry.__init__(self, section, etype, node) self._section = bsection.Section(node.name, node) def ProcessFdt(self, fdt): @@ -89,3 +89,6 @@ class Entry_section(Entry): fd: File to write the map to """ self._section.WriteMap(fd, indent) + + def GetEntries(self): + return self._section.GetEntries() diff --git a/tools/binman/fmap_util.py b/tools/binman/fmap_util.py new file mode 100644 index 0000000000..7d520e3391 --- /dev/null +++ b/tools/binman/fmap_util.py @@ -0,0 +1,109 @@ +# SPDX-License-Identifier: GPL-2.0+ +# Copyright (c) 2018 Google, Inc +# Written by Simon Glass +# +# Support for flashrom's FMAP format. This supports a header followed by a +# number of 'areas', describing regions of a firmware storage device, +# generally SPI flash. + +import collections +import struct + +# constants imported from lib/fmap.h +FMAP_SIGNATURE = '__FMAP__' +FMAP_VER_MAJOR = 1 +FMAP_VER_MINOR = 0 +FMAP_STRLEN = 32 + +FMAP_AREA_STATIC = 1 << 0 +FMAP_AREA_COMPRESSED = 1 << 1 +FMAP_AREA_RO = 1 << 2 + +FMAP_HEADER_LEN = 56 +FMAP_AREA_LEN = 42 + +FMAP_HEADER_FORMAT = '<8sBBQI%dsH'% (FMAP_STRLEN) +FMAP_AREA_FORMAT = '; + #size-cells = <1>; + + binman { + section@0 { + read-only; + name-prefix = "ro-"; + size = <0x10>; + pad-byte = <0x21>; + + u-boot { + }; + }; + section@1 { + name-prefix = "rw-"; + size = <0x10>; + pad-byte = <0x61>; + + u-boot { + }; + }; + fmap { + }; + }; +}; -- 2.39.5