يجب على مصنعي المعدات الأصلية وبائعي SoC الذين يرغبون في تنفيذ تحديثات نظام A / B التأكد من أن محمل الإقلاع الخاص بهم ينفذ boot_control HAL ويمرر المعلمات الصحيحة إلى kernel.
تنفيذ التحكم في التمهيد HAL
يجب على محمل الإقلاع الذي يدعم A / B تنفيذ boot_control
HAL على hardware/libhardware/include/hardware/boot_control.h
. يمكنك اختبار التطبيقات باستخدام الأداة المساعدة system/extras/bootctl
system/extras/tests/bootloader/
.
يجب عليك أيضًا تنفيذ آلة الحالة الموضحة أدناه:

إعداد النواة
لتنفيذ تحديثات نظام A / B:
- Cherrypick سلسلة تصحيح kernel التالية (إذا لزم الأمر):
- في حالة التشغيل بدون ramdisk واستخدام "التمهيد كاسترداد" ، فإن cherrypick android-review.googlesource.com/#/c/158491/ .
- لإعداد dm-verity بدون ramdisk ، قم باختيار cherrypick android-review.googlesource.com/#/q/status:merged+project:kernel/common+branch:android-3.18+topic:A_B_Changes_3.18 .
- تأكد من احتواء وسيطات سطر أوامر kernel على الوسائط الإضافية التالية:
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 ) . - أضف شهادة .X509 التي تحتوي على المفتاح العام إلى حلقة مفاتيح النظام:
- انسخ شهادة .X509 المنسقة بتنسيق
.der
إلى جذر دليلkernel
. إذا تم تنسيق شهادة.pem
كملف .pem ، فاستخدم الأمرopenssl
التالي للتحويل من تنسيق.pem
إلى تنسيق.der
:openssl x509 -in <x509-pem-certificate> -outform der -out <x509-der-certificate>
- قم بإنشاء
zImage
لتضمين الشهادة كجزء من حلقة مفاتيح النظام. للتحقق ، تحقق من إدخالprocfs
(يتطلب تمكينKEYS_CONFIG_DEBUG_PROC_KEYS
):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
يشير التضمين الناجح لشهادة .X509 إلى وجود المفتاح العام في سلسلة مفاتيح النظام (يشير التمييز إلى معرف المفتاح العام). - استبدل المسافة بـ
#
وقم بتمريرها كـ<public-key-id>
في سطر أوامر kernel. على سبيل المثال ، مررAndroid:#7e4333f9bba00adfe0ede979e28ed1920492b40f
بدلاً من<public-key-id>
.
- انسخ شهادة .X509 المنسقة بتنسيق
تحديد متغيرات البناء
يجب أن تفي محمل الإقلاع القادر على تشغيل A / B بمعايير متغير البناء التالية:
يجب تحديد هدف 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-ed على النحو التالي (تسمى الفتحات دائمًا 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
في سطر أوامر kernel.
بالنسبة للتحديثات بخلاف A / B ، يحتوي قسم الاسترداد على الكود المستخدم لتطبيق التحديثات. يتم تطبيق تحديثات A / B عن طريق update_engine
الذي يعمل في صورة نظام التشغيل العادي. لا يزال هناك وضع استرداد يستخدم لتنفيذ إعادة تعيين بيانات المصنع والتحميل الجانبي لحزم التحديث (حيث جاء اسم "الاسترداد"). يتم تخزين رمز وبيانات وضع الاسترداد في قسم التمهيد العادي في ramdisk ؛ للإقلاع في صورة النظام ، يخبر محمل الإقلاع النواة بتخطي ذاكرة الوصول العشوائي (وإلا سيتم تشغيل الجهاز في وضع الاسترداد. وضع الاسترداد صغير (وكان الكثير منه موجودًا بالفعل في قسم التمهيد) ، لذلك لا يزيد قسم التمهيد في الحجم.
فستاب
يجب أن تكون وسيطة slotselect
على سطر أقسام A / B-ed. فمثلا:
<path-to-block-device>/vendor /vendor ext4 ro wait,verify=<path-to-block-device>/metadata,slotselect
لا يجب تسمية أي قسم vendor
. بدلاً من ذلك ، سيتم تحديد قسم vendor_a
أو vendor_b
على /vendor
mount point.
وسيطات فتحة Kernel
يجب تمرير لاحقة الفتحة الحالية إما من خلال عقدة شجرة جهاز محددة (DT) ( /firmware/android/slot_suffix
) أو من خلال سطر أوامر androidboot.slot_suffix
kernel أو وسيطة bootconfig.
بشكل افتراضي ، يومض fastboot الفتحة الحالية على جهاز A / B. إذا كانت حزمة التحديث تحتوي أيضًا على صور للفتحة الأخرى غير الحالية ، فإن fastboot تومض تلك الصور أيضًا. تشمل الخيارات المتاحة:
-
--slot SLOT
. تجاوز السلوك الافتراضي وحث fastboot على وميض الفتحة التي تم تمريرها كوسيطة. -
--set-active [ SLOT ]
. اضبط الفتحة على أنها نشطة. إذا لم يتم تحديد وسيطة اختيارية ، فسيتم تعيين الفتحة الحالية على أنها نشطة. -
fastboot --help
. احصل على تفاصيل حول الأوامر.
إذا قام برنامج bootloader بتنفيذ fastboot ، فيجب أن يدعم الأمر set_active <slot>
الذي يعيّن الفتحة النشطة الحالية إلى الفتحة المحددة (يجب أيضًا مسح العلامة غير القابلة للتمهيد لتلك الفتحة وإعادة تعيين عدد مرات إعادة المحاولة إلى القيم الافتراضية). يجب أن يدعم برنامج bootloader أيضًا المتغيرات التالية:
-
has-slot:<partition-base-name-without-suffix>
. إرجاع "نعم" إذا كان القسم المحدد يدعم الفتحات ، "لا" بخلاف ذلك. -
current-slot
. تُرجع لاحقة الفتحة التي سيتم تشغيلها من التالي. -
slot-count
. تُرجع عددًا صحيحًا يمثل عدد الفتحات المتاحة. حاليًا ، يتم دعم فتحتين ، لذا فإن هذه القيمة هي2
. -
slot-successful:<slot-suffix>
. لعرض "نعم" إذا تم وضع علامة على الفتحة المحددة على أنها تمهيد ناجح ، أو إرجاع "لا" بخلاف ذلك. -
slot-unbootable:<slot-suffix>
. لعرض "نعم" إذا تم وضع علامة على الفتحة المحددة على أنها غير قابلة للتمهيد ، أو إرجاع "لا" بخلاف ذلك. -
slot-retry-count
. عدد المحاولات المتبقية لمحاولة تمهيد الفتحة المحددة.
لعرض جميع المتغيرات ، قم بتشغيل fastboot getvar all
.
توليد حزم OTA
تتبع أدوات حزمة OTA نفس الأوامر مثل الأوامر للأجهزة غير A / B. يجب إنشاء ملف target_files.zip
عن طريق تحديد متغيرات البناء لهدف 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
). تم تكوين قائمة الأقسام التي يحدد منشئ الحمولة النافعة تحديثًا لها بواسطة AB_OTA_PARTITIONS
جعلها متغيرة.
على سبيل المثال ، إذا تم تضمين زوج من الأقسام 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
تجميع
لأسباب أمنية ، لا يمكن system_server
استخدام التجميع في الوقت المناسب (JIT) . هذا يعني أنه يجب عليك تجميع ملفات odex مسبقًا لـ system_server
وتبعياتها كحد أدنى ؛ أي شيء آخر اختياري.
لتجميع التطبيقات في الخلفية ، يجب عليك إضافة ما يلي إلى تكوين جهاز المنتج (في device.mk الخاص بالمنتج):
- قم بتضمين المكونات الأصلية في الإنشاء لضمان تجميع نصوص وثنائيات التجميع وتضمينها في صورة النظام.
# 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 .