android boot image格式分析

来源:互联网 发布:工业设计软件图标 编辑:程序博客网 时间:2024/05/23 19:05

boot.img和recovery.img的格式是google自定义的。


1. image的完整构成

一个完整的bootimage是由boot header、kernel、ramdisk、second stage(可选)、X509证书(可选)、签名信息(可选)组成。原始的boot.img只包括boot header、kernel、ramdisk、second stage(可选),且一般而言second staga都是没有的。

2. 原始boot.img格式
包括文件头boot_img_hdr,kernel.gz(Linux内核zImage),以及ramdisk.cpio.gz(根文件系统)
结构如下:
*
** +-----------------+
** | boot header     | 1 page
** +-----------------+
** | kernel              | n pages
** +-----------------+
** | ramdisk           | m pages
** +-----------------+
** | second stage    | o pages
** +-----------------+


原始boot.img的每部分都是页对齐的。其中boot header固定占用1个page的大小。kernel、ramdisk、second stage实际的大小会在boot header中标明。


3. boot header结构

boot header其实就是一个结构体struct boot_img_hdr,它的定义如下

struct boot_img_hdr{    unsigned char magic[BOOT_MAGIC_SIZE]; /* 8 byte */    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 */};

这里有几个比较重要的值。一个是page_size,这个是页大小。前面说了,boot.img的每个部分都是页对齐的,那一个page的大小就记录在page_size里,通常是2048,也就是2K对齐。kernel_size是kernel.gz的原始大小,页对齐后,kernel占用的空间会比kernel_size大,多余的部分用0填充。ramdisk_size是ramdisk的原始大小,页对齐后,ramdisk占用的空间会比ramdisk_size大,多余的部分用0填充。


4. 签名

如果需要在android启动时对boot.img进行校验,确保其合法性,那么就需要在编译完成后对boot.img进行签名。google对boot.img的签名方式,就是使用verity .pk8对原始的boot.img进行加密。并且在boot.img的最后追加对应的verity.x509.pem证书,以及一段加密数据(也就是签名信息)

追加的证书,并不是直接把源码里面的verity.x509.pem粘贴上去的,而是做了编码的转换。verity.x509.pem是base64编码的,而追加的证书是二进制的ASN1格式。追加的证书也是页对齐的。ASN1格式会标明证书的实际大小。证书的开头是整个证书的大小,一般开头是0x30 0x82 0xaa 0xbb,30表示SEQUENCE, 0x82表示长度占用两个2字节,那么证书长度就是0xaabb。追加证书时也是页对齐的。(这里android 7.0和android 5.x似乎略有差别,android 5.x并没有做对齐处理)

除了证书以外,还有签名。签名是对原始boot.img的内容计算hash后,把hash值进行加密后得到的内容。具体的hash算法和加密算法都是在证书里规定的。最后得到的签名长度跟hash和加密算法相关。例如证书里规定sha1RSA2048,sha1摘要长度是160bit,那么RSA密文的长度就是256字节,所以最后的签名信息长度是256字节,且签名信息是不需要页对齐的。

https://source.android.com/security/verifiedboot/verified-boot?hl=zh-cn


5. 镜像大小

boot.img的总大小是

total = align(sizeof(struct boot_img_hdr))        + align(kernel_size)         + align(ramdisk_size)         + align(second_size)         + align(cert_size)         + signature_size;



原创粉丝点击