Android A/B パーティション
比較的新しいAndroidでは、A/Bパーティション方式が採用されている。簡単に言えば、システムのパーティションを2つ作っておいて、アップデートのたびに起動していない方のパーティションを書き換えて再起動する方式。これによって、アップデート中に電源が喪失したりしても修復が可能になる。
手元のOneplus 6 (Android 10)でブロックデバイスを表示させてみると以下のようになった。
ちなみに、ラベル付きブロックデバイスを見ようと思ったら、通常のLinuxの/dev/disk/by-nameではなく/dev/block/platform/soc/hoge/by-nameを確認する必要がある。
code:shell
lrwxrwxrwx 1 root root 15 Sep 26 05:19 ALIGN_TO_128K_1 -> /dev/block/sdd1
lrwxrwxrwx 1 root root 15 Sep 26 05:19 ALIGN_TO_128K_2 -> /dev/block/sdf1
lrwxrwxrwx 1 root root 16 Sep 26 05:19 ImageFv -> /dev/block/sde72
lrwxrwxrwx 1 root root 16 Sep 26 05:19 LOGO_a -> /dev/block/sde20
lrwxrwxrwx 1 root root 16 Sep 26 05:19 LOGO_b -> /dev/block/sde48
lrwxrwxrwx 1 root root 15 Sep 26 05:19 abl_a -> /dev/block/sde8
lrwxrwxrwx 1 root root 16 Sep 26 05:19 abl_b -> /dev/block/sde36
lrwxrwxrwx 1 root root 15 Sep 26 05:19 aop_a -> /dev/block/sde1
lrwxrwxrwx 1 root root 16 Sep 26 05:19 aop_b -> /dev/block/sde29
lrwxrwxrwx 1 root root 16 Sep 26 05:19 apdp -> /dev/block/sde63
lrwxrwxrwx 1 root root 41 Sep 26 05:20 bluetooth -> /dev/block/bootdevice/by-name/bluetooth_a
lrwxrwxrwx 1 root root 15 Sep 26 05:19 bluetooth_a -> /dev/block/sde5
lrwxrwxrwx 1 root root 16 Sep 26 05:19 bluetooth_b -> /dev/block/sde33
lrwxrwxrwx 1 root root 36 Sep 26 05:19 boot -> /dev/block/bootdevice/by-name/boot_a
lrwxrwxrwx 1 root root 16 Sep 26 05:19 boot_a -> /dev/block/sde11
lrwxrwxrwx 1 root root 16 Sep 26 05:19 boot_aging -> /dev/block/sde58
lrwxrwxrwx 1 root root 16 Sep 26 05:19 boot_b -> /dev/block/sde39
lrwxrwxrwx 1 root root 15 Sep 26 05:19 cdt -> /dev/block/sdd2
lrwxrwxrwx 1 root root 16 Sep 26 05:19 cmnlib64_a -> /dev/block/sde13
lrwxrwxrwx 1 root root 16 Sep 26 05:19 cmnlib64_b -> /dev/block/sde41
lrwxrwxrwx 1 root root 16 Sep 26 05:19 cmnlib_a -> /dev/block/sde12
lrwxrwxrwx 1 root root 16 Sep 26 05:19 cmnlib_b -> /dev/block/sde40
lrwxrwxrwx 1 root root 16 Sep 26 05:19 config -> /dev/block/sda12
lrwxrwxrwx 1 root root 15 Sep 26 05:19 ddr -> /dev/block/sdd3
lrwxrwxrwx 1 root root 16 Sep 26 05:19 devcfg_a -> /dev/block/sde14
lrwxrwxrwx 1 root root 16 Sep 26 05:19 devcfg_b -> /dev/block/sde42
lrwxrwxrwx 1 root root 16 Sep 26 05:19 devinfo -> /dev/block/sde61
lrwxrwxrwx 1 root root 16 Sep 26 05:19 dip -> /dev/block/sde62
lrwxrwxrwx 1 root root 35 Sep 26 05:20 dsp -> /dev/block/bootdevice/by-name/dsp_a
lrwxrwxrwx 1 root root 15 Sep 26 05:19 dsp_a -> /dev/block/sde9
lrwxrwxrwx 1 root root 16 Sep 26 05:19 dsp_b -> /dev/block/sde37
lrwxrwxrwx 1 root root 16 Sep 26 05:19 dtbo_a -> /dev/block/sde18
lrwxrwxrwx 1 root root 16 Sep 26 05:19 dtbo_b -> /dev/block/sde46
lrwxrwxrwx 1 root root 15 Sep 26 05:19 frp -> /dev/block/sda6
lrwxrwxrwx 1 root root 15 Sep 26 05:19 fsc -> /dev/block/sdf5
lrwxrwxrwx 1 root root 15 Sep 26 05:19 fsg -> /dev/block/sdf4
lrwxrwxrwx 1 root root 16 Sep 26 05:19 fw_4j1ed_a -> /dev/block/sde21
lrwxrwxrwx 1 root root 16 Sep 26 05:19 fw_4j1ed_b -> /dev/block/sde49
lrwxrwxrwx 1 root root 16 Sep 26 05:19 fw_4u1ea_a -> /dev/block/sde22
lrwxrwxrwx 1 root root 16 Sep 26 05:19 fw_4u1ea_b -> /dev/block/sde50
lrwxrwxrwx 1 root root 16 Sep 26 05:19 fw_ufs3_a -> /dev/block/sde23
lrwxrwxrwx 1 root root 16 Sep 26 05:19 fw_ufs3_b -> /dev/block/sde51
lrwxrwxrwx 1 root root 16 Sep 26 05:19 fw_ufs4_a -> /dev/block/sde24
lrwxrwxrwx 1 root root 16 Sep 26 05:19 fw_ufs4_b -> /dev/block/sde52
lrwxrwxrwx 1 root root 16 Sep 26 05:19 fw_ufs5_a -> /dev/block/sde25
lrwxrwxrwx 1 root root 16 Sep 26 05:19 fw_ufs5_b -> /dev/block/sde53
lrwxrwxrwx 1 root root 16 Sep 26 05:19 fw_ufs6_a -> /dev/block/sde26
lrwxrwxrwx 1 root root 16 Sep 26 05:19 fw_ufs6_b -> /dev/block/sde54
lrwxrwxrwx 1 root root 16 Sep 26 05:19 fw_ufs7_a -> /dev/block/sde27
lrwxrwxrwx 1 root root 16 Sep 26 05:19 fw_ufs7_b -> /dev/block/sde55
lrwxrwxrwx 1 root root 16 Sep 26 05:19 fw_ufs8_a -> /dev/block/sde28
lrwxrwxrwx 1 root root 16 Sep 26 05:19 fw_ufs8_b -> /dev/block/sde56
lrwxrwxrwx 1 root root 15 Sep 26 05:19 hyp_a -> /dev/block/sde3
lrwxrwxrwx 1 root root 16 Sep 26 05:19 hyp_b -> /dev/block/sde31
lrwxrwxrwx 1 root root 16 Sep 26 05:19 keymaster_a -> /dev/block/sde10
lrwxrwxrwx 1 root root 16 Sep 26 05:19 keymaster_b -> /dev/block/sde38
lrwxrwxrwx 1 root root 15 Sep 26 05:19 keystore -> /dev/block/sda5
lrwxrwxrwx 1 root root 16 Sep 26 05:19 limits -> /dev/block/sde67
lrwxrwxrwx 1 root root 16 Sep 26 05:19 logdump -> /dev/block/sde71
lrwxrwxrwx 1 root root 16 Sep 26 05:19 logfs -> /dev/block/sde69
lrwxrwxrwx 1 root root 15 Sep 26 05:19 mdtp_a -> /dev/block/sde7
lrwxrwxrwx 1 root root 16 Sep 26 05:19 mdtp_b -> /dev/block/sde35
lrwxrwxrwx 1 root root 15 Sep 26 05:19 mdtpsecapp_a -> /dev/block/sde6
lrwxrwxrwx 1 root root 16 Sep 26 05:19 mdtpsecapp_b -> /dev/block/sde34
lrwxrwxrwx 1 root root 16 Sep 26 05:19 minidump -> /dev/block/sde57
lrwxrwxrwx 1 root root 15 Sep 26 05:19 misc -> /dev/block/sda3
lrwxrwxrwx 1 root root 37 Sep 26 05:20 modem -> /dev/block/bootdevice/by-name/modem_a
lrwxrwxrwx 1 root root 15 Sep 26 05:19 modem_a -> /dev/block/sde4
lrwxrwxrwx 1 root root 16 Sep 26 05:19 modem_b -> /dev/block/sde32
lrwxrwxrwx 1 root root 15 Sep 26 05:19 modemst1 -> /dev/block/sdf2
lrwxrwxrwx 1 root root 15 Sep 26 05:19 modemst2 -> /dev/block/sdf3
lrwxrwxrwx 1 root root 16 Sep 26 05:19 msadp -> /dev/block/sde64
lrwxrwxrwx 1 root root 16 Sep 26 05:19 odm_a -> /dev/block/sda15
lrwxrwxrwx 1 root root 16 Sep 26 05:19 odm_b -> /dev/block/sda16
lrwxrwxrwx 1 root root 15 Sep 26 05:19 oem_dycnvbk -> /dev/block/sda8
lrwxrwxrwx 1 root root 15 Sep 26 05:19 oem_stanvbk -> /dev/block/sda9
lrwxrwxrwx 1 root root 41 Sep 26 05:19 oem_stanvbk_a -> /dev/block/bootdevice/by-name/oem_stanvbk
lrwxrwxrwx 1 root root 41 Sep 26 05:19 oem_stanvbk_b -> /dev/block/bootdevice/by-name/oem_stanvbk
lrwxrwxrwx 1 root root 16 Sep 26 05:19 op1 -> /dev/block/sde59
lrwxrwxrwx 1 root root 15 Sep 26 05:19 op2 -> /dev/block/sda7
lrwxrwxrwx 1 root root 15 Sep 26 05:19 param -> /dev/block/sda4
lrwxrwxrwx 1 root root 15 Sep 26 05:19 persist -> /dev/block/sda2
lrwxrwxrwx 1 root root 16 Sep 26 05:19 qupfw_a -> /dev/block/sde15
lrwxrwxrwx 1 root root 16 Sep 26 05:19 qupfw_b -> /dev/block/sde43
lrwxrwxrwx 1 root root 16 Sep 26 05:19 reserve1 -> /dev/block/sda10
lrwxrwxrwx 1 root root 16 Sep 26 05:19 reserve2 -> /dev/block/sda11
lrwxrwxrwx 1 root root 16 Sep 26 05:19 sec -> /dev/block/sde60
lrwxrwxrwx 1 root root 16 Sep 26 05:19 splash -> /dev/block/sde66
lrwxrwxrwx 1 root root 16 Sep 26 05:19 spunvm -> /dev/block/sde65
lrwxrwxrwx 1 root root 15 Sep 26 05:19 ssd -> /dev/block/sda1
lrwxrwxrwx 1 root root 16 Sep 26 05:19 sti -> /dev/block/sde70
lrwxrwxrwx 1 root root 16 Sep 26 05:19 storsec_a -> /dev/block/sde19
lrwxrwxrwx 1 root root 16 Sep 26 05:19 storsec_b -> /dev/block/sde47
lrwxrwxrwx 1 root root 38 Sep 26 05:19 system -> /dev/block/bootdevice/by-name/system_a
lrwxrwxrwx 1 root root 16 Sep 26 05:19 system_a -> /dev/block/sda13
lrwxrwxrwx 1 root root 16 Sep 26 05:19 system_b -> /dev/block/sda14
lrwxrwxrwx 1 root root 16 Sep 26 05:19 toolsfv -> /dev/block/sde68
lrwxrwxrwx 1 root root 15 Sep 26 05:19 tz_a -> /dev/block/sde2
lrwxrwxrwx 1 root root 16 Sep 26 05:19 tz_b -> /dev/block/sde30
lrwxrwxrwx 1 root root 16 Sep 26 05:19 userdata -> /dev/block/sda17
lrwxrwxrwx 1 root root 16 Sep 26 05:19 vbmeta_a -> /dev/block/sde17
lrwxrwxrwx 1 root root 16 Sep 26 05:19 vbmeta_b -> /dev/block/sde45
lrwxrwxrwx 1 root root 38 Sep 26 05:19 vendor -> /dev/block/bootdevice/by-name/vendor_a
lrwxrwxrwx 1 root root 16 Sep 26 05:19 vendor_a -> /dev/block/sde16
lrwxrwxrwx 1 root root 16 Sep 26 05:19 vendor_b -> /dev/block/sde44
lrwxrwxrwx 1 root root 15 Sep 26 05:19 xbl_a -> /dev/block/sdb1
lrwxrwxrwx 1 root root 15 Sep 26 05:19 xbl_b -> /dev/block/sdc1
lrwxrwxrwx 1 root root 15 Sep 26 05:19 xbl_config_a -> /dev/block/sdb2
lrwxrwxrwx 1 root root 15 Sep 26 05:19 xbl_config_b -> /dev/block/sdc2
量が多くて見づらいが、注目すべきは、boot_aとboot_b、それにsystem_aとsystem_bだ。他のブロックデバイスは/にマウントするされるので特筆はない。
boot_aとboot_bは、カーネルと初期ram空間、(A/Bパーティション方式の場合それにリカバリー用OSが含まれている。)もっと簡単に言うと、vmlinuzとinitrdとhoge.imgが入っている。これは通常のLinuxマシンと変わらない。
リカバリーOSは、その実体はramfsであり、Androidが起動できないような場合はこのhoge.imgをramに展開し起動する用になっている。そのため、このhoge.imgというイメージファイル自体をrecovery_aやrecovery_bといったパーティションとして呼ぶこともある。リカバリーOSはそれ自体にまたカーネルとinitramfsが含まれており、imgファイルの形式はbootと同じAndroid Boot Fs。非A/Bデバイスではrecoveryパーティションとして分離していたが、A/Bデバイスではリカバリーはbootに含められることになった。
system_aとsystem_bは、Linuxにおけるrootfsであり、正確には/systemにマウントされるOSの本体である。
こうして、Androidは_aと_bのパーティションを交互に更新することで、OSのアップデートを可能にしている。
現在のスロットを確認するには、先程のbootやsystemがboot_aやsystem_aへシンボリックリンクを貼っていることで確認ができる。fastbootだと、sudo fastboot getvar allでactive slot的な項目があったはず。
ちなみに変更は sudo fastboot --set-active=b