การนำการอัปเดต A/B ไปใช้

OEM และ SoC ผู้ขายที่ต้องการที่จะใช้ A / B การปรับปรุงระบบต้องให้แน่ใจว่าการดำเนินการของพวกเขา bootloader boot_control HAL และผ่าน พารามิเตอร์ที่ถูกต้อง เคอร์เนล

การใช้งานการควบคุมการบูตHAL

A / B-bootloaders ความสามารถจะต้องดำเนินการ boot_control HAL ที่ hardware/libhardware/include/hardware/boot_control.h คุณสามารถทดสอบการใช้งานโดยใช้ system/extras/bootctl สาธารณูปโภคและ system/extras/tests/bootloader/ /

คุณต้องใช้เครื่องสถานะที่แสดงด้านล่าง:

เครื่องของรัฐรูปที่ 1 Bootloader

การตั้งค่าเคอร์เนล

การนำการอัปเดตระบบ A/B ไปใช้:

  1. Cherrypick ซีรีส์แพทช์เคอร์เนลต่อไปนี้ (ถ้าจำเป็น):
  2. ตรวจสอบให้แน่ใจอาร์กิวเมนต์บรรทัดคำสั่งเคอร์เนลมีข้อโต้แย้งพิเศษต่อไปนี้:
    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-สิ่งที่เป็นจริง ) .
  3. เพิ่มใบรับรอง .X509 ที่มีคีย์สาธารณะในคีย์ริงของระบบ:
    1. คัดลอกใบรับรอง .X509 การจัดรูปแบบใน .der รูปแบบไปยังรากของ kernel ไดเรกทอรี หากใบรับรอง .X509 มีรูปแบบเป็น .pem ไฟล์ใช้ต่อไปนี้ openssl คำสั่งการแปลงจาก .pem เพื่อ .der รูปแบบ:
      openssl x509 -in <x509-pem-certificate> -outform der -out <x509-der-certificate>
    2. สร้าง 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 บ่งชี้ว่าการปรากฏตัวของคีย์สาธารณะในพวงกุญแจระบบ (ไฮไลท์หมายถึงรหัสคีย์สาธารณะ)
    3. เปลี่ยนพื้นที่ที่มี # และผ่านมันเป็น <public-key-id> ในบรรทัดคำสั่งเคอร์เนล ยกตัวอย่างเช่นผ่าน Android:#7e4333f9bba00adfe0ede979e28ed1920492b40f ในสถานที่ของ <public-key-id>

การตั้งค่าตัวแปรบิวด์

bootloaders ที่รองรับ A/B ต้องเป็นไปตามเกณฑ์ตัวแปรบิวด์ต่อไปนี้:

ต้องกำหนดสำหรับเป้าหมาย A/B
  • AB_OTA_UPDATER := true
  • AB_OTA_PARTITIONS := \
    boot \
    system \
    vendor
    และพาร์ทิชันอื่น ๆ การปรับปรุงผ่าน update_engine (วิทยุ bootloader ฯลฯ )
  • PRODUCT_PACKAGES += \
    update_engine \
    update_verifier
ยกตัวอย่างเช่นการอ้างถึง /device/google/marlin/+/android-7.1.0_r1/device-common.mk คุณสามารถเลือกดำเนินการหลังการติดตั้ง ( แต่ก่อนรีบูต) dex2oat ขั้นตอนที่อธิบายไว้ใน รวบรวม
แนะนำเป็นอย่างยิ่งสำหรับเป้าหมาย A/B
  • กำหนด TARGET_NO_RECOVERY := true
  • กำหนด BOARD_USES_RECOVERY_AS_BOOT := true
  • ไม่ได้กำหนด BOARD_RECOVERYIMAGE_PARTITION_SIZE
ไม่สามารถกำหนดเป้าหมาย A/B ได้
  • BOARD_CACHEIMAGE_PARTITION_SIZE
  • BOARD_CACHEIMAGE_FILE_SYSTEM_TYPE
เป็นทางเลือกสำหรับการสร้างดีบัก 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 ไฟล์ เมื่อจะเข้าสู่การกู้คืน bootloader ไม่สามารถใส่ skip_initramfs ตัวเลือกในบรรทัดคำสั่งเคอร์เนล

สำหรับการอัพเดตที่ไม่ใช่ A/B พาร์ติชั่นการกู้คืนจะมีรหัสที่ใช้ในการอัพเดต ปรับปรุง / B จะถูกนำมาใช้โดย update_engine ทำงานในระบบภาพบูตปกติ ยังคงมีโหมดการกู้คืนที่ใช้ในการดำเนินการรีเซ็ตข้อมูลเป็นค่าเริ่มต้นและไซด์โหลดของแพ็คเกจการอัปเดต (ซึ่งเป็นที่มาของชื่อ "การกู้คืน") รหัสและข้อมูลสำหรับโหมดการกู้คืนถูกเก็บไว้ในพาร์ติชันสำหรับเริ่มระบบปกติใน ramdisk ในการบูตเข้าสู่อิมเมจระบบ bootloader จะบอกเคอร์เนลให้ข้าม ramdisk (มิฉะนั้นอุปกรณ์จะบู๊ตเข้าสู่โหมดการกู้คืน โหมดการกู้คืนมีขนาดเล็ก (และส่วนใหญ่อยู่ในพาร์ติชันสำหรับเริ่มระบบแล้ว) ดังนั้นพาร์ติชันสำหรับเริ่มระบบจึงไม่เพิ่มขึ้น ในขนาด.

Fstab

slotselect อาร์กิวเมนต์ต้องจะอยู่ในบรรทัดสำหรับพาร์ทิชัน / B-ed ตัวอย่างเช่น:

<path-to-block-device>/vendor  /vendor  ext4  ro
wait,verify=<path-to-block-device>/metadata,slotselect

พาร์ทิชันไม่ควรตั้งชื่อ vendor แต่พาร์ทิชัน vendor_a หรือ vendor_b จะถูกเลือกและติดตั้งอยู่บน /vendor ติดจุด

อาร์กิวเมนต์สล็อตเคอร์เนล

ต่อท้ายสล็อตปัจจุบันควรจะผ่านทั้งผ่านต้นไม้อุปกรณ์ที่เฉพาะเจาะจง (DT) โหนด ( /firmware/android/slot_suffix ) หรือผ่าน androidboot.slot_suffix เคอร์เนลบรรทัดคำสั่งหรือ bootconfig โต้แย้ง

โดยค่าเริ่มต้น fastboot จะกะพริบช่องปัจจุบันบนอุปกรณ์ A/B หากแพ็คเกจการอัพเดทยังมีอิมเมจสำหรับสล็อตอื่นที่ไม่ใช่สล็อตปัจจุบัน fastboot จะแฟลชอิมเมจเหล่านั้นด้วย ตัวเลือกที่มีจำหน่าย ได้แก่ :

  • --slot SLOT แทนที่การทำงานเริ่มต้นและพร้อมต์ให้ fastboot เพื่อแฟลชสล็อตที่ส่งผ่านเป็นอาร์กิวเมนต์
  • --set-active [ SLOT ] ตั้งค่าช่องเป็นใช้งานอยู่ หากไม่มีการระบุอาร์กิวเมนต์ที่เป็นทางเลือก ช่องปัจจุบันจะถูกตั้งค่าเป็นแอ็คทีฟ
  • fastboot --help รับรายละเอียดเกี่ยวกับคำสั่ง

ถ้า bootloader ดำเนิน fastboot ก็ควรสนับสนุนคำสั่ง set_active <slot> ว่าชุดช่องเสียบที่ใช้งานอยู่ในปัจจุบันในช่องที่กำหนด (นี้ยังต้องล้างธง unbootable สำหรับช่องที่และการตั้งค่าการนับลองใหม่อีกครั้งเป็นค่าเริ่มต้น) 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 / บี เครื่องมือแพ็คเกจ 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 ของผลิตภัณฑ์):

  1. รวมส่วนประกอบดั้งเดิมในบิลด์เพื่อให้แน่ใจว่าคอมไพล์สคริปต์และไบนารีได้รับการคอมไพล์และรวมอยู่ในอิมเมจระบบ
      # A/B OTA dexopt package
      PRODUCT_PACKAGES += otapreopt_script
    
  2. เชื่อมต่อสคริปต์รวบรวมเพื่อ 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
    

สำหรับความช่วยเหลือในการติดตั้งไฟล์ preopted ในพาร์ทิชันระบบที่สองที่ไม่ได้ใช้หมายถึง การติดตั้งบูตแรกของไฟล์ DEX_PREOPT