blob: 520a080fa0cb1e46baa40e10d9ed8f65d042f7e2 [file] [log] [blame]
Doug Zongker021796c2012-08-14 13:36:09 -07001import common
2import struct
3
Doug Zongker4c179ca2012-08-14 16:04:34 -07004def FindRadio(zipfile):
5 try:
6 return zipfile.read("RADIO/radio.img")
7 except KeyError:
8 return None
9
10
Doug Zongker021796c2012-08-14 13:36:09 -070011def 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
Doug Zongker4c179ca2012-08-14 16:04:34 -070019 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
Doug Zongker021796c2012-08-14 13:36:09 -070039def 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
Doug Zongker4c179ca2012-08-14 16:04:34 -070054 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,))
Doug Zongker021796c2012-08-14 13:36:09 -070096
97
98# /* mako 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):
Doug Zongker4c179ca2012-08-14 16:04:34 -0700115 info.script.Print("Writing bootloader...")
116
Doug Zongker4c89a842012-08-16 16:20:10 -0700117 # 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
Doug Zongker021796c2012-08-14 13:36:09 -0700123
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
Doug Zongker021796c2012-08-14 13:36:09 -0700147 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
Doug Zongker4c89a842012-08-16 16:20:10 -0700157 # 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
Doug Zongker021796c2012-08-14 13:36:09 -0700173 common.ZipWriteStr(info.output_zip, "bootloader.%s.img" % (i,),
174 bootloader[imgs[i][0]:imgs[i][0]+imgs[i][1]])
Doug Zongker4c89a842012-08-16 16:20:10 -0700175
Doug Zongker021796c2012-08-14 13:36:09 -0700176 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:
Doug Zongker4c89a842012-08-16 16:20:10 -0700184 # there is no "sbl1b" partition
Doug Zongker021796c2012-08-14 13:36:09 -0700185 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
Doug Zongker021796c2012-08-14 13:36:09 -0700193def trunc_to_null(s):
194 if '\0' in s:
195 return s[:s.index('\0')]
196 else:
197 return s