barebox分析

来源:互联网 发布:淘宝上卖视频资料赚钱 编辑:程序博客网 时间:2024/06/05 03:04
 

barebox分析

 246人阅读 评论(0) 收藏 举报
cmdcommanddiskstructimagelinker

启动分析

arch\arm\目录下是对应构架的目录

Makefile文件

lds-$(CONFIG_GENERIC_LINKER_SCRIPT)    :=arch/arm/lib/barebox.lds

lds-$(CONFIG_BOARD_LINKER_SCRIPT)  := $(BOARD)/barebox.lds

配置时使用arch/arm/lib/barebox.lds链接脚本。

OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")

OUTPUT_ARCH(arm)

ENTRY(start)

SECTIONS

{

  . = TEXT_BASE;

arch/arm/Makefile:143:TEXT_BASE = $(CONFIG_TEXT_BASE)

CONFIG_TEXT_BASE是在配置文件中配置的

TEXT_BASE

  PRE_IMAGE

 

  . = ALIGN(4);

  .text      :

  {

     _stext = .;

     _text = .;

     *(.text_entry*)

      __ll_return = .;

     *(.text_ll_return*)

#ifdef CONFIG_ARCH_EP93XX

     /* the EP93xx expects to find the pattern 'CRUS' at 0x1000 */

    . = 0x1000;

    LONG(0x53555243) /* 'CRUS' */

#endif

     __bare_init_start = .;

     *(.text_bare_init*)

     __bare_init_end = .;

      __exceptions_start = .;

     KEEP(*(.text_exceptions*))

     __exceptions_stop = .;

     *(.text*)

  }

  BAREBOX_BARE_INIT_SIZE

 

  . = ALIGN(4);

  .rodata : { *(.rodata*) }

 

#ifdef CONFIG_ARM_UNWIND

  /*

   * Stack unwinding tables

   */

  . = ALIGN(8);

  .ARM.unwind_idx : {

     __start_unwind_idx = .;

     *(.ARM.exidx*)

     __stop_unwind_idx = .;

  }

  .ARM.unwind_tab : {

     __start_unwind_tab = .;

     *(.ARM.extab*)

     __stop_unwind_tab = .;

  }

#endif

  _etext = .;          /* End of text and rodata section */

 

  . = ALIGN(4);

  .data : { *(.data*) }

 

  . = ALIGN(4);

  .got : { *(.got*) }

 

  . = .;

  __barebox_cmd_start = .;

  .barebox_cmd : { BAREBOX_CMDS }

  __barebox_cmd_end = .;

 

  __barebox_magicvar_start = .;

  .barebox_magicvar : { BAREBOX_MAGICVARS }

  __barebox_magicvar_end = .;

 

  __barebox_initcalls_start = .;

  .barebox_initcalls : { INITCALLS }

  __barebox_initcalls_end = .;

 

  __usymtab_start = .;

  __usymtab : { BAREBOX_SYMS }

  __usymtab_end = .;

 

  . = ALIGN(4);

  __bss_start = .;

  .bss : { *(.bss*) }

  __bss_stop = .;

  _end = .;

  _barebox_image_size = __bss_start - TEXT_BASE;

}

 

刚开始时.text_entry,

void __naked__section(.text_entry) start(void)

{

    barebox_arm_head();

}

    进入的函数是barebox_arm_head(),是跳转函数。

staticinlinevoid barebox_arm_head(void)

{

    __asm__ __volatile__ (

       "b reset\n"

       "1: b 1b\n"

       "1: b 1b\n"

       "1: b 1b\n"

       "1: b 1b\n"

       "1: b 1b\n"

       "1: b 1b\n"

       "1: b 1b\n"

       ".word 0x65726162\n"        /* 'bare' */

       ".word 0x00786f62\n"        /* 'box' */

       ".word _text\n"             /* text base. If copied there,

                          * barebox can skip relocation

                          */

       ".word_barebox_image_size\n"      /* image size tocopy */

    );

}

    这个函数就是一些列跳转函数,正常情况下调转到reset函数。

       Reset函数修饰用

#define __bare_init          __section(.text_bare_init.text)

              __bare_init_start= .;

              *(.text_bare_init*)

              __bare_init_end= .;

Lds链接脚本有对此的修饰。

 

void __naked__bare_init reset(void)

{

 

    /* set the cpu to SVC32 mode */

#ifdef CONFIG_ARCH_HAS_LOWLEVEL_INIT

    arch_init_lowlevel();

#endif

    /* disable MMU stuff and caches */

#ifdef CONFIG_MACH_DO_LOWLEVEL_INIT

    board_init_lowlevel(); 这个是特定板子的文件

#endif

    board_init_lowlevel_return();

}

lowlevel_init.S (arch\arm\boards\tq2440)  中

.section ".text_bare_init.board_init_lowlevel","ax"

 

/* ------------------------------------------------------------------------*/

 

.globl board_init_lowlevel

board_init_lowlevel:

 

    mov r10, lr       /* save the link register */

 

    bl s3c24x0_disable_wd

 

    /* skip everything here if we are alreadyrunning from SDRAM */

    cmp pc, #S3C_SDRAM_BASE

    blo 1f

    cmp pc, #S3C_SDRAM_END

    bhs 1f

 

    mov pc, r10

 

/* we are running from NOR or NAND/SRAM memory. Do further initialisation*/

1:

    bl s3c24x0_pll_init

 

    bl s3c24x0_sdram_init

 

#ifdef CONFIG_S3C24XX_NAND_BOOT

    mov lr, r10       /* restore the linkregister */

/* up to here we are running from the internal SRAM area */

    b s3c24x0_nand_boot  /* does return directly to our caller into SDRAM */

#else

    mov pc, r10

#endif

       执行完函数board_init_lowlevel后,执行board_init_lowlevel_return。

       函数board_init_lowlevel中

s3c24x0_disable_wd关闭看门狗

s3c24x0_pll_init PLL初始化

s3c24x0_sdram_init SDRAM初始化,在2440板子上,只初始化了bank6和bank7,其他bank的配置保留。

s3c24x0_nand_boot:如果配置了从nand启动,会将代码从nand中拷贝到SDRAM中的TEXT_BASE地址处。

 

void __naked__section(.text_ll_return)board_init_lowlevel_return(void)

{

    uint32_t r, addr;

 

    /*

     * Get runtime address of this function. Do not

     * put any code above this.

     */

    __asm__ __volatile__("1: adr %0,1b":"=r"(addr));

Adr是当前程序运行的地址

    /* Setup the stack */

    r = STACK_BASE + STACK_SIZE -16;

    __asm__ __volatile__("mov sp,%0"::"r"(r));

 

    /* Get start of binary image */

    addr -=(uint32_t)&__ll_return- TEXT_BASE;

TEXT_BASE;这是在arch/XXX/configs/*_defconfig定义的

进行代码重定位

    /* relocate to link address ifnecessary */

    if(addr != TEXT_BASE)

       memcpy((void*)TEXT_BASE,(void*)addr,

              (unsignedint)&__bss_start- TEXT_BASE);

__***这些都是在链接脚本中定义的

    /* clear bss */

清楚bss

    memset(__bss_start,0, __bss_stop - __bss_start);

 

    /* call start_barebox with itsabsolute address */

    r =(unsignedint)&start_barebox跳转到函数去

    __asm__ __volatile__("mov pc,%0"::"r"(r));

}

              __ll_return= .;

              *(.text_ll_return*)

void __naked __section(.text_ll_return) board_init_lowlevel_return(void)

这是放在.text_entry之后的函数

 

函数void __naked __bare_init reset(void)

这是复位函数,其中

1. /* set the cpu to SVC32 mode */

2. #ifdefCONFIG_ARCH_HAS_LOWLEVEL_INIT

    arch_init_lowlevel();//对板子硬件中断向量进行了初始化

   #endif

3. __mmu_cache_flush

4.disable MMU stuff and caches

5. #ifdefCONFIG_MACH_DO_LOWLEVEL_INIT

    board_init_lowlevel();// 板子特定的文件,进行一些板子初始化,板级初始化

   #endif

6.board_init_lowlevel_return();// 进行代码重定位

reset函数中清空cache,disable掉mmu后跳去执行board_init_lowlevelCONFIG_MACH_DO_LOWLEVEL_INIT可以在menuconfig中看到被选中。board_init_lowlevel就是板子特定的文件了

       在函数board_init_lowlevel_return中会跳转到start_barebox去接着执行。

 

voidstart_barebox (void)

{

    initcall_t *initcall;

    int result;

#ifdef CONFIG_COMMAND_SUPPORT

    struct stat s;

#endif

首先执行一系列的初始化函数

    for(initcall = __barebox_initcalls_start;

           initcall <__barebox_initcalls_end; initcall++){

       debug("initcall->%pS\n",*initcall);

       result =(*initcall)();

       debug("initcall<-%pS (%d)\n",*initcall, result);

    }

 

    debug("initcalls done\n");

打印内存信息

    display_meminfo();

配置了处理环境信息选项则去读环境变量

首先程序去读取/dev/env0到/env,正常情况下/dev/env0放的是一个(类似)压缩文件,envfs_load会对它做校验。毫无疑问,初始启动时肯定是找不到这个文件的,所以接着读取/dev/defaultenv到/env (loader跑起来后执行saveenv就把/env的东西打包到/dev/env0去了)。然后执行/env/bin/init。

#ifdef CONFIG_ENV_HANDLING

    if(envfs_load(default_environment_path,"/env")){

#ifdef CONFIG_DEFAULT_ENVIRONMENT

       printf("no validenvironment found on %s. "

           "Using defaultenvironment\n",

           default_environment_path);

       envfs_load("/dev/defaultenv","/env");

#endif

    }

#endif

#ifdef CONFIG_COMMAND_SUPPORT

    printf("running/env/bin/init...\n");

执行默认的init脚本

    if(!stat("/env/bin/init",&s)){

       run_command("source/env/bin/init",0);

    }else{

       printf("notfound\n");

    }

#endif

    /* main_loop() can return to retry autoboot,if so just run it again. */

    for(;;)

       run_shell();

 

    /* NOTREACHED - no way out of commandloop except booting */

}

initcall-> 0x33d1e658

initcall<- 0x33d1e658 (0)

initcall-> 0x33d1fd34

initcall<- 0x33d1fd34 (0)

initcall-> 0x33d05368

initcall<- 0x33d05368 (0)

initcall-> 0x33d06480

initcall<- 0x33d06480 (0)

initcall-> 0x33d18088

initcall<- 0x33d18088 (0)

initcall-> 0x33d1a964

initcall<- 0x33d1a964 (0)

initcall-> 0x33d1d62c

initcall<- 0x33d1d62c (0)

initcall-> 0x33d0805c

initcall<- 0x33d0805c (0)

initcall-> 0x33d1e414

 

 

barebox 2012.05.0 (Jun  7 2012 - 21:00:25)

 

Board: TQ   2440

initcall<- 0x33d1e414 (0)

initcall-> 0x33d1e3f0

initcall<- 0x33d1e3f0 (0)

initcall-> 0x33d03780

initcall<- 0x33d03780 (0)

initcall-> 0x33d0dc50

initcall<- 0x33d0dc50 (0)

initcall-> 0x33d1bfb0

initcall<- 0x33d1bfb0 (0)

initcall-> 0x33d1cdcc

initcall<- 0x33d1cdcc (0)

initcall-> 0x33d05e38

initcall<- 0x33d05e38 (0)

initcall-> 0x33d05de8

initcall<- 0x33d05de8 (0)

initcall-> 0x33d071ec

initcall<- 0x33d071ec (0)

initcall-> 0x33d07be8

initcall<- 0x33d07be8 (0)

initcall-> 0x33d0d4d0

initcall<- 0x33d0d4d0 (0)

initcall-> 0x33d0f18c

initcall<- 0x33d0f18c (0)

initcall-> 0x33d1099c

initcall<- 0x33d1099c (0)

initcall-> 0x33d11a88

initcall<- 0x33d11a88 (0)

initcall-> 0x33d125e0

initcall<- 0x33d125e0 (0)

initcall-> 0x33d12618

initcall<- 0x33d12618 (0)

initcall-> 0x33d1e484

NAND device: Manufacturer ID: 0xec, Chip ID: 0xda (Samsung NAND 256MiB 3,3V 8-bit)

Bad block table found at page 131008, version 0x01

Bad block table found at page 130944, version 0x01

nand_read_bbt: Bad block at 0x01b20000

nand_read_bbt: Bad block at 0x02340000

nand_read_bbt: Bad block at 0x08820000

nand_read_bbt: Bad block at 0x09a00000

nand_read_bbt: Bad block at 0x0a6e0000

nand_read_bbt: Bad block at 0x0c840000

dm9000@dm90000: Found DM9000E at i/o: 0x20000300

s3c_mci@mci0: registered as mci0

initcall<- 0x33d1e484 (0)

initcall-> 0x33d04930

initcall<- 0x33d04930 (0)

initcall-> 0x33d1ea80

refclk:    12000 kHz

mpll:     405000 kHz

upll:      48000 kHz

fclk:     405000 kHz

hclk:     101250 kHz

pclk:      50625 kHz

SDRAM1:   CL3@101MHz

SDRAM2:   CL3@101MHz

initcall<- 0x33d1ea80 (0)

initcall-> 0x33d1f7c0

initcall<- 0x33d1f7c0 (0)

完成了初始化函数

initcalls done

barebox code: 0x33d00000 -> 0x33d285d0

bss segment:  0x33d2a4d8 -> 0x33d2e89c

Malloc space: 0x33900000 -> 0x33cfffff (size  4 MB)

Stack space : 0x338f8000 -> 0x33900000 (size 32 kB)

err -74

envfs: wrong magic on /dev/env0

no valid environment found on /dev/env0. Using default environment

running /env/bin/init...

 

Hit any key to stop autoboot:  1

tq2440:/

      接下去我们分析一下/env/bin/init即/dev/defaultenv/bin/init。打开barebox下的default/bin,找到init文件:

#!/bin/sh

 

PATH=/env/bin

export PATH

包含config文件

./env/config

判断/dev/nor0是否存在,存在就执行addpart命令,对nor0按照变量nor_parts的设定进行分区。

if[-e/dev/nor0 -a-n"$nor_parts"];then

    addpart /dev/nor0 $nor_parts

fi

 

if[-e/dev/disk0 -a-n"$disk_parts"];then

    addpart /dev/disk0 $disk_parts

fi

判断/dev/nand0是否存在,存在就执行对nand0按照变量nand_parts的设定进行分区,并执行source /env/bin/hush_hack

if[-e/dev/nand0 -a-n"$nand_parts"];then

    addpart /dev/nand0 $nand_parts

 

    # Uh, oh, hush first expands wildcards and then starts executing

    # commands. What a bug!

    source /env/bin/hush_hack

fi

如果/env/bin/init_board存在,就执行它。

if[-f/env/bin/init_board ];then

    ./env/bin/init_board

fi

 

echo

执行shell timeout,如果timeout不到0的话,就执行update -h,见下面对update文件的分析。如果timeout到0的话,就执行boot

echo -n "Hit any key to stop autoboot: "

timeout -a $autoboot_timeout

if[$?!=0];then

    exit

fi

 

boot

/env/config是barebox下arch/arm/board/{myboard}/env/config的一个复制:

#!/bin/sh

 

machine=FIXME

#user=

 

# Enter MAC address here if not retrieved automatically

#eth0.ethaddr=de:ad:be:ef:00:00

 

# use 'dhcp' to do dhcp in barebox and in kernel

# use 'none' if you want to skip kernel ip autoconfiguration

ip=dhcp

dhcp_vendor_id=barebox

 

# or set your networking parameters here

#eth0.ipaddr=a.b.c.d

#eth0.netmask=a.b.c.d

#eth0.serverip=a.b.c.d

#eth0.gateway=a.b.c.d

 

# can be either 'tftp', 'nfs', 'nand', 'nor' or 'disk'

kernel_loc=tftp

# can be either 'net', 'nand', 'nor', 'disk' or 'initrd'

rootfs_loc=net

 

# for flash based rootfs: 'jffs2' or 'ubifs'

# in case of disk any regular filesystem like 'ext2', 'ext3', 'reiserfs'

rootfs_type=ubifs

# where is the rootfs in case of 'rootfs_loc=disk' (linux name)

rootfs_part_linux_dev=mmcblk0p4

rootfsimage=rootfs-${machine}.$rootfs_type

 

# where is the kernel image in case of 'kernel_loc=disk'

kernel_part=disk0.2

 

kernelimage=zImage-$machine

#kernelimage=uImage-$machine

#kernelimage=Image-$machine

#kernelimage=Image-$machine.lzo

 

bareboximage=barebox-${machine}.bin

bareboxenvimage=barebox-${machine}.bin

 

if[-n$user];then

    bareboximage="$user"-"$bareboximage"

    bareboxenvimage="$user"-"$bareboxenvimage"

    kernelimage="$user"-"$kernelimage"

    rootfsimage="$user"-"$rootfsimage"

    nfsroot="/home/$user/nfsroot/$machine"

else

    nfsroot="/path/to/nfs/root"

fi

 

autoboot_timeout=3

 

bootargs="console=ttyFIXME,115200"

 

nor_parts="256k(barebox)ro,128k(bareboxenv),3M(kernel),-(root)"

rootfs_mtdblock_nor=3

 

nand_parts="256k(barebox)ro,128k(bareboxenv),3M(kernel),-(root)"

nand_device="FIXME"

rootfs_mtdblock_nand=7

 

# set a fancy prompt (if support is compiled in)

PS1="\e[1;32mbarebox@\e[1;31m\h:\w\e[0m "

 

 

boot文件建立起bootargs,然后boot系统:

#!/bin/sh

 

./env/config

 

if[ x$kernel_loc= xnet ];then

    kernel_loc=tftp

fi

 

whilegetopt"hk:r:i:m:" Option

do

if[${Option}= k ];then

    kernel_loc=${OPTARG}

elif[${Option}= r ];then

    rootfs_loc=${OPTARG}

elif[${Option}= i ];then

    ip=${OPTARG}

elif[${Option}= m ];then

    mode=${OPTARG}

else

    ./env/bin/_boot_help

    exit0

fi

done

 

if[ x$mode= xnand ];then

    rootfs_loc=nand

    kernel_loc=nand

elif[ x$mode= xnor ];then

    rootfs_loc=nor

    kernel_loc=nor

elif[ x$mode= xnfs ];then

    rootfs_loc=net

    kernel_loc=nfs

elif[ x$mode= xtftp ];then

    rootfs_loc=net

    kernel_loc=tftp

elif[ x$mode= xdisk ];then

    rootfs_loc=disk

    kernel_loc=disk

fi

 

if[ x$ip= xdhcp -o x$ip="xdhcp-barebox"];then

    if[ x$kernel_loc= xnfs -o x$kernel_loc= xtftp ];then

       dhcp

       if[ x$rootpath!= x ];then

           nfsroot=$rootpath

       fi

       if[ x$bootfile!= x ];then

           kernelimage=$bootfile

       fi

    fi

fi

 

if[ x$ip= xdhcp -o];then

    bootargs="$bootargs ip=dhcp"

elif[ x$ip= xnone ];then

    bootargs="$bootargs ip=none"

else

    bootargs="$bootargs ip=$eth0.ipaddr:$eth0.serverip:$eth0.gateway:$eth0.netmask::eth0:"

fi

 

 

if[ x$rootfs_loc= xnet ];then

    bootargs="$bootargs root=/dev/nfs nfsroot=$nfsroot,v3,tcp noinitrd"

elif[ x$rootfs_loc= xdisk ];then

    bootargs="$bootargs root=/dev/$rootfs_part_linux_dev rootfstype=$rootfs_type noinitrd rootwait"

elif[ x$rootfs_loc= xinitrd ];then

    bootargs="$bootargs root=/dev/ram0 rdinit=/sbin/init"

else

    if[ x$rootfs_loc= xnand ];then

       rootfs_mtdblock=$rootfs_mtdblock_nand

    else

       rootfs_mtdblock=$rootfs_mtdblock_nor

    fi

 

    if[ x$rootfs_type= xubifs ];then

       if[-z$ubiroot];then

           ubiroot="root"

       fi

        bootargs="$bootargs root=ubi0:$ubiroot ubi.mtd=$rootfs_mtdblock"

    else

       bootargs="$bootargs root=/dev/mtdblock$rootfs_mtdblock"

    fi

 

    bootargs="$bootargs rootfstype=$rootfs_type noinitrd"

fi

 

if[-n$nor_parts];then

    mtdparts="${mtdparts}physmap-flash.0:${nor_parts}"

fi

 

if[-n$nand_parts];then

    if[-n${mtdparts}];then

       mtdparts="${mtdparts};"

    fi

    mtdparts="${mtdparts}${nand_device}:${nand_parts}"

fi

 

if[-n$mtdparts];then

    bootargs="${bootargs} mtdparts=${mtdparts}"

fi

 

if[ x$kernel_loc= xnfs -o x$kernel_loc= xtftp ];then

    kdev=/image

    $kernel_loc$kernelimage$kdev||exit1

elif[ x$kernel_loc= xnor ];then

    kdev="/dev/nor0.kernel"

elif[ x$kernel_loc= xnand ];then

    kdev="/dev/nand0.kernel.bb"

elif[ x$kernel_loc= xdisk ];then

    kdev="/dev/$kernel_part"

else

    echo"error: set kernel_loc to one of 'tftp', 'nfs', 'nand', 'nor' or 'disk'"

    exit1

fi

 

echo"booting kernel from $kdev"

 

bootm $bootm_opt$kdev

 

 

 

Barebox中命令的声明方式

BAREBOX_CMD_START(addpart)

    .cmd = do_addpart,

    .usage ="adds a partition table to adevice",

    BAREBOX_CMD_HELP(cmd_addpart_help)

BAREBOX_CMD_END

我们以addpart命令为例,在commands/partions.c文件中有上面几行,是对命令的声明。

#define Struct_Section  __attribute__((unused,section (".barebox_cmd")))

 

#define BAREBOX_CMD_START(_name)                        \

extern const struct command __barebox_cmd_##_name;                 \

const struct command __barebox_cmd_##_name                     \

    __attribute__ ((unused,section(".barebox_cmd_" __stringify(_name)))) = { \

    .name      = #_name,

 

#define BAREBOX_CMD_END                \

};

#define BAREBOX_CMD_HELP(text)   .help= text,

 

BAREBOX_CMD_HELP_START(addpart)

BAREBOX_CMD_HELP_USAGE("addpart <device><part_desc>\n")

BAREBOX_CMD_HELP_SHORT("Add a partition description to adevice.\n")

BAREBOX_CMD_HELP_OPT ("-n", "no prefix. Do not prepend the device name asprefix before the partition name\n")

BAREBOX_CMD_HELP_OPT ("<device>",   "device being worked on\n")

BAREBOX_CMD_HELP_OPT ("<part_desc>", "size1[@offset1](name1)[ro],size2[@offset2](name2)[ro],...\n")

BAREBOX_CMD_HELP_END

上面是对声明了一个字符串cmd_addpart_help

将上面的宏展开

extern const struct command __barebox_cmd_addpart;                 \

const struct command __barebox_cmd_addpart                     \

    __attribute__ ((unused,section(".barebox_cmd_addpart”)) = {   \

    .name      = addpart,

    .cmd = do_addpart,

    .usage ="adds a partition table to adevice",

  .help = cmd_addpart_help,

};

  命令的段属性是.barebox_cmd_addpart

  在lds文件中就有

__barebox_cmd_start = .;

  .barebox_cmd : { BAREBOX_CMDS }

  __barebox_cmd_end= .;

  里面将有关命令的部分都放在了一个地方,用__barebox_cmd_start表示开始,__barebox_cmd_end标记结束。

 

小结:

  现在对后面一部分进行总结,barebox执行完初始化函数后,接着去执行一些环境变量设置,其设置是:

 

 

 

/dev/defaultenv

  à/env/bin/init

     à. /env/config

     àaddpart /dev/nand0 $nand_parts

     àsource /env/bin/hush_hack

     àtimeout -a $autoboot_timeout

     àboot

     环境变量的设置,环境变量是在/env/config中设置的。

Nand的分区设置

nand_parts="256k(barebox)ro,128k(bareboxenv),3M(kernel),-(root)"

  以上是一部分设置,后面的目标是能够加载内核,能够挂载文件系统。


原创粉丝点击