文章目录

  • 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/中的三个文件

  1. 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

  1. recovery/log:recovery模式中的log

在recovery服务运行中,stdout和stderr会重定位到/tmp/recovery.log在recovery退出之前将其转存到/cache/recovery/log中

  1. recovery/intent:recovery传递给main system的信息,作用不详

如何进入recovery升级

  1. 系统重启并进入recovery模式之前,android会向BCB中的command域写入boot-recovery,用来告知bootloader重启后进入recovery模式(必须)。
  2. 向/cache/recovery/command中写入recovery将要进行的操作命令,或向BCB(recovery字符数组)中写入升级命令。
  3. 重启进入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的基本介绍相关推荐

  1. 《Bootloader 启动流程和概念介绍》

    Bootloader 启动流程 和 概念 介绍 1.概念 简单地说,Bootloader 就是在操作系统内核运行之前运行的一段程序,它类似于 PC机中的 BIOS 程序.通过这段程序,可以完成硬件设备 ...

  2. OTA和Recovery系统升级流程介绍

    本文介绍了Android原生OTA和Recovery升级过程步骤. 进入升级 - 1.1 正常启动和进入Recovery的区别 下面给出了升级流程的简单示意图.    上图中的上下两个部分,上面一部分 ...

  3. oracle之Flash Recovery Area全面介绍

    1. 设置闪回恢复区 闪回恢复区主要通过3个初始化参数来设置和管理 db_recovery_file_dest:指定闪回恢复区的位置 db_recovery_file_dest_size:指定闪回恢复 ...

  4. 启动代码和Bootloader的区别和关系介绍

    注意:很多初学者总是将启动代码和Bootloader联系在一起,这是错误的 什么是启动代码?     启动代码是系统上电或者复位后运行的第一段代码,是进入C 语言的main 函数之前需要执行的那段汇编 ...

  5. Android Recovery:功能简介。Recovery模式介绍

    Android Recovery Theory Android Recovery:功能简介 Android支持Recovery模式.在某些操作之后,系统会自动重启并进入到Recovery模式,用户按组 ...

  6. 嵌入式 Linux 启动流程和 bootloader 介绍

    目录 嵌入式 Linux 启动流程 简介 启动流程 Bootloader 简介 市面上可见的 bootloader 入式 Linux 启动流程 简介 对于一个 SoC 芯片而言,bootloader ...

  7. 【转】Android Recovery模式

    原文网址:http://leox.iteye.com/blog/975303 (muddogxp 原创,转载请注明) Recovery简介 Android利用Recovery模式,进行恢复出厂设置,O ...

  8. htc+one+m7+linux驱动,HTC One M7简易刷Recovery教程

    HTC One M7作为当下HTC旗下的旗舰热门机,用户们对于刷机的需求都比较强烈,对于刷ROM的前提就是要刷入Recovery,当然作为安卓智能手机HTC one而言也不例外,最近有些用户在刷机啦论 ...

  9. 又一篇Android Recovery的文章

    TOP: uboot里会读取 环境 变量类似的东西,判断是否进入RECOVERY 进入则load recovery.img 不进则load kernel.img 进入recovery: kernel ...

最新文章

  1. python入门学习基础数据结构与语法
  2. python统计excel出现次数_Python读取Excel一列并计算所有对象出现次数的方法
  3. 用python画猫咪怎么画-如何用Python画一只机器猫?
  4. (转载)Hadoop2.7.1配置
  5. 【安全系列之跨域】跨域解决方案
  6. Mybatis之加载mybatis-config.xml
  7. CSS之Responsive设计的关键三步
  8. snmp 获得硬件信息_信息系统项目管理师(三)
  9. (转)Bootstrap 之 Metronic 模板的学习之路 - (1)总览
  10. 你必须学会HTML和CSS的9大理由,让你在以后的工作中更香
  11. Unbuntu和Centos中部署同时多版本PHP的详细过程
  12. 钱花了才是自己的你们觉得这句话对吗?
  13. idea生成WebService调用代码
  14. magisk卸载内置软件_如何卸载/恢复iPhone自带的内置应用?
  15. Linux文件打包与解压缩
  16. 降龙十八掌搞定rt3070 USB WIFI模块在android2.3平台上上网[基于x210开发板]
  17. 图形界面介绍——Blockage相关
  18. 附合导线简易平差(4500PA)
  19. word表格合并单元格后,光标居中
  20. 快速搭建静态网站生成器

热门文章

  1. raise JSONDecodeError(“Extra data“, s, end) json.decoder.JSONDecodeError: Extra data: line 1 column
  2. MFC使用system有弹黑窗的解决 用WinExec(szBuffer, SW_HIDE);代替
  3. 常见的鼠标问题和解决方法
  4. 在surface go 2上安装ubuntu 20.04
  5. 本是后山人,偶做前堂客,醉舞经阁半卷书,坐井说天阔
  6. [win7]设置登录密码
  7. linux内网编译源码包,Netkeeper For Linux(含源码)
  8. 四阶r k matlab程序,四阶R-K公式计算
  9. 飞蚊症学计算机,电脑族,小心别让“飞蚊症”找上你
  10. 使用python爬虫技术进行有道词典翻译中英文【修正转载】