Skip to content

Instantly share code, notes, and snippets.

@morfikov
Last active April 24, 2018 14:26
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save morfikov/2cb0f2d16aa4435cf274b4aa2b372cf4 to your computer and use it in GitHub Desktop.
Save morfikov/2cb0f2d16aa4435cf274b4aa2b372cf4 to your computer and use it in GitHub Desktop.
How to change the default flash layout of the LG G4C phone in oder to make more space for user data

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.

Let's begin with downloading the ZIP file for LG G4C phone. You can download it from the links: LineageOS for LG G4C, RR-N for LG G4C

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
  • system.patch.dat
  • system.transfer.list

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.

@morfikov
Copy link
Author

morfikov commented Mar 19, 2018

The Backup of both partition tables (the stock one and the resized one) can be also found here:
https://app.box.com/s/kkk5xzf32gl0ehgxdlak9owls8wmqf20

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment