BootLoader

Posted dongry

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了BootLoader相关的知识,希望对你有一定的参考价值。

1 Uboot启动流程

技术图片

2 程序入口的查看

  (1)首先在uboot文件夹中找到Makefile文件,搜索smdk2440查看配置情况;

技术图片

  (2)在uboot文件夹中->board文件夹->samsung文件夹->smdk2440文件夹->u-boot.lds;

    在u-boot.lds中找到start文件的位置:

技术图片

  (3)uboot文件夹->cpu文件夹->s3c24xx文件夹->start.S

技术图片

3 第一阶段程序分析

.globl _start
_start:
        b reset

/*以下语句都是用来设置中断向量表的*/
        ldr pc,_undefined_instruction     
        ldr pc,_software_interrupt
        ldr pc,_prefetch_abort
        ldr pc,_data_abort
        ldr pc,_not_used
        ldr pc,_irq
        ldr pc,_fiq
/*程序从b reset跳过来*/
reset:
        /*set the cpu to svc32 mode 
           设置处理器为svc32模式*/
        mrs r0,cpsr
        bic r0,r0,#0x1f
        orr r0,r0,#0xd3
        msr cpsr,r0
/*顺序执行下去到达*/
cpu_init_crit:
        /*flush v4 I/D caches
          刷新I/D caches*/
        mov r0,#0
        mcr p15,0,r0,c7,c7,0
        mcr p15,0,r0,c8,c7,0


        /*disable MMU stuff and caches
            关闭MMU和caches*/
        mrc p15,0,r0,c1,c0,0
        bic r0,r0,#0x00002300
        bic r0,r0,#0x00000087
        orr r0,r0,#0x00000002
        orr r0,r0,#0x00001000
        mcr p15,0,r0,c1,c0,0
接着到达函数“bl lowlevel_init”
lowlevel_init:
        mov r12,lr

        /*init system clock
        初始化系统时钟*/
        bl system_clock_init

        /*for UART
        初始化串口*/
        bl uart_asm_init

        /*simple init for NAND
        简单初始化NAND flash*/
        bl nand_asm_init
/*when we already run in ram,we don‘t need to relocate U-Boot. and actually,memory controller must be configured before U-boot is running in ram
判断U-boot是否允许在内存当中*/
    ldr r0,=0xf0000fff
    bic r1,pc,r0     /*r0<-current base addr of code*/
    ldr r2,_TEXT_BASE    /*r1<-original base addr in ram*/
    bic r2,r2,r0    /*r0<-current base addr of code*/
    cmp r1,r2    /*compare r0,r1*/
    beq 1f     /*r0==r1 then skip sdram init*/
    
    adr1 r0,mem_cfg_val
    bl mem_con_init

    ldr r0,=ELFIN_UART_BASE
    ldr r1,=0x4b4b4b4b
    str r1,[r0,#0x20]

1:    mov lr,r12
       mov pc,lr
/*如果没有运行在内存当中,说明在NAND flash中启动,就要对内存进行初始化,即(bl mem_con_init)
/*返回到start.S文件*/

/*判断是nor flash还是nand flash*/
check boot deviec:
        ldr r0,=0xff000fff
        bic r1,pc,r0    /*r0<-current base addr of code*/
        ldr r2,_TEXT_BASE     /*r1<-original base addr in ram*/
        bic r2,r2,r0    /*r0<-current base addr of code*/
        cmp r1,r2    /*compare r0,r1*/
        beq after_copy    /*r0==r1 then skip flash copy*/
/*set up the stack
设置堆栈*/
stack_setup:
#ifdef CONFIG_MEMORY_UPPER_CODE
    ldr sp,=(CFG_UBOOT_BASE+CFG_UBOOT_SIZE-0xc)
#else
    ldr r0,_TEXT_BASE     /*upper 128 kib:relocated uboot*/
    sub r0,r0,#CFG_MALLOC_LEN     /*malloc area*/
    sub r0,r0,#CFG_GBL_DATA_SIZE    /*bdinfo*/
#ifdef CONFIG_USE_IRQ
    sub r0,r0,#(CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ)
#endif
    sub sp,r0,#12    /*leave 3 words for abort-stack*/
/*清除bss段*/
clear_bss:
        ldr r0,_bss_start    /*find start of bss segment*/
        ldr r1,_bss_end    /*stop here*/
        mov r2,#0x000000000    /*clear*/

3.1 第一阶段分析

  1.上电后CPU会将NAND flash中的前4K拷贝到steppingstone中,最前面的就是start.S,然后CPU就从start.S的_start处开始运行。

  2.start.S有一个环节是将NAND flash剩余的内存复制到内存(SDRAM)中去

  3.从steppingstone中跳转到内存中去。

技术图片

ldr pc,_start_armboot    /*PC指针跳转到内存中去*/

 3.2 基础配置

[email protected]:~/Uboot/uboot$ make smdk2440_config  //配置
[email protected]:~/Uboot/uboot$ make     //再配置

[email protected]-linux:~/Uboot/uboot$ arm-linux-objdump -D -S u-boot > dump
/*生成一个dump文件*/
[email protected]-linux:~/Uboot/uboot$vim dump //打开dump文件

3.3 相关命令

“/”+要搜索的文字                //eg:  /start_armboot
“/”+“要搜索的文字”+“n”       //同一文档连续搜寻下一个

3.4 相对跳转B

技术图片

  假设stepping stone的地址从零开始,内存地址从0x30008000开始,程序运行一段时间后,假设PC指针到了100,将要运行程序lowleave_init函数,假设此函数的入口地址为0x30008010,假如用bl lowleave_init PC指针指向的值为100+(0x30008010-0x30008000)=116,所以PC指针不会进入内存中去(这就是相对跳转相对的意思);

  而使用 ldr pc,=0x30008010(绝对跳转)会使PC直接等于30008010跳到了内存中去。

4 第二阶段程序分析

/*第二阶段程序入口*/

        ......
        ldr pc,_start_armboot

start_armboot:
        .word start_armboot
/*start_armboot在uboot/uboot2440/lib_arm的board.c中*/

  第二阶段会进行两方面的初始化,一部分硬件方面的(主讲),一部分软件方面的

for(init_fnc_ptr=init_sequence;*init_fnc_ptr;++init_fnc_ptr)     //init_fnc_ptr指针数组,可查
{
        if((*init_fnc_ptr)()!=0)
        {
                hang();
        }
}
init_fnc_t *init_sequence[]=
{
        ...
        serial_init,  /*serial communications setup 初始化串口*/
        ...
}
/*LCD初始化*/
#ifdef LCD_FRAMBUFFER_ADDR
    addr=(void *)LCD_FRAMBUFFER_ADDR;
#else
    addr=(_bss_end+(PAGE_SIZE-1))&~(PAGE_SIZE-1);
#endif
    size=lcd_setmem(addr);
    gd->fb_base=addr;
#endif
/*网卡初始化*/
    eth_initialize(gd->bd)
/*led初始化*/
    led_init();
/*main_loop() can return to retry autoboot,if so just run it again
用户在控制台上输入的命令去进行解析,然后执行相应的用户输入的命令*/

        for(;;)
        {
                main_loop();
        }

5 uboot架构流程

技术图片

 

以上是关于BootLoader的主要内容,如果未能解决你的问题,请参考以下文章

最简单的bootloader的编写

怎样自己写bootloader

图解Linux内核:内核启动从Bootloader到内核代码

Arduino编译bootloader

NRF52 SDK16.0 代码启动流程

ucore lab1 练习4—bootloader加载ELF格式OS