Recovery.img-系统升级


Recovery.img-系统升级
在V12bn 的机器上按住电源键+音量up 就可以进入Recovery 模式
从上图中我们也可以看出来恢复出厂设置有如下选项:
1)、Reboot system now: 重启手机
2)、Reboot to bootloader:重启到Recovery 模式
3)、Apply update from ADB:从ADB 进行更新
4)、Apply update from SD card:安装存储卡中的update.zip 升级包
5)、wipe data/factory reset: 清楚数据,恢复出厂设置
6)、wipe cache partition: 清除系统缓存
7)、Mount /system: 挂载system 文件夹
8)、View recovery logs: 恢复日志
9)、Run Graphics test: 图形测试
10)、Power off: 关机
当设备上电或Reboot 进入bootloader 时会检测此时是否有特殊键
被按下,V12N 机器电源键+音量up 就会进入recovery。bootloader
会读取misc 分区中bootloader_message 结构信息。
(bootloader_message 会告诉Recovery 系统需执行什么样的动作)。如:
1)、"recovery\n--update_package=CACHE:update.zip":更新AndroidOS
系统,升级包是/cache/update.zip。
2)、"recovery\n--wipe_date":清除用户数据后重启,通常用它做恢
复出厂设置功能。
3)、"recovery\n--wipe_cache":清除cachec 分区内容后重启,cache
分区一般放临时文件用。
一、Recovery 的启动
bootloader 加载recovery.img 读取img 头信息,并将相关信息加载
至制定内存地址,设置参数等操作后,跳转至kernel 在内存中的地址,
kernel 被加载启动。挂载根文件后执行init,init 会解析init.rc。init.rc:
service recovery /sbin/recovery
(Note:这里的init.rc 是在bootloader 目录下)
执行到这里recovery 就启动了。
二、update.zip 包
来源:OTA 在线下载,一般下载到cache 分区;或手动拷贝到SD 卡。
(即在cache 或者data 分区)
执行: 通过将--update_package=CACHE:some_filename.zip 或
--update_package=SDCARD:update.zip 命令写入到
/cache/recovery/command 中,当进入Recovery 之后,读取到command
文件中关于升级包的命令,就会开始执行升级。
签名:update.zip 包的签名:update.zip 更新包在制作完成后需要对其
签名,否则在升级时会出现认证失败的错误提示。而且签名要使用和
目标板一致的加密公钥。
相关升级函数:install_package()
Path:./bootable/recoovery/install.cpp
Int install_package(const char* path, bool* wipe_cache, const char* install_file,
bool needs_mount, int retry_count)
{
modified_flash = true;
auto start = std::chrono::system_clock::now();
//install_file 为/cache/recovery/last_install
FILE* install_log = fopen_path(install_file, "w");
if (install_log) {
fputs(path, install_log);
fputc('\n', install_log);
} else {
LOGE("failed to open last_install: %s\n", strerror(errno));
}
int result;
std::vector<std::string> log_buffer;
if (setup_install_mounts() != 0) {
LOGE("failed to set up expected mounts for install; aborting\n");
result = INSTALL_ERROR;
} else {
result = really_install_package(path, wipe_cache, needs_mount, log_buffer,
retry_count);
}
if (install_log != nullptr) {
fputc(result == INSTALL_SUCCESS ? '1' : '0', install_log);
fputc('\n', install_log);
std::chrono::duration<double> duration = std::chrono::system_clock::now()
- start;
int count = static_cast<int>(duration.count());
// Report the time spent to apply OTA update in seconds.
fprintf(install_log, "time_total: %d\n", count);
fprintf(install_log, "retry: %d\n", retry_count);
for (const auto& s : log_buffer) {
fprintf(install_log, "%s\n", s.c_str());
}
fclose(install_log);
}
if (result) {
LOGE("install package error, result = %d\n",result);
}
return result;
}
Note:返回升级安装包的结果result。在这个过程中它还会去调用一个重要的函数
really_install_package。
三、really_install_package
(这个函数的代码挺多的,不给出源码,下面是这个函数主要完成的工作)
really_install_package 函数在install_package 函数中被调用,函数的主要作用是
调用ensure_path_mounted 确保升级包所在的分区已经挂载(mount),另外,还
会对升级包进行一系列的校验,
在具体升级时,对update.zip 包检查时大致会分三步:
检验SF 文件与RSA 文件是否匹配;
检验MANIFEST.MF 与签名文件中的digest 是否一致;(所以需要签名!!!)
检验包中的文件与MANIFEST 中所描述的是否一致
通过校验后,调用try_update_binary 函数去实现真正的升级。
四、try_update_binary()
真正实现对升级包进行升级的函数
try_update_binary(const char* path, ZipArchive* zip, bool* wipe_cache,
std::vector<std::string>& log_buffer, int retry_count)
{
.................
const char* binary = "/tmp/update_binary";
unlink(binary); //将升级包里面META-INF/com/google/android/update-binary
解压到内存文件系统的/tmp/update_binary 中。
pid_t pid = fork(); //创建子线程
if (pid == 0) {
umask(022);
close(pipefd[0]);
execv(binary, (char* const*)args); //执行binary
fprintf(stdout, "E:Can't run %s (%s)\n", binary, strerror(errno));
_exit(-1);
}
..............
}
Note:update_binary 是Recovery OTA 升级的核心程序,是一个二进制文件,实现
代码位于系统源码bootable/recovery/updater。其实质是相当于一个脚本解释器,
能够识别updater-script 中描述的操作并执行。
总结:
1、判断是不是升级包是否适用于该设备,如果不适用,则停止
升级,否则继续
2、显示进度条
3、格式化system 分区
4、挂载system 分区
5、将ota 升级包里的system、recovery 目录解压到system 分区
6、建立一些软链接,升级过程需要用到
7、设置部分文件权限
8、将升级包里面的boot.img 写入到/boot 分区
9、清空misc 分区,即BCB 块(启动信息块)置为NULL
10、卸载system 分区

猜你喜欢

转载自blog.csdn.net/Toc_SunWinner/article/details/79314752