• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1import common
2import struct
3
4def FindRadio(zipfile):
5  try:
6    return zipfile.read("RADIO/radio.img")
7  except KeyError:
8    return None
9
10
11def FullOTA_InstallEnd(info):
12  try:
13    bootloader_img = info.input_zip.read("RADIO/bootloader.img")
14  except KeyError:
15    print "no bootloader.img in target_files; skipping install"
16  else:
17    WriteBootloader(info, bootloader_img)
18
19  radio_img = FindRadio(info.input_zip)
20  if radio_img:
21    WriteRadio(info, radio_img)
22  else:
23    print "no radio.img in target_files; skipping install"
24
25
26def IncrementalOTA_VerifyEnd(info):
27  target_radio_img = FindRadio(info.target_zip)
28  source_radio_img = FindRadio(info.source_zip)
29  if not target_radio_img or not source_radio_img: return
30  if source_radio_img != target_radio_img:
31    info.script.CacheFreeSpaceCheck(len(source_radio_img))
32    radio_type, radio_device = common.GetTypeAndDevice("/radio", info.info_dict)
33    info.script.PatchCheck("%s:%s:%d:%s:%d:%s" % (
34        radio_type, radio_device,
35        len(source_radio_img), common.sha1(source_radio_img).hexdigest(),
36        len(target_radio_img), common.sha1(target_radio_img).hexdigest()))
37
38
39def IncrementalOTA_InstallEnd(info):
40  try:
41    target_bootloader_img = info.target_zip.read("RADIO/bootloader.img")
42    try:
43      source_bootloader_img = info.source_zip.read("RADIO/bootloader.img")
44    except KeyError:
45      source_bootloader_img = None
46
47    if source_bootloader_img == target_bootloader_img:
48      print "bootloader unchanged; skipping"
49    else:
50      WriteBootloader(info, target_bootloader_img)
51  except KeyError:
52    print "no bootloader.img in target target_files; skipping install"
53
54  tf = FindRadio(info.target_zip)
55  if not tf:
56    # failed to read TARGET radio image: don't include any radio in update.
57    print "no radio.img in target target_files; skipping install"
58  else:
59    tf = common.File("radio.img", tf)
60
61    sf = FindRadio(info.source_zip)
62    if not sf:
63      # failed to read SOURCE radio image: include the whole target
64      # radio image.
65      WriteRadio(info, tf.data)
66    else:
67      sf = common.File("radio.img", sf)
68
69      if tf.sha1 == sf.sha1:
70        print "radio image unchanged; skipping"
71      else:
72        diff = common.Difference(tf, sf, diff_program="bsdiff")
73        common.ComputeDifferences([diff])
74        _, _, d = diff.GetPatch()
75        if d is None or len(d) > tf.size * common.OPTIONS.patch_threshold:
76          # computing difference failed, or difference is nearly as
77          # big as the target:  simply send the target.
78          WriteRadio(info, tf.data)
79        else:
80          common.ZipWriteStr(info.output_zip, "radio.img.p", d)
81          info.script.Print("Patching radio...")
82          radio_type, radio_device = common.GetTypeAndDevice(
83              "/radio", info.info_dict)
84          info.script.ApplyPatch(
85              "%s:%s:%d:%s:%d:%s" % (radio_type, radio_device,
86                                     sf.size, sf.sha1, tf.size, tf.sha1),
87              "-", tf.size, tf.sha1, sf.sha1, "radio.img.p")
88
89
90def WriteRadio(info, radio_img):
91  info.script.Print("Writing radio...")
92  common.ZipWriteStr(info.output_zip, "radio.img", radio_img)
93  _, device = common.GetTypeAndDevice("/radio", info.info_dict)
94  info.script.AppendExtra(
95      'package_extract_file("radio.img", "%s");' % (device,))
96
97
98# /* msm8974 bootloader.img format */
99#
100# #define BOOTLDR_MAGIC "BOOTLDR!"
101# #define BOOTLDR_MAGIC_SIZE 8
102#
103# struct bootloader_images_header {
104#         char magic[BOOTLDR_MAGIC_SIZE];
105#         unsigned int num_images;
106#         unsigned int start_offset;
107#         unsigned int bootldr_size;
108#         struct {
109#                 char name[64];
110#                 unsigned int size;
111#         } img_info[];
112# };
113#
114# Hammerhead's bootloader.img contains 6 separate images.
115# Each goes to its own partition:
116#    aboot, rpm, tz, sbl1, sdi, imgdata
117#
118# Hammerhead also has 4 backup partitions:
119#    aboot, rpm, sbl1, tz
120#
121
122release_partitions = "aboot rpm tz sbl1 sdi imgdata"
123debug_partitions = "aboot rpm tz sbl1 sdi imgdata"
124backup_partitions = "aboot rpm sbl1 tz"
125
126def WriteBootloader(info, bootloader):
127  info.script.Print("Writing bootloader...")
128
129  header_fmt = "<8sIII"
130  header_size = struct.calcsize(header_fmt)
131  magic, num_images, start_offset, bootloader_size = struct.unpack(
132      header_fmt, bootloader[:header_size])
133  assert magic == "BOOTLDR!", "bootloader.img bad magic value"
134
135  img_info_fmt = "<64sI"
136  img_info_size = struct.calcsize(img_info_fmt)
137
138  imgs = [struct.unpack(img_info_fmt,
139                        bootloader[header_size+i*img_info_size:
140                                     header_size+(i+1)*img_info_size])
141          for i in range(num_images)]
142
143  total = 0
144  p = start_offset
145  img_dict = {}
146  for name, size in imgs:
147    img_dict[trunc_to_null(name)] = p, size
148    p += size
149  assert p - start_offset == bootloader_size, "bootloader.img corrupted"
150  imgs = img_dict
151
152  common.ZipWriteStr(info.output_zip, "bootloader-flag.txt",
153                     "updating-bootloader" + "\0" * 13)
154  common.ZipWriteStr(info.output_zip, "bootloader-flag-clear.txt", "\0" * 32)
155
156  _, misc_device = common.GetTypeAndDevice("/misc", info.info_dict)
157
158  info.script.AppendExtra(
159      'package_extract_file("bootloader-flag.txt", "%s");' %
160      (misc_device,))
161
162  # Depending on the build fingerprint, we can decide which partitions
163  # to update.
164  fp = info.info_dict["build.prop"]["ro.build.fingerprint"]
165  if "release-keys" in fp:
166    to_flash = release_partitions.split()
167  else:
168    to_flash = debug_partitions.split()
169
170  # Write the images to separate files in the OTA package
171  for i in to_flash:
172    try:
173      _, device = common.GetTypeAndDevice("/"+i, info.info_dict)
174    except KeyError:
175      print "skipping flash of %s; not in recovery.fstab" % (i,)
176      continue
177    common.ZipWriteStr(info.output_zip, "bootloader.%s.img" % (i,),
178                       bootloader[imgs[i][0]:imgs[i][0]+imgs[i][1]])
179
180    info.script.AppendExtra('package_extract_file("bootloader.%s.img", "%s");' %
181                            (i, device))
182
183  info.script.AppendExtra(
184      'package_extract_file("bootloader-flag-clear.txt", "%s");' %
185      (misc_device,))
186
187  try:
188    for i in backup_partitions.split():
189      _, device = common.GetTypeAndDevice("/"+i+"b", info.info_dict)
190      info.script.AppendExtra(
191          'package_extract_file("bootloader.%s.img", "%s");' % (i, device))
192  except KeyError:
193    pass
194
195
196def trunc_to_null(s):
197  if '\0' in s:
198    return s[:s.index('\0')]
199  else:
200    return s
201