|
发表于 2014-12-18 11:02:15
只看该作者
推荐
本帖最后由 busybee 于 2014-12-18 11:09 编辑
如何固化 Android 的 data 分区
前言
Android 的 data 分区保存着系统的配置数据和用户安装的应用等重要信息。将该分区数据固化下来,便可以灵活地定制固件,而不用修改系统代码,加入诸多预置参数。
但是,直接烧写 data 分区数据不能实现固化的目的。因为初次升级固件后,设备会先进入急救模式做初始化操作,格式化 data 和 cache 等分区;而用户在设置里选择“恢复出厂设置“,同样也会进入急救模式,格式化掉 data 分区。
怎么办呢?其中的一种方法,便是另外新建一个分区,用来存储 data 分区的数据。该分区不会被 Android 系统挂载和修改,仅用来恢复 data 分区。
RK3288 SDK 已经内置了这种解决方案:将 data 分区的数据打包好,并烧录到名为 databk 的新分区中,在急救模式时,如果 databk 分区存在,则将其数据复制到 data 分区中。
以下便是相关步骤。
步骤
1. 准备好 data 分区数据
本文默认使用 out/target/product/rk3288/data/ 作为 data 分区的数据路径。
可以通过 adb,将设备的 data 分区打包并解压到主机上,以下指令仅作参考:
adb shell busybox tar -cz -C /data . | \
tar -xz -C out/target/product/rk3288/data/
# 清理 data 目录数据
|
2. 打包 data 分区数据
假设 data 分区的大小为 1G (如果是其它值,请修改以下命令的对应参数),运行以下命令:
PATH=$PATH:./out/host/linux-x86/bin \
out/host/linux-x86/bin/mkuserimg.sh \
-s \
out/target/product/rk3288/data/ \
rockdev/Image-rk3288/databk.img \
ext4 /data 1G
|
便可生成打包好的数据文件 databk.img,其格式为 sparse ext4fs 。
该文件可以转换为 ext4fs 格式,方便查看实际生成的文件及权限:
out/host/linux-x86/bin/simg2img \
rockdev/Image-rk3288/databk.img \
rockdev/Image-rk3288/databk.ext4.img
|
转换后的 databk.ext4.img, 便可以挂载到空目录下查看:
sudo mkdir -p /mnt/databk
sudo mount -o loop rockdev/Image-rk3288/databk.ext4.img /mnt/databk
find /mnt/databk
# ...
sudo umount /mnt/databk
|
3. 增加 databk 分区
修改 parameter 文件,注意其分区大小和偏移量单位增为扇区(512 字节)。该分区的大小应能容纳 databk.img 。
4. 烧写固件
修改分区后,需要将 databk.img 烧写到 databk 分区,并重新烧写 databk 之后所有移动过的分区。
相关代码
恢复 data 分区的逻辑在 bootable/recovery/recovery.cpp 中:
static const char *DATA_PARTITION_NAME = "userdata";
static const char *DATABK_PARTITION_NAME = "databk";
int start_to_clone(const char *data_devname, const char *databk_devname) {
if(simg2img(databk_devname, data_devname)){
LOGE("null of databk ->failed to clone\n");
return -1;
}
LOGI("Cloning %s to %s\n", databk_devname, data_devname);
return 0;
}
static int clone_data_if_exist() {
// ...
const MtdPartitionbyCmdline *databk_partition = mtd_find_partition_by_cmdline(DATABK_PARTITION_NAME);
const MtdPartitionbyCmdline *data_partition = mtd_find_partition_by_cmdline(DATA_PARTITION_NAME);
sprintf(data_devname, "/dev/block/mmcblk0p%d", data_partition->device_index);
sprintf(databk_devname, "/dev/block/mmcblk0p%d", databk_partition->device_index);
// Start to clone
if (start_to_clone(data_devname, databk_devname)) {
LOGE("clone_data_if_exist->error clone data\n");
return -1;
}
return 0;
}
|
|
|