目录
一、crt0_64.S
二、board_init_f函数
三、init_sequence_f[] 函数数组(一)
四、init_sequence_f[] 函数数组(二)
五、内存分配如图
一、crt0_64.S
文件位置:u-boot-2022.01/arch/arm/lib/crt0_64.S
_main入口
- 执行3函数,前2个在u-boot-2022.01\common\init\board_init.c 中
board_init_f_alloc_reserve
board_init_f_init_reserve
board_init_f 在u-boot-2022.01\common\board_f.c
-
board_init_f_alloc_reserve,board_init_f_init_reserve主要实现内存排布:
uboot区,堆区,栈区,gd(bd)
board_init_f_alloc_reserve:最终算出gd的内存地址,top指向
board_init_f_init_reserve:实例化gd,并初始化为0
二、board_init_f函数
void board_init_f(ulong boot_flags)
{
gd->flags = boot_flags;
gd->have_console = 0;
if (initcall_run_list(init_sequence_f))
hang();
#if !defined(CONFIG_ARM) && !defined(CONFIG_SANDBOX) && \
!defined(CONFIG_EFI_APP) && !CONFIG_IS_ENABLED(X86_64) && \
!defined(CONFIG_ARC)
/* NOTREACHED - jump_to_copy() does not return */
hang();
#endif
}
static inline int initcall_run_list(const init_fnc_t init_sequence[])
{
const init_fnc_t *init_fnc_ptr;
for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) {
unsigned long reloc_ofs = 0;
int ret;
/*
* Sandbox is relocated by the OS, so symbols always appear at
* the relocated address.
*/
if (IS_ENABLED(CONFIG_SANDBOX) || (gd->flags & GD_FLG_RELOC))
reloc_ofs = gd->reloc_off;
#ifdef CONFIG_EFI_APP //debug开关
reloc_ofs = (unsigned long)image_base;
#endif
if (reloc_ofs)
debug("initcall: %p (relocated to %p)\n",
(char *)*init_fnc_ptr - reloc_ofs,
(char *)*init_fnc_ptr);
else
debug("initcall: %p\n", (char *)*init_fnc_ptr - reloc_ofs);
ret = (*init_fnc_ptr)();
if (ret) {
printf("initcall sequence %p failed at call %p (err=%d)\n",
init_sequence,
(char *)*init_fnc_ptr - reloc_ofs, ret);
return -1;
}
}
return 0;
}
static const init_fnc_t init_sequence_f[] = {
setup_mon_len,
#ifdef CONFIG_OF_CONTROL
fdtdec_setup,
#endif
#ifdef CONFIG_TRACE_EARLY
trace_early_init,
#endif
initf_malloc,
log_init,
initf_bootstage, /* uses its own timer, so does not need DM */
#ifdef CONFIG_BLOBLIST
bloblist_init,
#endif
setup_spl_handoff,
#if defined(CONFIG_CONSOLE_RECORD_INIT_F)
console_record_init,
#endif
#if defined(CONFIG_HAVE_FSP)
arch_fsp_init,
#endif
arch_cpu_init, /* basic arch cpu dependent setup */
mach_cpu_init, /* SoC/machine dependent CPU setup */
initf_dm,
arch_cpu_init_dm,
#if defined(CONFIG_BOARD_EARLY_INIT_F)
board_early_init_f,
#endif
#if defined(CONFIG_PPC) || defined(CONFIG_SYS_FSL_CLK) || defined(CONFIG_M68K)
/* get CPU and bus clocks according to the environment variable */
get_clocks, /* get CPU and bus clocks (etc.) */
#endif
#if !defined(CONFIG_M68K)
timer_init, /* initialize timer */
#endif
#if defined(CONFIG_BOARD_POSTCLK_INIT)
board_postclk_init,
#endif
env_init, /* initialize environment */
init_baud_rate, /* initialze baudrate settings */
serial_init, /* serial communications setup */
console_init_f, /* stage 1 init of console */
display_options, /* say that we are here */
display_text_info, /* show debugging info if required */
checkcpu,
#if defined(CONFIG_SYSRESET)
print_resetinfo,
#endif
#if defined(CONFIG_DISPLAY_CPUINFO)
print_cpuinfo, /* display cpu info (and speed) */
#endif
#if defined(CONFIG_DTB_RESELECT)
embedded_dtb_select,
#endif
#if defined(CONFIG_DISPLAY_BOARDINFO)
show_board_info,
#endif
INIT_FUNC_WATCHDOG_INIT
#if defined(CONFIG_MISC_INIT_F)
misc_init_f,
#endif
INIT_FUNC_WATCHDOG_RESET
#if CONFIG_IS_ENABLED(SYS_I2C_LEGACY)
init_func_i2c,
#endif
#if defined(CONFIG_VID) && !defined(CONFIG_SPL)
init_func_vid,
#endif
announce_dram_init,
dram_init, /* configure available RAM banks */
#ifdef CONFIG_POST
post_init_f,
#endif
INIT_FUNC_WATCHDOG_RESET
#if defined(CONFIG_SYS_DRAM_TEST)
testdram,
#endif /* CONFIG_SYS_DRAM_TEST */
INIT_FUNC_WATCHDOG_RESET
#ifdef CONFIG_POST
init_post,
#endif
INIT_FUNC_WATCHDOG_RESET
/*
* Now that we have DRAM mapped and working, we can
* relocate the code and continue running from DRAM.
*
* Reserve memory at end of RAM for (top down in that order):
* - area that won't get touched by U-Boot and Linux (optional)
* - kernel log buffer
* - protected RAM
* - LCD framebuffer
* - monitor code
* - board info struct
*/
setup_dest_addr,
#ifdef CONFIG_OF_BOARD_FIXUP
fix_fdt,
#endif
#ifdef CONFIG_PRAM
reserve_pram,
#endif
reserve_round_4k,
arch_reserve_mmu,
reserve_video,
reserve_trace,
reserve_uboot,
reserve_malloc,
reserve_board,
reserve_global_data,
reserve_fdt,
reserve_bootstage,
reserve_bloblist,
reserve_arch,
reserve_stacks,
dram_init_banksize,
show_dram_config,
INIT_FUNC_WATCHDOG_RESET
setup_bdinfo,
display_new_sp,
INIT_FUNC_WATCHDOG_RESET
reloc_fdt,
reloc_bootstage,
reloc_bloblist,
setup_reloc,
#if defined(CONFIG_X86) || defined(CONFIG_ARC)
copy_uboot_to_ram,
do_elf_reloc_fixups,
#endif
clear_bss,
#if !defined(CONFIG_ARM) && !defined(CONFIG_SANDBOX) && \
!CONFIG_IS_ENABLED(X86_64)
jump_to_copy,
#endif
NULL,
};
- gd->flags = boot_flags;
gd->have_console = 0;
flags:全局数据标志
have_console:控制台1可用,0不可用
- typedef int (*init_fnc_t)(void); 一个函数类型
- init_sequence是一个函数指针数组,数组中存储了很多个函数指针,这些指向指向的函数都是init_fnc_t类型(参数是void类型,返回值是int)
都是board级别的各种硬件初始化
- 函数:int initcall_run_list(const init_fnc_t init_sequence[])
返回值int,参数是一个二级指针init_sequence这个函数指针数组
- for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) {
依次执行init_sequence这个函数指针数组里的函数,直到NULL退出循环
函数执行出错返回-1,退出到board_init_f()函数,进入hang()函数
- hang() 死循环,只能重新上电
三、init_sequence_f[] 函数数组(一)
串口、定时器、设备树、malloc、cpu、DM驱动模型、dram、
static const init_fnc_t init_sequence_f[] = {
setup_mon_len,
fdtdec_setup,
initf_malloc,
log_init,
initf_bootstage, /* uses its own timer, so does not need DM */
setup_spl_handoff,
arch_cpu_init, /* basic arch cpu dependent setup */
mach_cpu_init, /* SoC/machine dependent CPU setup */
initf_dm,
arch_cpu_init_dm,
get_clocks, /* get CPU and bus clocks (etc.) */
board_postclk_init,
env_init, /* initialize environment */
init_baud_rate, /* initialze baudrate settings */
serial_init, /* serial communications setup */
console_init_f, /* stage 1 init of console */
display_options, /* say that we are here */
display_text_info, /* show debugging info if required */
checkcpu,
announce_dram_init,
dram_init, /* configure available RAM banks */
testdram,
setup_dest_addr,
reserve_pram,
reserve_round_4k,
arch_reserve_mmu,
reserve_video,
reserve_trace,
reserve_uboot,
reserve_malloc,
reserve_board,
reserve_global_data,
reserve_fdt,
reserve_bootstage,
reserve_bloblist,
reserve_arch,
reserve_stacks,
dram_init_banksize,
show_dram_config,
setup_bdinfo,
display_new_sp,
reloc_fdt,
reloc_bootstage,
reloc_bloblist,
setup_reloc,
clear_bss,
NULL,
};
- setup_mon_len:设置 gd 的 mon_len 成员变量,整个代码的长度
- fdtdec_setup:获取设备树地址
- initf_malloc:设置gd 的malloc_limit,malloc内存池大小
CONFIG_SYS_MALLOC_F_LEN=0x2000
- log_init,initf_bootstage,setup_spl_handoff:什么也没做返回0
- arch_cpu_init:硬件 CPU初始化
- mach_cpu_init:特定SoC的初始化
- initf_dm,arch_cpu_init_dm:DM驱动模型的一些初始化,DM驱动模型参考
- get_clocks:获取一些时钟值
- timer_init:初始化定时器,为 uboot 提供时间
- board_postclk_init:对于 I.MX6ULL 来说是设置 VDDSOC 电压
- env_init:设置 gd 的成员变量 env_addr,也就是环境变量的保存地址
- init_baud_rate:初始化波特率,env_get函数用来读取环境变量的值 baudrate
初始化 gd->baudrate
baudrate初始化时的规则是:先去环境变量中读取"baudrate"这个环境变量的值。如果读取成功则使用这个值作为环境变量,记录在gd->baudrate中;如果读取不成功则使用CONFIG_BAUDRATE的值作为波特率
- serial_init:初始化串口
加一句自己调试,验证初始化成功
drivers/serial/serial-uclass.c 编辑
- console_init_f:设置 gd->have_console 为 1表示有个控制台,此函数也将前面暂存在缓冲区中的数据通过控制台打印出来。
- display_options:通过串口输出一些信息,如u-boot的版本信息,注释到可以发现版本信息没有了
lib/display_options.c 编辑
- display_text_info:打印一些文本信息,如果开启 UBOOT 的 DEBUG 功能的话就会输出 text_base、bss_start、bss_end
开启DEBUG方法:在include/common.h文件添加 #define DEBUG
也可以自己添加调试信息打印(printf)
- checkcpu:什么也没做返回0
- announce_dram_init:打印字符串DRAM:
- dram_init:DRAM初始化
- testdram:测试DRAM,并打印一些信息
现在我们已经映射了DRAM并开始工作,我们可以重新定位代码并继续从DRAM运行
四、init_sequence_f[] 函数数组(二)
对uboot重定位的一些地址设置
- setup_dest_addr:uboot重定位设置gd->ram_size,gd->ram_top,gd->relocaddr这三个的值
- reserve_round_4k:对gd->relocaddr做4KB对齐
- arch_reserve_mmu:预留空间存放TLB表,以及64kb对齐
文件位置:arch\arm\lib\cache.c
- reserve_trace:留出跟踪调试的内存
- reserve_uboot: 留出重定位后的 uboot 所占用的内存区域
- reserve_malloc:留出malloc区域
malloc 区域由宏TOTAL_MALLOC_LEN 定义
- reserve_board:预留bd_info结构体大小空间,并清零
- reserve_global_data:预留空间给gd_t结构体
- reserve_fdt:预留空间给设备树驱动,没有使用,所以没预留
- reserve_bootstage,reserve_bloblist:什么也没做
- reserve_arch:空函数
- reserve_stacks:预留空间给栈16字节
- dram_init_banksize:设置 dram 信息,gd->bd->bi_dram[0].start,gd->bd->bi_dram[0].size
- show_dram_config:显示 DRAM 的配置start,size
- setup_bdinfo:什么也没做
- display_new_sp:debug打印当前start_addr_sp
- reloc_fdt,reloc_bootstage,reloc_bloblist:什么也没做
- setup_reloc:设置gd结构体的其他一些成员变量,供后面重定位的时候使用,并且将以前的 gd 拷贝到 gd->new_gd 处
- clear_bss:空函数
五、内存分配如图
编辑
参考博文1
参考博文2
参考博文3
【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱:
cloudbbs@huaweicloud.com
评论(0)