Google에서는 하드웨어에서 SDV를 내부적으로 테스트합니다. 가상화에는 QNX에서 QVM을 사용합니다. 모든 타겟, 문서, 구성은 샘플로 공유됩니다.
기본 요건
이 페이지에서는 미리 구성된 QNX를 가정하며 하드웨어에 QNX를 빌드하거나 구성하거나 플래시하는 단계는 포함하지 않습니다.
이 페이지에서는 arm64 하드웨어에서 QNX를 실행하고 SDV의 _arm64 타겟을 빌드하고 사용한다고 가정합니다.
필수 구성요소
- 가상 하드웨어를 정의하는 기기 트리 Blob (DTB)
- 사용할 Linux 커널
- 모든 램디스크 부팅 속성을 포함하는 결합된 램디스크
- SDV VM 인증을 위한 DICE 체인의 핸드오프
- 시스템의 모든 디스크 파티션
- VM의 QVM 구성
기기 트리 Blob (DTB)
QVM은 구성을 기반으로 대부분의 기기 트리 Blob (DTB)을 생성합니다. 따라서 DTB는 최소화할 수 있습니다.
/*
* Copyright (C) 2026 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/dts-v1/;
/ {
model = "Virtual Machine";
#address-cells = <2>;
#size-cells = <2>;
// This reserved-memory node specifies for the open-dice driver which memory region(s) to
// expose as /dev/open-dice<n> device(s)
reserved-memory {
// The number of u32 cells to represent the address of a memory region
#address-cells = <2>;
// The number of u32 cells to represent the size of a memory region
#size-cells = <2>;
ranges;
// The unit address (after the @) must match the address in the reg property
dice@D1C30000 {
// The open-dice driver receives this device tree node based on this
// property.
compatible = "google,open-dice";
no-map;
// The address and the size of the memory region that is passed to the
// open-dice driver.
// First two hex numbers (cells) represent the address of the memory region,
// the last two represent its size (4K, in this case).
reg = <0x0 0xD1C30000 0x0 0x1000>;
};
};
};
커널
SDV는 일반 커널 이미지 (GKI)를 사용하며 빌드 출력을 직접 사용할 수 있습니다.
램디스크
램디스크 정보에는 Android에서 생성하는 다양한 램디스크와 부팅 속성이 포함되어야 합니다. QNX는 기본적으로 부트로더를 지원하지 않으므로 예상 데이터 형식으로 램디스크를 생성해야 합니다.
다음 Python 스크립트를 사용하면 여러 램디스크를 연결하고 예상 형식으로 bootconfig (vendor-bootconfig.img 파일)를 추가할 수 있습니다.
def create_qnx_ramdisk(output: io.BytesIO,
ramdisks: Sequence[io.BytesIO],
bootconfig: Optional[io.BytesIO]):
BUFFER_SIZE = 4096
for ramdisk in ramdisks:
while buf := ramdisk.read(BUFFER_SIZE):
output.write(buf)
# Kernel looks for bootconfig at the end of ramdisk.
if bootconfig:
bootconfig_checksum = 0
bootconfig_size = 0
while buf := bootconfig.read(BUFFER_SIZE):
bootconfig_checksum = (bootconfig_checksum + sum(buf)) & 0xFFFFFFFF
bootconfig_size += len(buf)
output.write(buf)
output.write(struct.pack('II', bootconfig_size, bootconfig_checksum))
output.write(b'#BOOTCONFIG\n')
DICE 체인
프로덕션 시스템에서 호스트 시스템과 부트로더는 부팅 프로세스 중에 DICE 체인을 동적으로 구성하고 이미지를 신뢰할 수 있는지 확인할 수 있도록 게스트에 DICE 체인을 제공합니다. 이 요구사항으로 인해 테스트 및 개발 흐름이 복잡해질 수 있으므로 DICE 체인 스냅샷을 대신 로드합니다.
dice_handover_instance* 파일을 생성하려면 SDV Cuttlefish 빌드를 사용하세요.
예를 들면 다음과 같습니다.
lunch sdv_core_cf-trunk_staging-userdebug
m
cp $OUT/product/etc/dice_handover_instance* <GUEST>/test_dice_handover
디스크
QVM은 가상 디스크의 여러 형식을 지원합니다. 참조 구성에서는 모든 파티션을 포함하는 디스크 이미지 파일을 사용합니다. bpttool은 이러한 디스크를 생성할 수 있지만 Android 내에서 적극적으로 개발되지는 않습니다.
QVM 구성
QVM 구성은 구성을 설정하고 여러 파일을 가리킵니다. 다음과 같은 샘플 구성을 제공합니다.
자주 묻는 질문(FAQ)
Q: adb가 VM에 연결할 수 없습니다. 어떻게 해야 하나요?
A: 이 설정에서 adb는 이더넷을 사용하여 VM에 연결합니다. 포트 5555의 게스트로 요청을 전달하는 QNX의 포트 전달 구성이 필요합니다. 호스트 시스템에 연결해야 합니다. 또는 VM에 브리지를 구성하고 직접 연결할 수도 있습니다.
Q: 시스템 로그에 IServiceRegistrationAgent가 누락된 것으로 표시됩니다. 이유가 무엇인가요?
A: 서비스 검색은 완전히 작동하는 신뢰 및 바인더 설정을 사용합니다. OpenDICE가 성공적으로 로드되었는지, HwBinder가 시작 중에 오류를 표시하지 않는지 확인합니다. 이러한 문제가 해결되지 않으면 먼저 문제를 해결해야 합니다.
Q: init_open_dice이 실패합니다. 어떻게 된 건가요?
A: 시작 스크립트는 시작 중에 신뢰 정보를 로드하고 메모리 위치를 삭제합니다. QVM 구성에서 cmdline 구성과 메모리 위치의 공유 데이터가 서로 맞는지 확인합니다. 또한 드라이버, QVM 구성, DTB의 메모리 위치가 일치하고 메모리 위치를 쓸 수 있는지 확인합니다.