blob: 0cc6b3e73f38ab3b3842ad00f1acfdd09fae8b08
1 | # Copyright (C) 2012 The Android Open Source Project |
2 | # |
3 | # Licensed under the Apache License, Version 2.0 (the "License"); |
4 | # you may not use this file except in compliance with the License. |
5 | # You may obtain a copy of the License at |
6 | # |
7 | # http://www.apache.org/licenses/LICENSE-2.0 |
8 | # |
9 | # Unless required by applicable law or agreed to in writing, software |
10 | # distributed under the License is distributed on an "AS IS" BASIS, |
11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
12 | # See the License for the specific language governing permissions and |
13 | # limitations under the License. |
14 | |
15 | """Emit extra commands needed for Group during OTA installation |
16 | (installing the bootloader).""" |
17 | |
18 | import os |
19 | import tempfile |
20 | import struct |
21 | import common |
22 | import sparse_img |
23 | import add_img_to_target_files |
24 | |
25 | def SetBootloaderEnv(script, name, val): |
26 | """Set bootloader env name with val.""" |
27 | script.AppendExtra('set_bootloader_env("%s", "%s");' % (name, val)) |
28 | |
29 | def LoadInfoDict_amlogic(info_dict, input_file, input_dir=None): |
30 | """Read and parse the META/misc_info.txt key/value pairs from the |
31 | input target files and return a dict.""" |
32 | |
33 | data = input_file.read("VENDOR/build.prop") |
34 | data += input_file.read("VENDOR/default.prop") |
35 | |
36 | info_dict["vendor.prop"] = common.LoadDictionaryFromLines(data.split("\n")) |
37 | |
38 | print("--- *************** ---") |
39 | common.DumpInfoDict(info_dict) |
40 | |
41 | return True |
42 | |
43 | def GetBuildProp(prop, info_dict): |
44 | """Return the fingerprint of the build of a given target-files info_dict.""" |
45 | try: |
46 | return info_dict.get("build.prop", {})[prop] |
47 | except KeyError: |
48 | print "couldn't find %s in build.prop, try vendor.prop" %(prop) |
49 | #raise common.ExternalError("couldn't find %s in build.prop" % (prop,)) |
50 | |
51 | try: |
52 | return info_dict.get("vendor.prop", {})[prop] |
53 | except KeyError: |
54 | raise common.ExternalError("couldn't find %s in build.prop & vendor.prop" % (prop,)) |
55 | |
56 | def HasTargetImage(target_files_zip, image_path): |
57 | try: |
58 | target_files_zip.getinfo(image_path) |
59 | return True |
60 | except KeyError: |
61 | return False |
62 | |
63 | def BuildExt4(name, input_dir, info_dict, block_list=None): |
64 | """Build the (sparse) vendor image and return the name of a temp |
65 | file containing it.""" |
66 | return add_img_to_target_files.CreateImage(input_dir, info_dict, name, block_list=block_list) |
67 | |
68 | def GetImage(which, tmpdir, info_dict): |
69 | # Return an image object (suitable for passing to BlockImageDiff) |
70 | # for the 'which' partition (most be "system" or "vendor"). If a |
71 | # prebuilt image and file map are found in tmpdir they are used, |
72 | # otherwise they are reconstructed from the individual files. |
73 | |
74 | path = os.path.join(tmpdir, "IMAGES", which + ".img") |
75 | mappath = os.path.join(tmpdir, "IMAGES", which + ".map") |
76 | if os.path.exists(path) and os.path.exists(mappath): |
77 | print "using %s.img from target-files" % (which,) |
78 | # This is a 'new' target-files, which already has the image in it. |
79 | else: |
80 | print "building %s.img from target-files" % (which,) |
81 | # This is an 'old' target-files, which does not contain images |
82 | # already built. Build them. |
83 | mappath = tempfile.mkstemp()[1] |
84 | common.OPTIONS.tempfiles.append(mappath) |
85 | path = BuildExt4(which, tmpdir, info_dict, block_list = mappath) |
86 | |
87 | return sparse_img.SparseImage(path, mappath) |
88 | |
89 | def BuildCustomerImage(info): |
90 | print "amlogic extensions:BuildCustomerImage" |
91 | if info.info_dict.get("update_user_parts") == "true" : |
92 | partsList = info.info_dict.get("user_parts_list"); |
93 | for list_i in partsList.split(' '): |
94 | tmp_tgt = GetImage(list_i, info.input_tmp, info.info_dict) |
95 | tmp_tgt.ResetFileMap() |
96 | tmp_diff = common.BlockDifference(list_i, tmp_tgt, src = None) |
97 | tmp_diff.WriteScript(info.script,info.output_zip) |
98 | |
99 | def BuildCustomerIncrementalImage(info, *par, **dictarg): |
100 | print "amlogic extensions:BuildCustomerIncrementalImage" |
101 | fun = [] |
102 | for pp in par: |
103 | fun.append(pp) |
104 | if info.info_dict.get("update_user_parts") == "true" : |
105 | partsList = info.info_dict.get("user_parts_list"); |
106 | for list_i in partsList.split(' '): |
107 | if HasTargetImage(info.source_zip, list_i.upper() + "/"): |
108 | tmp_diff = fun[0](list_i, info.source_zip, info.target_zip, info.output_zip) |
109 | recovery_mount_options = common.OPTIONS.info_dict.get("recovery_mount_options") |
110 | info.script.Mount("/"+list_i, recovery_mount_options) |
111 | so_far = tmp_diff.EmitVerification(info.script) |
112 | size = [] |
113 | if tmp_diff.patch_list: |
114 | size.append(tmp_diff.largest_source_size) |
115 | tmp_diff.RemoveUnneededFiles(info.script) |
116 | total_patch_size = 1.0 + tmp_diff.TotalPatchSize() |
117 | total_patch_size += tmp_diff.TotalPatchSize() |
118 | tmp_diff.EmitPatches(info.script, total_patch_size, 0) |
119 | tmp_items = fun[1](list_i, "META/" + list_i + "_filesystem_config.txt") |
120 | |
121 | fun[2](tmp_items, info.target_zip, None) |
122 | temp_script = info.script.MakeTemporary() |
123 | tmp_items.GetMetadata(info.target_zip) |
124 | tmp_items.Get(list_i).SetPermissions(temp_script) |
125 | fun[2](tmp_items, info.source_zip, None) |
126 | if tmp_diff and tmp_diff.verbatim_targets: |
127 | info.script.Print("Unpacking new files...") |
128 | info.script.UnpackPackageDir(list_i, "/" + list_i) |
129 | |
130 | tmp_diff.EmitRenames(info.script) |
131 | if common.OPTIONS.verify and tmp_diff: |
132 | info.script.Print("Remounting and verifying partition files...") |
133 | info.script.Unmount("/" + list_i) |
134 | info.script.Mount("/" + list_i) |
135 | tmp_diff.EmitExplicitTargetVerification(info.script) |
136 | |
137 | |
138 | def FullOTA_Assertions(info): |
139 | print "amlogic extensions:FullOTA_Assertions" |
140 | |
141 | def FullOTA_InstallBegin(info): |
142 | print "amlogic extensions:FullOTA_InstallBegin" |
143 | LoadInfoDict_amlogic(info.info_dict, info.input_zip); |
144 | platform = GetBuildProp("ro.board.platform", info.info_dict) |
145 | print "ro.board.platform: %s" % (platform) |
146 | if "meson3" in platform: |
147 | SetBootloaderEnv(info.script, "upgrade_step", "0") |
148 | elif "meson6" in platform: |
149 | SetBootloaderEnv(info.script, "upgrade_step", "0") |
150 | else: |
151 | SetBootloaderEnv(info.script, "upgrade_step", "3") |
152 | |
153 | def FullOTA_InstallEnd(info): |
154 | print "amlogic extensions:FullOTA_InstallEnd" |
155 | bootloader_img_exist = 0 |
156 | try: |
157 | bootloader_img_info = info.input_zip.getinfo("BOOTLOADER/bootloader") |
158 | bootloader_img_exist = 1 |
159 | bootloader_img = common.File("bootloader.img", info.input_zip.read("BOOTLOADER/bootloader")); |
160 | except KeyError: |
161 | print 'WARNING: No BOOTLOADER found' |
162 | |
163 | if bootloader_img_exist: |
164 | common.CheckSize(bootloader_img.data, "bootloader.img", info.info_dict) |
165 | common.ZipWriteStr(info.output_zip, "bootloader.img", bootloader_img.data) |
166 | info.script.WriteRawImage("/bootloader", "bootloader.img") |
167 | SetBootloaderEnv(info.script, "upgrade_step", "1") |
168 | else: |
169 | SetBootloaderEnv(info.script, "upgrade_step", "1") |
170 | |
171 | SetBootloaderEnv(info.script, "force_auto_update", "false") |
172 | |
173 | |
174 | def IncrementalOTA_VerifyBegin(info): |
175 | print "amlogic extensions:IncrementalOTA_VerifyBegin" |
176 | |
177 | def IncrementalOTA_VerifyEnd(info): |
178 | print "amlogic extensions:IncrementalOTA_VerifyEnd" |
179 | |
180 | def IncrementalOTA_InstallBegin(info): |
181 | LoadInfoDict_amlogic(info.info_dict, info.target_zip); |
182 | platform = GetBuildProp("ro.board.platform", info.info_dict) |
183 | print "ro.board.platform: %s" % (platform) |
184 | if "meson3" in platform: |
185 | SetBootloaderEnv(info.script, "upgrade_step", "0") |
186 | elif "meson6" in platform: |
187 | SetBootloaderEnv(info.script, "upgrade_step", "0") |
188 | else: |
189 | SetBootloaderEnv(info.script, "upgrade_step", "3") |
190 | print "amlogic extensions:IncrementalOTA_InstallBegin" |
191 | |
192 | def IncrementalOTA_ImageCheck(info, name): |
193 | source_image = False; target_image = False; updating_image = False; |
194 | |
195 | image_path = name.upper() + "/" + name |
196 | image_name = name + ".img" |
197 | |
198 | if HasTargetImage(info.source_zip, image_path): |
199 | source_image = common.File(image_name, info.source_zip.read(image_path)); |
200 | |
201 | if HasTargetImage(info.target_zip, image_path): |
202 | target_image = common.File(image_name, info.target_zip.read(image_path)); |
203 | |
204 | if target_image: |
205 | if source_image: |
206 | updating_image = (source_image.data != target_image.data); |
207 | else: |
208 | updating_image = 1; |
209 | |
210 | if updating_image: |
211 | message_process = "install " + name + " image..." |
212 | info.script.Print(message_process); |
213 | common.ZipWriteStr(info.output_zip, image_name, target_image.data) |
214 | if name == "dtb": |
215 | info.script.WriteDtbImage(image_name) |
216 | else: |
217 | info.script.WriteRawImage("/" + name, image_name) |
218 | |
219 | if name == "bootloader": |
220 | if updating_image: |
221 | SetBootloaderEnv(info.script, "upgrade_step", "1") |
222 | else: |
223 | SetBootloaderEnv(info.script, "upgrade_step", "2") |
224 | |
225 | |
226 | def IncrementalOTA_InstallEnd(info): |
227 | print "amlogic extensions:IncrementalOTA_InstallEnd" |
228 | IncrementalOTA_ImageCheck(info, "logo"); |
229 | IncrementalOTA_ImageCheck(info, "dtb"); |
230 | IncrementalOTA_ImageCheck(info, "bootloader"); |
231 |