日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > Android >内容正文

Android

android动态分区AB升级,Android A/B System OTA分析(四)系统的启动和升级

發布時間:2023/12/8 Android 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 android动态分区AB升级,Android A/B System OTA分析(四)系统的启动和升级 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

Android從7.0開始引入新的OTA升級方式,A/B System Updates,這里將其叫做A/B系統,涉及的內容較多,分多篇對A/B系統的各個方面進行分析。本文為第四篇,系統的啟動和升級。

本文基于AOSP 7.1.1_r23 (NMF27D)代碼進行分析。

1. 系統的啟動

1.1 bootloader檢查slot metadata

系統復位后,bootloader會去讀取boot_control私有的存儲數slot metadata并進行解析,以此確定從哪一個slot啟動。

以下是Android官方的一個bootloader加載流程圖:

1.2 linux系統的啟動

上一步中,bootloader會根據slot metadata確定讀取哪一個slot的boot分區進行啟動。

每一個slot上有兩個rootfs:

boot分區自帶recovery mode的ramdisk;

system分區包含了Android系統的rootfs;

啟動中,如何選擇加載boot分區的ramdisk還是system分區的rootfs呢?

答案是由kernel的命令行參數skip_initramfs來決定。

下面來看skip_initramfs參數是如何起作用的。

系統同時包含init\noinitramfs.c和init\initramfs.c的代碼,并在initramfs.c模塊中定義并解析skip_initramfs參數:

# init\initramfs.c

static int __initdata do_skip_initramfs;

static int __init skip_initramfs_param(char *str)

{

if (*str)

return 0;

# 設置do_skip_initramfs標志

do_skip_initramfs = 1;

return 1;

}

# 用于解析命令行的`skip_initramfs`參數

__setup("skip_initramfs", skip_initramfs_param);

如果命令行設置了skip_initramfs,則do_skip_initramfs會被設置為1。

linux調用populate_rootfs默認會并加載boot分區自帶的ramdisk,但如果do_skip_initramfs被

設置為1,則調用default_rootfs生成一個極小的rootfs:

# init\initramfs.c

static int __init populate_rootfs(void)

{

char *err;

# 如果do_skip_initramfs置1,則調用default_rootfs生成一個極小的rootfs

if (do_skip_initramfs)

return default_rootfs();

# 沒有設置do_skip_initramfs的情況下,才會解析并加載`boot`分區所包含的`ramdisk`

err = unpack_to_rootfs(__initramfs_start, __initramfs_size);

if (err)

panic("%s", err); /* Failed to decompress INTERNAL initramfs */

...

return 0;

}

default_rootfs的內容很簡單,用于在內存中生成一個極小的rootfs,僅包含/dev和root兩個文件夾以及一個設備節點/dev/console:

# init\noinitramfs.c

/*

* Create a simple rootfs that is similar to the default initramfs

*/

static int __init default_rootfs(void)

{

int err;

# 創建/dev文件夾用于存放/dev/console設備節點

err = sys_mkdir((const char __user __force *) "/dev", 0755);

if (err < 0)

goto out;

# 創建/dev/console設備節點

err = sys_mknod((const char __user __force *) "/dev/console",

S_IFCHR | S_IRUSR | S_IWUSR,

new_encode_dev(MKDEV(5, 1)));

if (err < 0)

goto out;

# 創建/root目錄,作為根用戶root的home

err = sys_mkdir((const char __user __force *) "/root", 0700);

if (err < 0)

goto out;

return 0;

out:

printk(KERN_WARNING "Failed to create a rootfs\n");

return err;

}

因此skip_initramfs參數決定了加載哪一個rootfs,進入哪一個系統。

加載android系統的命令行參數

skip_initramfs rootwait ro init=/init root="/dev/dm-0 dm=system none ro,0 1 android-verity "

例如Broadcom的7252SSFFDR3參考平臺的啟動Android系統的參數為:

mem=1016m@0m mem=1024m@2048m bmem=339m@669m bmem=237m@2048m \

brcm_cma=784m@2288m \

ramoops.mem_address=0x3F800000 ramoops.mem_size=0x800000 ramoops.console_size=0x400000 \

buildvariant=userdebug \

veritykeyid=id:7e4333f9bba00adfe0ede979e28ed1920492b40f buildvariant=eng \

rootwait init=/init ro \

root=/dev/dm-0 dm="system none ro,0 1 android-verity PARTUUID=c49e0acb-1b38-95e5-548a-2b7260e704a4" skip_initramfs

除去rootfs不相關的參數,看起來是這樣的:

rootwait init=/init ro root=/dev/dm-0 dm="system none ro,0 1 android-verity PARTUUID=c49e0acb-1b38-95e5-548a-2b7260e704a4" skip_initramfs

命令行中,文件系統的root設備由參數root="/dev/dm-0 dm=system none ro,0 1 android-verity "指定,顯然,這里的root參數設置將設備名設置為/dev/dm-0,至于設備/dev/dm-0是一個什么設備,作用為何,屬于另一個話題dm-verity,此處不再展開討論。

加載recovery系統的命令行參數

rootwait init=/init ro

例如Broadcom的7252SSFFDR3參考平臺的啟動Recovery的參數為:

mem=1016m@0m mem=1024m@2048m bmem=339m@669m bmem=237m@2048m \

brcm_cma=784m@2288m \

ramoops.mem_address=0x3F800000 ramoops.mem_size=0x800000 ramoops.console_size=0x400000 \

rootwait init=/init ro \

buildvariant=userdebug veritykeyid=id:7e4333f9bba00adfe0ede979e28ed1920492b40f buildvariant=eng

除去rootfs不相關的參數,看起來是這樣的:

rootwait init=/init ro

1.3 Android系統的啟動

linux啟動后,通過dm-verify機制校驗system分區,完成后加載system分區內包含的rootfs,通過/init程序解析/init.rc腳本,完成Android系統的啟動。

這部分的啟動過程跟傳統的系統啟動是一樣的。

1.4 Recovery系統的啟動

linux啟動后,根據參數,加載boot分區的ramdisk,通過/init程序解析/init.rc腳本,啟動Recovery系統。

這部分的啟動過程跟傳統的Recovery系統啟動是一樣的。

2. 系統的升級

A/B系統升級包的制作方式跟傳統系統升級包制作方式基本一致,主要分為兩步:

編譯系統文件

制作升級包

升級方式根據升級包的內容分為兩種:

完整升級,升級包包含完整的系統,對內容進行全新升級;

增量升級/差分升級,升級包僅包含跟當前系統不一樣的內容,對系統進行打補丁式升級;

2.1 完整升級

升級包的制作

第一步,編譯系統

$ source build/envsetup.sh

$ lunch bcm7252ssffdr4-userdebug

$ mkdir dist_output

$ make -j32 dist DIST_DIR=dist_output

[...]

$ ls -lh dist-output/*target_files*

-rw-r--r-- 1 ygu users 566M May 21 14:49 bcm7252ssffdr4-target_files-eng.ygu.zip

第二步,制作安裝包

$ ./build/tools/releasetools/ota_from_target_files dist-output/bcm7252ssffdr4-target_files-eng.ygu.zip full-ota.zip

$ ls -lh dist-output

-rw-r--r-- 1 ygu users 270M May 21 14:51 full-ota.zip

升級包的內容

解壓縮full-ota.zip可以看到其內容:

$ mkdir full-ota

$ unzip full-ota.zip -d full-ota

Archive: full-ota.zip

signed by SignApk

extracting: full-ota/payload.bin

inflating: full-ota/META-INF/com/android/metadata

inflating: full-ota/care_map.txt

inflating: full-ota/payload_properties.txt

inflating: full-ota/META-INF/com/android/otacert

inflating: full-ota/META-INF/MANIFEST.MF

inflating: full-ota/META-INF/CERT.SF

inflating: full-ota/META-INF/CERT.RSA

$ ls -lh full-ota

total 270M

drwxr-sr-x 3 ygu users 4.0K May 21 18:14 META-INF

-rw-r--r-- 1 ygu users 36 Jan 1 2009 care_map.txt

-rw-r--r-- 1 ygu users 270M Jan 1 2009 payload.bin

-rw-r--r-- 1 ygu users 154 Jan 1 2009 payload_properties.txt

$ tree -l full-ota

full-ota

|-- META-INF

| |-- CERT.RSA

| |-- CERT.SF

| |-- MANIFEST.MF

| `-- com

| `-- android

| |-- metadata

| `-- otacert

|-- care_map.txt

|-- payload.bin

`-- payload_properties.txt

3 directories, 8 files

其中,payload.bin是系統要更新的數據文件,payload_properties.txt包含了升級內容的一些屬性信息,如下:

$ cat full-ota/payload_properties.txt

FILE_HASH=ozGgyQEcnkI5ZaX+Wbjo5I/PCR7PEZka9fGd0nWa+oY=

FILE_SIZE=282164983

METADATA_HASH=GLIKfE6KRwylWMHsNadG/Q8iy5f7ENWTatvMdBlpoPg=

METADATA_SIZE=21023

升級時會使用到payload_properties.txt里面的信息。

系統包的使用

A/B系統在debug模式下會包含升級應用update_engine_client,其參數如下:

bcm7252ssffdr4:/ # which update_engine_client

/system/bin/update_engine_client

bcm7252ssffdr4:/ # update_engine_client --help

Android Update Engine Client

--cancel (Cancel the ongoing update and exit.) type: bool default: false

--follow (Follow status update changes until a final state is reached. Exit status is 0 if the update succeeded, and 1 otherwise.) type: bool default: false

--headers (A list of key-value pairs, one element of the list per line. Used when --update is passed.) type: string default: ""

--help (Show this help message) type: bool default: false

--offset (The offset in the payload where the CrAU update starts. Used when --update is passed.) type: int64 default: 0

--payload (The URI to the update payload to use.) type: string default: "http://127.0.0.1:8080/payload"

--reset_status (Reset an already applied update and exit.) type: bool default: false

--resume (Resume a suspended update.) type: bool default: false

--size (The size of the CrAU part of the payload. If 0 is passed, it will be autodetected. Used when --update is passed.) type: int64 default: 0

--suspend (Suspend an ongoing update and exit.) type: bool default: false

--update (Start a new update, if no update in progress.) type: bool default: false

將payload.bin文件放到可以通過http訪問的地方,然后在命令行調用update_engine_client進行升級:

bcm7252ssffdr4:/ # update_engine_client \

--payload=http://stbszx-bld-5/public/android/full-ota/payload.bin \

--update \

--headers="\

FILE_HASH=ozGgyQEcnkI5ZaX+Wbjo5I/PCR7PEZka9fGd0nWa+oY= \

FILE_SIZE=282164983

METADATA_HASH=GLIKfE6KRwylWMHsNadG/Q8iy5f7ENWTatvMdBlpoPg= \

METADATA_SIZE=21023 \

"

其中headers選項需要填寫payload_properties.txt文件的內容。

2.2 增量升級/差分升級

差分包升級與完整包升級除了升級包的制作不一樣之外,生成的升級包文件內容一樣,使用update_engine_client進行升級的操作也完全一樣,因此這里僅說明差分包的制作。

差分升級包的制作

第一步,對android進行改動并編譯系統

差分升級時,需要保留原有系統的生成文件,然后修改后生成新的系統文件,這里假定原有系統生成文件位于:dist_output,修改后生成的系統文件位于dist_output-new,編譯方式跟完整包的生成方式一樣。

$ source build/envsetup.sh

$ lunch bcm7252ssffdr4-userdebug

$ mkdir dist_output

$ make -j32 dist DIST_DIR=dist_output

[...]

$ ls -lh dist-output-new/*target_files*

-rw-r--r-- 1 ygu users 566M May 21 15:27 bcm7252ssffdr4-target_files-eng.ygu.zip

第二步,制作安裝包

對比原有系統文件和修改后的系統文件生成差分包,這里通過-i指定差分包生成的基線(baseline)。

$./build/tools/releasetools/ota_from_target_files \

-i dist-output/bcm7252ssffdr4-target_files-eng.ygu.zip \

dist-output-new/bcm7252ssffdr4-target_files-eng.ygu.zip \

incremental-ota.zip

2.3 升級日志樣本

調用update_engine_client進行升級后可以通過logcat查看其升級日志,如:

bcm7252ssffdr4:/ # update_engine_client \

--payload=http://stbszx-bld-5/public/android/full-ota/payload.bin \

--update \

--headers="\

FILE_HASH=ozGgyQEcnkI5ZaX+Wbjo5I/PCR7PEZka9fGd0nWa+oY= \

FILE_SIZE=282164983 \

METADATA_HASH=GLIKfE6KRwylWMHsNadG/Q8iy5f7ENWTatvMdBlpoPg= \

METADATA_SIZE=21023 \

"

bcm7252ssffdr4:/ #

bcm7252ssffdr4:/ # logcat -s update_engine:v

--------- beginning of main

--------- beginning of system

I update_engine: [INFO:main.cc(113)] Chrome OS Update Engine starting

I update_engine: [INFO:boot_control_android.cc(78)] Loaded boot_control HAL 'boot control hal for bcm platform' version 0.1 authored by 'Broadcom'.

I update_engine: [INFO:daemon_state_android.cc(43)] Booted in dev mode.

I update_engine: [INFO:update_attempter_android.cc(199)] Using this install plan:

I update_engine: [INFO:install_plan.cc(71)] InstallPlan: new_update, payload type: unknown, source_slot: A, target_slot: B, url: http://stbszx-bld-5/public/android/full-ota/payload.bin, payload size: 282164983, payload hash: ozGgyQEcnkI5ZaX+Wbjo5I/PCR7PEZka9fGd0nWa+oY=, metadata size: 21023, metadata signature: , hash_checks_mandatory: true, powerwash_required: false

W update_engine: [WARNING:hardware_android.cc(126)] STUB: Assuming OOBE is complete.

I update_engine: [INFO:cpu_limiter.cc(71)] Setting cgroup cpu shares to 2

E update_engine: [ERROR:utils.cc(199)] 0 == writer.Open(path, O_WRONLY | O_CREAT | O_TRUNC, 0600) failed: No such file or directory

E update_engine: [ERROR:cpu_limiter.cc(74)] Failed to change cgroup cpu shares to 2 using /sys/fs/cgroup/cpu/update-engine/cpu.shares

I update_engine: [INFO:update_attempter_android.cc(379)] Marking booted slot as good.

I update_engine: [INFO:update_attempter_android.cc(394)] Scheduling an action processor start.

I update_engine: [INFO:action_processor.cc(46)] ActionProcessor: starting InstallPlanAction

I update_engine: [INFO:action_processor.cc(116)] ActionProcessor: finished InstallPlanAction with code ErrorCode::kSuccess

I update_engine: [INFO:action_processor.cc(143)] ActionProcessor: starting DownloadAction

I update_engine: [INFO:install_plan.cc(71)] InstallPlan: new_update, payload type: unknown, source_slot: A, target_slot: B, url: http://stbszx-bld-5/public/android/full-ota/payload.bin, payload size: 282164983, payload hash: ozGgyQEcnkI5ZaX+Wbjo5I/PCR7PEZka9fGd0nWa+oY=, metadata size: 21023, metadata signature: , hash_checks_mandatory: true, powerwash_required: false

I update_engine: [INFO:download_action.cc(178)] Marking new slot as unbootable

I update_engine: [INFO:multi_range_http_fetcher.cc(45)] starting first transfer

I update_engine: [INFO:multi_range_http_fetcher.cc(73)] starting transfer of range 0+282164983

I update_engine: [INFO:libcurl_http_fetcher.cc(94)] Starting/Resuming transfer

I update_engine: [INFO:libcurl_http_fetcher.cc(106)] Using proxy: no

I update_engine: [INFO:libcurl_http_fetcher.cc(237)] Setting up curl options for HTTP

I update_engine: [INFO:delta_performer.cc(196)] Completed 0/? operations, 14169/282164983 bytes downloaded (0%), overall progress 0%

I update_engine: [INFO:delta_performer.cc(536)] Manifest size in payload matches expected value from Omaha

I update_engine: [INFO:delta_performer.cc(1396)] Verifying metadata hash signature using public key: /etc/update_engine/update-payload-key.pub.pem

I update_engine: [INFO:payload_verifier.cc(93)] signature blob size = 264

I update_engine: [INFO:payload_verifier.cc(112)] Verified correct signature 1 out of 1 signatures.

I update_engine: [INFO:delta_performer.cc(1439)] Metadata hash signature matches value in Omaha response.

I update_engine: [INFO:delta_performer.cc(1459)] Detected a 'full' payload.

I update_engine: [INFO:delta_performer.cc(374)] PartitionInfo old boot sha256: size: 0

I update_engine: [INFO:delta_performer.cc(374)] PartitionInfo new boot sha256: dZpLY9KsQYa2B14B0oBzfUKxVFIH7ocbgT70JavheSc= size: 19480576

I update_engine: [INFO:delta_performer.cc(374)] PartitionInfo old system sha256: size: 0

I update_engine: [INFO:delta_performer.cc(374)] PartitionInfo new system sha256: kFXbYzaM47PifNjuL+Plz1zTMEp1MoajOuXZuCh9yw0= size: 769654784

I update_engine: [INFO:delta_performer.cc(359)] Applying 10 operations to partition "boot"

I update_engine: [INFO:delta_performer.cc(647)] Starting to apply update payload operations

I update_engine: [INFO:delta_performer.cc(359)] Applying 367 operations to partition "system"

I update_engine: [INFO:delta_performer.cc(196)] Completed 23/377 operations (6%), 40302425/282164983 bytes downloaded (14%), overall progress 10%

I update_engine: [INFO:delta_performer.cc(196)] Completed 48/377 operations (12%), 79017817/282164983 bytes downloaded (28%), overall progress 20%

I update_engine: [INFO:delta_performer.cc(196)] Completed 74/377 operations (19%), 118519641/282164983 bytes downloaded (42%), overall progress 30%

I update_engine: [INFO:delta_performer.cc(196)] Completed 98/377 operations (25%), 158021465/282164983 bytes downloaded (56%), overall progress 40%

I update_engine: [INFO:delta_performer.cc(196)] Completed 121/377 operations (32%), 192001881/282164983 bytes downloaded (68%), overall progress 50%

I update_engine: [INFO:delta_performer.cc(196)] Completed 145/377 operations (38%), 231389017/282164983 bytes downloaded (82%), overall progress 60%

I update_engine: [INFO:delta_performer.cc(196)] Completed 171/377 operations (45%), 270890841/282164983 bytes downloaded (96%), overall progress 70%

I update_engine: [INFO:delta_performer.cc(196)] Completed 242/377 operations (64%), 273413977/282164983 bytes downloaded (96%), overall progress 80%

I update_engine: [INFO:delta_performer.cc(196)] Completed 317/377 operations (84%), 273430361/282164983 bytes downloaded (96%), overall progress 90%

I update_engine: [INFO:delta_performer.cc(196)] Completed 377/377 operations (100%), 282164983/282164983 bytes downloaded (100%), overall progress 100%

I update_engine: [INFO:delta_performer.cc(1336)] Extracted signature data of size 264 at 282143432

I update_engine: [INFO:multi_range_http_fetcher.cc(111)] terminating transfer

I update_engine: [INFO:multi_range_http_fetcher.cc(171)] Received transfer terminated.

I update_engine: [INFO:multi_range_http_fetcher.cc(123)] TransferEnded w/ code 206

I update_engine: [INFO:multi_range_http_fetcher.cc(157)] Done w/ all transfers

I update_engine: [INFO:delta_performer.cc(1596)] Verifying payload using public key: /etc/update_engine/update-payload-key.pub.pem

I update_engine: [INFO:payload_verifier.cc(93)] signature blob size = 264

I update_engine: [INFO:payload_verifier.cc(112)] Verified correct signature 1 out of 1 signatures.

I update_engine: [INFO:delta_performer.cc(1633)] Payload hash matches value in payload.

I update_engine: [INFO:action_processor.cc(116)] ActionProcessor: finished DownloadAction with code ErrorCode::kSuccess

I update_engine: [INFO:action_processor.cc(143)] ActionProcessor: starting FilesystemVerifierAction

I update_engine: [INFO:filesystem_verifier_action.cc(157)] Hashing partition 0 (boot) on device /dev/block/by-name/boot_e

I update_engine: [INFO:filesystem_verifier_action.cc(248)] Hash of boot: dZpLY9KsQYa2B14B0oBzfUKxVFIH7ocbgT70JavheSc=

I update_engine: [INFO:filesystem_verifier_action.cc(157)] Hashing partition 1 (system) on device /dev/block/by-name/system_e

I update_engine: [INFO:filesystem_verifier_action.cc(248)] Hash of system: kFXbYzaM47PifNjuL+Plz1zTMEp1MoajOuXZuCh9yw0=

I update_engine: [INFO:action_processor.cc(116)] ActionProcessor: finished FilesystemVerifierAction with code ErrorCode::kSuccess

I update_engine: [INFO:action_processor.cc(143)] ActionProcessor: starting PostinstallRunnerAction

I update_engine: [INFO:postinstall_runner_action.cc(341)] All post-install commands succeeded

I update_engine: [INFO:action_processor.cc(116)] ActionProcessor: finished last action PostinstallRunnerAction with code ErrorCode::kSuccess

I update_engine: [INFO:update_attempter_android.cc(282)] Processing Done.

I update_engine: [INFO:update_attempter_android.cc(291)] Update successfully applied, waiting to reboot.

以上logcat信息已經去掉了時間戳,原始的log信息請參考:update_engine_client log

update_engine更新操作成功后會提示Update successfully applied, waiting to reboot.,要求系統進行重啟,重啟后會設置相應分區slot的屬性為successful,表明系統能夠成功啟動。

重啟系統,檢查Android系統的編譯版本和時間戳,驗證升級是否成功。

總結

以上是生活随笔為你收集整理的android动态分区AB升级,Android A/B System OTA分析(四)系统的启动和升级的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。