SDV sur QNX

Nous testons en interne la SDV sur du matériel. Nous utilisons QVM sur QNX pour la virtualisation. Nous partageons tous les cibles, la documentation et les configurations en tant qu'exemples.

Prérequis

Cette page suppose que QNX est préconfiguré et n'inclut pas les étapes de compilation, de configuration ni de flashage de QNX sur le matériel.

Cette page suppose que vous exécutez QNX sur du matériel arm64 et que vous créez et utilisez les cibles _arm64 de SDV.

Composants requis

  • Un blob d'arborescence de périphériques (DTB) pour définir le matériel virtuel
  • Noyau Linux à utiliser
  • Un ramdisk combiné qui inclut toutes les propriétés de démarrage du ramdisk
  • Transfert d'une chaîne DICE pour l'authentification de la VM SDV
  • Toutes les partitions de disque du système
  • Configuration QVM de la VM

Blob d'arborescence de périphériques (DTB)

QVM génère la majeure partie du blob de l'arborescence des périphériques (DTB) en fonction de sa configuration. Par conséquent, le DTB peut être minimal :

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

Noyau

SDV utilise l'image générique du noyau (GKI, Generic Kernel Image). Vous pouvez utiliser directement le résultat d'une compilation.

Ramdisk

Les informations du ramdisk doivent inclure les différents ramdisks générés par Android et les propriétés de démarrage. Étant donné que QNX ne prend pas en charge de bootloader par défaut, vous devez générer un ramdisk avec le format de données attendu.

Vous pouvez le faire avec le script Python suivant, qui concatène plusieurs ramdisks et ajoute la configuration de démarrage (qui est le fichier vendor-bootconfig.img) au format attendu :

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

Chaîne DICE

Dans un système de production, le système hôte et le chargeur de démarrage construisent la chaîne DICE de manière dynamique pendant le processus de démarrage et fournissent une chaîne DICE à l'invité pour vérifier que l'image est fiable. Étant donné que cette exigence peut compliquer les flux de test et de développement, vous chargez plutôt un instantané de la chaîne DICE.

Pour générer les fichiers dice_handover_instance*, utilisez n'importe quelle version SDV Cuttlefish. Exemple :

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

Disque

QVM est compatible avec plusieurs formats de disque virtuel. Notre configuration de référence utilise un fichier image de disque contenant toutes les partitions. bpttool peut générer ces disques, mais n'est pas activement développé dans Android.

Configuration de la QVM

La configuration QVM définit la configuration et pointe vers les différents fichiers. Nous fournissons les exemples de configurations suivants :

Questions fréquentes

Q : adb ne parvient pas à se connecter à ma VM. Que dois-je faire ?

R : Dans cette configuration, adb utilise Ethernet pour se connecter à votre VM. Vous avez besoin d'une configuration de transfert de port sur QNX qui transfère les requêtes vers les invités sur le port 5555. Vous devez vous connecter au système hôte. Vous pouvez également configurer un pont vers la VM et vous y connecter directement.

Q : Le journal système indique que IServiceRegistrationAgent est manquant. Pourquoi ?

R : La découverte de services repose sur une configuration de confiance et de binder entièrement fonctionnelle. Vérifiez qu'OpenDICE a été chargé correctement et que HwBinder n'affiche pas d'erreurs au démarrage. Si elles ne fonctionnent pas, vous devez d'abord les corriger.

Q : init_open_dice échoue. Que s'est-il passé ?

R : Les scripts de démarrage chargent les informations de confiance au démarrage et effacent l'emplacement de mémoire. Dans la configuration de votre QVM, vérifiez que la configuration de la ligne de commande et les données partagées dans l'emplacement de mémoire sont compatibles. Vérifiez également que l'emplacement de la mémoire dans le pilote, la configuration de la QVM et le DTB correspondent, et que l'emplacement de la mémoire est accessible en écriture.