공급업체 부팅 파티션

Android 11에는 일반 커널 이미지(GKI) 개념이 도입되었습니다. GKI로 임의의 기기를 쉽게 부팅할 수 있도록 Android 11 기기에서는 부팅 이미지 헤더 버전 3을 사용할 수 있습니다. 버전 3에서는 모든 공급업체별 정보가 boot 파티션에서 제외되어 새 vendor_boot 파티션으로 재배치됩니다. 5.4 Linux 커널에서 Android 11로 실행되는 ARM64 기기는 GKI 테스트를 통과하려면 vendor_boot 파티션 및 업데이트된 boot 파티션 형식을 지원해야 합니다.

Android 12 기기는 부팅 이미지 헤더 버전 4를 사용할 수 있습니다. 이 버전은 여러 공급업체 램디스크를 vendor_boot 파티션에 포함하는 작업을 지원합니다. 여러 공급업체 램디스크 프래그먼트는 공급업체 램디스크 섹션에서 차례로 연결됩니다. 공급업체 램디스크 표는 공급업체 램디스크 섹션의 레이아웃과 각 공급업체 램디스크 프래그먼트의 메타데이터를 설명하는 데 사용됩니다.

파티션 구조

공급업체 부팅 파티션은 가상 A/B를 통해 A/B되며 Android 자체 검사 부팅으로 보호됩니다.

버전 3

파티션은 헤더, 공급업체 램디스크, 기기 트리 blob(DTB)으로 구성됩니다.

섹션 페이지 수
공급업체 부팅 헤더(n페이지) n = (2112 + page_size - 1) / page_size
공급업체 램디스크(o페이지) o = (vendor_ramdisk_size + page_size - 1) / page_size
DTB(p페이지) p = (dtb_size + page_size - 1) / page_size

버전 4

파티션은 헤더와 공급업체 램디스크 섹션(연결된 모든 공급업체 램디스크 프래그먼트로 구성됨), 기기 트리 blob(DTB), 공급업체 램디스크 표로 구성됩니다.

섹션 페이지 수
공급업체 부팅 헤더(n페이지) n = (2128 + page_size - 1) / page_size
공급업체 램디스크 프래그먼트(o페이지) o = (vendor_ramdisk_size + page_size - 1) / page_size
DTB(p페이지) p = (dtb_size + page_size - 1) / page_size
공급업체 램디스크 표(q페이지) q = (vendor_ramdisk_table_size + page_size - 1) / page_size
Bootconfig(r페이지) r = (bootconfig_size + page_size - 1) / page_size

공급업체 부팅 헤더

공급업체 부팅 파티션 헤더의 콘텐츠는 주로 부팅 이미지 헤더에서 그곳에 재배치된 데이터로 구성됩니다. 여기에는 공급업체 램디스크 정보도 포함되어 있습니다.

버전 3

struct vendor_boot_img_hdr_v3
{
#define VENDOR_BOOT_MAGIC_SIZE 8
    uint8_t magic[VENDOR_BOOT_MAGIC_SIZE];
    uint32_t header_version;
    uint32_t page_size;           /* flash page size we assume */

    uint32_t kernel_addr;         /* physical load addr */
    uint32_t ramdisk_addr;        /* physical load addr */

    uint32_t vendor_ramdisk_size; /* size in bytes */

#define VENDOR_BOOT_ARGS_SIZE 2048
    uint8_t cmdline[VENDOR_BOOT_ARGS_SIZE];

    uint32_t tags_addr;           /* physical addr for kernel tags */

#define VENDOR_BOOT_NAME_SIZE 16
    uint8_t name[VENDOR_BOOT_NAME_SIZE]; /* asciiz product name */
    uint32_t header_size;         /* size of vendor boot image header in
                                   * bytes */
    uint32_t dtb_size;            /* size of dtb image */
    uint64_t dtb_addr;            /* physical load address */

};

버전 4

struct vendor_boot_img_hdr_v4
{
#define VENDOR_BOOT_MAGIC_SIZE 8
    uint8_t magic[VENDOR_BOOT_MAGIC_SIZE];
    uint32_t header_version;
    uint32_t page_size;           /* flash page size we assume */

    uint32_t kernel_addr;         /* physical load addr */
    uint32_t ramdisk_addr;        /* physical load addr */

    uint32_t vendor_ramdisk_size; /* size in bytes */

#define VENDOR_BOOT_ARGS_SIZE 2048
    uint8_t cmdline[VENDOR_BOOT_ARGS_SIZE];

    uint32_t tags_addr;           /* physical addr for kernel tags */

#define VENDOR_BOOT_NAME_SIZE 16
    uint8_t name[VENDOR_BOOT_NAME_SIZE]; /* asciiz product name */
    uint32_t header_size;         /* size of vendor boot image header in
                                   * bytes */
    uint32_t dtb_size;            /* size of dtb image */
    uint64_t dtb_addr;            /* physical load address */

    uint32_t vendor_ramdisk_table_size; /* size in bytes for the vendor ramdisk table */
    uint32_t vendor_ramdisk_table_entry_num; /* number of entries in the vendor ramdisk table */
    uint32_t vendor_ramdisk_table_entry_size; /* size in bytes for a vendor ramdisk table entry */
    uint32_t bootconfig_size; /* size in bytes for the bootconfig section */
};

#define VENDOR_RAMDISK_TYPE_NONE 0
#define VENDOR_RAMDISK_TYPE_PLATFORM 1
#define VENDOR_RAMDISK_TYPE_RECOVERY 2
#define VENDOR_RAMDISK_TYPE_DLKM 3

struct vendor_ramdisk_table_entry_v4
{
    uint32_t ramdisk_size; /* size in bytes for the ramdisk image */
    uint32_t ramdisk_offset; /* offset to the ramdisk image in vendor ramdisk section */
    uint32_t ramdisk_type; /* type of the ramdisk */
#define VENDOR_RAMDISK_NAME_SIZE 32
    uint8_t ramdisk_name[VENDOR_RAMDISK_NAME_SIZE]; /* asciiz ramdisk name */

#define VENDOR_RAMDISK_TABLE_ENTRY_BOARD_ID_SIZE 16
    // Hardware identifiers describing the board, soc or platform which this
    // ramdisk is intended to be loaded on.
    uint32_t board_id[VENDOR_RAMDISK_TABLE_ENTRY_BOARD_ID_SIZE];
};
  • vendor_ramdisk_size는 모든 공급업체 램디스크 프래그먼트의 총 크기입니다.
  • ramdisk_type은 램디스크 유형을 나타냅니다. 가능한 값은 다음과 같습니다.
    • VENDOR_RAMDISK_TYPE_NONE은 값이 지정되지 않았음을 나타냅니다.
    • VENDOR_RAMDISK_TYPE_PLATFORM 램디스크에는 플랫폼별 비트가 포함되어 있습니다. 부트로더는 이를 항상 메모리에 로드해야 합니다.
    • VENDOR_RAMDISK_TYPE_RECOVERY 램디스크에는 복구 리소스가 포함되어 있습니다. 부트로더는 복구로 부팅할 때 이를 메모리에 로드해야 합니다.
    • VENDOR_RAMDISK_TYPE_DLKM 램디스크에는 로드 가능한 동적 커널 모듈이 포함되어 있습니다.
  • ramdisk_name은 램디스크의 고유 이름입니다.
  • board_id는 공급업체에서 정의한 하드웨어 식별자의 벡터입니다.

부트로더 지원

공급업체 부팅 파티션에는 이전에 부팅 파티션에 있던 정보(플래시 페이지 크기, 커널, 램디스크 로드 주소, DTB 자체)가 들어 있으므로, 부트로더는 부팅 파티션과 공급업체 부팅 파티션 모두에 액세스하여 부팅을 완료하는 데 필요한 충분한 데이터를 가져와야 합니다.

부트로더는 공급업체 램디스크 바로 다음에 일반 램디스크를 메모리에 로드해야 합니다(CPIO, Gzip 및 lz4 형식이 이 연결 유형을 지원함). 일반 램디스크 이미지를 페이지 정렬하거나, 이 이미지와 메모리의 공급업체 램디스크 끝 사이에 다른 공간을 넣지 마세요. 커널은 압축 해제되면 연결된 파일을 initramfs에 추출합니다. 이를 통해 파일 구조가 생성되고 이 파일 구조가 공급업체 램디스크 파일 구조에 오버레이되는 일반 램디스크에 해당합니다.

일반 램디스크와 공급업체 램디스크는 서로 연결되기 때문에 형식이 동일해야 합니다. GKI 부팅 이미지는 lz4 압축 일반 램디스크를 사용하므로 GKI 규격 기기는 lz4 압축 공급업체 램디스크를 사용해야 합니다. 이를 위한 구성은 아래와 같습니다.

bootconfig 지원을 위한 부트로더 요구사항은 Bootconfig 구현 페이지에 설명되어 있습니다.

여러 공급업체 램디스크(버전 4)

부팅 이미지 헤더 버전 4를 사용하면 부트로더는 부팅 시간 동안 initramfs로 로드할 공급업체 램디스크의 일부나 전부를 선택할 수 있습니다. 공급업체 램디스크 표에는 각 램디스크의 메타데이터가 포함되어 있고 이 표를 통해 부트로더는 로드할 램디스크를 결정할 수 있습니다. 부트로더는 선택한 공급업체 램디스크를 로드할 순서를 정할 수 있습니다. 단 일반 램디스크가 마지막으로 로드되어야 합니다.

예를 들어 부트로더는 일반 부팅 중에 VENDOR_RAMDISK_TYPE_RECOVERY 유형의 공급업체 램디스크 로드를 생략하여 리소스를 절약할 수 있으므로 VENDOR_RAMDISK_TYPE_PLATFORMVENDOR_RAMDISK_TYPE_DLKM 유형의 공급업체 램디스크만 메모리에 로드됩니다. 반면에 VENDOR_RAMDISK_TYPE_PLATFORM, VENDOR_RAMDISK_TYPE_RECOVERY, VENDOR_RAMDISK_TYPE_DLKM 유형의 공급업체 램디스크는 복구 모드(Recovery mode)로 부팅될 때 메모리에 로드됩니다.

또는 부트로더가 공급업체 램디스크 표를 무시하고 전체 공급업체 램디스크 섹션을 로드할 수 있습니다. 이렇게 하면 vendor_boot 파티션에서 공급업체 램디스크 프래그먼트를 모두 로드하는 것과 효과가 같습니다.

빌드 지원

기기에 공급업체 부팅 지원을 구현하려면 다음 단계를 따르세요.

  • BOARD_BOOT_HEADER_VERSION3 이상으로 설정합니다.

  • 기기가 GKI 규격이거나 lz4 압축 일반 램디스크를 사용하는 경우 BOARD_RAMDISK_USE_LZ4true로 설정합니다.

  • 공급업체 램디스크에서 사용해야 하는 커널 모듈을 고려하여 BOARD_VENDOR_BOOTIMAGE_PARTITION_SIZE를 기기에 적합한 크기로 설정합니다.

  • 기기의 vendor_boot 및 공급업체별 OTA 파티션 목록을 포함하도록 AB_OTA_PARTITIONS를 업데이트합니다.

  • 기기 fstabboot 파티션이 아닌 vendor_boot 파티션의 /first_stage_ramdisk에 복사합니다. 예를 들면 다음과 같습니다. $(LOCAL_PATH)/fstab.hardware:$(TARGET_COPY_OUT_VENDOR_RAMDISK)/first_stage_ramdisk/fstab.$(PRODUCT_PLATFORM)

vendor_boot에 여러 공급업체 램디스크를 포함하려면 다음 안내를 따르세요.

  • BOARD_BOOT_HEADER_VERSION4로 설정합니다.
  • BOARD_VENDOR_RAMDISK_FRAGMENTSvendor_boot에 포함할 논리적 공급업체 램디스크 프래그먼트 이름 목록으로 설정합니다.

  • 사전 빌드된 공급업체 램디스크를 추가하려면 BOARD_VENDOR_RAMDISK_FRAGMENT.$(vendor_ramdisk).PREBUILT를 사전 빌드된 파일 경로로 설정합니다.

  • DLKM 공급업체 램디스크를 추가하려면 포함할 커널 모듈 디렉터리 목록으로 BOARD_VENDOR_RAMDISK_FRAGMENT.$(vendor_ramdisk).KERNEL_MODULE_DIRS를 설정합니다.

  • BOARD_VENDOR_RAMDISK_FRAGMENT.$(vendor_ramdisk).MKBOOTIMG_ARGSmkbootimg 인수로 설정합니다. 이는 공급업체 램디스크 프래그먼트의 --board_id[0-15]--ramdisk_type 인수입니다. DLKM 공급업체 램디스크의 경우 달리 지정되지 않으면 기본 --ramdisk_typeDLKM입니다.

vendor_boot에서 복구 리소스를 독립형 recovery 램디스크로 빌드하려면 다음 안내를 따르세요.

  • BOARD_BOOT_HEADER_VERSION4로 설정합니다.
  • BOARD_MOVE_RECOVERY_RESOURCES_TO_VENDOR_BOOTtrue로 설정합니다.
  • BOARD_INCLUDE_RECOVERY_RAMDISK_IN_VENDOR_BOOTtrue로 설정합니다.
  • 이렇게 하면 ramdisk_namerecovery이고 ramdisk_typeVENDOR_RAMDISK_TYPE_RECOVERY인 공급업체 램디스크 프래그먼트가 추가됩니다. 그러면 램디스크에는 모든 복구 파일($(TARGET_RECOVERY_ROOT_OUT) 아래에 설치된 파일)이 포함됩니다.

mkbootimg 인수

인수 설명
--ramdisk_type 램디스크 유형은 NONE, PLATFORM, RECOVERY, DLKM 중 하나일 수 있습니다.
--board_id[0-15] board_id 벡터를 지정합니다. 기본값은 0입니다.

다음은 구성 예를 보여줍니다.

BOARD_KERNEL_MODULE_DIRS := foo bar baz
BOARD_BOOT_HEADER_VERSION := 4
BOARD_VENDOR_RAMDISK_FRAGMENTS := dlkm_foobar
BOARD_VENDOR_RAMDISK_FRAGMENT.dlkm_foobar.KERNEL_MODULE_DIRS := foo bar
BOARD_VENDOR_RAMDISK_FRAGMENT.dlkm_foobar.MKBOOTIMG_ARGS := --board_id0 0xF00BA5 --board_id1 0xC0FFEE

결과 vendor_boot에는 공급업체 램디스크 프래그먼트 2개가 포함됩니다. 첫 번째는 '기본' 램디스크로, 여기에는 DLKM 디렉터리 baz$(TARGET_VENDOR_RAMDISK_OUT)의 나머지 파일이 포함됩니다. 두 번째는 dlkm_foobar 램디스크로, 여기에는 DLKM 디렉터리 foobar가 포함되고 --ramdisk_type의 기본값은 DLKM입니다.