我们在内部硬件上测试 SDV。我们在 QNX 上使用 QVM 进行虚拟化。 我们会将所有目标、文档和配置作为示例进行分享。
前提条件
本页面假定您已预先配置 QNX,并且不包含在硬件上构建、配置或刷写 QNX 的步骤。
本页面假定您在 arm64 硬件上运行 QNX,并构建和使用 SDV 的 _arm64 目标。
必需组件
- 用于定义虚拟硬件的设备树 blob (DTB)
- 要使用的 Linux 内核
- 包含所有 ramdisk 启动属性的组合 ramdisk
- 用于 SDV 虚拟机身份验证的 DICE 链 的移交
- 系统的所有磁盘分区
- 虚拟机的 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),您可以直接使用 build 的输出。
Ramdisk
ramdisk 信息应包含 Android 生成的不同 ramdisk 和启动属性。由于 QNX 默认不支持引导加载程序 ,因此您必须生成具有预期数据格式的 ramdisk。
您可以使用以下 Python 脚本执行此操作,该脚本会连接多个 ramdisk 并以预期格式添加 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 build。
例如:
lunch sdv_core_cf-trunk_staging-userdebug
m
cp $OUT/product/etc/dice_handover_instance* <GUEST>/test_dice_handover
磁盘
QVM 支持多种虚拟磁盘格式;我们的参考配置 使用包含所有分区的磁盘映像文件。bpttool 可以生成 这些磁盘,但在 Android 中并未积极开发。
QVM 配置
QVM 配置会设置配置,并指向不同的文件。 我们提供了以下示例配置:
- SDV Core 虚拟机配置
- SDV Media 虚拟机配置
- 集成 SDV 的 IVI 虚拟机
常见问题解答
问:adb 无法连接到我的虚拟机。我该怎么办?
答:在此设置中,adb 使用以太网连接到您的虚拟机。您需要在 QNX 上进行端口转发配置,以将请求转发到端口 5555 上的访客。 您需要连接到主机系统。或者,您也可以为虚拟机配置网桥,并直接连接到该虚拟机。
问:系统日志显示 IServiceRegistrationAgent 缺失。为什么?
答:服务发现依赖于完全正常运行的信任和 binder 设置。验证 OpenDICE 是否已成功加载,并且 HwBinder 在启动期间未显示错误。如果这些设置不起作用,您需要先修复它们。
问:init_open_dice 失败。发生了什么?
答:启动脚本会在启动期间加载信任信息,并擦除内存位置。在 QVM 配置中验证 cmdline 配置和内存位置中的共享数据是否匹配。另请验证驱动程序、QVM 配置和 DTB 中的内存位置是否匹配,以及内存位置是否可写。