מחיצה כללית להפעלה

ב-Android 12, תמונת boot גנרית, שנקראת Generic Kernel Image (GKI), מכילה את ה-ramdisk הגנרי ואת ליבת ה-GKI.

במכשירים שמופעלת בהם Android 13, ה-ramdisk הגנרי מוסר מתמונת boot ומוצב בתמונת init_boot נפרדת. בעקבות השינוי הזה, תמונת boot תכלול רק את ליבת GKI.

לשדרוג מכשירים שממשיכים להשתמש ב-Android 12 או בגרסאות ליבה ישנות יותר, ה-ramdisk הגנרי נשאר במקומו ולא נדרש קובץ init_boot חדש.

כדי ליצור ramdisk גנרי, צריך להוציא משאבים ספציפיים לספק מה-ramdisk כך שה-ramdisk הגנרי יכיל רק את השלב הראשון init וקובץ מאפיינים שמכיל מידע על חותמת זמן.

במכשירים שבהם:

  • אל תשתמשו במחיצה ייעודית של recovery, כל ביטי השחזור עוברים מ-ramdisk כללי ל-ramdisk של vendor_boot.

  • כן, צריך להשתמש במחיצה ייעודית recovery, אין צורך לבצע שינוי ב-recovery ramdisk כי הוא עצמאי.recovery

ארכיטקטורה

התרשימים הבאים מציגים את הארכיטקטורה של מכשירים עם Android 12 ואילך. מכשירים שמופעלים עם Android 13 כוללים תמונת init_boot חדשה שמכילה את ramdisk הגנרי. מכשירים שמשדרגים מ-Android 12 ל-Android 13 משתמשים באותה ארכיטקטורה כמו ב-Android 12.

ההשקה עם Android 13, ללא שחזור ייעודי

הפעלת המכשיר או שדרוג שלו, GKI, ללא שחזור ייעודי

איור 1. מכשירים שמופעלים עם Android 13 או משודרגים ל-Android 13, עם GKI, ללא שחזור ייעודי.

השקה עם Android 13, שחזור ייעודי ושחזור A/B (דיסק RAM ייעודי)

הפעלת המכשיר או שדרוג שלו, GKI, שחזור ייעודי ושחזור A/B

איור 2. מכשירים שמופעלים או משודרגים ל-Android 13, עם GKI, שחזור ייעודי ושחזור A/B.

אם במכשיר יש מחיצות recovery_a ו-recovery_b, כדאי לעיין באיור הזה.

השקה עם Android 13, שחזור ייעודי ולא A/B (דיסק RAM ייעודי)

הפעלת המכשיר או שדרוג שלו, GKI, שחזור ייעודי ושחזור שאינו A/B

איור 3. מכשירים שמופעלים או משודרגים ל-Android 13, עם GKI, שחזור ייעודי ושחזור שאינו A/B.

אם למכשיר יש מחיצה בשם recovery ללא סיומת של משבצת, אפשר להיעזר באיור הזה.

השקה או שדרוג ל-Android 12, ללא שחזור ייעודי

הפעלת המכשיר או שדרוג שלו, GKI, ללא שחזור ייעודי

איור 4. מכשירים שמופעלים עם Android 12 או משודרגים ל-Android 12, עם GKI, ללא שחזור ייעודי.

הפעלה או שדרוג ל-Android 12, שחזור ייעודי ושחזור A/B (דיסק RAM ייעודי)

הפעלת המכשיר או שדרוג שלו, GKI, שחזור ייעודי ושחזור A/B

איור 5. מכשירים שמושקים עם Android 12 או משודרגים ל-Android 12, עם GKI, שחזור ייעודי ושחזור A/B.

אם במכשיר יש מחיצות recovery_a ו-recovery_b, כדאי לעיין באיור הזה.

הפעלה או שדרוג ל-Android 12, שחזור ייעודי ולא A/B (דיסק RAM ייעודי)

הפעלת המכשיר או שדרוג שלו, GKI, שחזור ייעודי ושחזור שאינו A/B

איור 6. מכשירים שהושקו עם Android 12 או שודרגו ל-Android 12, עם GKI, שחזור ייעודי ושחזור שאינו A/B.

אם למכשיר יש מחיצה בשם recovery ללא סיומת של משבצת, אפשר להיעזר באיור הזה.

שדרוג ל-Android 12, שחזור כאתחול (שחזור כ-ramdisk)

הפעלת המכשיר או שדרוג שלו, ללא GKI, שחזור כהפעלה

איור 7. מכשירים שמשדרגים ל-Android 12, ללא GKI, שחזור כהפעלה.

שדרוג ל-Android 12, שחזור ייעודי (ramdisk ייעודי)

הפעלת המכשיר או שדרוג שלו, ללא GKI, שחזור ייעודי

איור 8. מכשירים שמשדרגים ל-Android 12, ללא GKI, שחזור ייעודי.

התוכן של קובצי אימג' לאתחול

תמונות האתחול של Android מכילות את הרכיבים הבאים.

  • init_boot נוספה תמונה למכשירים עם Android 13

    • גרסת הכותרת V4
    • תמונת ramdisk גנרית
  • תמונה גנרית (boot)

    • גרסת הכותרת V3 או V4
      • boot_signature לאישור של GKI boot.img (גרסה 4 בלבד). ‫GKI boot.img המאושר לא חתום להפעלה מאומתת. יצרני ציוד מקורי (OEM) עדיין צריכים לחתום על boot.img שנבנה מראש באמצעות מפתח AVB שייחודי למכשיר.
      • כרטיסים גנריים cmdline (GENERIC_KERNEL_CMDLINE)
      • ליבת GKI
    • תמונת ramdisk גנרית
      • כלול רק בתמונות boot מ-Android 12 ומגרסאות קודמות
  • vendor_boot תמונה (פרטים נוספים זמינים במאמר בנושא מחיצות של ספק)

    • vendor_boot header
      • מכשיר ספציפי cmdline (BOARD_KERNEL_CMDLINE)
    • vendor_boot ramdisk image
      • lib/modules
      • משאבי שחזור (אם אין שחזור ייעודי)
    • תמונה אחת (dtb)
  • תמונה אחת (recovery)

    • Header version V2
      • cmdline ספציפי למכשיר לשחזור, אם צריך
      • במחיצת שחזור שאינה A/B, התוכן של הכותרת חייב להיות עצמאי. אפשר לעיין בתמונות שחזור. לדוגמה:
      • הכתובת cmdline לא משורשרת לכתובות boot ו-vendor_boot cmdline.
      • אם צריך, הכותרת מציינת את DTBO השחזור.
      • במחיצת שחזור A/B, אפשר לשרשר את התוכן או להסיק אותו מ-boot ומ-vendor_boot. לדוגמה:
      • המחרוזת cmdline מורכבת מ-boot ומ-vendor_boot cmdline.
      • אפשר להסיק את DTBO מהכותרת vendor_boot.
    • recovery ramdisk image
      • מקורות מידע לשחזור
      • במחיצת שחזור שאינה A/B, התוכן של ramdisk צריך להיות עצמאי. אפשר לעיין בתמונות שחזור. לדוגמה:
      • lib/modules חייב להכיל את כל מודולי הליבה שנדרשים כדי להפעיל את מצב השחזור
      • ה-ramdisk של השחזור חייב להכיל את init.
      • במחיצת שחזור A/B, ה-ramdisk של השחזור מתווסף לפני ה-ramdisk הכללי ו-vendor_boot, ולכן הוא לא צריך להיות עצמאי. לדוגמה:
      • lib/modules עשוי להכיל רק מודולים נוספים של ליבת המערכת שנדרשים כדי להפעיל את מצב השחזור, בנוסף למודולים של ליבת המערכת ב-ramdisk של vendor_boot.
      • יכול להיות שהקישור הסמלי ב-/init קיים, אבל הוא מוצל על ידי הקובץ הבינארי /init בשלב הראשון בתמונת האתחול.

תוכן גנרי של תמונת ramdisk

ה-ramdisk הגנרי מכיל את הרכיבים הבאים.

  • init
  • system/etc/ramdisk/build.prop
  • ro.PRODUCT.bootimg.* build props
  • ספריות ריקות לנקודות צירוף: debug_ramdisk/, mnt/, dev/, sys/, proc/, metadata/
  • first_stage_ramdisk/
    • ספריות ריקות משוכפלות לנקודות טעינה: debug_ramdisk/, ‏ mnt/,‏ dev/, ‏ sys/, ‏ proc/, ‏ metadata/

שילוב של קובץ אימג' לאתחול

דגלי build קובעים איך נוצרים קובצי התמונות של init_boot,‏ boot,‏ recovery ו-vendor_boot. הערך של משתנה בוליאני בלוח צריך להיות המחרוזת true או ריק (שהוא ברירת המחדל).

  • TARGET_NO_KERNEL. המשתנה הזה מציין אם הבנייה משתמשת בתמונת אתחול מוכנה מראש. אם המשתנה הזה מוגדר ל-true, צריך להגדיר את BOARD_PREBUILT_BOOTIMAGE למיקום של תמונת האתחול המוכנה מראש (BOARD_PREBUILT_BOOTIMAGE:= device/${company}/${board}/boot.img)

  • BOARD_USES_RECOVERY_AS_BOOT. המשתנה הזה מציין אם המכשיר משתמש בתמונה recovery כתמונה boot. כשמשתמשים ב-GKI, המשתנה הזה ריק וצריך להעביר את משאבי השחזור אל vendor_boot.

  • BOARD_USES_GENERIC_KERNEL_IMAGE. המשתנה הזה מציין שהלוח משתמש ב-GKI. המשתנה הזה לא משפיע על sysprops או על PRODUCT_PACKAGES.

    זהו מתג GKI ברמת הלוח. כל המשתנים הבאים מוגבלים על ידי המשתנה הזה.

  • BOARD_MOVE_RECOVERY_RESOURCES_TO_VENDOR_BOOT. המשתנה הזה קובע אם משאבי השחזור של ramdisk נוצרים ב-vendor_boot.

    • אם המדיניות מוגדרת ל-true, משאבי השחזור נוצרים רק ב-vendor-ramdisk/ ולא ב-recovery/root/.

    • אם השדה ריק, משאבי השחזור נוצרים רק ב-recovery/root/ ולא ב-vendor-ramdisk/.

  • BOARD_MOVE_GSI_AVB_KEYS_TO_VENDOR_BOOT. המשתנה הזה קובע אם מפתחות GSI AVB נוצרים ב-vendor_boot.

    • אם ההגדרה היא true, והתנאי BOARD_MOVE_RECOVERY_RESOURCES_TO_VENDOR_BOOT מתקיים:

      • מוגדר, מפתחות GSI AVB נוצרים ל $ANDROID_PRODUCT_OUT/vendor-ramdisk/first_stage_ramdisk/avb.

      • לא מוגדר, מפתחות GSI AVB מובנים כדי $ANDROID_PRODUCT_OUT/vendor-ramdisk/avb.

    • אם השדה ריק, אם BOARD_RECOVERY_AS_ROOT:

      • מוגדר, מפתחות GSI AVB נוצרים ל $ANDROID_PRODUCT_OUT/recovery/root/first_stage_ramdisk/avb.

      • לא מוגדר, מפתחות GSI AVB מובנים כדי $ANDROID_PRODUCT_OUT/ramdisk/avb.

  • BOARD_EXCLUDE_KERNEL_FROM_RECOVERY_IMAGE. המשתנה הזה קובע אם התמונה recovery מכילה ליבה או לא. במכשירים עם Android מגרסה 12 ומעלה שמשתמשים במחיצת A/B recovery, צריך להגדיר את המשתנה הזה ל-true. במכשירים עם Android 12 שמשתמשים במחיצות שאינן A/B, צריך להגדיר את המשתנה הזה לערך false כדי לשמור את תמונת השחזור עצמאית.

  • BOARD_COPY_BOOT_IMAGE_TO_TARGET_FILES. המשתנה הזה קובע אם $OUT/boot*.img מועתק אל IMAGES/ בקבצי היעד.

    • aosp_arm64 צריך להגדיר את המשתנה הזה ל-true.

    • במכשירים אחרים, המשתנה הזה צריך להיות ריק.

  • BOARD_INIT_BOOT_IMAGE_PARTITION_SIZE. המשתנה הזה קובע אם המשתנה init_boot.img נוצר ומגדיר את הגודל שלו. כשההגדרה מופעלת, ה-ramdisk הגנרי מתווסף ל-init_boot.img במקום ל-boot.img, ונדרשת הגדרה של המשתנים BOARD_AVB_INIT_BOOT* בשביל שרשור של vbmeta.

שילובים מותרים

רכיב או משתנה שדרוג מכשיר ללא מחיצת שחזור שדרוג מכשיר עם מחיצת שחזור הפעלת המכשיר ללא מחיצת שחזור הפעלת המכשיר עם מחיצת שחזור A/B הפעלת המכשיר עם מחיצת שחזור שאינה A/B aosp_arm64
מכיל boot כן כן כן כן כן כן
כולל את init_boot (Android 13) לא לא כן כן כן כן
מכיל vendor_boot אופציונלי אופציונלי כן כן כן לא
מכיל recovery לא כן לא כן כן לא
BOARD_USES_RECOVERY_AS_BOOT true ריק ריק ריק ריק ריק
BOARD_USES_GENERIC_KERNEL_IMAGE ריק ריק true true true true
PRODUCT_BUILD_RECOVERY_IMAGE ריק true או ריק ריק true או ריק true או ריק ריק
BOARD_RECOVERYIMAGE_PARTITION_SIZE ריק > 0 ריק > 0 > 0 ריק
BOARD_MOVE_RECOVERY_RESOURCES_TO_VENDOR_BOOT ריק ריק true ריק ריק ריק
BOARD_MOVE_GSI_AVB_KEYS_TO_VENDOR_BOOT ריק ריק true true true ריק
BOARD_EXCLUDE_KERNEL_FROM_RECOVERY_IMAGE ריק ריק ריק true ריק ריק
BOARD_COPY_BOOT_IMAGE_TO_TARGET_FILES ריק ריק ריק ריק ריק true

במכשירים עם מחיצה ייעודית של recovery, אפשר להגדיר את PRODUCT_BUILD_RECOVERY_IMAGE לערך true או לערך ריק. במכשירים האלה, אם מוגדר BOARD_RECOVERYIMAGE_PARTITION_SIZE, נוצרת תמונת recovery.

הפעלת vbmeta בשרשרת להפעלה

צריך להפעיל שרשור של קובצי vbmeta לתמונות boot ו-init_boot. מציינים את הפרטים הבאים:

BOARD_AVB_BOOT_KEY_PATH := external/avb/test/data/testkey_rsa4096.pem
BOARD_AVB_BOOT_ALGORITHM := SHA256_RSA4096
BOARD_AVB_BOOT_ROLLBACK_INDEX := $(PLATFORM_SECURITY_PATCH_TIMESTAMP)
BOARD_AVB_BOOT_ROLLBACK_INDEX_LOCATION := 2

BOARD_AVB_INIT_BOOT_KEY_PATH := external/avb/test/data/testkey_rsa2048.pem
BOARD_AVB_INIT_BOOT_ALGORITHM := SHA256_RSA2048
BOARD_AVB_INIT_BOOT_ROLLBACK_INDEX := $(PLATFORM_SECURITY_PATCH_TIMESTAMP)
BOARD_AVB_INIT_BOOT_ROLLBACK_INDEX_LOCATION := 3

לדוגמה, אפשר לעיין בשינוי הזה.

System-as-root

מערכת כשורש לא נתמכת במכשירים שמשתמשים ב-GKI. במכשירים כאלה, השדה BOARD_BUILD_SYSTEM_ROOT_IMAGE צריך להיות ריק. מערכת כבסיס (System-as-root) לא נתמכת גם במכשירים שמשתמשים במחיצות דינמיות.

הגדרות מוצר

במכשירים שמשתמשים ב-ramdisk כללי, צריך להתקין רשימה של קבצים שמותר להתקין ב-ramdisk. כדי לעשות זאת, מציינים את הפרטים הבאים ב-device.mk:

$(call inherit-product, $(SRC_TARGET_DIR)/product/generic_ramdisk.mk)

הקובץ generic_ramdisk.mk גם מונע מקובצי makefile אחרים להתקין בטעות קבצים אחרים ב-ramdisk (צריך להעביר קבצים כאלה אל vendor_ramdisk).

הגדרת מכשירים

הוראות ההגדרה שונות בין מכשירים שהושקו עם Android 13, מכשירים ששודרגו ל-Android 12 ומכשירים שהושקו עם Android 12. ‫Android 13, ההגדרה דומה להגדרה ב-Android 12

  • מכשירים שמשדרגים ל-Android 12:

    • אפשר לשמור את הערך של BOARD_USES_RECOVERY_AS_BOOT. אם הם עושים זאת, הם משתמשים בהגדרות מדור קודם, והמשתנים החדשים של הגדרות ה-build חייבים להיות ריקים. אם המכשירים האלה:

      • מגדירים את BOARD_USES_RECOVERY_AS_BOOT ל-true, והארכיטקטורה היא כמו שמוצג באיור 3.

      • אם מגדירים את BOARD_USES_RECOVERY_AS_BOOT כריק, הארכיטקטורה תהיה כמו שמוצג באיור 4.

    • אפשר להגדיר את BOARD_USES_RECOVERY_AS_BOOT כריק. אם הם עושים זאת, הם משתמשים בהגדרות חדשות. אם המכשירים האלה:

      • אל תשתמשו במחיצה ייעודית recovery, הארכיטקטורה היא כמו שמוצג באיור 1 ואפשרות הגדרת המכשיר היא אפשרות 1.

      • משתמשים במחיצה ייעודית recovery, הארכיטקטורה היא כמו שמוצג באיור 2א או באיור 2ב, ואפשרות הגדרת המכשיר היא אפשרות 2א או אפשרות 2ב.

  • במכשירים שיושקו עם Android 12, צריך להגדיר את BOARD_USES_RECOVERY_AS_BOOT כריק ולהשתמש בהגדרות חדשות. אם המכשירים האלה:

    • לא משתמשים במחיצה ייעודית recovery, הארכיטקטורה היא כמו שמוצג באיור 1 ואפשרות הגדרת המכשיר היא אפשרות 1.

    • משתמשים במחיצה ייעודית recovery, הארכיטקטורה היא כמו שמוצג באיור 2א או באיור 2ב, ואפשרות הגדרת המכשיר היא אפשרות 2א או אפשרות 2ב.

מכיוון ש-aosp_arm64 בונה רק GKI (ולא vendor_boot או שחזור), הוא לא יעד מלא. למידע על aosp_arm64הגדרות של גרסאות build, אפשר לעיין במאמר generic_arm64.

אפשרות 1: אין מחיצת שחזור ייעודית

במכשירים ללא מחיצת recovery, התמונה הגנרית boot נמצאת במחיצת boot. ה-ramdisk‏ vendor_boot מכיל את כל משאבי השחזור, כולל lib/modules (עם מודולים של ליבת הספק). במכשירים כאלה, הגדרת המוצר עוברת בירושה מ-generic_ramdisk.mk.

הגדרת ערכים של לוח

מגדירים את הערכים הבאים:

BOARD_USES_RECOVERY_AS_BOOT :=
BOARD_USES_GENERIC_KERNEL_IMAGE := true
BOARD_MOVE_RECOVERY_RESOURCES_TO_VENDOR_BOOT := true
BOARD_EXCLUDE_KERNEL_FROM_RECOVERY_IMAGE :=
BOARD_MOVE_GSI_AVB_KEYS_TO_VENDOR_BOOT := true

ה-ramdisk‏ vendor_boot יכול להכיל קישור סמלי /init עד /system/bin/init, ו-init_second_stage.recovery ב-/system/bin/init. עם זאת, מכיוון ש-ramdisk גנרי מורכב אחרי ramdisk‏ vendor_boot, הקישור הסמלי /init נכתב מחדש. כשהמכשיר מבצע אתחול למצב שחזור, נדרש קובץ הבינארי /system/bin/init כדי לתמוך באתחול בשלב השני. התוכן של vendor_boot + generic ramdisks הוא:

  • /init (מ-ramdisk כללי, שנבנה מ-init_first_stage)
  • /system/bin/init (מ-vendor_ramdisk, נוצר מ-init_second_stage.recovery)

העברת קובצי fstab

מעבירים את כל הקבצים fstab שהותקנו ב-ramdisk הכללי אל vendor_ramdisk. לדוגמה, אפשר לעיין בשינוי הזה.

התקנת מודולים

אפשר להתקין מודולים ספציפיים למכשיר כדי vendor_ramdisk (אפשר לדלג על השלב הזה אם אין לכם מודולים ספציפיים למכשיר להתקנה).

  • משתמשים בגרסת vendor_ramdisk של המודול כשהמודול מותקן ב-/first_stage_ramdisk. המודול הזה אמור להיות זמין אחרי ש-init מעביר את השורש אל /first_stage_ramdisk, אבל לפני ש-init מעביר את השורש אל /system. דוגמאות אפשר לראות במאמרים סכומי ביקורת של מטא-נתונים ודחיסה וירטואלית של בדיקות A/B.

  • משתמשים בגרסת recovery של המודול כשהמודול מותקן ב-/. המודול הזה צריך להיות זמין לפני ש-init מעביר את השורש אל /first_stage_ramdisk. פרטים על התקנת מודולים ב-/ זמינים במאמר בנושא מסוף השלב הראשון.

מסוף השלב הראשון

מכיוון שהמסוף בשלב הראשון מתחיל לפני ש-init מעביר את השורש אל /first_stage_ramdisk, צריך להתקין את מודולי recovery. כברירת מחדל, שני סוגי המודולים מותקנים בתיקייה build/make/target/product/base_vendor.mk, כך שאם קובץ ה-Makefile של המכשיר עובר בירושה מקובץ זה, לא צריך להתקין במפורש את סוג המודול recovery.

כדי להתקין במפורש את מודולי השחזור, משתמשים בפקודה הבאה.

PRODUCT_PACKAGES += \
    linker.recovery \
    shell_and_utilities_recovery \

כך מוודאים שהאפליקציות linker, sh ו-toybox יותקנו ב-$ANDROID_PRODUCT_OUT/recovery/root/system/bin, שמותקן ב-/system/bin במסגרת vendor_ramdisk.

כדי להוסיף מודולים שנדרשים למסוף בשלב הראשון (לדוגמה, adbd), משתמשים בפקודה הבאה.

PRODUCT_PACKAGES += adbd.recovery

כך מוודאים שהמודולים שצוינו מותקנים ב-$ANDROID_PRODUCT_OUT/recovery/root/system/bin, שמותקן ב-/system/bin מתחת ל-vendor_ramdisk.

סכומי ביקורת של מטא-נתונים

כדי לתמוך בסיכומי ביקורת של מטא-נתונים במהלך ההרכבה בשלב הראשון, מכשירים שלא תומכים ב-GKI מתקינים את גרסת ה-ramdisk של המודולים הבאים. כדי להוסיף תמיכה ב-GKI, מעבירים את המודולים אל $ANDROID_PRODUCT_OUT/vendor-ramdisk/first_stage_ramdisk/system/bin:

PRODUCT_PACKAGES += \
    linker.vendor_ramdisk \
    resize2fs.vendor_ramdisk \
    tune2fs.vendor_ramdisk \

דוגמה אפשר לראות ברשימת השינויים הזו.

דחיסה וירטואלית של A/B

כדי לתמוך בדחיסת A/B וירטואלית, צריך להתקין את snapuserd ב-vendor_ramdisk. המכשיר אמור לקבל בירושה מ-virtual_ab_ota/compression.mk את הגרסה vendor_ramdisk של snapuserd.

שינויים בתהליך האתחול

תהליך האתחול למצב שחזור או ל-Android לא משתנה, למעט המקרים הבאים:

  • ‫Ramdisk build.prop עובר אל /second_stage_resources כדי שהשלב השני init יוכל לקרוא את חותמת הזמן של האתחול.

הסיבה לכך היא שהמשאבים עוברים מ-ramdisk גנרי ל-ramdisk של vendor_boot, ולכן התוצאה של שרשור ramdisk גנרי ל-ramdisk של vendor_boot לא משתנה.

הפיכת e2fsck לזמין

קבצי ה-Makefile של המכשיר יכולים לרשת מ:

  • virtual_ab_ota/launch_with_vendor_ramdisk.mk אם המכשיר תומך במחיצות וירטואליות מסוג A/B אבל לא בדחיסה.

  • virtual_ab_ota/compression.mk אם המכשיר תומך בדחיסה וירטואלית של A/B.

קובצי ה-Makefile של המוצר מתקינים את $ANDROID_PRODUCT_OUT/vendor-ramdisk/first_stage_ramdisk/system/bin/e2fsck. בזמן הריצה, השלב הראשון init מעביר את השורש אל /first_stage_ramdisk ואז מפעיל את /system/bin/e2fsck.

אפשרות 2א: מחיצת שחזור ייעודית ומחיצת שחזור של בדיקת A/B

משתמשים באפשרות הזו במכשירים עם מחיצות A/B‏ recovery, כלומר, במכשיר יש recovery_a ו-recovery_b partition. מכשירים כאלה כוללים מכשירי A/B ומכשירי Virtual A/B שניתן לעדכן את מחיצת השחזור שלהם, עם ההגדרה הבאה:

AB_OTA_PARTITIONS += recovery

ה-ramdisk‏ vendor_boot מכיל את חלקי הספק של ה-ramdisk ומודולים של ליבת הספק, כולל:

  • קבצים ספציפיים למכשיר fstab

  • lib/modules (כולל מודולים של ליבת ספקים)

ה-ramdisk ‏recovery מכיל את כל משאבי השחזור. במכשירים כאלה, הגדרת המוצר עוברת בירושה מ-generic_ramdisk.mk.

הגדרת ערכים של לוח

מגדירים את הערכים הבאים למכשירים עם מחיצת A/B recovery:

BOARD_USES_RECOVERY_AS_BOOT :=
BOARD_USES_GENERIC_KERNEL_IMAGE := true
BOARD_MOVE_RECOVERY_RESOURCES_TO_VENDOR_BOOT :=
BOARD_EXCLUDE_KERNEL_FROM_RECOVERY_IMAGE := true
BOARD_MOVE_GSI_AVB_KEYS_TO_VENDOR_BOOT := true

ה-recovery ramdisk יכול להכיל /init -> /system/bin/init symlink, ו-init_second_stage.recovery ב-/system/bin/init. עם זאת, מכיוון ש-boot ramdisk משורשר אחרי recovery ramdisk, הקישור הסמלי /init נדרס. כשהמכשיר נטען למצב שחזור, נדרש קובץ /system/bin/init בינארי כדי לתמוך בשלב השני של ההפעלה.

כשהמכשיר מבצע אתחול ל-recovery, התוכן של recovery + vendor_boot + ramdisks כלליים הוא כדלקמן:

  • /init (מ-ramdisk, נוצר מ-init_first_stage)
  • /system/bin/init (מ-recovery ramdisk, נוצר מ-init_second_stage.recovery, והופעל מ-/init)

כשהמכשיר מאתחל ל-Android, התוכן של vendor_boot + generic ramdisks הוא כדלקמן:

  • /init (מ-ramdisk כללי, שנבנה מ-init_first_stage)

העברת קובצי fstab

מעבירים את כל הקבצים fstab שהותקנו ב-ramdisk הכללי אל vendor_ramdisk. לדוגמה, אפשר לעיין בשינוי הזה.

התקנת מודולים

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

מסוף השלב הראשון

כדי להתקין את הגרסה vendor_ramdisk של המודולים, משתמשים בפקודה הבאה:

PRODUCT_PACKAGES += \
    linker.vendor_ramdisk \
    shell_and_utilities_vendor_ramdisk \

כך מוודאים שהאפליקציות linker, sh ו-toybox יותקנו ב-$ANDROID_PRODUCT_OUT/vendor-ramdisk/system/bin, שמותקן ב-/system/bin במסגרת vendor_ramdisk.

כדי להוסיף מודולים שנדרשים למסוף בשלב הראשון (לדוגמה, adbd), צריך להפעיל את וריאנט vendor_ramdisk של המודולים האלה על ידי העלאת תיקונים רלוונטיים ל-AOSP, ואז להשתמש בפקודה הבאה:

PRODUCT_PACKAGES += adbd.vendor_ramdisk

כך מוודאים שהמודולים שצוינו יותקנו ב-$ANDROID_PRODUCT_OUT/vendor-ramdisk/system/bin. אם vendor_boot ramdisk נטען במצב שחזור, המודול זמין גם ב-recovery. אם ה-ramdisk של vendor_boot לא נטען במצב שחזור, המכשיר יכול גם להתקין את adbd.recovery.

סכומי ביקורת של מטא-נתונים

כדי לתמוך בסיכומי ביקורת של מטא-נתונים במהלך ההרכבה בשלב הראשון, מכשירים שלא תומכים ב-GKI מתקינים את גרסת ה-ramdisk של המודולים הבאים. כדי להוסיף תמיכה ב-GKI, מעבירים את המודולים אל $ANDROID_PRODUCT_OUT/vendor-ramdisk/system/bin:

PRODUCT_PACKAGES += \
    linker.vendor_ramdisk \
    resize2fs.vendor_ramdisk \
    tune2fs.vendor_ramdisk \

דוגמה אפשר לראות ברשימת השינויים הזו.

דחיסה וירטואלית של A/B

כדי לתמוך בדחיסה של בדיקות A/B וירטואליות, צריך להתקין את snapuserd ב-vendor_ramdisk. המכשיר אמור לקבל בירושה מ-virtual_ab_ota/compression.mk את הגרסה vendor_ramdisk של snapuserd.

שינויים בתהליך האתחול

תהליך האתחול לא משתנה כשמבצעים אתחול ל-Android. ה-vendor_boot + generic ramdisk דומה לתהליך האתחול הקיים, רק ש-fstab נטען מ-vendor_boot. מכיוון שהקובץ system/bin/recovery לא קיים, המערכת של first_stage_init מטפלת בזה כאילו מדובר באתחול רגיל.

כשמבצעים אתחול למצב שחזור, תהליך האתחול משתנה. השחזור + vendor_boot + דיסק RAM גנרי דומה לתהליך השחזור הקיים, אבל הליבה נטענת מהתמונה boot במקום מהתמונה recovery. תהליך ההפעלה של מצב השחזור הוא כזה:

  1. תוכנת האתחול מתחילה לפעול, ואז מתבצעות הפעולות הבאות:

    1. העברת שחזור + vendor_boot + generic ramdisk אל /. (אם יצרן הציוד המקורי משכפל מודולים של ליבת המערכת ב-ramdisk לשחזור על ידי הוספתם אל BOARD_RECOVERY_KERNEL_MODULES, אז vendor_boot הוא אופציונלי).
    2. מפעילים את הליבה מהמחיצה boot.
  2. הליבה מטמיעה את ramdisk ב-/ ואז מפעילה את /init מ-ramdisk כללי.

  3. השלב הראשון של ההפעלה מתחיל, ואז מתבצעות הפעולות הבאות:

    1. הגדרת IsRecoveryMode() == true ו-ForceNormalBoot() == false.
    2. טעינת מודולי ליבה של ספקים מ-/lib/modules.
    3. התקשרות אל DoFirstStageMount() אבל דילוג על ההתקנה כי IsRecoveryMode() == true. (המכשיר לא מפנה את ה-ramdisk (כי / עדיין זהה), אבל הוא קורא ל-SetInitAvbVersionInRecovery()).
    4. מתחיל את שלב האתחול השני מ-/system/bin/init מ-recovery ramdisk.

הפיכת e2fsck לזמין

קבצי ה-Makefile של המכשיר יכולים לרשת מ:

  • virtual_ab_ota/launch_with_vendor_ramdisk.mk אם המכשיר תומך במחיצות וירטואליות מסוג A/B אבל לא בדחיסה.

  • virtual_ab_ota/compression.mk אם המכשיר תומך בדחיסה וירטואלית של A/B.

קובצי ה-Makefile של המוצר מתקינים את $ANDROID_PRODUCT_OUT/vendor-ramdisk/system/bin/e2fsck. בזמן הריצה, השלב הראשון init מופעל /system/bin/e2fsck.

אפשרות 2ב: מחיצת שחזור ייעודית שאינה A/B

משתמשים באפשרות הזו במכשירים עם מחיצה מסוג recovery שאינה A/B, כלומר, במכשיר יש מחיצה בשם recovery ללא סיומת של משבצת. מכשירים כאלה כוללים:

  • מכשירים מסוג A/B;
  • מכשירי A/B ומכשירי Virtual A/B, שאי אפשר לעדכן את מחיצת השחזור שלהם. (זה לא רגיל).

ה-ramdisk‏ vendor_boot מכיל את חלקי הספק של ה-ramdisk ומודולים של ליבת הספק, כולל:

  • קבצים ספציפיים למכשיר fstab
  • lib/modules (כולל מודולים של ליבת ספקים)

תמונת recovery צריכה להיות עצמאית. הוא צריך להכיל את כל המשאבים הנדרשים להפעלה של מצב השחזור, כולל:

  • קובץ האימג' של הליבה
  • קובץ ה-DTBO
  • מודולי ליבה ב-lib/modules
  • הפעלה בשלב הראשון כקישור סמלי /init -> /system/bin/init
  • קובץ בינארי של שלב שני של init‏ /system/bin/init
  • קבצים ספציפיים למכשיר fstab
  • כל שאר משאבי השחזור, כולל קובץ ה-recovery הבינארי

במכשירים כאלה, הגדרת המוצר עוברת בירושה מ-generic_ramdisk.mk.

הגדרת ערכים של לוח

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

BOARD_USES_RECOVERY_AS_BOOT :=
BOARD_USES_GENERIC_KERNEL_IMAGE := true
BOARD_MOVE_RECOVERY_RESOURCES_TO_VENDOR_BOOT :=
BOARD_EXCLUDE_KERNEL_FROM_RECOVERY_IMAGE :=
BOARD_MOVE_GSI_AVB_KEYS_TO_VENDOR_BOOT := true

ה-ramdisk‏ recovery חייב להכיל קישור סמלי /init -> /system/bin/init ו-init_second_stage.recovery ב-/system/bin/init. כשמפעילים את המכשיר במצב שחזור, צריך את הקובץ הבינארי /system/bin/init כדי לתמוך באתחול בשלב הראשון ובשלב השני.

כשהמכשיר מבצע אתחול ל-recovery, התוכן של recovery ramdisks הוא כדלקמן:

  • /init -> /system/bin/init (מ-recovery ramdisk)
  • /system/bin/init (מ-recovery ramdisk, נוצר מ-init_second_stage.recovery, והופעל מ-/init)

כשהמכשיר מאתחל ל-Android, התוכן של vendor_boot + generic ramdisks הוא כדלקמן:

  • /init (מ-ramdisk, נוצר מ-init_first_stage)

העברת קובצי fstab

מעבירים את כל הקבצים fstab שהותקנו ל-ramdisk הכללי אל ה-ramdisk של vendor_ramdisk ושל recovery. לדוגמה, אפשר לעיין בשינוי הזה.

התקנת מודולים

אפשר להתקין מודולים ספציפיים למכשיר ב-vendor_ramdisk וב-recovery ramdisk (מדלגים על השלב הזה אם אין מודולים ספציפיים למכשיר להתקנה). init לא מתבצעת החלפה של שורש. הווריאציה vendor_ramdisk של המודולים מותקנת בתיקיית הבסיס של vendor_ramdisk. הווריאנט recovery של המודולים מותקן בבסיס של recovery ramdisk. דוגמאות להתקנת מודולים ב-vendor_ramdisk וב-recovery ramdisk מופיעות במאמרים מסוף השלב הראשון וסכומי ביקורת של מטא-נתונים.

מסוף השלב הראשון

כדי להתקין את הגרסה vendor_ramdisk של המודולים, משתמשים בפקודה הבאה:

PRODUCT_PACKAGES += \
    linker.vendor_ramdisk \
    shell_and_utilities_vendor_ramdisk \

כך מוודאים שהאפליקציות linker, sh ו-toybox יותקנו ב-$ANDROID_PRODUCT_OUT/vendor-ramdisk/system/bin, שמותקן ב-/system/bin במסגרת vendor_ramdisk.

כדי להוסיף מודולים שנדרשים למסוף בשלב הראשון (לדוגמה, adbd), צריך להפעיל את וריאנט vendor_ramdisk של המודולים האלה על ידי העלאת תיקונים רלוונטיים ל-AOSP, ואז להשתמש בפקודה הבאה:

PRODUCT_PACKAGES += adbd.vendor_ramdisk

כך מוודאים שהמודולים שצוינו יותקנו ב-$ANDROID_PRODUCT_OUT/vendor-ramdisk/system/bin.

כדי להתקין את הווריאציה recovery של המודולים, מחליפים את vendor_ramdisk ב-recovery:

PRODUCT_PACKAGES += \
    linker.recovery \
    shell_and_utilities_recovery \
    adbd.recovery \

סכומי ביקורת של מטא-נתונים

כדי לתמוך בסיכומי ביקורת של מטא-נתונים במהלך ההרכבה בשלב הראשון, מכשירים שלא תומכים ב-GKI מתקינים את גרסת ה-ramdisk של המודולים הבאים. כדי להוסיף תמיכה ב-GKI, מעבירים את המודולים אל $ANDROID_PRODUCT_OUT/vendor-ramdisk/system/bin:

PRODUCT_PACKAGES += \
    linker.vendor_ramdisk \
    resize2fs.vendor_ramdisk \
    tune2fs.vendor_ramdisk \

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

שינויים בתהליך האתחול

תהליך האתחול לא משתנה כשמבצעים אתחול ל-Android. ה-vendor_boot + generic ramdisk דומה לתהליך האתחול הקיים, רק ש-fstab נטען מ-vendor_boot. מכיוון שהקובץ system/bin/recovery לא קיים, המערכת של first_stage_init מטפלת בזה כאילו מדובר באתחול רגיל.

כשמבצעים הפעלה במצב שחזור, תהליך ההפעלה לא משתנה. ה-ramdisk של השחזור נטען באותו אופן כמו בתהליך השחזור הקיים. הליבה נטענת מקובץ האימג' של recovery. תהליך האתחול של מצב השחזור הוא כזה:

  1. תוכנת האתחול מתחילה לפעול, ואז מתבצעות הפעולות הבאות:

    1. העברת ramdisk לשחזור אל /.
    2. מפעילים את הליבה מהמחיצה recovery.
  2. הליבה מטמיעה את ramdisk ב-/ ואז מפעילה את /init, שהוא קישור סמלי ל-/system/bin/init מ-ramdisk‏ recovery.

  3. השלב הראשון של ההפעלה מתחיל, ואז מתבצעות הפעולות הבאות:

    1. הגדרת IsRecoveryMode() == true ו-ForceNormalBoot() == false.
    2. טעינת מודולי ליבה של ספקים מ-/lib/modules.
    3. התקשרות אל DoFirstStageMount() אבל דילוג על ההתקנה כי IsRecoveryMode() == true. (המכשיר לא מפנה את ה-ramdisk (כי / עדיין זהה), אבל הוא קורא ל-SetInitAvbVersionInRecovery()).
    4. מתחיל את שלב האתחול השני מ-/system/bin/init מ-recovery ramdisk.

חותמות זמן של קובץ אימג' לאתחול

הקוד הבא הוא דוגמה לקובץ חותמת זמן של תמונה boot:

####################################
# from generate-common-build-props
# These properties identify this partition image.
####################################
ro.product.bootimage.brand=Android
ro.product.bootimage.device=generic_arm64
ro.product.bootimage.manufacturer=unknown
ro.product.bootimage.model=AOSP on ARM64
ro.product.bootimage.name=aosp_arm64
ro.bootimage.build.date=Mon Nov 16 22:46:27 UTC 2020
ro.bootimage.build.date.utc=1605566787
ro.bootimage.build.fingerprint=Android/aosp_arm64/generic_arm64:S/MASTER/6976199:userdebug/test-keys
ro.bootimage.build.id=MASTER
ro.bootimage.build.tags=test-keys
ro.bootimage.build.type=userdebug
ro.bootimage.build.version.incremental=6976199
ro.bootimage.build.version.release=11
ro.bootimage.build.version.release_or_codename=S
ro.bootimage.build.version.sdk=30
# Auto-added by post_process_props.py
persist.sys.usb.config=none
# end of file
  • בזמן הבנייה, קובץ system/etc/ramdisk/build.prop נוסף ל-ramdisk הכללי. הקובץ הזה מכיל מידע על חותמות הזמן של ה-build.

  • בזמן הריצה, השלב הראשון init מעתיק קבצים מ-ramdisk אל tmpfs לפני שמשחרר את ה-ramdisk, כדי שהשלב השני init יוכל לקרוא את הקובץ הזה כדי להגדיר את מאפייני חותמת הזמן של התמונה boot.