u-boot学习笔记之一 -- PPC

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的


//驱动相关的部分:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值