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