FL2440 Linux-3.0内核最小系统移植

来源:互联网 发布:java,string split方法 编辑:程序博客网 时间:2024/06/13 11:24

FL2440 Linux-3.0最小系统移植

该文档基于crosstool-ng这个交叉编译器制作,可以使用下面脚本和命令制作交叉编译器:

[wudongxu@localhost~l]$mkdir crosstool

[wudongxu@localhost ~]$cd crosstool

[wudongxu@localhost crosstool]$vim build.sh //编写制作交叉编译器的脚本,该脚本主要是从FTP服务器上下载文件并修改只制作arm920t的交叉编译器

#!/bin/bash 

# This shell script used to download crosstool-ng install binary and compile it for arm920t 

CROSSTOOL=crosstool-ng-centos-LingYun-v1.0.0.bin
if [ ! -f ${CROSSTOOL} ] ; then 

  wget ftp://master.iot-yun.com/linux_tools/${CROSSTOOL}

   sed -i -e "s|^sup_arch=.*|sup_arch=(\"\", \"arm920t\")|g" ${CROSSTOOL}
fi

chmod a+x ${CROSSTOOL}
./${CROSSTOOL}

[wudongxu@localhost crosstool]$sh build.sh   //开始制作交叉编译器,这个过程较长

[wudongxu@localhost crosstool]$/opt/xtools/arm920t/bin/arm-linux-gcc -v // 验证交叉编译器制作是否正确

Using built-in specs. 

Target: arm-arm920t-linux-gnueabi
Configured with: /home/guowenxue/crosstool-ng-1.16.0/.build/src/gcc-4.4.6/configure --build=x86_64-build_unknown-linux-gnu --host=x86_64- build_unknown-linux-gnu --target=arm-arm920t-linux-gnueabi --prefix=/opt/xtools/arm920t --with-sysroot=/opt/xtools/arm920t/arm-arm920t-linux- gnueabi/sysroot --enable-languages=c,c++ --with-arch=armv4t --with-cpu=arm9tdmi --with-tune=arm920t --with-float=soft --with- pkgversion='crosstool-NG 1.16.0' --enable-__cxa_atexit --disable-libmudflap --disable-libgomp --disable-libssp --with- gmp=/home/guowenxue/crosstool-ng-1.16.0/.build/arm-arm920t-linux-gnueabi/buildtools --with-mpfr=/home/guowenxue/crosstool-ng-1.16.0/.build/arm-arm920t-linux-gnueabi/buildtools --with-ppl=/home/guowenxue/crosstool-ng-1.16.0/.build/arm-arm920t-linux-gnueabi/buildtools
--with-cloog=/home/guowenxue/crosstool-ng-1.16.0/.build/arm-arm920t-linux-gnueabi/buildtools --with-host-libstdcxx='-static-libgcc -Wl,-Bstatic,-
lstdc++,-Bdynamic -lm' --enable-threads=posix --enable-target-optspace --disable-multilib --with-local-prefix=/opt/xtools/arm920t/arm-arm920tlinux-gnueabi/sysroot --enable-c99 --enable-long-long
Thread model: posix 

gcc version 4.4.6 (crosstool-NG 1.16.

一、 开发板简介

     FL2440开发板是飞凌公司使用三星的ARM9 S3C2440 CPU做的一个ARM Linux学习开发板,该CPU是使用armv4t指令集的ARM920T核,工作主频最高在400MHz。每个CPU厂商在研发并生产出CPU时并不是直接将该CPU推给客户让客户自己研究该CPU特性后再做硬件设计(因为客户不懂这些具体的CPU使用细节,而研发该CPU的公司会更懂它),而会先使用该CPU设计出母板(demo板,如SMDK2440),在母板上尽可能将该CPU的硬件使用信息展示给客户,客户再参考母板根据实际的功能、市场需求来高度定制自己的硬件,例如产品不需要显示则可以把母板中的LCD硬件部分去掉、CS8900网卡供货存在问题那就换成DM9000等等。
   相应的CPU厂商在开发出相应的硬件demo板后,也不是直接丢给客户来开发相应的软件,而是会安排软件研发人员针对母板硬件完成u-boot和Linux内核的开发,以支持相应硬件。因为我们的硬件是参考母板来定制开发的,所以我们的软件移植(u-boot和linux内核)也可以在相关源码里的母板代码上做针对硬件的修改来支持我们的产品。在FL2440开发板的移植过程中,我们将以SMDK2440为模版在它的基础上做些修改来支持我们相应的硬件。在开始移植之前,我们先创建FL2440整个项目的目录框架:

[wudongxu@localhost ~]$ mkdir fl2440
[wudongxu@localhost ~]$ cd fl2440
[wudongxu@localhost fl2440]$ mkdir -p {crosstool,bootloader,linux/{kernel,rootfs},driver,3rdparty,program,images}
[wudongxu@localhost fl2440]$ tree

|-- 3rdparty            ///今后移植到ARM开发板上的第三方应用程序软件包
|-- bootloader      //u-boot移植代码
|-- crosstool         ///交叉编译器
|-- driver               ///今后写的驱动文件
|-- images            ///编译出的image文件,如Linux内核,根文件系统等;
|-- linux
| |-- kernel            ///Linux内核源码路径
| `-- rootfs             ////根文件系统目录树路径
`-- program          ///我们今后自己写的应用程序
 


二、源码修改

Linux 是一个源码开放的操作系统,无论是普通用户还是企业用户都可以编写自己的内核代码,再加上对标准内核的裁剪从而制作出适合自己的操作系统。Linux操作系统有很多发行版本,如Redhat, CentOS, Ubuntu等等,但所有的这些Linux操作系统都是选择一个Linux内核稳定版本,外加不同的C基础库和应用程序构建的一个操作系统。嵌入式Linux系统开发其本质就是我们拿到源码并进行修改DIY(Do It Yourself)一个属于我们自己的操作系统,这个过程包括Booloader和Linux内核(裁剪)移植、驱动模块编写、根文件系统制作、第三方应用程序移植等,这个工作叫做BSP(Board Support Packet,板级支持包)开发,这里面需要相应的硬件协议、操作系统、以及C语言和数据结构等知识,难度较高。


Linux内核下载地址: https://www.kernel.org/pub/linux/kernel/v3.x/


[wudongxu@localhost ~]$ cd gitee/fl2440/linux/
[wudongxu@localhost linux]$ wget https://www.kernel.org/pub/linux/kernel/v3.x/linux-3.0.tar.bz2
[wudongxu@localhost linux]$ tar -xjf linux-3.0.tar.bz2

[wudongxu@localhost linux]$ cd linux-3.0
[wudongxu@localhost linux-3.0]$ ls 

arch  CREDITS    drivers  include   Kbuild    lib mm    REPORTING-BUGS   security usr    block crypto    firmware init   Kconfig      MAINTAINERS net samples sound virt
COPYING    Documentation fs ipc   kernel Makefile README scripts tools 


下图是Linux源码目录树的目录结构:


.



修改1:

SMDK2440上使用的是16MHz的晶振,而FL2440上使用的是12MHz的晶振,所以开发板相应代码要做修改:



linux-3.0/arch/arm/mach-s3c2440/下支持很多使用S3C2440 CPU做的开发板(大家可以使用ls命令看看具体有哪些开发板,今后驱动添加我们可以参考其他开发板如mini2440的信息),我们以mach-smdk2440.c为原型来进行修改:
[wudongxu@localhost linux-3.0]$ vim arch/arm/mach-s3c2440/mach-smdk2440.c

static void __init smdk2440_map_io(void)
{
    s3c24xx_init_io(smdk2440_iodesc, ARRAY_SIZE(smdk2440_iodesc));
-   s3c24xx_init_clocks(16934400);
+  s3c24xx_init_clocks(12000000);

    s3c24xx_init_uarts(smdk2440_uartcfgs, ARRAY_SIZE(smdk2440_uartcfgs));
}


修改2:

我们的u-boot给Linux内核传的machine ID值为1999,而Linux内核里smdk2440开发板对应的machine ID是362,所以我们要修改内核代码让smdk2440的machine ID与u-boot里的保持一致,这里我们在源码中将两个machine ID值互换:
[wudongxu@localhost linux-3.0]$ vim arch/arm/tools/mach-types 

-   s3c2440                   ARCH_S3C2440          S3C2440                      362
+   s3c2440                  ARCH_S3C2440          S3C2440                     1999
... ...
-   mini2440                 MACH_MINI2440           MINI2440                   1999
+   mini2440                MACH_MINI2440           MINI2440                   362


修改3:

samsung的串口驱动设备名字默认叫ttySAC,而我们一般使用ttyS,所以将源码中的设备名改掉:
[wudongxu@localhost linux-3.0]$ vim drivers/tty/serial/samsung.c 

 -  #define                      S3C24XX_SERIAL_NAME                "ttySAC"
+  #define                     S3C24XX_SERIAL_NAME                  "ttyS"
   //注意S要大写


修改4:

修改顶层Makefile的ARCH为arm, CROSS_COMPILE为我们自己相应的交叉编译器:
[wudongxu@localhost linux-3.0]$ vim Makefile

-ARCH ?= $(SUBARCH)
-CROSS_COMPILE ?= $(CONFIG_CROSS_COMPILE:"%"=%)
+ARCH ?= arm
+CROSS_COMPILE ?= /opt/xtools/arm920t/bin/arm-linux-    
 //这里改成大家自己的交叉编译器,注意arm-linux-后面应该紧跟回车,不能有其
他任何字符


修改5:
添加DM9000网卡设备支持,下图是FL2440底板上的DM9000网卡原理图,注意这里网卡INT使用EINT7管脚,CMD连ADDR2,CS#片选管脚连了NGCS4,以及数据位数为LDATA0~LDATA15(16位模式)。下面是修改Linux内核源码添加DM9000网卡设备支持的过程。


[wudongxu@localhost linux-3.0]$ vim arch/arm/mach-s3c2440/mach-smdk2440.c

static struct platform_device *smdk2440_devices[] __initdata = {
&s3c_device_wdt,
&s3c_device_i2c0,
&s3c_device_iis,
+ &s3c_device_dm9000,  /* 添加DM9000网卡的设备,告诉Linux内核现在有这个硬件连上来了 */
};


[wudongxu@localhost linux-3.0]$ vim arch/arm/plat-s3c24xx/devs.c //在该C文件中定义结构体变量 s3c_device_dm9000

... ... ...
EXPORT_SYMBOL(s3c_device_iis);
+#ifdef CONFIG_DM9000 /* DM9000 network device support add by guowenxue 2011.08.30*/
+#include <linux/dm9000.h>
+static struct resource s3c_dm9000_resource[] = {
+ [0] = {
+ .start = S3C2410_CS4 + 0x300,     // DM9000网卡的CS片选管脚连接的是CS4
+ .end = S3C2410_CS4 + 0x300 + 0x3,
+ .flags = IORESOURCE_MEM
+ },
+ [1]={
+ .start = S3C2410_CS4 + 0x300 + 0x4, //CMD pin is A2
+ .end = S3C2410_CS4 + 0x300 + 0x4 + 0x7c,
+ .flags = IORESOURCE_MEM
+ },
+ [2] = {
+ .start = IRQ_EINT7,    // DM9000网卡的中断管脚连的是 EINT7这个Pin
+ .end = IRQ_EINT7,
+ .flags = IORESOURCE_IRQ
+ },
+};
+
+static struct dm9000_plat_data s3c_device_dm9000_platdata = {
+ .flags= DM9000_PLATF_16BITONLY,     // DM9000网卡的使用LDATA0~15 16位模式
+};
+
+struct platform_device s3c_device_dm9000 = {
+ .name= "dm9000",
+ .id= 0,
+ .num_resources= ARRAY_SIZE(s3c_dm9000_resource),
+ .resource= s3c_dm9000_resource,
+ .dev= {
+ .platform_data = &s3c_device_dm9000_platdata,
+ }
+};

+#endif
+
/* RTC */
... ... ...

[wudongxu@localhost linux-3.0]$ vim arch/arm/plat-samsung/include/plat/devs.h    //在该头文件中导出s3c_device_dm9000的声明

extern struct platform_device s3c_device_hsmmc1;
extern struct platform_device s3c_device_hsmmc2;
extern struct platform_device s3c_device_hsmmc3;
extern struct platform_device s3c_device_cfcon;
+extern struct platform_device s3c_device_dm9000;    /* 声明devs.c中定义的结构体变量s3c_device_dm9000 */
extern struct platform_device s3c_device_spi0;

[wudongxu@localhost linux-3.0]$ vim drivers/net/dm9000.c //修改dm9000.c的驱动代码,添加中断的初始化

... ... ...
static int
dm9000_open(struct net_device *dev)
{
board_info_t *db = netdev_priv(dev);
- unsigned long irqflags = db->irq_res->flags & IRQF_TRIGGER_MASK;
+ unsigned long irqflags = (db->irq_res->flags|IRQ_TYPE_EDGE_RISING) & IRQF_TRIGGER_MASK;
+
+ irq_set_irq_type(dev->irq, IRQ_TYPE_EDGE_RISING);
if (netif_msg_ifup(db))
dev_dbg(db->dev, "enabling %s\n", dev->name);
... ... ...


三、内核配置和编译
[guowenxue@localhost linux-3.0]$ find -name *.c | wc -l
16198
[guowenxue@localhost linux-3.0]$ find -name *.S | wc -l
1223
Linux-3.0内核有16198个C文件和1223个汇编文件,就这一份源码支持了不同体系结构CPU, 并且包含了绝大部分硬件的驱动源码。那么根据不同的硬件设计和功能需求,定制化编译生成一个具有特定用途的嵌入式Linux系统image将是一场灾难,好在Linux的源码编译系统有一个非常巧妙的铁三角关系,导致这个过程显得没那么复杂。这个铁三角分别是Kconfig、.config和Makefile文件,他们三者之间的关系简单来说就是去饭店点菜:Kconfig是菜单,.config就是你点的菜,Makefile是做法。
Kconfig:一个文本形式的文件,存在内核源码中的每一个文件夹下,内核配置命令make menuconfig读取相应的Konfig文件生成菜单界面;
.config:隐藏文件存放在内核源码顶层目录中,make menuconfig命令配置的结果,里面的每个选项用来指导Makefile哪些C文件需要编译,哪
些不需要编译;
Makefile:一个文本形式的文件,存在内核源码中的每一个文件夹下,用来控制编译该目录下的源码编译;



[wudongxu@localhost linux-3.0]$ make s3c2410_defconfig
[wudongxu@localhost linux-3.0]$ export TERM=vt100

[wudongxu@localhost linux-3.0]$ make menuconfig

我们是使用S3C2440做的SMDK2440开发板,所有其他的开发板都不应该选择 System Type --->
S3C2400 Machines ---> 里面全部不选 S3C2410 Machines ---> 里面全部不选 S3C2412 Machines ---> 里面全部不选 S3C2416 Machines ---> 里面全部不选 S3C2440 and S3C2442 Machines --->
[*] SMDK2440
[*] SMDK2440 with S3C2440 CPU module
其它全部不选 S3C2443 Machines ---> 里面全部不选

... ...
我们的交叉编译器使用的是EABI接口,所以这里一定要修改配置,否则跑不起来。 Kernel Features --->
[*] Use the ARM EABI to compile the kernel
[*] Allow old ABI binaries to run with this kernel (EXPERIMENTAL) (NEW)
Device Drivers --->
[*] Network device support --->
[*] Ethernet (10 or 100Mbit) --->
<*> DM9000 support
(4) DM9000 maximum debug level
所有其他选项都不要选
[ ] Ethernet (1000 Mbit) ---> DM9000是100M网卡,1000M的网卡就不要选
[ ] Ethernet (10000 Mbit) ---> DM9000是100M网卡, 10000M的网卡都不要选

因为我们编译内核经常需要做下面几个命令,所以我们可以写个shell脚本完成这些相应命令。
[wudongxu@localhost linux-3.0]$ vim build.sh

#!/bin/bash
make
mkimage -A arm -O linux -T kernel -C none -a 30008000 -e 30008040 -n "Linux Kernel" -d arch/arm/boot/zImage linuxroms3c2440.bin
chmod a+x linuxrom-s3c2440.bin

Shell脚本解释说明:
make命令是编译Linux内核源码,编译完成后将生产arch/arm/boot/zImage内核启动文件。
zImage并不能被u-boot的bootm命令启动,而需要使用mkimage工具在其前面加上bootm命令启动内核所需要的64字节(0x40)头信息方可启动,处
理后的文件一般叫做uImage。
mkimage命令是由u-boot编译产生(u-boot-2010.09/tools/mkimage),在编译完成u-boot后我们需要将它以root权限拷贝到系统/bin路径下。
mkimage -A arm -O linux -T kernel -C none -a 30008000 -e 30008040 -n "Linux Kernel" -d arch/arm/boot/zImage linuxrom- s3c2440.bin
-A arm 指定ARCH为arm
-O linux 指定操作系统(OS)为Linux
-T kernel 指定类型(Type)为内核
-C none 指定压缩类型为未压缩,zImage里有自解压的代码;
-a 30008000 指定Image加载的地址, u-boot下使用tftp命令下载linux内核到内存的相应地址
-e 30008040 指定Linux内核的入口地址, uImage的地址在30008000,uImage是在zImage前面加了64字节(0x40)头,所以内核
zImage入口地址为30008040。
-n "Linux Kernel" 指定Image的名字
-d arch/arm/boot/zImage 指定zImage文件所在位置
linuxrom-s3c2440.bin 指定生成的uImage文件名
chmod a+x linuxrom-s3c2440.bin 将生成的uImage文件(linuxrom-s3c2440.bin)变成绿色显眼。
[wudongxu@localhost linux-3.0]$ chmod a+x build.sh
[wudongxu@localhost linux-3.0]$ ./build.sh


编译完成后将会生成linuxrom-s3c2440.bin,该文件即为u-boot里bootm命令能识别的uImage文件。u-boot中的bootm命令的实现代码片段如下:

[wudongxu@localhost u-boot-2010.09]$ vim arch/arm/lib/bootm.c
int do_bootm_linux(int flag, int argc, char * const argv[], bootm_headers_t *images) // images指向的地址就是 0x3000 8000
{
  bd_t *bd = gd->bd;

   char *s;   

  // Linux内核入口地址的函数原型为 void entry(int zero, int arch, uint params); 第一个参数为0,第二个参数为Machine ID,第三个参数为u-boot传给内核的参数参数

// 关于这三个参数的详细情况,请参考 linux-3.0/Documentation/arm/Booting
      int machid = bd->bi_arch_number; 

      void (*theKernel)(int zero, int arch, uint params); 

   #ifdef CONFIG_CMDLINE_TAG
   char *commandline = getenv ("bootargs"); 

   #endif
        if ((flag != 0) && (flag != BOOTM_STATE_OS_GO)) 

   return 1; 

     // 让thekernel函数指针指向内核的入口地址: 0x30008040,因为uImage是通过mkimage在zImage上加入了64字节的头后得到的image。所以Linux内核的入口地址应该是uImage地址偏移64字节(0x40)。

   theKernel = (void (*)(int, int, uint))images->ep;

   // 从环境变量machid中获取设置的Machine ID

  s = getenv ("machid"); 

  if (s) { machid = simple_strtoul (s, NULL, 16);

   printf ("Using machid 0x%x from environment\n", machid); 

}
... ... ... ... ... /* we assume that the kernel is in place */
    printf ("\nStarting kernel ...\n\n"); 

 #ifdef CONFIG_USB_DEVICE
{ extern void udc_disconnect (void); udc_disconnect (); 

}

 #endif cleanup_before_linux (); // 调用Linux内核的入口函数,启动Linux内核
theKernel (0, machid, bd->bi_boot_params); /* does not return */
return 1; 

}

四、u-boot启动Linux内核及bug修复
在Linux内核还是调试阶段时,我们没必要每次将Linux内核下载到Nandflash上,而只需要在u-boot下使用tftp命令把Linux内核下载到0x30008000地址上后,直接使用bootm命令启动即可。等内核调试稳定后,我们在将它写入到Nandflash上上电直接启动。
[fl2440@lingyun]# tftp 30008000 linuxrom-s3c2440.bin; bootm 30008000

s3c2440-uart.0: ttyS0 at MMIO 0x50000000 (irq = 70) is a S3C2440
------------[ cut here ]------------
WARNING: at fs/sysfs/dir.c:455 sysfs_add_one+0x84/0xac()
sysfs: cannot create duplicate filename '/class/tty/ttyS0'
Modules linked in:
[<c003a078>] (unwind_backtrace+0x0/0xf4) from [<c0048b20>] (warn_slowpath_common+0x48/0x60)
[<c0048b20>] (warn_slowpath_common+0x48/0x60) from [<c0048bcc>] (warn_slowpath_fmt+0x30/0x40)
[<c0048bcc>] (warn_slowpath_fmt+0x30/0x40) from [<c00f596c>] (sysfs_add_one+0x84/0xac)
[<c00f596c>] (sysfs_add_one+0x84/0xac) from [<c00f6a40>] (sysfs_do_create_link+0x114/0x204)
[<c00f6a40>] (sysfs_do_create_link+0x114/0x204) from [<c01d17f8>] (device_add+0x32c/0x590)
[<c01d17f8>] (device_add+0x32c/0x590) from [<c01d1b00>] (device_create_vargs+0x8c/0xb0)
[<c01d1b00>] (device_create_vargs+0x8c/0xb0) from [<c01d1b44>] (device_create+0x20/0x28)
[<c01d1b44>] (device_create+0x20/0x28) from [<c01a7a9c>] (tty_register_device+0x6c/0xe0)
[<c01a7a9c>] (tty_register_device+0x6c/0xe0) from [<c01bfb24>] (uart_add_one_port+0x128/0x36c)
[<c01bfb24>] (uart_add_one_port+0x128/0x36c) from [<c01c6808>] (s3c24xx_serial_probe+0x4c/0x94)
[<c01c6808>] (s3c24xx_serial_probe+0x4c/0x94) from [<c01d4838>] (platform_drv_probe+0x18/0x1c)
[<c01d4838>] (platform_drv_probe+0x18/0x1c) from [<c01d3570>] (driver_probe_device+0x84/0x188)
[<c01d3570>] (driver_probe_device+0x84/0x188) from [<c01d3700>] (__driver_attach+0x8c/0x90)
[<c01d3700>] (__driver_attach+0x8c/0x90) from [<c01d2dfc>] (bus_for_each_dev+0x68/0x90)
[<c01d2dfc>] (bus_for_each_dev+0x68/0x90) from [<c01d26bc>] (bus_add_driver+0xa0/0x238)
[<c01d26bc>] (bus_add_driver+0xa0/0x238) from [<c01d3ce0>] (driver_register+0x78/0x13c)
[<c01d3ce0>] (driver_register+0x78/0x13c) from [<c0028378>] (do_one_initcall+0x34/0x188)
[<c0028378>] (do_one_initcall+0x34/0x188) from [<c00083c0>] (kernel_init+0x74/0x110)
[<c00083c0>] (kernel_init+0x74/0x110) from [<c0035b78>] (kernel_thread_exit+0x0/0x8)
---[ end trace 65f8ea860415c04f ]---
Cannot register tty device on line 0
s3c2440-uart.1: ttyS1 at MMIO 0x50004000 (irq = 73) is a S3C2440
------------[ cut here ]------------

系统启动时会抛出这个错误,这是因为串口驱动冲突。解决方法:
重新配置Linux内核,然后再编译:
[wudongxu@localhost linux-3.0]$ make menuconfig

Device Drivers --->
Character devices --->
Serial drivers --->
把<> 8250/16550 and compatible serial support取消 <*> Samsung SoC serial support
[ ] Samsung SoC serial debug
[*] Support for console on Samsung SoC serial port
<*> Samsung S3C2440/S3C2442/S3C2416 Serial port support

[wodongxu@localhost linux-3.0]$ ./build.sh

五、Linux内核启动信息说明

 u-boot下每次启动调试内核要敲 tftp 30008000 linuxrom-s3c2440.bin; bootm 30008000 这么长的命令比较麻烦,所以我们可以定义一个别名然后
用run命令执行它:
[fl2440@lingyun]# set tb 'tftp 30008000 linuxrom-s3c2440.bin; bootm 30008000'

[fl2440@lingyun]# save
[fl2440@lingyun]# run tb

dm9000 i/o: 0x20000300, id: 0x90000a46
DM9000: running in 16 bit mode
MAC: 08:00:3e:26:0a:5b
could not establish link
Using dm9000 device
TFTP from server 192.168.10.8; our IP address is 192.168.10.168
Filename 'linuxrom-s3c2440.bin'.
Load address: 0x30008000
Loading: T #################################################################
#################################################################
###########################
done
Bytes transferred = 2304420 (2329a4 hex)
## Booting kernel from Legacy Image at 30008000 ...
Image Name: Linux Kernel
Created: 2017-10-27 12:47:37 UTC
Image Type: ARM Linux Kernel Image (uncompressed)
Data Size: 2304356 Bytes = 2.2 MiB
Load Address: 30008000
Entry Point: 30008040
Verifying Checksum ... OK
XIP Kernel Image ... OK
OK
Starting kernel ...
Uncompressing Linux... done, booting the kernel.
Linux内核版本,GCC版本以及编译时间信息 Linux version 3.0.0 (guowenxue@centos6.localdomain) (gcc version 4.4.6 (crosstool-NG 1.16.0) ) #5 Fri Oct 27 20:43:53 CST
2017
CPU相关信息 CPU: ARM920T [41129200] revision 0 (ARMv4T), cr=c0007177
CPU: VIVT data cache, VIVT instruction cache
Machine: SMDK2440
Memory policy: ECC disabled, Data cache writeback
CPU S3C2440A (id 0x32440001)
S3C24XX Clocks, Copyright 2004 Simtec Electronics
S3C244X: core 405.000 MHz, memory 101.250 MHz, peripheral 50.625 MHz
CLOCK: Slow mode (1.500 MHz), fast, MPLL on, UPLL on
Built 1 zonelists in Zone order, mobility grouping on. Total pages: 16256
U-boot启动Linux内核时通过bootargs传给Linux的参数,其中: console=tty0 指定Linux启动信息要输出到屏幕上; console=ttyS0,115200 指定Linux控制终端使用串口0,其波特率为115200; ubi.mtd=2 root=ubi0:rootfs rootfstype=ubifs Linux内核启动的根文件系统,不同的根文件系统这个参数不同; mem=64M U-boot告诉Linux内核操作系统有64M内存,注意内存是由U-boot初始化的,Linux内核不会对内存进行重新初始化; noinitrd 没有使用initrd
rw 根文件系统为读写挂载 loglevel=7 指定内核模块的printk输出级别为最高级别7,所有的printk信息都会输出 Kernel command line: console=tty0 console=ttyS0,115200 ubi.mtd=2 root=ubi0:rootfs rootfstype=ubifs mem=64M noinitrd rw
loglevel=7
PID hash table entries: 256 (order: -2, 1024 bytes)
Dentry cache hash table entries: 8192 (order: 3, 32768 bytes)
Inode-cache hash table entries: 4096 (order: 2, 16384 bytes)
内存信息 Memory: 64MB = 64MB total
Memory: 60308k/60308k available, 5228k reserved, 0K highmem
Virtual kernel memory layout:
vector : 0xffff0000 - 0xffff1000 ( 4 kB)
fixmap : 0xfff00000 - 0xfffe0000 ( 896 kB)
DMA : 0xffc00000 - 0xffe00000 ( 2 MB)
vmalloc : 0xc4800000 - 0xf6000000 ( 792 MB)
lowmem : 0xc0000000 - 0xc4000000 ( 64 MB)
modules : 0xbf000000 - 0xc0000000 ( 16 MB)
.init : 0xc0008000 - 0xc0028000 ( 128 kB)
.text : 0xc0028000 - 0xc042f0ac (4125 kB)
.data : 0xc0430000 - 0xc0456060 ( 153 kB)
.bss : 0xc0456084 - 0xc047e02c ( 160 kB)
NR_IRQS:85
irq: clearing pending ext status 00000800
irq: clearing subpending status 00000003
irq: clearing subpending status 00000002
Console: colour dummy device 80x30
console [tty0] enabled
console [ttyS0] enabled
CPU性能评估参数BogoMIPS
Calibrating delay loop... 201.52 BogoMIPS (lpj=503808)
pid_max: default: 32768 minimum: 301
Mount-cache hash table entries: 512
CPU: Testing write buffer coherency: ok
GPIO注册信息 gpiochip_add: gpios 288..303 (GPIOK) failed to register
gpiochip_add: gpios 320..334 (GPIOL) failed to register
gpiochip_add: gpios 352..353 (GPIOM) failed to register
NET: Registered protocol family 16
S3C Power Management, Copyright 2004 Simtec Electronics
S3C2440: Initialising architecture
S3C2440: IRQ Support
S3C244X: Clock Support, DVS off
bio: create slab <bio-0> at 0
SCSI subsystem initialized
usbcore: registered new interface driver usbfs

usbcore: registered new interface driver hub
usbcore: registered new device driver usb
I2C控制器信息 s3c-i2c s3c2440-i2c: slave address 0x10
s3c-i2c s3c2440-i2c: bus frequency set to 98 KHz
s3c-i2c s3c2440-i2c: i2c-0: S3C I2C adapter
ALSA声卡驱动信息 Advanced Linux Sound Architecture Driver Version 1.0.24.
TCP/IP协议栈 NET: Registered protocol family 2
IP route cache hash table entries: 1024 (order: 0, 4096 bytes)
TCP established hash table entries: 2048 (order: 2, 16384 bytes)
TCP bind hash table entries: 2048 (order: 1, 8192 bytes)
TCP: Hash tables configured (established 2048 bind 2048)
TCP reno registered
UDP hash table entries: 256 (order: 0, 4096 bytes)
UDP-Lite hash table entries: 256 (order: 0, 4096 bytes)
NET: Registered protocol family 1
RPC: Registered named UNIX socket transport module.
RPC: Registered udp transport module.
RPC: Registered tcp transport module.
RPC: Registered tcp NFSv4.1 backchannel transport module.
NetWinder Floating Point Emulator V0.97 (extended precision)
JFFS2和ROMFS文件系统支持 JFFS2 version 2.2. (NAND) (SUMMARY) 漏 2001-2006 Red Hat, Inc.
ROMFS MTD (C) 2007 Red Hat, Inc.
msgmni has been set to 117
io scheduler noop registered
io scheduler deadline registered
io scheduler cfq registered (default)
LCD显示屏驱动信息 Console: switching to colour frame buffer device 30x40
fb0: s3c2410fb frame buffer device
3个串口设备驱动信息 s3c2440-uart.0: ttyS0 at MMIO 0x50000000 (irq = 70) is a S3C2440
s3c2440-uart.1: ttyS1 at MMIO 0x50004000 (irq = 73) is a S3C2440
s3c2440-uart.2: ttyS2 at MMIO 0x50008000 (irq = 76) is a S3C2440
lp: driver loaded but no devices found
ppdev: user-space parallel port driver
brd: module loaded
loop: module loaded
Uniform Multi-Platform E-IDE driver
ide-gd driver 1.18
ide-cd driver 5.00
Nandflash信息 S3C24XX NAND Driver, (c) 2004 Simtec Electronics
s3c24xx-nand s3c2440-nand: Tacls=3, 29ns Twrph0=7 69ns, Twrph1=3 29ns
s3c24xx-nand s3c2440-nand: NAND soft ECC
NAND device: Manufacturer ID: 0xec, Chip ID: 0xda (Samsung NAND 256MiB 3,3V 8-bit)
Scanning device for bad blocks
Bad eraseblock 354 at 0x000002c40000
Bad eraseblock 420 at 0x000003480000
Bad eraseblock 708 at 0x000005880000
Bad eraseblock 902 at 0x0000070c0000
Bad eraseblock 1126 at 0x000008cc0000
Bad eraseblock 1344 at 0x00000a800000
Bad eraseblock 1610 at 0x00000c940000
Bad eraseblock 1682 at 0x00000d240000
Bad eraseblock 1712 at 0x00000d600000
Nandflash分区表 Creating 8 MTD partitions on "NAND":
0x000000000000-0x000000004000 : "Boot Agent"
mtd: partition "Boot Agent" doesn't end on an erase block -- force read-only
0x000000000000-0x000000200000 : "S3C2410 flash partition 1"
0x000000400000-0x000000800000 : "S3C2410 flash partition 2"
0x000000800000-0x000000a00000 : "S3C2410 flash partition 3"
0x000000a00000-0x000000e00000 : "S3C2410 flash partition 4"
0x000000e00000-0x000001800000 : "S3C2410 flash partition 5"
0x000001800000-0x000003000000 : "S3C2410 flash partition 6"
0x000003000000-0x000010000000 : "S3C2410 flash partition 7"
dm9000网卡驱动信息 dm9000 Ethernet Driver, V1.31
usbmon: debugfs is not available
USB Host驱动信息 ohci_hcd: USB 1.1 'Open' Host Controller (OHCI) Driver
s3c2410-ohci s3c2410-ohci: S3C24XX OHCI
s3c2410-ohci s3c2410-ohci: new USB bus registered, assigned bus number 1
s3c2410-ohci s3c2410-ohci: irq 42, io mem 0x49000000
发现USB Hub
hub 1-0:1.0: USB hub found
hub 1-0:1.0: 2 ports detected
usbcore: registered new interface driver libusual
usbcore: registered new interface driver usbserial
USB转串口驱动 USB Serial support registered for generic
usbcore: registered new interface driver usbserial_generic
usbserial: USB Serial Driver core
FTDI(如FT232)USB转串口芯片驱动 USB Serial support registered for FTDI USB Serial Device
usbcore: registered new interface driver ftdi_sio
ftdi_sio: v1.6.0:USB FTDI Serial Converters Driver
PL2303 USB转串口驱动 USB Serial support registered for pl2303
usbcore: registered new interface driver pl2303
pl2303: Prolific PL2303 USB to serial adaptor driver
mousedev: PS/2 mouse device common for all mice
RTC、看门狗和ALSA声卡驱动信息 S3C24XX RTC, (c) 2004,2006 Simtec Electronics
S3C2410 Watchdog Timer, (c) 2004 Simtec Electronics

s3c2410-wdt s3c2410-wdt: watchdog inactive, reset disabled, irq enabled
ALSA device list:
No soundcards found.
TCP cubic registered
NET: Registered protocol family 17
drivers/rtc/hctosys.c: unable to open rtc device (rtc0)
Linux内核根据u-boot的bootargs环境变量传过来的参数查找根文件系统并启动init进程执行根文件系统里的/init或/initrc程序,这时候我们并没有提供根
文件系统,所以系统死掉 VFS: Cannot open root device "ubi0:rootfs" or unknown-block(0,0)
Please append a correct "root=" boot option; here are the available partitions:
1f00 16 mtdblock0 (driver?)
1f01 2048 mtdblock1 (driver?)
1f02 4096 mtdblock2 (driver?)
1f03 2048 mtdblock3 (driver?)
1f04 4096 mtdblock4 (driver?)
1f05 10240 mtdblock5 (driver?)
1f06 24576 mtdblock6 (driver?)
1f07 212992 mtdblock7 (driver?)
Linux找不到根文件系统死掉 Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(0,0)
[<c003a078>] (unwind_backtrace+0x0/0xf4) from [<c032edfc>] (panic+0x58/0x188)
[<c032edfc>] (panic+0x58/0x188) from [<c0008e30>] (mount_block_root+0x16c/0x220)
[<c0008e30>] (mount_block_root+0x16c/0x220) from [<c0009038>] (prepare_namespace+0x8c/0x1bc)
[<c0009038>] (prepare_namespace+0x8c/0x1bc) from [<c0008428>] (kernel_init+0xdc/0x110)
[<c0008428>] (kernel_init+0xdc/0x110) from [<c0035b78>] (kernel_thread_exit+0x0/0x8)
Linux内核自举启动完成之后,最后将创建init进程并执行根文件系统中的/init或/initrc程序,该程序解析并执行根文件系统中的/etc/inittab配置文件,在此文件中配置了init进程在系统启动要启动哪些应用程序。接下来的内容中我们将讲解根文件系统的制作过程。

六、根文件系统树制作
1.创建根文件系统树目录结构
根文件系统目录树用来存放Linux的基本命令、系统配置、动态库、设备节点、应用程序等所有文件,这些文件是存放在我们的Linux服务器上,在接下来
的内容中我们将使用不同的工具将他制作成不同格式的根文件系统。
[wudongxu@localhost ~]$ cd ~/gitee/fl2440/linux/
[wudongxu@localhost linux]$ ls
linux-3.0
[wudongxu@localhost linux]$ mkdir rootfs
[wudongxu@localhost linux]$ ls
linux-3.0 rootfs
[wudongxu@localhost linux]$ cd rootfs/
[wudongxu@localhost rootfs]$ mkdir -p
{apps,bin,data,dev,info,proc,root,sbin,sys,tmp,var,etc/init.d,mnt/{usb,mmc},usr/{,bin,sbin,lib},lib/{,modules/{,3.0.0}}}
[wudongxu@localhost rootfs]$ tree

|-- bin 系统基本命令bin
|-- sbin 系统管理命令
|-- dev 系统设备节点所在路径
|-- root root用户home
|-- etc 系统配置文件所在路径
| `-- init.d 系统初始化、启动程序脚本
|-- lib 系统动态库路径
| `-- modules
| `-- 3.0.0 linux内核驱动模块需要该路径
|-- usr
| |-- bin 用户基本命令路径
| |-- lib 用户动态库文件
| `-- sbin 用户管理命令路径
|-- apps nandflash apps分区挂载点,用来存放应用程序
|-- data nandflash data分区挂载点,用来存放数据
|-- info nandflash info分区挂载点,用来存放设备信息
|-- mnt 系统挂载点
| |-- mmc SD卡挂载点
| `-- usb U盘挂载点
|-- proc linux proc文件系统挂载点
|-- sys linux sys文件系统挂载点
|-- tmp linux tmp文件系统挂载点 `-- var 系统日志等文件存放路径 23 directories, 0 files



2.安装动态库
Linux下所有的应用程序运行都离不开动态库,程序在运行时默认会在/lib路径下查找相关的动态库文件。如果动态库文件不在该路径下,可以通
过LD_LIBRARY_PATH环境变量来指定其它需要加载的动态库路。因为开发板上所有的程序都是使用交叉编译器编译的,所以我们需要将交叉编译器里的
动态库文件拷贝到根文件系统树的lib路径下:
切换路径到lib路径下
[wudongxu@localhost ~]$ cd ~/gitee/fl2440/linux/rootfs/

[wudongxu@localhost rootfs]$ ls apps bin data dev etc info init lib linuxrc mnt proc root sbin sys tmp usr var

 [wudongxu@localhost rootfs]$ cd lib/
下面这个命令用来将/opt/xtools/arm920t路径下除gconv相关的所有动态库(.so)文件拷贝到
[wudongxu@localhost lib]$ find /opt/xtools/arm920t/ -name "*.so*" | grep -v gconv | xargs -i cp -af {} ./
列出所有失效的符号链接文件
[wudongxu@localhost lib]$ ls lib/
[wudongxu@localhost lib]$ ls -l `find -L -type l`


在上面的输出中有很多红色的文件为失效的符号链接(../../lib/libxxxx),我们可以创建并使用下面脚本来重新制作符号链接到本地路径下:

[wudongxu@localhost lib]$ vim symlink.sh

#!/bin/bash
# find all the invalid symlink file and remove "./" before it
for sf in `find -L -type l | cut -d'/' -f2` ; do
# parser and get symlink target file name
file=`ls -l $sf | awk -F '/' '{ print $NF }'`
# remove invalid symlink file and generate new one
rm -f $sf && ln -s $file $sf
done

[wudongxu@localhost lib]$ sh symlink.sh && rm -f symlink.sh
[wudongxu@localhost lib]$ ls
[wudongxu@localhost lib]$ cd ..



3、安装busybox
Linux系统在执行一条命令时,默认会到/bin、/sbin、/usr/bin、/usr/sbin这些路径下找,如果找不到则提示command not found,当然我们也可以
通过PATH环境变量告诉系统其它命令存放的路径。现在根文件系统树下这些路径里并没有Linux系统相关命令。
[wudongxu@localhost ~]$ cd ~/gitee/fl2440/linux/rootfs/
[wudongxu@localhost rootfs]$ ls apps bin data dev etc info init lib linuxrc mnt proc root sbin sys tmp usr var BusyBox 是一个集成了一百多个最常用Linux命令和工具的软件,如ls、cat、ifconfig、vim、grep、sed、awk、find、mount、telnet等。有些人将
BusyBox 称为 Linux 工具里的瑞士军刀,简单的说BusyBox就好像是个大工具箱,它集成压缩了 Linux 的许多工具和命令。我们通过下载busybox源码、
配置编译并安装它就会提供这些Linux的基本命令的实现,它们将会被安装到根文件系统树的 bin、sbin、usr/bin、usr/sbin等路径下。
进入到FL2440项目下创建busybox的工作目录
[wudongxu@localhost ~]$ cd ~/gitee/fl2440/
[wudongxu@localhost fl2440]$ mkdir 3rdparty

[wudongxu@ localhost fl2440]$ ls 3rdparty bootloader crosstool LICENSE linux README.md
[wudongxu@localhost fl2440]$ cd 3rdparty/
下载解压busybox
[wudongxu@localhost 3rdparty]$ wget https://busybox.net/downloads/busybox-1.27.1.tar.bz2
[wudongxu@localhost 3rdparty]$ tar -xjf busybox-1.27.1.tar.bz2
[wudongxu@localhost 3rdparty]$ cd busybox-1.27.1

[wudongxu@localhost busybox-1.27.1]$ ls 


类似Linux内核,对busybox进行配置,选择哪些Linux命令需要编译,哪些不需要
[wudongxu@localhost busybox-1.27.1]$ export TERM=vt100
[wudongxu@localhost busybox-1.27.1]$ make menuconfig

Busybox Settings --->
[ ] Enable options for full-blown desktop systems 我们的Linux不带桌面,可以去掉这个选项节约代码
[*] Build BusyBox as a static binary (no shared libs) 使用静态链接,不使用动态库
(/opt/xtools/arm920t/bin/arm-linux-) Cross Compiler prefix 设置自己的交叉编译器路径
(../../linux/rootfs/) BusyBox installation prefix 设置busybox的安装路径,它应该是根文件系统树的路径 Linux System Utilities --->
[ ] nsenter 将该选项去掉,否则编译出现错误: undefined reference to `setns'
Coreutils --->
[*] sync
[ ] Enable -d and -f flags (requires syncfs(2) in libc) 将该选项去掉,否则编译出现错误: undefined reference to `syncfs' Miscellaneous Utilities --->
[*] flashcp Norflash拷贝命令
[*] flash_eraseall Norflash和Nandflash的擦除命令
[*] flash_lock Norflash的写保护命令
[*] flash_unlock Norflash的解写保护命令
Print Utilities ---> 打印机我们不用的话,里面的全部不要选,可以节约空间 Mail Utilities ---> 邮件收发我们不用的话,里面的全部不要选,可以节约空间

编译并安装busybox到根文件系统树路径下:
[wudongxu@localhost busybox-1.27.1]$ make && make install
切换到根文件系统树路径下,创建符号链接指向busybox程序,如果使用initramfs根文件系统启动需要该命令: [guowenxue@centos6_master busybox-1.27.1]$ cd ../../linux/rootfs/
[wudongxu@localhost rootfs]$ ln -s bin/busybox init
列出根文件系统目录树下的linux命令,这些命令其实都是符号链接到busybox: [guowenxue@centos6_master busybox-1.27.1]$ ls ../../linux/rootfs/
[wudongxu@localhost busybox-1.27.1]$ ls ../../linux/rootfs/bin/



4.创建/dev路径下的设备节点
Linux下所有的东西都是文件,其中设备也是当作文件来处理。/dev路径下存放所有的Linux的设备文件,我们需要使用root权限执行mknod命令在这
里创建系统启动必须的设备文件节点,其他的设备节点将有mdev动态创建。
[wudongxu@localhost ~]$ cd ~/gitee/fl2440/linux/rootfs/
[wudongxu@localhost rootfs]$ ls apps bin data dev etc info init lib linuxrc mnt proc root sbin sys tmp usr var [guowenxue@centos6_master rootfs]$ sudo mknod -m666 dev/null c 1 3
[wudongxu@localhost rootfs]$ sudo mknod -m666 dev/console c 5 1
[wudongxu@localhost rootfs]$ sudo mknod -m666 dev/ttyS0 c 4 64
[wudongxu@localhost rootfs]$ ls -l dev/
total 0
crw-rw-rw- 1 root root 5, 1 Oct 29 01:09 console
crw-rw-rw- 1 root root 1, 3 Oct 29 01:08 null crw-rw-rw- 1 root root 4, 64 Oct 29 01:09 ttyS0


5.创建/var路径下文件
/var路径会存放系统运行时的一些文件(如系统日志文件/var/log/messages),我们在该路径下创建相应的符号链接到/tmp路径下。
[wudongxu@localhost rootfs]$ ln -s /tmp var/lock
[wudongxu@localhost rootfs]$ ln -s /tmp var/log
[wudongxu@localhost rootfs]$ ln -s /tmp var/run
[wudongxu@localhost rootfs]$ ln -s /tmp var/tmp


6.创建/etc路径下文件
6.1 创建 /etc/inittab 文件
Linux内核自举启动完成之后,最后将创建init进程并执行根文件系统中的/init或/initrc程序,该程序解析并执行/etc/inittab配置文件,在此文件中配置
了init进程在系统启动要启动哪些应用程序。
[wudongxu@localhost ~]$ cd ~/gitee/fl2440/linux/rootfs/
[wudongxu@localhost rootfs]$ vim etc/inittab


# Note: BusyBox init doesn't support runlevels. The runlevels field is
# completely ignored by BusyBox init. If you want runlevels, use sysvinit.
#

# Format for each entry: <id>:<runlevels>:<action>:<process>
#
# id == tty to run on, or empty for /dev/console.
# If specified, then /dev/$id device must exist
# runlevels == ignored, busybox doesn't support it
# action == one of sysinit, respawn, askfirst, wait, and once
# process == program to run
# Startup the system
# mount all the file systems specified in /etc/fstab
::sysinit:/bin/mount -a
# Use mdev to auto generate device nod and auto mount SD card and USB storage
::sysinit:/bin/echo /sbin/mdev > /proc/sys/kernel/hotplug
::sysinit:/sbin/mdev -s
#make shm, pts support
::sysinit:/bin/mkdir -p /dev/pts
::sysinit:/bin/mkdir -p /dev/shm
::sysinit:/bin/mount -t devpts devpts /dev/pts
#Set hostname
null::sysinit:/bin/hostname -F /etc/hostname
#Enable console logon
null::respawn:/sbin/getty -L ttyS0 115200 vt100
# now run any rc scripts, which used to start other application
null::wait:/etc/init.d/rcS
# system daemon
null::respawn:/sbin/syslogd -n
null::respawn:/sbin/klogd -n
# Stuff to do before rebooting
null::shutdown:/bin/killall klogd
null::shutdown:/bin/killall syslogd
null::shutdown:/bin/umount -a -r

6.2 创建/etc/fstab文件
Linux下的mount -a命令将自动挂载/etc/fstab文件中指定的所有需要系统自动挂载的文件。在/etc/inittab中会使用该命令在上电时自动挂载相应的文件
系统,这里面主要是挂载一些伪文件系统,这些伪文件系统主要是导出Linux内核运行的相关信息,如比较重要的tmpfs、sysfs、proc文件系统等。
[ wudongxu@localhost ~]$ cd ~/gitee/fl2440/linux/rootfs/

[wudongxu@localhost rootfs]$ vim etc/fstab

# /etc/fstab: static file system information.
#
# <file system> <mount pt> <type> <options> <dump> <pass>
/dev/root / ext2 rw,noauto 0 1
proc /proc proc defaults 0 0
usbfs /proc/bus/usb usbfs defaults 0 0
tmpfs /dev tmpfs defaults 0 0
ramfs /tmp ramfs defaults 0 0
sysfs /sys sysfs defaults 0 0

6.3 创建hostname文件
/etc/hostname文件指定主机名,/etc/inittab文件中通过 hostname -F /etc/hostname 命令设置主机名
[wudongxu@localhost  ~]$ cd ~/gitee/fl2440/linux/rootfs/
[wudongxu@localhost  rootfs]$ vim etc/hostname

wudongxufl2440

6.4 创建系统启动脚本
系统所有的启动脚本我们都将放在/etc/init.d路径下,接下来我们将创建这些系统启动脚本:

[wudongxu@localhost  ~]$ cd ~/gitee/fl2440/linux/rootfs/
[wudongxu@localhost  rootfs]$ ls etc/
fstab hostname init.d inittab
[wudongxu@localhost  rootfs]$ cd etc/init.d/
[wudongxu@localhost  init.d]$ ls
启动脚本一、 /etc/init.d/rcS
/etc/inittab脚本会使用命令/etc/init.d/rcS启动所有其它的应用程序,下面创建etc/rcS脚本,该脚本将执行/etc/init.d/下所有文件名以S开头且后面紧
跟至少包括2个字符的文件。

[wudongxu@localhost  init.d]$ vim rcS

#!/bin/sh
# Start all scripts in /etc/init.d, executing them in numerical order.
for i in /etc/init.d/S??* ; do
$i
done 

我们需要将该脚本给执行的权限才能执行
[wudongxu@localhost  init.d]$ chmod a+x rcS

启动脚本二、 /etc/init.d/S10_network
假设我们希望系统启动时自动设置网卡的IP地址,则可以创建一个文件名以S开头且后面紧跟至少包括2个字符的启动脚本,并给执行权限。
[wudongxu@localhost  init.d]$ vim S10_network

#!/bin/sh
ifconfig eth0 192.168.1.250 netmask 255.255.255.0 up

[wudongxu@localhost  init.d]$ chmod a+x S10_network
启动脚本三、 /etc/init.d/S99_rcsApp
今后我们很多应用程序将会存放在/apps分区下,有时我们希望这些应用程序的启动脚本也存放在该分区下以便于管理。这时我们可以参考rcS脚本的实现
机制,让它也执行在/apps/etc下的所有启动脚本。
[wudongxu@localhost  init.d]$ vim S99_rcsApp

#!/bin/sh
# Start all scripts in /apps/etc/init.d, executing them in numerical order.
for i in /apps/etc/init.d/S??* ; do
$i
done
[wudongxu@localhost  init.d]$ chmod a+x S99_rcsApp
[wudongxu@localhost  init.d]$ ls
rcS S10_network S99_rcsApp

6.5 创建shell的配置文件
在Linux服务器上,我们可以通过修改~/.bash_profile或~/.bashrc文件来修改Shell的配置文件,如修改PATH、LD_LIBRARY_PATH环境变量等,也
可以在里面定义命令别名。在嵌入式环境下,我们这些Shell的配置保存在/etc/profile文件中。这时我们可以创建该文件配置嵌入式环境busybox里的
shell(ash)。
切换到根文件系统树/etc路径下
[wudongxu@localhost  ~]$ cd ~/gitee/fl2440/linux/rootfs/etc/
[wudongxu@localhost  etc]$ ls
fstab hostname init.d inittab

[wudongxu@localhost  etc]$ vim profile

# Busybox Shell(ash) configure file
export PATH=/bin:sbin:/usr/bin:/usr/sbin:/apps/bin:/apps/tools
export PS1='\w >: '
export USER=`id -un`
export LOGNAME=$USER
export HOSTNAME=`/bin/hostname`
export HISTSIZE=500
export HISTFILESIZE=500
export PAGER='/bin/more'
export EDITOR='/bin/vi'
export INPUTRC=/etc/inputrc

export LD_LIBRARY_PATH=/lib:/usr/lib:/apps/lib
export network_cfg_dir=/apps/etc/network
### Some alias command
alias vim='vi'
alias ll='ls -l'
alias l.='ls -d .*'
alias df='df -h

6.6 创建Linux登录帐号文件
Linux系统中的登录帐号信息保存在/etc/group、/etc/passwd和/etc/shadow文件中。
 /etc/group文件保存了用户组信息;
 /etc/passwd文件保存了用户信息;
 /etc/shadow文件保存来相应用户的密码;
 下面我们需要在根文件系统中创建这些系统帐号文件,在这里我们只创建root帐号,其他帐号的过程类似。当然也可以在系统启动后以root帐号权限来添
加。
[wudongxu@localhost  ~]$ cd ~/gitee/fl2440/linux/rootfs/etc
[wudongxu@localhost  etc]$ ls
fstab hostname init.d inittab profile 
一、 /etc/group文件
[wudongxu@localhost  etc]$ vim group

root:x:0:root

该文件的格式为:
groupname:password:gid:members 第一个字段为用户组名称;
第二个字段为用户组密码,当为x时密码是映射到/etc/gshadow中的,是非逆的;
第三个字段为GID,及组号,为正整数或0,0被付于了root用户组;系统通常会预留一些较靠前的GID给系统虚拟用户之用,每个系统预留的GID都
不同,一般普通用户的GID从500开始;
第四个字段为用户列表,每个用户间用逗号分隔;
二、 /etc/passwd文件
[wudongxu@localhost  etc]$ vim passwd

root:x:0:0:root:/:/bin/sh

该文件的格式为:
username:password:uid:gid:fullname:homedir:shell
第一个字段为登录用户名
第二个字段为密码,这里设置为x表示密码被映射到/etc/shadow文件中
第三个字段为用户ID(UID)
第四个字段为用户所属组ID(GID)
第五个字段为用户名全称
第六个字段为用户根目录
第七个字段为用户所用shell的类型
 Unix系统最初是用明文保存密码的,后来由于安全的考虑,采用crypt()算法加密密码并存放在/etc/passwd文件。现在,由于计算机处理能力的提高,使
密码破解变得越来越容易。/etc/passwd文件是所有合法用户都可访问的,大家都可互相看到密码的加密字符串,这给系统带来很大的安全威胁。现代的
Unix系统使用影子密码系统,它把密码从/etc/passwd文件中分离出来,真正的密码保存在/etc/shadow文件中,shadow文件只能由超级用户访问。这样
入侵者就不能获得加密密码串,用于破解。使用shadow密码文件后,/etc/passwd文件中所有帐户的password域的内容为"x",如果password域的内容
为"*",则该帐号被停用。
三、 /etc/shadow文件
 /etc/shadow文件保存了相应帐号的密文,这个文件内容不能直接创建。如果我们想在嵌入式Linux系统中设置root的登录密码为123456,则我们先在自
己的Linux服务器或虚拟机上修改root密码为123456,然后再将Linux服务器或虚拟机上的/etc/shadow文件里root帐号的密码密文部分拷贝出来,创建根
文件系统树里的etc/shadow时将密文部分用这个密文替换。这个过程做完后记得将自己的Linux服务器或虚拟机的root密码还原回去。

[wudongxu@localhost  ~]$ sudo passwd root 修改自己Linux主机上的root密码为 123456

Changing password for user root.
New password:
BAD PASSWORD: it is too simplistic/systematic
BAD PASSWORD: is too simple
Retype new password:
passwd: all authentication tokens updated successfully.
[wudongxu@localhost  ~]$
[wudongxu@localhost  ~]$ sudo cat /etc/shadow | grep root 记录下来root帐号的加密密文信息 root:$6$Gc/FAOs5$P2Dww7IlmliXKW5HRd6QJVGBExGmU7.H6Ec9p95PTtQwP063GZee1ouvNejpScs0OazVFXpiBsiDl1KlUkrTw1:17467:0:99999:7:::docke
[wudongxu@localhost  ~]$
[wudongxu@localhost  ~]$ sudo passwd root 恢复自己Linux主机上的root密码
Changing password for user root.
New password:
Retype new password:
passwd: all authentication tokens updated successfully.
[wudongxu@localhost  ~]$

现在我们创建根文件系统树下的/etc/shadow文件, 参考下文内容只将上面root帐号的加密密文部分($6$Gc****lUkrTw1)拷贝过来,其它部分保持不变:

 [wudongxu@localhost etc]$ vim shadow

root:$6$Gc/FAOs5$P2Dww7IlmliXKW5HRd6QJVGBExGmU7.H6Ec9p95PTtQwP063GZee1ouvNejpScs0OazVFXpiBsiDl1KlUkrTw1:0:0:99999:7::: 

该文件的格式为:
username:password:last_change:min_change:max_change:warm:failed_expire:expiration:reserved
第一字段:用户名(也被称为登录名),在/etc/shadow中,用户名和/etc/passwd 是相同的,这样就把passwd 和shadow中用的用户记录联系在
一起;这个字段是非空的;
第二字段:密码加密后的密文,这个字段是非空的;
第三字段:上次修改密码的时间;这个时间是从1970年01月01日算起到最近一次修改口令的时间间隔(天数);
第四字段:两次修改密码间隔最少的天数;如果这个字段的值为空,帐号永久可用;
第五字段:两次修改密码间隔最多的天数;如果这个字段的值为空,帐号永久可用;
第六字段:提前多少天警告用户密码将过期;如果这个字段的值为空,帐号永久可用;
第七字段:在密码过期之后多少天禁用此用户;如果这个字段的值为空,帐号永久可用;
第八字段:用户过期日期;此字段指定了用户作废的天数(从1970年的1月1日开始的天数),如果这个字段的值为空,帐号永久可用;
第九字段:保留字段,目前为空,以备将来发展之用;

6.6 创建Linux其他文件
切换到根文件系统树etc路径下:
[wudongxu@localhost  ~]$ cd ~/gitee/fl2440/linux/rootfs/etc/
[wudongxu@localhost  etc]$ ls
fstab group hostname init.d inittab passwd profile shadow
一、 /etc/resolv.conf文件
 该文件用来设置Linux系统的DNS服务器,DNS服务器用来将域名转换成IP地址。
[wudongxu@localhost  etc]$ vim resolv.conf

nameserver 114.114.114.114
nameserver 4.2.2.2

二、 /etc/hosts文件
/etc/hosts文件存放本机静态绑定的域名,如下面在本机上域名localhost就会被解析成127.0.0.1,不需要DNS来做解析。
[wudongxu@localhost  etc]$ vim hosts

127.0.0.1 localhost

三、 /etc/TZ文件
/etc/TZ文件配置了系统的时区
[wudongxu@localhost  etc]$ vim TZ

MST7MDT

四、 /etc/issue文件
/etc/issue文件里存放在console上登录系统时提示的警告信息
[wudongxu@localhost  etc]$ vim issue

Default Logon Username: root Password: 123456


至此Linux根文件系统树所需要的基本文件都已经有了,接下来我们可以使用Linux内核启动这个根文件系统。可以查看一下文件系统目录树的大小:
[wudongxu@localhost  linux]$ du -sh rootfs 12M rootfs

七、Linux内核使用initramfs文件系统启动
7.1 initramfs文件系统简介
initramfs是Linus开发的一种基于内存的根文件系统,在编译Linux内核的时候,它会直接把根文件系统树打包进内核的镜像文件中(zImage),这也意味
着该镜像文件同时包含了Linux内核和根文件系统。因为根文件系统是内核打包进去的,所以内核自己知道根文件系统的位置,这样u-boot也就不需要通过
bootargs参数告诉内核根文件系统的信息,此外也不需要额外烧录根文件系统镜像文件,如ubifs、yaffs2、jffs2等。在今后做其他根文件系统的时候,请
务必在内核中禁用initramfs,否则Linux内核将优先使用initramfs启动了。
因为initramfs是基于内存的根文件系统,所以大家在开发板上对根文件系统里的任何文件的操作,包括创建、删除、修改在重启后都会丢失。因此如果
想要更改根文件系统里的文件,必须修改根文件系统树,然后重新编译Linux内核并使用u-boot重新烧录。
7.2 内核配置与编译
Linux内核使用initramfs启动,只需要在make menuconfig作下面修改,然后重新编译即可。
[wudongxu@localhost  linux-3.0]$ make menuconfig

七、Linux内核使用initramfs文件系统启动
7.1 initramfs文件系统简介
initramfs是Linus开发的一种基于内存的根文件系统,在编译Linux内核的时候,它会直接把根文件系统树打包进内核的镜像文件中(zImage),这也意味
着该镜像文件同时包含了Linux内核和根文件系统。因为根文件系统是内核打包进去的,所以内核自己知道根文件系统的位置,这样u-boot也就不需要通过
bootargs参数告诉内核根文件系统的信息,此外也不需要额外烧录根文件系统镜像文件,如ubifs、yaffs2、jffs2等。在今后做其他根文件系统的时候,请
务必在内核中禁用initramfs,否则Linux内核将优先使用initramfs启动了。
因为initramfs是基于内存的根文件系统,所以大家在开发板上对根文件系统里的任何文件的操作,包括创建、删除、修改在重启后都会丢失。因此如果
想要更改根文件系统里的文件,必须修改根文件系统树,然后重新编译Linux内核并使用u-boot重新烧录。
7.2 内核配置与编译
Linux内核使用initramfs启动,只需要在make menuconfig作下面修改,然后重新编译即可。
[wudongxu@localhost  linux-3.0]$ make menuconfig

General setup --->
[*] Initial RAM filesystem and RAM disk (initramfs/initrd) support
(../../linux/rootfs/) Initramfs source file(s) 指定前面制作的根文件系统树所在的路径 Device Drivers --->
[*] Block devices --->
< > Network block device support
< > Low Performance USB Block driver
< > RAM block device support 务必将这个ramdisk选项取消掉,否则initramfs根文件系统不能启动,默认用作 initrd启动。 < > ATA over Ethernet support

[wudongxu@localhost  linux-3.0]$ make
CHK include/linux/version.h
CHK include/generated/utsrelease.h
make[1]: `include/generated/mach-types.h' is up to date.
CALL scripts/checksyscalls.sh
CHK include/generated/compile.h
GEN usr/initramfs_data.cpio
AS usr/initramfs_data.o
LD usr/built-in.o
LD vmlinux.o
MODPOST vmlinux.o
GEN .version
CHK include/generated/compile.h
UPD include/generated/compile.h
CC init/version.o
LD init/built-in.o
LD .tmp_vmlinux1
KSYM .tmp_kallsyms1.S
AS .tmp_kallsyms1.o
LD .tmp_vmlinux2
KSYM .tmp_kallsyms2.S
AS .tmp_kallsyms2.o
LD vmlinux
SYSMAP System.map
SYSMAP .tmp_System.map
OBJCOPY arch/arm/boot/Image
Kernel: arch/arm/boot/Image is ready
GZIP arch/arm/boot/compressed/piggy.gzip
AS arch/arm/boot/compressed/piggy.gzip.o
SHIPPED arch/arm/boot/compressed/lib1funcs.S
AS arch/arm/boot/compressed/lib1funcs.o
LD arch/arm/boot/compressed/vmlinux
OBJCOPY arch/arm/boot/zImage
Kernel: arch/arm/boot/zImage is ready
Building modules, stage 2.
MODPOST 308 modules
[wudongxu@localhost  linux-3.0]$ mkimage -A arm -O linux -T kernel -C none -a 30008000 -e 30008040 -n "Linux Kernel" -d

arch/arm/boot/zImage linuxrom-s3c2440.bin

Image Name: Linux Kernel
Created: Wed Nov 8 06:46:33 2017
Image Type: ARM Linux Kernel Image (uncompressed)
Data Size: 7271940 Bytes = 7101.50 kB = 6.94 MB
Load Address: 30008000
Entry Point: 30008040
[wudongxu@localhost  linux-3.0]$ ls -l arch/arm/boot/zImage
-rwxrwxr-x 1 wudongxu wudongxu 7271940 Nov 8 06:46 arch/arm/boot/zImage
[wudongxu linux-3.0]$ du -sh arch/arm/boot/zImage 7.0M arch/arm/boot/zImage
[wudongxu linux-3.0]$ ls -l linuxrom-s3c2440.bin
-rwxrwxr-x 1 guowenxue guowenxue 7272004 Nov 8 06:46 linuxrom-s3c2440.bin
[wudongxu linux-3.0]$ du -sh linuxrom-s3c2440.bin
7.0M linuxrom-s3c2440.bin 因为现在把根文件系统树以initramfs文件系统格式压缩、打包进Linux内核了,所以现在Linux内核要大些。

7.3 u-boot系统启动和环境变量配置
使用u-boot重新启动Linux系统:
u-boot里设置bootargs参数,该参数是u-boot传给Linux内核的参数,这里不需要告诉Linux内核根文件系统信息:
[fl2440@lingyun]# set bootargs 'console=tty0 console=ttyS0,115200 mem=64M rw loglevel=7' [fl2440@lingyun]# save
[fl2440@lingyun]# tftp 30008000 linuxrom-s3c2440.bin;bootm 30008000
dm9000 i/o: 0x20000300, id: 0x90000a46
DM9000: running in 16 bit mode MAC: 08:00:3e:26:0a:5b
could not establish link
Using dm9000 device TFTP from server 192.168.2.2; our IP address is 192.168.2.222
Filename 'linuxrom-s3c2440.bin'. Load address: 0x30008000
Loading: #################################################################
#################################################################
#################################################################
#################################################################
#################################################################
#################################################################
#################################################################
################################ done Bytes transferred = 7135380 (6ce094 hex) ## Booting kernel from Legacy Image at 30008000 ... Image Name: Linux Kernel
Created: 2017-10-28 22:36:11 UTC
Image Type: ARM Linux Kernel Image (uncompressed)
Data Size: 7135316 Bytes = 6.8 MiB
Load Address: 30008000
Entry Point: 30008040
Verifying Checksum ... OK
XIP Kernel Image ... OK
OK
Starting kernel ... Uncompressing Linux... done, booting the kernel. Linux version 3.0.0 (guowenxue@centos6.localdomain) (gcc version 4.4.6 (crosstool-NG 1.16.0) ) #13 Sun Oct 29 06:36:04 CST 2017
CPU: ARM920T [41129200] revision 0 (ARMv4T), cr=c0007177
CPU: VIVT data cache, VIVT instruction cache Machine: SMDK2440
Memory policy: ECC disabled, Data cache writeback
CPU S3C2440A (id 0x32440001)
S3C24XX Clocks, Copyright 2004 Simtec Electronics S3C244X: core 405.000 MHz, memory 101.250 MHz, peripheral 50.625 MHz ... ... ... ... ... NET: Registered protocol family 17
drivers/rtc/hctosys.c: unable to open rtc device (rtc0)
Freeing init memory: 11576K 找到根文件系统并成功启动
usb 1-1: new full speed USB device number 2 using s3c2410-ohci usb 1-1: device descriptor read/64, error -62 usb 1-1: device descriptor read/64, error -62 usb 1-1: new full speed USB device number 3 using s3c2410-ohci usb 1-1: device descriptor read/64, error -62 usb 1-1: device descriptor read/64, error -62 usb 1-1: new full speed USB device number 4 using s3c2410-ohci usb 1-1: device not accepting address 4, error -62

usb 1-1: new full speed USB device number 5 using s3c2410-ohci usb 1-1: device not accepting address 5, error -62
hub 1-0:1.0: unable to enumerate USB device on port 1文件里的信息
Default Logon Username: root Password: 123456 文件里的信息
wudongxufl2440 login: root /etc/hostname 里设置主机名为LingYunFl2440,登录用户名为root,密码为123456
Password: ~ >: ~ >: ls apps dev init mnt sbin usr bin etc lib proc sys var data info linuxrc root tmp

7.4 登录测试: ~ >: mount 查看根文件系统挂载类型

rootfs on / type rootfs (rw) 这里为initramfs
proc on /proc type proc (rw,relatime)
usbfs on /proc/bus/usb type usbfs (rw,relatime)
tmpfs on /dev type tmpfs (rw,relatime)
ramfs on /tmp type ramfs (rw,relatime)
sysfs on /sys type sysfs (rw,relatime)
devpts on /dev/pts type devpts (rw,relatime,mode=600)

因为initramfs是建立在内存上的根文件系统,在该文件系统路径下所有的文件修改掉电后都会丢失。所以我们在根路径下创建haha文件后,把开发板重启
后发现该文件丢失了。
~ >: pwd
/~ >: touch haha ~ >: reboot

原创粉丝点击