barebox分析
来源:互联网 发布:淘宝上卖视频资料赚钱 编辑:程序博客网 时间:2024/06/05 03:04
barebox分析
启动分析
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)"
以上是一部分设置,后面的目标是能够加载内核,能够挂载文件系统。
- barebox分析
- barebox分析
- barebox简要分析
- barebox启动分析(一)
- BareBox 移植及系统自动更新(一)
- 让Barebox在Tiny6410上跑起来
- [树莓派内核学习]u-boot移植-barebox
- 让Barebox正确引导Tiny6410的linux内核
- 分析
- 分析
- 分析
- 分析
- 分析
- 分析
- 分析
- 分析
- 分析
- 大家帮忙分析分析!
- [Android]文本框实现搜索和清空效果
- Android实用开源项目
- 微软等面试100题系列--(41-60)
- 物联网最新资料大全
- spring的申明式事务处理
- barebox分析
- SMF 2.0.4 PHP Code Injection
- python中eval, exec, execfile,和compile [转载]
- python 学习笔记(7)类和迭代器
- javascript 不用一句if语句 对表单进行验证
- \r and \n
- openstack nova 基础知识——cfg
- 记录两个一问一答的在线编程题
- 语法练习(静态字段,文件读写)