一uboot
1。uboot增加自己的命令
原理:
每个命令都有一个命令结构体
struct cmd_tbl_s {
char*name; /* Command Name*/
intmaxargs; /* maximum number of arguments*/
intrepeatable; /* autorepeat allowed?*/
int (*cmd)(struct cmd_tbl_s *, int, int, char *[]); /* Implementation function*/
char*usage;/* Usage message(short)*/
char*help;/* Help message(long)*/
};
去定义它。Cmd为要调用的命令函数!name为该命令名字符串。
在u-boot里面有这样的宏
#define Struct_Section __attribute__ ((unused,section (".u_boot_cmd")))
#define U_BOOT_CMD(name,maxargs,rep,cmd,usage,help) /
cmd_tbl_t __u_boot_cmd_##name Struct_Section = {#name, maxargs, rep, cmd, usage, help}
宏U_BOOT_CMD(name,maxargs,rep,cmd,usage,help)就是将
cmd_tbl_s{
name,
maxargs,
rep,
cmd,
usage,
help
}这样的一个命令结构体放入内存.u_boot_cmd这个区域,.u_boot_cmd这个域在board/smdk2410/u-boot.lds中定义!在U-boot中的shell中,根据用户输入的命令,就会在.u_boot_cmd这个内存区域中查找,当.u_boot_cmd中某一个cmd_tbl_s命令结构体的cmd_tbl_s.name和输入的命令字符串相符时,就调用该命令
结构体的cmd_tbl_s.cmd( ….)函数!
怎样添加命令函参数!
下面以添加USB下载命令为例!
a
在include/configs/smdk2410.h中的CONFIG_COMMDNDS中增加一项:
CFG_CMD_USBLOAD,
/***********************************************************
* Command definition
***********************************************************/
#define CONFIG_COMMANDS /
(CONFIG_CMD_DFL | /
CFG_CMD_CACHE | /
CFG_CMD_NET | /
CFG_CMD_ENV | /
CFG_CMD_FLASH | /
CFG_CMD_PING | /
CFG_CMD_NAND | /
/*CFG_CMD_EEPROM |*/ /
/*CFG_CMD_I2C |*/ /
/*CFG_CMD_USB |*/ /
CFG_CMD_REGINFO | /
CFG_CMD_DATE | /
CFG_CMD_USBLOAD |/
CFG_CMD_ELF)
b
在include/cmd_confdefs.h中加入命令标志位
#define CFG_CMD_USBLOAD0x00000055ULL (可以是其它值,不冲突就好)
c
在common/下面加入usbload.c
框架如下
#If(CONFIG_COMMANDS & CFG_CMD_USBLOAD)
Int usb_load(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[ ] )
{
………………….
}
U_BOOT_CMD{
Usbload,
2,
1,
usb_load,
“usb load img file”,
“This is a test”
};
#endif
d
在common/Makefile 添加要编译的目标文件
e
重新编译u-boot,就OK啦!
参考:http://www.cublog.cn/u/17660/showart.php?id=279308
2。uboot增加对gpio,mii phy寄存器的设置
二。文件系统
dhcpc和httpd在busybox的menuconfig中可以选择安装。但是,我们的busybox工具包是方案直接提供的,目前没有时间重头定制。因此选用了源代码交叉编译来得到。
1。busybox
下载busybox1.10.0
make menuconfig //选择需要安装的部件
make ARCH=mips CROSS_COMPILE=mips-linux- //交叉编译
make install
会出现一个_install目录,拷贝相应文件到文件系统中即可。
2。dhcpc
从busybox网站下载dhcpc包,http://udhcp.busybox.net/
交叉编译.拷贝至/sbin/
拷贝example下面的simple.script 至文件系统的/usr/share/udhcpc/,更改文件名字为default.script
如此系统启动的时候将自动运行dhcp来获取ip地址
3。boa。
1)下载Boa源码
下载地址: http://www.boa.org/, 或者http://sourceforge.net/:
boa-0.94.13.tar.gz,解压:# tar zxvf boa-0.94.13.tar.gz
2)生成Makefile文件
# cd boa-0.94.13
# src/configure
3)修改Makefile文件,编译
# cd boa-0.94.13/src
修改Makefile文件:修改 CC=gcc 为CC=/usr/local/arm/2.95.3/bin/arm-linux-gcc
修改 CPP=gcc -E为CPP=/usr/local/arm/2.95.3/bin/arm-linux-gcc –E
make
在编译时有可能会提示查不到“yacc”等等的软件,. 请安装bison(yacc的GNU版本)和flex
# mips-linux-strip boa
4)boa的配置
进入制作的根文件夹
# mkdir /etc/boa
# cp / boa-0.94.13/boa.conf /etc/boa/
修改boa.conf:
1、 Group的修改:修改 Group nogroup 为Group 0
由于在/etc/group文件中没有nogroup组,所以设成0。另外在/etc/passwd中有nobody用户,所以User nobody不用修改。
2、scriptAlias的修改:修改 scriptAlias /cgi-bin/ /usr/lib/cgi-bin/
为 scriptAlias /cgi-bin/ /var/www/cgi-bin/
3、ServerName的设置:修改 #ServerName http://www.your.org.here/
为 ServerName http://www.your.org.here/
注意:该项默认为未打开,执行Boa会异常退出,提示“gethostbyname::No such file or directory”,所以必须打开。其它默认设置即可。
5)boa的执行
进入制作的根文件夹
# mkdir /var/log
# mkdir /var/log/boa(创建日志文件目录)
# mkdir /var/www (创建HTML文档的主目录)
可以将主机 /usr/share/doc/HTML/目录下的index.html文件和img目录复制到/var/www目录下,将主机/etc目录下的mime.types文件放置到制作的根文件夹的/etc下
最后将boa-0.94.13下的boa可执行文件拷贝到bin下面。
参考:http://www.linuxidc.com/Linux/2007-09/7697.htm
4.thttpd
从http://www.acme.com/software/thttpd/ 下载thttpd
./configure
vi Makefile
CC= mips-linux-gcc
make ARCH=mips CROSS_COMPILE=mips-linux-
配置
拷贝thttpd二进制可执行文件到根文件系统/root/目录中
修改thttpd配置文件
vi thttpd.conf
# This section overrides defaults
dir=/www #指明WebServer存放网页的根目录路径
chroot
user=root #以root身份运行thttpd
logfile=/var/log/thttpd.log #日志文件路径
pidfile=/var/run/thttpd.pid #pid文件路径
port=8080
拷贝thttpd.conf配置文件到根文件系统的/etc/目录,
执行:/root/thttpd -C /et/thttpd.conf
参考: http://blog.csdn.net/zhulingchen/archive/2007/02/02/1501134.aspx
5.busybox自带的httpd
使用了busybox自带的httpd之后,boa以及thttpd都被我扫进了历史的垃圾堆
参考:http://pank.org/blog/2003/08/busybox-10-httpd.html
基本用法: httpd -h /documentroot -c /etc/httpd.conf
一句话,搭建httpd太方便了
如果网页需要认证,在/etc/httpd.conf里加入:
/:admin:adminpass
三 busybox
1。向 BusyBox 中添加新命令
向 BusyBox 添加一个新命令非常简单,这是因为它具有良好定义的体系结构。第一个步骤是为新命令的源代码选择一个位置。我们要根据命令的类型(网络,shell 等)来选择位置,并与其他命令保持一致。这一点非常重要,因为这个新命令最终会在 menuconfig 的配置菜单中出现(在下面的例子中,是 Miscellaneous Utilities 菜单)。
对于这个例子来说,我将这个新命令称为 newcmd,并将它放到了 ./miscutils 目录中。这个新命令的源代码如清单 13 所示。
清单 1. 集成到 BusyBox 中的新命令的源代码
#include "busybox.h" int newcmd_main( int argc, char *argv[] ) { int i; printf("newcmd called:/n"); for (i = 0 ; i < argc ; i++) { printf("arg[%d] = %s/n", i, argv[i]); } return 0; } |
接下来,我们要将这个新命令的源代码添加到所选子目录中的 Makefile.in 中。在本例中,我更新了 ./miscutils/Makefile.in 文件。请按照字母顺序来添加新命令,以便维持与现有命令的一致性:
清单 2. 将命令添加到 Makefile.in 中
MISCUTILS-$(CONFIG_MT) += mt.o MISCUTILS-$(CONFIG_NEWCMD) += newcmd.o MISCUTILS-$(CONFIG_RUNLEVEL) += runlevel.o |
接下来再次更新 ./miscutils 目录中的配置文件,以便让新命令在配置过程中是可见的。这个文件名为 Config.in,新命令是按照字母顺序添加的:
清单 3. 将命令添加到 Config.in 中
config CONFIG_NEWCMD bool "newcmd" default n help newcmd is a new test command |
这个结构定义了一个新配置项(通过 config 关键字)以及一个配置选项(CONFIG_NEWCMD)。新命令可以启用,也可以禁用,因此我们对配置的菜单属性使用了 bool (Boolean)值。这个命令默认是禁用的(n 表示 No),我们可以最后放上一个简短的 Help 描述。在源代码树的 ./scripts/config/Kconfig-language.txt 文件中,我们可以看到配置语法的完整文法。
接下来需要更新 ./include/applets.h 文件,使其包含这个新命令。将下面这行内容添加到这个文件中,记住要按照字母顺序。维护这个次序非常重要,否则我们的命令就会找不到。
清单 4. 将命令添加到 applets.h 中
USE_NEWCMD(APPLET(newcmd, newcmd_main, _BB_DIR_USER_BIN, _BB_SUID_NEVER)) |
这定义了命令名(newcmd),它在 Busybox 源代码中的函数名(newcmd_main),应该在哪里会为这个新命令创建链接(在这种情况中,它在 /usr/bin 目录中),最后这个命令是否有权设置用户 id(在本例中是 no)。
倒数第二个步骤是向 ./include/usage.h 文件中添加详细的帮助信息。正如您可以从这个文件的例子中看到的一样,使用信息可能非常详细。在本例中,我只添加了一点信息,这样就可以编译这个新命令了:
清单 5. 向 usage.h 添加帮助信息
#define newcmd_trivial_usage "None" #define newcmd_full_usage "None" |
最后一个步骤是启用新命令(通过 make menuconfig,然后在 Miscellaneous Utilities 菜单中启用这个选项)然后使用 make 来编译 BusyBox。
使用新的 BusyBox,我们可以对这个新命令进行测试,如清单 18 所示。
清单 6. 测试新命令
$ ./busybox newcmd arg1 newcmd called: arg[0] = newcmd arg[1] = arg1 $ ./busybox newcmd --help BusyBox v1.1.1 (2006.04.12-13:47+0000) multi-call binary Usage: newcmd None None |
就是这样!BusyBox 开发人员开发了一个优秀但非常容易扩展的工具。
参考:http://www.xxlinux.com/linux/article/development/embed/20060918/4364.html
2。完善文件系统
参考一个正常的Linux系统就会发现,busybox建立的文件系统还缺少很多文件。下面三行命令建立了常见UNIX系统中包含的一些目录,虽然它们不全是必需的,但建立它们更符合标准一些。这些命令都是在新文件系统的根目录中执行的,第三条命令的执行还必须要有root权限。mkdir mnt root var tmp proc boot etc lib
mkdir /var/{lock,log,mail,run,spool}
chown 0:0R *如果busybox采用了动态链接的方式编译,还需要把busybox所需要的动态库:libcrypt.so.1、libc.so.6、ldlinux.so.2放到lib目录中。最好按照标准的方式建立相应的文件和链接,可以参考下面的列表:-rwxrwxrwx 192519ld-2.3.2.so
lrwxrwxrwx 111ld-linux.so.2 -> ld-2.3.2.so
-rwxrwxrwx 1 1190032libc-2.3.2.so
lrwxrwxrwx 113libc.so.6 -> libc-2.3.2.so
-rwxr-xr-x 118348libcrypt-2.3.2.so
lrwxrwxrwx 117libcrypt.so.1 -> libcrypt-2.3.2.so3.2编写 etc文件夹下的文件
etc文件夹是许多系统配置文件保存的地方。这些文件非常重要,如果配置错误,就可能影响系统的启动。busybox源代码example/bootfloopy/etc目录中的文件算是一个简单的例子,可以把其中的文件拷贝过来作为基础。(在example/bootfloopy目录中的一些脚本和文档也很值得阅读)
首先inittab文件是系统启动后所访问的第一个脚本文件,后续启动的文件都由它指定。这个文件的格式和普通微机Linux上的inittab是有区别的,其具体含义可以参考busybox的文档。下面是一个比较简单的例子:::sysinit:/etc/init.d/rcS
tty0::respawn:/sbin/getty 38400 tty0
tty2::askfirst:/bin/sh
::ctrlaltdel:/sbin/reboot
::shutdown:/bin/umount ar
::shutdown:/bin/mount / o remount,ro其中第一行指定了系统的启动脚本为/etc/init.d/rcS;第二行指定在第一个虚拟终端打开一个登录会话;第三行指定在第三个虚拟终端打开一个无须登录验证的shell;第四行指定了当按下ctrl+alt+del组合键时的执行命令;最后两行指定了关机时执行的操作。
fstab文件定义了文件系统的各个“挂接点”,需要与实际的系统相配合。一个简单的fstab文件如下:proc/procprocdefaults00
/dev/hda1/ext2rw,noauto01
devpts/dev/ptsdevptsdefaults00其中第三行是为UNIX PTYs准备的,telnetd要用到。
profile文件是终端登录之后首先运行的脚本,这里可以不去管它。我们比较关心的是系统在无人登录的情况下有哪些程序要执行。从inittab文件可以看出系统启动之后要运行/etc/init.d/rcS脚本,需要启动的程序和需要进行的设置都可以写在这里面。一个可能的rcS文件如下:#! /bin/sh
echo e 'Starting System'
ifconfig lo 127.0.0.1
ifconfig eth0 192.168.0.100
hostname F /etc/hostname
/bin/mount / o remount,rw
/bin/mount /proc
/bin/mount /dev/pts
/usr/sbin/telnetd
dmesg > /var/log/dmesg为了满足终端登录用户验证的要求,etc目录下还需要有passwd、group和shadow (在编译busybox时如果不选择shadow功能将不需要这个文件)。这些文件至少要包含 root用户的定义,如下所示:passwd:
root:x:0:0:root:/root:/bin/sh
group:
root:x:0:
shadow:
root::12179:0:99999:7:::其中,如果shadow (对于不支持shadow的系统则是passwd )文件的第一个冒号和第二个冒号之间没有内容,表示这个用户登录不需要密码。如果需要设定密码或者增加新的登录用户,就可以参考开发主机上的相应文件,或者在目标系统启动之后用passwd命令和adduser命令完成。
最后还可以给目标机起一个名字,在/etc目录下建立文件hostname,将起好的名字写到里面。前面介绍的启动脚本rcS,通过hostname命令把文件的内容设置为机器名。
文件系统的安装随着应用环境的不同差别比较大。在嵌入式环境中,一般只要通过特殊的打包工具将文件系统打包,并烧录到非易失性存储器中就可以了。例如,对于JFFS2类型的文件系统就可以用mkfs.jffs2命令生成文件系统的映像。
文件系统安装之后重新启动目标设备,应该就可以使用新建立的文件系统了。如果系统启动失败,则可以通过内核消息查找错误的原因。如果错误信息提示不能正确挂载文件系统,问题可能出在启动引导装载程序(bootloader)上。文件系统比较容易出问题的是用户的验证和动态链接库的加载。最简单的检测办法是把busybox编译为静态链接并设置内核参数init=/bin/sh来躲开对用户登录的验证。
3。linux的启动
Linux有自己一套完整的启动体系,抓住了linux启动的脉络,linux的启动过程将不再神秘。我们可以按需要来手动添加和删除我们需要的应用服务。
本文中假设inittab中设置的init tree为:
/etc/rc.d/rc0.d
/etc/rc.d/rc1.d
/etc/rc.d/rc2.d
/etc/rc.d/rc3.d
/etc/rc.d/rc4.d
/etc/rc.d/rc5.d
/etc/rc.d/rc6.d
/etc/rc.d/init.d
1). 关于linux的启动
init是所有进程之父
init读取/etc/inittab,执行rc.sysinit脚本
(注意文件名是不一定的,有些unix甚至会将语句直接写在inittab中)
rc.sysinit脚本作了很多工作:
init $PATH
config network
start swap function
set hostname
check root file system, repair if needed
check root space
....
rc.sysinit根据inittab执行rc?.d脚本
linux是多用户系统,getty是多用户与单用户的分水岭
在getty之前运行的是系统脚本
2). 关于rc.d
所有启动脚本放置在 /etc/rc.d/init.d下
rc?.d中放置的是init.d中脚本的链接,命名格式是:
S{number}{name}
K{number}{name}
S开始的文件向脚本传递start参数
K开始的文件向脚本传递stop参数
number决定执行的顺序
3). 启动脚本示例
这是一个用来启动httpd的 /etc/rc.d/init.d/apache 脚本:
CODE: #!/bin/bash source /etc/sysconfig/rc source $rc_functions case "$1" in start) echo "Starting Apache daemon..." /usr/local/apache2/bin/apachectl -k start evaluate_retval ;; stop) echo "Stopping Apache daemon..." /usr/local/apache2/bin/apachectl -k stop evaluate_retval ;; restart) echo "Restarting Apache daemon..." /usr/local/apache2/bin/apachectl -k restart evaluate_retval ;; status) statusproc /usr/local/apache2/bin/httpd ;; *) echo "Usage: $0 {start|stop|restart|status}" exit 1 ;; esac [Copy to clipboard] |
然后可以这样建立rc?.d的链接:
CODE: cd /etc/rc.d/init.d && ln -sf ../init.d/apache ../rc0.d/K28apache && ln -sf ../init.d/apache ../rc1.d/K28apache && ln -sf ../init.d/apache ../rc2.d/K28apache && ln -sf ../init.d/apache ../rc3.d/S32apache && ln -sf ../init.d/apache ../rc4.d/S32apache && ln -sf ../init.d/apache ../rc5.d/S32apache && ln -sf ../init.d/apache ../rc6.d/K28apache [Copy to clipboard] |
经常使用的 rc.local 则完全是习惯问题,不是标准。
各个发行版有不同的实现方法,可以这样实现:
CODE: touch /etc/rc.d/rc.local chmod +x /etc/rc.d/rc.local ln -sf /etc/rc.d/rc.local /etc/rc.d/rc1.d/S999rc.local && ln -sf /etc/rc.d/rc.local /etc/rc.d/rc2.d/S999rc.local && ln -sf /etc/rc.d/rc.local /etc/rc.d/rc3.d/S999rc.local && ln -sf /etc/rc.d/rc.local /etc/rc.d/rc4.d/S999rc.local && ln -sf /etc/rc.d/rc.local /etc/rc.d/rc5.d/S999rc.local && ln -sf /etc/rc.d/rc.local /etc/rc.d/rc6.d/S999rc.local [Copy to clipboard] |
/etc/profile
/etc/bashrc
~/.bash_profile
~/.bashrc
是bash的启动脚本
一般用来设置单用户的启动环境,也可以实现开机单用户的程序,但要明确他们都是属于bash范畴而不是系统范畴。
他们的具体作用介绍如下:
/bin/bash这个命令解释程序(后面简称shell)使用了一系列启动文件来建立一个运行环境:
/etc/profile
/etc/bashrc
~/.bash_profile
~/.bashrc
~/.bash_logout
每一个文件都有特殊的功用并对登陆和交互环境有不同的影响。
/etc/profile 和 ~/.bash_profile 是在启动一个交互登陆shell的时候被调用。
/etc/bashrc 和 ~/.bashrc 是在一个交互的非登陆shell启动的时候被调用。
~/.bash_logout 在用户注销登陆的时候被读取
一个交互的登陆shell会在 /bin/login 成功登陆之后运行。一个交互的非登陆shell是通过命令行来运行的,如[prompt]$/bin/bash。一般一个非交互的shell出现在运行shell脚本的时候。之所以叫非交互的shell,是因为它不在命令行上等待输入而只是执行脚本程序。
6). 关于开机程序的自动启动
系统脚本可以放置在/etc/rc.d/init.d中并建立/etc/rc.d/rc?.d链接,也可以直接放置在/etc/rc.d/rc.local中。
init.d脚本包含完整的start,stop,status,reload等参数,是标准做法,推荐使用。
为特定用户使用的程序(如有的用户需要使用中文输入法而有的不需要)放置在~/中的bash启动脚本中。
参考:http://www.51cto.com/art/200707/52340.htm
四。利用BusyBox做一个简单的根文件系统
1、下载BusyBox源代码包 http://busybox.net/
2、找个地方解压缩包,例如tar -xjvf busybox-1.00.tar.bz2
3、进入busybox的文件夹,使用make menuconfig进入设置
4、在build options中有一些选项要注意
Build BusyBox as a static binary (no shared libs):如果选择了这个选项,那么BusyBox将被静态编译,也就是不需要动态链接库的支持就能运行,但是这样会使编译后文件的体积增大。
Do you want to build BusyBox with a Cross Compiler:如果你的busybox将要运行机器与编译主机的体系结构不同,比如s3c2410是ARM,与我们的X86主机芯片系统结构不一样,那么这个一定要选上,并且在 Cross Compiler prefix中写上交叉编译器的名字,比如ARM用arm-linux-
5、在Installation Options中 BusyBox installation prefix就是在编译完后运行make install 时,busybox将被安装的地址。
6、其它的选项按照默认选项就行,当然自己也可以看看有没有需要,把其它一些命令加入到编译选项中来
7、完成后保存,然后运行make
8、编译没有问题后运行make install这样编译好的busybox就会自动安装到BusyBox installation prefix中,一般是三个文件夹bin sbin usr和一个文件linuxrc。这样busybox的编译就完成了
9、准备一个空文件夹将BusyBox installation prefix中的东西拷过来,另外再建几个linux需要的文件夹
lib
dev
etc
home
proc
root
tmp
var
mnt
10、在etc文件夹下建一个目录init.d,并且在其中建立一个空文件rcS,在rcS中加上以下内容
#! /bin/sh
PATH=/sbin:/bin:/usr/sbin:/usr/bin
runlevel=S
prevlevel=N
umask 022
export PATH runlevel prevlevel
#
# Trap CTRL-C &c only in this shell so we can interrupt subprocesses.
#
trap ":" INT QUIT TSTP
/bin/mount -t proc none /proc
11、如果你的busybox是静态编译的,那么一个简单的能使用的根文件系统就这样完成了,但是这个文件系统中没有glibc的动态链接库,除了busybox以外的软件,如果对glibc有依赖,但是又没有静态编译的的话就无法运行。但如果所有的软件都用静态编译的话,那这个文件系统将很大。所以一般推荐软件不要使用静态编译,而使用一个库。
12、如果你不是用静态编译的,那么你需要编译好的glibc的动态链接库。在一般的交叉编译器中都带有已经编译好的库,直接拷过来就行了。
出现Warning: unable to open an initial console.提示,可以在rmadisk中建立
建立console和null试试,不一定非要去修改内核中的devfs去动态创建
cd /dev
mknod -m 660 console c 5 1
mknod -m 660 null c 1 3