유영창 (frog@falinux.com)
기존에 리눅스를 하던 사람들이 임베디드 리눅스의 세계로 발을 들여 놓으면서 기술적으로 어려워 하는 것이 바로 ‘부트로더’라는 프로그램이다. 부트로더는 PC 프로그래머들은 별로 접할 기회가 없는 프로그램이기도 하다. PC에서 동작하는 BIOS 같은 것으로 PC에서는 당연히 시스템에 내장되어 있어야 할 프로그램이기 때문이다. 하지만 임베디드 시스템에서는 프로그래머가 직접 만들어야 하거나 최소한 공개된 기존 부트로더를 수정해야 할 것이다. 이 때문에 부트로더에 대한 구성을 알고 있으면 큰 도움이 된다. 필자는 실무적인 체험을 바탕으로 직접 작성한 ‘이지부트’라는 부트로더를 설명해 가면서 실제 제작 과정을 펼쳐볼 예정이다.
ARM 프로세서
PXA255는 앞서 언급했듯 ARM 계열이다. 삼성이나 다른 회사에서 만든 프로세서가 ARM 코어를 라이선스한 것과는 다르게 아예 설계 자체를 사서 인텔 자사의 기술을 더한 프로세서이다. 그러나 결국은 이것도 개발자 입장에서 보면 ARM의 한 계열로 봐도 무방하다. 이 프로세서를 이해하면 ARM 코어를 사용하는 다른 프로세서들도 어느 정도 이해가 가능하다
그렇다면 ARM이란 것은 어떤 것일까? 아무래도 이 연재가 ARM용 부트로더를 작성하기 위한 것이므로 ARM 프로세서에 대해 모르고 갈 수는 없다. 그래서 ARM에 대해 잠깐 살펴보자.
우리가 알고 있는 펜티엄은 인텔에서 제작하고 있는 프로세서이다. 하지만 ARM에서 만든 ARM 프로세서는 실제로는 존재하지 않는다. 즉 ARM(회사 이름과 파는 프로세서 이름이 같다)에서는 ARM 프로세서를 직접 생산하지는 않고, 아키텍처 코어 및 시스템 코어를 라이선스해주는 IP 회사인 것이다. 코어는 일종의 설계도와 같은 것으로 설계도를 구입해간 회사에서는 이 코어를 이용해 주 프로세서를 구현하고 그 외에 판매하고자 하는 형태의 주변 디바이스를 추가한다. 이렇게 완성된 제품을 각 판매 회사의 고유 모델명을 붙인 후 판매하는 것이다. 우리가 주변에서 실제로 구매 가능한 것은 이렇게 나온 제품이다. 삼성의 S3C2410이나 S3C2800 같은 것이 이에 해당한다.
이런 ARM에도 종류가 매우 많은데 그 구현 방식에 따라 다른 이름을 갖기는 하지만 일종의 버전 번호와 같은 형식의 이름을 부른다. 예를 들면 ARM7 Thumb, ARM8 Thumb, ARM9 Thumb, ARM9E Thumb, ARM10 Thumb 등이다.
그 외 ARM720T, ARM920T 같은 이름이 붙기도 한다. 이런 프로세서 구분은 명령어 집합과 속도에 따라 구별한다. 이것은 부트로더 컴파일시 컴파일러 옵션에 영향을 미치는데 이런 자세한 내용은 추후 살펴 볼 것이다. 그리고 ARM 자체의 특성은 상당히 방대한 부분이기 때문에 이번 호에서 살펴보지는 않겠다. 부트로더의 실제 제작에서 자세하게 살펴볼 것이다.

XScale과 PXA255
인텔에서는 프로세서 이름을 기존 프로세서들과 다르게 두 가지 형태의 이름을 붙이는 습성이 있는 것 같다. 예전에는 80386이니 하는 이름을 붙이다가 어느 순간 펜티엄이니 아이테니엄이니 하는 이름으로 붙여 간다. XScale도 이런 명명법의 하나이다. 아마도 ARM이라는 꼬리표를 달기 싫었던 모양이다. XScale 프로세서를 설명하려면 먼저 스트롱암 프로세서를 알아봐야 한다.
스트롱암은 원래 인텔에서 만든 것은 아니다. DEC라는 회사에서 만든 제품이다. 이 회사는 ARM으로부터 아키텍처를 라이선스해 독자적인 ARM 코어 칩을 만들었는데 스트롱암이라는 모델명을 갖는다. 이 프로세서는 실제 SA-110, SA-1110이라는 이름을 갖는다. 이 DEC는 1993년에 스트롱암 관련 사업을 인텔에 매각하게 되고 인텔은 인텔 버전의 스트롱암을 생산하게 됐다. 그러다가 인텔 내부에서 기능 향상에 한계를 느껴서 새로운 내부 설계를 하기로 결정했다고 한다. 이후에 새로 설계되어 나온 것이 XScale 시리즈로 그 중 대표적인 것이 PXA250이라는 프로세서이다. 이 프로세서는 기존 스트롱암과 동일한 구성을 갖고 있으며 멀티미디어에 필요한 명령 셋이 추가됐다. 그 외에 주변 디바이스의 기능적인 확장을 했다. 또한 지원 클럭도 400MHz, 300MHz, 200MHz와 같이 다양한 종류를 선보였다. 하지만 초기 설계의 버그로 인한 버전업을 계속하다가 최종 버전을 PXA255란 모델명으로 바꾸게 된다. 결국 PXA255는 기존 스트롱암의 버전업된 프로세서로 봐도 무방할 정도로 그 구성은 유사하다. 실제 내부 버스도 매우 효율적으로 설계되어 있어서 스트롱암보다는 월등한 성능을 나타낸다.
PXA255는 워낙 유명한 회사에서 만든 프로세서이고 기존 스트롱암과 유사하게 만들어졌기 때문에 기존 스트롱암을 이용해 제품을 개발했던 회사들은 새로운 제품에 이 프로세서를 채택하는 추세이다. 이런 이유에 의해 PXA255 프로세서를 시험하거나 실제 제품에 이용할 수 있는 보드는 시중에 매우 다양하게 출시되어 있다. 이런 보드 중에 필자가 다니는 회사에서 판매하고 있는 것이 EZ-X5란 보드이고 이 보드에 구현된 것이 이지부트라는 부트로더이다. 물론 이렇게 특정 회사의 제품을 대상으로 해서 부트로더 제작에 관련된 연재를 진행하는 것은 공공적인 성격을 가지고 있는 잡지의 특성상 그리 탐탁치 않을 수 있다. 처음 이 연재를 계획했을 때 담당 기자의 걱정 또한 이런 부분이었다. 하지만 부트로더를 설명하기 위해서는 어쩔 수 없이 특정 타겟 보드가 있어야 하고 이왕이면 필자가 다니는 회사 제품을 가지고 설명한다면 좀더 정확하게 실제 개발과 관련된 노하우나 구현 과정에 필요한 사항을 모두 알려 줄 수 있다는 장점이 있다고 판단된다. 그래서 필자의 회사에서 판매하는 보드를 가지고 연재를 진행하는 것에 대해 독자들에게 양해를 구하는 바이다.

이지부트
이지부트는 필자와 필자의 회사 동료인 푸지라는 엔지니어가 직접 작성한 부트로더이다. 이 부트로더는 스트롱암 보드를 구동하기 위해 만들기 시작했던 것인데 굳이 공개된 부트로더를 이용하지 않고 다시 만들었던 것에는 나름대로 아픔이 있었기 때문이다.
초기에 스트롱암 보드가 만들어지고 이 보드에 포팅을 하기 시작한 시점에서 공개된 부트로더로 유명했던 것은 ARM 계열에 blob였다. 처음에는 blob를 분석해서 이를 조금 변형한 상태로 개발을 진행하려 했지만 기능적인 제약이 있었다. blob은 당시에 SA110 프로세서를 위한 구성을 가지고 있었는데 ARM용 부트로더로는 쓸만했지만 커널 이미지를 올리거나 램 디스크를 올리기 위해서는 시리얼 전송 방식 밖에 구현되지 않았다. 더구나 시리얼 통신을 이용한 것도 범용적인 ZMODEM이나 YMODEM 같은 방식이 아닌 UUDECODE와 UUENCODE 방식을 사용해야 했다. 필자와 같이 리눅스에서 개발하는 것보다 윈도우가 편한 사람에게 이 방식을 권하면 처음에는 개념도 어려웠고 사용상의 불편함이 이만저만한 것이 아니다. 그 외 가장 치명적인 것은 이더넷에 관련된 것을 지원하지 않는 것이었다. 실제 개발을 하다 보면 수차례의 이미지 다운로드를 수행하게 되는데 이때 전송 속도가 느려지면 필자와 같이 성격 급한 사람은 견디기 힘들어진다.
이런 저런 이유로 인해 blob의 부트로더를 변형해서 사용하는 것을 포기하고 새로운 부트로더를 만들기로 결심했다. 그런데 막상 실제 부트로더를 만들어 가면서 많은 기술적인 지식이 필요함을 느꼈다. 그래서 다른 부트로더를 살펴보고 필자의 마음에 드는 부분들만 골라서 재구성하기로 결정한 것이다. 물론 그대로 가져온 부분도 상당수 되지만 이것저것 수정하다 보니 아주 달라지는 부분도 많아졌다. 이후에 PXA255의 부트로더를 만들었을 때는 스트롱암용 이지부트의 부족한 점을 정리하고 추가했을 뿐이다. PXA255의 이지부트는 다음과 같은 기능을 갖는다.

◆ PXA255의 초기 설정 기능
◆ 부트 블럭 플래시 쓰기 기능
◆ NAND 플래시 쓰기 기능
◆ ZMODEM 시리얼 프로토콜
◆ TFTP 프로토콜
◆ 커널 부팅 기능
◆ 환경 설정 기능
◆ 리셋 기능

기능 이외에 이지부트의 특징은 다음과 같다.

◆ 자주 쓰는 명령은 3글자로 끝난다
필자는 매우 게으르다. 그래서 키보드 타이핑을 치는 것을 그리 좋아하지 않는다. 특히 계속 반복적인 내용을 쓰는 것을 무척 싫어한다. 다른 부트로더들은 명령어만 보면 무슨 일을 하는지 알 수 있지만 이지부트에서 사용되는 명령 자체만 보았을 때는 무슨 명령인지 모른다. 왜냐하면 3글자의 약어로 끝나기 때문이다. tfk라는 명령이 그 한 예인데 이것은 tftp 프로토콜을 사용해 플래시 메모리에 커널을 넣으라는 명령이다. 이 명령은 보드 개발 단계에서 수십 번에서 수백 번을 써 먹을 명령이다. 이 명령은 다른 부트로더에서는 다음과 같은 긴 명령이 되어 버린다. ‘download 0x3f000 tftp write flash’. 이것을 수백 번 치다 보면 신경이 곤두서게 된다. 그래서 이지부트에서는 자주 쓰는 명령들은 몽땅 3글자로 만들어 버렸다.

◆ 주석이 한글이다
요피 부트로더를 보면서 정말 이제는 세계화로 가는 것이 기본이구나 하는 생각을 했다. 소스에 모든 것이 영어이다. 하지만 영어에 영 자신 없는 필자 같은 사람은 주석을 보고서는 무엇을 하는 것인지 무척 헛갈리는 것이 솔직한 심정이다. 끼리끼리 모인다고, 필자 주위의 개발자들은 대부분 영어에 무척 약하다. 그래서 필자는 주석을 모두 한글로 쓰기로 했다. 또 한번 해석하기 싫은 국내 개발자들을 위해서다. 문제는 필자의 게으름의 기법상 복사문을 자주 사용해 함수가 실제로 하는 기능과 주석이 다른 것이 종종 발견되는 경우와 한번의 오타는 영원한 오타가 된다는 것이다. 원래 만들고 난 후에 공개할 생각이었고 소스를 참조할 사람들이 국내 사람일 것이기 때문에 한글로 주석을 달아 버렸다. 필자는 언젠가는 gcc가 해석하는 변수명과 함수명을 한글로 사용할 수 있게 만들 것이다. 언제가 될지 모르지만…

앞으로의 연재 방향
대부분의 연재들이 그러하듯 이 글 역시 소개 글로 채워져 버렸다. 하지만 소개 글이라기보다는 부트로더라는 프로그램의 기초 분석서라고 이해하는 아량을 베풀어 주기 바란다. 다음 호부터 본격적인 부트로더 제작 과정을 알아 볼 것이고 이 과정에 필요한 기술적인 사항 역시 기술할 것이다. 앞에서 보듯이 기능 자체는 몇 가지 안 되지만 다음과 같은 내용을 설명할 것이다.

◆ gcc 크로스 컴파일 구축 방법
◆ 펌웨어를 위한 gcc의 컴파일 방법
◆ PXA255의 내부 구조 및 ARM 코어의 동작 특징
◆ PXA255의 디바이스 중에서 부트로더에서 지원해야 할 주변 디바이스에 대한 설명과 드라이버 구현 방법
◆ PXA255의 메모리 설정과 구현 방법
◆ ARM용 gcc의 어셈블러와 C 함수의 링크 관계
◆ 최초 보드 시험 프로그램 로직
◆ 부트 블럭 플래시의 구조 및 구현 방법
◆ NAND 플래시의 구조 및 구현 방법
◆ C의 표준 입출력 함수의 구현 방법
◆ ARP, RARP 프로토콜의 구현 방법
◆ UDP 프로토콜의 구현 방법
◆ TFTP 프로토콜의 구현 방법
◆ PING 프로토콜의 구현 방법
◆ CS8900 이더넷 칩의 구조 및 구현 방법
◆ 커널과 부트로더의 관계
◆ 부트로더 탑재를 위한 JTAG의 이해

부트로더를 모든 임베디드 리눅스 개발자가 알아야 하는 것은 아니다. 하지만 펌웨어 프로그래머라면 32비트 ARM 프로세서에 직접 코딩을 해야 할 경우가 있을 때 이 연재가 도움이 될 수 있으리라 생각한다. 또는 간단한 TCP/IP 스택을 구현하는 프로그래머에게 도움이 될 수도 있을 것이다. 이지부트라는 프로그램을 처음 만들 때 필자 개인적인 용도로 사용하기 위해서만 만들지는 않았다. 서로 공유하는 문화의 혜택을 많이 받았던 필자도 공개 소프트웨어에 조금이라도 도움이 될 수 있지 않을까 해서 작성했기 때문이다. 부디 프로그램의 내용이 부실하고 사용된 프로그램의 기법이 별로 일지라도 너그러운 마음으로 보아주기 바란다. 그리고 개발자간에 서로 도와 가는 오픈소스 운동에 여러분도 참여해 주기를 바란다.

정리 | 박은정 | whoami@korea.cnet.com

Posted by 영웅기삼
,