ARM 임베디드 리눅스 포팅

우선 임베디드 리눅스 입문에 좋은 책. 그리고 한번 읽어볼 만한 문서

회사의 요구로 인해 나이들어 난생 처음 임베디드 분야를 접하고 있음. (오호!!)
이 글은 회사의 보드(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:0x38000” 라는 문구가 보임.
이 문구는 SD램의 0xc0008000 번지에 0x38000 사이즈로 부트로더가 올라가있음을 알려주는것임.

참고로 플래시 메모리 영역은 커널의 특정 파일(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,
        }

0x0~0x40000은 부트로더 영역, 0x40000 ~ 0x400000는 커널 영역, 0x400000 ~ 0x800000 램파일 시스템 영역, 0x800000 ~ 끝까지는 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 파라미터의 의미는 플래시 0x40000번지에서 SDRAM의 0xc0008000번지로 0x300000 사이즈만큼 복사하고, 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 파일 시스템이 0x400000 이후부터 이므로 0x400000 부터 끝까지 지움.
(올릴 타겟 보드의 플래시 메모리의 사이즈는 1Gbytes 이므로 0x40000000)
(끝까지 안지우면 커널 부팅시 파일 시스템 마운트중 에러가 발생할 수 있음. 요걸로 몇일 삽질!!!)

이제 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)"
.....

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

Windows 64비트로 드라이버 포팅

Windows 64비트로 드라이버 포팅 할 일이 생겼다.
아래의 문서와 링크를 참고한다.

윈도우 커널모드 드라이버 64비트 포팅.ppt

http://support.microsoft.com/kb/888728/ko

————–

64bit 플랫폼은 x64와 IA64가 있다.
IA64는 진정한 Real 64bit 운영체제를 위한 CPU로써 인텔 HP Microsoft의 공동 작품.
그리고 x64는 AMD에서 인텔의 64비트 프로세서에 대응하기 위해 Memory Addressing 영역을 2의 64승까지 늘린 프로세서.
IA64는 비싼가격이기에 보통 일반 유저는 사용하지 않는다.

————–

빌드시 error C2220: warning treated as error – no ‘object’ file generated 에러가 난다면 아래를 Sources 파일에 추가한다.

!if $(FREEBUILD)
MSC_WARNING_LEVEL=/W1
!else
MSC_WARNING_LEVEL=/W3
!endif

그래도 안되면.. /W1 부분을 /W0 으로 변경한다.

————–
64비트 드라이버는 반드시 인증을 거쳐야한다.
인증을 받지 않은 드라이버는 로딩조차 되지 않는다.

설치시 아래와 같은 화면이 뜬다.
ivory2

아래와 같이 사용할 수 없다.
ivory

개발시에는 테스트 모드로 부팅해서 개발이 가능하다.
하지만 어차피 인증은 받아야 하는데, 대략 1년에 40만원 정도라한다.
인증 방법은 여기, 여기 를 본다.

인증 업체는 아래와 같다.

Baltimore CyberTrust
Equifax Secure
GTE CyberTrust
GlobalSign
GeoTrust
VeriSign

——————
윈도우즈 7 테스트 모드로 변경 및 드라이버 파일(.sys) 에 테스트 사인 삽입 프로그램
(개발자들이 필요한 프로그램)

dseo13b.7z

sc

——————

아래는 64비트에 와서 갑자기 인증 방법이 왜 생겼는지에 대한 마소의 답변이다.

결론: 보안을 위해서 인증을 사용한다.

출처: http://www.driveronline.org/bbs/view.asp?tb=systembbs&no=12

대충의 내용을 살펴보면 아래와 같습니다.

Q. kernel-mode code signing을 하는 이유는 무엇이냐
커널 모드 code를 사용하는 악성코드가 많이 늘어났기 때문에

Q. 32Bit는 안하고 64Bit 에서만 하는 이유는?
32Bit를 할경우 이미 많은 드라이버가 설치 되어 있어서 문제가 많이 발생한다.
아주 적은 Driver 만이 64Bit에서 동작하고 있기 때문에 64Bit에서만 한다.

Q. 32Bit version을 가지고 있는데 signed 받아야 하나?
64Bit 모듈과 32Bit 모듈 둘다 제공 한다면 MS에서는 인증 받으라고 권하고 있다.

Q. 왜 그룹 Policy 적책으로 신뢰하게 하지 않는가
악성코드들이 이용할 수 있기 때문에 MS 에서는 허용하지 않는다.

Q. 왜 VeriSign 으로 부터 $499 짜리 인증서가 필요한가?
믿을만한 인증기관에서 인증을 받아야 한다고 한다. 전세계에 판매하는 Software에서 $499는 작은 돈이라고 한다.

Q. 왜 VeriSign만 되는가 다른 CA가 안되는 이유?
현재 MS가 OCA, WER 에서 VeriSign의 인증을 사용하고 있기 때문이고 다른 CA하고도 진행중이다.

Q. $500은 나에게 비싸다 다른 방법이 없겠나?
^^; 인증을 받는것이 더 좋다는 이야기 뿐이네요

Q. 이것은 DRM 적책의 시작인가?
아니다 보안과 품질을 향상 시키고자 하는 것이다.

Q. 왜 Windows Logo, DRS대신 signing 이 필요한 것인가?
Logo, DRS는 보안영역에 대한 보증을 하지 못한다 signing을 사용해야 한다.

————–
출처: http://www.driveronline.org/bbs/view.asp?tb=drivetc&no=948

H/W 를 사용하는 DeviceDriver 라면 WHQL 인증을 받으셔야 합니다.
(WHQL 인증방법: http://www.sinwoong.co.kr/144)
이것은 지금 DTM 으로 변경되었지요
결국 Microsoft 가 원하는 방식으로 Code 가 작성되고 동작하는지 검증을 받은 후 Microsoft 에서 해당 드라이버가 안전하다는 인증을 해주는 것 입니다.
그러나 파일 필터와 같이 장치를 사용하지 않는 드라이버에 대해서는 DTM 을 통하지 않고 SelfSing 을 진행 합니다.
필터 드라이버와 같이 자주 Update 하는 드라이버를 DTM 인증을 통하면 너무 많은 시간이 걸리기 때문에 다른 길을 열어 준 것 입니다.
방법은 Test sing 한 것과 비슷 합니다.
먼저 Microsoft 의 whdc 사이트에서 cross sign 을 지원하는 cross certification 을 지원하는 회사에서 인증서를 하나 구입하신 후 아래 site 에서 cross sing 인증서를 다운 받으신 후 구입하신 인증서와 cross 인증서를 사용하여 인증하시면 됩니다.
이 게시판에 인증에 대한 이야기가 있으므로 검색해보세요
그리고 보다 자세한 내용은 아래 사이트를 참고하세요

————–

바이너리 호환(.sys)은, 64bit 시스템에서 사용하는 드라이버는 64bit 컴파일러로 만든 바이너리 파일 이여야 한다.
32bit 컴파일러에서 만든 바이너리 파일은 응용프로그램에서는 wow64를 통해서 허용 되지만, 드라이버 파일에서는 허용되지 않는다.
반드시 64bit 컴파일러로 컴파일해서 사용한다.