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_InstallBegin(info): 40 # Reduce the space taken by the journal. 41 info.script.Unmount("/system") 42 info.script.TunePartition("/system", "-O", "^has_journal") 43 info.script.Mount("/system") 44 45 46def IncrementalOTA_InstallEnd(info): 47 try: 48 target_bootloader_img = info.target_zip.read("RADIO/bootloader.img") 49 try: 50 source_bootloader_img = info.source_zip.read("RADIO/bootloader.img") 51 except KeyError: 52 source_bootloader_img = None 53 54 if source_bootloader_img == target_bootloader_img: 55 print "bootloader unchanged; skipping" 56 else: 57 WriteBootloader(info, target_bootloader_img) 58 except KeyError: 59 print "no bootloader.img in target target_files; skipping install" 60 61 tf = FindRadio(info.target_zip) 62 if not tf: 63 # failed to read TARGET radio image: don't include any radio in update. 64 print "no radio.img in target target_files; skipping install" 65 else: 66 tf = common.File("radio.img", tf) 67 68 sf = FindRadio(info.source_zip) 69 if not sf: 70 # failed to read SOURCE radio image: include the whole target 71 # radio image. 72 WriteRadio(info, tf.data) 73 else: 74 sf = common.File("radio.img", sf) 75 76 if tf.sha1 == sf.sha1: 77 print "radio image unchanged; skipping" 78 else: 79 diff = common.Difference(tf, sf, diff_program="bsdiff") 80 common.ComputeDifferences([diff]) 81 _, _, d = diff.GetPatch() 82 if d is None or len(d) > tf.size * common.OPTIONS.patch_threshold: 83 # computing difference failed, or difference is nearly as 84 # big as the target: simply send the target. 85 WriteRadio(info, tf.data) 86 else: 87 common.ZipWriteStr(info.output_zip, "radio.img.p", d) 88 info.script.Print("Patching radio...") 89 radio_type, radio_device = common.GetTypeAndDevice( 90 "/radio", info.info_dict) 91 info.script.ApplyPatch( 92 "%s:%s:%d:%s:%d:%s" % (radio_type, radio_device, 93 sf.size, sf.sha1, tf.size, tf.sha1), 94 "-", tf.size, tf.sha1, sf.sha1, "radio.img.p") 95 96 97def WriteRadio(info, radio_img): 98 info.script.Print("Writing radio...") 99 common.ZipWriteStr(info.output_zip, "radio.img", radio_img) 100 _, device = common.GetTypeAndDevice("/radio", info.info_dict) 101 info.script.AppendExtra( 102 'package_extract_file("radio.img", "%s");' % (device,)) 103 104 105# /* msm8960 bootloader.img format */ 106# 107# #define BOOTLDR_MAGIC "BOOTLDR!" 108# #define BOOTLDR_MAGIC_SIZE 8 109# 110# struct bootloader_images_header { 111# char magic[BOOTLDR_MAGIC_SIZE]; 112# unsigned int num_images; 113# unsigned int start_offset; 114# unsigned int bootldr_size; 115# struct { 116# char name[64]; 117# unsigned int size; 118# } img_info[]; 119# }; 120 121def WriteBootloader(info, bootloader): 122 info.script.Print("Writing bootloader...") 123 124 # bootloader.img contains 6 separate images. Each goes to its own 125 # partition; we write all 6 for development devices but skip one for 126 # release devices.. There are backup partitions of all but the 127 # special one that we also write. The special one is "sbl1", which 128 # does not have a backup, so we don't update it on release devices.. 129 130 131 header_fmt = "<8sIII" 132 header_size = struct.calcsize(header_fmt) 133 magic, num_images, start_offset, bootloader_size = struct.unpack( 134 header_fmt, bootloader[:header_size]) 135 assert magic == "BOOTLDR!", "bootloader.img bad magic value" 136 137 img_info_fmt = "<64sI" 138 img_info_size = struct.calcsize(img_info_fmt) 139 140 imgs = [struct.unpack(img_info_fmt, 141 bootloader[header_size+i*img_info_size: 142 header_size+(i+1)*img_info_size]) 143 for i in range(num_images)] 144 145 total = 0 146 p = start_offset 147 img_dict = {} 148 for name, size in imgs: 149 img_dict[trunc_to_null(name)] = p, size 150 p += size 151 assert p - start_offset == bootloader_size, "bootloader.img corrupted" 152 imgs = img_dict 153 154 common.ZipWriteStr(info.output_zip, "bootloader-flag.txt", 155 "updating-bootloader" + "\0" * 13) 156 common.ZipWriteStr(info.output_zip, "bootloader-flag-clear.txt", "\0" * 32) 157 158 _, misc_device = common.GetTypeAndDevice("/misc", info.info_dict) 159 160 info.script.AppendExtra( 161 'package_extract_file("bootloader-flag.txt", "%s");' % 162 (misc_device,)) 163 164 # flashing sbl1 is somewhat dangerous because if we die while doing 165 # it the device can't boot. Do it for development devices but not 166 # release devices. 167 fp = info.info_dict["build.prop"]["ro.build.fingerprint"] 168 if "release-keys" in fp: 169 to_flash = "sbl2 sbl3 tz rpm aboot".split() 170 else: 171 to_flash = "sbl1 sbl2 sbl3 tz rpm aboot".split() 172 173 # Write the images to separate files in the OTA package 174 for i in to_flash: 175 try: 176 _, device = common.GetTypeAndDevice("/"+i, info.info_dict) 177 except KeyError: 178 print "skipping flash of %s; not in recovery.fstab" % (i,) 179 continue 180 common.ZipWriteStr(info.output_zip, "bootloader.%s.img" % (i,), 181 bootloader[imgs[i][0]:imgs[i][0]+imgs[i][1]]) 182 183 info.script.AppendExtra('package_extract_file("bootloader.%s.img", "%s");' % 184 (i, device)) 185 186 info.script.AppendExtra( 187 'package_extract_file("bootloader-flag-clear.txt", "%s");' % 188 (misc_device,)) 189 190 try: 191 # there is no "sbl1b" partition 192 for i in "sbl2 sbl3 tz rpm aboot".split(): 193 _, device = common.GetTypeAndDevice("/"+i+"b", info.info_dict) 194 info.script.AppendExtra( 195 'package_extract_file("bootloader.%s.img", "%s");' % (i, device)) 196 except KeyError: 197 pass 198 199 200def trunc_to_null(s): 201 if '\0' in s: 202 return s[:s.index('\0')] 203 else: 204 return s 205