ב-Android 10, מערכת הקבצים ברמה הבסיסית כבר לא כלולה ב-ramdisk.img
, אלא מוזגת עם system.img
(כלומר, system.img
נוצר תמיד כאילו הוגדר BOARD_BUILD_SYSTEM_ROOT_IMAGE
). במכשירים שהושקעו עם Android 10:
- שימוש בפריסה של מחיצה של מערכת כ-root (המערכת אוכפת את הפריסה הזו באופן אוטומטי במהלך ה-build, ללא אפשרויות לשינוי ההתנהגות).
- חובה להשתמש ב-ramdisk, שנדרש ל-dm-linear.
- צריך להגדיר את
BOARD_BUILD_SYSTEM_ROOT_IMAGE
לערךfalse
. ההגדרה הזו משמשת רק כדי להבדיל בין מכשירים שמשתמשים ב-ramdisk לבין מכשירים שלא משתמשים ב-ramdisk (ומטעינים אתsystem.img
ישירות במקום זאת).
המשמעות של הגדרת מערכת כ-root שונה בין Android 9 לבין Android 10. בתצורה של מערכת כ-root ב-Android 9, הערך של BOARD_BUILD_SYSTEM_ROOT_IMAGE
מוגדר כ-true
, כך שה-build יאילץ למזג את מערכת הקבצים ברמה הבסיסית (root) עם system.img
, ואז יטען את system.img
כמערכת הקבצים ברמה הבסיסית (rootfs). ההגדרה הזו חובה במכשירים שמריצים Android 9, אבל היא אופציונלית במכשירים שמשודרגים ל-Android 9 ובמכשירים עם גרסאות Android ישנות יותר. בהגדרה של מערכת Android 10 כ-root, תמיד מתבצע מיזוג של $TARGET_SYSTEM_OUT
ו-$TARGET_ROOT_OUT
ל-system.img
. זוהי התנהגות ברירת המחדל בכל המכשירים עם Android 10.
ב-Android 10 נוספו שינויים נוספים כדי לתמוך במחיצות דינמיות – מערכת מחיצות במרחב המשתמש שמאפשרת ליצור מחיצות, לשנות את הגודל שלהן או למחוק אותן באמצעות עדכונים אוויריים (OTA). במסגרת השינוי הזה, לליבת Linux אין יותר אפשרות לטעון את מחיצה המערכת הלוגית במכשירים עם Android 10, ולכן הפעולה הזו מטופלת על ידי init בשלב הראשון.
בקטעים הבאים מתוארות הדרישות למערכת כ-root עבור עדכוני OTA למערכת בלבד, ומפורטות הנחיות לעדכון מכשירים לשימוש במערכת כ-root (כולל שינויים בפריסה של המחיצות ודרישות הליבה של dm-verity). פרטים על השינויים ב-ramdisk מופיעים במאמר מחיצות של Ramdisk.
מידע על עדכוני OTA למערכת בלבד
כדי לעדכן את system.img
ו-product.img
במהדורות Android באמצעות עדכוני OTA למערכת בלבד, בלי לשנות את המחיצות האחרות, צריך פריסת מחיצה של מערכת כ-root. כדי להפעיל עדכוני OTA למערכת בלבד, כל המכשירים עם Android מגרסה 10 חייבים להשתמש בפריסה של מחיצה כמערכת ברמה הבסיסית (root).
- במכשירי A/B, שמרכבים את המחיצה
system
בתור rootfs, כבר נעשה שימוש ב-system-as-root ואין צורך בשינויים כדי לתמוך בעדכוני OTA למערכת. - במכשירים שאינם A/B, שמרכבים את המחיצה
system
ב-/system
, צריך לעדכן את פריסת המחיצה כך שתהיה 'מערכת כשורש' כדי לתמוך בעדכוני OTA למערכת.
לפרטים על מכשירים עם סביבות A/B ומכשירים ללא סביבות A/B, אפשר לעיין במאמר עדכוני מערכת A/B (חלקים).
שימוש בשכבת-על של ספק (AOSP 14 ואילך)
שכבת-על של הספק מאפשרת להוסיף שכבה לשינויים במחיצה vendor
בזמן האתחול של המכשיר. שכבת-על של ספק היא קבוצה של מודולים של ספק במחיצה product
שמתווספים למחיצה vendor
כשהמכשיר מופעל, ומחליפים את המודולים הקיימים ומוסיפים אליהם.
כשהמכשיר מופעל, התהליך init
משלים את הרכבת השלב הראשון וקורא את מאפייני ברירת המחדל. לאחר מכן, אם התנאים הבאים מתקיימים, מתבצע חיפוש ב-/product/vendor_overlay/<target_vendor_version>
ומתקינים כל ספריית משנה בספריית המחיצה vendor
המתאימה:
/vendor/<overlay_dir>
קיים./product/vendor_overlay/<target_vendor_version>/<overlay_dir>
יש את אותו הקשר קובץ כמו/vendor/<overlay_dir>
.- ל-
init
מותר לטעון את הקובץ בהקשר של/vendor/<overlay_dir>
.
הטמעת שכבת-על של ספק
מתקינים את קובצי שכבת-העל של הספקים ב-/product/vendor_overlay/<target_vendor_version>
. הקבצים האלה מוטמעים במחיצה vendor
כשהמכשיר מופעל, מחליפים קבצים באותו שם ומוסיפים קבצים חדשים. שכבת-העל של הספק לא יכולה להסיר קבצים מהמחיצה vendor
.
לקובצי שכבת-העל של הספקים צריך להיות אותו הקשר קובץ כמו של קובצי היעד שהם מחליפים במחיצה vendor
. כברירת מחדל, לקבצים בספרייה /product/vendor_overlay/<target_vendor_version>
יש את ההקשר vendor_file
. אם יש אי-התאמות בהקשר של קבצים בין קובצי שכבת-העל של הספק לבין הקבצים שהם מחליפים, צריך לציין זאת במדיניות האבטחה הספציפית למכשיר. ההקשר של הקובץ מוגדר ברמת הספרייה. אם הקשר הקובץ של ספריית שכבת-על של ספק לא תואם לספריית היעד, והקשר הקובץ הנכון לא צוין במדיניות האבטחה הספציפית למכשיר, ספריית שכבת-העל של הספק לא תתווסף לספריית היעד.
כדי להשתמש בשכבת-על של ספק, צריך להגדיר את OverlayFS בליבה באמצעות CONFIG_OVERLAY_FS=y
. בנוסף, צריך למזג את הליבה מהליבה המשותפת 4.4 ואילך, או לתקן אותה באמצעות "overlayfs:
override_creds=off option bypass creator_cred"
.
דוגמה להטמעה של שכבת-על של ספק
כאן מוצגת הטמעה של שכבת-על של ספק שמצפה על הספריות /vendor/lib/*
, /vendor/etc/*
ו-/vendor/app/*
.
-
מוסיפים קובצי ספקים מוכנים מראש בקטע
device/<vendor>/<target>/vendor_overlay/<target_vendor_version>/
:device/google/device/vendor_overlay/28/lib/libfoo.so device/google/device/vendor_overlay/28/lib/libbar.so device/google/device/vendor_overlay/28/etc/baz.xml device/google/device/vendor_overlay/28/app/qux.apk
-
מתקינים את קובצי הספק שנוצרו מראש ב-
product/vendor_overlay
ב-device/google/device/device.mk
:PRODUCT_COPY_FILES += \ $(call find-copy-subdir-files,*,device/google/device/vendor_overlay,$(TARGET_COPY_OUT_PRODUCT)/vendor_overlay)
-
מגדירים את ההקשרים של הקבצים אם לקבצים של מחיצה היעד
vendor
יש הקשרים שונים מ-vendor_file
. מכיוון ש-/vendor/lib/*
משתמש בהקשר שלvendor_file
, הדוגמה הזו לא כוללת את הספרייה הזו.מוסיפים את הפרטים הבאים ל-
device/google/device-sepolicy/private/file_contexts
:/(product|system/product)/vendor_overlay/[0-9]+/etc(/.*)? u:object_r:vendor_configs_file:s0 /(product|system/product)/vendor_overlay/[0-9]+/app(/.*)? u:object_r:vendor_app_file:s0
-
מאפשרים לתהליך
init
לטעון את שכבת-העל של הספק בהקשרים של קבצים שאינםvendor_file
. מכיוון שלתהליךinit
כבר יש הרשאה לטעון את ההקשרvendor_file
, בדוגמה הזו לא מוגדרת המדיניות עבורvendor_file
.מוסיפים את הפרטים הבאים ל-
device/google/device-sepolicy/public/init.te
:allow init vendor_configs_file:dir mounton; allow init vendor_app_file:dir mounton;
אימות שכבת-העל של הספק
כדי לאמת את ההגדרה של שכבת-העל של הספק, מוסיפים קבצים ב-/product/vendor_overlay/<target_vendor_version>/<overlay_dir>
ובודקים אם הקבצים מוטמעים מעל הקבצים ב-/vendor/<overlay_dir>
.
לגרסאות build של userdebug
יש מודול בדיקה ל-Atest:
$ atest -v fs_mgr_vendor_overlay_test
עדכון ל-system-as-root
כדי לעדכן מכשירי A/B לשימוש ב-system-as-root, צריך לעדכן את הסכימה של חלוקת המחיצות של boot.img
ו-system.img
, להגדיר את dm-verity ולהסיר את כל יחסי התלות של האתחול בתיקיות השורש הספציפיות למכשיר.
עדכון המחיצות
בניגוד למכשירי A/B שבהם /boot
משמש כמחיצה לשחזור, במכשירים שאינם A/B צריך להפריד את המחיצה /recovery
כי אין להם מחיצה של חריץ חלופי (לדוגמה, מ-boot_a
ל-boot_b
). אם המחיצה /recovery
תוסר במכשיר שאינו A/B ותתווסף לתוכנית A/B, מצב השחזור עלול להיפגע במהלך עדכון כושל למחיצה /boot
. לכן, במכשירים ללא תמיכה ב-A/B, מחיצה /recovery
חייבת להיות מחיצה נפרדת מ-/boot
. המשמעות היא שתמונת השחזור ממשיכה להתעדכן באופן מושהה (כלומר, כמו במכשירים עם Android מגרסה 8.1.0 ואילך).
בטבלה הבאה מפורטים ההבדלים בין מחיצות התמונות במכשירים שאינם A/B לפני ואחרי Android 9.
תמונה | דיסק זיכרון (עד גרסה 9) | מערכת כ-root (אחרי 9) |
---|---|---|
boot.img |
מכיל ליבה ו-ramdisk.img :
ramdisk.img -/ - init.rc - init - etc -> /system/etc - system/ (mount point) - vendor/ (mount point) - odm/ (mount point) ... |
מכיל ליבה רגילה לאתחול בלבד. |
recovery.img |
מכיל ליבה של שחזור ו-ramdisk.img של שחזור. |
|
system.img |
מכיל את הפרטים הבאים:
system.img -/ - bin/ - etc - vendor -> /vendor - ... |
מכיל את התוכן הממוזג של system.img ו-ramdisk.img המקוריים:
system.img -/ - init.rc - init - etc -> /system/etc - system/ - bin/ - etc/ - vendor -> /vendor - ... - vendor/ (mount point) - odm/ (mount point) ... |
המחיצות עצמן לא משתנות. גם ב-ramdisk וגם ב-system-as-root נעשה שימוש בסכימת המחיצות הבאה:
/boot
/system
/system
/recovery
/vendor
וכו'
הגדרת dm-verity
ב-system-as-root, הליבה צריכה לטעון את system.img
מתחת ל-/
(נקודת הטעינה) באמצעות dm-verity. AOSP תומך בהטמעות הבאות של dm-verity עבור system.img
.
vboot 1.0
ב-vboot 1.0, הליבה צריכה לנתח מטא-נתונים ספציפיים ל-Android ב-/system
, ולאחר מכן להמיר אותם לפרמטרים של dm-verity כדי להגדיר את dm-verity (נדרשים תיקוני הליבה האלה).
בדוגמה הבאה מוצגות הגדרות שקשורות ל-dm-verity למערכת כ-root בשורת הפקודה של הליבה:
ro root=/dev/dm-0 rootwait skip_initramfs init=/init dm="system none ro,0 1 android-verity /dev/sda34" veritykeyid=id:7e4333f9bba00adfe0ede979e28ed1920492b40f
vboot 2.0
ב-vboot 2.0 (AVB), תוכנת האתחול צריכה לשלב את external/avb/libavb, שמנתחת את התיאור של hashtree עבור /system
, ממירה אותו ל-dm-verity params ובסופו של דבר מעבירה את הפרמטרים לליבה דרך שורת הפקודה של הליבה. (התיאורים של עץ הגיבוב של /system
יכולים להיות ב-/vbmeta
או ב-/system
עצמו).
כדי להשתמש ב-vboot 2.0 נדרשים תיקוני הליבה הבאים:
- https://android-review.googlesource.com/#/c/kernel/common/+/158491/
- תיקוני kernel 4.4, תיקוני kernel 4.9 וכו'.
בדוגמה הבאה מוצגות הגדרות שקשורות ל-dm-verity למערכת כ-root בשורת הפקודה של הליבה:
ro root=/dev/dm-0 rootwait skip_initramfs init=/init dm="1 vroot none ro 1,0 5159992 verity 1 PARTUUID=00000016-0000-0000-0000-000000000000 PARTUUID=00000016-0000-0000-0000-000000000000 4096 4096 644999 644999 sha1 d80b4a8be3b58a8ab86fad1b498640892d4843a2 8d08feed2f55c418fb63447fec0d32b1b107e42c 10 restart_on_corruption ignore_zero_blocks use_fec_from_device PARTUUID=00000016-0000-0000-0000-000000000000 fec_roots 2 fec_blocks 650080 fec_start 650080"
שימוש בתיקיות ברמה הבסיסית (root) ספציפיות למכשיר
כשמשתמשים ב-system-as-root, אחרי שקובץ האימג' המערכת הגנרי (GSI) מופעל במכשיר (ולפני שמריצים את הבדיקות של Vendor Test Suite), כל התיקיות ברמה הבסיסית (root) שנוספו באמצעות BOARD_ROOT_EXTRA_FOLDERS
נמחקות כי כל התוכן של ספריית הבסיס הוחלף ב-GSI של system-as-root. אם יש תלות בתיקיות הבסיס הספציפיות למכשיר (לדוגמה, הן משמשות כנקודות קישור), הסרת התיקיות האלה עלולה לגרום לכך שלא תהיה אפשרות להפעיל את המכשיר.
כדי למנוע את הבעיה הזו, אל תשתמשו ב-BOARD_ROOT_EXTRA_FOLDERS
כדי להוסיף תיקיות ברמה הבסיסית ספציפיות למכשיר. אם צריך לציין נקודות עגינה ספציפיות למכשיר, משתמשים ב-/mnt/vendor/<mount point>
(נוסף ברשימות השינויים האלה). אפשר לציין את נקודות הטעינה הספציפיות לספק ישירות גם בעץ המכשיר fstab
(לטעינה בשלב הראשון) וגם בקובץ /vendor/etc/fstab.{ro.hardware}
בלי הגדרה נוספת (כי fs_mgr
יוצר אותן באופן אוטומטי ב-/mnt/vendor/*
).