הטמעת עדכוני A/B

יצרני OEM וספקי SoC שרוצים ליישם עדכוני מערכת A/B חייבים להבטיח שהמטען האתחול שלהם מיישם את ה-boot_control HAL ומעביר את הפרמטרים הנכונים לקרנל.

יישם את HAL בקרת האתחול

מאגרי אתחול בעלי יכולת A/B חייבים ליישם את boot_control HAL ב- hardware/libhardware/include/hardware/boot_control.h . אתה יכול לבדוק יישומים באמצעות כלי השירות system/extras/bootctl ו- system/extras/tests/bootloader/ .

עליך גם ליישם את מכונת המצב המוצגת להלן:

איור 1. מכונת מצב של טוען האתחול

הגדר את הקרנל

כדי ליישם עדכוני מערכת A/B:

  1. Cherrypick את סדרת תיקוני הגרעין הבאה (במידת הצורך):
  2. ודא שהארגומנטים של שורת הפקודה של הליבה מכילים את הארגומנטים הנוספים הבאים:
    skip_initramfs rootwait ro init=/init root="/dev/dm-0 dm=system none ro,0 1 android-verity <public-key-id> <path-to-system-partition>"
    ... כאשר הערך <public-key-id> הוא המזהה של המפתח הציבורי המשמש לאימות חתימת טבלת האימות (לפרטים, ראה dm-verity ) .
  3. הוסף את אישור .X509 המכיל את המפתח הציבורי למחזיק המפתחות של המערכת:
    1. העתק את אישור ה-.X509 המעוצב בפורמט .der לשורש ספריית kernel . אם אישור .X509 מעוצב כקובץ .pem , השתמש בפקודה openssl הבאה כדי להמיר מפורמט .pem לפורמט .der :
      openssl x509 -in <x509-pem-certificate> -outform der -out <x509-der-certificate>
    2. בנו את zImage כך שיכלול את האישור כחלק ממחזיק המפתחות של המערכת. כדי לאמת, בדוק את רשומת procfs (דורש הפעלה של KEYS_CONFIG_DEBUG_PROC_KEYS ):
      angler:/# cat /proc/keys
      
      1c8a217e I------     1 perm 1f010000     0     0 asymmetri
      Android: 7e4333f9bba00adfe0ede979e28ed1920492b40f: X509.RSA 0492b40f []
      2d454e3e I------     1 perm 1f030000     0     0 keyring
      .system_keyring: 1/4
      הכללה מוצלחת של תעודת .X509 מציינת את נוכחותו של המפתח הציבורי במחזיק המפתחות של המערכת (הדגשה מציינת את מזהה המפתח הציבורי).
    3. החלף את הרווח ב- # והעבר אותו בתור <public-key-id> בשורת הפקודה של הליבה. לדוגמה, העבר את Android:#7e4333f9bba00adfe0ede979e28ed1920492b40f במקום <public-key-id> .

הגדר משתני בנייה

מאגרי אתחול בעלי יכולת A/B חייבים לעמוד בקריטריונים הבאים של משתני הבנייה:

חייב להגדיר עבור יעד A/B
  • AB_OTA_UPDATER := true
  • AB_OTA_PARTITIONS := \
    boot \
    system \
    vendor
    ומחיצות אחרות שעודכנו באמצעות update_engine (רדיו, טוען אתחול וכו')
  • PRODUCT_PACKAGES += \
    update_engine \
    update_verifier
לדוגמא, עיין ב- /device/google/marlin/+/android-7.1.0_r1/device-common.mk . באפשרותך לבצע את שלב ה-dex2oat לאחר ההתקנה (אך לפני אתחול מחדש) המתואר בקומפילציה .
מומלץ בחום עבור יעד A/B
  • הגדר TARGET_NO_RECOVERY := true
  • הגדר BOARD_USES_RECOVERY_AS_BOOT := true
  • אל תגדיר BOARD_RECOVERYIMAGE_PARTITION_SIZE
לא ניתן להגדיר עבור יעד A/B
  • BOARD_CACHEIMAGE_PARTITION_SIZE
  • BOARD_CACHEIMAGE_FILE_SYSTEM_TYPE
אופציונלי עבור בניית באגים PRODUCT_PACKAGES_DEBUG += update_engine_client

הגדר מחיצות (חריצים)

מכשירי A/B אינם זקוקים למחיצת שחזור או למחיצת מטמון מכיוון ש-Android כבר לא משתמשת במחיצות אלו. מחיצת הנתונים משמשת כעת עבור חבילת OTA שהורדת, וקוד תמונת השחזור נמצא במחיצת האתחול. כל המחיצות שהן A/B-ed צריכות לקבל את השמות הבאים (משבצות נקראות תמיד a , b , וכו'): boot_a , boot_b , system_a , system_b , vendor_a , vendor_b .

מטמון

עבור עדכונים שאינם A/B, מחיצת המטמון שימשה לאחסון חבילות OTA שהורדו ולשמור בלוקים באופן זמני תוך החלת עדכונים. מעולם לא הייתה דרך טובה להתאים את גודל מחיצת המטמון: גודלה היה צריך להיות תלוי באילו עדכונים רצית להחיל. המקרה הגרוע ביותר יהיה מחיצת מטמון גדולה כמו תמונת המערכת. עם עדכוני A/B אין צורך להחביא בלוקים (כי אתה תמיד כותב למחיצה שאינה בשימוש כרגע) ועם A/B ​​סטרימינג אין צורך להוריד את כל חבילת OTA לפני החלתה.

התאוששות

דיסק RAM השחזור כלול כעת בקובץ boot.img . כאשר נכנסים לשחזור, טוען האתחול לא יכול לשים את אפשרות skip_initramfs בשורת הפקודה של הליבה.

עבור עדכונים שאינם A/B, מחיצת השחזור מכילה את הקוד המשמש להחלת עדכונים. עדכוני A/B מיושמים על ידי update_engine הפועל בתמונת המערכת הרגילה המאותחלת. עדיין קיים מצב שחזור המשמש ליישום איפוס נתוני היצרן וטעינת צד של חבילות עדכון (שממנו הגיע השם "שחזור"). הקוד והנתונים למצב שחזור מאוחסנים במחיצת האתחול הרגילה ב-ramdisk; כדי לאתחל לתוך תמונת המערכת, טוען האתחול אומר לקרנל לדלג על ה-ramdisk (אחרת המכשיר מאתחל למצב שחזור. מצב השחזור קטן (וחלק גדול ממנו כבר היה במחיצת האתחול), כך שמחיצת האתחול לא גדלה במידה.

Fstab

ארגומנט ה- slotselect חייב להיות על הקו עבור המחיצות A/B-ed. לדוגמה:

<path-to-block-device>/vendor  /vendor  ext4  ro
wait,verify=<path-to-block-device>/metadata,slotselect

אין לקרוא למחיצה vendor . במקום זאת, המחיצה vendor_a או vendor_b תיבחר ותותנה על נקודת הטעינה /vendor .

טיעוני משבצת ליבה

יש להעביר את סיומת החריץ הנוכחית או דרך צומת עץ מכשיר ספציפי (DT) ( /firmware/android/slot_suffix ) או דרך שורת הפקודה של ליבת androidboot.slot_suffix או ארגומנט bootconfig.

כברירת מחדל, fastboot מהבהב את החריץ הנוכחי בהתקן A/B. אם חבילת העדכון מכילה גם תמונות עבור המשבצת האחרת, הלא נוכחית, Fastboot מהבהב גם את התמונות הללו. האפשרויות הזמינות כוללות:

  • --slot SLOT . עוקף את התנהגות ברירת המחדל והנח את fastboot להבהב את החריץ המועבר כארגומנט.
  • --set-active [ SLOT ] . הגדר את החריץ כפעיל. אם לא צוין ארגומנט אופציונלי, החריץ הנוכחי מוגדר כפעיל.
  • fastboot --help . קבל פרטים על פקודות.

אם טוען האתחול מיישם את fastboot, עליו לתמוך בפקודה set_active <slot> שמגדירה את המשבצת הפעילה הנוכחית למשבצת הנתונה (זה חייב גם לנקות את הדגל הבלתי ניתן לאתחול עבור אותו משבצת ולאפס את ספירת הניסיונות החוזרים לערכי ברירת המחדל). טוען האתחול אמור לתמוך גם במשתנים הבאים:

  • has-slot:<partition-base-name-without-suffix> . מחזירה "כן" אם המחיצה הנתונה תומכת בחריצים, "לא" אחרת.
  • current-slot . מחזירה את סיומת המשבצת שתאותחל מהבא.
  • slot-count . מחזירה מספר שלם המייצג את מספר המשבצות הזמינות. נכון לעכשיו, שני חריצים נתמכים כך שהערך הזה הוא 2 .
  • slot-successful:<slot-suffix> . מחזירה "כן" אם המשבצת הנתונה סומנה כאתחול בהצלחה, "לא" אחרת.
  • slot-unbootable:<slot-suffix> . מחזירה "כן" אם המשבצת הנתונה מסומנת כלא ניתנת לאתחול, "לא" אחרת.
  • slot-retry-count . מספר הניסיונות החוזרים שנותרו לניסיון לאתחל את המשבצת הנתונה.

כדי להציג את כל המשתנים, הפעל את fastboot getvar all .

צור חבילות OTA

כלי החבילה של OTA פועלים לפי אותן פקודות כמו הפקודות עבור התקנים שאינם A/B. יש ליצור את הקובץ target_files.zip על ידי הגדרת משתני ה-build עבור יעד A/B. כלי החבילה של OTA מזהים ומייצרים חבילות באופן אוטומטי בפורמט עבור עדכון A/B.

דוגמאות:

  • כדי ליצור OTA מלא:
    ./build/make/tools/releasetools/ota_from_target_files \
        dist_output/tardis-target_files.zip \
        ota_update.zip
    
  • כדי ליצור OTA מצטבר:
    ./build/make/tools/releasetools/ota_from_target_files \
        -i PREVIOUS-tardis-target_files.zip \
        dist_output/tardis-target_files.zip \
        incremental_ota_update.zip
    

הגדר מחיצות

ה- update_engine יכול לעדכן כל זוג מחיצות A/B המוגדרות באותו דיסק. לזוג מחיצות יש קידומת משותפת (כגון system או boot ) וסיומת לכל משבצת (כגון _a ). רשימת המחיצות שעבורן מחולל המטען מגדיר עדכון מוגדרת על ידי משתנה ה-make AB_OTA_PARTITIONS .

לדוגמה, אם כלולים זוג מחיצות bootloader_a ו- booloader_b ( _a ו _b הן סיומות החריצים), תוכל לעדכן מחיצות אלה על ידי ציון הדברים הבאים בתצורת המוצר או הלוח:

AB_OTA_PARTITIONS := \
  boot \
  system \
  bootloader

אין לשנות את כל המחיצות המעודכנות על ידי update_engine על ידי שאר המערכת. במהלך עדכונים מצטברים או דלתא , הנתונים הבינאריים מהחריץ הנוכחי משמשים ליצירת הנתונים במשבצת החדשה. כל שינוי עלול לגרום לכשל באימות נתוני המשבצת החדשים במהלך תהליך העדכון, ולפיכך להיכשל בעדכון.

הגדר את התצורה לאחר ההתקנה

אתה יכול להגדיר את שלב לאחר ההתקנה באופן שונה עבור כל מחיצה מעודכנת באמצעות קבוצה של זוגות מפתח-ערך. כדי להפעיל תוכנית הממוקמת ב- /system/usr/bin/postinst בתמונה חדשה, ציין את הנתיב ביחס לשורש מערכת הקבצים במחיצת המערכת.

לדוגמה, usr/bin/postinst הוא system/usr/bin/postinst (אם לא משתמשים בדיסק RAM). בנוסף, ציין את סוג מערכת הקבצים שיועבר לקריאה למערכת mount(2) . הוסף את הדברים הבאים לקבצי .mk של המוצר או המכשיר (אם רלוונטי):

AB_OTA_POSTINSTALL_CONFIG += \
  RUN_POSTINSTALL_system=true \
  POSTINSTALL_PATH_system=usr/bin/postinst \
  FILESYSTEM_TYPE_system=ext4

הידור אפליקציות

ניתן להרכיב אפליקציות ברקע לפני האתחול מחדש עם תמונת המערכת החדשה. כדי להרכיב אפליקציות ברקע, הוסף את הדברים הבאים לתצורת המכשיר של המוצר (ב-device.mk של המוצר):

  1. כלול את הרכיבים המקוריים ב-build כדי להבטיח שסקריפט קומפילציה וקבצים בינאריים יקומפלו ונכללים בתמונת המערכת.
      # A/B OTA dexopt package
      PRODUCT_PACKAGES += otapreopt_script
    
  2. חבר את סקריפט ההידור ל- update_engine כך שפועל כשלב לאחר ההתקנה.
      # A/B OTA dexopt update_engine hookup
      AB_OTA_POSTINSTALL_CONFIG += \
        RUN_POSTINSTALL_system=true \
        POSTINSTALL_PATH_system=system/bin/otapreopt_script \
        FILESYSTEM_TYPE_system=ext4 \
        POSTINSTALL_OPTIONAL_system=true
    

לקבלת עזרה בהתקנת הקבצים שנקבעו מראש במחיצת המערכת השנייה שאינה בשימוש, עיין בהתקנה אתחול ראשון של קבצי DEX_PREOPT .