酷派CPB升级文件中的recovery.img(qcdt校验)


CPB解包:http://my.oschina.net/u/570986/blog/352839


用的cpbtool工具解包4.3.066.P3.140417.8730L.CPB文件,得到下列文件:

8626_msimage.mbn
boot.img
cache.img
dt.img
dummy.bin
efs1.bin
efs2.bin
efs3.bin
efs_image_meta.bin
emmc_appsboot.mbn
mba.mbn
mcfg_hw.mbn
mcfg_sw.mbn
MISC.img
MPRG8626.mbn
NON-HLOS.bin
nv.tar.mbn
panic.img
persist.img
PhoneInfo.yl
qdsp6sw.mbn
recovery.img
rpm.mbn
sbl1.mbn
sdi.mbn
system.img
tz.mbn
userdata.img
上面的解压出来的img文件与平常的img不同。boot.img和recovery.img不能用bootimg.exe解包(这是个别人用python写的,下载》这里)。以recovery.img为例:

酷派CPB升级文件中的recovery.img(qcdt校验)

前头填充了12字节,目前不知道什么用途。去掉这12字节后,用bootimg.exe还是不能解开,会提示“invalid bootimg”的错误。原因在于bootimg.exe工具还校验了ramdisk_addr、second_addr、tags_addr。

boot.img和recovery.img文件头格式如下:

#define BOOT_MAGIC "ANDROID!"
#define BOOT_MAGIC_SIZE 8
#define BOOT_NAME_SIZE 16
#define BOOT_ARGS_SIZE 512
 
struct boot_img_hdr
{
    unsigned char magic[BOOT_MAGIC_SIZE];
 
    unsigned kernel_size;  /* size in bytes */
    unsigned kernel_addr;  /* physical load addr */
 
    unsigned ramdisk_size; /* size in bytes */
    unsigned ramdisk_addr; /* physical load addr */
 
    unsigned second_size;  /* size in bytes */
    unsigned second_addr;  /* physical load addr */
 
    unsigned tags_addr;    /* physical addr for kernel tags */
    unsigned page_size;    /* flash page size we assume */
    unsigned unused[2];    /* future expansion: should be 0 */
 
    unsigned char name[BOOT_NAME_SIZE]; /* asciiz product name */
     
    unsigned char cmdline[BOOT_ARGS_SIZE];
 
    unsigned id[8]; /* timestamp / checksum / sha1 / etc */
};

bootimg.exe的python源码文件校验地址部分代码:

base = kernel_addr - 0x00008000
    assert magic.decode('latin') == 'ANDROID!', 'invald bootimg'
    assert base == ramdisk_addr - 0x01000000, 'invalid bootimg'
    assert base == second_addr - 0x00f00000, 'invalid bootimg'
    assert base == tags_addr - 0x00000100, 'invalid bootimg'

修正这些地址域后就可以用bootimg.exe解开。但是bootimg.exe解开的并不完整, 4.3.066.P3.140417.8730L.CPB解开来的recovery.img还有一个qcdt节。猜测应该是qualcomm device tree节简称,高通cpu设备树。


qcdt节:


酷派CPB升级文件中的recovery.img(qcdt校验)

qcdt节下包含了两个dtb:


酷派CPB升级文件中的recovery.img(qcdt校验)

酷派CPB升级文件中的recovery.img(qcdt校验)

从qcdt节开始到文件结束都属于qcdt节的部分。因此封包程序不能用bootimg.exe封包成recovery.img,况且bootimg.exe封包并不会填充boot_img_hdr头的unsigned id[8];域,此域保存的是SHA1值。自己改的封包工具主要代码如下:

/* tools/mkbootimg/mkbootimg.c
**
** Copyright 2007, The Android Open Source Project
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
**     http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*/
 
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <io.h>
 
#include "sha.c"
#include "bootimg.h"
 
static void *load_file(const char *fn, unsigned *_sz)
{
    char *data;
    int sz, ret;
    int fd;
 
    data = 0;
    fd = open(fn, O_RDONLY | _O_BINARY);
    if (fd < 0) return 0;
 
    sz = lseek(fd, 0, SEEK_END);
    if (sz < 0) goto oops;
 
    if (lseek(fd, 0, SEEK_SET) != 0) goto oops;
 
    data = (char*) malloc(sz);
    if (data == 0)
    {
        printf("malloc fail! File '%s' size: 0x%.8X(%u).\n", fn, sz, sz) ;
        goto oops;
    }
 
    ret = read(fd, data, sz) ;
    if (ret != sz)
    {
        printf("read error: %d! File '%s'.\n", ret, fn) ;
        goto oops;
    }
    close(fd);
 
    if (_sz) *_sz = sz;
    return data;
 
oops:
    close(fd);
    if (data != 0) free(data);
    return 0;
}
 
int usage(void)
{
    fprintf(stderr,"usage: mkbootimg\n"
            "       --kernel <filename>\n"
            "       --ramdisk <filename>\n"
            "       [ --second <2ndbootloader-filename> ]\n"
            "       [ --qcdt <qualcomm-bin-device-tree-filename> ]\n"
            "       [ --cmdline <kernel-commandline> ]\n"
            "       [ --board <boardname> ]\n"
            "       [ --base <address> ]\n"
            "       [ --pagesize <pagesize> ]\n"
            "       -o|--output <filename>\n"
           );
    return 1;
}
 
 
 
static unsigned char padding[4096] = { 0, };
 
int write_padding(int fd, unsigned pagesize, unsigned itemsize)
{
    unsigned pagemask = pagesize - 1;
    unsigned count;
 
    if ((itemsize & pagemask) == 0)
    {
        return 0;
    }
 
    count = pagesize - (itemsize & pagemask);
 
    if (write(fd, padding, count) != count)
    {
        return -1;
    }
    else
    {
        return 0;
    }
}
 
int main(int argc, char **argv)
{
    boot_img_hdr hdr;
 
    char *kernel_fn = 0;
    void *kernel_data = 0;
    char *ramdisk_fn = 0;
    void *ramdisk_data = 0;
    char *second_fn = 0;
    void *second_data = 0;
    char *qcdt_fn = NULL ;
    void *qcdt_data = NULL ;
    char *cmdline = "";
    char *bootimg = 0;
    char *board = "";
    unsigned pagesize = 2048;
    int fd;
    SHA_CTX ctx;
    uint8_t* sha;
    unsigned uiQcdtSize = 0 ;
 
    argc--;
    argv++;
    if (argc == 0)
        return usage() ;
 
    memset(&hdr, 0, sizeof(hdr));
 
    /* default load addresses */
    hdr.kernel_addr =  0x10008000;
    hdr.ramdisk_addr = 0x11000000;
    hdr.second_addr =  0x10F00000;
    hdr.tags_addr =    0x10000100;
 
    while (argc > 0)
    {
        char *arg = argv[0];
        char *val = argv[1];
        if (argc < 2)
        {
            return usage();
        }
        argc -= 2;
        argv += 2;
        if (!strcmp(arg, "--output") || !strcmp(arg, "-o"))
        {
            bootimg = val;
        }
        else if (!strcmp(arg, "--kernel"))
        {
            kernel_fn = val;
        }
        else if (!strcmp(arg, "--ramdisk"))
        {
            ramdisk_fn = val;
        }
        else if (!strcmp(arg, "--second"))
        {
            second_fn = val;
        }
        else if (!strcmp(arg, "--qcdt"))
        {
            qcdt_fn = val ;
        }
        else if (!strcmp(arg, "--cmdline"))
        {
            cmdline = val;
        }
        else if (!strcmp(arg, "--base"))
        {
            unsigned base = strtoul(val, 0, 16);
            hdr.kernel_addr =  base + 0x00008000;
            hdr.ramdisk_addr = base + 0x01000000;
            hdr.second_addr =  base + 0x00F00000;
            hdr.tags_addr =    base + 0x00000100;
        }
        else if (!strcmp(arg, "--board"))
        {
            board = val;
        }
        else if (!strcmp(arg,"--pagesize"))
        {
            pagesize = strtoul(val, 0, 10);
            if ((pagesize != 2048) && (pagesize != 4096))
            {
                fprintf(stderr,"error: unsupported page size %d\n", pagesize);
                return -1;
            }
        }
        else
        {
            return usage();
        }
    }
    hdr.page_size = pagesize;
 
 
    if (bootimg == 0)
    {
        fprintf(stderr,"error: no output filename specified\n");
        return usage();
    }
 
    if (kernel_fn == 0)
    {
        fprintf(stderr,"error: no kernel image specified\n");
        return usage();
    }
 
    if (ramdisk_fn == 0)
    {
        fprintf(stderr,"error: no ramdisk image specified\n");
        return usage();
    }
 
    if (strlen(board) >= BOOT_NAME_SIZE)
    {
        fprintf(stderr,"error: board name too large\n");
        return usage();
    }
 
    strcpy(hdr.name, board);
 
    memcpy(hdr.magic, BOOT_MAGIC, BOOT_MAGIC_SIZE);
 
    if (strlen(cmdline) > (BOOT_ARGS_SIZE - 1))
    {
        fprintf(stderr,"error: kernel commandline too large\n");
        return 1;
    }
    strcpy((char*)hdr.cmdline, cmdline);
 
    kernel_data = load_file(kernel_fn, &hdr.kernel_size);
    if (kernel_data == 0)
    {
        fprintf(stderr,"error: could not load kernel '%s'\n", kernel_fn);
        return 1;
    }
 
    if (!strcmp(ramdisk_fn,"NONE"))
    {
        ramdisk_data = 0;
        hdr.ramdisk_size = 0;
    }
    else
    {
        ramdisk_data = load_file(ramdisk_fn, &hdr.ramdisk_size);
        if (ramdisk_data == 0)
        {
            fprintf(stderr,"error: could not load ramdisk '%s'\n", ramdisk_fn);
            return 1;
        }
    }
 
    if (second_fn)
    {
        second_data = load_file(second_fn, &hdr.second_size);
        if (second_data == 0)
        {
            fprintf(stderr,"error: could not load secondstage '%s'\n", second_fn);
            return 1;
        }
    }
 
    if (qcdt_fn)
    {
        qcdt_data = load_file(qcdt_fn, &uiQcdtSize);
        if (qcdt_data == 0)
        {
            fprintf(stderr,"error: could not load qualcomm binary device tree '%s'\n", qcdt_fn);
            return 1;
        }
    }
 
    /* put a hash of the contents in the header so boot images can be
     * differentiated based on their first 2k.
     */
    SHA_init(&ctx);
    SHA_update(&ctx, kernel_data, hdr.kernel_size);
    SHA_update(&ctx, &hdr.kernel_size, sizeof(hdr.kernel_size));
    SHA_update(&ctx, ramdisk_data, hdr.ramdisk_size);
    SHA_update(&ctx, &hdr.ramdisk_size, sizeof(hdr.ramdisk_size));
    SHA_update(&ctx, second_data, hdr.second_size);
    SHA_update(&ctx, &hdr.second_size, sizeof(hdr.second_size));
    if (qcdt_fn)
    {
        SHA_update(&ctx, qcdt_data, uiQcdtSize);
        SHA_update(&ctx, &uiQcdtSize, sizeof(uiQcdtSize));
        //
        hdr.unused[0] = uiQcdtSize ;
    }
    sha = SHA_final(&ctx);
    memcpy(hdr.id, sha,
           SHA_DIGEST_SIZE > sizeof(hdr.id) ? sizeof(hdr.id) : SHA_DIGEST_SIZE);
 
    fd = open(bootimg, O_CREAT | O_TRUNC | O_WRONLY | _O_BINARY, 0644);
    if (fd < 0)
    {
        fprintf(stderr,"error: could not create '%s'\n", bootimg);
        return 1;
    }
 
    if (write(fd, &hdr, sizeof(hdr)) != sizeof(hdr)) goto fail;
    if (write_padding(fd, pagesize, sizeof(hdr))) goto fail;
 
    if (write(fd, kernel_data, hdr.kernel_size) != hdr.kernel_size) goto fail;
    if (write_padding(fd, pagesize, hdr.kernel_size)) goto fail;
 
    if (write(fd, ramdisk_data, hdr.ramdisk_size) != hdr.ramdisk_size) goto fail;
    if (write_padding(fd, pagesize, hdr.ramdisk_size)) goto fail;
 
    if (second_data)
    {
        if (write(fd, second_data, hdr.second_size) != hdr.second_size) goto fail;
        if (write_padding(fd, pagesize, hdr.ramdisk_size)) goto fail;
    }
 
    if (qcdt_data)
    {
        if (write(fd, qcdt_data, uiQcdtSize) != uiQcdtSize) goto fail;
        if (write_padding(fd, pagesize, uiQcdtSize)) goto fail;
    }
 
    free(kernel_data) ;
    free(ramdisk_data) ;
    free(second_data) ;
    free(qcdt_data) ;
    return 0;
 
fail:
    free(kernel_data) ;
    free(ramdisk_data) ;
    free(second_data) ;
    free(qcdt_data) ;
    unlink(bootimg);
    close(fd);
    fprintf(stderr,"error: failed writing '%s': %s\n", bootimg,
            strerror(errno));
    return 1;
}

完整的代码》这里下载

你可能感兴趣的:(酷派CPB升级文件中的recovery.img(qcdt校验))