mmc: Update u-boot if needed

Calculate a hash over the u-boot image file and the mmc device
where u-boot is stored to determine if it needs to be updated.

Tested: Verified that after the mmc device is updated, an update
to the same image does not rewrite the device where u-boot is.

Change-Id: I9f3cb8cc639512c02030b7be34845a67f3e15319
Signed-off-by: Adriana Kobylak <anoo@us.ibm.com>
diff --git a/obmc-flash-bmc b/obmc-flash-bmc
index 043ebf0..af477b9 100644
--- a/obmc-flash-bmc
+++ b/obmc-flash-bmc
@@ -446,6 +446,30 @@
   fi
 }
 
+# Compare the device where u-boot resides with an image file. Specify the full
+# path to the device and image file to use for the compare. Print a value of
+# "0" if identical, "1" otherwise.
+cmp_uboot() {
+  device="$1"
+  image="$2"
+
+  # Since the image file can be smaller than the device, copy the device to a
+  # tmp file and write the image file on top, then compare the sum of each.
+  # Use cat / redirection since busybox does not have the conv=notrunc option.
+  tmpFile="$(mktemp ubootdev.XXXXXX)"
+  dd if="${device}" of="${tmpFile}"
+  devSum="$(sha256sum ${tmpFile})"
+  cat < "${image}" 1<> "${tmpFile}"
+  imgSum="$(sha256sum ${tmpFile})"
+  rm -f "${tmpFile}"
+
+  if [ "${imgSum}" == "${devSum}" ]; then
+    echo "0";
+  else
+    echo "1";
+  fi
+}
+
 # The eMMC partition labels for the kernel and rootfs are boot-a/b and rofs-a/b.
 # Return the label (a or b) for the running partition.
 mmc_get_primary_label() {
@@ -478,6 +502,16 @@
 }
 
 mmc_update() {
+  # Update u-boot if needed
+  bootPartition="mmcblk0boot0"
+  devUBoot="/dev/${bootPartition}"
+  imgUBoot="${imgpath}/${version}/image-u-boot"
+  if [ "$(cmp_uboot "${devUBoot}" "${imgUBoot}")" != "0" ]; then
+    echo 0 > "/sys/block/${bootPartition}/force_ro"
+    dd if="${imgUBoot}" of="${devUBoot}"
+    echo 1 > "/sys/block/${bootPartition}/force_ro"
+  fi
+
   # Update the secondary (non-running) boot and rofs partitions.
   label="$(mmc_get_secondary_label)"