Upgrade Nexus 4 to LineageOS 16.0
I recently found my Nexus 4 after the move and wanted to get it usable again. It was running the last official version of Android, 5.1.1, for the device from November 2014. LineageOS dropped support for it several years ago, the device was released in 2012, so I hoped to find either the last nightly build or an unofficial build of something more recent. I found an install guide for the device that I used when installing LineageOS.
Partitioning
First however, I needed to repartition /system
because the original partition size was no longer large enough.
There were scripts out there to manage the partitioning but as an experienced Linux sysadmin I opted to do it myself.
I also didn’t search hard and realize the scripts existed before trying.
I installed android-tools
from Fedora’s repositories, plugged in the phone, and got it work.
I could adb reboot
and adb shell
all I wanted but fastboot
and adb sideload
refused to work.
The install guide mentioned this so I connected through a USB 3.0 hub and that fixed all of the sideload and fastboot
problems.
With fastboot
working, I booted the latest TWRP image for the Nexus 4.
# adb reboot bootloader
# fastboot boot /path/to/tmp/lineageos/twrp-3.5.2_9-0-mako.img
Sending 'boot.img' (10528 KB) OKAY [ 0.431s]
Booting OKAY [ 0.030s]
Finished. Total time: 0.486s
From an unofficial image thread, I knew I needed /system
to be at least 1272 MB.
I ran adb shell
, mounted /system
, and checked its size to see it was only 827 MB.
Following an answer on Android StackExchange on repartitioning a different device, I set out to increase /system
.
I pushed a statically linked parted
(I didn’t need gdisk
but pushed it anyway).
# adb push /path/to/tmp/lineageos/parted /
/path/to/tmp/lineageos/parted: 1 file pushed, 0 skipped. 591.9 MB/s (464372 bytes in 0.001s)
Now shell in, mark /parted
as executable for later, and check the partition layout.
# adb shell
~ # chmod +x /parted
~ # fdisk -l /dev/block/mmcblk0
Found valid GPT with protective MBR; using GPT
Disk /dev/block/mmcblk0: 30777344 sectors, 2740M
Logical sector size: 512
Disk identifier (GUID): 98101b32-bbe2-4bf2-a06e-2bb33d000c20
Partition table holds up to 28 entries
First usable sector is 34, last usable sector is 30777310
Number Start (sector) End (sector) Size Code Name
1 1024 132095 64.0M 0700 modem
2 132096 133119 512K 0700 sbl1
3 133120 134143 512K 0700 sbl2
4 134144 138239 2048K 0700 sbl3
5 138240 139263 512K 0700 tz
6 139264 184319 22.0M 0700 boot
7 184320 229375 22.0M 0700 recovery
8 229376 230935 780K 0700 m9kefs1
9 230936 232495 780K 0700 m9kefs2
10 232496 234055 780K 0700 m9kefs3
11 234496 235519 512K 0700 rpm
12 235520 236543 512K 0700 aboot
13 236544 237567 512K 0700 sbl2b
14 237568 241663 2048K 0700 sbl3b
15 241664 242687 512K 0700 abootb
16 242688 243711 512K 0700 rpmb
17 243712 244735 512K 0700 tzb
18 244736 245759 512K 0700 metadata
19 245760 278527 16.0M 0700 misc
20 278528 311295 16.0M 0700 persist
21 311296 2031615 840M 0700 system
22 2031616 3178495 560M 0700 cache
23 3178496 30775295 13.1G 0700 userdata
24 30775296 30776319 512K 0700 DDR
25 30776320 30777310 495K 0700 grow
/system
is partition 21.
In order to resize it, I need to move at least the next partition.
/cache
is next but at 560 MB, it was not large enough and I would also need to shrink userdata (or /data
).
I saved the above layout in case I needed to redo it exactly. NOTE, I already unlocked the bootloader and wiped everything but if you haven’t, this will reformat and lose everything and you must start from scratch.
Unmount partitions 21, 22, and 23 if mounted.
~ # df -h
Filesystem Size Used Available Use% Mounted on
tmpfs 935.1M 20.0K 935.1M 0% /dev
tmpfs 935.1M 16.0K 935.1M 0% /tmp
/dev/block/mmcblk0p23
12.9G 129.6M 12.8G 1% /data
/dev/block/mmcblk0p23
12.9G 129.6M 12.8G 1% /sdcard
/dev/block/mmcblk0p22
551.7M 9.8M 541.9M 2% /cache
~ # umount /sdcard /data /cache
Delete partitions 21, 22, and 23.
~ # /parted /dev/block/mmcblk0
GNU Parted 3.2
Using /dev/block/mmcblk0
...
(parted) print
Error: The backup GPT table is corrupt, but the primary appears OK, so that will
be used.
OK/Cancel? ok
The backup GPT being corrupt was disconcerting but I couldn’t do anything about it so accepted and continued onward.
The StackExchange answer used parted
’s resizepart
but that only works if there’s space after the partition.
There is zero free space here so must delete and recreate.
Model: MMC 016G92 (sd/mmc)
Disk /dev/block/mmcblk0: 15.8GB
Sector size (logical/physical): 512B/512B
Partition Table: gpt
Disk Flags:
Number Start End Size File system Name Flags
1 524kB 67.6MB 67.1MB fat16 modem msftdata
2 67.6MB 68.2MB 524kB sbl1
3 68.2MB 68.7MB 524kB sbl2
4 68.7MB 70.8MB 2097kB sbl3
5 70.8MB 71.3MB 524kB tz
6 71.3MB 94.4MB 23.1MB boot
7 94.4MB 117MB 23.1MB recovery
8 117MB 118MB 799kB m9kefs1
9 118MB 119MB 799kB m9kefs2
10 119MB 120MB 799kB m9kefs3
11 120MB 121MB 524kB rpm
12 121MB 121MB 524kB aboot
13 121MB 122MB 524kB sbl2b
14 122MB 124MB 2097kB sbl3b
15 124MB 124MB 524kB abootb
16 124MB 125MB 524kB rpmb
17 125MB 125MB 524kB tzb
18 125MB 126MB 524kB metadata
19 126MB 143MB 16.8MB misc
20 143MB 159MB 16.8MB ext4 persist
21 159MB 1040MB 881MB ext4 system
22 1040MB 1627MB 587MB ext4 cache
23 1627MB 15.8GB 14.1GB ext4 userdata
24 15.8GB 15.8GB 524kB DDR
25 15.8GB 15.8GB 507kB grow
(parted) rm 21
(parted) rm 22
(parted) rm 23
I switched the units to sectors to get the partition math exactly correct.
I did not think using MB, or anything other than only B(ytes), would be precise enough and using bytes could cause a partition to not end on a sector boundary.
parted
warned if I did not end on a good boundary, I think every 2 MB?
When doing the sector math, I ensured the three partitions ended on a 2 MB boundary and parted
was satisfied.
(parted) unit S
(parted) print
Model: MMC 016G92 (sd/mmc)
Disk /dev/block/mmcblk0: 30777344s
Sector size (logical/physical): 512B/512B
Partition Table: gpt
Disk Flags:
Number Start End Size File system Name Flags
1 1024s 132095s 131072s fat16 modem msftdata
2 132096s 133119s 1024s sbl1
3 133120s 134143s 1024s sbl2
4 134144s 138239s 4096s sbl3
5 138240s 139263s 1024s tz
6 139264s 184319s 45056s boot
7 184320s 229375s 45056s recovery
8 229376s 230935s 1560s m9kefs1
9 230936s 232495s 1560s m9kefs2
10 232496s 234055s 1560s m9kefs3
11 234496s 235519s 1024s rpm
12 235520s 236543s 1024s aboot
13 236544s 237567s 1024s sbl2b
14 237568s 241663s 4096s sbl3b
15 241664s 242687s 1024s abootb
16 242688s 243711s 1024s rpmb
17 243712s 244735s 1024s tzb
18 244736s 245759s 1024s metadata
19 245760s 278527s 32768s misc
20 278528s 311295s 32768s ext4 persist
21 311296s 2811295s 2500000s ext4 system
24 30775296s 30776319s 1024s DDR
25 30776320s 30777310s 991s grow
(parted) mkpart primary ext4 311296s 3178495s
(parted) mkpart primary ext4 3178496s 4202495s
(parted) mkpart primary ext4 4202496s 30775295s
(parted) print
Model: MMC 016G92 (sd/mmc)
Disk /dev/block/mmcblk0: 30777344s
Sector size (logical/physical): 512B/512B
Partition Table: gpt
Disk Flags:
Number Start End Size File system Name Flags
1 1024s 132095s 131072s fat16 modem msftdata
2 132096s 133119s 1024s sbl1
3 133120s 134143s 1024s sbl2
4 134144s 138239s 4096s sbl3
5 138240s 139263s 1024s tz
6 139264s 184319s 45056s boot
7 184320s 229375s 45056s recovery
8 229376s 230935s 1560s m9kefs1
9 230936s 232495s 1560s m9kefs2
10 232496s 234055s 1560s m9kefs3
11 234496s 235519s 1024s rpm
12 235520s 236543s 1024s aboot
13 236544s 237567s 1024s sbl2b
14 237568s 241663s 4096s sbl3b
15 241664s 242687s 1024s abootb
16 242688s 243711s 1024s rpmb
17 243712s 244735s 1024s tzb
18 244736s 245759s 1024s metadata
19 245760s 278527s 32768s misc
20 278528s 311295s 32768s ext4 persist
21 311296s 3178495s 2867200s ext4
22 3178496s 4202495s 1024000s ext4
23 4202496s 30775295s 26572800s ext4
24 30775296s 30776319s 1024s DDR
25 30776320s 30777310s 991s grow
(parted) name 21 system
(parted) name 22 cache
(parted) name 23 userdata
(parted) unit MB
(parted) print
Model: MMC 016G92 (sd/mmc)
Disk /dev/block/mmcblk0: 15758MB
Sector size (logical/physical): 512B/512B
Partition Table: gpt
Disk Flags:
Number Start End Size File system Name Flags
1 0.52MB 67.6MB 67.1MB fat16 modem msftdata
2 67.6MB 68.2MB 0.52MB sbl1
3 68.2MB 68.7MB 0.52MB sbl2
4 68.7MB 70.8MB 2.10MB sbl3
5 70.8MB 71.3MB 0.52MB tz
6 71.3MB 94.4MB 23.1MB boot
7 94.4MB 117MB 23.1MB recovery
8 117MB 118MB 0.80MB m9kefs1
9 118MB 119MB 0.80MB m9kefs2
10 119MB 120MB 0.80MB m9kefs3
11 120MB 121MB 0.52MB rpm
12 121MB 121MB 0.52MB aboot
13 121MB 122MB 0.52MB sbl2b
14 122MB 124MB 2.10MB sbl3b
15 124MB 124MB 0.52MB abootb
16 124MB 125MB 0.52MB rpmb
17 125MB 125MB 0.52MB tzb
18 125MB 126MB 0.52MB metadata
19 126MB 143MB 16.8MB misc
20 143MB 159MB 16.8MB ext4 persist
21 159MB 1627MB 1468MB ext4 system
22 1627MB 2152MB 524MB ext4 cache
23 2152MB 15757MB 13605MB ext4 userdata
24 15757MB 15757MB 0.52MB DDR
25 15757MB 15758MB 0.51MB grow
Partitions created.
I shrunk /cache
from 587 MB to 524 MB and /data
from 14.1 GB to 13.6 GB.
/system
went from 881 MB to 1468 MB.
Creating File Systems
Next re-created the ext4 file system for the three partitions.
~ # make_ext4fs /dev/block/mmcblk0p21
Creating filesystem with parameters:
Size: 1468006400
Block size: 4096
Blocks per group: 32768
Inodes per group: 8160
Inode size: 256
Journal blocks: 5600
Label:
Blocks: 358400
Block groups: 11
Reserved block group size: 87
Created filesystem with 11/89760 inodes and 11769/358400 blocks
~ # make_ext4fs /dev/block/mmcblk0p22
Creating filesystem with parameters:
Size: 524288000
Block size: 4096
Blocks per group: 32768
Inodes per group: 8000
Inode size: 256
Journal blocks: 2000
Label:
Blocks: 128000
Block groups: 4
Reserved block group size: 31
Created filesystem with 11/32000 inodes and 4110/128000 blocks
~ # make_ext4fs /dev/block/mmcblk0p23
Creating filesystem with parameters:
Size: 13605273600
Block size: 4096
Blocks per group: 32768
Inodes per group: 8144
Inode size: 256
Journal blocks: 32768
Label:
Blocks: 3321600
Block groups: 102
Reserved block group size: 815
Created filesystem with 11/830688 inodes and 93063/3321600 blocks
~ # e2fsck -f /dev/block/mmcblk0p21
e2fsck 1.42.9 (28-Dec-2013)
Pass 1: Checking inodes, blocks, and sizes
Pass 2: Checking directory structure
Pass 3: Checking directory connectivity
Pass 4: Checking reference counts
Pass 5: Checking group summary information
system: 2563/53760 files (0.0% non-contiguous), 176829/215040 blocks
~ # resize2fs /dev/block/mmcblk0p21
resize2fs 1.42.9 (28-Dec-2013)
Resizing the filesystem on /dev/block/mmcblk0p21 to 358400 (4k) blocks.
The filesystem on /dev/block/mmcblk0p21 is now 358400 blocks long.
I forgot to verify if /system
was created as a 1.4 GB file system or as 827 MB but resize2fs
grew the file system so I assume it was too small.
One last check that /etc/fstab
will function
~ # cat /etc/fstab
/dev/block/mmcblk0p21 /system ext4 rw 0 0
/dev/block/mmcblk0p23 /data ext4 rw 0 0
/dev/block/mmcblk0p22 /cache ext4 rw 0 0
~ # mount /system
~ # mount /data
~ # mount /cache
~ # df -h
Filesystem Size Used Available Use% Mounted on
tmpfs 935.1M 20.0K 935.1M 0% /dev
tmpfs 935.1M 16.0K 935.1M 0% /tmp
/dev/block/mmcblk0p21
1.3G 26.2M 1.3G 2% /system
/dev/block/mmcblk0p23
12.4G 129.5M 12.3G 1% /data
/dev/block/mmcblk0p22
492.6M 8.6M 483.9M 2% /cache
Installing LineageOS
I tried to sideload the image now but there were errors about unable to detect filesystem for /dev/block/platform/msm_sdcc.1/by-name/system
.
I rebooted, skipped through the warning about no OS, and booted the recovery image again from fastboot.
I had numerous issues when trying to sideload the last nightly LineageOS 15.1 image for the Nexus 4 along with the matching Open GApps.
That image resized /system
back to 827 MB each time.
After growing it again to sideload Open GApps, rebooting would load LineageOS only for it to reboot into the recovery image.
What did work was the unofficial image created by voron00 and the matching Open GApps for Android 9.0, micro version.
The LineageOS 15.1 image also shrunk /system
a small amount that I grew back to its maximum size before sideloading Open GApps.
# adb sideload /path/to/tmp/lineageos/lineage-16.0-20210311-UNOFFICIAL-mako-signed.zip
Total xfer: 1.00x
# adb shell
# ...resizing again...
# adb sideload /path/to/tmp/lineageos/open_gapps-arm-9.0-micro-20210409.zip
Total xfer: 1.07x
# adb reboot
I watched the LineageOS boot screen for a long time and then the Android 9.0 startup screen appeared. I breezed through the setup and the device was ready.
I also have the Nexus 7 from 2012 (code name grouper) that suffers from the same problem. Next up, moving that to something newer than the CyanogenMod 12.1 install.