1. 程序调用过程
do_bootm
bootm_start(cmdtp, flag, argc, argv)
bootm_load_os(images.os, &load_end, 1)
boot_fn = boot_os[images.os.os];
boot_fn(0, argc, argv, &images);
do_bootm_linux
boot_prep_linux
create_fdt(bootm_headers_t *images)
ftd_chosen
bootargs
2. 详细分析
do_bootm
bootm_start(cmdtp, flag, argc, argv)
bootm_load_os(images.os, &load_end, 1)
boot_fn = boot_os[images.os.os];
boot_fn(0, argc, argv, &images);
do_bootm_linux
boot_prep_linux
//以上内容。参见上节
#ifdef CONFIG_OF_LIBFDT
if (images->ft_len) {
debug("using: FDT\n");
if (create_fdt(images)) {
printf("FDT creation failed! hanging...");
hang();
}
} else
#endif
//如果使用设备树进行传递参数,则需要在相应的头文件中宏定义 #define CONFIG_OF_LIBFDT ( origen.h (\include\configs)
boot_jump_linux
3. create_fdt 分析
static int create_fdt(bootm_headers_t *images)4.
ulong of_size = images->ft_len;
char **of_flat_tree = &images->ft_addr;
ulong *initrd_start = &images->initrd_start;
ulong *initrd_end = &images->initrd_end;
struct lmb *lmb = &images->lmb;
ulong rd_len;
int ret;
boot_fdt_add_mem_rsv_regions(lmb, *of_flat_tree);
//为fdt 保留一块空间
ret = boot_ramdisk_high(lmb, images->rd_start, rd_len,initrd_start, initrd_end);
//ramdisk 设置,暂且不管
ret = boot_relocate_fdt(lmb, of_flat_tree, &of_size);
//对设备树进行重定向。得到设备树的地址 ret = boot_relocate_fdt(lmb, of_flat_tree, &of_size);
fdt_chosen(*of_flat_tree, 1);
// 寻找 chosen node ,如果没有这个节点则创建
str = getenv("bootargs");
//获取 启动参数
err = fdt_setprop(fdt, nodeoffset,"bootargs", str, strlen(str)+1);
//将bootargs 设置为设备树的属性
fixup_memory_node(*of_flat_tree);
for (bank = 0; bank < CONFIG_NR_DRAM_BANKS; bank++) {
start[bank] = bd->bi_dram[bank].start;
size[bank] = bd->bi_dram[bank].size;
}
//内存的首地址和长度
fdt_fixup_memory_banks(blob, start, size, CONFIG_NR_DRAM_BANKS);
//修正或者添加 memory node
fdt_fixup_ethernet(*of_flat_tree);
//和网卡相关的fdt
fdt_initrd(*of_flat_tree, *initrd_start, *initrd_end, 1);
//ramdisk 相关的fdt
boot_jump_linux #ifdef CONFIG_OF_LIBFDT if (images->ft_len) r2 = (unsigned long)images->ft_addr; else #endif kernel_entry(0, machid, r2); //传递给内核的参数存放的地址,设备树的地址。 //在为使用设备树之前,使用的 gd->bd->bi_boot_params;即0x30001000 这个地址
参考文献:
http://blog.csdn.net/xy010902100449/article/details/46918145
Uboot mainline 从 v1.1.3开始支持Device Tree,其对ARM的支持则是和ARM内核支持Device Tree同期完成。
为了使能Device Tree,需要编译Uboot的时候在config文件中加入#define CONFIG_OF_LIBFDT
在Uboot中,可以从NAND、SD或者TFTP等任意介质将.dtb读入内存,假设.dtb放入的内存地址为0x71000000,之后可在Uboot运行命令fdt addr命令设置.dtb的地址,如:
U-Boot> fdt addr 0x71000000
fdt的其他命令就变地可以使用,如fdt resize、fdt print等。
对于ARM来讲,可以透过bootz kernel_addr initrd_address dtb_address的命令来启动内核,即dtb_address作为bootz或者bootm的最后一次参数,第一个参数为内核映像的地址,第二个参数为initrd的地址,若不存在initrd,可以用 -代替。