커널이미지

 

커널 이미지

보통 32비트 arm 시스템들은 이미지의 크기, ROM/Flash 및 DRAM 용량에 민감하여 커널 이미지의 압축, 자체 압축 해제, 실행 방법 및 재배치 방법등을 고려하느라 조금 다양한 방법으로 커널 이미지를 만든다. 그에 비해 어느 정도 용량에 자유로운 arm64 시스템들은 커널 이미지의 생성이 비교적 단순하고 간단하다.

 

커널 이미지 종류

커널을 빌드하여 만들어내는 이미지는 사용 목적에 따라 다음과 같이 여러 유형으로 제작된다.

  • Image
    • 압축하지 않고 사용하는 이미지이다.
  • zImage
    • 압축하여 사용하는 이미지이며, 자체 압축 해제 루틴이 포함되어 있다. (ARM32)
  • Image.gz
    • 압축하여 사용하는 이미지이며, 자체 압축 해제 루틴이 포함되지 않는다. (ARM64)
      • Image.* (gz, bz2,lz4,lzma,lzo)
  • uImage
    • u-Boot라는 부트로더가 zImage를 약간 변형(64바이트 헤더 추가)하여 사용하는 이미지 이다.
  • bzImage
    • zImage를 확장시켜 PC에서 사용하는 포맷이다.
  • bootpImage
    • zImage + RAM 디스크 형태로 장치에 이미지가 없고, 부팅시 TFTP 서버를 통해 이미지를 다운 받아 동작시킨다.
  • xipImage
    • 압축하지 않고 바로 플래시 ROM에서 커널이 동작하는 이미지이다.
    • zImage에 비해 0.5초의 부트 시간 단축 효과를 가져 일부 시스템 및 모바일에서 사용하였었다.

 

커널 이미지 실행 위치

커널 이미지가 디스크나 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가 생성되는 과정을 보여준다.

iamge5

 

boopImage, uImage, bzImage, xipImage – ARM32

아래 그림은 ARM32 시스템에서 zImage로부터 bzImage, uImage, bootpImage 및 xipImage가 생성되는 과정을 보여준다.

image6

 


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의 정보가 추가되어 사용한다.

config_arm_append_dtb0a

 

config_arm_append_dtb

 


커널 이미지 분석

커널 이미지의 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

dump1

 

압축된 커널 이미지의 바이너리 덤프 분석 – ARM32

dump2

 

zImage 내부 – ARM32

vmlinux-1a

  • 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

댓글 남기기