设为首页 加入收藏

TOP

Android Recovery升级原理(三)
2019-09-19 11:10:27 】 浏览:144
Tags:Android Recovery 升级 原理
r **) malloc(sizeof(char *) * MAX_ARGS); (*argv)[0] = argv0; // use the same program name char buf[MAX_ARG_LENGTH]; for (*argc = 1; *argc < MAX_ARGS; ++*argc) { if (!fgets(buf, sizeof(buf), fp)) break; (*argv)[*argc] = strdup(strtok(buf, "\r\n")); // Strip newline. } check_and_fclose(fp, COMMAND_FILE); LOGI("Got arguments from %s\n", COMMAND_FILE); } } ...... set_bootloader_message(&boot); //回写BCB

这里需要说一下“BCB”,即bootloader control block, 中文可以呼之为“启动控制模信息块”**,位于/misc分区,从代码上看,就是一个struct 结构体 :

struct bootloader_message {  
    char command[32];  
    char status[32];  
    char recovery[1024];  
}; 

bootloader_message 结构体包含三个字段,具体含义如下:

command 字段中存储的是命令,它有以下几个可能值:

  • boot-recovery:系统将启动进入Recovery模式
  • update-radia 或者 update-hboot:系统将启动进入更新firmware的模式,这个更新过程由bootloader完成
  • NULL:空值,系统将启动进入Main System主系统,正常启动。

status 字段存储的是更新的结果。更新结束后,由Recovery或者Bootloader将更新结果写入到这个字段中。

recovery 字段存放的是recovry模块的启动参数,一般包括升级包路径。其存储结构如下:第一行存放字符串“recovery”,第二行存放路径信息“–update_package=/mnt/sdcard/update.zip”等。 因此,参数之间是以“\n”分割的。

2. update_package

ota升级包的存放路径,从BCB或者/cache/recovery/command里面解析得到的,升级包一般下载后存放在cache或sdcard分区,当然,也有一些是存放到U盘之类的外接存储设备中的。一般赋值格式如下:

--update_package=/mnt/sdcard/update.zip 或 --update_package=CACHE:update.zip

3. int install_package (const char path, int wipe_cache, const char* install_file)

int install_package(const char* path, int* wipe_cache, const char* install_file)
{
    //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 = really_install_package(path, wipe_cache); 
    if (install_log) {
        fputc(result == INSTALL_SUCCESS ? '1' : '0', install_log);
        fputc('\n', install_log);
        fclose(install_log);
    }
    return result;
}

4. static int really_install_package(const char path, int wipe_cache)

really_install_package函数在install_package函数中被调用,函数的主要作用是调用ensure_path_mounted确保升级包所在的分区已经挂载,另外,还会对升级包进行一系列的校验,在具体升级时,对update.zip包检查时大致会分三步:

  1. 检验SF文件与RSA文件是否匹配;

  2. 检验MANIFEST.MF与签名文件中的digest是否一致;

  3. 检验包中的文件与MANIFEST中所描述的是否一致

通过校验后,调用try_update_binary函数去实现真正的升级。

5. static int try_update_binary(const char path, ZipArchive zip, int wipe_cache)

try_update_binary是真正实现对升级包进行升级的函数:

static int try_update_binary(const char *path, ZipArchive *zip, int* wipe_cache) {

    const ZipEntry* binary_entry = mzFindZipEntry(zip, ASSUMED_UPDATE_BINARY_NAME);
    ......
    const char* binary = "/tmp/update_binary";
    unlink(binary);
    int fd = creat(binary, 0755); 
    .....
    //将升级包里面的update_binary解压到/tmp/update_binary
    bool ok = mzExtractZipEntryToFile(zip, binary_entry, fd);
    close(fd);
    mzCloseZipArchive(zip);
    ......
    int pipefd[2];
    pipe(pipefd);

    const char** args = (const char**)malloc(sizeof(char*) * 5);
    args[0] = binary; //update_binary存放路径
    args[1] = EXPAND(RECOVERY_API_VERSION);  // Recovery版本号
    char* temp = (char*)malloc(10);
    sprintf(temp, "%d", pipefd[1]);
    args[2] = temp;
    args[3] = (char*)path; //升级包存放路径
    args[4] = NULL;

    pid_t pid = fork();//fork一个子进程
    if (pid == 0) {
        close(pipefd[0]);
        //子进程调用update-binary执行升级操作
        execv(binary, (char* const*)args);
        fprintf(stdout, "E:Can't run
首页 上一页 1 2 3 4 5 下一页 尾页 3/5/5
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇linux 的swap、swappiness及kswap.. 下一篇android-ramdisk.img分析、recove..

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目