cros_write_firmware: support 32K SPL blobs properly

When calculating BL1 + SPL padding size to the nearest 8K boundary,
the code assumed SPL to be of 14K in size. In fact it could be either
14K (potentially coming in a 16K envelope) or 30K (potentially coming
in a 32K).

BUG=none
TEST=manual

   . after this fix it is possible to create a flasher for snow (32K
     SPL platform). Both of the below commands produce working
     flashers and the DUTs boot from SPI after flashing.

   $  emerge-daisy chromeos-u-boot chromeos-bootimage  exynos-pre-boot && \
      cros_write_firmware -b daisy -w sd:. -D -M exynos \
      -i /build/daisy/firmware/nv_image-snow.bin \
      --dt /build/daisy/firmware/dtb/exynos5250-snow.dtb \
      -F spi -U /build/daisy/firmware/u-boot.bin

  $  emerge-peach_pit chromeos-u-boot chromeos-bootimage exynos-pre-boot &&\
     sudo cros_write_firmware -b peach -w sd:. -M exynos \
     -i /build/peach_pit/firmware/image-peach_pit.bin \
     --dt /build/peach_pit/firmware/dtb/exynos5420-peach_pit.dtb \
     -F spi -U /build/peach_pit/firmware/u-boot.bin

Change-Id: I5544ce0fb57bd114d096b3007ddf59f0daff42ae
Signed-off-by: Vadim Bendebury <vbendeb@chromium.org>
Reviewed-on: https://gerrit.chromium.org/gerrit/58940
Reviewed-by: Simon Glass <sjg@chromium.org>
Commit-Queue: Doug Anderson <dianders@chromium.org>
diff --git a/host/lib/exynos.py b/host/lib/exynos.py
index fcaf0e2..cedd081 100644
--- a/host/lib/exynos.py
+++ b/host/lib/exynos.py
@@ -298,11 +298,22 @@
           return
 
       # This is not var size spl, let's see if it's the fixed size one.
-      check_sum = sum(ord(x) for x in data[:-4])
-      if check_sum == struct.unpack('<I', data[-4:])[0]:
-        self._spl_type = self.FIXED_SPL
-        self._out.Progress('Fixed size BL2 detected')
-        return
+      # Checksum is placed at a fixed location in the blob, as defined in
+      # tools/mkexynosspl.c in the u--boot tree. There are two possibilities
+      # for blob sizes - 14K or 30K. The checksum is put in the last 4 bytes
+      # of the blob.
+      #
+      # To complicate things further the blob here could have come not from
+      # mkexynosspl directly, it could have been pulled out of a previously
+      # bundled image. I that case it the blob will be in a chunk aligned to
+      # the closest 16K boundary.
+      blob_size  = ((len(data) + 0x3fff) & ~0x3fff) - 2 * 1024
+      if blob_size == len(data) or (loose_check and (blob_size < len(data))):
+        check_sum = sum(ord(x) for x in data[:blob_size - 4])
+        if check_sum == struct.unpack('<I', data[blob_size - 4:blob_size])[0]:
+          self._spl_type = self.FIXED_SPL
+          self._out.Progress('Fixed size BL2 detected')
+          return
     except IndexError:
       # This will be thrown if bl2 is too small
       pass
diff --git a/host/lib/write_firmware.py b/host/lib/write_firmware.py
index 69b251b..1268f58 100644
--- a/host/lib/write_firmware.py
+++ b/host/lib/write_firmware.py
@@ -684,10 +684,14 @@
                                        bl2, 'flasher', True)
       data = self._tools.ReadFile(bl1) + self._tools.ReadFile(bl2_file)
 
-      # Pad BL2 out to the required size.
-      # We require that it be 24KB, but data will only contain 8KB + 14KB.
-      # Add the extra padding to bring it to 24KB.
-      data += '\0' * (0x6000 - len(data))
+      # Pad BL2 out to the required size. Its size could be either 14K or 30K
+      # bytes, but the next object in the file needs to be aligned at an 8K
+      # boundary. The BL1 size is also known to be 8K bytes, so the total BL1
+      # + BL2 size needs to be aligned to 8K (0x2000) boundary.
+      aligned_size = (len(data) + 0x1fff) & ~0x1fff
+      pad_size =  aligned_size - len(data)
+      data += '\0' * pad_size
+
       data += self._tools.ReadFile(raw_image)
       image = os.path.join(self._tools.outdir, 'flasher-with-bl.bin')
       self._tools.WriteFile(image, data)