Home | History | Annotate | Download | only in flo
      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