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

הגדרת הליבה
כדי להטמיע עדכוני מערכת מסוג A/B:
-
אם צריך, בוחרים את סדרת תיקוני הליבה הבאה:
- אם מבצעים אתחול ללא ramdisk ומשתמשים באפשרות boot as recovery, צריך לבחור את השינוי android-review.googlesource.com/#/c/158491/.
- כדי להגדיר את dm-verity בלי ramdisk, צריך לבחור את android-review.googlesource.com/#/q/status:merged+project:kernel/common+branch:android-3.18+topic:A_B_Changes_3.18.
-
מוודאים שהארגומנטים בשורת הפקודה של ליבת המערכת מכילים את הארגומנטים הנוספים הבאים:
… כאשר הערך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). -
מוסיפים את אישור X .509 שמכיל את המפתח הציבורי למחזיק המפתחות של המערכת:
-
מעתיקים את אישור X .509 בפורמט
.der
אל ספריית הבסיס שלkernel
. אם אישור X .509 הוא בפורמט של קובץ.pem
, משתמשים בפקודהopenssl
הבאה כדי להמיר מפורמט.pem
לפורמט.der
:openssl x509 -in <x509-pem-certificate> -outform der -out <x509-der-certificate>
-
יוצרים את
zImage
כך שיכלול את האישור כחלק מ-keyring המערכת. כדי לוודא,בודקים את הרשומהprocfs
(נדרשת הפעלה שלKEYS_CONFIG_DEBUG_PROC_KEYS
): הכללה מוצלחת של אישור X .509 מציינת שהמפתח הציבורי נמצא במחזיק המפתחות של המערכת (ההדגשה מציינת את מזהה המפתח הציבורי).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
-
מחליפים את הרווח ב-
#
ומעבירים אותו כ-<public-key-id>
בשורת הפקודה של ליבת המערכת. לדוגמה, מעבירים אתAndroid:#7e4333f9bba00adfe0ede979e28ed1920492b40f
במקום<public-key-id>
.
-
מעתיקים את אישור X .509 בפורמט
הגדרת משתני build
טועני אתחול עם תמיכה ב-A/B צריכים לעמוד בקריטריונים הבאים של משתני build:
חובה להגדיר את היעד של בדיקת A/B |
/device/google/marlin/+/android-7.1.0_r1/device-common.mk . אפשר גם לבצע את השלב dex2oat אחרי ההתקנה (אבל לפני ההפעלה מחדש) שמתואר במאמר בנושא קומפילציה.
|
---|---|
מומלץ מאוד לטירגוט לבדיקות A/B |
|
אי אפשר להגדיר יעד לבדיקת A/B |
|
אופציונלי בגרסאות ניפוי באגים | PRODUCT_PACKAGES_DEBUG += update_engine_client |
הגדרת מחיצות (משבצות)
במכשירים עם חלוקה A/B אין צורך במחיצת שחזור או במחיצת מטמון, כי מערכת Android כבר לא משתמשת במחיצות האלה. מחיצת הנתונים משמשת עכשיו לחבילת ה-OTA שהורדה, והקוד של תמונת השחזור נמצא במחיצת האתחול. כל המחיצות שמופעל בהן A/B טסטינג צריכות להיקרא באופן הבא (המשבצות תמיד נקראות 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. לדוגמה:
<path-to-block-device>/vendor /vendor ext4 ro wait,verify=<path-to-block-device>/metadata,slotselect
אסור לתת למחיצה את השם vendor
. במקום זאת, מחיצה vendor_a
או vendor_b
תיבחר ותותקן בנקודת ההרכבה /vendor
.
ארגומנטים של יחידות קיבולת (Slot) בליבה
צריך להעביר את הסיומת הנוכחית של המשבצת דרך צומת ספציפי של עץ המכשיר (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>
שמגדירה את המשבצת הפעילה הנוכחית למשבצת הנתונה (הפקודה הזו צריכה גם לנקות את הדגל unbootable עבור המשבצת הזו ולאפס את מספר הניסיונות לערכי ברירת המחדל). טוען האתחול צריך לתמוך גם במשתנים הבאים:
-
has-slot:<partition-base-name-without-suffix>
. הפונקציה מחזירה yes אם המחיצה שצוינה תומכת במשבצות, אחרת היא מחזירה no. -
current-slot
. מחזירה את הסיומת של המשבצת שממנה תתבצע האתחול הבא. -
slot-count
. הפונקציה מחזירה מספר שלם שמייצג את מספר המשבצות הפנויות. בשלב הזה, המערכת תומכת בשני מיקומי מודעות, ולכן הערך הוא2
. -
slot-successful:<slot-suffix>
. הפונקציה מחזירה yes אם המשבצת הנתונה סומנה כמשבצת שהפעלה שלה הסתיימה בהצלחה, אחרת היא מחזירה no. -
slot-unbootable:<slot-suffix>
. הפונקציה מחזירה yes אם המשבצת הנתונה מסומנת כמשבצת שלא ניתן לאתחל ממנה, אחרת היא מחזירה no. -
slot-retry-count:<slot-suffix>
. מספר הניסיונות החוזרים שנותרו כדי לנסות לאתחל את המשבצת הנתונה.
כדי להציג את כל המשתנים, מריצים את הפקודה
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
). רשימת המחיצות שעבורן גנרטור המטען הייעודי (payload)
מגדיר עדכון מוגדרת על ידי המשתנה AB_OTA_PARTITIONS
make.
לדוגמה, אם כוללים זוג מחיצות 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 של המוצר):
-
כדי לוודא שסקריפט ההידור וקבצים בינאריים עוברים הידור ונכללים בתמונת המערכת, צריך לכלול את הרכיבים המקוריים ב-build.
# A/B OTA dexopt package PRODUCT_PACKAGES += otapreopt_script
-
מחברים את סקריפט ההידור אל
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 באתחול הראשון.