Bootloader和Recovery的基本介绍
文章目录
- Bootloader之高通LK介绍:
- bootloader的信息来源:Bootloader Control Block
- Android Recovery之系统升级:
- 信息交互:cache/recovery/中的三个文件
- 如何进入recovery升级
- 升级包(update.zip)
- fix.sh中update机制
- recovery进程获取command源码分析
- 比较容易弄混淆的点:
Bootloader之高通LK介绍:
硬件通电后,bootloader是必须要启动运行的,由bootloader来决定运行recovery系统还是android系统(即使在64bit架构,LK依旧运行在32bit模式)
bootloader进行硬件初始化,读取Linux内核和ramdisk,设置寄存器以及内核命令行参数,并跳转至内核运行主要功能:
- 硬件初始化:设置向量表,MMU,cache,初始化外设
- 从储存器加载boot.img
- kernel授权,生成boot.img的签名与校验(???)
iMX平台的bootloader用的是U-boot和高通不一样。
bootloader的信息来源:Bootloader Control Block
BCB是BootLoader和recovery的通信接口,也是BootLoader和android的通信接口,储存在MISC分区,占用3个page其本身是一个结构体:
struct bootloader_message {char command[32];char status[32];char recovery[1280];// The 'recovery' field used to be 1024 bytes. It has only ever// been used to store the recovery command line, so 768 bytes// should be plenty. We carve off the last 256 bytes to store the// stage string (for multistage packages) and possible future// expansion.char stage[32];// The 'reserved' field used to be 224 bytes when it was initially// carved off from the 1024-byte recovery field. Bump it up to// 1184-byte so that the entire bootloader_message struct rounds up// to 2048-byte.char reserved[672];
};
char command[32]:
可能的取值:NULL,boot-recovery,others
当想要进入recovery时更新这个值,结束recovery时,清除这个值,防止重启后再次进入recovery模式
char status[32]:
在完成相应的更新后,recovery会将执行结果写入到这个字段
char recovery[1024]:
可被main system写入,也可被recovery服务程序写入。该文件的内容格式:
"recovery\n<recovery command>\n<recovery command>"
该文件储存的就是一个字符串,必须以recovery\n开头,否则这个字段的所有内容会被忽略.开头之后的部分为command命令。
recovery对其操作的过程为:先读取BCB中是否有参数,如果BCB中没有就读取/cache/recovery/command 然后将其重新写入BCB(断电续升).
在进入main system之前,recovery又会清空BCB的command域和recovery域,这样确认重启之后不再进入recovery模式
bootloader将根据区域(char command[32])内的内容,进行判断该跳转至android系统还是recovery系统.
- android mode:正常启动模式(BCB中无命令),启动boot.img对应的系统,是android的正常工作模式.
- recovery mode:android重启进入recovery模式之前,会向BCB中写入命令,以便在重启后告诉bootloader进入recovery模式。
- 除了正常的加载启动系统之外,还会通过读取MISC分区(BCB)获得来自android和recovery的其他消息。
Android Recovery之系统升级:
recovery主要目的就是升级,系统进入recovery模式后会装载recovery分区,该分区包含recovery.img(与boot.img相同,包含了标准的内核和根文件系统).进入该模式后主要运行recovery服务(/sbin/recovery)
信息交互:cache/recovery/中的三个文件
- recovery/command:该文件保存着android传给recovery的命令行,每一行是一条命令,支持以下几种组合。
update_package=root:path
//这条命令存在时代表系统需要升级,在进入recovery模式后,将该文件中的命令读取并写入到BCB中,然后读取相应的zip包进行升级。
send_intent=anystring
//在recovery结束时在finish_recovery函数中将send_intent字符串作为参数传进来,并写入到intent中
wipe_data //擦除data和cache分区,擦除data分区时必须要擦除cache分区-> reboot
wipe_cache //擦除cache分区-> reboot
- recovery/log:recovery模式中的log
在recovery服务运行中,stdout和stderr会重定位到/tmp/recovery.log在recovery退出之前将其转存到/cache/recovery/log中
- recovery/intent:recovery传递给main system的信息,作用不详
如何进入recovery升级
- 系统重启并进入recovery模式之前,android会向BCB中的command域写入boot-recovery,用来告知bootloader重启后进入recovery模式(必须)。
- 向/cache/recovery/command中写入recovery将要进行的操作命令,或向BCB(recovery字符数组)中写入升级命令。
- 重启进入recovery模式后,recovery会从/cache/recovery/command中读取值并放入BCB的recovery域(如果BCB中无命令).
升级包(update.zip)
- 标准升级包:XXX_update.zip
- zip中包含升级可执行文件(upgrade可选)+升级文件+升级脚本(script)
- 升级脚本script中包含了如何进行升级(img文件的解压至相应分区)
- 定制升级包:upgrade为可执行文件,进行相应的升级流程(display/tp等)
fix.sh中update机制
- auto_update调用到minirecovery 对应源码/hardware/***/minirecovery.c
- /bootable/recovery/minirecovery对应生成minirecovery
- /bootable/recovery/bootloader_message/bootloader_message.cpp该代码中将minirecovery的参数bootargs写入BCB中
recovery进程获取command源码分析
下记源码记录了/sbin/recovery进程启动后获取升级命令行参数及处理过程 :
// command line args come from, in decreasing precedence:
// - the actual command line
// - the bootloader control block (one per line, after "recovery")
// - the contents of COMMAND_FILE (one per line)
static std::vector<std::string> get_args(const int argc, char** const argv) {CHECK_GT(argc, 0);bootloader_message boot = {};//定义BCB结构体std::string err;if (!read_bootloader_message(&boot, &err)) {//从BCB中读取数据LOG(ERROR) << err;// If fails, leave a zeroed bootloader_message.boot = {};}stage = std::string(boot.stage);if (boot.command[0] != 0) {std::string boot_command = std::string(boot.command, sizeof(boot.command));LOG(INFO) << "Boot command: " << boot_command;//此处确认BCB中是否有升级命令 log: [ 0.003542] I:Boot command: boot-recovery//通过log能看出此处的command指示了bootloader跳转至recovery系统}if (boot.status[0] != 0) {std::string boot_status = std::string(boot.status, sizeof(boot.status));LOG(INFO) << "Boot status: " << boot_status;}std::vector<std::string> args(argv, argv + argc);//该行将recovery进程启动时的参数保存,该处通常不使用// --- if arguments weren't supplied, look in the bootloader control blockif (args.size() == 1) {//size为1意味着recovery进程启动时的参数只有它自己boot.recovery[sizeof(boot.recovery) - 1] = '\0'; // Ensure terminationstd::string boot_recovery(boot.recovery);//将BCB中的recovery域内容保存下来std::vector<std::string> tokens = android::base::Split(boot_recovery, "\n");//将recovery域的内容以"\n"符号进行分隔if (!tokens.empty() && tokens[0] == "recovery") {//recovery域不是空的,且第一行是recovery(前面提到过需以recovery\n开头)for (auto it = tokens.begin() + 1; it != tokens.end(); it++) {// Skip empty and '\0'-filled tokens.if (!it->empty() && (*it)[0] != '\0') args.push_back(std::move(*it));//将BCB中的recovery命令追加到args后面}LOG(INFO) << "Got " << args.size() << " arguments from boot message";} else if (boot.recovery[0] != 0) {LOG(ERROR) << "Bad boot message: \"" << boot_recovery << "\"";}}LOG(INFO) << "commandline: "<< args[1] << " line:" << strlen(args[1].c_str());// --- if that doesn't work, try the command file (if we have /cache).if ((args.size() == 1) && has_cache) {//此处如果BCB中的recovery域无内容,则尝试在/cache/recovery/command中获取参数std::string content;if (ensure_path_mounted(COMMAND_FILE) == 0 &&android::base::ReadFileToString(COMMAND_FILE, &content)) {std::vector<std::string> tokens = android::base::Split(content, "\n");// All the arguments in COMMAND_FILE are needed (unlike the BCB message,// COMMAND_FILE doesn't use filename as the first argument).for (auto it = tokens.begin(); it != tokens.end(); it++) {// Skip empty and '\0'-filled tokens.if (!it->empty() && (*it)[0] != '\0') args.push_back(std::move(*it));}LOG(INFO) << "Got " << args.size() << " arguments from " << COMMAND_FILE;}}// Write the arguments (excluding the filename in args[0]) back into the// bootloader control block. So the device will always boot into recovery to// finish the pending work, until finish_recovery() is called.std::vector<std::string> options(args.cbegin() + 1, args.cend());if (!update_bootloader_message(options, &err)) {//将此处获取到的升级参数回写到BCB中,如果升级出现异常,再次启动还会进行升级LOG(ERROR) << "Failed to set BCB message: " << err;}return args;
}
比较容易弄混淆的点:
BCB中的command和/cache/recovery/command的内容并不等价,且不同类。
- BCB中的command:决定了bootloader该去引导android系统还是recovery系统
- BCB中的recovery:此处内容和/cache/recovery/command内容是等价的,以此来保存recovery在升级过程中的安装包是什么?是否要擦除用户数据等等参数。
to be continued
Bootloader和Recovery的基本介绍相关推荐
- 《Bootloader 启动流程和概念介绍》
Bootloader 启动流程 和 概念 介绍 1.概念 简单地说,Bootloader 就是在操作系统内核运行之前运行的一段程序,它类似于 PC机中的 BIOS 程序.通过这段程序,可以完成硬件设备 ...
- OTA和Recovery系统升级流程介绍
本文介绍了Android原生OTA和Recovery升级过程步骤. 进入升级 - 1.1 正常启动和进入Recovery的区别 下面给出了升级流程的简单示意图. 上图中的上下两个部分,上面一部分 ...
- oracle之Flash Recovery Area全面介绍
1. 设置闪回恢复区 闪回恢复区主要通过3个初始化参数来设置和管理 db_recovery_file_dest:指定闪回恢复区的位置 db_recovery_file_dest_size:指定闪回恢复 ...
- 启动代码和Bootloader的区别和关系介绍
注意:很多初学者总是将启动代码和Bootloader联系在一起,这是错误的 什么是启动代码? 启动代码是系统上电或者复位后运行的第一段代码,是进入C 语言的main 函数之前需要执行的那段汇编 ...
- Android Recovery:功能简介。Recovery模式介绍
Android Recovery Theory Android Recovery:功能简介 Android支持Recovery模式.在某些操作之后,系统会自动重启并进入到Recovery模式,用户按组 ...
- 嵌入式 Linux 启动流程和 bootloader 介绍
目录 嵌入式 Linux 启动流程 简介 启动流程 Bootloader 简介 市面上可见的 bootloader 入式 Linux 启动流程 简介 对于一个 SoC 芯片而言,bootloader ...
- 【转】Android Recovery模式
原文网址:http://leox.iteye.com/blog/975303 (muddogxp 原创,转载请注明) Recovery简介 Android利用Recovery模式,进行恢复出厂设置,O ...
- htc+one+m7+linux驱动,HTC One M7简易刷Recovery教程
HTC One M7作为当下HTC旗下的旗舰热门机,用户们对于刷机的需求都比较强烈,对于刷ROM的前提就是要刷入Recovery,当然作为安卓智能手机HTC one而言也不例外,最近有些用户在刷机啦论 ...
- 又一篇Android Recovery的文章
TOP: uboot里会读取 环境 变量类似的东西,判断是否进入RECOVERY 进入则load recovery.img 不进则load kernel.img 进入recovery: kernel ...
最新文章
- python入门学习基础数据结构与语法
- python统计excel出现次数_Python读取Excel一列并计算所有对象出现次数的方法
- 用python画猫咪怎么画-如何用Python画一只机器猫?
- (转载)Hadoop2.7.1配置
- 【安全系列之跨域】跨域解决方案
- Mybatis之加载mybatis-config.xml
- CSS之Responsive设计的关键三步
- snmp 获得硬件信息_信息系统项目管理师(三)
- (转)Bootstrap 之 Metronic 模板的学习之路 - (1)总览
- 你必须学会HTML和CSS的9大理由,让你在以后的工作中更香
- Unbuntu和Centos中部署同时多版本PHP的详细过程
- 钱花了才是自己的你们觉得这句话对吗?
- idea生成WebService调用代码
- magisk卸载内置软件_如何卸载/恢复iPhone自带的内置应用?
- Linux文件打包与解压缩
- 降龙十八掌搞定rt3070 USB WIFI模块在android2.3平台上上网[基于x210开发板]
- 图形界面介绍——Blockage相关
- 附合导线简易平差(4500PA)
- word表格合并单元格后,光标居中
- 快速搭建静态网站生成器
热门文章
- raise JSONDecodeError(“Extra data“, s, end) json.decoder.JSONDecodeError: Extra data: line 1 column
- MFC使用system有弹黑窗的解决 用WinExec(szBuffer, SW_HIDE);代替
- 常见的鼠标问题和解决方法
- 在surface go 2上安装ubuntu 20.04
- 本是后山人,偶做前堂客,醉舞经阁半卷书,坐井说天阔
- [win7]设置登录密码
- linux内网编译源码包,Netkeeper For Linux(含源码)
- 四阶r k matlab程序,四阶R-K公式计算
- 飞蚊症学计算机,电脑族,小心别让“飞蚊症”找上你
- 使用python爬虫技术进行有道词典翻译中英文【修正转载】