summaryrefslogtreecommitdiff
path: root/scripts/cow_converter.py
blob: 14e016cb4dfcf23666f7acc08cc6db15dc189a30 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
#!/usr/bin/env python3
#
# Copyright (C) 2021 The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

"""Command-line tool for converting OTA payloads to VABC style COW images."""

import os
import sys
import tempfile
import zipfile
import subprocess


def IsSparseImage(filepath):
  """Determine if an image is a sparse image
  Args:
    filepath: str, a path to an .img file

  Returns:
    return true iff the filepath is a sparse image.

  """
  with open(filepath, 'rb') as fp:
    # Magic for android sparse image format
    # https://source.android.com/devices/bootloader/images
    return fp.read(4) == b'\x3A\xFF\x26\xED'


def ConvertCOW(ota_path, target_file_path, tmp_dir, output_dir):
  """Convert ota payload to COW IMAGE
  Args:
    ota_path: str, path to ota.zip
    target_file_path: str, path to target_file.zip,
      must be the target build for OTA.
    tmp_dir: A temp dir as scratch space
    output_dir: A directory where all converted COW images will be written.
  """
  with zipfile.ZipFile(ota_path) as ota_zip:
    payload_path = ota_zip.extract("payload.bin", output_dir)
  with zipfile.ZipFile(target_file_path) as zfp:
    for fileinfo in zfp.infolist():
      img_name = os.path.basename(fileinfo.filename)
      if not fileinfo.filename.endswith(".img"):
        continue
      if fileinfo.filename.startswith("IMAGES/") or \
              fileinfo.filename.startswith("RADIO/"):
        img_path = zfp.extract(fileinfo, tmp_dir)
        target_img_path = os.path.join(output_dir, img_name)
        if IsSparseImage(img_path):
          subprocess.check_call(["simg2img", img_path, target_img_path])
        else:
          os.rename(img_path, target_img_path)
        print("Extracted", fileinfo.filename, "size:", fileinfo.file_size)

  subprocess.call(["cow_converter", payload_path,
                   output_dir])


def main():
  if len(sys.argv) != 4:
    print(
        "Usage:", sys.argv[0], "<your_ota.zip> <target_file.zip> <output dir>")
    return 1
  ota_path = sys.argv[1]
  target_file_path = sys.argv[2]
  output_dir = sys.argv[3]
  os.makedirs(output_dir, exist_ok=True)
  with tempfile.TemporaryDirectory() as tmp_dir:
    ConvertCOW(ota_path, target_file_path, tmp_dir, output_dir)
  return 0


if __name__ == '__main__':
  sys.exit(main())