從 Android 10(Q) 開始,引入了動態(tài)分區(qū),伴隨的就是一組動態(tài)分區(qū)內(nèi)容數(shù)據(jù)增刪改查相關(guān)的操作,以及這些操作所需要的工具,包括 lpdump, lpmake, lpunpack, lpadd, lpflash。
工具名稱前綴 lp 表示是 logic partition,即邏輯分區(qū)。
所謂邏輯分區(qū),是相對于物理分區(qū)而言,因?yàn)閯討B(tài)分區(qū)內(nèi)部的各種分區(qū)并不是實(shí)際的物理分區(qū)。
因此,可以說動態(tài)分區(qū)本身的 super 是物理分區(qū),但 super 內(nèi)包含的各種分區(qū)就是邏輯分區(qū)。
前面兩篇分別介紹了 lpdump 和 lpmake,本篇介紹 lpunpack。
本文基于 android-13.0.0_r41 編譯生成的 lpunpack 介紹該工具的使用,但也適用于 Android 10(Q) 開始的其它 Android 版本。
《Android OTA 相關(guān)工具》系列,目前已有文章列表:
- 《Android OTA 相關(guān)工具(一) 虛擬 A/B 之 snapshotctl》
- 《Android OTA 相關(guān)工具(二) 動態(tài)分區(qū)之 dmctl》
- 《Android OTA 相關(guān)工具(三) A/B 系統(tǒng)之 bootctl 工具》
- 《Android OTA 相關(guān)工具(四) 查看 payload 文件信息》
- 《Android OTA 相關(guān)工具(五) 使用 lpdump 查看動態(tài)分區(qū)》
- 《Android OTA 相關(guān)工具(六) 使用 lpmake 打包生成 super.img》
- 《Android OTA 相關(guān)工具(七) 使用 lpunpack 解包 super.img》
本文為洛奇看世界(guyongqiangx)原創(chuàng),轉(zhuǎn)載請注明出處。
文章鏈接:https://blog.csdn.net/guyongqiangx/article/details/132598451
1. lpunpack 的編譯
lpmake 工具從 Android Q 版代碼開始引入,源碼位于 system/extras/partition_tools
目錄下,默認(rèn)編譯 Android 后輸出到 out/host/linux-x86/bin/lpmake
,第一次編譯以后,通過 source 和 lunch 操作設(shè)置 Android 編譯環(huán)境后就可以引用。
例如:
$ source build/envsetup.sh
$ lunch aosp_panther-userdebug
$ which lpunpack
/public/rocky/android-13.0.0_r41/out/host/linux-x86/bin/lpunpack
當(dāng)然,也可以將 out/host/linux-x86/bin
添加到當(dāng)前目錄下使用:
$ echo $PATH
/home/rocky/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
$ export PATH=${PWD}/out/host/linux-x86/bin:$PATH
$ echo $PATH
/public/rocky/android-13.0.0_r41/out/host/linux-x86/bin:/home/rocky/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
$ which lpunpack
/public/rocky/android-13.0.0_r41/out/host/linux-x86/bin/lpunpack
兩種方式都差不多,不過個人推薦前者。
2. lpunpack 的幫助信息
lpunpack 的幫助信息非常簡單:
android-13.0.0_r41$ lpunpack -h
lpunpack - command-line tool for extracting partition images from super
Usage:
lpunpack [options...] SUPER_IMAGE [OUTPUT_DIR]
Options:
-p, --partition=NAME Extract the named partition. This can
be specified multiple times.
-S, --slot=NUM Slot number (default is 0).
直接將 raw 格式的 super 鏡像解包到指定的輸出目錄。
lpunpack 不能識別 sparse 鏡像格式,所以如果 super.img 是 sparse 格式,則需要先將其轉(zhuǎn)換成 raw 格式。
有兩個可選參數(shù)"–partition" 和 “–slot”,分別用于指定提取鏡像的分區(qū)名稱(name)和槽位(slot),如果沒有提供選項(xiàng)參數(shù),則默認(rèn)提取所有存在的分區(qū)鏡像。
3. lpunpack 的用法
從上一節(jié)的幫助信息可以看到,lpunpack 的用法比較簡單,主要分成兩步:
- 將 sparse 格式的 super.img 轉(zhuǎn)換成 raw 格式
- 提取 raw 格式的 super.img 內(nèi)部的分區(qū)鏡像
這里以 android-13.0.0_r41 代碼編譯參考設(shè)備 panther 得到的 super.img 為例演示 lpunpack 的操作
準(zhǔn)備工作:
# 設(shè)置環(huán)境
$ source build/envsetup.sh
$ lunch aosp_panther-userdebug
# 編譯 dist 輸出
$ make dist -j80
# 查找系統(tǒng)的 super.img 鏡像
$ find out -type f -name super.img
out/target/product/panther/obj/PACKAGING/super.img_intermediates/super.img
out/dist/super.img
# 把 dist 下的 sparse 格式的 super.img 轉(zhuǎn)換成 raw 格式
$ file out/dist/super.img
out/dist/super.img: Android sparse image, version: 1.0, Total of 2082816 4096-byte output blocks in 159 input chunks.
# 使用 simg2img 將 sparse 格式轉(zhuǎn)換成 raw 格式
$ simg2img out/dist/super.img super_raw.img
# 查看 super 分區(qū)的信息
$ lpdump super_raw.img
Slot 0:
Metadata version: 10.2
Metadata size: 1256 bytes
Metadata max size: 65536 bytes
Metadata slot count: 3
Header flags: virtual_ab_device
Partition table:
------------------------
Name: system_a
Group: google_dynamic_partitions_a
Attributes: readonly
Extents:
0 .. 1732063 linear super 2048
------------------------
Name: system_b
Group: google_dynamic_partitions_b
Attributes: readonly
Extents:
0 .. 53343 linear super 1734656
------------------------
Name: system_dlkm_a
Group: google_dynamic_partitions_a
Attributes: readonly
Extents:
0 .. 679 linear super 1789952
------------------------
Name: system_dlkm_b
Group: google_dynamic_partitions_b
Attributes: readonly
Extents:
------------------------
Name: system_ext_a
Group: google_dynamic_partitions_a
Attributes: readonly
Extents:
0 .. 588663 linear super 1792000
------------------------
Name: system_ext_b
Group: google_dynamic_partitions_b
Attributes: readonly
Extents:
------------------------
Name: product_a
Group: google_dynamic_partitions_a
Attributes: readonly
Extents:
0 .. 718839 linear super 2381824
------------------------
Name: product_b
Group: google_dynamic_partitions_b
Attributes: readonly
Extents:
------------------------
Name: vendor_a
Group: google_dynamic_partitions_a
Attributes: readonly
Extents:
0 .. 1214359 linear super 3100672
------------------------
Name: vendor_b
Group: google_dynamic_partitions_b
Attributes: readonly
Extents:
------------------------
Name: vendor_dlkm_a
Group: google_dynamic_partitions_a
Attributes: readonly
Extents:
0 .. 84063 linear super 4315136
------------------------
Name: vendor_dlkm_b
Group: google_dynamic_partitions_b
Attributes: readonly
Extents:
------------------------
Super partition layout:
------------------------
super: 2048 .. 1734112: system_a (1732064 sectors)
super: 1734656 .. 1788000: system_b (53344 sectors)
super: 1789952 .. 1790632: system_dlkm_a (680 sectors)
super: 1792000 .. 2380664: system_ext_a (588664 sectors)
super: 2381824 .. 3100664: product_a (718840 sectors)
super: 3100672 .. 4315032: vendor_a (1214360 sectors)
super: 4315136 .. 4399200: vendor_dlkm_a (84064 sectors)
------------------------
Block device table:
------------------------
Partition name: super
First sector: 2048
Size: 8531214336 bytes
Flags: none
------------------------
Group table:
------------------------
Name: default
Maximum size: 0 bytes
Flags: none
------------------------
Name: google_dynamic_partitions_a
Maximum size: 8527020032 bytes
Flags: none
------------------------
Name: google_dynamic_partitions_b
Maximum size: 8527020032 bytes
Flags: none
------------------------
總結(jié)下 super 分區(qū)內(nèi)的鏡像內(nèi)容:
- 槽位 A 中包含 system_a, system_dlkm_a, system_ext_a, product_a, vendor_a 和 vendor_dlkm_a 鏡像
- 槽位 B 中包含 system_b 鏡像(大小和 system_a 的鏡像不一樣)
關(guān)于如何下載 Android 代碼并基于 Google 官方的參考設(shè)備進(jìn)行編譯,請參考:
《如何下載和編譯 Android 源碼?》
3.1 解包所有鏡像
不帶參數(shù)解包所有分區(qū)鏡像。
$ mkdir temp
$ lpunpack super_raw.img temp/
$ ls -lh temp/
total 2.1G
-rw-r--r-- 1 rocky users 351M Aug 29 14:09 product_a.img
-rw-r--r-- 1 rocky users 0 Aug 29 14:09 product_b.img
-rw-r--r-- 1 rocky users 846M Aug 29 14:09 system_a.img
-rw-r--r-- 1 rocky users 27M Aug 29 14:09 system_b.img
-rw-r--r-- 1 rocky users 340K Aug 29 14:09 system_dlkm_a.img
-rw-r--r-- 1 rocky users 0 Aug 29 14:09 system_dlkm_b.img
-rw-r--r-- 1 rocky users 288M Aug 29 14:09 system_ext_a.img
-rw-r--r-- 1 rocky users 0 Aug 29 14:09 system_ext_b.img
-rw-r--r-- 1 rocky users 593M Aug 29 14:09 vendor_a.img
-rw-r--r-- 1 rocky users 0 Aug 29 14:09 vendor_b.img
-rw-r--r-- 1 rocky users 42M Aug 29 14:09 vendor_dlkm_a.img
-rw-r--r-- 1 rocky users 0 Aug 29 14:09 vendor_dlkm_b.img
3.2 解包指定名稱分區(qū)鏡像
使用 “-p” 參數(shù)解包單個分區(qū) system_a 的鏡像:
$ rm -rf temp/*
$ lpunpack -p system_a super_raw.img temp/
$ ls -lh temp/
total 843M
-rw-r--r-- 1 rocky users 846M Aug 30 19:48 system_a.img
使用多個 “-p” 參數(shù)解包多個分區(qū)(system_a 和 vendor_a)鏡像:
$ rm -rf temp/*
$ lpunpack -p system_a -p vendor_a super_raw.img temp/
$ ls -lh temp/
total 1.5G
-rw-r--r-- 1 rocky users 846M Aug 30 19:50 system_a.img
-rw-r--r-- 1 rocky users 593M Aug 30 19:50 vendor_a.img
3.3 解包指定槽位分區(qū)鏡像
根據(jù) help 信息,可以使用 “-S”/“–slot” 選項(xiàng)指定槽位,解包單個槽位鏡像。
但必須吐槽一下這個選項(xiàng),Bug 叢生。
槽點(diǎn) 1:使用 “-S”(大寫) 選項(xiàng),提示不認(rèn)識 “-S” 選項(xiàng)
android-13.0.0_r41$ lpunpack -S 1 super_raw.img temp
lpunpack: unrecognized option '-S'
Unrecognized argument.
lpunpack - command-line tool for extracting partition images from super
Usage:
lpunpack [options...] SUPER_IMAGE [OUTPUT_DIR]
Options:
-p, --partition=NAME Extract the named partition. This can
be specified multiple times.
-S, --slot=NUM Slot number (default is 0).
槽點(diǎn) 2:使用 “-s”(小寫) 選項(xiàng),提示不認(rèn)識的參數(shù)
android-13.0.0_r41$ lpunpack -s 1 super_raw.img temp
Unrecognized command-line arguments.
lpunpack - command-line tool for extracting partition images from super
Usage:
lpunpack [options...] SUPER_IMAGE [OUTPUT_DIR]
Options:
-p, --partition=NAME Extract the named partition. This can
be specified multiple times.
-S, --slot=NUM Slot number (default is 0).
槽點(diǎn) 3: 使用 “–slot 1” 選項(xiàng)提取槽位 1 的分區(qū)鏡像,但實(shí)際上兩個槽位的 image 都提取出來了
android-13.0.0_r41$ rm -rf temp/*
android-13.0.0_r41$ lpunpack --slot 1 super_raw.img temp/
android-13.0.0_r41$ ls -lh temp/
total 2.1G
-rw-r--r-- 1 rocky users 351M Aug 31 10:11 product_a.img
-rw-r--r-- 1 rocky users 0 Aug 31 10:11 product_b.img
-rw-r--r-- 1 rocky users 846M Aug 31 10:11 system_a.img
-rw-r--r-- 1 rocky users 27M Aug 31 10:11 system_b.img
-rw-r--r-- 1 rocky users 340K Aug 31 10:11 system_dlkm_a.img
-rw-r--r-- 1 rocky users 0 Aug 31 10:11 system_dlkm_b.img
-rw-r--r-- 1 rocky users 288M Aug 31 10:11 system_ext_a.img
-rw-r--r-- 1 rocky users 0 Aug 31 10:11 system_ext_b.img
-rw-r--r-- 1 rocky users 593M Aug 31 10:11 vendor_a.img
-rw-r--r-- 1 rocky users 0 Aug 31 10:11 vendor_b.img
-rw-r--r-- 1 rocky users 42M Aug 31 10:11 vendor_dlkm_a.img
-rw-r--r-- 1 rocky users 0 Aug 31 10:11 vendor_dlkm_b.img
沒想到這個 lpunpack 工具已經(jīng)提供好幾年了,lpunpack 竟然還有問題。
好吧,那就只能去改下代碼了。
如果你需要指定槽位操作的話,可能需要修改下代碼,以下代碼僅供參考:
android-13.0.0_r41$ repo diff system/extras/partition_tools/lpunpack.cc
project system/extras/
diff --git a/partition_tools/lpunpack.cc b/partition_tools/lpunpack.cc
index 1f870c5d..951572d4 100644
--- a/partition_tools/lpunpack.cc
+++ b/partition_tools/lpunpack.cc
@@ -84,7 +84,7 @@ static int usage(int /* argc */, char* argv[]) {
"Options:\n"
" -p, --partition=NAME Extract the named partition. This can\n"
" be specified multiple times.\n"
- " -S, --slot=NUM Slot number (default is 0).\n",
+ " -s, --slot=NUM Slot number (default is 0).\n",
argv[0], argv[0]);
return EX_USAGE;
}
@@ -93,7 +93,7 @@ int main(int argc, char* argv[]) {
// clang-format off
struct option options[] = {
{ "partition", required_argument, nullptr, 'p' },
- { "slot", required_argument, nullptr, 'S' },
+ { "slot", required_argument, nullptr, 's' },
{ nullptr, 0, nullptr, 0 },
};
// clang-format on
@@ -102,7 +102,7 @@ int main(int argc, char* argv[]) {
std::unordered_set<std::string> partitions;
int rv, index;
- while ((rv = getopt_long_only(argc, argv, "+p:sh", options, &index)) != -1) {
+ while ((rv = getopt_long_only(argc, argv, "+p:s:h", options, &index)) != -1) {
switch (rv) {
case 'h':
usage(argc, argv);
@@ -110,7 +110,7 @@ int main(int argc, char* argv[]) {
case '?':
std::cerr << "Unrecognized argument.\n";
return usage(argc, argv);
- case 'S':
+ case 's':
if (!android::base::ParseUint(optarg, &slot_num)) {
std::cerr << "Slot must be a valid unsigned number.\n";
return usage(argc, argv);
從代碼中可以看到,如果指定了 slot,實(shí)際上是從 super 中讀取該 slot 對應(yīng)的 metadata,然后使用這個 metadata 提取分區(qū)鏡像。
由于讀取到的 metadata 實(shí)際上還是包含了 a, b 兩個槽位的信息,所以看起來即使指定了 “-s” 選項(xiàng),但沒什么作用,除非讀取到的 metadata 只有 b 槽位的信息。
關(guān)于 metadata 的布局,請參考《Android 動態(tài)分區(qū)詳解(一) 5 張圖讓你搞懂動態(tài)分區(qū)原理》中的下圖:
好了,說了一大堆廢話。
總結(jié)起來一句話就是:lpunpack 的 “-S”/“–slot” 選項(xiàng)有問題,沒事就少用。使用的話,要慎重。
4. 其它
- 到目前為止,我寫過 Android OTA 升級相關(guān)的話題包括:
- 基礎(chǔ)入門:《Android A/B 系統(tǒng)》系列
- 核心模塊:《Android Update Engine 分析》 系列
- 動態(tài)分區(qū):《Android 動態(tài)分區(qū)》 系列
- 虛擬 A/B:《Android 虛擬 A/B 分區(qū)》系列
- 升級工具:《Android OTA 相關(guān)工具》系列
更多這些關(guān)于 Android OTA 升級相關(guān)文章的內(nèi)容,請參考《Android OTA 升級系列專欄文章導(dǎo)讀》。
如果您已經(jīng)訂閱了動態(tài)分區(qū)和虛擬分區(qū)付費(fèi)專欄,請務(wù)必加我微信,備注訂閱賬號,拉您進(jìn)“動態(tài)分區(qū) & 虛擬分區(qū)專欄 VIP 答疑群”。我會在方便的時候,回答大家關(guān)于 A/B 系統(tǒng)、動態(tài)分區(qū)、虛擬分區(qū)、各種 OTA 升級和簽名的問題,此群僅限專欄訂閱者參與~
除此之外,我有一個 Android OTA 升級討論群,里面現(xiàn)在有 400+ 朋友,主要討論手機(jī),車機(jī),電視,機(jī)頂盒,平板等各種設(shè)備的 OTA 升級話題,如果您從事 OTA 升級工作,歡迎加群一起交流,請?jiān)诩游椅⑿艜r注明“Android OTA 討論組”。此群僅限 Android OTA 開發(fā)者參與~文章來源:http://www.zghlxwxcb.cn/news/detail-785044.html
公眾號“洛奇看世界”后臺回復(fù)“wx”獲取個人微信。文章來源地址http://www.zghlxwxcb.cn/news/detail-785044.html
到了這里,關(guān)于Android OTA 相關(guān)工具(七) 使用 lpunpack 解包 super.img的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!