Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 68658c0f authored by Tao Bao's avatar Tao Bao
Browse files

Add post-install verification for BBOTAs

Similar to the assertations in file-based OTA, we perform verification
for block-based OTAs (BBOTAs) after updating a partition, for both of
the incremental and full OTAs. It increases the update time (~20s on
Nexus 6), but will capture unnoticed errors right away.

Bug: 21500869
Change-Id: I89ac8fe623b855721b7affd07cf9426a23433ab0
parent b7bb040c
Loading
Loading
Loading
Loading
+10 −5
Original line number Diff line number Diff line
@@ -74,7 +74,7 @@ class Image(object):
  def ReadRangeSet(self, ranges):
    raise NotImplementedError

  def TotalSha1(self):
  def TotalSha1(self, include_clobbered_blocks=False):
    raise NotImplementedError


@@ -87,7 +87,10 @@ class EmptyImage(Image):
  file_map = {}
  def ReadRangeSet(self, ranges):
    return ()
  def TotalSha1(self):
  def TotalSha1(self, include_clobbered_blocks=False):
    # EmptyImage always carries empty clobbered_blocks, so
    # include_clobbered_blocks can be ignored.
    assert self.clobbered_blocks.size() == 0
    return sha1().hexdigest()


@@ -136,8 +139,9 @@ class DataImage(Image):
  def ReadRangeSet(self, ranges):
    return [self.data[s*self.blocksize:e*self.blocksize] for (s, e) in ranges]

  def TotalSha1(self):
    # DataImage always carries empty clobbered_blocks.
  def TotalSha1(self, include_clobbered_blocks=False):
    # DataImage always carries empty clobbered_blocks, so
    # include_clobbered_blocks can be ignored.
    assert self.clobbered_blocks.size() == 0
    return sha1(self.data).hexdigest()

@@ -201,7 +205,8 @@ class Transfer(object):
#
#    TotalSha1(): a function that returns (as a hex string) the SHA-1
#      hash of all the data in the image (ie, all the blocks in the
#      care_map minus clobbered_blocks).
#      care_map minus clobbered_blocks, or including the clobbered
#      blocks if include_clobbered_blocks is True).
#
# When creating a BlockImageDiff, the src image may be None, in which
# case the list of transfers produced will never read from the
+16 −0
Original line number Diff line number Diff line
@@ -1182,6 +1182,7 @@ class BlockDifference(object):
    if progress:
      script.ShowProgress(progress, 0)
    self._WriteUpdate(script, output_zip)
    self._WritePostInstallVerifyScript(script)

  def WriteVerifyScript(self, script):
    partition = self.partition
@@ -1220,6 +1221,21 @@ class BlockDifference(object):
      script.AppendExtra(('abort("%s partition has unexpected contents");\n'
                          'endif;') % (partition,))

  def _WritePostInstallVerifyScript(self, script):
    partition = self.partition
    script.Print('Verifying the updated %s image...' % (partition,))
    # Unlike pre-install verification, clobbered_blocks should not be ignored.
    ranges = self.tgt.care_map
    ranges_str = ranges.to_string_raw()
    script.AppendExtra('if range_sha1("%s", "%s") == "%s" then' % (
                       self.device, ranges_str,
                       self.tgt.TotalSha1(include_clobbered_blocks=True)))
    script.Print('Verified the updated %s image.' % (partition,))
    script.AppendExtra(
        'else\n'
        '  abort("%s partition has unexpected contents after OTA update");\n'
        'endif;' % (partition,))

  def _WriteUpdate(self, script, output_zip):
    ZipWrite(output_zip,
             '{}.transfer.list'.format(self.path),
+1 −0
Original line number Diff line number Diff line
@@ -917,6 +917,7 @@ else

  system_diff.WriteScript(script, output_zip,
                          progress=0.8 if vendor_diff else 0.9)

  if vendor_diff:
    vendor_diff.WriteScript(script, output_zip, progress=0.1)

+9 −4
Original line number Diff line number Diff line
@@ -118,11 +118,16 @@ class SparseImage(object):
  def ReadRangeSet(self, ranges):
    return [d for d in self._GetRangeData(ranges)]

  def TotalSha1(self):
    """Return the SHA-1 hash of all data in the 'care' regions but not in
    clobbered_blocks of this image."""
  def TotalSha1(self, include_clobbered_blocks=False):
    """Return the SHA-1 hash of all data in the 'care' regions.

    If include_clobbered_blocks is True, it returns the hash including the
    clobbered_blocks."""
    ranges = self.care_map
    if not include_clobbered_blocks:
      ranges.subtract(self.clobbered_blocks)
    h = sha1()
    for d in self._GetRangeData(self.care_map.subtract(self.clobbered_blocks)):
    for d in self._GetRangeData(ranges):
      h.update(d)
    return h.hexdigest()