• 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 ("
    Starting kernel with device tree at 0x%x...
    
    ", 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!
    
    ", 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分区
    
  • 相关阅读:
    【转】 vue的路由安全验证
    【转】 Vuex模块化
    【转】 后端小白的VUE入门笔记, 进阶篇
    【转】 后端小白的VUE入门笔记, 前端高能慎入
    【转】 一个后端开发的 Vue 笔记【入门级】
    【转】 前端笔记之Vue(七)Vue-router&amp;axios&amp;Vue插件&amp;Mock.js&amp;cookie|session&amp;加密
    【转】 前端笔记之Vue(六)分页排序|酷表单实战&amp;Vue-cli
    【转】 前端笔记之Vue(五)TodoList实战&amp;拆分store&amp;跨域&amp;练习代理跨域
    算法题
    vue的虚拟dom(Virtual DOM )
  • 原文地址:https://www.cnblogs.com/zongzi10010/p/10793084.html
Copyright © 2020-2023  润新知