现在的位置: 首页 > 综合 > 正文

安卓Android Recovery具体工作原理

2013年08月06日 ⁄ 综合 ⁄ 共 9213字 ⁄ 字号 评论关闭

http://www.itqun.net/content-detail/76360_2.html

什么是Android系统Recovery?Android系统Recovery有什么功能?请参考:http://www.anzhuoba.com/thread-5984-1-1.html】! ^" ?2 p/ N- b- j0 I$ V; a

% |0 d$ w8 {4 G! M  ^
Android系统利用Recovery模式,进行恢复出厂设置,OTA升级,patch升级及firmware升级,系统备份等。Recovery模式功能的强弱跟Recovery Image软件版本有关系,也就是在制作Recovery Image时,开发者给Recovery添加功能的多少,这是一个完全可以裁减的工作。
1 D: n% h' r$ B9 }$ z, V3 k7 }" }- C; ]' h) \8 z- w( {
一、Recovery升级简介
. D' f3 ]. j+ D( P: ^* ]升级一般通过运行升级包中的META-INF/com/google/android/update-script脚本来执行自定义升级,脚本中是一组recovery系统能识别的UI控制,文件系统操作命令,例如write_raw_image(写FLASH分区),copy_dir(复制目录)。该包一般被下载至SDCARD和CACHE分区下。如果对该包内容感兴趣,可以从http://forum.xda-developers.com/showthread.php?t=442480下载JF升级包来看看。3
D+ [5 X3 w0 x! y) `- F5 I
升级中还涉及到包的数字签名,签名方式和普通JAR文件签名差不错。公钥会被硬编译入recovery,编译时生成在:out/target/product/XX/obj/PACKAGING/ota_keys_inc_intermediates/keys.inc2 c. O- O! D) X: W& p7 ?* O( g

% J" b5 O# T$ Q% g5 }二、Android系统三种启动模式
# `& G3 ?; h0 }8 M8 a9 c这里为了了解Recovery机制,我们以G1手机为例,后续的Android版本可能有些细微差别,但是大同小异。6 ]- G2 v! q) v, N" i
G1手机的Magic Key操作有:
* ?+ }* a; r9 V1 v% [& x(1) camera +power:bootloader模式,ADP里则可以使用fastboot模式
, B% J" X+ [! A(2) home + power:recovery模式
! @' G; L' c( r+ v; O& \: Q- k5 BG1手机有三种正常启动模式,或者说三种Bootloader正常启动。按照BCB(Bootloader Control Block, 下节介绍)中的command分类:  
- O8 I+ o8 O! A2 U' V(1)  command == 'boot-recovery'   → 启动recovery.img。recovery模式
! N4 G  e5 h/ J+ m2 Y(2)  command =='update-radio/hboot' → 更新firmware(bootloader)
/ n- w4 G- m, _+ Y, [( ~8 V(3)  其他 → 启动boot.img   
1 {6 B# a8 Z" [) @' f3 {# u' T/ r9 ]7 }6 b
三、Recovery涉及到的其他系统及文件
5 f- \3 C! P6 M0 T
  d* ?! o/ N4 y2 _2 Z1、CACHE分区文件
* D& ^5 `! [0 {2 F$ F* \* n' A* @' K       Recovery 工具通过NAND cache分区上的三个文件和主系统打交道。主系统(包括恢复出厂设置和% |* r7 r" J" ?6 A2 U, Q
       OTA升级)可以写入recovery所需的命令,读出recovery过程中的LOG和intent。3 m: Q0 w9 f! V, `# ^8 B" e
       1)/cache/recovery/command: recovery命令,由主系统写入。所有命令如下:7 h6 e: E, ?/ k5 K
         --send_intent=anystring - write the text out to recovery.intent
: C- c6 A6 [5 N' ^# X6 z- I/ d         --update_package=root:path - verify install an OTA package file8 |, w7 I) a! t+ ~
         --wipe_data - erase user data (and cache), then reboot9 c8 |' ]# C0 t+ F
         --wipe_cache - wipe cache (but not user data), then reboot  _5 w9 v/ z, y; P: R4 p* j" Q
       2)/cache/recovery/log:recovery过程日志,由主系统读出
& m2 f1 s! O5 a. g6 Q0 o+ w  y' A       3)/cache/recovery/intent:recovery输出的intent. r' ?2 z  L7 e& O) k4 A  u
& b  O1 @: @7 j! w) ]) [
2、MISC分区内容, U1 T" d3 j! B) \8 ?! v  j: t" E% _7 Y
       Bootloader Control Block (BCB) 存放recovery bootloader message。       ) S6 `2 w3 G$ `/ H! v8 e# O
       结构如下:
8 }* S. X0 j- U       struct bootloader_message {
2 z) V" E( `& h9 F- N              char command[32];9 Q1 t: f" p4 o! b6 f
              char status[32]; // 未知用途; c: S. z! B9 X
              char recovery[1024];7 d9 g4 d$ w* ?) k5 R/ o
       };' P$ [, ?3 G* \' W1 `/ V0 m
       command可以有以下两个值:
( ]( B. i/ O  ^" B  Z/ D" H4 H) N        1)boot-recovery:标示recovery正在进行,或指示bootloader应该进入recovery mode% f; L& q1 o. @9 G* z
        2)update-hboot/radio:指示bootloader更新firmware
- ?0 L* V2 A0 j# u1 K$ V# z       recovery的值:
8 _9 S# S, o( N9 L5 T2 n& L* L4 Z        1)<recovery command>
4 T" U1 W( o5 y: r# E; v" Y: P       其中recovery command为CACHE:/recovery/command命令。
( C9 g7 ]  s6 P- z# z  Z$ G4 T4 b1 n) r1 t( n, F7 W  n
四、两种操作分析9 |  ^7 l7 S- v9 G8 ]" y0 t% B

3 h) |# i9 y4 m    1、FACTORY RESET(恢复出厂设置
" ?- y& e7 W$ r; ]  J2 i) M       1)用户选择“恢复出厂设置”' e. l; l) c* |# s. K; G
       2)设置系统将"--wipe_data"命令写入/cache/recovery/command
6 b+ W$ S' o2 ], r. {$ W       3)系统重启,并进入recover模式(/sbin/recovery)4 o1 S$ a. n1 l, f0 v  a$ r
       4)get_args() 将 "boot-recovery"和"--wipe_data"写入BCB(Bootloader Control Block) 2 N& i7 A6 E& f0 M6 Q2 i* O% t
       5)erase_root() 格式化(擦除)DATA分区
" T. x; G0 s5 h$ {5 q       6)erase_root() 格式化(擦除)CACHE分区
5 q4 r0 Q: h' P/ _: ]       7)finish_recovery() 擦除BCB# B/ n2 _. Z6 a! o5 f3 o  z
       8)重启系统$ w& J0 X" M) k' c9 K2 ~

7 U* ]& {0 E4 P& A5 X' Q2 X9 H    2、OTA INSTALL(OTA升级)$ O  V: ?- ?1 y' U: ]5 o
       1)升级系统下载OTA包到/cache/some-filename.zip
; s! ^  j2 ^) L" ~6 y       2)升级系统写入recovery命令"--update_package=CACHE:some-filename.zip"/ d3 f% c" {' p
       3)重启,并进入recovery模式7 k7 N4 j$ E3 ]! Q: {) n4 ~
       4)get_args() 将"boot-recovery" 和 "--update_package=..." 写入BCB& U4 R! D7 e1 m6 j4 ^- O
       5)install_package() 作升级' v! C8 F$ g9 S0 T( [5 S; y
       6)finish_recovery() 擦除 BCB
* F* U/ f9 V7 M& z       7)** 如果安装包失败 ** prompt_and_wait() 等待用户操作,选择ALT+S或ALT+W 升级或恢复出厂设置4 Y& y8 _. o9 |" M$ \5 h
       8)main() 调用 maybe_install_firmware_update()5 s) b" D1 F- J/ F  b( N
          8.1) 如果包里有hboot/radio的firmware则继续,否则返回& }# L0 K' Q- I% B$ g% I8 h
          8.2) 将 "boot-recovery" 和 "--wipe_cache" 写入BCB
; E, p6 Y  @. g5 W3 c          8.3) 将 firmware image写入cache分区: W& q4 K" x  s  y, i
          8.4) 将 "update-radio/hboot" 和 "--wipe_cache" 写入BCB, M7 G1 j9 a2 Y' E* F
          8.5) 重启系统
0 t" Z' f8 o. a          8.6) bootloader自身更新firmware
+ }5 d0 p7 p2 @: z3 \          8.7)bootloader 将 "boot-recovery" 写入BCB
% x5 ]+ {2 S% F! S5 d( m, a6 ~% O          8.8)erase_root() 擦除CACHE分区& S+ w7 s) U, I6 K% A) N2 o
          8.9)清除 BCB
6 z/ g$ ^1 Y* T' P       9)main() 调用 reboot() 重启系统
" n7 E  e% B3 U/ D3 M0 Y0 m1 c- b1 a( z* K0 @1 i1 {
五、Recovery模式流程
3 p5 @2 h* e8 l' G' ?6 `2 U
. h3 T( H% S% I    /init → init.rc → /sbin/recovery →
9 H7 [0 ^$ W' T9 Q/ f9 [  l. v6 f% `  v0 v' Y4 S
    main():recovery.c:
8 V/ W$ p- G1 F% E' z3 _5 q& @% F    ui_init():ui.c [UI initialize]
+ G0 s' O! A6 d    gr_init():minui/graphics.c [set tty0 to graphic mode, open fb0]
  k- x( ]' G, j    ev_init():minui/events.c [open /dev/input/event*]
+ r, Z  F+ o) Z+ e* R$ U    res_create_surface:minui/resource.c [create surfaces for all bitmaps used
: U- Q. r6 o8 D2 n                                          later, include icons, bmps]+ \& l. [. m1 [1 j# J
    create 2 threads: progress/input_thread [create progress show and input event
" T3 s& o* M& |) e. D& a/ g                                          handler thread]
* V; @% q  A5 l    get_args():recovery.c
) H! l# J* o1 ?1 W0 S) x  _    get_bootloader_message():bootloader.c [read mtdblock0(misc partition) 2nd page
" J& G0 u: P2 n                                          for commandline]
; s6 Z! D* X1 }; l+ ^: T    check if nand misc partition has boot message. If yes, fill argc/argv.$ {- ]9 v" W) ?( b" }, u
    If no, get arguments from /cache/recovery/command, and fill argc/argv.
8 M0 [9 j: {  U# \    set_bootloader_message():bootloader.c[set bootloader message back to mtdblock0]
) q* `6 m8 U$ H    Parser argv[] filled above  F6 T& _. [1 _5 q7 p4 H( R
    register_update_commands():commands.c [ register all commands with name + m2 C% v' v( b! b0 W8 v
                                                and hook function ]
2 f2 A( m! G+ P; Y& H- k% k    registerCommand():commands.c
9 n* `2 C& ^% _3 Z* F1 Y6 H    Register command with name, hook, type, cookie.
# B, T+ b" _0 i, E! g8 ~3 O: D    Commands, e.g: assert, delete, copy_dir, symlink, write_raw_image.
. Q3 H, j. k1 w  C* x    registerFunction():commands.c
% S4 W# B; l' S/ q3 |$ r" S8 V    Register function with name, hook, cookie.
7 o1 L' w3 w0 [5 R) }; p1 s7 k" Z( j    Function, e.g: get_mark, matches, getprop, file_contains( w- a+ i, i, [9 p( F( v
    install_package():8 G" @9 S* N2 W- `" y
    translate_root_path():roots.c [ "SYSTEM:lib" and turns it into a string   l8 ^( j! R& O
                             like "/system/lib", translate the updater.zip path ]7 Z2 H" H: J+ I; u. {: E; c7 d9 K
    mzOpenZipArchive():zip.c [ open updater.zip file (uncompass) ]
+ T+ X/ r; k9 T    handle_update_package():install.c( h& {3 [. c# x6 D
    verify_jar_signature():verifier.c [ verify signature with keys.inc key; verify
; _: m3 T5 K# T                                                manifest and zip package archive ]" x3 H9 g0 g& y  N7 I
    verifySignature() [ verify the signature file: CERT.sf/rsa. ]& F9 M! T9 h  }# P! `
    digestEntry():verifier.c [ get SHA-1 digest of CERT.sf file ]
4 M. H* b& ^$ O( h6 M% T; \% I, P    RSA_verify(public key:keys.inc, signature:CERT.rsa, CERT.sf's digest):/ m. D. z' ?. w7 c/ h+ s3 T
          libc/rsa.c [ Verify a 2048 bit RSA PKCS1.5 signature against an expected . P/ b* P* r+ q
                   SHA-1 hash. Use public key to decrypt the CERT.rsa to get
! `3 `; ?& a' D3 f                           original SHA digest,then compare to digest of CERT.sf ]
3 w2 p) G# z, O, d$ d) k" |    verifyManifest() [ Get manifest SHA1-Digest from CERT.sf. Then do digest to + `; y$ Z2 Y% Y: ^) o4 [9 o
                                                     MANIFEST.MF.Compare them ]
# O$ P: z, P0 n8 C+ F    verifyArchive() [ verify all the files in update.zip with digest listed in 0 ]( A4 B8 `. T7 `/ c# g  l- c
                                                              MANIFEST.MF ]7 i+ |1 G/ W! _2 V
    find_update_script():install.c [ find META-INF/com/google/android/update-
! e& o0 K7 t2 o                                                      script updater script ]
! H( s4 \: v4 C/ g7 H( {' X    handle_update_script():install.c [ read cmds from script file, and do parser,
: p: F4 p: u6 l+ W8 d& e                                                                        exec ]( t& m6 H. R# l
    parseAmendScript():amend.c [ call yyparse() to parse to command ]
; l4 k' |8 C& n2 P# j    exeCommandList():install.c; L+ p) F" @, K7 U% g, c& x' K
    exeCommand():execute.c [ call command hook function ]/ k- u6 T6 e0 A3 ~3 X
    erase DATA/CACHE partition
9 B6 G- I6 m- i. g. |" U2 C6 ]    prompt_and_wait():recovery.c [ wait for user input: 1) reboot 2) update.zip - S/ g. o# z, r. [) X3 q
                                                               3)wipe data ]
) w2 O5 R% P" f& x! ~6 e3 R* `* x+ f    ui_key_xxx get ALT+x keys! [) i2 @* f0 g1 v1 t) O6 S/ B; ^8 t
       1) do nothing
" M9 V) W& R# U! c4 n       2) install_package('SDCARD:update.zip')
$ C- v( r" y1 m4 Q; E% j       3) erase_root() → format_root_device() DATA/CACHE3 D2 X' H; t* r, \
       may_install_firmware_update():firmware.c [ remember_firmware_update() is
7 Q7 l; h+ T  R- I% L       called by   write_hboot/radio_image command, it stores the bootloader image
! Z1 V1 T# q- Q5 T- n# x3 h       to CACHE partition, and write update-hboot/radio command to MISC partition
$ N7 \/ K5 K) E' f       for bootloader message to let bootloader update itself after reboot ]
6 V# z! s* E/ v% O: d& n    set_bootloader_message(); W; q/ o5 [9 j# v
    write_update_for_bootloader():bootloader.c [ write firmware image into CACHE ( n! m$ ^: G7 t) B0 [# B' E9 L# l
    partition with update_header, busyimage and failimage ]8 j: N& Q, J2 g! ]1 c& U# k
    finish_recovery():recovery.c [ clear the recovery command and prepare to
  h2 w. P$ R; v1 n" e# Z7 W: l- b5 O    boot a (hopefully working)  system, copy our log file to cache as well (for
" Q& y  @  N: \    the system to read), and record any intent we were  asked to communicate back
, b* q7 o( K0 k: j' `1 g    to the system. ]. X: R) j4 a* E( D3 N$ s
! @8 [: ^# l$ X1 I% O
    reboot()0 N% Y6 d5 X2 H

: ]- m3 N6 N4 o2 i8 D- ]# T+ h; q8 F- r( Q8 u/ F
% [7 X& }( y" b+ A* i
六、Recovery模式流程图
# o+ f5 ?/ Y7 h9 G6 ]& |) j以下流程图绘制了系统从启动加载bootloader后的行为流程。
, r8 ~3 z2 C* z3 b( B$ N1.png

2011-10-24 04:49:27 上传

下载附件(27.25 KB)

' N1 j4 R7 f; [5 o6 x5 T2.png

2011-10-24 04:49:29 上传

下载附件(51 KB)

$ ?: m& R, J  M2 ?1 D# d" j: a

3.png

http://www.anzhuoba.com/thread-5985-1-1.html

2011-10-24 04:59:48 上传

下载附件(30.24 KB)

抱歉!评论已关闭.