binman: Expand feature set and documentation
Subsystems (5)
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
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
@@ -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
PATCH 2/29 binman: Rename 'position' to 'offset'
In reply to Simon GlassAfter 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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -24,7 +24,7 @@ u-boot-fixed { type = "u-boot"; - pos = <61>; + offset = <61>; }; }; };
tools/binman/test/12_pack_inv_align.dts +1 -1
@@ -6,7 +6,7 @@ binman { u-boot { - pos = <5>; + offset = <5>; align = <4>; }; };
tools/binman/test/14_pack_overlap.dts +1 -1
@@ -10,7 +10,7 @@ u-boot-align { type = "u-boot"; - pos = <3>; + offset = <3>; }; }; };
tools/binman/test/21_image_pad.dts +1 -1
@@ -10,7 +10,7 @@ }; u-boot { - pos = <20>; + offset = <20>; }; }; };
tools/binman/test/24_sorted.dts +3 -3
@@ -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
@@ -9,7 +9,7 @@ }; u-boot-spl { - pos = <0>; + offset = <0>; }; }; };
tools/binman/test/27_pack_4gb_no_size.dts +3 -3
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
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
@@ -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
PATCH 3/29 binman: Add comments to elf_test
In reply to Simon GlassThe 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
@@ -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
PATCH 4/29 binman: Tidy up some comments in the tests
In reply to Simon GlassA 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
@@ -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
PATCH 5/29 binman: Enhance the map and fdt-update output
In reply to Simon GlassAt 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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -24,5 +24,9 @@ u-boot { }; }; + section at 2 { + u-boot { + }; + }; }; };
Signature · 1 line
2.18.0.203.gfac676dfb9-goog
PATCH 6/29 binman: Update the device-tree file on exit
In reply to Simon GlassBinman 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
@@ -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
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.
Signed-off-by Simon Glass <[email protected]>---
tools/binman/control.py | 4 ++++ 1 file changed, 4 insertions(+)tools/binman/control.py +4
-1@@ -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
PATCH 7/29 binman: Add a new 'image-pos' property
In reply to Simon GlassAt 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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
PATCH 8/29 dtoc: Add missing comments to fdt_util
In reply to Simon GlassThis 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
@@ -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
PATCH 9/29 binman: Add support for passing arguments to entries
In reply to Simon GlassSometimes 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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
PATCH 10/29 binman: Support an entry that holds text
In reply to Simon GlassIt 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
@@ -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
@@ -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
@@ -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
PATCH 11/29 binman: Allow help to work without libfdt
In reply to Simon GlassAt 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
@@ -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
PATCH 12/29 binman: Expand documentation for entries
In reply to Simon GlassAt 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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
PATCH 13/29 binman: Allow creation of entry documentation
In reply to Simon GlassBinman 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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
PATCH 14/29 binman: Create README.entries
In reply to Simon GlassCreate 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
@@ -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
PATCH 15/29 binman: Add support for flashrom FMAP
In reply to Simon GlassAdd 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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
PATCH 16/29 binman: Add support for a cros_ec image
In reply to Simon GlassAdd 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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
PATCH 17/29 binman: Add an entry filled with a repeating byte
In reply to Simon GlassIt 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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
PATCH 18/29 dtoc: Export the _FindNode() function
In reply to Simon GlassThis 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
@@ -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
@@ -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
PATCH 19/29 patman: Allow test commands to fall back to real ones
In reply to Simon GlassTests 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
@@ -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
PATCH 20/29 patman: Add a few more helpers to the tools library
In reply to Simon GlassAdd 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
@@ -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
PATCH 21/29 binman: Add support for Chromium GBB
In reply to Simon GlassThis 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
@@ -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
@@ -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
@@ -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
@@ -0,0 +1,9 @@ +// SPDX-License-Identifier: GPL-2.0+ +/dts-v1/; + +/ { + binman { + gbb { + }; + }; +};
Signature · 1 line
2.18.0.203.gfac676dfb9-goog
PATCH 22/29 patman: Show the current directory in GetInputFilename()
In reply to Simon GlassWhen 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
@@ -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
PATCH 23/29 dtoc: Add a function to obtain a list of phandles
In reply to Simon GlassAdd 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
@@ -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
@@ -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
@@ -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
PATCH 24/29 binman: Add an entry for a Chromium vblock
In reply to Simon GlassThis 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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
PATCH 25/29 binman: Add support for adding TPL binaries
In reply to Simon GlassAdd 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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
PATCH 26/29 binman: Show the image position in the map
In reply to Simon GlassAt 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
@@ -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
@@ -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
@@ -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
@@ -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
PATCH 27/29 binman: Rename ReadContents() to ReadBlobContents()
In reply to Simon GlassThis 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
@@ -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
@@ -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
@@ -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
PATCH 28/29 binman: Add a test to catch use of the old 'pos' property
In reply to Simon GlassThis 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
@@ -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
@@ -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
@@ -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
PATCH 29/29 binman: Adjust _GetPropTree() parameters
In reply to Simon GlassAt 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
@@ -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
cover binman: Expand feature set and documentation
In reply to Simon GlassHi,
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 imageSimon Glass (29):
binman: Don't depend on dict order in ELFtestOutsideFile()
binman: Rename 'position' to 'offset'
binman: Add comments toelf_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 tofdt_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 acros_ecimage
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 inGetInputFilename()
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: RenameReadContents()toReadBlobContents()
binman: Add a test to catch use of the old 'pos' property
binman: Adjust_GetPropTree()parametersarch/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