uboot處理dtb



title: uboot處理dtb
date: 2019/4/28 17:18:19
toc: true

uboot處理dtb

傳遞參數給內核

之前在分析內核啟動參數的時候,可以看到內核處理的dtb的地址是原來atag的地址也就是R2,所以就是在轉入kernel參數為的第3個為dtb地址即可

我們的uboot是這么啟動的

  bootm <uImage_addr>                            // 無設備樹,bootm 0x30007FC0
  bootm <uImage_addr> <initrd_addr> <dtb_addr>   // 有設備樹 

所以就是講第4個參數讀取並轉換即可

/* 100ask for device tree, no initrd image used */
if (argc == 4) {
    //第三個參數0x32000000就是設備樹地址
    of_flat_tree = (char *) simple_strtoul(argv[3], NULL, 16);

    if  (be32_to_cpu(*(ulong *)of_flat_tree) == OF_DT_HEADER) {
        printf ("\nStarting kernel with device tree at 0x%x...\n\n", of_flat_tree);

        cleanup_before_linux ();
        //把dtb的地址傳到r2寄存器里			
        theKernel (0, bd->bi_arch_number, of_flat_tree);

    } else {
        printf("Bad magic of device tree at 0x%x!\n\n", of_flat_tree);
    }

}

最終的啟動流程如下

  nand read.jffs2 0x30007FC0 kernel;     // 讀內核uImage到內存0x30007FC0
  nand read.jffs2 32000000 device_tree;  // 讀dtb到內存32000000
  bootm 0x30007FC0 - 0x32000000          // 啟動, 沒有initrd時對應參數寫為"-"

dtb 地址選擇

使用mkimage -l arch/arm/boot/uImage來查看內核的加載地址,然后放置到正確的位置

  • 不要破壞u-boot本身
  • 內核本身的空間不能占用, 內核要用到的內存區域也不能占用
  • 內核啟動時一般會在它所處位置的下邊放置頁表, 這塊空間(一般是0x4000即16K字節)不能被占用
                    ------------------------------
 0x33f80000       ->|    u-boot                  | 分析lds鏈接文件
                    ------------------------------
                    |    u-boot所使用的內存(棧等)|
                    ------------------------------
                    |                            |
                    |                            |
                    |        空閑區域            |
                    |                            |
                    |                            |
                    |                            |
                    |                            |
                    ------------------------------
 0x30008000       ->|      zImage                |
                    ------------------------------  uImage = 64字節的頭部+zImage
 0x30007FC0       ->|      uImage頭部            |
                    ------------------------------
 0x30004000       ->|      內核創建的頁表        |  head.S
                    ------------------------------
                    |                            |
                    |                            |
             -----> ------------------------------
             |
             |
             --- (內存基址 0x30000000)

正確操作

nand read.jffs2 30000000 device_tree
nand read.jffs2 0x30007FC0 kernel
bootm 0x30007FC0 - 30000000    

破壞頁表不能啟動哦

nand read.jffs2 30004000 device_tree
nand read.jffs2 0x30007FC0 kernel
bootm 0x30007FC0 - 30004000

dtb修改

dtb的二進制文件還算簡單,可以直接來修改即可,具體的修改就是要注意一些字節長度和偏移

具體的步驟簡述一下,我覺得沒必要搞,還是dts文件方便

例子1. 修改屬性的值,
假設 老值: len
     新值: newlen (假設newlen > len)

a. 把原屬性val所占空間從len字節擴展為newlen字節:
   把老值之后的所有內容向后移動(newlen - len)字節
b. 把新值寫入val所占的newlen字節空間
c. 修改dtb頭部信息中structure block的長度: size_dt_struct
d. 修改dtb頭部信息中string block的偏移值: off_dt_strings
e. 修改dtb頭部信息中的總長度: totalsize



例子2. 添加一個全新的屬性
a. 如果在string block中沒有這個屬性的名字,
   就在string block尾部添加一個新字符串: 屬性的名
   並且修改dtb頭部信息中string block的長度: size_dt_strings
   修改dtb頭部信息中的總長度: totalsize
b. 找到屬性所在節點, 在節點尾部擴展一塊空間, 內容及長度為: 
   TAG      // 4字節, 對應0x00000003
   len      // 4字節, 表示屬性的val的長度
   nameoff  // 4字節, 表示屬性名的offset
   val      // len字節, 用來存放val
c. 修改dtb頭部信息中structure block的長度: size_dt_struct
d. 修改dtb頭部信息中string block的偏移值: off_dt_strings
e. 修改dtb頭部信息中的總長度: totalsize

移植fdt

uboot也有現成的源代碼,需要移植,具體錯誤可以參考

cmd/fdt.c
在編譯文件時可以用"-I"選項指定頭文件目錄
比如: arm-linux-gcc -I <dir> -c -o ....,對於u-boot來說, 一般就是源碼的include目錄。

常用命令如下

nand read.jffs2 32000000 device_tree  // 從flash讀出dtb文件到內存(0x32000000)
fdt addr 32000000                     // 告訴fdt, dtb文件在哪
fdt print /led pin                    // 打印/led節點的pin屬性
fdt get value XXX /led pin            // 讀取/led節點的pin屬性, 並且賦給環境變量XXX
print XXX                             // 打印環境變量XXX的值
fdt set /led pin <0x00050005>         // 設置/led節點的pin屬性
fdt print /led pin                    // 打印/led節點的pin屬性
nand erase device_tree                // 擦除flash分區
nand write.jffs2 32000000 device_tree // 把修改后的dtb文件寫入flash分區


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM