SDV on QNX

אנחנו בודקים את SDV באופן פנימי בחומרה. אנחנו משתמשים ב-QVM ב-QNX לצורך וירטואליזציה. אנחנו משתפים את כל יעדי הטירגוט, המסמכים וההגדרות כדוגמאות.

דרישות מוקדמות

בדף הזה מניחים ש-QNX מוגדר מראש, ולא כוללים בו שלבים לבנייה, להגדרה או להעברה של QNX לחומרה.

בדף הזה מניחים שאתם מריצים QNX על חומרה של arm64, ויוצרים ומשתמשים ביעדים של SDV‏ _arm64.

רכיבים נדרשים

  • בלוב של עץ מכשירים (DTB) להגדרת החומרה הווירטואלית
  • ליבת Linux לשימוש
  • דיסק RAM משולב שכולל את כל מאפייני האתחול של דיסק RAM
  • העברה של שרשרת DICE לאימות מכונת SDV וירטואלית
  • כל מחיצות הדיסק של המערכת
  • הגדרה של QVM של המכונה הווירטואלית

בלוב של פירוט מבנה המכשיר (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 נעשה שימוש ב-Generic Kernel Image ‏ (GKI), ואפשר להשתמש ישירות בפלט של build.

Ramdisk

פרטי ה-ramdisk צריכים לכלול את ה-ramdisk השונים ש-Android יוצרת ואת מאפייני האתחול. מכיוון ש-QNX לא תומכת בטוען אתחול כברירת מחדל, צריך ליצור ramdisk עם פורמט הנתונים הצפוי.

אפשר לעשות את זה באמצעות סקריפט 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 קובעת את התצורה ומפנה לקבצים השונים. הנה דוגמאות להגדרות:

  • הגדרה של מכונה וירטואלית של SDV Core
  • הגדרת מכונה וירטואלית של SDV Media
  • מכונת VM של IVI עם שילוב של SDV

שאלות נפוצות

ש: אי אפשר לחבר את adb למכונה הווירטואלית שלי. מה אפשר לעשות?

תשובה: בהגדרה הזו, adb משתמש ב-Ethernet כדי להתחבר למכונה הווירטואלית. צריך להגדיר העברת יציאות ב-QNX כדי להעביר בקשות לאורחים ביציאה 5555. צריך להתחבר למערכת המארחת. לחלופין, אפשר גם להגדיר גשר למכונה הווירטואלית ולהתחבר אליה ישירות.

שאלה: ביומן המערכת מופיעה הודעה על כך שחסר IServiceRegistrationAgent. למה?

תשובה: גילוי שירותים מסתמך על הגדרה תקינה של אמון ושל קובץ binder. צריך לוודא ש-OpenDICE נטען בהצלחה וש-HwBinder לא מציג שגיאות במהלך ההפעלה. אם אלה לא פועלים, צריך לתקן אותם קודם.

שאלה: init_open_dice נכשלת. מה קרה?

תשובה: סקריפטים להפעלה טוענים את נתוני האמון במהלך ההפעלה ומנקים את מיקום הזיכרון. צריך לוודא בהגדרת ה-QVM שההגדרה של שורת הפקודה והנתונים המשותפים במיקום הזיכרון מתאימים זה לזה. צריך גם לוודא שמיקום הזיכרון במנהל ההתקן, בהגדרת ה-QVM וב-DTB זהה, ושיש אפשרות כתיבה במיקום הזיכרון.