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

    xiaoxiao2021-03-25  78

    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);

             }

        }

        } }

    转载请注明原文地址: https://ju.6miu.com/read-24555.html

    最新回复(0)