AB_OTA升级模式开启条件下(MTK_AB_OTA_UPDATER=y),进行线刷验证OTA升级。
1.制作差分包相关参数说明
-b 过时的。
-k 签名所使用的密钥
-i 生成增量OTA包时使用此选项。后面我们会用到这个选项来生成OTA增量包。
-w 是否清除userdata分区
-n 在升级时是否不检查时间戳,缺省要检查,即缺省情况下只能基于旧版本升级。
-e 是否有额外运行的脚本
-p 定义脚本用到的一些可执行文件的路径。
-s 定义额外运行脚本的路径。
-x 定义额外运行的脚本可能用的键值对。
-v 执行过程中打印出执行的命令。
-h 命令帮助
-m 执行过程中生成脚本(updater-script)所需要的格式,目前有两种即amend和edify。对应上两种版本升级时会采用不同的解释器。缺省会同时生成两种格式的脚本。
2.制作差分包
使用命令制作差分包
./build/tools/releasetools/ota_from_target_files -v -p out/host/linux-x86/ -i ota/v1.zip ota/v2.zip ota/update.zip
差分包原包:
out/target/product/{project}/obj/PACKAGING/target_files_intermediates/{project}-target_files-mp5V4129.zip
整包:
out/target/product/{project}/{project}-ota-mp5V4129.zip
3.跳过Recovery菜单选择界面,直接进入线刷模式
- 源码:bootable/recovery/recovery.cpp
+int update_complete = 0;
static Device::BuiltinAction PromptAndWait(Device* device, InstallResult status) {
auto ui = device->GetUI();
bool update_in_progress = (device->GetReason().value_or("") == "update_in_progress");
@@ -395,19 +396,24 @@ static Device::BuiltinAction PromptAndWait(Device* device, InstallResult status)
" Your device may fail to boot if you reboot or power off now." };
}
- size_t chosen_item = ui->ShowMenu(
- headers, device->GetMenuItems(), 0, false,
- std::bind(&Device::HandleMenuKey, device, std::placeholders::_1, std::placeholders::_2));
- // Handle Interrupt key
- if (chosen_item == static_cast<size_t>(RecoveryUI::KeyError::INTERRUPTED)) {
- return Device::KEY_INTERRUPTED;
- }
- // Device-specific code may take some action here. It may return one of the core actions
- // handled in the switch statement below.
- Device::BuiltinAction chosen_action =
- (chosen_item == static_cast<size_t>(RecoveryUI::KeyError::TIMED_OUT))
- ? Device::REBOOT
- : device->InvokeMenuItem(chosen_item);
+ Device::BuiltinAction chosen_action = Device::NO_ACTION;
+ if (update_complete > 0){
+ size_t chosen_item = ui->ShowMenu(
+ headers, device->GetMenuItems(), 0, false,
+ std::bind(&Device::HandleMenuKey, device, std::placeholders::_1, std::placeholders::_2));
+ // Handle Interrupt key
+ if (chosen_item == static_cast<size_t>(RecoveryUI::KeyError::INTERRUPTED)) {
+ return Device::KEY_INTERRUPTED;
+ }
+ // Device-specific code may take some action here. It may return one of the core actions
+ // handled in the switch statement below.
+ chosen_action =
+ (chosen_item == static_cast<size_t>(RecoveryUI::KeyError::TIMED_OUT))
+ ? Device::REBOOT
+ : device->InvokeMenuItem(chosen_item);
+ } else {
+ // 默认选择线刷模式
+ chosen_action = Device::APPLY_ADB_SIDELOAD;
+ }
switch (chosen_action) {
case Device::REBOOT_FROM_FASTBOOT: // Can not happen
@@ -496,6 +502,7 @@ static Device::BuiltinAction PromptAndWait(Device* device, InstallResult status)
ui->Print("Installation aborted.\n");
copy_logs(save_current_log);
}
+ update_complete = 1;
break;
}
4.使用adb进行升级
设备先刷入v1版本软件
进入recovery模式
adb reboot recovery
稍等一会界面会提示
Now send the package you want to apply
to the device with "adb sidelaod <filename>"...
输入命令开始升级
adb sideload Z:\xxx\xxx\ota\update.zip
update.zip是制作好的差分包
5.出现kDownloadStateInitializationError错误
结果并没有成功,界面显示
Now send the package you want to apply
to the device with "adb sidelaod <filename>"...
Supported API: 3
Finding update package...
Verifying update package...
Update package verification took 0.2s (result 0).
Installing update...
Step 1/2
Error applaying update: 20 (ErrorCode:kDownloadStateInitializationError)
E:Error in /sideload/package.zip(status 1)
Install from ADB completed with status 1.
Installation aborted.
导出recovery.log
adb pull /tmp/recovery.log d:/log
关键log如下
[ 12.789101] update_engine_sideload I 03-22 03:23:25 243 243 [INFO:delta_performer.cc(397)] Applying 432 operations to partition "system"
[ 16.874701] update_engine_sideload I 03-22 03:23:29 243 243 [INFO:delta_performer.cc(209)] Completed 147/667 operations (22%), 2785280/2788529 bytes downloaded (99%), overall progress 60%
[ 21.930529] update_engine_sideload I 03-22 03:23:34 243 243 [INFO:delta_performer.cc(209)] Completed 281/667 operations (42%), 2785280/2788529 bytes downloaded (99%), overall progress 70%
[ 27.169636] update_engine_sideload I 03-22 03:23:39 243 243 [INFO:delta_performer.cc(209)] Completed 414/667 operations (62%), 2785280/2788529 bytes downloaded (99%), overall progress 80%
[ 27.628061] I:current maximum temperature: 53400
[ 30.098801] update_engine_sideload I 03-22 03:23:42 243 243 [INFO:delta_performer.cc(385)] Opening /dev/block/platform/soc/11230000.mmc/by-name/lk_b partition without O_DSYNC
[ 30.106429] update_engine_sideload I 03-22 03:23:42 243 243 [INFO:delta_performer.cc(128)] Caching writes.
[ 30.106723] update_engine_sideload I 03-22 03:23:42 243 243 [INFO:delta_performer.cc(397)] Applying 6 operations to partition "lk"
[ 30.148475] avb_footer.c:41: ERROR: Footer magic is incorrect.
[ 30.155000] update_engine_sideload E 03-22 03:23:42 243 243 [ERROR:fec_file_descriptor.cc(30)] No ECC data in the passed file
[ 30.155053] update_engine_sideload E 03-22 03:23:42 243 243 [ERROR:delta_performer.cc(431)] Unable to open ECC source partition lk on slot A, file /dev/block/platform/soc/11230000.mmc/by-name/lk_a: Invalid argument (22)
[ 30.155089] update_engine_sideload E 03-22 03:23:42 243 243 [ERROR:delta_performer.cc(1158)] The hash of the source data on disk for this operation doesn't match the expected value. This could mean that the delta update payload was targeted for another version, or that the source partition was modified after it was installed, for example, by mounting a filesystem.
[ 30.155110] update_engine_sideload E 03-22 03:23:42 243 243 [ERROR:delta_performer.cc(1163)] Expected: sha256|hex = D19BC4D6CE0BB9DA353AD26EFBD9D3A889EE24B926E0843E94E68F945C8BB1FD
[ 30.155143] update_engine_sideload E 03-22 03:23:42 243 243 [ERROR:delta_performer.cc(1166)] Calculated: sha256|hex = 9DD7A21C4009F84D831B64A483684DD27AB9D200AF935D4C2F4C3904F664B87F
[ 30.155163] update_engine_sideload E 03-22 03:23:42 243 243 [ERROR:delta_performer.cc(1177)] Operation source (offset:size) in blocks: 0:128,129:41
[ 30.155529] update_engine_sideload E 03-22 03:23:42 243 243 [ERROR:delta_performer.cc(1498)] source_fd != nullptr failed.
[ 30.155554] update_engine_sideload E 03-22 03:23:42 243 243 [ERROR:delta_performer.cc(297)] Failed to perform BROTLI_BSDIFF operation 463, which is the operation 1 in partition "lk"
[ 30.155575] update_engine_sideload E 03-22 03:23:42 243 243 [ERROR:download_action.cc(336)] Error ErrorCode::kDownloadStateInitializationError (20) in DeltaPerformer's Write method when processing the received payload -- Terminating processing
从log上可以看到是应用lk分区是出错,Hash值不匹配
原因: make otapackage 会对.img重新打包 导致重新打包的.img和out目录下的.img Hash值不一致. 也就是线刷版本的.img和OTA包的.img不一致;整包升级会替换.img,而差分包升级则需要保证系统内部的.img和整包中.img一致才能升级成功(差分包中保存了通过sha256 Hash算法计算出整包.img的值,通过这个值来确定两个.img一致).
做了如下两种测试
①使用差分包原包中的.img文件
使用out/target/product/{project}/obj/PACKAGING/target_files_intermediates/{project}-target_files-mp5V4129下的lk.img和tee.img替换掉out/target/product/{project}/下的文件,刷机后再进行OTA差分升级成功
②解包payload.bin
payload.bin文件是由整包文件解压得来的,使用payload.bin解包后中的lk.img和tee.img替换掉out/target/product/{project}/下的文件,刷机后再进行OTA差分升级成功
6.OTA升级失败错误码
ErrorCode::kSuccess (0) 升级成功
ErrorCode::kSuccess (1) 升级失败
ErrorCode::kFilesystemCopierError (4) 未知,暂时未使用的错误码
ErrorCode::kPostinstallRunnerError (5) 升级安装结束,设置启动分区失败
ErrorCode::kPayloadMismatchedType (6) 升级包的升级类型不匹配或升级包minor version不兼容
ErrorCode::kInstallDeviceOpenError (7) 无法启动升级。可能是原因:分区错误,设备支持升级的分区和升级包内的不匹配;设备处于disable-verity状态;
ErrorCode::kKernelDeviceOpenError (8) 未知,暂时未使用的错误码
ErrorCode::kDownloadTransferError (9) w,找不到升级包
ErrorCode::kPayloadHashMismatchError (10) FILE_HASH值不匹配
ErrorCode::kPayloadSizeMismatchError (11) 数据size不匹配
ErrorCode::kDownloadPayloadVerificationError (12) 签名验证失败
ErrorCode::kDownloadStateInitializationError (20) 升级包写入时失败 一般都是发生在差分包升级时,检测boot、system、vendor的hash值不匹配。
ErrorCode::kDownloadInvalidMetadataMagicString (21) 未找到正确bin文件,一般是offset不对导致
ErrorCode::kDownloadInvalidMetadataSize (32) METADATA_SIZE值不匹配
ErrorCode::kPayloadTimestampError (51) 升级包的date比机器当前版本早
Android 系统OTA升级
Android系统OTA差分升级失败kDownloadStateInitializationError
Android OTA差分包升级失败