2016년 12월 8일 목요일

BuildRoot 사용법 요약[기초편]

이번 blog에서는 BuildRoot 사용법을 간략히 요약해 보고자 한다.
BuildRoot는 kernel, bootloader는 물론이고 1000여개가 넘는 각종 application을 자동으로 build하여, 사용자가 원하는 root file system을  생성시켜 주는 tool로써 Yocto project와 더불어 최근 가장 널리 사용되는 build system 중의 하나이다.

BuildRoot 관련 자세한 내용은 관련 매뉴얼을 참고해 보기로 하고, 여기서는 반드시 알아두어야 할 내용만을 간략히 정리해 보기로 한다. BuildRoot 결과를 확인하기 위한 target board는 지난 시간과 마찬가지로 Atmel SAMA5D3 Xplained board를 사용하였다.

<목차>
1) BuildRoot Source Download & Build 하기
2) NFS Booting 하기 
3) Kernel Configuration 수정하기 
4) Custom BSP 관련 작업하기
5) 신규 Package 추가하기

<BuildRoot  개념도 - 출처 참고 문헌 [5]>


<BuildRoot  vs OpenEmbedded/Yocto - 출처 참고 문헌 [5]>


1. BuildRoot Source Download & Build 하기
BuildRoot source를 download한 후, build하는 과정을 요약해 보면 다음과 같다.

$ git clone git://git.buildroot.net/buildroot
    => git repository로 부터 source code를 내려 받는다.

$ cd buildroot
$ make atmel_sama5d3_xplained_defconfig
    => atmel sama5 xplained board(NAND flash 사용) 환경 값으로 초기화

$ make menuconfig
    => 필요한 설정을 바꾼다. 주요 configuration menu를 정리해 보면 다음과 같다.

<BuildRoot top menu>

<BuildRoot Build options menu>
주) buildroot 관련 option을 지정할 수 있다.

<BuildRoot Toolchain menu>
주) Toolchain 설정을 변경할 수 있다. uClibc, glibc 등에 대한 선택도 가능하다.

<BuldRoot System configuration menu>
주) target system configuration을 지정할 수 있다.

<BuildRoot Kernel menu>
주) linux kernel 관련 설정을 할 수 있다(단, kernel config 자체에 대한 설정은 별도의 명령으로 진행함 - 3절 참조)

<BuildRoot Target packages menu>
주) target board에 올라가는 각종 package를 선택 지정할 수 있다.

<BuildRoot Filesystem images menu>
주> 사용하고자 하는 root file system을 지정할 수 있다.

<BuildRoot Bootloaders menu>
주) bootloader를 선택 지정할 수 있다.


$ make
     => buildroot source를 build한다(Host PC 성능 및 internet 속도에 따라 30분 ~ 1시간 소요)
     => Host PC의 성능에 따라 -jNUMBER option(예: -j8)을 사용하면 됨.

<결과 파일>
buildroot/output/images/
-rw-r--r--  1 chyi chyi     34858 12월  7 16:25 at91-sama5d3_xplained.dtb
                                                                          <= device tree blob(sama5d3 xplained 보드 용)
-rw-r--r--  1 chyi chyi     36453 12월  7 16:25 at91-sama5d3_xplained_pda4.dtb
-rw-r--r--  1 chyi chyi     36461 12월  7 16:25 at91-sama5d3_xplained_pda7.dtb
-rw-r--r--  1 chyi chyi     36461 12월  7 16:25 at91-sama5d3_xplained_pda7b.dtb
-rwxr-xr-x  1 chyi chyi     10620 12월  5 15:10 at91bootstrap.bin
                                                                          <= secondary bootloader 이미지
-rwxr-xr-x  1 chyi chyi     10620 12월  5 15:10 boot.bin
-rw-r--r--  1 chyi chyi 114554880 12월  8 11:51 rootfs.tar
                                                                          <= rootfs tarball
-rw-r--r--  1 chyi chyi  65011712 12월  8 11:51 rootfs.ubi
                                                                          <= ubifs root file system 이미지
-rw-r--r--  1 chyi chyi  62726144 12월  8 11:51 rootfs.ubifs
-rwxr-xr-x  1 chyi chyi     10620 12월  5 15:10 sama5d3_xplained-nandflashboot-uboot-3.8.7.bin
-rwxr-xr-x  1 chyi chyi    476644 12월  7 14:41 u-boot.bin
                                                                          <= u-boot(3rd bootloader) 이미지
-rw-r--r--  1 chyi chyi   4426056 12월  7 16:25 zImage
                                                                          <= kernel 이미지

여기서 잠깐 ! make tips
1) make clean: build 디렉토리, host, staging, target trees, images, toolchain을 포함한 모든 build products를 지울 때 사용함.
2) make distclean: make clean + 모든 configuration 제거 시 사용(초기 상태로 되돌림)


2. NFS Booting하기
이번 절에서는 1절에서 build하여 생성한 image file을 가지고 target board에서 동작시키는 과정을 설명하고자 한다. 편의상 NAND booting 보다는 NFS booting을 시도해 보도록 하자.
NFS booting이 가능하도록 하기 위해서는 사전에 host PC에 tftp server와 NFS server가 정상적으로 설정되어 있어야 한다(이 설정 방법은 인터넷에서 쉽게 확인 가능한 사항이므로 여기서는 생략하기로 함).

<Host PC 설정>
$ cd output/images
$ cp ./zImage /tftpboot
   => kernel image를 /tftpboot 디렉토리로 복사한다.

$ cp ./at91-sama5d3_xplained.dtb /tftpboot
   => device tree blob file을 /tftpboot 디렉토리로 복사한다.

$ mkdir rootfs
$ sudo tar xvf ./rootfs.tar -C rootfs
   => rootfs.tar 파일을 푼다. NFS 부팅시 rootfs로 사용하기 위함임.

</etc/exports file 내용>
/home/chyi/Atmel/buildroot/output/images/rootfs 192.168.1.*(rw,no_root_squash,sync,no_subtree_check)

(*) NFS booting이 가능하려면 kernel config 중 CONFIG_ROOT_NFS feature 등이 enable되어 있어야 한다(아래 내용 참조).


<NFS booting을 위한 kernel config 설정 예>

<Target board u-boot 설정>
Console 상에서 부팅 시작 직전에 <Enter>를 입력하여 u-boot CLI 모드로 진입한 후, 아래 명령을 입력한다.

=> setenv ethaddr 12:34:56:ab:cd:ef
   (*) target board의 ethernet port에 대한 MAC 주소를 설정한다.

=> setenv ipaddr 192.168.1.50
   (*) target board의 ethernet port에 대한 IP 주소를 설정한다.

=> setenv serverip 192.168.1.100
   (*) host PC(nfs server)의 IP 주소를 지정한다.

=> setenv rootpath /home/chyi/Atmel/buildroot/output/images/rootfs
   (*) nfs booting시 사용할 rootfs 위치를 지정한다.

=> setenv nfsboot 'setenv bootargs root=/dev/nfs rw nfsroot=${serverip}:${rootpath}
ip=${ipaddr}:${serverip}::${netmask}::eth0:off console=ttyS0,115200; tftp 0x22000000 zImage; tftp 0x21000000 at91-sama5d3_xplained.dtb; bootz 0x22000000 - 0x21000000'
   (*) nfs booting을 위한 설정을 한다.
   (*) kernel, device tree 내용은 tftp를 통해 download하고, rootfs는 앞서 설정한 위치의 내용을 사용한다.
   (*) bootz 사용법: bootz [address of kernel] [address of ramdisk] [ address of dtb], 위의 경우는 ramdisk를 사용하지 않으므로 '-'로 표시함.

=> saveenv
   (*) 지금까지 설정한 내용을 저장한다.

=> run nfsboot
   (*) nfs booting을 시작한다.


<NFS booting 모습>


3. Kernel Configuration 수정하기
이번 절에서는 default kernel config 파일(예: sama5_defconfig)을 새로운 것(예: sama5_chyi_defconfig)으로 교체하는 방법을 소개해 보고자 한다.

$ make menuconfig
   (*) kernel configuration 지정 방법을 변경하기 위해 아래 내용을 수행한다.

    Kernel  --->
         Kernel configuration (Using an in-tree defconfig file)
         Kernel configuration (Using a custom (def)config file)로 변경 

(*) 새로운 config file에 대한 full path를 입력한다.
              ex) /home/chyi/Atmel/buildroot/output/build/linux-linux4sam_5.5/arch/arm/configs/sama5_chyi_defconfig



$  make linux-menuconfig
   (*) linux kernel configuration을 원하는 내용으로 수정한다.
   (*) 참고로 sama5d3 xplained의 경우는 output/build/linux-linux4sam_5.5 에  kernel source가 위치함.

$ make linux-update-defconfig
   (*) 앞서 변경한 kernel configuration을 저장한다.
   (*) ~/buildroot/output/build/linux-linux4sam_5.5/arch/arm/configs/sama5_chyi_defconfig 파일 내용이 변경될 것임.

make savedefconfig BR2_DEFCONFIG=configs/atmel_sama5d3_xplained_defconfig
   (*) 앞서 변경한 buildroot 전체 configuration 내용을 저장한다.

여기서 잠깐 !
buildroot에서 kernel만 재 build를 하려면 어찌해야 할까 ? 답은 아래와 같다.
$ make linux-rebuild

마찬가지 원리로, uboot을 재 build하려면, make uboot-rebuild 명령을 사용하면 된다.


4. Custom BSP  관련 작업하기
이번 절에서는 신규 target board를 이용하여 개발 진행시, u-boot, device tree, kernel 등 BSP 작업과 관련하여 buildroot를 어떻게 수정하는지에 관련된 사항을 정리해 보고자 한다.

4.1 새로운 target board 에 맞는 U-Boot  작업하기
<TBD>

4.2 새로운 target board에 맞는 Kernel 작업하기
<TBD>


5. 신규 Package 추가하기
BuildRoot에 application(binary 및 각종 환경 file 포함) 혹은 kernel module을 포함시키는 방법은 크게 2가지로 나누어 생각해 볼 수 있다. 하나는 BuildRoot에 package를 추가하는 일반(정식) 방식을 따르는 것이고, 다른 하나는 buildroot toolchain을 사용하여 외부에서 build한 후, rootfs에 binary만 포함시키는 방식(overlay 방식이라고 함)이 되겠다.

5.1 수동으로 build한 후, binary file만 buildroot에 추가하기(Overlay 방식)
BuilRoot package를 이용하여 build하는 것이 다소 어려울 경우에는 외부에서 별도로 build한 후, 아래의 방식을 이용하여 rootfs에 해당 binary만을 포함시켜 사용하는 것이 가능하다.

$ export PATH=<PATH_TO_BUILDROOT>/output/host/usr/bin:$PATH
  => output/host/usr/bin 아래에 buildroot toolchain이 자리하고 있음.
=============================================================
lrwxrwxrwx 1 chyi chyi      32 12월  5 14:50 arm-linux-ar -> arm-buildroot-linux-gnueabihf-ar
lrwxrwxrwx 1 chyi chyi      32 12월  5 14:50 arm-linux-as -> arm-buildroot-linux-gnueabihf-as
lrwxrwxrwx 1 chyi chyi      37 12월  5 14:50 arm-linux-c++filt -> arm-buildroot-linux-gnueabihf-c++filt
lrwxrwxrwx 1 chyi chyi      17 12월  5 14:50 arm-linux-cc -> toolchain-wrapper
lrwxrwxrwx 1 chyi chyi      40 12월  5 14:50 arm-linux-cc.br_real -> arm-buildroot-linux-gnueabihf-cc.br
_real
lrwxrwxrwx 1 chyi chyi      17 12월  5 14:50 arm-linux-cpp -> toolchain-wrapper
lrwxrwxrwx 1 chyi chyi      41 12월  5 14:50 arm-linux-cpp.br_real -> arm-buildroot-linux-gnueabihf-cpp.
br_real
lrwxrwxrwx 1 chyi chyi      37 12월  5 14:50 arm-linux-elfedit -> arm-buildroot-linux-gnueabihf-elfedit
lrwxrwxrwx 1 chyi chyi      17 12월  5 14:50 arm-linux-gcc -> toolchain-wrapper
lrwxrwxrwx 1 chyi chyi      17 12월  5 14:50 arm-linux-gcc-5.4.0 -> toolchain-wrapper
lrwxrwxrwx 1 chyi chyi      47 12월  5 14:50 arm-linux-gcc-5.4.0.br_real -> arm-buildroot-linux-gnueabih
f-gcc-5.4.0.br_real
lrwxrwxrwx 1 chyi chyi      36 12월  5 14:50 arm-linux-gcc-ar -> arm-buildroot-linux-gnueabihf-gcc-ar
lrwxrwxrwx 1 chyi chyi      36 12월  5 14:50 arm-linux-gcc-nm -> arm-buildroot-linux-gnueabihf-gcc-nm
lrwxrwxrwx 1 chyi chyi      40 12월  5 14:50 arm-linux-gcc-ranlib -> arm-buildroot-linux-gnueabihf-gcc-r
anlib
lrwxrwxrwx 1 chyi chyi      41 12월  5 14:50 arm-linux-gcc.br_real -> arm-buildroot-linux-gnueabihf-gcc.
br_real
lrwxrwxrwx 1 chyi chyi      34 12월  5 14:50 arm-linux-gcov -> arm-buildroot-linux-gnueabihf-gcov
lrwxrwxrwx 1 chyi chyi      39 12월  5 14:50 arm-linux-gcov-tool -> arm-buildroot-linux-gnueabihf-gcov-t
ool
lrwxrwxrwx 1 chyi chyi      35 12월  5 14:50 arm-linux-gprof -> arm-buildroot-linux-gnueabihf-gprof
lrwxrwxrwx 1 chyi chyi      32 12월  5 14:50 arm-linux-ld -> arm-buildroot-linux-gnueabihf-ld
lrwxrwxrwx 1 chyi chyi      36 12월  5 14:50 arm-linux-ld.bfd -> arm-buildroot-linux-gnueabihf-ld.bfd
lrwxrwxrwx 1 chyi chyi      32 12월  5 14:50 arm-linux-nm -> arm-buildroot-linux-gnueabihf-nm
lrwxrwxrwx 1 chyi chyi      37 12월  5 14:50 arm-linux-objcopy -> arm-buildroot-linux-gnueabihf-objcopy
lrwxrwxrwx 1 chyi chyi      37 12월  5 14:50 arm-linux-objdump -> arm-buildroot-linux-gnueabihf-objdump
lrwxrwxrwx 1 chyi chyi      36 12월  5 14:50 arm-linux-ranlib -> arm-buildroot-linux-gnueabihf-ranlib
lrwxrwxrwx 1 chyi chyi      37 12월  5 14:50 arm-linux-readelf -> arm-buildroot-linux-gnueabihf-readelf
lrwxrwxrwx 1 chyi chyi      34 12월  5 14:50 arm-linux-size -> arm-buildroot-linux-gnueabihf-size
lrwxrwxrwx 1 chyi chyi      37 12월  5 14:50 arm-linux-strings -> arm-buildroot-linux-gnueabihf-strings
lrwxrwxrwx 1 chyi chyi      35 12월  5 14:50 arm-linux-strip -> arm-buildroot-linux-gnueabihf-strip
...
=============================================================

$ mkdir -p board/<YOUR_NEW_TARGET_BOARD>/overlay
  => 여기에 binary 및 etc file 등 복사. 단, rootfs에 맞게 디렉토리 구조를 유지해 주어야 함.
  => 아래 예 참조 
=============================================================
chyi@earth:~/Atmel/buildroot/board/chyi/overlay$ ls -al
합계 16
drwxrwxr-x 4 chyi chyi 4096 12월  8 11:09 .
drwxrwxr-x 3 chyi chyi 4096 12월  8 11:09 ..
drwxrwxr-x 2 chyi chyi 4096 12월  8 11:09 bin
drwxrwxr-x 3 chyi chyi 4096 12월  8 11:28 etc
chyi@earth:~/Atmel/buildroot/board/chyi/overlay$ cd bin/
chyi@earth:~/Atmel/buildroot/board/chyi/overlay/bin$ ls -l
합계 8
-rwxr-xr-x 1 chyi chyi 5524 12월  8 11:09 hello_world  (이 파일을 사전에 복사해 둠)
chyi@earth:~/Atmel/buildroot/board/chyi/overlay/bin$ cd ../etc
chyi@earth:~/Atmel/buildroot/board/chyi/overlay/etc$ ls -l
합계 4
drwxrwxr-x 2 chyi chyi 4096 12월  8 11:28 init.d
chyi@earth:~/Atmel/buildroot/board/chyi/overlay/etc$ cd init.d/
chyi@earth:~/Atmel/buildroot/board/chyi/overlay/etc/init.d$ ls -l
합계 4
-rwxr-xr-x 1 chyi chyi 289 12월  8 11:25 S09hello (이 파일을 사전에 복사해 둠)
chyi@earth:~/Atmel/buildroot/board/chyi/overlay/etc/init.d$ 
=============================================================

$ make menuconfig
   System configuration -->
      () Root filesystem overlay directories 
      (board/chyi/overlay) Root filesystem overlay directories 로 수정 

$ make
   => 이후 NFS booting하여 내용 확인하면 됨.


5.2 Package를 추가하기(일반적인 방법)
앞선 overlay 방법이 buildroot를 통해 build하는데 어려움이 있을 경우 사용하는 방법이라면, 아래 설명하는 방법은 buildroot에서 제공하는 일반적인 방법이라고 할 수 있다. 아래 내용을 이해하기 위해서는 참고 문헌 [2] 혹은 [3]을 필독하기 바란다.

$ cd package
$ mkdir hello_world
$ vi Config.in
config BR2_PACKAGE_HELLO_WORLD
    bool "hello_world"
    default n
    help
    This is a hello world package to show how to integrate a new
    package into Buildroot.

$ vi hello_world.mk
#
# Test mk file for hello world
#

HELLO_WORLD_VERSION = 0.0.1
HELLO_WORLD_SITE = $(TOPDIR)/../misc/test/src   #이곳에 Makefile, hello.c 위치함.
HELLO_WORLD_SITE_METHOD = local
HELLO_WORLD_LICENSE = GPLv2+

define HELLO_WORLD_BUILD_CMDS
    $(MAKE) $(TARGET_CONFIGURE_OPTS) -C $(@D)
endef

define HELLO_WORLD_INSTALL_TARGET_CMDS
    $(INSTALL) -m 0755 -D $(@D)/hello_world $(TARGET_DIR)/usr/bin/helloworld
endef

$(eval $(generic-package))

$ cd ..
$ vi Config.in
...
menu "Miscellaneous"
    source "package/aespipe/Config.in"
    source "package/bc/Config.in"
    source "package/clamav/Config.in"
    source "package/collectd/Config.in"
    source "package/domoticz/Config.in"
    source "package/empty/Config.in"
    source "package/gnuradio/Config.in"
    source "package/googlefontdirectory/Config.in"
    source "package/gr-osmosdr/Config.in"
    source "package/gsettings-desktop-schemas/Config.in"
    source "package/haveged/Config.in"
#test code - added by chunghan.yi@gmail.com - 12/05/2016
    source "package/hello_world/Config.in"
    source "package/mcrypt/Config.in"
    source "package/mobile-broadband-provider-info/Config.in"
    source "package/qemu/Config.in"
    source "package/qpdf/Config.in"
    source "package/shared-mime-info/Config.in"
    source "package/snowball-init/Config.in"
    source "package/taskd/Config.in"
    source "package/wine/Config.in"
    source "package/xutil_util-macros/Config.in"
endmenu
...

$ cd ..
$ make menuconfig
  Target packages --->
      Miscellaneous --->
         [*] hello_world

<앞서 추가한 hello_world package 선택 화면>

$ make
   => 이후 NFS booting하여 내용 확인하면 됨.


여기서 잠깐 ! make tips for package - 패키지를 별도로 build하고자 할때 사용 가능한 option ...
$ make <package>-<target>
  => target 자리에 올 수 있는  option을 정리해 보면 다음과 같다.
  => 가령, test1 package를 재 build하려면, $ make test1-rebuild 해주면 된다. 단, 이 경우, output/build/test1-VERSION 디렉토리를 제거 후, 시도해야 할 수도 있다.




이상으로 간단하게 나마 BuildRoot 사용법(기초편)을 정리해 보았다. 실제로 BuildRoot를 제대로 사용하기 위해서는 Make 문법과 BuildRoot mk file 문법을 제대로 이해할 필요가 있다. 본 blog에서는 이러한 내용을 따로 정리하지는 않았는데, 이 내용과 관련해서는 아래 문서(특히 문서 [2])를 참조해 보기를 권한다. 추후 시간이 되면 BuildRoot 2탄 고급편을 작성해서 올리도록 할 예정이다.


References
1. http://www.at91.com/linux4sam/bin/view/Linux4SAM/BuildRoot
2. buildroot-slides.pdf - free-electrons(http://free-electrons.com/docs/)
3. https://buildroot.org/downloads/manual/manual.pdf
4. Mastering Embedded Linux Programming Chapter 6 - Chris Simmonds, PACKT Publishing.
5. Buildroot2.pdf - Buildroot: a nice, simple and efficient embedded Linux build system - free-electrons.


Slowboot

댓글 3개:

  1. 좋은 글 잘 읽었습니다 감사합니다^^

    답글삭제
  2. 안녕하세요. 좋은 글 잘 읽었습니다.
    궁금한 사항이 있어 문의 드립니다.
    Embedded Linux는 OS 종류 같은 개념이 없는 건가요? Ubuntu나 Debian같은...
    Host PC에서는 어떤 OS를 깔던지 buildroot로 컴파일을 하면 생성되는 결과물은
    Host PC에서 어떤 OS를 깔았던 상관없이 결과물이 나오는 건지요?

    답글삭제
  3. 많은 도움이 되었습니다. ^^

    답글삭제