SDV en QNX

Realizamos pruebas internas de SDV en hardware. Usamos QVM en QNX para la virtualización. Compartimos todos los objetivos, la documentación y las configuraciones como muestras.

Requisitos previos

En esta página, se supone que QNX ya está configurado y no se incluyen los pasos para compilar, configurar o escribir QNX en el hardware.

En esta página, se supone que ejecutas QNX en hardware arm64 y que compilas y usas los destinos _arm64 del SDV.

Componentes obligatorios

  • Un BLOB del árbol de dispositivos (DTB) para definir el hardware virtual
  • Un kernel de Linux para usar
  • Un disco RAM combinado que incluye todas las propiedades de arranque del disco RAM
  • Transferencia de una cadena de DICE para la autenticación de la VM de SDV
  • Todas las particiones de disco del sistema
  • Es una configuración de QVM de la VM.

BLOB del árbol de dispositivos (DTB)

La QVM genera la mayor parte del blob del árbol de dispositivos (DTB) según su configuración. Por lo tanto, el DTB puede ser mínimo:

/*
 * 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>;
        };
    };
};

Kernel

El SDV usa la imagen genérica del kernel (GKI), y puedes usar el resultado de una compilación directamente.

Ramdisk

La información del disco RAM debe incluir los diferentes discos RAM que genera Android y las propiedades de arranque. Dado que QNX no admite un cargador de arranque de forma predeterminada, debes generar un disco RAM con el formato de datos esperado.

Puedes hacerlo con la siguiente secuencia de comandos de Python, que concatena varios ramdisks y agrega el bootconfig (que es el archivo vendor-bootconfig.img) en el formato esperado:

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')

Cadena de DICE

En un sistema de producción, el sistema host y el cargador de arranque construyen la cadena de DICE de forma dinámica durante el proceso de arranque y proporcionan una cadena de DICE al invitado para verificar que se puede confiar en la imagen. Debido a que este requisito puede complicar los flujos de prueba y desarrollo, en su lugar, cargas una instantánea de la cadena de DICE.

Para generar los archivos dice_handover_instance*, usa cualquier compilación de Cuttlefish de SDV. Por ejemplo:

lunch sdv_core_cf-trunk_staging-userdebug
m
cp $OUT/product/etc/dice_handover_instance* <GUEST>/test_dice_handover

Disco

QVM admite varios formatos para un disco virtual. Nuestra configuración de referencia usa un archivo de imagen de disco que contiene todas las particiones. bpttool puede generar esos discos, pero no se desarrolla de forma activa en Android.

Configuración de QVM

La configuración de la QVM establece la configuración y apunta a los diferentes archivos. Proporcionamos los siguientes ejemplos de configuración:

  • Configuración de la VM de SDV Core
  • Configuración de la VM de SDV Media
  • VM de IVI con integración de SDV

Preguntas frecuentes

P.: adb no se puede conectar a mi VM. ¿Qué puedo hacer?

R.: En esta configuración, adb usa Ethernet para conectarse a tu VM. Necesitas una configuración de redirección de puertos en QNX que reenvíe solicitudes a invitados en el puerto 5555. Debes conectarte al sistema host. Como alternativa, también puedes configurar un puente a la VM y conectarte a ella directamente.

P.: El registro del sistema muestra que falta IServiceRegistrationAgent. ¿Por qué?

R.: El descubrimiento de servicios depende de una configuración de confianza y vinculador que funcione correctamente. Verifica que OpenDICE se haya cargado correctamente y que HwBinder no muestre errores durante el inicio. Si no funcionan, primero debes corregirlos.

P.: init_open_dice falla. ¿Qué sucedió?

R.: Los secuencias de comandos de inicio cargan la información de confianza durante el inicio y borran la ubicación de memoria. Verifica en la configuración de la QVM que la configuración de la línea de comandos y los datos compartidos en la ubicación de memoria coincidan. También verifica que la ubicación de memoria en el controlador, la configuración de la QVM y el DTB coincidan, y que la ubicación de memoria sea grabable.