מחיצת אתחול כללית

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

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

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

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

במכשירים:

  • לא להשתמש במחיצת recovery ייעודית. כל ביטים של השחזור עוברים מרדיסק הגנרי לרדיסק (ramdisk) של vendor_boot.

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

ארכיטקטורה

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

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

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

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

הפעלה עם Android 13, שחזור ייעודי ו-A/B (ramdisk ייעודי)

השקה/שדרוג של מכשיר, GKI, שחזור A/B ושחזור A/B

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

שדרוג ל-Android 12, recovery-as-boot (recovery-as-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 לאישור boot.img של GKI (גרסה 4 בלבד). מכשיר GKI boot.img שאושר לא חתום להפעלה מאומתת. יצרני ציוד מקורי עדיין צריכים לחתום על boot.img שנוצר מראש באמצעות מפתח AVB ספציפי למכשיר.
      • cmdline גנרי (GENERIC_KERNEL_CMDLINE)
      • ליבת GKI
    • תמונת ramdisk גנרית
      • כלול רק בתמונות boot מ-Android 12 ודגמים קודמים
  • קובץ אימג' של vendor_boot (פרטים נוספים זמינים במאמר מחיצות אתחול של ספקים)

    • vendor_boot header
      • cmdline ספציפי למכשיר (BOARD_KERNEL_CMDLINE)
    • תמונה של vendor_boot ramdisk
      • 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
      • מקורות מידע לשחזור החשבון
      • במחיצה לא לשחזור מסוג A/B, התוכן של ה-ramdisk חייב להיות עצמאי. אפשר לקרוא מידע נוסף במאמר תמונות שחזור. לדוגמה:
      • lib/modules חייב להכיל את כל המודולים של הליבה שנדרשים להפעלה של מצב השחזור
      • שרת ה-ramdisk לשחזור חייב להכיל init.
      • במחיצה לשחזור A/B, ה-ramdisk לשחזור מצורף ל-ramdisk הגנרי ול-vendor_boot, ולכן הוא לא צריך להיות עצמאי. לדוגמה:
      • lib/modules יכול להכיל רק מודולים נוספים של ליבה שנדרשים כדי להפעיל את מצב השחזור, מלבד מודולי הליבה ב-vendor_boot ramdisk.
      • יכול להיות שהקישור הסמלי ב-/init קיים, אבל הוא מכוסה על ידי הקובץ הבינארי /init מהשלב הראשון בתמונת האתחול.

תוכן תמונה גנרי של דיסק RAM

דיסק ה-RAM הגנרי מכיל את הרכיבים הבאים.

  • init
  • system/etc/ramdisk/build.prop
  • ro.PRODUCT.bootimg.* build אביזרי תפאורה
  • ספריות ריקות לנקודות טעינה: 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. המשתנה הזה מציין אם ב-build נעשה שימוש בתמונת אתחול שנוצרה מראש. אם המשתנה הזה מוגדר כ-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. המשתנה הזה לא משפיע על syspros או על 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 מכילה ליבה (kernel) או לא. במכשירים שמריצים Android 12 ומשתמשים במחיצה recovery של A/B, צריך להגדיר את המשתנה הזה ל-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* עבור chained 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

לדוגמה, ראו את השינוי הזה.

מערכת ברמה הבסיסית (root)

אין תמיכה ב-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 אחרים להתקין בטעות קבצים אחרים בדיסק ה-RAM (במקום זאת, צריך להעביר קבצים כאלה לקובץ 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, הארכיטקטורה היא כפי שמוצגת באיור 2a או באיור 2b, ואפשרות ההגדרה של המכשיר היא אפשרות 2a או אפשרות 2b.

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

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

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

הגדרת הערכים של board

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

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

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

  • /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 מעביר את ה-root ל-/first_stage_ramdisk, אבל לפני ש-init מעביר את ה-root ל-/system. לדוגמאות, תוכלו לקרוא את המאמר סיכום ביקורת (checksums) של מטא-נתונים ודחיסת נתוני A/B וירטואליים.

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

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

מאחר שמסוף השלב הראשון מתחיל לפעול לפני ש-init מעביר את root ל-/first_stage_ramdisk, צריך להתקין את הווריאנט recovery של המודולים. כברירת מחדל, שתי הווריאנטים של המודול מותקנות ב-build/make/target/product/base_vendor.mk, כך שאם קובץ היצרן של המכשיר יורש מהקובץ הזה, אין צורך להתקין באופן מפורש את הווריאנט 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.

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

כדי לתמוך בסיכומי ביקורת של מטא-נתונים במהלך הרכבת השלב הראשון, במכשירים שלא תומכים ב-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 לא משתנה, למעט במקרה הבא:

  • דיסק ה-RAM build.prop עובר אל /second_stage_resources כדי שאפשר יהיה לקרוא את חותמת הזמן של ה-build של האתחול בשלב השני 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 מעביר את הרמה הבסיסית (root) ל-/first_stage_ramdisk ואז יריץ את /system/bin/e2fsck.

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

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

AB_OTA_PARTITIONS += recovery

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

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

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

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

הגדרת ערכים של BOARD

מגדירים את הערכים הבאים למכשירים עם מחיצה recovery של 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 := true
BOARD_MOVE_GSI_AVB_KEYS_TO_VENDOR_BOOT := true

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

כשהמכשיר נכנס ל-recovery, התוכן של recovery + vendor_boot + ramdisk גנרי הוא:

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

כשהמכשיר מופעל ל-Android, התוכן של vendor_boot + generic ramdisks הוא:

  • /init (מ-ramdisk כללי, שנוצר מ-init_first_stage)

העברת קובצי fstab

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

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

אפשר גם להתקין ב-vendor_ramdisk מודולים ספציפיים למכשיר (אפשר לדלג על השלב הזה אם אין לכם מודולים ספציפיים למכשיר להתקנה). Init לא מחליף את הרשאת root. הווריאנט 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. אם ה-ramdisk vendor_boot נטען במצב שחזור, המודול זמין גם ב-recovery. אם דיסק ה-RAM של 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. דחיפה של recovery +‏ vendor_boot +‏ generic ramdisk אל /. (אם ה-OEM (יצרן הציוד המקורי) משכפל מודולים של ליבה ב-ramdisk לגבי שחזור על ידי ההוספה שלהם ל-BOARD_RECOVERY_KERNEL_MODULES), השימוש ב-vendor_boot הוא אופציונלי.
    2. הפעלת הליבה מהמחיצה boot.
  2. הליבה מחברת את ה-ramdisk אל / ואז מריצה את /init מה-ramdisk הגנרי.

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

    1. הגדרה של IsRecoveryMode() == true ו-ForceNormalBoot() == false.
    2. טוען מודולים של ליבה של ספקים מ-/lib/modules.
    3. קוראת ל-DoFirstStageMount() אבל מדלגת על הטעינה כי IsRecoveryMode() == true. (המכשיר לא משחרר את ה-ramdisk (כי הערך של / עדיין זהה), אבל הוא כן קורא ל-SetInitAvbVersionInRecovery()).
    4. הפעלת שלב שני של init מ-/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, שאי אפשר לעדכן את מחיצת השחזור. (זה חריג).

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

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

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

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

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

הגדרת ערכים של BOARD

צריך להגדיר את הערכים הבאים למכשירים שהם לא מסוג 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

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

כשהמכשיר מופעל ב-recovery, התוכן של דיסקים וירטואליים ב-recovery הוא:

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

כשהמכשיר נכנס ל-Android, התוכן של vendor_boot + ramdis גנריים הוא:

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

העברת קובצי fstab

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

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

אפשר להתקין מודולים ספציפיים למכשיר ב-vendor_ramdisk וב-recovery של דיסק ה-RAM (אפשר לדלג על השלב הזה אם אין לכם מודולים ספציפיים למכשיר להתקנה). init לא מחליף את הרשאת root. הווריאנט vendor_ramdisk של המודולים מותקן ברמת הבסיס של vendor_ramdisk. וריאנט recovery של המודולים מתקין את המודולים ברמה הבסיסית של דיסק ה-RAM‏ recovery. דוגמאות להתקנת מודולים ב-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 \

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

כדי לתמוך בסיכום ביקורת (checksum) של מטא-נתונים במהלך הטעינה בשלב הראשון, במכשירים שלא תומכים ב-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. דחיפה של דיסק RAM לשחזור אל /.
    2. הפעלת הליבה מהמחיצה recovery.
  2. הליבה מחברת את ה-ramdisk אל / ואז מריצה את /init, שהוא קישור סימלי ל-/system/bin/init מה-ramdisk של recovery.

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

    1. הגדרה של IsRecoveryMode() == true ו-ForceNormalBoot() == false.
    2. טוען מודולים של ליבה של ספקים מ-/lib/modules.
    3. קוראת ל-DoFirstStageMount() אבל מדלגת על הטעינה כי IsRecoveryMode() == true. (המכשיר לא משחרר את ה-ramdisk (כי הערך של / עדיין זהה), אבל הוא כן קורא ל-SetInitAvbVersionInRecovery()).
    4. הפעלת שלב שני של init מ-/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
  • בזמן ה-build, קובץ system/etc/ramdisk/build.prop מתווסף ל-ramdisk הכללי. הקובץ הזה מכיל את פרטי חותמת הזמן של ה-build.

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