Перейти к содержанию

Дуалбут Android 14 и postmarketOS на OnePlus 6 без кастомного рекавери

Для OnePlus 6 есть кастомные рекавери на базе TWRP или OrangeFox, которые позволяют установить 2 андроид системы, разделяя раздел userdata на userdata_a и userdata_b. Однако эти рекавери заточены на версию Android 9 и 10.

У мобильных Linux дистрибутивов, использующих mainline ядро, есть особенность - у них не захардкожен раздел для хранения данных и можно использовать какой угодно, нам не придётся патчить рекавери и сам Android не сможет никак взаимодействовать с этим разделом!

Переведенная цитата из pmOS Wiki

[...] Поскольку pmOS initramfs ищет название раздела, а не конкретный раздел, он автоматически определит раздел, на который был установлен pmOS rootfs.

Увы, такая возможность есть только у mainline дистрибутивов по типу postmarketOS, Mobian и Kupfer Linux (ArchLinux ARM) - с Droidian так не выйдет, так как "под капотом" там Halium и Android ядро.

Выделяем место для postmarketOS

Опасная зона!

С этого момента мы начинаем модификацию разделов и тут есть большой шанс накосячить! На всякий случай лучше приготовить Windows компьютер для восстановления через EDL.

Впрочем, оригинальная схема разделов будет ниже и по ней можно будет попробовать восстановить.

В качестве примера используется OnePlus 6 с хранилищем на 128 Гб. Нас интересует раздел userdata, от него нам и нужно будет "откусить" часть.

За основу был взять этот гайд с XDA. Бинарник parted тоже оттуда.

  • Загружаемся в рекавери - TWRP или LineageOS Recovery и включаем adb.

  • Передаём скаченный parted в /sbin/ и делаем его исполняемым:

    adb push /path/to/parted /sbin/parted
    adb shell
    chmod 777 /sbin/parted
    parted /dev/block/sda
    p free
    
Вывод таблицы разделов до модификаций (LineageOS 20)
Model: SAMSUNG KLUDG4U1EA-B0C1 (scsi)
Disk /dev/block/sda: 125GB
Sector size (logical/physical): 4096B/4096B
Partition Table: gpt
Disk Flags: 

Number  Start   End     Size    File system  Name         Flags
        12.3kB  24.6kB  12.3kB  Free Space
 1      24.6kB  32.8kB  8192B                ssd
 2      32.8kB  33.6MB  33.6MB  ext4         persist
 3      33.6MB  34.6MB  1049kB               misc
 4      34.6MB  35.7MB  1049kB               param
 5      35.7MB  36.2MB  524kB                keystore
 6      36.2MB  36.7MB  524kB                frp
 7      36.7MB  305MB   268MB   ext4         op2
 8      305MB   316MB   10.5MB               oem_dycnvbk
 9      316MB   326MB   10.5MB               oem_stanvbk
10      326MB   334MB   8290kB               reserve1
11      334MB   351MB   16.6MB               reserve2
12      351MB   352MB   524kB                config
13      352MB   3350MB  2999MB  ext2         system_a
14      3350MB  6349MB  2999MB  ext4         system_b
15      6349MB  6454MB  105MB   ext4         odm_a
16      6454MB  6559MB  105MB   ext4         odm_b
17      6559MB  125GB   118GB   ext4         userdata
        125GB   125GB   12.3kB  Free Space
  • Удаляем раздел userdata, в моём случае он под номером 17:

    rm 17
    

  • Создаём раздел userdata заново, но выделяем ему меньше места. Я пытался выделить 64 Гб поровну как для Android, так и для Linux:

    mkpart userdata ext4 6559MB 70.5GB
    

Шаблон для mkpart

mkpart name fs_type start end

  • name - название раздела, например userdata. parted не всегда его сохраняет, то этому его надо писать ещё и после mkpart;
  • fs_type - файловая система, оставляем ext4;
  • start - см. где заканчивается прерырущий раздел в столбце End;
  • end - прибавляем значение start + размер будущего раздела.
  • Проверяем имя раздела через p free. Если оно пустое, то задаём заново:

    name 17 userdata
    

  • Создаём раздел с данными для Linux под названием linux_rootfs:

    mkpart linux_rootfs ext4 70.5GB 125GB
    name 18 linux_rootfs
    

  • Проверяем созданную таблицу разделов:

Таблица разделов после модификаций
Model: SAMSUNG KLUDG4U1EA-B0C1 (scsi)
Disk /dev/block/sda: 125GB
Sector size (logical/physical): 4096B/4096B
Partition Table: gpt
Disk Flags: 

Number  Start   End     Size    File system  Name         Flags
        12.3kB  24.6kB  12.3kB  Free Space
 1      24.6kB  32.8kB  8192B                ssd
 2      32.8kB  33.6MB  33.6MB  ext4         persist
 3      33.6MB  34.6MB  1049kB               misc
 4      34.6MB  35.7MB  1049kB               param
 5      35.7MB  36.2MB  524kB                keystore
 6      36.2MB  36.7MB  524kB                frp
 7      36.7MB  305MB   268MB   ext4         op2
 8      305MB   316MB   10.5MB               oem_dycnvbk
 9      316MB   326MB   10.5MB               oem_stanvbk
10      326MB   334MB   8290kB               reserve1
11      334MB   351MB   16.6MB               reserve2
12      351MB   352MB   524kB                config
13      352MB   3350MB  2999MB  ext2         system_a
14      3350MB  6349MB  2999MB  ext4         system_b
15      6349MB  6454MB  105MB   ext4         odm_a
16      6454MB  6559MB  105MB   ext4         odm_b
17      6559MB  70.5GB  63.9GB  ext4         userdata
        70.5GB  70.5GB  1004kB  Free Space
18      70.5GB  125GB   54.2GB               linux_rootfs
        125GB   125GB   1040kB  Free Space
  • Выходим из parted командой quit.

  • После форматирования разделов, сделайте в рекавери сброс на заводские настройки, чтобы рекавери отформатировала раздел userdata как нужно и не было бутлупа.

Прошивка Android в Слот A

Примеры команд для прошивки LineageOS 20 (A13). Будем использовать стандартный рекавери LineageOS, так как рабочих и актуальных вариантов TWRP и OrangeFox нет.

  • Прошиваем разделы, не забываем указывать _a:
fastboot flash boot_a boot.img
fastboot flash dtbo_a dtbo.img
fastboot flash vbmeta_a vbmeta.img
  • Для прошивки LineageOS через LOS Recovery нам нужен рекавери на слоте B. Прошиваем его и перезагружаемся:
fastboot flash boot_b boot.img
fastboot --set-active=b
  • Перезагружаемся в рекавери: Выбираем кнопками громкости "Recovery mode" и нажимаем на кнопку питания. Из bootloader нельзя перезагрузиться в рекавери командой.

Рекавери должно выдать, что у нас сейчас активен B слот - так и должно быть, так как пакет с обновлениями будет прошиваться на соседний слот.

  • Прошиваем .zip пакет с обновлениями через "Apply update" и adb sideload.
    adb sideload имя-пакета.zip
    

После прошивки система будет загружаться с слота А. Это можно проверить следующей командой в режиме bootloader:

fastboot getvar current-slot

  • Если вы хотите установить пакет GAPPS, то подтвердите перезагрузку в рекавери. (Magisk ставится уже после первой загрузки в систему)

  • Перед первой загрузкой в систему лучше сделать Factory reset.

Прошивка pmOS в Слот B

Перед тем как продолжить...

Я полагаю что вы уже знаете как прошивать postmarketOS на OnePlus 6 и делали это самостоятельно хотя бы раз. По этому ниже только краткая сводка команд.

Готовый образ

Переключаемся на слот B и прошиваем образы на второй boot раздел и на наш новый специально созданный раздел под данные:

fastboot --set-active=b
fastboot erase dtbo_b
fastboot flash boot_b [файл который заканчивается на -boot.img]
fastboot flash linux_rootfs [второй .img файл]

Во время первой загрузки отключите устройство от USB, чтобы не было вот такого.

Сборка своего образа с шифрованием данных

Клонируем исходники pmbootstrap, проходим инициализацию и сборку, переключаемся на слот B и прошиваем образы на второй boot раздел и на наш новый специально созданный раздел под данные:

git clone --depth=1 https://git.sr.ht/~postmarketos/pmbootstrap
mkdir -p ~/.local/bin
ln -s "$PWD/pmbootstrap/pmbootstrap.py" ~/.local/bin/pmbootstrap

pmbootstrap init
pmbootstrap install --fde

fastboot --set-active=b
fastboot erase dtbo_b
pmbootstrap flasher flash_kernel --partition boot_b
pmbootstrap flasher flash_rootfs --partition linux_rootfs

pmbootstrap shutdown

Во время первой загрузки отключите устройство от USB, чтобы не было вот такого.

Как обновлять Android

Обновление Android на A/B устройствах при дуалбуте - это боль, но это возможно.

LineageOS всё ещё будет пытаться обновлять наше устройство как A/B, то есть устанавливать все обновления на соседний системный слот и перезаписывая boot раздел, на котором находится postmarketOS

Однако, обновления можно установить через bootloader!

Внимание!

Во время обновления у вас слетят GAPPS'ы, Magisk и прочие модификации которые вы делали с системным разделом! Их нужно будет прошивать заново!

И перед тем как обновляться лучше всего сделать бэкап важных файлов. Быстрее всего это можно сделать через adb pull /sdcard/Название_папки

Как сделать бэкап разделов в виде прошиваемого .img-образа

Для этого нам нужен adb с root доступом - это можно включить в настройках разработчика LineageOS:

Показан пример только для system раздела, но вы можете указать какой угодно:

adb root
adb shell
dd if=/dev/block/bootdevice/by-name/system_a of=/sdcard/system_a_backup.img bs=4k
exit
adb pull /sdcard/system_a_backup.img

В таком случае нужно устанавливать Android обновления, не через рекавери или встроенные обновления в систему, а через fastboot.

  • Скачиваем .zip архив с обновлением и распаковываем его при помощи payload-dumper-go

В итоге мы получим следующий список прошиваемых через fastboot образов:

  • system.img
  • vendor.img
  • boot.img
  • vbmeta.img
  • dtbo.img
  • и т.д.

В составе LineageOS рекавери есть fastbootd, которым я рекомендую пользоваться при прошивке разделов из пакета обновлений.

Синтаксис будет тот же самый что и в режиме bootloader'а, просто багов меньше. Энтузиасты часто жаловались на кривую стоковую реализацию fastboot и по возможности лучше использовать fastbootd в составе рекавери.

Совет пользователям Magisk

Перед тем как шить boot.img образ, его можно перекинуть на устройство через adb push /sdcard и пропатчить его Magisk'ом заранее.

  • Загружаемся в рекавери, переходим в режим fastbootd и прошиваем образы:
    fastboot flash system_a system.img
    fastboot flash vendor_a vendor.img
    fastboot flash boot_a boot.img       # Напомню, можете перед этим пропатчить образ Magisk'ом
    fastboot flash vbmeta_a vbmeta.img
    fastboot flash dtbo_a dtbo.img
    

Если в распакованном образе помимо system и vendor образов есть ещё что-то (например, обновление модема и других разделов), то шьём их тоже!

Payload dumper может также распаковать из архива образы boot, dtbo, vbmeta. Если вы до этого уже скачали их отдельно и прошили, то распакованные можно игнорировать - они идентичные.

  • Если вы используете GAPPS'ы, то загрузитесь в рекавери сейчас и прошейте пакет заново!

  • На этом обновление закончено - можно загружаться!

Работает даже между мажорными релизами!

Протестировано при обновлении с LineageOS 20 на 21 с сохранением рабочего пакета NikGapps Core и Magisk.