cros_bundle_firmware: Support 30KB SPL for Exynos

U-Boot will soon support this, so add support for the new size, rather
than hard-coding the SPL size. We do this by detecting the start of
U-Boot.

BUG=chrome-os-partner:12746
TEST=manual
Build and boot snow to kernel with both the smaller and larger SPL.
See that the SPL size is detected correct, U-Boot boots normally and
the kernel runs to a login prompt.

Change-Id: Ia0da542403e7e62db360fb9c802cf2c98f5fcc78
Signed-off-by: Simon Glass <sjg@chromium.org>
Reviewed-on: https://gerrit.chromium.org/gerrit/40899
Reviewed-by: Che-Liang Chiou <clchiou@chromium.org>
Reviewed-by: Tom Wai-Hong Tam <waihong@chromium.org>
diff --git a/host/lib/write_firmware.py b/host/lib/write_firmware.py
index 2751be7..4d98170 100644
--- a/host/lib/write_firmware.py
+++ b/host/lib/write_firmware.py
@@ -6,6 +6,7 @@
 import glob
 import os
 import re
+import struct
 import time
 import tools
 from tools import CmdError
@@ -394,14 +395,30 @@
 
     # The BL1 is always 8KB - extract that part into a new file
     # TODO(sjg@chromium.org): Perhaps pick these up from the fdt?
-    self._tools.WriteFile(bl1, data[:0x2000])
+    bl1_size = 0x2000
+    self._tools.WriteFile(bl1, data[:bl1_size])
 
-    # The BL2 (U-Boot SPL) is 14KB and follows BL1. After that there is
-    # a 2KB gap
-    self._tools.WriteFile(bl2, data[0x2000:0x5800])
+    # Try to detect the BL2 size. We look for 0xea000014 which is the
+    # 'B reset' instruction at the start of U-Boot.
+    first_instr = struct.pack('<L', 0xea000014)
+    uboot_offset = data.find(first_instr, bl1_size + 0x3800)
+    if uboot_offset == -1:
+        raise ValueError('Could not locate start of U-Boot')
+    bl2_size = uboot_offset - bl1_size - 0x800  # 2KB gap after BL2
 
-    # U-Boot itself starts at 24KB, after the gap
-    self._tools.WriteFile(image, data[0x6000:])
+    # Sanity check: At present we only allow 14KB and 30KB for SPL
+    allowed = [14, 30]
+    if (bl2_size >> 10) not in allowed:
+        raise ValueError('BL2 size is %dK - only %s supported' %
+                (bl2_size >> 10, ', '.join([str(size) for size in allowed])))
+    self._out.Notice('BL2 size is %dKB' % (bl2_size >> 10))
+
+    # The BL2 (U-Boot SPL) follows BL1. After that there is a 2KB gap
+    bl2_end = uboot_offset - 0x800
+    self._tools.WriteFile(bl2, data[0x2000:bl2_end])
+
+    # U-Boot itself starts after the gap
+    self._tools.WriteFile(image, data[uboot_offset:])
     return bl1, bl2, image
 
   def _ExynosFlashImage(self, flash_dest, flash_uboot, bl1, bl2, payload,