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

Commit 7589e961 authored by Tao Bao's avatar Tao Bao
Browse files

releasetools: Always write the last block if it's padded.

In BBOTAs if the last block of a DataImage is padded, we should always
write the whole block even for incremental OTAs. Because otherwise the
last block may be skipped if unchanged, but would fail the post-install
verification if it has non-zero contents in the padding bytes.

Bug: 23828506
Change-Id: I4b0af7344d18261258cd48d18c029c089d6ff365
parent 76274670
Loading
Loading
Loading
Loading
+21 −6
Original line number Original line Diff line number Diff line
@@ -106,11 +106,13 @@ class DataImage(Image):
    assert not (trim and pad)
    assert not (trim and pad)


    partial = len(self.data) % self.blocksize
    partial = len(self.data) % self.blocksize
    padded = False
    if partial > 0:
    if partial > 0:
      if trim:
      if trim:
        self.data = self.data[:-partial]
        self.data = self.data[:-partial]
      elif pad:
      elif pad:
        self.data += '\0' * (self.blocksize - partial)
        self.data += '\0' * (self.blocksize - partial)
        padded = True
      else:
      else:
        raise ValueError(("data for DataImage must be multiple of %d bytes "
        raise ValueError(("data for DataImage must be multiple of %d bytes "
                          "unless trim or pad is specified") %
                          "unless trim or pad is specified") %
@@ -120,6 +122,15 @@ class DataImage(Image):


    self.total_blocks = len(self.data) / self.blocksize
    self.total_blocks = len(self.data) / self.blocksize
    self.care_map = RangeSet(data=(0, self.total_blocks))
    self.care_map = RangeSet(data=(0, self.total_blocks))
    # When the last block is padded, we always write the whole block even for
    # incremental OTAs. Because otherwise the last block may get skipped if
    # unchanged for an incremental, but would fail the post-install
    # verification if it has non-zero contents in the padding bytes.
    # Bug: 23828506
    if padded:
      self.clobbered_blocks = RangeSet(
          data=(self.total_blocks-1, self.total_blocks))
    else:
      self.clobbered_blocks = RangeSet()
      self.clobbered_blocks = RangeSet()
    self.extended = RangeSet()
    self.extended = RangeSet()


@@ -127,7 +138,7 @@ class DataImage(Image):
    nonzero_blocks = []
    nonzero_blocks = []
    reference = '\0' * self.blocksize
    reference = '\0' * self.blocksize


    for i in range(self.total_blocks):
    for i in range(self.total_blocks-1 if padded else self.total_blocks):
      d = self.data[i*self.blocksize : (i+1)*self.blocksize]
      d = self.data[i*self.blocksize : (i+1)*self.blocksize]
      if d == reference:
      if d == reference:
        zero_blocks.append(i)
        zero_blocks.append(i)
@@ -139,13 +150,17 @@ class DataImage(Image):
    self.file_map = {"__ZERO": RangeSet(zero_blocks),
    self.file_map = {"__ZERO": RangeSet(zero_blocks),
                     "__NONZERO": RangeSet(nonzero_blocks)}
                     "__NONZERO": RangeSet(nonzero_blocks)}


    if self.clobbered_blocks:
      self.file_map["__COPY"] = self.clobbered_blocks

  def ReadRangeSet(self, ranges):
  def ReadRangeSet(self, ranges):
    return [self.data[s*self.blocksize:e*self.blocksize] for (s, e) in ranges]
    return [self.data[s*self.blocksize:e*self.blocksize] for (s, e) in ranges]


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