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

Commit 405e71dc authored by Sami Tolvanen's avatar Sami Tolvanen
Browse files

Fix metadata location when file system doesn't span the partition

Pad the sparse image with a zero fill chunk to correctly position
verity and FEC metadata at the end of the partition.

Bug: 27073791
Change-Id: I9f70d579a42e5007d50e9c02a98a608d2815f0ed
(cherry picked from commit 6a8781a2)
parent fb5ac541
Loading
Loading
Loading
Loading
+14 −7
Original line number Diff line number Diff line
@@ -28,6 +28,7 @@ import sys
import commands
import common
import shutil
import sparse_img
import tempfile

OPTIONS = common.OPTIONS
@@ -91,6 +92,16 @@ def GetVeritySize(partition_size, fec_supported):
    return verity_size + fec_size
  return verity_size

def GetSimgSize(image_file):
  simg = sparse_img.SparseImage(image_file, build_map=False)
  return simg.blocksize * simg.total_blocks

def ZeroPadSimg(image_file, pad_size):
  blocks = pad_size // BLOCK_SIZE
  print("Padding %d blocks (%d bytes)" % (blocks, pad_size))
  simg = sparse_img.SparseImage(image_file, mode="r+b", build_map=False)
  simg.AppendFillChunk(0, blocks)

def AdjustPartitionSizeForVerity(partition_size, fec_supported):
  """Modifies the provided partition size to account for the verity metadata.

@@ -329,7 +340,7 @@ def BuildImage(in_dir, prop_dict, out_file, target_out=None):

  # Adjust the partition size to make room for the hashes if this is to be
  # verified.
  if verity_supported and is_verity_partition and fs_spans_partition:
  if verity_supported and is_verity_partition:
    partition_size = int(prop_dict.get("partition_size"))
    adjusted_size = AdjustPartitionSizeForVerity(partition_size,
                                                 verity_fec_supported)
@@ -440,17 +451,13 @@ def BuildImage(in_dir, prop_dict, out_file, target_out=None):
  if not fs_spans_partition:
    mount_point = prop_dict.get("mount_point")
    partition_size = int(prop_dict.get("partition_size"))
    image_size = os.stat(out_file).st_size
    image_size = GetSimgSize(out_file)
    if image_size > partition_size:
      print("Error: %s image size of %d is larger than partition size of "
            "%d" % (mount_point, image_size, partition_size))
      return False
    if verity_supported and is_verity_partition:
      if 2 * image_size - AdjustPartitionSizeForVerity(image_size, verity_fec_supported) > partition_size:
        print "Error: No more room on %s to fit verity data" % mount_point
        return False
    prop_dict["original_partition_size"] = prop_dict["partition_size"]
    prop_dict["partition_size"] = str(image_size)
      ZeroPadSimg(out_file, partition_size - image_size)

  # create the verified image if this is to be verified
  if verity_supported and is_verity_partition:
+21 −3
Original line number Diff line number Diff line
@@ -31,8 +31,9 @@ class SparseImage(object):
  the form of a string like "0" or "0 1-5 8".
  """

  def __init__(self, simg_fn, file_map_fn=None, clobbered_blocks=None):
    self.simg_f = f = open(simg_fn, "rb")
  def __init__(self, simg_fn, file_map_fn=None, clobbered_blocks=None,
               mode="rb", build_map=True):
    self.simg_f = f = open(simg_fn, mode)

    header_bin = f.read(28)
    header = struct.unpack("<I4H4I", header_bin)
@@ -44,7 +45,7 @@ class SparseImage(object):
    chunk_hdr_sz = header[4]
    self.blocksize = blk_sz = header[5]
    self.total_blocks = total_blks = header[6]
    total_chunks = header[7]
    self.total_chunks = total_chunks = header[7]

    if magic != 0xED26FF3A:
      raise ValueError("Magic should be 0xED26FF3A but is 0x%08X" % (magic,))
@@ -61,6 +62,9 @@ class SparseImage(object):
    print("Total of %u %u-byte output blocks in %u input chunks."
          % (total_blks, blk_sz, total_chunks))

    if not build_map:
      return

    pos = 0   # in blocks
    care_data = []
    self.offset_map = offset_map = []
@@ -126,6 +130,20 @@ class SparseImage(object):
    else:
      self.file_map = {"__DATA": self.care_map}

  def AppendFillChunk(self, data, blocks):
    f = self.simg_f

    # Append a fill chunk
    f.seek(0, os.SEEK_END)
    f.write(struct.pack("<2H3I", 0xCAC2, 0, blocks, 16, data))

    # Update the sparse header
    self.total_blocks += blocks
    self.total_chunks += 1

    f.seek(16, os.SEEK_SET)
    f.write(struct.pack("<2I", self.total_blocks, self.total_chunks))

  def ReadRangeSet(self, ranges):
    return [d for d in self._GetRangeData(ranges)]