빠른 부팅을 사용자 공간으로 이동

Android 10 및 이후 버전에서는 빠른 부팅 구현을 부트로더에서 사용자 공간으로 재배치하여 크기를 조절할 수 있는 파티션을 지원합니다. 이 재배치를 통해 HAL(하드웨어 추상화 계층)에 의해 구현된 빠른 부팅의 공급업체별 부분만 사용하여 플래싱 코드를 관리 및 테스트 가능한 일반적인 위치로 이동할 수 있습니다. 또한 Android 12 이상에서는 추가된 빠른 부팅 명령어를 통해 램디스크 플래시를 지원합니다.

빠른 부팅 및 복구 통합

사용자 공간 빠른 부팅과 복구는 유사하기 때문에 하나의 파티션이나 바이너리로 병합할 수 있습니다. 이렇게 하면 더 적은 공간을 사용하고 전체 파티션 수가 줄며 빠른 부팅 및 복구가 커널과 라이브러리를 공유하는 등의 이점이 생깁니다.

fastbootd를 지원하려면 부트로더가 boot-fastboot의 새로운 BCB(부팅 제어 블록) 명령어를 구현해야 합니다. fastbootd 모드를 시작하려면 부트로더가 boot-fastboot를 BCB 메시지의 명령어 필드에 작성하고 BCB의 recovery 필드를 변경하지 않고 그대로 두어 중단된 복구 작업을 다시 시작할 수 있도록 해야 합니다. status, stage, reserved 필드도 변경하지 않고 그대로 둡니다. BCB 명령어 필드에 boot-fastboot가 표시되면 부트로더가 로드되고 복구 이미지로 부팅됩니다. 이후 복구가 BCB 메시지를 파싱하고 fastbootd 모드로 전환됩니다.

ADB 명령어

이 섹션에서는 fastbootd 통합을 위한 adb 명령어를 설명합니다. 명령어는 시스템에서 실행하는지 또는 복구로 실행되는지에 따라 결과가 다릅니다.

명령어 설명
reboot fastboot
  • fastbootd(시스템)으로 재부팅합니다.
  • 재부팅 없이 fastbootd를 직접 입력합니다(복구).

빠른 부팅 명령어

이 섹션에서는 fastbootd 통합을 위한 빠른 부팅 명령어를 설명합니다. 여기에는 논리 파티션을 플래시하고 관리하기 위한 새로운 명령어가 포함되어 있습니다. 일부 명령어는 부트로더로 실행되었는지 또는 fastbootd로 실행되었는지에 따라 결과가 다릅니다.

명령어 설명
reboot recovery
  • 복구로 재부팅합니다(부트로더).
  • 재부팅 없이 직접 복구를 입력합니다(fastbootd).
reboot fastboot fastbootd로 재부팅합니다.
getvar is-userspace
  • yes를 반환합니다(fastbootd).
  • no를 반환합니다(부트로더).
getvar is-logical:<partition> 지정된 파티션이 논리 파티션이면 yes를 반환하고 그렇지 않으면 no를 반환합니다. 논리 파티션은 아래에 나열된 명령어를 전부 지원합니다.
getvar super-partition-name super 파티션의 이름을 반환합니다. super 파티션이 드물게 A/B 파티션인 경우 이름에 현재 슬롯 접미사가 포함됩니다.
create-logical-partition <partition> <size> 지정된 이름과 크기로 논리 파티션을 만듭니다. 이 이름이 이미 논리 파티션으로 존재해서는 안 됩니다.
delete-logical-partition <partition> 지정된 논리 파티션을 삭제합니다(사실상 파티션이 삭제됨).
resize-logical-partition <partition> <size> 콘텐츠를 변경하지 않고 논리 파티션의 크기를 새로운 크기로 조정합니다. 크기를 조정하기에 공간이 충분하지 않으면 실패합니다.
update-super <partition> 변경사항을 super 파티션 메타데이터에 병합합니다. 기기의 형식이 지원되지 않는 버전인 경우와 같이 병합이 불가능한 경우 이 명령어는 실패합니다. 선택사항인 wipe 매개변수는 병합을 수행하지 않고 기기의 메타데이터를 덮어씁니다.
flash <partition><filename> ] 플래시 파티션에 파일을 씁니다. 기기는 잠금 해제 상태여야 합니다.
erase <partition> 파티션을 삭제합니다(secure erase일 필요 없음). 기기는 잠금 해제 상태여야 합니다.
getvar <variable> | all 부트로더 변수 또는 모든 변수를 표시합니다. 변수가 없으면 오류를 반환합니다.
set_active <slot>

지정된 A/B 부팅 슬롯을 active로 설정합니다. 다음 부팅 시도 시 시스템은 지정된 슬롯에서 부팅됩니다.

A/B 지원의 경우 슬롯은 독립적으로 부팅될 수 있는 중복된 파티션 집합입니다. 슬롯의 이름은 a, b 등으로 지정되며 접미사 _a, _b 등을 파티션 이름에 추가하여 구분될 수 있습니다.

reboot 기기를 정상적으로 재부팅합니다.
reboot-bootloader(또는 reboot bootloader) 기기를 부트로더로 재부팅합니다.
fastboot fetch vendor_boot <out.img>

Android 12 이상에서 사용하여 공급업체 램디스크 플래시를 지원합니다.

전체 파티션 크기와 청크 크기를 가져옵니다. 각 청크의 데이터를 가져와 데이터를 함께 <out.img>에 병합합니다.

자세한 내용은 fastboot fetch vendor_boot <out.img>를 참고하세요.

fastboot flash vendor_boot:default <vendor-ramdisk.img>

Android 12 이상에서 사용하여 공급업체 램디스크 플래시를 지원합니다.

이는 플래시 명령어의 특수한 변형입니다. 마치 fastboot fetch가 호출된 것처럼 fetch vendor_boot 이미지 함수를 실행합니다. 플래시되는 새 vendor_boot 이미지는 부팅 헤더 버전이 버전 3인지 버전 4인지에 따라 다릅니다.

자세한 내용은 fastboot flash vendor_boot:default <vendor-ramdisk.img>를 참고하세요.

fastboot flash vendor_boot:<foo> <vendor-ramdisk.img> Android 12 이상에서 사용하여 공급업체 램디스크 플래시를 지원합니다.

vendor_boot 이미지를 가져옵니다. 공급업체 부팅 헤더가 버전 3이면 오류를 반환합니다. 버전 4인 경우 올바른 공급업체 램디스크 프래그먼트가 있다면 이를 찾습니다. 이를 주어진 이미지로 바꾸고 크기와 오프셋을 다시 계산하여 새 vendor_boot image를 플래시합니다.

자세한 내용은 fastboot flash vendor_boot:<foo> <vendor-ramdisk.img>를 참고하세요.

빠른 부팅 및 부트로더

부트로더는 bootloader, radioboot/recovery 파티션을 플래시한 다음, 기기가 빠른 부팅(사용자 공간)으로 부팅하고 다른 모든 파티션을 플래시합니다. 부트로더는 다음 명령어를 지원해야 합니다.

명령어 설명
download 이미지를 플래시로 다운로드합니다.
flash recovery <image>/ flash boot <image>/ flash bootloader <image>/ recovery/boot 파티션 및 부트로더를 플래시합니다.
reboot 기기를 재부팅합니다.
reboot fastboot 빠른 부팅으로 재부팅합니다.
reboot recovery 복구로 재부팅합니다.
getvar 복구/부팅 이미지를 플래시하는 데 필요한 부트로더 변수를 가져옵니다(예: current-slotmax-download-size).
oem <command> OEM에서 정의한 명령어입니다.

동적 파티션

부트로더는 동적 파티션의 플래싱 또는 삭제를 허용해서는 안 되며 이러한 작업을 시도하면 오류가 반환되어야 합니다. 재구성된 동적 파티션 기기의 경우 빠른 부팅 도구(및 부트로더)는 부트로더 모드에서 동적 파티션을 직접 플래시하기 위해 강제 모드를 지원합니다. 예를 들어 system이 재구성된 기기의 동적 파티션인 경우 fastboot --force flash system 명령어를 사용하면 부트로더가 fastbootd 대신 파티션을 플래시할 수 있습니다.

오프 모드 충전

기기가 오프 모드 충전을 지원하거나 전원이 공급될 때 특수 모드로 자동 부팅되는 경우 fastboot oem off-mode-charge 0 명령어 구현에서는 이러한 특수 모드를 우회해야 합니다. 그래야 기기가 마치 사용자가 전원 버튼을 누른 것처럼 부팅됩니다.

빠른 부팅 OEM HAL

부트로더 빠른 부팅을 완전히 교체하려면 빠른 부팅이 모든 기존 빠른 부팅 명령어를 처리해야 합니다. 이러한 명령어의 대부분은 OEM에서 제공되며 문서화되지만, 맞춤 구현이 필요합니다. OEM 관련 명령어는 대부분 문서화되지 않습니다. 이러한 명령어를 처리하기 위해 빠른 부팅 HAL은 필수 OEM 명령어를 지정합니다. OEM은 자체 명령어를 구현할 수도 있습니다.

빠른 부팅 HAL의 정의는 다음과 같습니다.

import IFastbootLogger;

/**
 * IFastboot interface implements vendor specific fastboot commands.
 */
interface IFastboot {
    /**
     * Returns a bool indicating whether the bootloader is enforcing verified
     * boot.
     *
     * @return verifiedBootState True if the bootloader is enforcing verified
     * boot and False otherwise.
     */
    isVerifiedBootEnabled() generates (bool verifiedBootState);

    /**
     * Returns a bool indicating the off-mode-charge setting. If off-mode
     * charging is enabled, the device autoboots into a special mode when
     * power is applied.
     *
     * @return offModeChargeState True if the setting is enabled and False if
     * not.
     */
    isOffModeChargeEnabled() generates (bool offModeChargeState);

    /**
     * Returns the minimum battery voltage required for flashing in mV.
     *
     * @return batteryVoltage Minimum battery voltage (in mV) required for
     * flashing to be successful.
     */
    getBatteryVoltageFlashingThreshold() generates (int32_t batteryVoltage);

    /**
     * Returns the file system type of the partition. This is only required for
     * physical partitions that need to be wiped and reformatted.
     *
     * @return type Can be ext4, f2fs or raw.
     * @return result SUCCESS if the operation is successful,
     * FAILURE_UNKNOWN if the partition is invalid or does not require
     * reformatting.
     */
    getPartitionType(string partitionName) generates (FileSystemType type, Result result);

    /**
     * Executes a fastboot OEM command.
     *
     * @param oemCmd The oem command that is passed to the fastboot HAL.
     * @response result Returns the status SUCCESS if the operation is
     * successful,
     * INVALID_ARGUMENT for bad arguments,
     * FAILURE_UNKNOWN for an invalid/unsupported command.
     */
    doOemCommand(string oemCmd) generates (Result result);

};

fastbootd 사용 설정

기기에서 fastbootd를 사용 설정하는 방법은 다음과 같습니다.

  1. 다음과 같이 fastbootddevice.mkPRODUCT_PACKAGESPRODUCT_PACKAGES += fastbootd와 같이 추가합니다.

  2. 빠른 부팅 HAL, 부팅 제어 HAL, 상태 HAL이 복구 이미지의 일부로 패키징되는지 확인합니다.

  3. fastbootd에 필요한 기기별 SEPolicy 권한을 모두 추가합니다. 예를 들어 fastbootd는 파티션을 플래시하기 위해 기기별 파티션에 관한 쓰기 액세스 권한이 필요합니다. 빠른 부팅 HAL 구현에도 기기별 권한이 필요할 수 있습니다.

사용자 공간 빠른 부팅을 검사하려면 VTS(공급업체 테스트 모음)를 실행합니다.

공급업체 램디스크 플래시

Android 12 이상에서는 기기에서 전체 vendor_boot 이미지를 가져오는 추가된 빠른 부팅 명령어로 램디스크 플래시를 지원합니다. 이 명령어는 호스트 측 빠른 부팅 도구가 공급업체 부팅 헤더를 읽고 이미지를 다시 만들어 새 이미지를 플래시하도록 합니다.

전체 vendor_boot 이미지를 가져오기 위해 빠른 부팅 프로토콜과 Android 12의 fastbootd 프로토콜 구현에 모두 fetch:vendor_boot 명령어가 추가되었습니다. fastbootd로 이를 구현할 수 있지만 부트로더 자체로는 구현하지 못할 수 있습니다. OEM은 fetch:vendor_boot 명령어를 프로토콜의 부트로더 구현에 추가할 수 있습니다. 그러나 명령어가 부트로더 모드에서 인식되지 않으면 개별 공급업체 램디스크를 부트로더 모드에서 플래시하는 것은 공급업체 지원 옵션이 아닙니다.

부트로더 변경사항

getvar:max-fetch-sizefetch:name 명령어는 fastbootd에서 구현됩니다. 부트로더에서 공급업체 램디스크 플래시를 지원하려면 이 두 명령어를 구현해야 합니다.

Fastbootd 변경사항

getvar:max-fetch-sizemax-download-size와 비슷합니다. 기기에서 하나의 데이터 응답으로 전송할 수 있는 최대 크기를 지정합니다. 드라이버는 이 값보다 큰 크기를 가져오면 안 됩니다.

fetch:name[:offset[:size]]는 기기에서 일련의 검사를 실행합니다. 다음 내용이 모두 참이면 fetch:name[:offset[:size]] 명령어는 데이터를 반환합니다.

  • 기기에서 디버그 가능한 빌드를 실행하고 있습니다.
  • 기기가 잠금 해제되었습니다(부팅 상태 주황색).
  • 가져온 파티션 이름이 vendor_boot입니다.
  • size 값이 0 < size <= max-fetch-size 범위에 속합니다.

이러한 내용이 확인되면 fetch:name[:offset[:size]]는 파티션 크기와 오프셋을 반환합니다. 다음 내용을 참고하세요.

  • fetch:namefetch:name:0과 같고 이는 fetch:name:0:partition_size와 같습니다.
  • fetch:name:offsetfetch:name:offset:(partition_size - offset)과 같습니다.

따라서 fetch:name[:offset[:size]]fetch:name:offset:(partition_size - offset)과 같습니다.

offset이나 partition_size(또는 둘 다)가 지정되지 않으면 기본값이 사용되며, 기본값은 offset의 경우에는 0이고 size의 경우에는 partition_size - offset의 계산된 값입니다.

  • 오프셋은 지정되고 크기는 지정되지 않음: size = partition_size - offset
  • 둘 다 지정되지 않음: 둘 다 기본값이 사용됨, size = partition_size - 0

예를 들어 fetch:foo는 오프셋 0에서 전체 foo 파티션을 가져옵니다.

드라이버 변경사항

드라이버 변경사항을 구현하기 위해 빠른 부팅 도구에 명령어가 추가되었습니다. 각각 빠른 부팅 명령어 표의 전체 정의에 링크되어 있습니다.

  • fastboot fetch vendor_boot out.img

    • getvar max-fetch-size를 호출하여 청크 크기를 결정합니다.
    • getvar partition-size:vendor_boot[_a]를 호출하여 전체 파티션 크기를 결정합니다.
    • 각 청크에 fastboot fetch vendor_boot[_a]:offset:size를 호출합니다. 청크 크기는 vendor_boot 크기보다 크므로 청크는 일반적으로 하나만 있습니다.
    • 데이터를 out.img에 함께 병합합니다.
  • fastboot flash vendor_boot:default vendor-ramdisk.img

    이는 플래시 명령어의 특수한 변형입니다. 마치 fastboot fetch가 호출된 것처럼 vendor_boot 이미지를 가져옵니다.

    • 공급업체 부팅 헤더가 버전 3이면 다음이 실행됩니다.
      • 공급업체 램디스크를 주어진 이미지로 바꿉니다.
      • vendor_boot 이미지를 플래시합니다.
    • 공급업체 부팅 헤더가 버전 4이면 다음이 실행됩니다.
      • 주어진 이미지가 vendor_boot 이미지에서 유일한 공급업체 램디스크 프래그먼트가 되도록 전체 공급업체 램디스크를 주어진 이미지로 바꿉니다.
      • 공급업체 램디스크 표의 크기와 오프셋을 다시 계산합니다.
      • vendor_boot 이미지를 플래시합니다.
  • fastboot flash vendor_boot:foo vendor-ramdisk.img

    마치 fastboot fetch가 호출된 것처럼 vendor_boot image를 가져옵니다.

    • 공급업체 부팅 헤더가 버전 3이면 오류를 반환합니다.
    • 공급업체 부팅 헤더가 버전 4이면 다음이 실행됩니다.

      • 이름이 foo인 공급업체 램디스크 프래그먼트를 찾습니다. 찾을 수 없거나 일치하는 항목이 여러 개인 경우 오류를 반환합니다.
      • 공급업체 램디스크 프래그먼트를 주어진 이미지로 바꿉니다.
      • 공급업체 램디스크 표의 각 크기와 오프셋을 다시 계산합니다.
      • vendor_boot 이미지를 플래시합니다.

mkbootimg

default 이름은 Android 12 이상에서 공급업체 램디스크 프래그먼트의 이름을 지정하기 위해 예약되어 있습니다. 빠른 부팅 flash vendor_boot:default 시맨틱스는 동일하게 유지되지만 램디스크 프래그먼트의 이름을 default로 지정해서는 안 됩니다.

SELinux 변경사항

공급업체 램디스크 플래시를 지원하기 위해 fastbootd.te가 변경되었습니다.