- 문서 통합:
- 커널 이미지 | 문c
카테고리: 리눅스 커널
커널이미지
커널 이미지
보통 32비트 arm 시스템들은 이미지의 크기, ROM/Flash 및 DRAM 용량에 민감하여 커널 이미지의 압축, 자체 압축 해제, 실행 방법 및 재배치 방법등을 고려하느라 조금 다양한 방법으로 커널 이미지를 만든다. 그에 비해 어느 정도 용량에 자유로운 arm64 시스템들은 커널 이미지의 생성이 비교적 단순하고 간단하다.
커널 이미지 종류
커널을 빌드하여 만들어내는 이미지는 사용 목적에 따라 다음과 같이 여러 유형으로 제작된다.
- Image
- 압축하지 않고 사용하는 이미지이다.
- zImage
- 압축하여 사용하는 이미지이며, 자체 압축 해제 루틴이 포함되어 있다. (ARM32)
- Image.gz
- 압축하여 사용하는 이미지이며, 자체 압축 해제 루틴이 포함되지 않는다. (ARM64)
- Image.* (gz, bz2,lz4,lzma,lzo)
- 압축하여 사용하는 이미지이며, 자체 압축 해제 루틴이 포함되지 않는다. (ARM64)
- uImage
- u-Boot라는 부트로더가 zImage를 약간 변형(64바이트 헤더 추가)하여 사용하는 이미지 이다.
- bzImage
- zImage를 확장시켜 PC에서 사용하는 포맷이다.
- bootpImage
- zImage + RAM 디스크 형태로 장치에 이미지가 없고, 부팅시 TFTP 서버를 통해 이미지를 다운 받아 동작시킨다.
- xipImage
- 압축하지 않고 바로 플래시 ROM에서 커널이 동작하는 이미지이다.
- zImage에 비해 0.5초의 부트 시간 단축 효과를 가져 일부 시스템 및 모바일에서 사용하였었다.
- 참고: Kernel XIP | eLinux.org
커널 이미지 실행 위치
커널 이미지가 디스크나 ROM/Flash로부터 SDRAM에 로드하여 구동하는 방법은 가장 일반적인 구동방법이다. 그 외의 다양한 다양한 형태를 알아본다.
- 1) CONFIG_ZBOOT_ROM 옵션으로 Image나 zImage(uImage) 등을 보통 SDRAM으로 옮긴 후 동작을 시키지만, 옮기지 않고 ROM/Flash에서 곧바로 동작시킬 때 사용하는 옵션이다. 그러나 커널을 ROM/Flash에서 동작 시킨다는 것은 아니다. 커널마저 ROM/Flash에서 동작시키려 할 때엔 xipImage를 사용한다.
- 2) 커널 코드는 SDRAM에 옮기지 않지만 Data 공간은 SDRAM에 옮긴다.
일반 이미지 vs CONFIG_ZBOOT_ROM – 32bit 시스템
압축죈 이미지(zImage, uImage, bzImage, ..)를 보통 SDRAM에 로딩하여 실행하지만, 시스템 구성에 따라 곧바로 ROM/Flash에서 동작시킬 수 있는 방법도 있다.
- ROM/Flash에서 동작시키려는 경우 커널 빌드 시 CONFIG_ZBOOT_ROM 옵션이 enable되어 있어야 한다.
- SDRAM에서 코드를 동작시키면 ROM/Flash보다 코드 수행속도는 빠르나 ROM/Flash에서 SDRAM으로 로딩하는 절차가 추가된다.
zImage의 물리 시작 주소 – ARM32
zImage가 실행되는 물리 주소는 시스템마다 다르며 이를 커널에 알리기 위해 TEXT_OFFSET에 정의하여 사용한다.
- zImage의 코드는 절대주소를 사용하지 않아 메모리의 어느 위치에서든 옮겨(relocatable) 동작할 수 있도록 설계되어 있다.
CONFIG_ZBOOT_ROM vs xipImage – ARM32
이미지를 ROM/Flash에서 SDRAM으로 먼저 옮기지 않고 직접 실행시킬 때 두 가지 방법이 있다.
- 압축된 커널 이미지를 ROM/Flash에서 동작시키지만 실제 커널은 SDRAM에 압축을 풀어서 동작
- 압축하지 않은 커널 이미지를 ROM/Flash에서 직접 실행
Image.gz 생성 과정 – ARM64
아래 그림은 ARM64 시스템에서 Image와 Image.gz가 생성되는 과정을 보여준다.
zImage 생성 과정 – ARM32
아래 그림은 ARM32 시스템에서 zImage가 생성되는 과정을 보여준다.
boopImage, uImage, bzImage, xipImage – ARM32
아래 그림은 ARM32 시스템에서 zImage로부터 bzImage, uImage, bootpImage 및 xipImage가 생성되는 과정을 보여준다.
DTB 추가
Device Tree Blobs를 사용할 때 배치는 아래와 같다.
- 일반적으로 A와 같이 CONFIG_ARM_APPENDED_DTB 옵션(only for ARM32)을 사용하는 경우는 zImage(uImage, bzImage 포함)의 위쪽에 붙여서 위치한다.
- 그 외에 B와 같이 별도의 공간에 로드하여 사용하기도 한다.
- 마지막 항목은 A와 같이 DTB를 공급하는 부트로더 또는 ATAG를 공급하는 부트로더(옛날 부트로더)와 연결되어 사용되며 ATAG 구조 몇 개는 DTB로 변환되어 사용된다.
- 마지막 항목의 형태로 DTB와 ATAG를 같이 사용하는 특수한 경우(only for ARM32)도 있다. 이 때에는 기존 DTB에 ATAG의 정보가 추가되어 사용한다.
커널 이미지 분석
커널 이미지의 ELF 분석 – ARM64
$ file vmlinux vmlinux: ELF 64-bit LSB shared object, ARM aarch64, version 1 (SYSV), statically linked, BuildID[sha1]=f0ac40ea0edb8b073327839245acaeef1dc402e1, stripped $ readelf --headers vmlinux ELF Header: Magic: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 Class: ELF64 Data: 2's complement, little endian Version: 1 (current) OS/ABI: UNIX - System V ABI Version: 0 Type: DYN (Shared object file) Machine: AArch64 Version: 0x1 Entry point address: 0xffff800010000000 Start of program headers: 64 (bytes into file) Start of section headers: 30395216 (bytes into file) Flags: 0x0 Size of this header: 64 (bytes) Size of program headers: 56 (bytes) Number of program headers: 3 Size of section headers: 64 (bytes) Number of section headers: 28 Section header string table index: 27 Section Headers: [Nr] Name Type Address Offset Size EntSize Flags Link Info Align [ 0] NULL 0000000000000000 00000000 0000000000000000 0000000000000000 0 0 0 [ 1] .head.text PROGBITS ffff800010000000 00010000 0000000000010000 0000000000000000 AX 0 0 65536 [ 2] .text PROGBITS ffff800010010000 00020000 0000000000d281a8 0000000000000008 AX 0 0 2048 [ 3] .got.plt PROGBITS ffff800010d381a8 00d481a8 0000000000000018 0000000000000008 WA 0 0 8 [ 4] .rodata PROGBITS ffff800010d40000 00d50000 00000000006c1de0 0000000000000000 WA 0 0 4096 [ 5] .pci_fixup PROGBITS ffff800011401de0 01411de0 00000000000025e0 0000000000000000 A 0 0 16 [ 6] __ksymtab PROGBITS ffff8000114043c0 014143c0 000000000000f564 0000000000000000 A 0 0 4 [ 7] __ksymtab_gpl PROGBITS ffff800011413924 01423924 0000000000013ef0 0000000000000000 A 0 0 4 [ 8] __ksymtab_strings PROGBITS ffff800011427814 01437814 0000000000038dae 0000000000000001 AMS 0 0 1 [ 9] __param PROGBITS ffff8000114605c8 014705c8 00000000000041f0 0000000000000000 A 0 0 8 [10] __modver PROGBITS ffff8000114647b8 014747b8 00000000000000f0 0000000000000000 A 0 0 8 [11] __ex_table PROGBITS ffff8000114648a8 014748a8 0000000000002088 0000000000000000 A 0 0 8 [12] .notes NOTE ffff800011466930 01476930 000000000000003c 0000000000000000 A 0 0 4 [13] .init.text PROGBITS ffff800011470000 01480000 000000000006d340 0000000000000000 AX 0 0 4 [14] .exit.text PROGBITS ffff8000114dd340 014ed340 0000000000006034 0000000000000000 AX 0 0 4 [15] .altinstructions PROGBITS ffff8000114e3374 014f3374 0000000000038214 0000000000000000 A 0 0 1 [16] .init.data PROGBITS ffff800011520000 01530000 0000000000095ee5 0000000000000000 WA 0 0 256 [17] .data..percpu PROGBITS ffff8000115b6000 015c6000 000000000000dc58 0000000000000000 WA 0 0 64 [18] .hyp.data..percpu PROGBITS ffff8000115c4000 015d4000 0000000000000e20 0000000000000000 WA 0 0 16 [19] .rela.dyn RELA ffff8000115c4e20 015d4e20 0000000000464c40 0000000000000018 A 0 0 8 [20] .data PROGBITS ffff800011a30000 01a40000 00000000002a51a0 0000000000000000 WA 0 0 4096 [21] __bug_table PROGBITS ffff800011cd51a0 01ce51a0 000000000001689c 0000000000000000 WA 0 0 4 [22] .mmuoff.data.writ PROGBITS ffff800011cec000 01cfc000 0000000000000018 0000000000000000 WA 0 0 2048 [23] .mmuoff.data.read PROGBITS ffff800011cec800 01cfc800 0000000000000008 0000000000000000 WA 0 0 8 [24] .pecoff_edata_pad PROGBITS ffff800011cec808 01cfc808 00000000000001f8 0000000000000000 WA 0 0 1 [25] .bss NOBITS ffff800011ced000 01cfca00 000000000008cabc 0000000000000000 WA 0 0 4096 [26] .comment PROGBITS 0000000000000000 01cfca00 000000000000002a 0000000000000001 MS 0 0 1 [27] .shstrtab STRTAB 0000000000000000 01cfca2a 0000000000000122 0000000000000000 0 0 1 Key to Flags: W (write), A (alloc), X (execute), M (merge), S (strings), I (info), L (link order), O (extra OS processing required), G (group), T (TLS), C (compressed), x (unknown), o (OS specific), E (exclude), p (processor specific) Program Headers: Type Offset VirtAddr PhysAddr FileSiz MemSiz Flags Align LOAD 0x0000000000010000 0xffff800010000000 0xffff800010000000 0x0000000001ceca00 0x0000000001d79abc RWE 0x10000 NOTE 0x0000000001476930 0xffff800011466930 0xffff800011466930 0x000000000000003c 0x000000000000003c R 0x4 GNU_STACK 0x0000000000000000 0x0000000000000000 0x0000000000000000 0x0000000000000000 0x0000000000000000 RW 0x10 Section to Segment mapping: Segment Sections... 00 .head.text .text .got.plt .rodata .pci_fixup __ksymtab __ksymtab_gpl __ksymtab_strings __param __modver __ex_table .notes .init.text .exit.text .altinstructions .init.data .data..percpu .hyp.data..percpu .rela.dyn .data __bug_table .mmuoff.data.write .mmuoff.data.read .pecoff_edata_padding .bss 01 .notes 02
압축된 커널 이미지의 ELF 분석 – ARM32
압축된 커널 이미지의 바이너리 덤프 분석 – ARM32
zImage 내부 – ARM32
- rpi2:
- objdump -d arch/arm/boot/compressed/vmlinux
- readelf –all arch/arm/boot/compressed/vmlinux
- hexdump arch/arm/boot/zImage -C -n 1024
참고
- Execute in Place (XIP) with Quad SPI Interface(QSPI) | Atmel – 다운로드 pdf