장비 펌웨어 업그레이드 패키지를 받아서 풀어 봤다.
runme.sh
ubi_info
c5/
angstrom_rootfs.jffs2
soc_system.rbf
upgrade-marker.bin
xilinx/
BOOT.bin
devicetree.dtb
uImage
rootfs.jffs2
upgrade-marker.bin
폴더가 둘이다.
Table of contents
Open Table of contents
같은 제품인데 보드가 둘이다
c5 와 xilinx 는 서로 다른 제어 보드용이다. 같은 제품인데 생산 시기에 따라 들어간 보드가 다르다.
초기 물량에 들어간 보드와 후기 물량에 들어간 보드가 따로 있고 각각 펌웨어가 다르다. 겉모양과 제품 이름은 같으니 밖에서는 구분이 안 된다.
한 패키지에 두 벌을 담은 것이 처음에는 이상해 보였는데 배포 쪽에서 보면 그 반대다. 가르는 순간 받는 쪽이 자기 보드를 알아야 한다.
하나로 묶은 이유
패키지를 둘로 나누는 것도 가능하기는 하다.
[나누면] 사용자가 자기 보드를 알아야 함
[합치면] 아무거나 받아도 됨
문제는 사용자가 자기 보드를 모른다는 점이다. 케이스를 열어 봐야 아는 것을 물어보는 것은 무리다.
잘못 고르면 장비가 안 뜨는데 그 판단을 사용자에게 맡길 수 없다. 그래서 합치는 쪽이 맞아 보인다.
전체 흐름 — 판정 순서
합치면 그다음은 스크립트가 판정해야 한다. runme.sh 를 열어 봤다.
if [ -e /usr/bin/ctrl_bd ]; then
ret=`cat /usr/bin/ctrl_bd | grep "XILINX" | wc -l`
else
ret=0
fi
if [ $ret -eq 1 ]; then
cd ./xilinx
...
/usr/bin/ctrl_bd 라는 제어 바이너리를 cat 해서 XILINX 문자열이 있는지를 센다. 그 수가 1이면 xilinx 폴더로 들어간다.
바이너리에서 문자열을 찾는다
이 방법이 흥미로웠다. 실행 파일 안에 보드 이름이 문자열로 들어 있고 그것을 grep 으로 찾는다.
실행 파일 안에 보드 이름이 문자열로 들어 있음
↓
grep 으로 찾음
↓
있으면 그 보드
바이너리를 텍스트처럼 다루는 셈이다. 더 나은 자리가 있었을 것 같은데 셋 다 없었던 모양이다.
[설정 파일] 보드 이름이 적힌 파일 — 있으면 그걸 읽음
[장치 노드] /proc, /sys 에서 확인
[전용 명령] 보드 정보를 출력하는 명령
있는 것으로 판정하려니 바이너리 grep 이 남은 것으로 보인다.
주의 — 우연한 조건에 기댄 판정
이 방식이 성립하려면 조건 셋이 동시에 유지돼야 한다.
그 바이너리 이름이 바뀌면 안 됨
그 문자열이 사라지면 안 됨
다른 보드 바이너리에 그 문자열이 없어야 함
셋 다 코드가 보장하는 것이 아니라 그렇게 돼 있을 뿐이다. ctrl_bd 의 경로가 바뀌거나 빌드 설정이 달라져 그 문자열이 빠지면 판정이 뒤집힌다.
판정 근거가 우연이면 그 근거가 언제 사라지는지를 아무도 모른다. 보드마다 식별 값을 한 자리에 두고 그것을 읽는 쪽이 안전해 보인다.
판정 실패 시의 기본값
ctrl_bd 가 없을 때의 처리가 위에 함께 있다.
if [ -e /usr/bin/ctrl_bd ]; then
ret=`...`
else
ret=0
fi
파일이 없으면 ret 가 0이고 그러면 다른 보드 쪽으로 간다. 판정에 실패해도 설치는 그대로 진행된다는 뜻이다.
[안전한 기본값] 판정 실패 시 아무것도 안 함
[이 스크립트] 판정 실패 시 다른 쪽을 씀
플래시에 잘못된 이미지를 쓰면 장비가 안 뜨므로 멈추는 쪽이 안전해 보인다. 다만 그러면 판정이 조금만 어긋나도 아무도 업그레이드를 못 하게 된다.
어느 쪽 위험을 안을지의 문제로 보인다. 현장에서 벽돌이 되는 쪽과 아무도 못 올리는 쪽 중 어느 것이 덜 나쁜지는 그 제품의 사정이 정할 일이다.
두 보드는 부팅 구조가 다르다
두 폴더의 파일 목록도 달랐다.
A 보드 rootfs, FPGA 비트스트림, 업그레이드 마커
B 보드 BOOT, 디바이스트리, 커널, rootfs, 업그레이드 마커
xilinx 쪽에는 BOOT.bin 과 devicetree.dtb 와 uImage 가 있다. 부트로더가 커널을 올리고 커널이 rootfs 를 잡는 흐름이다.
c5 쪽에는 그 대신 soc_system.rbf 가 있다. FPGA 설정 파일이라 회로 구성부터 시작하는 셈이다.
겉으로는 같은 제품인데 안쪽은 아키텍처가 다르다. 그 둘을 패키지 하나가 다 받아 준다.
양쪽에 upgrade-marker.bin 이 함께 있는 것도 눈에 띈다. 플래시 특정 자리에 표시를 남겨서 다음에 이미 했는지를 확인하려는 것으로 보인다.
사람이 읽는 메모가 들어 있다
패키지에 ubi_info 라는 파일이 하나 더 있었다. 열어 보니 한 줄이었다.
only for this update 2 ubi package
스크립트가 읽는 값이 아니라 사람이 읽는 메모다. 파싱해서 쓰는 것과 읽어 보라고 넣은 것이 한 패키지에 섞여 있다.
이 방식이 나쁘지 않아 보였다. 패키지가 여러 벌 돌아다니면 어느 것이 무엇인지 헷갈리는데 파일명은 옮기고 다시 압축하는 사이에 바뀐다.
안에 넣어 두면 안 바뀐다. 문서 안쪽에 갱신 일자를 적어 두는 것과 같은 이유로 보인다.
정리
- 한 패키지에 두 보드용 펌웨어가
c5와xilinx로 나뉘어 들어 있다 - 사용자가 자기 보드를 알 수 없으니
runme.sh가 판정한다 - 판정을
/usr/bin/ctrl_bd안의 문자열을grep하는 것으로 한다 - 그 문자열이 남아 있다는 우연에 기대는 방식이라 취약해 보인다
- 파일이 없으면
ret가 0이 되어 다른 쪽 보드로 설치된다 - 판정이 안 되면 멈추는 쪽이 안전해 보인다
c5는 FPGA 구성부터,xilinx는 부트로더부터라 부팅 구조가 다르다upgrade-marker.bin이 이미 올렸는지를 남기는 표시로 보인다ubi_info처럼 사람이 읽는 메모는 파일명과 달리 안 바뀐다