binman: Support writing symbols inside a mkimage image
authorSimon Glass <sjg@chromium.org>
Tue, 18 Jul 2023 13:24:08 +0000 (07:24 -0600)
committerSimon Glass <sjg@chromium.org>
Thu, 20 Jul 2023 20:10:58 +0000 (14:10 -0600)
Add support for writing symbols and determining the assumed position of
binaries inside a mkimage image. This is useful as an example for other
entry types which might want to do the same thing.

Signed-off-by: Simon Glass <sjg@chromium.org>
tools/binman/entry.py
tools/binman/etype/mkimage.py
tools/binman/ftest.py
tools/binman/test/290_mkimage_sym.dts [new file with mode: 0644]

index 0d4cb94..42e0b7b 100644 (file)
@@ -1314,8 +1314,6 @@ features to produce new behaviours.
         """
         data = b''
         for entry in entries:
-            # First get the input data and put it in a file
-            entry.ObtainContents(fake_size=fake_size)
             data += entry.GetData()
         uniq = self.GetUniqueName()
         fname = tools.get_output_filename(f'{prefix}.{uniq}')
index 31ac05d..6ae5d0c 100644 (file)
@@ -218,3 +218,39 @@ class Entry_mkimage(Entry_section):
 
     def CheckEntries(self):
         pass
+
+    def ProcessContents(self):
+        # The blob may have changed due to WriteSymbols()
+        ok = super().ProcessContents()
+        data = self.BuildSectionData(True)
+        ok2 = self.ProcessContentsUpdate(data)
+        return ok and ok2
+
+    def SetImagePos(self, image_pos):
+        """Set the position in the image
+
+        This sets each subentry's offsets, sizes and positions-in-image
+        according to where they ended up in the packed mkimage file.
+
+        NOTE: This assumes a legacy mkimage and assumes that the images are
+        written to the output in order. SoC-specific mkimage handling may not
+        conform to this, in which case these values may be wrong.
+
+        Args:
+            image_pos (int): Position of this entry in the image
+        """
+        # The mkimage header consists of 0x40 bytes, following by a table of
+        # offsets for each file
+        upto = 0x40
+
+        # Skip the 0-terminated list of offsets (assume a single image)
+        upto += 4 + 4
+        for entry in self.GetEntries().values():
+            entry.SetOffsetSize(upto, None)
+
+            # Give up if any entries lack a size
+            if entry.size is None:
+                return
+            upto += entry.size
+
+        super().SetImagePos(image_pos)
index e96223c..e53181a 100644 (file)
@@ -6820,6 +6820,70 @@ fdt         fdtmap                Extract the devicetree blob from the fdtmap
         second = U_BOOT_DATA + b'#' + VGA_DATA + U_BOOT_DTB_DATA
         self.assertEqual(U_BOOT_IMG_DATA + first + second + first, data)
 
+    def testMkimageSymbols(self):
+        """Test using mkimage to build an image with symbols in it"""
+        self._SetupSplElf('u_boot_binman_syms')
+        data = self._DoReadFile('290_mkimage_sym.dts')
+
+        image = control.images['image']
+        entries = image.GetEntries()
+        self.assertIn('u-boot', entries)
+        u_boot = entries['u-boot']
+
+        mkim = entries['mkimage']
+        mkim_entries = mkim.GetEntries()
+        self.assertIn('u-boot-spl', mkim_entries)
+        spl = mkim_entries['u-boot-spl']
+        self.assertIn('u-boot-spl2', mkim_entries)
+        spl2 = mkim_entries['u-boot-spl2']
+
+        # skip the mkimage header and the area sizes
+        mk_data = data[mkim.offset + 0x40:]
+        size, term = struct.unpack('>LL', mk_data[:8])
+
+        # There should be only one image, so check that the zero terminator is
+        # present
+        self.assertEqual(0, term)
+
+        content = mk_data[8:8 + size]
+
+        # The image should contain the symbols from u_boot_binman_syms.c
+        # Note that image_pos is adjusted by the base address of the image,
+        # which is 0x10 in our test image
+        spl_data = content[:0x18]
+        content = content[0x1b:]
+
+        # After the header is a table of offsets for each image. There should
+        # only be one image, then a 0 terminator, so figure out the real start
+        # of the image data
+        base = 0x40 + 8
+
+        # Check symbols in both u-boot-spl and u-boot-spl2
+        for i in range(2):
+            vals = struct.unpack('<LLQLL', spl_data)
+
+            # The image should contain the symbols from u_boot_binman_syms.c
+            # Note that image_pos is adjusted by the base address of the image,
+            # which is 0x10 in our 'u_boot_binman_syms' test image
+            self.assertEqual(elf.BINMAN_SYM_MAGIC_VALUE, vals[0])
+            self.assertEqual(base, vals[1])
+            self.assertEqual(spl2.offset, vals[2])
+            # figure out the internal positions of its components
+            self.assertEqual(0x10 + u_boot.image_pos, vals[3])
+
+            # Check that spl and spl2 are actually at the indicated positions
+            self.assertEqual(
+                elf.BINMAN_SYM_MAGIC_VALUE,
+                struct.unpack('<I', data[spl.image_pos:spl.image_pos + 4])[0])
+            self.assertEqual(
+                elf.BINMAN_SYM_MAGIC_VALUE,
+                struct.unpack('<I', data[spl2.image_pos:spl2.image_pos + 4])[0])
+
+            self.assertEqual(len(U_BOOT_DATA), vals[4])
+
+            # Move to next
+            spl_data = content[:0x18]
+
 
 if __name__ == "__main__":
     unittest.main()
diff --git a/tools/binman/test/290_mkimage_sym.dts b/tools/binman/test/290_mkimage_sym.dts
new file mode 100644 (file)
index 0000000..2dfd286
--- /dev/null
@@ -0,0 +1,27 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+/dts-v1/;
+
+/ {
+       #address-cells = <1>;
+       #size-cells = <1>;
+
+       binman {
+               u-boot-dtb {
+               };
+
+               mkimage {
+                       args = "-n test -T script";
+
+                       u-boot-spl {
+                       };
+
+                       u-boot-spl2 {
+                               type = "u-boot-spl";
+                       };
+               };
+
+               u-boot {
+               };
+       };
+};