The purpose of this HOWTO
This HOWTO is for people who have a LG G4C phone (H525N) and don't really like the flash layout that comes with it. Basically this phone has a /system/ partition that is 2.4 GiB in size and a /cache/ partition that is 850.0 MiB in size, which is a waste of space when you deal with custom ROMs. Also you have only 3.6 GiB for user data. What I want to do is to repartition the phone's flash and add around 2 GiB to the user data partition making it a little bit larger ~5,7 GiB. It will be done by taking ~1,5 GiB from the /system partition/ and ~600MiB from the /cache/ partition. All of the steps will be done in the TWRP recovery, so you have to flash it before (here some XDA link).
The BoardConfig.mk file and size of the /system/ partition
The problem with this setup is that the sock ROM or even LOS (and others) won't work OOTB. It's because of the block-based updates/ROMs structure that are built by default by developers. This means that you (or the developer/maintainer of the ROM) have to adjust settings in the BoardConfig.mk. What have to be changed depends on the flash layout. In the case of LG G4C phone, we have this kind of flash layout:
$ adb shell ~ # sgdisk --print /dev/block/mmcblk0 Disk /dev/block/mmcblk0: 15269888 sectors, 7.3 GiB Logical sector size: 512 bytes Disk identifier (GUID): 98101B32-BBE2-4BF2-A06E-2BB33D000C20 Partition table holds up to 40 entries First usable sector is 34, last usable sector is 15269854 Partitions will be aligned on 2-sector boundaries Total free space is 990 sectors (495.0 KiB) Number Start (sector) End (sector) Size Code Name 1 1024 2047 512.0 KiB FFFF sbl1 2 2048 3071 512.0 KiB FFFF tz 3 3072 4095 512.0 KiB FFFF hyp 4 4096 5119 512.0 KiB FFFF rpm 5 5120 9215 2.0 MiB FFFF aboot 6 9216 12287 1.5 MiB 0700 pad 7 12288 13311 512.0 KiB FFFF sbl1bak 8 13312 14335 512.0 KiB FFFF tzbak 9 14336 15359 512.0 KiB FFFF hypbak 10 15360 16383 512.0 KiB FFFF rpmbak 11 16384 20479 2.0 MiB FFFF abootbak 12 20480 53247 16.0 MiB FFFF misc 13 53248 86015 16.0 MiB 0700 persist 14 86016 87039 512.0 KiB 8301 metadata 15 87040 90111 1.5 MiB FFFF modemst1 16 90112 93183 1.5 MiB FFFF modemst2 17 93184 142335 24.0 MiB FFFF laf 18 142336 191487 24.0 MiB FFFF boot 19 191488 240639 24.0 MiB FFFF recovery 20 240640 243711 1.5 MiB FFFF fsg 21 243712 244735 512.0 KiB FFFF fsc 22 244736 245759 512.0 KiB FFFF ssd 23 245760 246783 512.0 KiB FFFF DDR 24 246784 247807 512.0 KiB FFFF sec 25 247808 248831 512.0 KiB FFFF encrypt 26 248832 249855 512.0 KiB FFFF eksst 27 249856 258047 4.0 MiB 0700 persist-lg 28 258048 266239 4.0 MiB 0700 persistent 29 266240 267263 512.0 KiB FFFF rct 30 267264 283647 8.0 MiB 0700 sns 31 283648 488447 100.0 MiB 0700 cust 32 488448 553983 32.0 MiB FFFF factory 33 553984 619519 32.0 MiB FFFF fota 34 619520 635903 8.0 MiB 0700 drm 35 635904 685055 24.0 MiB 0700 mpt 36 685056 816127 64.0 MiB 0700 modem 37 816128 5849293 2.4 GiB 0700 system 38 5849294 7590093 850.0 MiB 0700 cache 39 7590094 15077375 3.6 GiB 0700 userdata 40 15077376 15269854 94.0 MiB 0700 grow
As you can see the partitions /system/ , /cache/ and /userdata/ reside next to each other, and only the three partitions will be changed (removed and recreated). So you have to change the following lines in the BoardConfig.mk file:
BOARD_SYSTEMIMAGE_PARTITION_SIZE := 2576980992 # 2516583 * 1024 mmcblk0p37 BOARD_CACHEIMAGE_PARTITION_SIZE := 1782579200 # 1740800 * 1024 mmcblk0p38 BOARD_USERDATAIMAGE_PARTITION_SIZE := 3833488384 # 3743641 * 1024 mmcblk0p39
To something like this:
BOARD_SYSTEMIMAGE_PARTITION_SIZE := 1073741824 # 1048576 * 1024 mmcblk0p37 (1 GiB) BOARD_CACHEIMAGE_PARTITION_SIZE := 134217728 # 131072 * 1024 mmcblk0p38 (128 MiB) BOARD_USERDATAIMAGE_PARTITION_SIZE := 6985089024 # 6821376 * 1024 mmcblk0p39 (6,5 GiB)
I used the values above based on the following output:
~ # df -h Filesystem Size Used Available Use% Mounted on /dev/block/mmcblk0p37 2.3G 711.4M 1.6G 30% /system /dev/block/mmcblk0p38 823.3M 952.0K 806.4M 0% /cache /dev/block/mmcblk0p39 3.5G 1.4G 2.1G 39% /data
So as you can see both the /system/ and /cache/ partitions can be shrunk a little bit. And also don't worry about the /cache/ partition because it doesn't need much space.
Changing the size of the /system/ partition without touching the BoardConfig.mk file
Of course, not everyone wants to build the ROM from its source, and for those who don't there's another way to make any ROM work with different flash layout of the phone. In this case you'll have to repack the stock/LOS ROM and change the size of the /system/ partition. Here's how to do it (based on Debian Linux distribution).
Install the following package:
# aptitude install android-tools-fsutils brotli
That package has tools like make_ext4fs , img2simg and simg2img included, but it lacks of sdat2img, img2sdat and sefcontext_decompile, hence the three tools have to be downloaded separately. Also since Android 8.1 (OREO) the system.new.dat is compressed with (brotli)[https://github.com/google/brotli] and it has to be decompressed first, so if we deal with this version of Android, we have to install the tool as well.
Unzip the file:
$ cd /media/Android/image/ $ patool extract RR-N-v5.8.5-20180304-c90.zip patool: Extracting RR-N-v5.8.5-20180304-c90.zip ... patool: running /usr/bin/7z x -o./Unpack_re3r1me5 -- RR-N-v5.8.5-20180304-c90.zip patool: ... RR-N-v5.8.5-20180304-c90.zip extracted to `RR-N-v5.8.5-20180304-c90' (multiple files in root).
Download the tools I mentioned earlier:
$ git clone https://github.com/xpirt/img2sdat $ git clone https://github.com/xpirt/sdat2img $ git clone https://github.com/wuxianlin/sefcontext_decompile
Now we have to decompress the system.new.dat file.
$ brotli --decompress RR-N-v5.8.5-20180304-c90//system.new.dat.br $ ./sdat2img/sdat2img.py RR-N-v5.8.5-20180304-c90/system.transfer.list RR-N-v5.8.5-20180304-c90/system.new.dat system.img sdat2img binary - version: 1.0 Android Nougat 7.x / Oreo 8.x detected! Skipping command erase... Copying 1024 blocks into position 0... Copying 1024 blocks into position 1024... Copying 1024 blocks into position 2048... Copying 1024 blocks into position 3072... .... Skipping command zero... Done! Output image: system.img $ ls -alh system.img -rw-r--r-- 1 morfik morfik 2.4G 2018-03-06 14:34:28 system.img
As you can see, the system.img file is 2,4 GiB in size, which is the same as the /system/ partition's size, and that's why flashing this ZIP file always will fail on phones that have the /system/ partition touched in some way.
We also have to decompile file_contexts.bin to a text file:
$ ./sefcontext_decompile/sefcontext_decompile -o file_contexts ./RR-N-v5.8.5-20180304-c90/file_contexts.bin
Now we have to shrink the image. So open it first:
# mount -t ext4 -o loop,ro system.img /mnt
And now we create another system.img based on the /mnt folder's content:
# make_ext4fs -T 0 -S file_contexts -l 1073741824 -a system system_new.img /mnt/ Creating filesystem with parameters: Size: 1073741824 Block size: 4096 Blocks per group: 32768 Inodes per group: 8192 Inode size: 256 Journal blocks: 4096 Label: Blocks: 262144 Block groups: 8 Reserved block group size: 63 Created filesystem with 2372/65536 inodes and 187943/262144 blocks
The -l parameter says how big the resulting image should be, and as you may know, this value should be the same as in the BOARD_SYSTEMIMAGE_PARTITION_SIZE variable. Of course, we didn't change the BoardConfig.mk, and we just repartitioned the phone's flash, so the -l value should match the size of the /system/ partition, which in this case is 1024 * 1024 * 1024 = 1073741824 bytes (1 GiB).
And as we can see, we got another system.img that is 1 GiB in size:
# umount /mnt # ls -alh system_new.img -rw-r--r-- 1 root root 1.0G 2018-03-06 14:24:09 system_new.img
Now we have to compress the image:
# chown morfik:morfik system_new.img $ img2simg system_new.img system_new.img-sparse $ ls -alh system_new.img-sparse -rw-r--r-- 1 morfik morfik 697M 2018-03-06 14:27:48 system_new.img-sparse
And the last step is to convert the image to .dat format:
$ rm ./system.img $ ./img2sdat/img2sdat.py system_new.img-sparse img2sdat binary - version: 1.6 1. Android Lollipop 5.0 2. Android Lollipop 5.1 3. Android Marshmallow 6.0 4. Android Nougat 7.0/7.1/8.0 Choose system version: 4 Total of 262144 4096-byte output blocks in 2145 input chunks. Generating digraph... Finding vertex sequence... Reversing backward edges... 0/0 dependencies (0.00%) were violated; 0 source blocks stashed. Improving vertex order... Reticulating splines... max stashed blocks: 0 (0 bytes), limit: <unknown> Done! Output files: .
If we deal with Android 8.1, we also have to compress the image. The compression level can be 1-9, but bigger values cause slower compression:
$ brotli -6 system.new.dat
We should have now three additional files in the working directory:
- system.new.dat or system.new.dat.br
And those files have to be replaced in the ZIP file.
$ mv ./system.new.dat ./system.patch.dat ./system.transfer.list ./RR-N-v5.8.5-20180304-c90/ $ rm ./RR-N-v5.8.5-20180304-c90/system.new.dat $ cd ./RR-N-v5.8.5-20180304-c90/ $ zip -r update.zip * adding: META-INF/ (stored 0%) adding: META-INF/org/ (stored 0%) adding: META-INF/org/lineageos/ (stored 0%) adding: META-INF/org/lineageos/releasekey (deflated 63%) adding: META-INF/com/ (stored 0%) adding: META-INF/com/google/ (stored 0%) adding: META-INF/com/google/android/ (stored 0%) adding: META-INF/com/google/android/updater-script (deflated 73%) adding: META-INF/com/google/android/update-binary (deflated 40%) adding: META-INF/com/android/ (stored 0%) adding: META-INF/com/android/metadata (deflated 13%) adding: boot.img (deflated 2%) adding: file_contexts.bin (deflated 87%) adding: install/ (stored 0%) adding: install/bin/ (stored 0%) adding: install/bin/backuptool.sh (deflated 65%) adding: install/bin/otasigcheck.sh (deflated 65%) adding: install/bin/backuptool.functions (deflated 52%) adding: install/bin/check_features.sh (deflated 36%) adding: system/ (stored 0%) adding: system/build.prop (deflated 59%) adding: system.new.dat (deflated 52%) adding: system.patch.dat (stored 0%) adding: system.transfer.list (deflated 70%)
Now the ZIP file can be flashed to the phone, but in order to do so, we need to repartition its flash first.
Repartitioning the phone's flash
Boot LG G4C into TWRP recovery, plug the phone to your computer, and type the following command in a terminal:
$ adb shell ~ #
All of the following commands will be typed using ADB.
First of all, make a backup of the current partition table of your phone's flash. When something goes wrong you can easily go back to the point when you started. This backup is also useful when you want to revert to the stock flash layout, or when you want to pass the same partition layout to someone else (that someone will have to restore the backup).
~ # sgdisk --backup=/external_sd/backup-partition-table-lg-g4c /dev/block/mmcblk 0 The operation has completed successfully. ~ # ls -al /external_sd/backup-partition-table-lg-g4c -rwxrwxrwx 1 root root 6656 Mar 6 13:42 /external_sd/backup-partition-table-lg-g4c
Unmount the /system/ , /cache/ and /data/ partitions:
~ # umount /cache ~ # umount /data ~ # umount /sdcard ~ # umount /system
And remove the three partitions using sgdisk:
~ # ls -al /dev/block/bootdevice/by-name/ | egrep "system|cache|userdata" lrwxrwxrwx 1 root root 21 Jan 7 1970 cache -> /dev/block/mmcblk0p38 lrwxrwxrwx 1 root root 21 Jan 7 1970 system -> /dev/block/mmcblk0p37 lrwxrwxrwx 1 root root 21 Jan 7 1970 userdata -> /dev/block/mmcblk0p39 ~ # sgdisk --delete=37 /dev/block/mmcblk0 ~ # sgdisk --delete=38 /dev/block/mmcblk0 ~ # sgdisk --delete=39 /dev/block/mmcblk0
Now all the three partitions are gone, and we have to recreate them with the sizes we wanted at the beginning of this HOWTO.
Fist look at the partition table. We need to know what's the end sector of the partition that was before the /system/ partition:
~ # sgdisk --print /dev/block/mmcblk0 Number Start (sector) End (sector) Size Code Name ... 36 685056 816127 64.0 MiB 0700 modem 40 15077376 15269854 94.0 MiB 0700 grow
So in this case we have 816127, and in the next one (816128) the /system/ partition should begin. It's size will be 1 GiB, so create it:
~ # sgdisk --new=37:816128:+1024M /dev/block/mmcblk0 ~ # sgdisk --change-name=37:system /dev/block/mmcblk0 ~ # sgdisk --typecode=37:0700 /dev/block/mmcblk0
In the same way we create the /cache/ partition:
~ # sgdisk --print /dev/block/mmcblk0 Number Start (sector) End (sector) Size Code Name ... 36 685056 816127 64.0 MiB 0700 modem 37 816128 2913279 1024.0 MiB 0700 system 40 15077376 15269854 94.0 MiB 0700 grow ~ # sgdisk --new=38:2913280:+128M /dev/block/mmcblk0 ~ # sgdisk --change-name=38:cache /dev/block/mmcblk0 ~ # sgdisk --typecode=38:0700 /dev/block/mmcblk0
And now we create the /userdata/ partition, but in this case we don't use size, instead we use a sector that precedes the partition number 40:
~ # sgdisk --print /dev/block/mmcblk0 Number Start (sector) End (sector) Size Code Name 36 685056 816127 64.0 MiB 0700 modem 37 816128 2913279 1024.0 MiB 0700 system 38 2913280 3175423 128.0 MiB 0700 cache 40 15077376 15269854 94.0 MiB 0700 grow ~ # sgdisk --new=39:3175424:15077375 /dev/block/mmcblk0 ~ # sgdisk --change-name=39:userdata /dev/block/mmcblk0 ~ # sgdisk --typecode=39:0700 /dev/block/mmcblk0
Now we check whether everything is as it should be:
~ # sgdisk --print /dev/block/mmcblk0 Number Start (sector) End (sector) Size Code Name ... 36 685056 816127 64.0 MiB 0700 modem 37 816128 2913279 1024.0 MiB 0700 system 38 2913280 3175423 128.0 MiB 0700 cache 39 3175424 15077375 5.7 GiB 0700 userdata 40 15077376 15269854 94.0 MiB 0700 grow
We format all the three newly created partitions with ext4 file system:
~ # mke2fs -t ext4 /dev/block/bootdevice/by-name/system ~ # mke2fs -t ext4 /dev/block/bootdevice/by-name/cache ~ # mke2fs -t ext4 /dev/block/bootdevice/by-name/userdata
The above step should be be done via TWRP GUI in order to avoid problems with directory structure. Just go under Wipe => Advanced Wipe and wipe everything except external SD card.
Flashing the ROM
Everything is set up, so we can finally flash the repacked ROM using TWRP. You do it just like you would do in the case of any other ROM. Don't forget to mount the /cache/ partition if it's not mounted already (also if there's no recovery dir on it, create it):
# mount /cache # mkdir /cache/recovery/
And flash the ZIP file using the install menu or via ADB sideload. After the process is finished, clear everything except the /system/ partition. If there's no errors, it means that the process was successful and you can reboot your phone.
Reverting to the stock partition table
In order to revert to the stock partition table, you have to restore the backup you had created earlier. Of course, this will restore only the partition layout and won't recreate file systems on the /system/, /cache/ and /data/ partitions -- this has to be done in a separate step.
To restore the partition table, boot into the TWRP recovery and type the following command into its terminal or via ADB:
~ # sgdisk --load-backup /external_sd/backup-partition-table-lg-g4c /dev/block/mmcblk0 The operation has completed successfully.
You can check whether the partitions were reverted to their stock sizes:
~ # sgdisk --print /dev/block/mmcblk0 ... Number Start (sector) End (sector) Size Code Name ... 37 816128 5849293 2.4 GiB 0700 system 38 5849294 7590093 850.0 MiB 0700 cache 39 7590094 15077375 3.6 GiB 0700 userdata ...
The file system of each partition can be created manually via "mke2fs -t ext4" or you can use the TWRP GUI and format the /system/ , /cache/ and /data/ partition from the menu.