1. 自制BL1

参考Android_Exynos4412_iROM_Secure_Booting_Guide_Ver.1.00.00.pdf,Exynos4412会自动把BL加载到0x0202_1400运行。所以BL1的入口地址需要设置为0x0202_1400,这样才能保证位置相关码可以正常执行。

Exynos4412内部的BL0会对BL1进行校验,BL1的头部为16字节的校验码,这个校验码是根据头部之后,其余的(8k-16)字节的数据计算出来的,工具源码可以参考mkbl1。对于编译生成的文件不足8k的情况,要将其用0填充到8k。当然,这里是以非安全启动方式来说明的。

编写源码时,要在对面中预留16字节的占位符,比如:

1.word 0x0
2.word 0x0
3.word 0x0
4.word 0x0
5
6    .global _start
7_start:
8    ldr sp, =0x02040000
9    bl _main

至于15k的BL1文件如何制作,我没有找到资料。

1.1. mkbl1源码

  1#include <stdio.h>
  2#include <string.h>
  3
  4#define BL1_SIZE        8 * 1024
  5#define HEAD_SIZE       16
  6
  7static unsigned int calc_checksum(unsigned char *buf, unsigned int buf_size)
  8{
  9    unsigned int checksum = 0;
 10    int i;
 11
 12    for(i = HEAD_SIZE; i < buf_size; i++) {
 13        checksum += buf[i] & 0xff;
 14    }
 15
 16    return checksum;
 17}
 18
 19static unsigned int calc_header(unsigned char *head, unsigned int checksum)
 20{
 21    int i;
 22
 23    memset(head, 0x00, HEAD_SIZE);
 24
 25    head[3] = (0x1f >> 24) & 0xff;
 26    head[2] = (0x1f >> 16) & 0xff;
 27    head[1] = (0x1f >> 8 ) & 0xff;
 28    head[0] = (0x1f >> 0 ) & 0xff;
 29
 30    head[7] = (checksum >> 24) & 0xff;
 31    head[6] = (checksum >> 16) & 0xff;
 32    head[5] = (checksum >> 8 ) & 0xff;
 33    head[4] = (checksum >> 0 ) & 0xff;
 34
 35    head[0]  ^= 0xbc;
 36    head[1]  ^= 0xca;
 37    head[2]  ^= 0xba;
 38    head[3]  ^= 0xcb;
 39    head[4]  ^= 0xcb;
 40    head[5]  ^= 0xce;
 41    head[6]  ^= 0xcd;
 42    head[7]  ^= 0xdf;
 43    head[8]  ^= 0xb7;
 44    head[9]  ^= 0xba;
 45    head[10] ^= 0xbe;
 46    head[11] ^= 0xbb;
 47    head[12] ^= 0xba;
 48    head[13] ^= 0xad;
 49    head[14] ^= 0xdf;
 50    head[15] ^= 0xdf;
 51
 52    for(i = 1; i < HEAD_SIZE; i++)	{
 53        head[i] ^= head[i-1];
 54    }
 55}
 56
 57int main(int argc, char *argv[])
 58{
 59    unsigned char head[HEAD_SIZE];
 60    unsigned char buffer[BL1_SIZE];
 61
 62    char *infile;
 63    char *outfile = "E4412bl1.bin";
 64    FILE *fin, *fout;
 65
 66    int filesize;
 67    unsigned int checksum;
 68
 69    if (argc < 2 || 0 == strcmp(argv[1], "?") || 0 == strcmp(argv[1], "help")) {
 70        printf("Usage: %s <infile> [outfile=E4412bl1.bin]\n", argv[0]);
 71        return -1;
 72    }
 73
 74    infile = argv[1];
 75    if (argc > 2)	{
 76        outfile = argv[2];
 77    }
 78
 79    fin = fopen(infile, "rb");
 80    if (!fin) {
 81        printf("Can not open file '%s'\n", infile);
 82        return -1;
 83    }
 84
 85    fseek(fin, 0L, SEEK_END);
 86    filesize = ftell(fin);
 87    if (filesize > BL1_SIZE) {
 88        printf("file %s size is %d, larger than %d!\n", infile, filesize, BL1_SIZE);
 89        fclose(fin);
 90        return -1;
 91    }
 92    fseek(fin, 0L, SEEK_SET);
 93
 94    // clear buffer in BL1_SIZE
 95    memset(buffer, 0x00, sizeof(buffer));
 96
 97    if (filesize != fread(buffer, 1, filesize, fin)) {
 98        printf("Can't read %s\n", infile);
 99        fclose(fin);
100        return -1;
101    }
102    fclose(fin);
103
104    fout = fopen(outfile, "wb");
105    if (fout == NULL) {
106        printf("Can not open file '%s'\n", outfile);
107        return -1;
108    }
109
110    checksum = calc_checksum(buffer, filesize);
111    calc_header(head, checksum);
112
113    printf("checksum is 0x%08X of %d bytes\n", checksum, filesize);
114    printf("input [%s], output [%s]\n", infile, outfile);
115
116    fwrite(buffer, 1, BL1_SIZE, fout);
117    fseek(fout, 0L, SEEK_SET);
118    // write header
119    fwrite(head, 1, sizeof(head), fout);
120
121    fflush(fout);
122    fclose(fout);
123
124    return 0;
125}