Nexus 7 (2013) postmarketOS Install
The Nexus 7 (2012) was the first tablet I liked a tablet. The small size meant it was similar to a small book and easy to carry (and can fits in men’s jeans front and back pockets). The follow-up Nexus 7 (2013; a.k.a. 2nd gen) was the same but much better hardware (better screen, flash, RAM).
To this day I still use the device for e-book reading, but the OS is woefully out-of-date. I’ve been wanting to play with postmarketOS. The 2012 tablet is in pmOS’s community category (pmOS device asus-grouper) so it’d be the better candidate, but the one I quickly found wouldn’t turn on after charging. The screen just flashed garbage for a split-second. (Of course, trying now has it booting…) So I tried my hand with the 2013 tablet which is in pmOS’s testing category (pmOS device asus-flo). The pmOS chipset Qualcomm APQ8064 page also had some info.
I first installed TWRP using the “Fastboot install method” to backup the system. This worked well, as did using USB-OTG with a USB thumb drive for storing the backup itself.
For pmOS itself, I followed the Using pmbootstrap install method. That shouldn’t have been too bad, mostly:
# pacman -S pmbootstrap
$ pmbootstrap init # answer lots of questions
$ pmbootstrap install
$ pmbootstrap flasher flash_rootfs # to userdata; system is too small
$ pmbootstrap flasher flash_kernel
However, flash_rootfs
failed:
$ pmbootstrap flasher flash_rootfs
[14:42:27] (native) flash rootfs image
[14:42:28] (native) install android-tools
Sending 'userdata' (2060288 KB) FAILED (remote: 'data too large')
fastboot: error: Command failed
Using pmbootstrap export
I was able to try running fastboot myself, but it
failed in the same way. And the device didn’t understand sparse files (-S 512M
).
$ fastboot flash userdata /tmp/postmarketOS-export/asus-flo.img
Sending 'userdata' (2060288 KB) FAILED (remote: 'data too large')
fastboot: error: Command failed
$ fastboot flash userdata -S 512M /tmp/postmarketOS-export/asus-flo.img
Sending sparse 'userdata' 1/3 (523464 KB) OKAY [ 16.669s]
Writing 'userdata' FAILED (remote: 'Unknown chunk type')
fastboot: error: Command failed
The “userdata” partition is 13 GB, so it should have plenty of space. The “system” partition is indeed too small at 880 MB.
$ fastboot getvar all
(bootloader) version-bootloader: FLO-04.08
(bootloader) version-baseband: none
(bootloader) version-hardware: rev_e
(bootloader) version-cdma: N/A
(bootloader) variant: flo 16G
(bootloader) serialno: 07d38b3e
(bootloader) product: flo
(bootloader) secure_boot: enabled
(bootloader) lock_state: unlocked
(bootloader) project: flo
(bootloader) off-mode-charge: yes
(bootloader) uart-on: no
(bootloader) partition-type:bootloader: emmc
(bootloader) partition-size:bootloader: 0x0000000000aee000
(bootloader) partition-type:recovery: emmc
(bootloader) partition-size:recovery: 0x0000000000a00000
(bootloader) partition-type:boot: emmc
(bootloader) partition-size:boot: 0x0000000001000000
(bootloader) partition-type:system: ext4
(bootloader) partition-size:system: 0x0000000034800000
(bootloader) partition-type:cache: ext4
(bootloader) partition-size:cache: 0x0000000023000000
(bootloader) partition-type:userdata: ext4
(bootloader) partition-size:userdata: 0x000000031b3fbe00
all:
Finished. Total time: 0.025s
The problem seems to be the entire file is buffered in RAM before anything is
written, so anything near or larger than 2 GiB is out of the question. I tried
Installation from recovery
mode and
it failed on the device as well. I was able to use the pmOS console
UI, as it
was smaller. I also was able to write the larger image by copying it to a USB
flash stick, plugging that in with USB-OTG, going into TWRP’s shell and running
dd
. But as I was playing with the pmOS UI options and kernels, I wasn’t
willing to do that more than once.
I figured out the ideal workaround: Boot into recovery mode (TWRP) and use adb push
to write directly to the userdata partition.
$ adb push /tmp/postmarketOS-export/asus-flo.img /dev/block/mmcblk0p30
To see the partition ids, I looked at the by-name mapping in /dev:
$ adb shell
# ls -l /dev/block/platform/msm_sdcc.1/by-name/userdata
lrwxrwxrwx 1 root root 21 Oct 5 21:43 /dev/block/platform/msm_sdcc.1/by-name/userdata -> /dev/block/mmcblk0p30
However, I found fdisk was also available in TWRP, so that’s probably the easier option:
# 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): ...
Partition table holds up to 32 entries
First usable sector is 34, last usable sector is 30777310
Number Start (sector) End (sector) Size Code Name
1 131072 306143 85.4M 0700 radio
2 393216 399359 3072K 0700 modemst1
3 399360 405503 3072K 0700 modemst2
4 524288 554287 14.6M 0700 persist
5 655360 656919 780K 0700 m9kefs1
6 656920 658479 780K 0700 m9kefs2
7 786432 787991 780K 0700 m9kefs3
8 787992 794135 3072K 0700 fsg
9 917504 920503 1500K 0700 sbl1
10 920504 923503 1500K 0700 sbl2
11 923504 927599 2048K 0700 sbl3
12 927600 937839 5120K 0700 aboot
13 937840 938863 512K 0700 rpm
14 1048576 1081343 16.0M 0700 boot
15 1179648 1180671 512K 0700 tz
16 1180672 1180673 1024 0700 pad
17 1180674 1183673 1500K 0700 sbl2b
18 1183674 1187769 2048K 0700 sbl3b
19 1187770 1198009 5120K 0700 abootb
20 1198010 1199033 512K 0700 rpmb
21 1199034 1200057 512K 0700 tzb
22 1310720 3031039 840M 0700 system
23 3031040 4177919 560M 0700 cache
24 4194304 4196351 1024K 0700 misc
25 4325376 4345855 10.0M 0700 recovery
26 4456448 4456463 8192 0700 DDR
27 4456464 4456479 8192 0700 ssd
28 4456480 4456481 1024 0700 m9kefsc
29 4587520 4587583 32768 0700 metadata
30 4718592 30777310 12.4G 0700 userdata
I ended up avoiding Full Disk Encryption (FDE) because unl0kr made the boot
image too large. It sounds like this could be fixed by using
deviceinfo_create_initfs_extra
,
but I didn’t test it.
Using USB Internet worked great, but the device needed to be plugged into my host when it booted.
$ ssh 172.16.42.1 # connect to device
$ sudo ip route add default via 172.16.42.2 dev usb0
$ echo nameserver 1.1.1.1 > /etc/resolv.conf # only needed first boot
When the screen turned off after going idle, I couldn’t figure out how to turn it back on. So SSH was pretty useful.
You can apparently get UART access through the headphone jack, which looks relatively easy. The page it references for the Nexus 4 UART is available on archive.org. But I didn’t have trouble booting into the kernels, so SSH was sufficient.
The 4.11 kernel won’t work well with systemd, so while I did at one point try it, I was hoping the newer kernel would work better. Most of my testing was with 5.10.98-postmarketos-qcom-apq8064.
While the screen worked for the plain terminal, there was no DRM device for
Phosh. dmesg
showed it didn’t have the firmware:
[ 2.798974] [drm] Initialized msm 1.6.0 20130625 for 5100000.mdp on minor 0
[ 2.799480] msm 5100000.mdp: Direct firmware load for qcom/a300_pm4.fw failed with error -2
[ 2.804866] msm 5100000.mdp: Falling back to sysfs fallback for: qcom/a300_pm4.fw
[ 64.470868] msm 5100000.mdp: [drm:adreno_request_fw] *ERROR* failed to load a300_pm4.fw
I found the file in my backup at system.ext4/vendor/firmware/
, but I also
found it was already available on the root disk at
/usr/lib/firmware/postmarketos/
. lsmod
showed no modules, so I couldn’t
reload the module for it to re-probe for the firmware.
I was glad it is so easy to add files to the
initrd. I created
50-asus-flo.files (with sudo
), and then updated the boot partition with
fastboot.
$ cat ~/.local/var/pmbootstrap/chroot_rootfs_asus-flo/usr/share/mkinitfs/files/50-asus-flo.files
/usr/lib/firmware/postmarketos/a300_pm4.fw:/usr/lib/firmware/qcom/a300_pm4.fw
/usr/lib/firmware/postmarketos/a300_pfp.fw:/usr/lib/firmware/qcom/a300_pfp.fw
$ pmbootstrap initfs # Not necessary, as the next command does this
$ pmbootstrap flasher flash_kernel
Using mkinitfs
on the device wasn’t enough, because that just updated /boot
(which lives as a subpartition of “userdata”). I didn’t see instructions for
how to make the Android boot image to write to the “boot” partition. But
writing it using pmbootstrap from the host was easy.
That then allows DRM to load, but the card hangs on initialization:
Oct 05 15:55:48 asus-flo phoc[522]: [backend/drm/backend.c:225] Initializing DRM backend for /dev/dri/card0 (msm)
Oct 05 15:55:48 asus-flo phoc[522]: [backend/drm/drm.c:310] Found 2 DRM CRTCs
Oct 05 15:55:48 asus-flo phoc[522]: [backend/drm/drm.c:268] Found 4 DRM planes
Oct 05 15:55:48 asus-flo phoc[522]: [render/egl.c:205] Supported EGL client extensions: EGL_EXT_client_extensions EGL_EXT_device_base EGL_EXT_device_enumeration EGL_EXT_device_query EGL_EXT_platform_base EGL_KHR_client_get_all_proc_addresses EGL_KHR_debug EGL_EXT_platform_device EGL_EXT_explicit_device EGL_EXT_platform_wayland EGL_KHR_platform_wayland EGL_EXT_platform_x11 EGL_KHR_platform_x11 EGL_EXT_platform_xcb EGL_MESA_platform_gbm EGL_KHR_platform_gbm EGL_MESA_platform_surfaceless
Oct 05 15:55:49 asus-flo phoc[522]: [render/egl.c:369] Using EGL 1.5
Oct 05 15:55:49 asus-flo phoc[522]: [render/egl.c:370] Supported EGL display extensions: EGL_ANDROID_blob_cache EGL_ANDROID_native_fence_sync EGL_EXT_config_select_group EGL_EXT_create_context_robustness EGL_EXT_image_dma_buf_import EGL_EXT_image_dma_buf_import_modifiers EGL_EXT_query_reset_notification_strategy EGL_EXT_surface_compression EGL_IMG_context_priority EGL_KHR_cl_event2 EGL_KHR_config_attribs EGL_KHR_context_flush_control EGL_KHR_create_context EGL_KHR_create_context_no_error EGL_KHR_fence_sync EGL_KHR_get_all_proc_addresses EGL_KHR_gl_colorspace EGL_KHR_gl_renderbuffer_image EGL_KHR_gl_texture_2D_image EGL_KHR_gl_texture_3D_image EGL_KHR_gl_texture_cubemap_image EGL_KHR_image_base EGL_KHR_no_config_context EGL_KHR_reusable_sync EGL_KHR_surfaceless_context EGL_EXT_pixel_format_float EGL_KHR_wait_sync EGL_MESA_configless_context EGL_MESA_gl_interop EGL_MESA_image_dma_buf_export EGL_MESA_query_driver EGL_MESA_x11_native_visual_id
Oct 05 15:55:49 asus-flo phoc[522]: [render/egl.c:372] Supported EGL device extensions: EGL_EXT_device_drm EGL_EXT_device_drm_render_node EGL_EXT_device_query_name EGL_EXT_device_persistent_id
Oct 05 15:55:49 asus-flo phoc[522]: [render/egl.c:374] EGL vendor: Mesa Project
Oct 05 15:55:49 asus-flo phoc[522]: [render/egl.c:376] EGL driver name: msm
Oct 05 15:55:49 asus-flo phoc[522]: [render/egl.c:447] Failed to obtain a high priority context
Oct 05 15:55:49 asus-flo phoc[522]: [render/gles2/renderer.c:538] Creating GLES2 renderer
Oct 05 15:55:49 asus-flo phoc[522]: [render/gles2/renderer.c:539] Using OpenGL ES 3.0 Mesa 25.2.4
Oct 05 15:55:49 asus-flo phoc[522]: [render/gles2/renderer.c:540] GL vendor: freedreno
Oct 05 15:55:49 asus-flo phoc[522]: [render/gles2/renderer.c:541] GL renderer: FD320
Oct 05 15:55:49 asus-flo phoc[522]: [render/gles2/renderer.c:542] Supported GLES2 extensions: GL_EXT_blend_minmax GL_EXT_multi_draw_arrays GL_EXT_texture_filter_anisotropic GL_EXT_texture_compression_s3tc GL_EXT_texture_compression_dxt1 GL_EXT_texture_compression_rgtc GL_EXT_texture_format_BGRA8888 GL_OES_compressed_ETC1_RGB8_texture GL_OES_depth24 GL_OES_element_index_uint GL_OES_fbo_render_mipmap GL_OES_mapbuffer GL_OES_rgb8_rgba8 GL_OES_standard_derivatives GL_OES_stencil8 GL_OES_texture_3D GL_OES_texture_float GL_OES_texture_half_float GL_OES_texture_half_float_linear GL_OES_texture_npot GL_OES_vertex_half_float GL_EXT_draw_instanced GL_EXT_texture_sRGB_decode GL_OES_EGL_image GL_OES_depth_texture GL_OES_packed_depth_stencil GL_AMD_compressed_ATC_texture GL_EXT_texture_type_2_10_10_10_REV GL_NV_conditional_render GL_OES_get_program_binary GL_APPLE_texture_max_level GL_EXT_discard_framebuffer GL_EXT_read_format_bgra GL_EXT_texture_storage GL_NV_pack_subimage GL_NV_texture_barrier GL_EXT_frag_depth GL_NV_fbo_color_attachments GL_OES_EGL_image_external GL_OES_EGL_sync GL_OES_vertex_array_object GL_ANGLE_pack_reverse_row_order GL_ANGLE_texture_compression_dxt3 GL_ANGLE_texture_compression_dxt5 GL_EXT_occlusion_query_boolean GL_EXT_robustness GL_EXT_texture_rg GL_EXT_unpack_subimage GL_NV_draw_buffers GL_NV_read_buffer GL_NV_read_depth GL_NV_read_depth_stencil GL_NV_read_stencil GL_APPLE_sync GL_EXT_draw_buffers GL_EXT_instanced_arrays GL_EXT_map_buffer_range GL_EXT_shadow_samplers GL_KHR_debug GL_KHR_robustness GL_KHR_texture_compression_astc_ldr GL_NV_generate_mipmap_sRGB GL_NV_pixel_buffer_object GL_OES_depth_texture_cube_map GL_OES_required_internalformat GL_OES_surfaceless_context GL_EXT_color_buffer_float GL_EXT_debug_label GL_EXT_sRGB_write_control GL_EXT_separate_shader_objects GL_EXT_shader_integer_mix GL_EXT_compressed_ETC1_RGB8_sub_texture GL_EXT_draw_buffers_indexed GL_EXT_draw_elements_base_vertex GL_EXT_texture_border_clamp GL_KHR_context_flush_control GL_KHR_robust_buffer_access_behavior GL_NV_shader_noperspective_interpolation GL_OES_draw_buffers_indexed GL_OES_draw_elements_base_vertex GL_OES_texture_border_clamp GL_EXT_blend_func_extended GL_EXT_float_blend GL_EXT_texture_sRGB_R8 GL_EXT_texture_sRGB_RG8 GL_KHR_no_error GL_KHR_texture_compression_astc_sliced_3d GL_OES_EGL_image_external_essl3 GL_EXT_conservative_depth GL_EXT_texture_compression_s3tc_srgb GL_MESA_shader_integer_functions GL_EXT_clip_control GL_EXT_color_buffer_half_float GL_EXT_memory_object GL_EXT_memory_object_fd GL_EXT_semaphore GL_EXT_semaphore_fd GL_EXT_texture_compression_bptc GL_EXT_texture_mirror_clamp_to_edge GL_KHR_parallel_shader_compile GL_EXT_EGL_image_storage GL_MESA_framebuffer_flip_y GL_EXT_depth_clamp GL_MESA_sampler_objects GL_EXT_EGL_image_storage_compression GL_EXT_texture_storage_compression GL_MESA_bgra GL_MESA_texture_const_bandwidth
Oct 05 15:55:50 asus-flo phoc[522]: Running compositor on wayland display 'wayland-0'
Oct 05 15:55:50 asus-flo phoc[522]: [backend/drm/drm.c:1741] Scanning DRM connectors on /dev/dri/card0
Oct 05 15:55:50 asus-flo phoc[522]: [backend/drm/drm.c:1796] Found connector 'DSI-1'
Oct 05 15:55:50 asus-flo phoc[522]: [backend/drm/drm.c:1821] 'DSI-1' connected
Oct 05 15:55:50 asus-flo phoc[522]: [backend/drm/drm.c:1610] Detected modes:
Oct 05 15:55:50 asus-flo phoc[522]: [backend/drm/drm.c:1634] 1200x1920 @ 60.000 Hz
Oct 05 15:55:50 asus-flo phoc[522]: MESA: warning: Failed to set BO metadata with DRM_MSM_GEM_INFO: -22
Oct 05 15:55:50 asus-flo phoc[522]: [backend/drm/drm.c:1671] Physical size: 95x151
Oct 05 15:55:50 asus-flo phoc[522]: [backend/drm/util.c:65] Failed to parse EDID
Oct 05 15:55:50 asus-flo phoc[522]: [backend/drm/drm.c:1855] connector DSI-1: Requesting modeset
Oct 05 15:55:50 asus-flo phoc[522]: [backend/drm/drm.c:944] connector DSI-1: Modesetting with 1200x1920 @ 60.000 Hz
Oct 05 15:55:52 asus-flo phoc[522]: Output 'DSI-1' added ('(null)'/'(null)'/'(null)'), 95mm x 151mm
Oct 05 15:55:54 asus-flo phoc[522]: Enabling shell mode
Oct 05 15:55:56 asus-flo kernel: [drm:a3xx_hw_init] *ERROR* A320: timeout waiting for GPU to idle!
Oct 05 15:55:57 asus-flo kernel: msm 5100000.mdp: [drm:hangcheck_handler] *ERROR* A320: hangcheck detected gpu lockup rb 0!
Oct 05 15:55:57 asus-flo kernel: msm 5100000.mdp: [drm:hangcheck_handler] *ERROR* A320: completed fence: 2
Oct 05 15:55:57 asus-flo kernel: msm 5100000.mdp: [drm:hangcheck_handler] *ERROR* A320: submitted fence: 3
Oct 05 15:55:57 asus-flo kernel: msm 5100000.mdp: [drm:recover_worker] *ERROR* A320: hangcheck recover!
Oct 05 15:55:57 asus-flo kernel: msm 5100000.mdp: [drm:recover_worker] *ERROR* A320: offending task: phoc (/usr/bin/phoc -v -S -C /usr/share/phosh/phoc.ini -E bash -lc 'exec gnome-session --disable-acceleration-check --session=phosh')
Oct 05 15:55:57 asus-flo kernel: revision: 320 (3.2.0.2)
Oct 05 15:55:57 asus-flo kernel: rb 0: fence: 2/3
Oct 05 15:55:57 asus-flo kernel: rptr: 32
Oct 05 15:55:57 asus-flo kernel: rb wptr: 32
Oct 05 15:55:57 asus-flo kernel: CP_SCRATCH_REG0: 0
Oct 05 15:55:57 asus-flo kernel: CP_SCRATCH_REG1: 0
Oct 05 15:55:57 asus-flo kernel: CP_SCRATCH_REG2: 2
Oct 05 15:55:57 asus-flo kernel: CP_SCRATCH_REG3: 0
Oct 05 15:55:57 asus-flo kernel: CP_SCRATCH_REG4: 0
Oct 05 15:55:57 asus-flo kernel: CP_SCRATCH_REG5: 0
Oct 05 15:55:57 asus-flo kernel: CP_SCRATCH_REG6: 0
Oct 05 15:55:57 asus-flo kernel: CP_SCRATCH_REG7: 0
Oct 05 15:55:57 asus-flo phoc[522]: [render/gles2/pass.c:306] GPU reset (guilty)
Oct 05 15:55:57 asus-flo phoc[522]: [render/gles2/pass.c:306] GPU reset (guilty)
Oct 05 15:55:57 asus-flo phoc[522]: [GLES2] GL_CONTEXT_LOST in context lost
... LOTS more GL_CONTEXT_LOST...
Apparently, this is a long-standing problem. And others also suffer from the display not turning back on, although I don’t see a kernel dump.
I feel like I now know how to find my way around postmarketOS and pmbootstrap. pmbootstrap is fast and relatively easy. I wish it didn’t remove my regular binfmt configuration, but I know why, so I can forgive it. There’s some other times it uses sudo which I wish it was able to avoid, like mkosi apparently can but most operations seem to run as my regular user, which is good. I keep getting the sense I’m aligned with their goals, like supporting lots of devices with UEFI and systemd-boot, the push to use unified /usr, getting systemd, and now this image building system. It isn’t Arch, but I’ve warmed up to this version of Alpine.
The most painful part of this was trying to write the 2 GB image to userdata, as it wasn’t clear what the problem was and the workarounds initially weren’t great. But apparently that is just an issue with this device.