L I N U X

Arm embedded linux porting

53프로 2012. 3. 9. 11:36

Cramfs 로 검색을 하다가 지금 내가 하고 있는 일이랑 무척 많이 연관이 되어 있는 부분을 발견하고 스크립해 놓는다.
내가 쓰는 보드도 같고 ..... 하지만 따라 했는데 잘 안된다......좀더 공부 해보고 내 개발 환경에 맞게 좀더 추가 해야되겠다


http://blog.tcltk.co.kr/?p=2250

-
------------------------------------------------------------------------------------------------------------

회사의 요구로 인해 나이들어 난생 처음 임베디드 분야를 접하고 있음. (오호!!)
이 글은 회사의 보드(ARM9 베이스드)에 리눅스를 포팅하기 위한 전초 단계로, 먼지더미에 굴러다니는 보드에 리눅스 포팅을 먼저 해보기로 결정.
타켓 보드는 ARM11 베이스드 삼성 S3C6410.

사실 말이 좋아 포팅이지 있는거 그대로 빌드만 해보고 테스트해봄.
대부분의 arm 코어에 포팅한다는 것은 리눅스 커널 포팅보다 디바이스 드라이버 포팅에 더 가깝다고 봄.
즉 리눅스 드라이버를 개발해본 경험이 있는 나로서는 다행이라 생각함.

호스트 리눅스 설치

브엠웨어에 ubuntu 10.10 을 설치한다.

삼바설정을 해두면 편한데 이 블로그 카테고리에 Virtual Machine을 클릭하면 나옴.

크로스 컴파일러 설치

% tar xvf arm-2008q3.tar.bz2

환경변수 PATH에 추가한다.

export PATH=$PATH:/home/ihmin/Works/arm-linux/arm-2008q3/bin
 
$ source ~/.bashrc

컴파일러 버전을 확인해봄.

ihmin@ubuntu:~/Works/arm-linux$ arm-linux-gcc -v
Using built-in specs.
Target: arm-none-linux-gnueabi
Configured with: /scratch/julian/lite-respin/linux/src/gcc-4.3/configure --build=i686-pc-linux-gnu --host=i686-pc-linux-gnu --target=arm-none-linux-gnueabi --enable-threads --disable-libmudflap --disable-libssp --disable-libstdcxx-pch --with-gnu-as --with-gnu-ld --enable-languages=c,c++ --enable-shared --enable-symvers=gnu --enable-__cxa_atexit --with-pkgversion='Sourcery G++ Lite 2008q3-72' --with-bugurl=https://support.codesourcery.com/GNUToolchain/ --disable-nls --prefix=/opt/codesourcery --with-sysroot=/opt/codesourcery/arm-none-linux-gnueabi/libc --with-build-sysroot=/scratch/julian/lite-respin/linux/install/arm-none-linux-gnueabi/libc --with-gmp=/scratch/julian/lite-respin/linux/obj/host-libs-2008q3-72-arm-none-linux-gnueabi-i686-pc-linux-gnu/usr --with-mpfr=/scratch/julian/lite-respin/linux/obj/host-libs-2008q3-72-arm-none-linux-gnueabi-i686-pc-linux-gnu/usr --disable-libgomp --enable-poison-system-directories --with-build-time-tools=/scratch/julian/lite-respin/linux/install/arm-none-linux-gnueabi/bin --with-build-time-tools=/scratch/julian/lite-respin/linux/install/arm-none-linux-gnueabi/bin
Thread model: posix
gcc version 4.3.2 (Sourcery G++ Lite 2008q3-72)
ihmin@ubuntu:~/Works/arm-linux$

tftp 서버 설치

이 과정은 여기서 사용할 타겟보드에서는 필요없음.
SD카드로 올리면 되나까.

어쨌든 SD카드가 없다면 우선 부트 로더를 빌드하기 전에 부트로더 빌드후에 생성되는 부트 이미지를 보드에 전송하기 위한 환경을 아래와 같이 셋팅함.

% sudo apt-get install xinetd (ubuntu 10.10에서 필요한지 모르겠음)
% sudo apt-get install tftp tftpd
% sudo apt-get install tftpd-hpa
% sudo mkdir tftpboot
% sudo chmod 777 tftpboot

다음 아래의 파일을 수정.

% sudo vim /etc/default/tftpd-hpa
 
# /etc/default/tftpd-hpa
TFTP_USERNAME="nobody" <== 가능한 사용자 이름으로 수정
TFTP_DIRECTORY="/tftpboot" <== 수정
TFTP_ADDRESS="0.0.0.0:69"
TFTP_OPTIONS="--secure --create" <== --create추가

다음 재시작.

% sudo service tftpd-hpa restart

다음 테스트.

% cd /tftpboot
% touch test
% cd /tmp
% tftp 127.0.0.1
tftp> get test

부트로더 빌드

부트로더는 운영 체제가 시동되기 이전에 커널이 올바르게 동작되기 위해 필요한 모든 셋팅을 함.
PC에는 이런 작업들을 바이오스가 담당을 하는데 임베디드에서는 바이오스가 없으니 부트로더가 담당을함.
어쨌든 셋팅을 한 후에는 플래시 메모리에서 커널을 읽어들여 에스디램으로 복사하고 적당한 parameter를 커널에 넘겨주는 역할을 수행함.
여기서 보듯이 부트로더는 플래시와 에스디램에 자유롭게 접근가능함.

우선 부트로더 압축을 푼다.

% tar xvf s3c-u-boot-1.1.6-Real6410.tar.bz2
% cd s3c-u-boot-1.1.6-Real6410

다음 configuring을 한다.

% make distclean
% make smdk6410_config
Configuring for smdk6410 board...

nand flash용 부트 이미지를 만든다.

% ./make_nand_image
......
......
/libs3c64xx.a cpu/s3c64xx/s3c6410/libs3c6410.a lib_arm/libarm.a fs/cramfs/libcramfs.a fs/fat/libfat.a fs/fdos/libfdos.a fs/jffs2/libjffs2.a fs/reiserfs/libreiserfs.a fs/ext2/libext2fs.a net/libnet.a disk/libdisk.a rtc/librtc.a dtt/libdtt.a drivers/libdrivers.a drivers/nand/libnand.a drivers/nand_legacy/libnand_legacy.a drivers/onenand/libonenand.a drivers/sk98lin/libsk98lin.a post/libpost.a post/cpu/libcpu.a common/libcommon.a --end-group -L /home/ihmin/Works/arm-linux/compiler/bin/../lib/gcc/arm-none-linux-gnueabi/4.3.2 -lgcc \
-Map u-boot.map -o u-boot
arm-linux-objcopy --gap-fill=0xff -O srec u-boot u-boot.srec
arm-linux-objcopy --gap-fill=0xff -O binary u-boot u-boot.bin
arm-linux-objdump -d u-boot > u-boot.dis

에러 없이 빌드가 되었다면 현재 디렉토리에 u-boot.bin 파일이 생성되어 있으며 자동으로 /tfpboot로 복사된다.

다음 필요하면 SD card용 부트 이미지를 만듬.

% ./make_mmc_image
......
......
/libs3c64xx.a cpu/s3c64xx/s3c6410/libs3c6410.a lib_arm/libarm.a fs/cramfs/libcramfs.a fs/fat/libfat.a fs/fdos/libfdos.a fs/jffs2/libjffs2.a fs/reiserfs/libreiserfs.a fs/ext2/libext2fs.a net/libnet.a disk/libdisk.a rtc/librtc.a dtt/libdtt.a drivers/libdrivers.a drivers/nand/libnand.a drivers/nand_legacy/libnand_legacy.a drivers/onenand/libonenand.a drivers/sk98lin/libsk98lin.a post/libpost.a post/cpu/libcpu.a common/libcommon.a --end-group -L /home/ihmin/Works/arm-linux/compiler/bin/../lib/gcc/arm-none-linux-gnueabi/4.3.2 -lgcc \
-Map u-boot.map -o u-boot
arm-linux-objcopy --gap-fill=0xff -O srec u-boot u-boot.srec
arm-linux-objcopy --gap-fill=0xff -O binary u-boot u-boot.bin
arm-linux-objdump -d u-boot > u-boot.dis

최종적으로 u-boot_mmc.bin 파일이 생성됨.

리눅스 커널 빌드

압축을 푼다.

% tar xvf s3c-linux-2.6.28.6-Real6410.tar.bz2
% cd s3c-linux-2.6.28.6-Real6410

다음 커널을 빌드하는데 커널 빌드 설정 파일은 제공되는 파일을 이용함.
차후 용량을 줄이거나 새로운 디바이스를 지원해야 한다면 설정 파일을 적당히 셋팅해서 다시 빌드해줌.

% make distclean
% cp Real6410.config .config <== 제공해주는 빌드 설정파일을 그대로 이용.
% make
....
....
GZIP    arch/arm/boot/compressed/piggy.gz
AS      arch/arm/boot/compressed/piggy.o
CC      arch/arm/boot/compressed/misc.o
LD      arch/arm/boot/compressed/vmlinux
OBJCOPY arch/arm/boot/zImage
Kernel: arch/arm/boot/zImage is ready
Building modules, stage 2.
MODPOST 2 modules
CC      drivers/net/wireless/libertas/libertas_sdio.mod.o
LD [M]  drivers/net/wireless/libertas/libertas_sdio.ko
CC      drivers/scsi/scsi_wait_scan.mod.o
LD [M]  drivers/scsi/scsi_wait_scan.ko

에러 없이 빌드 되었다면 arch/arm/boot/zImage 에 커널 이미지가 생성된다.

참고로 아래는 커널 이미지 생성순서.

루트 파일 시스템 구축

루트 파일 시스템은 “/” 로 마운트할 수 있는 파일시스템.
즉 /etc, /sbin, /dev, /var, /tmp 등등 중요한 모든 디렉토리와 파일들(설정파일 포함)을 모아놓고 하나의 파일 시스템 이미지로 만드는 과정임.

보통 아래의 단계를 거침.

디바이스 파일 만들기 => 라이브러리 복사 => 초기화 파일및 환경설정 파일 만들기 => 쉘과 시스템 유틸 복사 => 혹은 응용프로그램 복사 => 루트파일 시스템 만들기

임베디드에서는 항상(?) 리소스에 허덕이기 때문에 필요 최소한의 파일 시스템을 구축해야 하는데 busybox가 좋은 대안이 되고 있음.
busybox는 리눅스에서 자주 사용되는 프로그램들(rm, cp, sh, insmod..) 을 임베디드용으로 포팅한 프로젝트이며 이것을 이용하면 용량을 줄일수 있음.

먼저 디렉토리를 생성함.

% mkdir root_mkfs <== 이곳에 파일 시스템을 만들것임.
% cd root_mkfs
% mkdir bin sbin etc dev lib usr mnt proc sys

busybox 설치

다음 busybox를 다운로드 받아 아래와 같이 빌드및 설치함.

% wget http://busybox.net/downloads/busybox-1.18.4.tar.bz2
% tar xvf busybox-1.18.4.tar.bz2
% cd busybox-1.18.4

다음 빌드 옵션을 지정하는데 필요한 프로그램을 빼거나 넣거나 할 수 있다.

% make menuconfig

여기서는 기본으로 하고 그냥 저장하고 나옴. 빌드 옵션 파일인 .config 파일이 생성됨.
마지막으로 빌드및 설치를 하고 _inst 폴더 밑에 제대로 설치가 되었는지 확인함.

% make
% make CROSS_COMPILE=arm-linux- ARCH=arm CONFIG_PREFIX=_inst install <== dynamic 컴파일
% make CROSS_COMPILE=arm-linux- ARCH=arm CFLAGS=--static LDFLAGS=--static CONFIG_PREFIX=_inst install <== static 컴파일

마지막으로 _inst 폴더및의 파일들 전부 root_mkfs 로 복사함.

% cp -af _inst/* ../root_mkfs/

lib 구성

이제 lib 파일들을 복사할 차례.
이 작업은 커널이 최초 부팅후에 init 프로그램을 실행하는데 필요한 라이브러리들을 구성하는 단계임.
만약 전 단계에서 busybox를 dynamic 컴파일 했다면 필요한 공유 라이브러리를 복사해줘야함.
busybox에서 필요로 하는 공유 라이브러리를 확인하는 방법은 아래와 같음.

$ arm-linux-objdump -p busybox | grep ".so"
NEEDED               libm.so.6
NEEDED               libc.so.6
required from libm.so.6:
required from libc.so.6:
 
$ cd /home/ihmin/Works/arm-linux/arm-none-linux-gnueabi/libc/lib
 
$ arm-linux-objdump -p libm.so.6 | grep .so
libm.so.6:     file format elf32-littlearm
NEEDED               ld-linux.so.3
NEEDED               libc.so.6
SONAME               libm.so.6
1 0x01 0x0905f4e6 libm.so.6
required from ld-linux.so.3:
required from libc.so.6:
 
$ arm-linux-objdump -p libc.so.6 | grep .so
libc.so.6:     file format elf32-littlearm
NEEDED               ld-linux.so.3
SONAME               libc.so.6
1 0x01 0x0865f4e6 libc.so.6
required from ld-linux.so.3:
 
$ ls -al libm.so.6 libc.so.6 ld-linux.so.3
lrwxrwxrwx 1 ihmin ihmin  9 2011-05-25 12:32 ld-linux.so.3 -> ld-2.8.so
lrwxrwxrwx 1 ihmin ihmin 11 2011-05-25 12:32 libc.so.6 -> libc-2.8.so
lrwxrwxrwx 1 ihmin ihmin 11 2011-05-25 12:32 libm.so.6 -> libm-2.8.so

최종적으로 busybox는 ld-linux.so.3, ld-2.8.so, libm.so.6, libc.so.6, libm-2.8.so libc-2.8.so 파일이 필요함.

위의 라이브러리는 크로스 컴파일러 arm-none-linux-gnueabi/libc/lib 에 위치해 있으며 lib에 복사해줌.

참고로 위에 보면 복사시 cp -af 옵션을 주어야 하는데 -a 옵션은 혹시 모를 링크파일의 속성을 보존하기 위해서임.

$ cp -af /home/ihmin/Works/arm-linux/arm-none-linux-gnueabi/libc/lib/ld-linux.so.3 lib/
$ cp -af /home/ihmin/Works/arm-linux/arm-none-linux-gnueabi/libc/lib/ld-2.8.so lib/
$ cp -af /home/ihmin/Works/arm-linux/arm-none-linux-gnueabi/libc/lib/libm.so.6 lib/
$ cp -af /home/ihmin/Works/arm-linux/arm-none-linux-gnueabi/libc/lib/libc.so.6 lib/
$ cp -af /home/ihmin/Works/arm-linux/arm-none-linux-gnueabi/libc/lib/libm-2.8.so lib/
$ cp -af /home/ihmin/Works/arm-linux/arm-none-linux-gnueabi/libc/lib/libc-2.8.so lib/

만약 busybox를 static으로 컴파일 했다면 위의 파일들을 lib으로 복사해줄 필요가 없음.

dev 구성

dev 폴더내에서 아래의 디바이스 노드를 만듬. 반드시 루트권한을 주어 만들어야함.

$ sudo mknod tty c 4 0
$ sudo mknod tty1 c 4 1
$ sudo mknod tty2 c 4 2
$ sudo mknod tty3 c 4 3
$ sudo mknod tty4 c 4 4
$ sudo mknod console c 5 1
$ sudo mknod null c 1 3
$ sudo mknod zero c 1 5

이외것들 구성

etc usr mnt proc sys 등은 따로 파일을 적절히 만들어서 넣으면 됨.

램 디스크 이미지 생성

마지막으로 위와 같이 꾸민 정보로 램 디스크 파일 시스템 이미지를 생성함.

$ dd if=/dev/zero of=rootfs_rd.img bs=1K count=25k <== 25M 크기 이미지 생성
$ mke2fs rootfs_rd.img <== ext2 파일 시스템을 생성한다. 머라 물어보는 y를 입력한다.
 
생성된 이미지를 마운트하여 파일들을 복사함.
$ mkdir tmp
$ sudo mount rootfs_rd.img tmp -o loop <== 이미지 마운트
$ sudo cp -af root_mkfs/* tmp/ <== 복사
$ sudo umount tmp <== 언마운트
$ gzip -9 rootfs_rd.img <== 압축

JFFS2 디스크 이미지 생성

램 디스크를 파일 시스템으로 사용한다면 전원이 나감과 동시에 데이타도 손실이 됨.
때문에 플래시 메모리를 파일 시스템으로 사용해야 하는데 이때 JFFS2 (Journalling Flash File System, version 2)를 사용하며 JFFS2는 MTD(Memory Technology Device) 계층위에서 동작.
(YAFFS 라는것도 많이 사용된다고 함.)

우선 위에서 빌드한 리눅스 커널에 JFFS2 기능이 함되어 빌드되어 있는지 확인함.
안되어 있으면 옵션을 켜서 다시 빌드해줘야함.

$ make menuconfig

커널 설정 화면이 뜨면 “Filesystems” > “Miscellaneous filesystems” > “Journalling Flash File System v2 (JFFS2) support” 를 켜줌.
(* 는 커널에 포함되는것이고, M은 모듈형태로 빌드 되는것임.)

그리고 다시 빌드.

$ make

이제 본론으로 돌아와서 아래와 같이 파일 시스템을 빌드함.
램 디스크보다 쉬움.

mkfs.jffs2 -d root_mkfs -o rootfs_jffs2.img

생성된 이미지를 마운트해봄.

$ sudo modprobe mtdblock
$ sudo modprobe mtdram
$ sudo modprobe jffs2
 
$ sudo dd if=rootfs_jffs2.img of=/dev/mtdblock0
$ sudo mount /dev/mtdblock0 ./tmp -t jffs2
 
$ sudo umount ./tmp

루프 파일 시스템 지정

이제 리눅스 커널에 위에서 생성한 루트 파일시스템을 지정해야하는데, 여기서는 위에서 만든 JFFS2 파일 시스템을 사용함.
커널의 .config 파일을 보면 아래와 같이 CONFIG_CMDLINE 이 있는데 여기에 지정해야함.

아래와 같이 수정하고 커널 이미지 다시 생성.

CONFIG_CMDLINE="rootfstype=jffs2 root=/dev/mtdblock2 init=/init console=ttySAC1,115200"
 
$ make zImage

커널 부팅하기

이제 마지막으로 리눅스 커널을 보드에 올려 부팅해봐야함.
참고로 보드는 아래와 같이 생겼음.

중요 코어 보드를 확대해보면.

1번은 1G 바이트 낸드 플래시 메모리 .
2번은 ARM S3C6410 코어.
3번은 이더넷 콘트롤러.
4번은 256M 바이트 DDR SDRAM.
5번은 AC’97 오디오 코덱 하고 터치 스크린 판넬 코덱.

부트로더 올리기

부트로더를 플래시 메모리에 올리는 방법은 타겟 보드마다 다른데, 현재 타겟 보드는 SD 카드로 부팅이 가능하므로 SD 카드로 구울것임.

(SD카드 지원이 안된다면 타겟 보드에 이더넷 케이블을 연결해서 tftp로 구우면됨.)

우선 SD 카드 리더기를 호스트 PC에 연결하고 리더기에 SD 카드를 넣음.
IROM_Fusing_Tool.exe 프로그램을 실행한후
위에 부트로더 빌드시에 SD카드용 부트로더를 빌드했는데 그 파일(u-boot_mmc.bin)을 넣어줌.
그리고 SD카드 드라이브로 골라주고 START 버튼을 누르면 됨.

“..done” 뜨면 제대로 구워진것임. 하지만 제대로 구워졌는지 확인시 헥사 에디터로 열어서 확인해 볼수도 있음.

다음 타겟 보드에서 SD 카드로 부팅하기 위해 점퍼를 셋팅함.

마지막으로 SD 카드를 타겟 보드에 넣고 전원을 넣으면, SD 카드로 부팅을 하는데 부팅이 제대로 되었는지 확인할 수 없으므로 이때 dnw.exe 프로그램을 이용하여 메세지를 확인해봐야함.

dnw는 터미널 에뮬레이터와 USB를 통해서 SDRAM으로 부트로더를 다운로드 할수 있는 프로그램임. (dnw 대신에 하이퍼 터미널같은 다른 터미널 프로그램을 이용해도 상과없음.)

우선 dnw를 실행한후 호스트 PC의 포트와 dnw의 포트를 맞춰줌.

dnw의 Configuration -> Options 에서 포트를 바꿀수 있는데, 일단 호스트 PC의 장치 관리자에서 포트 번호를 확인하여 dnw의 포트를 맞추어주고 Serial Port -> Connect를 누름.

다음 타겟 보드를 리셋하면 SD카드에 구웠던 부트로더로 부팅하면서 dnw 프로그램에 메세지가 찍히는것을 아래와 같이 볼수있음.

부트로더는 플래시 메모리와 SDRAM 메모리를 접근할 수 있다고 얘기했음.
이제 플래시 메모리에 부트로더를 구워야함.

이제 터미널에 다음을 입력하여 플래시 메모리를 초기화함.

SMDK6410 # nand erase 0

위와 같이 잘 지워졌음.

이제 터미널에 다음을 입력하여 usb를 통하여 SDRAM으로 부트로더를 복사함.
부트로더는 오프셋 0xc0008000 으로 복사됨.

SMDK6410 # dnw

타겟보드의 USB otg 포트와 호스트 PC의 USB 포트를 케이블로 연결.
다음 타겟보드에서 제공해준 디바이스 드라이버를 설치.

드라이버가 설치되었다면 dnw의 USB Port -> Transmit -> Transmit을 누름.

이제 플래시 메모리용 부트로더를 선택하여 업로드함.

아래와 같이 제대로 SDRAM에 부트로더가 올려짐을 확인.

위의 스샷을 보면 “Download Address: 0xc0008000, Download Filesize:0×38000″ 라는 문구가 보임.
이 문구는 SD램의 0xc0008000 번지에 0×38000 사이즈로 부트로더가 올라가있음을 알려주는것임.

참고로 플래시 메모리 영역은 커널의 특정 파일(arch/arm/plat-s3c/include/plat/partition.h)을 변경하여 정할수 있음.
초기에는 아래와 같이 플래시 영역이 나뉘어져 있었음.

{
.name       = "cramfs",
.offset     = (4*SZ_1M),
.size       = (4*SZ_1M),
},
{
.name       = "ubifs",
.offset     = MTDPART_OFS_APPEND,
.size       = MTDPART_SIZ_FULL,
}

0×0~0×40000은 부트로더 영역, 0×40000 ~ 0×400000는 커널 영역, 0×400000 ~ 0×800000 램파일 시스템 영역, 0×800000 ~ 끝까지는 ubi파일 시스템으로 정해져 있음.

나는 앞으로 jffs2 파일 시스템을 올릴것이므로 아래와 같이 심플하게 수정함.

{
.name       = "Bootloader",
.offset     = 0,
// (0x40000: 256Kbytes) (0x0 ~ 0x40000)
.size       = (256*SZ_1K),
},
{
.name       = "Kernel",
.offset     = (256*SZ_1K),
// (0x3c0000: 3.8Mbytes) (0x40000 ~ 0x400000)
.size       = (4*SZ_1M) - (256*SZ_1K),
},
{
.name       = "Filesystem (jffs2)",
.offset     = MTDPART_OFS_APPEND,
// 0x400000 ~
.size       = MTDPART_SIZ_FULL,
},

그리고 커널 컴파일함.

다시 본론으로 돌아와서 에스디램으로 복사되어 있는 부트로더를 dnw에서 아래의 명령으로 에스디램에서 플래시 메모리로 복사함.
플래시에 쓰기전 반드시 써질 영역을 지워야함.

SMDK6410# nand erase 0 40000
==> 0부터 40000번지까지 지움.
 
SMDK6410# nand write c0008000 0 40000
==> SDRAM c0008000 번지에서 플래시 0번지로 40000 바이트 사이즈 복사.

다음 타겟보드의 점퍼를 플래시 메모리 부팅으로 맞춘후 보드 리셋.

SD카드 없이도 플래시 메모리에 올라가 있는 부트로더로 부팅이 됨을 확인.

다음은 리눅스 커널을 올릴차례.

이제 부팅된 부트로더에서 dnw를 입력하고 커널을 선택하여 에스디램으로 복사.

다시 커널을 플래시로 복사.

SMDK6410# nand erase 40000 300000
 
SMDK6410# nand write c0008000 40000 300000

다음 # printenv를 입력하여 부트로더의 환경변수를 확인.

bootcmd는 부트로더가 부팅후 자동 수행되는 커맨드임.
bootcmd 파라미터의 의미는 플래시 0×40000번지에서 SDRAM의 0xc0008000번지로 0×300000 사이즈만큼 복사하고, bootm으로 0xc0008000으로 점프하여 커널 동작 수행.

또한 bootargs는 커널의 아규먼트로 넘겨주는 변수임.
이 값은 부트로더에서 정해줄수도 있고 커널 코드를 변경하여 고칠수도 있음.
(커널의 설정 파일인 .config 파일의 CONFIG_CMDLINE)

초기의 bootatgs는 ubi 파일시스템으로 셋팅이 되어 있으므로,
jffs2 파일 시스템에 맞게 bootargs 변수값을 아래와 같이 수정.

SMDK6410# setenv bootargs noinitrd init=/linuxrc rootfstype=jffs2 root=/dev/mtdblock2 console=ttySAC0 <== 환경변수 변경
 
SMDK6410 # saveenv <== 환경변수 플래시에 기록
Saving Environment to NAND...
Erasing Nand...Writing to Nand... done
 
SMDK6410 # printenv <== 변경된 값 다시 확인.

이제 jffs2 파일 시스템 이미지를 올릴차례.

우선 파일시스템이 올라갈 플래시 영역을 지움.
앞서 partition.h 파일을 변경 하였는데, jffs2 파일 시스템이 0×400000 이후부터 이므로 0×400000 부터 끝까지 지움.
(올릴 타겟 보드의 플래시 메모리의 사이즈는 1Gbytes 이므로 0×40000000)
(끝까지 안지우면 커널 부팅시 파일 시스템 마운트중 에러가 발생할 수 있음. 요걸로 몇일 삽질!!!)

이제 dnw를 입력하고 파일시스템 이미지를 선택하여 에스디램으로 복사한후 플래시로 복사.

이제 커널을 부팅해본다.

SMDK6410 # nand read c0008000 40000 300000 <== 플래시에 있는 커널을 에스디램으로 복사.
 
SMDK6410 # bootm c0008000 <==  커널 부팅

오호.. 부팅이 되었음.

아래는 커널 부팅 메세지의 일부분중 파일 시스템 관련.

....
S3C NAND Driver, (c) 2008 Samsung Electronics
S3C NAND Driver is using hardware ECC.
NAND device: Manufacturer ID: 0xec, Chip ID: 0xd3 (Samsung NAND 1GiB 3,3V 8-bit)
Creating 3 MTD partitions on "NAND 1GiB 3,3V 8-bit":
0x00000000-0x00040000 : "Bootloader"
0x00040000-0x00400000 : "Kernel"
0x00400000-0x40000000 : "Filesystem (jffs2)"
.....

이제 설정 파일들을 조금씩 만져주고, 디바이스 추가할거 있으면 추가하고..
프로그램 추가할거 있으면 추가하고.. 등등 하면됨.