前言
學習筆記,提綱擎領
參考資料:
https://www.cnblogs.com/xiaolei-kaiyuan/
09年初寫的Android Recovery_百度
MTK 7.0 源碼
Android 相關
Recovery 相關
具體代碼流程
【recoery 類關係】:
RecoveryUI: 進行按鍵相關操作
ScreenRecoveryUI: 繼承 RecoveryUI 界面顯示操作操作
Device: 代表設備,有定義支持的相關 BuiltinAction 命令,有指針指向 RecoveryUI 的子類 ScreenRecoveryUI
【recovery 分區】:
// Mt_common.h (bootable\recovery)
#define PRELOADER_PART "/dev/block/mmcblk0boot0"
#define PRELOADER2_PART "/dev/block/mmcblk0boot1"
#define BOOT_PART "/dev/block/platform/mtk-msdc.0/by-name/boot"
#define CACHE_PART "/dev/block/platform/mtk-msdc.0/by-name/cache"
#define FAT_PART "/dev/block/platform/mtk-msdc.0/by-name/intsd"
#define SYSTEM_PART "/dev/block/platform/mtk-msdc.0/by-name/system"
#define DATA_PART "/dev/block/platform/mtk-msdc.0/by-name/userdata"
#define MISC_PART "/dev/block/platform/mtk-msdc.0/by-name/para"
#define RECOVERY_PART "/dev/block/platform/mtk-msdc.0/by-name/recovery"
#define CUSTOM_PART "/dev/block/platform/mtk-msdc.0/by-name/custom"
#define VENDOR_PART "/dev/block/platform/mtk-msdc.0/by-name/vendor"
#define LOGO_PART "/dev/block/platform/mtk-msdc.0/by-name/logo"
#define LK_PART "/dev/block/platform/mtk-msdc.0/by-name/lk"
#define TEE1_PART "/dev/block/platform/mtk-msdc.0/by-name/tee1"
#define TEE2_PART "/dev/block/platform/mtk-msdc.0/by-name/tee2"
#define PERSIST_PART "/dev/block/platform/mtk-msdc.0/by-name/persist"
#define NVDATA_PART "/dev/block/platform/mtk-msdc.0/by-name/nvdata"
#define MT_GPT_PART "/dev/block/platform/mtk-msdc.0/by-name"
// device\mediatek\build\build\tools\ptgen\MT6750\partition_table_MT6750_E266L.xls
preloader Raw data
pgpt Raw data
recovery Raw data
para Raw data
custom EXT4
factory EXT4
APD EXT4
ADF EXT4
expdb Raw data
frp Raw data
ppl Raw data
misc2 Raw data
persist EXT4
nvdata EXT4
metadata Raw data
protect1 EXT4
protect2 EXT4
seccfg Raw data
oemkeystore Raw data
proinfo Raw data
efuse Raw data
md1img Raw data
md1dsp Raw data
md1arm7 Raw data
md3img Raw data
nvram Raw data
lk Raw data
lk2 Raw data
boot Raw data
logo Raw data
tee1 Raw data
tee2 Raw data
secro Raw data
keystore Raw data
system EXT4
cache EXT4
userdata EXT4
intsd FAT
otp Raw data
flashinfo Raw data
sgpt Raw data
/dev/block/platform/mtk-msdc.0/11230000.msdc0/by-name
lrwxrwxrwx 1 root root 20 2017-07-08 16:39 ADF -> /dev/block/mmcblk0p5
lrwxrwxrwx 1 root root 20 2017-07-08 16:39 APD -> /dev/block/mmcblk0p4
lrwxrwxrwx 1 root root 21 2017-07-08 16:39 boot -> /dev/block/mmcblk0p23
lrwxrwxrwx 1 root root 21 2017-07-08 16:39 cache -> /dev/block/mmcblk0p30
lrwxrwxrwx 1 root root 20 2017-07-08 16:39 expdb -> /dev/block/mmcblk0p6
lrwxrwxrwx 1 root root 20 2017-07-08 16:39 factory -> /dev/block/mmcblk0p3
lrwxrwxrwx 1 root root 21 2017-07-08 16:39 flashinfo -> /dev/block/mmcblk0p32
lrwxrwxrwx 1 root root 20 2017-07-08 16:39 frp -> /dev/block/mmcblk0p7
lrwxrwxrwx 1 root root 21 2017-07-08 16:39 keystore -> /dev/block/mmcblk0p28
lrwxrwxrwx 1 root root 21 2017-07-08 16:39 lk -> /dev/block/mmcblk0p21
lrwxrwxrwx 1 root root 21 2017-07-08 16:39 lk2 -> /dev/block/mmcblk0p22
lrwxrwxrwx 1 root root 21 2017-07-08 16:39 logo -> /dev/block/mmcblk0p24
lrwxrwxrwx 1 root root 21 2017-07-08 16:39 md1arm7 -> /dev/block/mmcblk0p18
lrwxrwxrwx 1 root root 21 2017-07-08 16:39 md1dsp -> /dev/block/mmcblk0p17
lrwxrwxrwx 1 root root 21 2017-07-08 16:39 md1img -> /dev/block/mmcblk0p16
lrwxrwxrwx 1 root root 21 2017-07-08 16:39 md3img -> /dev/block/mmcblk0p19
lrwxrwxrwx 1 root root 21 2017-07-08 16:39 metadata -> /dev/block/mmcblk0p10
lrwxrwxrwx 1 root root 20 2017-07-08 16:39 nvdata -> /dev/block/mmcblk0p9
lrwxrwxrwx 1 root root 21 2017-07-08 16:39 nvram -> /dev/block/mmcblk0p20
lrwxrwxrwx 1 root root 21 2017-07-08 16:39 oemkeystore -> /dev/block/mmcblk0p14
lrwxrwxrwx 1 root root 20 2017-07-08 16:39 para -> /dev/block/mmcblk0p2
lrwxrwxrwx 1 root root 20 2017-07-08 16:39 ppl -> /dev/block/mmcblk0p8
lrwxrwxrwx 1 root root 21 2017-07-08 16:39 proinfo -> /dev/block/mmcblk0p15
lrwxrwxrwx 1 root root 21 2017-07-08 16:39 protect1 -> /dev/block/mmcblk0p11
lrwxrwxrwx 1 root root 21 2017-07-08 16:39 protect2 -> /dev/block/mmcblk0p12
lrwxrwxrwx 1 root root 20 2017-07-08 16:39 recovery -> /dev/block/mmcblk0p1
lrwxrwxrwx 1 root root 21 2017-07-08 16:39 seccfg -> /dev/block/mmcblk0p13
lrwxrwxrwx 1 root root 21 2017-07-08 16:39 secro -> /dev/block/mmcblk0p27
lrwxrwxrwx 1 root root 21 2017-07-08 16:39 system -> /dev/block/mmcblk0p29
lrwxrwxrwx 1 root root 21 2017-07-08 16:39 tee1 -> /dev/block/mmcblk0p25
lrwxrwxrwx 1 root root 21 2017-07-08 16:39 tee2 -> /dev/block/mmcblk0p26
lrwxrwxrwx 1 root root 21 2017-07-08 16:39 userdata -> /dev/block/mmcblk0p31
【Recovery 流程總結】:
//////////////////////////////////////////////////////////////////////////////////////////////////
// 0. 帶 --adbd 參數啓動,其只支持 adb sideload 命令
// 1. 進行輸入輸出重定向,啓動一個 log 子進程進行 log 輸出工作,讓 log 打印到指定文件裏
// 2. 加載文件系統掛載表 fstab 文件,保存到內存的 fstab 中,類似 VOLD 中的操作,解析完成後
// 保存在全局變量 fstab 中,後面有用到
// 3. 搜索 fstab 文件中,判斷是否有 /cache 分區
// 4. 如果支持第二個 sdcard 的話,創建 "/sdcard2" 目錄
// 5. 主要是用來判斷存儲是什麼類型的:Nand or Emmc ,這通過讀取設備的 GPT(GUID Partion Table)全局唯一標識磁盤分區表
// 來實現,最後設置 phone_type 類型:NAND_TYPE or EMMC_TYPE
// 6. 進行文件系統掛載
// 1. 獲得 fstab 中指定路徑的那行參數
// 2. 獲得 /proc/mounts 中已掛載分區的信息,保存在全局變量 g_mounts_state 中
// 3. 遍歷 /proc/mounts 中的數據,獲取傳入掛點的那行參數,如 /dev/block/platform/mtk-msdc.0/11230000.msdc0/by-name/system /system ext4 ro,seclabel,relatime,data=ordered 0 0
// 4. 進行文件系統掛載:ubifs/yaffs2/ext4/squashfs/vfat
// 5. 掛載 /sdcard ,這個裏面掛載了我們自己的添加的 ntfs/exfat 系統用來支持 ntfs/exfat 的 SD 存儲卡
// 7. log 重命令, last_log/last_kmsg 重命令爲 last_log.[number]/last_kmsg.[number]
// 8. 獲得命令行參數,首先獲得 /misc 分區下的命令,再獲得 /cache 下的命令
// 最後將這些命令再寫入 /misc, 讓其重啓再進入 recovery, 用於升級失敗重試,升級成功則清除
// 9. 解析從 /misc 和 /cache 獲得的參數,可以用的命令如下:
// static const struct option OPTIONS[] = {
// { "send_intent", required_argument, NULL, 'i' },
// { "update_package", required_argument, NULL, 'u' },
// { "retry_count", required_argument, NULL, 'n' },
// { "wipe_data", no_argument, NULL, 'w' },
// { "wipe_cache", no_argument, NULL, 'c' },
// { "show_text", no_argument, NULL, 't' },
// { "sideload", no_argument, NULL, 's' },
// { "sideload_auto_reboot", no_argument, NULL, 'a' },
// { "just_exit", no_argument, NULL, 'x' },
// { "locale", required_argument, NULL, 'l' },
// MT_OPTION
// { "stages", required_argument, NULL, 'g' },
// { "shutdown_after", no_argument, NULL, 'p' },
// { "reason", required_argument, NULL, 'r' },
// { "security", no_argument, NULL, 'e'},
// //[email protected] add 20161101 for asus ota fota begin
// { "requester", required_argument, NULL, 'q' },
// //[email protected] add 20161101 for asus ota fota end
// { NULL, 0, NULL, 0 },
// };
// 10. locale = "en_US" 這個不爲空指針,不走這裏,這裏只是加載 /cache 下的命令
// 11. 使用 ScreenRecoveryUI 類初始化了 Device 類
// ScreenRecoveryUI 類:負責界面顯示相關的操作,繼承實現 RecoveryUI 抽象類
// 12. 獲得 Device 類中的 ScreenRecoveryUI 對象,然後進行界面操作
// 13. 顯示相關初始化
// 初始化全局變量 gr_font, 通過 libpng 打開 font.png, 保存到 gr_font->texture 中
// 【核心,假裝用的此函數】:打開內核的 /dev/graphics/fb0 顯示節點:
// 節點的文件描述符保存在 fb_fd 中
// mmap() 的內存顯示空間,保存在全局變量 gr_framebuffer 中
// 設置 g_draw 指向顯示緩衝區
// 對顯示界面進行翻轉操作
// 獲得屬性 ro.sf.lcd_density 顯示密度,設置一此 ScreenRecoveryUI 的屬性值,並分配一些內存
// 加載一些圖片進 ScreenRecoveryUI 的變量中保存
// 加載圖片流程:
// 打開 /res/images/ 下的圖片
// 分配一個 surface 對象內存
// 將 png 圖片讀入 surface 對象中保存
// 然後將 surface 對象返回給對應 ScreenRecoveryUI 變量中保存
// 加載本地化的字體,png 圖片中可以保存哪國語言信息?加載過一個 surface 內存中保存
// 加載 /res/images/ 下的圖片進 surface 數組中,動畫是通過一幀幀圖片實現的
// 創建了一個進程,進行顯示更新
// 死循環:
// 定時更新進度條,20ms 更新一次
// 如果需要重繪
// 更新全部,繪製菜單等
// 更新部分,如動畫,進度條
// 監聽 /dev/input/event 下的節點,當有按鍵事件時,回調 RecoveryUI::InputCallback() 進行處理
// 他會在裏面調用 ProcessKey() 進行按鍵處理
// 14. 根據是否啓用安全更新,來設置背景字符串
// 15. 如果命令行設置了 -update_package 更新指令,則解析下鏡像存放路徑格式爲:
// -update_package=[分區]:[路徑]
// 將更新的鏡像路徑存在 update_package 中
// 16. 先進行更新安裝包
// 進行電池電量檢測,至少 20%
// 首先將更新命令寫入 /misc 中,用於升級失敗後自動再進入升級
// 將當前更新路徑寫入 /tmp/last_install 中保存
// 確保 /tmp 和 /cache 路徑被掛載,其他路徑被卸載?
// 顯示更新界面
// 進行路徑掛載
// 將路徑指向的文件 mmap 映射到內存中?
// 加載加密用的密鑰:RSA 算法
// 對加載進來的安裝包進行校驗,使用 RSA
// 打開 update.zip 安裝包
// 進行升級前的一些準備工作,如 data 分區備份與恢復
// 在 update.zip 中查找 "META-INF/com/google/android/update-binary" 更新程序
// 首先將 update.zip 解壓到 /tmp/update_binary 中
// 然後創建一個子進程:
// 執行 "META-INF/com/google/android/update-binary" 更新程序
// ecex(/tmp/update_binary) 進行更新操作
// 父子通過管道通信,父提供一些重啓、進度條顯示服務
// 進行 modem 更新
// 更新成功後,清除 /cache 分區
// 更新 Modem 的 persist.sys.extmddlprogress 屬性值
// 更新失敗了,需要再重進 recovery 再進行更新
// 17. 進行雙清、或從 adb 中獲取安裝包 或從 /sdcard 中更新 data 分區
// 18. 將更新結果寫入 MOTA_RESULT_FILE = "/data/data/com.mediatek.systemupdate/files/updateResult" 和 /misc 中?
// 然後保存系統 log 到 cache 分區中:
// 保存 INTENT_FILE = "/cache/recovery/intent";
// 保存 LOCALE_FILE = "/cache/recovery/last_locale";
// "/tmp/recovery.log" ==》"/cache/recovery/log"
// "/tmp/recovery.log" ==》 "/cache/recovery/last_log"
// "/tmp/last_install" ==》 "/cache/recovery/last_install"
// 保存 kernel log ===> "/cache/recovery/last_kmsg"
// 然後清 /misc 設置,讓其重啓能正常進入系統
// 19. 等待用戶按鍵操作
// 進行菜單顯示與響應按鍵
// 處理按鍵事件
// 20. 更新系統屬性
// 21. 死循環