파티션 및 이미지

파티션

Android 기기에는 부팅 프로세스에서 다양한 기능을 제공하는 여러 파티션이 포함됩니다. A/B 업데이트를 지원하려면 기기에는 boot, system, vendor, radio와 관련하여 파티션마다 슬롯 하나가 필요합니다.

  • boot: boot 파티션에는 mkbootimg를 통해 결합된 커널 이미지와 RAM 디스크가 포함됩니다. 새 boot 파티션을 플래시하지 않고 직접 커널을 플래시하기 위해 가상 파티션을 사용할 수 있습니다.
    • kernel: 가상 kernel 파티션은 이전 이미지 위에 새 이미지를 작성하여 커널만 덮어씁니다(zImage, zImage-dtb, Image.gz-dtb). 이를 위해 kernel 파티션은 eMMC에 있는 기존 커널 이미지의 시작 위치를 확인하고 해당 위치로 새 커널 이미지를 복사합니다. 새 커널 이미지는 기존 커널 이미지보다 클 수 있습니다. 부트로더는 후속 데이터를 이동하거나 오류가 발생한 작업을 종료하여 공간을 확보할 수 있습니다. 제공된 개발 커널이 호환되지 않으면 dtb 파티션이 있는 경우 이를 업데이트하거나 관련 커널 모듈로 vendor 파티션 또는 system 파티션을 업데이트해야 할 수도 있습니다.
    • ramdisk: 가상 ramdisk 파티션은 이전 이미지 위에 새 이미지를 써서 RAM 디스크만 덮어씁니다. 이를 위해 eMMC에 있는 기존 ramdisk.img의 시작 위치를 확인하고 해당 위치로 새 RAM 디스크를 복사합니다. 새 RAM 디스크는 기존 RAM 디스크보다 클 수 있습니다. 부트로더는 후속 데이터를 이동하거나 오류가 발생한 작업을 종료하여 공간을 확보할 수 있습니다.
  • system: system 파티션에는 주로 Android 프레임워크가 포함됩니다.
  • recovery: recovery 파티션은 OTA 프로세스 중에 부팅된 복구 이미지를 저장합니다. 기기가 A/B 업데이트를 지원하는 경우 복구는 별도의 이미지가 아닌 부팅 이미지에 포함된 RAM 디스크일 수 있습니다.
  • cache: cache 파티션은 임시 데이터를 저장합니다. 기기가 A/B 업데이트를 사용하는 경우에는 선택사항입니다. cache 파티션은 부트로더에서 쓰기 가능할 필요가 없으며 삭제만 가능하면 됩니다.크기는 기기 유형 및 사용자 데이터 공간의 사용 가능 여부에 따라 다릅니다. 현재는 50~100MB 정도면 됩니다.
  • misc: misc 파티션은 복구에 사용되며 4KB 이상입니다.
  • userdata: userdata 파티션에는 맞춤설정 데이터를 포함하여 사용자가 설치한 애플리케이션과 데이터가 포함됩니다.
  • metadata: metadata 파티션은 기기가 암호화되고 16MB 이상인 경우에 사용됩니다.
  • vendor: vendor 파티션에는 Android 오픈소스 프로젝트(AOSP)에 배포할 수 없는 바이너리가 포함됩니다. 독점 정보가 없으면 이 파티션을 생략할 수 있습니다.
  • radio: radio 파티션에는 무선 이미지가 포함됩니다. 이 파티션은 전용 파티션에 무선 관련 소프트웨어가 있는 기기(무선 기능 포함)에만 필요합니다.
  • tos: tos 파티션은 Trusty OS의 바이너리 이미지를 저장하며 기기에 Trusty가 있는 경우에만 사용됩니다.

흐름

부트로더의 작동 방식은 다음과 같습니다.

  1. 먼저 부트로더가 로드됩니다.
  2. 부트로더가 메모리를 초기화합니다.
  3. A/B 업데이트를 사용하는 경우 부팅할 현재 슬롯을 결정합니다.
  4. 업데이트 지원에 설명된 대로 복구 모드를 대신 부팅해야 하는지 확인합니다.
  5. 부트로더는 커널과 RAM 디스크가 포함된 이미지를 로드합니다(Treble에서는 더 많이).
  6. 부트로더는 자체적으로 실행할 수 있는 압축된 바이너리로 커널을 메모리에 로드하기 시작합니다.
  7. 커널은 자체적으로 압축을 풀고 메모리로의 실행을 시작합니다.
  8. 해당 시점에서 오래된 기기는 RAM 디스크에서 init을 로드하고, 새로 나온 기기는 /system 파티션에서 이를 로드합니다.
  9. /system에서 init이 실행되며 /vendor, /oem, /odm 등 다른 모든 파티션이 마운트되기 시작하고, 이후에는 코드 실행이 시작되어 기기가 시작됩니다.

이미지

부트로더는 다음과 같은 이미지를 사용합니다.

커널 이미지

커널 이미지는 zImage, Image 또는 Image.gz와 같은 표준 Linux 형식으로 생성됩니다. 커널 이미지는 독립적으로 플래시되고 RAM 디스크 이미지와 결합되어 boot 파티션으로 플래시되거나 메모리에서 부팅될 수 있습니다. 커널 이미지 생성 시 기기 트리에 별도의 파티션을 사용하는 것보다 연결된 기기 트리 바이너리를 사용하는 것이 좋습니다. 서로 다른 보드 버전에 여러 기기 트리 Blob(DTB)을 사용하는 경우 보드 버전을 기준으로 하여 내림차순으로 여러 DTB를 연결합니다.

RAM 디스크 이미지

RAM 디스크에는 rootfs로 마운트하는 데 적합한 루트 파일 시스템이 포함되어야 합니다. RAM 디스크 이미지는 mkbootfs를 사용하여 커널 이미지와 결합된 다음 boot 파티션으로 플래시됩니다.

부팅 이미지

부팅 이미지에는 수정되지 않은 mkbootimg를 사용하여 결합된 커널 및 RAM 디스크가 포함되어야 합니다.

mkbootimg의 구현은 system/core/mkbootimg에서 확인할 수 있습니다.

부트로더는 mkbootimg에 의해 생성된 bootimg.h 헤더 파일을 읽고 커널 헤더를 업데이트하여 플래시 내 RAM 디스크의 올바른 위치와 크기, 커널의 기본 주소, 명령줄 매개변수 등을 포함합니다. 그런 다음 부트로더는 부팅 이미지에 지정된 명령줄을 부트로더에서 생성한 명령줄의 끝에 추가합니다.

파일 시스템 이미지(시스템, 사용자 데이터, 복구)

YAFFS2 이미지 형식

원시 NAND 저장소를 사용하는 경우 이러한 이미지는 external/yaffs2/yaffs2/utils에 있는 Android 오픈소스 프로젝트(AOSP)에서 확인할 수 있는 수정되지 않은 mkyaffs2image에 의해 생성된 YAFFS2여야 합니다. 형식은 다음과 같습니다.

    
    | 2k bytes of data| yaffs extra data | padding | | 0  2048 | 0 64 | variable|
    
    

부트로더는 이러한 이미지를 사용하고 yaffs 추가 데이터를 지정된 nand 하드웨어의 대역 외 영역에 있는 적절한 위치로 재배치하는 역할을 합니다. 소프트웨어 ECC가 필요한 경우 해당 시점에 부트로더는 이를 계산도 해야 합니다.

스파스 이미지 형식

스파스 이미지 형식을 지원해야 합니다. 이에 관한 내용은 'ext4 압축 이미지' 및 system/core/libsparse/sparse_format.h에 명시되어 있으며 system/core/libsparse/sparse_read.cpp에 구현되어 있습니다.

블록 기반 저장장치를 사용하는 경우 ext4 또는 f2fs를 지원해야 합니다. 빈 대용량 ext4 파일 시스템(사용자 데이터)을 신속하게 전송하고 플래시하려면, 쓰지 않은 상태로 둘 수 있는 파일 시스템 영역에 관한 정보가 포함된 스파스 형식으로 이미지를 저장합니다. 파일 형식의 쓰기는 이미지를 생성하는 데에도 사용되는 mke2fs 유틸리티에 의해 처리되며, 파일 형식의 읽기와 플래시는 부트로더에 의해 처리됩니다. 속성은 아래 섹션을 참조하세요.

파일 형식
  • 모든 필드는 부호가 없는 little-endian입니다.
  • 파일에는 파일 헤더와 그 다음에 오는 일련의 청크가 포함됩니다.
  • 파일 헤더, 청크 헤더, 청크 데이터의 길이는 모두 4바이트의 배수입니다.
  • 32비트 매직: 0xed26ff3a
  • 16비트 주 버전(0x1) - 상위 주 버전이 있는 이미지 거부
  • 16비트 부 버전(0x0) - 상위 부 버전이 있는 이미지 허용
  • 바이트 단위의 16비트 파일 헤더 크기(v1.0에서 28바이트)
  • 바이트 단위의 16비트 청크 헤더 크기(v1.0에서 12바이트)
  • 바이트 단위의 32비트 블록 크기, 4의 배수여야 함
  • 출력 파일의 총 32비트 블록
  • 입력 파일의 총 32비트 청크

원본 데이터의 32비트 CRC32 체크섬은 '상관없음'을 표준 802.3 다항식에 따라 0으로 계산하고, 공개 도메인 테이블 구현을 사용합니다.

청크
  • 16비트 청크 유형:
    • 0xCAC1 원시
    • 0xCAC2 채우기
    • 0xCAC3 상관없음
  • 16비트 예약(0으로 쓰고 읽기에서는 무시됨)
  • 출력 이미지의 블록 단위로 된 32비트 청크 크기
  • 청크 헤더와 데이터를 포함한 청크 입력 파일의 총 32비트 크기(바이트 단위)
데이터
  • 원시: 원시 데이터, 블록 단위 크기 * 바이트 단위의 블록 크기
  • 채우기: 4바이트의 채우기 데이터
작성기 구현

mke2fs 유틸리티는 이미지의 어떤 영역을 써야 하는지 이미 알고 있으며, 그 사이에 '상관없음' 청크를 인코딩합니다. 또 다른 도구인 img2simg는 일반(스파스 아님) 이미지를 스파스 이미지로 변환합니다. 일반 이미지에는 '상관없음' 영역에 관한 정보가 없습니다. 변환이 가져다 주는 최고의 효과는 반복되는 데이터 블록을 찾아 결과로 나타나는 이미지 크기를 줄이는 것입니다.

판독기 구현

판독기는 알 수 없는 주 버전이 포함된 이미지를 거부하고 알 수 없는 부 버전이 포함된 이미지는 허용해야 합니다. 판독기는 지원하지 않는 청크 크기가 있는 된 이미지를 거부할 수 있습니다.

주 버전이 검증되면 판독기는 알 수 없는 유형 필드가 포함된 청크를 무시해야 합니다. 판독기는 '파일의 청크 크기'를 사용하여 파일의 청크를 건너뛰고 출력에서 '블록 단위의 청크 크기' 블록을 건너뛰어야 합니다.

순환 중복 검사 - 802.3 CRC32 - 디스크에 쓸 데이터에 대해 계산되어야 합니다. 쓰지 않은 모든 영역(상관없음 또는 건너뛴 청크)은 CRC에서 0으로 계산해야 합니다. 썼거나 건너뛴 블록의 총 개수는 헤더의 '총 블록 수' 필드와 비교되어야 합니다. simg2img 도구는 스파스 이미지 형식을 표준 이미지로 변환하며, 이때 스파스 정보는 삭제됩니다.