Yocto에 OSTree upgrade 적용(2) - 부팅 절차
이전글 Yocto에 OSTree upgrade 적용(1) - 이미지 생성 에서는 Yocto 빌드 과정을 통한 target 에 write 할 이미지를 만드는 과정까지 설명 하였다.
이번글에서는 부팅 이미지를 이용하여 부팅 절차를 설명한다.
디스크 이미지 파일
최종적으로 디스크에 쓰는 이미지를 Yocto 의 wic 툴을 이용하여 확인해 보면 다음과 같이 두개의 partition 으로 구성된다.
- Partiton 1(fat16): DOS FAT16 의 부팅 디스크로 u-boot 과 부팅에 필요한 설정 파일이 있다.
- 파일 중 boot.scr 파일이 있는데, 이 파일로 u-boot 의 script를 대체하여 OSTree 이미지가 로드되도록 한다.
- Partition 2(ext4): OSTree용 이미지
|
|
이 중 EXT4 partition은 이전 글에 설명한 것과 같이 아래와 같은 디렉토리를 가진다.
|
|
Bootloader에 관련된 파일들은 첫번째 FAT16 partition에 있고, 위의 디렉토리 구조 중 boot 디렉토리에는 kernel booting에 관련된 파일들이 있다.
특징적인 파일은 다음과 같다.
- /boot/loader/uEnv.txt: kernel 위치와 bootargs 옵션을 정의한다. 파일 내용은 다음과 같다.
|
|
- kernel, initramfs는 위 파일에 있는 /boot/ostree/poky-1f8…f7d/ 안에 있다.
U-Boot 에서 커널 부팅 처리
U-Boot는 Hush Shell 이라는 shell script를 지원한다. 이를 이용하여 기본적인 부팅 정책이 설정되어 있는데, 보통은 다음과 같은 정책을 가진다.
- Block device의 bootable partition 에서
boot.scr
을 찾는다. 이 파일은 U-Boot의 mkimage를 이용하여 패킹한 U-Boot용 script 파일이다. 이 파일이 있으면 이를 로드 후 script 를 실행한다. - 만일
boot.scr
이 없으면 미리 지정된 kernel booting 절차를 수행한다.
Yocto OSTree 이미지에서는 이 boot.scr을 다음과 같이 설정하여 OSTree에 맞도록 부팅을 수행한다.
|
|
위 script를 간단하게 정리하면 다음과 같다.
- EXT4 Partition의 /boot/loader/uEnv.txt 를 읽음. 이곳에는 위에 설명한 것과 같이
kernel_image
,ramdisk_image
,bootargs
값이 있음- ramdisk_image 변수는 U-Boot에서는 사용하지 않고, kernel_image만 사용한다. 여기에서 가리키는 kernel는 U-Boot FIT Image로 kernel, DTB, initramfs 파일이 패킹되어 있다.
- 아래와 같이 bootargs 에
ostree
,ostreee_root
를 설정하고 ramdisk를 rootfs로 initramfs 로 부팅한다.
|
|
Initramfs의 동작
Initramfs로 부팅이 되면 init script에서는 다음과 같은 동작을 수행한다.
환경 변수로 다음과 같이 설정
ostree_root
: /dev/mmcblk0p2 로 EXT4 partitionostree
: /ostree/boot.1/poky/1f8…f7d/0 로 OSTree image가 deploy된 디렉토리
ostreee_root
를 /sysroot 디렉토리에 마운트/sysroot/
${ostree}
/usr를 read-only 가 되도록 bind remount 수행/sysroot/
${ostree}
/deploy/poky/var를 /sysroot/${ostree}
/var 에 마운트 (/var 는 업그레이드에도 바뀌지 않도록 별도의 폴더를 사용)초기 디스크 이미지를 참조할 수 있도록 /sysroot를 /sysroot/
${ostree}
/sysroot 로 bind mount/sysroot/
${ostree}
를 /sysroot 로 mount (Deploy 된 OSTree 이미지)
이렇게 되면 /sysroot 는 ostree
가 가리키는 /ostree/boot.1/poky/1f8…f7d/0 가 되고, 고정된 /var 도 이 안에 마운트 되고, 전체 EXT4 파티션도 symbolic link를 통해서 /sysroot/sysroot 로 된다.
이 상태에서 switch_root 명령으로 /sysroot 를 루트로 전환하여 정상적인 init script가 실행되도록 한다.
이 과정을 거치면 정상적인 부팅이 된다.
디스크 내의 디렉토리가 최종적으로 어떻게 마운트 되었는지를 정리해보면 다음과 같다.
디스크이미지 | 최종 실행된 시스템 | 설명 |
---|---|---|
/ | /sysroot | 전체 디스크 이미지 |
/ostree/deploy/poky/var | /var | Upgrade 에도 영향을 받지 않는 /var 디렉토리 |
/ostree/boot.1/poky/1f8…f7d/0 | / | Deploy된 OSTree 이미지 |
/ostree/repo | /sysroot/ostree/repo | OSTree local repository |
bind mount 관계를 shell 로 확인해 보면 다음과 같다.
|
|
참고로 /etc 를 생성한 소스는 /usr/etc 에 있다. 이를 3-way merge를 통하여 OTA 시 신규 /etc를 만든다.
Target 에 Yocto 적용하기
meta-updater layer에서 Raspberry Pi 와 같이 기존 제공하는 보드가 아닌, 개발하고 있는 제품에 적용하기 위한 절차를 정리하면 다음과 같다.
- layer.conf 에 meta-updater(sota) 의존성 추가
|
|
- bblayers.conf 에
BBLAYERS
에 meta-updater 추가 - local.conf 에
DISTRO
를 poky에서 poky-sota로 변경
|
|
- machine conf (conf/machine/sc-gateway.conf)에
SOTA_MACHINE
추가
|
|
- classes/sota_sc-gateway.bbclass 와 같이
SOTA_MACHINE
에 맞는 bbclass 추가 및 적절히 수정. WKS_FILES 로 wks script 변경
|
|
- wic/sc-gateway-sdcard-image.wks.in 으로 root parition을 otaimge로 변경
|
|
u-boot 을 변경하여 boot.scr을 대체
- u-boot_%.bbappend
1
FILESEXTRAPATHS:prepend:sc-gateway := "${THISDIR}/files:"
- u-boot/boot.cmd
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
setenv loadaddr ${kernel_addr_r} setenv bootcmd_resetvars 'setenv kernel_image; setenv bootargs; setenv kernel_image2; setenv bootargs2' setenv bootcmd_otenv 'run bootcmd_resetvars; load mmc 0:2 $loadaddr /boot/loader/uEnv.txt; env import -t ${loadaddr} ${filesize}' setenv bootcmd_rollbackenv 'setenv kernel_image ${kernel_image2}; setenv bootargs ${bootargs2}' setenv bootcmd_args 'setenv bootargs "${bootargs} ${bootargs_fdt} ostree_root=/dev/mmcblk0p2 root=/dev/ram0 rw rootwait rootdelay=2 ramdisk_size=8192 panic=1"' setenv bootcmd_getroot 'setexpr ostree_root gsub "^.*ostree=([^ ]*).*$" "\\\\1" "${bootargs}";' setenv bootcmd_load 'load mmc 0:2 ${ramdisk_addr_r} "/boot"${kernel_image}' setenv bootcmd_run 'bootm "${ramdisk_addr_r}"' setenv bootcmd_create_envfile 'if test ! -e mmc 0:1 uboot.env; then saveenv; fi;' setenv bootlimit 3 setenv bootcmd 'if test "${rollback}" = "1"; then run altbootcmd; else run bootcmd_create_envfile; run bootcmd_otenv; run bootcmd_args; run bootcmd_load; run bootcmd_run; if ! "${upgrade_available}" = "1"; then setenv upgrade_available 1; saveenv; fi; reset; fi' setenv bootcmd_set_rollback 'if test ! "${rollback}" = "1"; then setenv rollback 1; setenv upgrade_available 0; saveenv; fi' setenv altbootcmd 'run bootcmd_create_envfile; run bootcmd_otenv; run bootcmd_set_rollback; if test -n "${kernel_image2}"; then run bootcmd_rollbackenv; fi; run bootcmd_args; run bootcmd_load; run bootcmd_run; reset' run bootcmd
위와 같이 변경한 후 빌드를 하면 OSTRee가 적용된 이미지를 생성할 수 있다.
정리
이번 과정은 OSTree 의 부팅과정과 이를 다른 타겟에 적용하는 방법을 알아보았다. 다음 Yocto에 OSTree upgrade 적용(3) - 업그레이드/롤백 및 OSTree 리뷰 에서는 ostree를 이용하여 업그레이드, 롤백하는 과정을 알아보기로 한다.