环境 arm-linux-gcc 3.4.1
1.linux根文件系统概述
linux系统可以将磁盘,flash等存储设备划分为若该个分区,但是linux系统需要在一个分区上存放系统启动的所有文件,比如内核镜像、内核启动的第一个进程init进程、根文件系统等。系统在启动时会自动mount该文件系统。
linux系统上FHS :
/
|-- arm-linux-gcc-3.3.2.tar.bz2
|-- bin
|-- boot
|-- cdrom -> media/cdrom
|-- dev
|-- etc
|-- home
|-- host
|-- initrd.img -> boot/initrd.img-2.6.28-18-generic
|-- initrd.img.old -> boot/initrd.img-2.6.28-16-generic
|-- lib
|-- lost+found
|-- media
|-- mnt
|-- opt
|-- proc
|-- root
|-- sbin
|-- selinux
|-- srv
|-- sys
|-- tmp
|-- usr
|-- var
|-- vmlinuz -> boot/vmlinuz-2.6.28-18-generic
`-- vmlinuz.old -> boot/vmlinuz-2.6.28-16-generic
21 directories, 5 files
所谓的构建跟文件系统就是指构建符合FHS标准的文件夹,然后使用特定工具将上面生成的文件夹压制成某个特定的格式。
2.busybox使用
使用busybox的主要目的是构建以下的两个目录 /bin和/sbin。如果是创建最小根文件系统的话,另外还需要作的工作是:在/dev目录下创建设备节点,在/etc下创建配置文件,如果busybox使用动态连接库的话,还需要在/lib下放置需要的动态连接库。
init进程简介
init进程是内核启动之后第一个运行的进程,在init/main.c中启动。
/* This is a non __init function. Force it to be noinline otherwise gcc
* makes it inline to init() and it becomes part of init.text section
*/
static int noinline init_post(void)
{
...
// 试图打开/dev/console,如果成功,将/dev/console设置成init进程的标准输入
if (sys_open((const char __user *) "/dev/console", O_RDWR, 0) < 0)
printk(KERN_WARNING "Warning: unable to open an initial console./n");
(void) sys_dup(0);
(void) sys_dup(0);
// ramdisk_execute_command变量指定要运行的程序
if (ramdisk_execute_command) {
run_init_process(ramdisk_execute_command);
printk(KERN_WARNING "Failed to execute %s/n",
ramdisk_execute_command);
}
/*
* We try each of these until one succeeds.
*
* The Bourne shell can be used instead of init if we are
* trying to recover a really broken machine.
*/
// execute_command指定要运行的程序
if (execute_command) {
run_init_process(execute_command);
printk(KERN_WARNING "Failed to execute %s. Attempting "
"defaults.../n", execute_command);
}
run_init_process("/sbin/init");
run_init_process("/etc/init");
run_init_process("/bin/init");
run_init_process("/bin/sh");
panic("No init found. Try passing init= option to kernel.");
}
busybox的init进程在启动起来之后,会自动解析/etc/inittab中所列出的各项,其中每一条目定义一个子进程,格式如下<id>:<runlevel>:<action>:<process>。例如;
ttySACO::askfirst:-/bin/sh
id字段表示使用控制台,runlevel对于此字段没有意义,askfirst表示在启动该进程之前,输出“Please press Enter to activate this console”,/bin/sh需要启动的进程,“-”字符表示该进程是交互进程。
编译时出现:
miscutils/taskset.c:17: error: parse error before '*' token
miscutils/taskset.c:18: warning: function declaration isn't a prototype
miscutils/taskset.c: In function `__from_cpuset':
miscutils/taskset.c:22: error: `CPU_SETSIZE' undeclared (first use in this function)
miscutils/taskset.c:22: error: (Each undeclared identifier is reported only once
miscutils/taskset.c:22: error: for each function it appears in.)
miscutils/taskset.c:26: warning: implicit declaration of function `CPU_ISSET'
miscutils/taskset.c:26: error: `mask' undeclared (first use in this function)
miscutils/taskset.c: In function `taskset_main':
miscutils/taskset.c:47: error: `cpu_set_t' undeclared (first use in this function)
miscutils/taskset.c:47: error: parse error before "mask"
miscutils/taskset.c:68: warning: implicit declaration of function `CPU_ZERO'
miscutils/taskset.c:68: error: `new_mask' undeclared (first use in this function)
miscutils/taskset.c:69: error: `CPU_SETSIZE' undeclared (first use in this function)
miscutils/taskset.c:71: warning: implicit declaration of function `CPU_SET'
miscutils/taskset.c:78: error: `mask' undeclared (first use in this function)
make[1]: *** [miscutils/taskset.o] Error 1
make: *** [miscutils] Error 2
google得到:http://hi.baidu.com/zengzhaonong/blog/item/b0895436d24c33dea2cc2b03.html解决方案。
之后有出现:
Trying libraries: crypt m
Library crypt is needed
Library m is needed
Final link with: crypt m
http://blog.csdn.net/gnuhpc/archive/2009/07/05/4322521.aspx
这里说道可以不必理会直接make install。试之,果然在该目录下生成_install目录。ls -al ./bin :
drwxr-xr-x 2 xuqiang xuqiang 4096 2010-04-07 18:38 .
drwxr-xr-x 6 xuqiang xuqiang 4096 2010-04-07 18:41 ..
lrwxrwxrwx 1 xuqiang xuqiang 7 2010-04-07 18:38 addgroup -> busybox
lrwxrwxrwx 1 xuqiang xuqiang 7 2010-04-07 18:38 adduser -> busybox
lrwxrwxrwx 1 xuqiang xuqiang 7 2010-04-07 18:38 ash -> busybox
-rwxr-xr-x 1 xuqiang xuqiang 483424 2010-04-07 18:38 busybox
lrwxrwxrwx 1 xuqiang xuqiang 7 2010-04-07 18:38 cat -> busybox
...
说明这些可执行文件都是busybox的连接文件。
由于上面使用的是shared library,所以需要将程序中使用的库文件添加到/lib中。glibc套件包含若干个动态连接库。一般在安装/usr/local/arm/3.4.1/arm-linux/lib/目录下。
一般而言,开发板中只需要加载器和动态库即可,可以根据程序的以来关系得到需要保留的动态库。需要使用ldd.host来查看。
下载ulibc : http://ftp.ntu.edu.tw/linux/libs/uclibc/
cd uClibc-0.9.28/utils
make
生成ldd.host,可以使用ldd.host来查看以来关系。
xuqiang@ubuntu:~/Embedded/docs/Linux-Embedded/system/mini_fs/bin$ ldd.host busybox
libcrypt.so.1 => /lib/libcrypt.so.1 (0x00000000)
libm.so.6 => /lib/libm.so.6 (0x00000000)
libc.so.6 => /lib/libc.so.6 (0x00000000)
/lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0x00000000)
经过上面的步骤的话,bin,sbin,lib目录已经构建好了,下面开始构建etc目录。
1.创建/etc/inittab
# /etc/inittab
::sysinit:/etc/init.d/rcS
ttySAC0:askfirst:-/bin/sh
::ctrlaltdel:/sbin/reboot
::shutdown:/bin/umount -a -r
说明 :mount -a [-t|-O] ... : mount all stuff from /etc/fstab
2.创建/etc/init.d/rcS,这是个脚本文件,在其中放置需要自动执行的命令。
#!/bin/sh
# ifconfig eth0 192.168.1.17
mount -a
3.创建/etc/fstab,每种文件系统都对应一个独立的行,每行中的字段都有空格或tab键分开。
# maybe the blank is not correct
#device mount-point type options dump fsck order
proc /proc proc defaults 0 0
tmpfs /tmp tmpfs defaults 0 0
构建设备dev目录。这里使用的是mdev来动态的构建。mdev是在busybox中生成,在/sbin/下。
修改fstab文件:
# maybe the blank is not correct
#device mount-point type options dump fsck order
proc /proc proc defaults 0 0
tmpfs /tmp tmpfs defaults 0 0
sysfs /sys sysfs defaults 0 0
tmpfs /tmp tmpfs defaults 0 0
修改rcS文件:
#!/bin/sh
# ifconfig eth0 192.168.1.17
mount -a
mkdir /dev/pts
mount -t devpts devpts /dev/pts
echo /sbin/mdev > /proc/sys/kernel/hotplug
mdev -s
使用medv生辰的串口名是s3c2410_serial0,所以修改inittab文件:
s3c2410_serial0:askfirst:-/bin/sh
手动创建console,null设备。
mkdir dev
sudo mknod console c 5 1
sudo mknod null c 1 3
构建其他的空文件夹。
制作yaffs文件镜像。
下载源码,在utils文件夹中,执行make命令来生成。由于在内核的配置中没有设置CONFIG_YAFFS_DOES_ECC, 所以使用ecc校验函数是:内核源码的drivers/mtd/nand/nand_ecc.c中nand_calculate_ecc函数来实现。所以需要修改mkyaffsimage源码。
mkyaffsimage.c
///////////////////////////////////////////////////////
#include "yaffs_packedtags1.h"
static int write_chunk(__u8 *data, __u32 objId, __u32 chunkId, __u32 nBytes)
{
#ifdef CONFIG_YAFFS_9BYTE_TAGS
yaffs_Tags t;
yaffs_Spare s;
error = write(outFile,data,512);
if(error < 0) return error;
memset(&t,0xff,sizeof (yaffs_Tags));
memset(&s,0xff,sizeof (yaffs_Spare));
t.chunkId = chunkId;
t.serialNumber = 0;
t.byteCount = nBytes;
t.objectId = objId;
if (convert_endian)
{
little_to_big_endian(&t);
}
yaffs_CalcTagsECC(&t);
yaffs_LoadTagsIntoSpare(&s,&t);
yaffs_CalcECC(data,&s);
nPages++;
return write(outFile,&s,sizeof(yaffs_Spare));
#else
yaffs_PackedTags1 pt1;
yaffs_ExtendedTags etags;
__u8 ecc_code[6];
__u8 oobbuf[16];
error = write (outFile, data, 512);
if(error < 0)
{
return error;
}
etags.chunkId = chunkId;
etags.serialNumber = 0;
etags.byteCount = nBytes;
etags.objectId = objId;
etags.chunkDeleted = 0;
yaffs_PackTags1(&pt1, &etags);
yaffs_CalcTagsECC((yaffs_Tags*)&pt1);
memset (oobbuf, 0xff, 16);
memset (oobbuf + 8, &pt1, 8);
nand_calculate_ecc (data, &ecc_code[0]);
nand_calculate_ecc (data + 256, &ecc_code[3]);
oobbuf[0] = ecc_code [0];
oobbuf[1] = ecc_code[1];
oobbuf[2] = ecc_code[2];
oobbuf[3] = ecc_code[3];
oobbuf[6] = ecc_code[4];
oobbuf[7] = ecc_code[5];
nPages++;
return write (outFile, oobbuf, 16);
#endif
}
将上层的文件yaffs_packedtags1.c拷贝到utils中。
修改Makefile
/////////////////////////////////////////////////////
MKYAFFSSOURCES = mkyaffsimage.c nand_ecc.c yaffs_packedtags1.c
MKYAFFSIMAGEOBJS = $(MKYAFFSSOURCES:.c=.o)
将drivers/mtd/nand/nand_ecc.c拷贝到utils中,并修改成(该文件已经修改):
///////////////////////////////////////////////////////////////////////////////
/*
* This file contains an ECC algorithm from Toshiba that detects and
* corrects 1 bit errors in a 256 byte block of data.
*
* drivers/mtd/nand/nand_ecc.c
*
* Copyright (C) 2000-2004 Steven J. Hill (sjhill@realitydiluted.com)
* Toshiba America Electronics Components, Inc.
*
* Copyright (C) 2006 Thomas Gleixner <tglx@linutronix.de>
*
* $Id: nand_ecc.c,v 1.15 2005/11/07 11:14:30 gleixner Exp $
*
* This file is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 or (at your option) any
* later version.
*
* This file is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* You should have received a copy of the GNU General Public License along
* with this file; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*
* As a special exception, if other files instantiate templates or use
* macros or inline functions from these files, or you compile these
* files and link them with other works to produce a work based on these
* files, these files do not by themselves cause the resulting work to be
* covered by the GNU General Public License. However the source code for
* these files must still be made available in accordance with section (3)
* of the GNU General Public License.
*
* This exception does not invalidate any other reasons why a work based on
* this file might be covered by the GNU General Public License.
*/
//////////////////////////////////////////////////
#include "linux/types.h"
#include <linux/kernel.h>
// #include <linux/module.h>
// #include <linux/mtd/nand_ecc.h>
////////////////////////////////////////////////
#include <inttypes.h>
/*
* Pre-calculated 256-way 1 byte column parity
*/
static const unsigned char nand_ecc_precalc_table[] = {
0x00, 0x55, 0x56, 0x03, 0x59, 0x0c, 0x0f, 0x5a, 0x5a, 0x0f, 0x0c, 0x59, 0x03, 0x56, 0x55, 0x00,
0x65, 0x30, 0x33, 0x66, 0x3c, 0x69, 0x6a, 0x3f, 0x3f, 0x6a, 0x69, 0x3c, 0x66, 0x33, 0x30, 0x65,
0x66, 0x33, 0x30, 0x65, 0x3f, 0x6a, 0x69, 0x3c, 0x3c, 0x69, 0x6a, 0x3f, 0x65, 0x30, 0x33, 0x66,
0x03, 0x56, 0x55, 0x00, 0x5a, 0x0f, 0x0c, 0x59, 0x59, 0x0c, 0x0f, 0x5a, 0x00, 0x55, 0x56, 0x03,
0x69, 0x3c, 0x3f, 0x6a, 0x30, 0x65, 0x66, 0x33, 0x33, 0x66, 0x65, 0x30, 0x6a, 0x3f, 0x3c, 0x69,
0x0c, 0x59, 0x5a, 0x0f, 0x55, 0x00, 0x03, 0x56, 0x56, 0x03, 0x00, 0x55, 0x0f, 0x5a, 0x59, 0x0c,
0x0f, 0x5a, 0x59, 0x0c, 0x56, 0x03, 0x00, 0x55, 0x55, 0x00, 0x03, 0x56, 0x0c, 0x59, 0x5a, 0x0f,
0x6a, 0x3f, 0x3c, 0x69, 0x33, 0x66, 0x65, 0x30, 0x30, 0x65, 0x66, 0x33, 0x69, 0x3c, 0x3f, 0x6a,
0x6a, 0x3f, 0x3c, 0x69, 0x33, 0x66, 0x65, 0x30, 0x30, 0x65, 0x66, 0x33, 0x69, 0x3c, 0x3f, 0x6a,
0x0f, 0x5a, 0x59, 0x0c, 0x56, 0x03, 0x00, 0x55, 0x55, 0x00, 0x03, 0x56, 0x0c, 0x59, 0x5a, 0x0f,
0x0c, 0x59, 0x5a, 0x0f, 0x55, 0x00, 0x03, 0x56, 0x56, 0x03, 0x00, 0x55, 0x0f, 0x5a, 0x59, 0x0c,
0x69, 0x3c, 0x3f, 0x6a, 0x30, 0x65, 0x66, 0x33, 0x33, 0x66, 0x65, 0x30, 0x6a, 0x3f, 0x3c, 0x69,
0x03, 0x56, 0x55, 0x00, 0x5a, 0x0f, 0x0c, 0x59, 0x59, 0x0c, 0x0f, 0x5a, 0x00, 0x55, 0x56, 0x03,
0x66, 0x33, 0x30, 0x65, 0x3f, 0x6a, 0x69, 0x3c, 0x3c, 0x69, 0x6a, 0x3f, 0x65, 0x30, 0x33, 0x66,
0x65, 0x30, 0x33, 0x66, 0x3c, 0x69, 0x6a, 0x3f, 0x3f, 0x6a, 0x69, 0x3c, 0x66, 0x33, 0x30, 0x65,
0x00, 0x55, 0x56, 0x03, 0x59, 0x0c, 0x0f, 0x5a, 0x5a, 0x0f, 0x0c, 0x59, 0x03, 0x56, 0x55, 0x00
};
/**
* nand_calculate_ecc - [NAND Interface] Calculate 3-byte ECC for 256-byte block
* @mtd: MTD block structure
* @dat: raw data
* @ecc_code: buffer for ECC
*/
int nand_calculate_ecc(const unsigned char *dat,
unsigned char* ecc_code)
{
uint8_t idx, reg1, reg2, reg3, tmp1, tmp2;
int i;
/* Initialize variables */
reg1 = reg2 = reg3 = 0;
/* Build up column parity */
for(i = 0; i < 256; i++) {
/* Get CP0 - CP5 from table */
idx = nand_ecc_precalc_table[*dat++];
reg1 ^= (idx & 0x3f);
/* All bit XOR = 1 ? */
if (idx & 0x40) {
reg3 ^= (uint8_t) i;
reg2 ^= ~((uint8_t) i);
}
}
/* Create non-inverted ECC code from line parity */
tmp1 = (reg3 & 0x80) >> 0; /* B7 -> B7 */
tmp1 |= (reg2 & 0x80) >> 1; /* B7 -> B6 */
tmp1 |= (reg3 & 0x40) >> 1; /* B6 -> B5 */
tmp1 |= (reg2 & 0x40) >> 2; /* B6 -> B4 */
tmp1 |= (reg3 & 0x20) >> 2; /* B5 -> B3 */
tmp1 |= (reg2 & 0x20) >> 3; /* B5 -> B2 */
tmp1 |= (reg3 & 0x10) >> 3; /* B4 -> B1 */
tmp1 |= (reg2 & 0x10) >> 4; /* B4 -> B0 */
tmp2 = (reg3 & 0x08) << 4; /* B3 -> B7 */
tmp2 |= (reg2 & 0x08) << 3; /* B3 -> B6 */
tmp2 |= (reg3 & 0x04) << 3; /* B2 -> B5 */
tmp2 |= (reg2 & 0x04) << 2; /* B2 -> B4 */
tmp2 |= (reg3 & 0x02) << 2; /* B1 -> B3 */
tmp2 |= (reg2 & 0x02) << 1; /* B1 -> B2 */
tmp2 |= (reg3 & 0x01) << 1; /* B0 -> B1 */
tmp2 |= (reg2 & 0x01) << 0; /* B7 -> B0 */
/* Calculate final ECC code */
#ifdef CONFIG_MTD_NAND_ECC_SMC
ecc_code[0] = ~tmp2;
ecc_code[1] = ~tmp1;
#else
ecc_code[0] = ~tmp1;
ecc_code[1] = ~tmp2;
#endif
ecc_code[2] = ((~reg1) << 2) | 0x03;
return 0;
}
最后make一下,生成mkyaffsimage和mkyaffs2image,使用mkyaffsimage来生成yaffs镜像。
mkyaffsimage mini_fs mini_fs.yaffs
分享到:
相关推荐
嵌入式linux2 6平台搭建之根文件系统制作过程; (一)使用busybox制作Linux根文件系统 (二):nfs服务器配置过程 RedHatAS5环境 (三):开发板通过nfs服务挂载虚拟机指定目录 (四):通过nfs服务挂载根文件...
该文档主要用于详细介绍Linux根文件系统制作过程,可参考步骤流程
linux yaffsyaffs2根文件系统制作工具及说明。。。。。。
第二章 制作根文件系统 19 2.1 根文件系统预备知识 19 2.2、构建根文件按系统 19 2.2.1、建立根文件系统目录 19 2.2.2、建立动态链接库 21 2.2.3 交叉编译Bosybox 21 2.2.4 建立etc目录下的配置文件 24 2.2.5 制作根...
根文件系统制作.
ubi根文件系统制作文档及所需文件都包含在里面了
嵌入式linux根文件系统制作(经典) 汇集了很多情况,应该使用于很多人,希望对别人有帮助
S5PV210的根文件系统制作, S5PV210的根文件系统制作, S5PV210的根文件系统制作,很不错的资料哈。
根文件系统制作
本文基于xilinx的zynq 7z045芯片使用buildroot工具制作根文件系统,并添加网络工具:dropbear、vsftpd、tcpdump、iperf3等,移植mkfs.ext4工具,并添加交叉编译器lib库到根文件系统。
Linux内核移植和根文件系统制作,嵌入式学习必备资料!霍霍……
本文档主要讲述了Arm板的Ubuntu18.04根文件系统的制作,从官网下载Ubuntu文件系统,在里面加入各种需要的软件,最后烧录到开发板,本文压缩包,里面附带自动化脚本文件。
qte带tslib的根文件系统制作,很详细!
内核定制与根文件系统制作:文章简介了如何在ARM9开发环境下,为其裁剪linux内核并编译根文件系统的方法.
uclinux 内核编译 与根文件系统制作