Skip to contentSkip to conversation

binman: Expand feature set and documentation

PATCH New Simon Glass 1 participant 32 messages Jul 17, 2018 – Jul 26, 2018

Subsystems (5)
lore
Share & tools
lore
#0 lore raw

cover binman: Expand feature set and documentation

This series adds various new features to binman to round out its capabilities. It also adds documentation of each entry type since there are quite a few now.

Noteably this series changes the 'pos' property to be called 'offset'. The 'pos' name is a misnomer with hierarchical images since the position is always relative to the parent. A new 'image-pos' property (calculated by binman) is introduced instead, with a clear meaning.

This is a fairy major change since all source .dts files need to be updated to accommodate it. I believe that doing this rename now (without using the old name for anything else) is the best approach. See the rename patch for motivation and more details.

Changes:

- Passing arguments for entries in via the command line
- Entries filled with a repeated byte
- Putting text in an entry
- TPL
- Chromium entries
- Add README.entries to document entries
- An 'image-pos' property which provides the position of an entry within an image

Simon Glass (29):
binman: Don't depend on dict order in ELF testOutsideFile()
binman: Rename 'position' to 'offset'
binman: Add comments to elf_test
binman: Tidy up some comments in the tests
binman: Enhance the map and fdt-update output
binman: Update the device-tree file on exit
binman: Add a new 'image-pos' property
dtoc: Add missing comments to fdt_util
binman: Add support for passing arguments to entries
binman: Support an entry that holds text
binman: Allow help to work without libfdt
binman: Expand documentation for entries
binman: Allow creation of entry documentation
binman: Create README.entries
binman: Add support for flashrom FMAP
binman: Add support for a cros_ec image
binman: Add an entry filled with a repeating byte
dtoc: Export the _FindNode() function
patman: Allow test commands to fall back to real ones
patman: Add a few more helpers to the tools library
binman: Add support for Chromium GBB
patman: Show the current directory in GetInputFilename()
dtoc: Add a function to obtain a list of phandles
binman: Add an entry for a Chromium vblock
binman: Add support for adding TPL binaries
binman: Show the image position in the map
binman: Rename ReadContents() to ReadBlobContents()
binman: Add a test to catch use of the old 'pos' property
binman: Adjust _GetPropTree() parameters

 arch/arm/dts/sunxi-u-boot.dtsi                |   2 +-
 arch/arm/dts/tegra-u-boot.dtsi                |   6 +-
 arch/x86/dts/u-boot.dtsi                      |  24 +-
 tools/binman/README                           | 135 ++--
 tools/binman/README.entries                   | 585 ++++++++++++++++++
 tools/binman/binman.py                        |  22 +-
 tools/binman/bsection.py                      | 151 +++--
 tools/binman/cmdline.py                       |   6 +-
 tools/binman/control.py                       |  39 +-
 tools/binman/elf.py                           |  10 +-
 tools/binman/elf_test.py                      |  33 +
 tools/binman/entry.py                         | 267 ++++++--
 tools/binman/etype/_testing.py                |  47 +-
 tools/binman/etype/blob.py                    |  16 +-
 tools/binman/etype/blob_named_by_arg.py       |  34 +
 tools/binman/etype/cros_ec_rw.py              |  22 +
 tools/binman/etype/fill.py                    |  32 +
 tools/binman/etype/fmap.py                    |  61 ++
 tools/binman/etype/gbb.py                     |  96 +++
 tools/binman/etype/intel_cmc.py               |  10 +
 tools/binman/etype/intel_descriptor.py        |  26 +-
 tools/binman/etype/intel_fsp.py               |  14 +
 tools/binman/etype/intel_me.py                |  15 +
 tools/binman/etype/intel_mrc.py               |  11 +
 tools/binman/etype/intel_vbt.py               |  10 +
 tools/binman/etype/intel_vga.py               |  12 +
 tools/binman/etype/section.py                 |  48 +-
 tools/binman/etype/text.py                    |  57 ++
 tools/binman/etype/u_boot.py                  |  16 +
 tools/binman/etype/u_boot_dtb.py              |   9 +
 tools/binman/etype/u_boot_dtb_with_ucode.py   |  22 +-
 tools/binman/etype/u_boot_img.py              |  11 +
 tools/binman/etype/u_boot_nodtb.py            |  11 +
 tools/binman/etype/u_boot_spl.py              |  21 +
 tools/binman/etype/u_boot_spl_bss_pad.py      |  16 +
 tools/binman/etype/u_boot_spl_dtb.py          |  11 +-
 tools/binman/etype/u_boot_spl_nodtb.py        |  12 +
 tools/binman/etype/u_boot_tpl.py              |  43 ++
 tools/binman/etype/u_boot_tpl_dtb.py          |  25 +
 tools/binman/etype/u_boot_ucode.py            |  12 +-
 tools/binman/etype/u_boot_with_ucode_ptr.py   |  44 +-
 tools/binman/etype/vblock.py                  |  74 +++
 tools/binman/etype/x86_start16.py             |  14 +
 tools/binman/etype/x86_start16_spl.py         |  14 +
 tools/binman/fmap_util.py                     | 109 ++++
 tools/binman/ftest.py                         | 428 +++++++++++--
 tools/binman/image.py                         |  16 +-
 tools/binman/test/08_pack.dts                 |   2 +-
 tools/binman/test/12_pack_inv_align.dts       |   2 +-
 tools/binman/test/14_pack_overlap.dts         |   2 +-
 tools/binman/test/21_image_pad.dts            |   2 +-
 tools/binman/test/24_sorted.dts               |   6 +-
 tools/binman/test/25_pack_zero_size.dts       |   2 +-
 tools/binman/test/27_pack_4gb_no_size.dts     |   6 +-
 tools/binman/test/28_pack_4gb_outside.dts     |   6 +-
 tools/binman/test/29_x86-rom.dts              |   6 +-
 tools/binman/test/30_x86-rom-me-no-desc.dts   |   4 +-
 tools/binman/test/31_x86-rom-me.dts           |   4 +-
 tools/binman/test/34_x86_ucode.dts            |   2 +-
 tools/binman/test/35_x86_single_ucode.dts     |   2 +-
 tools/binman/test/37_x86_no_ucode.dts         |   2 +-
 .../binman/test/38_x86_ucode_missing_node.dts |   2 +-
 .../test/39_x86_ucode_missing_node2.dts       |   2 +-
 .../binman/test/40_x86_ucode_not_in_image.dts |   2 +-
 tools/binman/test/44_x86_optional_ucode.dts   |   2 +-
 tools/binman/test/45_prop_test.dts            |   4 +-
 tools/binman/test/49_x86_ucode_spl.dts        |   2 +-
 tools/binman/test/53_symbols.dts              |   2 +-
 tools/binman/test/55_sections.dts             |   4 +
 .../test/58_x86_ucode_spl_needs_retry.dts     |   2 +-
 tools/binman/test/62_entry_args.dts           |  14 +
 tools/binman/test/63_entry_args_missing.dts   |  13 +
 tools/binman/test/64_entry_args_required.dts  |  14 +
 .../test/65_entry_args_unknown_datatype.dts   |  15 +
 tools/binman/test/66_text.dts                 |  28 +
 tools/binman/test/67_fmap.dts                 |  29 +
 tools/binman/test/68_blob_named_by_arg.dts    |  12 +
 tools/binman/test/69_fill.dts                 |  15 +
 tools/binman/test/70_fill_no_size.dts         |  14 +
 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 +
 tools/binman/test/74_vblock.dts               |  28 +
 tools/binman/test/75_vblock_no_content.dts    |  23 +
 tools/binman/test/76_vblock_bad_phandle.dts   |  24 +
 tools/binman/test/77_vblock_bad_entry.dts     |  27 +
 tools/binman/test/78_u_boot_tpl.dts           |  11 +
 tools/binman/test/79_uses_pos.dts             |  10 +
 tools/binman/test/u_boot_binman_syms          | Bin 4921 -> 4916 bytes
 tools/binman/test/u_boot_binman_syms.c        |   6 +-
 tools/dtoc/fdt.py                             |  23 +-
 tools/dtoc/fdt_util.py                        |  96 +++
 tools/dtoc/test_fdt.py                        |  49 +-
 tools/patman/command.py                       |   8 +-
 tools/patman/tools.py                         |  80 ++-
 95 files changed, 3012 insertions(+), 346 deletions(-)
 create mode 100644 tools/binman/README.entries
 create mode 100644 tools/binman/etype/blob_named_by_arg.py
 create mode 100644 tools/binman/etype/cros_ec_rw.py
 create mode 100644 tools/binman/etype/fill.py
 create mode 100644 tools/binman/etype/fmap.py
 create mode 100644 tools/binman/etype/gbb.py
 create mode 100644 tools/binman/etype/text.py
 create mode 100644 tools/binman/etype/u_boot_tpl.py
 create mode 100644 tools/binman/etype/u_boot_tpl_dtb.py
 create mode 100644 tools/binman/etype/vblock.py
 create mode 100644 tools/binman/fmap_util.py
 create mode 100644 tools/binman/test/62_entry_args.dts
 create mode 100644 tools/binman/test/63_entry_args_missing.dts
 create mode 100644 tools/binman/test/64_entry_args_required.dts
 create mode 100644 tools/binman/test/65_entry_args_unknown_datatype.dts
 create mode 100644 tools/binman/test/66_text.dts
 create mode 100644 tools/binman/test/67_fmap.dts
 create mode 100644 tools/binman/test/68_blob_named_by_arg.dts
 create mode 100644 tools/binman/test/69_fill.dts
 create mode 100644 tools/binman/test/70_fill_no_size.dts
 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
 create mode 100644 tools/binman/test/74_vblock.dts
 create mode 100644 tools/binman/test/75_vblock_no_content.dts
 create mode 100644 tools/binman/test/76_vblock_bad_phandle.dts
 create mode 100644 tools/binman/test/77_vblock_bad_entry.dts
 create mode 100644 tools/binman/test/78_u_boot_tpl.dts
 create mode 100644 tools/binman/test/79_uses_pos.dts
Signature · 1 line
2.18.0.203.gfac676dfb9-goog
#1 lore raw

PATCH 1/29 binman: Don't depend on dict order in ELF testOutsideFile()

At present this test assumes that the symbols are returned in address order. However, objdump can list symbols in any order and dictionaries do not guarantee any particular order when iterating through item.

Update elf.GetSymbols() to return an OrderedDict, sorted by address, to avoid any problems.

---

 tools/binman/elf.py | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)
tools/binman/elf.py +3 -1
index 0ae3b611ba..8c23040d8c 100644
@@ -57,7 +57,9 @@ def GetSymbols(fname, patterns):
             name = parts[2]
             syms[name] = Symbol(section, int(value, 16), int(size,16),
                                 flags[1] == 'w')
-    return syms
+
+    # Sort dict by address
+    return OrderedDict(sorted(syms.iteritems(), key=lambda x: x[1].address))
 
 def GetSymbolAddress(fname, sym_name):
     """Get a value of a symbol from an ELF file
Signature · 1 line
2.18.0.203.gfac676dfb9-goog
#2 lore raw

PATCH 2/29 binman: Rename 'position' to 'offset'

In reply to Simon Glass

After some thought, I believe there is an unfortunate naming flaw in binman. Entries have a position and size, but now that we support hierarchical sections it is unclear whether a position should be an absolute position within the image, or a relative position within its parent section.

At present 'position' actually means the relative position. This indicates a need for an 'image position' for code that wants to find the location of an entry without having to do calculations back through parents to discover this image position.

A better name for the current 'position' or 'pos' is 'offset'. It is not always an absolute position, but it is always an offset from its parent offset.

It is unfortunate to rename this concept now, 18 months after binman was introduced. However I believe it is the right thing to do. The impact is mostly limited to binman itself and a few changes to in-tree users to binman:

tegra
sunxi
x86

The change makes old binman definitions (e.g. downstream or out-of-tree) incompatible if they use the 'pos = <...>' property. Later work will adjust binman to generate an error when it is used.

---

 arch/arm/dts/sunxi-u-boot.dtsi                |   2 +-
 arch/arm/dts/tegra-u-boot.dtsi                |   6 +-
 arch/x86/dts/u-boot.dtsi                      |  24 ++---
 tools/binman/README                           |  79 ++++++++--------
 tools/binman/bsection.py                      |  88 +++++++++---------
 tools/binman/cmdline.py                       |   2 +-
 tools/binman/control.py                       |   4 +-
 tools/binman/elf.py                           |   6 +-
 tools/binman/entry.py                         |  73 ++++++++-------
 tools/binman/etype/_testing.py                |   4 +-
 tools/binman/etype/intel_descriptor.py        |   8 +-
 tools/binman/etype/section.py                 |  14 +--
 tools/binman/etype/u_boot_dtb_with_ucode.py   |   4 +-
 tools/binman/etype/u_boot_ucode.py            |   4 +-
 tools/binman/etype/u_boot_with_ucode_ptr.py   |  35 +++----
 tools/binman/ftest.py                         |  85 +++++++++--------
 tools/binman/image.py                         |  12 +--
 tools/binman/test/08_pack.dts                 |   2 +-
 tools/binman/test/12_pack_inv_align.dts       |   2 +-
 tools/binman/test/14_pack_overlap.dts         |   2 +-
 tools/binman/test/21_image_pad.dts            |   2 +-
 tools/binman/test/24_sorted.dts               |   6 +-
 tools/binman/test/25_pack_zero_size.dts       |   2 +-
 tools/binman/test/27_pack_4gb_no_size.dts     |   6 +-
 tools/binman/test/28_pack_4gb_outside.dts     |   6 +-
 tools/binman/test/29_x86-rom.dts              |   6 +-
 tools/binman/test/30_x86-rom-me-no-desc.dts   |   4 +-
 tools/binman/test/31_x86-rom-me.dts           |   4 +-
 tools/binman/test/34_x86_ucode.dts            |   2 +-
 tools/binman/test/35_x86_single_ucode.dts     |   2 +-
 tools/binman/test/37_x86_no_ucode.dts         |   2 +-
 .../binman/test/38_x86_ucode_missing_node.dts |   2 +-
 .../test/39_x86_ucode_missing_node2.dts       |   2 +-
 .../binman/test/40_x86_ucode_not_in_image.dts |   2 +-
 tools/binman/test/44_x86_optional_ucode.dts   |   2 +-
 tools/binman/test/45_prop_test.dts            |   4 +-
 tools/binman/test/49_x86_ucode_spl.dts        |   2 +-
 tools/binman/test/53_symbols.dts              |   2 +-
 .../test/58_x86_ucode_spl_needs_retry.dts     |   2 +-
 tools/binman/test/u_boot_binman_syms          | Bin 4921 -> 4916 bytes
 tools/binman/test/u_boot_binman_syms.c        |   6 +-
 41 files changed, 263 insertions(+), 259 deletions(-)
arch/arm/dts/sunxi-u-boot.dtsi +1 -1
index 5adfd9bca2..8a9f2a6417 100644
@@ -8,7 +8,7 @@
 			filename = "spl/sunxi-spl.bin";
 		};
 		u-boot-img {
-			pos = <CONFIG_SPL_PAD_TO>;
+			offset = <CONFIG_SPL_PAD_TO>;
 		};
 	};
 };
arch/arm/dts/tegra-u-boot.dtsi +3 -3
index 4f692ee975..fe19619919 100644
@@ -15,7 +15,7 @@
 			u-boot-spl {
 			};
 			u-boot {
-				pos = <(U_BOOT_OFFSET)>;
+				offset = <(U_BOOT_OFFSET)>;
 			};
 		};
 
@@ -26,7 +26,7 @@
 			u-boot-spl {
 			};
 			u-boot {
-				pos = <(U_BOOT_OFFSET)>;
+				offset = <(U_BOOT_OFFSET)>;
 			};
 		};
 
@@ -36,7 +36,7 @@
 			u-boot-spl {
 			};
 			u-boot-nodtb {
-				pos = <(U_BOOT_OFFSET)>;
+				offset = <(U_BOOT_OFFSET)>;
 			};
 		};
 	};
arch/x86/dts/u-boot.dtsi +12 -12
index 1253fa51c2..1050236330 100644
@@ -11,7 +11,7 @@
 	binman {
 		filename = "u-boot.rom";
 		end-at-4gb;
-		sort-by-pos;
+		sort-by-offset;
 		pad-byte = <0xff>;
 		size = <CONFIG_ROM_SIZE>;
 #ifdef CONFIG_HAVE_INTEL_ME
@@ -24,18 +24,18 @@
 #endif
 #ifdef CONFIG_SPL
 		u-boot-spl-with-ucode-ptr {
-			pos = <CONFIG_SPL_TEXT_BASE>;
+			offset = <CONFIG_SPL_TEXT_BASE>;
 		};
 
 		u-boot-dtb-with-ucode2 {
 			type = "u-boot-dtb-with-ucode";
 		};
 		u-boot {
-			pos = <0xfff00000>;
+			offset = <0xfff00000>;
 		};
 #else
 		u-boot-with-ucode-ptr {
-			pos = <CONFIG_SYS_TEXT_BASE>;
+			offset = <CONFIG_SYS_TEXT_BASE>;
 		};
 #endif
 		u-boot-dtb-with-ucode {
@@ -45,45 +45,45 @@
 		};
 #ifdef CONFIG_HAVE_MRC
 		intel-mrc {
-			pos = <CONFIG_X86_MRC_ADDR>;
+			offset = <CONFIG_X86_MRC_ADDR>;
 		};
 #endif
 #ifdef CONFIG_HAVE_FSP
 		intel-fsp {
 			filename = CONFIG_FSP_FILE;
-			pos = <CONFIG_FSP_ADDR>;
+			offset = <CONFIG_FSP_ADDR>;
 		};
 #endif
 #ifdef CONFIG_HAVE_CMC
 		intel-cmc {
 			filename = CONFIG_CMC_FILE;
-			pos = <CONFIG_CMC_ADDR>;
+			offset = <CONFIG_CMC_ADDR>;
 		};
 #endif
 #ifdef CONFIG_HAVE_VGA_BIOS
 		intel-vga {
 			filename = CONFIG_VGA_BIOS_FILE;
-			pos = <CONFIG_VGA_BIOS_ADDR>;
+			offset = <CONFIG_VGA_BIOS_ADDR>;
 		};
 #endif
 #ifdef CONFIG_HAVE_VBT
 		intel-vbt {
 			filename = CONFIG_VBT_FILE;
-			pos = <CONFIG_VBT_ADDR>;
+			offset = <CONFIG_VBT_ADDR>;
 		};
 #endif
 #ifdef CONFIG_HAVE_REFCODE
 		intel-refcode {
-			pos = <CONFIG_X86_REFCODE_ADDR>;
+			offset = <CONFIG_X86_REFCODE_ADDR>;
 		};
 #endif
 #ifdef CONFIG_SPL
 		x86-start16-spl {
-			pos = <CONFIG_SYS_X86_START16>;
+			offset = <CONFIG_SYS_X86_START16>;
 		};
 #else
 		x86-start16 {
-			pos = <CONFIG_SYS_X86_START16>;
+			offset = <CONFIG_SYS_X86_START16>;
 		};
 #endif
 	};
tools/binman/README +40 -39

198 lines not on this page · raw message

tools/binman/bsection.py +45 -43

186 lines not on this page · raw message

tools/binman/cmdline.py +1 -1
index ae2d1670f9..5c9b4dfead 100644
@@ -43,7 +43,7 @@ def ParseArgs(argv):
     parser.add_option('-T', '--test-coverage', action='store_true',
                     default=False, help='run tests and check for 100% coverage')
     parser.add_option('-u', '--update-fdt', action='store_true',
-        default=False, help='Update the binman node with position/size info')
+        default=False, help='Update the binman node with offset/size info')
     parser.add_option('-v', '--verbosity', default=1,
         type='int', help='Control verbosity: 0=silent, 1=progress, 3=full, '
         '4=debug')
tools/binman/control.py +2 -2
index a40b300fda..17c6d7a2d2 100644
@@ -142,7 +142,7 @@ def Binman(options, args):
             # size of the device tree is correct. Later, in
             # SetCalculatedProperties() we will insert the correct values
             # without changing the device-tree size, thus ensuring that our
-            # entry positions remain the same.
+            # entry offsets remain the same.
             for image in images.values():
                 if options.update_fdt:
                     image.AddMissingProperties()
@@ -157,7 +157,7 @@ def Binman(options, args):
                 # image will be reported after earlier images are already
                 # completed and written, but that does not seem important.
                 image.GetEntryContents()
-                image.GetEntryPositions()
+                image.GetEntryOffsets()
                 image.PackEntries()
                 image.CheckSize()
                 image.CheckEntries()
tools/binman/elf.py +3 -3
index 8c23040d8c..97df8e32c5 100644
@@ -81,9 +81,9 @@ def LookupAndWriteSymbols(elf_fname, entry, section):
     """Replace all symbols in an entry with their correct values
 
     The entry contents is updated so that values for referenced symbols will be
-    visible at run time. This is done by finding out the symbols positions in
-    the entry (using the ELF file) and replacing them with values from binman's
-    data structures.
+    visible at run time. This is done by finding out the symbols offsets in the
+    entry (using the ELF file) and replacing them with values from binman's data
+    structures.
 
     Args:
         elf_fname: Filename of ELF image containing the symbol information for
tools/binman/entry.py +37 -36

168 lines not on this page · raw message

tools/binman/etype/_testing.py +2 -2
index 6a1af57798..31f625c026 100644
@@ -14,7 +14,7 @@ class Entry__testing(Entry):
     """A fake entry used for testing
 
     Properties:
-        return_invalid_entry: Return an invalid entry from GetPositions()
+        return_invalid_entry: Return an invalid entry from GetOffsets()
     """
     def __init__(self, section, etype, node):
         Entry.__init__(self, section, etype, node)
@@ -35,7 +35,7 @@ class Entry__testing(Entry):
         self.contents_size = len(self.data)
         return True
 
-    def GetPositions(self):
+    def GetOffsets(self):
         if self.return_invalid_entry :
             return {'invalid-entry': [1, 2]}
         return {}
tools/binman/etype/intel_descriptor.py +4 -4
index 0e7865521e..0a5151d466 100644
@@ -36,12 +36,12 @@ class Entry_intel_descriptor(Entry_blob):
         Entry_blob.__init__(self, section, etype, node)
         self._regions = []
 
-    def GetPositions(self):
-        pos = self.data.find(FD_SIGNATURE)
-        if pos == -1:
+    def GetOffsets(self):
+        offset = self.data.find(FD_SIGNATURE)
+        if offset == -1:
             self.Raise('Cannot find FD signature')
         flvalsig, flmap0, flmap1, flmap2 = struct.unpack('<LLLL',
-                                                    self.data[pos:pos + 16])
+                                                self.data[offset:offset + 16])
         frba = ((flmap0 >> 16) & 0xff) << 4
         for i in range(MAX_REGIONS):
             self._regions.append(Region(self.data, frba, i))
tools/binman/etype/section.py +7 -7
index 787257d3ec..5a0b0b8c70 100644
@@ -30,20 +30,20 @@ class Entry_section(Entry):
     def GetData(self):
         return self._section.GetData()
 
-    def GetPositions(self):
-        """Handle entries that want to set the position/size of other entries
+    def GetOffsets(self):
+        """Handle entries that want to set the offset/size of other entries
 
-        This calls each entry's GetPositions() method. If it returns a list
+        This calls each entry's GetOffsets() method. If it returns a list
         of entries to update, it updates them.
         """
-        self._section.GetEntryPositions()
+        self._section.GetEntryOffsets()
         return {}
 
-    def Pack(self, pos):
+    def Pack(self, offset):
         """Pack all entries into the section"""
         self._section.PackEntries()
         self.size = self._section.CheckSize()
-        return super(Entry_section, self).Pack(pos)
+        return super(Entry_section, self).Pack(offset)
 
     def WriteSymbols(self, section):
         """Write symbol values into binary files for access at run time"""
@@ -57,7 +57,7 @@ class Entry_section(Entry):
         self._section.ProcessEntryContents()
         super(Entry_section, self).ProcessContents()
 
-    def CheckPosition(self):
+    def CheckOffset(self):
         self._section.CheckEntries()
 
     def WriteMap(self, fd, indent):
tools/binman/etype/u_boot_dtb_with_ucode.py +2 -2
index 3808d6d278..55d3a38a64 100644
@@ -33,10 +33,10 @@ class Entry_u_boot_dtb_with_ucode(Entry_blob):
         # If the section does not need microcode, there is nothing to do
         ucode_dest_entry = self.section.FindEntryType(
             'u-boot-spl-with-ucode-ptr')
-        if not ucode_dest_entry or not ucode_dest_entry.target_pos:
+        if not ucode_dest_entry or not ucode_dest_entry.target_offset:
             ucode_dest_entry = self.section.FindEntryType(
                 'u-boot-with-ucode-ptr')
-        if not ucode_dest_entry or not ucode_dest_entry.target_pos:
+        if not ucode_dest_entry or not ucode_dest_entry.target_offset:
             return True
 
         # Remove the microcode
tools/binman/etype/u_boot_ucode.py +2 -2
index ea0c85cc5c..922a607cfe 100644
@@ -59,8 +59,8 @@ class Entry_u_boot_ucode(Entry_blob):
         ucode_dest_entry = self.section.FindEntryType('u-boot-with-ucode-ptr')
         ucode_dest_entry_spl = self.section.FindEntryType(
             'u-boot-spl-with-ucode-ptr')
-        if ((not ucode_dest_entry or not ucode_dest_entry.target_pos) and
-            (not ucode_dest_entry_spl or not ucode_dest_entry_spl.target_pos)):
+        if ((not ucode_dest_entry or not ucode_dest_entry.target_offset) and
+            (not ucode_dest_entry_spl or not ucode_dest_entry_spl.target_offset)):
             self.data = ''
             return True
 
tools/binman/etype/u_boot_with_ucode_ptr.py +18 -17
index 8b1e41152e..97e58a0bfc 100644
@@ -23,7 +23,7 @@ class Entry_u_boot_with_ucode_ptr(Entry_blob):
     def __init__(self, section, etype, node):
         Entry_blob.__init__(self, section, etype, node)
         self.elf_fname = 'u-boot'
-        self.target_pos = None
+        self.target_offset = None
 
     def GetDefaultFilename(self):
         return 'u-boot-nodtb.bin'
@@ -33,52 +33,53 @@ class Entry_u_boot_with_ucode_ptr(Entry_blob):
         fname = tools.GetInputFilename(self.elf_fname)
         sym = elf.GetSymbolAddress(fname, '_dt_ucode_base_size')
         if sym:
-           self.target_pos = sym
+           self.target_offset = sym
         elif not fdt_util.GetBool(self._node, 'optional-ucode'):
             self.Raise('Cannot locate _dt_ucode_base_size symbol in u-boot')
         return True
 
     def ProcessContents(self):
         # If the image does not need microcode, there is nothing to do
-        if not self.target_pos:
+        if not self.target_offset:
             return
 
-        # Get the position of the microcode
+        # Get the offset of the microcode
         ucode_entry = self.section.FindEntryType('u-boot-ucode')
         if not ucode_entry:
             self.Raise('Cannot find microcode region u-boot-ucode')
 
         # Check the target pos is in the section. If it is not, then U-Boot is
-        # being linked incorrectly, or is being placed at the wrong position
+        # being linked incorrectly, or is being placed at the wrong offset
         # in the section.
         #
         # The section must be set up so that U-Boot is placed at the
         # flash address to which it is linked. For example, if
         # CONFIG_SYS_TEXT_BASE is 0xfff00000, and the ROM is 8MB, then
-        # the U-Boot region must start at position 7MB in the section. In this
-        # case the ROM starts at 0xff800000, so the position of the first
+        # the U-Boot region must start at offset 7MB in the section. In this
+        # case the ROM starts@0xff800000, so the offset of the first
         # entry in the section corresponds to that.
-        if (self.target_pos < self.pos or
-                self.target_pos >= self.pos + self.size):
+        if (self.target_offset < self.offset or
+                self.target_offset >= self.offset + self.size):
             self.Raise('Microcode pointer _dt_ucode_base_size at %08x is '
                 'outside the section ranging from %08x to %08x' %
-                (self.target_pos, self.pos, self.pos + self.size))
+                (self.target_offset, self.offset, self.offset + self.size))
 
         # Get the microcode, either from u-boot-ucode or u-boot-dtb-with-ucode.
         # If we have left the microcode in the device tree, then it will be
         # in the former. If we extracted the microcode from the device tree
         # and collated it in one place, it will be in the latter.
         if ucode_entry.size:
-            pos, size = ucode_entry.pos, ucode_entry.size
+            offset, size = ucode_entry.offset, ucode_entry.size
         else:
             dtb_entry = self.section.FindEntryType('u-boot-dtb-with-ucode')
             if not dtb_entry or not dtb_entry.ready:
                 self.Raise('Cannot find microcode region u-boot-dtb-with-ucode')
-            pos = dtb_entry.pos + dtb_entry.ucode_offset
+            offset = dtb_entry.offset + dtb_entry.ucode_offset
             size = dtb_entry.ucode_size
 
-        # Write the microcode position and size into the entry
-        pos_and_size = struct.pack('<2L', pos, size)
-        self.target_pos -= self.pos
-        self.ProcessContentsUpdate(self.data[:self.target_pos] + pos_and_size +
-                                   self.data[self.target_pos + 8:])
+        # Write the microcode offset and size into the entry
+        offset_and_size = struct.pack('<2L', offset, size)
+        self.target_offset -= self.offset
+        self.ProcessContentsUpdate(self.data[:self.target_offset] +
+                                   offset_and_size +
+                                   self.data[self.target_offset + 8:])
tools/binman/ftest.py +42 -43

264 lines not on this page · raw message

tools/binman/image.py +6 -6
index 94028f19a5..ed8261a652 100644
@@ -57,7 +57,7 @@ class Image:
     def AddMissingProperties(self):
         """Add properties that are not present in the device tree
 
-        When binman has completed packing the entries the position and size of
+        When binman has completed packing the entries the offset and size of
         each entry are known. But before this the device tree may not specify
         these. Add any missing properties, with a dummy value, so that the
         size of the entry is correct. That way we can insert the correct values
@@ -73,13 +73,13 @@ class Image:
         """
         self._section.GetEntryContents()
 
-    def GetEntryPositions(self):
-        """Handle entries that want to set the position/size of other entries
+    def GetEntryOffsets(self):
+        """Handle entries that want to set the offset/size of other entries
 
-        This calls each entry's GetPositions() method. If it returns a list
+        This calls each entry's GetOffsets() method. If it returns a list
         of entries to update, it updates them.
         """
-        self._section.GetEntryPositions()
+        self._section.GetEntryOffsets()
 
     def PackEntries(self):
         """Pack all entries into the image"""
@@ -121,5 +121,5 @@ class Image:
         filename = '%s.map' % self._name
         fname = tools.GetOutputFilename(filename)
         with open(fname, 'w') as fd:
-            print('%8s  %8s  %s' % ('Position', 'Size', 'Name'), file=fd)
+            print('%8s  %8s  %s' % ('Offset', 'Size', 'Name'), file=fd)
             self._section.WriteMap(fd, 0)
tools/binman/test/08_pack.dts +1 -1
index dc63d99dcb..a88785d835 100644
@@ -24,7 +24,7 @@
 
 		u-boot-fixed {
 			type = "u-boot";
-			pos = <61>;
+			offset = <61>;
 		};
 	};
 };
tools/binman/test/12_pack_inv_align.dts +1 -1
index 1d9d80a65c..d8dd600edb 100644
@@ -6,7 +6,7 @@
 
 	binman {
 		u-boot {
-			pos = <5>;
+			offset = <5>;
 			align = <4>;
 		};
 	};
tools/binman/test/14_pack_overlap.dts +1 -1
index 611cfd9730..3895cba3bd 100644
@@ -10,7 +10,7 @@
 
 		u-boot-align {
 			type = "u-boot";
-			pos = <3>;
+			offset = <3>;
 		};
 	};
 };
tools/binman/test/21_image_pad.dts +1 -1
index bf39dc1b6f..c6516689d9 100644
@@ -10,7 +10,7 @@
 		};
 
 		u-boot {
-			pos = <20>;
+			offset = <20>;
 		};
 	};
 };
tools/binman/test/24_sorted.dts +3 -3
index 43a7831341..d35d39f077 100644
@@ -5,13 +5,13 @@
 	#size-cells = <1>;
 
 	binman {
-		sort-by-pos;
+		sort-by-offset;
 		u-boot {
-			pos = <22>;
+			offset = <22>;
 		};
 
 		u-boot-spl {
-			pos = <1>;
+			offset = <1>;
 		};
 	};
 };
tools/binman/test/25_pack_zero_size.dts +1 -1
index 7d2baad3c6..e863c44e3f 100644
@@ -9,7 +9,7 @@
 		};
 
 		u-boot-spl {
-			pos = <0>;
+			offset = <0>;
 		};
 	};
 };
tools/binman/test/27_pack_4gb_no_size.dts +3 -3
index e0b6519e75..371cca10d5 100644
@@ -5,14 +5,14 @@
 	#size-cells = <1>;
 
 	binman {
-		sort-by-pos;
+		sort-by-offset;
 		end-at-4gb;
 		u-boot {
-			pos = <0xfffffff0>;
+			offset = <0xfffffff0>;
 		};
 
 		u-boot-spl {
-			pos = <0xfffffff7>;
+			offset = <0xfffffff7>;
 		};
 	};
 };
tools/binman/test/28_pack_4gb_outside.dts +3 -3
index 18d6bb5b8a..2216abfb70 100644
@@ -5,15 +5,15 @@
 	#size-cells = <1>;
 
 	binman {
-		sort-by-pos;
+		sort-by-offset;
 		end-at-4gb;
 		size = <32>;
 		u-boot {
-			pos = <0>;
+			offset = <0>;
 		};
 
 		u-boot-spl {
-			pos = <0xffffffeb>;
+			offset = <0xffffffeb>;
 		};
 	};
 };
tools/binman/test/29_x86-rom.dts +3 -3
index d49078e19e..d5c69f9d4a 100644
@@ -5,15 +5,15 @@
 	#size-cells = <1>;
 
 	binman {
-		sort-by-pos;
+		sort-by-offset;
 		end-at-4gb;
 		size = <32>;
 		u-boot {
-			pos = <0xffffffe0>;
+			offset = <0xffffffe0>;
 		};
 
 		u-boot-spl {
-			pos = <0xffffffeb>;
+			offset = <0xffffffeb>;
 		};
 	};
 };
tools/binman/test/30_x86-rom-me-no-desc.dts +2 -2
index 68d3ce09ec..796cb87afc 100644
@@ -5,12 +5,12 @@
 	#size-cells = <1>;
 
 	binman {
-		sort-by-pos;
+		sort-by-offset;
 		end-at-4gb;
 		size = <16>;
 		intel-me {
 			filename = "me.bin";
-			pos-unset;
+			offset-unset;
 		};
 	};
 };
tools/binman/test/31_x86-rom-me.dts +2 -2
index ee3dac875a..b8b0a5a74b 100644
@@ -5,7 +5,7 @@
 	#size-cells = <1>;
 
 	binman {
-		sort-by-pos;
+		sort-by-offset;
 		end-at-4gb;
 		size = <0x800000>;
 		intel-descriptor {
@@ -14,7 +14,7 @@
 
 		intel-me {
 			filename = "me.bin";
-			pos-unset;
+			offset-unset;
 		};
 	};
 };
tools/binman/test/34_x86_ucode.dts +1 -1
index 64a6c2c3d5..40725731cd 100644
@@ -5,7 +5,7 @@
 	#size-cells = <1>;
 
 	binman {
-		sort-by-pos;
+		sort-by-offset;
 		end-at-4gb;
 		size = <0x200>;
 		u-boot-with-ucode-ptr {
tools/binman/test/35_x86_single_ucode.dts +1 -1
index 973e97f864..2b1f086a41 100644
@@ -5,7 +5,7 @@
 	#size-cells = <1>;
 
 	binman {
-		sort-by-pos;
+		sort-by-offset;
 		end-at-4gb;
 		size = <0x200>;
 		u-boot-with-ucode-ptr {
tools/binman/test/37_x86_no_ucode.dts +1 -1
index 9e12156ee2..6da49c3da6 100644
@@ -5,7 +5,7 @@
 	#size-cells = <1>;
 
 	binman {
-		sort-by-pos;
+		sort-by-offset;
 		end-at-4gb;
 		size = <0x200>;
 		u-boot-with-ucode-ptr {
tools/binman/test/38_x86_ucode_missing_node.dts +1 -1
index d6cf0d844e..720677c9c1 100644
@@ -5,7 +5,7 @@
 	#size-cells = <1>;
 
 	binman {
-		sort-by-pos;
+		sort-by-offset;
 		end-at-4gb;
 		size = <0x200>;
 		u-boot-with-ucode-ptr {
tools/binman/test/39_x86_ucode_missing_node2.dts +1 -1
index b7e26c5ae4..10ac086d54 100644
@@ -5,7 +5,7 @@
 	#size-cells = <1>;
 
 	binman {
-		sort-by-pos;
+		sort-by-offset;
 		end-at-4gb;
 		size = <0x200>;
 		u-boot-with-ucode-ptr {
tools/binman/test/40_x86_ucode_not_in_image.dts +1 -1
index 67d17d392f..609725824a 100644
@@ -5,7 +5,7 @@
 	#size-cells = <1>;
 
 	binman {
-		sort-by-pos;
+		sort-by-offset;
 		size = <0x200>;
 		u-boot-with-ucode-ptr {
 		};
tools/binman/test/44_x86_optional_ucode.dts +1 -1
index abe1322798..24a7040d31 100644
@@ -5,7 +5,7 @@
 	#size-cells = <1>;
 
 	binman {
-		sort-by-pos;
+		sort-by-offset;
 		end-at-4gb;
 		size = <0x200>;
 		u-boot-with-ucode-ptr {
tools/binman/test/45_prop_test.dts +2 -2
index d22e460d29..064de2b316 100644
@@ -5,12 +5,12 @@
 	#size-cells = <1>;
 
 	binman {
-		sort-by-pos;
+		sort-by-offset;
 		end-at-4gb;
 		size = <16>;
 		intel-me {
 			filename = "me.bin";
-			pos-unset;
+			offset-unset;
 			intval = <3>;
 			intarray = <5 6>;
 			byteval = [08];
tools/binman/test/49_x86_ucode_spl.dts +1 -1
index 67db93ad50..350d2c4730 100644
@@ -5,7 +5,7 @@
 	#size-cells = <1>;
 
 	binman {
-		sort-by-pos;
+		sort-by-offset;
 		end-at-4gb;
 		size = <0x200>;
 		u-boot-spl-with-ucode-ptr {
tools/binman/test/53_symbols.dts +1 -1
index 980b066eb2..9f135676cb 100644
@@ -10,7 +10,7 @@
 		};
 
 		u-boot {
-			pos = <20>;
+			offset = <20>;
 		};
 
 		u-boot-spl2 {
tools/binman/test/58_x86_ucode_spl_needs_retry.dts +1 -1
index e2cb80cf6e..a04adaaf7b 100644
@@ -7,7 +7,7 @@
 	#size-cells = <1>;
 
 	binman {
-		sort-by-pos;
+		sort-by-offset;
 		end-at-4gb;
 		size = <0x200>;
 		u-boot-spl-with-ucode-ptr {
tools/binman/test/u_boot_binman_syms binary +0 -0
index 2e02dc0ca9e2651bc12ac6d61d95dfa5ccee7a68..f2dcb887ed84e4799ae9eca1d2d39585635fb4c6 100755
GIT binary patch

z1 at ZZ5X~n4}4Dm^sdAW&s at ul%e`S~UBiFuXyq>Br3kfkRx3R_H$7r4r3GTBs6nd!3N k<S0Qk-V6Z-h66w=*?^dJa<8DYgoYpk!)hQ81{k3X02qTyEC2ui

delta 311
zcmdm at wo3_0@DhCjY{wM{giSY5Bn9IT;WmHowz;j+V6#vLY6V00e5F-D+P_vq|&^S zQUwz|3q2EEqf#)>u+Gp#&%i{_SQ8>XI6u at M(xQfg_N1%1ty;pQsX@!$iQ#XdW8~ zPi7RBW}P6!z_4=iMIqsdGh;W2$<9(+s4B1 at xK^QKm~|dfLM@$iNOd-fdB&|gC&r! z0mK|o7jD0K_o$ML@O*5QBgKP=7O!2AKx}ApSHUjo>p*Ru|Nq+%L$+RghoI5MNx9 XSX46ER#1u=$ekQ3C<&%#3t9jG`lCCI

tools/binman/test/u_boot_binman_syms.c +3 -3
index d8371610a5..cbb2f3f7b1 100644
@@ -8,6 +8,6 @@
 #define CONFIG_BINMAN
 #include <binman_sym.h>
 
-binman_sym_declare(unsigned long, u_boot_spl, pos);
-binman_sym_declare(unsigned long long, u_boot_spl2, pos);
-binman_sym_declare(unsigned long, u_boot_any, pos);
+binman_sym_declare(unsigned long, u_boot_spl, offset);
+binman_sym_declare(unsigned long long, u_boot_spl2, offset);
+binman_sym_declare(unsigned long, u_boot_any, offset);
Signature · 1 line
2.18.0.203.gfac676dfb9-goog
#3 lore raw

PATCH 3/29 binman: Add comments to elf_test

In reply to Simon Glass

The purpose of some of the tests is not obvious from the function names. Add a few comments to help with understanding.

---

 tools/binman/elf_test.py | 33 +++++++++++++++++++++++++++++++++
 1 file changed, 33 insertions(+)
tools/binman/elf_test.py +33 -0
index 9c8f1feca8..c16f71401d 100644
@@ -15,6 +15,10 @@ binman_dir = os.path.dirname(os.path.realpath(sys.argv[0]))
 
 
 class FakeEntry:
+    """A fake Entry object, usedfor testing
+
+    This supports an entry with a given size.
+    """
     def __init__(self, contents_size):
         self.contents_size = contents_size
         self.data = 'a' * contents_size
@@ -22,7 +26,14 @@ class FakeEntry:
     def GetPath(self):
         return 'entry_path'
 
+
 class FakeSection:
+    """A fake Section object, used for testing
+
+    This has the minimum feature set needed to support testing elf functions.
+    A LookupSymbol() function is provided which returns a fake value for amu
+    symbol requested.
+    """
     def __init__(self, sym_value=1):
         self.sym_value = sym_value
 
@@ -30,15 +41,19 @@ class FakeSection:
         return 'section_path'
 
     def LookupSymbol(self, name, weak, msg):
+        """Fake implementation which returns the same value for all symbols"""
         return self.sym_value
 
+
 class TestElf(unittest.TestCase):
     def testAllSymbols(self):
+        """Test that we can obtain a symbol from the ELF file"""
         fname = os.path.join(binman_dir, 'test', 'u_boot_ucode_ptr')
         syms = elf.GetSymbols(fname, [])
         self.assertIn('.ucode', syms)
 
     def testRegexSymbols(self):
+        """Test that we can obtain from the ELF file by regular expression"""
         fname = os.path.join(binman_dir, 'test', 'u_boot_ucode_ptr')
         syms = elf.GetSymbols(fname, ['ucode'])
         self.assertIn('.ucode', syms)
@@ -48,6 +63,7 @@ class TestElf(unittest.TestCase):
         self.assertIn('.ucode', syms)
 
     def testMissingFile(self):
+        """Test that a missing file is detected"""
         entry = FakeEntry(10)
         section = FakeSection()
         with self.assertRaises(ValueError) as e:
@@ -56,6 +72,7 @@ class TestElf(unittest.TestCase):
                       str(e.exception))
 
     def testOutsideFile(self):
+        """Test a symbol which extends outside the entry area is detected"""
         entry = FakeEntry(10)
         section = FakeSection()
         elf_fname = os.path.join(binman_dir, 'test', 'u_boot_binman_syms')
@@ -65,6 +82,11 @@ class TestElf(unittest.TestCase):
                       'is a', str(e.exception))
 
     def testMissingImageStart(self):
+        """Test that we detect a missing __image_copy_start symbol
+
+        This is needed to mark the start of the image. Without it we cannot
+        locate the offset of a binman symbol within the image.
+        """
         entry = FakeEntry(10)
         section = FakeSection()
         elf_fname = os.path.join(binman_dir, 'test', 'u_boot_binman_syms_bad')
@@ -72,6 +94,11 @@ class TestElf(unittest.TestCase):
                          None)
 
     def testBadSymbolSize(self):
+        """Test that an attempt to use an 8-bit symbol are detected
+
+        Only 32 and 64 bits are supported, since we need to store an offset
+        into the image.
+        """
         entry = FakeEntry(10)
         section = FakeSection()
         elf_fname = os.path.join(binman_dir, 'test', 'u_boot_binman_syms_size')
@@ -81,6 +108,11 @@ class TestElf(unittest.TestCase):
                       str(e.exception))
 
     def testNoValue(self):
+        """Test the case where we have no value for the symbol
+
+        This should produce -1 values for all thress symbols, taking up the
+        first 16 bytes of the image.
+        """
         entry = FakeEntry(20)
         section = FakeSection(sym_value=None)
         elf_fname = os.path.join(binman_dir, 'test', 'u_boot_binman_syms')
@@ -88,6 +120,7 @@ class TestElf(unittest.TestCase):
         self.assertEqual(chr(255) * 16 + 'a' * 4, entry.data)
 
     def testDebug(self):
+        """Check that enabling debug in the elf module produced debug output"""
         elf.debug = True
         entry = FakeEntry(20)
         section = FakeSection()
Signature · 1 line
2.18.0.203.gfac676dfb9-goog
#4 lore raw

PATCH 4/29 binman: Tidy up some comments in the tests

In reply to Simon Glass

A few lines are commented out and can be removed. Also fix return-value docs for _DoReadFile() and _DoReadFileDtb().

---

 tools/binman/ftest.py | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)
tools/binman/ftest.py +4 -2
index 1efedc2ec3..91b59f84ea 100644
@@ -212,6 +212,7 @@ class TestFunctional(unittest.TestCase):
                 Resulting image contents
                 Device tree contents
                 Map data showing contents of image (or None if none)
+                Output device tree binary filename ('u-boot.dtb' path)
         """
         dtb_data = None
         # Use the compiled test file as the u-boot-dtb input
@@ -249,6 +250,9 @@ class TestFunctional(unittest.TestCase):
                 the u-boot-dtb entry. Normally this is not needed and the
                 test contents (the U_BOOT_DTB_DATA string) can be used.
                 But in some test we need the real contents.
+
+        Returns:
+            Resulting image contents
         """
         return self._DoReadFileDtb(fname, use_real_dtb)[0]
 
@@ -312,7 +316,6 @@ class TestFunctional(unittest.TestCase):
         def AddNode(node, path):
             if node.name != '/':
                 path += '/' + node.name
-            #print 'path', path
             for subnode in node.subnodes:
                 for prop in subnode.props.values():
                     if prop.name in node_names:
@@ -408,7 +411,6 @@ class TestFunctional(unittest.TestCase):
         with self.assertRaises(Exception) as e:
             result = self._RunBinman('-d',
                                      self.TestFile('04_invalid_entry.dts'))
-        #print e.exception
         self.assertIn("Unknown entry type 'not-a-valid-type' in node "
                 "'/binman/not-a-valid-type'", str(e.exception))
 
Signature · 1 line
2.18.0.203.gfac676dfb9-goog
#5 lore raw

PATCH 5/29 binman: Enhance the map and fdt-update output

In reply to Simon Glass

At present the .map file produced for each image does not include the overall image size. This is useful information.

Update the code to generate it in the .map file as well as the updated FDT. Also fix a few comments while we are here.

---

 tools/binman/README               |  9 +++++----
 tools/binman/bsection.py          | 32 +++++++++++++++++++++++++++++--
 tools/binman/entry.py             | 13 ++++++++-----
 tools/binman/etype/section.py     |  6 +++---
 tools/binman/ftest.py             | 24 ++++++++++++++---------
 tools/binman/test/55_sections.dts |  4 ++++
 6 files changed, 65 insertions(+), 23 deletions(-)
tools/binman/README +5 -4
index 5ff20f15c6..4b13776ffa 100644
@@ -584,10 +584,11 @@ The -m option causes binman to output a .map file for each image that it
 generates. This shows the offset and size of each entry. For example:
 
       Offset      Size  Name
-    00000000  00000010  section at 0
-     00000000  00000004  u-boot
-    00000010  00000010  section at 1
-     00000000  00000004  u-boot
+    00000000  00000028  main-section
+     00000000  00000010  section at 0
+      00000000  00000004  u-boot
+     00000010  00000010  section at 1
+      00000000  00000004  u-boot
 
 This shows a hierarchical image with two sections, each with a single entry. The
 offsets of the sections are absolute hex byte offsets within the image. The
tools/binman/bsection.py +30 -2
index d78a25e83d..1604b9915e 100644
@@ -50,6 +50,7 @@ class Section(object):
         import entry
         from entry import Entry
 
+        self._name = name
         self._node = node
         self._offset = 0
         self._size = None
@@ -90,11 +91,20 @@ class Section(object):
             entry.SetPrefix(self._name_prefix)
             self._entries[node.name] = entry
 
+    def SetOffset(self, offset):
+        self._offset = offset
+
     def AddMissingProperties(self):
+        """Add new properties to the device tree as needed for this entry"""
+        for prop in ['offset', 'size']:
+            if not prop in self._node.props:
+                self._node.AddZeroProp(prop)
         for entry in self._entries.values():
             entry.AddMissingProperties()
 
     def SetCalculatedProperties(self):
+        self._node.SetInt('offset', self._offset)
+        self._node.SetInt('size', self._size)
         for entry in self._entries.values():
             entry.SetCalculatedProperties()
 
@@ -269,7 +279,7 @@ class Section(object):
         fd.write(self.GetData())
 
     def GetData(self):
-        """Write the section to a file"""
+        """Get the contents of the section"""
         section_data = chr(self._pad_byte) * self._size
 
         for entry in self._entries.values():
@@ -335,13 +345,31 @@ class Section(object):
             raise ValueError("%s: No such property '%s'" % (msg, prop_name))
 
     def GetEntries(self):
+        """Get the number of entries in a section
+
+        Returns:
+            Number of entries in a section
+        """
         return self._entries
 
+    def GetSize(self):
+        """Get the size of a section in bytes
+
+        This is only meaningful if the section has a pre-defined size, or the
+        entries within it have been packed, so that the size has been
+        calculated.
+
+        Returns:
+            Entry size in bytes
+        """
+        return self._size
+
     def WriteMap(self, fd, indent):
         """Write a map of the section to a .map file
 
         Args:
             fd: File to write the map to
         """
+        Entry.WriteMapLine(fd, indent, self._name, self._offset, self._size)
         for entry in self._entries.values():
-            entry.WriteMap(fd, indent)
+            entry.WriteMap(fd, indent + 1)
tools/binman/entry.py +8 -5
index c9529d8322..cb693c9382 100644
@@ -36,7 +36,7 @@ class Entry(object):
     Entry.
 
     Attributes:
-        section: The section containing this entry
+        section: Section object containing this entry
         node: The node that created this entry
         offset: Offset of entry within the section, None if not known yet (in
             which case it will be calculated by Pack())
@@ -72,7 +72,7 @@ class Entry(object):
         """Create a new entry for a node.
 
         Args:
-            section:  Image object containing this node
+            section:  Section object containing this node
             node:   Node object containing information about the entry to create
             etype:  Entry type to use, or None to work it out (used for tests)
 
@@ -133,7 +133,7 @@ class Entry(object):
 
     def AddMissingProperties(self):
         """Add new properties to the device tree as needed for this entry"""
-        for prop in ['offset', 'size', 'global-pos']:
+        for prop in ['offset', 'size']:
             if not prop in self._node.props:
                 self._node.AddZeroProp(prop)
 
@@ -285,6 +285,10 @@ class Entry(object):
         """
         pass
 
+    @staticmethod
+    def WriteMapLine(fd, indent, name, offset, size):
+        print('%s%08x  %08x  %s' % (' ' * indent, offset, size, name), file=fd)
+
     def WriteMap(self, fd, indent):
         """Write a map of the entry to a .map file
 
@@ -292,5 +296,4 @@ class Entry(object):
             fd: File to write the map to
             indent: Curent indent level of map (0=none, 1=one level, etc.)
         """
-        print('%s%08x  %08x  %s' % (' ' * indent, self.offset, self.size,
-                                    self.name), file=fd)
+        self.WriteMapLine(fd, indent, self.name, self.offset, self.size)
tools/binman/etype/section.py +3 -3
index 5a0b0b8c70..1d27301ae9 100644
@@ -42,7 +42,8 @@ class Entry_section(Entry):
     def Pack(self, offset):
         """Pack all entries into the section"""
         self._section.PackEntries()
-        self.size = self._section.CheckSize()
+        self._section.SetOffset(offset)
+        self.size = self._section.GetSize()
         return super(Entry_section, self).Pack(offset)
 
     def WriteSymbols(self, section):
@@ -66,5 +67,4 @@ class Entry_section(Entry):
         Args:
             fd: File to write the map to
         """
-        super(Entry_section, self).WriteMap(fd, indent)
-        self._section.WriteMap(fd, indent + 1)
+        self._section.WriteMap(fd, indent)
tools/binman/ftest.py +15 -9
index 91b59f84ea..94e48f3ab3 100644
@@ -1004,27 +1004,32 @@ class TestFunctional(unittest.TestCase):
     def testSections(self):
         """Basic test of sections"""
         data = self._DoReadFile('55_sections.dts')
-        expected = U_BOOT_DATA + '!' * 12 + U_BOOT_DATA + 'a' * 12 + '&' * 8
+        expected = (U_BOOT_DATA + '!' * 12 + U_BOOT_DATA + 'a' * 12 +
+                    U_BOOT_DATA + '&' * 4)
         self.assertEqual(expected, data)
 
     def testMap(self):
         """Tests outputting a map of the images"""
         _, _, map_data, _ = self._DoReadFileDtb('55_sections.dts', map=True)
         self.assertEqual('''  Offset      Size  Name
-00000000  00000010  section at 0
- 00000000  00000004  u-boot
-00000010  00000010  section at 1
- 00000000  00000004  u-boot
+00000000  00000028  main-section
+ 00000000  00000010  section at 0
+  00000000  00000004  u-boot
+ 00000010  00000010  section at 1
+  00000000  00000004  u-boot
+ 00000020  00000004  section at 2
+  00000000  00000004  u-boot
 ''', map_data)
 
     def testNamePrefix(self):
         """Tests that name prefixes are used"""
         _, _, map_data, _ = self._DoReadFileDtb('56_name_prefix.dts', map=True)
         self.assertEqual('''  Offset      Size  Name
-00000000  00000010  section at 0
- 00000000  00000004  ro-u-boot
-00000010  00000010  section at 1
- 00000000  00000004  rw-u-boot
+00000000  00000028  main-section
+ 00000000  00000010  section at 0
+  00000000  00000004  ro-u-boot
+ 00000010  00000010  section at 1
+  00000000  00000004  rw-u-boot
 ''', map_data)
 
     def testUnknownContents(self):
@@ -1051,6 +1056,7 @@ class TestFunctional(unittest.TestCase):
             with open(out_dtb_fname) as inf:
                 outf.write(inf.read())
         self.assertEqual({
+            'offset': 0,
             '_testing:offset': 32,
             '_testing:size': 1,
             'section at 0/u-boot:offset': 0,
tools/binman/test/55_sections.dts +4 -0
index 2ada395b03..6b306aeda4 100644
@@ -24,5 +24,9 @@
 			u-boot {
 			};
 		};
+		section at 2 {
+			u-boot {
+			};
+		};
 	};
 };
Signature · 1 line
2.18.0.203.gfac676dfb9-goog
#6 lore raw

PATCH 6/29 binman: Update the device-tree file on exit

In reply to Simon Glass

Binman can make additions to the device tree which are useful to U-Boot when it runs (e.g. the position of each entry in the image). Write the changes back so that they are easily accessible.

---

 tools/binman/control.py | 4 ++++
 1 file changed, 4 insertions(+)
tools/binman/control.py +4 -0
index 17c6d7a2d2..97652334e0 100644
@@ -168,8 +168,12 @@ def Binman(options, args):
                 image.BuildImage()
                 if options.map:
                     image.WriteMap()
+            # Write the updated FDT to our output file, and also back to the
+            # input file, so it is visible after binman exits.
             with open(fname, 'wb') as outfd:
                 outfd.write(dtb.GetContents())
+            with open(dtb_fname, 'wb') as outfd:
+                outfd.write(dtb.GetContents())
         finally:
             tools.FinaliseOutputDir()
     finally:
Signature · 1 line
2.18.0.203.gfac676dfb9-goog
#7 lore raw

PATCH 6/29 binman: Update the device-tree file on exit

Hi,

Quoted 28 lines · Simon Glass

Binman can make additions to the device tree which are useful to U-Boot when it runs (e.g. the position of each entry in the image). Write the changes back so that they are easily accessible.

---

 tools/binman/control.py | 4 ++++
 1 file changed, 4 insertions(+)
tools/binman/control.py +4 -1
index 17c6d7a2d2..97652334e0 100644
@@ -168,8 +168,12 @@ def Binman(options, args):
                 image.BuildImage()
                 if options.map:
                     image.WriteMap()
+            # Write the updated FDT to our output file, and also back to the
+            # input file, so it is visible after binman exits.
             with open(fname, 'wb') as outfd:
                 outfd.write(dtb.GetContents())
+            with open(dtb_fname, 'wb') as outfd:
+                outfd.write(dtb.GetContents())
         finally:
             tools.FinaliseOutputDir()
     finally:
--
Quoted 2 lines

2.18.0.203.gfac676dfb9-goog

Actually I think this patch is a bad idea since it can cause race conditions. U-Boot's Makefile builds the .dtb, someone changes the source, then binman updates the .dtb, causing the Makefile to think that it does not need updating next time. I'll drop this patch.

Regards,
Simon

#8 lore raw

PATCH 7/29 binman: Add a new 'image-pos' property

In reply to Simon Glass

At present each entry has an offset within its parent section. This is useful for figuring out how entries relate to one another. However it is sometimes necessary to locate an entry within an image, regardless of which sections it is nested inside.

Add a new 'image-pos' property to provide this information. Also add some documentation for the -u option binman provides, which updates the device tree with final entry information.

---

 tools/binman/README           | 22 ++++++++++++++++++++--
 tools/binman/bsection.py      |  8 +++++++-
 tools/binman/control.py       |  1 +
 tools/binman/entry.py         | 12 +++++++++++-
 tools/binman/etype/section.py |  4 ++++
 tools/binman/ftest.py         |  9 ++++++++-
 tools/binman/image.py         |  3 +++
 7 files changed, 54 insertions(+), 5 deletions(-)
tools/binman/README +20 -2
index 4b13776ffa..df88819a1c 100644
@@ -324,6 +324,12 @@ offset-unset:
 	property is present, binman will give an error if another entry does
 	not set the offset (with the GetOffsets() method).
 
+image-pos:
+	This cannot be set on entry (or at least it is ignored if it is), but
+	with the -u option, binman will set it to the absolute image position
+	for each entry. This makes it easy to find out exactly where the entry
+	ended up in the image, regardless of parent sections, etc.
+
 
 The attributes supported for images are described below. Several are similar
 to those for entries.
@@ -550,8 +556,8 @@ the 'warning' line in scripts/Makefile.lib to see what it has found:
    # u_boot_dtsi_options_debug = $(u_boot_dtsi_options_raw)
 
 
-Access to binman entry offsets at run time
-------------------------------------------
+Access to binman entry offsets at run time (symbols)
+----------------------------------------------------
 
 Binman assembles images and determines where each entry is placed in the image.
 This information may be useful to U-Boot at run time. For example, in SPL it
@@ -577,6 +583,18 @@ At present this feature is only supported in SPL. In principle it is possible
 to fill in such symbols in U-Boot proper, as well.
 
 
+Access to binman entry offsets at run time (fdt)
+------------------------------------------------
+
+Binman can update the U-Boot FDT to include the final position and size of
+each entry in the images it processes. The option to enable this is -u and it
+causes binman to make sure that the 'offset', 'image-pos' and 'size' properties
+are set correctly for every entry. Since it is not necessary to specify these in
+the image definition, binman calculates the final values and writes these to
+the device tree. These can be used by U-Boot at run-time to find the location
+of each entry.
+
+
 Map files
 ---------
 
tools/binman/bsection.py +7 -1
index 1604b9915e..47fe37ccb9 100644
@@ -96,7 +96,7 @@ class Section(object):
 
     def AddMissingProperties(self):
         """Add new properties to the device tree as needed for this entry"""
-        for prop in ['offset', 'size']:
+        for prop in ['offset', 'size', 'image-pos']:
             if not prop in self._node.props:
                 self._node.AddZeroProp(prop)
         for entry in self._entries.values():
@@ -105,6 +105,7 @@ class Section(object):
     def SetCalculatedProperties(self):
         self._node.SetInt('offset', self._offset)
         self._node.SetInt('size', self._size)
+        self._node.SetInt('image-pos', self._image_pos)
         for entry in self._entries.values():
             entry.SetCalculatedProperties()
 
@@ -260,6 +261,11 @@ class Section(object):
             offset = entry.offset + entry.size
             prev_name = entry.GetPath()
 
+    def SetImagePos(self, image_pos):
+        self._image_pos = image_pos
+        for entry in self._entries.values():
+            entry.SetImagePos(image_pos)
+
     def ProcessEntryContents(self):
         """Call the ProcessContents() method for each entry
 
tools/binman/control.py +1 -0
index 97652334e0..43d192c9a7 100644
@@ -161,6 +161,7 @@ def Binman(options, args):
                 image.PackEntries()
                 image.CheckSize()
                 image.CheckEntries()
+                image.SetImagePos()
                 if options.update_fdt:
                     image.SetCalculatedProperties()
                 image.ProcessEntryContents()
tools/binman/entry.py +11 -1
index cb693c9382..8004918eb5 100644
@@ -64,6 +64,7 @@ class Entry(object):
         self.pad_before = 0
         self.pad_after = 0
         self.offset_unset = False
+        self.image_pos = None
         if read_node:
             self.ReadNode()
 
@@ -133,7 +134,7 @@ class Entry(object):
 
     def AddMissingProperties(self):
         """Add new properties to the device tree as needed for this entry"""
-        for prop in ['offset', 'size']:
+        for prop in ['offset', 'size', 'image-pos']:
             if not prop in self._node.props:
                 self._node.AddZeroProp(prop)
 
@@ -141,6 +142,7 @@ class Entry(object):
         """Set the value of device-tree properties calculated by binman"""
         self._node.SetInt('offset', self.offset)
         self._node.SetInt('size', self.size)
+        self._node.SetInt('image-pos', self.image_pos)
 
     def ProcessFdt(self, fdt):
         return True
@@ -265,6 +267,14 @@ class Entry(object):
         self.offset = pos
         self.size = size
 
+    def SetImagePos(self, image_pos):
+        """Set the position in the image
+
+        Args:
+            image_pos: Position of this entry in the image
+        """
+        self.image_pos = image_pos + self.offset
+
     def ProcessContents(self):
         pass
 
tools/binman/etype/section.py +4 -0
index 1d27301ae9..b90b80e4ce 100644
@@ -46,6 +46,10 @@ class Entry_section(Entry):
         self.size = self._section.GetSize()
         return super(Entry_section, self).Pack(offset)
 
+    def SetImagePos(self, image_pos):
+        Entry.SetImagePos(self, image_pos)
+        self._section.SetImagePos(image_pos + self.offset)
+
     def WriteSymbols(self, section):
         """Write symbol values into binary files for access at run time"""
         self._section.WriteSymbols()
tools/binman/ftest.py +8 -1
index 94e48f3ab3..94a50aac16 100644
@@ -1051,23 +1051,30 @@ class TestFunctional(unittest.TestCase):
         """Test that we can update the device tree with offset/size info"""
         _, _, _, out_dtb_fname = self._DoReadFileDtb('60_fdt_update.dts',
                                                      update_dtb=True)
-        props = self._GetPropTree(out_dtb_fname, ['offset', 'size'])
+        props = self._GetPropTree(out_dtb_fname, ['offset', 'size',
+                                                  'image-pos'])
         with open('/tmp/x.dtb', 'wb') as outf:
             with open(out_dtb_fname) as inf:
                 outf.write(inf.read())
         self.assertEqual({
+            'image-pos': 0,
             'offset': 0,
             '_testing:offset': 32,
             '_testing:size': 1,
+            '_testing:image-pos': 32,
             'section at 0/u-boot:offset': 0,
             'section at 0/u-boot:size': len(U_BOOT_DATA),
+            'section at 0/u-boot:image-pos': 0,
             'section at 0:offset': 0,
             'section at 0:size': 16,
+            'section at 0:image-pos': 0,
 
             'section at 1/u-boot:offset': 0,
             'section at 1/u-boot:size': len(U_BOOT_DATA),
+            'section at 1/u-boot:image-pos': 16,
             'section at 1:offset': 16,
             'section at 1:size': 16,
+            'section at 1:image-pos': 16,
             'size': 40
         }, props)
 
tools/binman/image.py +3 -0
index ed8261a652..4debc73451 100644
@@ -96,6 +96,9 @@ class Image:
     def SetCalculatedProperties(self):
         self._section.SetCalculatedProperties()
 
+    def SetImagePos(self):
+        self._section.SetImagePos(0)
+
     def ProcessEntryContents(self):
         """Call the ProcessContents() method for each entry
 
Signature · 1 line
2.18.0.203.gfac676dfb9-goog
#9 lore raw

PATCH 8/29 dtoc: Add missing comments to fdt_util

In reply to Simon Glass

This module has a few missing comments. Add them.

---

 tools/dtoc/fdt_util.py | 34 ++++++++++++++++++++++++++++++++++
 1 file changed, 34 insertions(+)
tools/dtoc/fdt_util.py +34 -0
index 5b631419a9..05cb9c0775 100644
@@ -5,6 +5,9 @@
 # Written by Simon Glass <[email protected]>
 #
 
+# Utility functions for reading from a device tree. Once the upstream pylibfdt
+# implementation advances far enough, we should be able to drop these.
+
 import os
 import struct
 import sys
@@ -90,6 +93,16 @@ def EnsureCompiled(fname, capture_stderr=False):
     return dtb_output
 
 def GetInt(node, propname, default=None):
+    """Get an integer from a property
+
+    Args:
+        node: Node object to read from
+        propname: property name to read
+        default: Default value to use if the node/property do not exist
+
+    Returns:
+        Integer value read, or default if none
+    """
     prop = node.props.get(propname)
     if not prop:
         return default
@@ -100,6 +113,16 @@ def GetInt(node, propname, default=None):
     return value
 
 def GetString(node, propname, default=None):
+    """Get a string from a property
+
+    Args:
+        node: Node object to read from
+        propname: property name to read
+        default: Default value to use if the node/property do not exist
+
+    Returns:
+        String value read, or default if none
+    """
     prop = node.props.get(propname)
     if not prop:
         return default
@@ -110,6 +133,17 @@ def GetString(node, propname, default=None):
     return value
 
 def GetBool(node, propname, default=False):
+    """Get an boolean from a property
+
+    Args:
+        node: Node object to read from
+        propname: property name to read
+        default: Default value to use if the node/property do not exist
+
+    Returns:
+        Boolean value read, or default if none (if you set this to True the
+            function will always return True)
+    """
     if propname in node.props:
         return True
     return default
Signature · 1 line
2.18.0.203.gfac676dfb9-goog
#10 lore raw

PATCH 9/29 binman: Add support for passing arguments to entries

In reply to Simon Glass

Sometimes it is useful to pass binman the value of an entry property from the command line. For example some entries need access to files and it is not always convenient to put these filenames in the image definition (device tree).

Add a -a option which can be used like this:

-a<prop>=<value>

where

<prop> is the property to set
<value> is the value to set it to

---

 tools/binman/README                           | 20 +++++
 tools/binman/cmdline.py                       |  2 +
 tools/binman/control.py                       | 19 +++++
 tools/binman/entry.py                         | 69 +++++++++++++++
 tools/binman/etype/_testing.py                | 19 ++++-
 tools/binman/ftest.py                         | 83 ++++++++++++++++++-
 tools/binman/test/62_entry_args.dts           | 14 ++++
 tools/binman/test/63_entry_args_missing.dts   | 13 +++
 tools/binman/test/64_entry_args_required.dts  | 14 ++++
 .../test/65_entry_args_unknown_datatype.dts   | 15 ++++
 tools/dtoc/fdt_util.py                        | 21 +++++
 tools/dtoc/test_fdt.py                        |  8 ++
 12 files changed, 293 insertions(+), 4 deletions(-)
 create mode 100644 tools/binman/test/62_entry_args.dts
 create mode 100644 tools/binman/test/63_entry_args_missing.dts
 create mode 100644 tools/binman/test/64_entry_args_required.dts
 create mode 100644 tools/binman/test/65_entry_args_unknown_datatype.dts
tools/binman/README +20 -0
index df88819a1c..d60c7fd6a3 100644
@@ -615,6 +615,26 @@ each entry is also shown, in bytes (hex). The indentation shows the entries
 nested inside their sections.
 
 
+Passing command-line arguments to entries
+-----------------------------------------
+
+Sometimes it is useful to pass binman the value of an entry property from the
+command line. For example some entries need access to files and it is not
+always convenient to put these filenames in the image definition (device tree).
+
+The-a option supports this:
+
+    -a<prop>=<value>
+
+where
+
+    <prop> is the property to set
+    <value> is the value to set it to
+
+Not all properties can be provided this way. Only some entries support it,
+typically for filenames.
+
+
 Code coverage
 -------------
 
tools/binman/cmdline.py +2 -0
index 5c9b4dfead..54e4fb13dc 100644
@@ -18,6 +18,8 @@ def ParseArgs(argv):
             args is a list of string arguments
     """
     parser = OptionParser()
+    parser.add_option('-a', '--entry-arg', type='string', action='append',
+            help='Set argument value arg=value')
     parser.add_option('-b', '--board', type='string',
             help='Board name to build')
     parser.add_option('-B', '--build-dir', type='string', default='b',
tools/binman/control.py +19 -0
index 43d192c9a7..4fa505da81 100644
@@ -7,6 +7,7 @@
 
 from collections import OrderedDict
 import os
+import re
 import sys
 import tools
 
@@ -25,6 +26,9 @@ images = OrderedDict()
 # 'u-boot-spl.dtb')
 fdt_files = {}
 
+# Arguments passed to binman to provide arguments to entries
+entry_args = {}
+
 
 def _ReadImageDesc(binman_node):
     """Read the image descriptions from the /binman node
@@ -76,6 +80,20 @@ def GetFdt(fname):
 def GetFdtPath(fname):
     return fdt_files[fname]._fname
 
+def SetEntryArgs(args):
+    global entry_args
+
+    entry_args = {}
+    if args:
+        for arg in args:
+            m = re.match('([^=]*)=(.*)', arg)
+            if not m:
+                raise ValueError("Invalid entry arguemnt '%s'" % arg)
+            entry_args[m.group(1)] = m.group(2)
+
+def GetEntryArg(name):
+    return entry_args.get(name)
+
 def Binman(options, args):
     """The main control code for binman
 
@@ -116,6 +134,7 @@ def Binman(options, args):
         try:
             tools.SetInputDirs(options.indir)
             tools.PrepareOutputDir(options.outdir, options.preserve)
+            SetEntryArgs(options.entry_arg)
 
             # Get the device tree ready by compiling it and copying the compiled
             # output into a file in our output directly. Then scan it for use
tools/binman/entry.py +69 -0

96 lines not on this page · raw message

tools/binman/etype/_testing.py +18 -1
index 31f625c026..3eeec72b36 100644
@@ -5,7 +5,9 @@
 # Entry-type module for testing purposes. Not used in real images.
 #
 
-from entry import Entry
+from collections import OrderedDict
+
+from entry import Entry, EntryArg
 import fdt_util
 import tools
 
@@ -27,6 +29,21 @@ class Entry__testing(Entry):
         self.process_fdt_ready = False
         self.never_complete_process_fdt = fdt_util.GetBool(self._node,
                                                 'never-complete-process-fdt')
+        self.require_args = fdt_util.GetBool(self._node, 'require-args')
+
+        # This should be picked up by GetEntryArgsOrProps()
+        self.test_existing_prop = 'existing'
+        self.force_bad_datatype = fdt_util.GetBool(self._node,
+                                                   'force-bad-datatype')
+        (self.test_str_fdt, self.test_str_arg, self.test_int_fdt,
+         self.test_int_arg, existing) = self.GetEntryArgsOrProps([
+            EntryArg('test-str-fdt', str),
+            EntryArg('test-str-arg', str),
+            EntryArg('test-int-fdt', int),
+            EntryArg('test-int-arg', int),
+            EntryArg('test-existing-prop', str)], self.require_args)
+        if self.force_bad_datatype:
+            self.GetEntryArgsOrProps([EntryArg('test-bad-datatype-arg', bool)])
 
     def ObtainContents(self):
         if self.return_unknown_contents:
tools/binman/ftest.py +80 -3

112 lines not on this page · raw message

tools/binman/test/62_entry_args.dts new file +14 -0
new file mode 100644
index 0000000000..4d4f102d60
@@ -0,0 +1,14 @@
+// SPDX-License-Identifier: GPL-2.0+
+/dts-v1/;
+
+/ {
+	#address-cells = <1>;
+	#size-cells = <1>;
+
+	binman {
+		_testing {
+			test-str-fdt = "test0";
+			test-int-fdt = <123>;
+		};
+	};
+};
tools/binman/test/63_entry_args_missing.dts new file +13 -0
new file mode 100644
index 0000000000..1644e2fef3
@@ -0,0 +1,13 @@
+// SPDX-License-Identifier: GPL-2.0+
+/dts-v1/;
+
+/ {
+	#address-cells = <1>;
+	#size-cells = <1>;
+
+	binman {
+		_testing {
+			test-str-fdt = "test0";
+		};
+	};
+};
tools/binman/test/64_entry_args_required.dts new file +14 -0
new file mode 100644
index 0000000000..705be10069
@@ -0,0 +1,14 @@
+// SPDX-License-Identifier: GPL-2.0+
+/dts-v1/;
+
+/ {
+	#address-cells = <1>;
+	#size-cells = <1>;
+
+	binman {
+		_testing {
+			require-args;
+			test-str-fdt = "test0";
+		};
+	};
+};
tools/binman/test/65_entry_args_unknown_datatype.dts new file +15 -0
new file mode 100644
index 0000000000..3e4838f4ff
@@ -0,0 +1,15 @@
+// SPDX-License-Identifier: GPL-2.0+
+/dts-v1/;
+
+/ {
+	#address-cells = <1>;
+	#size-cells = <1>;
+
+	binman {
+		_testing {
+			test-str-fdt = "test0";
+			test-int-fdt = <123>;
+			force-bad-datatype;
+		};
+	};
+};
tools/dtoc/fdt_util.py +21 -0
index 05cb9c0775..b229038569 100644
@@ -147,3 +147,24 @@ def GetBool(node, propname, default=False):
     if propname in node.props:
         return True
     return default
+
+def GetDatatype(node, propname, datatype):
+    """Get a value of a given type from a property
+
+    Args:
+        node: Node object to read from
+        propname: property name to read
+        datatype: Type to read (str or int)
+
+    Returns:
+        value read, or None if none
+
+    Raises:
+        ValueError if datatype is not str or int
+    """
+    if datatype == str:
+        return GetString(node, propname)
+    elif datatype == int:
+        return GetInt(node, propname)
+    raise ValueError("fdt_util internal error: Unknown data type '%s'" %
+                     datatype)
tools/dtoc/test_fdt.py +8 -0
index f085b1dd1a..03cf4b4f7c 100755
@@ -380,6 +380,14 @@ class TestFdtUtil(unittest.TestCase):
         self.assertEqual(True, fdt_util.GetBool(self.node, 'missing', True))
         self.assertEqual(False, fdt_util.GetBool(self.node, 'missing', False))
 
+    def testGetDataType(self):
+        self.assertEqual(1, fdt_util.GetDatatype(self.node, 'intval', int))
+        self.assertEqual('message', fdt_util.GetDatatype(self.node, 'stringval',
+                                                         str))
+        with self.assertRaises(ValueError) as e:
+            self.assertEqual(3, fdt_util.GetDatatype(self.node, 'boolval',
+                                                     bool))
+
     def testFdtCellsToCpu(self):
         val = self.node.props['intarray'].value
         self.assertEqual(0, fdt_util.fdt_cells_to_cpu(val, 0))
Signature · 1 line
2.18.0.203.gfac676dfb9-goog
#11 lore raw

PATCH 10/29 binman: Support an entry that holds text

In reply to Simon Glass

It is useful to able to write an identifying string to the image within an entry. Add a 'text' entry type to handle this. The actual text is typically passed to binman on the command line. The text is not itself nul-terminated but this can be achieved if required by setting the size of the entry to something larger than the text.

---

 tools/binman/etype/text.py    | 50 +++++++++++++++++++++++++++++++++++
 tools/binman/ftest.py         | 16 +++++++++++
 tools/binman/test/66_text.dts | 28 ++++++++++++++++++++
 3 files changed, 94 insertions(+)
 create mode 100644 tools/binman/etype/text.py
 create mode 100644 tools/binman/test/66_text.dts
tools/binman/etype/text.py new file +50 -0
new file mode 100644
index 0000000000..1c69afa72e
@@ -0,0 +1,50 @@
+# SPDX-License-Identifier: GPL-2.0+
+# Copyright (c) 2018 Google, Inc
+# Written by Simon Glass <[email protected]>
+#
+
+from collections import OrderedDict
+
+from entry import Entry, EntryArg
+import fdt_util
+
+
+class Entry_text(Entry):
+    """An entry which contains text
+
+    The text can be provided either in the node itself or by a command-line
+    argument.
+
+    Example node:
+
+        text {
+            size = <50>;
+            text-label = "message";
+        };
+
+    You can then use:
+
+        binman -amessage="this is my message"
+
+    and binman will insert that string into the entry.
+
+    It is also possible to put the string directly in the node:
+
+        text {
+            size = <8>;
+            text-label = "message";
+            message = "a message directly in the node"
+        };
+
+    The text is not itself nul-terminated. This can be achieved, if required,
+    by setting the size of the entry to something larger than the text.
+    """
+    def __init__(self, section, etype, node):
+        Entry.__init__(self, section, etype, node)
+        self.text_label, = self.GetEntryArgsOrProps(
+            [EntryArg('text-label', str)])
+        self.value, = self.GetEntryArgsOrProps([EntryArg(self.text_label, str)])
+
+    def ObtainContents(self):
+        self.SetContents(self.value)
+        return True
tools/binman/ftest.py +16 -0
index c54cd12e71..696889601e 100644
@@ -41,6 +41,9 @@ FSP_DATA              = 'fsp'
 CMC_DATA              = 'cmc'
 VBT_DATA              = 'vbt'
 MRC_DATA              = 'mrc'
+TEXT_DATA             = 'text'
+TEXT_DATA2            = 'text2'
+TEXT_DATA3            = 'text3'
 
 class TestFunctional(unittest.TestCase):
     """Functional tests for binman
@@ -1161,6 +1164,19 @@ class TestFunctional(unittest.TestCase):
         self.assertIn('GetArg() internal error: Unknown data type ',
                       str(e.exception))
 
+    def testText(self):
+        """Test for a text entry type"""
+        entry_args = {
+            'test-id': TEXT_DATA,
+            'test-id2': TEXT_DATA2,
+            'test-id3': TEXT_DATA3,
+        }
+        data, _, _, _ = self._DoReadFileDtb('66_text.dts',
+                                            entry_args=entry_args)
+        expected = (TEXT_DATA + chr(0) * (8 - len(TEXT_DATA)) + TEXT_DATA2 +
+                    TEXT_DATA3 + 'some text')
+        self.assertEqual(expected, data)
+
 
 if __name__ == "__main__":
     unittest.main()
tools/binman/test/66_text.dts new file +28 -0
new file mode 100644
index 0000000000..59b1fed0ef
@@ -0,0 +1,28 @@
+// SPDX-License-Identifier: GPL-2.0+
+/dts-v1/;
+
+/ {
+	#address-cells = <1>;
+	#size-cells = <1>;
+
+	binman {
+		text {
+			size = <8>;
+			text-label = "test-id";
+		};
+		text2 {
+			type = "text";
+			text-label = "test-id2";
+		};
+		text3 {
+			type = "text";
+			text-label = "test-id3";
+		};
+		/* This one does not use command-line args */
+		text4 {
+			type = "text";
+			text-label = "test-id4";
+			test-id4 = "some text";
+		};
+	};
+};
Signature · 1 line
2.18.0.203.gfac676dfb9-goog
#12 lore raw

PATCH 11/29 binman: Allow help to work without libfdt

In reply to Simon Glass

At present binman needs libfdt.py to be available before it will do anything, even print help. Import those modules later to avoid this, as it is bad practice to fail to even show help on startup.

---

 tools/binman/control.py | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)
tools/binman/control.py +5 -2
index 4fa505da81..3e5eac2c52 100644
@@ -13,8 +13,6 @@ import tools
 
 import command
 import elf
-import fdt
-import fdt_util
 from image import Image
 import tout
 
@@ -129,6 +127,11 @@ def Binman(options, args):
         options.indir.append(board_pathname)
 
     try:
+        # Import these here in case libfdt.py is not available, in which case
+        # the above help option still works.
+        import fdt
+        import fdt_util
+
         tout.Init(options.verbosity)
         elf.debug = options.debug
         try:
Signature · 1 line
2.18.0.203.gfac676dfb9-goog
#13 lore raw

PATCH 12/29 binman: Expand documentation for entries

In reply to Simon Glass

At present only the more complex entries are documented. It is useful to have documentation for all entries in one place.

As a first step, add and expand the documentation to cover all entries.

---

 tools/binman/etype/_testing.py              | 26 ++++++++++++++++++++-
 tools/binman/etype/blob.py                  | 12 ++++++++++
 tools/binman/etype/intel_cmc.py             | 10 ++++++++
 tools/binman/etype/intel_descriptor.py      | 18 +++++++++++---
 tools/binman/etype/intel_fsp.py             | 14 +++++++++++
 tools/binman/etype/intel_me.py              | 15 ++++++++++++
 tools/binman/etype/intel_mrc.py             | 11 +++++++++
 tools/binman/etype/intel_vbt.py             | 10 ++++++++
 tools/binman/etype/intel_vga.py             | 12 ++++++++++
 tools/binman/etype/section.py               | 17 ++++++++++++++
 tools/binman/etype/text.py                  |  9 ++++++-
 tools/binman/etype/u_boot.py                | 16 +++++++++++++
 tools/binman/etype/u_boot_dtb.py            |  9 +++++++
 tools/binman/etype/u_boot_dtb_with_ucode.py | 12 ++++++++--
 tools/binman/etype/u_boot_img.py            | 11 +++++++++
 tools/binman/etype/u_boot_nodtb.py          | 11 +++++++++
 tools/binman/etype/u_boot_spl.py            | 21 +++++++++++++++++
 tools/binman/etype/u_boot_spl_bss_pad.py    | 16 +++++++++++++
 tools/binman/etype/u_boot_spl_dtb.py        |  9 +++++++
 tools/binman/etype/u_boot_spl_nodtb.py      | 12 ++++++++++
 tools/binman/etype/u_boot_ucode.py          |  6 +++++
 tools/binman/etype/u_boot_with_ucode_ptr.py |  9 +++++--
 tools/binman/etype/x86_start16.py           | 14 +++++++++++
 tools/binman/etype/x86_start16_spl.py       | 14 +++++++++++
 24 files changed, 305 insertions(+), 9 deletions(-)
tools/binman/etype/_testing.py +25 -1
index 3eeec72b36..02c165c0c3 100644
@@ -15,8 +15,30 @@ import tools
 class Entry__testing(Entry):
     """A fake entry used for testing
 
+    This entry should not be used in normal images. It is a special entry with
+    strange features used for testing.
+
+    Properties / Entry arguments
+        test-str-fdt: Test string, normally in the node
+        test-int-fdt: Test integer, normally in the node
+        test-str-arg: Test string, normally in the entry arguments
+        test-int-arg: Test integer, normally in the entry arguments
+
+    The entry has a single 'a' byte as its contents. Operation is controlled by
+    a number of properties in the node, as follows:
+
     Properties:
-        return_invalid_entry: Return an invalid entry from GetOffsets()
+        return-invalid-entry: Return an invalid entry from GetOffsets()
+        return-unknown-contents: Refuse to provide any contents (to cause a
+            failure)
+        bad-update-contents: Implement ProcessContents() incorrectly so as to
+            cause a failure
+        never-complete-process-fdt: Refund to process the FDT (to cause a
+            failure)
+        require-args: Require that all used args are present (generating an
+            error if not)
+        force-bad-datatype: Force a call to GetEntryArgsOrProps() with a bad
+            data type (generating an error)
     """
     def __init__(self, section, etype, node):
         Entry.__init__(self, section, etype, node)
@@ -26,6 +48,8 @@ class Entry__testing(Entry):
                                                      'return-unknown-contents')
         self.bad_update_contents = fdt_util.GetBool(self._node,
                                                     'bad-update-contents')
+
+        # Set to True when the entry is ready to process the FDT.
         self.process_fdt_ready = False
         self.never_complete_process_fdt = fdt_util.GetBool(self._node,
                                                 'never-complete-process-fdt')
tools/binman/etype/blob.py +12 -0
index 28e6651a93..692d8683c3 100644
@@ -10,6 +10,18 @@ import fdt_util
 import tools
 
 class Entry_blob(Entry):
+    """Entry containing an arbitrary binary blob
+
+    Note: This should not be used by itself. It is normally used as a parent
+    class by other entry types.
+
+    Properties / Entry arguments:
+        - filename: Filename of file to read into entry
+
+    This entry reads data from a file and places it in the entry. The
+    default filename is often specified specified by the subclass. See for
+    example the 'u_boot' entry which provides the filename 'u-boot.bin'.
+    """
     def __init__(self, section, etype, node):
         Entry.__init__(self, section, etype, node)
         self._filename = fdt_util.GetString(self._node, "filename", self.etype)
tools/binman/etype/intel_cmc.py +10 -0
index b8621e0cc5..fa6f7793c6 100644
@@ -9,5 +9,15 @@ from entry import Entry
 from blob import Entry_blob
 
 class Entry_intel_cmc(Entry_blob):
+    """Entry containing an Intel Chipset Micro Code (CMC) file
+
+    Properties / Entry arguments:
+        - filename: Filename of file to read into entry
+
+    This file contains microcode for some devices in a special format. An
+    example filename is 'Microcode/C0_22211.BIN'.
+
+    See README.x86 for information about x86 binary blobs.
+    """
     def __init__(self, section, etype, node):
         Entry_blob.__init__(self, section, etype, node)
tools/binman/etype/intel_descriptor.py +15 -3
index 0a5151d466..6acbbd8b7a 100644
@@ -13,6 +13,7 @@ from blob import Entry_blob
 FD_SIGNATURE   = struct.pack('<L', 0x0ff0a55a)
 MAX_REGIONS    = 5
 
+# Region numbers supported by the Intel firmware format
 (REGION_DESCRIPTOR, REGION_BIOS, REGION_ME, REGION_GBE,
         REGION_PDATA) = range(5)
 
@@ -27,10 +28,21 @@ class Region:
 class Entry_intel_descriptor(Entry_blob):
     """Intel flash descriptor block (4KB)
 
-    This is placed at the start of flash and provides information about
+    Properties / Entry arguments:
+        filename: Filename of file containing the descriptor. This is typically
+            a 4KB binary file, sometimes called 'descriptor.bin'
+
+    This entry is placed at the start of flash and provides information about
     the SPI flash regions. In particular it provides the base address and
-    size of the ME region, allowing us to place the ME binary in the right
-    place.
+    size of the ME (Management Engine) region, allowing us to place the ME
+    binary in the right place.
+
+    With this entry in your image, the position of the 'intel-me' entry will be
+    fixed in the image, which avoids you needed to specify an offset for that
+    region. This is useful, because it is not possible to change the position
+    of the ME region without updating the descriptor.
+
+    See README.x86 for information about x86 binary blobs.
     """
     def __init__(self, section, etype, node):
         Entry_blob.__init__(self, section, etype, node)
tools/binman/etype/intel_fsp.py +14 -0
index cb80a617c3..00a78e7083 100644
@@ -9,5 +9,19 @@ from entry import Entry
 from blob import Entry_blob
 
 class Entry_intel_fsp(Entry_blob):
+    """Entry containing an Intel Firmware Support Package (FSP) file
+
+    Properties / Entry arguments:
+        - filename: Filename of file to read into entry
+
+    This file contains binary blobs which are used on some devices to make the
+    platform work. U-Boot executes this code since it is not possible to set up
+    the hardware using U-Boot open-source code. Documentation is typically not
+    available in sufficient detail to allow this.
+
+    An example filename is 'FSP/QUEENSBAY_FSP_GOLD_001_20-DECEMBER-2013.fd'
+
+    See README.x86 for information about x86 binary blobs.
+    """
     def __init__(self, section, etype, node):
         Entry_blob.__init__(self, section, etype, node)
tools/binman/etype/intel_me.py +15 -0
index 0682ead943..247c5b3386 100644
@@ -9,5 +9,20 @@ from entry import Entry
 from blob import Entry_blob
 
 class Entry_intel_me(Entry_blob):
+    """Entry containing an Intel Management Engine (ME) file
+
+    Properties / Entry arguments:
+        - filename: Filename of file to read into entry
+
+    This file contains code used by the SoC that is required to make it work.
+    The Management Engine is like a background task that runs things that are
+    not clearly documented, but may include keyboard, deplay and network
+    access. For platform that use ME it is not possible to disable it. U-Boot
+    does not directly execute code in the ME binary.
+
+    A typical filename is 'me.bin'.
+
+    See README.x86 for information about x86 binary blobs.
+    """
     def __init__(self, section, etype, node):
         Entry_blob.__init__(self, section, etype, node)
tools/binman/etype/intel_mrc.py +11 -0
index 305ac98888..4dbc99a04f 100644
@@ -9,6 +9,17 @@ from entry import Entry
 from blob import Entry_blob
 
 class Entry_intel_mrc(Entry_blob):
+    """Entry containing an Intel Memory Reference Code (MRC) file
+
+    Properties / Entry arguments:
+        - filename: Filename of file to read into entry
+
+    This file contains code for setting up the SDRAM on some Intel systems. This
+    is executed by U-Boot when needed early during startup. A typical filename
+    is 'mrc.bin'.
+
+    See README.x86 for information about x86 binary blobs.
+    """
     def __init__(self, section, etype, node):
         Entry_blob.__init__(self, section, etype, node)
 
tools/binman/etype/intel_vbt.py +10 -0
index d4e8c3f797..d93dd19634 100644
@@ -8,5 +8,15 @@ from entry import Entry
 from blob import Entry_blob
 
 class Entry_intel_vbt(Entry_blob):
+    """Entry containing an Intel Video BIOS Table (VBT) file
+
+    Properties / Entry arguments:
+        - filename: Filename of file to read into entry
+
+    This file contains code that sets up the integrated graphics subsystem on
+    some Intel SoCs. U-Boot executes this when the display is started up.
+
+    See README.x86 for information about Intel binary blobs.
+    """
     def __init__(self, section, etype, node):
         Entry_blob.__init__(self, section, etype, node)
tools/binman/etype/intel_vga.py +12 -0
index 140dd40dda..40982c8665 100644
@@ -9,5 +9,17 @@ from entry import Entry
 from blob import Entry_blob
 
 class Entry_intel_vga(Entry_blob):
+    """Entry containing an Intel Video Graphics Adaptor (VGA) file
+
+    Properties / Entry arguments:
+        - filename: Filename of file to read into entry
+
+    This file contains code that sets up the integrated graphics subsystem on
+    some Intel SoCs. U-Boot executes this when the display is started up.
+
+    This is similar to the VBT file but in a different format.
+
+    See README.x86 for information about Intel binary blobs.
+    """
     def __init__(self, section, etype, node):
         Entry_blob.__init__(self, section, etype, node)
tools/binman/etype/section.py +17 -0
index b90b80e4ce..2e68f276f0 100644
@@ -13,6 +13,23 @@ import tools
 import bsection
 
 class Entry_section(Entry):
+    """Entry that contains other entries
+
+    Properties / Entry arguments: (see binman README for more information)
+        - size: Size of section in bytes
+        - align-size: Align size to a particular power of two
+        - pad-before: Add padding before the entry
+        - pad-after: Add padding after the entry
+        - pad-byte: Pad byte to use when padding
+        - sort-by-offset: Reorder the entries by offset
+        - end-at-4gb: Used to build an x86 ROM which ends@4GB (2^32)
+        - name-prefix: Adds a prefix to the name of every entry in the section
+            when writing out the map
+
+    A section is an entry which can contain other entries, thus allowing
+    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)
         self._section = bsection.Section(node.name, node)
tools/binman/etype/text.py +8 -1
index 1c69afa72e..7a1cddf4af 100644
@@ -13,7 +13,14 @@ class Entry_text(Entry):
     """An entry which contains text
 
     The text can be provided either in the node itself or by a command-line
-    argument.
+    argument. There is a level of indirection to allow multiple text strings
+    and sharing of text.
+
+    Properties / Entry arguments:
+        text-label: The value of this string indicates the property / entry-arg
+            that contains the string to place in the entry
+        <xxx> (actual name is the value of text-label): contains the string to
+            place in the entry.
 
     Example node:
 
tools/binman/etype/u_boot.py +16 -0
index b6058bf6b5..23dd12ce43 100644
@@ -9,6 +9,22 @@ from entry import Entry
 from blob import Entry_blob
 
 class Entry_u_boot(Entry_blob):
+    """U-Boot flat binary
+
+    Properties / Entry arguments:
+        - filename: Filename of u-boot.bin (default 'u-boot.bin')
+
+    This is the U-Boot binary, containing relocation information to allow it
+    to relocate itself at runtime. The binary typically includes a device tree
+    blob at the end of it. Use u_boot_nodtb if you want to package the device
+    tree separately.
+
+    U-Boot can access binman symbols at runtime. See:
+
+        'Access to binman entry offsets at run time (fdt)'
+
+    in the binman README for more information.
+    """
     def __init__(self, section, etype, node):
         Entry_blob.__init__(self, section, etype, node)
 
tools/binman/etype/u_boot_dtb.py +9 -0
index dd3c5b2790..fb3dd1cf64 100644
@@ -9,6 +9,15 @@ from entry import Entry
 from blob import Entry_blob
 
 class Entry_u_boot_dtb(Entry_blob):
+    """U-Boot device tree
+
+    Properties / Entry arguments:
+        - filename: Filename of u-boot.dtb (default 'u-boot.dtb')
+
+    This is the U-Boot device tree, containing configuration information for
+    U-Boot. U-Boot needs this to know what devices are present and which drivers
+    to activate.
+    """
     def __init__(self, section, etype, node):
         Entry_blob.__init__(self, section, etype, node)
 
tools/binman/etype/u_boot_dtb_with_ucode.py +10 -2
index 55d3a38a64..752d0ac0ba 100644
@@ -14,8 +14,16 @@ import tools
 class Entry_u_boot_dtb_with_ucode(Entry_blob):
     """A U-Boot device tree file, with the microcode removed
 
-    See Entry_u_boot_ucode for full details of the 3 entries involved in this
-    process.
+    Properties / Entry arguments:
+        - filename: Filename of u-boot.dtb (default 'u-boot.dtb')
+
+    See Entry_u_boot_ucode for full details of the three entries involved in
+    this process. This entry provides the U-Boot device-tree file, which
+    contains the microcode. If the microcode is not being collated into one
+    place then the offset and size of the microcode is recorded by this entry,
+    for use by u_boot_with_ucode_ptr. If it is being collated, then this
+    entry deletes the microcode from the device tree (to save space) and makes
+    it available to u_boot_ucode.
     """
     def __init__(self, section, etype, node):
         Entry_blob.__init__(self, section, etype, node)
tools/binman/etype/u_boot_img.py +11 -0
index 6e0b736af1..1ec0757c7f 100644
@@ -9,6 +9,17 @@ from entry import Entry
 from blob import Entry_blob
 
 class Entry_u_boot_img(Entry_blob):
+    """U-Boot legacy image
+
+    Properties / Entry arguments:
+        - filename: Filename of u-boot.img (default 'u-boot.img')
+
+    This is the U-Boot binary as a packaged image, in legacy format. It has a
+    header which allows it to be loaded at the correct address for execution.
+
+    You should use FIT (Flat Image Tree) instead of the legacy image for new
+    applications.
+    """
     def __init__(self, section, etype, node):
         Entry_blob.__init__(self, section, etype, node)
 
tools/binman/etype/u_boot_nodtb.py +11 -0
index ca9e53a094..a4b95a4390 100644
@@ -9,6 +9,17 @@ from entry import Entry
 from blob import Entry_blob
 
 class Entry_u_boot_nodtb(Entry_blob):
+    """U-Boot flat binary without device tree appended
+
+    Properties / Entry arguments:
+        - filename: Filename of u-boot.bin (default 'u-boot-nodtb.bin')
+
+    This is the U-Boot binary, containing relocation information to allow it
+    to relocate itself at runtime. It does not include a device tree blob at
+    the end of it so normally cannot work without it. You can add a u_boot_dtb
+    entry after this one, or use a u_boot entry instead (which contains both
+    U-Boot and the device tree).
+    """
     def __init__(self, section, etype, node):
         Entry_blob.__init__(self, section, etype, node)
 
tools/binman/etype/u_boot_spl.py +21 -0
index 9edd2dad03..0e99a2d2a7 100644
@@ -11,6 +11,27 @@ from entry import Entry
 from blob import Entry_blob
 
 class Entry_u_boot_spl(Entry_blob):
+    """U-Boot SPL binary
+
+    Properties / Entry arguments:
+        - filename: Filename of u-boot-spl.bin (default 'spl/u-boot-spl.bin')
+
+    This is the U-Boot SPL (Secondary Program Loader) binary. This is a small
+    binary which loads before U-Boot proper, typically into on-chip SRAM. It is
+    responsible for locating, loading and jumping to U-Boot. Note that SPL is
+    not relocatable so must be loaded to the correct address in SRAM, or written
+    to run from the correct address is direct flash execution is possible (e.g.
+    on x86 devices).
+
+    SPL can access binman symbols at runtime. See:
+
+        'Access to binman entry offsets at run time (symbols)'
+
+    in the binman README for more information.
+
+    The ELF file 'spl/u-boot-spl' must also be available for this to work, since
+    binman uses that to look up symbols to write into the SPL binary.
+    """
     def __init__(self, section, etype, node):
         Entry_blob.__init__(self, section, etype, node)
         self.elf_fname = 'spl/u-boot-spl'
tools/binman/etype/u_boot_spl_bss_pad.py +16 -0
index 65f631d3c5..00b7ac5004 100644
@@ -14,6 +14,22 @@ from blob import Entry_blob
 import tools
 
 class Entry_u_boot_spl_bss_pad(Entry_blob):
+    """U-Boot SPL binary padded with a BSS region
+
+    Properties / Entry arguments:
+        None
+
+    This is similar to u_boot_spl except that padding is added after the SPL
+    binary to cover the BSS (Block Started by Symbol) region. This region holds
+    the various used by SPL. It is set to 0 by SPL when it starts up. If you
+    want to append data to the SPL image (such as a device tree file), you must
+    pad out the BSS region to avoid the data overlapping with U-Boot variables.
+    This entry is useful in that case. It automatically pads out the entry size
+    to cover both the code, data and BSS.
+
+    The ELF file 'spl/u-boot-spl' must also be available for this to work, since
+    binman uses that to look up the BSS address.
+    """
     def __init__(self, section, etype, node):
         Entry_blob.__init__(self, section, etype, node)
 
tools/binman/etype/u_boot_spl_dtb.py +9 -0
index eefa1ff53a..6a30edc83c 100644
@@ -9,6 +9,15 @@ from entry import Entry
 from blob import Entry_blob
 
 class Entry_u_boot_spl_dtb(Entry_blob):
+    """U-Boot SPL device tree
+
+    Properties / Entry arguments:
+        - filename: Filename of u-boot.dtb (default 'spl/u-boot-spl.dtb')
+
+    This is the SPL device tree, containing configuration information for
+    SPL. SPL needs this to know what devices are present and which drivers
+    to activate.
+    """
     def __init__(self, section, etype, node):
         Entry_blob.__init__(self, section, etype, node)
 
tools/binman/etype/u_boot_spl_nodtb.py +12 -0
index 99e56ebe3b..41c17366b1 100644
@@ -9,6 +9,18 @@ from entry import Entry
 from blob import Entry_blob
 
 class Entry_u_boot_spl_nodtb(Entry_blob):
+    """SPL binary without device tree appended
+
+    Properties / Entry arguments:
+        - filename: Filename of spl/u-boot-spl-nodtb.bin (default
+            'spl/u-boot-spl-nodtb.bin')
+
+    This is the U-Boot SPL binary, It does not include a device tree blob at
+    the end of it so may not be able to work without it, assuming SPL needs
+    a device tree to operation on your platform. You can add a u_boot_spl_dtb
+    entry after this one, or use a u_boot_spl entry instead (which contains
+    both SPL and the device tree).
+    """
     def __init__(self, section, etype, node):
         Entry_blob.__init__(self, section, etype, node)
 
tools/binman/etype/u_boot_ucode.py +6 -0
index 922a607cfe..0f1761afc8 100644
@@ -12,6 +12,12 @@ import tools
 class Entry_u_boot_ucode(Entry_blob):
     """U-Boot microcode block
 
+    Properties / Entry arguments:
+        None
+
+    The contents of this entry are filled in automatically by other entries
+    which must also be in the image.
+
     U-Boot on x86 needs a single block of microcode. This is collected from
     the various microcode update nodes in the device tree. It is also unable
     to read the microcode from the device tree on platforms that use FSP
tools/binman/etype/u_boot_with_ucode_ptr.py +7 -2
index 97e58a0bfc..51e7ba48f5 100644
@@ -17,8 +17,13 @@ import tools
 class Entry_u_boot_with_ucode_ptr(Entry_blob):
     """U-Boot with embedded microcode pointer
 
-    See Entry_u_boot_ucode for full details of the 3 entries involved in this
-    process.
+    Properties / Entry arguments:
+        - filename: Filename of u-boot-nodtb.dtb (default 'u-boot-nodtb.dtb')
+
+    See Entry_u_boot_ucode for full details of the three entries involved in
+    this process. This entry updates U-Boot with the offset and size of the
+    microcode, to allow early x86 boot code to find it without doing anything
+    complicated. Otherwise it is the same as the u_boot entry.
     """
     def __init__(self, section, etype, node):
         Entry_blob.__init__(self, section, etype, node)
tools/binman/etype/x86_start16.py +14 -0
index 23d27f0704..7d32ecd321 100644
@@ -9,6 +9,20 @@ from entry import Entry
 from blob import Entry_blob
 
 class Entry_x86_start16(Entry_blob):
+    """x86 16-bit start-up code for U-Boot
+
+    Properties / Entry arguments:
+        - filename: Filename of u-boot-x86-16bit.bin (default
+            'u-boot-x86-16bit.bin')
+
+    x86 CPUs start up in 16-bit mode, even if they are 32-bit CPUs. This code
+    must be placed at a particular address. This entry holds that code. It is
+    typically placed at offset CONFIG_SYS_X86_START16. The code is responsible
+    for changing to 32-bit mode and jumping to U-Boot's entry point, which
+    requires 32-bit mode (for 32-bit U-Boot).
+
+    For 64-bit U-Boot, the 'x86_start16_spl' entry type is used instead.
+    """
     def __init__(self, section, etype, node):
         Entry_blob.__init__(self, section, etype, node)
 
tools/binman/etype/x86_start16_spl.py +14 -0
index 176420ba88..d85909e7ae 100644
@@ -9,6 +9,20 @@ from entry import Entry
 from blob import Entry_blob
 
 class Entry_x86_start16_spl(Entry_blob):
+    """x86 16-bit start-up code for SPL
+
+    Properties / Entry arguments:
+        - filename: Filename of spl/u-boot-x86-16bit-spl.bin (default
+            'spl/u-boot-x86-16bit-spl.bin')
+
+    x86 CPUs start up in 16-bit mode, even if they are 64-bit CPUs. This code
+    must be placed at a particular address. This entry holds that code. It is
+    typically placed at offset CONFIG_SYS_X86_START16. The code is responsible
+    for changing to 32-bit mode and starting SPL, which in turn changes to
+    64-bit mode and jumps to U-Boot (for 64-bit U-Boot).
+
+    For 32-bit U-Boot, the 'x86_start16' entry type is used instead.
+    """
     def __init__(self, section, etype, node):
         Entry_blob.__init__(self, section, etype, node)
 
Signature · 1 line
2.18.0.203.gfac676dfb9-goog
#14 lore raw

PATCH 13/29 binman: Allow creation of entry documentation

In reply to Simon Glass

Binman supports quite a number of different entries now. The operation of these is not always obvious but at present the source code is the only reference for understanding how an entry works.

Add a way to create documentation (from the source code) which can be put in a new 'README.entries' file.

---

 tools/binman/binman.py                      | 22 +++--
 tools/binman/cmdline.py                     |  2 +
 tools/binman/control.py                     |  4 +
 tools/binman/entry.py                       | 93 ++++++++++++++++++---
 tools/binman/etype/u_boot_dtb_with_ucode.py |  4 +-
 tools/binman/ftest.py                       | 15 ++++
 6 files changed, 118 insertions(+), 22 deletions(-)
tools/binman/binman.py +14 -8
index 52e02ed91b..1536e95651 100755
@@ -77,9 +77,20 @@ def RunTests(debug, args):
       return 1
     return 0
 
+def GetEntryModules(include_testing=True):
+    """Get a set of entry class implementations
+
+    Returns:
+        Set of paths to entry class filenames
+    """
+    glob_list = glob.glob(os.path.join(our_path, 'etype/*.py'))
+    return set([os.path.splitext(os.path.basename(item))[0]
+                for item in glob_list
+                if include_testing or '_testing' not in item])
+
 def RunTestCoverage():
     """Run the tests and check that we get 100% coverage"""
-    glob_list = glob.glob(os.path.join(our_path, 'etype/*.py'))
+    glob_list = GetEntryModules(False)
     all_set = set([os.path.splitext(os.path.basename(item))[0]
                    for item in glob_list if '_testing' not in item])
     test_util.RunTestCoverage('tools/binman/binman.py', None,
@@ -107,13 +118,8 @@ def RunBinman(options, args):
     elif options.test_coverage:
         RunTestCoverage()
 
-    elif options.full_help:
-        pager = os.getenv('PAGER')
-        if not pager:
-            pager = 'more'
-        fname = os.path.join(os.path.dirname(os.path.realpath(sys.argv[0])),
-                            'README')
-        command.Run(pager, fname)
+    elif options.entry_docs:
+        control.WriteEntryDocs(GetEntryModules())
 
     else:
         try:
tools/binman/cmdline.py +2 -0
index 54e4fb13dc..f0de4ded44 100644
@@ -28,6 +28,8 @@ def ParseArgs(argv):
             help='Configuration file (.dtb) to use')
     parser.add_option('-D', '--debug', action='store_true',
             help='Enabling debugging (provides a full traceback on error)')
+    parser.add_option('-E', '--entry-docs', action='store_true',
+            help='Write out entry documentation (see README.entries)')
     parser.add_option('-I', '--indir', action='append',
             help='Add a path to a directory to use for input files')
     parser.add_option('-H', '--full-help', action='store_true',
tools/binman/control.py +4 -0
index 3e5eac2c52..188a52b72b 100644
@@ -92,6 +92,10 @@ def SetEntryArgs(args):
 def GetEntryArg(name):
     return entry_args.get(name)
 
+def WriteEntryDocs(modules, test_missing=None):
+    from entry import Entry
+    Entry.WriteDocs(modules, test_missing)
+
 def Binman(options, args):
     """The main control code for binman
 
tools/binman/entry.py +80 -13

118 lines not on this page · raw message

tools/binman/etype/u_boot_dtb_with_ucode.py +3 -1
index 752d0ac0ba..adcb898a7b 100644
@@ -6,7 +6,6 @@
 #
 
 import control
-import fdt
 from entry import Entry
 from blob import Entry_blob
 import tools
@@ -38,6 +37,9 @@ class Entry_u_boot_dtb_with_ucode(Entry_blob):
         return 'u-boot.dtb'
 
     def ProcessFdt(self, fdt):
+        # So the module can be loaded without it
+        import fdt
+
         # If the section does not need microcode, there is nothing to do
         ucode_dest_entry = self.section.FindEntryType(
             'u-boot-spl-with-ucode-ptr')
tools/binman/ftest.py +15 -0
index 696889601e..9c01805c72 100644
@@ -21,6 +21,7 @@ import control
 import elf
 import fdt
 import fdt_util
+import test_util
 import tools
 import tout
 
@@ -1177,6 +1178,20 @@ class TestFunctional(unittest.TestCase):
                     TEXT_DATA3 + 'some text')
         self.assertEqual(expected, data)
 
+    def testEntryDocs(self):
+        """Test for creation of entry documentation"""
+        with test_util.capture_sys_output() as (stdout, stderr):
+            control.WriteEntryDocs(binman.GetEntryModules())
+        self.assertTrue(len(stdout.getvalue()) > 0)
+
+    def testEntryDocsMissing(self):
+        """Test handling of missing entry documentation"""
+        with self.assertRaises(ValueError) as e:
+            with test_util.capture_sys_output() as (stdout, stderr):
+                control.WriteEntryDocs(binman.GetEntryModules(), 'u_boot')
+        self.assertIn('Documentation is missing for modules: u_boot',
+                      str(e.exception))
+
 
 if __name__ == "__main__":
     unittest.main()
Signature · 1 line
2.18.0.203.gfac676dfb9-goog
#15 lore raw

PATCH 14/29 binman: Create README.entries

In reply to Simon Glass

Create a new README containing documentation for the entry types supported by binman. This provides an easy reference in one place. It is automatically generated from the source-code documentation.

Add a reference to this from the binman README.

---

 tools/binman/README         |   9 +
 tools/binman/README.entries | 448 ++++++++++++++++++++++++++++++++++++
 2 files changed, 457 insertions(+)
 create mode 100644 tools/binman/README.entries
tools/binman/README +9 -0
index d60c7fd6a3..cb34171e5f 100644
@@ -453,6 +453,15 @@ name-prefix:
 	distinguish binaries with otherwise identical names.
 
 
+Entry Documentation
+-------------------
+
+For details on the various entry types supported by binman and how to use them,
+see README.entries. This is generated from the source code using:
+
+	binman -E >tools/binman/README.entries
+
+
 Special properties
 ------------------
 
tools/binman/README.entries new file +448 -0

448 lines not on this page · raw message

Signature · 1 line
2.18.0.203.gfac676dfb9-goog
#16 lore raw

PATCH 15/29 binman: Add support for flashrom FMAP

In reply to Simon Glass

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.

---

 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
tools/binman/README.entries +20 -0
index 60cb2488c0..0b3be69f5e 100644
@@ -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
 -------------------------------------------------------------------------
 
tools/binman/entry.py +9 -0
index dc09b81677..8b910feff6 100644
@@ -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
 
tools/binman/etype/fmap.py new file +61 -0

61 lines not on this page · raw message

tools/binman/etype/section.py +5 -2
index 2e68f276f0..f5b2ed67cf 100644
@@ -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()
tools/binman/fmap_util.py new file +109 -0

109 lines not on this page · raw message

tools/binman/ftest.py +32 -0
index 9c01805c72..bd4de4e287 100644
@@ -21,6 +21,7 @@ import control
 import elf
 import fdt
 import fdt_util
+import fmap_util
 import test_util
 import tools
 import tout
@@ -1192,6 +1193,37 @@ class TestFunctional(unittest.TestCase):
         self.assertIn('Documentation is missing for modules: u_boot',
                       str(e.exception))
 
+    def testFmap(self):
+        """Basic test of generation of a flashrom fmap"""
+        data = self._DoReadFile('67_fmap.dts')
+        fhdr, fentries = fmap_util.DecodeFmap(data[32:])
+        expected = U_BOOT_DATA + '!' * 12 + U_BOOT_DATA + 'a' * 12
+        self.assertEqual(expected, data[:32])
+        self.assertEqual('__FMAP__', fhdr.signature)
+        self.assertEqual(1, fhdr.ver_major)
+        self.assertEqual(0, fhdr.ver_minor)
+        self.assertEqual(0, fhdr.base)
+        self.assertEqual(16 + 16 +
+                         fmap_util.FMAP_HEADER_LEN +
+                         fmap_util.FMAP_AREA_LEN * 3, fhdr.image_size)
+        self.assertEqual('FMAP', fhdr.name)
+        self.assertEqual(3, fhdr.nareas)
+        for fentry in fentries:
+            self.assertEqual(0, fentry.flags)
+
+        self.assertEqual(0, fentries[0].offset)
+        self.assertEqual(4, fentries[0].size)
+        self.assertEqual('RO_U_BOOT', fentries[0].name)
+
+        self.assertEqual(16, fentries[1].offset)
+        self.assertEqual(4, fentries[1].size)
+        self.assertEqual('RW_U_BOOT', fentries[1].name)
+
+        self.assertEqual(32, fentries[2].offset)
+        self.assertEqual(fmap_util.FMAP_HEADER_LEN +
+                         fmap_util.FMAP_AREA_LEN * 3, fentries[2].size)
+        self.assertEqual('FMAP', fentries[2].name)
+
 
 if __name__ == "__main__":
     unittest.main()
tools/binman/test/67_fmap.dts new file +29 -0
new file mode 100644
index 0000000000..9c0e293ac8
@@ -0,0 +1,29 @@
+// SPDX-License-Identifier: GPL-2.0+
+/dts-v1/;
+
+/ {
+	#address-cells = <1>;
+	#size-cells = <1>;
+
+	binman {
+		section at 0 {
+			read-only;
+			name-prefix = "ro-";
+			size = <0x10>;
+			pad-byte = <0x21>;
+
+			u-boot {
+			};
+		};
+		section at 1 {
+			name-prefix = "rw-";
+			size = <0x10>;
+			pad-byte = <0x61>;
+
+			u-boot {
+			};
+		};
+		fmap {
+		};
+	};
+};
Signature · 1 line
2.18.0.203.gfac676dfb9-goog
#17 lore raw

PATCH 16/29 binman: Add support for a cros_ec image

In reply to Simon Glass

Add an entry type which can hold a Chrome OS EC.

To make this work a new entry type is created, which supports getting a blob filename from the command line.

---

 tools/binman/README.entries                | 29 ++++++++++++++++++
 tools/binman/etype/blob_named_by_arg.py    | 34 ++++++++++++++++++++++
 tools/binman/etype/cros_ec_rw.py           | 22 ++++++++++++++
 tools/binman/ftest.py                      | 11 +++++++
 tools/binman/test/68_blob_named_by_arg.dts | 12 ++++++++
 5 files changed, 108 insertions(+)
 create mode 100644 tools/binman/etype/blob_named_by_arg.py
 create mode 100644 tools/binman/etype/cros_ec_rw.py
 create mode 100644 tools/binman/test/68_blob_named_by_arg.dts
tools/binman/README.entries +29 -0
index 0b3be69f5e..147dd40bff 100644
@@ -26,6 +26,35 @@ example the 'u_boot' entry which provides the filename 'u-boot.bin'.
 
 
 
+Entry: blob-named-by-arg: A blob entry which gets its filename property from its subclass
+-----------------------------------------------------------------------------------------
+
+Properties / Entry arguments:
+    - <xxx>-path: Filename containing the contents of this entry (optional,
+        defaults to 0)
+
+where <xxx> is the blob_fname argument to the constructor.
+
+This entry cannot be used directly. Instead, it is used as a parent class
+for another entry, which defined blob_fname. This parameter is used to
+set the entry-arg or property containing the filename. The entry-arg or
+property is in turn used to set the actual filename.
+
+See cros_ec_rw for an example of this.
+
+
+
+Entry: cros-ec-rw: A blob entry which contains a Chromium OS read-write EC image
+--------------------------------------------------------------------------------
+
+Properties / Entry arguments:
+    - cros-ec-rw-path: Filename containing the EC image
+
+This entry holds a Chromium OS EC (embedded controller) image, for use in
+updating the EC on startup via software sync.
+
+
+
 Entry: fmap: An entry which contains an Fmap section
 ----------------------------------------------------
 
tools/binman/etype/blob_named_by_arg.py new file +34 -0
new file mode 100644
index 0000000000..344112bc42
@@ -0,0 +1,34 @@
+# SPDX-License-Identifier: GPL-2.0+
+# Copyright (c) 2018 Google, Inc
+# Written by Simon Glass <[email protected]>
+#
+# Entry-type module for a blob where the filename comes from a property in the
+# node or an entry argument. The property is called '<blob_fname>-path' where
+# <blob_fname> is provided by the subclass using this entry type.
+
+from collections import OrderedDict
+
+from blob import Entry_blob
+from entry import EntryArg
+
+
+class Entry_blob_named_by_arg(Entry_blob):
+    """A blob entry which gets its filename property from its subclass
+
+    Properties / Entry arguments:
+        - <xxx>-path: Filename containing the contents of this entry (optional,
+            defaults to 0)
+
+    where <xxx> is the blob_fname argument to the constructor.
+
+    This entry cannot be used directly. Instead, it is used as a parent class
+    for another entry, which defined blob_fname. This parameter is used to
+    set the entry-arg or property containing the filename. The entry-arg or
+    property is in turn used to set the actual filename.
+
+    See cros_ec_rw for an example of this.
+    """
+    def __init__(self, section, etype, node, blob_fname):
+        Entry_blob.__init__(self, section, etype, node)
+        self._filename, = self.GetEntryArgsOrProps(
+            [EntryArg('%s-path' % blob_fname, str)])
tools/binman/etype/cros_ec_rw.py new file +22 -0
new file mode 100644
index 0000000000..261f8657a6
@@ -0,0 +1,22 @@
+# SPDX-License-Identifier: GPL-2.0+
+# Copyright (c) 2018 Google, Inc
+# Written by Simon Glass <[email protected]>
+#
+# Entry-type module for a Chromium OS EC image (read-write section)
+#
+
+from blob_named_by_arg import Entry_blob_named_by_arg
+
+
+class Entry_cros_ec_rw(Entry_blob_named_by_arg):
+    """A blob entry which contains a Chromium OS read-write EC image
+
+    Properties / Entry arguments:
+        - cros-ec-rw-path: Filename containing the EC image
+
+    This entry holds a Chromium OS EC (embedded controller) image, for use in
+    updating the EC on startup via software sync.
+    """
+    def __init__(self, section, etype, node):
+        Entry_blob_named_by_arg.__init__(self, section, etype, node,
+                                         'cros-ec-rw')
tools/binman/ftest.py +11 -0
index bd4de4e287..5428ee651a 100644
@@ -46,6 +46,8 @@ MRC_DATA              = 'mrc'
 TEXT_DATA             = 'text'
 TEXT_DATA2            = 'text2'
 TEXT_DATA3            = 'text3'
+CROS_EC_RW_DATA       = 'ecrw'
+
 
 class TestFunctional(unittest.TestCase):
     """Functional tests for binman
@@ -92,6 +94,7 @@ class TestFunctional(unittest.TestCase):
         TestFunctional._MakeInputFile('cmc.bin', CMC_DATA)
         TestFunctional._MakeInputFile('vbt.bin', VBT_DATA)
         TestFunctional._MakeInputFile('mrc.bin', MRC_DATA)
+        TestFunctional._MakeInputFile('ecrw.bin', CROS_EC_RW_DATA)
         self._output_setup = False
 
         # ELF file with a '_dt_ucode_base_size' symbol
@@ -1224,6 +1227,14 @@ class TestFunctional(unittest.TestCase):
                          fmap_util.FMAP_AREA_LEN * 3, fentries[2].size)
         self.assertEqual('FMAP', fentries[2].name)
 
+    def testBlobNamedByArg(self):
+        """Test we can add a blob with the filename coming from an entry arg"""
+        entry_args = {
+            'cros-ec-rw-path': 'ecrw.bin',
+        }
+        data, _, _, _ = self._DoReadFileDtb('68_blob_named_by_arg.dts',
+                                            entry_args=entry_args)
+
 
 if __name__ == "__main__":
     unittest.main()
tools/binman/test/68_blob_named_by_arg.dts new file +12 -0
new file mode 100644
index 0000000000..e129f843cd
@@ -0,0 +1,12 @@
+// SPDX-License-Identifier: GPL-2.0+
+/dts-v1/;
+
+/ {
+	#address-cells = <1>;
+	#size-cells = <1>;
+
+	binman {
+		cros-ec-rw {
+		};
+	};
+};
Signature · 1 line
2.18.0.203.gfac676dfb9-goog
#18 lore raw

PATCH 17/29 binman: Add an entry filled with a repeating byte

In reply to Simon Glass

It is sometimes useful to have an area of the image which is all zeroes, or all 0xff. This can often be achieved by padding the size of an an existing entry and setting the pad byte for an entry or image.

But it is useful to have an explicit means of adding blocks of repeating data to the image. Add a 'fill' entry type to handle this.

---

 tools/binman/README.entries           | 16 ++++++++++++++
 tools/binman/etype/fill.py            | 32 +++++++++++++++++++++++++++
 tools/binman/ftest.py                 | 13 +++++++++++
 tools/binman/test/69_fill.dts         | 15 +++++++++++++
 tools/binman/test/70_fill_no_size.dts | 14 ++++++++++++
 tools/dtoc/fdt_util.py                | 23 +++++++++++++++++++
 tools/dtoc/test_fdt.py                | 15 ++++++++++++-
 7 files changed, 127 insertions(+), 1 deletion(-)
 create mode 100644 tools/binman/etype/fill.py
 create mode 100644 tools/binman/test/69_fill.dts
 create mode 100644 tools/binman/test/70_fill_no_size.dts
tools/binman/README.entries +16 -0
index 147dd40bff..6f09626b24 100644
@@ -55,6 +55,22 @@ updating the EC on startup via software sync.
 
 
 
+Entry: fill: An entry which is filled to a particular byte value
+----------------------------------------------------------------
+
+Properties / Entry arguments:
+    - fill-byte: Byte to use to fill the entry
+
+Note that the size property must be set since otherwise this entry does not
+know how large it should be.
+
+You can often achieve the same effect using the pad-byte property of the
+overall image, in that the space between entries will then be padded with
+that byte. But this entry is sometimes useful for explicitly setting the
+byte value of a region.
+
+
+
 Entry: fmap: An entry which contains an Fmap section
 ----------------------------------------------------
 
tools/binman/etype/fill.py new file +32 -0
new file mode 100644
index 0000000000..7210a8324a
@@ -0,0 +1,32 @@
+# SPDX-License-Identifier: GPL-2.0+
+# Copyright (c) 2018 Google, Inc
+# Written by Simon Glass <[email protected]>
+#
+
+from entry import Entry
+import fdt_util
+
+
+class Entry_fill(Entry):
+    """An entry which is filled to a particular byte value
+
+    Properties / Entry arguments:
+        - fill-byte: Byte to use to fill the entry
+
+    Note that the size property must be set since otherwise this entry does not
+    know how large it should be.
+
+    You can often achieve the same effect using the pad-byte property of the
+    overall image, in that the space between entries will then be padded with
+    that byte. But this entry is sometimes useful for explicitly setting the
+    byte value of a region.
+    """
+    def __init__(self, section, etype, node):
+        Entry.__init__(self, section, etype, node)
+        if not self.size:
+            self.Raise("'fill' entry must have a size property")
+        self.fill_value = fdt_util.GetByte(self._node, 'fill-byte', 0)
+
+    def ObtainContents(self):
+        self.SetContents(chr(self.fill_value) * self.size)
+        return True
tools/binman/ftest.py +13 -0
index 5428ee651a..4e467145d7 100644
@@ -1235,6 +1235,19 @@ class TestFunctional(unittest.TestCase):
         data, _, _, _ = self._DoReadFileDtb('68_blob_named_by_arg.dts',
                                             entry_args=entry_args)
 
+    def testFill(self):
+        """Test for an fill entry type"""
+        data = self._DoReadFile('69_fill.dts')
+        expected = 8 * chr(0xff) + 8 * chr(0)
+        self.assertEqual(expected, data)
+
+    def testFillNoSize(self):
+        """Test for an fill entry type with no size"""
+        with self.assertRaises(ValueError) as e:
+            self._DoReadFile('70_fill_no_size.dts')
+        self.assertIn("'fill' entry must have a size property",
+                      str(e.exception))
+
 
 if __name__ == "__main__":
     unittest.main()
tools/binman/test/69_fill.dts new file +15 -0
new file mode 100644
index 0000000000..e372ea37aa
@@ -0,0 +1,15 @@
+// SPDX-License-Identifier: GPL-2.0+
+/dts-v1/;
+
+/ {
+	#address-cells = <1>;
+	#size-cells = <1>;
+
+	binman {
+		size = <16>;
+		fill {
+			size = <8>;
+			fill-byte = [ff];
+		};
+	};
+};
tools/binman/test/70_fill_no_size.dts new file +14 -0
new file mode 100644
index 0000000000..7b1fcf1b68
@@ -0,0 +1,14 @@
+// SPDX-License-Identifier: GPL-2.0+
+/dts-v1/;
+
+/ {
+	#address-cells = <1>;
+	#size-cells = <1>;
+
+	binman {
+		size = <16>;
+		fill {
+			fill-byte = [ff];
+		};
+	};
+};
tools/dtoc/fdt_util.py +23 -0
index b229038569..d762f93a9a 100644
@@ -148,6 +148,29 @@ def GetBool(node, propname, default=False):
         return True
     return default
 
+def GetByte(node, propname, default=None):
+    """Get an byte from a property
+
+    Args:
+        node: Node object to read from
+        propname: property name to read
+        default: Default value to use if the node/property do not exist
+
+    Returns:
+        Byte value read, or default if none
+    """
+    prop = node.props.get(propname)
+    if not prop:
+        return default
+    value = prop.value
+    if isinstance(value, list):
+        raise ValueError("Node '%s' property '%s' has list value: expecting "
+                         "a single byte" % (node.name, propname))
+    if len(value) != 1:
+        raise ValueError("Node '%s' property '%s' has length %d, expecting %d" %
+                         (node.name, propname, len(value), 1))
+    return ord(value[0])
+
 def GetDatatype(node, propname, datatype):
     """Get a value of a given type from a property
 
tools/dtoc/test_fdt.py +14 -1
index 03cf4b4f7c..38e1732f52 100755
@@ -380,6 +380,20 @@ class TestFdtUtil(unittest.TestCase):
         self.assertEqual(True, fdt_util.GetBool(self.node, 'missing', True))
         self.assertEqual(False, fdt_util.GetBool(self.node, 'missing', False))
 
+    def testGetByte(self):
+        self.assertEqual(5, fdt_util.GetByte(self.node, 'byteval'))
+        self.assertEqual(3, fdt_util.GetByte(self.node, 'missing', 3))
+
+        with self.assertRaises(ValueError) as e:
+            fdt_util.GetByte(self.node, 'longbytearray')
+        self.assertIn("property 'longbytearray' has list value: expecting a "
+                      'single byte', str(e.exception))
+
+        with self.assertRaises(ValueError) as e:
+            fdt_util.GetByte(self.node, 'intval')
+        self.assertIn("property 'intval' has length 4, expecting 1",
+                      str(e.exception))
+
     def testGetDataType(self):
         self.assertEqual(1, fdt_util.GetDatatype(self.node, 'intval', int))
         self.assertEqual('message', fdt_util.GetDatatype(self.node, 'stringval',
@@ -387,7 +401,6 @@ class TestFdtUtil(unittest.TestCase):
         with self.assertRaises(ValueError) as e:
             self.assertEqual(3, fdt_util.GetDatatype(self.node, 'boolval',
                                                      bool))
-
     def testFdtCellsToCpu(self):
         val = self.node.props['intarray'].value
         self.assertEqual(0, fdt_util.fdt_cells_to_cpu(val, 0))
Signature · 1 line
2.18.0.203.gfac676dfb9-goog
#19 lore raw

PATCH 18/29 dtoc: Export the _FindNode() function

In reply to Simon Glass

This is useful for clients that want to find a node. Export it so it can be used by others.

---

 tools/dtoc/fdt.py      | 4 ++--
 tools/dtoc/test_fdt.py | 8 ++++----
 2 files changed, 6 insertions(+), 6 deletions(-)
tools/dtoc/fdt.py +2 -2
index 9d69b426c1..01e39b8a2a 100644
@@ -181,7 +181,7 @@ class Node:
         self.subnodes = []
         self.props = {}
 
-    def _FindNode(self, name):
+    def FindNode(self, name):
         """Find a node given its name
 
         Args:
@@ -349,7 +349,7 @@ class Fdt:
         if len(parts) < 2:
             return None
         for part in parts[1:]:
-            node = node._FindNode(part)
+            node = node.FindNode(part)
             if not node:
                 return None
         return node
tools/dtoc/test_fdt.py +4 -4
index 38e1732f52..abec9e57e1 100755
@@ -155,12 +155,12 @@ class TestNode(unittest.TestCase):
         self.assertEqual(prop.value, value)
 
     def testFindNode(self):
-        """Tests that we can find a node using the _FindNode() functoin"""
-        node = self.dtb.GetRoot()._FindNode('i2c at 0')
+        """Tests that we can find a node using the FindNode() functoin"""
+        node = self.dtb.GetRoot().FindNode('i2c at 0')
         self.assertEqual('i2c at 0', node.name)
-        subnode = node._FindNode('pmic at 9')
+        subnode = node.FindNode('pmic at 9')
         self.assertEqual('pmic@9', subnode.name)
-        self.assertEqual(None, node._FindNode('missing'))
+        self.assertEqual(None, node.FindNode('missing'))
 
     def testRefreshMissingNode(self):
         """Test refreshing offsets when an extra node is present in dtb"""
Signature · 1 line
2.18.0.203.gfac676dfb9-goog
#20 lore raw

PATCH 19/29 patman: Allow test commands to fall back to real ones

In reply to Simon Glass

Tests use the 'test_result' feature to return a predetermined command result for particular commands. The avoids needing to have the real command available just to run a test. It works by calling the function provided by the test, to get the value.

However sometimes the test does need to run the real command. Allow it to fall back to do this when the function does not return a result.

---

 tools/patman/command.py | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)
tools/patman/command.py +6 -2
index 598bfdcd90..14edcdaffd 100644
@@ -61,8 +61,12 @@ def RunPipe(pipe_list, infile=None, outfile=None,
     """
     if test_result:
         if hasattr(test_result, '__call__'):
-            return test_result(pipe_list=pipe_list)
-        return test_result
+            result = test_result(pipe_list=pipe_list)
+            if result:
+                return result
+        else:
+            return test_result
+        # No result: fall through to normal processing
     result = CommandResult()
     last_pipe = None
     pipeline = list(pipe_list)
Signature · 1 line
2.18.0.203.gfac676dfb9-goog
#21 lore raw

PATCH 20/29 patman: Add a few more helpers to the tools library

In reply to Simon Glass

Add functions to read and write a file, looking through a list of search paths to find it.

---

 tools/patman/tools.py | 76 ++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 75 insertions(+), 1 deletion(-)
tools/patman/tools.py +75 -1
index 700cb4505d..006306bd60 100644
@@ -3,16 +3,26 @@
 # Copyright (c) 2016 Google, Inc
 #
 
+import command
 import os
 import shutil
 import tempfile
 
 import tout
 
+# Output directly (generally this is temporary)
 outdir = None
-indirs = None
+
+# True to keep the output directory around after exiting
 preserve_outdir = False
 
+# Path to the Chrome OS chroot, if we know it
+chroot_path = None
+
+# Search paths to use for Filename(), used to find files
+search_paths = []
+
+
 def PrepareOutputDir(dirname, preserve=False):
     """Select an output directory, ensuring it exists.
 
@@ -117,3 +127,67 @@ def Align(pos, align):
 
 def NotPowerOfTwo(num):
     return num and (num & (num - 1))
+
+def Run(name, *args):
+    command.Run(name, *args, cwd=outdir)
+
+def Filename(fname):
+    """Resolve a file path to an absolute path.
+
+    If fname starts with ##/ and chroot is available, ##/ gets replaced with
+    the chroot path. If chroot is not available, this file name can not be
+    resolved, `None' is returned.
+
+    If fname is not prepended with the above prefix, and is not an existing
+    file, the actual file name is retrieved from the passed in string and the
+    search_paths directories (if any) are searched to for the file. If found -
+    the path to the found file is returned, `None' is returned otherwise.
+
+    Args:
+      fname: a string,  the path to resolve.
+
+    Returns:
+      Absolute path to the file or None if not found.
+    """
+    if fname.startswith('##/'):
+      if chroot_path:
+        fname = os.path.join(chroot_path, fname[3:])
+      else:
+        return None
+
+    # Search for a pathname that exists, and return it if found
+    if fname and not os.path.exists(fname):
+        for path in search_paths:
+            pathname = os.path.join(path, os.path.basename(fname))
+            if os.path.exists(pathname):
+                return pathname
+
+    # If not found, just return the standard, unchanged path
+    return fname
+
+def ReadFile(fname):
+    """Read and return the contents of a file.
+
+    Args:
+      fname: path to filename to read, where ## signifiies the chroot.
+
+    Returns:
+      data read from file, as a string.
+    """
+    with open(Filename(fname), 'rb') as fd:
+        data = fd.read()
+    #self._out.Info("Read file '%s' size %d (%#0x)" %
+                   #(fname, len(data), len(data)))
+    return data
+
+def WriteFile(fname, data):
+    """Write data into a file.
+
+    Args:
+        fname: path to filename to write
+        data: data to write to file, as a string
+    """
+    #self._out.Info("Write file '%s' size %d (%#0x)" %
+                   #(fname, len(data), len(data)))
+    with open(Filename(fname), 'wb') as fd:
+        fd.write(data)
Signature · 1 line
2.18.0.203.gfac676dfb9-goog
#22 lore raw

PATCH 21/29 binman: Add support for Chromium GBB

In reply to Simon Glass

This entry contains a Google Binary Block, used to store keys and bitmaps in a Chromium image.

---

 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
tools/binman/README.entries +19 -0
index 6f09626b24..41b70192c0 100644
@@ -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
 -------------------------------------------------------------------------
 
tools/binman/etype/gbb.py new file +96 -0

96 lines not on this page · raw message

tools/binman/ftest.py +56 -0

80 lines not on this page · raw message

tools/binman/test/71_gbb.dts new file +31 -0
new file mode 100644
index 0000000000..551756372a
@@ -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;
+			};
+		};
+	};
+};
tools/binman/test/72_gbb_too_small.dts new file +10 -0
new file mode 100644
index 0000000000..c088f36a1d
@@ -0,0 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0+
+/dts-v1/;
+
+/ {
+	binman {
+		gbb {
+			size = <0x200>;
+		};
+	};
+};
tools/binman/test/73_gbb_no_size.dts new file +9 -0
new file mode 100644
index 0000000000..83be403785
@@ -0,0 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0+
+/dts-v1/;
+
+/ {
+	binman {
+		gbb {
+		};
+	};
+};
Signature · 1 line
2.18.0.203.gfac676dfb9-goog
#23 lore raw

PATCH 22/29 patman: Show the current directory in GetInputFilename()

In reply to Simon Glass

When this fails it is useful to see the current directory, since U-Boot's build system will typically change into the output directory during the build. Add this information to the error.

---

 tools/patman/tools.py | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
tools/patman/tools.py +2 -2
index 006306bd60..e80481438b 100644
@@ -116,8 +116,8 @@ def GetInputFilename(fname):
         if os.path.exists(pathname):
             return pathname
 
-    raise ValueError("Filename '%s' not found in input path (%s)" %
-                     (fname, ','.join(indir)))
+    raise ValueError("Filename '%s' not found in input path (%s) (cwd='%s')" %
+                     (fname, ','.join(indir), os.getcwd()))
 
 def Align(pos, align):
     if align:
Signature · 1 line
2.18.0.203.gfac676dfb9-goog
#24 lore raw

PATCH 23/29 dtoc: Add a function to obtain a list of phandles

In reply to Simon Glass

Add a function which can decode a property containing a list of phandles. This is useful for finding nodes linked to a property. Also provide a way to look up a single phandle and get the Fdt object from a Node.

---

 tools/dtoc/fdt.py      | 19 +++++++++++++++++++
 tools/dtoc/fdt_util.py | 18 ++++++++++++++++++
 tools/dtoc/test_fdt.py | 20 ++++++++++++++++++++
 3 files changed, 57 insertions(+)
tools/dtoc/fdt.py +19 -0
index 01e39b8a2a..d36179bad3 100644
@@ -181,6 +181,14 @@ class Node:
         self.subnodes = []
         self.props = {}
 
+    def GetFdt(self):
+        """Get the Fdt object for this node
+
+        Returns:
+            Fdt object
+        """
+        return self._fdt
+
     def FindNode(self, name):
         """Find a node given its name
 
@@ -314,6 +322,17 @@ class Fdt:
             with open(self._fname) as fd:
                 self._fdt_obj = libfdt.Fdt(fd.read())
 
+    def LookupPhandle(self, phandle):
+        """Look up a phandle
+
+        Args:
+            phandle: Phandle to look up (int)
+
+        Returns:
+            Node object the phandle points to
+        """
+        return self.phandle_to_node.get(phandle)
+
     def Scan(self, root='/'):
         """Scan a device tree, building up a tree of Node objects
 
tools/dtoc/fdt_util.py +18 -0
index d762f93a9a..5fbfc8877b 100644
@@ -171,6 +171,24 @@ def GetByte(node, propname, default=None):
                          (node.name, propname, len(value), 1))
     return ord(value[0])
 
+def GetPhandleList(node, propname):
+    """Get a list of phandles from a property
+
+    Args:
+        node: Node object to read from
+        propname: property name to read
+
+    Returns:
+        List of phandles read, each an integer
+    """
+    prop = node.props.get(propname)
+    if not prop:
+        return None
+    value = prop.value
+    if not isinstance(value, list):
+        value = [value]
+    return [fdt32_to_cpu(v) for v in value]
+
 def GetDatatype(node, propname, datatype):
     """Get a value of a given type from a property
 
tools/dtoc/test_fdt.py +20 -0
index abec9e57e1..6fe03ac53d 100755
@@ -115,6 +115,9 @@ class TestFdt(unittest.TestCase):
             fdt.CheckErr(-libfdt.NOTFOUND, 'hello')
         self.assertIn('FDT_ERR_NOTFOUND: hello', str(e.exception))
 
+    def testGetFdt(self):
+        node = self.dtb.GetNode('/spl-test')
+        self.assertEqual(self.dtb, node.GetFdt())
 
 class TestNode(unittest.TestCase):
     """Test operation of the Node class"""
@@ -188,6 +191,14 @@ class TestNode(unittest.TestCase):
         self.assertIn("Internal error, property 'notstring' missing, offset ",
                       str(e.exception))
 
+    def testLookupPhandle(self):
+        """Test looking up a single phandle"""
+        dtb = fdt.FdtScan('tools/dtoc/dtoc_test_phandle.dts')
+        node = dtb.GetNode('/phandle-source2')
+        prop = node.props['clocks']
+        target = dtb.GetNode('/phandle-target')
+        self.assertEqual(target, dtb.LookupPhandle(fdt32_to_cpu(prop.value)))
+
 
 class TestProp(unittest.TestCase):
     """Test operation of the Prop class"""
@@ -394,6 +405,15 @@ class TestFdtUtil(unittest.TestCase):
         self.assertIn("property 'intval' has length 4, expecting 1",
                       str(e.exception))
 
+    def testGetPhandleList(self):
+        dtb = fdt.FdtScan('tools/dtoc/dtoc_test_phandle.dts')
+        node = dtb.GetNode('/phandle-source2')
+        self.assertEqual([1], fdt_util.GetPhandleList(node, 'clocks'))
+        node = dtb.GetNode('/phandle-source')
+        self.assertEqual([1, 2, 11, 3, 12, 13, 1],
+                         fdt_util.GetPhandleList(node, 'clocks'))
+        self.assertEqual(None, fdt_util.GetPhandleList(node, 'missing'))
+
     def testGetDataType(self):
         self.assertEqual(1, fdt_util.GetDatatype(self.node, 'intval', int))
         self.assertEqual('message', fdt_util.GetDatatype(self.node, 'stringval',
Signature · 1 line
2.18.0.203.gfac676dfb9-goog
#25 lore raw

PATCH 24/29 binman: Add an entry for a Chromium vblock

In reply to Simon Glass

This adds support for a Chromium verified boot block, used to sign a read-write section of the image.

---

 tools/binman/README.entries                 | 17 +++++
 tools/binman/bsection.py                    | 24 +++++++
 tools/binman/entry.py                       |  2 +-
 tools/binman/etype/vblock.py                | 74 +++++++++++++++++++++
 tools/binman/ftest.py                       | 41 ++++++++++++
 tools/binman/test/74_vblock.dts             | 28 ++++++++
 tools/binman/test/75_vblock_no_content.dts  | 23 +++++++
 tools/binman/test/76_vblock_bad_phandle.dts | 24 +++++++
 tools/binman/test/77_vblock_bad_entry.dts   | 27 ++++++++
 9 files changed, 259 insertions(+), 1 deletion(-)
 create mode 100644 tools/binman/etype/vblock.py
 create mode 100644 tools/binman/test/74_vblock.dts
 create mode 100644 tools/binman/test/75_vblock_no_content.dts
 create mode 100644 tools/binman/test/76_vblock_bad_phandle.dts
 create mode 100644 tools/binman/test/77_vblock_bad_entry.dts
tools/binman/README.entries +17 -0
index 41b70192c0..1b75ca0052 100644
@@ -496,6 +496,23 @@ complicated. Otherwise it is the same as the u_boot entry.
 
 
 
+Entry: vblock: An entry which contains a Chromium OS verified boot block
+------------------------------------------------------------------------
+
+Properties / Entry arguments:
+    - keydir: Directory containing the public keys to use
+    - keyblock: Name of the key file to use (inside keydir)
+    - signprivate: Name of provide key file to use (inside keydir)
+    - version: Version number of the vblock (typically 1)
+    - kernelkey: Name of the kernel key to use (inside keydir)
+    - preamble-flags: Value of the vboot preamble flags (typically 0)
+
+Chromium OS  signs the read-write firmware and kernel, writing the signature
+in this block. This allows U-Boot to verify that the next firmware stage
+and kernel are genuine.
+
+
+
 Entry: x86-start16: x86 16-bit start-up code for U-Boot
 -------------------------------------------------------
 
tools/binman/bsection.py +24 -0
index 47fe37ccb9..f3a95fda8e 100644
@@ -379,3 +379,27 @@ class Section(object):
         Entry.WriteMapLine(fd, indent, self._name, self._offset, self._size)
         for entry in self._entries.values():
             entry.WriteMap(fd, indent + 1)
+
+    def GetContentsByPhandle(self, phandle, source_entry):
+        """Get the data contents of an entry specified by a phandle
+
+        This uses a phandle to look up a node and and find the entry
+        associated with it. Then it returnst he contents of that entry.
+
+        Args:
+            phandle: Phandle to look up (integer)
+            source_entry: Entry containing that phandle (used for error
+                reporting)
+
+        Returns:
+            data from associated entry (as a string), or None if not found
+        """
+        node = self._node.GetFdt().LookupPhandle(phandle)
+        if not node:
+            source_entry.Raise("Cannot find node for phandle %d" % phandle)
+        for entry in self._entries.values():
+            if entry._node == node:
+                if entry.data is None:
+                    return None
+                return entry.data
+        source_entry.Raise("Cannot find entry for node '%s'" % node.name)
tools/binman/entry.py +1 -1
index 8b910feff6..996f03e3a6 100644
@@ -65,7 +65,7 @@ class Entry(object):
         self.name = node and (name_prefix + node.name) or 'none'
         self.offset = None
         self.size = None
-        self.data = ''
+        self.data = None
         self.contents_size = 0
         self.align = None
         self.align_size = None
tools/binman/etype/vblock.py new file +74 -0

74 lines not on this page · raw message

tools/binman/ftest.py +41 -0

53 lines not on this page · raw message

tools/binman/test/74_vblock.dts new file +28 -0
new file mode 100644
index 0000000000..f0c21bfe9f
@@ -0,0 +1,28 @@
+// SPDX-License-Identifier: GPL-2.0+
+/dts-v1/;
+
+/ {
+	#address-cells = <1>;
+	#size-cells = <1>;
+
+	binman {
+		u_boot: u-boot {
+		};
+
+		vblock {
+			content = <&u_boot &dtb>;
+			keyblock = "firmware.keyblock";
+			signprivate = "firmware_data_key.vbprivk";
+			version = <1>;
+			kernelkey = "kernel_subkey.vbpubk";
+			preamble-flags = <1>;
+		};
+
+		/*
+		 * Put this after the vblock so that its contents are not
+		 * available when the vblock first tries to obtain its contents
+		 */
+		dtb: u-boot-dtb {
+		};
+	};
+};
tools/binman/test/75_vblock_no_content.dts new file +23 -0
new file mode 100644
index 0000000000..676d9474b3
@@ -0,0 +1,23 @@
+// SPDX-License-Identifier: GPL-2.0+
+/dts-v1/;
+
+/ {
+	#address-cells = <1>;
+	#size-cells = <1>;
+
+	binman {
+		u_boot: u-boot {
+		};
+
+		vblock {
+			keyblock = "firmware.keyblock";
+			signprivate = "firmware_data_key.vbprivk";
+			version = <1>;
+			kernelkey = "kernel_subkey.vbpubk";
+			preamble-flags = <1>;
+		};
+
+		dtb: u-boot-dtb {
+		};
+	};
+};
tools/binman/test/76_vblock_bad_phandle.dts new file +24 -0
new file mode 100644
index 0000000000..ffbd0c335c
@@ -0,0 +1,24 @@
+// SPDX-License-Identifier: GPL-2.0+
+/dts-v1/;
+
+/ {
+	#address-cells = <1>;
+	#size-cells = <1>;
+
+	binman {
+		u_boot: u-boot {
+		};
+
+		vblock {
+			content = <1000>;
+			keyblock = "firmware.keyblock";
+			signprivate = "firmware_data_key.vbprivk";
+			version = <1>;
+			kernelkey = "kernel_subkey.vbpubk";
+			preamble-flags = <1>;
+		};
+
+		dtb: u-boot-dtb {
+		};
+	};
+};
tools/binman/test/77_vblock_bad_entry.dts new file +27 -0
new file mode 100644
index 0000000000..764c42a56e
@@ -0,0 +1,27 @@
+// SPDX-License-Identifier: GPL-2.0+
+/dts-v1/;
+
+/ {
+	#address-cells = <1>;
+	#size-cells = <1>;
+
+	binman {
+		u_boot: u-boot {
+		};
+
+		vblock {
+			content = <&u_boot &other>;
+			keyblock = "firmware.keyblock";
+			signprivate = "firmware_data_key.vbprivk";
+			version = <1>;
+			kernelkey = "kernel_subkey.vbpubk";
+			preamble-flags = <1>;
+		};
+
+		dtb: u-boot-dtb {
+		};
+	};
+
+	other: other {
+	};
+};
Signature · 1 line
2.18.0.203.gfac676dfb9-goog
#26 lore raw

PATCH 25/29 binman: Add support for adding TPL binaries

In reply to Simon Glass

Add support for U-Boot's TPL and TPL device tree. Also fix a few comments in the other device-tree entries.

---

 tools/binman/README.entries          | 38 +++++++++++++++++++++++-
 tools/binman/etype/u_boot_spl.py     |  2 +-
 tools/binman/etype/u_boot_spl_dtb.py |  2 +-
 tools/binman/etype/u_boot_tpl.py     | 43 ++++++++++++++++++++++++++++
 tools/binman/etype/u_boot_tpl_dtb.py | 25 ++++++++++++++++
 tools/binman/ftest.py                | 22 ++++++++++++--
 tools/binman/test/78_u_boot_tpl.dts  | 11 +++++++
 7 files changed, 137 insertions(+), 6 deletions(-)
 create mode 100644 tools/binman/etype/u_boot_tpl.py
 create mode 100644 tools/binman/etype/u_boot_tpl_dtb.py
 create mode 100644 tools/binman/test/78_u_boot_tpl.dts
tools/binman/README.entries +37 -1
index 1b75ca0052..c6e7b22609 100644
@@ -365,7 +365,7 @@ This is the U-Boot SPL (Secondary Program Loader) binary. This is a small
 binary which loads before U-Boot proper, typically into on-chip SRAM. It is
 responsible for locating, loading and jumping to U-Boot. Note that SPL is
 not relocatable so must be loaded to the correct address in SRAM, or written
-to run from the correct address is direct flash execution is possible (e.g.
+to run from the correct address if direct flash execution is possible (e.g.
 on x86 devices).
 
 SPL can access binman symbols at runtime. See:
@@ -433,6 +433,42 @@ process.
 
 
 
+Entry: u-boot-tpl: U-Boot TPL binary
+------------------------------------
+
+Properties / Entry arguments:
+    - filename: Filename of u-boot-tpl.bin (default 'tpl/u-boot-tpl.bin')
+
+This is the U-Boot TPL (Tertiary Program Loader) binary. This is a small
+binary which loads before SPL, typically into on-chip SRAM. It is
+responsible for locating, loading and jumping to SPL, the next-stage
+loader. Note that SPL is not relocatable so must be loaded to the correct
+address in SRAM, or written to run from the correct address if direct
+flash execution is possible (e.g. on x86 devices).
+
+SPL can access binman symbols at runtime. See:
+
+    'Access to binman entry offsets at run time (symbols)'
+
+in the binman README for more information.
+
+The ELF file 'tpl/u-boot-tpl' must also be available for this to work, since
+binman uses that to look up symbols to write into the TPL binary.
+
+
+
+Entry: u-boot-tpl-dtb: U-Boot TPL device tree
+---------------------------------------------
+
+Properties / Entry arguments:
+    - filename: Filename of u-boot.dtb (default 'tpl/u-boot-tpl.dtb')
+
+This is the TPL device tree, containing configuration information for
+TPL. TPL needs this to know what devices are present and which drivers
+to activate.
+
+
+
 Entry: u-boot-ucode: U-Boot microcode block
 -------------------------------------------
 
tools/binman/etype/u_boot_spl.py +1 -1
index 0e99a2d2a7..ab78714c8d 100644
@@ -20,7 +20,7 @@ class Entry_u_boot_spl(Entry_blob):
     binary which loads before U-Boot proper, typically into on-chip SRAM. It is
     responsible for locating, loading and jumping to U-Boot. Note that SPL is
     not relocatable so must be loaded to the correct address in SRAM, or written
-    to run from the correct address is direct flash execution is possible (e.g.
+    to run from the correct address if direct flash execution is possible (e.g.
     on x86 devices).
 
     SPL can access binman symbols at runtime. See:
tools/binman/etype/u_boot_spl_dtb.py +1 -1
index 6a30edc83c..cb29ba3fd8 100644
@@ -2,7 +2,7 @@
 # Copyright (c) 2016 Google, Inc
 # Written by Simon Glass <[email protected]>
 #
-# Entry-type module for U-Boot device tree
+# Entry-type module for U-Boot device tree in SPL (Secondary Program Loader)
 #
 
 from entry import Entry
tools/binman/etype/u_boot_tpl.py new file +43 -0

43 lines not on this page · raw message

tools/binman/etype/u_boot_tpl_dtb.py new file +25 -0
new file mode 100644
index 0000000000..9c4e668347
@@ -0,0 +1,25 @@
+# SPDX-License-Identifier: GPL-2.0+
+# Copyright (c) 2018 Google, Inc
+# Written by Simon Glass <[email protected]>
+#
+# Entry-type module for U-Boot device tree in TPL (Tertiary Program Loader)
+#
+
+from entry import Entry
+from blob import Entry_blob
+
+class Entry_u_boot_tpl_dtb(Entry_blob):
+    """U-Boot TPL device tree
+
+    Properties / Entry arguments:
+        - filename: Filename of u-boot.dtb (default 'tpl/u-boot-tpl.dtb')
+
+    This is the TPL device tree, containing configuration information for
+    TPL. TPL needs this to know what devices are present and which drivers
+    to activate.
+    """
+    def __init__(self, section, etype, node):
+        Entry_blob.__init__(self, section, etype, node)
+
+    def GetDefaultFilename(self):
+        return 'tpl/u-boot-tpl.dtb'
tools/binman/ftest.py +19 -3
index a6de4cb93b..d09868588c 100644
@@ -30,11 +30,13 @@ import tout
 U_BOOT_DATA           = '1234'
 U_BOOT_IMG_DATA       = 'img'
 U_BOOT_SPL_DATA       = '56780123456789abcde'
+U_BOOT_TPL_DATA       = 'tpl'
 BLOB_DATA             = '89'
 ME_DATA               = '0abcd'
 VGA_DATA              = 'vga'
 U_BOOT_DTB_DATA       = 'udtb'
 U_BOOT_SPL_DTB_DATA   = 'spldtb'
+U_BOOT_TPL_DTB_DATA   = 'tpldtb'
 X86_START16_DATA      = 'start16'
 X86_START16_SPL_DATA  = 'start16spl'
 U_BOOT_NODTB_DATA     = 'nodtb with microcode pointer somewhere in here'
@@ -82,11 +84,11 @@ class TestFunctional(unittest.TestCase):
         TestFunctional._MakeInputFile('u-boot.bin', U_BOOT_DATA)
         TestFunctional._MakeInputFile('u-boot.img', U_BOOT_IMG_DATA)
         TestFunctional._MakeInputFile('spl/u-boot-spl.bin', U_BOOT_SPL_DATA)
+        TestFunctional._MakeInputFile('tpl/u-boot-tpl.bin', U_BOOT_TPL_DATA)
         TestFunctional._MakeInputFile('blobfile', BLOB_DATA)
         TestFunctional._MakeInputFile('me.bin', ME_DATA)
         TestFunctional._MakeInputFile('vga.bin', VGA_DATA)
-        TestFunctional._MakeInputFile('u-boot.dtb', U_BOOT_DTB_DATA)
-        TestFunctional._MakeInputFile('spl/u-boot-spl.dtb', U_BOOT_SPL_DTB_DATA)
+        self._ResetDtbs()
         TestFunctional._MakeInputFile('u-boot-x86-16bit.bin', X86_START16_DATA)
         TestFunctional._MakeInputFile('spl/u-boot-x86-16bit-spl.bin',
                                       X86_START16_SPL_DATA)
@@ -126,6 +128,12 @@ class TestFunctional(unittest.TestCase):
         """Remove the temporary output directory"""
         tools._FinaliseForTest()
 
+    @classmethod
+    def _ResetDtbs(self):
+        TestFunctional._MakeInputFile('u-boot.dtb', U_BOOT_DTB_DATA)
+        TestFunctional._MakeInputFile('spl/u-boot-spl.dtb', U_BOOT_SPL_DTB_DATA)
+        TestFunctional._MakeInputFile('tpl/u-boot-tpl.dtb', U_BOOT_TPL_DTB_DATA)
+
     def _RunBinman(self, *args, **kwargs):
         """Run binman using the command line
 
@@ -257,7 +265,7 @@ class TestFunctional(unittest.TestCase):
         finally:
             # Put the test file back
             if use_real_dtb:
-                TestFunctional._MakeInputFile('u-boot.dtb', U_BOOT_DTB_DATA)
+                self._ResetDtbs()
 
     def _DoReadFile(self, fname, use_real_dtb=False):
         """Helper function which discards the device-tree binary
@@ -1345,6 +1353,14 @@ class TestFunctional(unittest.TestCase):
         self.assertIn("Node '/binman/vblock': Cannot find entry for node "
                       "'other'", str(e.exception))
 
+    def testTpl(self):
+        """Test that an image with TPL and ots device tree can be created"""
+        # ELF file with a '__bss_size' symbol
+        with open(self.TestFile('bss_data')) as fd:
+            TestFunctional._MakeInputFile('tpl/u-boot-tpl', fd.read())
+        data = self._DoReadFile('78_u_boot_tpl.dts')
+        self.assertEqual(U_BOOT_TPL_DATA + U_BOOT_TPL_DTB_DATA, data)
+
 
 if __name__ == "__main__":
     unittest.main()
tools/binman/test/78_u_boot_tpl.dts new file +11 -0
new file mode 100644
index 0000000000..6c60b4c46f
@@ -0,0 +1,11 @@
+// SPDX-License-Identifier: GPL-2.0+
+/dts-v1/;
+
+/ {
+	binman {
+		u-boot-tpl {
+		};
+		u-boot-tpl-dtb {
+		};
+	};
+};
Signature · 1 line
2.18.0.203.gfac676dfb9-goog
#27 lore raw

PATCH 26/29 binman: Show the image position in the map

In reply to Simon Glass

At present the map only shows the offset and size for each region. The image position provides the actual position of each entry in the image, regardless of the section hierarchy.

Add the image position to the map.

---

 tools/binman/bsection.py |  3 ++-
 tools/binman/entry.py    |  8 +++++---
 tools/binman/ftest.py    | 28 ++++++++++++++--------------
 tools/binman/image.py    |  3 ++-
 4 files changed, 23 insertions(+), 19 deletions(-)
tools/binman/bsection.py +2 -1
index f3a95fda8e..30c8f307a8 100644
@@ -376,7 +376,8 @@ class Section(object):
         Args:
             fd: File to write the map to
         """
-        Entry.WriteMapLine(fd, indent, self._name, self._offset, self._size)
+        Entry.WriteMapLine(fd, indent, self._name, self._offset, self._size,
+                           self._image_pos)
         for entry in self._entries.values():
             entry.WriteMap(fd, indent + 1)
 
tools/binman/entry.py +5 -3
index 996f03e3a6..6ce5dbdc90 100644
@@ -349,8 +349,9 @@ class Entry(object):
         pass
 
     @staticmethod
-    def WriteMapLine(fd, indent, name, offset, size):
-        print('%s%08x  %08x  %s' % (' ' * indent, offset, size, name), file=fd)
+    def WriteMapLine(fd, indent, name, offset, size, image_pos):
+        print('%08x  %s%08x  %08x  %s' % (image_pos, ' ' * indent, offset,
+                                          size, name), file=fd)
 
     def WriteMap(self, fd, indent):
         """Write a map of the entry to a .map file
@@ -359,7 +360,8 @@ class Entry(object):
             fd: File to write the map to
             indent: Curent indent level of map (0=none, 1=one level, etc.)
         """
-        self.WriteMapLine(fd, indent, self.name, self.offset, self.size)
+        self.WriteMapLine(fd, indent, self.name, self.offset, self.size,
+                          self.image_pos)
 
     def GetEntries(self):
         """Return a list of entries contained by this entry
tools/binman/ftest.py +14 -14
index d09868588c..ce473dfaff 100644
@@ -1052,25 +1052,25 @@ class TestFunctional(unittest.TestCase):
     def testMap(self):
         """Tests outputting a map of the images"""
         _, _, map_data, _ = self._DoReadFileDtb('55_sections.dts', map=True)
-        self.assertEqual('''  Offset      Size  Name
-00000000  00000028  main-section
- 00000000  00000010  section at 0
-  00000000  00000004  u-boot
- 00000010  00000010  section at 1
-  00000000  00000004  u-boot
- 00000020  00000004  section at 2
-  00000000  00000004  u-boot
+        self.assertEqual('''ImagePos    Offset      Size  Name
+00000000  00000000  00000028  main-section
+00000000   00000000  00000010  section at 0
+00000000    00000000  00000004  u-boot
+00000010   00000010  00000010  section at 1
+00000010    00000000  00000004  u-boot
+00000020   00000020  00000004  section at 2
+00000020    00000000  00000004  u-boot
 ''', map_data)
 
     def testNamePrefix(self):
         """Tests that name prefixes are used"""
         _, _, map_data, _ = self._DoReadFileDtb('56_name_prefix.dts', map=True)
-        self.assertEqual('''  Offset      Size  Name
-00000000  00000028  main-section
- 00000000  00000010  section at 0
-  00000000  00000004  ro-u-boot
- 00000010  00000010  section at 1
-  00000000  00000004  rw-u-boot
+        self.assertEqual('''ImagePos    Offset      Size  Name
+00000000  00000000  00000028  main-section
+00000000   00000000  00000010  section at 0
+00000000    00000000  00000004  ro-u-boot
+00000010   00000010  00000010  section at 1
+00000010    00000000  00000004  rw-u-boot
 ''', map_data)
 
     def testUnknownContents(self):
tools/binman/image.py +2 -1
index 4debc73451..68126bc3e6 100644
@@ -124,5 +124,6 @@ class Image:
         filename = '%s.map' % self._name
         fname = tools.GetOutputFilename(filename)
         with open(fname, 'w') as fd:
-            print('%8s  %8s  %s' % ('Offset', 'Size', 'Name'), file=fd)
+            print('%8s  %8s  %8s  %s' % ('ImagePos', 'Offset', 'Size', 'Name'),
+                  file=fd)
             self._section.WriteMap(fd, 0)
Signature · 1 line
2.18.0.203.gfac676dfb9-goog
#28 lore raw

PATCH 27/29 binman: Rename ReadContents() to ReadBlobContents()

In reply to Simon Glass

This function name is too generic for its purpose and is therefore confusing. It actually only applies to blobs, so rename it to indicate this.

---

 tools/binman/etype/blob.py                  | 4 ++--
 tools/binman/etype/u_boot_dtb_with_ucode.py | 2 +-
 tools/binman/etype/u_boot_ucode.py          | 2 +-
 3 files changed, 4 insertions(+), 4 deletions(-)
tools/binman/etype/blob.py +2 -2
index 692d8683c3..3f46eecf30 100644
@@ -29,10 +29,10 @@ class Entry_blob(Entry):
     def ObtainContents(self):
         self._filename = self.GetDefaultFilename()
         self._pathname = tools.GetInputFilename(self._filename)
-        self.ReadContents()
+        self.ReadBlobContents()
         return True
 
-    def ReadContents(self):
+    def ReadBlobContents(self):
         with open(self._pathname) as fd:
             # We assume the data is small enough to fit into memory. If this
             # is used for large filesystem image that might not be true.
tools/binman/etype/u_boot_dtb_with_ucode.py +1 -1
index adcb898a7b..285a28dd1e 100644
@@ -71,7 +71,7 @@ class Entry_u_boot_dtb_with_ucode(Entry_blob):
         # Call the base class just in case it does something important.
         Entry_blob.ObtainContents(self)
         self._pathname = control.GetFdtPath(self._filename)
-        self.ReadContents()
+        self.ReadBlobContents()
         if self.ucode:
             for node in self.ucode.subnodes:
                 data_prop = node.props.get('data')
tools/binman/etype/u_boot_ucode.py +1 -1
index 0f1761afc8..6acf94d8cb 100644
@@ -92,6 +92,6 @@ class Entry_u_boot_ucode(Entry_blob):
             fd.write(fdt_entry.ucode_data)
 
         self._pathname = fname
-        self.ReadContents()
+        self.ReadBlobContents()
 
         return True
Signature · 1 line
2.18.0.203.gfac676dfb9-goog
#29 lore raw

PATCH 28/29 binman: Add a test to catch use of the old 'pos' property

In reply to Simon Glass

This property has been changed to 'offset'. To help downstream users who might still be using 'pos', add a check that this is not used by mistake.

---

 tools/binman/entry.py             |  2 ++
 tools/binman/ftest.py             |  7 +++++++
 tools/binman/test/79_uses_pos.dts | 10 ++++++++++
 3 files changed, 19 insertions(+)
 create mode 100644 tools/binman/test/79_uses_pos.dts
tools/binman/entry.py +2 -0
index 6ce5dbdc90..77cfab9c5d 100644
@@ -143,6 +143,8 @@ class Entry(object):
 
         This reads all the fields we recognise from the node, ready for use.
         """
+        if 'pos' in self._node.props:
+            self.Raise("Please use 'offset' instead of 'pos'")
         self.offset = fdt_util.GetInt(self._node, 'offset')
         self.size = fdt_util.GetInt(self._node, 'size')
         self.align = fdt_util.GetInt(self._node, 'align')
tools/binman/ftest.py +7 -0
index ce473dfaff..3d5f23558c 100644
@@ -1361,6 +1361,13 @@ class TestFunctional(unittest.TestCase):
         data = self._DoReadFile('78_u_boot_tpl.dts')
         self.assertEqual(U_BOOT_TPL_DATA + U_BOOT_TPL_DTB_DATA, data)
 
+    def testUsesPos(self):
+        """Test that the 'pos' property cannot be used anymore"""
+        with self.assertRaises(ValueError) as e:
+           data = self._DoReadFile('79_uses_pos.dts')
+        self.assertIn("Node '/binman/u-boot': Please use 'offset' instead of "
+                      "'pos'", str(e.exception))
+
 
 if __name__ == "__main__":
     unittest.main()
tools/binman/test/79_uses_pos.dts new file +10 -0
new file mode 100644
index 0000000000..7638b9b5e0
@@ -0,0 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0+
+/dts-v1/;
+
+/ {
+	binman {
+		u-boot {
+			pos = <10>;
+		};
+	};
+};
Signature · 1 line
2.18.0.203.gfac676dfb9-goog
#30 lore raw

PATCH 29/29 binman: Adjust _GetPropTree() parameters

In reply to Simon Glass

At present this function takes a filename, but it is better to use an Fdt object so that the caller can control this, perhaps obtainint the device tree from a bytearray. Update the method accordingly and also fix a confusing parameter name.

---

 tools/binman/ftest.py | 14 +++++---------
 1 file changed, 5 insertions(+), 9 deletions(-)
tools/binman/ftest.py +5 -9
index 3d5f23558c..a8456c2615 100644
@@ -353,21 +353,19 @@ class TestFunctional(unittest.TestCase):
         """
         return struct.unpack('>L', dtb[4:8])[0]
 
-    def _GetPropTree(self, dtb_data, node_names):
+    def _GetPropTree(self, dtb, prop_names):
         def AddNode(node, path):
             if node.name != '/':
                 path += '/' + node.name
             for subnode in node.subnodes:
                 for prop in subnode.props.values():
-                    if prop.name in node_names:
+                    if prop.name in prop_names:
                         prop_path = path + '/' + subnode.name + ':' + prop.name
                         tree[prop_path[len('/binman/'):]] = fdt_util.fdt32_to_cpu(
                             prop.value)
                 AddNode(subnode, path)
 
         tree = {}
-        dtb = fdt.Fdt(dtb_data)
-        dtb.Scan()
         AddNode(dtb.GetRoot(), '')
         return tree
 
@@ -1092,11 +1090,9 @@ class TestFunctional(unittest.TestCase):
         """Test that we can update the device tree with offset/size info"""
         _, _, _, out_dtb_fname = self._DoReadFileDtb('60_fdt_update.dts',
                                                      update_dtb=True)
-        props = self._GetPropTree(out_dtb_fname, ['offset', 'size',
-                                                  'image-pos'])
-        with open('/tmp/x.dtb', 'wb') as outf:
-            with open(out_dtb_fname) as inf:
-                outf.write(inf.read())
+        dtb = fdt.Fdt(out_dtb_fname)
+        dtb.Scan()
+        props = self._GetPropTree(dtb, ['offset', 'size', 'image-pos'])
         self.assertEqual({
             'image-pos': 0,
             'offset': 0,
Signature · 1 line
2.18.0.203.gfac676dfb9-goog
#31 lore raw

cover binman: Expand feature set and documentation

In reply to Simon Glass

Hi,

Quoted 183 lines · Simon Glass

This series adds various new features to binman to round out its capabilities. It also adds documentation of each entry type since there are quite a few now.

Noteably this series changes the 'pos' property to be called 'offset'. The 'pos' name is a misnomer with hierarchical images since the position is always relative to the parent. A new 'image-pos' property (calculated by binman) is introduced instead, with a clear meaning.

This is a fairy major change since all source .dts files need to be updated to accommodate it. I believe that doing this rename now (without using the old name for anything else) is the best approach. See the rename patch for motivation and more details.

Changes:

- Passing arguments for entries in via the command line
- Entries filled with a repeated byte
- Putting text in an entry
- TPL
- Chromium entries
- Add README.entries to document entries
- An 'image-pos' property which provides the position of an entry within an image

Simon Glass (29):
binman: Don't depend on dict order in ELF testOutsideFile()
binman: Rename 'position' to 'offset'
binman: Add comments to elf_test
binman: Tidy up some comments in the tests
binman: Enhance the map and fdt-update output
binman: Update the device-tree file on exit
binman: Add a new 'image-pos' property
dtoc: Add missing comments to fdt_util
binman: Add support for passing arguments to entries
binman: Support an entry that holds text
binman: Allow help to work without libfdt
binman: Expand documentation for entries
binman: Allow creation of entry documentation
binman: Create README.entries
binman: Add support for flashrom FMAP
binman: Add support for a cros_ec image
binman: Add an entry filled with a repeating byte
dtoc: Export the _FindNode() function
patman: Allow test commands to fall back to real ones
patman: Add a few more helpers to the tools library
binman: Add support for Chromium GBB
patman: Show the current directory in GetInputFilename()
dtoc: Add a function to obtain a list of phandles
binman: Add an entry for a Chromium vblock
binman: Add support for adding TPL binaries
binman: Show the image position in the map
binman: Rename ReadContents() to ReadBlobContents()
binman: Add a test to catch use of the old 'pos' property
binman: Adjust _GetPropTree() parameters

 arch/arm/dts/sunxi-u-boot.dtsi                |   2 +-
 arch/arm/dts/tegra-u-boot.dtsi                |   6 +-
 arch/x86/dts/u-boot.dtsi                      |  24 +-
 tools/binman/README                           | 135 ++--
 tools/binman/README.entries                   | 585 ++++++++++++++++++
 tools/binman/binman.py                        |  22 +-
 tools/binman/bsection.py                      | 151 +++--
 tools/binman/cmdline.py                       |   6 +-
 tools/binman/control.py                       |  39 +-
 tools/binman/elf.py                           |  10 +-
 tools/binman/elf_test.py                      |  33 +
 tools/binman/entry.py                         | 267 ++++++--
 tools/binman/etype/_testing.py                |  47 +-
 tools/binman/etype/blob.py                    |  16 +-
 tools/binman/etype/blob_named_by_arg.py       |  34 +
 tools/binman/etype/cros_ec_rw.py              |  22 +
 tools/binman/etype/fill.py                    |  32 +
 tools/binman/etype/fmap.py                    |  61 ++
 tools/binman/etype/gbb.py                     |  96 +++
 tools/binman/etype/intel_cmc.py               |  10 +
 tools/binman/etype/intel_descriptor.py        |  26 +-
 tools/binman/etype/intel_fsp.py               |  14 +
 tools/binman/etype/intel_me.py                |  15 +
 tools/binman/etype/intel_mrc.py               |  11 +
 tools/binman/etype/intel_vbt.py               |  10 +
 tools/binman/etype/intel_vga.py               |  12 +
 tools/binman/etype/section.py                 |  48 +-
 tools/binman/etype/text.py                    |  57 ++
 tools/binman/etype/u_boot.py                  |  16 +
 tools/binman/etype/u_boot_dtb.py              |   9 +
 tools/binman/etype/u_boot_dtb_with_ucode.py   |  22 +-
 tools/binman/etype/u_boot_img.py              |  11 +
 tools/binman/etype/u_boot_nodtb.py            |  11 +
 tools/binman/etype/u_boot_spl.py              |  21 +
 tools/binman/etype/u_boot_spl_bss_pad.py      |  16 +
 tools/binman/etype/u_boot_spl_dtb.py          |  11 +-
 tools/binman/etype/u_boot_spl_nodtb.py        |  12 +
 tools/binman/etype/u_boot_tpl.py              |  43 ++
 tools/binman/etype/u_boot_tpl_dtb.py          |  25 +
 tools/binman/etype/u_boot_ucode.py            |  12 +-
 tools/binman/etype/u_boot_with_ucode_ptr.py   |  44 +-
 tools/binman/etype/vblock.py                  |  74 +++
 tools/binman/etype/x86_start16.py             |  14 +
 tools/binman/etype/x86_start16_spl.py         |  14 +
 tools/binman/fmap_util.py                     | 109 ++++
 tools/binman/ftest.py                         | 428 +++++++++++--
 tools/binman/image.py                         |  16 +-
 tools/binman/test/08_pack.dts                 |   2 +-
 tools/binman/test/12_pack_inv_align.dts       |   2 +-
 tools/binman/test/14_pack_overlap.dts         |   2 +-
 tools/binman/test/21_image_pad.dts            |   2 +-
 tools/binman/test/24_sorted.dts               |   6 +-
 tools/binman/test/25_pack_zero_size.dts       |   2 +-
 tools/binman/test/27_pack_4gb_no_size.dts     |   6 +-
 tools/binman/test/28_pack_4gb_outside.dts     |   6 +-
 tools/binman/test/29_x86-rom.dts              |   6 +-
 tools/binman/test/30_x86-rom-me-no-desc.dts   |   4 +-
 tools/binman/test/31_x86-rom-me.dts           |   4 +-
 tools/binman/test/34_x86_ucode.dts            |   2 +-
 tools/binman/test/35_x86_single_ucode.dts     |   2 +-
 tools/binman/test/37_x86_no_ucode.dts         |   2 +-
 .../binman/test/38_x86_ucode_missing_node.dts |   2 +-
 .../test/39_x86_ucode_missing_node2.dts       |   2 +-
 .../binman/test/40_x86_ucode_not_in_image.dts |   2 +-
 tools/binman/test/44_x86_optional_ucode.dts   |   2 +-
 tools/binman/test/45_prop_test.dts            |   4 +-
 tools/binman/test/49_x86_ucode_spl.dts        |   2 +-
 tools/binman/test/53_symbols.dts              |   2 +-
 tools/binman/test/55_sections.dts             |   4 +
 .../test/58_x86_ucode_spl_needs_retry.dts     |   2 +-
 tools/binman/test/62_entry_args.dts           |  14 +
 tools/binman/test/63_entry_args_missing.dts   |  13 +
 tools/binman/test/64_entry_args_required.dts  |  14 +
 .../test/65_entry_args_unknown_datatype.dts   |  15 +
 tools/binman/test/66_text.dts                 |  28 +
 tools/binman/test/67_fmap.dts                 |  29 +
 tools/binman/test/68_blob_named_by_arg.dts    |  12 +
 tools/binman/test/69_fill.dts                 |  15 +
 tools/binman/test/70_fill_no_size.dts         |  14 +
 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 +
 tools/binman/test/74_vblock.dts               |  28 +
 tools/binman/test/75_vblock_no_content.dts    |  23 +
 tools/binman/test/76_vblock_bad_phandle.dts   |  24 +
 tools/binman/test/77_vblock_bad_entry.dts     |  27 +
 tools/binman/test/78_u_boot_tpl.dts           |  11 +
 tools/binman/test/79_uses_pos.dts             |  10 +
 tools/binman/test/u_boot_binman_syms          | Bin 4921 -> 4916 bytes
 tools/binman/test/u_boot_binman_syms.c        |   6 +-
 tools/dtoc/fdt.py                             |  23 +-
 tools/dtoc/fdt_util.py                        |  96 +++
 tools/dtoc/test_fdt.py                        |  49 +-
 tools/patman/command.py                       |   8 +-
 tools/patman/tools.py                         |  80 ++-
 95 files changed, 3012 insertions(+), 346 deletions(-)
 create mode 100644 tools/binman/README.entries
 create mode 100644 tools/binman/etype/blob_named_by_arg.py
 create mode 100644 tools/binman/etype/cros_ec_rw.py
 create mode 100644 tools/binman/etype/fill.py
 create mode 100644 tools/binman/etype/fmap.py
 create mode 100644 tools/binman/etype/gbb.py
 create mode 100644 tools/binman/etype/text.py
 create mode 100644 tools/binman/etype/u_boot_tpl.py
 create mode 100644 tools/binman/etype/u_boot_tpl_dtb.py
 create mode 100644 tools/binman/etype/vblock.py
 create mode 100644 tools/binman/fmap_util.py
 create mode 100644 tools/binman/test/62_entry_args.dts
 create mode 100644 tools/binman/test/63_entry_args_missing.dts
 create mode 100644 tools/binman/test/64_entry_args_required.dts
 create mode 100644 tools/binman/test/65_entry_args_unknown_datatype.dts
 create mode 100644 tools/binman/test/66_text.dts
 create mode 100644 tools/binman/test/67_fmap.dts
 create mode 100644 tools/binman/test/68_blob_named_by_arg.dts
 create mode 100644 tools/binman/test/69_fill.dts
 create mode 100644 tools/binman/test/70_fill_no_size.dts
 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
 create mode 100644 tools/binman/test/74_vblock.dts
 create mode 100644 tools/binman/test/75_vblock_no_content.dts
 create mode 100644 tools/binman/test/76_vblock_bad_phandle.dts
 create mode 100644 tools/binman/test/77_vblock_bad_entry.dts
 create mode 100644 tools/binman/test/78_u_boot_tpl.dts
 create mode 100644 tools/binman/test/79_uses_pos.dts
Quoted 3 lines

--
2.18.0.203.gfac676dfb9-goog

Does anyone have comments on this please? I'd like to pull it in for the release. I hope people are comfortable with the rename from 'pos' to 'offset'.

Regards,
Simon