u-boot中的GOT段
//@u-boot/mds-dc3/common/start.S
...
START_GOT
GOT_ENTRY(_GOT2_TABLE_)
GOT_ENTRY(_FIXUP_TABLE_)
GOT_ENTRY(_start)
GOT_ENTRY(_start_of_vectors)
GOT_ENTRY(_end_of_vectors)
GOT_ENTRY(transfer_to_handler)
GOT_ENTRY(__init_end)
GOT_ENTRY(_end)
GOT_ENTRY(__bss_start)
END_GOT
/*
* e500 Startup -- after reset only the last 4KB of the effective
* address space is mapped in the MMU L2 TLB1 Entry0. The .bootpg
* section is located at THIS LAST page and basically does three
* things: clear some registers, set up exception tables and
* add more TLB entries for 'larger spaces'(e.g. the boot rom) to
* continue the boot procedure.
* Once the boot rom is mapped by TLB entries we can proceed
* with normal startup.
*
*/
.section .bootpg,"ax"
.globl _start_e500
_start_e500:
...
/* Jump out the last 4K page and continue to 'normal' start */
1: bl 3f
b _start
...
.globl _start
_start:
/* Clear and set up some registers. */
...
GET_GOT
bl cpu_init_f
bl icache_enable
bl board_init_f
isync
.globl _start_of_vectors
_start_of_vectors:
...
//@cpu/mpc85xx/start.S
.globl relocate_code
relocate_code:
...
bl board_init_r //从这里跳转到C代码
//board_init_r()会完成u-boot所需的最基本的初始化工作,然后进入命令解析的循环 -- main_loop();
//@lib_ppc/board.c
void board_init_r (gd_t *id, ulong dest_addr)
//first CPU Boot
+-- if(!(whoAmI() == 1)) {
//first CPU Boot
//各种初始化...
} else{
//SLAVE - second CPU Boot
misc_init_r();
}
//check if hotkey was pressed
+-- if( ctrlc() ) {
goto skip_autoboot;
}
+-- if(do_autoboot() < 0) {
debug("Auto boot failed. Going to interactive mode.\n");
}
skip_autoboot:
//Initialization complete - start the monitor ...
+-- if (board_get_sprom_boot_mode() == DEFAULT_MODE){
evfs_reg_dev_fs("ide", 0, EVFS_EXT2);
if(uboot_evfs_mount("bootflash:", CFG_BOOTFLASH_PARTITION) != 0 ) {
printf("Unable to mount default partition %d as bootflash:\n", CFG_BOOTFLASH_PARTITION);
}
}
//main_loop() can return to retry autoboot, if so just run it again.
+-- for (;;) {
WATCHDOG_RESET ();
#ifdef CONFIG_PCI_SLAVE
change_to_slave();
#endif
main_loop ();
}
void
main_loop (void)
+-- ...
+-- for (;;) {
len = readline (command_prompt);
...
strcpy (lastcommand, console_buffer);
...
rc = run_command (lastcommand, flag); //执行命令行对应的函数
...
}
//总体上run_command()就是先找到命令对应的函数,然后执行之,里面涉及到的命令解析的细节我们不关心
int run_command (const char *cmd, int flag)
+-- ...
+-- cmdtp = find_cmd(argv[0])
+-- ...
+-- (cmdtp->cmd) (cmdtp, flag, argc, argv)
//find_cmd()是在cmd_tbl_entries[]这个数组中查找命令的:
cmd_tbl_t *find_cmd (const char *cmd)
+-- len = ((p = strchr(cmd, '.')) == NULL) ? strlen (cmd) : (p - cmd);
+-- for (idx = cmd_tbl_idx_start; idx < cmd_tbl_idx_end; idx++){
for (cmdtp = cmd_tbl_entries[idx]; cmdtp->name; cmdtp++){
if (strncmp (cmd, cmdtp->name, len) == 0){
if (len == strlen (cmdtp->name))
return cmdtp; //full match
cmdtp_temp = cmdtp; //abbreviated command?
n_found++;
}
}
if (n_found == 1 && !(cmdtp_temp->flags & CMD_FLAG_HIDDEN))
{
//exactly one match, and not a hidden command
return cmdtp_temp;
}
}
//cmd_tbl_entries[]中的cmd一共有两种:
//一种是base_cmd,由void init_cmd_tbl( cmd_tbl_t *base_cmds )提供;
//一种是后来添加的cmd,由add_cmd_tbl()提供;
//1. init_cmd_tbl()是在“first CPU Boot”的初始化阶段调用的:
...
//重定位bios_base_cmds[]数组
relocate_cmd_tbl(bios_base_cmds,(cmd_tbl_t *)(((ulong) bios_base_cmd_end)+gd->reloc_off), (gd_t*) gd );
init_cmd_tbl( (cmd_tbl_t*) bios_base_cmds ); //将bios_base_cmds[]中的命令描述符拷贝到cmd_tbl_entries[]中去
...
//bios_base_cmds[]的定义如下:
U_BOOT_MENU_START ( bios_base_cmds )
U_BOOT_MENU_ENTRY( boot, 3, 1, do_bios_boot_cmd,
"boot Boot image\n",
"- Boot an image from the compact flash or tftp server.\n\n"
...
NULL, 0 ),
U_BOOT_MENU_ENTRY( dir, CFG_MAXARGS, 1, do_bios_dir_cmd,
"dir List Directory\n",
"- Print directory listings from the compact flash\n\n"
...
NULL, PLATF_VISIBILITY_FLAG ),
...
U_BOOT_MENU_END ( bios_base_cmds )
cmd_tbl_t *bios_base_cmd_end = bios_base_cmds +
(sizeof(bios_base_cmds) / sizeof(cmd_tbl_t));
//U_BOOT_MENU_START/END的定义如下:
#define U_BOOT_MENU_START( name ) cmd_tbl_t name[] = {
#define U_BOOT_MENU_END(name) ,{(char*)0, 0, 0, NULL, (char*)0, (char*)0, NULL, 0 } }; //最后一个命令为空
//所以上面一堆实际上就是定义并初始化了一个数组 cmd_tbl_t bios_base_cmds[]={ ... }
//2. add_cmd_tbl()是在执行sw_tbl命令的时候调用的:
U_BOOT_MENU_ENTRY( sw_tbl, 1, 1, do_cmd_subcmd,
NULL,
"- Switch command table\n",
&__u_boot_cmd_start, CMD_FLAG_HIDDEN | CMD_FLAG_RELOCATE )
int
do_cmd_subcmd( cmd_tbl_t *cmdtp, int flag, int argc, char *argv[] )
+-- relocate_cmd_tbl( &__u_boot_cmd_start, &__u_boot_cmd_end, (gd_t*) gd );
+-- sub_cmd_tbl( cmdtp->sub_cmd, (const char*)prompt );
+-- add_cmd_tbl(cmds);
//board specific的部分:
//在lds文件中可以指定链接的顺序以及二进制代码的分布:
//board/xxx/xxx/xxx/u-boot.lds
SECTIONS
{
.resetvec 0xFFFFFFFC :
{
*(.resetvec)
} = 0xffff
.bootpg 0xFFFFF000 :
{
cpu/mpc85xx/start.o (.bootpg)
board/xxx/xxx/xxx/init.o (.bootpg)
} = 0xffff
...
.text :
{
cpu/mpc85xx/start.o (.text)
board/xxx/xxx/xxx/init.o (.text)
cpu/mpc85xx/traps.o (.text)
cpu/mpc85xx/interrupts.o (.text)
cpu/mpc85xx/cpu_init.o (.text)
cpu/mpc85xx/cpu.o (.text)
cpu/mpc85xx/tsec.o (.text)
cpu/mpc85xx/speed.o (.text)
cpu/mpc85xx/pci.o (.text)
common/dlmalloc.o (.text)
lib_generic/crc32.o (.text)
lib_ppc/extable.o (.text)
lib_generic/zlib.o (.text)
*(.text)
*(.fixup)
*(.got1)
}
_etext = .;
...
.reloc :
{
*(.got)
_GOT2_TABLE_ = .;
*(.got2)
_FIXUP_TABLE_ = .;
*(.fixup)
}
__got2_entries = (_FIXUP_TABLE_ - _GOT2_TABLE_) >> 2;
__fixup_entries = (. - _FIXUP_TABLE_) >> 2;
...
. = .;
__u_boot_cmd_start = .;
.u_boot_cmd :
{
*(.u_boot_cmd)
*(.u_boot_null)
}__u_boot_cmd_end = .;
. = .;
__u_boot_subcmd_start = .;
.u_boot_subcmd : { *(.u_boot_subcmd) }
__u_boot_subcmd_end = .;
. = .;
__start___ex_table = .;
__ex_table : { *(__ex_table) }
__stop___ex_table = .;
...
}
//"FirstCPU Boot"阶段会涉及到一些board specific的函数,如果没有输入参数的话,一般都放在
//lib_ppc/board.c中定义的数组init_fnc_t *init_sequence[]中,
//@lib_ppc/board.c
init_fnc_t *init_sequence[] = {
#if defined(CONFIG_BOARD_PRE_INIT)
board_pre_init, /* very early board init code (fpga boot, etc.) */
#endif
...
//@lib_ppc/board.c
//init_fnc_ptr = init_sequence,之后遍历init_sequence[]这个数组,调用其中每一个函数
for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) {
if ((*init_fnc_ptr) () != 0) {
hang ();
}
}
//而在初始化函数序列init_sequence中的board_pre_init()等函数则是在
//lib_ppc/board.c和board/xxx/xxx/xxx/xxx_board.c两个文件中定义的
//前者是ppc平台common的,后者是某个具体的board specific的
//驱动相关的部分:
u-boot学习笔记之一 -- PPC
最新推荐文章于 2022-08-15 11:14:21 发布