上篇讲到start_barebox在执行死循环的shell之前会调用environment,这次来分析一下这些env。
1 if (envfs_load("/dev/env0", "/env")) {
2 #ifdef CONFIG_DEFAULT_ENVIRONMENT
3 printf("no valid environment found on /dev/env0. "
4 "Using default environment\n");
5 envfs_load("/dev/defaultenv", "/env");
6 #endif
7 }
8 #endif
9 printf("running /env/bin/init...\n");
10
11 if (!stat("/env/bin/init", &s)) {
12 run_command("source /env/bin/init", 0);
13
首先程序去读取/dev/env0到/env,正常情况下/dev/env0放的是一个(类似)压缩文件,envfs_load会对它做校验。毫无疑问,初始启动时肯定是找不到这个文件的,所以接着读取/dev/defaultenv到/env (loader跑起来后执行saveenv就把/env的东西打包到/dev/env0去了)。然后执行/env/bin/init。
接下去我们分析一下/env/bin/init即/dev/defaultenv/bin/init。打开barebox下的default/bin,找到init文件:
1 #!/bin/sh
2
3 PATH=/env/bin
4 export PATH
5
6 . /env/config
7 if [ -e /dev/nor0 ]; then
8 addpart /dev/nor0 $nor_parts
9 fi
10
11 if [ -e /dev/disk0 ]; then
12 addpart /dev/disk0 $disk_parts
13 fi
14
15 if [ -e /dev/nand0 ]; then
16 addpart /dev/nand0 $nand_parts
17
18 # Uh, oh, hush first expands wildcards and then starts executing
19 # commands. What a bug!
20 source /env/bin/hush_hack
21 fi
22
23 if [ -f /env/bin/init_board ]; then
24 /env/bin/init_board
25 fi
26
27 echo
28 echo -n "Hit any key to stop autoboot: "
29 timeout -a $autoboot_timeout
30 if [ $? != 0 ]; then
31 echo
32 update -h
33 echo
34 exit
35 fi
36
37 boot
38
上面第6行. /env/config 相当于c语言中的include,是把/env/config文件包含进来,config文件的分析见下面。
上面第7行判断/dev/nor0是否存在,存在就执行第8行addpart命令,对nor0按照变量nor_parts的设定进行分区。addpart是一个barebox命令,可以在源代码里找到,以下barebox命令同。
上面第15行判断/dev/nand0是否存在,存在就执行16行对nand0按照变量nand_parts的设定进行分区,并执行source /env/bin/hush_hack (这里再加路径是否多余了?),hush_hack里就一句话" nand -a /dev/nand0.* ",其实是因为hush的一个bug不得不另外写一个文件(具体是否有这bug不明)。" nand -a /dev/nand0.* " 执行nand命令,为每个nand0的分区对应的创建一个bb(bad block aware)设备。
上面23行如果/env/bin/init_board存在,就执行它。现在是不存在,所以无视。
上面29行执行shell timeout,如果timeout不到0的话,就执行update -h,见下面对update文件的分析。如果timeout到0的话,就执行boot,见下面boot文件的分析。
/env/config是barebox下arch/arm/board/{myboard}/env/config的一个复制:
1 #!/bin/sh
2
3 machine=pcm038
4 eth0.serverip=
5 user=
6
7 # use 'dhcp' to do dhcp in barebox and in kernel
8 # use 'none' if you want to skip kernel ip autoconfiguration
9 ip=dhcp
10
11 # or set your networking parameters here
12 #eth0.ipaddr=a.b.c.d
13 #eth0.netmask=a.b.c.d
14 #eth0.gateway=a.b.c.d
15 #eth0.serverip=a.b.c.d
16
17 # can be either 'net', 'nor' or 'nand'
18 kernel_loc=net
19 # can be either 'net', 'nor', 'nand' or 'initrd'
20 rootfs_loc=net
21
22 # can be either 'jffs2' or 'ubifs'
23 rootfs_type=ubifs
24 rootfsimage=root-$machine.$rootfs_type
25
26 # The image type of the kernel. Can be uimage, zimage, raw, or raw_lzo
27 kernelimage_type=zimage
28 kernelimage=zImage-$machine
29 #kernelimage_type=uimage
30 #kernelimage=uImage-$machine
31 #kernelimage_type=raw
32 #kernelimage=Image-$machine
33 #kernelimage_type=raw_lzo
34 #kernelimage=Image-$machine.lzo
35
36 if [ -n $user ]; then
37 kernelimage="$user"-"$kernelimage"
38 nfsroot="$eth0.serverip:/home/$user/nfsroot/$machine"
39 rootfsimage="$user"-"$rootfsimage"
40 else
41 nfsroot="$eth0.serverip:/path/to/nfs/root"
42 fi
43
44 autoboot_timeout=3
45
46 bootargs="console=ttymxc0,115200"
47
48 nor_parts="256k(barebox)ro,128k(bareboxenv),2M(kernel),-(root)"
49 rootfs_mtdblock_nor=3
50
51 nand_parts="256k(barebox)ro,128k(bareboxenv),2M(kernel),-(root)"
52 rootfs_mtdblock_nand=7
53
54 # set a fancy prompt (if support is compiled in)
55 PS1="\e[1;32mbarebox@\e[1;31m\h:\w\e[0m "
56
57
这个文件定义了一堆变量,注意52行,如果没有nor_parts的话,那么rootfs_mtdblock_nand(在nand_parts的root,从0~3)就等于3了。大部分变量都为init文件和boot文件所用。
最后一句PS1可以在hush.c中的getprompt看到,具体就是跟hyperterminal配合把命令提示字符串barebox@<board_name>的barebox@改成了绿色,把board_name改成了红色。
update文件提供了组合了下载,擦除flash,烧写和检查等的一个update命令,如果输入的参数是h的话就调用(见init)就调用_update_help,打印update的用法,如果参数输入正确的话,调用_update文件进行实际的下载烧写动作(update文件主要是对参数做判断)。
boot文件建立起bootargs,然后boot系统:
1 #!/bin/sh
2
3 . /env/config
4
5 if [ x$1 = xnand ]; then
6 rootfs_loc=nand
7 kernel_loc=nand
8 elif [ x$1 = xnor ]; then
9 rootfs_loc=nor
10 kernel_loc=nor
11 elif [ x$1 = xnet ]; then
12 rootfs_loc=net
13 kernel_loc=net
14 fi
15
16 if [ x$ip = xdhcp ]; then
17 bootargs="$bootargs ip=dhcp"
18 elif [ x$ip = xnone ]; then
19 bootargs="$bootargs ip=none"
20 else
21 bootargs="$bootargs ip=$eth0.ipaddr::$eth0.gateway:$eth0.netmask:::"
22 fi
23
24
25 if [ x$rootfs_loc = xnet ]; then
26 bootargs="$bootargs root=/dev/nfs nfsroot=$nfsroot,v3,tcp noinitrd"
27 elif [ x$rootfs_loc = xinitrd ]; then
28 bootargs="$bootargs root=/dev/ram0 rdinit=/sbin/init"
29 else
30 if [ x$rootfs_loc = xnand ]; then
31 rootfs_mtdblock=$rootfs_mtdblock_nand
32 else
33 rootfs_mtdblock=$rootfs_mtdblock_nor
34 fi
35
36 if [ x$rootfs_type = xubifs ]; then
37 bootargs="$bootargs root=ubi0:root ubi.mtd=$rootfs_mtdblock"
38 else
39 bootargs="$bootargs root=/dev/mtdblock$rootfs_mtdblock"
40 fi
41
42 bootargs="$bootargs rootfstype=$rootfs_type noinitrd"
43 fi
44
45 if [ -n $nor_parts ]; then
46 mtdparts="${mtdparts}physmap-flash.0:${nor_parts};"
47 fi
48
49 if [ -n $nand_parts ]; then
50 mtdparts="${mtdparts}${nand_device}:${nand_parts};"
51 fi
52
53 if [ -n $mtdparts ]; then
54 bootargs="${bootargs} mtdparts=${mtdparts}"
55 fi
56
57 if [ ! -e /dev/ram0.kernelraw ]; then
58 # arm raw kernel images are usually located at sdram start + 0x8000
59 addpart dev/ram0 8M@0x8000(kernelraw)
60 fi
61
62 if [ ! -e /dev/ram0.kernel ]; then
63 # Here we can safely put the kernel without risking of overwriting it
64 # while extracting
65 addpart dev/ram0 8M@8M(kernel)
66 fi
67
68 if [ x$kernel_loc = xnet ]; then
69 if [ x$ip = xdhcp ]; then
70 dhcp
71 fi
72 if [ $kernelimage_type = uimage ]; then
73 netload="/dev/ram0.kernel"
74 elif [ $kernelimage_type = zimage ]; then
75 netload="/dev/ram0.kernel"
76 elif [ $kernelimage_type = raw ]; then
77 netload="/dev/ram0.kernelraw"
78 elif [ $kernelimage_type = raw_lzo ]; then
79 netload="/dev/ram0.kernel"
80 else
81 echo "error: set kernelimage_type to one of 'uimage', 'zimage', 'raw' or 'raw_lzo'"
82 exit 1
83 fi
84 tftp $kernelimage $netload || exit 1
85 kdev="$netload"
86 elif [ x$kernel_loc = xnor ]; then
87 kdev="/dev/nor0.kernel"
88 elif [ x$kernel_loc = xnand ]; then
89 kdev="/dev/nand0.kernel.bb"
90 else
91 echo "error: set kernel_loc to one of 'net', 'nand' or 'nor'"
92 exit 1
93 fi
94
95 echo "booting kernel of type $kernelimage_type from $kdev"
96
97 if [ x$kernelimage_type = xuimage ]; then
98 bootm $kdev
99 elif [ x$kernelimage_type = xzimage ]; then
100 bootz $kdev
101 elif [ x$kernelimage_type = xraw ]; then
102 if [ $kernel_loc != net ]; then
103 cp $kdev /dev/ram0.kernelraw
104 fi
105 bootu /dev/ram0.kernelraw
106 elif [ x$kernelimage_type = xraw_lzo ]; then
107 unlzo $kdev /dev/ram0.kernelraw
108 bootu /dev/ram0.kernelraw
109 fi
110
boot的执行有两种,一种是timeout后init里的调用,无输入参数,这时5~14行就没有意义,那些变量就采取config里的定义。一种是没到timeout就按键进入了barebox,这时可以对boot加上参数来改变那些变量。
上面16~55行重新设定了内核启动参数bootargs。
上面57~60行添加了Linux内核运行的分区kernelraw,大小为8M,位于/dev/ram0即SDRAM的0x8000偏移处。
上面62~66行添加了Linux解压缩的一个分区kernel,大小为8M,位于/dev/ram0即SDRAM的8MB=0x80 0000偏移处。(跟kernelraw重合了0x8000即32KB的空间,不过Linux内核肯定小于8M-32K,所以无所谓)
上面68~93行设定变量kdev,如果是从网络下载的话,首先执行dhcp,然后用tftp下载内核到kernel分区(如果内核未经压缩,那就直接下载到kernelraw),然后再把kdev设定为/dev/kernelraw或者/dev/kernel或者/dev/nor0.kernel或者/dev/nand0.kernel.bb。
上面97~109判断kernel类型,如果是压缩的就先解压,最后都是bootu /dev/ram0.kernalraw
附1:Env里用到的barebox命令:
1 addpart(do_addpart)
2 bootm(do_bootm)
3 bootu(do_bootu)
4 bootz(do_bootz)
5 cp(do_cp)
6 crc32(do_crc)
7 dhcp(do_dhcp)
8 echo(do_echo)
9 erase(do_flerase)
10 exit(do_exit)
11 export(do_export)
12 getopt(do_getopt)
13 loadb(do_load_serial_bin)
14 nand(do_nand)
15 ping(do_ping)
16 protect(do_protect)
17 source(do_source)
18 tftp(do_tftp)
19 timeout(do_timeout)
20 unprotect(do_protect)
21 unlzo(do_unlzo)