cros_bundle_firmware: Remove FDT when extracting U-Boot from image

To flash an image onto a board we download a flasher to the board, complete
with a script telling it what to do. The flasher is itself just U-Boot, and
we doctor up the FDT with a suitable script.

If no u-boot.bin is available, it is convenient to be able to extract the
U-Boot from the image being flashed. It is exactly the same binary, so there
is no problem with doing this.

However, at present the code that does this doesn't correctly determine the
end of U-Boot, partly since there is no defined way to do this. The intent
is that we will start using the fdtmap instead of FMAP, and so will have
access to that information. Until then, we need a workaround.

Search for the FDT magic word at the end of the extract image portion. Since
the FDT is attached to the end of U-Boot, this magic word marks the end of
the original u-boot.bin which was placed in the image. Use this smaller
portion as our u-boot.bin. When the flasher code adds its specially
doctored-up FDT, it will go in right place, and the flasher will work.

BUG=TBD, Vadim?
TEST=manual
Without this change:

$ cros_write_firmware -b daisy -w usb \
	-d /build/daisy/firmware/dts/exynos5250-snow.dts \
	-F spi -i /build/daisy/firmware/image-snow.bin -V -D -O out

just does a verified boot into the kernel.

With this change, it runs the flasher.

Change-Id: I53a50fd9bb19ec2ff2dc2e88b0dc894937678957
Signed-off-by: Simon Glass <sjg@chromium.org>
Reviewed-on: https://gerrit.chromium.org/gerrit/43503
diff --git a/host/lib/write_firmware.py b/host/lib/write_firmware.py
index 336310a..c9e1623 100644
--- a/host/lib/write_firmware.py
+++ b/host/lib/write_firmware.py
@@ -426,7 +426,7 @@
           if self._DOWNLOAD_FAILURE_MESSAGE in string:
             raise CmdError('Download failed!')
 
-  def _ExtractPayloadParts(self, payload):
+  def _ExtractPayloadParts(self, payload, truncate_to_fdt):
     """Extract the BL1, BL2 and U-Boot parts from a payload.
 
     An exynos image consists of 3 parts: BL1, BL2 and U-Boot/FDT.
@@ -436,6 +436,8 @@
 
     Args:
       payload: Full path to payload.
+      truncate_to_fdt: Truncate the U-Boot image at the start of its
+        embedded FDT
 
     Returns:
       (bl1, bl2, image) where:
@@ -481,11 +483,18 @@
     self._tools.WriteFile(bl2, data[0x2000:bl2_end])
 
     # U-Boot itself starts at 24KB, after the gap. As a hack, truncate it
-    # to an assumed maximum size.
+    # to an assumed maximum size. As a secondary hack, locate the FDT
+    # and truncate U-Boot from that point. The correct FDT will be added
+    # when the image is written to the board.
     # TODO(sjg@chromium.org): Get a proper flash map here so we know how
     # large it is
-    # U-Boot itself starts after the gap
-    self._tools.WriteFile(image, data[uboot_offset:uboot_offset + 0xa0000])
+    uboot_data = data[uboot_offset:uboot_offset + 0xa0000]
+    if truncate_to_fdt:
+      fdt_magic = struct.pack('>L', 0xd00dfeed)
+      fdt_offset = uboot_data.rfind(fdt_magic)
+      uboot_data = uboot_data[:fdt_offset]
+
+    self._tools.WriteFile(image, uboot_data)
     return bl1, bl2, image
 
   def ExynosFlashImage(self, flash_dest, flash_uboot, bl1, bl2, payload,
@@ -509,7 +518,7 @@
     """
     tools = self._tools
     payload_bl1, payload_bl2, payload_image = (
-        self._ExtractPayloadParts(payload))
+        self._ExtractPayloadParts(payload, flash_dest is not None))
     if flash_dest:
       # If we don't have some bits, get them from the image
       if not flash_uboot or not os.path.exists(tools.Filename(flash_uboot)):