u-boot-2013.01完美的支持了pandaboardES開發板,其能夠生成MLO和u-boot.img文件,現在來分析一下這兩個文件是怎麼生成的。
1.打開頂層目錄下的Makefile,找到424行all,all目標依賴於$(ALL-y),
424 all: $(ALL-y) $(SUBDIR_EXAMPLES)
繼續向上需找,在411行得知需要依賴於CONFIG_SPL宏,411 ALL-$(CONFIG_SPL) += $(obj)spl/u-boot-spl.bin
該宏在include/configs/Omap4_common.h中234行定義233 /* Defines for SPL */
234 #define CONFIG_SPL
打開分析spl/Makefile,在第164行跟蹤u-boot-spl.bin如何生成164 $(obj)u-boot-spl.bin: $(obj)u-boot-spl
165 $(OBJCOPY) $(OBJCFLAGS) -O binary $< $@
在spl/Makefile第18行得知,導出CONFIG_SPL_BUILD:=y宏18 CONFIG_SPL_BUILD := y
19 export CONFIG_SPL_BUILD
2.打開arch/arm/cpu/armv7/omap4/config.mk,可以得知,定義了CONFIG_SPL_BUILD宏生成ALL-y+=
$(OBJTREE)/MLO,而沒有定義CONFIG_SPL_BUILD宏,則生成u-boot.img
ifdef CONFIG_SPL_BUILD
ALL-y += $(OBJTREE)/MLO
else
ALL-y += $(obj)u-boot.img
endif
3.進而分析頂層目錄下的Makefile第462行,可以知道u-boot.img是通過tools/mkimage工具由u-boot.bin生成的,u-boot.bin是如何生成的就不分析了,網上資料比我好的很多。462 $(obj)u-boot.img: $(obj)u-boot.bin
463 $(obj)tools/mkimage -A $(ARCH) -T firmware -C none \
464 -O u-boot -a $(CONFIG_SYS_TEXT_BASE) \
465 -e $(CONFIG_SYS_UBOOT_START) \
466 -n $(shell sed -n -e 's/.*U_BOOT_VERSION//p' $(VERSION_FILE) | \
467 sed -e 's/"[ ]*$$/ for $(BOARD) board"/') \
468 -d $< $@
4.進而分析spl/Makefile第136,MLO是通過tools/mkimage工具有u-boot-spl.bin生成的
136 $(OBJTREE)/MLO: $(obj)u-boot-spl.bin
137 $(OBJTREE)/tools/mkimage -T omapimage \
138 -a $(CONFIG_SPL_TEXT_BASE) -d $< $
至此,MLO和u-boot.img兩文件是怎麼生成的已經簡要的分析了一下,剩下的都是網絡上有很多資料,而且說的比我好多了。
下面分析下MLO的執行流程,通過上面的分析可以知道,uboot在編譯的時候會導出CONFIG_SPL_BUILD := y宏
1.arch/arm/cpu/armv7/start.S 126行 reset處開始執行
126 reset:
127 bl save_boot_params //保存啓動參數
2.arch/arm/cpu/armv7/start.S 153行153 #ifndef CONFIG_SKIP_LOWLEVEL_INIT
154 bl cpu_init_cp15
155 bl cpu_init_crit
156 #endif
158 bl _main
3._main 位於arch/arm/lib/crt0.S第96行115 bl board_init_f
4.board_init_f 位於arc/arm/lib/Spl.c第42行 52 board_init_r(NULL, 0);
5.board_init_r 位於arc/arm/lib/Spl.c第158行,在這個函數里加載uboot.img到內存裏,通過跳轉過去,同時通過r0把啓動信息給傳遞過去242 jump_to_image_no_args(&spl_image);
__weak void __noreturn jump_to_image_no_args(struct spl_image_info *spl_image)
{
typedef void __noreturn (*image_entry_noargs_t)(u32 *);
image_entry_noargs_t image_entry =
(image_entry_noargs_t) spl_image->entry_point;
debug("image entry point: 0x%X\n", spl_image->entry_point);
/* Pass the saved boot_params from rom code */
#if defined(CONFIG_VIRTIO) || defined(CONFIG_ZEBU)
image_entry = (image_entry_noargs_t)0x80100000;
#endif
u32 boot_params_ptr_addr = (u32)&boot_params_ptr;
image_entry((u32 *)boot_params_ptr_addr);
}