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_lowlevel(CONFIG_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)"
以上是一部分设置,后面的目标是能够加载内核,能够挂载文件系统。