|
Posted at 2/11/2015 11:13:47
1#
Re: Firefly/Pad Windows Tools
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
HOW TO MAKE ANDROID USERDATA PARTITION
PERSISTENT
Busybee
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Table of Contents
─────────────────
How to make Android Userdata Partition Persistent
.. Intro
.. Steps
..... 1. Prepare userdata Partition Data
..... 2. Pack the Data
..... 3. Add databk Partition
..... 4. Flash Fimware
..... 5. Check the Result
.. Related Source Code
How to make Android Userdata Partition Persistent
═════════════════════════════════════════════════
Intro
─────
Android's userdata partition contains system configuration and user
app data. If we can make this partition persistent, there's no need to
modify system source code in order to customize the firmware.
But the question is, flashing image directly to userdata partition
does not work. When the device is flashed with new firmware, it will
enter to recovery mode, where the userdata and cache partition will be
formatted. Also, when user selects "Factory data reset" in Settings,
the device will go to recovery mode to erase the userdata partition.
One solution is, creating new partition to store persistent data of
userdata partition. This special partition is only used to recover
userdata partition, which will not be mounted or edited by Android
system.
RK3288 SDK has this solution builtin: pack userdata partition to an
image file, and flash it to the special parition named "databk". Then
in recovery mode, if databk partition exists, it'll be cloned to
userdata parition.
Here are the steps required:
Steps
─────
1. Prepare userdata Partition Data
╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌
The default path `out/target/product/rk3288/data/' is used as an
example, which will store persistent data of userdata partition.
You can pack the userdata parition of device and extract it to the
host via adb, for example:
╭────
│ adb shell busybox tar -cz -C /data . | \
│ tar -xz -C out/target/product/rk3288/data/
│
│ # You need to clean the data, removing unneccessary ones.
╰────
2. Pack the Data
╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌
We assume the size of the userdata partition is 1GiB(Modify it below
accordingly), Run:
╭────
│ 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
╰────
An image file named databk.img will be created, which has format of
sparse ext4fs.
This file can be convert to ext4fs format, just for convenience of
checking files and permissions. If you do not want this, skip it:
╭────
│ out/host/linux-x86/bin/simg2img \
│ rockdev/Image-rk3288/databk.img \
│ rockdev/Image-rk3288/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. Add databk Partition
╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌
Modify parameter file. Please pay attention that unit of partition
size and offset is sector (which is 512 bytes here). The newly added
"databk" partition must be larger than databk.img file.
We recommend to split the "user" partition (which is internal storage
of Android and is the last one in the flash storage.).
Hint: you can fetch the parameter from your board using rkflashkit:
╭────
│ sudo rkflashkit backup @parameter new_parameter.txt
╰────
4. Flash Fimware
╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌
Use rkflashkit to flash the newly parameter and databk.img:
╭────
│ sudo rkflashkit flash @parameter new_parameter.txt
│ sudo rkflashkit flash @databk databk.img
╰────
5. Check the Result
╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌
Selects "Factory data reset" in Settings to check the result.
Related Source Code
───────────────────
The source code of recovering userdata partition is in
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;
│ }
╰────
|
|