העברת אתחול מהיר למרחב המשתמשים

ב-Android מגרסה 10 ואילך יש תמיכה במחיצות שניתנות לשינוי גודל על ידי שינוי המיקום של הטמעת האתחול מתוכנת האתחול למרחב המשתמשים. המיקום הזה מאפשר להעביר את הקוד המהבהב למיקום משותף שניתן לתחזק ולבדיקה, שבו רק החלקים הספציפיים לספק של אתחול מהיר הוטמעו על ידי שכבת הפשטה של החומרה (HAL). בנוסף, ב-Android מגרסה 12 ואילך יש תמיכה בהבהוב של ramdisk באמצעות פקודת אתחול מהיר נוספת.

איחוד אתחול מהיר ושחזור

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

כדי לתמוך ב-fastbootd, תוכנת האתחול צריכה להטמיע פקודת בלוק של בקרת אתחול (BCB) חדשה של boot-fastboot. כדי להיכנס למצב fastbootd, תוכנת האתחול כותבת את הערך boot-fastboot בשדה הפקודה של הודעת ה-BCB ומשאירה את השדה recovery של BCB ללא שינוי (כדי לאפשר הפעלה מחדש של משימות שחזור שהופסקו). גם השדות status, stage ו-reserved לא ישתנו. תוכנת האתחול נטענת לתמונת השחזור ומבצעת אתחול שלה כשמופיעה boot-fastboot בשדה הפקודה של BCB. לאחר מכן, השחזור ינתח את הודעת ה-BCB ועובר למצב fastbootd.

פקודות ADB

בקטע הזה מתוארת הפקודה adb לשילוב fastbootd. לפקודה יש תוצאות שונות, בהתאם להפעלה של המערכת או לשחזור.

הוראה תיאור
reboot fastboot
  • בוצעה הפעלה מחדש לתוך fastbootd (מערכת).
  • הזנת fastbootd ישירות ללא הפעלה מחדש (שחזור).

פקודות Fastboot

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

הוראה תיאור
reboot recovery
  • אתחולים מחדש לצורך שחזור (תוכנת אתחול).
  • כניסה ישירה לשחזור ללא הפעלה מחדש (fastbootd).
reboot fastboot הפעלה מחדש תתבצע בעוד fastbootd.
getvar is-userspace
  • הפונקציה מחזירה את הערך yes (fastbootd).
  • הפונקציה מחזירה את הערך no (תוכנת אתחול).
getvar is-logical:<partition> הפונקציה מחזירה את הערך yes אם המחיצה הנתונה היא מחיצה לוגית, אחרת no. מחיצות לוגיות תומכות בכל הפקודות שמפורטות בהמשך.
getvar super-partition-name מחזירה את השם של מחיצת-העל. השם כולל את סיומת המשבצת הנוכחית אם מחיצת ה-Super היא מחיצת A/B (בדרך כלל היא לא).
create-logical-partition <partition> <size> יצירת מחיצה לוגית עם השם והגודל הנתונים. השם לא יכול להיות כבר קיים כמחיצה לוגית.
delete-logical-partition <partition> מוחק את המחיצה הלוגית הנתונה (מאפס באופן יעיל את המחיצה).
resize-logical-partition <partition> <size> משנה את גודל המחיצה הלוגית לגודל החדש מבלי לשנות את התוכן שלה. הפעולה תיכשל אם אין מספיק מקום פנוי לביצוע שינוי הגודל.
update-super <partition> מיזוג שינויים במטא-נתונים של מחיצת-על. אם אי אפשר לבצע מיזוג (למשל, הפורמט במכשיר הוא גרסה שלא נתמכת), הפקודה הזו תיכשל. פרמטר wipe אופציונלי מחליף את המטא-נתונים של המכשיר, במקום לבצע מיזוג.
flash <partition><filename> ] כותב קובץ למחיצה של Flash. המכשיר צריך להיות במצב לא נעול.
erase <partition> מוחק מחיצה (לא נדרשת לצורך מחיקה מאובטחת). המכשיר חייב להיות במצב 'לא נעול'.
getvar <variable> | all מציגה משתנה של תוכנת אתחול או את כל המשתנים. אם המשתנה לא קיים, תוחזר שגיאה.
set_active <slot>

הגדרת חריץ ההפעלה של A/B הנתון כ-active. בניסיון האתחול הבא, המערכת תופעל מהחריץ שצוין.

לתמיכה ב-A/B, משבצות הן קבוצות כפולות של מחיצות שאפשר לאתחל מהן בנפרד. המשבצות נקראים a, b וכן הלאה, והן מופרדות באמצעות הסיומות _a ו-_b, וכן הלאה לשם המחיצה.

reboot המכשיר מופעל מחדש כרגיל.
reboot-bootloader (או reboot bootloader) הפעלת המכשיר מחדש באמצעות תוכנת אתחול.
fastboot fetch vendor_boot <out.img>

צריך להשתמש ב-Android מגרסה 12 ואילך כדי לתמוך ברדיסקים של ספקים מהבהבים.

הפונקציה מקבלת את כל גודל המחיצה ואת גודל המקטע. מקבל נתונים עבור כל מקטע, ולאחר מכן מחבר את הנתונים ל-<out.img>

מידע נוסף מופיע כאן: fastboot fetch vendor_boot <out.img>.

fastboot flash vendor_boot:default <vendor-ramdisk.img>

צריך להשתמש ב-Android 12 ואילך כדי לתמוך ב-Radisk של ספקים מהבהבים.

זוהי וריאציה מיוחדת של פקודת ה-Flash. היא מבצעת פונקציית תמונה fetch vendor_boot, כאילו שנקראה fastboot fetch. תמונת vendor_boot החדשה שהיא מהבהבת תלויה בגרסה 3 או בגרסה 4 של כותרת האתחול.

למידע נוסף, אפשר לעיין במאמר fastboot flash vendor_boot:default <vendor-ramdisk.img>.

fastboot flash vendor_boot:<foo> <vendor-ramdisk.img> צריך להשתמש בו ב-Android 12 ואילך כדי לתמוך ב-Radisk מהבהב של ספקים.

אחזור התמונה של vendor_boot. הפונקציה מחזירה שגיאה אם כותרת האתחול של הספק היא גרסה 3. אם מדובר בגרסה 4, היא מוצאת את המקטע הנכון של RAMdisk של הספק (אם הוא זמין). היא מחליפה אותה בתמונה הנתונה, מחשבת מחדש את הגדלים וההיסט, ומחזירה את הערך של vendor_boot image החדש.

לפרטים נוספים: fastboot flash vendor_boot:<foo> <vendor-ramdisk.img>

אתחול מהיר ותוכנת אתחול

תוכנת האתחול יהבהב את המחיצות bootloader, radio ו-boot/recovery, ואחר כך המכשיר יבצע אתחול מהיר (userspace) ויהבהב את כל המחיצות האחרות. תוכנת האתחול צריכה לתמוך בפקודות הבאות.

הוראה תיאור
download הורדת התמונה להבהוב.
flash recovery <image>/ flash boot <image>/ flash bootloader <image>/ מפעילה את המחיצה ותוכנת האתחול של recovery/boot.
reboot הפעלת המכשיר מחדש.
reboot fastboot מופעל מחדש לצורך אתחול מהיר (fastboot).
reboot recovery הפעלה מחדש לצורך שחזור.
getvar הפונקציה מקבלת משתנה של תוכנת אתחול שנדרש להבהוב של תמונת שחזור/אתחול (לדוגמה current-slot ו-max-download-size).
oem <command> הפקודה הוגדרה על ידי ה-OEM (יצרן הציוד המקורי).

מחיצות דינמיות

תוכנת האתחול לא יכולה לאפשר את ההבהוב או המחיקה של מחיצות דינמיות וחייב להחזיר שגיאה אם מבצעים את הפעולות האלה. במכשירי מחיצות דינמיים שהותקנו, הכלי לאתחול מהיר (ותוכנת האתחול) תומך במצב כוח להפעלת מחיצה דינמית ישירות במצב של תוכנת אתחול. לדוגמה, אם system היא מחיצה דינמית במכשיר שהותקן, באמצעות הפקודה fastboot --force flash system, תוכנת האתחול (במקום fastbootd) תעדכן את המחיצה.

טעינה ללא חיבור לאינטרנט

אם במכשיר יש תמיכה בטעינה במצב אופליין או באתחול אוטומטי במצב מיוחד לאחר הפעלת חשמל, הטמעה של הפקודה fastboot oem off-mode-charge 0 חייבת לעקוף את המצבים המיוחדים האלה, כך שהמכשיר יופעל כאילו המשתמש לחץ על לחצן ההפעלה.

אתחול מהיר של OEM (יצרן ציוד מקורי) HAL

כדי להחליף לגמרי את האתחול המהיר של תוכנת האתחול, תהליך האתחול המהיר צריך לטפל בכל הפקודות הקיימות של אתחול מהיר (fastboot). הרבה מהפקודות האלה מגיעות מיצרני ציוד מקורי (OEM) והן מתועדות, אבל נדרשת הטמעה בהתאמה אישית. פקודות רבות שספציפיות ל-OEM לא מתועדות. כדי לטפל בפקודות כאלה, רכיב האתחול המהיר HAL מציין את פקודות ה-OEM הנדרשות. יצרני ציוד מקורי יכולים גם ליישם פקודות משלהם.

ההגדרה של אתחול מהיר עם HAL היא:

import IFastbootLogger;

/**
 * IFastboot interface implements vendor specific fastboot commands.
 */
interface IFastboot {
    /**
     * Returns a bool indicating whether the bootloader is enforcing verified
     * boot.
     *
     * @return verifiedBootState True if the bootloader is enforcing verified
     * boot and False otherwise.
     */
    isVerifiedBootEnabled() generates (bool verifiedBootState);

    /**
     * Returns a bool indicating the off-mode-charge setting. If off-mode
     * charging is enabled, the device autoboots into a special mode when
     * power is applied.
     *
     * @return offModeChargeState True if the setting is enabled and False if
     * not.
     */
    isOffModeChargeEnabled() generates (bool offModeChargeState);

    /**
     * Returns the minimum battery voltage required for flashing in mV.
     *
     * @return batteryVoltage Minimum battery voltage (in mV) required for
     * flashing to be successful.
     */
    getBatteryVoltageFlashingThreshold() generates (int32_t batteryVoltage);

    /**
     * Returns the file system type of the partition. This is only required for
     * physical partitions that need to be wiped and reformatted.
     *
     * @return type Can be ext4, f2fs or raw.
     * @return result SUCCESS if the operation is successful,
     * FAILURE_UNKNOWN if the partition is invalid or does not require
     * reformatting.
     */
    getPartitionType(string partitionName) generates (FileSystemType type, Result result);

    /**
     * Executes a fastboot OEM command.
     *
     * @param oemCmd The oem command that is passed to the fastboot HAL.
     * @response result Returns the status SUCCESS if the operation is
     * successful,
     * INVALID_ARGUMENT for bad arguments,
     * FAILURE_UNKNOWN for an invalid/unsupported command.
     */
    doOemCommand(string oemCmd) generates (Result result);

};

הפעלת Fastbootd

כדי להפעיל את fastbootd במכשיר:

  1. הוספה של fastbootd אל PRODUCT_PACKAGES ב-device.mk: PRODUCT_PACKAGES += fastbootd.

  2. חשוב לוודא שהרכיבים מסוג HAL לאתחול מהיר, בקרת אתחול HAL ו-HAL של Health נארזים כחלק מקובץ האימג' לשחזור מערכת ההפעלה.

  3. יש להוסיף את כל הרשאות SEPolicy הספציפיות למכשיר שנדרשות על ידי fastbootd. לדוגמה, ל-fastbootd נדרשת גישת כתיבה למחיצה ספציפית למכשיר כדי לגרום ל-Flash של המחיצה להקפיץ אותה. בנוסף, ייתכן שהטמעה של אתחול מהיר עם HAL תדרוש גם הרשאות ספציפיות למכשיר.

כדי לאמת את האתחול המהיר במרחב המשתמשים, מריצים את Vendor Test Suite (VTS).

ramdisks של ספקי Flash

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

כדי לשלוף את קובץ האימג' המלא של vendor_boot, נוספה הפקודה fetch:vendor_boot גם לפרוטוקול Quickboot וגם להטמעת Quickbootd של הפרוטוקול ב-Android 12. שימו לב שהפעולה הזו מבטיחה אתחול מהיר (Fastbootd), אבל יכול להיות שתוכנת האתחול לא פועלת. יצרני ציוד מקורי יכולים להוסיף את הפקודה fetch:vendor_boot לתוכנת האתחול של הפרוטוקול שלהם. עם זאת, אם הפקודה לא מזוהה במצב תוכנת אתחול, המשמעות של RAMdisk של ספק ספציפי במצב תוכנת האתחול לא יכולה להיות אפשרות שנתמכת על ידי הספק.

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

הפקודות getvar:max-fetch-size ו-fetch:name מוטמעות ב-fastbootd. כדי לתמוך בהבהוב של RAMdisk של ספקים בתוכנת האתחול, צריך להטמיע את שתי הפקודות האלה.

שינויי אתחול מהיר (Fastbootd)

getvar:max-fetch-size דומה ל-max-download-size. הוא מציין את הגודל המקסימלי שהמכשיר יכול לשלוח בתגובת DATA אחת. אסור לנהג לשלוף גודל שגדול מהערך הזה.

האפליקציה fetch:name[:offset[:size]] מבצעת סדרה של בדיקות במכשיר. אם כל התנאים הבאים מתקיימים, הפקודה fetch:name[:offset[:size]] תחזיר נתונים:

  • במכשיר פועלת גרסת build שניתנת לניפוי באגים.
  • המכשיר לא נעול (מצב הפעלה כתום).
  • שם המחיצה שאוחזר הוא vendor_boot.
  • הערך size הוא בטווח של 0 < size <= max-fetch-size.

לאחר האימות, fetch:name[:offset[:size]] מחזיר את גודל המחיצה ואת ההיסט. שימו לב:

  • fetch:name היא שוות-ערך ל-fetch:name:0, שמקבילה ל-fetch:name:0:partition_size.
  • fetch:name:offset זהה ל-fetch:name:offset:(partition_size - offset)

לכן fetch:name[:offset[:size]] = fetch:name:offset:(partition_size - offset).

אם לא מציינים את offset או את partition_size (או את שניהם), המערכת משתמשת בערכי ברירת המחדל, שבהם הערך של offset הוא 0, והערך של size הוא partition_size - offset.

  • צוין היסט, הגודל לא צוין: size = partition_size - offset
  • לא צוין: ערכי ברירת מחדל משמשים לשניהם, size = partition_size - 0.

לדוגמה, fetch:foo מאחזר את כל המחיצה של foo בהיסט 0.

שינויים במנהל ההתקן

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

  • fastboot fetch vendor_boot out.img

    • הפונקציה מפעילה את הפקודה getvar max-fetch-size כדי לקבוע את גודל המקטע.
    • קוראת לפונקציה getvar partition-size:vendor_boot[_a] כדי לקבוע את גודל המחיצה כולה.
    • הפונקציה קוראת ל-fastboot fetch vendor_boot[_a]:offset:size לכל מקטע. (הגודל של מקטע גדול יותר מהגודל vendor_boot, כך שבדרך כלל יש רק מקטע אחד).
    • חיבור הנתונים זה לזה, כדי out.img.
  • fastboot flash vendor_boot:default vendor-ramdisk.img

    זוהי וריאציה מיוחדת של פקודת ה-Flash. הוא מאחזר את התמונה vendor_boot, כאילו קוראים לפונקציה fastboot fetch.

    • אם האתחול של הספק הוא הכותרת גרסה 3, היא מבצעת את הפעולות הבאות:
      • מחליפה את ה-ramdisk של הספק בתמונה הנתונה.
      • ההבהוב של תמונת vendor_boot החדשה.
    • אם כותרת האתחול של הספק היא גרסה 4, היא מבצעת את הפעולות הבאות:
      • מחליפה את כל ה-ramdisk של הספק בתמונה הנתונה, כך שהתמונה הנתונה תהפוך למקטע היחיד של ramdisk של הספק בתמונה של vendor_boot.
      • מחשבת מחדש את הגודל וההיסט בטבלת ה-ramdisk של הספק.
      • ההבהוב של תמונת vendor_boot החדשה.
  • fastboot flash vendor_boot:foo vendor-ramdisk.img

    הפונקציה מאחזרת את vendor_boot image, כאילו נשלחה קריאה אל fastboot fetch.

    • אם כותרת האתחול של הספק היא גרסה 3, היא תחזיר שגיאה.
    • אם כותרת האתחול של הספק היא גרסה 4, היא מבצעת את הפעולות הבאות:

      • מתבצע חיפוש של מקטע ה-ramdisk של הספק בשם foo. אם הוא לא נמצא או שיש כמה התאמות, תוחזר הודעת שגיאה.
      • מחליפה את המקטע של Ramdisk של הספק בתמונה הנתונה.
      • מחשבת מחדש כל גודל והיסט בטבלת ה-ramdisk של הספק.
      • ההבהוב של תמונת vendor_boot החדשה.

Mkbootimg

השם default שמור למתן שמות למקטעי ramdisk של הספק ב-Android 12 ואילך. למרות שהסמנטיקה של flash vendor_boot:default בתהליך האתחול המהיר נשארת ללא שינוי, אסור לתת למקטעי ה-ramdisk את השם default.

שינויים ב-SELinux

בוצע שינוי ב-fastbootd.te כדי לתמוך ב-Radisk מהבהבים של ספקים.