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# /* msm8960 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 114def WriteBootloader(info, bootloader): 115 info.script.Print("Writing bootloader...") 116 117 # bootloader.img contains 6 separate images. Each goes to its own 118 # partition; we write all 6 for development devices but skip one for 119 # release devices.. There are backup partitions of all but the 120 # special one that we also write. The special one is "sbl1", which 121 # does not have a backup, so we don't update it on release devices.. 122 123 124 header_fmt = "<8sIII" 125 header_size = struct.calcsize(header_fmt) 126 magic, num_images, start_offset, bootloader_size = struct.unpack( 127 header_fmt, bootloader[:header_size]) 128 assert magic == "BOOTLDR!", "bootloader.img bad magic value" 129 130 img_info_fmt = "<64sI" 131 img_info_size = struct.calcsize(img_info_fmt) 132 133 imgs = [struct.unpack(img_info_fmt, 134 bootloader[header_size+i*img_info_size: 135 header_size+(i+1)*img_info_size]) 136 for i in range(num_images)] 137 138 total = 0 139 p = start_offset 140 img_dict = {} 141 for name, size in imgs: 142 img_dict[trunc_to_null(name)] = p, size 143 p += size 144 assert p - start_offset == bootloader_size, "bootloader.img corrupted" 145 imgs = img_dict 146 147 common.ZipWriteStr(info.output_zip, "bootloader-flag.txt", 148 "updating-bootloader" + "\0" * 13) 149 common.ZipWriteStr(info.output_zip, "bootloader-flag-clear.txt", "\0" * 32) 150 151 _, misc_device = common.GetTypeAndDevice("/misc", info.info_dict) 152 153 info.script.AppendExtra( 154 'package_extract_file("bootloader-flag.txt", "%s");' % 155 (misc_device,)) 156 157 # flashing sbl1 is somewhat dangerous because if we die while doing 158 # it the device can't boot. Do it for development devices but not 159 # release devices. 160 fp = info.info_dict["build.prop"]["ro.build.fingerprint"] 161 if "release-keys" in fp: 162 to_flash = "sbl2 sbl3 tz rpm aboot".split() 163 else: 164 to_flash = "sbl1 sbl2 sbl3 tz rpm aboot".split() 165 166 # Write the images to separate files in the OTA package 167 for i in to_flash: 168 try: 169 _, device = common.GetTypeAndDevice("/"+i, info.info_dict) 170 except KeyError: 171 print "skipping flash of %s; not in recovery.fstab" % (i,) 172 continue 173 common.ZipWriteStr(info.output_zip, "bootloader.%s.img" % (i,), 174 bootloader[imgs[i][0]:imgs[i][0]+imgs[i][1]]) 175 176 info.script.AppendExtra('package_extract_file("bootloader.%s.img", "%s");' % 177 (i, device)) 178 179 info.script.AppendExtra( 180 'package_extract_file("bootloader-flag-clear.txt", "%s");' % 181 (misc_device,)) 182 183 try: 184 # there is no "sbl1b" partition 185 for i in "sbl2 sbl3 tz rpm aboot".split(): 186 _, device = common.GetTypeAndDevice("/"+i+"b", info.info_dict) 187 info.script.AppendExtra( 188 'package_extract_file("bootloader.%s.img", "%s");' % (i, device)) 189 except KeyError: 190 pass 191 192 193def trunc_to_null(s): 194 if '\0' in s: 195 return s[:s.index('\0')] 196 else: 197 return s 198