安卓recovery启动到升级一目了然

recovery源码的入口位置为:bootable/recovery/recovery.cpp文件

int main(int argc, char **argv)
{
    打印启动recovery的时间
    printf("Starting recovery on %s", ctime(&start));

    一、填充fstab结构体

     load_volume_table(){

        1.1解析/etc/recovery.fstab配置文件,填充fstab结构体

        fstab = fs_mgr_read_fstab("/etc/recovery.fstab");

        1.2在fstab结构体中增加/tmp分区

        ret = fs_mgr_add_entry(fstab, "/tmp", "ramdisk", "ramdisk", 0);
    }

    二、挂载cache分区

     ensure_path_mounted(LAST_LOG_FILE){

        2.1这里是在fstab结构体中找到挂载点为/cache的fstab_recs

        Volume* v = volume_for_path(path);

        2.2ramdisk类型的分区是一直挂载的。

        if (strcmp(v->fs_type, "ramdisk") == 0) {
            return 0;
        }

        2.3当前分区是否被挂载

        const MountedVolume* mv = find_mounted_volume_by_mount_point(v->mount_point);
        if (mv) {
           //已经被挂载
           return 0;
       }

        2.4具体的挂载过程

        mkdir(v->mount_point, 0755);
        if (strcmp(v->fs_type, "ext4") == 0 || strcmp(v->fs_type, "vfat") == 0) {
            // ext4和vfat类型的分区调用mount函数进行挂载,挂载成功返回0,失败返回-1
            result = mount(v->blk_device, v->mount_point, v->fs_type, MS_NOATIME | MS_NODEV | MS_NODIRATIME, "");
        }
    }

    三、获取Recovery命令参数

     get_args(&argc, &argv){

        3.1首先从MISC分区中读取BCB数据块到boot变量中,可能存在为空的情况。

        get_bootloader_message(&boot);
        stage = strndup(boot.stage, sizeof(boot.stage));

        3.2从/cache/recovery/command获取参数,一般常用的ota升级做法。

        if (*argc < 1) {
            FILE *fp = fopen_path(COMMAND_FILE, "r");
            if (fp != NULL) {        
                *argv = (char **) malloc(sizeof(char *) * MAX_ARGS);
                for (*argc = 1; *argc < MAX_ARGS; ++*argc) {
                    if (!fgets(buf, sizeof(buf), fp)) break;
                }
                check_and_fclose(fp, COMMAND_FILE);
            }
        }

        3.3将从/cache/recovery/command获取的参数写入到misc分区

        ...省略
    }

    四、分析recovery命令

      while ((arg = getopt_long(argc, argv, "", OPTIONS, NULL)) != -1) {
            switch(arg) {
            case 's': send_intent = optarg; break;
            case 'u': update_package = optarg; break;
            case 'w': wipe_data = wipe_cache = 1; break;
            case 'c': wipe_cache = 1; break;
            case 't': show_text = 1; break;
            case 'x': just_exit = true; break;
            case 'l': locale = optarg; break;
            case 'p': shutdown_after = true; break;
            case '?':
                LOGE("Invalid command argument\n");
                continue;
            }
        }

    五、升级install_package过程

     if (update_package != NULL) {
        status = install_package(update_package, &wipe_cache, TEMPORARY_INSTALL_FILE){

        5.1卸载除了/tmp和/cache的其他分区

        setup_install_mounts()

        5.2ota升级的真正实现,这里去除掉跟UI显示相关的逻辑

        result = really_install_package(path, wipe_cache){

            5.2.1确保zip包所在的目录是挂载的

            if (ensure_path_mounted(path) != 0)

            5.2.2加载公钥源文件,根据公钥对zip包进行校验

            Certificate* loadedKeys = load_keys(PUBLIC_KEYS_FILE, &numKeys);
            err = verify_file(path, loadedKeys, numKeys);

            5.2.3打开升级包,并将相关的信息拷贝到一个临时的ZipArchinve变量中。这一步并未对我们的update.zip包解压。

            err = mzOpenZipArchive(path, &zip);

            5.2.4真正fota升级的过程

            return try_update_binary(path, &zip, wipe_cache);

         }

    }

    }
}




  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Leonban

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值