基于iTop-4412的U-Boot 2017移植[0]:Exynos4412基礎

基于iTop-4412的U-Boot 2017移植[0]:Exynos4412基礎

參考資料:

Exynos4412 SoC基礎

- Exynos4412的地址空間

memory_map

iROM:這段地址空間對應Exynos4412內部固化的一段程序,Exynos4412啟動的第一條指令就存放在這里。

iRAM:這段地址空間對應的是Exynos4412內部的一個存儲器,這段存儲器的特點是上電就可以用,不用初始化。

DMC0:這段地址空間就是核心板上的DDR3對應的存儲空間,上電后需要初始化DRAM控制器才能使用。

- Exynos4412的啟動過程

boot

由圖中數字順序得知:

  1. iROM
  2. BL1
  3. OS

首先從iROM運行,然后根據OM的值判斷從哪個存儲設備(Nand\SD/MMC\eMMC\USB OTG)加載BL1到iRAM;

其次,BL1再根據OM的值判斷從哪個存儲設備加載OS到DRAM中;

最后,運行OS代碼。

注意: iROM固化在SoC內部,BL1是Samsung提供的鏡像文件E4412_N.bl1.bin,OS在這里可以認為是BL2,這部分是u-boot代碼中編譯生成的SPL,BL2是由BL1加載到iRAM中運行的。最后,BL2再根據OM值,從sdcard中將u-boot代碼拷貝到DRAM中。

我們接下來要進行移植的U-Boot啟動過程為iROM->BL1(E4412_N.bl1.bin)->BL2(U-Boot SPL)->U-Boot

- Exynos4412的運行空間

program_text_base

如圖,標出了iROM、BL1和BL2的運行地址空間。

iRAM的地址空間是0x02020000 - 0x02060000

  • iROM: iRAM的0x02020000 - 0x02021400的5KB地址空間分配給iROM用,用于存放iROM的全局變量(ZI/RW,分別存放全局未初始化變量、全局已初始化變量)、局部變量(stack)等等。

  • BL1: 從0x02021400 - 0x02023400的8KB地址空間屬于BL1,可以認為BL1的第一條指令就存放在0x02021400地址單元。

  • BL2: 緊接著的0x02023400 - 0x02027400的16KB地址空間屬于BL2,即:BL2的第一條指令存放的地址就是0x02023400,這個值很重要,如果我們的SPL中有非“位置無關碼”,那么就必須將SPL加載到其運行地址處,否則在執(zhí)行那些非位置無關碼的時候會出錯。后續(xù)編寫U-Boot的時候需要設置宏定義:#define CONFIG_SPL_TEXT_BASE 0x02023400

- 用于Exynos4412啟動的SD卡布局

sd_layout

其中sdcard的扇區(qū)大小是1Block = 512B。

第0個扇區(qū)是保留扇區(qū)(Reserved),第1到第16扇區(qū)共8KB的空間存放BL1(E4412_N.bl1.bin),從第17到第48扇區(qū)的16KB空間用于存放BL2(u-boot-spl.bin),之后的扇區(qū)可以根據實際需求自己安排。

- 制作用于Exynos4412啟動的BL2

BL1可以自己寫也可以使用官方提供的E4412_N.bl1.bin,本次移植我們采用官方的。

Q: BL1有了,怎么制作BL2呢?

A: 使用mkbl2工具。

mkbl2.c:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int main (int argc, char *argv[])
{
    FILE *fp;
    unsigned char src;
    char *buf, *a;
    int buf_len;
    int nbytes, file_len;
    unsigned int checksum = 0;
    int i;

    if (argc != 4) {
        printf("Usage: mkbl2 <source file> <destination file> <size> \n");
        return -1;
    }

    buf_len = atoi(argv[3]);
    buf = (char *)malloc(buf_len);
    memset(buf, 0x00, buf_len);

    fp = fopen(argv[1], "rb");
    if( fp == NULL) {
        printf("source file open error\n");
        free(buf);
        return -1;
    }

    fseek(fp, 0L, SEEK_END);
    file_len = ftell(fp);
    fseek(fp, 0L, SEEK_SET);

    nbytes = fread(buf, 1, file_len, fp);

    if (nbytes != file_len) {
        printf("source file read error\n");
        free(buf);
        fclose(fp);
        return -1;
    }

    fclose(fp);

    for(i = 0; i < (14 * 1024) - 4; i++)
        checksum += (unsigned char)(buf[i]);

    *(unsigned int*)(buf + i) = checksum;

    fp = fopen(argv[2], "wb");
    if (fp == NULL) {
        printf("destination file open error\n");
        free(buf);
        return -1;
    }

    a = buf;
    nbytes = fwrite(a, 1, buf_len, fp);

    if (nbytes != buf_len) {
        printf("destination file write error\n");
        free(buf);
        fclose(fp);
        return -1;
    }

    free(buf);
    fclose(fp);
    return 0;
}

該程序的功能就是為BL2添加校驗碼。【BL2 不能大于(14K – 4B) 字節(jié),最后 4B用于存放較驗碼】

編譯:

$ gcc mkbl2.c -o mkbl2

使用:

$ ./mkbl2 u-boot-spl.bin bl2.bin 14336

有了上面的基礎知識,下面開始移植。


最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容