`
ladymaidu
  • 浏览: 678534 次
文章分类
社区版块
存档分类
最新评论

根文件系统制作

 
阅读更多

环境 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

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics