韦东山_My_Uboot全解

来源:互联网 发布:剑三魏无羡捏脸数据 编辑:程序博客网 时间:2024/04/29 13:00

1、链接文件

在链接脚本里指定了起始地址->代码段->只读数据段->数据段

. = ALIIGN(4) //向4取整


SECTIONS {. = 0x33f80000;.text : { *(.text) }. = ALIGN(4);.rodata : {*(.rodata*)} . = ALIGN(4);.data : { *(.data) }. = ALIGN(4);__bss_start = .;.bss : { *(.bss)  *(COMMON) }__bss_end = .;}

2、Makefile

CC  = arm-linux-gccLD  = arm-linux-ldAR  = arm-linux-arOBJCOPY = arm-linux-objcopyOBJDUMP = arm-linux-objdumpCFLAGS      := -Wall -O2CPPFLAGS    := -nostdinc -nostdlib -fno-builtinobjs := start.o init.o boot.oboot.bin: $(objs)    ${LD} -Tboot.lds -o boot.elf $^    ${OBJCOPY} -O binary -S boot.elf $@    ${OBJDUMP} -D -m arm boot.elf > boot.dis%.o:%.c    ${CC} $(CPPFLAGS) $(CFLAGS) -c -o $@ $<%.o:%.S    ${CC} $(CPPFLAGS) $(CFLAGS) -c -o $@ $<clean:    rm -f *.o *.bin *.elf *.dis

这里说一下:
但当工程里面有自己定义的函数:例如strcpy,但是编译器里已经有了这个函数那么我们想不用编译器里的 ,在编译链里 加上

-fno-buiiltin

这里生成的反汇编:

arm-linux-objdump -D -m arm boot.elf>boot.dis

生成的反汇编文件特别有用:

我们一起来分析下重定位代码时,反汇编对我们的帮助:

重定位代码:

/* 4. 重定位 : 把bootloader本身的代码从flash复制到它的链接地址去 */    ldr sp, =0x34000000    bl nand_init    mov r0, #0    ldr r1, =_start    ldr r2, =__bss_start    sub r2, r2, r1    bl copy_code_to_sdram    bl clear_bss

这里很难看出到底拷贝了多少到SDRAM中。

那么我们通过反汇编来分析吧。


33f80050:   eb000032    bl  33f80120 <nand_init>33f80054:   e3a00000    mov r0, #0  ; 0x033f80058:   e59f1058    ldr r1, [pc, #88]   ; 33f800b8 <sdram_config+0x40>33f8005c:   e59f2058    ldr r2, [pc, #88]   ; 33f800bc <sdram_config+0x44>33f80060:   e0422001    sub r2, r2, r133f80064:   eb0000c8    bl  33f8038c <copy_code_to_sdram>33f80068:   eb000021    bl  33f800f4 <clear_bss>33f8006c:   e59fe04c    ldr lr, [pc, #76]   ; 33f800c0 <sdram_config+0x48>33f80070:   e59ff04c    ldr pc, [pc, #76]   ; 33f800c4 <sdram_config+0x4c>

ldr r1,=_start== ldr r1,[pc,#88] ;33f800b8 sdram_config+0x40
跳到
33f800b8: 33f80000 mvnccs r0, #0 ; 0x0
33f800bc: 33f806b0 mvnccs r0, #184549376 ; 0xb000000

sub r2, r2, r133f800b8    -   33f800006b0  就是我们要拷贝的文件大小   1712四字节对齐 因为.=ALIGN(4);

看一下 清BSS段

跳到C函数中:

Void clear_bss(void){Extern int __bss_start,__bss_end;Int *p = &__bss_start;For(;p<&__bss_end;p++)*p = 0;}

看看一下反汇编:

33f80068:   eb000021    bl  33f800f4 <clear_bss>33f8006c:   e59fe04c    ldr lr, [pc, #76]   ; 33f800c0 <sdram_config+0x48>33f80070:   e59ff04c    ldr pc, [pc, #76]   ; 33f800c4 <sdram_config+0x4c>

33f800f4 <clear_bss>:33f800f4:   e59f301c    ldr r3, [pc, #28]   ; 33f80118 <.text+0x118>33f800f8:   e59f101c    ldr r1, [pc, #28]   ; 33f8011c <.text+0x11c>33f800fc:   e1530001    cmp r3, r133f80100:   21a0f00e    movcs   pc, lr33f80104:   e3a02000    mov r2, #0  ; 0x033f80108:   e4832004    str r2, [r3], #433f8010c:   e1530001    cmp r3, r133f80110:   3afffffc    bcc 33f80108 <clear_bss+0x14>33f80114:   e1a0f00e    mov pc, lr33f80118:   33f806b0    mvnccs  r0, #184549376  ; 0xb00000033f8011c:   33f806b4    mvnccs  r0, #188743680  ; 0xb400000

Disassembly of section .bss:33f806b0 <params>:33f806b0:   00000000    andeq   r0, r0, r0Disassembly of section .comment:

3、START.S

.text.global _start_start:/* 1. 关看门狗 */    ldr r0, =0x53000000    mov r1, #0    str r1, [r0]

/* 2. 设置时钟 */    ldr r0, =0x4c000014    //  mov r1, #0x03;            // FCLK:HCLK:PCLK=1:2:4, HDIVN=1,PDIVN=1    mov r1, #0x05;            // FCLK:HCLK:PCLK=1:4:8    str r1, [r0]    /* 如果HDIVN非0,CPU的总线模式应该从“fast bus mode”变为“asynchronous bus mode” */    mrc p15, 0, r1, c1, c0, 0       /* 读出控制寄存器 */     orr r1, r1, #0xc0000000         /* 设置为“asynchronous bus mode” */    mcr p15, 0, r1, c1, c0, 0       /* 写入控制寄存器 */    /* MPLLCON = S3C2440_MPLL_200MHZ */    ldr r0, =0x4c000004    ldr r1, =S3C2440_MPLL_400MHZ    str r1, [r0]    /* 启动ICACHE */    mrc p15, 0, r0, c1, c0, 0   @ read control reg    orr r0, r0, #(1<<12)    mcr p15, 0, r0, c1, c0, 0   @ write it back

/* 3. 初始化SDRAM */    ldr r0, =MEM_CTL_BASE    adr r1, sdram_config /* sdram_config的当前地址 */    add r3, r0, #(13*4)1:    ldr r2, [r1], #4    str r2, [r0], #4    cmp r0, r3    bne 1b

/* 4. 重定位 : 把bootloader本身的代码从flash复制到它的链接地址去 */    ldr sp, =0x34000000    bl nand_init    mov r0, #0    ldr r1, =_start    ldr r2, =__bss_start    sub r2, r2, r1    bl copy_code_to_sdram    bl clear_bss

/* 5. 执行main */    ldr lr, =halt    ldr pc, =mainhalt:    b haltsdram_config:    .long 0x22011110     //BWSCON    .long 0x00000700     //BANKCON0    .long 0x00000700     //BANKCON1    .long 0x00000700     //BANKCON2    .long 0x00000700     //BANKCON3      .long 0x00000700     //BANKCON4    .long 0x00000700     //BANKCON5    .long 0x00018005     //BANKCON6    .long 0x00018005     //BANKCON7    .long 0x008C04F4     // REFRESH    .long 0x000000B1     //BANKSIZE    .long 0x00000030     //MRSRB6    .long 0x00000030     //MRSRB7

设置栈 sp->内存 调用C函数


4、配置过程:

make 100ask23x0_config时候:

在u-boot源码中:

atstk1002_config    :   unconfig    @./mkconfig $(@:_config=) avr32 at32ap atstk1000 atmel at32ap7000

就相当于 :

mkconfig 100ask24x0 arm arm920t 100ask24x0 NULL S3C24X0

分析: Mkconfig 脚本文件:

$0  $1  $2  $3  $4$#代表参数的个数。[$# -lt 4] $$ exit 1   小于4个[$# -gt 6] $$ exit1    大于6个OBJTREE     := $(if$(BULLD_DIR),$(BUILD_DIR),$(CURDIR))是否定义:BULLD_DIRCd ./include    rm -f asmLn -s asm-$2 asm   #创建链接文件ln -s asm-arm asm因为源码include中有好多单板这里指定  arm架构Rm -f asm-$2/arch      #rm  -f  asm-arm/archLn -s ${LNPRERIX}proc-armvasm-$2/proc  #ln     -s  proc-armv  asm-arm/procEcho “ARCH  =  $2”>    config.mkEcho”CPU    =  $3”>>config.mkEcho”BOARD  =   $4”>>config.mk内容:ARCH    =   armCPU     =   arm920tBOARD   =   100ask24x0SOC     =   s3c24x0

最后生成了 config.mk


5、UBOOT给内核传参数:

1、 帮内核设置串口: 内核启动的开始部分会从串口打印一些信息,但是内核一开始没有初始化串口

uart0_init();

2、从NAND FLASH里把内核读入内存

3、设置参数 tag

setup_start_tag();setup_memory_tags();setup_commandline_tag("noinitrd root=/dev/mtdblock3 init=/linuxrc console=ttySAC0");setup_end_tag();

分析下tag这个参数:


struct tag {struct tag_header hdr;union {    struct tag_core     core;    struct tag_mem32    mem;    struct tag_videotext    videotext;    struct tag_ramdisk  ramdisk;    struct tag_initrd   initrd;    struct tag_serialnr serialnr;    struct tag_revision revision;    struct tag_videolfb videolfb;    struct tag_cmdline  cmdline;    /*     * Acorn specific     */    struct tag_acorn    acorn;    /*     * DC21285 specific     */    struct tag_memclk   memclk;} u;};

struct tag_header {    u32 size;    u32 tag;};

这个结构体怎么用:

有一个关键函数:

#define tag_next(t) ((struct tag *)((u32 *)(t) + (t)->hdr.size))

参数存放地址: 0x30000100

实现地址一直往后偏移0x30000100 + sizeof() +sizeof() +sizeof()


void setup_start_tag(void){    params = (struct tag *)0x30000100;    params->hdr.tag = ATAG_CORE;    params->hdr.size = tag_size (tag_core);    params->u.core.flags = 0;    params->u.core.pagesize = 0;    params->u.core.rootdev = 0;    params = tag_next (params);}

void setup_memory_tags(void){    params->hdr.tag = ATAG_MEM;    params->hdr.size = tag_size (tag_mem32);    params->u.mem.start = 0x30000000;    params->u.mem.size  = 64*1024*1024;    params = tag_next (params);}

void setup_commandline_tag(char *cmdline){    int len = strlen(cmdline) + 1;    params->hdr.tag  = ATAG_CMDLINE;    params->hdr.size = (sizeof (struct tag_header) + len + 3) >> 2;    strcpy (params->u.cmdline.cmdline, cmdline);    params = tag_next (params);}

void setup_end_tag(void){    params->hdr.tag = ATAG_NONE;    params->hdr.size = 0;}

4、跳转执行

void (*theKernel)(int zero, int arch, unsigned int params);volatile unsigned int *p = (volatile unsigned int *)0x30008000;theKernel = (void (*)(int, int, unsigned int))0x30008000;theKernel(0, 362, 0x30000100);  


这样 内核就启动了 uboot就一去不复返了。

原创粉丝点击